diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b79bd672e..4d5f46c9f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -165,7 +165,6 @@ jobs: --inconclusive \ --inline-suppr \ --std=c99 \ - --suppress="memleak:${{ github.workspace }}/src/u_scanner.c" \ --project="${{ github.workspace }}/build/compile_commands.json" \ -i"${{ github.workspace }}/third-party" \ -D__GNUC__ diff --git a/.gitignore b/.gitignore index 818793e79..16bb0fcad 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ CMakeSettings.json # clangd /.cache/ +CMakeFiles/ +src/CMakeFiles/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ecd93b74..edf044f4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ ## Changes +- **Merged changes from [Woof! post-15.0.1]**, note: + - Replaced `fullscreen_hud_type` with `use_nughud`, with the NUGHUD now replacing the second-to-last HUD + - Removed `fuzzdark_mode` in favor of Woof!'s `fuzzmode` (_Refraction_ is equivalent to _Selective Fuzz Darkening_) + - Removed `comp_blazing2`; its functionality has been integrated into `comp_blazing` - **Improved interpolation of weapon sprites** - **Applied weapon inertia when firing** (added `weapon_inertia_fire` CVAR to disable it) - **Lowered `weapon_inertia_scale_pct` limit to -200** diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b6b34a12..25f077eed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ check_library_exists(m pow "" HAVE_LIBM) check_include_file("dirent.h" HAVE_DIRENT_H) check_symbol_exists(strcasecmp "strings.h" HAVE_DECL_STRCASECMP) check_symbol_exists(strncasecmp "strings.h" HAVE_DECL_STRNCASECMP) +check_symbol_exists(getpwuid "unistd.h;sys/types.h;pwd.h" HAVE_GETPWUID) check_c_source_compiles(" #include <windows.h> int main() @@ -76,6 +77,16 @@ check_c_source_compiles(" " HAVE__DIV64 ) +check_c_source_compiles(" + typedef float vec __attribute__((ext_vector_type(4))); + int main() + { + vec a = (vec){0, 1, 2, 3}; + return 0; + } + " + HAVE_EXT_VECTOR_TYPE +) option(CMAKE_FIND_PACKAGE_PREFER_CONFIG "Lookup package config files before using find modules" ON) diff --git a/README.md b/README.md index b4b7a08ae..25c287dfd 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,6 @@ All of these are CFG-only, so their CVAR names are included. - Attackers face fuzzy targets straight (`comp_faceshadow`) - Fix lopsided Icon of Sin explosions (`comp_iosdeath`) - Permanent IDCHOPPERS invulnerability (`comp_choppers`) -- Blazing doors reopen with wrong sound (`comp_blazing2`) [p.f. Crispy Doom] - Manually toggled moving doors are silent (`comp_manualdoor`) [p.f. Crispy Doom] - Corrected switch sound source (`comp_switchsource`) [p.f. Crispy Doom] - Chaingun makes two sounds with one bullet (`comp_cgundblsnd`) @@ -260,7 +259,7 @@ The Nugget Doom source code is available at GitHub: <https://github.com/MrAlaux/ The following build system and libraries need to be installed: - * [CMake](https://cmake.org) (>= 3.9) + * [CMake](https://cmake.org) (>= 3.15) * [SDL2](https://github.com/libsdl-org/SDL/tree/SDL2) (>= 2.0.18) * [SDL2_net](https://github.com/libsdl-org/SDL_net) * [openal-soft](https://github.com/kcat/openal-soft) (>= 1.22.0 for PC Speaker emulation) @@ -330,7 +329,6 @@ Copyright: © 2007-2011 Moritz "Ripper" Kroll; © 2008-2019 Simon Judd; © 2017 Christoph Oelckers; - © 2019 Fernando Carmona Varo; © 2020 Alex Mayfield; © 2020 JadingTsunami; © 2020-2024 Fabian Greffrath; @@ -341,7 +339,8 @@ Copyright: © 2022-2024 ceski; © 2023 Andrew Apted; © 2023 liPillON; - © 2024 pvictress. + © 2024 pvictress; + © 2025 Guilherme Miranda. License: [GPL-2.0+](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html) Files: `src/i_flickstick.*, src/i_gyro.*` @@ -356,10 +355,9 @@ Copyright: © 2023 Andrew Apted. License: [MIT](https://opensource.org/licenses/MIT) -Files: `src/u_scanner.*` +Files: `src/m_scanner.*` Copyright: - © 2010 Braden "Blzut3" Obrzut; - © 2019 Fernando Carmona Varo. + © 2015 Braden "Blzut3" Obrzut. License: [BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) Files: `src/v_flextran.*` diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 7b7662f4c..5eaebfdc5 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -215,18 +215,18 @@ set(BASE_SOURCES all-all/sprites/ngtrf0.png all-all/sprites/ngtrg0.png - betalevl.wad/umapdef.lmp + betalevl.wad/umapinfo.lmp chex.wad/brghtmps.lmp chex.wad/dehacked.lmp - chex.wad/umapdef.lmp + chex.wad/umapinfo.lmp chex2.wad/brghtmps.lmp doom-all/brghtmps.lmp - e1m4b.wad/umapdef.lmp - e1m8b.wad/umapdef.lmp + e1m4b.wad/umapinfo.lmp + e1m8b.wad/umapinfo.lmp extras.wad/sbardef.lmp @@ -235,16 +235,10 @@ set(BASE_SOURCES id1.wad/sbardef.lmp - masterlevels.wad/umapdef.lmp - - nerve.wad/umapdef.lmp - rekkr.wad/dehacked.lmp rekkrsa.wad/dehacked.lmp rekkrsl.wad/dehacked.lmp - sigil_v1_21.wad/umapdef.lmp - tnt.wad/brghtmps.lmp) add_custom_command(OUTPUT "${BASE_PK3_PATH}" diff --git a/base/all-all/compdb.lmp b/base/all-all/compdb.lmp index 5508c5855..8c458321d 100644 --- a/base/all-all/compdb.lmp +++ b/base/all-all/compdb.lmp @@ -1,10 +1,8 @@ { "type": "compatibility", "version": "1.0.0", - "data": - { - "levels": - [ + "data": { + "levels": [ { "name": "eternal_doom_25", "md5": "6da6fcba8089161bdec6a1d3f6c8d60f", @@ -19,181 +17,360 @@ } ] }, + { + "name": "doomsday_of_uac_e1m8", + "md5": "32fc3115a3162b623f0d0f4e7dee6861", + "complevel": "1.9" + }, { "name": "hell_revealed_map19", "md5": "811a0c97777a198bc9b2bb558cb46e6a", - "options": [ {"name": "comp_pain", "value": 1} ] + "options": [ + { + "name": "comp_pain", + "value": 1 + } + ] }, { "name": "roger_ritenour_phobos_map03", "md5": "8fa29398776146189396aa1ac6bb9e13", - "options": [ {"name": "comp_floors", "value": 1} ] + "options": [ + { + "name": "comp_floors", + "value": 1 + } + ] }, { "name": "hell_revealed_map26", "md5": "145c4dfcf843f2b92c73036ba0e1d98a", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, - { "name": "hell_to_pay_map14", "md5": "5379c080299eb961792b50ad96821543", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "hell_to_pay_map22", "md5": "7837b5334a277f107515d649bcefb682", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "icarus_map24", "md5": "2eeb1e12fa9f9545de9d99990a4a78e5", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "plutonia2_map32", "md5": "65a53a09a09525ae42ea210bf879cd37", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "requiem_map23", "md5": "2499cf9a9351be9bc4e9c66fc9f291a7", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "the_waterfront_map01", "md5": "3ca5493feff2e27bfd4181e6c4a3c2bf", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "gather2_map05_and_darkside_map01", "md5": "cbdfefac579a62de8f1b48ca4a09d381", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "reverie_map18", "md5": "c7a2fafb0afb2632c50ad625cdb50e51", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "project_x_map14", "md5": "9e5724bc6135aa6f86ee54fd4d91f1e2", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "archie_map01", "md5": "01899825ffeae016d39c02a7da4b218f", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "seej_map01", "md5": "1d9f3afdc2517c2e450491ed13896712", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "sixpack2_map02", "md5": "0ae745a3ab86d15fb2fb74489962c421", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "squadron_417_map21", "md5": "2ea635c6b6aec76b6bc77448dab22f9a", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "mayhem_2013_map05", "md5": "1e998262ee319b7d088e01de782e6b41", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "imps_are_ghost_gods_map01", "md5": "a81e2734f735a82720d8e0f1442ba0c9", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "confinement_map31", "md5": "aad7502cb39bc050445e17b15f72356f", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "conf256b_map07", "md5": "5592ea1ca3b8ee0dbb2cb352aaa00911", - "options": [ {"name": "comp_pain", "value": 1} ] + "options": [ + { + "name": "comp_pain", + "value": 1 + } + ] }, { "name": "conf256b_map12", "md5": "cecedae33b970f2bf7f8b8631da0c8dd", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "sunlust_map30", "md5": "41efe03223e41935849f64114c5cb471", - "options": [ {"name": "comp_telefrag", "value": 1} ] + "options": [ + { + "name": "comp_telefrag", + "value": 1 + } + ] }, { "name": "tnt_map30", "md5": "42b68b84ff8e55f264c31e6f4cfea82d", - "options": [ {"name": "comp_stairs", "value": 1} ] + "options": [ + { + "name": "comp_stairs", + "value": 1 + } + ] }, { "name": "intercep2_map03", "md5": "86587e4f8c8086991c8fc5c1ccfd30b9", - "options": [ {"name": "comp_ledgeblock", "value": 0} ] + "options": [ + { + "name": "comp_ledgeblock", + "value": 0 + } + ] }, { "name": "skulltiverse_map02", "md5": "b3fa4a18b31bd96e724f9aab101776a1", - "options": [ {"name": "comp_ledgeblock", "value": 0} ] + "options": [ + { + "name": "comp_ledgeblock", + "value": 0 + } + ] }, { "name": "tntr_map30", "md5": "1d3c6d456bfcf360ce14aeecc155a96c", - "options": [ {"comp_telefrag": true} ] + "options": [ + { + "name": "comp_telefrag", + "value": 1 + } + ] }, { "name": "roomblow_e1m1", "md5": "68ffa69f2eaa5ced3dc4da5a300d022a", - "options": [ {"name": "comp_stairs", "value": 1} ] + "options": [ + { + "name": "comp_stairs", + "value": 1 + } + ] }, { "name": "esp_map21", "md5": "97088f2849904bc1cd5ae1d92d163b13", - "options": [ {"name": "comp_stairs", "value": 1} ] + "options": [ + { + "name": "comp_stairs", + "value": 1 + } + ] }, { "name": "av_map07", "md5": "941e4cb56ee4184e0b1ed43486ab0bbf", - "options": [ {"name": "comp_model", "value": 1} ] + "options": [ + { + "name": "comp_model", + "value": 1 + } + ] }, { "name": "sin2_9_map02", "md5": "9aa5aa3020434f824624eba88916ee23", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "d2reload_map09", "md5": "c8de798a4d658ffc94151884c6c2bf37", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "amoreupho_map02", "md5": "66a8310a0a7d2af99e3a0089b2d6c897", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "dbp20_dnd_map07", "md5": "e26c1b6f4dfd90bb6533e6381bf61be5", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "arch_map01", "md5": "1d37cbd32a1ecf4763437631e7b3c29a", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] }, { "name": "ur_map06", "md5": "cfb054683af1ed187d0565942d3dbb8f", - "options": [ {"name": "comp_vile", "value": 1} ] + "options": [ + { + "name": "comp_vile", + "value": 1 + } + ] } ] } diff --git a/base/all-all/sbardef.lmp b/base/all-all/sbardef.lmp index 758aa7c20..5929a8693 100644 --- a/base/all-all/sbardef.lmp +++ b/base/all-all/sbardef.lmp @@ -981,7 +981,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 16, "alignment": 34, "tranmap": null, @@ -996,7 +996,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 8, "alignment": 34, "tranmap": null, @@ -1010,7 +1010,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 0, "alignment": 34, "tranmap": null, @@ -1024,7 +1024,7 @@ { "widget": { - "x": 0, + "x": 2, "y": 8, "alignment": 0, "tranmap": null, @@ -1038,7 +1038,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 167, "alignment": 42, "tranmap": null, @@ -1851,7 +1851,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 16, "alignment": 34, "tranmap": null, @@ -1866,7 +1866,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 8, "alignment": 34, "tranmap": null, @@ -1880,7 +1880,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 0, "alignment": 34, "tranmap": null, @@ -1894,7 +1894,7 @@ { "widget": { - "x": 0, + "x": 2, "y": 8, "alignment": 0, "tranmap": null, @@ -1908,7 +1908,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 167, "alignment": 42, "tranmap": null, @@ -2033,262 +2033,1331 @@ "children": [ { - "widget": + "number": { - "x": 2, - "y": 192, - "alignment": 16, + "x": 44, + "y": 171, + "alignment": 18, + "font": "BigRed", "tranmap": null, "translation": null, - "type": 0, - "font": "Digits", - "vertical_layout": 0, + "type": 4, + "param": 0, + "maxlength": 3, "conditions": [ { - "condition": 19, - "param": 4 + "condition": 4, + "param": 0 } ], "children": null } }, { - "widget": + "percent": { - "x": 2, - "y": 184, - "alignment": 16, + "x": 104, + "y": 171, + "alignment": 18, + "font": "BigRed", "tranmap": null, "translation": null, - "type": 1, - "font": "Digits", - "conditions": - [ - { - "condition": 19, - "param": 4 - }, - { - "condition": 20, - "param": 0 - } - ], + "type": 0, + "param": 0, + "maxlength": 3, + "conditions": null, "children": null } }, { - "widget": + "percent": { - "x": 2, - "y": 192, - "alignment": 16, + "x": 235, + "y": 171, + "alignment": 34, + "font": "BigRed", "tranmap": null, "translation": null, "type": 1, - "font": "Digits", - "conditions": - [ - { - "condition": 19, - "param": 4 - }, - { - "condition": 21, - "param": 0 - } - ], + "param": 0, + "maxlength": 3, + "conditions": null, "children": null } }, { - "widget": + "number": { - "x": 2, - "y": 184, - "alignment": 16, + "x": 138, + "y": 171, + "alignment": 18, + "font": "BigRed", "tranmap": null, "translation": null, - "type": 0, - "font": "Digits", - "vertical_layout": 0, + "type": 2, + "param": 0, + "maxlength": 2, "conditions": [ { - "condition": 19, - "param": 3 + "condition": 14, + "param": 2 } ], "children": null } }, { - "widget": + "canvas": { - "x": 2, - "y": 176, - "alignment": 16, - "tranmap": null, - "translation": null, - "type": 1, - "font": "Digits", + "x": 104, + "y": 168, + "alignment": 0, "conditions": [ { - "condition": 19, - "param": 3 - }, - { - "condition": 20, - "param": 0 + "condition": 15, + "param": 2 } ], - "children": null - } - }, - { - "widget": - { - "x": 2, - "y": 184, - "alignment": 16, - "tranmap": null, - "translation": null, - "type": 1, - "font": "Digits", - "conditions": + "children": [ { - "condition": 19, - "param": 3 + "graphic": + { + "x": 7, + "y": 4, + "alignment": 16, + "patch": "STGNUM2", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 2 + } + ], + "children": null + } }, { - "condition": 21, - "param": 0 - } - ], - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 16, - "alignment": 34, - "tranmap": null, - "translation": null, - "type": 2, - "font": "Digits", - "vertical_layout": 0, - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 8, - "alignment": 34, - "tranmap": null, - "translation": null, - "type": 32, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 0, - "alignment": 34, - "tranmap": null, - "translation": null, - "type": 3, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 0, - "y": 8, - "alignment": 0, - "tranmap": null, - "translation": null, - "type": 4, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 200, - "alignment": 42, - "tranmap": null, - "translation": null, - "type": 5, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 160, - "y": 200, - "alignment": 9, - "tranmap": null, - "translation": null, - "type": 6, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 2, - "y": 0, - "alignment": 16, - "tranmap": null, - "translation": null, - "type": 7, - "font": "Console", - "duration": 4, - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 160, - "y": 68, - "alignment": 1, - "tranmap": null, - "translation": null, - "type": 8, - "font": "Console", + "graphic": + { + "x": 7, + "y": 4, + "alignment": 16, + "patch": "STYSNUM2", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 2 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 4, + "alignment": 16, + "patch": "STGNUM3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 3 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 4, + "alignment": 16, + "patch": "STYSNUM3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 3 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 4, + "alignment": 16, + "patch": "STGNUM4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 4, + "alignment": 16, + "patch": "STYSNUM4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 7, + "y": 14, + "alignment": 16, + "patch": "STGNUM5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 7, + "y": 14, + "alignment": 16, + "patch": "STYSNUM5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 14, + "alignment": 16, + "patch": "STGNUM6", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 14, + "alignment": 16, + "patch": "STYSNUM6", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 14, + "alignment": 16, + "patch": "STGNUM7", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 7 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 14, + "alignment": 16, + "patch": "STYSNUM7", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 7 + } + ], + "children": null + } + } + ] + } + }, + { + "number": + { + "x": 288, + "y": 173, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 0, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 173, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 0, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 288, + "y": 179, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 1, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 179, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 1, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 288, + "y": 185, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 3, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 185, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 3, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 288, + "y": 191, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 2, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 191, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 2, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS0", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 1 + }, + { + "condition": 11, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 11, + "param": 1 + }, + { + "condition": 10, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 1 + }, + { + "condition": 10, + "param": 4 + }, + { + "condition": 13, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS6", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 1 + }, + { + "condition": 10, + "param": 4 + }, + { + "condition": 12, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS1", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 2 + }, + { + "condition": 11, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 11, + "param": 2 + }, + { + "condition": 10, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 2 + }, + { + "condition": 10, + "param": 5 + }, + { + "condition": 13, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS7", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 2 + }, + { + "condition": 10, + "param": 5 + }, + { + "condition": 12, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS2", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 3 + }, + { + "condition": 11, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 11, + "param": 3 + }, + { + "condition": 10, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 3 + }, + { + "condition": 10, + "param": 6 + }, + { + "condition": 13, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS8", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 3 + }, + { + "condition": 10, + "param": 6 + }, + { + "condition": 12, + "param": 1 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 160, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "vertical_layout": 0, + "conditions": + [ + { + "condition": 19, + "param": 4 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 152, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 160, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 152, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "vertical_layout": 0, + "conditions": + [ + { + "condition": 19, + "param": 3 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 144, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 152, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 16, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 2, + "font": "Digits", + "vertical_layout": 0, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 8, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 32, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 0, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 3, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 8, + "alignment": 0, + "tranmap": null, + "translation": null, + "type": 4, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 167, + "alignment": 42, + "tranmap": null, + "translation": null, + "type": 5, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 160, + "y": 167, + "alignment": 9, + "tranmap": null, + "translation": null, + "type": 6, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, + "y": 0, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 7, + "font": "Console", + "duration": 4, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 160, + "y": 52, + "alignment": 1, + "tranmap": null, + "translation": null, + "type": 8, + "font": "Console", "duration": 2.5, "conditions": null, "children": null } }, + { + "widget": + { + "x": 0, + "y": 0, + "alignment": 16, + "tranmap": null, + "translation": "CRGOLD", + "type": 9, + "font": "Console", + "under_messages": true, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, + "y": 160, + "alignment": 16, + "tranmap": null, + "translation": "CRGOLD", + "type": 10, + "font": "Console", + "conditions": + [ + { + "condition": 19, + "param": 3 + } + ], + "children": null + } + }, + { + "carousel": + { + "x": 0, + "y": 18, + "alignment": 0, + "tranmap": null, + "translation": null, + "conditions": null, + "children": null + } + }, + { + "minimap": + { + "x": 8, + "y": 0, + "alignment": 80, + "width": 80, + "height": 80, + "under_messages": true + } + } + ] + }, + { + "height": 200, + "fullscreenrender": true, + "fillflat": null, + "children": + [ + { + "widget": + { + "x": 2, + "y": 192, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "vertical_layout": 0, + "conditions": + [ + { + "condition": 19, + "param": 4 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 184, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 192, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 184, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "vertical_layout": 0, + "conditions": + [ + { + "condition": 19, + "param": 3 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 176, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 184, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 16, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 2, + "font": "Digits", + "vertical_layout": 0, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 8, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 32, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 0, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 3, + "font": "Digits", + "conditions": null, + "children": null + } + }, { "widget": { "x": 2, + "y": 8, + "alignment": 0, + "tranmap": null, + "translation": null, + "type": 4, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 200, + "alignment": 42, + "tranmap": null, + "translation": null, + "type": 5, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 160, + "y": 200, + "alignment": 9, + "tranmap": null, + "translation": null, + "type": 6, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, + "y": 0, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 7, + "font": "Console", + "duration": 4, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 160, + "y": 68, + "alignment": 1, + "tranmap": null, + "translation": null, + "type": 8, + "font": "Console", + "duration": 2.5, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, "y": 0, "alignment": 16, "tranmap": null, @@ -2303,7 +3372,7 @@ { "widget": { - "x": 2, + "x": 0, "y": 192, "alignment": 16, "tranmap": null, diff --git a/base/all-all/sbhuddef.lmp b/base/all-all/sbhuddef.lmp index ca2f4a3ac..cab824204 100644 --- a/base/all-all/sbhuddef.lmp +++ b/base/all-all/sbhuddef.lmp @@ -157,7 +157,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 8, "alignment": 34, "tranmap": null, @@ -171,7 +171,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 0, "alignment": 34, "tranmap": null, @@ -185,7 +185,7 @@ { "widget": { - "x": 0, + "x": 2, "y": 8, "alignment": 0, "tranmap": null, @@ -199,7 +199,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 167, "alignment": 42, "tranmap": null, diff --git a/base/betalevl.wad/umapdef.lmp b/base/betalevl.wad/umapinfo.lmp similarity index 100% rename from base/betalevl.wad/umapdef.lmp rename to base/betalevl.wad/umapinfo.lmp diff --git a/base/chex.wad/umapdef.lmp b/base/chex.wad/umapinfo.lmp similarity index 100% rename from base/chex.wad/umapdef.lmp rename to base/chex.wad/umapinfo.lmp diff --git a/base/e1m4b.wad/umapdef.lmp b/base/e1m4b.wad/umapinfo.lmp similarity index 100% rename from base/e1m4b.wad/umapdef.lmp rename to base/e1m4b.wad/umapinfo.lmp diff --git a/base/e1m8b.wad/umapdef.lmp b/base/e1m8b.wad/umapinfo.lmp similarity index 100% rename from base/e1m8b.wad/umapdef.lmp rename to base/e1m8b.wad/umapinfo.lmp diff --git a/base/extras.wad/sbardef.lmp b/base/extras.wad/sbardef.lmp index ea77bb95c..c6f6eaa37 100644 --- a/base/extras.wad/sbardef.lmp +++ b/base/extras.wad/sbardef.lmp @@ -980,7 +980,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 16, "alignment": 34, "tranmap": null, @@ -1009,7 +1009,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 0, "alignment": 34, "tranmap": null, @@ -1023,7 +1023,7 @@ { "widget": { - "x": 0, + "x": 2, "y": 8, "alignment": 0, "tranmap": null, @@ -1037,7 +1037,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 167, "alignment": 42, "tranmap": null, @@ -1839,7 +1839,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 16, "alignment": 34, "tranmap": null, @@ -1868,7 +1868,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 0, "alignment": 34, "tranmap": null, @@ -1882,7 +1882,7 @@ { "widget": { - "x": 0, + "x": 2, "y": 8, "alignment": 0, "tranmap": null, @@ -1896,7 +1896,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 167, "alignment": 42, "tranmap": null, @@ -2010,243 +2010,1298 @@ "children": [ { - "widget": + "number": { - "x": 2, - "y": 192, - "alignment": 16, + "x": 44, + "y": 171, + "alignment": 18, + "font": "BigRed", "tranmap": null, "translation": null, - "type": 0, - "font": "Digits", - "vertical_layout": 0, + "type": 4, + "param": 0, + "maxlength": 3, "conditions": [ { - "condition": 19, - "param": 4 + "condition": 4, + "param": 0 } ], "children": null } }, { - "widget": + "percent": { - "x": 2, - "y": 184, - "alignment": 16, + "x": 104, + "y": 171, + "alignment": 18, + "font": "BigRed", "tranmap": null, "translation": null, - "type": 1, - "font": "Digits", - "conditions": - [ - { - "condition": 19, - "param": 4 - }, - { - "condition": 20, - "param": 0 - } - ], + "type": 0, + "param": 0, + "maxlength": 3, + "conditions": null, "children": null } }, { - "widget": + "percent": { - "x": 2, - "y": 192, - "alignment": 16, + "x": 235, + "y": 171, + "alignment": 34, + "font": "BigRed", "tranmap": null, "translation": null, "type": 1, - "font": "Digits", - "conditions": - [ - { - "condition": 19, - "param": 4 - }, - { - "condition": 21, - "param": 0 - } - ], + "param": 0, + "maxlength": 3, + "conditions": null, "children": null } }, { - "widget": + "number": { - "x": 2, - "y": 184, - "alignment": 16, + "x": 138, + "y": 171, + "alignment": 18, + "font": "BigRed", "tranmap": null, "translation": null, - "type": 0, - "font": "Digits", - "vertical_layout": 0, + "type": 2, + "param": 0, + "maxlength": 2, "conditions": [ { - "condition": 19, - "param": 3 + "condition": 14, + "param": 2 } ], "children": null } }, { - "widget": + "canvas": { - "x": 2, - "y": 176, - "alignment": 16, - "tranmap": null, - "translation": null, - "type": 1, - "font": "Digits", + "x": 104, + "y": 168, + "alignment": 0, "conditions": [ { - "condition": 19, - "param": 3 - }, - { - "condition": 20, - "param": 0 + "condition": 15, + "param": 2 } ], - "children": null - } - }, - { - "widget": - { - "x": 2, - "y": 184, - "alignment": 16, - "tranmap": null, - "translation": null, - "type": 1, - "font": "Digits", - "conditions": + "children": [ { - "condition": 19, - "param": 3 + "graphic": + { + "x": 7, + "y": 4, + "alignment": 16, + "patch": "STGNUM2", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 2 + } + ], + "children": null + } }, { - "condition": 21, - "param": 0 - } - ], - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 16, - "alignment": 34, - "tranmap": null, - "translation": null, - "type": 2, - "font": "Digits", - "vertical_layout": 0, - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 8, - "alignment": 34, - "tranmap": null, - "translation": null, - "type": 32, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 0, - "alignment": 34, - "tranmap": null, - "translation": null, - "type": 3, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 0, - "y": 8, - "alignment": 0, - "tranmap": null, - "translation": null, - "type": 4, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 200, - "alignment": 42, - "tranmap": null, - "translation": null, - "type": 5, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 160, - "y": 200, - "alignment": 9, - "tranmap": null, - "translation": null, - "type": 6, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 2, - "y": 0, - "alignment": 16, - "tranmap": null, - "translation": null, - "type": 7, - "font": "Console", - "duration": 4, - "conditions": null, - "children": null - } - }, + "graphic": + { + "x": 7, + "y": 4, + "alignment": 16, + "patch": "STYSNUM2", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 2 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 4, + "alignment": 16, + "patch": "STGNUM3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 3 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 4, + "alignment": 16, + "patch": "STYSNUM3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 3 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 4, + "alignment": 16, + "patch": "STGNUM4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 4, + "alignment": 16, + "patch": "STYSNUM4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 7, + "y": 14, + "alignment": 16, + "patch": "STGNUM5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 7, + "y": 14, + "alignment": 16, + "patch": "STYSNUM5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 14, + "alignment": 16, + "patch": "STGNUM6", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 14, + "alignment": 16, + "patch": "STYSNUM6", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 14, + "alignment": 16, + "patch": "STGNUM7", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 7 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 14, + "alignment": 16, + "patch": "STYSNUM7", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 7 + } + ], + "children": null + } + } + ] + } + }, + { + "number": + { + "x": 288, + "y": 173, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 0, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 173, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 0, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 288, + "y": 179, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 1, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 179, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 1, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 288, + "y": 185, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 3, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 185, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 3, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 288, + "y": 191, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 2, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 191, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 2, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS0", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 1 + }, + { + "condition": 11, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 11, + "param": 1 + }, + { + "condition": 10, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 1 + }, + { + "condition": 10, + "param": 4 + }, + { + "condition": 13, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS6", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 1 + }, + { + "condition": 10, + "param": 4 + }, + { + "condition": 12, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS1", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 2 + }, + { + "condition": 11, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 11, + "param": 2 + }, + { + "condition": 10, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 2 + }, + { + "condition": 10, + "param": 5 + }, + { + "condition": 13, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS7", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 2 + }, + { + "condition": 10, + "param": 5 + }, + { + "condition": 12, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS2", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 3 + }, + { + "condition": 11, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 11, + "param": 3 + }, + { + "condition": 10, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 3 + }, + { + "condition": 10, + "param": 6 + }, + { + "condition": 13, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS8", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 3 + }, + { + "condition": 10, + "param": 6 + }, + { + "condition": 12, + "param": 1 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 160, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 152, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 160, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 152, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 144, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 152, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 16, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 2, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 8, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 32, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 0, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 3, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 8, + "alignment": 0, + "tranmap": null, + "translation": null, + "type": 4, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 167, + "alignment": 42, + "tranmap": null, + "translation": null, + "type": 5, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 160, + "y": 167, + "alignment": 9, + "tranmap": null, + "translation": null, + "type": 6, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, + "y": 0, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 7, + "font": "Console", + "duration": 4, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 160, + "y": 52, + "alignment": 1, + "tranmap": null, + "translation": null, + "type": 8, + "font": "Console", + "duration": 2.5, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, + "y": 0, + "alignment": 16, + "tranmap": null, + "translation": "CRGOLD", + "type": 9, + "font": "Console", + "under_messages": true, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, + "y": 160, + "alignment": 16, + "tranmap": null, + "translation": "CRGOLD", + "type": 10, + "font": "Console", + "conditions": + [ + { + "condition": 19, + "param": 3 + } + ], + "children": null + } + }, + { + "carousel": + { + "x": 0, + "y": 18, + "alignment": 0, + "tranmap": null, + "translation": null, + "conditions": null, + "children": null + } + } + ] + }, + { + "height": 200, + "fullscreenrender": true, + "fillflat": null, + "children": + [ + { + "widget": + { + "x": 2, + "y": 192, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "vertical_layout": 0, + "conditions": + [ + { + "condition": 19, + "param": 4 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 184, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 192, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 184, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "vertical_layout": 0, + "conditions": + [ + { + "condition": 19, + "param": 3 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 176, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 184, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 16, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 2, + "font": "Digits", + "vertical_layout": 0, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 8, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 32, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 0, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 3, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 8, + "alignment": 0, + "tranmap": null, + "translation": null, + "type": 4, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 200, + "alignment": 42, + "tranmap": null, + "translation": null, + "type": 5, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 160, + "y": 200, + "alignment": 9, + "tranmap": null, + "translation": null, + "type": 6, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, + "y": 0, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 7, + "font": "Console", + "duration": 4, + "conditions": null, + "children": null + } + }, { "widget": { @@ -2265,7 +3320,7 @@ { "widget": { - "x": 2, + "x": 0, "y": 0, "alignment": 16, "tranmap": null, @@ -2280,7 +3335,7 @@ { "widget": { - "x": 2, + "x": 0, "y": 192, "alignment": 16, "tranmap": null, diff --git a/base/id1.wad/sbardef.lmp b/base/id1.wad/sbardef.lmp index ba9c4e44e..10606af7b 100644 --- a/base/id1.wad/sbardef.lmp +++ b/base/id1.wad/sbardef.lmp @@ -980,7 +980,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 16, "alignment": 34, "tranmap": null, @@ -1009,7 +1009,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 0, "alignment": 34, "tranmap": null, @@ -1023,7 +1023,7 @@ { "widget": { - "x": 0, + "x": 2, "y": 8, "alignment": 0, "tranmap": null, @@ -1037,7 +1037,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 167, "alignment": 42, "tranmap": null, @@ -1839,7 +1839,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 16, "alignment": 34, "tranmap": null, @@ -1868,7 +1868,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 0, "alignment": 34, "tranmap": null, @@ -1882,7 +1882,7 @@ { "widget": { - "x": 0, + "x": 2, "y": 8, "alignment": 0, "tranmap": null, @@ -1896,7 +1896,7 @@ { "widget": { - "x": 320, + "x": 318, "y": 167, "alignment": 42, "tranmap": null, @@ -2010,243 +2010,1298 @@ "children": [ { - "widget": + "number": { - "x": 2, - "y": 192, - "alignment": 16, + "x": 44, + "y": 171, + "alignment": 18, + "font": "BigRed", "tranmap": null, "translation": null, - "type": 0, - "font": "Digits", - "vertical_layout": 0, + "type": 4, + "param": 0, + "maxlength": 3, "conditions": [ { - "condition": 19, - "param": 4 + "condition": 4, + "param": 0 } ], "children": null } }, { - "widget": + "percent": { - "x": 2, - "y": 184, - "alignment": 16, + "x": 104, + "y": 171, + "alignment": 18, + "font": "BigRed", "tranmap": null, "translation": null, - "type": 1, - "font": "Digits", - "conditions": - [ - { - "condition": 19, - "param": 4 - }, - { - "condition": 20, - "param": 0 - } - ], + "type": 0, + "param": 0, + "maxlength": 3, + "conditions": null, "children": null } }, { - "widget": + "percent": { - "x": 2, - "y": 192, - "alignment": 16, + "x": 235, + "y": 171, + "alignment": 34, + "font": "BigRed", "tranmap": null, "translation": null, "type": 1, - "font": "Digits", - "conditions": - [ - { - "condition": 19, - "param": 4 - }, - { - "condition": 21, - "param": 0 - } - ], + "param": 0, + "maxlength": 3, + "conditions": null, "children": null } }, { - "widget": + "number": { - "x": 2, - "y": 184, - "alignment": 16, + "x": 138, + "y": 171, + "alignment": 18, + "font": "BigRed", "tranmap": null, "translation": null, - "type": 0, - "font": "Digits", - "vertical_layout": 0, + "type": 2, + "param": 0, + "maxlength": 2, "conditions": [ { - "condition": 19, - "param": 3 + "condition": 14, + "param": 2 } ], "children": null } }, { - "widget": + "canvas": { - "x": 2, - "y": 176, - "alignment": 16, - "tranmap": null, - "translation": null, - "type": 1, - "font": "Digits", + "x": 104, + "y": 168, + "alignment": 0, "conditions": [ { - "condition": 19, - "param": 3 - }, - { - "condition": 20, - "param": 0 + "condition": 15, + "param": 2 } ], - "children": null - } - }, - { - "widget": - { - "x": 2, - "y": 184, - "alignment": 16, - "tranmap": null, - "translation": null, - "type": 1, - "font": "Digits", - "conditions": + "children": [ { - "condition": 19, - "param": 3 + "graphic": + { + "x": 7, + "y": 4, + "alignment": 16, + "patch": "STGNUM2", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 2 + } + ], + "children": null + } }, { - "condition": 21, - "param": 0 - } - ], - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 16, - "alignment": 34, - "tranmap": null, - "translation": null, - "type": 2, - "font": "Digits", - "vertical_layout": 0, - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 8, - "alignment": 34, - "tranmap": null, - "translation": null, - "type": 32, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 0, - "alignment": 34, - "tranmap": null, - "translation": null, - "type": 3, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 0, - "y": 8, - "alignment": 0, - "tranmap": null, - "translation": null, - "type": 4, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 320, - "y": 200, - "alignment": 42, - "tranmap": null, - "translation": null, - "type": 5, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 160, - "y": 200, - "alignment": 9, - "tranmap": null, - "translation": null, - "type": 6, - "font": "Digits", - "conditions": null, - "children": null - } - }, - { - "widget": - { - "x": 2, - "y": 0, - "alignment": 16, - "tranmap": null, - "translation": null, - "type": 7, - "font": "Console", - "duration": 4, - "conditions": null, - "children": null - } - }, + "graphic": + { + "x": 7, + "y": 4, + "alignment": 16, + "patch": "STYSNUM2", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 2 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 4, + "alignment": 16, + "patch": "STGNUM3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 3 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 4, + "alignment": 16, + "patch": "STYSNUM3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 3 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 4, + "alignment": 16, + "patch": "STGNUM4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 4, + "alignment": 16, + "patch": "STYSNUM4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 7, + "y": 14, + "alignment": 16, + "patch": "STGNUM5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 7, + "y": 14, + "alignment": 16, + "patch": "STYSNUM5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 14, + "alignment": 16, + "patch": "STGNUM6", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 19, + "y": 14, + "alignment": 16, + "patch": "STYSNUM6", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 14, + "alignment": 16, + "patch": "STGNUM7", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 7, + "param": 7 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 31, + "y": 14, + "alignment": 16, + "patch": "STYSNUM7", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 6, + "param": 7 + } + ], + "children": null + } + } + ] + } + }, + { + "number": + { + "x": 288, + "y": 173, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 0, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 173, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 0, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 288, + "y": 179, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 1, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 179, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 1, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 288, + "y": 185, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 3, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 185, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 3, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 288, + "y": 191, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 3, + "param": 2, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "number": + { + "x": 314, + "y": 191, + "alignment": 34, + "font": "SmallYellow", + "tranmap": null, + "translation": null, + "type": 5, + "param": 2, + "maxlength": 3, + "conditions": null, + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS0", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 1 + }, + { + "condition": 11, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 11, + "param": 1 + }, + { + "condition": 10, + "param": 4 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS3", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 1 + }, + { + "condition": 10, + "param": 4 + }, + { + "condition": 13, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 171, + "alignment": 32, + "patch": "STKEYS6", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 1 + }, + { + "condition": 10, + "param": 4 + }, + { + "condition": 12, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS1", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 2 + }, + { + "condition": 11, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 11, + "param": 2 + }, + { + "condition": 10, + "param": 5 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS4", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 2 + }, + { + "condition": 10, + "param": 5 + }, + { + "condition": 13, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 181, + "alignment": 32, + "patch": "STKEYS7", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 2 + }, + { + "condition": 10, + "param": 5 + }, + { + "condition": 12, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS2", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 3 + }, + { + "condition": 11, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 11, + "param": 3 + }, + { + "condition": 10, + "param": 6 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS5", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 3 + }, + { + "condition": 10, + "param": 6 + }, + { + "condition": 13, + "param": 1 + } + ], + "children": null + } + }, + { + "graphic": + { + "x": 239, + "y": 191, + "alignment": 32, + "patch": "STKEYS8", + "tranmap": null, + "translation": null, + "conditions": + [ + { + "condition": 10, + "param": 3 + }, + { + "condition": 10, + "param": 6 + }, + { + "condition": 12, + "param": 1 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 160, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 152, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 160, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 152, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 144, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 152, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 16, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 2, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 8, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 32, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 0, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 3, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 8, + "alignment": 0, + "tranmap": null, + "translation": null, + "type": 4, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 167, + "alignment": 42, + "tranmap": null, + "translation": null, + "type": 5, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 160, + "y": 167, + "alignment": 9, + "tranmap": null, + "translation": null, + "type": 6, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, + "y": 0, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 7, + "font": "Console", + "duration": 4, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 160, + "y": 52, + "alignment": 1, + "tranmap": null, + "translation": null, + "type": 8, + "font": "Console", + "duration": 2.5, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, + "y": 0, + "alignment": 16, + "tranmap": null, + "translation": "CRGOLD", + "type": 9, + "font": "Console", + "under_messages": true, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, + "y": 160, + "alignment": 16, + "tranmap": null, + "translation": "CRGOLD", + "type": 10, + "font": "Console", + "conditions": + [ + { + "condition": 19, + "param": 3 + } + ], + "children": null + } + }, + { + "carousel": + { + "x": 0, + "y": 18, + "alignment": 0, + "tranmap": null, + "translation": null, + "conditions": null, + "children": null + } + } + ] + }, + { + "height": 200, + "fullscreenrender": true, + "fillflat": null, + "children": + [ + { + "widget": + { + "x": 2, + "y": 192, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "vertical_layout": 0, + "conditions": + [ + { + "condition": 19, + "param": 4 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 184, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 192, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 4 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 184, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 0, + "font": "Digits", + "vertical_layout": 0, + "conditions": + [ + { + "condition": 19, + "param": 3 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 176, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 20, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 184, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 1, + "font": "Digits", + "conditions": + [ + { + "condition": 19, + "param": 3 + }, + { + "condition": 21, + "param": 0 + } + ], + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 16, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 2, + "font": "Digits", + "vertical_layout": 0, + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 320, + "y": 8, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 32, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 0, + "alignment": 34, + "tranmap": null, + "translation": null, + "type": 3, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 2, + "y": 8, + "alignment": 0, + "tranmap": null, + "translation": null, + "type": 4, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 318, + "y": 200, + "alignment": 42, + "tranmap": null, + "translation": null, + "type": 5, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 160, + "y": 200, + "alignment": 9, + "tranmap": null, + "translation": null, + "type": 6, + "font": "Digits", + "conditions": null, + "children": null + } + }, + { + "widget": + { + "x": 0, + "y": 0, + "alignment": 16, + "tranmap": null, + "translation": null, + "type": 7, + "font": "Console", + "duration": 4, + "conditions": null, + "children": null + } + }, { "widget": { @@ -2265,7 +3320,7 @@ { "widget": { - "x": 2, + "x": 0, "y": 0, "alignment": 16, "tranmap": null, @@ -2280,7 +3335,7 @@ { "widget": { - "x": 2, + "x": 0, "y": 192, "alignment": 16, "tranmap": null, diff --git a/base/masterlevels.wad/umapdef.lmp b/base/masterlevels.wad/umapdef.lmp deleted file mode 100644 index 53719af18..000000000 --- a/base/masterlevels.wad/umapdef.lmp +++ /dev/null @@ -1,162 +0,0 @@ -map MAP01 -{ - levelname = "Attack" - levelpic = "CWILV00" -} - -map MAP02 -{ - levelname = "Canyon" - levelpic = "CWILV01" -} - -map MAP03 -{ - levelname = "The Catwalk" - levelpic = "CWILV02" -} - -map MAP04 -{ - levelname = "The Combine" - levelpic = "CWILV03" -} - -map MAP05 -{ - levelname = "The Fistula" - levelpic = "CWILV04" -} - -map MAP06 -{ - levelname = "The Garrison" - levelpic = "CWILV05" - intertext = clear -} - -map MAP07 -{ - levelname = "Titan Manor" - levelpic = "CWILV06" -} - -map MAP08 -{ - levelname = "Paradox" - levelpic = "CWILV07" -} - -map MAP09 -{ - levelname = "Subspace" - levelpic = "CWILV08" -} - -map MAP10 -{ - levelname = "Subterra" - levelpic = "CWILV09" -} - -map MAP11 -{ - levelname = "Trapped On Titan" - levelpic = "CWILV10" - intertext = clear -} - -map MAP12 -{ - levelname = "Virgil's Lead" - levelpic = "CWILV11" -} - -map MAP13 -{ - levelname = "Minos' Judgement" - levelpic = "CWILV12" -} - -map MAP14 -{ - levelname = "Bloodsea Keep" - levelpic = "CWILV13" - bossaction = Fatso, 23, 666 - bossaction = Arachnotron, 30, 667 -} - -map MAP15 -{ - levelname = "Mephisto's Maosoleum" - levelpic = "CWILV14" - bossaction = Fatso, 23, 666 - bossaction = Arachnotron, 30, 667 -} - -map MAP16 -{ - levelname = "Nessus" - levelpic = "CWILV15" - bossaction = Fatso, 23, 666 - bossaction = Arachnotron, 30, 667 -} - -map MAP17 -{ - levelname = "Geryon" - levelpic = "CWILV16" -} - -map MAP18 -{ - levelname = "Vesperas" - levelpic = "CWILV17" -} - -map MAP19 -{ - levelname = "Black Tower" - levelpic = "CWILV18" -} - -map MAP20 -{ - levelname = "The Express Elevator To Hell" - levelpic = "CWILV19" - nextsecret = "MAP21" - intertextsecret = clear - endcast = true - intertext = "CONGRATULATIONS YOU HAVE FINISHED... ", -"", -"MOST OF THE MASTER LEVELS", -"", -"You have ventured through the most", -"twisted levels that hell had to", -"offer and you have survived. ", -"", -"But alas the demons laugh at you", -"since you have shown cowardice and didn't", -"reach the most hideous level", -"they had made for you." -} - -map MAP21 -{ - levelname = "Bad Dream" - levelpic = "CWILV20" - endcast = true - intertext = "CONGRATULATIONS YOU HAVE FINISHED... ", -"", -"ALL THE MASTER LEVELS", -"", -"You have ventured through all the", -"twisted levels that hell had to", -"offer and you have survived. ", -"", -"The Flames of rage flow through", -"your veins, you are ready", -"for more - but you don't know where", -"to find more when the demons hide", -"like cowards when they see you." -} diff --git a/base/nerve.wad/umapdef.lmp b/base/nerve.wad/umapdef.lmp deleted file mode 100644 index 3d4477498..000000000 --- a/base/nerve.wad/umapdef.lmp +++ /dev/null @@ -1,111 +0,0 @@ -map MAP01 -{ - levelname = "The Earth Base" - label = "Level 1" - levelpic = "CWILV00" - music = "D_MESSAG" - skytexture = "SKY1" - partime = 75 -} - -map MAP02 -{ - levelname = "The Pain Labs" - label = "Level 2" - levelpic = "CWILV01" - music = "D_DDTBLU" - skytexture = "SKY1" - partime = 105 -} - -map MAP03 -{ - levelname = "Canyon of the Dead" - label = "Level 3" - levelpic = "CWILV02" - music = "D_DOOM" - skytexture = "SKY1" - partime = 120 -} - -map MAP04 -{ - levelname = "Hell Mountain" - label = "Level 4" - levelpic = "CWILV03" - music = "D_SHAWN" - nextsecret = "map09" - skytexture = "SKY3" - partime = 105 -} - -map MAP05 -{ - levelname = "Vivisection" - label = "Level 5" - levelpic = "CWILV04" - music = "D_IN_CIT" - skytexture = "SKY3" - partime = 210 -} - -map MAP06 -{ - levelname = "Inferno of Blood" - label = "Level 6" - levelpic = "CWILV05" - music = "D_THE_DA" - skytexture = "SKY3" - partime = 105 - intertext = clear -} - -map MAP07 -{ - levelname = "Baron's Banquet" - label = "Level 7" - levelpic = "CWILV06" - music = "D_IN_CIT" - skytexture = "SKY3" - partime = 165 -} - -map MAP08 -{ - levelname = "Tomb of Malevolence" - label = "Level 8" - levelpic = "CWILV07" - music = "D_SHAWN" - skytexture = "SKY3" - partime = 105 - endcast = true - intertext = "TROUBLE WAS BREWING AGAIN IN YOUR FAVORITE", -"VACATION SPOT... HELL. SOME CYBERDEMON", -"PUNK THOUGHT HE COULD TURN HELL INTO A", -"PERSONAL AMUSEMENT PARK, AND MAKE EARTH", -"THE TICKET BOOTH.", -"", -"WELL THAT HALF-ROBOT FREAK SHOW DIDN'T", -"KNOW WHO WAS COMING TO THE FAIR. THERE'S", -"NOTHING LIKE A SHOOTING GALLERY FULL OF", -"HELLSPAWN TO GET THE BLOOD PUMPING...", -"", -"NOW THE WALLS OF THE DEMON'S LABYRINTH", -"ECHO WITH THE SOUND OF HIS METALLIC LIMBS", -"HITTING THE FLOOR. HIS DEATH MOAN GURGLES", -"OUT THROUGH THE MESS YOU LEFT OF HIS FACE.", -"", -"THIS RIDE IS CLOSED." - interbackdrop = "SLIME16" -} - -map MAP09 -{ - levelname = "March of the Demons" - label = "Level 9" - levelpic = "CWILV08" - music = "D_DDTBLU" - next = "map05" - skytexture = "SKY1" - partime = 135 -} diff --git a/base/sigil_v1_21.wad/umapdef.lmp b/base/sigil_v1_21.wad/umapdef.lmp deleted file mode 100644 index 2f672769f..000000000 --- a/base/sigil_v1_21.wad/umapdef.lmp +++ /dev/null @@ -1,4 +0,0 @@ -map E5M8 -{ - bossaction = clear -} diff --git a/config.h.in b/config.h.in index 11cde77c6..abff4507f 100644 --- a/config.h.in +++ b/config.h.in @@ -6,6 +6,7 @@ #cmakedefine HAVE_DIRENT_H #cmakedefine01 HAVE_DECL_STRCASECMP #cmakedefine01 HAVE_DECL_STRNCASECMP +#cmakedefine HAVE_GETPWUID #cmakedefine HAVE_HIGH_RES_TIMER #cmakedefine HAVE__DIV64 #cmakedefine HAVE_ALSA diff --git a/docs/nughud.md b/docs/nughud.md index 4f9bf6af4..f78ed509f 100644 --- a/docs/nughud.md +++ b/docs/nughud.md @@ -1,7 +1,7 @@ # Nugget Doom's NUGHUD guide **The `NUGHUD` lump** is a variant of MBF's `OPTIONS` lump, **used exclusively by Nugget Doom to customize the fullscreen HUD** -used when the `screenblocks` CVAR is set to 11 and the _Fullscreen HUD Type_ setting is set to _NUGHUD_. +used when the `screenblocks` CVAR is set to the maximum size minus one (usually 12) and the _Use NUGHUD_ setting is enabled. From this point onwards, _NUGHUD_ refers to the customization system in general, whereas _`NUGHUD`_ refers to a NUGHUD lump. diff --git a/setup/multiplayer.c b/setup/multiplayer.c index bd332e9e1..b898b6f95 100644 --- a/setup/multiplayer.c +++ b/setup/multiplayer.c @@ -282,6 +282,7 @@ static void UpdateSkillButton(void) switch(iwad->mission) { case pack_chex: + case pack_chex3v: skillbutton->values = chex_skills; break; case pack_hacx: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1e7dbf020..e9eec9802 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ include(NuggetDoomSettings) set(NUGGETDOOM_SOURCES am_map.c am_map.h d_deh.c d_deh.h + d_demoloop.c d_demoloop.h d_englsh.h d_event.h d_french.h @@ -27,6 +28,7 @@ set(NUGGETDOOM_SOURCES g_game.c g_game.h g_input.c g_input.h g_nextweapon.c g_nextweapon.h + g_umapinfo.c g_umapinfo.h hu_command.c hu_command.h hu_coordinates.c hu_coordinates.h hu_crosshair.c hu_crosshair.h @@ -64,6 +66,7 @@ set(NUGGETDOOM_SOURCES m_input.c m_input.h m_io.c m_io.h m_json.c m_json.h + m_scanner.c m_scanner.h mn_font.c mn_font.h mn_menu.c mn_menu.h mn_setup.c mn_internal.h @@ -137,8 +140,6 @@ set(NUGGETDOOM_SOURCES st_widgets.c st_widgets.h statdump.c statdump.h tables.c tables.h - u_mapinfo.c u_mapinfo.h - u_scanner.c u_scanner.h v_flextran.c v_flextran.h v_fmt.c v_fmt.h v_trans.c v_trans.h diff --git a/src/am_map.c b/src/am_map.c index b4d6a2d7d..defe3ee48 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -2843,15 +2843,7 @@ void AM_Drawer (void) } if (automapoverlay == AM_OVERLAY_OFF) - { AM_clearFB(mapcolor_back); //jff 1/5/98 background default color - - // [Nugget] New weapon interpolation: don't need this - /* - if (automapactive == AM_FULL) // [Nugget] Minimap - pspr_interp = false; - */ - } // [Alaux] Dark automap overlay else if (automapoverlay == AM_OVERLAY_DARK) AM_shadeScreen(); diff --git a/src/d_deh.c b/src/d_deh.c index f6041deb5..8568257ec 100644 --- a/src/d_deh.c +++ b/src/d_deh.c @@ -1503,6 +1503,8 @@ char *deh_weapon[] = // mbf21 "Ammo per shot", // .ammopershot "MBF21 Bits", // .flags + // id24 + "Carousel icon", // .carouselicon }; // CHEATS - Dehacked block name = "Cheat" @@ -1558,124 +1560,124 @@ typedef struct { deh_bexptr deh_bexptrs[] = { - {{A_Light0}, "A_Light0"}, - {{A_WeaponReady}, "A_WeaponReady"}, - {{A_Lower}, "A_Lower"}, - {{A_Raise}, "A_Raise"}, - {{A_Punch}, "A_Punch"}, - {{A_ReFire}, "A_ReFire"}, - {{A_FirePistol}, "A_FirePistol"}, - {{A_Light1}, "A_Light1"}, - {{A_FireShotgun}, "A_FireShotgun"}, - {{A_Light2}, "A_Light2"}, - {{A_FireShotgun2}, "A_FireShotgun2"}, - {{A_CheckReload}, "A_CheckReload"}, - {{A_OpenShotgun2}, "A_OpenShotgun2"}, - {{A_LoadShotgun2}, "A_LoadShotgun2"}, - {{A_CloseShotgun2}, "A_CloseShotgun2"}, - {{A_FireCGun}, "A_FireCGun"}, - {{A_GunFlash}, "A_GunFlash"}, - {{A_FireMissile}, "A_FireMissile"}, - {{A_Saw}, "A_Saw"}, - {{A_FirePlasma}, "A_FirePlasma"}, - {{A_BFGsound}, "A_BFGsound"}, - {{A_FireBFG}, "A_FireBFG"}, - {{A_BFGSpray}, "A_BFGSpray"}, - {{A_Explode}, "A_Explode"}, - {{A_Pain}, "A_Pain"}, - {{A_PlayerScream}, "A_PlayerScream"}, - {{A_Fall}, "A_Fall"}, - {{A_XScream}, "A_XScream"}, - {{A_Look}, "A_Look"}, - {{A_Chase}, "A_Chase"}, - {{A_FaceTarget}, "A_FaceTarget"}, - {{A_PosAttack}, "A_PosAttack"}, - {{A_Scream}, "A_Scream"}, - {{A_SPosAttack}, "A_SPosAttack"}, - {{A_VileChase}, "A_VileChase"}, - {{A_VileStart}, "A_VileStart"}, - {{A_VileTarget}, "A_VileTarget"}, - {{A_VileAttack}, "A_VileAttack"}, - {{A_StartFire}, "A_StartFire"}, - {{A_Fire}, "A_Fire"}, - {{A_FireCrackle}, "A_FireCrackle"}, - {{A_Tracer}, "A_Tracer"}, - {{A_SkelWhoosh}, "A_SkelWhoosh"}, - {{A_SkelFist}, "A_SkelFist"}, - {{A_SkelMissile}, "A_SkelMissile"}, - {{A_FatRaise}, "A_FatRaise"}, - {{A_FatAttack1}, "A_FatAttack1"}, - {{A_FatAttack2}, "A_FatAttack2"}, - {{A_FatAttack3}, "A_FatAttack3"}, - {{A_BossDeath}, "A_BossDeath"}, - {{A_CPosAttack}, "A_CPosAttack"}, - {{A_CPosRefire}, "A_CPosRefire"}, - {{A_TroopAttack}, "A_TroopAttack"}, - {{A_SargAttack}, "A_SargAttack"}, - {{A_HeadAttack}, "A_HeadAttack"}, - {{A_BruisAttack}, "A_BruisAttack"}, - {{A_SkullAttack}, "A_SkullAttack"}, - {{A_Metal}, "A_Metal"}, - {{A_SpidRefire}, "A_SpidRefire"}, - {{A_BabyMetal}, "A_BabyMetal"}, - {{A_BspiAttack}, "A_BspiAttack"}, - {{A_Hoof}, "A_Hoof"}, - {{A_CyberAttack}, "A_CyberAttack"}, - {{A_PainAttack}, "A_PainAttack"}, - {{A_PainDie}, "A_PainDie"}, - {{A_KeenDie}, "A_KeenDie"}, - {{A_BrainPain}, "A_BrainPain"}, - {{A_BrainScream}, "A_BrainScream"}, - {{A_BrainDie}, "A_BrainDie"}, - {{A_BrainAwake}, "A_BrainAwake"}, - {{A_BrainSpit}, "A_BrainSpit"}, - {{A_SpawnSound}, "A_SpawnSound"}, - {{A_SpawnFly}, "A_SpawnFly"}, - {{A_BrainExplode}, "A_BrainExplode"}, - {{A_Detonate}, "A_Detonate"}, // killough 8/9/98 - {{A_Mushroom}, "A_Mushroom"}, // killough 10/98 - {{A_Die}, "A_Die"}, // killough 11/98 - {{A_Spawn}, "A_Spawn"}, // killough 11/98 - {{A_Turn}, "A_Turn"}, // killough 11/98 - {{A_Face}, "A_Face"}, // killough 11/98 - {{A_Scratch}, "A_Scratch"}, // killough 11/98 - {{A_PlaySound}, "A_PlaySound"}, // killough 11/98 - {{A_RandomJump}, "A_RandomJump"}, // killough 11/98 - {{A_LineEffect}, "A_LineEffect"}, // killough 11/98 - - {{A_FireOldBFG}, "A_FireOldBFG"}, // killough 7/19/98: classic BFG firing function - {{A_BetaSkullAttack}, "A_BetaSkullAttack"}, // killough 10/98: beta lost souls attacked different - {{A_Stop}, "A_Stop"}, + {{.p2 = A_Light0}, "A_Light0"}, + {{.p2 = A_WeaponReady}, "A_WeaponReady"}, + {{.p2 = A_Lower}, "A_Lower"}, + {{.p2 = A_Raise}, "A_Raise"}, + {{.p2 = A_Punch}, "A_Punch"}, + {{.p2 = A_ReFire}, "A_ReFire"}, + {{.p2 = A_FirePistol}, "A_FirePistol"}, + {{.p2 = A_Light1}, "A_Light1"}, + {{.p2 = A_FireShotgun}, "A_FireShotgun"}, + {{.p2 = A_Light2}, "A_Light2"}, + {{.p2 = A_FireShotgun2}, "A_FireShotgun2"}, + {{.p2 = A_CheckReload}, "A_CheckReload"}, + {{.p2 = A_OpenShotgun2}, "A_OpenShotgun2"}, + {{.p2 = A_LoadShotgun2}, "A_LoadShotgun2"}, + {{.p2 = A_CloseShotgun2}, "A_CloseShotgun2"}, + {{.p2 = A_FireCGun}, "A_FireCGun"}, + {{.p2 = A_GunFlash}, "A_GunFlash"}, + {{.p2 = A_FireMissile}, "A_FireMissile"}, + {{.p2 = A_Saw}, "A_Saw"}, + {{.p2 = A_FirePlasma}, "A_FirePlasma"}, + {{.p2 = A_BFGsound}, "A_BFGsound"}, + {{.p2 = A_FireBFG}, "A_FireBFG"}, + {{.p1 = A_BFGSpray}, "A_BFGSpray"}, + {{.p1 = A_Explode}, "A_Explode"}, + {{.p1 = A_Pain}, "A_Pain"}, + {{.p1 = A_PlayerScream}, "A_PlayerScream"}, + {{.p1 = A_Fall}, "A_Fall"}, + {{.p1 = A_XScream}, "A_XScream"}, + {{.p1 = A_Look}, "A_Look"}, + {{.p1 = A_Chase}, "A_Chase"}, + {{.p1 = A_FaceTarget}, "A_FaceTarget"}, + {{.p1 = A_PosAttack}, "A_PosAttack"}, + {{.p1 = A_Scream}, "A_Scream"}, + {{.p1 = A_SPosAttack}, "A_SPosAttack"}, + {{.p1 = A_VileChase}, "A_VileChase"}, + {{.p1 = A_VileStart}, "A_VileStart"}, + {{.p1 = A_VileTarget}, "A_VileTarget"}, + {{.p1 = A_VileAttack}, "A_VileAttack"}, + {{.p1 = A_StartFire}, "A_StartFire"}, + {{.p1 = A_Fire}, "A_Fire"}, + {{.p1 = A_FireCrackle}, "A_FireCrackle"}, + {{.p1 = A_Tracer}, "A_Tracer"}, + {{.p1 = A_SkelWhoosh}, "A_SkelWhoosh"}, + {{.p1 = A_SkelFist}, "A_SkelFist"}, + {{.p1 = A_SkelMissile}, "A_SkelMissile"}, + {{.p1 = A_FatRaise}, "A_FatRaise"}, + {{.p1 = A_FatAttack1}, "A_FatAttack1"}, + {{.p1 = A_FatAttack2}, "A_FatAttack2"}, + {{.p1 = A_FatAttack3}, "A_FatAttack3"}, + {{.p1 = A_BossDeath}, "A_BossDeath"}, + {{.p1 = A_CPosAttack}, "A_CPosAttack"}, + {{.p1 = A_CPosRefire}, "A_CPosRefire"}, + {{.p1 = A_TroopAttack}, "A_TroopAttack"}, + {{.p1 = A_SargAttack}, "A_SargAttack"}, + {{.p1 = A_HeadAttack}, "A_HeadAttack"}, + {{.p1 = A_BruisAttack}, "A_BruisAttack"}, + {{.p1 = A_SkullAttack}, "A_SkullAttack"}, + {{.p1 = A_Metal}, "A_Metal"}, + {{.p1 = A_SpidRefire}, "A_SpidRefire"}, + {{.p1 = A_BabyMetal}, "A_BabyMetal"}, + {{.p1 = A_BspiAttack}, "A_BspiAttack"}, + {{.p1 = A_Hoof}, "A_Hoof"}, + {{.p1 = A_CyberAttack}, "A_CyberAttack"}, + {{.p1 = A_PainAttack}, "A_PainAttack"}, + {{.p1 = A_PainDie}, "A_PainDie"}, + {{.p1 = A_KeenDie}, "A_KeenDie"}, + {{.p1 = A_BrainPain}, "A_BrainPain"}, + {{.p1 = A_BrainScream}, "A_BrainScream"}, + {{.p1 = A_BrainDie}, "A_BrainDie"}, + {{.p1 = A_BrainAwake}, "A_BrainAwake"}, + {{.p1 = A_BrainSpit}, "A_BrainSpit"}, + {{.p1 = A_SpawnSound}, "A_SpawnSound"}, + {{.p1 = A_SpawnFly}, "A_SpawnFly"}, + {{.p1 = A_BrainExplode}, "A_BrainExplode"}, + {{.p1 = A_Detonate}, "A_Detonate"}, // killough 8/9/98 + {{.p1 = A_Mushroom}, "A_Mushroom"}, // killough 10/98 + {{.p1 = A_Die}, "A_Die"}, // killough 11/98 + {{.p1 = A_Spawn}, "A_Spawn"}, // killough 11/98 + {{.p1 = A_Turn}, "A_Turn"}, // killough 11/98 + {{.p1 = A_Face}, "A_Face"}, // killough 11/98 + {{.p1 = A_Scratch}, "A_Scratch"}, // killough 11/98 + {{.p1 = A_PlaySound}, "A_PlaySound"}, // killough 11/98 + {{.p1 = A_RandomJump}, "A_RandomJump"}, // killough 11/98 + {{.p1 = A_LineEffect}, "A_LineEffect"}, // killough 11/98 + + {{.p2 = A_FireOldBFG}, "A_FireOldBFG"}, // killough 7/19/98: classic BFG firing function + {{.p1 = A_BetaSkullAttack}, "A_BetaSkullAttack"}, // killough 10/98: beta lost souls attacked different + {{.p1 = A_Stop}, "A_Stop"}, // [XA] New mbf21 codepointers - {{A_SpawnObject}, "A_SpawnObject", 8}, - {{A_MonsterProjectile}, "A_MonsterProjectile", 5}, - {{A_MonsterBulletAttack}, "A_MonsterBulletAttack", 5, {0, 0, 1, 3, 5}}, - {{A_MonsterMeleeAttack}, "A_MonsterMeleeAttack", 4, {3, 8, 0, 0}}, - {{A_RadiusDamage}, "A_RadiusDamage", 2}, - {{A_NoiseAlert}, "A_NoiseAlert", 0}, - {{A_HealChase}, "A_HealChase", 2}, - {{A_SeekTracer}, "A_SeekTracer", 2}, - {{A_FindTracer}, "A_FindTracer", 2, {0, 10}}, - {{A_ClearTracer}, "A_ClearTracer", 0}, - {{A_JumpIfHealthBelow}, "A_JumpIfHealthBelow", 2}, - {{A_JumpIfTargetInSight}, "A_JumpIfTargetInSight", 2}, - {{A_JumpIfTargetCloser}, "A_JumpIfTargetCloser", 2}, - {{A_JumpIfTracerInSight}, "A_JumpIfTracerInSight", 2}, - {{A_JumpIfTracerCloser}, "A_JumpIfTracerCloser", 2}, - {{A_JumpIfFlagsSet}, "A_JumpIfFlagsSet", 3}, - {{A_AddFlags}, "A_AddFlags", 2}, - {{A_RemoveFlags}, "A_RemoveFlags", 2}, - {{A_WeaponProjectile}, "A_WeaponProjectile", 5}, - {{A_WeaponBulletAttack}, "A_WeaponBulletAttack", 5, {0, 0, 1, 5, 3}}, - {{A_WeaponMeleeAttack}, "A_WeaponMeleeAttack", 5, {2, 10, 1 * FRACUNIT, 0, 0}}, - {{A_WeaponSound}, "A_WeaponSound", 2}, - {{A_WeaponAlert}, "A_WeaponAlert", 0}, - {{A_WeaponJump}, "A_WeaponJump", 2}, - {{A_ConsumeAmmo}, "A_ConsumeAmmo", 1}, - {{A_CheckAmmo}, "A_CheckAmmo", 2}, - {{A_RefireTo}, "A_RefireTo", 2}, - {{A_GunFlashTo}, "A_GunFlashTo", 2}, + {{.p1 = A_SpawnObject}, "A_SpawnObject", 8}, + {{.p1 = A_MonsterProjectile}, "A_MonsterProjectile", 5}, + {{.p1 = A_MonsterBulletAttack}, "A_MonsterBulletAttack", 5, {0, 0, 1, 3, 5}}, + {{.p1 = A_MonsterMeleeAttack}, "A_MonsterMeleeAttack", 4, {3, 8, 0, 0}}, + {{.p1 = A_RadiusDamage}, "A_RadiusDamage", 2}, + {{.p1 = A_NoiseAlert}, "A_NoiseAlert", 0}, + {{.p1 = A_HealChase}, "A_HealChase", 2}, + {{.p1 = A_SeekTracer}, "A_SeekTracer", 2}, + {{.p1 = A_FindTracer}, "A_FindTracer", 2, {0, 10}}, + {{.p1 = A_ClearTracer}, "A_ClearTracer", 0}, + {{.p1 = A_JumpIfHealthBelow}, "A_JumpIfHealthBelow", 2}, + {{.p1 = A_JumpIfTargetInSight}, "A_JumpIfTargetInSight", 2}, + {{.p1 = A_JumpIfTargetCloser}, "A_JumpIfTargetCloser", 2}, + {{.p1 = A_JumpIfTracerInSight}, "A_JumpIfTracerInSight", 2}, + {{.p1 = A_JumpIfTracerCloser}, "A_JumpIfTracerCloser", 2}, + {{.p1 = A_JumpIfFlagsSet}, "A_JumpIfFlagsSet", 3}, + {{.p1 = A_AddFlags}, "A_AddFlags", 2}, + {{.p1 = A_RemoveFlags}, "A_RemoveFlags", 2}, + {{.p2 = A_WeaponProjectile}, "A_WeaponProjectile", 5}, + {{.p2 = A_WeaponBulletAttack}, "A_WeaponBulletAttack", 5, {0, 0, 1, 5, 3}}, + {{.p2 = A_WeaponMeleeAttack}, "A_WeaponMeleeAttack", 5, {2, 10, 1 * FRACUNIT, 0, 0}}, + {{.p2 = A_WeaponSound}, "A_WeaponSound", 2}, + {{.p2 = A_WeaponAlert}, "A_WeaponAlert", 0}, + {{.p2 = A_WeaponJump}, "A_WeaponJump", 2}, + {{.p2 = A_ConsumeAmmo}, "A_ConsumeAmmo", 1}, + {{.p2 = A_CheckAmmo}, "A_CheckAmmo", 2}, + {{.p2 = A_RefireTo}, "A_RefireTo", 2}, + {{.p2 = A_GunFlashTo}, "A_GunFlashTo", 2}, // This NULL entry must be the last in the list {{NULL}, "A_NULL"}, // Ty 05/16/98 @@ -2566,7 +2568,20 @@ void deh_procWeapon(DEHFILE *fpin, FILE* fpout, char *line) weaponinfo[indexnum].flags = value; } - else + else + if (!strcasecmp(key, deh_weapon[8])) // Carousel icon + { + char candidate[9] = {0}; + M_CopyLumpName(candidate, ptr_lstrip(strval)); + int len = strlen(candidate); + if (len < 1 || len > 7) + { + if (fpout) fprintf(fpout,"Bad length for carousel icon name '%s'\n",candidate); + continue; + } + weaponinfo[indexnum].carouselicon = M_StringDuplicate(candidate); + } + else if (fpout) fprintf(fpout,"Invalid weapon string index for '%s'\n",key); } return; @@ -3397,7 +3412,7 @@ void rstrip(char *s) // strip trailing whitespace // char *ptr_lstrip(char *p) // point past leading whitespace { - while (*p >= 0 && isspace(*p)) + while (*p && isspace(*p)) p++; return p; } diff --git a/src/d_demoloop.c b/src/d_demoloop.c new file mode 100644 index 000000000..66a2cd241 --- /dev/null +++ b/src/d_demoloop.c @@ -0,0 +1,181 @@ +// +// Copyright (C) 2025 Guilherme Miranda +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// DESCRIPTION: +// ID24 DemoLoop Specification - User customizable title screen sequence. +// Though originally hardcoded on the original Doom engine this allows +// for Doom modders to define custom sequences, using any provided custom +// graphic-and-music, or DEMO lump. +// + +#include "doomdef.h" +#include "doomstat.h" + +#include "i_printf.h" +#include "m_array.h" +#include "m_json.h" +#include "m_misc.h" + +#include "d_demoloop.h" + +// Doom +static demoloop_entry_t demoloop_registered[] = { + { "TITLEPIC", "D_INTRO", 170, TYPE_ART, WIPE_MELT }, + { "DEMO1", "", 0, TYPE_DEMO, WIPE_MELT }, + { "CREDIT", "", 200, TYPE_ART, WIPE_MELT }, + { "DEMO2", "", 0, TYPE_DEMO, WIPE_MELT }, + { "HELP2", "", 200, TYPE_ART, WIPE_MELT }, + { "DEMO3", "", 0, TYPE_DEMO, WIPE_MELT }, +}; + +// Ultimate Doom +static demoloop_entry_t demoloop_retail[] = { + { "TITLEPIC", "D_INTRO", 170, TYPE_ART, WIPE_MELT }, + { "DEMO1", "", 0, TYPE_DEMO, WIPE_MELT }, + { "CREDIT", "", 200, TYPE_ART, WIPE_MELT }, + { "DEMO2", "", 0, TYPE_DEMO, WIPE_MELT }, + { "CREDIT", "", 200, TYPE_ART, WIPE_MELT }, + { "DEMO3", "", 0, TYPE_DEMO, WIPE_MELT }, + { "DEMO4", "", 0, TYPE_DEMO, WIPE_MELT }, +}; + +// Doom II & Final Doom +static demoloop_entry_t demoloop_commercial[] = { + { "TITLEPIC", "D_DM2TTL", 385, TYPE_ART, WIPE_MELT }, + { "DEMO1", "", 0, TYPE_DEMO, WIPE_MELT }, + { "CREDIT", "", 200, TYPE_ART, WIPE_MELT }, + { "DEMO2", "", 0, TYPE_DEMO, WIPE_MELT }, + { "TITLEPIC", "D_DM2TTL", 385, TYPE_ART, WIPE_MELT }, + { "DEMO3", "", 0, TYPE_DEMO, WIPE_MELT }, + { "DEMO4", "", 0, TYPE_DEMO, WIPE_MELT }, +}; + +demoloop_t demoloop = NULL; +int demoloop_count = 0; + +void D_ParseDemoLoopEntry(json_t *entry) +{ + const char* primary_buffer = JS_GetStringValue(entry, "primarylump"); + const char* secondary_buffer = JS_GetStringValue(entry, "secondarylump"); + double seconds = JS_GetNumberValue(entry, "duration"); + int type = JS_GetIntegerValue(entry, "type"); + int outro_wipe = JS_GetIntegerValue(entry, "outro_wipe"); + + // We don't want a malformed entry to creep in, and break the titlescreen. + // If one such entry does exist, skip it. + // TODO: modify later to check locally for lump type. + if (primary_buffer == NULL || secondary_buffer == NULL || type < TYPE_ART + || type > TYPE_DEMO) + { + return; + } + + // Similarly, but this time it isn't game-breaking. + // Let it gracefully default to "closest vanilla behavior". + if (outro_wipe <= WIPE_NONE || outro_wipe > WIPE_MELT) + { + outro_wipe = WIPE_MELT; + } + + demoloop_entry_t current_entry = {0}; + + // Remove pointer reference to in-memory JSON data. + M_CopyLumpName(current_entry.primary_lump, primary_buffer); + M_CopyLumpName(current_entry.secondary_lump, secondary_buffer); + // Providing the time in seconds is much more intuitive for the end users. + current_entry.duration = seconds * TICRATE; + current_entry.type = type; + current_entry.outro_wipe = outro_wipe; + + array_push(demoloop, current_entry); +} + +static void D_ParseDemoLoop(void) +{ + // Does the JSON lump even exist? + json_t *json = JS_Open("DEMOLOOP", "demoloop", (version_t){1, 0, 0}); + if (json == NULL) + { + return; + } + + // Does lump actually have any data? + json_t *data = JS_GetObject(json, "data"); + if (JS_IsNull(data) || !JS_IsObject(data)) + { + I_Printf(VB_WARNING, "DEMOLOOP: data object not defined"); + JS_Close("DEMOLOOP"); + return; + } + + // Does is it even have the definitions we are looking for? + json_t *entry_list = JS_GetObject(data, "entries"); + if (JS_IsNull(entry_list) || !JS_IsArray(entry_list)) + { + I_Printf(VB_WARNING, "DEMOLOOP: no entries defined"); + JS_Close("DEMOLOOP"); + return; + } + + // If so, now parse them. + json_t *entry; + JS_ArrayForEach(entry, entry_list) + { + D_ParseDemoLoopEntry(entry); + } + demoloop_count = array_size(demoloop); + + // No need to keep in memory + JS_Close("DEMOLOOP"); +} + +static void D_GetDefaultDemoLoop(GameMode_t mode) +{ + switch(mode) + { + case shareware: + case registered: + demoloop = demoloop_registered; + demoloop_count = arrlen(demoloop_registered); + break; + + case retail: + demoloop = demoloop_retail; + demoloop_count = arrlen(demoloop_retail); + break; + + case commercial: + demoloop = demoloop_commercial; + demoloop_count = arrlen(demoloop_commercial); + break; + + case indetermined: + default: + // How did we get here? + demoloop = NULL; + demoloop_count = 0; + break; + } + + return; +} + +void D_SetupDemoLoop(void) +{ + D_ParseDemoLoop(); + + if (demoloop == NULL) + { + D_GetDefaultDemoLoop(gamemode); + } +} diff --git a/src/d_demoloop.h b/src/d_demoloop.h new file mode 100644 index 000000000..14355660b --- /dev/null +++ b/src/d_demoloop.h @@ -0,0 +1,60 @@ +// +// Copyright (C) 2025 Guilherme Miranda +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// DESCRIPTION: +// ID24 DemoLoop Specification - User customizable title screen sequence. +// Though originally hardcoded on the original Doom engine this allows +// for Doom modders to define custom sequences, using any provided custom +// graphic, music or DEMO lump. +// + +#ifndef _D_DEMOLOOP_ +#define _D_DEMOLOOP_ + +// Screen graphic or DEMO lump, NONE is used for fault tolerance. +typedef enum +{ + TYPE_ART, + TYPE_DEMO, +} dl_type_t; + +// Immediate switch or screen melt, NONE is used for fault tolerance. +// TODO: reimplement more cleanly at a later, more relevant moment +typedef enum +{ + WIPE_NONE = -1, + WIPE_IMMEDIATE, + WIPE_MELT, +} dl_wipe_t; + +// Individual demoloop units. +typedef struct +{ + char primary_lump[9]; // Screen graphic or DEMO lump. + char secondary_lump[9]; // Music lump for screen graphic. + int duration; // Game tics. + dl_type_t type; + dl_wipe_t outro_wipe; +} demoloop_entry_t; + +typedef demoloop_entry_t* demoloop_t; + +// Actual DemoLoop data structure. +extern demoloop_t demoloop; +// Formerly 7 for Ultimate Doom & Final Doom, 6 otherwise. +extern int demoloop_count; + +// Perform both "D_ParseDemoLoop" and "D_GetDefaultDemoLoop". +void D_SetupDemoLoop(void); + +#endif // _D_DEMOLOOP_ diff --git a/src/d_items.h b/src/d_items.h index a120a69b9..b53624806 100644 --- a/src/d_items.h +++ b/src/d_items.h @@ -59,6 +59,7 @@ typedef struct int flags; // id24 int slot; + const char *carouselicon; } weaponinfo_t; extern weaponinfo_t weaponinfo[NUMWEAPONS+2]; diff --git a/src/d_iwad.c b/src/d_iwad.c index 040aee3bb..781ad6672 100644 --- a/src/d_iwad.c +++ b/src/d_iwad.c @@ -28,24 +28,26 @@ #include "m_misc.h" static const iwad_t iwads[] = { - {"doom2.wad", doom2, commercial, "DOOM II: Hell on Earth" }, - {"plutonia.wad", pack_plut, commercial, "Final DOOM: Plutonia Experiment"}, - {"tnt.wad", pack_tnt, commercial, "Final DOOM: TNT - Evilution" }, + {"doom2.wad", doom2, commercial, "DOOM II: Hell on Earth" }, + {"plutonia.wad", pack_plut, commercial, "Final DOOM: Plutonia Experiment"}, + {"tnt.wad", pack_tnt, commercial, "Final DOOM: TNT - Evilution" }, // "doom.wad" may be retail or registered - {"doom.wad", doom, indetermined, "DOOM" }, - {"doom.wad", doom, registered, "DOOM Registered" }, - {"doom.wad", doom, retail, "The Ultimate DOOM" }, + {"doom.wad", doom, indetermined, "DOOM" }, + {"doom.wad", doom, registered, "DOOM Registered" }, + {"doom.wad", doom, retail, "The Ultimate DOOM" }, // "doomu.wad" alias to allow retail wad to coexist with registered in the same folder - {"doomu.wad", doom, retail, "The Ultimate DOOM" }, - {"doom1.wad", doom, shareware, "DOOM Shareware" }, - {"doom2f.wad", doom2, commercial, "DOOM II: L'Enfer sur Terre" }, - {"freedoom2.wad", doom2, commercial, "Freedoom: Phase 2" }, - {"freedoom1.wad", doom, retail, "Freedoom: Phase 1" }, - {"freedm.wad", doom2, commercial, "FreeDM" }, - {"chex.wad", pack_chex, retail, "Chex Quest" }, - {"hacx.wad", pack_hacx, commercial, "HACX: Twitch n' Kill" }, - {"rekkrsa.wad", pack_rekkr, retail, "REKKR" }, - {"rekkrsl.wad", pack_rekkr, retail, "REKKR: Sunken Land" }, + {"doomu.wad", doom, retail, "The Ultimate DOOM" }, + {"doom1.wad", doom, shareware, "DOOM Shareware" }, + {"doom2f.wad", doom2, commercial, "DOOM II: L'Enfer sur Terre" }, + {"freedoom2.wad", doom2, commercial, "Freedoom: Phase 2" }, + {"freedoom1.wad", doom, retail, "Freedoom: Phase 1" }, + {"freedm.wad", doom2, commercial, "FreeDM" }, + {"chex.wad", pack_chex, retail, "Chex Quest" }, + {"chex3v.wad", pack_chex3v, retail, "Chex Quest 3: Vanilla Edition" }, + {"chex3d2.wad", pack_chex3v, commercial, "Chex Quest 3: Modding Edition" }, + {"hacx.wad", pack_hacx, commercial, "HACX: Twitch n' Kill" }, + {"rekkrsa.wad", pack_rekkr, retail, "REKKR" }, + {"rekkrsl.wad", pack_rekkr, retail, "REKKR: Sunken Land" }, }; static const char *const gamemode_str[] = { @@ -56,24 +58,11 @@ static const char *const gamemode_str[] = { "Unknown mode" }; -// "128 IWAD search directories should be enough for anybody". - -#define MAX_IWAD_DIRS 128 - // Array of locations to search for IWAD files +#define M_ARRAY_INIT_CAPACITY 32 +#include "m_array.h" -static boolean iwad_dirs_built = false; -char *iwad_dirs[MAX_IWAD_DIRS]; -int num_iwad_dirs = 0; - -static void AddIWADDir(char *dir) -{ - if (num_iwad_dirs < MAX_IWAD_DIRS) - { - iwad_dirs[num_iwad_dirs] = dir; - ++num_iwad_dirs; - } -} +static char **iwad_dirs; // Return the path where the executable lies -- Lee Killough @@ -100,6 +89,38 @@ char *D_DoomExeDir(void) return base; } +// [FG] get the path to the default configuration dir to use + +char *D_DoomPrefDir(void) +{ + static char *dir; + + if (dir == NULL) + { +#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 = SDL_GetPrefPath("", PROJECT_SHORTNAME); + if (result != NULL) + { + dir = M_DirName(result); + SDL_free(result); + } + else +#endif /* #ifndef _WIN32 */ + { + dir = D_DoomExeDir(); + } + + M_MakeDirectory(dir); + } + + return dir; +} + // 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 @@ -353,7 +374,7 @@ static void CheckUninstallStrings(void) { path = unstr + strlen(UNINSTALLER_STRING); - AddIWADDir(path); + array_push(iwad_dirs, path); } } } @@ -381,7 +402,7 @@ static void CheckInstallRootPaths(void) { subpath = M_StringJoin(install_path, DIR_SEPARATOR_S, root_path_subdirs[j]); - AddIWADDir(subpath); + array_push(iwad_dirs, subpath); } free(install_path); @@ -408,7 +429,7 @@ static void CheckSteamEdition(void) subpath = M_StringJoin(install_path, DIR_SEPARATOR_S, steam_install_subdirs[i]); - AddIWADDir(subpath); + array_push(iwad_dirs, subpath); } free(install_path); @@ -421,26 +442,17 @@ 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"); + array_push(iwad_dirs, "\\doom2"); // Doom II + array_push(iwad_dirs, "\\plutonia"); // Final Doom + array_push(iwad_dirs, "\\tnt"); + array_push(iwad_dirs, "\\doom_se"); // Ultimate Doom + array_push(iwad_dirs, "\\doom"); // Shareware / Registered Doom + array_push(iwad_dirs, "\\dooms"); // Shareware versions + array_push(iwad_dirs, "\\doomsw"); } #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); -} - // Add IWAD directories parsed from splitting a path string containing // paths separated by PATH_SEPARATOR. 'suffix' is a string to concatenate // to the end of the paths before adding them. @@ -462,7 +474,7 @@ static void AddIWADPath(const char *path, const char *suffix) // as another iwad dir *p = '\0'; - AddIWADDir(M_StringJoin(left, suffix)); + array_push(iwad_dirs, M_StringJoin(left, suffix)); left = p + 1; } else @@ -471,7 +483,7 @@ static void AddIWADPath(const char *path, const char *suffix) } } - AddIWADDir(M_StringJoin(left, suffix)); + array_push(iwad_dirs, M_StringJoin(left, suffix)); free(dup_path); } @@ -484,33 +496,12 @@ static void AddIWADPath(const char *path, const char *suffix) // <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html> static void AddXdgDirs(void) { - char *env, *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 = M_getenv("XDG_DATA_HOME"); - tmp_env = NULL; - - if (env == NULL) - { - char *homedir = M_getenv("HOME"); - if (homedir == NULL) - { - homedir = "/"; - } - - tmp_env = M_StringJoin(homedir, "/.local/share"); - env = tmp_env; - } + char *env = M_DataDir(); // 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")); - free(tmp_env); + array_push(iwad_dirs, M_StringJoin(env, "/games/doom")); // Quote: // > $XDG_DATA_DIRS defines the preference-ordered set of base @@ -548,11 +539,7 @@ static void AddSteamDirs(void) { char *homedir, *steampath; - homedir = M_getenv("HOME"); - if (homedir == NULL) - { - homedir = "/"; - } + homedir = M_HomeDir(); steampath = M_StringJoin(homedir, "/.steam/root/steamapps/common"); AddIWADPath(steampath, "/Doom 2/base"); @@ -569,27 +556,31 @@ static void AddSteamDirs(void) // Build a list of IWAD files // +static char **iwad_dirs_append; + void BuildIWADDirList(void) { char *env; - if (iwad_dirs_built) + if (array_size(iwad_dirs) > 0) { return; } // Look in the current directory. Doom always does this. - AddIWADDir("."); + array_push(iwad_dirs, "."); // Next check the directory where the executable is located. This might // be different from the current directory. - AddIWADDir(D_DoomExeDir()); + // D_DoomPrefDir() returns the executable directory on Windows, + // and a user-writable config directory everywhere else. + array_push(iwad_dirs, D_DoomPrefDir()); // Add DOOMWADDIR if it is in the environment env = M_getenv("DOOMWADDIR"); if (env != NULL) { - AddIWADDir(env); + array_push(iwad_dirs, env); } // Add dirs from DOOMWADPATH: @@ -599,13 +590,6 @@ void BuildIWADDirList(void) AddIWADPath(env, ""); } - // [FG] Add plain HOME directory - env = M_getenv("HOME"); - if (env != NULL) - { - AddIWADDir(env); - } - #ifdef _WIN32 // Search the registry and find where IWADs have been installed. @@ -622,9 +606,11 @@ void BuildIWADDirList(void) # endif #endif - // Don't run this function again. - - iwad_dirs_built = true; + char **dir; + array_foreach(dir, iwad_dirs_append) + { + array_push(iwad_dirs, *dir); + } } // @@ -633,9 +619,7 @@ void BuildIWADDirList(void) char *D_FindWADByName(const char *name) { - char *path; char *probe; - int i; // Absolute path? @@ -649,14 +633,15 @@ char *D_FindWADByName(const char *name) // Search through all IWAD paths for a file with the given name. - for (i = 0; i < num_iwad_dirs; ++i) + char **dir; + array_foreach(dir, iwad_dirs) { // As a special case, if this is in DOOMWADDIR or DOOMWADPATH, // the "directory" may actually refer directly to an IWAD // file. - probe = M_FileCaseExists(iwad_dirs[i]); - if (DirIsFile(iwad_dirs[i], name) && probe != NULL) + probe = M_FileCaseExists(*dir); + if (probe != NULL) { return probe; } @@ -664,7 +649,7 @@ char *D_FindWADByName(const char *name) // Construct a string for the full path - path = M_StringJoin(iwad_dirs[i], DIR_SEPARATOR_S, name); + char *path = M_StringJoin(*dir, DIR_SEPARATOR_S, name); probe = M_FileCaseExists(path); if (probe != NULL) @@ -769,8 +754,7 @@ char *D_FindIWADFile(void) char *iwadfile = myargv[iwadparm + 1]; - char *file = malloc(strlen(iwadfile) + 5); - AddDefaultExtension(strcpy(file, iwadfile), ".wad"); + char *file = AddDefaultExtension(iwadfile, ".wad"); result = D_FindWADByName(file); @@ -778,6 +762,11 @@ char *D_FindIWADFile(void) { I_Error("IWAD file '%s' not found!", file); } + else + { + char *iwad_dir = M_DirName(result); + array_push(iwad_dirs_append, iwad_dir); + } free(file); } diff --git a/src/d_iwad.h b/src/d_iwad.h index c527df866..28ecef55b 100644 --- a/src/d_iwad.h +++ b/src/d_iwad.h @@ -30,6 +30,7 @@ typedef struct } iwad_t; char *D_DoomExeDir(void); // killough 2/16/98: path to executable's dir +char *D_DoomPrefDir(void); // [FG] default configuration dir char *D_FindWADByName(const char *filename); char *D_TryFindWADByName(const char *filename); char *D_FindLMPByName(const char *filename); diff --git a/src/d_main.c b/src/d_main.c index 9ea4ae576..1e2864629 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -29,6 +29,7 @@ #include "am_map.h" #include "config.h" #include "d_deh.h" // Ty 04/08/98 - Externalizations +#include "d_demoloop.h" #include "d_event.h" #include "d_iwad.h" #include "d_loop.h" @@ -80,7 +81,7 @@ #include "st_stuff.h" #include "st_widgets.h" #include "statdump.h" -#include "u_mapinfo.h" +#include "g_umapinfo.h" #include "v_fmt.h" #include "v_video.h" #include "w_wad.h" @@ -268,7 +269,7 @@ void D_Display (void) static boolean viewactivestate = false; static boolean menuactivestate = false; static gamestate_t oldgamestate = GS_NONE; - static int borderdrawcount; + static boolean borderdrawcount; int wipestart; boolean done, wipe; @@ -320,7 +321,7 @@ void D_Display (void) { R_ExecuteSetViewSize(); oldgamestate = GS_NONE; // force background redraw - borderdrawcount = 3; + borderdrawcount = true; } if (gamestate == GS_LEVEL && gametic) @@ -364,11 +365,11 @@ void D_Display (void) if (gamestate == GS_LEVEL && automap_off && scaledviewwidth != video.unscaledw) { if (menuactive || menuactivestate || !viewactivestate) - borderdrawcount = 3; + borderdrawcount = true; if (borderdrawcount) { R_DrawViewBorder(); // erase old menu stuff - borderdrawcount--; + borderdrawcount = false; } } @@ -446,7 +447,8 @@ void D_Display (void) static int demosequence; // killough 5/2/98: made static static int pagetic; -static char *pagename; +static const char *pagename; +static demoloop_t demoloop_point; static int no_page_ticking; // [Nugget] @@ -484,15 +486,17 @@ void D_PageDrawer(void) // Called after each demo or intro demosequence finishes // -void D_AdvanceDemo (void) +void D_AdvanceDemo(void) { advancedemo = true; } -// // This cycles through the demo sequences. -// FIXME - version dependend demo numbers? -// +void D_AdvanceDemoLoop(void) +{ + demosequence = (demosequence + 1) % demoloop_count; + demoloop_point = &demoloop[demosequence]; +} void D_DoAdvanceDemo(void) { @@ -502,94 +506,48 @@ void D_DoAdvanceDemo(void) 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 (W_CheckNumForName("DEMO4") >= 0) + D_AdvanceDemoLoop(); + switch (demoloop_point->type) { - demosequence = (demosequence + 1) % 7; - } - else - { - demosequence = (demosequence + 1) % 6; - } - - switch (demosequence) - { - case 0: - if (gamemode == commercial) - { - pagetic = TICRATE * 11; - } - else - { - pagetic = 170; - } + case TYPE_ART: gamestate = GS_DEMOSCREEN; - pagename = "TITLEPIC"; - if (gamemode == commercial) + + // Needed to support the Doom 3: BFG Edition variant + if (W_CheckNumForName(demoloop_point->primary_lump) < 0 + && !strcasecmp(demoloop_point->primary_lump, "TITLEPIC")) { - S_StartMusic(mus_dm2ttl); + M_CopyLumpName(demoloop_point->primary_lump, "DMENUPIC"); } - else + + if (W_CheckNumForName(demoloop_point->primary_lump) >= 0) { - S_StartMusic(mus_intro); + pagename = demoloop_point->primary_lump; + pagetic = demoloop_point->duration; + int music = W_CheckNumForName(demoloop_point->secondary_lump); + if (music >= 0) + { + S_ChangeMusInfoMusic(music, false); + } + break; } - break; - case 1: - G_DeferedPlayDemo("DEMO1"); - break; - case 2: - pagetic = 200; - gamestate = GS_DEMOSCREEN; - pagename = "CREDIT"; - break; - case 3: - G_DeferedPlayDemo("DEMO2"); - break; - case 4: + // fallthrough + + case TYPE_DEMO: gamestate = GS_DEMOSCREEN; - if (gamemode == commercial) + + if (W_CheckNumForName(demoloop_point->primary_lump) >= 0) { - pagetic = TICRATE * 11; - pagename = "TITLEPIC"; - S_StartMusic(mus_dm2ttl); + G_DeferedPlayDemo(demoloop_point->primary_lump); + break; } - else - { - pagetic = 200; + // fallthrough - if (gameversion >= exe_ultimate) - { - pagename = "CREDIT"; - } - else - { - pagename = "HELP2"; - } - } - break; - case 5: - G_DeferedPlayDemo("DEMO3"); - break; - // THE DEFINITIVE DOOM Special Edition demo - case 6: - G_DeferedPlayDemo("DEMO4"); + default: + I_Printf(VB_WARNING, + "D_DoAdvanceDemo: Invalid demoloop[%d] entry, skipping", + demosequence); break; } - - // The Doom 3: BFG Edition version of doom2.wad does not have a - // TITLETPIC lump. - if (!strcasecmp(pagename, "TITLEPIC") && W_CheckNumForName("TITLEPIC") < 0) - { - pagename = "DMENUPIC"; - } } // @@ -622,54 +580,9 @@ void D_AddFile(const char *file) } // killough 10/98: return the name of the program the exe was invoked as -char *D_DoomExeName(void) +const char *D_DoomExeName(void) { - static char *name; - - if (!name) // cache multiple requests - { - char *ext; - - name = M_StringDuplicate(M_BaseName(myargv[0])); - - ext = strrchr(name, '.'); - if (ext) - *ext = '\0'; - } - - return name; -} - -// [FG] get the path to the default configuration dir to use - -char *D_DoomPrefDir(void) -{ - static char *dir; - - if (dir == NULL) - { -#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 = SDL_GetPrefPath("", PROJECT_SHORTNAME); - if (result != NULL) - { - dir = M_DirName(result); - SDL_free(result); - } - else -#endif /* #ifndef _WIN32 */ - { - dir = D_DoomExeDir(); - } - - M_MakeDirectory(dir); - } - - return dir; + return PROJECT_SHORTNAME; } // Calculate the path to the directory for autoloaded WADs/DEHs. @@ -842,9 +755,9 @@ static boolean CheckMapLump(const char *lumpname, const char *filename) static boolean FileContainsMaps(const char *filename) { - for (int i = 0; i < U_mapinfo.mapcount; ++i) + for (int i = 0; i < array_size(umapinfo); ++i) { - if (CheckMapLump(U_mapinfo.maps[i].mapname, filename)) + if (CheckMapLump(umapinfo[i].mapname, filename)) { return true; } @@ -907,57 +820,6 @@ void IdentifyVersion(void) basedefault = M_StringJoin(D_DoomPrefDir(), DIR_SEPARATOR_S, D_DoomExeName(), ".cfg"); - // set save path to -save parm or current dir - - screenshotdir = M_StringDuplicate("."); // [FG] default to current dir - - basesavegame = M_StringDuplicate( - D_DoomPrefDir()); // jff 3/27/98 default to current dir - - //! - // @arg <directory> - // - // Specify a path from which to load and save games. If the directory - // does not exist then it will automatically be created. - // - - int p = M_CheckParmWithArgs("-save", 1); - if (p > 0) - { - if (basesavegame) - { - free(basesavegame); - } - basesavegame = M_StringDuplicate(myargv[p + 1]); - - M_MakeDirectory(basesavegame); - - // [FG] fall back to -save parm - if (screenshotdir) - { - free(screenshotdir); - } - screenshotdir = M_StringDuplicate(basesavegame); - } - - //! - // @arg <directory> - // - // Specify a path to save screenshots. If the directory does not - // exist then it will automatically be created. - // - - p = M_CheckParmWithArgs("-shotdir", 1); - if (p > 0) - { - if (screenshotdir) - { - free(screenshotdir); - } - screenshotdir = M_StringDuplicate(myargv[p + 1]); - - M_MakeDirectory(screenshotdir); - } // locate the IWAD and determine game mode from it @@ -965,7 +827,11 @@ void IdentifyVersion(void) if (!iwadfile) { - I_Error("IWAD not found"); + I_Error("IWAD not found!\n" + "\n" + "Place an IWAD file (e.g. doom.wad, doom2.wad)\n" + "in one of the IWAD search directories, e.g.\n" + "%s", D_DoomPrefDir()); } D_AddFile(iwadfile); @@ -1026,7 +892,7 @@ static void InitGameVersion(void) // Determine automatically if (gamemode == shareware || gamemode == registered || - (gamemode == commercial && gamemission == doom2)) + (gamemode == commercial && gamemission != pack_tnt && gamemission != pack_plut)) { // original gameversion = exe_doom_1_9; @@ -1083,8 +949,7 @@ void FindResponseFile (void) // READ THE RESPONSE FILE INTO MEMORY // killough 10/98: add default .rsp extension - char *filename = malloc(strlen(myargv[i])+5); - AddDefaultExtension(strcpy(filename,&myargv[i][1]),".rsp"); + char *filename = AddDefaultExtension(&myargv[i][1],".rsp"); handle = M_fopen(filename,"rb"); if (!handle) @@ -1446,14 +1311,15 @@ static void D_ProcessDehCommandLine(void) if (deh) { char *probe; - char *file = malloc(strlen(myargv[p]) + 5); // killough - AddDefaultExtension(strcpy(file, myargv[p]), ".bex"); + char *file = AddDefaultExtension(myargv[p], ".bex"); probe = D_TryFindWADByName(file); + free(file); if (M_access(probe, F_OK)) // nope { free(probe); - AddDefaultExtension(strcpy(file, myargv[p]), ".deh"); + file = AddDefaultExtension(myargv[p], ".deh"); probe = D_TryFindWADByName(file); + free(file); if (M_access(probe, F_OK)) // still nope { free(probe); @@ -1465,7 +1331,6 @@ static void D_ProcessDehCommandLine(void) // (apparently, this was never removed after Boom beta-killough) ProcessDehFile(probe, D_dehout(), 0); // killough 10/98 free(probe); - free(file); } } // ty 03/09/98 end of do dehacked stuff @@ -1504,6 +1369,15 @@ static void LoadIWadBase(void) { W_AddBaseDir("doom-all"); } + if (local_gamemission == doom) + { + W_AddBaseDir("doom1-all"); + } + else if (local_gamemission >= doom2 + && local_gamemission <= pack_plut) + { + W_AddBaseDir("doom2-all"); + } W_AddBaseDir(M_BaseName(wadfiles[0])); } @@ -1705,15 +1579,17 @@ void D_SetBloodColor(void) typedef enum { EXIT_SEQUENCE_OFF, // Skip sound, skip ENDOOM. EXIT_SEQUENCE_SOUND_ONLY, // Play sound, skip ENDOOM. - EXIT_SEQUENCE_PWAD_ENDOOM, // Play sound, show ENDOOM for PWADs only. + EXIT_SEQUENCE_ENDOOM_ONLY, // Skip sound, show ENDOOM. EXIT_SEQUENCE_FULL // Play sound, show ENDOOM. } exit_sequence_t; static exit_sequence_t exit_sequence; +static boolean endoom_pwad_only; boolean D_AllowQuitSound(void) { - return (exit_sequence != EXIT_SEQUENCE_OFF); + return (exit_sequence == EXIT_SEQUENCE_FULL + || exit_sequence == EXIT_SEQUENCE_SOUND_ONLY); } static void D_ShowEndDoom(void) @@ -1728,17 +1604,29 @@ boolean disable_endoom = false; static boolean AllowEndDoom(void) { - return !disable_endoom && (exit_sequence == EXIT_SEQUENCE_FULL - || (exit_sequence == EXIT_SEQUENCE_PWAD_ENDOOM - && !W_IsIWADLump(W_CheckNumForName("ENDOOM")))); + return (!disable_endoom + && (exit_sequence == EXIT_SEQUENCE_FULL + || exit_sequence == EXIT_SEQUENCE_ENDOOM_ONLY)); } static void D_EndDoom(void) { - if (AllowEndDoom()) + // Do we even want to show an ENDOOM? + if (!AllowEndDoom()) { - D_ShowEndDoom(); + return; } + + // If so, is it from the IWAD? + bool iwad_endoom = W_IsIWADLump(W_CheckNumForName("ENDOOM")); + + // Does the user want to see it, in that case? + if (iwad_endoom && endoom_pwad_only) + { + return; + } + + D_ShowEndDoom(); } // [FG] fast-forward demo to the desired map @@ -1777,8 +1665,127 @@ static boolean CheckHaveSSG (void) return true; } +static int mainwadfile; + +#define SET_DIR(a, b) \ + if ((a)) \ + { \ + free((a)); \ + } \ + (a) = (b); + +void D_SetSavegameDirectory(void) +{ + // set save path to -save parm or current dir + + SET_DIR(screenshotdir, M_StringDuplicate(".")); + + SET_DIR(basesavegame, M_StringDuplicate(D_DoomPrefDir())); + + //! + // @arg <directory> + // + // Specify a path from which to load and save games. If the directory + // does not exist then it will automatically be created. + // + + int p = M_CheckParmWithArgs("-save", 1); + if (p > 0) + { + SET_DIR(basesavegame, M_StringDuplicate(myargv[p + 1])); + + M_MakeDirectory(basesavegame); + + // [FG] fall back to -save parm + SET_DIR(screenshotdir, M_StringDuplicate(basesavegame)); + } + else + { + // [Nugget] Set savegame path as determined by config file + if (savegame_dir && strcmp(savegame_dir, "")) + { + SET_DIR(basesavegame, M_StringDuplicate(savegame_dir)); + + M_MakeDirectory(basesavegame); + } + + if (organize_savefiles == -1) + { + // [FG] check for at least one savegame in the old location + glob_t *glob = I_StartMultiGlob( + basesavegame, GLOB_FLAG_NOCASE | GLOB_FLAG_SORTED, "*.dsg"); + + organize_savefiles = (I_NextGlob(glob) == NULL); + + I_EndGlob(glob); + } + + if (organize_savefiles) + { + const char *wadname = wadfiles[0]; + + for (int i = mainwadfile; i < array_size(wadfiles); i++) + { + if (FileContainsMaps(wadfiles[i])) + { + wadname = wadfiles[i]; + break; + } + } + + char *oldsavegame = basesavegame; + + // [Nugget] Don't default to a "savegames" directory if path is set by config file + if (!savegame_dir || !strcmp(savegame_dir, "")) + { + basesavegame = + M_StringJoin(oldsavegame, DIR_SEPARATOR_S, "savegames"); + free(oldsavegame); + } + + M_MakeDirectory(basesavegame); + + oldsavegame = basesavegame; + basesavegame = M_StringJoin(oldsavegame, DIR_SEPARATOR_S, + M_BaseName(wadname)); + free(oldsavegame); + } + } + + //! + // @arg <directory> + // + // Specify a path to save screenshots. If the directory does not + // exist then it will automatically be created. + // + + p = M_CheckParmWithArgs("-shotdir", 1); + if (p > 0) + { + SET_DIR(screenshotdir, M_StringDuplicate(myargv[p + 1])); + + M_MakeDirectory(screenshotdir); + } + // [Nugget] Set screenshot path as determined by config file + else if (screenshot_dir && strcmp(screenshot_dir, "")) + { + SET_DIR(screenshotdir, M_StringDuplicate(screenshot_dir)); + + M_MakeDirectory(screenshotdir); + } + + I_Printf(VB_INFO, "Savegame directory: %s", basesavegame); + + // [Nugget] Print screenshot directory too + I_Printf(VB_INFO, "Screenshot directory: %s\n", screenshotdir); +} + +#undef SET_DIR + // [Nugget] /----------------------------------------------------------------- +boolean fail_safe; + void D_ValidateStartSkill(void) { if (startskill == sk_custom @@ -1809,8 +1816,6 @@ void D_UpdateCasualPlay(void) // [Nugget] -----------------------------------------------------------------/ -boolean fail_safe; - // // D_DoomMain // @@ -1818,7 +1823,6 @@ boolean fail_safe; void D_DoomMain(void) { int p; - int mainwadfile = 0; setbuf(stdout,NULL); @@ -1885,6 +1889,21 @@ void D_DoomMain(void) IdentifyVersion(); + //! + // @category mod + // + // Disable auto-loading of extars.wad file. + // + + if (gamemission < pack_chex && !M_ParmExists("-noextras")) + { + char *path = D_FindWADByName("extras.wad"); + if (path) + { + D_AddFile(path); + } + } + // [FG] emulate a specific version of Doom InitGameVersion(); @@ -2390,8 +2409,6 @@ void D_DoomMain(void) I_Error("\nThis is not the registered version."); } - W_ProcessInWads("UMAPDEF", U_ParseMapDefInfo, PROCESS_PWAD); - //! // @category mod // @@ -2400,82 +2417,12 @@ void D_DoomMain(void) if (!M_ParmExists("-nomapinfo")) { - W_ProcessInWads("UMAPINFO", U_ParseMapInfo, PROCESS_IWAD | PROCESS_PWAD); + W_ProcessInWads("UMAPINFO", G_ParseMapInfo, PROCESS_IWAD | PROCESS_PWAD); } G_ParseCompDatabase(); - if (!M_CheckParm("-save")) - { - // [Nugget] Set savegame path as determined by config file - if (savegame_dir && strcmp(savegame_dir, "")) - { - if (basesavegame) - free(basesavegame); - basesavegame = M_StringDuplicate(savegame_dir); - - M_MakeDirectory(basesavegame); - } - - if (organize_savefiles == -1) - { - // [FG] check for at least one savegame in the old location - glob_t *glob = I_StartMultiGlob( - basesavegame, GLOB_FLAG_NOCASE | GLOB_FLAG_SORTED, "*.dsg"); - - organize_savefiles = (I_NextGlob(glob) == NULL); - - I_EndGlob(glob); - } - - if (organize_savefiles) - { - int i; - const char *wadname = wadfiles[0]; - char *oldsavegame = basesavegame; - - for (i = mainwadfile; i < array_size(wadfiles); i++) - { - if (FileContainsMaps(wadfiles[i])) - { - wadname = wadfiles[i]; - break; - } - } - - // [Nugget] Don't default to a "savegames" directory if path is set by config file - if (!savegame_dir || !strcmp(savegame_dir, "")) - { - basesavegame = - M_StringJoin(oldsavegame, DIR_SEPARATOR_S, "savegames"); - free(oldsavegame); - } - - M_MakeDirectory(basesavegame); - - oldsavegame = basesavegame; - basesavegame = M_StringJoin(oldsavegame, DIR_SEPARATOR_S, - M_BaseName(wadname)); - free(oldsavegame); - - M_MakeDirectory(basesavegame); - } - } - - I_Printf(VB_INFO, "Savegame directory: %s", basesavegame); - - // [Nugget] Set screenshot path as determined by config file - if (!M_CheckParm("-shotdir") && screenshot_dir && strcmp(screenshot_dir, "")) - { - if (screenshotdir) - free(screenshotdir); - screenshotdir = M_StringDuplicate(screenshot_dir); - - M_MakeDirectory(screenshotdir); - } - - // [Nugget] Print screenshot directory too - I_Printf(VB_INFO, "Screenshot directory: %s\n", screenshotdir); + D_SetSavegameDirectory(); V_InitColorTranslation(); //jff 4/24/98 load color translation lumps @@ -2510,6 +2457,7 @@ void D_DoomMain(void) } W_ProcessInWads("TRAKINFO", S_ParseTrakInfo, PROCESS_IWAD | PROCESS_PWAD); + D_SetupDemoLoop(); I_Printf(VB_INFO, "M_Init: Init miscellaneous info."); M_Init(); @@ -2812,7 +2760,8 @@ void D_DoomMain(void) void D_BindMiscVariables(void) { BIND_NUM_GENERAL(exit_sequence, 0, 0, EXIT_SEQUENCE_FULL, - "Exit sequence (0 = Off; 1 = Sound Only; 2 = PWAD ENDOOM; 3 = Full)"); + "Exit sequence (0 = Off; 1 = Sound Only; 2 = ENDOOM Only; 3 = Full)"); + BIND_BOOL_GENERAL(endoom_pwad_only, false, "Show only ENDOOM from PWAD"); BIND_BOOL_GENERAL(demobar, false, "Show demo progress bar"); // [Nugget] More wipes diff --git a/src/d_main.h b/src/d_main.h index 0974f7642..067737fbd 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -32,10 +32,10 @@ extern boolean fail_safe; void D_AddFile(const char *file); -char *D_DoomExeName(void); // killough 10/98: executable's name +const char *D_DoomExeName(void); // killough 10/98: executable's name extern char *basesavegame; // killough 2/16/98: savegame path extern char *screenshotdir; // [FG] screenshot path -char *D_DoomPrefDir(void); // [FG] default configuration dir +void D_SetSavegameDirectory(void); extern const char *gamedescription; diff --git a/src/d_think.h b/src/d_think.h index f10e34f16..d5bf40948 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -22,9 +22,11 @@ #ifndef __D_THINK__ #define __D_THINK__ -typedef void (*actionf_v)(); -typedef void (*actionf_p1)(void *); -typedef void (*actionf_p2)(void *, void *); +#include "p_action.h" + +typedef void (*actionf_v)(void); +typedef void (*actionf_p1)(struct mobj_s *); +typedef void (*actionf_p2)(struct player_s *, struct pspdef_s *); typedef union actionf_u { diff --git a/src/doomdef.h b/src/doomdef.h index aea50b647..cb9d504d7 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -40,6 +40,7 @@ typedef enum { pack_chex, // Chex Quest pack_hacx, // Hacx pack_rekkr, // Rekkr + pack_chex3v, // Chex Quest 3: Vanilla Edition none } GameMission_t; diff --git a/src/doomtype.h b/src/doomtype.h index 68c8c1daa..eebd266f6 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -23,6 +23,7 @@ #include <stddef.h> // size_t, NULL #include <stdint.h> // [FG] intptr_t types +#include <stdbool.h> #include "config.h" @@ -73,11 +74,25 @@ typedef byte lighttable_t; #define arrlen(array) (sizeof(array) / sizeof(*array)) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#if defined(__GNUC__) || defined(__clang__) + #define MIN(a,b) \ + ({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; \ + }) + #define MAX(a,b) \ + ({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; \ + }) +#else + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif -#define BETWEEN(l, u, x) ((l) > (x) ? (l) : (x) > (u) ? (u) : (x)) +#define BETWEEN(l, u, x) (MAX((l), (MIN((u), (x))))) #define DIV_ROUND_FLOOR(n, d) (((n) - (d) / 2) / (d)) diff --git a/src/f_finale.c b/src/f_finale.c index 82eb2a244..602774aed 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -27,6 +27,7 @@ #include "doomstat.h" #include "doomtype.h" #include "g_game.h" +#include "g_umapinfo.h" #include "info.h" #include "m_misc.h" // [FG] M_StringDuplicate() #include "m_swap.h" @@ -36,7 +37,6 @@ #include "sounds.h" #include "st_sbardef.h" #include "st_stuff.h" -#include "u_mapinfo.h" #include "v_fmt.h" #include "v_video.h" #include "w_wad.h" @@ -51,8 +51,17 @@ // Stage of animation: // 0 = text, 1 = art screen, 2 = character cast -int finalestage; -int finalecount; + +typedef enum +{ + FINALE_STAGE_TEXT, + FINALE_STAGE_ART, + FINALE_STAGE_CAST +} finalestage_t; + +static finalestage_t finalestage; + +static int finalecount; // defines for the end mission display text // phares @@ -64,21 +73,196 @@ int finalecount; static const char *finaletext; static const char *finaleflat; -void F_StartCast (void); -void F_CastTicker (void); -boolean F_CastResponder (event_t *ev); -void F_CastDrawer (void); +static void F_StartCast(void); +static void F_CastTicker(void); +static boolean F_CastResponder(event_t *ev); +static void F_CastDrawer(void); +static void F_TextWrite(void); +static void F_BunnyScroll(void); +static float Get_TextSpeed(void); static int midstage; // whether we're in "mid-stage" -boolean using_FMI; +static boolean mapinfo_finale; + +static boolean MapInfo_StartFinale(void) +{ + mapinfo_finale = false; + + if (!gamemapinfo) + { + return false; + } + + if (secretexit) + { + if (gamemapinfo->flags & MapInfo_InterTextSecretClear) + { + finaletext = NULL; + } + else if (gamemapinfo->intertextsecret) + { + finaletext = gamemapinfo->intertextsecret; + } + } + else + { + if (gamemapinfo->flags & MapInfo_InterTextClear) + { + finaletext = NULL; + } + else if (gamemapinfo->intertext) + { + finaletext = gamemapinfo->intertext; + } + } + + if (gamemapinfo->interbackdrop[0]) + { + finaleflat = gamemapinfo->interbackdrop; + } + + if (!finaleflat) + { + finaleflat = "FLOOR4_8"; // use a single fallback for all maps. + } + + int lumpnum = W_CheckNumForName(gamemapinfo->intermusic); + if (lumpnum >= 0) + { + S_ChangeMusInfoMusic(lumpnum, true); + } + + mapinfo_finale = true; + + return lumpnum >= 0; +} + +static boolean MapInfo_Ticker() +{ + if (!mapinfo_finale) + { + return false; + } + + boolean next_level = false; + + if (!demo_compatibility) + { + WI_checkForAccelerate(); + } + else + { + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (players[i].cmd.buttons) + { + next_level = true; + } + } + } + + if (!next_level) + { + // advance animation + finalecount++; + + if (finalestage == FINALE_STAGE_CAST) + { + F_CastTicker(); + return true; + } + + if (finalestage == FINALE_STAGE_TEXT) + { + int textcount = 0; + if (finaletext) + { + float speed = demo_compatibility ? TEXTSPEED : Get_TextSpeed(); + textcount = strlen(finaletext) * speed + + (midstage ? NEWTEXTWAIT : TEXTWAIT); + } + + if (!textcount || finalecount > textcount + || (midstage && acceleratestage)) + { + next_level = true; + } + } + } + + if (next_level) + { + if (!secretexit && gamemapinfo->flags & MapInfo_EndGame) + { + if (gamemapinfo->flags & MapInfo_EndGameCast) + { + F_StartCast(); + } + else + { + finalecount = 0; + finalestage = FINALE_STAGE_ART; + wipegamestate = -1; // force a wipe + if (gamemapinfo->flags & MapInfo_EndGameBunny) + { + S_StartMusic(mus_bunny); + } + else if (gamemapinfo->flags & MapInfo_EndGameStandard) + { + mapinfo_finale = false; + } + } + } + else + { + gameaction = ga_worlddone; // next level, e.g. MAP07 + } + } + + return true; +} + +static boolean MapInfo_Drawer(void) +{ + if (!mapinfo_finale) + { + return false; + } + + switch (finalestage) + { + case FINALE_STAGE_TEXT: + if (finaletext) + { + F_TextWrite(); + } + break; + case FINALE_STAGE_ART: + if (gamemapinfo->flags & MapInfo_EndGameBunny) + { + F_BunnyScroll(); + } + else if (gamemapinfo->endpic[0]) + { + V_DrawPatchFullScreen( + V_CachePatchName(gamemapinfo->endpic, PU_CACHE)); + } + break; + case FINALE_STAGE_CAST: + F_CastDrawer(); + break; + } + + return true; +} // // F_StartFinale // void F_StartFinale (void) { - boolean mus_changed = false; + musicenum_t music_id = mus_None; gameaction = ga_nothing; gamestate = GS_FINALE; @@ -91,16 +275,6 @@ void F_StartFinale (void) finaletext = NULL; finaleflat = NULL; - if (gamemapinfo && gamemapinfo->intermusic[0]) - { - int l = W_CheckNumForName(gamemapinfo->intermusic); - if (l >= 0) - { - S_ChangeMusInfoMusic(l, true); - mus_changed = true; - } - } - // Okay - IWAD dependend stuff. // This has been changed severly, and // some stuff might have changed in the process. @@ -111,7 +285,7 @@ void F_StartFinale (void) case registered: case retail: { - if (!mus_changed) S_ChangeMusic(mus_victor, true); + music_id = mus_victor; switch (gameepisode) { @@ -141,7 +315,7 @@ void F_StartFinale (void) // DOOM II and missions packs with E1, M34 case commercial: { - if (!mus_changed) S_ChangeMusic(mus_read_m, true); + music_id = mus_read_m; // Ty 08/27/98 - added the gamemission logic @@ -188,49 +362,25 @@ void F_StartFinale (void) // Indeterminate. default: // Ty 03/30/98 - not externalized - if (!mus_changed) S_ChangeMusic(mus_read_m, true); + music_id = mus_read_m; finaleflat = "F_SKY1"; // Not used anywhere else. finaletext = s_C1TEXT; // FIXME - other text, music? break; } - - using_FMI = false; - if (gamemapinfo) + if (!MapInfo_StartFinale()) { - if (U_CheckField(gamemapinfo->intertextsecret) && secretexit) - { - finaletext = gamemapinfo->intertextsecret; - } - else if (U_CheckField(gamemapinfo->intertext) && !secretexit) - { - finaletext = gamemapinfo->intertext; - } - - if (!finaletext) - finaletext = "The End"; // this is to avoid a crash on a missing text in the last map. - - if (gamemapinfo->interbackdrop[0]) - { - finaleflat = gamemapinfo->interbackdrop; - } - - if (!finaleflat) - finaleflat = "FLOOR4_8"; // use a single fallback for all maps. - - using_FMI = true; + S_ChangeMusic(music_id, true); } - finalestage = 0; + finalestage = FINALE_STAGE_TEXT; finalecount = 0; } - - boolean F_Responder (event_t *event) { - if (finalestage == 2) - return F_CastResponder (event); + if (finalestage == FINALE_STAGE_CAST) + return F_CastResponder(event); return false; } @@ -244,7 +394,6 @@ static float Get_TextSpeed(void) acceleratestage=0, NEWTEXTSPEED : TEXTSPEED; } - // // F_Ticker // @@ -258,41 +407,18 @@ static float Get_TextSpeed(void) // killough 5/10/98: add back v1.9 demo compatibility // -static void FMI_Ticker() +void F_Ticker(void) { - if (U_CheckField(gamemapinfo->endpic)) + if (MapInfo_Ticker()) { - if (!strcasecmp(gamemapinfo->endpic, "$CAST")) - { - F_StartCast(); - using_FMI = false; - } - else - { - finalecount = 0; - finalestage = 1; - wipegamestate = -1; // force a wipe - if (!strcasecmp(gamemapinfo->endpic, "$BUNNY")) - { - S_StartMusic(mus_bunny); - } - else if (!strcasecmp(gamemapinfo->endpic, "!")) - { - using_FMI = false; - } - } + return; } - else - gameaction = ga_worlddone; // next level, e.g. MAP07 -} -void F_Ticker(void) -{ int i; if (!demo_compatibility) WI_checkForAccelerate(); // killough 3/28/98: check for acceleration else - if (gamemode == commercial && (using_FMI || finalecount > 50)) // check for skipping + if (gamemode == commercial && finalecount > 50) // check for skipping for (i=0; i<MAXPLAYERS; i++) if (players[i].cmd.buttons) goto next_level; // go on to the next level @@ -300,24 +426,20 @@ void F_Ticker(void) // advance animation finalecount++; - if (finalestage == 2) + if (finalestage == FINALE_STAGE_CAST) F_CastTicker(); - if (!finalestage) + if (finalestage == FINALE_STAGE_TEXT) { float speed = demo_compatibility ? TEXTSPEED : Get_TextSpeed(); if (finalecount > strlen(finaletext)*speed + // phares (midstage ? NEWTEXTWAIT : TEXTWAIT) || // killough 2/28/98: (midstage && acceleratestage)) // changed to allow acceleration { - if (using_FMI) - { - FMI_Ticker(); - } - else if (gamemode != commercial) // Doom 1 / Ultimate Doom episode end + if (gamemode != commercial) // Doom 1 / Ultimate Doom episode end { // with enough time, it's automatic finalecount = 0; - finalestage = 1; + finalestage = FINALE_STAGE_ART; wipegamestate = -1; // force a wipe if (gameepisode == 3) S_StartMusic(mus_bunny); @@ -326,11 +448,7 @@ void F_Ticker(void) if (!demo_compatibility && midstage) { next_level: - if (using_FMI) - { - FMI_Ticker(); - } - else if (gamemap == 30) + if (gamemap == 30) F_StartCast(); // cast of Doom 2 characters else gameaction = ga_worlddone; // next level, e.g. MAP07 @@ -350,7 +468,7 @@ void F_Ticker(void) // text can be increased, and there's still time to read what's // | // written. // phares -void F_TextWrite (void) +static void F_TextWrite(void) { int w; // killough 8/9/98: move variables below int count; @@ -470,14 +588,6 @@ static int F_RandomizeSound (int sound) } } -extern void A_BruisAttack(); extern void A_BspiAttack(); extern void A_CPosAttack(); -extern void A_CPosRefire(); extern void A_CyberAttack(); extern void A_FatAttack1(); -extern void A_FatAttack2(); extern void A_FatAttack3(); extern void A_HeadAttack(); -extern void A_PainAttack(); extern void A_PosAttack(); extern void A_SargAttack(); -extern void A_SkelFist(); extern void A_SkelMissile(); extern void A_SkelWhoosh(); -extern void A_SkullAttack(); extern void A_SPosAttack(); extern void A_TroopAttack(); -extern void A_VileTarget(); extern void A_RandomJump(); - extern boolean flipcorpses; typedef struct { @@ -541,7 +651,7 @@ static int F_SoundForState (int st) // // F_StartCast // -void F_StartCast (void) +static void F_StartCast(void) { // Ty 03/23/98 - clumsy but time is of the essence castorder[0].name = s_CC_ZOMBIE, castorder[0].type = MT_POSSESSED; @@ -568,7 +678,7 @@ void F_StartCast (void) caststate = &states[mobjinfo[castorder[castnum].type].seestate]; casttics = caststate->tics; castdeath = false; - finalestage = 2; + finalestage = FINALE_STAGE_CAST; castframes = 0; castonmelee = 0; castattacking = false; @@ -579,7 +689,7 @@ void F_StartCast (void) // // F_CastTicker // -void F_CastTicker (void) +static void F_CastTicker(void) { int st; int sfx; @@ -693,7 +803,7 @@ void F_CastTicker (void) // F_CastResponder // -boolean F_CastResponder (event_t* ev) +static boolean F_CastResponder(event_t* ev) { if (ev->type != ev_keydown && ev->type != ev_mouseb_down && ev->type != ev_joyb_down) return false; @@ -778,7 +888,7 @@ boolean F_CastResponder (event_t* ev) } -void F_CastPrint (char* text) +static void F_CastPrint(char* text) { char* ch; int c; @@ -832,7 +942,7 @@ void F_CastPrint (char* text) // F_CastDrawer // -void F_CastDrawer (void) +static void F_CastDrawer(void) { spritedef_t* sprdef; spriteframe_t* sprframe; @@ -866,7 +976,7 @@ void F_CastDrawer (void) // // F_BunnyScroll // -void F_BunnyScroll (void) +static void F_BunnyScroll(void) { int scrolled; patch_t* p1; @@ -944,30 +1054,18 @@ void F_BunnyScroll (void) // void F_Drawer (void) { - if (using_FMI) + if (MapInfo_Drawer()) { - if (!finalestage) - { - F_TextWrite(); - } - else if (strcmp(gamemapinfo->endpic, "$BUNNY") == 0) - { - F_BunnyScroll(); - } - else - { - V_DrawPatchFullScreen(V_CachePatchName(gamemapinfo->endpic, PU_CACHE)); - } - return; + return; } - if (finalestage == 2) + if (finalestage == FINALE_STAGE_CAST) { F_CastDrawer (); return; } - if (!finalestage) + if (finalestage == FINALE_STAGE_TEXT) F_TextWrite (); else { diff --git a/src/f_wipe.c b/src/f_wipe.c index de0284fdd..08a994a59 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -260,6 +260,17 @@ int wipe_renderMelt(int width, int height, int ticks) } } + for (currcol = wipe_columns * horizblocksize / 100; currcol < width; ++currcol) + { + pixel_t *dest = wipe_scr + currcol; + + for (int i = 0; i < height; ++i) + { + *dest = v_darkest_color; + dest += video.pitch; + } + } + return done; } diff --git a/src/g_compatibility.c b/src/g_compatibility.c index 56207e06e..40ca10f85 100644 --- a/src/g_compatibility.c +++ b/src/g_compatibility.c @@ -20,6 +20,7 @@ #include "doomstat.h" #include "doomtype.h" +#include "g_game.h" #include "i_printf.h" #include "m_array.h" #include "m_misc.h" @@ -77,6 +78,7 @@ typedef struct { md5_digest_t checksum; option_t *options; + char *complevel; } comp_record_t; static comp_record_t *comp_database; @@ -125,6 +127,14 @@ void G_ParseCompDatabase(void) I_Printf(VB_ERROR, "COMPDB: wrong key %s", md5); continue; } + + record.complevel = NULL; + const char *complevel = JS_GetStringValue(level, "complevel"); + if (complevel) + { + record.complevel = M_StringDuplicate(complevel); + } + json_t *js_options = JS_GetObject(level, "options"); json_t *js_option = NULL; JS_ArrayForEach(js_option, js_options) @@ -184,19 +194,23 @@ static void GetLevelCheckSum(int lump, md5_checksum_t* cksum) void G_ApplyLevelCompatibility(int lump) { - if (demorecording || demoplayback || netgame || !mbf21) - { - return; - } - static boolean restore_comp; static int old_comp[COMP_TOTAL]; if (restore_comp) { + if (demo_version != DV_MBF21) + { + demo_version = DV_MBF21; + G_ReloadDefaults(true); + } memcpy(comp, old_comp, sizeof(*comp)); restore_comp = false; } + else if (demorecording || demoplayback || netgame || !mbf21) + { + return; + } md5_checksum_t cksum; @@ -212,6 +226,20 @@ void G_ApplyLevelCompatibility(int lump) memcpy(old_comp, comp, sizeof(*comp)); restore_comp = true; + char *new_demover = record->complevel; + if (new_demover) + { + demo_version = G_GetNamedComplevel(new_demover); + G_ReloadDefaults(true); + I_Printf(VB_INFO, "Automatically setting compatibility level \"%s\"", + G_GetCurrentComplevelName()); + } + + if (!mbf21) + { + return; + } + option_t *option; array_foreach(option, record->options) { diff --git a/src/g_game.c b/src/g_game.c index 99b8ef004..2d6e0bb08 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -42,6 +42,7 @@ #include "f_finale.h" #include "g_game.h" #include "g_nextweapon.h" +#include "g_umapinfo.h" #include "hu_command.h" #include "hu_obituary.h" #include "i_gamepad.h" @@ -88,7 +89,6 @@ #include "st_widgets.h" #include "statdump.h" // [FG] StatCopy() #include "tables.h" -#include "u_mapinfo.h" #include "v_video.h" #include "version.h" #include "w_wad.h" @@ -107,7 +107,7 @@ static size_t savegamesize = SAVEGAMESIZE; // killough static char *demoname = NULL; // [crispy] the name originally chosen for the demo, i.e. without "-00000" -static char *orig_demoname = NULL; +static const char *orig_demoname = NULL; static boolean netdemo; static byte *demobuffer; // made some static -- killough static size_t maxdemosize; @@ -1481,7 +1481,7 @@ int G_GotoNextLevel(int *pEpi, int *pMap) next = gamemapinfo->nextsecret; else if (gamemapinfo->nextmap[0]) next = gamemapinfo->nextmap; - else if (U_CheckField(gamemapinfo->endpic)) + else if (gamemapinfo->flags & MapInfo_EndGame) { epsd = 1; map = 1; @@ -1836,7 +1836,7 @@ static void CheckPlayersInNetGame(void) int playback_tic = 0, playback_totaltics = 0; -static char *defdemoname; +static const char *defdemoname; #define DEMOMARKER 0x80 @@ -1996,7 +1996,7 @@ static void G_PlayerFinishLevel(int player) // [crispy] format time for level statistics #define TIMESTRSIZE 16 -static void G_FormatLevelStatTime(char *str, int tics, boolean total) +static void FormatLevelStatTime(char *str, int tics, boolean total) { int exitHours, exitMinutes; float exitTime, exitSeconds; @@ -2027,31 +2027,39 @@ static void G_FormatLevelStatTime(char *str, int tics, boolean total) // [crispy] Write level statistics upon exit static void G_WriteLevelStat(void) { - static FILE *fstream = NULL; + int playerKills = 0, playerItems = 0, playerSecrets = 0; - int i, playerKills = 0, playerItems = 0, playerSecrets = 0; + char levelString[9] = {0}; + char levelTimeString[TIMESTRSIZE] = {0}; + char totalTimeString[TIMESTRSIZE] = {0}; - char levelString[8]; - char levelTimeString[TIMESTRSIZE]; - char totalTimeString[TIMESTRSIZE]; + static boolean firsttime = true; - if (fstream == NULL) + FILE *fstream = NULL; + + if (firsttime) { + firsttime = false; fstream = M_fopen("levelstat.txt", "w"); + } + else + { + fstream = M_fopen("levelstat.txt", "a"); + } - if (fstream == NULL) - { - I_Printf(VB_ERROR, "G_WriteLevelStat: Unable to open levelstat.txt for writing!"); - return; - } + if (fstream == NULL) + { + I_Printf(VB_ERROR, + "G_WriteLevelStat: Unable to open levelstat.txt for writing!"); + return; } strcpy(levelString, MapName(gameepisode, gamemap)); - G_FormatLevelStatTime(levelTimeString, leveltime, false); - G_FormatLevelStatTime(totalTimeString, totalleveltimes + leveltime, true); + FormatLevelStatTime(levelTimeString, leveltime, false); + FormatLevelStatTime(totalTimeString, totalleveltimes + leveltime, true); - for (i = 0; i < MAXPLAYERS; i++) + for (int i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) { @@ -2065,6 +2073,8 @@ static void G_WriteLevelStat(void) levelString, (secretexit ? "s" : ""), levelTimeString, totalTimeString, playerKills, totalkills, playerItems, totalitems, playerSecrets, totalsecret); + + fclose(fstream); } // [Nugget] Custom Skill @@ -2152,9 +2162,9 @@ static void G_DoCompleted(void) const char *next = NULL; boolean intermission = false; - if (U_CheckField(gamemapinfo->endpic)) + if (gamemapinfo->flags & MapInfo_EndGame) { - if (gamemapinfo->nointermission) + if (gamemapinfo->flags & MapInfo_NoIntermission) { gameaction = ga_victory; return; @@ -3011,6 +3021,8 @@ static void DoSaveGame(char *name) length = save_p - savebuffer; + M_MakeDirectory(basesavegame); + if (!M_WriteFile(name, savebuffer, length)) displaymsg("%s", errno ? strerror(errno) : "Could not save game: Error unknown"); else if (show_save_messages && !is_periodic_autosave) // [Nugget] @@ -4531,25 +4543,44 @@ void G_WorldDone(void) if (gamemapinfo) { - if (gamemapinfo->intertextsecret && secretexit) - { - if (U_CheckField(gamemapinfo->intertextsecret)) // if the intermission was not cleared - F_StartFinale(); - return; - } - else if (gamemapinfo->intertext && !secretexit) - { - if (U_CheckField(gamemapinfo->intertext)) // if the intermission was not cleared - F_StartFinale(); - return; - } - else if (U_CheckField(gamemapinfo->endpic) && !secretexit) - { - // game ends without a status screen. - gameaction = ga_victory; - return; - } - // if nothing applied, use the defaults. + if (gamemapinfo->flags & MapInfo_InterTextClear + && gamemapinfo->flags & MapInfo_EndGame) + { + I_Printf(VB_DEBUG, + "UMAPINFO: 'intertext = clear' with one of the end game keys."); + } + + if (secretexit) + { + if (gamemapinfo->flags & MapInfo_InterTextSecretClear) + { + return; + } + if (gamemapinfo->intertextsecret) + { + F_StartFinale(); + return; + } + } + else + { + if (gamemapinfo->flags & MapInfo_EndGame) + { + // game ends without a status screen. + gameaction = ga_victory; + return; + } + else if (gamemapinfo->flags & MapInfo_InterTextClear) + { + return; + } + else if (gamemapinfo->intertext) + { + F_StartFinale(); + return; + } + } + // if nothing applied, use the defaults. } if (gamemode == commercial) @@ -5067,65 +5098,6 @@ void G_SetFastParms(int fast_pending) } } -mapentry_t *G_LookupMapinfo(int episode, int map) -{ - int i; - char lumpname[9]; - - strcpy(lumpname, MapName(episode, map)); - - for (i = 0; i < U_mapinfo.mapcount; i++) - { - if (!strcasecmp(lumpname, U_mapinfo.maps[i].mapname)) - return &U_mapinfo.maps[i]; - } - - for (i = 0; i < default_mapinfo.mapcount; i++) - { - if (!strcasecmp(lumpname, default_mapinfo.maps[i].mapname)) - return &default_mapinfo.maps[i]; - } - - return NULL; -} - -// Check if the given map name can be expressed as a gameepisode/gamemap pair -// and be reconstructed from it. -int G_ValidateMapName(const char *mapname, int *pEpi, int *pMap) -{ - char lumpname[9], mapuname[9]; - int epi = -1, map = -1; - - if (strlen(mapname) > 8) - return 0; - strncpy(mapuname, mapname, 8); - mapuname[8] = 0; - M_StringToUpper(mapuname); - - if (gamemode != commercial) - { - if (sscanf(mapuname, "E%dM%d", &epi, &map) != 2) - return 0; - strcpy(lumpname, MapName(epi, map)); - } - else - { - if (sscanf(mapuname, "MAP%d", &map) != 1) - return 0; - strcpy(lumpname, MapName(epi = 1, map)); - } - - if (epi > 4) - EpiCustom = true; - - if (pEpi) - *pEpi = epi; - if (pMap) - *pMap = map; - - return !strcmp(mapuname, lumpname); -} - // // G_InitNew // Can be called by the startup code or the menu task, @@ -5219,7 +5191,7 @@ void G_InitNew(skill_t skill, int episode, int map) // G_RecordDemo // -void G_RecordDemo(char *name) +void G_RecordDemo(const char *name) { int i; size_t demoname_size; @@ -5235,9 +5207,13 @@ void G_RecordDemo(char *name) demo_insurance = 0; usergame = false; - demoname_size = strlen(name) + 5 + 6; // [crispy] + 6 for "-00000" + if (demoname) + { + free(demoname); + } + demoname = AddDefaultExtension(name, ".lmp"); // 1/18/98 killough + demoname_size = strlen(demoname) + 6; // [crispy] + 6 for "-00000" demoname = I_Realloc(demoname, demoname_size); - AddDefaultExtension(strcpy(demoname, name), ".lmp"); // 1/18/98 killough for(; j <= 99999 && !M_access(demoname, F_OK); ++j) { @@ -5667,7 +5643,7 @@ void G_BeginRecording(void) void D_CheckNetPlaybackSkip(void); -void G_DeferedPlayDemo(char* name) +void G_DeferedPlayDemo(const char* name) { defdemoname = name; gameaction = ga_playdemo; @@ -6128,7 +6104,7 @@ void G_BindCompVariables(void) BIND_COMP(comp_vile, 0, "Arch-viles can create ghost monsters"); BIND_COMP(comp_pain, 0, "Pain elementals are limited to 20 lost souls"); BIND_COMP(comp_skull, 0, "Lost souls can spawn past impassable lines"); - BIND_COMP(comp_blazing, 0, "Blazing doors make double closing sounds"); + BIND_COMP(comp_blazing, 0, "Incorrect sound behavior for blazing doors"); BIND_COMP(comp_doorlight, 0, "Door lighting changes are immediate"); BIND_COMP(comp_god, 0, "God mode isn't absolute"); BIND_COMP(comp_skymap, 0, "Don't apply invulnerability palette to skies"); @@ -6164,7 +6140,6 @@ void G_BindCompVariables(void) M_BindBool("comp_nonbleeders", &comp_nonbleeders, NULL, false, ss_none, wad_yes, "Non-bleeders don't bleed when crushed"); M_BindBool("comp_iosdeath", &comp_iosdeath, NULL, false, ss_none, wad_yes, "Fix lopsided Icon of Sin explosions"); M_BindBool("comp_choppers", &comp_choppers, NULL, false, ss_none, wad_yes, "Permanent IDCHOPPERS invulnerability"); - M_BindBool("comp_blazing2", &comp_blazing2, NULL, true, ss_none, wad_yes, "Blazing doors reopen with wrong sound"); M_BindBool("comp_manualdoor", &comp_manualdoor, NULL, true, ss_none, wad_yes, "Manually toggled moving doors are silent"); M_BindBool("comp_switchsource", &comp_switchsource, NULL, false, ss_none, wad_yes, "Corrected switch sound source"); M_BindBool("comp_cgundblsnd", &comp_cgundblsnd, NULL, true, ss_none, wad_yes, "Chaingun makes two sounds with one bullet"); diff --git a/src/g_game.h b/src/g_game.h index 3eaf37edc..267432490 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -45,7 +45,7 @@ boolean G_CheckDemoStatus(void); 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); -void G_DeferedPlayDemo(char *demo); +void G_DeferedPlayDemo(const char *demo); void G_LoadAutoSave(char *name, boolean is_command); void G_LoadGame(char *name, int slot, boolean is_command); // killough 5/15/98 void G_ForcedLoadAutoSave(void); @@ -54,7 +54,7 @@ void G_SaveAutoSave(char *description); void G_SaveGame(int slot, char *description); // Called by M_Responder. boolean G_AutoSaveEnabled(void); boolean G_LoadAutoSaveDeathUse(void); -void G_RecordDemo(char *name); // Only called by startup code. +void G_RecordDemo(const char *name); // Only called by startup code. void G_BeginRecording(void); void G_PlayDemo(char *name); void G_ExitLevel(void); @@ -75,8 +75,6 @@ byte *G_WriteOptions(byte *demo_p); // killough 3/1/98 void G_PlayerReborn(int player); void G_DoVictory(void); -int G_ValidateMapName(const char *mapname, int *pEpi, int *pMap); - void G_EnableWarp(boolean warp); void G_SetTimeScale(void); diff --git a/src/g_umapinfo.c b/src/g_umapinfo.c new file mode 100644 index 000000000..d2bafbeb4 --- /dev/null +++ b/src/g_umapinfo.c @@ -0,0 +1,707 @@ +// +// Copyright(C) 2017 Christoph Oelckers +// Copyright(C) 2021 Roman Fomin +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT 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 "g_umapinfo.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "doomdef.h" +#include "doomstat.h" +#include "doomtype.h" +#include "m_array.h" +#include "m_misc.h" +#include "m_scanner.h" +#include "mn_menu.h" +#include "w_wad.h" +#include "z_zone.h" + +mapentry_t *umapinfo = NULL; + +static level_t *secretlevels; + +static const char *const actor_names[] = +{ + "DoomPlayer", "ZombieMan", "ShotgunGuy", "Archvile", "ArchvileFire", + "Revenant", "RevenantTracer", "RevenantTracerSmoke", "Fatso", "FatShot", + "ChaingunGuy", "DoomImp", "Demon", "Spectre", "Cacodemon", "BaronOfHell", + "BaronBall", "HellKnight", "LostSoul", "SpiderMastermind", "Arachnotron", + "Cyberdemon", "PainElemental", "WolfensteinSS", "CommanderKeen", + "BossBrain", "BossEye", "BossTarget", "SpawnShot", "SpawnFire", + "ExplosiveBarrel", "DoomImpBall", "CacodemonBall", "Rocket", "PlasmaBall", + "BFGBall", "ArachnotronPlasma", "BulletPuff", "Blood", "TeleportFog", + "ItemFog", "TeleportDest", "BFGExtra", "GreenArmor", "BlueArmor", + "HealthBonus", "ArmorBonus", "BlueCard", "RedCard", "YellowCard", + "YellowSkull", "RedSkull", "BlueSkull", "Stimpack", "Medikit", "Soulsphere", + "InvulnerabilitySphere", "Berserk", "BlurSphere", "RadSuit", "Allmap", + "Infrared", "Megasphere", "Clip", "ClipBox", "RocketAmmo", "RocketBox", + "Cell", "CellPack", "Shell", "ShellBox", "Backpack", "BFG9000", "Chaingun", + "Chainsaw", "RocketLauncher", "PlasmaRifle", "Shotgun", "SuperShotgun", + "TechLamp", "TechLamp2", "Column", "TallGreenColumn", "ShortGreenColumn", + "TallRedColumn", "ShortRedColumn", "SkullColumn", "HeartColumn", "EvilEye", + "FloatingSkull", "TorchTree", "BlueTorch", "GreenTorch", "RedTorch", + "ShortBlueTorch", "ShortGreenTorch", "ShortRedTorch", "Stalagtite", + "TechPillar", "CandleStick", "Candelabra", "BloodyTwitch", "Meat2", "Meat3", + "Meat4", "Meat5", "NonsolidMeat2", "NonsolidMeat4", "NonsolidMeat3", + "NonsolidMeat5", "NonsolidTwitch", "DeadCacodemon", "DeadMarine", + "DeadZombieMan", "DeadDemon", "DeadLostSoul", "DeadDoomImp", + "DeadShotgunGuy", "GibbedMarine", "GibbedMarineExtra", "HeadsOnAStick", + "Gibs", "HeadOnAStick", "HeadCandles", "DeadStick", "LiveStick", "BigTree", + "BurningBarrel", "HangNoGuts", "HangBNoBrain", "HangTLookingDown", + "HangTSkull", "HangTLookingUp", "HangTNoBrain", "ColonGibs", + "SmallBloodPool", "BrainStem", + // Boom/MBF additions + "PointPusher", "PointPuller", "MBFHelperDog", "PlasmaBall1", "PlasmaBall2", + "EvilSceptre", "UnholyBible", "MusicChanger", "Deh_Actor_145", + "Deh_Actor_146", "Deh_Actor_147", "Deh_Actor_148", "Deh_Actor_149", + // DEHEXTRA Actors start here + "Deh_Actor_150", // Extra thing 0 + "Deh_Actor_151", // Extra thing 1 + "Deh_Actor_152", // Extra thing 2 + "Deh_Actor_153", // Extra thing 3 + "Deh_Actor_154", // Extra thing 4 + "Deh_Actor_155", // Extra thing 5 + "Deh_Actor_156", // Extra thing 6 + "Deh_Actor_157", // Extra thing 7 + "Deh_Actor_158", // Extra thing 8 + "Deh_Actor_159", // Extra thing 9 + "Deh_Actor_160", // Extra thing 10 + "Deh_Actor_161", // Extra thing 11 + "Deh_Actor_162", // Extra thing 12 + "Deh_Actor_163", // Extra thing 13 + "Deh_Actor_164", // Extra thing 14 + "Deh_Actor_165", // Extra thing 15 + "Deh_Actor_166", // Extra thing 16 + "Deh_Actor_167", // Extra thing 17 + "Deh_Actor_168", // Extra thing 18 + "Deh_Actor_169", // Extra thing 19 + "Deh_Actor_170", // Extra thing 20 + "Deh_Actor_171", // Extra thing 21 + "Deh_Actor_172", // Extra thing 22 + "Deh_Actor_173", // Extra thing 23 + "Deh_Actor_174", // Extra thing 24 + "Deh_Actor_175", // Extra thing 25 + "Deh_Actor_176", // Extra thing 26 + "Deh_Actor_177", // Extra thing 27 + "Deh_Actor_178", // Extra thing 28 + "Deh_Actor_179", // Extra thing 29 + "Deh_Actor_180", // Extra thing 30 + "Deh_Actor_181", // Extra thing 31 + "Deh_Actor_182", // Extra thing 32 + "Deh_Actor_183", // Extra thing 33 + "Deh_Actor_184", // Extra thing 34 + "Deh_Actor_185", // Extra thing 35 + "Deh_Actor_186", // Extra thing 36 + "Deh_Actor_187", // Extra thing 37 + "Deh_Actor_188", // Extra thing 38 + "Deh_Actor_189", // Extra thing 39 + "Deh_Actor_190", // Extra thing 40 + "Deh_Actor_191", // Extra thing 41 + "Deh_Actor_192", // Extra thing 42 + "Deh_Actor_193", // Extra thing 43 + "Deh_Actor_194", // Extra thing 44 + "Deh_Actor_195", // Extra thing 45 + "Deh_Actor_196", // Extra thing 46 + "Deh_Actor_197", // Extra thing 47 + "Deh_Actor_198", // Extra thing 48 + "Deh_Actor_199", // Extra thing 49 + "Deh_Actor_200", // Extra thing 50 + "Deh_Actor_201", // Extra thing 51 + "Deh_Actor_202", // Extra thing 52 + "Deh_Actor_203", // Extra thing 53 + "Deh_Actor_204", // Extra thing 54 + "Deh_Actor_205", // Extra thing 55 + "Deh_Actor_206", // Extra thing 56 + "Deh_Actor_207", // Extra thing 57 + "Deh_Actor_208", // Extra thing 58 + "Deh_Actor_209", // Extra thing 59 + "Deh_Actor_210", // Extra thing 60 + "Deh_Actor_211", // Extra thing 61 + "Deh_Actor_212", // Extra thing 62 + "Deh_Actor_213", // Extra thing 63 + "Deh_Actor_214", // Extra thing 64 + "Deh_Actor_215", // Extra thing 65 + "Deh_Actor_216", // Extra thing 66 + "Deh_Actor_217", // Extra thing 67 + "Deh_Actor_218", // Extra thing 68 + "Deh_Actor_219", // Extra thing 69 + "Deh_Actor_220", // Extra thing 70 + "Deh_Actor_221", // Extra thing 71 + "Deh_Actor_222", // Extra thing 72 + "Deh_Actor_223", // Extra thing 73 + "Deh_Actor_224", // Extra thing 74 + "Deh_Actor_225", // Extra thing 75 + "Deh_Actor_226", // Extra thing 76 + "Deh_Actor_227", // Extra thing 77 + "Deh_Actor_228", // Extra thing 78 + "Deh_Actor_229", // Extra thing 79 + "Deh_Actor_230", // Extra thing 80 + "Deh_Actor_231", // Extra thing 81 + "Deh_Actor_232", // Extra thing 82 + "Deh_Actor_233", // Extra thing 83 + "Deh_Actor_234", // Extra thing 84 + "Deh_Actor_235", // Extra thing 85 + "Deh_Actor_236", // Extra thing 86 + "Deh_Actor_237", // Extra thing 87 + "Deh_Actor_238", // Extra thing 88 + "Deh_Actor_239", // Extra thing 89 + "Deh_Actor_240", // Extra thing 90 + "Deh_Actor_241", // Extra thing 91 + "Deh_Actor_242", // Extra thing 92 + "Deh_Actor_243", // Extra thing 93 + "Deh_Actor_244", // Extra thing 94 + "Deh_Actor_245", // Extra thing 95 + "Deh_Actor_246", // Extra thing 96 + "Deh_Actor_247", // Extra thing 97 + "Deh_Actor_248", // Extra thing 98 + "Deh_Actor_249", // Extra thing 99 +}; + +static void ReplaceString(char **to, const char *from) +{ + if (*to != NULL) + { + free(*to); + } + *to = M_StringDuplicate(from); +} + +static void FreeMapEntry(mapentry_t *mape) +{ + if (mape->levelname) + { + free(mape->levelname); + } + if (mape->label) + { + free(mape->label); + } + if (mape->intertext) + { + free(mape->intertext); + } + if (mape->intertextsecret) + { + free(mape->intertextsecret); + } + if (mape->author) + { + free(mape->author); + } + array_free(mape->bossactions); + memset(mape, 0, sizeof(*mape)); +} + +// Parses a set of string and concatenates them +// Returns a pointer to the string (must be freed) + +static char *ParseMultiString(scanner_t *s) +{ + char *build = NULL; + + do + { + SC_MustGetToken(s, TK_StringConst); + if (build == NULL) + { + build = M_StringDuplicate(SC_GetString(s)); + } + else + { + char *tmp = build; + build = M_StringJoin(tmp, "\n", SC_GetString(s)); + free(tmp); + } + } while (SC_CheckToken(s, ',')); + + return build; +} + +// Parses a lump name. The buffer must be at least 9 characters. + +static void ParseLumpName(scanner_t *s, char *buffer) +{ + SC_MustGetToken(s, TK_StringConst); + if (strlen(SC_GetString(s)) > 8) + { + SC_Error(s, "String too long. Maximum size is 8 characters."); + } + strncpy(buffer, SC_GetString(s), 8); + buffer[8] = 0; + M_StringToUpper(buffer); +} + +// Parses a standard property that is already known +// These do not get stored in the property list +// but in dedicated struct member variables. + +static void ParseStandardProperty(scanner_t *s, mapentry_t *mape) +{ + SC_MustGetToken(s, TK_Identifier); + char *prop = M_StringDuplicate(SC_GetString(s)); + + SC_MustGetToken(s, '='); + if (!strcasecmp(prop, "levelname")) + { + SC_MustGetToken(s, TK_StringConst); + ReplaceString(&mape->levelname, SC_GetString(s)); + } + else if (!strcasecmp(prop, "label")) + { + if (SC_CheckToken(s, TK_Identifier)) + { + if (!strcasecmp(SC_GetString(s), "clear")) + { + mape->flags |= MapInfo_LabelClear; + } + else + { + SC_Error(s, "Either 'clear' or string constant expected"); + } + } + else + { + mape->flags &= ~MapInfo_LabelClear; + SC_MustGetToken(s, TK_StringConst); + ReplaceString(&mape->label, SC_GetString(s)); + } + } + else if (!strcasecmp(prop, "author")) + { + SC_MustGetToken(s, TK_StringConst); + ReplaceString(&mape->author, SC_GetString(s)); + } + else if (!strcasecmp(prop, "episode")) + { + if (SC_CheckToken(s, TK_Identifier)) + { + if (!strcasecmp(SC_GetString(s), "clear")) + { + MN_ClearEpisodes(); + } + else + { + SC_Error(s, "Either 'clear' or string constant expected"); + } + } + else + { + char lumpname[9] = {0}; + char *alttext = NULL; + char key = 0; + + ParseLumpName(s, lumpname); + if (SC_CheckToken(s, ',')) + { + SC_MustGetToken(s, TK_StringConst); + alttext = M_StringDuplicate(SC_GetString(s)); + if (SC_CheckToken(s, ',')) + { + SC_MustGetToken(s, TK_StringConst); + const char *tmp = SC_GetString(s); + key = M_ToLower(tmp[0]); + } + } + + MN_AddEpisode(mape->mapname, lumpname, alttext, key); + + if (alttext) + { + free(alttext); + } + } + } + else if (!strcasecmp(prop, "next")) + { + ParseLumpName(s, mape->nextmap); + if (!G_ValidateMapName(mape->nextmap, NULL, NULL)) + { + SC_Error(s, "Invalid map name %s.", mape->nextmap); + } + } + else if (!strcasecmp(prop, "nextsecret")) + { + ParseLumpName(s, mape->nextsecret); + level_t level = {0}; + if (!G_ValidateMapName(mape->nextsecret, &level.episode, &level.map)) + { + SC_Error(s, "Invalid map name %s", mape->nextsecret); + } + array_push(secretlevels, level); + } + else if (!strcasecmp(prop, "levelpic")) + { + ParseLumpName(s, mape->levelpic); + } + else if (!strcasecmp(prop, "skytexture")) + { + ParseLumpName(s, mape->skytexture); + } + else if (!strcasecmp(prop, "music")) + { + ParseLumpName(s, mape->music); + } + else if (!strcasecmp(prop, "endpic")) + { + mape->flags |= MapInfo_EndGameArt; + ParseLumpName(s, mape->endpic); + } + else if (!strcasecmp(prop, "endcast")) + { + SC_MustGetToken(s, TK_BoolConst); + if (SC_GetBoolean(s)) + { + mape->flags |= MapInfo_EndGameCast; + } + else + { + mape->flags &= ~MapInfo_EndGameCast; + mape->flags |= MapInfo_EndGameClear; + } + } + else if (!strcasecmp(prop, "endbunny")) + { + SC_MustGetToken(s, TK_BoolConst); + if (SC_GetBoolean(s)) + { + mape->flags |= MapInfo_EndGameBunny; + } + else + { + mape->flags &= ~MapInfo_EndGameBunny; + mape->flags |= MapInfo_EndGameClear; + } + } + else if (!strcasecmp(prop, "endgame")) + { + SC_MustGetToken(s, TK_BoolConst); + if (SC_GetBoolean(s)) + { + mape->flags |= MapInfo_EndGameStandard; + } + else + { + mape->flags &= ~MapInfo_EndGameStandard; + mape->flags |= MapInfo_EndGameClear; + } + } + else if (!strcasecmp(prop, "exitpic")) + { + ParseLumpName(s, mape->exitpic); + } + else if (!strcasecmp(prop, "enterpic")) + { + ParseLumpName(s, mape->enterpic); + } + else if (!strcasecmp(prop, "exitanim")) + { + ParseLumpName(s, mape->exitanim); + } + else if (!strcasecmp(prop, "enteranim")) + { + ParseLumpName(s, mape->enteranim); + } + else if (!strcasecmp(prop, "nointermission")) + { + SC_MustGetToken(s, TK_BoolConst); + if (SC_GetBoolean(s)) + { + mape->flags |= MapInfo_NoIntermission; + } + else + { + mape->flags &= ~MapInfo_NoIntermission; + } + } + else if (!strcasecmp(prop, "partime")) + { + SC_MustGetToken(s, TK_IntConst); + mape->partime = SC_GetNumber(s); + } + else if (!strcasecmp(prop, "intertext")) + { + if (SC_CheckToken(s, TK_Identifier)) + { + if (!strcasecmp(SC_GetString(s), "clear")) + { + mape->flags |= MapInfo_InterTextClear; + } + else + { + SC_Error(s, "Either 'clear' or string constant expected"); + } + } + else + { + mape->flags &= ~MapInfo_InterTextClear; + if (mape->intertext) + { + free(mape->intertext); + } + mape->intertext = ParseMultiString(s); + } + } + else if (!strcasecmp(prop, "intertextsecret")) + { + if (SC_CheckToken(s, TK_Identifier)) + { + if (!strcasecmp(SC_GetString(s), "clear")) + { + mape->flags |= MapInfo_InterTextSecretClear; + } + else + { + SC_Error(s, "Either 'clear' or string constant expected"); + } + } + else + { + mape->flags &= ~MapInfo_InterTextSecretClear; + if (mape->intertextsecret) + { + free(mape->intertextsecret); + } + mape->intertextsecret = ParseMultiString(s); + } + } + else if (!strcasecmp(prop, "interbackdrop")) + { + ParseLumpName(s, mape->interbackdrop); + } + else if (!strcasecmp(prop, "intermusic")) + { + ParseLumpName(s, mape->intermusic); + } + else if (!strcasecmp(prop, "bossaction")) + { + SC_MustGetToken(s, TK_Identifier); + if (!strcasecmp(SC_GetString(s), "clear")) + { + mape->flags |= MapInfo_BossActionClear; + array_free(mape->bossactions); + } + else + { + mape->flags &= ~MapInfo_BossActionClear; + int type, special, tag; + for (type = 0; arrlen(actor_names); ++type) + { + if (!strcasecmp(SC_GetString(s), actor_names[type])) + { + break; + } + } + if (type == arrlen(actor_names)) + { + SC_Error(s, "bossaction: unknown thing type '%s'", + SC_GetString(s)); + } + SC_MustGetToken(s, ','); + SC_MustGetToken(s, TK_IntConst); + special = SC_GetNumber(s); + SC_MustGetToken(s, ','); + SC_MustGetToken(s, TK_IntConst); + tag = SC_GetNumber(s); + // allow no 0-tag specials here, unless a level exit. + if (tag != 0 || special == 11 || special == 51 || special == 52 + || special == 124) + { + bossaction_t bossaction = {type, special, tag}; + array_push(mape->bossactions, bossaction); + } + } + } + // If no known property name was given, skip all comma-separated values + // after the = sign + else + { + do + { + SC_GetNextToken(s, true); + } while (SC_CheckToken(s, ',')); + } + + free(prop); +} + +static void ParseMapEntry(scanner_t *s, mapentry_t *entry) +{ + SC_MustGetToken(s, TK_Identifier); + if (strcasecmp(SC_GetString(s), "map")) + { + SC_Error(s, "Expected 'map' but got '%s' instead", SC_GetString(s)); + } + + SC_MustGetToken(s, TK_Identifier); + if (!G_ValidateMapName(SC_GetString(s), NULL, NULL)) + { + SC_Error(s, "Invalid map name %s", SC_GetString(s)); + } + ReplaceString(&entry->mapname, SC_GetString(s)); + + SC_MustGetToken(s, '{'); + while (!SC_CheckToken(s, '}')) + { + ParseStandardProperty(s, entry); + } +} + +void G_ParseMapInfo(int lumpnum) +{ + scanner_t *s = SC_Open("UMAPINFO", W_CacheLumpNum(lumpnum, PU_CACHE), + W_LumpLength(lumpnum)); + while (SC_TokensLeft(s)) + { + mapentry_t parsed = {0}; + ParseMapEntry(s, &parsed); + + // Set default level progression here to simplify the checks elsewhere. + // Doing this lets us skip all normal code for this if nothing has been + // defined. + if (parsed.flags & MapInfo_EndGame) + { + parsed.nextmap[0] = 0; + } + else if (!parsed.nextmap[0] && !(parsed.flags & MapInfo_EndGameClear)) + { + if (!strcasecmp(parsed.mapname, "MAP30")) + { + parsed.flags |= MapInfo_EndGameCast; + } + else if (!strcasecmp(parsed.mapname, "E1M8")) + { + parsed.flags |= MapInfo_EndGameArt; + strcpy(parsed.endpic, gamemode == retail ? "CREDIT" : "HELP2"); + } + else if (!strcasecmp(parsed.mapname, "E2M8")) + { + parsed.flags |= MapInfo_EndGameArt; + strcpy(parsed.endpic, "VICTORY2"); + } + else if (!strcasecmp(parsed.mapname, "E3M8")) + { + parsed.flags |= MapInfo_EndGameBunny; + } + else if (!strcasecmp(parsed.mapname, "E4M8")) + { + parsed.flags |= MapInfo_EndGameArt; + strcpy(parsed.endpic, "ENDPIC"); + } + else + { + int ep, map; + if (G_ValidateMapName(parsed.mapname, &ep, &map)) + { + strcpy(parsed.nextmap, MapName(ep, map + 1)); + } + } + } + + // Does this entry already exist? If yes, replace it. + int i; + for (i = 0; i < array_size(umapinfo); ++i) + { + if (!strcmp(parsed.mapname, umapinfo[i].mapname)) + { + FreeMapEntry(&umapinfo[i]); + umapinfo[i] = parsed; + break; + } + } + // Not found so create a new one. + if (i == array_size(umapinfo)) + { + array_push(umapinfo, parsed); + } + } + + SC_Close(s); +} + +mapentry_t *G_LookupMapinfo(int episode, int map) +{ + char lumpname[9] = {0}; + M_StringCopy(lumpname, MapName(episode, map), sizeof(lumpname)); + + mapentry_t *entry; + array_foreach(entry, umapinfo) + { + if (!strcasecmp(lumpname, entry->mapname)) + { + return entry; + } + } + + return NULL; +} + +// Check if the given map name can be expressed as a gameepisode/gamemap pair +// and be reconstructed from it. + +boolean G_ValidateMapName(const char *mapname, int *episode, int *map) +{ + if (strlen(mapname) > 8) + { + return false; + } + + char lumpname[9], mapuname[9]; + int e = -1, m = -1; + + M_StringCopy(mapuname, mapname, 8); + mapuname[8] = 0; + M_StringToUpper(mapuname); + + if (gamemode != commercial) + { + if (sscanf(mapuname, "E%dM%d", &e, &m) != 2) + { + return false; + } + strcpy(lumpname, MapName(e, m)); + } + else + { + if (sscanf(mapuname, "MAP%d", &m) != 1) + { + return false; + } + strcpy(lumpname, MapName(e = 1, m)); + } + + if (episode) + { + *episode = e; + } + if (map) + { + *map = m; + } + + return strcmp(mapuname, lumpname) == 0; +} + +boolean G_IsSecretMap(int episode, int map) +{ + level_t *level; + array_foreach(level, secretlevels) + { + if (level->episode == episode && level->map == map) + { + return true; + } + } + return false; +} diff --git a/src/g_umapinfo.h b/src/g_umapinfo.h new file mode 100644 index 000000000..487c24b0c --- /dev/null +++ b/src/g_umapinfo.h @@ -0,0 +1,83 @@ +// +// Copyright(C) 2017 Christoph Oelckers +// Copyright(C) 2021 Roman Fomin +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT 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 G_UMAPINFO_H +#define G_UMAPINFO_H + +#include "doomtype.h" + +typedef enum +{ + MapInfo_LabelClear = (1u << 0), + + MapInfo_EndGameArt = (1u << 2), + MapInfo_EndGameStandard = (1u << 3), + MapInfo_EndGameCast = (1u << 4), + MapInfo_EndGameBunny = (1u << 5), + MapInfo_EndGame = (MapInfo_EndGameArt | MapInfo_EndGameStandard + | MapInfo_EndGameCast | MapInfo_EndGameBunny), + MapInfo_EndGameClear = (1u << 6), + + MapInfo_NoIntermission = (1u << 7), + MapInfo_InterTextClear = (1u << 8), + MapInfo_InterTextSecretClear = (1u << 9), + + MapInfo_BossActionClear = (1u << 10) +} mapinfo_flags_t; + +typedef struct +{ + int type; + int special; + int tag; +} bossaction_t; + +typedef struct mapentry_s +{ + char *mapname; + char *levelname; + char *label; + char *intertext; + char *intertextsecret; + char *author; + char levelpic[9]; + char nextmap[9]; + char nextsecret[9]; + char music[9]; + char skytexture[9]; + char endpic[9]; + char exitpic[9]; + char enterpic[9]; + char exitanim[9]; + char enteranim[9]; + char interbackdrop[9]; + char intermusic[9]; + int partime; + bossaction_t *bossactions; + mapinfo_flags_t flags; +} mapentry_t; + +extern mapentry_t *umapinfo; + +extern boolean EpiCustom; + +mapentry_t *G_LookupMapinfo(int episode, int map); + +boolean G_ValidateMapName(const char *mapname, int *episode, int *map); + +void G_ParseMapInfo(int lumpnum); + +boolean G_IsSecretMap(int episode, int map); + +#endif diff --git a/src/hu_crosshair.c b/src/hu_crosshair.c index 3d8f77c4b..763a4e267 100644 --- a/src/hu_crosshair.c +++ b/src/hu_crosshair.c @@ -95,11 +95,6 @@ void HU_InitCrosshair(void) void HU_StartCrosshair(void) { - if (crosshair.patch) - { - Z_ChangeTag(crosshair.patch, PU_CACHE); - } - if (crosshair_lumps[hud_crosshair]) { crosshair.patch = diff --git a/src/i_flmusic.c b/src/i_flmusic.c index a7c265010..a8ccc10b6 100644 --- a/src/i_flmusic.c +++ b/src/i_flmusic.c @@ -121,21 +121,10 @@ static void ScanDir(const char *dir, boolean recursion) const char usr_share[] = "/usr/share"; if (strncmp(dir, usr_share, strlen(usr_share)) == 0) { - char *home_dir = M_getenv("XDG_DATA_HOME"); - - if (home_dir == NULL) - { - home_dir = M_getenv("HOME"); - } - - if (home_dir) - { - char *local_share = M_StringJoin(home_dir, "/.local/share"); - char *local_dir = M_StringReplace(dir, usr_share, local_share); - free(local_share); - ScanDir(local_dir, true); - free(local_dir); - } + char *local_share = M_DataDir(); + char *local_dir = M_StringReplace(dir, usr_share, local_share); + ScanDir(local_dir, true); + free(local_dir); } else if (dir[0] == '.') { diff --git a/src/i_gyro.c b/src/i_gyro.c index fe8d10290..35108c256 100644 --- a/src/i_gyro.c +++ b/src/i_gyro.c @@ -192,13 +192,13 @@ static void SaveCalibration(void) static void ProcessAccelCalibration(void) { cal.accel_count++; - cal.accel_sum += vec_length(&motion.accel); + cal.accel_sum += vec_length(motion.accel); } static void ProcessGyroCalibration(void) { cal.gyro_count++; - cal.gyro_sum = vec_add(&cal.gyro_sum, &motion.gyro); + cal.gyro_sum = vec_add(cal.gyro_sum, motion.gyro); } static void PostProcessCalibration(void) @@ -211,8 +211,8 @@ static void PostProcessCalibration(void) motion.accel_magnitude = cal.accel_sum / cal.accel_count; motion.accel_magnitude = BETWEEN(0.0f, 2.0f, motion.accel_magnitude); - motion.gyro_offset = vec_scale(&cal.gyro_sum, 1.0f / cal.gyro_count); - motion.gyro_offset = vec_clamp(-1.0f, 1.0f, &motion.gyro_offset); + motion.gyro_offset = vec_scale(cal.gyro_sum, 1.0f / cal.gyro_count); + motion.gyro_offset = vec_clamp(-1.0f, 1.0f, motion.gyro_offset); SaveCalibration(); @@ -505,7 +505,7 @@ static void ApplyGyroSpace_Local(void) static void ApplyGyroSpace_Player(void) { - const vec grav_norm = vec_normalize(&motion.gravity); + const vec grav_norm = vec_normalize(motion.gravity); const float world_yaw = motion.gyro.y * grav_norm.y + motion.gyro.z * grav_norm.z; @@ -532,36 +532,36 @@ static void CalcGravityVector_Skip(void) static void CalcGravityVector_Full(void) { // Convert gyro input to reverse rotation. - const float angle_speed = vec_length(&motion.gyro); + const float angle_speed = vec_length(motion.gyro); const float angle = angle_speed * motion.delta_time; - const vec negative_gyro = vec_negative(&motion.gyro); - const quat reverse_rotation = angle_axis(angle, &negative_gyro); + const vec negative_gyro = vec_negative(motion.gyro); + const quat reverse_rotation = angle_axis(angle, negative_gyro); // Rotate gravity vector. - motion.gravity = vec_rotate(&motion.gravity, &reverse_rotation); + motion.gravity = vec_rotate(motion.gravity, reverse_rotation); // Check accelerometer magnitude now. - const float accel_magnitude = vec_length(&motion.accel); + const float accel_magnitude = vec_length(motion.accel); if (accel_magnitude <= 0.0f) { return; } - const vec accel_norm = vec_scale(&motion.accel, 1.0f / accel_magnitude); + const vec accel_norm = vec_scale(motion.accel, 1.0f / accel_magnitude); // Shakiness/smoothness. - motion.smooth_accel = vec_rotate(&motion.smooth_accel, &reverse_rotation); + motion.smooth_accel = vec_rotate(motion.smooth_accel, reverse_rotation); const float smooth_factor = exp2f(-motion.delta_time * SMOOTH_HALF_TIME); motion.shakiness *= smooth_factor; - const vec delta_accel = vec_subtract(&motion.accel, &motion.smooth_accel); - const float delta_accel_magnitude = vec_length(&delta_accel); + const vec delta_accel = vec_subtract(motion.accel, motion.smooth_accel); + const float delta_accel_magnitude = vec_length(delta_accel); motion.shakiness = MAX(motion.shakiness, delta_accel_magnitude); motion.smooth_accel = - vec_lerp(&motion.accel, &motion.smooth_accel, smooth_factor); + vec_lerp(motion.accel, motion.smooth_accel, smooth_factor); // Find the difference between gravity and raw acceleration. - const vec new_gravity = vec_scale(&accel_norm, -motion.accel_magnitude); - const vec gravity_delta = vec_subtract(&new_gravity, &motion.gravity); - const vec gravity_direction = vec_normalize(&gravity_delta); + const vec new_gravity = vec_scale(accel_norm, -motion.accel_magnitude); + const vec gravity_delta = vec_subtract(new_gravity, motion.gravity); + const vec gravity_direction = vec_normalize(gravity_delta); // Calculate correction rate. float still_or_shaky = (motion.shakiness - SHAKINESS_MIN_THRESH) @@ -575,7 +575,7 @@ static void CalcGravityVector_Full(void) const float correction_limit = MAX(angle_speed_adjusted, COR_MIN_SPEED); if (correction_rate > correction_limit) { - const float gravity_delta_magnitude = vec_length(&gravity_delta); + const float gravity_delta_magnitude = vec_length(gravity_delta); float close_factor = (gravity_delta_magnitude - COR_GYRO_MIN_THRESH) / (COR_GYRO_MAX_THRESH - COR_GYRO_MIN_THRESH); close_factor = BETWEEN(0.0f, 1.0f, close_factor); @@ -585,20 +585,20 @@ static void CalcGravityVector_Full(void) // Apply correction to gravity vector. const vec correction = - vec_scale(&gravity_direction, correction_rate * motion.delta_time); - if (vec_lengthsquared(&correction) < vec_lengthsquared(&gravity_delta)) + vec_scale(gravity_direction, correction_rate * motion.delta_time); + if (vec_lengthsquared(correction) < vec_lengthsquared(gravity_delta)) { - motion.gravity = vec_add(&motion.gravity, &correction); + motion.gravity = vec_add(motion.gravity, correction); } else { - motion.gravity = vec_scale(&accel_norm, -motion.accel_magnitude); + motion.gravity = vec_scale(accel_norm, -motion.accel_magnitude); } } static void ApplyCalibration(void) { - motion.gyro = vec_subtract(&motion.gyro, &motion.gyro_offset); + motion.gyro = vec_subtract(motion.gyro, motion.gyro_offset); } static float GetDeltaTime(void) diff --git a/src/i_oalmusic.c b/src/i_oalmusic.c index a9d538f58..fa1c64668 100644 --- a/src/i_oalmusic.c +++ b/src/i_oalmusic.c @@ -439,7 +439,11 @@ static boolean I_OAL_InitMusic(int device) return false; } -static int fl_gain, opl_gain; +#if defined(HAVE_FLUIDSYNTH) +static int fl_gain; +#endif + +static int opl_gain; static void I_OAL_SetMusicVolume(int volume) { @@ -609,7 +613,7 @@ static const char **I_OAL_DeviceList(void) static midiplayertype_t I_OAL_MidiPlayerType(void) { -#ifdef HAVE_FLUIDSYNTH +#if defined (HAVE_FLUIDSYNTH) if (active_module == &stream_fl_module) { return midiplayer_fluidsynth; diff --git a/src/i_printf.h b/src/i_printf.h index cb91c69aa..d404c9b6f 100644 --- a/src/i_printf.h +++ b/src/i_printf.h @@ -31,7 +31,7 @@ typedef enum VB_MAX } verbosity_t; -#define VB_DEMO (gameaction == ga_playdemo ? VB_INFO : VB_DEBUG) +#define VB_DEMO (gameaction == ga_playdemo || demoplayback ? VB_INFO : VB_DEBUG) int I_ConsoleStdout(void); diff --git a/src/i_video.c b/src/i_video.c index 42ebcbc73..530f7691e 100644 --- a/src/i_video.c +++ b/src/i_video.c @@ -1810,7 +1810,8 @@ static void I_InitGraphicsMode(void) SDL_RendererInfo info; if (SDL_GetRendererInfo(renderer, &info) == 0) { - I_Printf(VB_DEBUG, "SDL render driver: %s", info.name); + I_Printf(VB_DEBUG, "SDL render driver: %s (%s)", info.name, + SDL_GetCurrentVideoDriver()); #ifdef _WIN32 d3d_renderer = !strncmp(info.name, "direct3d", strlen(info.name)); #endif diff --git a/src/info.c b/src/info.c index 2ad98bea0..22795092e 100644 --- a/src/info.c +++ b/src/info.c @@ -109,53 +109,53 @@ char *original_sprnames[NUMSPRITES+1] = { state_t original_states[NUMSTATES] = { {SPR_TROO,0,-1,{NULL},S_NULL}, // S_NULL - {SPR_SHTG,4,0,{A_Light0},S_NULL}, // S_LIGHTDONE - {SPR_PUNG,0,1,{A_WeaponReady},S_PUNCH}, // S_PUNCH - {SPR_PUNG,0,1,{A_Lower},S_PUNCHDOWN}, // S_PUNCHDOWN - {SPR_PUNG,0,1,{A_Raise},S_PUNCHUP}, // S_PUNCHUP + {SPR_SHTG,4,0,{.p2 = A_Light0},S_NULL}, // S_LIGHTDONE + {SPR_PUNG,0,1,{.p2 = A_WeaponReady},S_PUNCH}, // S_PUNCH + {SPR_PUNG,0,1,{.p2 = A_Lower},S_PUNCHDOWN}, // S_PUNCHDOWN + {SPR_PUNG,0,1,{.p2 = A_Raise},S_PUNCHUP}, // S_PUNCHUP {SPR_PUNG,1,4,{NULL},S_PUNCH2}, // S_PUNCH1 - {SPR_PUNG,2,4,{A_Punch},S_PUNCH3}, // S_PUNCH2 + {SPR_PUNG,2,4,{.p2 = A_Punch},S_PUNCH3}, // S_PUNCH2 {SPR_PUNG,3,5,{NULL},S_PUNCH4}, // S_PUNCH3 {SPR_PUNG,2,4,{NULL},S_PUNCH5}, // S_PUNCH4 - {SPR_PUNG,1,5,{A_ReFire},S_PUNCH}, // S_PUNCH5 - {SPR_PISG,0,1,{A_WeaponReady},S_PISTOL},// S_PISTOL - {SPR_PISG,0,1,{A_Lower},S_PISTOLDOWN}, // S_PISTOLDOWN - {SPR_PISG,0,1,{A_Raise},S_PISTOLUP}, // S_PISTOLUP + {SPR_PUNG,1,5,{.p2 = A_ReFire},S_PUNCH}, // S_PUNCH5 + {SPR_PISG,0,1,{.p2 = A_WeaponReady},S_PISTOL},// S_PISTOL + {SPR_PISG,0,1,{.p2 = A_Lower},S_PISTOLDOWN}, // S_PISTOLDOWN + {SPR_PISG,0,1,{.p2 = A_Raise},S_PISTOLUP}, // S_PISTOLUP {SPR_PISG,0,4,{NULL},S_PISTOL2}, // S_PISTOL1 - {SPR_PISG,1,6,{A_FirePistol},S_PISTOL3},// S_PISTOL2 + {SPR_PISG,1,6,{.p2 = A_FirePistol},S_PISTOL3},// S_PISTOL2 {SPR_PISG,2,4,{NULL},S_PISTOL4}, // S_PISTOL3 - {SPR_PISG,1,5,{A_ReFire},S_PISTOL}, // S_PISTOL4 - {SPR_PISF,0|FF_FULLBRIGHT,7,{A_Light1},S_LIGHTDONE}, // S_PISTOLFLASH - {SPR_SHTG,0,1,{A_WeaponReady},S_SGUN}, // S_SGUN - {SPR_SHTG,0,1,{A_Lower},S_SGUNDOWN}, // S_SGUNDOWN - {SPR_SHTG,0,1,{A_Raise},S_SGUNUP}, // S_SGUNUP + {SPR_PISG,1,5,{.p2 = A_ReFire},S_PISTOL}, // S_PISTOL4 + {SPR_PISF,0|FF_FULLBRIGHT,7,{.p2 = A_Light1},S_LIGHTDONE}, // S_PISTOLFLASH + {SPR_SHTG,0,1,{.p2 = A_WeaponReady},S_SGUN}, // S_SGUN + {SPR_SHTG,0,1,{.p2 = A_Lower},S_SGUNDOWN}, // S_SGUNDOWN + {SPR_SHTG,0,1,{.p2 = A_Raise},S_SGUNUP}, // S_SGUNUP {SPR_SHTG,0,3,{NULL},S_SGUN2}, // S_SGUN1 - {SPR_SHTG,0,7,{A_FireShotgun},S_SGUN3}, // S_SGUN2 + {SPR_SHTG,0,7,{.p2 = A_FireShotgun},S_SGUN3}, // S_SGUN2 {SPR_SHTG,1,5,{NULL},S_SGUN4}, // S_SGUN3 {SPR_SHTG,2,5,{NULL},S_SGUN5}, // S_SGUN4 {SPR_SHTG,3,4,{NULL},S_SGUN6}, // S_SGUN5 {SPR_SHTG,2,5,{NULL},S_SGUN7}, // S_SGUN6 {SPR_SHTG,1,5,{NULL},S_SGUN8}, // S_SGUN7 {SPR_SHTG,0,3,{NULL},S_SGUN9}, // S_SGUN8 - {SPR_SHTG,0,7,{A_ReFire},S_SGUN}, // S_SGUN9 - {SPR_SHTF,0|FF_FULLBRIGHT,4,{A_Light1},S_SGUNFLASH2}, // S_SGUNFLASH1 - {SPR_SHTF,1|FF_FULLBRIGHT,3,{A_Light2},S_LIGHTDONE}, // S_SGUNFLASH2 - {SPR_SHT2,0,1,{A_WeaponReady},S_DSGUN}, // S_DSGUN - {SPR_SHT2,0,1,{A_Lower},S_DSGUNDOWN}, // S_DSGUNDOWN - {SPR_SHT2,0,1,{A_Raise},S_DSGUNUP}, // S_DSGUNUP + {SPR_SHTG,0,7,{.p2 = A_ReFire},S_SGUN}, // S_SGUN9 + {SPR_SHTF,0|FF_FULLBRIGHT,4,{.p2 = A_Light1},S_SGUNFLASH2}, // S_SGUNFLASH1 + {SPR_SHTF,1|FF_FULLBRIGHT,3,{.p2 = A_Light2},S_LIGHTDONE}, // S_SGUNFLASH2 + {SPR_SHT2,0,1,{.p2 = A_WeaponReady},S_DSGUN}, // S_DSGUN + {SPR_SHT2,0,1,{.p2 = A_Lower},S_DSGUNDOWN}, // S_DSGUNDOWN + {SPR_SHT2,0,1,{.p2 = A_Raise},S_DSGUNUP}, // S_DSGUNUP {SPR_SHT2,0,3,{NULL},S_DSGUN2}, // S_DSGUN1 // killough 9/5/98: make SSG lighting flash more uniform along super shotgun: - {SPR_SHT2,0|FF_FULLBRIGHT /* killough */,7,{A_FireShotgun2},S_DSGUN3}, // S_DSGUN2 + {SPR_SHT2,0|FF_FULLBRIGHT /* killough */,7,{.p2 = A_FireShotgun2},S_DSGUN3}, // S_DSGUN2 {SPR_SHT2,1,7,{NULL},S_DSGUN4}, // S_DSGUN3 - {SPR_SHT2,2,7,{A_CheckReload},S_DSGUN5}, // S_DSGUN4 - {SPR_SHT2,3,7,{A_OpenShotgun2},S_DSGUN6}, // S_DSGUN5 + {SPR_SHT2,2,7,{.p2 = A_CheckReload},S_DSGUN5}, // S_DSGUN4 + {SPR_SHT2,3,7,{.p2 = A_OpenShotgun2},S_DSGUN6}, // S_DSGUN5 {SPR_SHT2,4,7,{NULL},S_DSGUN7}, // S_DSGUN6 - {SPR_SHT2,5,7,{A_LoadShotgun2},S_DSGUN8}, // S_DSGUN7 + {SPR_SHT2,5,7,{.p2 = A_LoadShotgun2},S_DSGUN8}, // S_DSGUN7 {SPR_SHT2,6,6,{NULL},S_DSGUN9}, // S_DSGUN8 - {SPR_SHT2,7,6,{A_CloseShotgun2},S_DSGUN10}, // S_DSGUN9 - {SPR_SHT2,0,5,{A_ReFire},S_DSGUN}, // S_DSGUN10 + {SPR_SHT2,7,6,{.p2 = A_CloseShotgun2},S_DSGUN10}, // S_DSGUN9 + {SPR_SHT2,0,5,{.p2 = A_ReFire},S_DSGUN}, // S_DSGUN10 {SPR_SHT2,1,7,{NULL},S_DSNR2}, // S_DSNR1 {SPR_SHT2,0,3,{NULL},S_DSGUNDOWN}, // S_DSNR2 @@ -163,52 +163,52 @@ state_t original_states[NUMSTATES] = { // killough 8/20/98: reduce first SSG flash frame one tic, to fix // Doom II SSG flash bug, in which SSG raises before flash finishes - {SPR_SHT2,8|FF_FULLBRIGHT,4/*killough*/,{A_Light1},S_DSGUNFLASH2}, // S_DSGUNFLASH1 + {SPR_SHT2,8|FF_FULLBRIGHT,4/*killough*/,{.p2 = A_Light1},S_DSGUNFLASH2}, // S_DSGUNFLASH1 #else - {SPR_SHT2,8|FF_FULLBRIGHT,5,{A_Light1},S_DSGUNFLASH2}, // S_DSGUNFLASH1 + {SPR_SHT2,8|FF_FULLBRIGHT,5,{.p2 = A_Light1},S_DSGUNFLASH2}, // S_DSGUNFLASH1 #endif - {SPR_SHT2,9|FF_FULLBRIGHT,4,{A_Light2},S_LIGHTDONE}, // S_DSGUNFLASH2 - {SPR_CHGG,0,1,{A_WeaponReady},S_CHAIN}, // S_CHAIN - {SPR_CHGG,0,1,{A_Lower},S_CHAINDOWN}, // S_CHAINDOWN - {SPR_CHGG,0,1,{A_Raise},S_CHAINUP}, // S_CHAINUP - {SPR_CHGG,0,4,{A_FireCGun},S_CHAIN2}, // S_CHAIN1 - {SPR_CHGG,1,4,{A_FireCGun},S_CHAIN3}, // S_CHAIN2 - {SPR_CHGG,1,0,{A_ReFire},S_CHAIN}, // S_CHAIN3 - {SPR_CHGF,0|FF_FULLBRIGHT,5,{A_Light1},S_LIGHTDONE}, // S_CHAINFLASH1 - {SPR_CHGF,1|FF_FULLBRIGHT,5,{A_Light2},S_LIGHTDONE}, // S_CHAINFLASH2 - {SPR_MISG,0,1,{A_WeaponReady},S_MISSILE}, // S_MISSILE - {SPR_MISG,0,1,{A_Lower},S_MISSILEDOWN}, // S_MISSILEDOWN - {SPR_MISG,0,1,{A_Raise},S_MISSILEUP}, // S_MISSILEUP - {SPR_MISG,1,8,{A_GunFlash},S_MISSILE2}, // S_MISSILE1 - {SPR_MISG,1,12,{A_FireMissile},S_MISSILE3}, // S_MISSILE2 - {SPR_MISG,1,0,{A_ReFire},S_MISSILE}, // S_MISSILE3 - {SPR_MISF,0|FF_FULLBRIGHT,3,{A_Light1},S_MISSILEFLASH2}, // S_MISSILEFLASH1 + {SPR_SHT2,9|FF_FULLBRIGHT,4,{.p2 = A_Light2},S_LIGHTDONE}, // S_DSGUNFLASH2 + {SPR_CHGG,0,1,{.p2 = A_WeaponReady},S_CHAIN}, // S_CHAIN + {SPR_CHGG,0,1,{.p2 = A_Lower},S_CHAINDOWN}, // S_CHAINDOWN + {SPR_CHGG,0,1,{.p2 = A_Raise},S_CHAINUP}, // S_CHAINUP + {SPR_CHGG,0,4,{.p2 = A_FireCGun},S_CHAIN2}, // S_CHAIN1 + {SPR_CHGG,1,4,{.p2 = A_FireCGun},S_CHAIN3}, // S_CHAIN2 + {SPR_CHGG,1,0,{.p2 = A_ReFire},S_CHAIN}, // S_CHAIN3 + {SPR_CHGF,0|FF_FULLBRIGHT,5,{.p2 = A_Light1},S_LIGHTDONE}, // S_CHAINFLASH1 + {SPR_CHGF,1|FF_FULLBRIGHT,5,{.p2 = A_Light2},S_LIGHTDONE}, // S_CHAINFLASH2 + {SPR_MISG,0,1,{.p2 = A_WeaponReady},S_MISSILE}, // S_MISSILE + {SPR_MISG,0,1,{.p2 = A_Lower},S_MISSILEDOWN}, // S_MISSILEDOWN + {SPR_MISG,0,1,{.p2 = A_Raise},S_MISSILEUP}, // S_MISSILEUP + {SPR_MISG,1,8,{.p2 = A_GunFlash},S_MISSILE2}, // S_MISSILE1 + {SPR_MISG,1,12,{.p2 = A_FireMissile},S_MISSILE3}, // S_MISSILE2 + {SPR_MISG,1,0,{.p2 = A_ReFire},S_MISSILE}, // S_MISSILE3 + {SPR_MISF,0|FF_FULLBRIGHT,3,{.p2 = A_Light1},S_MISSILEFLASH2}, // S_MISSILEFLASH1 {SPR_MISF,1|FF_FULLBRIGHT,4,{NULL},S_MISSILEFLASH3}, // S_MISSILEFLASH2 - {SPR_MISF,2|FF_FULLBRIGHT,4,{A_Light2},S_MISSILEFLASH4}, // S_MISSILEFLASH3 - {SPR_MISF,3|FF_FULLBRIGHT,4,{A_Light2},S_LIGHTDONE}, // S_MISSILEFLASH4 - {SPR_SAWG,2,4,{A_WeaponReady},S_SAWB}, // S_SAW - {SPR_SAWG,3,4,{A_WeaponReady},S_SAW}, // S_SAWB - {SPR_SAWG,2,1,{A_Lower},S_SAWDOWN}, // S_SAWDOWN - {SPR_SAWG,2,1,{A_Raise},S_SAWUP}, // S_SAWUP - {SPR_SAWG,0,4,{A_Saw},S_SAW2}, // S_SAW1 - {SPR_SAWG,1,4,{A_Saw},S_SAW3}, // S_SAW2 - {SPR_SAWG,1,0,{A_ReFire},S_SAW}, // S_SAW3 - {SPR_PLSG,0,1,{A_WeaponReady},S_PLASMA}, // S_PLASMA - {SPR_PLSG,0,1,{A_Lower},S_PLASMADOWN}, // S_PLASMADOWN - {SPR_PLSG,0,1,{A_Raise},S_PLASMAUP}, // S_PLASMAUP - {SPR_PLSG,0,3,{A_FirePlasma},S_PLASMA2}, // S_PLASMA1 - {SPR_PLSG,1,20,{A_ReFire},S_PLASMA}, // S_PLASMA2 - {SPR_PLSF,0|FF_FULLBRIGHT,4,{A_Light1},S_LIGHTDONE}, // S_PLASMAFLASH1 - {SPR_PLSF,1|FF_FULLBRIGHT,4,{A_Light1},S_LIGHTDONE}, // S_PLASMAFLASH2 - {SPR_BFGG,0,1,{A_WeaponReady},S_BFG}, // S_BFG - {SPR_BFGG,0,1,{A_Lower},S_BFGDOWN}, // S_BFGDOWN - {SPR_BFGG,0,1,{A_Raise},S_BFGUP}, // S_BFGUP - {SPR_BFGG,0,20,{A_BFGsound},S_BFG2}, // S_BFG1 - {SPR_BFGG,1,10,{A_GunFlash},S_BFG3}, // S_BFG2 - {SPR_BFGG,1,10,{A_FireBFG},S_BFG4}, // S_BFG3 - {SPR_BFGG,1,20,{A_ReFire},S_BFG}, // S_BFG4 - {SPR_BFGF,0|FF_FULLBRIGHT,11,{A_Light1},S_BFGFLASH2}, // S_BFGFLASH1 - {SPR_BFGF,1|FF_FULLBRIGHT,6,{A_Light2},S_LIGHTDONE}, // S_BFGFLASH2 + {SPR_MISF,2|FF_FULLBRIGHT,4,{.p2 = A_Light2},S_MISSILEFLASH4}, // S_MISSILEFLASH3 + {SPR_MISF,3|FF_FULLBRIGHT,4,{.p2 = A_Light2},S_LIGHTDONE}, // S_MISSILEFLASH4 + {SPR_SAWG,2,4,{.p2 = A_WeaponReady},S_SAWB}, // S_SAW + {SPR_SAWG,3,4,{.p2 = A_WeaponReady},S_SAW}, // S_SAWB + {SPR_SAWG,2,1,{.p2 = A_Lower},S_SAWDOWN}, // S_SAWDOWN + {SPR_SAWG,2,1,{.p2 = A_Raise},S_SAWUP}, // S_SAWUP + {SPR_SAWG,0,4,{.p2 = A_Saw},S_SAW2}, // S_SAW1 + {SPR_SAWG,1,4,{.p2 = A_Saw},S_SAW3}, // S_SAW2 + {SPR_SAWG,1,0,{.p2 = A_ReFire},S_SAW}, // S_SAW3 + {SPR_PLSG,0,1,{.p2 = A_WeaponReady},S_PLASMA}, // S_PLASMA + {SPR_PLSG,0,1,{.p2 = A_Lower},S_PLASMADOWN}, // S_PLASMADOWN + {SPR_PLSG,0,1,{.p2 = A_Raise},S_PLASMAUP}, // S_PLASMAUP + {SPR_PLSG,0,3,{.p2 = A_FirePlasma},S_PLASMA2}, // S_PLASMA1 + {SPR_PLSG,1,20,{.p2 = A_ReFire},S_PLASMA}, // S_PLASMA2 + {SPR_PLSF,0|FF_FULLBRIGHT,4,{.p2 = A_Light1},S_LIGHTDONE}, // S_PLASMAFLASH1 + {SPR_PLSF,1|FF_FULLBRIGHT,4,{.p2 = A_Light1},S_LIGHTDONE}, // S_PLASMAFLASH2 + {SPR_BFGG,0,1,{.p2 = A_WeaponReady},S_BFG}, // S_BFG + {SPR_BFGG,0,1,{.p2 = A_Lower},S_BFGDOWN}, // S_BFGDOWN + {SPR_BFGG,0,1,{.p2 = A_Raise},S_BFGUP}, // S_BFGUP + {SPR_BFGG,0,20,{.p2 = A_BFGsound},S_BFG2}, // S_BFG1 + {SPR_BFGG,1,10,{.p2 = A_GunFlash},S_BFG3}, // S_BFG2 + {SPR_BFGG,1,10,{.p2 = A_FireBFG},S_BFG4}, // S_BFG3 + {SPR_BFGG,1,20,{.p2 = A_ReFire},S_BFG}, // S_BFG4 + {SPR_BFGF,0|FF_FULLBRIGHT,11,{.p2 = A_Light1},S_BFGFLASH2}, // S_BFGFLASH1 + {SPR_BFGF,1|FF_FULLBRIGHT,6,{.p2 = A_Light2},S_LIGHTDONE}, // S_BFGFLASH2 {SPR_BLUD,2,8,{NULL},S_BLOOD2}, // S_BLOOD1 {SPR_BLUD,1,8,{NULL},S_BLOOD3}, // S_BLOOD2 {SPR_BLUD,0,8,{NULL},S_NULL}, // S_BLOOD3 @@ -238,7 +238,7 @@ state_t original_states[NUMSTATES] = { {SPR_BFS1,1|FF_FULLBRIGHT,4,{NULL},S_BFGSHOT}, // S_BFGSHOT2 {SPR_BFE1,0|FF_FULLBRIGHT,8,{NULL},S_BFGLAND2}, // S_BFGLAND {SPR_BFE1,1|FF_FULLBRIGHT,8,{NULL},S_BFGLAND3}, // S_BFGLAND2 - {SPR_BFE1,2|FF_FULLBRIGHT,8,{A_BFGSpray},S_BFGLAND4}, // S_BFGLAND3 + {SPR_BFE1,2|FF_FULLBRIGHT,8,{.p1 = A_BFGSpray},S_BFGLAND4}, // S_BFGLAND3 {SPR_BFE1,3|FF_FULLBRIGHT,8,{NULL},S_BFGLAND5}, // S_BFGLAND4 {SPR_BFE1,4|FF_FULLBRIGHT,8,{NULL},S_BFGLAND6}, // S_BFGLAND5 {SPR_BFE1,5|FF_FULLBRIGHT,8,{NULL},S_NULL}, // S_BFGLAND6 @@ -246,7 +246,7 @@ state_t original_states[NUMSTATES] = { {SPR_BFE2,1|FF_FULLBRIGHT,8,{NULL},S_BFGEXP3}, // S_BFGEXP2 {SPR_BFE2,2|FF_FULLBRIGHT,8,{NULL},S_BFGEXP4}, // S_BFGEXP3 {SPR_BFE2,3|FF_FULLBRIGHT,8,{NULL},S_NULL}, // S_BFGEXP4 - {SPR_MISL,1|FF_FULLBRIGHT,8,{A_Explode},S_EXPLODE2}, // S_EXPLODE1 + {SPR_MISL,1|FF_FULLBRIGHT,8,{.p1 = A_Explode},S_EXPLODE2}, // S_EXPLODE1 {SPR_MISL,2|FF_FULLBRIGHT,6,{NULL},S_EXPLODE3}, // S_EXPLODE2 {SPR_MISL,3|FF_FULLBRIGHT,4,{NULL},S_NULL}, // S_EXPLODE3 {SPR_TFOG,0|FF_FULLBRIGHT,6,{NULL},S_TFOG01}, // S_TFOG @@ -276,46 +276,46 @@ state_t original_states[NUMSTATES] = { {SPR_PLAY,4,12,{NULL},S_PLAY}, // S_PLAY_ATK1 {SPR_PLAY,5|FF_FULLBRIGHT,6,{NULL},S_PLAY_ATK1}, // S_PLAY_ATK2 {SPR_PLAY,6,4,{NULL},S_PLAY_PAIN2}, // S_PLAY_PAIN - {SPR_PLAY,6,4,{A_Pain},S_PLAY}, // S_PLAY_PAIN2 + {SPR_PLAY,6,4,{.p1 = A_Pain},S_PLAY}, // S_PLAY_PAIN2 {SPR_PLAY,7,10,{NULL},S_PLAY_DIE2}, // S_PLAY_DIE1 - {SPR_PLAY,8,10,{A_PlayerScream},S_PLAY_DIE3}, // S_PLAY_DIE2 - {SPR_PLAY,9,10,{A_Fall},S_PLAY_DIE4}, // S_PLAY_DIE3 + {SPR_PLAY,8,10,{.p1 = A_PlayerScream},S_PLAY_DIE3}, // S_PLAY_DIE2 + {SPR_PLAY,9,10,{.p1 = A_Fall},S_PLAY_DIE4}, // S_PLAY_DIE3 {SPR_PLAY,10,10,{NULL},S_PLAY_DIE5}, // S_PLAY_DIE4 {SPR_PLAY,11,10,{NULL},S_PLAY_DIE6}, // S_PLAY_DIE5 {SPR_PLAY,12,10,{NULL},S_PLAY_DIE7}, // S_PLAY_DIE6 {SPR_PLAY,13,-1,{NULL},S_NULL}, // S_PLAY_DIE7 {SPR_PLAY,14,5,{NULL},S_PLAY_XDIE2}, // S_PLAY_XDIE1 - {SPR_PLAY,15,5,{A_XScream},S_PLAY_XDIE3}, // S_PLAY_XDIE2 - {SPR_PLAY,16,5,{A_Fall},S_PLAY_XDIE4}, // S_PLAY_XDIE3 + {SPR_PLAY,15,5,{.p1 = A_XScream},S_PLAY_XDIE3}, // S_PLAY_XDIE2 + {SPR_PLAY,16,5,{.p1 = A_Fall},S_PLAY_XDIE4}, // S_PLAY_XDIE3 {SPR_PLAY,17,5,{NULL},S_PLAY_XDIE5}, // S_PLAY_XDIE4 {SPR_PLAY,18,5,{NULL},S_PLAY_XDIE6}, // S_PLAY_XDIE5 {SPR_PLAY,19,5,{NULL},S_PLAY_XDIE7}, // S_PLAY_XDIE6 {SPR_PLAY,20,5,{NULL},S_PLAY_XDIE8}, // S_PLAY_XDIE7 {SPR_PLAY,21,5,{NULL},S_PLAY_XDIE9}, // S_PLAY_XDIE8 {SPR_PLAY,22,-1,{NULL},S_NULL}, // S_PLAY_XDIE9 - {SPR_POSS,0,10,{A_Look},S_POSS_STND2}, // S_POSS_STND - {SPR_POSS,1,10,{A_Look},S_POSS_STND}, // S_POSS_STND2 - {SPR_POSS,0,4,{A_Chase},S_POSS_RUN2}, // S_POSS_RUN1 - {SPR_POSS,0,4,{A_Chase},S_POSS_RUN3}, // S_POSS_RUN2 - {SPR_POSS,1,4,{A_Chase},S_POSS_RUN4}, // S_POSS_RUN3 - {SPR_POSS,1,4,{A_Chase},S_POSS_RUN5}, // S_POSS_RUN4 - {SPR_POSS,2,4,{A_Chase},S_POSS_RUN6}, // S_POSS_RUN5 - {SPR_POSS,2,4,{A_Chase},S_POSS_RUN7}, // S_POSS_RUN6 - {SPR_POSS,3,4,{A_Chase},S_POSS_RUN8}, // S_POSS_RUN7 - {SPR_POSS,3,4,{A_Chase},S_POSS_RUN1}, // S_POSS_RUN8 - {SPR_POSS,4,10,{A_FaceTarget},S_POSS_ATK2}, // S_POSS_ATK1 - {SPR_POSS,5,8,{A_PosAttack},S_POSS_ATK3}, // S_POSS_ATK2 + {SPR_POSS,0,10,{.p1 = A_Look},S_POSS_STND2}, // S_POSS_STND + {SPR_POSS,1,10,{.p1 = A_Look},S_POSS_STND}, // S_POSS_STND2 + {SPR_POSS,0,4,{.p1 = A_Chase},S_POSS_RUN2}, // S_POSS_RUN1 + {SPR_POSS,0,4,{.p1 = A_Chase},S_POSS_RUN3}, // S_POSS_RUN2 + {SPR_POSS,1,4,{.p1 = A_Chase},S_POSS_RUN4}, // S_POSS_RUN3 + {SPR_POSS,1,4,{.p1 = A_Chase},S_POSS_RUN5}, // S_POSS_RUN4 + {SPR_POSS,2,4,{.p1 = A_Chase},S_POSS_RUN6}, // S_POSS_RUN5 + {SPR_POSS,2,4,{.p1 = A_Chase},S_POSS_RUN7}, // S_POSS_RUN6 + {SPR_POSS,3,4,{.p1 = A_Chase},S_POSS_RUN8}, // S_POSS_RUN7 + {SPR_POSS,3,4,{.p1 = A_Chase},S_POSS_RUN1}, // S_POSS_RUN8 + {SPR_POSS,4,10,{.p1 = A_FaceTarget},S_POSS_ATK2}, // S_POSS_ATK1 + {SPR_POSS,5,8,{.p1 = A_PosAttack},S_POSS_ATK3}, // S_POSS_ATK2 {SPR_POSS,4,8,{NULL},S_POSS_RUN1}, // S_POSS_ATK3 {SPR_POSS,6,3,{NULL},S_POSS_PAIN2}, // S_POSS_PAIN - {SPR_POSS,6,3,{A_Pain},S_POSS_RUN1}, // S_POSS_PAIN2 + {SPR_POSS,6,3,{.p1 = A_Pain},S_POSS_RUN1}, // S_POSS_PAIN2 {SPR_POSS,7,5,{NULL},S_POSS_DIE2}, // S_POSS_DIE1 - {SPR_POSS,8,5,{A_Scream},S_POSS_DIE3}, // S_POSS_DIE2 - {SPR_POSS,9,5,{A_Fall},S_POSS_DIE4}, // S_POSS_DIE3 + {SPR_POSS,8,5,{.p1 = A_Scream},S_POSS_DIE3}, // S_POSS_DIE2 + {SPR_POSS,9,5,{.p1 = A_Fall},S_POSS_DIE4}, // S_POSS_DIE3 {SPR_POSS,10,5,{NULL},S_POSS_DIE5}, // S_POSS_DIE4 {SPR_POSS,11,-1,{NULL},S_NULL}, // S_POSS_DIE5 {SPR_POSS,12,5,{NULL},S_POSS_XDIE2}, // S_POSS_XDIE1 - {SPR_POSS,13,5,{A_XScream},S_POSS_XDIE3}, // S_POSS_XDIE2 - {SPR_POSS,14,5,{A_Fall},S_POSS_XDIE4}, // S_POSS_XDIE3 + {SPR_POSS,13,5,{.p1 = A_XScream},S_POSS_XDIE3}, // S_POSS_XDIE2 + {SPR_POSS,14,5,{.p1 = A_Fall},S_POSS_XDIE4}, // S_POSS_XDIE3 {SPR_POSS,15,5,{NULL},S_POSS_XDIE5}, // S_POSS_XDIE4 {SPR_POSS,16,5,{NULL},S_POSS_XDIE6}, // S_POSS_XDIE5 {SPR_POSS,17,5,{NULL},S_POSS_XDIE7}, // S_POSS_XDIE6 @@ -326,29 +326,29 @@ state_t original_states[NUMSTATES] = { {SPR_POSS,9,5,{NULL},S_POSS_RAISE3}, // S_POSS_RAISE2 {SPR_POSS,8,5,{NULL},S_POSS_RAISE4}, // S_POSS_RAISE3 {SPR_POSS,7,5,{NULL},S_POSS_RUN1}, // S_POSS_RAISE4 - {SPR_SPOS,0,10,{A_Look},S_SPOS_STND2}, // S_SPOS_STND - {SPR_SPOS,1,10,{A_Look},S_SPOS_STND}, // S_SPOS_STND2 - {SPR_SPOS,0,3,{A_Chase},S_SPOS_RUN2}, // S_SPOS_RUN1 - {SPR_SPOS,0,3,{A_Chase},S_SPOS_RUN3}, // S_SPOS_RUN2 - {SPR_SPOS,1,3,{A_Chase},S_SPOS_RUN4}, // S_SPOS_RUN3 - {SPR_SPOS,1,3,{A_Chase},S_SPOS_RUN5}, // S_SPOS_RUN4 - {SPR_SPOS,2,3,{A_Chase},S_SPOS_RUN6}, // S_SPOS_RUN5 - {SPR_SPOS,2,3,{A_Chase},S_SPOS_RUN7}, // S_SPOS_RUN6 - {SPR_SPOS,3,3,{A_Chase},S_SPOS_RUN8}, // S_SPOS_RUN7 - {SPR_SPOS,3,3,{A_Chase},S_SPOS_RUN1}, // S_SPOS_RUN8 - {SPR_SPOS,4,10,{A_FaceTarget},S_SPOS_ATK2}, // S_SPOS_ATK1 - {SPR_SPOS,5|FF_FULLBRIGHT,10,{A_SPosAttack},S_SPOS_ATK3}, // S_SPOS_ATK2 + {SPR_SPOS,0,10,{.p1 = A_Look},S_SPOS_STND2}, // S_SPOS_STND + {SPR_SPOS,1,10,{.p1 = A_Look},S_SPOS_STND}, // S_SPOS_STND2 + {SPR_SPOS,0,3,{.p1 = A_Chase},S_SPOS_RUN2}, // S_SPOS_RUN1 + {SPR_SPOS,0,3,{.p1 = A_Chase},S_SPOS_RUN3}, // S_SPOS_RUN2 + {SPR_SPOS,1,3,{.p1 = A_Chase},S_SPOS_RUN4}, // S_SPOS_RUN3 + {SPR_SPOS,1,3,{.p1 = A_Chase},S_SPOS_RUN5}, // S_SPOS_RUN4 + {SPR_SPOS,2,3,{.p1 = A_Chase},S_SPOS_RUN6}, // S_SPOS_RUN5 + {SPR_SPOS,2,3,{.p1 = A_Chase},S_SPOS_RUN7}, // S_SPOS_RUN6 + {SPR_SPOS,3,3,{.p1 = A_Chase},S_SPOS_RUN8}, // S_SPOS_RUN7 + {SPR_SPOS,3,3,{.p1 = A_Chase},S_SPOS_RUN1}, // S_SPOS_RUN8 + {SPR_SPOS,4,10,{.p1 = A_FaceTarget},S_SPOS_ATK2}, // S_SPOS_ATK1 + {SPR_SPOS,5|FF_FULLBRIGHT,10,{.p1 = A_SPosAttack},S_SPOS_ATK3}, // S_SPOS_ATK2 {SPR_SPOS,4,10,{NULL},S_SPOS_RUN1}, // S_SPOS_ATK3 {SPR_SPOS,6,3,{NULL},S_SPOS_PAIN2}, // S_SPOS_PAIN - {SPR_SPOS,6,3,{A_Pain},S_SPOS_RUN1}, // S_SPOS_PAIN2 + {SPR_SPOS,6,3,{.p1 = A_Pain},S_SPOS_RUN1}, // S_SPOS_PAIN2 {SPR_SPOS,7,5,{NULL},S_SPOS_DIE2}, // S_SPOS_DIE1 - {SPR_SPOS,8,5,{A_Scream},S_SPOS_DIE3}, // S_SPOS_DIE2 - {SPR_SPOS,9,5,{A_Fall},S_SPOS_DIE4}, // S_SPOS_DIE3 + {SPR_SPOS,8,5,{.p1 = A_Scream},S_SPOS_DIE3}, // S_SPOS_DIE2 + {SPR_SPOS,9,5,{.p1 = A_Fall},S_SPOS_DIE4}, // S_SPOS_DIE3 {SPR_SPOS,10,5,{NULL},S_SPOS_DIE5}, // S_SPOS_DIE4 {SPR_SPOS,11,-1,{NULL},S_NULL}, // S_SPOS_DIE5 {SPR_SPOS,12,5,{NULL},S_SPOS_XDIE2}, // S_SPOS_XDIE1 - {SPR_SPOS,13,5,{A_XScream},S_SPOS_XDIE3}, // S_SPOS_XDIE2 - {SPR_SPOS,14,5,{A_Fall},S_SPOS_XDIE4}, // S_SPOS_XDIE3 + {SPR_SPOS,13,5,{.p1 = A_XScream},S_SPOS_XDIE3}, // S_SPOS_XDIE2 + {SPR_SPOS,14,5,{.p1 = A_Fall},S_SPOS_XDIE4}, // S_SPOS_XDIE3 {SPR_SPOS,15,5,{NULL},S_SPOS_XDIE5}, // S_SPOS_XDIE4 {SPR_SPOS,16,5,{NULL},S_SPOS_XDIE6}, // S_SPOS_XDIE5 {SPR_SPOS,17,5,{NULL},S_SPOS_XDIE7}, // S_SPOS_XDIE6 @@ -360,39 +360,39 @@ state_t original_states[NUMSTATES] = { {SPR_SPOS,9,5,{NULL},S_SPOS_RAISE4}, // S_SPOS_RAISE3 {SPR_SPOS,8,5,{NULL},S_SPOS_RAISE5}, // S_SPOS_RAISE4 {SPR_SPOS,7,5,{NULL},S_SPOS_RUN1}, // S_SPOS_RAISE5 - {SPR_VILE,0,10,{A_Look},S_VILE_STND2}, // S_VILE_STND - {SPR_VILE,1,10,{A_Look},S_VILE_STND}, // S_VILE_STND2 - {SPR_VILE,0,2,{A_VileChase},S_VILE_RUN2}, // S_VILE_RUN1 - {SPR_VILE,0,2,{A_VileChase},S_VILE_RUN3}, // S_VILE_RUN2 - {SPR_VILE,1,2,{A_VileChase},S_VILE_RUN4}, // S_VILE_RUN3 - {SPR_VILE,1,2,{A_VileChase},S_VILE_RUN5}, // S_VILE_RUN4 - {SPR_VILE,2,2,{A_VileChase},S_VILE_RUN6}, // S_VILE_RUN5 - {SPR_VILE,2,2,{A_VileChase},S_VILE_RUN7}, // S_VILE_RUN6 - {SPR_VILE,3,2,{A_VileChase},S_VILE_RUN8}, // S_VILE_RUN7 - {SPR_VILE,3,2,{A_VileChase},S_VILE_RUN9}, // S_VILE_RUN8 - {SPR_VILE,4,2,{A_VileChase},S_VILE_RUN10}, // S_VILE_RUN9 - {SPR_VILE,4,2,{A_VileChase},S_VILE_RUN11}, // S_VILE_RUN10 - {SPR_VILE,5,2,{A_VileChase},S_VILE_RUN12}, // S_VILE_RUN11 - {SPR_VILE,5,2,{A_VileChase},S_VILE_RUN1}, // S_VILE_RUN12 - {SPR_VILE,6|FF_FULLBRIGHT,0,{A_VileStart},S_VILE_ATK2}, // S_VILE_ATK1 - {SPR_VILE,6|FF_FULLBRIGHT,10,{A_FaceTarget},S_VILE_ATK3}, // S_VILE_ATK2 - {SPR_VILE,7|FF_FULLBRIGHT,8,{A_VileTarget},S_VILE_ATK4}, // S_VILE_ATK3 - {SPR_VILE,8|FF_FULLBRIGHT,8,{A_FaceTarget},S_VILE_ATK5}, // S_VILE_ATK4 - {SPR_VILE,9|FF_FULLBRIGHT,8,{A_FaceTarget},S_VILE_ATK6}, // S_VILE_ATK5 - {SPR_VILE,10|FF_FULLBRIGHT,8,{A_FaceTarget},S_VILE_ATK7}, // S_VILE_ATK6 - {SPR_VILE,11|FF_FULLBRIGHT,8,{A_FaceTarget},S_VILE_ATK8}, // S_VILE_ATK7 - {SPR_VILE,12|FF_FULLBRIGHT,8,{A_FaceTarget},S_VILE_ATK9}, // S_VILE_ATK8 - {SPR_VILE,13|FF_FULLBRIGHT,8,{A_FaceTarget},S_VILE_ATK10}, // S_VILE_ATK9 - {SPR_VILE,14|FF_FULLBRIGHT,8,{A_VileAttack},S_VILE_ATK11}, // S_VILE_ATK10 + {SPR_VILE,0,10,{.p1 = A_Look},S_VILE_STND2}, // S_VILE_STND + {SPR_VILE,1,10,{.p1 = A_Look},S_VILE_STND}, // S_VILE_STND2 + {SPR_VILE,0,2,{.p1 = A_VileChase},S_VILE_RUN2}, // S_VILE_RUN1 + {SPR_VILE,0,2,{.p1 = A_VileChase},S_VILE_RUN3}, // S_VILE_RUN2 + {SPR_VILE,1,2,{.p1 = A_VileChase},S_VILE_RUN4}, // S_VILE_RUN3 + {SPR_VILE,1,2,{.p1 = A_VileChase},S_VILE_RUN5}, // S_VILE_RUN4 + {SPR_VILE,2,2,{.p1 = A_VileChase},S_VILE_RUN6}, // S_VILE_RUN5 + {SPR_VILE,2,2,{.p1 = A_VileChase},S_VILE_RUN7}, // S_VILE_RUN6 + {SPR_VILE,3,2,{.p1 = A_VileChase},S_VILE_RUN8}, // S_VILE_RUN7 + {SPR_VILE,3,2,{.p1 = A_VileChase},S_VILE_RUN9}, // S_VILE_RUN8 + {SPR_VILE,4,2,{.p1 = A_VileChase},S_VILE_RUN10}, // S_VILE_RUN9 + {SPR_VILE,4,2,{.p1 = A_VileChase},S_VILE_RUN11}, // S_VILE_RUN10 + {SPR_VILE,5,2,{.p1 = A_VileChase},S_VILE_RUN12}, // S_VILE_RUN11 + {SPR_VILE,5,2,{.p1 = A_VileChase},S_VILE_RUN1}, // S_VILE_RUN12 + {SPR_VILE,6|FF_FULLBRIGHT,0,{.p1 = A_VileStart},S_VILE_ATK2}, // S_VILE_ATK1 + {SPR_VILE,6|FF_FULLBRIGHT,10,{.p1 = A_FaceTarget},S_VILE_ATK3}, // S_VILE_ATK2 + {SPR_VILE,7|FF_FULLBRIGHT,8,{.p1 = A_VileTarget},S_VILE_ATK4}, // S_VILE_ATK3 + {SPR_VILE,8|FF_FULLBRIGHT,8,{.p1 = A_FaceTarget},S_VILE_ATK5}, // S_VILE_ATK4 + {SPR_VILE,9|FF_FULLBRIGHT,8,{.p1 = A_FaceTarget},S_VILE_ATK6}, // S_VILE_ATK5 + {SPR_VILE,10|FF_FULLBRIGHT,8,{.p1 = A_FaceTarget},S_VILE_ATK7}, // S_VILE_ATK6 + {SPR_VILE,11|FF_FULLBRIGHT,8,{.p1 = A_FaceTarget},S_VILE_ATK8}, // S_VILE_ATK7 + {SPR_VILE,12|FF_FULLBRIGHT,8,{.p1 = A_FaceTarget},S_VILE_ATK9}, // S_VILE_ATK8 + {SPR_VILE,13|FF_FULLBRIGHT,8,{.p1 = A_FaceTarget},S_VILE_ATK10}, // S_VILE_ATK9 + {SPR_VILE,14|FF_FULLBRIGHT,8,{.p1 = A_VileAttack},S_VILE_ATK11}, // S_VILE_ATK10 {SPR_VILE,15|FF_FULLBRIGHT,20,{NULL},S_VILE_RUN1}, // S_VILE_ATK11 {SPR_VILE,26|FF_FULLBRIGHT,10,{NULL},S_VILE_HEAL2}, // S_VILE_HEAL1 {SPR_VILE,27|FF_FULLBRIGHT,10,{NULL},S_VILE_HEAL3}, // S_VILE_HEAL2 {SPR_VILE,28|FF_FULLBRIGHT,10,{NULL},S_VILE_RUN1}, // S_VILE_HEAL3 {SPR_VILE,16,5,{NULL},S_VILE_PAIN2}, // S_VILE_PAIN - {SPR_VILE,16,5,{A_Pain},S_VILE_RUN1}, // S_VILE_PAIN2 + {SPR_VILE,16,5,{.p1 = A_Pain},S_VILE_RUN1}, // S_VILE_PAIN2 {SPR_VILE,16,7,{NULL},S_VILE_DIE2}, // S_VILE_DIE1 - {SPR_VILE,17,7,{A_Scream},S_VILE_DIE3}, // S_VILE_DIE2 - {SPR_VILE,18,7,{A_Fall},S_VILE_DIE4}, // S_VILE_DIE3 + {SPR_VILE,17,7,{.p1 = A_Scream},S_VILE_DIE3}, // S_VILE_DIE2 + {SPR_VILE,18,7,{.p1 = A_Fall},S_VILE_DIE4}, // S_VILE_DIE3 {SPR_VILE,19,7,{NULL},S_VILE_DIE5}, // S_VILE_DIE4 {SPR_VILE,20,7,{NULL},S_VILE_DIE6}, // S_VILE_DIE5 {SPR_VILE,21,7,{NULL},S_VILE_DIE7}, // S_VILE_DIE6 @@ -400,74 +400,74 @@ state_t original_states[NUMSTATES] = { {SPR_VILE,23,5,{NULL},S_VILE_DIE9}, // S_VILE_DIE8 {SPR_VILE,24,5,{NULL},S_VILE_DIE10}, // S_VILE_DIE9 {SPR_VILE,25,-1,{NULL},S_NULL}, // S_VILE_DIE10 - {SPR_FIRE,0|FF_FULLBRIGHT,2,{A_StartFire},S_FIRE2}, // S_FIRE1 - {SPR_FIRE,1|FF_FULLBRIGHT,2,{A_Fire},S_FIRE3}, // S_FIRE2 - {SPR_FIRE,0|FF_FULLBRIGHT,2,{A_Fire},S_FIRE4}, // S_FIRE3 - {SPR_FIRE,1|FF_FULLBRIGHT,2,{A_Fire},S_FIRE5}, // S_FIRE4 - {SPR_FIRE,2|FF_FULLBRIGHT,2,{A_FireCrackle},S_FIRE6}, // S_FIRE5 - {SPR_FIRE,1|FF_FULLBRIGHT,2,{A_Fire},S_FIRE7}, // S_FIRE6 - {SPR_FIRE,2|FF_FULLBRIGHT,2,{A_Fire},S_FIRE8}, // S_FIRE7 - {SPR_FIRE,1|FF_FULLBRIGHT,2,{A_Fire},S_FIRE9}, // S_FIRE8 - {SPR_FIRE,2|FF_FULLBRIGHT,2,{A_Fire},S_FIRE10}, // S_FIRE9 - {SPR_FIRE,3|FF_FULLBRIGHT,2,{A_Fire},S_FIRE11}, // S_FIRE10 - {SPR_FIRE,2|FF_FULLBRIGHT,2,{A_Fire},S_FIRE12}, // S_FIRE11 - {SPR_FIRE,3|FF_FULLBRIGHT,2,{A_Fire},S_FIRE13}, // S_FIRE12 - {SPR_FIRE,2|FF_FULLBRIGHT,2,{A_Fire},S_FIRE14}, // S_FIRE13 - {SPR_FIRE,3|FF_FULLBRIGHT,2,{A_Fire},S_FIRE15}, // S_FIRE14 - {SPR_FIRE,4|FF_FULLBRIGHT,2,{A_Fire},S_FIRE16}, // S_FIRE15 - {SPR_FIRE,3|FF_FULLBRIGHT,2,{A_Fire},S_FIRE17}, // S_FIRE16 - {SPR_FIRE,4|FF_FULLBRIGHT,2,{A_Fire},S_FIRE18}, // S_FIRE17 - {SPR_FIRE,3|FF_FULLBRIGHT,2,{A_Fire},S_FIRE19}, // S_FIRE18 - {SPR_FIRE,4|FF_FULLBRIGHT,2,{A_FireCrackle},S_FIRE20}, // S_FIRE19 - {SPR_FIRE,5|FF_FULLBRIGHT,2,{A_Fire},S_FIRE21}, // S_FIRE20 - {SPR_FIRE,4|FF_FULLBRIGHT,2,{A_Fire},S_FIRE22}, // S_FIRE21 - {SPR_FIRE,5|FF_FULLBRIGHT,2,{A_Fire},S_FIRE23}, // S_FIRE22 - {SPR_FIRE,4|FF_FULLBRIGHT,2,{A_Fire},S_FIRE24}, // S_FIRE23 - {SPR_FIRE,5|FF_FULLBRIGHT,2,{A_Fire},S_FIRE25}, // S_FIRE24 - {SPR_FIRE,6|FF_FULLBRIGHT,2,{A_Fire},S_FIRE26}, // S_FIRE25 - {SPR_FIRE,7|FF_FULLBRIGHT,2,{A_Fire},S_FIRE27}, // S_FIRE26 - {SPR_FIRE,6|FF_FULLBRIGHT,2,{A_Fire},S_FIRE28}, // S_FIRE27 - {SPR_FIRE,7|FF_FULLBRIGHT,2,{A_Fire},S_FIRE29}, // S_FIRE28 - {SPR_FIRE,6|FF_FULLBRIGHT,2,{A_Fire},S_FIRE30}, // S_FIRE29 - {SPR_FIRE,7|FF_FULLBRIGHT,2,{A_Fire},S_NULL}, // S_FIRE30 + {SPR_FIRE,0|FF_FULLBRIGHT,2,{.p1 = A_StartFire},S_FIRE2}, // S_FIRE1 + {SPR_FIRE,1|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE3}, // S_FIRE2 + {SPR_FIRE,0|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE4}, // S_FIRE3 + {SPR_FIRE,1|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE5}, // S_FIRE4 + {SPR_FIRE,2|FF_FULLBRIGHT,2,{.p1 = A_FireCrackle},S_FIRE6}, // S_FIRE5 + {SPR_FIRE,1|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE7}, // S_FIRE6 + {SPR_FIRE,2|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE8}, // S_FIRE7 + {SPR_FIRE,1|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE9}, // S_FIRE8 + {SPR_FIRE,2|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE10}, // S_FIRE9 + {SPR_FIRE,3|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE11}, // S_FIRE10 + {SPR_FIRE,2|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE12}, // S_FIRE11 + {SPR_FIRE,3|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE13}, // S_FIRE12 + {SPR_FIRE,2|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE14}, // S_FIRE13 + {SPR_FIRE,3|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE15}, // S_FIRE14 + {SPR_FIRE,4|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE16}, // S_FIRE15 + {SPR_FIRE,3|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE17}, // S_FIRE16 + {SPR_FIRE,4|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE18}, // S_FIRE17 + {SPR_FIRE,3|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE19}, // S_FIRE18 + {SPR_FIRE,4|FF_FULLBRIGHT,2,{.p1 = A_FireCrackle},S_FIRE20}, // S_FIRE19 + {SPR_FIRE,5|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE21}, // S_FIRE20 + {SPR_FIRE,4|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE22}, // S_FIRE21 + {SPR_FIRE,5|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE23}, // S_FIRE22 + {SPR_FIRE,4|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE24}, // S_FIRE23 + {SPR_FIRE,5|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE25}, // S_FIRE24 + {SPR_FIRE,6|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE26}, // S_FIRE25 + {SPR_FIRE,7|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE27}, // S_FIRE26 + {SPR_FIRE,6|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE28}, // S_FIRE27 + {SPR_FIRE,7|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE29}, // S_FIRE28 + {SPR_FIRE,6|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_FIRE30}, // S_FIRE29 + {SPR_FIRE,7|FF_FULLBRIGHT,2,{.p1 = A_Fire},S_NULL}, // S_FIRE30 {SPR_PUFF,1,4,{NULL},S_SMOKE2}, // S_SMOKE1 {SPR_PUFF,2,4,{NULL},S_SMOKE3}, // S_SMOKE2 {SPR_PUFF,1,4,{NULL},S_SMOKE4}, // S_SMOKE3 {SPR_PUFF,2,4,{NULL},S_SMOKE5}, // S_SMOKE4 {SPR_PUFF,3,4,{NULL},S_NULL}, // S_SMOKE5 - {SPR_FATB,0|FF_FULLBRIGHT,2,{A_Tracer},S_TRACER2}, // S_TRACER - {SPR_FATB,1|FF_FULLBRIGHT,2,{A_Tracer},S_TRACER}, // S_TRACER2 + {SPR_FATB,0|FF_FULLBRIGHT,2,{.p1 = A_Tracer},S_TRACER2}, // S_TRACER + {SPR_FATB,1|FF_FULLBRIGHT,2,{.p1 = A_Tracer},S_TRACER}, // S_TRACER2 {SPR_FBXP,0|FF_FULLBRIGHT,8,{NULL},S_TRACEEXP2}, // S_TRACEEXP1 {SPR_FBXP,1|FF_FULLBRIGHT,6,{NULL},S_TRACEEXP3}, // S_TRACEEXP2 {SPR_FBXP,2|FF_FULLBRIGHT,4,{NULL},S_NULL}, // S_TRACEEXP3 - {SPR_SKEL,0,10,{A_Look},S_SKEL_STND2}, // S_SKEL_STND - {SPR_SKEL,1,10,{A_Look},S_SKEL_STND}, // S_SKEL_STND2 - {SPR_SKEL,0,2,{A_Chase},S_SKEL_RUN2}, // S_SKEL_RUN1 - {SPR_SKEL,0,2,{A_Chase},S_SKEL_RUN3}, // S_SKEL_RUN2 - {SPR_SKEL,1,2,{A_Chase},S_SKEL_RUN4}, // S_SKEL_RUN3 - {SPR_SKEL,1,2,{A_Chase},S_SKEL_RUN5}, // S_SKEL_RUN4 - {SPR_SKEL,2,2,{A_Chase},S_SKEL_RUN6}, // S_SKEL_RUN5 - {SPR_SKEL,2,2,{A_Chase},S_SKEL_RUN7}, // S_SKEL_RUN6 - {SPR_SKEL,3,2,{A_Chase},S_SKEL_RUN8}, // S_SKEL_RUN7 - {SPR_SKEL,3,2,{A_Chase},S_SKEL_RUN9}, // S_SKEL_RUN8 - {SPR_SKEL,4,2,{A_Chase},S_SKEL_RUN10}, // S_SKEL_RUN9 - {SPR_SKEL,4,2,{A_Chase},S_SKEL_RUN11}, // S_SKEL_RUN10 - {SPR_SKEL,5,2,{A_Chase},S_SKEL_RUN12}, // S_SKEL_RUN11 - {SPR_SKEL,5,2,{A_Chase},S_SKEL_RUN1}, // S_SKEL_RUN12 - {SPR_SKEL,6,0,{A_FaceTarget},S_SKEL_FIST2}, // S_SKEL_FIST1 - {SPR_SKEL,6,6,{A_SkelWhoosh},S_SKEL_FIST3}, // S_SKEL_FIST2 - {SPR_SKEL,7,6,{A_FaceTarget},S_SKEL_FIST4}, // S_SKEL_FIST3 - {SPR_SKEL,8,6,{A_SkelFist},S_SKEL_RUN1}, // S_SKEL_FIST4 - {SPR_SKEL,9|FF_FULLBRIGHT,0,{A_FaceTarget},S_SKEL_MISS2}, // S_SKEL_MISS1 - {SPR_SKEL,9|FF_FULLBRIGHT,10,{A_FaceTarget},S_SKEL_MISS3}, // S_SKEL_MISS2 - {SPR_SKEL,10,10,{A_SkelMissile},S_SKEL_MISS4}, // S_SKEL_MISS3 - {SPR_SKEL,10,10,{A_FaceTarget},S_SKEL_RUN1}, // S_SKEL_MISS4 + {SPR_SKEL,0,10,{.p1 = A_Look},S_SKEL_STND2}, // S_SKEL_STND + {SPR_SKEL,1,10,{.p1 = A_Look},S_SKEL_STND}, // S_SKEL_STND2 + {SPR_SKEL,0,2,{.p1 = A_Chase},S_SKEL_RUN2}, // S_SKEL_RUN1 + {SPR_SKEL,0,2,{.p1 = A_Chase},S_SKEL_RUN3}, // S_SKEL_RUN2 + {SPR_SKEL,1,2,{.p1 = A_Chase},S_SKEL_RUN4}, // S_SKEL_RUN3 + {SPR_SKEL,1,2,{.p1 = A_Chase},S_SKEL_RUN5}, // S_SKEL_RUN4 + {SPR_SKEL,2,2,{.p1 = A_Chase},S_SKEL_RUN6}, // S_SKEL_RUN5 + {SPR_SKEL,2,2,{.p1 = A_Chase},S_SKEL_RUN7}, // S_SKEL_RUN6 + {SPR_SKEL,3,2,{.p1 = A_Chase},S_SKEL_RUN8}, // S_SKEL_RUN7 + {SPR_SKEL,3,2,{.p1 = A_Chase},S_SKEL_RUN9}, // S_SKEL_RUN8 + {SPR_SKEL,4,2,{.p1 = A_Chase},S_SKEL_RUN10}, // S_SKEL_RUN9 + {SPR_SKEL,4,2,{.p1 = A_Chase},S_SKEL_RUN11}, // S_SKEL_RUN10 + {SPR_SKEL,5,2,{.p1 = A_Chase},S_SKEL_RUN12}, // S_SKEL_RUN11 + {SPR_SKEL,5,2,{.p1 = A_Chase},S_SKEL_RUN1}, // S_SKEL_RUN12 + {SPR_SKEL,6,0,{.p1 = A_FaceTarget},S_SKEL_FIST2}, // S_SKEL_FIST1 + {SPR_SKEL,6,6,{.p1 = A_SkelWhoosh},S_SKEL_FIST3}, // S_SKEL_FIST2 + {SPR_SKEL,7,6,{.p1 = A_FaceTarget},S_SKEL_FIST4}, // S_SKEL_FIST3 + {SPR_SKEL,8,6,{.p1 = A_SkelFist},S_SKEL_RUN1}, // S_SKEL_FIST4 + {SPR_SKEL,9|FF_FULLBRIGHT,0,{.p1 = A_FaceTarget},S_SKEL_MISS2}, // S_SKEL_MISS1 + {SPR_SKEL,9|FF_FULLBRIGHT,10,{.p1 = A_FaceTarget},S_SKEL_MISS3}, // S_SKEL_MISS2 + {SPR_SKEL,10,10,{.p1 = A_SkelMissile},S_SKEL_MISS4}, // S_SKEL_MISS3 + {SPR_SKEL,10,10,{.p1 = A_FaceTarget},S_SKEL_RUN1}, // S_SKEL_MISS4 {SPR_SKEL,11,5,{NULL},S_SKEL_PAIN2}, // S_SKEL_PAIN - {SPR_SKEL,11,5,{A_Pain},S_SKEL_RUN1}, // S_SKEL_PAIN2 + {SPR_SKEL,11,5,{.p1 = A_Pain},S_SKEL_RUN1}, // S_SKEL_PAIN2 {SPR_SKEL,11,7,{NULL},S_SKEL_DIE2}, // S_SKEL_DIE1 {SPR_SKEL,12,7,{NULL},S_SKEL_DIE3}, // S_SKEL_DIE2 - {SPR_SKEL,13,7,{A_Scream},S_SKEL_DIE4}, // S_SKEL_DIE3 - {SPR_SKEL,14,7,{A_Fall},S_SKEL_DIE5}, // S_SKEL_DIE4 + {SPR_SKEL,13,7,{.p1 = A_Scream},S_SKEL_DIE4}, // S_SKEL_DIE3 + {SPR_SKEL,14,7,{.p1 = A_Fall},S_SKEL_DIE5}, // S_SKEL_DIE4 {SPR_SKEL,15,7,{NULL},S_SKEL_DIE6}, // S_SKEL_DIE5 {SPR_SKEL,16,-1,{NULL},S_NULL}, // S_SKEL_DIE6 {SPR_SKEL,16,5,{NULL},S_SKEL_RAISE2}, // S_SKEL_RAISE1 @@ -481,42 +481,42 @@ state_t original_states[NUMSTATES] = { {SPR_MISL,1|FF_FULLBRIGHT,8,{NULL},S_FATSHOTX2}, // S_FATSHOTX1 {SPR_MISL,2|FF_FULLBRIGHT,6,{NULL},S_FATSHOTX3}, // S_FATSHOTX2 {SPR_MISL,3|FF_FULLBRIGHT,4,{NULL},S_NULL}, // S_FATSHOTX3 - {SPR_FATT,0,15,{A_Look},S_FATT_STND2}, // S_FATT_STND - {SPR_FATT,1,15,{A_Look},S_FATT_STND}, // S_FATT_STND2 - {SPR_FATT,0,4,{A_Chase},S_FATT_RUN2}, // S_FATT_RUN1 - {SPR_FATT,0,4,{A_Chase},S_FATT_RUN3}, // S_FATT_RUN2 - {SPR_FATT,1,4,{A_Chase},S_FATT_RUN4}, // S_FATT_RUN3 - {SPR_FATT,1,4,{A_Chase},S_FATT_RUN5}, // S_FATT_RUN4 - {SPR_FATT,2,4,{A_Chase},S_FATT_RUN6}, // S_FATT_RUN5 - {SPR_FATT,2,4,{A_Chase},S_FATT_RUN7}, // S_FATT_RUN6 - {SPR_FATT,3,4,{A_Chase},S_FATT_RUN8}, // S_FATT_RUN7 - {SPR_FATT,3,4,{A_Chase},S_FATT_RUN9}, // S_FATT_RUN8 - {SPR_FATT,4,4,{A_Chase},S_FATT_RUN10}, // S_FATT_RUN9 - {SPR_FATT,4,4,{A_Chase},S_FATT_RUN11}, // S_FATT_RUN10 - {SPR_FATT,5,4,{A_Chase},S_FATT_RUN12}, // S_FATT_RUN11 - {SPR_FATT,5,4,{A_Chase},S_FATT_RUN1}, // S_FATT_RUN12 - {SPR_FATT,6,20,{A_FatRaise},S_FATT_ATK2}, // S_FATT_ATK1 - {SPR_FATT,7|FF_FULLBRIGHT,10,{A_FatAttack1},S_FATT_ATK3}, // S_FATT_ATK2 - {SPR_FATT,8,5,{A_FaceTarget},S_FATT_ATK4}, // S_FATT_ATK3 - {SPR_FATT,6,5,{A_FaceTarget},S_FATT_ATK5}, // S_FATT_ATK4 - {SPR_FATT,7|FF_FULLBRIGHT,10,{A_FatAttack2},S_FATT_ATK6}, // S_FATT_ATK5 - {SPR_FATT,8,5,{A_FaceTarget},S_FATT_ATK7}, // S_FATT_ATK6 - {SPR_FATT,6,5,{A_FaceTarget},S_FATT_ATK8}, // S_FATT_ATK7 - {SPR_FATT,7|FF_FULLBRIGHT,10,{A_FatAttack3},S_FATT_ATK9}, // S_FATT_ATK8 - {SPR_FATT,8,5,{A_FaceTarget},S_FATT_ATK10}, // S_FATT_ATK9 - {SPR_FATT,6,5,{A_FaceTarget},S_FATT_RUN1}, // S_FATT_ATK10 + {SPR_FATT,0,15,{.p1 = A_Look},S_FATT_STND2}, // S_FATT_STND + {SPR_FATT,1,15,{.p1 = A_Look},S_FATT_STND}, // S_FATT_STND2 + {SPR_FATT,0,4,{.p1 = A_Chase},S_FATT_RUN2}, // S_FATT_RUN1 + {SPR_FATT,0,4,{.p1 = A_Chase},S_FATT_RUN3}, // S_FATT_RUN2 + {SPR_FATT,1,4,{.p1 = A_Chase},S_FATT_RUN4}, // S_FATT_RUN3 + {SPR_FATT,1,4,{.p1 = A_Chase},S_FATT_RUN5}, // S_FATT_RUN4 + {SPR_FATT,2,4,{.p1 = A_Chase},S_FATT_RUN6}, // S_FATT_RUN5 + {SPR_FATT,2,4,{.p1 = A_Chase},S_FATT_RUN7}, // S_FATT_RUN6 + {SPR_FATT,3,4,{.p1 = A_Chase},S_FATT_RUN8}, // S_FATT_RUN7 + {SPR_FATT,3,4,{.p1 = A_Chase},S_FATT_RUN9}, // S_FATT_RUN8 + {SPR_FATT,4,4,{.p1 = A_Chase},S_FATT_RUN10}, // S_FATT_RUN9 + {SPR_FATT,4,4,{.p1 = A_Chase},S_FATT_RUN11}, // S_FATT_RUN10 + {SPR_FATT,5,4,{.p1 = A_Chase},S_FATT_RUN12}, // S_FATT_RUN11 + {SPR_FATT,5,4,{.p1 = A_Chase},S_FATT_RUN1}, // S_FATT_RUN12 + {SPR_FATT,6,20,{.p1 = A_FatRaise},S_FATT_ATK2}, // S_FATT_ATK1 + {SPR_FATT,7|FF_FULLBRIGHT,10,{.p1 = A_FatAttack1},S_FATT_ATK3}, // S_FATT_ATK2 + {SPR_FATT,8,5,{.p1 = A_FaceTarget},S_FATT_ATK4}, // S_FATT_ATK3 + {SPR_FATT,6,5,{.p1 = A_FaceTarget},S_FATT_ATK5}, // S_FATT_ATK4 + {SPR_FATT,7|FF_FULLBRIGHT,10,{.p1 = A_FatAttack2},S_FATT_ATK6}, // S_FATT_ATK5 + {SPR_FATT,8,5,{.p1 = A_FaceTarget},S_FATT_ATK7}, // S_FATT_ATK6 + {SPR_FATT,6,5,{.p1 = A_FaceTarget},S_FATT_ATK8}, // S_FATT_ATK7 + {SPR_FATT,7|FF_FULLBRIGHT,10,{.p1 = A_FatAttack3},S_FATT_ATK9}, // S_FATT_ATK8 + {SPR_FATT,8,5,{.p1 = A_FaceTarget},S_FATT_ATK10}, // S_FATT_ATK9 + {SPR_FATT,6,5,{.p1 = A_FaceTarget},S_FATT_RUN1}, // S_FATT_ATK10 {SPR_FATT,9,3,{NULL},S_FATT_PAIN2}, // S_FATT_PAIN - {SPR_FATT,9,3,{A_Pain},S_FATT_RUN1}, // S_FATT_PAIN2 + {SPR_FATT,9,3,{.p1 = A_Pain},S_FATT_RUN1}, // S_FATT_PAIN2 {SPR_FATT,10,6,{NULL},S_FATT_DIE2}, // S_FATT_DIE1 - {SPR_FATT,11,6,{A_Scream},S_FATT_DIE3}, // S_FATT_DIE2 - {SPR_FATT,12,6,{A_Fall},S_FATT_DIE4}, // S_FATT_DIE3 + {SPR_FATT,11,6,{.p1 = A_Scream},S_FATT_DIE3}, // S_FATT_DIE2 + {SPR_FATT,12,6,{.p1 = A_Fall},S_FATT_DIE4}, // S_FATT_DIE3 {SPR_FATT,13,6,{NULL},S_FATT_DIE5}, // S_FATT_DIE4 {SPR_FATT,14,6,{NULL},S_FATT_DIE6}, // S_FATT_DIE5 {SPR_FATT,15,6,{NULL},S_FATT_DIE7}, // S_FATT_DIE6 {SPR_FATT,16,6,{NULL},S_FATT_DIE8}, // S_FATT_DIE7 {SPR_FATT,17,6,{NULL},S_FATT_DIE9}, // S_FATT_DIE8 {SPR_FATT,18,6,{NULL},S_FATT_DIE10}, // S_FATT_DIE9 - {SPR_FATT,19,-1,{A_BossDeath},S_NULL}, // S_FATT_DIE10 + {SPR_FATT,19,-1,{.p1 = A_BossDeath},S_NULL}, // S_FATT_DIE10 {SPR_FATT,17,5,{NULL},S_FATT_RAISE2}, // S_FATT_RAISE1 {SPR_FATT,16,5,{NULL},S_FATT_RAISE3}, // S_FATT_RAISE2 {SPR_FATT,15,5,{NULL},S_FATT_RAISE4}, // S_FATT_RAISE3 @@ -525,32 +525,32 @@ state_t original_states[NUMSTATES] = { {SPR_FATT,12,5,{NULL},S_FATT_RAISE7}, // S_FATT_RAISE6 {SPR_FATT,11,5,{NULL},S_FATT_RAISE8}, // S_FATT_RAISE7 {SPR_FATT,10,5,{NULL},S_FATT_RUN1}, // S_FATT_RAISE8 - {SPR_CPOS,0,10,{A_Look},S_CPOS_STND2}, // S_CPOS_STND - {SPR_CPOS,1,10,{A_Look},S_CPOS_STND}, // S_CPOS_STND2 - {SPR_CPOS,0,3,{A_Chase},S_CPOS_RUN2}, // S_CPOS_RUN1 - {SPR_CPOS,0,3,{A_Chase},S_CPOS_RUN3}, // S_CPOS_RUN2 - {SPR_CPOS,1,3,{A_Chase},S_CPOS_RUN4}, // S_CPOS_RUN3 - {SPR_CPOS,1,3,{A_Chase},S_CPOS_RUN5}, // S_CPOS_RUN4 - {SPR_CPOS,2,3,{A_Chase},S_CPOS_RUN6}, // S_CPOS_RUN5 - {SPR_CPOS,2,3,{A_Chase},S_CPOS_RUN7}, // S_CPOS_RUN6 - {SPR_CPOS,3,3,{A_Chase},S_CPOS_RUN8}, // S_CPOS_RUN7 - {SPR_CPOS,3,3,{A_Chase},S_CPOS_RUN1}, // S_CPOS_RUN8 - {SPR_CPOS,4,10,{A_FaceTarget},S_CPOS_ATK2}, // S_CPOS_ATK1 - {SPR_CPOS,5|FF_FULLBRIGHT,4,{A_CPosAttack},S_CPOS_ATK3}, // S_CPOS_ATK2 - {SPR_CPOS,4|FF_FULLBRIGHT,4,{A_CPosAttack},S_CPOS_ATK4}, // S_CPOS_ATK3 - {SPR_CPOS,5,1,{A_CPosRefire},S_CPOS_ATK2}, // S_CPOS_ATK4 + {SPR_CPOS,0,10,{.p1 = A_Look},S_CPOS_STND2}, // S_CPOS_STND + {SPR_CPOS,1,10,{.p1 = A_Look},S_CPOS_STND}, // S_CPOS_STND2 + {SPR_CPOS,0,3,{.p1 = A_Chase},S_CPOS_RUN2}, // S_CPOS_RUN1 + {SPR_CPOS,0,3,{.p1 = A_Chase},S_CPOS_RUN3}, // S_CPOS_RUN2 + {SPR_CPOS,1,3,{.p1 = A_Chase},S_CPOS_RUN4}, // S_CPOS_RUN3 + {SPR_CPOS,1,3,{.p1 = A_Chase},S_CPOS_RUN5}, // S_CPOS_RUN4 + {SPR_CPOS,2,3,{.p1 = A_Chase},S_CPOS_RUN6}, // S_CPOS_RUN5 + {SPR_CPOS,2,3,{.p1 = A_Chase},S_CPOS_RUN7}, // S_CPOS_RUN6 + {SPR_CPOS,3,3,{.p1 = A_Chase},S_CPOS_RUN8}, // S_CPOS_RUN7 + {SPR_CPOS,3,3,{.p1 = A_Chase},S_CPOS_RUN1}, // S_CPOS_RUN8 + {SPR_CPOS,4,10,{.p1 = A_FaceTarget},S_CPOS_ATK2}, // S_CPOS_ATK1 + {SPR_CPOS,5|FF_FULLBRIGHT,4,{.p1 = A_CPosAttack},S_CPOS_ATK3}, // S_CPOS_ATK2 + {SPR_CPOS,4|FF_FULLBRIGHT,4,{.p1 = A_CPosAttack},S_CPOS_ATK4}, // S_CPOS_ATK3 + {SPR_CPOS,5,1,{.p1 = A_CPosRefire},S_CPOS_ATK2}, // S_CPOS_ATK4 {SPR_CPOS,6,3,{NULL},S_CPOS_PAIN2}, // S_CPOS_PAIN - {SPR_CPOS,6,3,{A_Pain},S_CPOS_RUN1}, // S_CPOS_PAIN2 + {SPR_CPOS,6,3,{.p1 = A_Pain},S_CPOS_RUN1}, // S_CPOS_PAIN2 {SPR_CPOS,7,5,{NULL},S_CPOS_DIE2}, // S_CPOS_DIE1 - {SPR_CPOS,8,5,{A_Scream},S_CPOS_DIE3}, // S_CPOS_DIE2 - {SPR_CPOS,9,5,{A_Fall},S_CPOS_DIE4}, // S_CPOS_DIE3 + {SPR_CPOS,8,5,{.p1 = A_Scream},S_CPOS_DIE3}, // S_CPOS_DIE2 + {SPR_CPOS,9,5,{.p1 = A_Fall},S_CPOS_DIE4}, // S_CPOS_DIE3 {SPR_CPOS,10,5,{NULL},S_CPOS_DIE5}, // S_CPOS_DIE4 {SPR_CPOS,11,5,{NULL},S_CPOS_DIE6}, // S_CPOS_DIE5 {SPR_CPOS,12,5,{NULL},S_CPOS_DIE7}, // S_CPOS_DIE6 {SPR_CPOS,13,-1,{NULL},S_NULL}, // S_CPOS_DIE7 {SPR_CPOS,14,5,{NULL},S_CPOS_XDIE2}, // S_CPOS_XDIE1 - {SPR_CPOS,15,5,{A_XScream},S_CPOS_XDIE3}, // S_CPOS_XDIE2 - {SPR_CPOS,16,5,{A_Fall},S_CPOS_XDIE4}, // S_CPOS_XDIE3 + {SPR_CPOS,15,5,{.p1 = A_XScream},S_CPOS_XDIE3}, // S_CPOS_XDIE2 + {SPR_CPOS,16,5,{.p1 = A_Fall},S_CPOS_XDIE4}, // S_CPOS_XDIE3 {SPR_CPOS,17,5,{NULL},S_CPOS_XDIE5}, // S_CPOS_XDIE4 {SPR_CPOS,18,5,{NULL},S_CPOS_XDIE6}, // S_CPOS_XDIE5 {SPR_CPOS,19,-1,{NULL},S_NULL}, // S_CPOS_XDIE6 @@ -561,30 +561,30 @@ state_t original_states[NUMSTATES] = { {SPR_CPOS,9,5,{NULL},S_CPOS_RAISE6}, // S_CPOS_RAISE5 {SPR_CPOS,8,5,{NULL},S_CPOS_RAISE7}, // S_CPOS_RAISE6 {SPR_CPOS,7,5,{NULL},S_CPOS_RUN1}, // S_CPOS_RAISE7 - {SPR_TROO,0,10,{A_Look},S_TROO_STND2}, // S_TROO_STND - {SPR_TROO,1,10,{A_Look},S_TROO_STND}, // S_TROO_STND2 - {SPR_TROO,0,3,{A_Chase},S_TROO_RUN2}, // S_TROO_RUN1 - {SPR_TROO,0,3,{A_Chase},S_TROO_RUN3}, // S_TROO_RUN2 - {SPR_TROO,1,3,{A_Chase},S_TROO_RUN4}, // S_TROO_RUN3 - {SPR_TROO,1,3,{A_Chase},S_TROO_RUN5}, // S_TROO_RUN4 - {SPR_TROO,2,3,{A_Chase},S_TROO_RUN6}, // S_TROO_RUN5 - {SPR_TROO,2,3,{A_Chase},S_TROO_RUN7}, // S_TROO_RUN6 - {SPR_TROO,3,3,{A_Chase},S_TROO_RUN8}, // S_TROO_RUN7 - {SPR_TROO,3,3,{A_Chase},S_TROO_RUN1}, // S_TROO_RUN8 - {SPR_TROO,4,8,{A_FaceTarget},S_TROO_ATK2}, // S_TROO_ATK1 - {SPR_TROO,5,8,{A_FaceTarget},S_TROO_ATK3}, // S_TROO_ATK2 - {SPR_TROO,6,6,{A_TroopAttack},S_TROO_RUN1}, // S_TROO_ATK3 + {SPR_TROO,0,10,{.p1 = A_Look},S_TROO_STND2}, // S_TROO_STND + {SPR_TROO,1,10,{.p1 = A_Look},S_TROO_STND}, // S_TROO_STND2 + {SPR_TROO,0,3,{.p1 = A_Chase},S_TROO_RUN2}, // S_TROO_RUN1 + {SPR_TROO,0,3,{.p1 = A_Chase},S_TROO_RUN3}, // S_TROO_RUN2 + {SPR_TROO,1,3,{.p1 = A_Chase},S_TROO_RUN4}, // S_TROO_RUN3 + {SPR_TROO,1,3,{.p1 = A_Chase},S_TROO_RUN5}, // S_TROO_RUN4 + {SPR_TROO,2,3,{.p1 = A_Chase},S_TROO_RUN6}, // S_TROO_RUN5 + {SPR_TROO,2,3,{.p1 = A_Chase},S_TROO_RUN7}, // S_TROO_RUN6 + {SPR_TROO,3,3,{.p1 = A_Chase},S_TROO_RUN8}, // S_TROO_RUN7 + {SPR_TROO,3,3,{.p1 = A_Chase},S_TROO_RUN1}, // S_TROO_RUN8 + {SPR_TROO,4,8,{.p1 = A_FaceTarget},S_TROO_ATK2}, // S_TROO_ATK1 + {SPR_TROO,5,8,{.p1 = A_FaceTarget},S_TROO_ATK3}, // S_TROO_ATK2 + {SPR_TROO,6,6,{.p1 = A_TroopAttack},S_TROO_RUN1}, // S_TROO_ATK3 {SPR_TROO,7,2,{NULL},S_TROO_PAIN2}, // S_TROO_PAIN - {SPR_TROO,7,2,{A_Pain},S_TROO_RUN1}, // S_TROO_PAIN2 + {SPR_TROO,7,2,{.p1 = A_Pain},S_TROO_RUN1}, // S_TROO_PAIN2 {SPR_TROO,8,8,{NULL},S_TROO_DIE2}, // S_TROO_DIE1 - {SPR_TROO,9,8,{A_Scream},S_TROO_DIE3}, // S_TROO_DIE2 + {SPR_TROO,9,8,{.p1 = A_Scream},S_TROO_DIE3}, // S_TROO_DIE2 {SPR_TROO,10,6,{NULL},S_TROO_DIE4}, // S_TROO_DIE3 - {SPR_TROO,11,6,{A_Fall},S_TROO_DIE5}, // S_TROO_DIE4 + {SPR_TROO,11,6,{.p1 = A_Fall},S_TROO_DIE5}, // S_TROO_DIE4 {SPR_TROO,12,-1,{NULL},S_NULL}, // S_TROO_DIE5 {SPR_TROO,13,5,{NULL},S_TROO_XDIE2}, // S_TROO_XDIE1 - {SPR_TROO,14,5,{A_XScream},S_TROO_XDIE3}, // S_TROO_XDIE2 + {SPR_TROO,14,5,{.p1 = A_XScream},S_TROO_XDIE3}, // S_TROO_XDIE2 {SPR_TROO,15,5,{NULL},S_TROO_XDIE4}, // S_TROO_XDIE3 - {SPR_TROO,16,5,{A_Fall},S_TROO_XDIE5}, // S_TROO_XDIE4 + {SPR_TROO,16,5,{.p1 = A_Fall},S_TROO_XDIE5}, // S_TROO_XDIE4 {SPR_TROO,17,5,{NULL},S_TROO_XDIE6}, // S_TROO_XDIE5 {SPR_TROO,18,5,{NULL},S_TROO_XDIE7}, // S_TROO_XDIE6 {SPR_TROO,19,5,{NULL},S_TROO_XDIE8}, // S_TROO_XDIE7 @@ -594,25 +594,25 @@ state_t original_states[NUMSTATES] = { {SPR_TROO,10,6,{NULL},S_TROO_RAISE4}, // S_TROO_RAISE3 {SPR_TROO,9,6,{NULL},S_TROO_RAISE5}, // S_TROO_RAISE4 {SPR_TROO,8,6,{NULL},S_TROO_RUN1}, // S_TROO_RAISE5 - {SPR_SARG,0,10,{A_Look},S_SARG_STND2}, // S_SARG_STND - {SPR_SARG,1,10,{A_Look},S_SARG_STND}, // S_SARG_STND2 - {SPR_SARG,0,2,{A_Chase},S_SARG_RUN2}, // S_SARG_RUN1 - {SPR_SARG,0,2,{A_Chase},S_SARG_RUN3}, // S_SARG_RUN2 - {SPR_SARG,1,2,{A_Chase},S_SARG_RUN4}, // S_SARG_RUN3 - {SPR_SARG,1,2,{A_Chase},S_SARG_RUN5}, // S_SARG_RUN4 - {SPR_SARG,2,2,{A_Chase},S_SARG_RUN6}, // S_SARG_RUN5 - {SPR_SARG,2,2,{A_Chase},S_SARG_RUN7}, // S_SARG_RUN6 - {SPR_SARG,3,2,{A_Chase},S_SARG_RUN8}, // S_SARG_RUN7 - {SPR_SARG,3,2,{A_Chase},S_SARG_RUN1}, // S_SARG_RUN8 - {SPR_SARG,4,8,{A_FaceTarget},S_SARG_ATK2}, // S_SARG_ATK1 - {SPR_SARG,5,8,{A_FaceTarget},S_SARG_ATK3}, // S_SARG_ATK2 - {SPR_SARG,6,8,{A_SargAttack},S_SARG_RUN1}, // S_SARG_ATK3 + {SPR_SARG,0,10,{.p1 = A_Look},S_SARG_STND2}, // S_SARG_STND + {SPR_SARG,1,10,{.p1 = A_Look},S_SARG_STND}, // S_SARG_STND2 + {SPR_SARG,0,2,{.p1 = A_Chase},S_SARG_RUN2}, // S_SARG_RUN1 + {SPR_SARG,0,2,{.p1 = A_Chase},S_SARG_RUN3}, // S_SARG_RUN2 + {SPR_SARG,1,2,{.p1 = A_Chase},S_SARG_RUN4}, // S_SARG_RUN3 + {SPR_SARG,1,2,{.p1 = A_Chase},S_SARG_RUN5}, // S_SARG_RUN4 + {SPR_SARG,2,2,{.p1 = A_Chase},S_SARG_RUN6}, // S_SARG_RUN5 + {SPR_SARG,2,2,{.p1 = A_Chase},S_SARG_RUN7}, // S_SARG_RUN6 + {SPR_SARG,3,2,{.p1 = A_Chase},S_SARG_RUN8}, // S_SARG_RUN7 + {SPR_SARG,3,2,{.p1 = A_Chase},S_SARG_RUN1}, // S_SARG_RUN8 + {SPR_SARG,4,8,{.p1 = A_FaceTarget},S_SARG_ATK2}, // S_SARG_ATK1 + {SPR_SARG,5,8,{.p1 = A_FaceTarget},S_SARG_ATK3}, // S_SARG_ATK2 + {SPR_SARG,6,8,{.p1 = A_SargAttack},S_SARG_RUN1}, // S_SARG_ATK3 {SPR_SARG,7,2,{NULL},S_SARG_PAIN2}, // S_SARG_PAIN - {SPR_SARG,7,2,{A_Pain},S_SARG_RUN1}, // S_SARG_PAIN2 + {SPR_SARG,7,2,{.p1 = A_Pain},S_SARG_RUN1}, // S_SARG_PAIN2 {SPR_SARG,8,8,{NULL},S_SARG_DIE2}, // S_SARG_DIE1 - {SPR_SARG,9,8,{A_Scream},S_SARG_DIE3}, // S_SARG_DIE2 + {SPR_SARG,9,8,{.p1 = A_Scream},S_SARG_DIE3}, // S_SARG_DIE2 {SPR_SARG,10,4,{NULL},S_SARG_DIE4}, // S_SARG_DIE3 - {SPR_SARG,11,4,{A_Fall},S_SARG_DIE5}, // S_SARG_DIE4 + {SPR_SARG,11,4,{.p1 = A_Fall},S_SARG_DIE5}, // S_SARG_DIE4 {SPR_SARG,12,4,{NULL},S_SARG_DIE6}, // S_SARG_DIE5 {SPR_SARG,13,-1,{NULL},S_NULL}, // S_SARG_DIE6 {SPR_SARG,13,5,{NULL},S_SARG_RAISE2}, // S_SARG_RAISE1 @@ -621,19 +621,19 @@ state_t original_states[NUMSTATES] = { {SPR_SARG,10,5,{NULL},S_SARG_RAISE5}, // S_SARG_RAISE4 {SPR_SARG,9,5,{NULL},S_SARG_RAISE6}, // S_SARG_RAISE5 {SPR_SARG,8,5,{NULL},S_SARG_RUN1}, // S_SARG_RAISE6 - {SPR_HEAD,0,10,{A_Look},S_HEAD_STND}, // S_HEAD_STND - {SPR_HEAD,0,3,{A_Chase},S_HEAD_RUN1}, // S_HEAD_RUN1 - {SPR_HEAD,1,5,{A_FaceTarget},S_HEAD_ATK2}, // S_HEAD_ATK1 - {SPR_HEAD,2,5,{A_FaceTarget},S_HEAD_ATK3}, // S_HEAD_ATK2 - {SPR_HEAD,3|FF_FULLBRIGHT,5,{A_HeadAttack},S_HEAD_RUN1}, // S_HEAD_ATK3 + {SPR_HEAD,0,10,{.p1 = A_Look},S_HEAD_STND}, // S_HEAD_STND + {SPR_HEAD,0,3,{.p1 = A_Chase},S_HEAD_RUN1}, // S_HEAD_RUN1 + {SPR_HEAD,1,5,{.p1 = A_FaceTarget},S_HEAD_ATK2}, // S_HEAD_ATK1 + {SPR_HEAD,2,5,{.p1 = A_FaceTarget},S_HEAD_ATK3}, // S_HEAD_ATK2 + {SPR_HEAD,3|FF_FULLBRIGHT,5,{.p1 = A_HeadAttack},S_HEAD_RUN1}, // S_HEAD_ATK3 {SPR_HEAD,4,3,{NULL},S_HEAD_PAIN2}, // S_HEAD_PAIN - {SPR_HEAD,4,3,{A_Pain},S_HEAD_PAIN3}, // S_HEAD_PAIN2 + {SPR_HEAD,4,3,{.p1 = A_Pain},S_HEAD_PAIN3}, // S_HEAD_PAIN2 {SPR_HEAD,5,6,{NULL},S_HEAD_RUN1}, // S_HEAD_PAIN3 {SPR_HEAD,6,8,{NULL},S_HEAD_DIE2}, // S_HEAD_DIE1 - {SPR_HEAD,7,8,{A_Scream},S_HEAD_DIE3}, // S_HEAD_DIE2 + {SPR_HEAD,7,8,{.p1 = A_Scream},S_HEAD_DIE3}, // S_HEAD_DIE2 {SPR_HEAD,8,8,{NULL},S_HEAD_DIE4}, // S_HEAD_DIE3 {SPR_HEAD,9,8,{NULL},S_HEAD_DIE5}, // S_HEAD_DIE4 - {SPR_HEAD,10,8,{A_Fall},S_HEAD_DIE6}, // S_HEAD_DIE5 + {SPR_HEAD,10,8,{.p1 = A_Fall},S_HEAD_DIE6}, // S_HEAD_DIE5 {SPR_HEAD,11,-1,{NULL},S_NULL}, // S_HEAD_DIE6 {SPR_HEAD,11,8,{NULL},S_HEAD_RAISE2}, // S_HEAD_RAISE1 {SPR_HEAD,10,8,{NULL},S_HEAD_RAISE3}, // S_HEAD_RAISE2 @@ -646,28 +646,28 @@ state_t original_states[NUMSTATES] = { {SPR_BAL7,2|FF_FULLBRIGHT,6,{NULL},S_BRBALLX2}, // S_BRBALLX1 {SPR_BAL7,3|FF_FULLBRIGHT,6,{NULL},S_BRBALLX3}, // S_BRBALLX2 {SPR_BAL7,4|FF_FULLBRIGHT,6,{NULL},S_NULL}, // S_BRBALLX3 - {SPR_BOSS,0,10,{A_Look},S_BOSS_STND2}, // S_BOSS_STND - {SPR_BOSS,1,10,{A_Look},S_BOSS_STND}, // S_BOSS_STND2 - {SPR_BOSS,0,3,{A_Chase},S_BOSS_RUN2}, // S_BOSS_RUN1 - {SPR_BOSS,0,3,{A_Chase},S_BOSS_RUN3}, // S_BOSS_RUN2 - {SPR_BOSS,1,3,{A_Chase},S_BOSS_RUN4}, // S_BOSS_RUN3 - {SPR_BOSS,1,3,{A_Chase},S_BOSS_RUN5}, // S_BOSS_RUN4 - {SPR_BOSS,2,3,{A_Chase},S_BOSS_RUN6}, // S_BOSS_RUN5 - {SPR_BOSS,2,3,{A_Chase},S_BOSS_RUN7}, // S_BOSS_RUN6 - {SPR_BOSS,3,3,{A_Chase},S_BOSS_RUN8}, // S_BOSS_RUN7 - {SPR_BOSS,3,3,{A_Chase},S_BOSS_RUN1}, // S_BOSS_RUN8 - {SPR_BOSS,4,8,{A_FaceTarget},S_BOSS_ATK2}, // S_BOSS_ATK1 - {SPR_BOSS,5,8,{A_FaceTarget},S_BOSS_ATK3}, // S_BOSS_ATK2 - {SPR_BOSS,6,8,{A_BruisAttack},S_BOSS_RUN1}, // S_BOSS_ATK3 + {SPR_BOSS,0,10,{.p1 = A_Look},S_BOSS_STND2}, // S_BOSS_STND + {SPR_BOSS,1,10,{.p1 = A_Look},S_BOSS_STND}, // S_BOSS_STND2 + {SPR_BOSS,0,3,{.p1 = A_Chase},S_BOSS_RUN2}, // S_BOSS_RUN1 + {SPR_BOSS,0,3,{.p1 = A_Chase},S_BOSS_RUN3}, // S_BOSS_RUN2 + {SPR_BOSS,1,3,{.p1 = A_Chase},S_BOSS_RUN4}, // S_BOSS_RUN3 + {SPR_BOSS,1,3,{.p1 = A_Chase},S_BOSS_RUN5}, // S_BOSS_RUN4 + {SPR_BOSS,2,3,{.p1 = A_Chase},S_BOSS_RUN6}, // S_BOSS_RUN5 + {SPR_BOSS,2,3,{.p1 = A_Chase},S_BOSS_RUN7}, // S_BOSS_RUN6 + {SPR_BOSS,3,3,{.p1 = A_Chase},S_BOSS_RUN8}, // S_BOSS_RUN7 + {SPR_BOSS,3,3,{.p1 = A_Chase},S_BOSS_RUN1}, // S_BOSS_RUN8 + {SPR_BOSS,4,8,{.p1 = A_FaceTarget},S_BOSS_ATK2}, // S_BOSS_ATK1 + {SPR_BOSS,5,8,{.p1 = A_FaceTarget},S_BOSS_ATK3}, // S_BOSS_ATK2 + {SPR_BOSS,6,8,{.p1 = A_BruisAttack},S_BOSS_RUN1}, // S_BOSS_ATK3 {SPR_BOSS,7,2,{NULL},S_BOSS_PAIN2}, // S_BOSS_PAIN - {SPR_BOSS,7,2,{A_Pain},S_BOSS_RUN1}, // S_BOSS_PAIN2 + {SPR_BOSS,7,2,{.p1 = A_Pain},S_BOSS_RUN1}, // S_BOSS_PAIN2 {SPR_BOSS,8,8,{NULL},S_BOSS_DIE2}, // S_BOSS_DIE1 - {SPR_BOSS,9,8,{A_Scream},S_BOSS_DIE3}, // S_BOSS_DIE2 + {SPR_BOSS,9,8,{.p1 = A_Scream},S_BOSS_DIE3}, // S_BOSS_DIE2 {SPR_BOSS,10,8,{NULL},S_BOSS_DIE4}, // S_BOSS_DIE3 - {SPR_BOSS,11,8,{A_Fall},S_BOSS_DIE5}, // S_BOSS_DIE4 + {SPR_BOSS,11,8,{.p1 = A_Fall},S_BOSS_DIE5}, // S_BOSS_DIE4 {SPR_BOSS,12,8,{NULL},S_BOSS_DIE6}, // S_BOSS_DIE5 {SPR_BOSS,13,8,{NULL},S_BOSS_DIE7}, // S_BOSS_DIE6 - {SPR_BOSS,14,-1,{A_BossDeath},S_NULL}, // S_BOSS_DIE7 + {SPR_BOSS,14,-1,{.p1 = A_BossDeath},S_NULL}, // S_BOSS_DIE7 {SPR_BOSS,14,8,{NULL},S_BOSS_RAISE2}, // S_BOSS_RAISE1 {SPR_BOSS,13,8,{NULL},S_BOSS_RAISE3}, // S_BOSS_RAISE2 {SPR_BOSS,12,8,{NULL},S_BOSS_RAISE4}, // S_BOSS_RAISE3 @@ -675,25 +675,25 @@ state_t original_states[NUMSTATES] = { {SPR_BOSS,10,8,{NULL},S_BOSS_RAISE6}, // S_BOSS_RAISE5 {SPR_BOSS,9,8,{NULL},S_BOSS_RAISE7}, // S_BOSS_RAISE6 {SPR_BOSS,8,8,{NULL},S_BOSS_RUN1}, // S_BOSS_RAISE7 - {SPR_BOS2,0,10,{A_Look},S_BOS2_STND2}, // S_BOS2_STND - {SPR_BOS2,1,10,{A_Look},S_BOS2_STND}, // S_BOS2_STND2 - {SPR_BOS2,0,3,{A_Chase},S_BOS2_RUN2}, // S_BOS2_RUN1 - {SPR_BOS2,0,3,{A_Chase},S_BOS2_RUN3}, // S_BOS2_RUN2 - {SPR_BOS2,1,3,{A_Chase},S_BOS2_RUN4}, // S_BOS2_RUN3 - {SPR_BOS2,1,3,{A_Chase},S_BOS2_RUN5}, // S_BOS2_RUN4 - {SPR_BOS2,2,3,{A_Chase},S_BOS2_RUN6}, // S_BOS2_RUN5 - {SPR_BOS2,2,3,{A_Chase},S_BOS2_RUN7}, // S_BOS2_RUN6 - {SPR_BOS2,3,3,{A_Chase},S_BOS2_RUN8}, // S_BOS2_RUN7 - {SPR_BOS2,3,3,{A_Chase},S_BOS2_RUN1}, // S_BOS2_RUN8 - {SPR_BOS2,4,8,{A_FaceTarget},S_BOS2_ATK2}, // S_BOS2_ATK1 - {SPR_BOS2,5,8,{A_FaceTarget},S_BOS2_ATK3}, // S_BOS2_ATK2 - {SPR_BOS2,6,8,{A_BruisAttack},S_BOS2_RUN1}, // S_BOS2_ATK3 + {SPR_BOS2,0,10,{.p1 = A_Look},S_BOS2_STND2}, // S_BOS2_STND + {SPR_BOS2,1,10,{.p1 = A_Look},S_BOS2_STND}, // S_BOS2_STND2 + {SPR_BOS2,0,3,{.p1 = A_Chase},S_BOS2_RUN2}, // S_BOS2_RUN1 + {SPR_BOS2,0,3,{.p1 = A_Chase},S_BOS2_RUN3}, // S_BOS2_RUN2 + {SPR_BOS2,1,3,{.p1 = A_Chase},S_BOS2_RUN4}, // S_BOS2_RUN3 + {SPR_BOS2,1,3,{.p1 = A_Chase},S_BOS2_RUN5}, // S_BOS2_RUN4 + {SPR_BOS2,2,3,{.p1 = A_Chase},S_BOS2_RUN6}, // S_BOS2_RUN5 + {SPR_BOS2,2,3,{.p1 = A_Chase},S_BOS2_RUN7}, // S_BOS2_RUN6 + {SPR_BOS2,3,3,{.p1 = A_Chase},S_BOS2_RUN8}, // S_BOS2_RUN7 + {SPR_BOS2,3,3,{.p1 = A_Chase},S_BOS2_RUN1}, // S_BOS2_RUN8 + {SPR_BOS2,4,8,{.p1 = A_FaceTarget},S_BOS2_ATK2}, // S_BOS2_ATK1 + {SPR_BOS2,5,8,{.p1 = A_FaceTarget},S_BOS2_ATK3}, // S_BOS2_ATK2 + {SPR_BOS2,6,8,{.p1 = A_BruisAttack},S_BOS2_RUN1}, // S_BOS2_ATK3 {SPR_BOS2,7,2,{NULL},S_BOS2_PAIN2}, // S_BOS2_PAIN - {SPR_BOS2,7,2,{A_Pain},S_BOS2_RUN1}, // S_BOS2_PAIN2 + {SPR_BOS2,7,2,{.p1 = A_Pain},S_BOS2_RUN1}, // S_BOS2_PAIN2 {SPR_BOS2,8,8,{NULL},S_BOS2_DIE2}, // S_BOS2_DIE1 - {SPR_BOS2,9,8,{A_Scream},S_BOS2_DIE3}, // S_BOS2_DIE2 + {SPR_BOS2,9,8,{.p1 = A_Scream},S_BOS2_DIE3}, // S_BOS2_DIE2 {SPR_BOS2,10,8,{NULL},S_BOS2_DIE4}, // S_BOS2_DIE3 - {SPR_BOS2,11,8,{A_Fall},S_BOS2_DIE5}, // S_BOS2_DIE4 + {SPR_BOS2,11,8,{.p1 = A_Fall},S_BOS2_DIE5}, // S_BOS2_DIE4 {SPR_BOS2,12,8,{NULL},S_BOS2_DIE6}, // S_BOS2_DIE5 {SPR_BOS2,13,8,{NULL},S_BOS2_DIE7}, // S_BOS2_DIE6 {SPR_BOS2,14,-1,{NULL},S_NULL}, // S_BOS2_DIE7 @@ -704,44 +704,44 @@ state_t original_states[NUMSTATES] = { {SPR_BOS2,10,8,{NULL},S_BOS2_RAISE6}, // S_BOS2_RAISE5 {SPR_BOS2,9,8,{NULL},S_BOS2_RAISE7}, // S_BOS2_RAISE6 {SPR_BOS2,8,8,{NULL},S_BOS2_RUN1}, // S_BOS2_RAISE7 - {SPR_SKUL,0|FF_FULLBRIGHT,10,{A_Look},S_SKULL_STND2}, // S_SKULL_STND - {SPR_SKUL,1|FF_FULLBRIGHT,10,{A_Look},S_SKULL_STND}, // S_SKULL_STND2 - {SPR_SKUL,0|FF_FULLBRIGHT,6,{A_Chase},S_SKULL_RUN2}, // S_SKULL_RUN1 - {SPR_SKUL,1|FF_FULLBRIGHT,6,{A_Chase},S_SKULL_RUN1}, // S_SKULL_RUN2 - {SPR_SKUL,2|FF_FULLBRIGHT,10,{A_FaceTarget},S_SKULL_ATK2}, // S_SKULL_ATK1 - {SPR_SKUL,3|FF_FULLBRIGHT,4,{A_SkullAttack},S_SKULL_ATK3}, // S_SKULL_ATK2 + {SPR_SKUL,0|FF_FULLBRIGHT,10,{.p1 = A_Look},S_SKULL_STND2}, // S_SKULL_STND + {SPR_SKUL,1|FF_FULLBRIGHT,10,{.p1 = A_Look},S_SKULL_STND}, // S_SKULL_STND2 + {SPR_SKUL,0|FF_FULLBRIGHT,6,{.p1 = A_Chase},S_SKULL_RUN2}, // S_SKULL_RUN1 + {SPR_SKUL,1|FF_FULLBRIGHT,6,{.p1 = A_Chase},S_SKULL_RUN1}, // S_SKULL_RUN2 + {SPR_SKUL,2|FF_FULLBRIGHT,10,{.p1 = A_FaceTarget},S_SKULL_ATK2}, // S_SKULL_ATK1 + {SPR_SKUL,3|FF_FULLBRIGHT,4,{.p1 = A_SkullAttack},S_SKULL_ATK3}, // S_SKULL_ATK2 {SPR_SKUL,2|FF_FULLBRIGHT,4,{NULL},S_SKULL_ATK4}, // S_SKULL_ATK3 {SPR_SKUL,3|FF_FULLBRIGHT,4,{NULL},S_SKULL_ATK3}, // S_SKULL_ATK4 {SPR_SKUL,4|FF_FULLBRIGHT,3,{NULL},S_SKULL_PAIN2}, // S_SKULL_PAIN - {SPR_SKUL,4|FF_FULLBRIGHT,3,{A_Pain},S_SKULL_RUN1}, // S_SKULL_PAIN2 + {SPR_SKUL,4|FF_FULLBRIGHT,3,{.p1 = A_Pain},S_SKULL_RUN1}, // S_SKULL_PAIN2 {SPR_SKUL,5|FF_FULLBRIGHT,6,{NULL},S_SKULL_DIE2}, // S_SKULL_DIE1 - {SPR_SKUL,6|FF_FULLBRIGHT,6,{A_Scream},S_SKULL_DIE3}, // S_SKULL_DIE2 + {SPR_SKUL,6|FF_FULLBRIGHT,6,{.p1 = A_Scream},S_SKULL_DIE3}, // S_SKULL_DIE2 {SPR_SKUL,7|FF_FULLBRIGHT,6,{NULL},S_SKULL_DIE4}, // S_SKULL_DIE3 - {SPR_SKUL,8|FF_FULLBRIGHT,6,{A_Fall},S_SKULL_DIE5}, // S_SKULL_DIE4 + {SPR_SKUL,8|FF_FULLBRIGHT,6,{.p1 = A_Fall},S_SKULL_DIE5}, // S_SKULL_DIE4 {SPR_SKUL,9,6,{NULL},S_SKULL_DIE6}, // S_SKULL_DIE5 {SPR_SKUL,10,6,{NULL},S_NULL}, // S_SKULL_DIE6 - {SPR_SPID,0,10,{A_Look},S_SPID_STND2}, // S_SPID_STND - {SPR_SPID,1,10,{A_Look},S_SPID_STND}, // S_SPID_STND2 - {SPR_SPID,0,3,{A_Metal},S_SPID_RUN2}, // S_SPID_RUN1 - {SPR_SPID,0,3,{A_Chase},S_SPID_RUN3}, // S_SPID_RUN2 - {SPR_SPID,1,3,{A_Chase},S_SPID_RUN4}, // S_SPID_RUN3 - {SPR_SPID,1,3,{A_Chase},S_SPID_RUN5}, // S_SPID_RUN4 - {SPR_SPID,2,3,{A_Metal},S_SPID_RUN6}, // S_SPID_RUN5 - {SPR_SPID,2,3,{A_Chase},S_SPID_RUN7}, // S_SPID_RUN6 - {SPR_SPID,3,3,{A_Chase},S_SPID_RUN8}, // S_SPID_RUN7 - {SPR_SPID,3,3,{A_Chase},S_SPID_RUN9}, // S_SPID_RUN8 - {SPR_SPID,4,3,{A_Metal},S_SPID_RUN10}, // S_SPID_RUN9 - {SPR_SPID,4,3,{A_Chase},S_SPID_RUN11}, // S_SPID_RUN10 - {SPR_SPID,5,3,{A_Chase},S_SPID_RUN12}, // S_SPID_RUN11 - {SPR_SPID,5,3,{A_Chase},S_SPID_RUN1}, // S_SPID_RUN12 - {SPR_SPID,0|FF_FULLBRIGHT,20,{A_FaceTarget},S_SPID_ATK2}, // S_SPID_ATK1 - {SPR_SPID,6|FF_FULLBRIGHT,4,{A_SPosAttack},S_SPID_ATK3}, // S_SPID_ATK2 - {SPR_SPID,7|FF_FULLBRIGHT,4,{A_SPosAttack},S_SPID_ATK4}, // S_SPID_ATK3 - {SPR_SPID,7|FF_FULLBRIGHT,1,{A_SpidRefire},S_SPID_ATK2}, // S_SPID_ATK4 + {SPR_SPID,0,10,{.p1 = A_Look},S_SPID_STND2}, // S_SPID_STND + {SPR_SPID,1,10,{.p1 = A_Look},S_SPID_STND}, // S_SPID_STND2 + {SPR_SPID,0,3,{.p1 = A_Metal},S_SPID_RUN2}, // S_SPID_RUN1 + {SPR_SPID,0,3,{.p1 = A_Chase},S_SPID_RUN3}, // S_SPID_RUN2 + {SPR_SPID,1,3,{.p1 = A_Chase},S_SPID_RUN4}, // S_SPID_RUN3 + {SPR_SPID,1,3,{.p1 = A_Chase},S_SPID_RUN5}, // S_SPID_RUN4 + {SPR_SPID,2,3,{.p1 = A_Metal},S_SPID_RUN6}, // S_SPID_RUN5 + {SPR_SPID,2,3,{.p1 = A_Chase},S_SPID_RUN7}, // S_SPID_RUN6 + {SPR_SPID,3,3,{.p1 = A_Chase},S_SPID_RUN8}, // S_SPID_RUN7 + {SPR_SPID,3,3,{.p1 = A_Chase},S_SPID_RUN9}, // S_SPID_RUN8 + {SPR_SPID,4,3,{.p1 = A_Metal},S_SPID_RUN10}, // S_SPID_RUN9 + {SPR_SPID,4,3,{.p1 = A_Chase},S_SPID_RUN11}, // S_SPID_RUN10 + {SPR_SPID,5,3,{.p1 = A_Chase},S_SPID_RUN12}, // S_SPID_RUN11 + {SPR_SPID,5,3,{.p1 = A_Chase},S_SPID_RUN1}, // S_SPID_RUN12 + {SPR_SPID,0|FF_FULLBRIGHT,20,{.p1 = A_FaceTarget},S_SPID_ATK2}, // S_SPID_ATK1 + {SPR_SPID,6|FF_FULLBRIGHT,4,{.p1 = A_SPosAttack},S_SPID_ATK3}, // S_SPID_ATK2 + {SPR_SPID,7|FF_FULLBRIGHT,4,{.p1 = A_SPosAttack},S_SPID_ATK4}, // S_SPID_ATK3 + {SPR_SPID,7|FF_FULLBRIGHT,1,{.p1 = A_SpidRefire},S_SPID_ATK2}, // S_SPID_ATK4 {SPR_SPID,8,3,{NULL},S_SPID_PAIN2}, // S_SPID_PAIN - {SPR_SPID,8,3,{A_Pain},S_SPID_RUN1}, // S_SPID_PAIN2 - {SPR_SPID,9,20,{A_Scream},S_SPID_DIE2}, // S_SPID_DIE1 - {SPR_SPID,10,10,{A_Fall},S_SPID_DIE3}, // S_SPID_DIE2 + {SPR_SPID,8,3,{.p1 = A_Pain},S_SPID_RUN1}, // S_SPID_PAIN2 + {SPR_SPID,9,20,{.p1 = A_Scream},S_SPID_DIE2}, // S_SPID_DIE1 + {SPR_SPID,10,10,{.p1 = A_Fall},S_SPID_DIE3}, // S_SPID_DIE2 {SPR_SPID,11,10,{NULL},S_SPID_DIE4}, // S_SPID_DIE3 {SPR_SPID,12,10,{NULL},S_SPID_DIE5}, // S_SPID_DIE4 {SPR_SPID,13,10,{NULL},S_SPID_DIE6}, // S_SPID_DIE5 @@ -750,35 +750,35 @@ state_t original_states[NUMSTATES] = { {SPR_SPID,16,10,{NULL},S_SPID_DIE9}, // S_SPID_DIE8 {SPR_SPID,17,10,{NULL},S_SPID_DIE10}, // S_SPID_DIE9 {SPR_SPID,18,30,{NULL},S_SPID_DIE11}, // S_SPID_DIE10 - {SPR_SPID,18,-1,{A_BossDeath},S_NULL}, // S_SPID_DIE11 - {SPR_BSPI,0,10,{A_Look},S_BSPI_STND2}, // S_BSPI_STND - {SPR_BSPI,1,10,{A_Look},S_BSPI_STND}, // S_BSPI_STND2 + {SPR_SPID,18,-1,{.p1 = A_BossDeath},S_NULL}, // S_SPID_DIE11 + {SPR_BSPI,0,10,{.p1 = A_Look},S_BSPI_STND2}, // S_BSPI_STND + {SPR_BSPI,1,10,{.p1 = A_Look},S_BSPI_STND}, // S_BSPI_STND2 {SPR_BSPI,0,20,{NULL},S_BSPI_RUN1}, // S_BSPI_SIGHT - {SPR_BSPI,0,3,{A_BabyMetal},S_BSPI_RUN2}, // S_BSPI_RUN1 - {SPR_BSPI,0,3,{A_Chase},S_BSPI_RUN3}, // S_BSPI_RUN2 - {SPR_BSPI,1,3,{A_Chase},S_BSPI_RUN4}, // S_BSPI_RUN3 - {SPR_BSPI,1,3,{A_Chase},S_BSPI_RUN5}, // S_BSPI_RUN4 - {SPR_BSPI,2,3,{A_Chase},S_BSPI_RUN6}, // S_BSPI_RUN5 - {SPR_BSPI,2,3,{A_Chase},S_BSPI_RUN7}, // S_BSPI_RUN6 - {SPR_BSPI,3,3,{A_BabyMetal},S_BSPI_RUN8}, // S_BSPI_RUN7 - {SPR_BSPI,3,3,{A_Chase},S_BSPI_RUN9}, // S_BSPI_RUN8 - {SPR_BSPI,4,3,{A_Chase},S_BSPI_RUN10}, // S_BSPI_RUN9 - {SPR_BSPI,4,3,{A_Chase},S_BSPI_RUN11}, // S_BSPI_RUN10 - {SPR_BSPI,5,3,{A_Chase},S_BSPI_RUN12}, // S_BSPI_RUN11 - {SPR_BSPI,5,3,{A_Chase},S_BSPI_RUN1}, // S_BSPI_RUN12 - {SPR_BSPI,0|FF_FULLBRIGHT,20,{A_FaceTarget},S_BSPI_ATK2}, // S_BSPI_ATK1 - {SPR_BSPI,6|FF_FULLBRIGHT,4,{A_BspiAttack},S_BSPI_ATK3}, // S_BSPI_ATK2 + {SPR_BSPI,0,3,{.p1 = A_BabyMetal},S_BSPI_RUN2}, // S_BSPI_RUN1 + {SPR_BSPI,0,3,{.p1 = A_Chase},S_BSPI_RUN3}, // S_BSPI_RUN2 + {SPR_BSPI,1,3,{.p1 = A_Chase},S_BSPI_RUN4}, // S_BSPI_RUN3 + {SPR_BSPI,1,3,{.p1 = A_Chase},S_BSPI_RUN5}, // S_BSPI_RUN4 + {SPR_BSPI,2,3,{.p1 = A_Chase},S_BSPI_RUN6}, // S_BSPI_RUN5 + {SPR_BSPI,2,3,{.p1 = A_Chase},S_BSPI_RUN7}, // S_BSPI_RUN6 + {SPR_BSPI,3,3,{.p1 = A_BabyMetal},S_BSPI_RUN8}, // S_BSPI_RUN7 + {SPR_BSPI,3,3,{.p1 = A_Chase},S_BSPI_RUN9}, // S_BSPI_RUN8 + {SPR_BSPI,4,3,{.p1 = A_Chase},S_BSPI_RUN10}, // S_BSPI_RUN9 + {SPR_BSPI,4,3,{.p1 = A_Chase},S_BSPI_RUN11}, // S_BSPI_RUN10 + {SPR_BSPI,5,3,{.p1 = A_Chase},S_BSPI_RUN12}, // S_BSPI_RUN11 + {SPR_BSPI,5,3,{.p1 = A_Chase},S_BSPI_RUN1}, // S_BSPI_RUN12 + {SPR_BSPI,0|FF_FULLBRIGHT,20,{.p1 = A_FaceTarget},S_BSPI_ATK2}, // S_BSPI_ATK1 + {SPR_BSPI,6|FF_FULLBRIGHT,4,{.p1 = A_BspiAttack},S_BSPI_ATK3}, // S_BSPI_ATK2 {SPR_BSPI,7|FF_FULLBRIGHT,4,{NULL},S_BSPI_ATK4}, // S_BSPI_ATK3 - {SPR_BSPI,7|FF_FULLBRIGHT,1,{A_SpidRefire},S_BSPI_ATK2}, // S_BSPI_ATK4 + {SPR_BSPI,7|FF_FULLBRIGHT,1,{.p1 = A_SpidRefire},S_BSPI_ATK2}, // S_BSPI_ATK4 {SPR_BSPI,8,3,{NULL},S_BSPI_PAIN2}, // S_BSPI_PAIN - {SPR_BSPI,8,3,{A_Pain},S_BSPI_RUN1}, // S_BSPI_PAIN2 - {SPR_BSPI,9,20,{A_Scream},S_BSPI_DIE2}, // S_BSPI_DIE1 - {SPR_BSPI,10,7,{A_Fall},S_BSPI_DIE3}, // S_BSPI_DIE2 + {SPR_BSPI,8,3,{.p1 = A_Pain},S_BSPI_RUN1}, // S_BSPI_PAIN2 + {SPR_BSPI,9,20,{.p1 = A_Scream},S_BSPI_DIE2}, // S_BSPI_DIE1 + {SPR_BSPI,10,7,{.p1 = A_Fall},S_BSPI_DIE3}, // S_BSPI_DIE2 {SPR_BSPI,11,7,{NULL},S_BSPI_DIE4}, // S_BSPI_DIE3 {SPR_BSPI,12,7,{NULL},S_BSPI_DIE5}, // S_BSPI_DIE4 {SPR_BSPI,13,7,{NULL},S_BSPI_DIE6}, // S_BSPI_DIE5 {SPR_BSPI,14,7,{NULL},S_BSPI_DIE7}, // S_BSPI_DIE6 - {SPR_BSPI,15,-1,{A_BossDeath},S_NULL}, // S_BSPI_DIE7 + {SPR_BSPI,15,-1,{.p1 = A_BossDeath},S_NULL}, // S_BSPI_DIE7 {SPR_BSPI,15,5,{NULL},S_BSPI_RAISE2}, // S_BSPI_RAISE1 {SPR_BSPI,14,5,{NULL},S_BSPI_RAISE3}, // S_BSPI_RAISE2 {SPR_BSPI,13,5,{NULL},S_BSPI_RAISE4}, // S_BSPI_RAISE3 @@ -793,51 +793,51 @@ state_t original_states[NUMSTATES] = { {SPR_APBX,2|FF_FULLBRIGHT,5,{NULL},S_ARACH_PLEX4}, // S_ARACH_PLEX3 {SPR_APBX,3|FF_FULLBRIGHT,5,{NULL},S_ARACH_PLEX5}, // S_ARACH_PLEX4 {SPR_APBX,4|FF_FULLBRIGHT,5,{NULL},S_NULL}, // S_ARACH_PLEX5 - {SPR_CYBR,0,10,{A_Look},S_CYBER_STND2}, // S_CYBER_STND - {SPR_CYBR,1,10,{A_Look},S_CYBER_STND}, // S_CYBER_STND2 - {SPR_CYBR,0,3,{A_Hoof},S_CYBER_RUN2}, // S_CYBER_RUN1 - {SPR_CYBR,0,3,{A_Chase},S_CYBER_RUN3}, // S_CYBER_RUN2 - {SPR_CYBR,1,3,{A_Chase},S_CYBER_RUN4}, // S_CYBER_RUN3 - {SPR_CYBR,1,3,{A_Chase},S_CYBER_RUN5}, // S_CYBER_RUN4 - {SPR_CYBR,2,3,{A_Chase},S_CYBER_RUN6}, // S_CYBER_RUN5 - {SPR_CYBR,2,3,{A_Chase},S_CYBER_RUN7}, // S_CYBER_RUN6 - {SPR_CYBR,3,3,{A_Metal},S_CYBER_RUN8}, // S_CYBER_RUN7 - {SPR_CYBR,3,3,{A_Chase},S_CYBER_RUN1}, // S_CYBER_RUN8 - {SPR_CYBR,4,6,{A_FaceTarget},S_CYBER_ATK2}, // S_CYBER_ATK1 - {SPR_CYBR,5,12,{A_CyberAttack},S_CYBER_ATK3}, // S_CYBER_ATK2 - {SPR_CYBR,4,12,{A_FaceTarget},S_CYBER_ATK4}, // S_CYBER_ATK3 - {SPR_CYBR,5,12,{A_CyberAttack},S_CYBER_ATK5}, // S_CYBER_ATK4 - {SPR_CYBR,4,12,{A_FaceTarget},S_CYBER_ATK6}, // S_CYBER_ATK5 - {SPR_CYBR,5,12,{A_CyberAttack},S_CYBER_RUN1}, // S_CYBER_ATK6 - {SPR_CYBR,6,10,{A_Pain},S_CYBER_RUN1}, // S_CYBER_PAIN + {SPR_CYBR,0,10,{.p1 = A_Look},S_CYBER_STND2}, // S_CYBER_STND + {SPR_CYBR,1,10,{.p1 = A_Look},S_CYBER_STND}, // S_CYBER_STND2 + {SPR_CYBR,0,3,{.p1 = A_Hoof},S_CYBER_RUN2}, // S_CYBER_RUN1 + {SPR_CYBR,0,3,{.p1 = A_Chase},S_CYBER_RUN3}, // S_CYBER_RUN2 + {SPR_CYBR,1,3,{.p1 = A_Chase},S_CYBER_RUN4}, // S_CYBER_RUN3 + {SPR_CYBR,1,3,{.p1 = A_Chase},S_CYBER_RUN5}, // S_CYBER_RUN4 + {SPR_CYBR,2,3,{.p1 = A_Chase},S_CYBER_RUN6}, // S_CYBER_RUN5 + {SPR_CYBR,2,3,{.p1 = A_Chase},S_CYBER_RUN7}, // S_CYBER_RUN6 + {SPR_CYBR,3,3,{.p1 = A_Metal},S_CYBER_RUN8}, // S_CYBER_RUN7 + {SPR_CYBR,3,3,{.p1 = A_Chase},S_CYBER_RUN1}, // S_CYBER_RUN8 + {SPR_CYBR,4,6,{.p1 = A_FaceTarget},S_CYBER_ATK2}, // S_CYBER_ATK1 + {SPR_CYBR,5,12,{.p1 = A_CyberAttack},S_CYBER_ATK3}, // S_CYBER_ATK2 + {SPR_CYBR,4,12,{.p1 = A_FaceTarget},S_CYBER_ATK4}, // S_CYBER_ATK3 + {SPR_CYBR,5,12,{.p1 = A_CyberAttack},S_CYBER_ATK5}, // S_CYBER_ATK4 + {SPR_CYBR,4,12,{.p1 = A_FaceTarget},S_CYBER_ATK6}, // S_CYBER_ATK5 + {SPR_CYBR,5,12,{.p1 = A_CyberAttack},S_CYBER_RUN1}, // S_CYBER_ATK6 + {SPR_CYBR,6,10,{.p1 = A_Pain},S_CYBER_RUN1}, // S_CYBER_PAIN {SPR_CYBR,7,10,{NULL},S_CYBER_DIE2}, // S_CYBER_DIE1 - {SPR_CYBR,8,10,{A_Scream},S_CYBER_DIE3}, // S_CYBER_DIE2 + {SPR_CYBR,8,10,{.p1 = A_Scream},S_CYBER_DIE3}, // S_CYBER_DIE2 {SPR_CYBR,9,10,{NULL},S_CYBER_DIE4}, // S_CYBER_DIE3 {SPR_CYBR,10,10,{NULL},S_CYBER_DIE5}, // S_CYBER_DIE4 {SPR_CYBR,11,10,{NULL},S_CYBER_DIE6}, // S_CYBER_DIE5 - {SPR_CYBR,12,10,{A_Fall},S_CYBER_DIE7}, // S_CYBER_DIE6 + {SPR_CYBR,12,10,{.p1 = A_Fall},S_CYBER_DIE7}, // S_CYBER_DIE6 {SPR_CYBR,13,10,{NULL},S_CYBER_DIE8}, // S_CYBER_DIE7 {SPR_CYBR,14,10,{NULL},S_CYBER_DIE9}, // S_CYBER_DIE8 {SPR_CYBR,15,30,{NULL},S_CYBER_DIE10}, // S_CYBER_DIE9 - {SPR_CYBR,15,-1,{A_BossDeath},S_NULL}, // S_CYBER_DIE10 - {SPR_PAIN,0,10,{A_Look},S_PAIN_STND}, // S_PAIN_STND - {SPR_PAIN,0,3,{A_Chase},S_PAIN_RUN2}, // S_PAIN_RUN1 - {SPR_PAIN,0,3,{A_Chase},S_PAIN_RUN3}, // S_PAIN_RUN2 - {SPR_PAIN,1,3,{A_Chase},S_PAIN_RUN4}, // S_PAIN_RUN3 - {SPR_PAIN,1,3,{A_Chase},S_PAIN_RUN5}, // S_PAIN_RUN4 - {SPR_PAIN,2,3,{A_Chase},S_PAIN_RUN6}, // S_PAIN_RUN5 - {SPR_PAIN,2,3,{A_Chase},S_PAIN_RUN1}, // S_PAIN_RUN6 - {SPR_PAIN,3,5,{A_FaceTarget},S_PAIN_ATK2}, // S_PAIN_ATK1 - {SPR_PAIN,4,5,{A_FaceTarget},S_PAIN_ATK3}, // S_PAIN_ATK2 - {SPR_PAIN,5|FF_FULLBRIGHT,5,{A_FaceTarget},S_PAIN_ATK4}, // S_PAIN_ATK3 - {SPR_PAIN,5|FF_FULLBRIGHT,0,{A_PainAttack},S_PAIN_RUN1}, // S_PAIN_ATK4 + {SPR_CYBR,15,-1,{.p1 = A_BossDeath},S_NULL}, // S_CYBER_DIE10 + {SPR_PAIN,0,10,{.p1 = A_Look},S_PAIN_STND}, // S_PAIN_STND + {SPR_PAIN,0,3,{.p1 = A_Chase},S_PAIN_RUN2}, // S_PAIN_RUN1 + {SPR_PAIN,0,3,{.p1 = A_Chase},S_PAIN_RUN3}, // S_PAIN_RUN2 + {SPR_PAIN,1,3,{.p1 = A_Chase},S_PAIN_RUN4}, // S_PAIN_RUN3 + {SPR_PAIN,1,3,{.p1 = A_Chase},S_PAIN_RUN5}, // S_PAIN_RUN4 + {SPR_PAIN,2,3,{.p1 = A_Chase},S_PAIN_RUN6}, // S_PAIN_RUN5 + {SPR_PAIN,2,3,{.p1 = A_Chase},S_PAIN_RUN1}, // S_PAIN_RUN6 + {SPR_PAIN,3,5,{.p1 = A_FaceTarget},S_PAIN_ATK2}, // S_PAIN_ATK1 + {SPR_PAIN,4,5,{.p1 = A_FaceTarget},S_PAIN_ATK3}, // S_PAIN_ATK2 + {SPR_PAIN,5|FF_FULLBRIGHT,5,{.p1 = A_FaceTarget},S_PAIN_ATK4}, // S_PAIN_ATK3 + {SPR_PAIN,5|FF_FULLBRIGHT,0,{.p1 = A_PainAttack},S_PAIN_RUN1}, // S_PAIN_ATK4 {SPR_PAIN,6,6,{NULL},S_PAIN_PAIN2}, // S_PAIN_PAIN - {SPR_PAIN,6,6,{A_Pain},S_PAIN_RUN1}, // S_PAIN_PAIN2 + {SPR_PAIN,6,6,{.p1 = A_Pain},S_PAIN_RUN1}, // S_PAIN_PAIN2 {SPR_PAIN,7|FF_FULLBRIGHT,8,{NULL},S_PAIN_DIE2}, // S_PAIN_DIE1 - {SPR_PAIN,8|FF_FULLBRIGHT,8,{A_Scream},S_PAIN_DIE3}, // S_PAIN_DIE2 + {SPR_PAIN,8|FF_FULLBRIGHT,8,{.p1 = A_Scream},S_PAIN_DIE3}, // S_PAIN_DIE2 {SPR_PAIN,9|FF_FULLBRIGHT,8,{NULL},S_PAIN_DIE4}, // S_PAIN_DIE3 {SPR_PAIN,10|FF_FULLBRIGHT,8,{NULL},S_PAIN_DIE5}, // S_PAIN_DIE4 - {SPR_PAIN,11|FF_FULLBRIGHT,8,{A_PainDie},S_PAIN_DIE6}, // S_PAIN_DIE5 + {SPR_PAIN,11|FF_FULLBRIGHT,8,{.p1 = A_PainDie},S_PAIN_DIE6}, // S_PAIN_DIE5 {SPR_PAIN,12|FF_FULLBRIGHT,8,{NULL},S_NULL}, // S_PAIN_DIE6 {SPR_PAIN,12,8,{NULL},S_PAIN_RAISE2}, // S_PAIN_RAISE1 {SPR_PAIN,11,8,{NULL},S_PAIN_RAISE3}, // S_PAIN_RAISE2 @@ -845,32 +845,32 @@ state_t original_states[NUMSTATES] = { {SPR_PAIN,9,8,{NULL},S_PAIN_RAISE5}, // S_PAIN_RAISE4 {SPR_PAIN,8,8,{NULL},S_PAIN_RAISE6}, // S_PAIN_RAISE5 {SPR_PAIN,7,8,{NULL},S_PAIN_RUN1}, // S_PAIN_RAISE6 - {SPR_SSWV,0,10,{A_Look},S_SSWV_STND2}, // S_SSWV_STND - {SPR_SSWV,1,10,{A_Look},S_SSWV_STND}, // S_SSWV_STND2 - {SPR_SSWV,0,3,{A_Chase},S_SSWV_RUN2}, // S_SSWV_RUN1 - {SPR_SSWV,0,3,{A_Chase},S_SSWV_RUN3}, // S_SSWV_RUN2 - {SPR_SSWV,1,3,{A_Chase},S_SSWV_RUN4}, // S_SSWV_RUN3 - {SPR_SSWV,1,3,{A_Chase},S_SSWV_RUN5}, // S_SSWV_RUN4 - {SPR_SSWV,2,3,{A_Chase},S_SSWV_RUN6}, // S_SSWV_RUN5 - {SPR_SSWV,2,3,{A_Chase},S_SSWV_RUN7}, // S_SSWV_RUN6 - {SPR_SSWV,3,3,{A_Chase},S_SSWV_RUN8}, // S_SSWV_RUN7 - {SPR_SSWV,3,3,{A_Chase},S_SSWV_RUN1}, // S_SSWV_RUN8 - {SPR_SSWV,4,10,{A_FaceTarget},S_SSWV_ATK2}, // S_SSWV_ATK1 - {SPR_SSWV,5,10,{A_FaceTarget},S_SSWV_ATK3}, // S_SSWV_ATK2 - {SPR_SSWV,6|FF_FULLBRIGHT,4,{A_CPosAttack},S_SSWV_ATK4}, // S_SSWV_ATK3 - {SPR_SSWV,5,6,{A_FaceTarget},S_SSWV_ATK5}, // S_SSWV_ATK4 - {SPR_SSWV,6|FF_FULLBRIGHT,4,{A_CPosAttack},S_SSWV_ATK6}, // S_SSWV_ATK5 - {SPR_SSWV,5,1,{A_CPosRefire},S_SSWV_ATK2}, // S_SSWV_ATK6 + {SPR_SSWV,0,10,{.p1 = A_Look},S_SSWV_STND2}, // S_SSWV_STND + {SPR_SSWV,1,10,{.p1 = A_Look},S_SSWV_STND}, // S_SSWV_STND2 + {SPR_SSWV,0,3,{.p1 = A_Chase},S_SSWV_RUN2}, // S_SSWV_RUN1 + {SPR_SSWV,0,3,{.p1 = A_Chase},S_SSWV_RUN3}, // S_SSWV_RUN2 + {SPR_SSWV,1,3,{.p1 = A_Chase},S_SSWV_RUN4}, // S_SSWV_RUN3 + {SPR_SSWV,1,3,{.p1 = A_Chase},S_SSWV_RUN5}, // S_SSWV_RUN4 + {SPR_SSWV,2,3,{.p1 = A_Chase},S_SSWV_RUN6}, // S_SSWV_RUN5 + {SPR_SSWV,2,3,{.p1 = A_Chase},S_SSWV_RUN7}, // S_SSWV_RUN6 + {SPR_SSWV,3,3,{.p1 = A_Chase},S_SSWV_RUN8}, // S_SSWV_RUN7 + {SPR_SSWV,3,3,{.p1 = A_Chase},S_SSWV_RUN1}, // S_SSWV_RUN8 + {SPR_SSWV,4,10,{.p1 = A_FaceTarget},S_SSWV_ATK2}, // S_SSWV_ATK1 + {SPR_SSWV,5,10,{.p1 = A_FaceTarget},S_SSWV_ATK3}, // S_SSWV_ATK2 + {SPR_SSWV,6|FF_FULLBRIGHT,4,{.p1 = A_CPosAttack},S_SSWV_ATK4}, // S_SSWV_ATK3 + {SPR_SSWV,5,6,{.p1 = A_FaceTarget},S_SSWV_ATK5}, // S_SSWV_ATK4 + {SPR_SSWV,6|FF_FULLBRIGHT,4,{.p1 = A_CPosAttack},S_SSWV_ATK6}, // S_SSWV_ATK5 + {SPR_SSWV,5,1,{.p1 = A_CPosRefire},S_SSWV_ATK2}, // S_SSWV_ATK6 {SPR_SSWV,7,3,{NULL},S_SSWV_PAIN2}, // S_SSWV_PAIN - {SPR_SSWV,7,3,{A_Pain},S_SSWV_RUN1}, // S_SSWV_PAIN2 + {SPR_SSWV,7,3,{.p1 = A_Pain},S_SSWV_RUN1}, // S_SSWV_PAIN2 {SPR_SSWV,8,5,{NULL},S_SSWV_DIE2}, // S_SSWV_DIE1 - {SPR_SSWV,9,5,{A_Scream},S_SSWV_DIE3}, // S_SSWV_DIE2 - {SPR_SSWV,10,5,{A_Fall},S_SSWV_DIE4}, // S_SSWV_DIE3 + {SPR_SSWV,9,5,{.p1 = A_Scream},S_SSWV_DIE3}, // S_SSWV_DIE2 + {SPR_SSWV,10,5,{.p1 = A_Fall},S_SSWV_DIE4}, // S_SSWV_DIE3 {SPR_SSWV,11,5,{NULL},S_SSWV_DIE5}, // S_SSWV_DIE4 {SPR_SSWV,12,-1,{NULL},S_NULL}, // S_SSWV_DIE5 {SPR_SSWV,13,5,{NULL},S_SSWV_XDIE2}, // S_SSWV_XDIE1 - {SPR_SSWV,14,5,{A_XScream},S_SSWV_XDIE3}, // S_SSWV_XDIE2 - {SPR_SSWV,15,5,{A_Fall},S_SSWV_XDIE4}, // S_SSWV_XDIE3 + {SPR_SSWV,14,5,{.p1 = A_XScream},S_SSWV_XDIE3}, // S_SSWV_XDIE2 + {SPR_SSWV,15,5,{.p1 = A_Fall},S_SSWV_XDIE4}, // S_SSWV_XDIE3 {SPR_SSWV,16,5,{NULL},S_SSWV_XDIE5}, // S_SSWV_XDIE4 {SPR_SSWV,17,5,{NULL},S_SSWV_XDIE6}, // S_SSWV_XDIE5 {SPR_SSWV,18,5,{NULL},S_SSWV_XDIE7}, // S_SSWV_XDIE6 @@ -885,7 +885,7 @@ state_t original_states[NUMSTATES] = { {SPR_KEEN,0,-1,{NULL},S_KEENSTND}, // S_KEENSTND {SPR_KEEN,0,6,{NULL},S_COMMKEEN2}, // S_COMMKEEN {SPR_KEEN,1,6,{NULL},S_COMMKEEN3}, // S_COMMKEEN2 - {SPR_KEEN,2,6,{A_Scream},S_COMMKEEN4}, // S_COMMKEEN3 + {SPR_KEEN,2,6,{.p1 = A_Scream},S_COMMKEEN4}, // S_COMMKEEN3 {SPR_KEEN,3,6,{NULL},S_COMMKEEN5}, // S_COMMKEEN4 {SPR_KEEN,4,6,{NULL},S_COMMKEEN6}, // S_COMMKEEN5 {SPR_KEEN,5,6,{NULL},S_COMMKEEN7}, // S_COMMKEEN6 @@ -893,34 +893,34 @@ state_t original_states[NUMSTATES] = { {SPR_KEEN,7,6,{NULL},S_COMMKEEN9}, // S_COMMKEEN8 {SPR_KEEN,8,6,{NULL},S_COMMKEEN10}, // S_COMMKEEN9 {SPR_KEEN,9,6,{NULL},S_COMMKEEN11}, // S_COMMKEEN10 - {SPR_KEEN,10,6,{A_KeenDie},S_COMMKEEN12},// S_COMMKEEN11 + {SPR_KEEN,10,6,{.p1 = A_KeenDie},S_COMMKEEN12},// S_COMMKEEN11 {SPR_KEEN,11,-1,{NULL},S_NULL}, // S_COMMKEEN12 {SPR_KEEN,12,4,{NULL},S_KEENPAIN2}, // S_KEENPAIN - {SPR_KEEN,12,8,{A_Pain},S_KEENSTND}, // S_KEENPAIN2 + {SPR_KEEN,12,8,{.p1 = A_Pain},S_KEENSTND}, // S_KEENPAIN2 {SPR_BBRN,0,-1,{NULL},S_NULL}, // S_BRAIN - {SPR_BBRN,1,36,{A_BrainPain},S_BRAIN}, // S_BRAIN_PAIN - {SPR_BBRN,0,100,{A_BrainScream},S_BRAIN_DIE2}, // S_BRAIN_DIE1 + {SPR_BBRN,1,36,{.p1 = A_BrainPain},S_BRAIN}, // S_BRAIN_PAIN + {SPR_BBRN,0,100,{.p1 = A_BrainScream},S_BRAIN_DIE2}, // S_BRAIN_DIE1 {SPR_BBRN,0,10,{NULL},S_BRAIN_DIE3}, // S_BRAIN_DIE2 {SPR_BBRN,0,10,{NULL},S_BRAIN_DIE4}, // S_BRAIN_DIE3 - {SPR_BBRN,0,-1,{A_BrainDie},S_NULL}, // S_BRAIN_DIE4 - {SPR_SSWV,0,10,{A_Look},S_BRAINEYE}, // S_BRAINEYE - {SPR_SSWV,0,181,{A_BrainAwake},S_BRAINEYE1}, // S_BRAINEYESEE - {SPR_SSWV,0,150,{A_BrainSpit},S_BRAINEYE1}, // S_BRAINEYE1 - {SPR_BOSF,0|FF_FULLBRIGHT,3,{A_SpawnSound},S_SPAWN2}, // S_SPAWN1 - {SPR_BOSF,1|FF_FULLBRIGHT,3,{A_SpawnFly},S_SPAWN3}, // S_SPAWN2 - {SPR_BOSF,2|FF_FULLBRIGHT,3,{A_SpawnFly},S_SPAWN4}, // S_SPAWN3 - {SPR_BOSF,3|FF_FULLBRIGHT,3,{A_SpawnFly},S_SPAWN1}, // S_SPAWN4 - {SPR_FIRE,0|FF_FULLBRIGHT,4,{A_Fire},S_SPAWNFIRE2}, // S_SPAWNFIRE1 - {SPR_FIRE,1|FF_FULLBRIGHT,4,{A_Fire},S_SPAWNFIRE3}, // S_SPAWNFIRE2 - {SPR_FIRE,2|FF_FULLBRIGHT,4,{A_Fire},S_SPAWNFIRE4}, // S_SPAWNFIRE3 - {SPR_FIRE,3|FF_FULLBRIGHT,4,{A_Fire},S_SPAWNFIRE5}, // S_SPAWNFIRE4 - {SPR_FIRE,4|FF_FULLBRIGHT,4,{A_Fire},S_SPAWNFIRE6}, // S_SPAWNFIRE5 - {SPR_FIRE,5|FF_FULLBRIGHT,4,{A_Fire},S_SPAWNFIRE7}, // S_SPAWNFIRE6 - {SPR_FIRE,6|FF_FULLBRIGHT,4,{A_Fire},S_SPAWNFIRE8}, // S_SPAWNFIRE7 - {SPR_FIRE,7|FF_FULLBRIGHT,4,{A_Fire},S_NULL}, // S_SPAWNFIRE8 + {SPR_BBRN,0,-1,{.p1 = A_BrainDie},S_NULL}, // S_BRAIN_DIE4 + {SPR_SSWV,0,10,{.p1 = A_Look},S_BRAINEYE}, // S_BRAINEYE + {SPR_SSWV,0,181,{.p1 = A_BrainAwake},S_BRAINEYE1}, // S_BRAINEYESEE + {SPR_SSWV,0,150,{.p1 = A_BrainSpit},S_BRAINEYE1}, // S_BRAINEYE1 + {SPR_BOSF,0|FF_FULLBRIGHT,3,{.p1 = A_SpawnSound},S_SPAWN2}, // S_SPAWN1 + {SPR_BOSF,1|FF_FULLBRIGHT,3,{.p1 = A_SpawnFly},S_SPAWN3}, // S_SPAWN2 + {SPR_BOSF,2|FF_FULLBRIGHT,3,{.p1 = A_SpawnFly},S_SPAWN4}, // S_SPAWN3 + {SPR_BOSF,3|FF_FULLBRIGHT,3,{.p1 = A_SpawnFly},S_SPAWN1}, // S_SPAWN4 + {SPR_FIRE,0|FF_FULLBRIGHT,4,{.p1 = A_Fire},S_SPAWNFIRE2}, // S_SPAWNFIRE1 + {SPR_FIRE,1|FF_FULLBRIGHT,4,{.p1 = A_Fire},S_SPAWNFIRE3}, // S_SPAWNFIRE2 + {SPR_FIRE,2|FF_FULLBRIGHT,4,{.p1 = A_Fire},S_SPAWNFIRE4}, // S_SPAWNFIRE3 + {SPR_FIRE,3|FF_FULLBRIGHT,4,{.p1 = A_Fire},S_SPAWNFIRE5}, // S_SPAWNFIRE4 + {SPR_FIRE,4|FF_FULLBRIGHT,4,{.p1 = A_Fire},S_SPAWNFIRE6}, // S_SPAWNFIRE5 + {SPR_FIRE,5|FF_FULLBRIGHT,4,{.p1 = A_Fire},S_SPAWNFIRE7}, // S_SPAWNFIRE6 + {SPR_FIRE,6|FF_FULLBRIGHT,4,{.p1 = A_Fire},S_SPAWNFIRE8}, // S_SPAWNFIRE7 + {SPR_FIRE,7|FF_FULLBRIGHT,4,{.p1 = A_Fire},S_NULL}, // S_SPAWNFIRE8 {SPR_MISL,1|FF_FULLBRIGHT,10,{NULL},S_BRAINEXPLODE2}, // S_BRAINEXPLODE1 {SPR_MISL,2|FF_FULLBRIGHT,10,{NULL},S_BRAINEXPLODE3}, // S_BRAINEXPLODE2 - {SPR_MISL,3|FF_FULLBRIGHT,10,{A_BrainExplode},S_NULL}, // S_BRAINEXPLODE3 + {SPR_MISL,3|FF_FULLBRIGHT,10,{.p1 = A_BrainExplode},S_NULL}, // S_BRAINEXPLODE3 {SPR_ARM1,0,6,{NULL},S_ARM1A}, // S_ARM1 {SPR_ARM1,1|FF_FULLBRIGHT,7,{NULL},S_ARM1}, // S_ARM1A {SPR_ARM2,0,6,{NULL},S_ARM2A}, // S_ARM2 @@ -928,9 +928,9 @@ state_t original_states[NUMSTATES] = { {SPR_BAR1,0,6,{NULL},S_BAR2}, // S_BAR1 {SPR_BAR1,1,6,{NULL},S_BAR1}, // S_BAR2 {SPR_BEXP,0|FF_FULLBRIGHT,5,{NULL},S_BEXP2}, // S_BEXP - {SPR_BEXP,1|FF_FULLBRIGHT,5,{A_Scream},S_BEXP3}, // S_BEXP2 + {SPR_BEXP,1|FF_FULLBRIGHT,5,{.p1 = A_Scream},S_BEXP3}, // S_BEXP2 {SPR_BEXP,2|FF_FULLBRIGHT,5,{NULL},S_BEXP4}, // S_BEXP3 - {SPR_BEXP,3|FF_FULLBRIGHT,10,{A_Explode},S_BEXP5}, // S_BEXP4 + {SPR_BEXP,3|FF_FULLBRIGHT,10,{.p1 = A_Explode},S_BEXP5}, // S_BEXP4 {SPR_BEXP,4|FF_FULLBRIGHT,10,{NULL},S_NULL}, // S_BEXP5 {SPR_FCAN,0|FF_FULLBRIGHT,4,{NULL},S_BBAR2}, // S_BBAR1 {SPR_FCAN,1|FF_FULLBRIGHT,4,{NULL},S_BBAR3}, // S_BBAR2 @@ -1090,33 +1090,33 @@ state_t original_states[NUMSTATES] = { {SPR_TNT1,0,-1,{NULL},S_TNT1}, // S_TNT1 // phares 3/8/98 // killough 8/9/98: grenade - {SPR_MISL,0|FF_FULLBRIGHT,1000,{A_Die},S_GRENADE}, // S_GRENADE + {SPR_MISL,0|FF_FULLBRIGHT,1000,{.p1 = A_Die},S_GRENADE}, // S_GRENADE // killough 8/10/98: variable damage explosion - {SPR_MISL,1|FF_FULLBRIGHT,4,{A_Scream},S_DETONATE2}, // S_DETONATE - {SPR_MISL,2|FF_FULLBRIGHT,6,{A_Detonate},S_DETONATE3}, // S_DETONATE2 + {SPR_MISL,1|FF_FULLBRIGHT,4,{.p1 = A_Scream},S_DETONATE2}, // S_DETONATE + {SPR_MISL,2|FF_FULLBRIGHT,6,{.p1 = A_Detonate},S_DETONATE3}, // S_DETONATE2 {SPR_MISL,3|FF_FULLBRIGHT,10,{NULL},S_NULL}, // S_DETONATE3 // killough 7/19/98: Marine's best friend :) - {SPR_DOGS,0,10,{A_Look},S_DOGS_STND2}, // S_DOGS_STND - {SPR_DOGS,1,10,{A_Look},S_DOGS_STND}, // S_DOGS_STND2 - {SPR_DOGS,0,2,{A_Chase},S_DOGS_RUN2}, // S_DOGS_RUN1 - {SPR_DOGS,0,2,{A_Chase},S_DOGS_RUN3}, // S_DOGS_RUN2 - {SPR_DOGS,1,2,{A_Chase},S_DOGS_RUN4}, // S_DOGS_RUN3 - {SPR_DOGS,1,2,{A_Chase},S_DOGS_RUN5}, // S_DOGS_RUN4 - {SPR_DOGS,2,2,{A_Chase},S_DOGS_RUN6}, // S_DOGS_RUN5 - {SPR_DOGS,2,2,{A_Chase},S_DOGS_RUN7}, // S_DOGS_RUN6 - {SPR_DOGS,3,2,{A_Chase},S_DOGS_RUN8}, // S_DOGS_RUN7 - {SPR_DOGS,3,2,{A_Chase},S_DOGS_RUN1}, // S_DOGS_RUN8 - {SPR_DOGS,4,8,{A_FaceTarget},S_DOGS_ATK2}, // S_DOGS_ATK1 - {SPR_DOGS,5,8,{A_FaceTarget},S_DOGS_ATK3}, // S_DOGS_ATK2 - {SPR_DOGS,6,8,{A_SargAttack},S_DOGS_RUN1}, // S_DOGS_ATK3 + {SPR_DOGS,0,10,{.p1 = A_Look},S_DOGS_STND2}, // S_DOGS_STND + {SPR_DOGS,1,10,{.p1 = A_Look},S_DOGS_STND}, // S_DOGS_STND2 + {SPR_DOGS,0,2,{.p1 = A_Chase},S_DOGS_RUN2}, // S_DOGS_RUN1 + {SPR_DOGS,0,2,{.p1 = A_Chase},S_DOGS_RUN3}, // S_DOGS_RUN2 + {SPR_DOGS,1,2,{.p1 = A_Chase},S_DOGS_RUN4}, // S_DOGS_RUN3 + {SPR_DOGS,1,2,{.p1 = A_Chase},S_DOGS_RUN5}, // S_DOGS_RUN4 + {SPR_DOGS,2,2,{.p1 = A_Chase},S_DOGS_RUN6}, // S_DOGS_RUN5 + {SPR_DOGS,2,2,{.p1 = A_Chase},S_DOGS_RUN7}, // S_DOGS_RUN6 + {SPR_DOGS,3,2,{.p1 = A_Chase},S_DOGS_RUN8}, // S_DOGS_RUN7 + {SPR_DOGS,3,2,{.p1 = A_Chase},S_DOGS_RUN1}, // S_DOGS_RUN8 + {SPR_DOGS,4,8,{.p1 = A_FaceTarget},S_DOGS_ATK2}, // S_DOGS_ATK1 + {SPR_DOGS,5,8,{.p1 = A_FaceTarget},S_DOGS_ATK3}, // S_DOGS_ATK2 + {SPR_DOGS,6,8,{.p1 = A_SargAttack},S_DOGS_RUN1}, // S_DOGS_ATK3 {SPR_DOGS,7,2,{NULL},S_DOGS_PAIN2}, // S_DOGS_PAIN - {SPR_DOGS,7,2,{A_Pain},S_DOGS_RUN1}, // S_DOGS_PAIN2 + {SPR_DOGS,7,2,{.p1 = A_Pain},S_DOGS_RUN1}, // S_DOGS_PAIN2 {SPR_DOGS,8,8,{NULL},S_DOGS_DIE2}, // S_DOGS_DIE1 - {SPR_DOGS,9,8,{A_Scream},S_DOGS_DIE3}, // S_DOGS_DIE2 + {SPR_DOGS,9,8,{.p1 = A_Scream},S_DOGS_DIE3}, // S_DOGS_DIE2 {SPR_DOGS,10,4,{NULL},S_DOGS_DIE4}, // S_DOGS_DIE3 - {SPR_DOGS,11,4,{A_Fall},S_DOGS_DIE5}, // S_DOGS_DIE4 + {SPR_DOGS,11,4,{.p1 = A_Fall},S_DOGS_DIE5}, // S_DOGS_DIE4 {SPR_DOGS,12,4,{NULL},S_DOGS_DIE6}, // S_DOGS_DIE5 {SPR_DOGS,13,-1,{NULL},S_NULL}, // S_DOGS_DIE6 {SPR_DOGS,13,5,{NULL},S_DOGS_RAISE2}, // S_DOGS_RAISE1 @@ -1130,11 +1130,11 @@ state_t original_states[NUMSTATES] = { // S_OLDBFG1 #define BFGDELAY 1 -#define OLDBFG_1FRAMES(x) {SPR_BFGG,1,BFGDELAY,{A_FireOldBFG},x+S_OLDBFG1+2}, +#define OLDBFG_1FRAMES(x) {SPR_BFGG,1,BFGDELAY,{.p2 = A_FireOldBFG},x+S_OLDBFG1+2}, #define OLDBFG_2FRAMES(x) OLDBFG_1FRAMES(x) OLDBFG_1FRAMES(x+1) #define OLDBFG_4FRAMES(x) OLDBFG_2FRAMES(x) OLDBFG_2FRAMES(x+2) #define OLDBFG_8FRAMES(x) OLDBFG_4FRAMES(x) OLDBFG_4FRAMES(x+4) - {SPR_BFGG,0,10,{A_BFGsound},S_OLDBFG1+1}, // S_OLDBFG1 + {SPR_BFGG,0,10,{.p2 = A_BFGsound},S_OLDBFG1+1}, // S_OLDBFG1 OLDBFG_8FRAMES(0) OLDBFG_8FRAMES(8) @@ -1142,8 +1142,8 @@ state_t original_states[NUMSTATES] = { OLDBFG_8FRAMES(24) OLDBFG_8FRAMES(32) - {SPR_BFGG,1,0,{A_Light0},S_OLDBFG43}, // S_OLDBFG42 - {SPR_BFGG,1,20,{A_ReFire},S_BFG}, // S_OLDBFG43 + {SPR_BFGG,1,0,{.p2 = A_Light0},S_OLDBFG43}, // S_OLDBFG42 + {SPR_BFGG,1,20,{.p2 = A_ReFire},S_BFG}, // S_OLDBFG43 // killough 7/11/98: end of beta BFG @@ -1171,22 +1171,22 @@ state_t original_states[NUMSTATES] = { // This is an approximation, but I'm sure it can be improved. // spawnstate - {SPR_SKUL,0,10,{A_Look},S_BSKUL_STND}, // S_BSKUL_STND + {SPR_SKUL,0,10,{.p1 = A_Look},S_BSKUL_STND}, // S_BSKUL_STND // chasestate - {SPR_SKUL,1,5,{A_Chase},S_BSKUL_RUN2}, // S_BSKUL_RUN1 - {SPR_SKUL,2,5,{A_Chase},S_BSKUL_RUN3}, // S_BSKUL_RUN2 - {SPR_SKUL,3,5,{A_Chase},S_BSKUL_RUN4}, // S_BSKUL_RUN3 - {SPR_SKUL,0,5,{A_Chase},S_BSKUL_RUN1}, // S_BSKUL_RUN4 + {SPR_SKUL,1,5,{.p1 = A_Chase},S_BSKUL_RUN2}, // S_BSKUL_RUN1 + {SPR_SKUL,2,5,{.p1 = A_Chase},S_BSKUL_RUN3}, // S_BSKUL_RUN2 + {SPR_SKUL,3,5,{.p1 = A_Chase},S_BSKUL_RUN4}, // S_BSKUL_RUN3 + {SPR_SKUL,0,5,{.p1 = A_Chase},S_BSKUL_RUN1}, // S_BSKUL_RUN4 // missilestate - {SPR_SKUL,4,4,{A_FaceTarget},S_BSKUL_ATK2}, // S_BSKUL_ATK1 - {SPR_SKUL,5,5,{A_BetaSkullAttack},S_BSKUL_ATK3}, // S_BSKUL_ATK2 + {SPR_SKUL,4,4,{.p1 = A_FaceTarget},S_BSKUL_ATK2}, // S_BSKUL_ATK1 + {SPR_SKUL,5,5,{.p1 = A_BetaSkullAttack},S_BSKUL_ATK3}, // S_BSKUL_ATK2 {SPR_SKUL,5,4,{NULL},S_BSKUL_RUN1}, // S_BSKUL_ATK3 // painstate {SPR_SKUL,6,4,{NULL},S_BSKUL_PAIN2}, // S_BSKUL_PAIN1 - {SPR_SKUL,7,2,{A_Pain},S_BSKUL_RUN1}, // S_BSKUL_PAIN2 + {SPR_SKUL,7,2,{.p1 = A_Pain},S_BSKUL_RUN1}, // S_BSKUL_PAIN2 {SPR_SKUL,8,4,{NULL},S_BSKUL_RUN1}, // S_BSKUL_PAIN3 // deathstate @@ -1194,13 +1194,13 @@ state_t original_states[NUMSTATES] = { {SPR_SKUL,10,5,{NULL},S_BSKUL_DIE3}, // S_BSKUL_DIE2 {SPR_SKUL,11,5,{NULL},S_BSKUL_DIE4}, // S_BSKUL_DIE3 {SPR_SKUL,12,5,{NULL},S_BSKUL_DIE5}, // S_BSKUL_DIE4 - {SPR_SKUL,13,5,{A_Scream},S_BSKUL_DIE6}, // S_BSKUL_DIE5 + {SPR_SKUL,13,5,{.p1 = A_Scream},S_BSKUL_DIE6}, // S_BSKUL_DIE5 {SPR_SKUL,14,5,{NULL},S_BSKUL_DIE7}, // S_BSKUL_DIE6 - {SPR_SKUL,15,5,{A_Fall},S_BSKUL_DIE8}, // S_BSKUL_DIE7 - {SPR_SKUL,16,5,{A_Stop},S_BSKUL_DIE8}, // S_BSKUL_DIE8 + {SPR_SKUL,15,5,{.p1 = A_Fall},S_BSKUL_DIE8}, // S_BSKUL_DIE7 + {SPR_SKUL,16,5,{.p1 = A_Stop},S_BSKUL_DIE8}, // S_BSKUL_DIE8 // killough 10/98: mushroom effect - {SPR_MISL,1|FF_FULLBRIGHT,8,{A_Mushroom},S_EXPLODE2}, // S_MUSHROOM + {SPR_MISL,1|FF_FULLBRIGHT,8,{.p1 = A_Mushroom},S_EXPLODE2}, // S_MUSHROOM }; // ******************************************************************** diff --git a/src/m_array.h b/src/m_array.h index 2955c663b..641f70213 100644 --- a/src/m_array.h +++ b/src/m_array.h @@ -72,20 +72,20 @@ inline static void array_clear(const void *v) } } -#define array_grow(v, n) ((v) = M_ArrayGrow((v), sizeof(*(v)), n)) +#define array_grow(v, n) ((v) = M_ArrayGrow(v, sizeof(*(v)), n)) #define array_push(v, e) \ do \ { \ if (!(v)) \ { \ - (v) = M_ArrayGrow((v), sizeof(*(v)), M_ARRAY_INIT_CAPACITY); \ + (v) = M_ArrayGrow(v, sizeof(*(v)), M_ARRAY_INIT_CAPACITY); \ } \ - else if (array_ptr((v))->size == array_ptr((v))->capacity) \ + else if (array_ptr(v)->size == array_ptr(v)->capacity) \ { \ - (v) = M_ArrayGrow((v), sizeof(*(v)), array_ptr((v))->capacity); \ + (v) = M_ArrayGrow(v, sizeof(*(v)), array_ptr(v)->capacity); \ } \ - (v)[array_ptr((v))->size++] = (e); \ + (v)[array_ptr(v)->size++] = (e); \ } while (0) #define array_free(v) \ @@ -93,13 +93,15 @@ inline static void array_clear(const void *v) { \ if (v) \ { \ - M_ARRAY_FREE(array_ptr((v))); \ + M_ARRAY_FREE(array_ptr(v)); \ (v) = NULL; \ } \ } while (0) +#define array_end(v) ((v) + array_size(v)) + #define array_foreach(ptr, v) \ - for (ptr = (v); ptr != &(v)[array_size((v))]; ++ptr) + for (ptr = (v); ptr < array_end(v); ++ptr) inline static void *M_ArrayGrow(void *v, size_t esize, int n) { diff --git a/src/m_cheat.c b/src/m_cheat.c index fb4579f5e..f61b835c7 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -30,8 +30,10 @@ #include "doomdef.h" #include "doomstat.h" #include "g_game.h" +#include "g_umapinfo.h" #include "info.h" #include "m_cheat.h" +#include "m_array.h" #include "m_fixed.h" #include "m_input.h" #include "m_misc.h" @@ -50,7 +52,6 @@ #include "sounds.h" #include "st_widgets.h" #include "tables.h" -#include "u_mapinfo.h" #include "w_wad.h" #include "ws_stuff.h" @@ -87,100 +88,100 @@ static void cheat_magic2(void) //----------------------------------------------------------------------------- static void cheat_mus(char *buf); -static void cheat_choppers(); -static void cheat_god(); -static void cheat_fa(); -static void cheat_k(); -static void cheat_kfa(); -static void cheat_noclip(); +static void cheat_choppers(void); +static void cheat_god(void); +static void cheat_fa(void); +static void cheat_k(void); +static void cheat_kfa(void); +static void cheat_noclip(void); static void cheat_pw(int pw); -static void cheat_behold(); +static void cheat_behold(void); static void cheat_clev(char *buf); -static void cheat_clev0(); -static void cheat_mypos(); +static void cheat_clev0(void); +static void cheat_mypos(void); static void cheat_comp(char *buf); -static void cheat_comp0(); +static void cheat_comp0(void); static void cheat_skill(char *buf); -static void cheat_skill0(); -static void cheat_friction(); -static void cheat_pushers(); -static void cheat_tran(); -static void cheat_massacre(); -static void cheat_ddt(); -static void cheat_hom(); -static void cheat_fast(); -static void cheat_key(); -static void cheat_keyx(); +static void cheat_skill0(void); +static void cheat_friction(void); +static void cheat_pushers(void); +static void cheat_tran(void); +static void cheat_massacre(void); +static void cheat_ddt(void); +static void cheat_hom(void); +static void cheat_fast(void); +static void cheat_key(void); +static void cheat_keyx(void); static void cheat_keyxx(int key); -static void cheat_weap(); +static void cheat_weap(void); static void cheat_weapx(char *buf); -static void cheat_ammo(); +static void cheat_ammo(void); static void cheat_ammox(char *buf); -static void cheat_smart(); -static void cheat_pitch(); -static void cheat_nuke(); -static void cheat_rate(); -static void cheat_buddha(); -static void cheat_spechits(); -static void cheat_notarget(); -static void cheat_freeze(); -static void cheat_health(); -static void cheat_megaarmour(); -static void cheat_reveal_secret(); -static void cheat_reveal_kill(); -static void cheat_reveal_item(); - -static void cheat_autoaim(); // killough 7/19/98 -static void cheat_tst(); -static void cheat_showfps(); // [FG] FPS counter widget -static void cheat_speed(); +static void cheat_smart(void); +static void cheat_pitch(void); +static void cheat_nuke(void); +static void cheat_rate(void); +static void cheat_buddha(void); +static void cheat_spechits(void); +static void cheat_notarget(void); +static void cheat_freeze(void); +static void cheat_health(void); +static void cheat_megaarmour(void); +static void cheat_reveal_secret(void); +static void cheat_reveal_kill(void); +static void cheat_reveal_item(void); + +static void cheat_autoaim(void); // killough 7/19/98 +static void cheat_tst(void); +static void cheat_showfps(void); // [FG] FPS counter widget +static void cheat_speed(void); // [Nugget] /----------------------------------------------------------------- -static void cheat_nomomentum(); -static void cheat_fauxdemo(); // Emulates demo/net play state, for debugging -static void cheat_infammo(); // Infinite ammo cheat -static void cheat_fastweaps(); // Fast weapons cheat -static void cheat_bobbers(); // Shortcut to the two cheats above +static void cheat_nomomentum(void); +static void cheat_fauxdemo(void); // Emulates demo/net play state, for debugging +static void cheat_infammo(void); // Infinite ammo cheat +static void cheat_fastweaps(void); // Fast weapons cheat +static void cheat_bobbers(void); // Shortcut to the two cheats above boolean gibbers; // Used for 'GIBBERS' -static void cheat_gibbers(); // Everything gibs +static void cheat_gibbers(void); // Everything gibs static void cheat_riotmode(void); -static void cheat_resurrect(); -static void cheat_fly(); -static void cheat_normalexit(); // Emulate normal level exit -static void cheat_secretexit(); // Emulate secret level exit +static void cheat_resurrect(void); +static void cheat_fly(void); +static void cheat_normalexit(void); // Emulate normal level exit +static void cheat_secretexit(void); // Emulate secret level exit static void cheat_turbo(char *buf); // Summon a mobj -static void cheat_summon(); +static void cheat_summon(void); // Enemy -static void cheat_summone0(); +static void cheat_summone0(void); static void cheat_summone(char *buf); // Friend -static void cheat_summonf0(); +static void cheat_summonf0(void); static void cheat_summonf(char *buf); // Repeat last -static void cheat_summonr(); +static void cheat_summonr(void); static int spawneetype = -1; static boolean spawneefriend; -static void cheat_reveal_key(); -static void cheat_reveal_keyx(); +static void cheat_reveal_key(void); +static void cheat_reveal_keyx(void); static void cheat_reveal_keyxx(int key); -static void cheat_linetarget(); // Give info on the current linetarget -static void cheat_trails(); // Show hitscan trails -static void cheat_mdk(); // Inspired by ZDoom's console command -static void cheat_saitama(); // MDK Fist +static void cheat_linetarget(void); // Give info on the current linetarget +static void cheat_trails(void); // Show hitscan trails +static void cheat_mdk(void); // Inspired by ZDoom's console command +static void cheat_saitama(void); // MDK Fist -static void cheat_boomcan(); // Explosive hitscan +static void cheat_boomcan(void); // Explosive hitscan -static void cheat_cheese(); +static void cheat_cheese(void); boolean idgaf; -static void cheat_idgaf(); +static void cheat_idgaf(void); // [Nugget] -----------------------------------------------------------------/ @@ -207,246 +208,247 @@ static void cheat_idgaf(); struct cheat_s cheat[] = { {"idmus", "Change music", always, - {cheat_mus}, -2 }, + {.s = cheat_mus}, -2 }, {"idchoppers", "Chainsaw", not_net | not_demo, - {cheat_choppers} }, + {.v = cheat_choppers} }, {"iddqd", "God mode", not_net | not_demo, - {cheat_god} }, + {.v = cheat_god} }, {"buddha", "Buddha mode", not_net | not_demo, - {cheat_buddha} }, + {.v = cheat_buddha} }, {"idk", NULL, not_net | not_demo | not_deh, - {cheat_k} }, // The most controversial cheat code in Doom history!!! + {.v = cheat_k} }, // The most controversial cheat code in Doom history!!! {"idkfa", "Ammo & Keys", not_net | not_demo, - {cheat_kfa} }, + {.v = cheat_kfa} }, {"idfa", "Ammo", not_net | not_demo, - {cheat_fa} }, + {.v = cheat_fa} }, {"idspispopd", "No Clipping 1", not_net | not_demo, - {cheat_noclip} }, + {.v = cheat_noclip} }, {"idclip", "No Clipping 2", not_net | not_demo, - {cheat_noclip} }, + {.v = cheat_noclip} }, {"idbeholdo", NULL, not_net | not_demo | not_deh, - {cheat_pw}, NUMPOWERS }, // [FG] disable all powerups at once + {.i = cheat_pw}, NUMPOWERS }, // [FG] disable all powerups at once {"idbeholdh", "Health", not_net | not_demo, - {cheat_health} }, + {.v = cheat_health} }, {"idbeholdm", "Mega Armor", not_net | not_demo, - {cheat_megaarmour} }, + {.v = cheat_megaarmour} }, {"idbeholdv", "Invincibility", not_net | not_demo, - {cheat_pw}, pw_invulnerability }, + {.i = cheat_pw}, pw_invulnerability }, {"idbeholds", "Berserk", not_net | not_demo, - {cheat_pw}, pw_strength }, + {.i = cheat_pw}, pw_strength }, - {"idbeholdi", "Invisibility", not_net | not_demo, - {cheat_pw}, pw_invisibility }, + {"idbeholdi", "Invisibility", not_net | not_demo, + {.i = cheat_pw}, pw_invisibility }, {"idbeholdr", "Radiation Suit", not_net | not_demo, - {cheat_pw}, pw_ironfeet }, + {.i = cheat_pw}, pw_ironfeet }, {"idbeholda", "Auto-map", not_dm, - {cheat_pw}, pw_allmap }, + {.i = cheat_pw}, pw_allmap }, {"idbeholdl", "Lite-Amp Goggles", not_dm, - {cheat_pw}, pw_infrared }, + {.i = cheat_pw}, pw_infrared }, {"idbehold", "BEHOLD menu", not_net | not_demo, - {cheat_behold} }, + {.v = cheat_behold} }, {"idclev", "Level Warp", not_net | not_demo | not_menu, - {cheat_clev}, -2 }, + {.s = cheat_clev}, -2 }, {"idclev", "Level Warp", not_net | not_demo | not_menu, - {cheat_clev0} }, + {.v = cheat_clev0} }, {"idmypos", "Player Position", not_dm, // [FG] not_net | not_demo, - {cheat_mypos} }, + {.v = cheat_mypos} }, {"comp", NULL, not_net | not_demo | not_menu, - {cheat_comp}, -2 }, + {.s = cheat_comp}, -2 }, {"comp", NULL, not_net | not_demo | not_menu, - {cheat_comp0} }, + {.v = cheat_comp0} }, {"skill", NULL, not_net | not_demo | not_menu, - {cheat_skill}, -1 }, + {.s = cheat_skill}, -1 }, {"skill", NULL, not_net | not_demo | not_menu, - {cheat_skill0} }, + {.v = cheat_skill0} }, {"killem", NULL, not_net | not_demo, - {cheat_massacre} }, // jff 2/01/98 kill all monsters + {.v = cheat_massacre} }, // jff 2/01/98 kill all monsters {"tntem", NULL, not_net | not_demo, {cheat_massacre} }, // [Nugget] 'KILLEM' alternative {"spechits", NULL, not_net | not_demo, - {cheat_spechits} }, + {.v = cheat_spechits} }, {"notarget", "Notarget mode", not_net | not_demo, - {cheat_notarget} }, + {.v = cheat_notarget} }, {"freeze", "Freeze", not_net | not_demo, - {cheat_freeze} }, + {.v = cheat_freeze} }, {"iddt", "Map cheat", not_dm, - {cheat_ddt} }, // killough 2/07/98: moved from am_map.c + {.v = cheat_ddt} }, // killough 2/07/98: moved from am_map.c {"iddst", NULL, not_dm, - {cheat_reveal_secret} }, + {.v = cheat_reveal_secret} }, {"iddkt", NULL, not_dm, - {cheat_reveal_kill} }, + {.v = cheat_reveal_kill} }, {"iddit", NULL, not_dm, - {cheat_reveal_item} }, + {.v = cheat_reveal_item} }, {"hom", NULL, always, - {cheat_hom} }, // killough 2/07/98: HOM autodetector + {.v = cheat_hom} }, // killough 2/07/98: HOM autodetector - {"key", NULL, not_net | not_demo, - {cheat_key} }, // killough 2/16/98: generalized key cheats + {"key", NULL, not_net | not_demo, + {.v = cheat_key} }, // killough 2/16/98: generalized key cheats {"keyr", NULL, not_net | not_demo, - {cheat_keyx} }, + {.v = cheat_keyx} }, {"keyy", NULL, not_net | not_demo, - {cheat_keyx} }, + {.v = cheat_keyx} }, {"keyb", NULL, not_net | not_demo, - {cheat_keyx} }, + {.v = cheat_keyx} }, - {"keyrc", NULL, not_net | not_demo, - {cheat_keyxx}, it_redcard }, + {"keyrc", NULL, not_net | not_demo, + {.i = cheat_keyxx}, it_redcard }, {"keyyc", NULL, not_net | not_demo, - {cheat_keyxx}, it_yellowcard }, + {.i = cheat_keyxx}, it_yellowcard }, - {"keybc", NULL, not_net | not_demo, - {cheat_keyxx}, it_bluecard }, + {"keybc", NULL, not_net | not_demo, + {.i = cheat_keyxx}, it_bluecard }, {"keyrs", NULL, not_net | not_demo, - {cheat_keyxx}, it_redskull }, + {.i = cheat_keyxx}, it_redskull }, {"keyys", NULL, not_net | not_demo, - {cheat_keyxx}, it_yellowskull }, + {.i = cheat_keyxx}, it_yellowskull }, {"keybs", NULL, not_net | not_demo, - {cheat_keyxx}, it_blueskull }, // killough 2/16/98: end generalized keys + {.i = cheat_keyxx}, it_blueskull }, // killough 2/16/98: end generalized keys {"weap", NULL, not_net | not_demo, - {cheat_weap} }, // killough 2/16/98: generalized weapon cheats + {.v = cheat_weap} }, // killough 2/16/98: generalized weapon cheats {"weap", NULL, not_net | not_demo, - {cheat_weapx}, -1 }, + {.s = cheat_weapx}, -1 }, {"ammo", NULL, not_net | not_demo, - {cheat_ammo} }, + {.v = cheat_ammo} }, {"ammo", NULL, not_net | not_demo, - {cheat_ammox}, -1 }, // killough 2/16/98: end generalized weapons + {.s = cheat_ammox}, -1 }, // killough 2/16/98: end generalized weapons {"tran", NULL, always, - {cheat_tran} }, // invoke translucency // phares + {.v = cheat_tran} }, // invoke translucency // phares {"smart", NULL, not_net | not_demo, - {cheat_smart} }, // killough 2/21/98: smart monster toggle + {.v = cheat_smart} }, // killough 2/21/98: smart monster toggle {"pitch", NULL, always, - {cheat_pitch} }, // killough 2/21/98: pitched sound toggle + {.v = cheat_pitch} }, // killough 2/21/98: pitched sound toggle // killough 2/21/98: reduce RSI injury by adding simpler alias sequences: - {"mbfran", NULL, always, - {cheat_tran} }, // killough 2/21/98: same as mbftran + {"mbfran", NULL, always, + {.v = cheat_tran} }, // killough 2/21/98: same as mbftran {"fast", NULL, not_net | not_demo, - {cheat_fast} }, // killough 3/6/98: -fast toggle + {.v = cheat_fast} }, // killough 3/6/98: -fast toggle {"ice", NULL, not_net | not_demo, - {cheat_friction} }, // phares 3/10/98: toggle variable friction effects + {.v = cheat_friction} }, // phares 3/10/98: toggle variable friction effects - {"push", NULL, not_net | not_demo, - {cheat_pushers} }, // phares 3/10/98: toggle pushers + {"push", NULL, not_net | not_demo, + {.v = cheat_pushers} }, // phares 3/10/98: toggle pushers {"nuke", NULL, not_net | not_demo, - {cheat_nuke} }, // killough 12/98: disable nukage damage + {.v = cheat_nuke} }, // killough 12/98: disable nukage damage {"rate", NULL, always, - {cheat_rate} }, + {.v = cheat_rate} }, {"aim", NULL, not_net | not_demo | beta_only, - {cheat_autoaim} }, + {.v = cheat_autoaim} }, {"eek", NULL, not_dm | not_demo | beta_only, - {cheat_ddt} }, // killough 2/07/98: moved from am_map.c + {.v = cheat_ddt} }, // killough 2/07/98: moved from am_map.c {"amo", NULL, not_net | not_demo | beta_only, - {cheat_kfa} }, + {.v = cheat_kfa} }, {"tst", NULL, not_net | not_demo | beta_only, - {cheat_tst} }, + {.v = cheat_tst} }, {"nc", NULL, not_net | not_demo | beta_only, - {cheat_noclip} }, + {.v = cheat_noclip} }, - // [Nugget] Change to just "fps" - {"fps", NULL, always, - {cheat_showfps} }, +// [FG] FPS counter widget +// [Nugget] Change to just "fps" + {"fps", NULL, always, + {.v = cheat_showfps} }, {"speed", NULL, not_dm, - {cheat_speed} }, + {.v = cheat_speed} }, // [Nugget] /--------------------------------------------------------------- - {"nomomentum", NULL, not_net | not_demo, {cheat_nomomentum} }, - {"fauxdemo", NULL, not_net | not_demo, {cheat_fauxdemo} }, // Emulates demo/net play state, for debugging - {"fullclip", NULL, not_net | not_demo, {cheat_infammo} }, // Infinite ammo cheat - {"valiant", NULL, not_net | not_demo, {cheat_fastweaps} }, // Fast weapons cheat - {"bobbers", NULL, not_net | not_demo, {cheat_bobbers} }, // Shortcut for the two above cheats - {"gibbers", NULL, not_net | not_demo, {cheat_gibbers} }, // Everything gibs - {"riotmode", NULL, not_net | not_demo, {cheat_riotmode} }, - {"resurrect", NULL, not_net | not_demo, {cheat_resurrect} }, - {"idres", NULL, not_net | not_demo, {cheat_resurrect} }, // 'RESURRECT' alternative - {"idfly", NULL, not_net | not_demo, {cheat_fly} }, - {"nextmap", NULL, not_net | not_demo, {cheat_normalexit} }, - {"nextsecret", NULL, not_net | not_demo, {cheat_secretexit} }, - {"turbo", NULL, not_net | not_demo, {cheat_turbo}, -3 }, - - {"summon", NULL, not_net | not_demo, {cheat_summon} }, // Summon "Menu" - {"summone", NULL, not_net | not_demo, {cheat_summone0} }, // Summon Enemy "Menu" - {"summone", NULL, not_net | not_demo, {cheat_summone}, -3 }, // Summon a hostile mobj - {"summonf", NULL, not_net | not_demo, {cheat_summonf0} }, // Summon Friend "Menu" - {"summonf", NULL, not_net | not_demo, {cheat_summonf}, -3 }, // Summon a friendly mobj - {"summonr", NULL, not_net | not_demo, {cheat_summonr} }, // Repeat last summon - - {"iddf", NULL, not_net | not_demo, {cheat_reveal_key} }, - {"iddfb", NULL, not_net | not_demo, {cheat_reveal_keyx} }, - {"iddfy", NULL, not_net | not_demo, {cheat_reveal_keyx} }, - {"iddfr", NULL, not_net | not_demo, {cheat_reveal_keyx} }, - {"iddfbc", NULL, not_net | not_demo, {cheat_reveal_keyxx}, 0 }, - {"iddfyc", NULL, not_net | not_demo, {cheat_reveal_keyxx}, 2 }, - {"iddfrc", NULL, not_net | not_demo, {cheat_reveal_keyxx}, 1 }, - {"iddfbs", NULL, not_net | not_demo, {cheat_reveal_keyxx}, 5 }, - {"iddfys", NULL, not_net | not_demo, {cheat_reveal_keyxx}, 3 }, - {"iddfrs", NULL, not_net | not_demo, {cheat_reveal_keyxx}, 4 }, - - {"linetarget", NULL, not_net | not_demo, {cheat_linetarget} }, // Give info on the current linetarget - {"trails", NULL, not_net | not_demo, {cheat_trails} }, // Show hitscan trails - {"mdk", NULL, not_net | not_demo, {cheat_mdk} }, - {"saitama", NULL, not_net | not_demo, {cheat_saitama} }, // MDK Fist - {"boomcan", NULL, not_net | not_demo, {cheat_boomcan} }, // Explosive hitscan - {"cheese", NULL, not_net | not_demo, {cheat_cheese} }, - {"idgaf", NULL, not_net | not_demo, {cheat_idgaf} }, + {"nomomentum", NULL, not_net | not_demo, {.v = cheat_nomomentum} }, + {"fauxdemo", NULL, not_net | not_demo, {.v = cheat_fauxdemo} }, // Emulates demo/net play state, for debugging + {"fullclip", NULL, not_net | not_demo, {.v = cheat_infammo} }, // Infinite ammo cheat + {"valiant", NULL, not_net | not_demo, {.v = cheat_fastweaps} }, // Fast weapons cheat + {"bobbers", NULL, not_net | not_demo, {.v = cheat_bobbers} }, // Shortcut for the two above cheats + {"gibbers", NULL, not_net | not_demo, {.v = cheat_gibbers} }, // Everything gibs + {"riotmode", NULL, not_net | not_demo, {.v = cheat_riotmode} }, + {"resurrect", NULL, not_net | not_demo, {.v = cheat_resurrect} }, + {"idres", NULL, not_net | not_demo, {.v = cheat_resurrect} }, // 'RESURRECT' alternative + {"idfly", NULL, not_net | not_demo, {.v = cheat_fly} }, + {"nextmap", NULL, not_net | not_demo, {.v = cheat_normalexit} }, + {"nextsecret", NULL, not_net | not_demo, {.v = cheat_secretexit} }, + {"turbo", NULL, not_net | not_demo, {.s = cheat_turbo}, -3 }, + + {"summon", NULL, not_net | not_demo, {.v = cheat_summon} }, // Summon "Menu" + {"summone", NULL, not_net | not_demo, {.v = cheat_summone0} }, // Summon Enemy "Menu" + {"summone", NULL, not_net | not_demo, {.s = cheat_summone}, -3 }, // Summon a hostile mobj + {"summonf", NULL, not_net | not_demo, {.v = cheat_summonf0} }, // Summon Friend "Menu" + {"summonf", NULL, not_net | not_demo, {.s = cheat_summonf}, -3 }, // Summon a friendly mobj + {"summonr", NULL, not_net | not_demo, {.v = cheat_summonr} }, // Repeat last summon + + {"iddf", NULL, not_net | not_demo, {.v = cheat_reveal_key} }, + {"iddfb", NULL, not_net | not_demo, {.v = cheat_reveal_keyx} }, + {"iddfy", NULL, not_net | not_demo, {.v = cheat_reveal_keyx} }, + {"iddfr", NULL, not_net | not_demo, {.v = cheat_reveal_keyx} }, + {"iddfbc", NULL, not_net | not_demo, {.i = cheat_reveal_keyxx}, 0 }, + {"iddfyc", NULL, not_net | not_demo, {.i = cheat_reveal_keyxx}, 2 }, + {"iddfrc", NULL, not_net | not_demo, {.i = cheat_reveal_keyxx}, 1 }, + {"iddfbs", NULL, not_net | not_demo, {.i = cheat_reveal_keyxx}, 5 }, + {"iddfys", NULL, not_net | not_demo, {.i = cheat_reveal_keyxx}, 3 }, + {"iddfrs", NULL, not_net | not_demo, {.i = cheat_reveal_keyxx}, 4 }, + + {"linetarget", NULL, not_net | not_demo, {.v = cheat_linetarget} }, // Give info on the current linetarget + {"trails", NULL, not_net | not_demo, {.v = cheat_trails} }, // Show hitscan trails + {"mdk", NULL, not_net | not_demo, {.v = cheat_mdk} }, + {"saitama", NULL, not_net | not_demo, {.v = cheat_saitama} }, // MDK Fist + {"boomcan", NULL, not_net | not_demo, {.v = cheat_boomcan} }, // Explosive hitscan + {"cheese", NULL, not_net | not_demo, {.v = cheat_cheese} }, + {"idgaf", NULL, not_net | not_demo, {.v = cheat_idgaf} }, #ifdef NUGMAGIC @@ -464,14 +466,14 @@ struct cheat_s cheat[] = { // [Nugget] /================================================================= -static void cheat_nomomentum() +static void cheat_nomomentum(void) { plyr->cheats ^= CF_NOMOMENTUM; displaymsg("No Momentum Mode %s", (plyr->cheats & CF_NOMOMENTUM) ? "ON" : "OFF"); } // Emulates demo and/or net play state, for debugging -static void cheat_fauxdemo() +static void cheat_fauxdemo(void) { extern void D_UpdateCasualPlay(void); @@ -483,21 +485,21 @@ static void cheat_fauxdemo() } // Infinite ammo -static void cheat_infammo() +static void cheat_infammo(void) { plyr->cheats ^= CF_INFAMMO; displaymsg("Infinite Ammo %s", (plyr->cheats & CF_INFAMMO) ? "ON" : "OFF"); } // Fast weapons -static void cheat_fastweaps() +static void cheat_fastweaps(void) { plyr->cheats ^= CF_FASTWEAPS; displaymsg("Fast Weapons %s", (plyr->cheats & CF_FASTWEAPS) ? "ON" : "OFF"); } // Shortcut for the two above cheats -static void cheat_bobbers() +static void cheat_bobbers(void) { if (!(plyr->cheats & CF_INFAMMO) || !(plyr->cheats & CF_FASTWEAPS)) { @@ -514,7 +516,7 @@ static void cheat_bobbers() } // Everything gibs -static void cheat_gibbers() +static void cheat_gibbers(void) { gibbers = !gibbers; displaymsg("%s", gibbers ? "Ludicrous Gibs!" : "Ludicrous Gibs no more."); @@ -554,7 +556,7 @@ static void DoResurrect(void) } // Resurrection cheat adapted from Crispy's IDDQD -static void cheat_resurrect() +static void cheat_resurrect(void) { // [crispy] dead players are first respawned at the current position if (plyr->playerstate == PST_DEAD) @@ -569,7 +571,7 @@ static void cheat_resurrect() // --------------------------------------------------------------------------- -static void cheat_fly() +static void cheat_fly(void) { plyr->cheats ^= CF_FLY; @@ -579,12 +581,12 @@ static void cheat_fly() displaymsg("Fly Mode %s", (plyr->cheats & CF_FLY) ? "ON" : "OFF"); } -static void cheat_normalexit() +static void cheat_normalexit(void) { G_ExitLevel(); } -static void cheat_secretexit() +static void cheat_secretexit(void) { G_SecretExitLevel(); } @@ -614,7 +616,7 @@ static void cheat_turbo(char *buf) // Summoning ----------------------------------------------------------------- -static void cheat_summon() +static void cheat_summon(void) { if (spawneetype == -1) { displaymsg("Summon: Enemy or Friend?"); } @@ -705,7 +707,7 @@ static void SummonMobj(boolean friendly) spawneefriend ? "Friend" : "Enemy", spawneetype); } -static void cheat_summone0() +static void cheat_summone0(void) { displaymsg("Summon Enemy: Enter mobj index"); } @@ -716,7 +718,7 @@ static void cheat_summone(char *buf) if (GetMobjType(buf)) { SummonMobj(false); } } -static void cheat_summonf0() +static void cheat_summonf0(void) { displaymsg("Summon Friend: Enter mobj index"); } @@ -728,21 +730,21 @@ static void cheat_summonf(char *buf) } // Summon the last summoned mobj -static void cheat_summonr() +static void cheat_summonr(void) { SummonMobj(spawneefriend); } // Key finder ---------------------------------------------------------------- -static void cheat_reveal_key() +static void cheat_reveal_key(void) { if (automapactive != AM_FULL) { return; } displaymsg("Key Finder: Red, Yellow or Blue?"); } -static void cheat_reveal_keyx() +static void cheat_reveal_keyx(void) { if (automapactive != AM_FULL) { return; } @@ -796,14 +798,14 @@ static void cheat_reveal_keyxx(int key) // --------------------------------------------------------------------------- // Give info on the current `linetarget` -static void cheat_linetarget() +static void cheat_linetarget(void) { plyr->cheats ^= CF_LINETARGET; displaymsg("Linetarget Query %s", (plyr->cheats & CF_LINETARGET) ? "ON" : "OFF"); } // Show hitscan trails -static void cheat_trails() +static void cheat_trails(void) { const int value = P_CycleShowHitscanTrails(); @@ -816,7 +818,7 @@ static void cheat_trails() } // 1-million-damage hitscan attack -static void cheat_mdk() +static void cheat_mdk(void) { fixed_t slope; @@ -841,14 +843,14 @@ static void cheat_mdk() } // MDK Fist -static void cheat_saitama() +static void cheat_saitama(void) { plyr->cheats ^= CF_SAITAMA; displaymsg("MDK Fist %s", (plyr->cheats & CF_SAITAMA) ? "ON" : "OFF"); } // Explosive hitscan -static void cheat_boomcan() +static void cheat_boomcan(void) { plyr->cheats ^= CF_BOOMCAN; displaymsg("Explosive Hitscan %s", (plyr->cheats & CF_BOOMCAN) ? "ON" : "OFF"); @@ -859,13 +861,13 @@ static void cheat_riotmode(void) displaymsg("Riot Mode %s", (riotmode = !riotmode) ? "ON" : "OFF"); } -static void cheat_cheese() +static void cheat_cheese(void) { cheese = !cheese; displaymsg("%s", cheese ? "cheese :)" : "no cheese :("); } -static void cheat_idgaf() +static void cheat_idgaf(void) { idgaf = !idgaf; displaymsg("I %s.", idgaf ? "don't" : "do"); @@ -874,18 +876,18 @@ static void cheat_idgaf() // [Nugget] =================================================================/ // [FG] FPS counter widget -static void cheat_showfps() +static void cheat_showfps(void) { plyr->cheats ^= CF_SHOWFPS; } -static void cheat_speed() +static void cheat_speed(void) { speedometer = (speedometer + 1) % 4; } // killough 7/19/98: Autoaiming optional in beta emulation mode -static void cheat_autoaim() +static void cheat_autoaim(void) { displaymsg((autoaim=!autoaim) ? "Projectile autoaiming on" : @@ -956,7 +958,7 @@ static void cheat_mus(char *buf) boolean comp_choppers; // [Nugget] // 'choppers' invulnerability & chainsaw -static void cheat_choppers() +static void cheat_choppers(void) { plyr->weaponowned[wp_chainsaw] = true; @@ -969,7 +971,7 @@ static void cheat_choppers() displaymsg("%s", s_STSTR_CHOPPERS); // Ty 03/27/98 - externalized } -static void cheat_god() +static void cheat_god(void) { // 'dqd' cheat for toggleable god mode // [crispy] dead players are first respawned at the current position if (plyr->playerstate == PST_DEAD) @@ -990,7 +992,7 @@ static void cheat_god() displaymsg("%s", s_STSTR_DQDOFF); // Ty 03/27/98 - externalized } -static void cheat_buddha() +static void cheat_buddha(void) { plyr->cheats ^= CF_BUDDHA; if (plyr->cheats & CF_BUDDHA) @@ -999,7 +1001,7 @@ static void cheat_buddha() displaymsg("Buddha Mode OFF"); } -static void cheat_notarget() +static void cheat_notarget(void) { plyr->cheats ^= CF_NOTARGET; @@ -1030,7 +1032,7 @@ static void cheat_notarget() boolean frozen_mode; -static void cheat_freeze() +static void cheat_freeze(void) { frozen_mode = !frozen_mode; if (frozen_mode) @@ -1039,7 +1041,7 @@ static void cheat_freeze() displaymsg("Freeze OFF"); } -static void cheat_avj() +static void cheat_avj(void) { void A_VileJump(mobj_t *mo); @@ -1048,7 +1050,7 @@ static void cheat_avj() } // CPhipps - new health and armour cheat codes -static void cheat_health() +static void cheat_health(void) { if (!(plyr->cheats & CF_GODMODE)) { @@ -1059,20 +1061,20 @@ static void cheat_health() } } -static void cheat_megaarmour() +static void cheat_megaarmour(void) { plyr->armorpoints = idfa_armor; // Ty 03/09/98 - deh plyr->armortype = idfa_armor_class; // Ty 03/09/98 - deh displaymsg("%s", s_STSTR_BEHOLDX); // Ty 03/27/98 - externalized } -static void cheat_tst() +static void cheat_tst(void) { // killough 10/98: same as iddqd except for message cheat_god(); displaymsg(plyr->cheats & CF_GODMODE ? "God Mode On" : "God Mode Off"); } -static void cheat_fa() +static void cheat_fa(void) { int i; @@ -1099,7 +1101,7 @@ static void cheat_fa() displaymsg("%s", s_STSTR_FAADDED); } -static void cheat_k() +static void cheat_k(void) { int i; for (i=0;i<NUMCARDS;i++) @@ -1110,14 +1112,14 @@ static void cheat_k() } } -static void cheat_kfa() +static void cheat_kfa(void) { cheat_k(); cheat_fa(); displaymsg("%s", s_STSTR_KFAADDED); } -static void cheat_noclip() +static void cheat_noclip(void) { // Simplified, accepting both "noclip" and "idspispopd". // no clipping mode cheat @@ -1154,13 +1156,13 @@ static void cheat_pw(int pw) } // 'behold' power-up menu -static void cheat_behold() +static void cheat_behold(void) { displaymsg("%s", s_STSTR_BEHOLD); // Ty 03/27/98 - externalized } // 'clev' change-level cheat -static void cheat_clev0() +static void cheat_clev0(void) { int epsd, map; char *cur, *next; @@ -1240,14 +1242,14 @@ static void cheat_clev(char *buf) // 'mypos' for player position // killough 2/7/98: simplified using dprintf and made output more user-friendly -static void cheat_mypos() +static void cheat_mypos(void) { plyr->cheats ^= CF_MAPCOORDS; if ((plyr->cheats & CF_MAPCOORDS) == 0) plyr->message = ""; } -void cheat_mypos_print() +void cheat_mypos_print(void) { displaymsg("X=%.10f Y=%.10f A=%-.0f", (double)players[consoleplayer].mo->x / FRACUNIT, @@ -1257,7 +1259,7 @@ void cheat_mypos_print() // compatibility cheat -static void cheat_comp0() +static void cheat_comp0(void) { displaymsg("Complevel: %s", G_GetCurrentComplevelName()); } @@ -1282,14 +1284,14 @@ static void cheat_comp(char *buf) } // variable friction cheat -static void cheat_friction() +static void cheat_friction(void) { displaymsg( // Ty 03/27/98 - *not* externalized (variable_friction = !variable_friction) ? "Variable Friction enabled" : "Variable Friction disabled"); } -static void cheat_skill0() +static void cheat_skill0(void) { displaymsg("Skill: %s", default_skill_strings[gameskill + 1]); } @@ -1309,20 +1311,20 @@ static void cheat_skill(char *buf) // Pusher cheat // phares 3/10/98 -static void cheat_pushers() +static void cheat_pushers(void) { displaymsg( // Ty 03/27/98 - *not* externalized (allow_pushers = !allow_pushers) ? "Pushers enabled" : "Pushers disabled"); } // translucency cheat -static void cheat_tran() +static void cheat_tran(void) { displaymsg( // Ty 03/27/98 - *not* externalized (translucency = !translucency) ? "Translucency enabled" : "Translucency disabled"); } -static void cheat_massacre() // jff 2/01/98 kill all monsters +static void cheat_massacre(void) // jff 2/01/98 kill all monsters { // jff 02/01/98 'em' cheat - kill all monsters // partially taken from Chi's .46 port @@ -1374,7 +1376,7 @@ static void cheat_massacre() // jff 2/01/98 kill all monsters bloodier_gibbing = oldgibbing; // [Nugget] } -static void cheat_spechits() +static void cheat_spechits(void) { int i, speciallines = 0; boolean origcards[NUMCARDS]; @@ -1443,7 +1445,7 @@ static void cheat_spechits() plyr->cards[i] = origcards[i]; } - if (gamemapinfo && gamemapinfo->numbossactions > 0) + if (gamemapinfo && array_size(gamemapinfo->bossactions)) { thinker_t *th; @@ -1453,13 +1455,14 @@ static void cheat_spechits() { mobj_t *mo = (mobj_t *) th; - for (i = 0; i < gamemapinfo->numbossactions; i++) + bossaction_t *bossaction; + array_foreach(bossaction, gamemapinfo->bossactions) { - if (gamemapinfo->bossactions[i].type == mo->type) + if (bossaction->type == mo->type) { dummy = *lines; - dummy.special = (short)gamemapinfo->bossactions[i].special; - dummy.tag = (short)gamemapinfo->bossactions[i].tag; + dummy.special = (short)bossaction->special; + dummy.tag = (short)bossaction->tag; // use special semantics for line activation to block problem types. if (!P_UseSpecialLine(mo, &dummy, 0, true)) P_CrossSpecialLine(&dummy, 0, mo, true); @@ -1533,13 +1536,13 @@ static void cheat_spechits() // killough 2/7/98: move iddt cheat from am_map.c to here // killough 3/26/98: emulate Doom better -static void cheat_ddt() +static void cheat_ddt(void) { if (automapactive) ddt_cheating = (ddt_cheating+1) % 3; } -static void cheat_reveal_secret() +static void cheat_reveal_secret(void) { static int last_secret = -1; @@ -1615,7 +1618,7 @@ static void cheat_cycle_mobj(mobj_t **last_mobj, int *last_count, } while (th != start_th); } -static void cheat_reveal_kill() +static void cheat_reveal_kill(void) { if (automapactive == AM_FULL) { @@ -1626,7 +1629,7 @@ static void cheat_reveal_kill() } } -static void cheat_reveal_item() +static void cheat_reveal_item(void) { if (automapactive == AM_FULL) { @@ -1638,14 +1641,14 @@ static void cheat_reveal_item() } // killough 2/7/98: HOM autodetection -static void cheat_hom() +static void cheat_hom(void) { displaymsg((autodetect_hom = !autodetect_hom) ? "HOM Detection On" : "HOM Detection Off"); } // killough 3/6/98: -fast parameter toggle -static void cheat_fast() +static void cheat_fast(void) { // [Nugget] Custom Skill if (gameskill == sk_custom) @@ -1663,12 +1666,12 @@ static void cheat_fast() } // killough 2/16/98: keycard/skullkey cheat functions -static void cheat_key() +static void cheat_key(void) { displaymsg("Red, Yellow, Blue"); // Ty 03/27/98 - *not* externalized } -static void cheat_keyx() +static void cheat_keyx(void) { displaymsg("Card, Skull"); // Ty 03/27/98 - *not* externalized } @@ -1681,7 +1684,7 @@ static void cheat_keyxx(int key) // killough 2/16/98: generalized weapon cheats -static void cheat_weap() +static void cheat_weap(void) { // Ty 03/27/98 - *not* externalized displaymsg(ALLOW_SSG ? // killough 2/28/98 "Weapon number 1-9" : "Weapon number 1-8"); @@ -1712,7 +1715,7 @@ static void cheat_weapx(char *buf) } // killough 2/16/98: generalized ammo cheats -static void cheat_ammo() +static void cheat_ammo(void) { displaymsg("Ammo 1-4, Backpack"); // Ty 03/27/98 - *not* externalized } @@ -1744,25 +1747,25 @@ static void cheat_ammox(char *buf) } } -static void cheat_smart() +static void cheat_smart(void) { displaymsg((monsters_remember = !monsters_remember) ? "Smart Monsters Enabled" : "Smart Monsters Disabled"); } -static void cheat_pitch() +static void cheat_pitch(void) { displaymsg((pitched_sounds = !pitched_sounds) ? "Pitch Effects Enabled" : "Pitch Effects Disabled"); } -static void cheat_nuke() +static void cheat_nuke(void) { displaymsg((disable_nuke = !disable_nuke) ? "Nukage Disabled" : "Nukage Enabled"); } -static void cheat_rate() +static void cheat_rate(void) { plyr->cheats ^= CF_RENDERSTATS; } @@ -1863,32 +1866,34 @@ static const struct { const cheatf_t func; const int arg; } cheat_input[] = { - { input_iddqd, not_net|not_demo, {cheat_god}, 0 }, - { input_idkfa, not_net|not_demo, {cheat_kfa}, 0 }, - { input_idfa, not_net|not_demo, {cheat_fa}, 0 }, - { input_idclip, not_net|not_demo, {cheat_noclip}, 0 }, - { input_idbeholdh, not_net|not_demo, {cheat_health}, 0 }, - { input_idbeholdm, not_net|not_demo, {cheat_megaarmour}, 0 }, - { input_idbeholdv, not_net|not_demo, {cheat_pw}, pw_invulnerability }, - { input_idbeholds, not_net|not_demo, {cheat_pw}, pw_strength }, - { input_idbeholdi, not_net|not_demo, {cheat_pw}, pw_invisibility }, - { input_idbeholdr, not_net|not_demo, {cheat_pw}, pw_ironfeet }, - { input_idbeholdl, not_dm, {cheat_pw}, pw_infrared }, - { input_iddt, not_dm, {cheat_ddt}, 0 }, - { input_notarget, not_net|not_demo, {cheat_notarget}, 0 }, - { input_freeze, not_net|not_demo, {cheat_freeze}, 0 }, - { input_avj, not_net|not_demo, {cheat_avj}, 0 }, + { input_iddqd, not_net|not_demo, {.v = cheat_god}, 0 }, + { input_idkfa, not_net|not_demo, {.v = cheat_kfa}, 0 }, + { input_idfa, not_net|not_demo, {.v = cheat_fa}, 0 }, + { input_idclip, not_net|not_demo, {.v = cheat_noclip}, 0 }, + { input_idbeholdh, not_net|not_demo, {.v = cheat_health}, 0 }, + { input_idbeholdm, not_net|not_demo, {.v = cheat_megaarmour}, 0 }, + { input_idbeholdv, not_net|not_demo, {.i = cheat_pw}, pw_invulnerability }, + { input_idbeholds, not_net|not_demo, {.i = cheat_pw}, pw_strength }, + { input_idbeholdi, not_net|not_demo, {.i = cheat_pw}, pw_invisibility }, + { input_idbeholdr, not_net|not_demo, {.i = cheat_pw}, pw_ironfeet }, + { input_idbeholdl, not_dm, {.i = cheat_pw}, pw_infrared }, + { input_iddt, not_dm, {.v = cheat_ddt}, 0 }, + { input_notarget, not_net|not_demo, {.v = cheat_notarget}, 0 }, + { input_freeze, not_net|not_demo, {.v = cheat_freeze}, 0 }, + { input_avj, not_net|not_demo, {.v = cheat_avj}, 0 }, + // [Nugget] ---------------------------------------------------------------- - { input_idbeholda, not_net|not_demo, {cheat_pw}, pw_allmap }, - { input_infammo, not_net|not_demo, {cheat_infammo}, 0 }, - { input_fastweaps, not_net|not_demo, {cheat_fastweaps}, 0 }, - { input_resurrect, not_net|not_demo, {cheat_resurrect}, 0 }, - { input_fly, not_net|not_demo, {cheat_fly}, 0 }, - { input_summonr, not_net|not_demo, {cheat_summonr}, 0 }, - { input_linetarget, not_net|not_demo, {cheat_linetarget}, 0 }, - { input_mdk, not_net|not_demo, {cheat_mdk}, 0 }, - { input_saitama, not_net|not_demo, {cheat_saitama}, 0 }, - { input_boomcan, not_net|not_demo, {cheat_boomcan}, 0 }, + + { input_idbeholda, not_net|not_demo, {.i = cheat_pw}, pw_allmap }, + { input_infammo, not_net|not_demo, {.v = cheat_infammo}, 0 }, + { input_fastweaps, not_net|not_demo, {.v = cheat_fastweaps}, 0 }, + { input_resurrect, not_net|not_demo, {.v = cheat_resurrect}, 0 }, + { input_fly, not_net|not_demo, {.v = cheat_fly}, 0 }, + { input_summonr, not_net|not_demo, {.v = cheat_summonr}, 0 }, + { input_linetarget, not_net|not_demo, {.v = cheat_linetarget}, 0 }, + { input_mdk, not_net|not_demo, {.v = cheat_mdk}, 0 }, + { input_saitama, not_net|not_demo, {.v = cheat_saitama}, 0 }, + { input_boomcan, not_net|not_demo, {.v = cheat_boomcan}, 0 }, }; boolean M_CheatResponder(event_t *ev) diff --git a/src/m_cheat.h b/src/m_cheat.h index cc1ca7c2a..60cf0ca98 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -27,7 +27,7 @@ struct event_s; // [Nugget] CVARs extern boolean comp_choppers; -typedef void (*cheatf_v)(); +typedef void (*cheatf_v)(void); typedef void (*cheatf_i)(int i); typedef void (*cheatf_s)(char *s); diff --git a/src/m_config.c b/src/m_config.c index 92d856ae9..988868766 100644 --- a/src/m_config.c +++ b/src/m_config.c @@ -30,6 +30,7 @@ #include "am_map.h" #include "config.h" #include "d_main.h" +#include "d_iwad.h" #include "doomdef.h" #include "doomstat.h" #include "doomtype.h" diff --git a/src/m_fixed.h b/src/m_fixed.h index 9e740a623..b73dc0180 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -30,6 +30,20 @@ #define div64_32(a, b) _div64((a), (b), NULL) +#elif defined(__GNUC__) && defined(__x86_64__) + + inline static int32_t div64_32(int64_t a, int32_t b) + { + if (__builtin_constant_p(b)) + { + return a / b; + } + int32_t lo = a; + int32_t hi = a >> 32; + asm("idivl %[divisor]" : "+a" (lo), "+d" (hi) : [divisor] "r" (b)); + return lo; + } + #else #define div64_32(a, b) ((fixed_t)((a) / (b))) @@ -72,7 +86,7 @@ inline static int64_t FixedMul64(int64_t a, int64_t b) inline static fixed_t FixedDiv(fixed_t a, fixed_t b) { // [FG] avoid 31-bit shift (from Chocolate Doom) - if ((abs(a) >> 14) >= abs(b)) + if (((unsigned)abs(a) >> 14) >= (unsigned)abs(b)) { return (a ^ b) < 0 ? INT_MIN : INT_MAX; } diff --git a/src/m_misc.c b/src/m_misc.c index 59cc68d8e..2af9fa42c 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -27,9 +27,16 @@ #include "m_misc.h" #include "z_zone.h" +#include "config.h" +#ifdef HAVE_GETPWUID +#include <unistd.h> +#include <sys/types.h> +#include <pwd.h> +#endif + // Check if a file exists -boolean M_FileExists(const char *filename) +static boolean M_FileExistsNotDir(const char *filename) { FILE *fstream; @@ -38,14 +45,11 @@ boolean M_FileExists(const char *filename) if (fstream != NULL) { fclose(fstream); - return true; + return M_DirExists(filename) == false; } else { - // If we can't open because the file is a directory, the - // "file" exists at least! - - return errno == EISDIR; + return false; } } @@ -111,7 +115,7 @@ char *M_FileCaseExists(const char *path) path_dup = M_StringDuplicate(path); // 0: actual path - if (M_FileExists(path_dup)) + if (M_FileExistsNotDir(path_dup)) { return path_dup; } @@ -123,7 +127,7 @@ char *M_FileCaseExists(const char *path) // 1: lowercase filename, e.g. doom2.wad M_StringToLower(filename); - if (M_FileExists(path_dup)) + if (M_FileExistsNotDir(path_dup)) { return path_dup; } @@ -131,7 +135,7 @@ char *M_FileCaseExists(const char *path) // 2: uppercase filename, e.g. DOOM2.WAD M_StringToUpper(filename); - if (M_FileExists(path_dup)) + if (M_FileExistsNotDir(path_dup)) { return path_dup; } @@ -142,7 +146,7 @@ char *M_FileCaseExists(const char *path) { M_StringToLower(ext + 1); - if (M_FileExists(path_dup)) + if (M_FileExistsNotDir(path_dup)) { return path_dup; } @@ -153,7 +157,7 @@ char *M_FileCaseExists(const char *path) { M_StringToLower(filename + 1); - if (M_FileExists(path_dup)) + if (M_FileExistsNotDir(path_dup)) { return path_dup; } @@ -231,23 +235,73 @@ const char *M_BaseName(const char *path) } } +char *M_HomeDir(void) +{ + static char *home_dir; + + if (home_dir == NULL) + { + home_dir = M_getenv("HOME"); + + if (home_dir == NULL) + { +#ifdef HAVE_GETPWUID + struct passwd *user_info = getpwuid(getuid()); + if (user_info != NULL) + home_dir = user_info->pw_dir; + else +#endif + home_dir = "/"; + } + } + + return home_dir; +} + +// 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. + +char *M_DataDir(void) +{ + static char *data_dir; + + if (data_dir == NULL) + { + data_dir = M_getenv("XDG_DATA_HOME"); + + if (data_dir == NULL || *data_dir == '\0') + { + const char *home_dir = M_HomeDir(); + data_dir = M_StringJoin(home_dir, "/.local/share"); + } + } + + return data_dir; +} + // Change string to uppercase. char M_ToUpper(const char c) { - if (c >= 'a' && c <= 'z') - return c + 'A' - 'a'; - else - return c; + if (c >= 'a' && c <= 'z') + { + return c + 'A' - 'a'; + } + else + { + return c; + } } -void M_StringToUpper(char *text) +void M_StringToUpper(char *str) { - char *p; - - for (p = text; *p != '\0'; ++p) + while (*str) { - *p = M_ToUpper(*p); + *str = M_ToUpper(*str); + ++str; } } @@ -255,19 +309,22 @@ void M_StringToUpper(char *text) char M_ToLower(const char c) { - if (c >= 'A' && c <= 'Z') - return c - 'A' + 'a'; - else - return c; + if (c >= 'A' && c <= 'Z') + { + return c - 'A' + 'a'; + } + else + { + return c; + } } -void M_StringToLower(char *text) +void M_StringToLower(char *str) { - char *p; - - for (p = text; *p != '\0'; ++p) + while (*str) { - *p = M_ToLower(*p); + *str = M_ToLower(*str); + ++str; } } @@ -505,30 +562,19 @@ void M_CopyLumpName(char *dest, const char *src) // // 1/18/98 killough: adds a default extension to a path -// Note: Backslashes are treated specially, for MS-DOS. // -char *AddDefaultExtension(char *path, const char *ext) +char *AddDefaultExtension(const char *path, const char *ext) { - char *p = path; - - while (*p++) - ; - - while (p-- > path && *p != '/' && *p != '\\') + if (strrchr(M_BaseName(path), '.') != NULL) { - if (*p == '.') - { - return path; - } + // path already has an extension + return M_StringDuplicate(path); } - - if (*ext != '.') + else { - strcat(path, "."); + return M_StringJoin(path, ext); } - - return strcat(path, ext); } // diff --git a/src/m_misc.h b/src/m_misc.h index fe549abd2..e8a948433 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -23,7 +23,6 @@ #include "doomtype.h" -boolean M_FileExists(const char *file); boolean M_DirExists(const char *path); int M_FileLength(const char *path); char *M_TempFile(const char *s); @@ -31,6 +30,8 @@ char *M_FileCaseExists(const char *file); boolean M_StrToInt(const char *str, int *result); char *M_DirName(const char *path); const char *M_BaseName(const char *path); +char *M_HomeDir(void); +char *M_DataDir(void); char M_ToUpper(const char c); void M_StringToUpper(char *text); char M_ToLower(const char c); @@ -55,7 +56,7 @@ 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_CopyLumpName(char *dest, const char *src); -char *AddDefaultExtension(char *path, const char *ext); +char *AddDefaultExtension(const char *path, const char *ext); boolean M_WriteFile(const char *name, void *source, int length); int M_ReadFile(const char *name, byte **buffer); boolean M_StringToDigest(const char *string, byte *digest, int size); diff --git a/src/m_scanner.c b/src/m_scanner.c new file mode 100644 index 000000000..eca0fce69 --- /dev/null +++ b/src/m_scanner.c @@ -0,0 +1,706 @@ +// +// Copyright (c) 2015, Braden "Blzut3" Obrzut +// Copyright (c) 2024, Roman Fomin +// +// 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. +// * 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 COPYRIGHT HOLDER 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. + +#include "m_scanner.h" + +#include <stdlib.h> +#include <string.h> + +#include "doomtype.h" +#include "i_system.h" +#include "m_misc.h" + +static const char* const token_names[] = +{ + [TK_Identifier] = "Identifier", + [TK_StringConst] = "String Constant", + [TK_IntConst] = "Integer Constant", + [TK_BoolConst] = "boolean Constant", + [TK_FloatConst] = "Float Constant", + [TK_AnnotateStart] = "Annotation Start", + [TK_AnnotateEnd] = "Annotation End", + [TK_LumpName] = "Lump Name" +}; + +typedef struct +{ + char *string; + int number; + double decimal; + char token; + + int tokenline; + int tokenlinepos; + int scanpos; +} parserstate_t; + +struct scanner_s +{ + parserstate_t state; + parserstate_t nextstate, prevstate; + + char *data; + size_t length; + + int line; + int linestart; + int logicalpos; + int scanpos; + + boolean neednext; // If CheckToken() returns false this will be false. + + const char *scriptname; +}; + +static void IncrementLine(scanner_t *s) +{ + s->line++; + s->linestart = s->scanpos; +} + +static void CheckForWhitespace(scanner_t *s) +{ + int comment = 0; // 1 = till next new line, 2 = till end block + + while (s->scanpos < s->length) + { + char cur = s->data[s->scanpos]; + char next = (s->scanpos + 1 < s->length) ? s->data[s->scanpos + 1] : 0; + + if (comment == 2) + { + if (cur != '*' || next != '/') + { + if (cur == '\n' || cur == '\r') + { + s->scanpos++; + + // Do a quick check for Windows style new line + if (cur == '\r' && next == '\n') + { + s->scanpos++; + } + IncrementLine(s); + } + else + { + s->scanpos++; + } + } + else + { + comment = 0; + s->scanpos += 2; + } + continue; + } + + if (cur == ' ' || cur == '\t' || cur == 0) + { + s->scanpos++; + } + else if (cur == '\n' || cur == '\r') + { + s->scanpos++; + if (comment == 1) + { + comment = 0; + } + + // Do a quick check for Windows style new line + if (cur == '\r' && next == '\n') + { + s->scanpos++; + } + IncrementLine(s); + } + else if (cur == '/' && comment == 0) + { + switch (next) + { + case '/': + comment = 1; + break; + case '*': + comment = 2; + break; + default: + return; + } + s->scanpos += 2; + } + else + { + if (comment == 0) + { + return; + } + else + { + s->scanpos++; + } + } + } +} + +static void CopyState(parserstate_t *to, const parserstate_t *from) +{ + if (to->string) + { + free(to->string); + to->string = NULL; + } + if (from->string) + { + to->string = M_StringDuplicate(from->string); + } + to->number = from->number; + to->decimal = from->decimal; + to->token = from->token; + to->tokenline = from->tokenline; + to->tokenlinepos = from->tokenlinepos; + to->scanpos = from->scanpos; +} + +static void ExpandState(scanner_t *s) +{ + s->scanpos = s->nextstate.scanpos; + s->logicalpos = s->scanpos; + CheckForWhitespace(s); + + CopyState(&s->prevstate, &s->state); + CopyState(&s->state, &s->nextstate); +} + +static void Unescape(char *str) +{ + char *p = str, c; + + while ((c = *p++)) + { + if (c != '\\') + { + *str++ = c; + } + else + { + switch (*p) + { + case 'n': + *str++ = '\n'; + break; + case 'r': + *str++ = '\r'; + break; + case 't': + *str++ = '\t'; + break; + case '"': + *str++ = '\"'; + break; + default: + *str++ = *p; + break; + } + p++; + } + } + *str = 0; +} + +boolean SC_GetNextToken(scanner_t *s, boolean expandstate) +{ + if (!s->neednext) + { + s->neednext = true; + if (expandstate) + { + ExpandState(s); + } + return true; + } + + s->nextstate.tokenline = s->line; + s->nextstate.tokenlinepos = s->scanpos - s->linestart; + s->nextstate.token = TK_NoToken; + if (s->scanpos >= s->length) + { + if (expandstate) + { + ExpandState(s); + } + return false; + } + + int start = s->scanpos; + int end = s->scanpos; + int integer_base = 10; + boolean float_has_decimal = false; + boolean float_has_exponent = false; + boolean string_finished = + false; // Strings are the only things that can have 0 length tokens. + + char cur = s->data[s->scanpos++]; + // Determine by first character + if (cur == '_' || (cur >= 'A' && cur <= 'Z') || (cur >= 'a' && cur <= 'z')) + { + s->nextstate.token = TK_Identifier; + } + else if (cur >= '0' && cur <= '9') + { + if (cur == '0') + { + integer_base = 8; + } + s->nextstate.token = TK_IntConst; + } + else if (cur == '.' && s->scanpos < s->length && s->data[s->scanpos] != '.') + { + float_has_decimal = true; + s->nextstate.token = TK_FloatConst; + } + else if (cur == '"') + { + end = ++start; // Move the start up one character so we don't have to + // trim it later. + s->nextstate.token = TK_StringConst; + } + else + { + end = s->scanpos; + s->nextstate.token = cur; + + // Now check for operator tokens + if (s->scanpos < s->length) + { + char next = s->data[s->scanpos]; + + if (cur == ':' && next == ':') + { + s->nextstate.token = TK_ScopeResolution; + } + else if (cur == '/' && next == '*') + { + s->nextstate.token = TK_AnnotateStart; + } + else if (cur == '*' && next == '/') + { + s->nextstate.token = TK_AnnotateEnd; + } + + if (s->nextstate.token != cur) + { + s->scanpos++; + end = s->scanpos; + } + } + } + + if (start == end) + { + while (s->scanpos < s->length) + { + cur = s->data[s->scanpos]; + switch (s->nextstate.token) + { + default: + break; + + case TK_Identifier: + if (cur != '_' && (cur < 'A' || cur > 'Z') + && (cur < 'a' || cur > 'z') && (cur < '0' || cur > '9')) + { + end = s->scanpos; + } + break; + + case TK_IntConst: + if (cur == '.' || (s->scanpos - 1 != start && cur == 'e')) + { + s->nextstate.token = TK_FloatConst; + } + else if ((cur == 'x' || cur == 'X') + && s->scanpos - 1 == start) + { + integer_base = 16; + break; + } + else + { + switch (integer_base) + { + default: + if (cur < '0' || cur > '9') + { + end = s->scanpos; + } + break; + case 8: + if (cur < '0' || cur > '7') + { + end = s->scanpos; + } + break; + case 16: + if ((cur < '0' || cur > '9') + && (cur < 'A' || cur > 'F') + && (cur < 'a' || cur > 'f')) + { + end = s->scanpos; + } + break; + } + break; + } + + case TK_FloatConst: + if (cur < '0' || cur > '9') + { + if (!float_has_decimal && cur == '.') + { + float_has_decimal = true; + break; + } + else if (!float_has_exponent && cur == 'e') + { + float_has_decimal = true; + float_has_exponent = true; + if (s->scanpos + 1 < s->length) + { + char next = s->data[s->scanpos + 1]; + if ((next < '0' || next > '9') && next != '+' + && next != '-') + { + end = s->scanpos; + } + else + { + s->scanpos++; + } + } + break; + } + end = s->scanpos; + } + break; + + case TK_StringConst: + if (cur == '"') + { + string_finished = true; + end = s->scanpos; + s->scanpos++; + } + else if (cur == '\\') + { + s->scanpos++; // Will add two since the loop + // automatically adds one + } + break; + } + if (start == end && !string_finished) + { + s->scanpos++; + } + else + { + break; + } + } + // Handle small tokens at the end of a file. + if (s->scanpos == s->length && !string_finished) + { + end = s->scanpos; + } + } + + s->nextstate.scanpos = s->scanpos; + if (end - start > 0 || string_finished) + { + if (s->nextstate.string) + { + free(s->nextstate.string); + } + int length = end - start; + s->nextstate.string = malloc(length + 1); + memcpy(s->nextstate.string, s->data + start, length); + s->nextstate.string[length] = '\0'; + + if (s->nextstate.token == TK_FloatConst) + { + if (float_has_decimal && strlen(s->nextstate.string) == 1) + { + // Don't treat a lone '.' as a decimal. + s->nextstate.token = '.'; + } + else + { + s->nextstate.decimal = atof(s->nextstate.string); + s->nextstate.number = (int)s->nextstate.decimal; + } + } + else if (s->nextstate.token == TK_IntConst) + { + s->nextstate.number = + strtol(s->nextstate.string, NULL, integer_base); + s->nextstate.decimal = (double)s->nextstate.number; + } + else if (s->nextstate.token == TK_Identifier) + { + // Check for a boolean constant. + if (!strcasecmp(s->nextstate.string, "true")) + { + s->nextstate.token = TK_BoolConst; + s->nextstate.number = true; + } + else if (!strcasecmp(s->nextstate.string, "false")) + { + s->nextstate.token = TK_BoolConst; + s->nextstate.number = false; + } + } + else if (s->nextstate.token == TK_StringConst) + { + Unescape(s->nextstate.string); + } + if (expandstate) + { + ExpandState(s); + } + return true; + } + s->nextstate.token = TK_NoToken; + if (expandstate) + { + ExpandState(s); + } + return false; +} + +void SC_GetNextTokenLumpName(scanner_t *s) +{ + if (!s->neednext) + { + s->neednext = true; + ExpandState(s); + return; + } + + s->nextstate.tokenline = s->line; + s->nextstate.tokenlinepos = s->scanpos - s->linestart; + s->nextstate.token = TK_NoToken; + if (s->scanpos >= s->length) + { + ExpandState(s); + return; + } + + int start = s->scanpos++; + while (s->scanpos < s->length) + { + char cur = s->data[s->scanpos]; + if (cur == ' ' || cur == '\t' || cur == '\n' || cur == '\r' || cur == 0) + { + break; + } + s->scanpos++; + } + s->nextstate.scanpos = s->scanpos; + + int length = s->scanpos - start; + if (length > 0) + { + s->nextstate.token = TK_LumpName; + if (s->nextstate.string) + { + free(s->nextstate.string); + } + s->nextstate.string = malloc(length + 1); + memcpy(s->nextstate.string, s->data + start, length); + s->nextstate.string[length] = '\0'; + } + + ExpandState(s); +} + +// Skips all Tokens in current line and parses the first token on the next +// line. +void SC_GetNextLineToken(scanner_t *s) +{ + int line = s->line; + while (SC_GetNextToken(s, true) && s->line == line) + ; +} + +boolean SC_CheckToken(scanner_t *s, char token) +{ + if (s->neednext) + { + if (!SC_GetNextToken(s, false)) + { + return false; + } + } + + // An int can also be a float. + if (s->nextstate.token == token + || (s->nextstate.token == TK_IntConst && token == TK_FloatConst)) + { + s->neednext = true; + ExpandState(s); + return true; + } + s->neednext = false; + return false; +} + +void SC_Error(scanner_t *s, const char *msg, ...) +{ + char buffer[1024]; + va_list args; + va_start(args, msg); + M_vsnprintf(buffer, sizeof(buffer), msg, args); + va_end(args); + + I_Error("%s(%d:%d): %s", s->scriptname, s->state.tokenline + 1, + s->state.tokenlinepos + 1, buffer); +} + +void SC_MustGetToken(scanner_t *s, char token) +{ + if (SC_CheckToken(s, token)) + { + return; + } + + ExpandState(s); + if (s->state.token == TK_NoToken) + { + SC_Error(s, "Unexpected end of script."); + } + else if (token < TK_NumSpecialTokens + && s->state.token < TK_NumSpecialTokens) + { + SC_Error(s, "Expected '%s' but got '%s' instead.", + token_names[(int)token], token_names[(int)s->state.token]); + } + else if (token < TK_NumSpecialTokens + && s->state.token >= TK_NumSpecialTokens) + { + SC_Error(s, "Expected '%s' but got '%c' instead.", + token_names[(int)token], s->state.token); + } + else if (token >= TK_NumSpecialTokens + && s->state.token < TK_NumSpecialTokens) + { + SC_Error(s, "Expected '%c' but got '%s' instead.", token, + token_names[(int)s->state.token]); + } + else + { + SC_Error(s, "Expected '%c' but got '%c' instead.", token, + s->state.token); + } +} + +void SC_Rewind(scanner_t *s) // Only can rewind one step. +{ + s->neednext = false; + + CopyState(&s->nextstate, &s->state); + CopyState(&s->state, &s->prevstate); + + s->line = s->prevstate.tokenline; + s->logicalpos = s->prevstate.tokenlinepos; + s->scanpos = s->prevstate.scanpos; +} + +boolean SC_TokensLeft(scanner_t *s) +{ + return s->scanpos < s->length; +} + +const char *SC_GetString(scanner_t *s) +{ + return s->state.string; +} + +int SC_GetNumber(scanner_t *s) +{ + return s->state.number; +} + +boolean SC_GetBoolean(scanner_t *s) +{ + return (boolean)s->state.number; +} + +double SC_GetDecimal(scanner_t *s) +{ + return s->state.decimal; +} + +scanner_t *SC_Open(const char *scriptname, const char *data, int length) +{ + scanner_t *s = calloc(1, sizeof(*s)); + + s->line = 1; + s->neednext = true; + + s->length = length; + s->data = malloc(length); + memcpy(s->data, data, length); + + CheckForWhitespace(s); + s->state.scanpos = s->scanpos; + s->scriptname = M_StringDuplicate(scriptname); + return s; +} + +void SC_Close(scanner_t *s) +{ + if (s->state.string) + { + free(s->state.string); + } + if (s->prevstate.string) + { + free(s->prevstate.string); + } + if (s->nextstate.string) + { + free(s->nextstate.string); + } + if (s->scriptname) + { + free((char *)s->scriptname); + } + free(s->data); + free(s); +} diff --git a/src/m_scanner.h b/src/m_scanner.h new file mode 100644 index 000000000..f275cdfe7 --- /dev/null +++ b/src/m_scanner.h @@ -0,0 +1,76 @@ +// +// Copyright (c) 2015, Braden "Blzut3" Obrzut +// Copyright (c) 2024, Roman Fomin +// +// 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. +// * 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 COPYRIGHT HOLDER 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. + +#ifndef M_SCANNER_H +#define M_SCANNER_H + +#include "doomtype.h" + +typedef struct scanner_s scanner_t; + +enum +{ + TK_Identifier, // Ex: SomeIdentifier + TK_StringConst, // Ex: "Some String" + TK_IntConst, // Ex: 27 + TK_BoolConst, // Ex: true + TK_FloatConst, // Ex: 1.5 + + TK_LumpName, + + TK_AnnotateStart, // Block comment start + TK_AnnotateEnd, // Block comment end + + TK_ScopeResolution, // :: + + TK_NumSpecialTokens, + + TK_NoToken = -1 +}; + +scanner_t *SC_Open(const char *scriptname, const char *data, int length); +void SC_Close(scanner_t *s); + +const char *SC_GetString(scanner_t *s); +int SC_GetNumber(scanner_t *s); +boolean SC_GetBoolean(scanner_t *s); +double SC_GetDecimal(scanner_t *s); + +boolean SC_TokensLeft(scanner_t *s); +boolean SC_CheckToken(scanner_t *s, char token); +boolean SC_GetNextToken(scanner_t *s, boolean expandstate); +void SC_GetNextLineToken(scanner_t *s); +void SC_MustGetToken(scanner_t *s, char token); +void SC_Rewind(scanner_t *s); // Only can rewind one step. + +void SC_GetNextTokenLumpName(scanner_t *s); + +void SC_Error(scanner_t *s, const char *msg, ...) PRINTF_ATTR(2, 3); + +#endif diff --git a/src/m_vector.h b/src/m_vector.h index b5f5573c4..896a16981 100644 --- a/src/m_vector.h +++ b/src/m_vector.h @@ -20,95 +20,104 @@ #include <math.h> +#include "config.h" #include "doomtype.h" +#if defined(HAVE_EXT_VECTOR_TYPE) +typedef float vec __attribute__((ext_vector_type(3))); +#else typedef struct { float x; float y; float z; } vec; +#endif +#if defined(HAVE_EXT_VECTOR_TYPE) +typedef float quat __attribute__((ext_vector_type(4))); +#else typedef struct { - float w; float x; float y; float z; + float w; } quat; +#endif // // Adds two vectors. // -inline static vec vec_add(const vec *a, const vec *b) +inline static vec vec_add(const vec a, const vec b) { - return (vec){a->x + b->x, a->y + b->y, a->z + b->z}; + return (vec){a.x + b.x, a.y + b.y, a.z + b.z}; } // // Subtracts two vectors. // -inline static vec vec_subtract(const vec *a, const vec *b) +inline static vec vec_subtract(const vec a, const vec b) { - return (vec){a->x - b->x, a->y - b->y, a->z - b->z}; + return (vec){a.x - b.x, a.y - b.y, a.z - b.z}; } // // Cross product of two vectors. // -inline static vec vec_crossproduct(const vec *a, const vec *b) +inline static vec vec_crossproduct(const vec a, const vec b) { - return (vec){a->y * b->z - a->z * b->y, - a->z * b->x - a->x * b->z, - a->x * b->y - a->y * b->x}; + return (vec){a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x}; } // // Dot product of two vectors. // -inline static float vec_dotproduct(const vec *a, const vec *b) +inline static float vec_dotproduct(const vec a, const vec b) { - return (a->x * b->x + a->y * b->y + a->z * b->z); + return (a.x * b.x + a.y * b.y + a.z * b.z); } // // Returns the negative of the input vector. // -inline static vec vec_negative(const vec *v) +inline static vec vec_negative(const vec v) { - return (vec){-v->x, -v->y, -v->z}; + return (vec){-v.x, -v.y, -v.z}; } // // Multiplies a vector by a scalar value. // -inline static vec vec_scale(const vec *v, float scalar) +inline static vec vec_scale(const vec v, float scalar) { - return (vec){v->x * scalar, v->y * scalar, v->z * scalar}; + return (vec){v.x * scalar, v.y * scalar, v.z * scalar}; } // // Clamps each vector component. // -inline static vec vec_clamp(float min, float max, const vec *v) +inline static vec vec_clamp(float min, float max, const vec v) { - return (vec){BETWEEN(min, max, v->x), - BETWEEN(min, max, v->y), - BETWEEN(min, max, v->z)}; + return (vec){BETWEEN(min, max, v.x), + BETWEEN(min, max, v.y), + BETWEEN(min, max, v.z)}; } // // Vector length squared. // -inline static float vec_lengthsquared(const vec *v) +inline static float vec_lengthsquared(const vec v) { - return (v->x * v->x + v->y * v->y + v->z * v->z); + return (v.x * v.x + v.y * v.y + v.z * v.z); } // // Vector magnitude. // -inline static float vec_length(const vec *v) +inline static float vec_length(const vec v) { return sqrtf(vec_lengthsquared(v)); } @@ -116,15 +125,15 @@ inline static float vec_length(const vec *v) // // Normalizes a vector using a given magnitude. // -inline static vec vec_normalize_mag(const vec *v, float mag) +inline static vec vec_normalize_mag(const vec v, float mag) { - return (mag > 0.0f ? vec_scale(v, 1.0f / mag) : *v); + return (mag > 0.0f ? vec_scale(v, 1.0f / mag) : v); } // // Normalizes a vector. // -inline static vec vec_normalize(const vec *v) +inline static vec vec_normalize(const vec v) { return vec_normalize_mag(v, vec_length(v)); } @@ -132,68 +141,68 @@ inline static vec vec_normalize(const vec *v) // // Is this a zero vector? // -inline static boolean is_zero_vec(const vec *v) +inline static boolean is_zero_vec(const vec v) { - return (v->x == 0.0f && v->y == 0.0f && v->z == 0.0f); + return (v.x == 0.0f && v.y == 0.0f && v.z == 0.0f); } // // Returns the conjugate of a unit quaternion (same as its inverse). // -inline static quat quat_inverse(const quat *q) +inline static quat quat_inverse(const quat q) { - return (quat){q->w, -q->x, -q->y, -q->z}; + return (quat){-q.x, -q.y, -q.z, q.w}; } // // Converts a vector to a quaternion. // -inline static quat vec_to_quat(const vec *v) +inline static quat vec_to_quat(const vec v) { - return (quat){0.0f, v->x, v->y, v->z}; + return (quat){v.x, v.y, v.z, 0.0f}; } // // Multiplies two quaternions. // -inline static quat quat_multiply(const quat *a, const quat *b) +inline static quat quat_multiply(const quat a, const quat b) { - return (quat){a->w * b->w - a->x * b->x - a->y * b->y - a->z * b->z, - a->w * b->x + a->x * b->w + a->y * b->z - a->z * b->y, - a->w * b->y - a->x * b->z + a->y * b->w + a->z * b->x, - a->w * b->z + a->x * b->y - a->y * b->x + a->z * b->w}; + return (quat){a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y, + a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x, + a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w, + a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z}; } // // Returns a unit quaternion from an angle and vector. // -inline static quat angle_axis(float angle, const vec *v) +inline static quat angle_axis(float angle, const vec v) { vec temp = vec_normalize(v); - temp = vec_scale(&temp, sinf(angle * 0.5f)); - return (quat){cosf(angle * 0.5f), temp.x, temp.y, temp.z}; + temp = vec_scale(temp, sinf(angle * 0.5f)); + return (quat){temp.x, temp.y, temp.z, cosf(angle * 0.5f)}; } // // Rotates a vector by a unit quaternion. // -inline static vec vec_rotate(const vec *v, const quat *q) +inline static vec vec_rotate(const vec v, const quat q) { const quat q_inv = quat_inverse(q); const quat v_quat = vec_to_quat(v); - quat temp = quat_multiply(q, &v_quat); - temp = quat_multiply(&temp, &q_inv); + quat temp = quat_multiply(q, v_quat); + temp = quat_multiply(temp, q_inv); return (vec){temp.x, temp.y, temp.z}; } // // Linear interpolation between two vectors. // -inline static vec vec_lerp(const vec *a, const vec *b, float factor) +inline static vec vec_lerp(const vec a, const vec b, float factor) { vec temp = vec_subtract(b, a); - temp = vec_scale(&temp, factor); - return vec_add(a, &temp); + temp = vec_scale(temp, factor); + return vec_add(a, temp); } #endif diff --git a/src/mn_internal.h b/src/mn_internal.h index 5de7e31ea..523a6b465 100644 --- a/src/mn_internal.h +++ b/src/mn_internal.h @@ -45,6 +45,8 @@ typedef enum key_mode } menu_input_mode_t; +extern int maxscreenblocks; + extern int bigfont_priority; extern menu_input_mode_t help_input, old_help_input; // pad_mode or key_mode. @@ -110,6 +112,8 @@ void MN_DrawColor(void); void MN_CustomSkill(void); void MN_DrawCustomSkill(void); +void MN_UpdateNughudItem(void); + // [Nugget] -----------------------------------------------------------------/ ///////////////////////////// diff --git a/src/mn_menu.c b/src/mn_menu.c index 7ed8cdc05..29953210e 100644 --- a/src/mn_menu.c +++ b/src/mn_menu.c @@ -37,6 +37,7 @@ #include "doomtype.h" #include "dstrings.h" #include "g_game.h" +#include "g_umapinfo.h" #include "i_input.h" #include "i_printf.h" #include "i_system.h" @@ -59,7 +60,6 @@ #include "st_sbardef.h" #include "st_stuff.h" #include "st_widgets.h" -#include "u_mapinfo.h" #include "v_fmt.h" #include "v_video.h" #include "w_wad.h" @@ -82,7 +82,7 @@ // Blocky mode, has default, 0 = high, 1 = normal // int detailLevel; obsolete -- killough -int screenblocks; // has default +int screenblocks, maxscreenblocks; // has default static int quickSaveSlot; // -1 = no quicksave slot picked! @@ -528,14 +528,13 @@ static short EpiMenuEpi[MAX_EPISODES] = {1, 2, 3, 4, -1, -1, -1, -1, -1, -1}; // static int epiChoice; -void M_ClearEpisodes(void) +void MN_ClearEpisodes(void) { EpiDef.numitems = 0; NewDef.prevMenu = &MainDef; } -void M_AddEpisode(const char *map, const char *gfx, const char *txt, - const char *alpha) +void MN_AddEpisode(const char *map, const char *gfx, const char *txt, char key) { int epi, mapnum; @@ -552,7 +551,8 @@ void M_AddEpisode(const char *map, const char *gfx, const char *txt, if (EpiDef.numitems == 8) { - I_Printf(VB_WARNING, "M_AddEpisode: UMAPINFO spec limit of 8 episodes exceeded!"); + I_Printf(VB_WARNING, + "MN_AddEpisode: UMAPINFO spec limit of 8 episodes exceeded!"); } else if (EpiDef.numitems >= MAX_EPISODES) { @@ -565,7 +565,7 @@ void M_AddEpisode(const char *map, const char *gfx, const char *txt, strncpy(EpisodeMenu[EpiDef.numitems].name, gfx, 8); EpisodeMenu[EpiDef.numitems].name[9] = 0; EpisodeMenu[EpiDef.numitems].alttext = txt ? strdup(txt) : NULL; - EpisodeMenu[EpiDef.numitems].alphaKey = alpha ? *alpha : 0; + EpisodeMenu[EpiDef.numitems].alphaKey = key; EpiDef.numitems++; if (EpiDef.numitems <= 4) @@ -1405,7 +1405,8 @@ static void SetDefaultSaveName(char *name, const char *append) char *maplump = MapName(gameepisode, gamemap); int maplumpnum = W_CheckNumForName(maplump); - if (gamemapinfo && U_CheckField(gamemapinfo->label)) + if (gamemapinfo && gamemapinfo->label + && !(gamemapinfo->flags & MapInfo_LabelClear)) { maplump = gamemapinfo->label; } @@ -1914,8 +1915,10 @@ static void M_SizeDisplay(int choice) default: break; } - screenblocks = BETWEEN(3, 12, screenblocks); + screenblocks = BETWEEN(3, maxscreenblocks, screenblocks); R_SetViewSize(screenblocks /*, detailLevel obsolete -- killough */); + + MN_UpdateNughudItem(); // [Nugget] NUGHUD } ///////////////////////////////////////////////////////////////////////////// @@ -2691,13 +2694,14 @@ boolean M_ShortcutResponder(const event_t *ev) else { ++screenblocks; - if (screenblocks > 12) + if (screenblocks > maxscreenblocks) { screenblocks = 10; } } R_SetViewSize(screenblocks); + MN_UpdateNughudItem(); // [Nugget] NUGHUD return true; } diff --git a/src/mn_menu.h b/src/mn_menu.h index b1165fa76..521b4a667 100644 --- a/src/mn_menu.h +++ b/src/mn_menu.h @@ -60,6 +60,9 @@ void M_Init(void); void MN_StartControlPanel(void); +void MN_AddEpisode(const char *map, const char *gfx, const char *txt, char key); +void MN_ClearEpisodes(void); + void MN_ForcedLoadAutoSave(const char *msg); void MN_ForcedLoadGame(const char *msg); // killough 5/15/98: forced loadgames void MN_Trans(void); // killough 11/98: reset translucency diff --git a/src/mn_setup.c b/src/mn_setup.c index 21f9cbe7a..2dfc21410 100644 --- a/src/mn_setup.c +++ b/src/mn_setup.c @@ -334,6 +334,7 @@ enum str_overlay, str_automap_preset, str_automap_keyed_door, + str_fuzzmode, str_weapon_slots_activation, str_weapon_slots_selection, str_weapon_slots, @@ -368,7 +369,6 @@ enum str_bobbing_style, str_force_carousel, - str_hud_type, str_crosshair_lockon, str_vertical_aiming, str_over_under, @@ -2034,6 +2034,7 @@ static setup_tab_t stat_tabs[] = { static void SizeDisplayAlt(void) { R_SetViewSize(screenblocks); + MN_UpdateNughudItem(); // [Nugget] NUGHUD } static void RefreshSolidBackground(void) @@ -2041,17 +2042,6 @@ static void RefreshSolidBackground(void) ST_refreshBackground(); // [Nugget] NUGHUD } -static const char *screensize_strings[] = { - "", "", "", "Status Bar", "Status Bar", - "Status Bar", "Status Bar", "Status Bar", "Status Bar", "Status Bar", - "Status Bar", "Fullscreen", "Fullscreen" -}; - -// [Nugget] NUGHUD -static const char *hud_type_strings[] = { - "SBARDEF", "NUGHUD" -}; - static const char *st_layout_strings[] = { "Original", "Wide" }; @@ -2067,8 +2057,7 @@ static setup_menu_t stat_settings1[] = { MI_GAP, // [Nugget] NUGHUD - {"Fullscreen HUD Type", S_CHOICE, H_X, M_SPC, {"fullscreen_hud_type"}, - .strings_id = str_hud_type}, + {"Use NUGHUD", S_ONOFF, H_X, M_SPC, {"use_nughud"}}, {"Layout", S_CHOICE, H_X, M_SPC, {"st_layout"}, .strings_id = str_stlayout, .action = AM_Start}, // [Nugget] Minimap @@ -2079,8 +2068,6 @@ static setup_menu_t stat_settings1[] = { {"Colored Numbers", S_ONOFF | S_COSMETIC, H_X, M_SPC, {"sts_colored_numbers"}}, - {"Gray Percent Sign", S_ONOFF | S_COSMETIC, H_X, M_SPC, {"sts_pct_always_gray"}}, - {"Solid Background Color", S_ONOFF, H_X, M_SPC, {"st_solidbackground"}, .action = RefreshSolidBackground}, @@ -2092,6 +2079,12 @@ static setup_menu_t stat_settings1[] = { MI_END }; +// [Nugget] NUGHUD +void MN_UpdateNughudItem(void) +{ + DisableItem(screenblocks != maxscreenblocks - 1, stat_settings1, "use_nughud"); +} + static void UpdateStatsFormatItem(void); static const char *show_widgets_strings[] = {"Off", "Automap", "HUD", "Always"}; @@ -2497,21 +2490,13 @@ static setup_menu_t enem_settings1[] = { // [Nugget] /------------------------------------------------------------- - // Restored menu item - // [FG] spectre drawing mode - {"Blocky Spectre Drawing", S_ONOFF, M_X, M_SPC, {"fuzzcolumn_mode"}, - .action = R_SetFuzzColumnMode}, - MI_GAP, - {"Nugget", S_SKIP|S_TITLE, M_X, M_SPC}, - {"Extra Gibbing", S_ONOFF|S_STRICT|S_CRITICAL, M_X, M_SPC, {"extra_gibbing"}}, - {"Bloodier Gibbing", S_ONOFF|S_STRICT|S_CRITICAL, M_X, M_SPC, {"bloodier_gibbing"}}, - {"Toss Items Upon Death", S_ONOFF|S_STRICT|S_CRITICAL, M_X, M_SPC, {"tossdrop"}}, + {"Nugget", S_SKIP|S_TITLE, M_X, M_SPC}, - // [Nugget - ceski] Selective fuzz darkening - {"Selective Fuzz Darkening", S_ONOFF|S_STRICT, M_X, M_SPC, - {"fuzzdark_mode"}, .action = R_SetFuzzColumnMode}, + {"Extra Gibbing", S_ONOFF|S_STRICT|S_CRITICAL, M_X, M_SPC, {"extra_gibbing"}}, + {"Bloodier Gibbing", S_ONOFF|S_STRICT|S_CRITICAL, M_X, M_SPC, {"bloodier_gibbing"}}, + {"Toss Items Upon Death", S_ONOFF|S_STRICT|S_CRITICAL, M_X, M_SPC, {"tossdrop"}}, // [Nugget] -------------------------------------------------------------/ @@ -2915,6 +2900,7 @@ static void SetMidiPlayerOpl(void) } } +#if defined(HAVE_FLUIDSYNTH) static void SetMidiPlayerFluidSynth(void) { if (I_MidiPlayerType() == midiplayer_fluidsynth) @@ -2922,6 +2908,7 @@ static void SetMidiPlayerFluidSynth(void) SetMidiPlayer(); } } +#endif static void RestartMusic(void) { @@ -3080,7 +3067,10 @@ static setup_menu_t music_settings1[] = { static void UpdateGainItems(void) { +#if defined (HAVE_FLUIDSYNTH) DisableItem(auto_gain, music_settings1, "fl_gain"); +#endif + DisableItem(auto_gain, music_settings1, "opl_gain"); } @@ -3661,7 +3651,11 @@ static void SmoothLight(void) static const char *menu_backdrop_strings[] = {"Off", "Dark", "Texture"}; static const char *exit_sequence_strings[] = { - "Off", "Sound Only", "PWAD ENDOOM", "Full" + "Off", "Sound Only", "ENDOOM Only", "Full" +}; + +static const char *fuzzmode_strings[] = { + "Vanilla", "Refraction", "Shadow" }; static setup_menu_t gen_settings5[] = { @@ -3672,8 +3666,8 @@ static setup_menu_t gen_settings5[] = { {"Sprite Translucency", S_ONOFF | S_STRICT, OFF_CNTR_X, M_SPC, {"translucency"}}, - {"Translucency Filter", S_NUM | S_ACTION | S_PCT, OFF_CNTR_X, M_SPC, - {"tran_filter_pct"}, .action = MN_Trans}, + {"Partial Invisibility", S_CHOICE | S_STRICT, OFF_CNTR_X, M_SPC, {"fuzzmode"}, + .strings_id = str_fuzzmode, .action = R_SetFuzzColumnMode}, MI_GAP, @@ -3753,7 +3747,7 @@ static setup_menu_t gen_settings6[] = { .action = AutoSaveStuff}, {"Organize save files", S_ONOFF | S_PRGWARN, OFF_CNTR_X, M_SPC, - {"organize_savefiles"}}, + {"organize_savefiles"}, .action = D_SetSavegameDirectory}, MI_GAP, @@ -3768,6 +3762,8 @@ static setup_menu_t gen_settings6[] = { {"Exit Sequence", S_CHOICE, OFF_CNTR_X, M_SPC, {"exit_sequence"}, .strings_id = str_exit_sequence}, + {"PWAD ENDOOM Only", S_ONOFF, OFF_CNTR_X, M_SPC, {"endoom_pwad_only"}}, + MI_END }; @@ -5004,6 +5000,8 @@ static boolean NextPage(int inc) return true; } +static setup_menu_t *active_thermo = NULL; + boolean MN_SetupResponder(menu_action_t action, int ch) { // phares 3/26/98 - 4/11/98: @@ -5252,6 +5250,7 @@ boolean MN_SetupResponder(menu_action_t action, int ch) set_weapon_active = false; default_verify = false; // phares 4/19/98 print_warning_about_changes = false; // [FG] reset + active_thermo = NULL; M_StartSoundOptional(sfx_mnucls, sfx_swtchx); // [Nugget]: [NS] Optional menu sounds. return true; } @@ -5318,8 +5317,6 @@ boolean MN_SetupMouseResponder(int x, int y) return true; } - static setup_menu_t *active_thermo = NULL; - if (M_InputDeactivated(input_menu_enter) && active_thermo) { int64_t flags = active_thermo->m_flags; @@ -5568,7 +5565,7 @@ static const char **selectstrings[] = { percent_strings, curve_strings, center_weapon_strings, - screensize_strings, + NULL, // str_screensize st_layout_strings, show_widgets_strings, show_adv_widgets_strings, @@ -5580,6 +5577,7 @@ static const char **selectstrings[] = { overlay_strings, automap_preset_strings, automap_keyed_door_strings, + fuzzmode_strings, weapon_slots_activation_strings, weapon_slots_selection_strings, NULL, // str_weapon_slots @@ -5609,7 +5607,6 @@ static const char **selectstrings[] = { bobbing_style_strings, force_carousel_strings, - hud_type_strings, crosshair_lockon_strings, vertical_aiming_strings, over_under_strings, @@ -5641,6 +5638,41 @@ static const char **GetMidiPlayerStrings(void) return I_DeviceList(); } +static const char **GetScreenSizeStrings(void) +{ + const char **strings = NULL; + + for (int i = 0; i < 3; ++i) + { + array_push(strings, ""); + } + for (int i = 3; i < 10; ++i) + { + array_push(strings, "Status Bar"); + } + + const char **st_strings = ST_StatusbarList(); + for (int i = 0; i < array_size(st_strings); ++i) + { + array_push(strings, st_strings[i]); + } + + // [Nugget] NUGHUD /------------------------------------------------------ + + // `maxscreenblocks` is now calculated in `ST_StatusbarList()` + + if (!st_strings) { + array_push(strings, "Status Bar"); + array_push(strings, "NUGHUD"); + } + + MN_UpdateNughudItem(); + + // [Nugget] -------------------------------------------------------------/ + + return strings; +} + void MN_InitMenuStrings(void) { UpdateWeaponSlotLabels(); @@ -5653,6 +5685,7 @@ void MN_InitMenuStrings(void) selectstrings[str_gyro_sens] = GetGyroSensitivityStrings(); selectstrings[str_gyro_accel] = GetGyroAccelStrings(); selectstrings[str_resampler] = GetResamplerStrings(); + selectstrings[str_screensize] = GetScreenSizeStrings(); } void MN_SetupResetMenu(void) @@ -5666,6 +5699,7 @@ void MN_SetupResetMenu(void) DisableItem(!brightmaps_found || force_brightmaps, gen_settings5, "brightmaps"); DisableItem(!trakinfo_found, gen_settings2, "extra_music"); + DisableItem(M_ParmExists("-save"), gen_settings6, "organize_savefiles"); UpdateInterceptsEmuItem(); UpdateStatsFormatItem(); UpdateCrosshairItems(); @@ -5682,6 +5716,7 @@ void MN_SetupResetMenu(void) enem_settings1, "extra_gibbing"); UpdatePaletteItems(); + MN_UpdateNughudItem(); // NUGHUD } void MN_BindMenuVariables(void) diff --git a/src/p_action.h b/src/p_action.h index c4cad6d32..c0cbe1a88 100644 --- a/src/p_action.h +++ b/src/p_action.h @@ -30,126 +30,126 @@ struct mobj_s; // modified for years by Dehacked enthusiasts. The new BEX format // allows more extensive changes (see d_deh.c) -void A_Light0(struct player_s *player, struct pspdef_s *psp); -void A_WeaponReady(struct player_s *player, struct pspdef_s *psp); -void A_Lower(struct player_s *player, struct pspdef_s *psp); -void A_Raise(struct player_s *player, struct pspdef_s *psp); -void A_Punch(struct player_s *player, struct pspdef_s *psp); -void A_ReFire(struct player_s *player, struct pspdef_s *psp); -void A_FirePistol(struct player_s *player, struct pspdef_s *psp); -void A_Light1(struct player_s *player, struct pspdef_s *psp); -void A_FireShotgun(struct player_s *player, struct pspdef_s *psp); -void A_Light2(struct player_s *player, struct pspdef_s *psp); -void A_FireShotgun2(struct player_s *player, struct pspdef_s *psp); -void A_CheckReload(struct player_s *player, struct pspdef_s *psp); -void A_OpenShotgun2(struct player_s *player, struct pspdef_s *psp); -void A_LoadShotgun2(struct player_s *player, struct pspdef_s *psp); -void A_CloseShotgun2(struct player_s *player, struct pspdef_s *psp); -void A_FireCGun(struct player_s *player, struct pspdef_s *psp); -void A_GunFlash(struct player_s *player, struct pspdef_s *psp); -void A_FireMissile(struct player_s *player, struct pspdef_s *psp); -void A_Saw(struct player_s *player, struct pspdef_s *psp); -void A_FirePlasma(struct player_s *player, struct pspdef_s *psp); -void A_BFGsound(struct player_s *player, struct pspdef_s *psp); -void A_FireBFG(struct player_s *player, struct pspdef_s *psp); -void A_BFGSpray(struct mobj_s *mo); -void A_Explode(struct mobj_s *thingy); -void A_Pain(struct mobj_s *actor); -void A_PlayerScream(struct mobj_s *mo); -void A_Fall(struct mobj_s *actor); -void A_XScream(struct mobj_s *actor); -void A_Look(struct mobj_s *actor); -void A_Chase(struct mobj_s *actor); -void A_FaceTarget(struct mobj_s *actor); -void A_PosAttack(struct mobj_s *actor); -void A_Scream(struct mobj_s *actor); -void A_SPosAttack(struct mobj_s *actor); -void A_VileChase(struct mobj_s *actor); -void A_VileStart(struct mobj_s *actor); -void A_VileTarget(struct mobj_s *actor); -void A_VileAttack(struct mobj_s *actor); -void A_StartFire(struct mobj_s *actor); -void A_Fire(struct mobj_s *actor); -void A_FireCrackle(struct mobj_s *actor); -void A_Tracer(struct mobj_s *actor); -void A_SkelWhoosh(struct mobj_s *actor); -void A_SkelFist(struct mobj_s *actor); -void A_SkelMissile(struct mobj_s *actor); -void A_FatRaise(struct mobj_s *actor); -void A_FatAttack1(struct mobj_s *actor); -void A_FatAttack2(struct mobj_s *actor); -void A_FatAttack3(struct mobj_s *actor); -void A_BossDeath(struct mobj_s *mo); -void A_CPosAttack(struct mobj_s *actor); -void A_CPosRefire(struct mobj_s *actor); -void A_TroopAttack(struct mobj_s *actor); -void A_SargAttack(struct mobj_s *actor); -void A_HeadAttack(struct mobj_s *actor); -void A_BruisAttack(struct mobj_s *actor); -void A_SkullAttack(struct mobj_s *actor); -void A_Metal(struct mobj_s *mo); -void A_SpidRefire(struct mobj_s *actor); -void A_BabyMetal(struct mobj_s *mo); -void A_BspiAttack(struct mobj_s *actor); -void A_Hoof(struct mobj_s *mo); -void A_CyberAttack(struct mobj_s *actor); -void A_PainAttack(struct mobj_s *actor); -void A_PainDie(struct mobj_s *actor); -void A_KeenDie(struct mobj_s *mo); -void A_BrainPain(struct mobj_s *mo); -void A_BrainScream(struct mobj_s *mo); -void A_BrainDie(struct mobj_s *mo); -void A_BrainAwake(struct mobj_s *mo); -void A_BrainSpit(struct mobj_s *mo); -void A_SpawnSound(struct mobj_s *mo); -void A_SpawnFly(struct mobj_s *mo); -void A_BrainExplode(struct mobj_s *mo); -void A_Detonate(struct mobj_s *mo); // killough 8/9/98 -void A_Mushroom(struct mobj_s *actor); // killough 10/98 -void A_Die(struct mobj_s *actor); // killough 11/98 -void A_Spawn(struct mobj_s *mo); // killough 11/98 -void A_Turn(struct mobj_s *mo); // killough 11/98 -void A_Face(struct mobj_s *mo); // killough 11/98 -void A_Scratch(struct mobj_s *mo); // killough 11/98 -void A_PlaySound(struct mobj_s *mo); // killough 11/98 -void A_RandomJump(struct mobj_s *mo); // killough 11/98 -void A_LineEffect(struct mobj_s *mo); // killough 11/98 +void A_Light0(struct player_s *, struct pspdef_s *); +void A_WeaponReady(struct player_s *, struct pspdef_s *); +void A_Lower(struct player_s *, struct pspdef_s *); +void A_Raise(struct player_s *, struct pspdef_s *); +void A_Punch(struct player_s *, struct pspdef_s *); +void A_ReFire(struct player_s *, struct pspdef_s *); +void A_FirePistol(struct player_s *, struct pspdef_s *); +void A_Light1(struct player_s *, struct pspdef_s *); +void A_FireShotgun(struct player_s *, struct pspdef_s *); +void A_Light2(struct player_s *, struct pspdef_s *); +void A_FireShotgun2(struct player_s *, struct pspdef_s *); +void A_CheckReload(struct player_s *, struct pspdef_s *); +void A_OpenShotgun2(struct player_s *, struct pspdef_s *); +void A_LoadShotgun2(struct player_s *, struct pspdef_s *); +void A_CloseShotgun2(struct player_s *, struct pspdef_s *); +void A_FireCGun(struct player_s *, struct pspdef_s *); +void A_GunFlash(struct player_s *, struct pspdef_s *); +void A_FireMissile(struct player_s *, struct pspdef_s *); +void A_Saw(struct player_s *, struct pspdef_s *); +void A_FirePlasma(struct player_s *, struct pspdef_s *); +void A_BFGsound(struct player_s *, struct pspdef_s *); +void A_FireBFG(struct player_s *, struct pspdef_s *); +void A_BFGSpray(struct mobj_s *); +void A_Explode(struct mobj_s *); +void A_Pain(struct mobj_s *); +void A_PlayerScream(struct mobj_s *); +void A_Fall(struct mobj_s *); +void A_XScream(struct mobj_s *); +void A_Look(struct mobj_s *); +void A_Chase(struct mobj_s *); +void A_FaceTarget(struct mobj_s *); +void A_PosAttack(struct mobj_s *); +void A_Scream(struct mobj_s *); +void A_SPosAttack(struct mobj_s *); +void A_VileChase(struct mobj_s *); +void A_VileStart(struct mobj_s *); +void A_VileTarget(struct mobj_s *); +void A_VileAttack(struct mobj_s *); +void A_StartFire(struct mobj_s *); +void A_Fire(struct mobj_s *); +void A_FireCrackle(struct mobj_s *); +void A_Tracer(struct mobj_s *); +void A_SkelWhoosh(struct mobj_s *); +void A_SkelFist(struct mobj_s *); +void A_SkelMissile(struct mobj_s *); +void A_FatRaise(struct mobj_s *); +void A_FatAttack1(struct mobj_s *); +void A_FatAttack2(struct mobj_s *); +void A_FatAttack3(struct mobj_s *); +void A_BossDeath(struct mobj_s *); +void A_CPosAttack(struct mobj_s *); +void A_CPosRefire(struct mobj_s *); +void A_TroopAttack(struct mobj_s *); +void A_SargAttack(struct mobj_s *); +void A_HeadAttack(struct mobj_s *); +void A_BruisAttack(struct mobj_s *); +void A_SkullAttack(struct mobj_s *); +void A_Metal(struct mobj_s *); +void A_SpidRefire(struct mobj_s *); +void A_BabyMetal(struct mobj_s *); +void A_BspiAttack(struct mobj_s *); +void A_Hoof(struct mobj_s *); +void A_CyberAttack(struct mobj_s *); +void A_PainAttack(struct mobj_s *); +void A_PainDie(struct mobj_s *); +void A_KeenDie(struct mobj_s *); +void A_BrainPain(struct mobj_s *); +void A_BrainScream(struct mobj_s *); +void A_BrainDie(struct mobj_s *); +void A_BrainAwake(struct mobj_s *); +void A_BrainSpit(struct mobj_s *); +void A_SpawnSound(struct mobj_s *); +void A_SpawnFly(struct mobj_s *); +void A_BrainExplode(struct mobj_s *); +void A_Detonate(struct mobj_s *); // killough 8/9/98 +void A_Mushroom(struct mobj_s *); // killough 10/98 +void A_Die(struct mobj_s *); // killough 11/98 +void A_Spawn(struct mobj_s *); // killough 11/98 +void A_Turn(struct mobj_s *); // killough 11/98 +void A_Face(struct mobj_s *); // killough 11/98 +void A_Scratch(struct mobj_s *); // killough 11/98 +void A_PlaySound(struct mobj_s *); // killough 11/98 +void A_RandomJump(struct mobj_s *); // killough 11/98 +void A_LineEffect(struct mobj_s *); // killough 11/98 // killough 7/19/98: classic BFG firing function -void A_FireOldBFG(struct player_s *player, struct pspdef_s *psp); +void A_FireOldBFG(struct player_s *, struct pspdef_s *); // killough 10/98: beta lost souls attacked different -void A_BetaSkullAttack(struct mobj_s *actor); -void A_Stop(struct mobj_s *actor); +void A_BetaSkullAttack(struct mobj_s *); +void A_Stop(struct mobj_s *); // [XA] New mbf21 codepointers -void A_SpawnObject(struct mobj_s *actor); -void A_MonsterProjectile(struct mobj_s *actor); -void A_MonsterBulletAttack(struct mobj_s *actor); -void A_MonsterMeleeAttack(struct mobj_s *actor); -void A_RadiusDamage(struct mobj_s *actor); -void A_NoiseAlert(struct mobj_s *actor); -void A_HealChase(struct mobj_s *actor); -void A_SeekTracer(struct mobj_s *actor); -void A_FindTracer(struct mobj_s *actor); -void A_ClearTracer(struct mobj_s *actor); -void A_JumpIfHealthBelow(struct mobj_s *actor); -void A_JumpIfTargetInSight(struct mobj_s *actor); -void A_JumpIfTargetCloser(struct mobj_s *actor); -void A_JumpIfTracerInSight(struct mobj_s *actor); -void A_JumpIfTracerCloser(struct mobj_s *actor); -void A_JumpIfFlagsSet(struct mobj_s *actor); -void A_AddFlags(struct mobj_s *actor); -void A_RemoveFlags(struct mobj_s *actor); -void A_WeaponProjectile(struct player_s *player, struct pspdef_s *psp); -void A_WeaponBulletAttack(struct player_s *player, struct pspdef_s *psp); -void A_WeaponMeleeAttack(struct player_s *player, struct pspdef_s *psp); -void A_WeaponSound(struct player_s *player, struct pspdef_s *psp); -void A_WeaponAlert(struct player_s *player, struct pspdef_s *psp); -void A_WeaponJump(struct player_s *player, struct pspdef_s *psp); -void A_ConsumeAmmo(struct player_s *player, struct pspdef_s *psp); -void A_CheckAmmo(struct player_s *player, struct pspdef_s *psp); -void A_RefireTo(struct player_s *player, struct pspdef_s *psp); -void A_GunFlashTo(struct player_s *player, struct pspdef_s *psp); +void A_SpawnObject(struct mobj_s *); +void A_MonsterProjectile(struct mobj_s *); +void A_MonsterBulletAttack(struct mobj_s *); +void A_MonsterMeleeAttack(struct mobj_s *); +void A_RadiusDamage(struct mobj_s *); +void A_NoiseAlert(struct mobj_s *); +void A_HealChase(struct mobj_s *); +void A_SeekTracer(struct mobj_s *); +void A_FindTracer(struct mobj_s *); +void A_ClearTracer(struct mobj_s *); +void A_JumpIfHealthBelow(struct mobj_s *); +void A_JumpIfTargetInSight(struct mobj_s *); +void A_JumpIfTargetCloser(struct mobj_s *); +void A_JumpIfTracerInSight(struct mobj_s *); +void A_JumpIfTracerCloser(struct mobj_s *); +void A_JumpIfFlagsSet(struct mobj_s *); +void A_AddFlags(struct mobj_s *); +void A_RemoveFlags(struct mobj_s *); +void A_WeaponProjectile(struct player_s *, struct pspdef_s *); +void A_WeaponBulletAttack(struct player_s *, struct pspdef_s *); +void A_WeaponMeleeAttack(struct player_s *, struct pspdef_s *); +void A_WeaponSound(struct player_s *, struct pspdef_s *); +void A_WeaponAlert(struct player_s *, struct pspdef_s *); +void A_WeaponJump(struct player_s *, struct pspdef_s *); +void A_ConsumeAmmo(struct player_s *, struct pspdef_s *); +void A_CheckAmmo(struct player_s *, struct pspdef_s *); +void A_RefireTo(struct player_s *, struct pspdef_s *); +void A_GunFlashTo(struct player_s *, struct pspdef_s *); #endif diff --git a/src/p_doors.c b/src/p_doors.c index 4d055110b..0fdf752ec 100644 --- a/src/p_doors.c +++ b/src/p_doors.c @@ -41,8 +41,6 @@ // /////////////////////////////////////////////////////////////// -boolean comp_blazing2; // [Nugget] - // // T_VerticalDoor // @@ -176,15 +174,15 @@ void T_VerticalDoor (vldoor_t *door) case doorClose: // Close types do not bounce, merely wait break; - // [Nugget]: [crispy] fix "fast doors reopening with wrong sound" case blazeRaise: case genBlazeRaise: - if (STRICTMODE(!comp_blazing2)) - { - door->direction = 1; - S_StartSound((mobj_t *)&door->sector->soundorg, sfx_bdopn); - break; - } + door->direction = 1; + if (!STRICTMODE_COMP(comp_blazing)) + { + S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn); + break; + } + // fallthrough default: // other types bounce off the obstruction door->direction = 1; diff --git a/src/p_enemy.c b/src/p_enemy.c index e437c5ad0..8df43db12 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -29,10 +29,12 @@ #include "doomstat.h" #include "doomtype.h" #include "g_game.h" +#include "g_umapinfo.h" #include "hu_obituary.h" #include "i_printf.h" #include "i_system.h" #include "info.h" +#include "m_array.h" #include "m_bbox.h" #include "m_fixed.h" #include "m_random.h" @@ -52,7 +54,6 @@ #include "s_sound.h" #include "sounds.h" #include "tables.h" -#include "u_mapinfo.h" #include "z_zone.h" // [Nugget] @@ -348,7 +349,7 @@ static int P_IsUnderDamage(mobj_t *actor) static fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000}; static fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000}; -static boolean P_Move(mobj_t *actor, boolean dropoff) // killough 9/12/98 +static boolean P_Move(mobj_t *actor, int dropoff) // killough 9/12/98 { fixed_t tryx, tryy, deltax, deltay; boolean try_ok; @@ -545,7 +546,7 @@ static boolean P_SmartMove(mobj_t *actor) P_Random(pr_dropoff) < 235) dropoff = 2; - if (!P_Move(actor, !!dropoff)) + if (!P_Move(actor, dropoff)) return false; // killough 9/9/98: avoid crushing ceilings or other damaging areas @@ -2426,52 +2427,70 @@ void A_BossDeath(mobj_t *mo) line_t junk; int i; - // numbossactions == 0 means to use the defaults. - // numbossactions == -1 means to do nothing. - // positive values mean to check the list of boss actions and run all that apply. - if (gamemapinfo && gamemapinfo->numbossactions != 0) + if (gamemapinfo && gamemapinfo->flags & MapInfo_BossActionClear) { - if (gamemapinfo->numbossactions < 0) return; + return; + } - // make sure there is a player alive for victory - for (i=0; i<MAXPLAYERS; i++) - if (playeringame[i] && players[i].health > 0) - break; + if (gamemapinfo && array_size(gamemapinfo->bossactions)) + { + // make sure there is a player alive for victory + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && players[i].health > 0) + { + break; + } + } + if (i == MAXPLAYERS) + { + return; // no one left alive, so do not end game + } - if (i==MAXPLAYERS) - return; // no one left alive, so do not end game + bossaction_t *bossaction; + array_foreach(bossaction, gamemapinfo->bossactions) + { + if (bossaction->type == mo->type) + { + break; + } + } + if (bossaction == array_end(gamemapinfo->bossactions)) + { + return; // no matches found + } - for (i = 0; i < gamemapinfo->numbossactions; i++) + // scan the remaining thinkers to see + // if all bosses are dead + for (th = thinkercap.next; th != &thinkercap; th = th->next) { - if (gamemapinfo->bossactions[i].type == mo->type) - break; + if (th->function.p1 == (actionf_p1)P_MobjThinker) + { + mobj_t *mo2 = (mobj_t *)th; + if (mo2 != mo && mo2->type == mo->type && mo2->health > 0) + { + return; // other boss not dead + } + } } - if (i >= gamemapinfo->numbossactions) - return; // no matches found - // scan the remaining thinkers to see - // if all bosses are dead - for (th = thinkercap.next ; th != &thinkercap ; th=th->next) - if (th->function.p1 == (actionf_p1)P_MobjThinker) - { - mobj_t *mo2 = (mobj_t *) th; - if (mo2 != mo && mo2->type == mo->type && mo2->health > 0) - return; // other boss not dead - } - for (i = 0; i < gamemapinfo->numbossactions; i++) + array_foreach(bossaction, gamemapinfo->bossactions) { - if (gamemapinfo->bossactions[i].type == mo->type) + if (bossaction->type == mo->type) { - junk = *lines; - junk.special = (short)gamemapinfo->bossactions[i].special; - junk.tag = (short)gamemapinfo->bossactions[i].tag; - // use special semantics for line activation to block problem types. - if (!P_UseSpecialLine(mo, &junk, 0, true)) - P_CrossSpecialLine(&junk, 0, mo, true); + junk = *lines; + junk.special = (short)bossaction->special; + junk.tag = (short)bossaction->tag; + // use special semantics for line activation to block problem + // types. + if (!P_UseSpecialLine(mo, &junk, 0, true)) + { + P_CrossSpecialLine(&junk, 0, mo, true); + } } } - return; + return; } if (gamemode == commercial) diff --git a/src/p_inter.c b/src/p_inter.c index eaaf73ff9..36f36e17d 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -772,7 +772,6 @@ static boolean P_NuggetForceGibbing( ) { extern boolean gibbers; // GIBBERS cheat - extern void A_Punch(), A_Saw(), A_FireShotgun2(); if (!casual_play) { return false; } diff --git a/src/p_map.c b/src/p_map.c index 93e019fb2..62c73876a 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1023,7 +1023,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) // // killough 3/15/98: allow dropoff as option -boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean dropoff) +boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, int dropoff) { fixed_t oldx, oldy; diff --git a/src/p_map.h b/src/p_map.h index 19d593095..d48cb82bf 100644 --- a/src/p_map.h +++ b/src/p_map.h @@ -49,7 +49,7 @@ extern boolean comp_lsamnesia; #define CROSSHAIR_AIM 1 // killough 3/15/98: add fourth argument to P_TryMove -boolean P_TryMove(struct mobj_s *thing, fixed_t x, fixed_t y, boolean dropoff); +boolean P_TryMove(struct mobj_s *thing, fixed_t x, fixed_t y, int dropoff); // killough 8/9/98: extra argument for telefragging boolean P_TeleportMove(struct mobj_s *thing, fixed_t x, fixed_t y, boolean boss); diff --git a/src/p_mobj.c b/src/p_mobj.c index d74311cfc..ef6e15374 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1287,8 +1287,6 @@ void P_SpawnPlayer (mapthing_t* mthing) p->momx = p->momy = 0; // killough 10/98: initialize bobbing to 0. - pspr_interp = false; - // setup gun psprite P_SetupPsprites (p); diff --git a/src/p_pspr.c b/src/p_pspr.c index 36dd7497d..e7360a098 100644 --- a/src/p_pspr.c +++ b/src/p_pspr.c @@ -189,22 +189,26 @@ static void P_BringUpWeapon(player_t *player) player->pendingweapon = wp_nochange; + pspdef_t *psp = &player->psprites[ps_weapon]; + // [Nugget] Weapon-switch interruption if (switch_interrupted) { switch_interrupted = false; } else - // killough 12/98: prevent pistol from starting visibly at bottom of screen: - player->psprites[ps_weapon].sy2 = // [Nugget] - player->psprites[ps_weapon].sy = demo_version >= DV_MBF ? - WEAPONBOTTOM+FRACUNIT*2 : WEAPONBOTTOM; + { + // killough 12/98: prevent pistol from starting visibly at bottom of screen: + psp->sy = demo_version >= DV_MBF ? WEAPONBOTTOM + FRACUNIT * 2 : WEAPONBOTTOM; + + psp->sy2 = psp->oldsy2 = psp->sy; + } // [Nugget]: [crispy] squat down weapon sprite - player->psprites[ps_weapon].dy = 0; + psp->dy = 0; // [Nugget] Reset offsets for weapon inertia - player->psprites[ps_weapon].wix = 0; - player->psprites[ps_weapon].wiy = 0; + psp->wix = 0; + psp->wiy = 0; P_SetPsprite(player, ps_weapon, newstate); } @@ -1531,9 +1535,10 @@ void P_MovePsprites(player_t *player) weapon_ready = false; // [Nugget] - // [Nugget] psp[ps_weapon].oldsx2 = psp[ps_weapon].sx2; psp[ps_weapon].oldsy2 = psp[ps_weapon].sy2; + + // [Nugget] psp[ps_weapon].oldwix = psp[ps_weapon].wix; psp[ps_weapon].oldwiy = psp[ps_weapon].wiy; @@ -1606,10 +1611,10 @@ void P_MovePsprites(player_t *player) player->psprites[ps_flash].sx2 = player->psprites[ps_weapon].sx2; player->psprites[ps_flash].sy2 = player->psprites[ps_weapon].sy2; - - // [Nugget] player->psprites[ps_flash].oldsx2 = player->psprites[ps_weapon].oldsx2; player->psprites[ps_flash].oldsy2 = player->psprites[ps_weapon].oldsy2; + + // [Nugget] player->psprites[ps_flash].dy = player->psprites[ps_weapon].dy; player->psprites[ps_flash].wix = player->psprites[ps_weapon].wix; player->psprites[ps_flash].oldwix = player->psprites[ps_weapon].oldwix; diff --git a/src/p_pspr.h b/src/p_pspr.h index 4ded0da29..14564251a 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -98,11 +98,11 @@ typedef struct pspdef_s // [FG] centered weapon sprite fixed_t sx2; fixed_t sy2; + fixed_t oldsx2; + fixed_t oldsy2; // [Nugget] ---------------------------------------------------------------- - fixed_t oldsx2, oldsy2; - // [crispy] squat down weapon sprite fixed_t dy; diff --git a/src/p_saveg.c b/src/p_saveg.c index 63f820416..e3b1d9c59 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -850,12 +850,21 @@ static void saveg_read_pspdef_t(pspdef_t *str) str->sy2 = str->sy; } - // [Nugget] - if (saveg_compat > saveg_woof600) { + str->oldsx2 = str->sx2; + str->oldsy2 = str->sy2; + + // [Nugget] -------------------------------------------------------------- + + if (saveg_compat > saveg_woof600) + { str->dy = saveg_read32(); // fixed_t dy; str->wix = saveg_read32(); // fixed_t wix; str->wiy = saveg_read32(); // fixed_t wiy; - } else { str->dy = str->wix = str->wiy = 0; } + } + else { str->dy = str->wix = str->wiy = 0; } + + str->oldwix = str->wix; + str->oldwiy = str->wiy; } static void saveg_write_pspdef_t(pspdef_t *str) diff --git a/src/p_spec.h b/src/p_spec.h index 6b4ad25e7..956ea787e 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -30,7 +30,6 @@ struct player_s; struct sector_s; // [Nugget] CVARs -extern boolean comp_blazing2; extern boolean comp_manualdoor; extern boolean comp_switchsource; extern boolean comp_keynoway; diff --git a/src/p_tick.c b/src/p_tick.c index 62f78ab31..11c358c79 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -237,7 +237,7 @@ static void P_RunThinkers (void) currentthinker != &thinkercap; currentthinker = currentthinker->next) if (currentthinker->function.p1) - currentthinker->function.p1(currentthinker); + currentthinker->function.p1((mobj_t *)currentthinker); // [crispy] support MUSINFO lump (dynamic music changing) T_MusInfo(); diff --git a/src/params.h b/src/params.h index 9ef1de67e..3bd35b542 100644 --- a/src/params.h +++ b/src/params.h @@ -44,6 +44,7 @@ static const char *params[] = { "-bsp", "-force_old_zdoom_nodes", "-noautoload", +"-noextras", "-nocheats", "-nodeh", "-nomapinfo", diff --git a/src/r_bmaps.c b/src/r_bmaps.c index dd91768a5..314aa3175 100644 --- a/src/r_bmaps.c +++ b/src/r_bmaps.c @@ -29,7 +29,7 @@ #include "m_array.h" #include "m_misc.h" #include "r_data.h" -#include "u_scanner.h" +#include "m_scanner.h" #include "w_wad.h" #include "z_zone.h" @@ -49,40 +49,35 @@ typedef struct byte colormask[COLORMASK_SIZE]; } brightmap_t; -static void ReadColormask(u_scanner_t *s, byte *colormask) +static void ReadColormask(scanner_t *s, byte *colormask) { memset(colormask, 0, COLORMASK_SIZE); do { unsigned int color1 = 0, color2 = 0; - if (U_MustGetInteger(s)) + SC_MustGetToken(s, TK_IntConst); + color1 = SC_GetNumber(s); + if (color1 >= 0 && color1 < COLORMASK_SIZE) { - color1 = s->number; - if (color1 >= 0 && color1 < COLORMASK_SIZE) - { - colormask[color1] = 1; - } + colormask[color1] = 1; } - if (!U_CheckToken(s, '-')) + if (!SC_CheckToken(s, '-')) { continue; } - if (U_MustGetInteger(s)) + SC_MustGetToken(s, TK_IntConst); + color2 = SC_GetNumber(s); + if (color2 >= 0 && color2 < COLORMASK_SIZE) { - color2 = s->number; - if (color2 >= 0 && color2 < COLORMASK_SIZE) + for (int i = color1 + 1; i <= color2; ++i) { - int i; - for (i = color1 + 1; i <= color2; ++i) - { - colormask[i] = 1; - } + colormask[i] = 1; } } - } while (U_CheckToken(s, ',')); + } while (SC_CheckToken(s, ',')); } static brightmap_t *brightmaps_array = NULL; @@ -119,43 +114,50 @@ enum DOOM2ONLY }; -static boolean ParseProperty(u_scanner_t *s, elem_t *elem) +static boolean ParseProperty(scanner_t *s, elem_t *elem) { char *name; int idx; int game = DOOM1AND2; - U_GetString(s); - name = M_StringDuplicate(s->string); - U_MustGetToken(s, TK_Identifier); - idx = GetBrightmap(s->string); + SC_GetNextTokenLumpName(s); + name = M_StringDuplicate(SC_GetString(s)); + SC_MustGetToken(s, TK_Identifier); + idx = GetBrightmap(SC_GetString(s)); if (idx < 0) { - U_Error(s, "brightmap '%s' not found", s->string); + SC_Error(s, "brightmap '%s' not found", SC_GetString(s)); free(name); return false; } - if (U_CheckToken(s, TK_Identifier)) + if (SC_CheckToken(s, TK_Identifier)) { - if (!strcasecmp("DOOM", s->string) || !strcasecmp("DOOM1", s->string)) + if (!strcasecmp("DOOM", SC_GetString(s)) + || !strcasecmp("DOOM1", SC_GetString(s))) { game = DOOM1ONLY; - if (U_CheckToken(s, '|')) + if (SC_CheckToken(s, '|')) { - if (U_MustGetIdentifier(s, "DOOM2")) + SC_MustGetToken(s, TK_Identifier); + if (!strcasecmp("DOOM2", SC_GetString(s))) { game = DOOM1AND2; } + else + { + SC_Error(s, "Expected 'DOOM2' but got '%s' instead.", + SC_GetString(s)); + } } } - else if (!strcasecmp("DOOM2", s->string)) + else if (!strcasecmp("DOOM2", SC_GetString(s))) { game = DOOM2ONLY; } else { - U_Unget(s); + SC_Rewind(s); } } if ((gamemission == doom && game == DOOM2ONLY) @@ -251,10 +253,6 @@ const byte *R_BrightmapForState(const int state) void R_ParseBrightmaps(int lumpnum) { - u_scanner_t *s; - const char *data = W_CacheLumpNum(lumpnum, PU_CACHE); - int length = W_LumpLength(lumpnum); - force_brightmaps = W_IsWADLump(lumpnum); if (!array_size(brightmaps_array)) @@ -265,24 +263,25 @@ void R_ParseBrightmaps(int lumpnum) array_push(brightmaps_array, brightmap); } - s = U_ScanOpen(data, length, "BRGHTMPS"); + scanner_t *s = SC_Open("BRGHTMPS", W_CacheLumpNum(lumpnum, PU_CACHE), + W_LumpLength(lumpnum)); - while (U_HasTokensLeft(s)) + while (SC_TokensLeft(s)) { - if (!U_CheckToken(s, TK_Identifier)) + if (!SC_CheckToken(s, TK_Identifier)) { - U_GetNextToken(s, true); + SC_GetNextToken(s, true); continue; } - if (!strcasecmp("BRIGHTMAP", s->string)) + if (!strcasecmp("BRIGHTMAP", SC_GetString(s))) { brightmap_t brightmap; - U_MustGetToken(s, TK_Identifier); - brightmap.name = M_StringDuplicate(s->string); + SC_MustGetToken(s, TK_Identifier); + brightmap.name = M_StringDuplicate(SC_GetString(s)); ReadColormask(s, brightmap.colormask); array_push(brightmaps_array, brightmap); } - else if (!strcasecmp("TEXTURE", s->string)) + else if (!strcasecmp("TEXTURE", SC_GetString(s))) { elem_t elem; if (ParseProperty(s, &elem)) @@ -290,7 +289,7 @@ void R_ParseBrightmaps(int lumpnum) array_push(textures_bm, elem); } } - else if (!strcasecmp("SPRITE", s->string)) + else if (!strcasecmp("SPRITE", SC_GetString(s))) { elem_t elem; if (ParseProperty(s, &elem)) @@ -307,7 +306,7 @@ void R_ParseBrightmaps(int lumpnum) } } } - else if (!strcasecmp("FLAT", s->string)) + else if (!strcasecmp("FLAT", SC_GetString(s))) { elem_t elem; if (ParseProperty(s, &elem)) @@ -315,29 +314,29 @@ void R_ParseBrightmaps(int lumpnum) array_push(flats_bm, elem); } } - else if (!strcasecmp("STATE", s->string)) + else if (!strcasecmp("STATE", SC_GetString(s))) { elem_t elem; elem.name = NULL; - U_MustGetInteger(s); - elem.num = s->number; + SC_MustGetToken(s, TK_IntConst); + elem.num = SC_GetNumber(s); if (elem.num < 0 || elem.num >= num_states) { - U_Error(s, "state '%d' not found", elem.num); + SC_Error(s, "state '%d' not found", elem.num); } - U_MustGetToken(s, TK_Identifier); - elem.idx = GetBrightmap(s->string); + SC_MustGetToken(s, TK_Identifier); + elem.idx = GetBrightmap(SC_GetString(s)); if (elem.idx >= 0) { array_push(states_bm, elem); } else { - U_Error(s, "brightmap '%s' not found", s->string); + SC_Error(s, "brightmap '%s' not found", SC_GetString(s)); } } } - U_ScanClose(s); + SC_Close(s); brightmaps_found = (array_size(brightmaps_array) > 1); } diff --git a/src/r_data.c b/src/r_data.c index 3cdfa97e0..32193abd1 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -25,7 +25,7 @@ #include <stdlib.h> #include <string.h> -#include "d_main.h" +#include "d_iwad.h" #include "d_think.h" #include "doomdef.h" #include "doomstat.h" @@ -1161,9 +1161,7 @@ void R_InitTranMap(int progress) int p = M_CheckParmWithArgs("-dumptranmap", 1); if (p > 0) { - char *path = malloc(strlen(myargv[p + 1]) + 5); - strcpy(path, myargv[p + 1]); - AddDefaultExtension(path, ".lmp"); + char *path = AddDefaultExtension(myargv[p + 1], ".lmp"); M_WriteFile(path, main_tranmap, 256 * 256); diff --git a/src/r_draw.c b/src/r_draw.c index 81011d60d..c6db31133 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -37,9 +37,6 @@ #include "v_video.h" #include "z_zone.h" -// [Nugget] -#include "m_random.h" - // // All drawing to the view buffer is accomplished in this file. // The other refresh files only know about ccordinates, @@ -342,7 +339,7 @@ static const int fuzzoffset[FUZZTABLE] = FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF, FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF, FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF -}; +}; static int fuzzpos = 0; @@ -373,7 +370,7 @@ void R_SetFuzzPosDraw(void) // i.e. spectres and invisible players. // -static void R_DrawFuzzColumn_orig(void) +static void DrawFuzzColumnOriginal(void) { boolean cutoff = false; @@ -451,7 +448,7 @@ static void R_DrawFuzzColumn_orig(void) static int fuzzblocksize; -static void R_DrawFuzzColumn_block(void) +static void DrawFuzzColumnBlocky(void) { boolean cutoff = false; @@ -491,6 +488,8 @@ static void R_DrawFuzzColumn_block(void) int lines = fuzzblocksize - (dc_yl % fuzzblocksize); + const int fuzzblockwidth = MIN(fuzzblocksize, video.width - dc_x); + do { count -= lines; @@ -509,7 +508,7 @@ static void R_DrawFuzzColumn_block(void) do { - memset(dest, fuzz, fuzzblocksize); + memset(dest, fuzz, fuzzblockwidth); dest += linesize; } while (--lines); @@ -529,117 +528,162 @@ static void R_DrawFuzzColumn_block(void) } } -// [Nugget - ceski] Selective fuzz darkening -// Reference: https://www.doomworld.com/forum/post/1335769 -// /-------------------------------------------------------------------------- - -boolean fuzzdark_mode; +#define FUZZDARK (6 * 256) +#define FUZZPAL 256 -#define FUZZDARK (256 * (Woof_Random() < 32 ? (Woof_Random() & 1 ? 4 : 8) : 6)) -#define FUZZSELECT ((fuzzoffset[fuzzpos] == -FUZZOFF) ? 0 : FUZZDARK) - -static void R_DrawSelectiveFuzzColumn(void) +static const int fuzzdark[FUZZTABLE] = +{ + 4 * FUZZPAL, 0, 6 * FUZZPAL, 0, 6 * FUZZPAL, 6 * FUZZPAL, 0, + 6 * FUZZPAL, 6 * FUZZPAL, 0, 6 * FUZZPAL, 6 * FUZZPAL, 6 * FUZZPAL, 0, + 6 * FUZZPAL, 8 * FUZZPAL, 6 * FUZZPAL, 0, 0, 0, 0, + 4 * FUZZPAL, 0, 0, 6 * FUZZPAL, 6 * FUZZPAL, 6 * FUZZPAL, 6 * FUZZPAL, 0, + 4 * FUZZPAL, 0, 6 * FUZZPAL, 6 * FUZZPAL, 0, 0, 6 * FUZZPAL, + 6 * FUZZPAL, 0, 0, 0, 0, 6 * FUZZPAL, 6 * FUZZPAL, + 6 * FUZZPAL, 6 * FUZZPAL, 0, 6 * FUZZPAL, 6 * FUZZPAL, 0, 6 * FUZZPAL, +}; + +static void DrawFuzzColumnRefraction(void) { - int count; - byte *dest; - boolean cutoff = false; + boolean cutoff = false; - if (fuzzblocksize > 1 && dc_x % fuzzblocksize) - { - return; - } + if (dc_x % fuzzblocksize) + { + return; + } - if (!dc_yl) - dc_yl = 1; + if (!dc_yl) + { + dc_yl = 1; + } - if (dc_yh == viewheight - 1) - { - dc_yh = viewheight - 2; - cutoff = true; - } + if (dc_yh == viewheight - 1) + { + dc_yh = viewheight - 2; + cutoff = true; + } - count = dc_yh - dc_yl; + int count = dc_yh - dc_yl; - if (count < 0) - return; + if (count < 0) + { + return; + } #ifdef RANGECHECK - if (dc_x >= video.width || dc_yl < 0 || dc_yh >= video.height) - I_Error("R_DrawSelectiveFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); + if ((unsigned)dc_x >= video.width || dc_yl < 0 || dc_yh >= video.height) + { + I_Error("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); + } #endif - ++count; - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - int lines = fuzzblocksize - (dc_yl % fuzzblocksize); + ++count; - do - { - count -= lines; + byte *dest = ylookup[dc_yl] + columnofs[dc_x]; - const int mask = count >> (8 * sizeof(mask) - 1); + int lines = fuzzblocksize - (dc_yl % fuzzblocksize); - lines += count & mask; - count &= ~mask; + const int fuzzblockwidth = MIN(fuzzblocksize, video.width - dc_x); - const byte fuzz = fullcolormap[FUZZSELECT + dest[linesize * fuzzoffset[fuzzpos]]]; + int dark = FUZZDARK; + int offset = 0; do { - memset(dest, fuzz, fuzzblocksize); - dest += linesize; - } while (--lines); + count -= lines; - ++fuzzpos; + // if (count < 0) + // { + // lines += count; + // count = 0; + // } + const int mask = count >> (8 * sizeof(mask) - 1); + lines += count & mask; + count &= ~mask; - // Clamp table lookup index. - fuzzpos &= (fuzzpos - FUZZTABLE) >> (8 * sizeof(fuzzpos) - 1); // killough 1/99 + const byte fuzz = fullcolormap[dark + dest[linesize * offset]]; - lines = fuzzblocksize; - } while (count); + do + { + memset(dest, fuzz, fuzzblockwidth); + dest += linesize; + } while (--lines); - if (cutoff) - { - const byte fuzz = fullcolormap[FUZZSELECT + dest[linesize * (fuzzoffset[fuzzpos] - FUZZOFF) / 2]]; + ++fuzzpos; - memset(dest, fuzz, fuzzblocksize); - } -} + // Clamp table lookup index. + fuzzpos &= (fuzzpos - FUZZTABLE) >> (8 * sizeof(fuzzpos) - 1); // killough 1/99 -// [Nugget] -----------------------------------------------------------------/ + dark = fuzzdark[fuzzpos]; + offset = fuzzoffset[fuzzpos]; -// [FG] spectre drawing mode: 0 original, 1 blocky (hires) + lines = fuzzblocksize; + } while (count); -boolean fuzzcolumn_mode; -void (*R_DrawFuzzColumn)(void) = R_DrawFuzzColumn_orig; + if (cutoff) + { + const byte fuzz = + fullcolormap[dark + dest[linesize * (offset - FUZZOFF) / 2]]; + memset(dest, fuzz, fuzzblocksize); + } +} -void R_SetFuzzColumnMode(void) +static void DrawFuzzColumnShadow(void) { - // [Nugget - ceski] Selective fuzz darkening - if (STRICTMODE(fuzzdark_mode)) - { - if (fuzzcolumn_mode && current_video_height > SCREENHEIGHT) - { - fuzzblocksize = FixedToInt(video.yscale); - } - else - { - fuzzblocksize = 1; - } + int count = dc_yh - dc_yl; - R_DrawFuzzColumn = R_DrawSelectiveFuzzColumn; + // Zero length. + if (count < 0) + { return; } - if (fuzzcolumn_mode && current_video_height > SCREENHEIGHT) +#ifdef RANGECHECK + if ((unsigned)dc_x >= video.width || dc_yl < 0 || dc_yh >= video.height) { - fuzzblocksize = FixedToInt(video.yscale); - R_DrawFuzzColumn = R_DrawFuzzColumn_block; + I_Error("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); } - else +#endif + + byte *dest = ylookup[dc_yl] + columnofs[dc_x]; + + count++; // killough 1/99: minor tuning + + do { - R_DrawFuzzColumn = R_DrawFuzzColumn_orig; + *dest = fullcolormap[8 * 256 + *dest]; + + dest += linesize; // killough 11/98 + } while (--count); +} + +fuzzmode_t fuzzmode; +void (*R_DrawFuzzColumn)(void) = DrawFuzzColumnOriginal; + +void R_SetFuzzColumnMode(void) +{ + fuzzmode_t mode = + (strictmode || (netgame && !solonet)) ? FUZZ_BLOCKY : fuzzmode; + + switch (mode) + { + case FUZZ_BLOCKY: + if (current_video_height > SCREENHEIGHT) + { + fuzzblocksize = FixedToInt(video.yscale); + R_DrawFuzzColumn = DrawFuzzColumnBlocky; + } + else + { + R_DrawFuzzColumn = DrawFuzzColumnOriginal; + } + break; + case FUZZ_REFRACTION: + fuzzblocksize = FixedToInt(video.yscale); + R_DrawFuzzColumn = DrawFuzzColumnRefraction; + break; + case FUZZ_SHADOW: + R_DrawFuzzColumn = DrawFuzzColumnShadow; + break; } } diff --git a/src/r_draw.h b/src/r_draw.h index b6602fb46..951d18f29 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -48,7 +48,14 @@ void R_SetFuzzPosTic(void); void R_SetFuzzPosDraw(void); // [FG] spectre drawing mode -extern boolean fuzzcolumn_mode; +typedef enum +{ + FUZZ_BLOCKY, + FUZZ_REFRACTION, + FUZZ_SHADOW, +} fuzzmode_t; + +extern fuzzmode_t fuzzmode; void R_SetFuzzColumnMode(void); // [Nugget - ceski] Selective fuzz darkening diff --git a/src/r_main.c b/src/r_main.c index 7f3e136ad..bec9ad87f 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1037,12 +1037,9 @@ void R_ExecuteSetViewSize (void) } } - // [crispy] forcefully initialize the status bar backing screen - // [Nugget] Unless the alt. intermission background is enabled + // [Nugget] Alt. intermission background if (!WI_UsingAltInterpic()) ST_refreshBackground(); // [Nugget] NUGHUD - - /*pspr_interp = false;*/ // [Nugget] New weapon interpolation: don't need this } // @@ -1879,22 +1876,19 @@ void R_BindRenderVariables(void) // [Nugget] (CFG-only) BIND_BOOL(no_killough_face, false, "Disable the Killough-face easter egg"); - BIND_NUM(screenblocks, 10, 3, 12, "Size of game-world screen"); + BIND_NUM(screenblocks, 10, 3, UL, "Size of game-world screen"); M_BindBool("translucency", &translucency, NULL, true, ss_gen, wad_yes, "Translucency for some things"); M_BindNum("tran_filter_pct", &tran_filter_pct, NULL, - 66, 0, 100, ss_gen, wad_yes, + 66, 0, 100, ss_none, wad_yes, "Percent of foreground/background translucency mix"); M_BindBool("flipcorpses", &flipcorpses, NULL, false, ss_enem, wad_no, "Randomly mirrored death animations"); - M_BindBool("fuzzcolumn_mode", &fuzzcolumn_mode, NULL, true, ss_enem, wad_no, // [Nugget] Restored menu item - "Fuzz rendering (0 = Resolution-dependent; 1 = Blocky)"); - - // [Nugget - ceski] Selective fuzz darkening - M_BindBool("fuzzdark_mode", &fuzzdark_mode, NULL, false, ss_enem, wad_no, - "Selective fuzz darkening"); + M_BindNum("fuzzmode", &fuzzmode, NULL, + FUZZ_BLOCKY, FUZZ_BLOCKY, FUZZ_SHADOW, ss_none, wad_no, + "Partial Invisibility (0 = Vanilla; 1 = Refraction; 2 = Shadow)"); BIND_BOOL(draw_nearby_sprites, true, "Draw sprites overlapping into visible sectors"); diff --git a/src/r_plane.c b/src/r_plane.c index bdc14a63e..8008192cf 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -39,6 +39,7 @@ #include "doomstat.h" #include "doomtype.h" #include "i_system.h" +#include "i_video.h" #include "m_fixed.h" #include "r_bmaps.h" // [crispy] R_BrightmapForTexName() #include "r_data.h" @@ -419,9 +420,21 @@ static void DrawSkyTex(visplane_t *pl, skytex_t *skytex) dc_texheight = textureheight[texture] >> FRACBITS; dc_iscale = FixedMul(skyiscale, skytex->scaley); - dc_texturemid += skytex->curry; + fixed_t deltax, deltay; + if (uncapped && leveltime > oldleveltime) + { + deltax = LerpFixed(skytex->prevx, skytex->currx); + deltay = LerpFixed(skytex->prevy, skytex->curry); + } + else + { + deltax = skytex->currx; + deltay = skytex->curry; + } + + dc_texturemid += deltay; - angle_t an = viewangle + FixedToAngle(skytex->currx); + angle_t an = viewangle + (deltax << (ANGLETOSKYSHIFT - FRACBITS)); for (int x = pl->minx; x <= pl->maxx; x++) { diff --git a/src/r_sky.c b/src/r_sky.c index 8aaf4b920..b190ae558 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -178,12 +178,16 @@ void R_UpdateSky(void) } skytex_t *background = &sky->skytex; + background->prevx = background->currx; + background->prevy = background->curry; background->currx += background->scrollx; background->curry += background->scrolly; if (sky->type == SkyType_WithForeground) { skytex_t *foreground = &sky->foreground; + foreground->prevx = foreground->currx; + foreground->prevy = foreground->curry; foreground->currx += foreground->scrollx; foreground->curry += foreground->scrolly; } diff --git a/src/r_skydefs.c b/src/r_skydefs.c index 5f00ff622..e075c5c18 100644 --- a/src/r_skydefs.c +++ b/src/r_skydefs.c @@ -50,6 +50,7 @@ static boolean ParseSkyTex(json_t *json, skytex_t *out) json_t *name = JS_GetObject(json, "name"); if (!JS_IsString(name)) { + out->name = "-"; // no texture return false; } out->name = M_StringDuplicate(JS_GetString(name)); diff --git a/src/r_skydefs.h b/src/r_skydefs.h index 0f20b3cff..c4d548108 100644 --- a/src/r_skydefs.h +++ b/src/r_skydefs.h @@ -37,8 +37,10 @@ typedef struct double mid; fixed_t scrollx; fixed_t currx; + fixed_t prevx; fixed_t scrolly; fixed_t curry; + fixed_t prevy; fixed_t scalex; fixed_t scaley; } skytex_t; diff --git a/src/r_things.c b/src/r_things.c index cb6b9bb25..ced6e2848 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -143,6 +143,11 @@ void R_InitSpritesRes(void) static void R_InstallSpriteLump(int lump, unsigned frame, unsigned rotation, boolean flipped) { + if (frame == '^' - 'A') + { + frame = '\\' - 'A'; + } + if (frame >= MAX_SPRITE_FRAMES || rotation > 8) I_Error("R_InstallSpriteLump: Bad frame characters in lump %i", lump); @@ -835,8 +840,6 @@ void R_NearbySprites (void) // R_DrawPSprite // -boolean pspr_interp = true; // weapon bobbing interpolation - void R_DrawPSprite (pspdef_t *psp, boolean translucent) // [Nugget] Translucent flashes { fixed_t tx; @@ -869,30 +872,29 @@ void R_DrawPSprite (pspdef_t *psp, boolean translucent) // [Nugget] Translucent lump = sprframe->lump[0]; flip = (boolean) sprframe->flip[0]; - // [Nugget] New interpolation /--------------------------------------------- + fixed_t sx2, sy2; - fixed_t sx2, sy2, wix, wiy; + fixed_t wix, wiy; // [Nugget] - if (uncapped && oldleveltime < leveltime && pspr_interp) + if (uncapped && oldleveltime < leveltime) { sx2 = LerpFixed(psp->oldsx2, psp->sx2); sy2 = LerpFixed(psp->oldsy2, psp->sy2); + wix = LerpFixed(psp->oldwix, psp->wix); wiy = LerpFixed(psp->oldwiy, psp->wiy); } - else { - pspr_interp = true; - + else + { sx2 = psp->sx2; sy2 = psp->sy2; + wix = psp->wix; wiy = psp->wiy; } - // [Nugget] ---------------------------------------------------------------/ - // calculate edges of the shape - tx = sx2-160*FRACUNIT; // [FG] centered weapon sprite + tx = sx2 - 160*FRACUNIT; // [FG] centered weapon sprite // [Nugget] Weapon inertia | Flip levels if (STRICTMODE(weapon_inertia)) @@ -919,10 +921,11 @@ void R_DrawPSprite (pspdef_t *psp, boolean translucent) // [Nugget] Translucent // killough 12/98: fix psprite positioning problem vis->texturemid = (BASEYCENTER<<FRACBITS) /* + FRACUNIT/2 */ - - (sy2-spritetopoffset[lump]) // [FG] centered weapon sprite - // [Nugget] - - (STRICTMODE(weapon_inertia) ? wiy : 0) // Weapon inertia - + MIN(0, R_GetFOVFX(FOVFX_ZOOM) * FRACUNIT/2); // Lower weapon based on zoom + (sy2 - spritetopoffset[lump]); // [FG] centered weapon sprite + + // [Nugget] + vis->texturemid += (STRICTMODE(weapon_inertia) ? -wiy : 0) // Weapon inertia + + MIN(0, R_GetFOVFX(FOVFX_ZOOM) * FRACUNIT/2); // Lower weapon based on zoom vis->x1 = x1 < 0 ? 0 : x1; vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; @@ -965,8 +968,6 @@ void R_DrawPSprite (pspdef_t *psp, boolean translucent) // [Nugget] Translucent // [Nugget] Translucent flashes vis->tranmap = translucent ? R_GetGenericTranMap(pspr_translucency_pct) : NULL; - // [Nugget] Removed old interpolation code - // [crispy] free look vis->texturemid += (centery - viewheight/2) * pspriteiscale - (STRICTMODE(ST_GetNughudOn()) ? nughud.weapheight*FRACUNIT : 0); // [Nugget] NUGHUD diff --git a/src/r_things.h b/src/r_things.h index f85d45a02..40321c554 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -39,7 +39,6 @@ extern int64_t sprtopscreen; // [FG] 64-bit integer math extern fixed_t pspritescale; extern fixed_t pspriteiscale; -extern boolean pspr_interp; // weapon bobbing interpolation extern boolean flipcorpses; extern lighttable_t **spritelights; diff --git a/src/s_musinfo.c b/src/s_musinfo.c index d3cea70f1..01cdcacd5 100644 --- a/src/s_musinfo.c +++ b/src/s_musinfo.c @@ -23,11 +23,11 @@ #include "s_musinfo.h" #include "doomtype.h" -#include "g_game.h" +#include "g_umapinfo.h" #include "i_printf.h" #include "p_mobj.h" #include "s_sound.h" -#include "u_scanner.h" +#include "m_scanner.h" #include "w_wad.h" #include "z_zone.h" @@ -40,51 +40,47 @@ musinfo_t musinfo = {0}; void S_ParseMusInfo(const char *mapid) { - u_scanner_t *s; - int num, lumpnum; - - lumpnum = W_CheckNumForName("MUSINFO"); - + int lumpnum = W_CheckNumForName("MUSINFO"); if (lumpnum < 0) { return; } - s = U_ScanOpen(W_CacheLumpNum(lumpnum, PU_CACHE), W_LumpLength(lumpnum), - "MUSINFO"); + scanner_t *s = SC_Open("MUSINFO", W_CacheLumpNum(lumpnum, PU_CACHE), + W_LumpLength(lumpnum)); - while (U_HasTokensLeft(s)) + while (SC_TokensLeft(s)) { - if (U_CheckToken(s, TK_Identifier)) + if (SC_CheckToken(s, TK_Identifier)) { - if (!strcasecmp(s->string, mapid)) + if (!strcasecmp(SC_GetString(s), mapid)) { break; } } else { - U_GetNextLineToken(s); + SC_GetNextLineToken(s); } } - while (U_HasTokensLeft(s)) + while (SC_TokensLeft(s)) { - if (U_CheckToken(s, TK_Identifier)) + if (SC_CheckToken(s, TK_Identifier)) { - if (G_ValidateMapName(s->string, NULL, NULL)) + if (G_ValidateMapName(SC_GetString(s), NULL, NULL)) { break; } } - else if (U_CheckInteger(s)) + else if (SC_CheckToken(s, TK_IntConst)) { - num = s->number; + int num = SC_GetNumber(s); // Check number in range if (num > 0 && num < MAX_MUS_ENTRIES) { - U_GetString(s); - lumpnum = W_CheckNumForName(s->string); + SC_GetNextTokenLumpName(s); + lumpnum = W_CheckNumForName(SC_GetString(s)); if (lumpnum > 0) { musinfo.items[num] = lumpnum; @@ -92,7 +88,7 @@ void S_ParseMusInfo(const char *mapid) else { I_Printf(VB_WARNING, "S_ParseMusInfo: Unknown MUS lump %s", - s->string); + SC_GetString(s)); } } else @@ -104,11 +100,11 @@ void S_ParseMusInfo(const char *mapid) } else { - U_GetNextLineToken(s); + SC_GetNextLineToken(s); } } - U_ScanClose(s); + SC_Close(s); } void T_MusInfo(void) diff --git a/src/s_sound.c b/src/s_sound.c index e36982b0f..e15c8c085 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -24,6 +24,7 @@ #include "doomdef.h" #include "doomstat.h" +#include "g_umapinfo.h" #include "i_printf.h" #include "i_rumble.h" #include "i_sound.h" @@ -36,7 +37,6 @@ #include "s_sound.h" #include "s_trakinfo.h" #include "sounds.h" -#include "u_mapinfo.h" #include "w_wad.h" #include "z_zone.h" diff --git a/src/s_trakinfo.c b/src/s_trakinfo.c index 903b81ecb..bb9c14b95 100644 --- a/src/s_trakinfo.c +++ b/src/s_trakinfo.c @@ -36,6 +36,10 @@ static trakinfo_t *trakinfo; void S_ParseTrakInfo(int lumpnum) { json_t *json = JS_OpenOptions(lumpnum, true); + if (!json) + { + return; + } json_obj_iter_t *iter = JS_ObjectIterator(json); diff --git a/src/sounds.c b/src/sounds.c index 1e7f71eb0..2c8365581 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -155,7 +155,7 @@ sfxinfo_t original_S_sfx[NUMSFX] = { SOUND("stnmov", sg_none, 119), SOUND("swtchn", sg_none, 78), SOUND("swtchx", sg_none, 78), - SOUND("plpain", sg_none, 96), + SOUND("plpain", sg_oof, 96), SOUND("dmpain", sg_none, 96), SOUND("popain", sg_none, 96), SOUND("vipain", sg_none, 96), diff --git a/src/st_carousel.c b/src/st_carousel.c index 30a7ff86e..cbcaa6c37 100644 --- a/src/st_carousel.c +++ b/src/st_carousel.c @@ -13,6 +13,7 @@ #include <math.h> +#include "d_items.h" #include "d_player.h" #include "doomdef.h" #include "doomtype.h" @@ -176,8 +177,17 @@ void ST_UpdateCarousel(player_t *player) static void DrawIcon(int x, int y, sbarelem_t *elem, weapon_icon_t icon) { char lump[9] = {0}; - M_snprintf(lump, sizeof(lump), "%s%d", names[icon.weapon], - icon.state == wpi_selected); + const char *name; + if (weaponinfo[icon.weapon].carouselicon) + { + name = weaponinfo[icon.weapon].carouselicon; + } + else + { + name = names[icon.weapon]; + } + + M_snprintf(lump, sizeof(lump), "%s%d", name, icon.state == wpi_selected); patch_t *patch = V_CachePatchName(lump, PU_CACHE); diff --git a/src/st_stuff.c b/src/st_stuff.c index 2ae3b6e21..cfdc1d3cc 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -59,11 +59,15 @@ #include "z_zone.h" // [Nugget] +#include "mn_internal.h" #include "m_nughud.h" #include "sounds.h" // [Nugget] /================================================================= +static sbardef_t *normal_sbardef = NULL, + *nughud_sbardef = NULL; // NUGHUD + static patch_t *stbersrk; static int lu_berserk; @@ -84,14 +88,7 @@ boolean no_radsuit_tint; boolean comp_godface; boolean comp_unusedpals; -typedef enum hudtype_s -{ - HUDTYPE_SBARDEF, - HUDTYPE_NUGHUD -} hudtype_t; - -static hudtype_t hud_type; - +static boolean use_nughud; static boolean hud_blink_keys; static boolean sts_show_berserk; int force_carousel; @@ -141,7 +138,11 @@ boolean ST_GetNughudOn(void) static void UpdateNughudOn(void) { - st_nughud = screenblocks == 11 && hud_type == HUDTYPE_NUGHUD && automap_off; + // If we have no proper status bars (e.g. SBARDEF is empty), + // use NUGHUD when `screenblocks == 11` + st_nughud = automap_off + && ( ( normal_sbardef && screenblocks == maxscreenblocks - 1 && use_nughud) + || (!normal_sbardef && screenblocks == 11)); } static sbarelem_t *nughud_health_elem = NULL, @@ -1189,13 +1190,23 @@ static void UpdateStatusBar(player_t *player) int barindex = MAX(screenblocks - 10, 0); + // [Nugget] NUGHUD + if (st_nughud) + { + barindex = -2; + } + else + + if (barindex >= array_size(sbardef->statusbars)) + { + barindex = array_size(sbardef->statusbars) - 1; + } + if (automapactive == AM_FULL && automapoverlay == AM_OVERLAY_OFF) { barindex = 0; } - if (st_nughud) { barindex = 3; } // [Nugget] NUGHUD - if (oldbarindex != barindex) { st_ammo_elem = NULL; // [Nugget] @@ -2208,11 +2219,6 @@ void ST_Drawer(void) } DrawStatusBar(); - - if (hud_crosshair_on) // [Nugget] Crosshair toggle - { - HU_DrawCrosshair(); - } } void ST_Start(void) @@ -2241,13 +2247,12 @@ void ST_Init(void) static boolean firsttime = true; - static sbardef_t *normal_sbardef = NULL, *nughud_sbardef = NULL; - if (firsttime) { normal_sbardef = ST_ParseSbarDef(); nughud_sbardef = CreateNughudSbarDef(); + ST_StatusbarList(); // Calculate `maxscreenblocks` UpdateNughudOn(); } @@ -2379,6 +2384,44 @@ void ST_InitRes(void) st_bar = Z_Malloc((video.pitch * V_ScaleY(stbar_height)) * sizeof(*st_bar), PU_RENDERER, 0); } +const char **ST_StatusbarList(void) +{ + // [Nugget] Use `normal_sbardef`; calculate `maxscreenblocks` here + + if (!normal_sbardef) + { + maxscreenblocks = 11; // [Nugget] NUGHUD + return NULL; + } + + maxscreenblocks = 10; + + static const char **strings; + + if (array_size(strings)) + { + maxscreenblocks += array_size(strings) - 1; + return strings; + } + + statusbar_t *item; + array_foreach(item, normal_sbardef->statusbars) + { + if (item->fullscreenrender) + { + array_push(strings, "Fullscreen"); + } + else + { + array_push(strings, "Status Bar"); + } + } + + maxscreenblocks += array_size(strings) - 1; + + return strings; +} + void ST_ResetPalette(void) { I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); @@ -3701,16 +3744,15 @@ static sbardef_t *CreateNughudSbarDef(void) void ST_BindSTSVariables(void) { // [Nugget] NUGHUD - M_BindNum("fullscreen_hud_type", &hud_type, NULL, - HUDTYPE_SBARDEF, HUDTYPE_SBARDEF, HUDTYPE_NUGHUD, - ss_stat, wad_no, "Fullscreen HUD type (0 = SBARDEF; 1 = NUGHUD)"); + M_BindBool("use_nughud", &use_nughud, NULL, + true, ss_stat, wad_no, "Replace second-to-last HUD with NUGHUD"); M_BindNum("st_layout", &st_layout, NULL, st_wide, st_original, st_wide, ss_stat, wad_no, "HUD layout"); M_BindBool("sts_colored_numbers", &sts_colored_numbers, NULL, false, ss_stat, wad_yes, "Colored numbers on the status bar"); M_BindBool("sts_pct_always_gray", &sts_pct_always_gray, NULL, - false, ss_stat, wad_yes, + false, ss_none, wad_yes, "Percent signs on the status bar are always gray"); M_BindBool("st_solidbackground", &st_solidbackground, NULL, false, ss_stat, wad_no, diff --git a/src/st_stuff.h b/src/st_stuff.h index 23db5439e..b91fe6f90 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -111,6 +111,8 @@ extern struct patch_s **hu_font; void WI_UpdateWidgets(void); void WI_DrawWidgets(void); +const char **ST_StatusbarList(void); + void ST_BindSTSVariables(void); #endif diff --git a/src/st_widgets.c b/src/st_widgets.c index 9dc57854b..b3a4b8960 100644 --- a/src/st_widgets.c +++ b/src/st_widgets.c @@ -24,6 +24,7 @@ #include "doomstat.h" #include "doomtype.h" #include "dstrings.h" +#include "g_umapinfo.h" #include "hu_command.h" #include "hu_coordinates.h" #include "hu_obituary.h" @@ -41,7 +42,6 @@ #include "sounds.h" #include "st_sbardef.h" #include "st_stuff.h" -#include "u_mapinfo.h" #include "v_video.h" // [Nugget] @@ -850,10 +850,11 @@ void ST_ResetTitle(void) s = gamemapinfo->mapname; } - if (s == gamemapinfo->mapname || U_CheckField(s)) + if (!(gamemapinfo->flags & MapInfo_LabelClear)) { M_snprintf(string, sizeof(string), "%s: ", s); } + s = gamemapinfo->levelname; } else if (gamestate == GS_LEVEL) @@ -902,7 +903,7 @@ void ST_ResetTitle(void) announce_string[0] = '\0'; if (hud_map_announce && leveltime == 0) { - if (gamemapinfo && U_CheckField(gamemapinfo->author)) + if (gamemapinfo && gamemapinfo->author) { M_snprintf(announce_string, sizeof(announce_string), "%s by %s", string, gamemapinfo->author); diff --git a/src/u_mapinfo.c b/src/u_mapinfo.c deleted file mode 100644 index 78c892450..000000000 --- a/src/u_mapinfo.c +++ /dev/null @@ -1,888 +0,0 @@ -//----------------------------------------------------------------------------- -// -// Copyright 2017 Christoph Oelckers -// Copyright 2019 Fernando Carmona Varo -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT 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, see http://www.gnu.org/licenses/ -// -//----------------------------------------------------------------------------- - -#include <stdlib.h> -#include <string.h> - -#include "doomdef.h" -#include "doomstat.h" -#include "doomtype.h" -#include "i_system.h" -#include "m_array.h" -#include "m_misc.h" -#include "u_mapinfo.h" -#include "u_scanner.h" -#include "w_wad.h" -#include "z_zone.h" - -void M_AddEpisode(const char *map, const char *gfx, const char *txt, - const char *alpha); -void M_ClearEpisodes(void); - -int G_ValidateMapName(const char *mapname, int *pEpi, int *pMap); - -umapinfo_t U_mapinfo; - -umapinfo_t default_mapinfo; - -static level_t *secretlevels; - -static const char *const ActorNames[] = -{ - "DoomPlayer", "ZombieMan", "ShotgunGuy", "Archvile", "ArchvileFire", - "Revenant", "RevenantTracer", "RevenantTracerSmoke", "Fatso", "FatShot", - "ChaingunGuy", "DoomImp", "Demon", "Spectre", "Cacodemon", "BaronOfHell", - "BaronBall", "HellKnight", "LostSoul", "SpiderMastermind", "Arachnotron", - "Cyberdemon", "PainElemental", "WolfensteinSS", "CommanderKeen", - "BossBrain", "BossEye", "BossTarget", "SpawnShot", "SpawnFire", - "ExplosiveBarrel", "DoomImpBall", "CacodemonBall", "Rocket", "PlasmaBall", - "BFGBall", "ArachnotronPlasma", "BulletPuff", "Blood", "TeleportFog", - "ItemFog", "TeleportDest", "BFGExtra", "GreenArmor", "BlueArmor", - "HealthBonus", "ArmorBonus", "BlueCard", "RedCard", "YellowCard", - "YellowSkull", "RedSkull", "BlueSkull", "Stimpack", "Medikit", "Soulsphere", - "InvulnerabilitySphere", "Berserk", "BlurSphere", "RadSuit", "Allmap", - "Infrared", "Megasphere", "Clip", "ClipBox", "RocketAmmo", "RocketBox", - "Cell", "CellPack", "Shell", "ShellBox", "Backpack", "BFG9000", "Chaingun", - "Chainsaw", "RocketLauncher", "PlasmaRifle", "Shotgun", "SuperShotgun", - "TechLamp", "TechLamp2", "Column", "TallGreenColumn", "ShortGreenColumn", - "TallRedColumn", "ShortRedColumn", "SkullColumn", "HeartColumn", "EvilEye", - "FloatingSkull", "TorchTree", "BlueTorch", "GreenTorch", "RedTorch", - "ShortBlueTorch", "ShortGreenTorch", "ShortRedTorch", "Stalagtite", - "TechPillar", "CandleStick", "Candelabra", "BloodyTwitch", "Meat2", "Meat3", - "Meat4", "Meat5", "NonsolidMeat2", "NonsolidMeat4", "NonsolidMeat3", - "NonsolidMeat5", "NonsolidTwitch", "DeadCacodemon", "DeadMarine", - "DeadZombieMan", "DeadDemon", "DeadLostSoul", "DeadDoomImp", - "DeadShotgunGuy", "GibbedMarine", "GibbedMarineExtra", "HeadsOnAStick", - "Gibs", "HeadOnAStick", "HeadCandles", "DeadStick", "LiveStick", "BigTree", - "BurningBarrel", "HangNoGuts", "HangBNoBrain", "HangTLookingDown", - "HangTSkull", "HangTLookingUp", "HangTNoBrain", "ColonGibs", - "SmallBloodPool", "BrainStem", - // Boom/MBF additions - "PointPusher", "PointPuller", "MBFHelperDog", "PlasmaBall1", "PlasmaBall2", - "EvilSceptre", "UnholyBible", "MusicChanger", "Deh_Actor_145", - "Deh_Actor_146", "Deh_Actor_147", "Deh_Actor_148", "Deh_Actor_149", - // DEHEXTRA Actors start here - "Deh_Actor_150", // Extra thing 0 - "Deh_Actor_151", // Extra thing 1 - "Deh_Actor_152", // Extra thing 2 - "Deh_Actor_153", // Extra thing 3 - "Deh_Actor_154", // Extra thing 4 - "Deh_Actor_155", // Extra thing 5 - "Deh_Actor_156", // Extra thing 6 - "Deh_Actor_157", // Extra thing 7 - "Deh_Actor_158", // Extra thing 8 - "Deh_Actor_159", // Extra thing 9 - "Deh_Actor_160", // Extra thing 10 - "Deh_Actor_161", // Extra thing 11 - "Deh_Actor_162", // Extra thing 12 - "Deh_Actor_163", // Extra thing 13 - "Deh_Actor_164", // Extra thing 14 - "Deh_Actor_165", // Extra thing 15 - "Deh_Actor_166", // Extra thing 16 - "Deh_Actor_167", // Extra thing 17 - "Deh_Actor_168", // Extra thing 18 - "Deh_Actor_169", // Extra thing 19 - "Deh_Actor_170", // Extra thing 20 - "Deh_Actor_171", // Extra thing 21 - "Deh_Actor_172", // Extra thing 22 - "Deh_Actor_173", // Extra thing 23 - "Deh_Actor_174", // Extra thing 24 - "Deh_Actor_175", // Extra thing 25 - "Deh_Actor_176", // Extra thing 26 - "Deh_Actor_177", // Extra thing 27 - "Deh_Actor_178", // Extra thing 28 - "Deh_Actor_179", // Extra thing 29 - "Deh_Actor_180", // Extra thing 30 - "Deh_Actor_181", // Extra thing 31 - "Deh_Actor_182", // Extra thing 32 - "Deh_Actor_183", // Extra thing 33 - "Deh_Actor_184", // Extra thing 34 - "Deh_Actor_185", // Extra thing 35 - "Deh_Actor_186", // Extra thing 36 - "Deh_Actor_187", // Extra thing 37 - "Deh_Actor_188", // Extra thing 38 - "Deh_Actor_189", // Extra thing 39 - "Deh_Actor_190", // Extra thing 40 - "Deh_Actor_191", // Extra thing 41 - "Deh_Actor_192", // Extra thing 42 - "Deh_Actor_193", // Extra thing 43 - "Deh_Actor_194", // Extra thing 44 - "Deh_Actor_195", // Extra thing 45 - "Deh_Actor_196", // Extra thing 46 - "Deh_Actor_197", // Extra thing 47 - "Deh_Actor_198", // Extra thing 48 - "Deh_Actor_199", // Extra thing 49 - "Deh_Actor_200", // Extra thing 50 - "Deh_Actor_201", // Extra thing 51 - "Deh_Actor_202", // Extra thing 52 - "Deh_Actor_203", // Extra thing 53 - "Deh_Actor_204", // Extra thing 54 - "Deh_Actor_205", // Extra thing 55 - "Deh_Actor_206", // Extra thing 56 - "Deh_Actor_207", // Extra thing 57 - "Deh_Actor_208", // Extra thing 58 - "Deh_Actor_209", // Extra thing 59 - "Deh_Actor_210", // Extra thing 60 - "Deh_Actor_211", // Extra thing 61 - "Deh_Actor_212", // Extra thing 62 - "Deh_Actor_213", // Extra thing 63 - "Deh_Actor_214", // Extra thing 64 - "Deh_Actor_215", // Extra thing 65 - "Deh_Actor_216", // Extra thing 66 - "Deh_Actor_217", // Extra thing 67 - "Deh_Actor_218", // Extra thing 68 - "Deh_Actor_219", // Extra thing 69 - "Deh_Actor_220", // Extra thing 70 - "Deh_Actor_221", // Extra thing 71 - "Deh_Actor_222", // Extra thing 72 - "Deh_Actor_223", // Extra thing 73 - "Deh_Actor_224", // Extra thing 74 - "Deh_Actor_225", // Extra thing 75 - "Deh_Actor_226", // Extra thing 76 - "Deh_Actor_227", // Extra thing 77 - "Deh_Actor_228", // Extra thing 78 - "Deh_Actor_229", // Extra thing 79 - "Deh_Actor_230", // Extra thing 80 - "Deh_Actor_231", // Extra thing 81 - "Deh_Actor_232", // Extra thing 82 - "Deh_Actor_233", // Extra thing 83 - "Deh_Actor_234", // Extra thing 84 - "Deh_Actor_235", // Extra thing 85 - "Deh_Actor_236", // Extra thing 86 - "Deh_Actor_237", // Extra thing 87 - "Deh_Actor_238", // Extra thing 88 - "Deh_Actor_239", // Extra thing 89 - "Deh_Actor_240", // Extra thing 90 - "Deh_Actor_241", // Extra thing 91 - "Deh_Actor_242", // Extra thing 92 - "Deh_Actor_243", // Extra thing 93 - "Deh_Actor_244", // Extra thing 94 - "Deh_Actor_245", // Extra thing 95 - "Deh_Actor_246", // Extra thing 96 - "Deh_Actor_247", // Extra thing 97 - "Deh_Actor_248", // Extra thing 98 - "Deh_Actor_249", // Extra thing 99 - NULL}; - -static void FreeMap(mapentry_t *mape) -{ - if (mape->mapname) - { - free(mape->mapname); - } - if (mape->levelname) - { - free(mape->levelname); - } - if (mape->label) - { - free(mape->label); - } - if (mape->intertext) - { - free(mape->intertext); - } - if (mape->intertextsecret) - { - free(mape->intertextsecret); - } - if (mape->author) - { - free(mape->author); - } - mape->mapname = NULL; -} - -static void ReplaceString(char **pptr, const char *newstring) -{ - if (*pptr != NULL) - { - free(*pptr); - } - *pptr = strdup(newstring); -} - -static void UpdateMapEntry(mapentry_t *mape, mapentry_t *newe) -{ - if (newe->mapname) - { - ReplaceString(&mape->mapname, newe->mapname); - } - if (newe->levelname) - { - ReplaceString(&mape->levelname, newe->levelname); - } - if (newe->label) - { - ReplaceString(&mape->label, newe->label); - } - if (newe->author) - { - ReplaceString(&mape->author, newe->author); - } - if (newe->intertext) - { - ReplaceString(&mape->intertext, newe->intertext); - } - if (newe->intertextsecret) - { - ReplaceString(&mape->intertextsecret, newe->intertextsecret); - } - if (newe->levelpic[0]) - { - strcpy(mape->levelpic, newe->levelpic); - } - if (newe->nextmap[0]) - { - strcpy(mape->nextmap, newe->nextmap); - } - if (newe->nextsecret[0]) - { - strcpy(mape->nextsecret, newe->nextsecret); - } - if (newe->music[0]) - { - strcpy(mape->music, newe->music); - } - if (newe->skytexture[0]) - { - strcpy(mape->skytexture, newe->skytexture); - } - if (newe->endpic[0]) - { - strcpy(mape->endpic, newe->endpic); - } - if (newe->exitpic[0]) - { - strcpy(mape->exitpic, newe->exitpic); - } - if (newe->enterpic[0]) - { - strcpy(mape->enterpic, newe->enterpic); - } - if (newe->exitanim[0]) - { - strcpy(mape->exitanim, newe->exitanim); - } - if (newe->enteranim[0]) - { - strcpy(mape->enteranim, newe->enteranim); - } - if (newe->interbackdrop[0]) - { - strcpy(mape->interbackdrop, newe->interbackdrop); - } - if (newe->intermusic[0]) - { - strcpy(mape->intermusic, newe->intermusic); - } - if (newe->partime) - { - mape->partime = newe->partime; - } - if (newe->nointermission) - { - mape->nointermission = newe->nointermission; - } - if (newe->numbossactions) - { - mape->numbossactions = newe->numbossactions; - if (mape->numbossactions == -1) - { - if (mape->bossactions) - { - free(mape->bossactions); - } - mape->bossactions = NULL; - } - else - { - mape->bossactions = realloc(mape->bossactions, - sizeof(bossaction_t) * mape->numbossactions); - memcpy(mape->bossactions, newe->bossactions, - sizeof(bossaction_t) * mape->numbossactions); - } - } -} - -// ----------------------------------------------- -// Parses a set of string and concatenates them -// Returns a pointer to the string (must be freed) -// ----------------------------------------------- -static char *ParseMultiString(u_scanner_t *s, int error) -{ - char *build = NULL; - - if (U_CheckToken(s, TK_Identifier)) - { - if (!strcasecmp(s->string, "clear")) - { - // this was explicitly deleted to override the default. - return strdup("-"); - } - else - { - U_Error(s, "Either 'clear' or string constant expected"); - } - } - - do - { - U_MustGetToken(s, TK_StringConst); - if (build == NULL) - { - build = strdup(s->string); - } - else - { - // plus room for one \n and one \0 - size_t newlen = strlen(build) + strlen(s->string) + 2; - build = I_Realloc(build, newlen); - // Replace the existing text's \0 terminator with a \n - strcat(build, "\n"); - // Concatenate the new line onto the existing text - strcat(build, s->string); - } - } while (U_CheckToken(s, ',')); - return build; -} - -// ----------------------------------------------- -// Parses a lump name. The buffer must be at least 9 characters. -// If parsed name is longer than 8 chars, sets NULL pointer. -// -// returns 1 on successfully parsing an element -// 0 on parse error in last read token -// ----------------------------------------------- -static int ParseLumpName(u_scanner_t *s, char *buffer) -{ - if (!U_MustGetToken(s, TK_StringConst)) - { - return 0; - } - - if (strlen(s->string) > 8) - { - U_Error(s, "String too long. Maximum size is 8 characters."); - return 1; // not a parse error - } - strncpy(buffer, s->string, 8); - buffer[8] = 0; - M_StringToUpper(buffer); - return 1; -} - -// ----------------------------------------------- -// Parses a standard property that is already known -// These do not get stored in the property list -// but in dedicated struct member variables. -// -// returns 1 on successfully parsing an element -// 0 on parse error in last read token -// ----------------------------------------------- -static int ParseStandardProperty(u_scanner_t *s, mapentry_t *mape) -{ - char *pname; - int status = 1; // 1 for success, 0 for parse error - if (!U_MustGetToken(s, TK_Identifier)) - { - return 0; - } - - pname = strdup(s->string); - U_MustGetToken(s, '='); - - if (!strcasecmp(pname, "levelname")) - { - if (U_MustGetToken(s, TK_StringConst)) - { - ReplaceString(&mape->levelname, s->string); - } - } - else if (!strcasecmp(pname, "label")) - { - if (U_CheckToken(s, TK_Identifier)) - { - if (!strcasecmp(s->string, "clear")) - { - ReplaceString(&mape->label, "-"); - } - else - { - U_Error(s, "Either 'clear' or string constant expected"); - } - } - else if (U_MustGetToken(s, TK_StringConst)) - { - ReplaceString(&mape->label, s->string); - } - } - else if (!strcasecmp(pname, "author")) - { - if (U_MustGetToken(s, TK_StringConst)) - { - ReplaceString(&mape->author, s->string); - } - } - else if (!strcasecmp(pname, "episode")) - { - if (U_CheckToken(s, TK_Identifier)) - { - if (!strcasecmp(s->string, "clear")) - { - M_ClearEpisodes(); - } - else - { - U_Error(s, "Either 'clear' or string constant expected"); - } - } - else - { - char lumpname[9] = {0}; - char *alttext = NULL; - char *key = NULL; - - ParseLumpName(s, lumpname); - if (U_CheckToken(s, ',')) - { - if (U_MustGetToken(s, TK_StringConst)) - { - alttext = strdup(s->string); - } - if (U_CheckToken(s, ',')) - { - if (U_MustGetToken(s, TK_StringConst)) - { - key = strdup(s->string); - key[0] = M_ToLower(key[0]); - } - } - } - - M_AddEpisode(mape->mapname, lumpname, alttext, key); - mape->flags |= MapInfo_Episode; - - if (alttext) - { - free(alttext); - } - if (key) - { - free(key); - } - } - } - else if (!strcasecmp(pname, "next")) - { - status = ParseLumpName(s, mape->nextmap); - if (!G_ValidateMapName(mape->nextmap, NULL, NULL)) - { - U_Error(s, "Invalid map name %s.", mape->nextmap); - status = 0; - } - } - else if (!strcasecmp(pname, "nextsecret")) - { - status = ParseLumpName(s, mape->nextsecret); - level_t level = {0}; - if (!G_ValidateMapName(mape->nextsecret, &level.episode, &level.map)) - { - U_Error(s, "Invalid map name %s", mape->nextsecret); - status = 0; - } - array_push(secretlevels, level); - } - else if (!strcasecmp(pname, "levelpic")) - { - status = ParseLumpName(s, mape->levelpic); - } - else if (!strcasecmp(pname, "skytexture")) - { - status = ParseLumpName(s, mape->skytexture); - } - else if (!strcasecmp(pname, "music")) - { - status = ParseLumpName(s, mape->music); - } - else if (!strcasecmp(pname, "endpic")) - { - status = ParseLumpName(s, mape->endpic); - } - else if (!strcasecmp(pname, "endcast")) - { - U_MustGetToken(s, TK_BoolConst); - if (s->sc_boolean) - { - strcpy(mape->endpic, "$CAST"); - mape->flags |= MapInfo_Endgame; - } - else - { - strcpy(mape->endpic, "-"); - } - } - else if (!strcasecmp(pname, "endbunny")) - { - U_MustGetToken(s, TK_BoolConst); - if (s->sc_boolean) - { - strcpy(mape->endpic, "$BUNNY"); - mape->flags |= MapInfo_Endgame; - } - else - { - strcpy(mape->endpic, "-"); - } - } - else if (!strcasecmp(pname, "endgame")) - { - U_MustGetToken(s, TK_BoolConst); - if (s->sc_boolean) - { - strcpy(mape->endpic, "!"); - mape->flags |= MapInfo_Endgame; - } - else - { - strcpy(mape->endpic, "-"); - } - } - else if (!strcasecmp(pname, "exitpic")) - { - status = ParseLumpName(s, mape->exitpic); - } - else if (!strcasecmp(pname, "enterpic")) - { - status = ParseLumpName(s, mape->enterpic); - } - else if (!strcasecmp(pname, "exitanim")) - { - status = ParseLumpName(s, mape->exitanim); - } - else if (!strcasecmp(pname, "enteranim")) - { - status = ParseLumpName(s, mape->enteranim); - } - else if (!strcasecmp(pname, "nointermission")) - { - if (U_MustGetToken(s, TK_BoolConst)) - { - mape->nointermission = s->sc_boolean; - } - } - else if (!strcasecmp(pname, "partime")) - { - if (U_MustGetInteger(s)) - { - mape->partime = s->number; - } - } - else if (!strcasecmp(pname, "intertext")) - { - char *lname = ParseMultiString(s, 1); - if (!lname) - { - return 0; - } - if (mape->intertext != NULL) - { - free(mape->intertext); - } - mape->intertext = lname; - } - else if (!strcasecmp(pname, "intertextsecret")) - { - char *lname = ParseMultiString(s, 1); - if (!lname) - { - return 0; - } - if (mape->intertextsecret != NULL) - { - free(mape->intertextsecret); - } - mape->intertextsecret = lname; - } - else if (!strcasecmp(pname, "interbackdrop")) - { - status = ParseLumpName(s, mape->interbackdrop); - } - else if (!strcasecmp(pname, "intermusic")) - { - status = ParseLumpName(s, mape->intermusic); - } - else if (!strcasecmp(pname, "bossaction")) - { - if (U_MustGetToken(s, TK_Identifier)) - { - if (!strcasecmp(s->string, "clear")) - { - // mark level free of boss actions - if (mape->bossactions) - { - free(mape->bossactions); - } - mape->bossactions = NULL; - mape->numbossactions = -1; - } - else - { - int i, special, tag; - for (i = 0; ActorNames[i]; i++) - { - if (!strcasecmp(s->string, ActorNames[i])) - { - break; - } - } - if (ActorNames[i] == NULL) - { - U_Error(s, "bossaction: unknown thing type '%s'", - s->string); - return 0; - } - U_MustGetToken(s, ','); - U_MustGetInteger(s); - special = s->number; - U_MustGetToken(s, ','); - U_MustGetInteger(s); - tag = s->number; - // allow no 0-tag specials here, unless a level exit. - if (tag != 0 || special == 11 || special == 51 || special == 52 - || special == 124) - { - if (mape->numbossactions == -1) - { - mape->numbossactions = 1; - } - else - { - mape->numbossactions++; - } - mape->bossactions = realloc(mape->bossactions, - sizeof(bossaction_t) * mape->numbossactions); - bossaction_t *bossaction = &mape->bossactions[mape->numbossactions - 1]; - bossaction->type = i; - bossaction->special = special; - bossaction->tag = tag; - } - } - } - } - // If no known property name was given, skip all comma-separated values - // after the = sign - else if (s->token == '=') - { - do - { - U_GetNextToken(s, true); - } while (U_CheckToken(s, ',')); - } - - free(pname); - return status; -} - -// ----------------------------------------------- -// -// Parses a complete map entry -// -// ----------------------------------------------- - -static int ParseMapEntry(u_scanner_t *s, mapentry_t *val) -{ - val->mapname = NULL; - - if (!U_MustGetIdentifier(s, "map")) - { - return 0; - } - - U_MustGetToken(s, TK_Identifier); - if (!G_ValidateMapName(s->string, NULL, NULL)) - { - U_Error(s, "Invalid map name %s", s->string); - return 0; - } - - ReplaceString(&val->mapname, s->string); - U_MustGetToken(s, '{'); - while (!U_CheckToken(s, '}')) - { - if (!ParseStandardProperty(s, val)) - { - // If there was an error parsing, skip to next token - U_GetNextToken(s, true); - } - } - return 1; -} - -// ----------------------------------------------- -// -// Parses a complete UMAPINFO lump -// -// ----------------------------------------------- - -static boolean UpdateDefaultMapEntry(mapentry_t *val, int num) -{ - int i; - - for (i = 0; i < default_mapinfo.mapcount; ++i) - { - if (!strcmp(val->mapname, default_mapinfo.maps[i].mapname)) - { - memset(&U_mapinfo.maps[num], 0, sizeof(mapentry_t)); - UpdateMapEntry(&U_mapinfo.maps[num], &default_mapinfo.maps[i]); - UpdateMapEntry(&U_mapinfo.maps[num], val); - FreeMap(val); - return true; - } - } - - return false; -} - -void U_ParseMapDefInfo(int lumpnum) -{ - const char *buffer = W_CacheLumpNum(lumpnum, PU_CACHE); - size_t length = W_LumpLength(lumpnum); - u_scanner_t *s = U_ScanOpen(buffer, length, "UMAPDEF"); - - while (U_HasTokensLeft(s)) - { - mapentry_t parsed = {0}; - if (!ParseMapEntry(s, &parsed)) - { - U_Error(s, "Skipping entry: %s", s->string); - continue; - } - - default_mapinfo.mapcount++; - default_mapinfo.maps = realloc(default_mapinfo.maps, - sizeof(mapentry_t) * default_mapinfo.mapcount); - default_mapinfo.maps[default_mapinfo.mapcount - 1] = parsed; - } - U_ScanClose(s); -} - -void U_ParseMapInfo(int lumpnum) -{ - unsigned int i; - const char *buffer = W_CacheLumpNum(lumpnum, PU_CACHE); - size_t length = W_LumpLength(lumpnum); - u_scanner_t *s = U_ScanOpen(buffer, length, "UMAPINFO"); - - while (U_HasTokensLeft(s)) - { - mapentry_t parsed = {0}; - if (!ParseMapEntry(s, &parsed)) - { - U_Error(s, "Skipping entry: %s", s->string); - continue; - } - - // Set default level progression here to simplify the checks elsewhere. - // Doing this lets us skip all normal code for this if nothing has been - // defined. - if (parsed.endpic[0] && (strcmp(parsed.endpic, "-") != 0)) - { - parsed.nextmap[0] = 0; - } - else if (!parsed.nextmap[0] && !parsed.endpic[0]) - { - if (!strcasecmp(parsed.mapname, "MAP30")) - { - strcpy(parsed.endpic, "$CAST"); - } - else if (!strcasecmp(parsed.mapname, "E1M8")) - { - strcpy(parsed.endpic, gamemode == retail ? "CREDIT" : "HELP2"); - } - else if (!strcasecmp(parsed.mapname, "E2M8")) - { - strcpy(parsed.endpic, "VICTORY2"); - } - else if (!strcasecmp(parsed.mapname, "E3M8")) - { - strcpy(parsed.endpic, "$BUNNY"); - } - else if (!strcasecmp(parsed.mapname, "E4M8")) - { - strcpy(parsed.endpic, "ENDPIC"); - } - else - { - int ep, map; - - G_ValidateMapName(parsed.mapname, &ep, &map); - - strcpy(parsed.nextmap, MapName(ep, map + 1)); - } - } - - // Does this property already exist? If yes, replace it. - for (i = 0; i < U_mapinfo.mapcount; i++) - { - if (!strcmp(parsed.mapname, U_mapinfo.maps[i].mapname)) - { - FreeMap(&U_mapinfo.maps[i]); - - if (!UpdateDefaultMapEntry(&parsed, i)) - { - U_mapinfo.maps[i] = parsed; - } - break; - } - } - // Not found so create a new one. - if (i == U_mapinfo.mapcount) - { - U_mapinfo.mapcount++; - U_mapinfo.maps = realloc(U_mapinfo.maps, - sizeof(mapentry_t) * U_mapinfo.mapcount); - - if (!UpdateDefaultMapEntry(&parsed, i)) - { - U_mapinfo.maps[U_mapinfo.mapcount - 1] = parsed; - } - } - } - U_ScanClose(s); -} - -boolean U_CheckField(char *str) -{ - return str && str[0] && strcmp(str, "-"); -} - -boolean U_IsSecretMap(int episode, int map) -{ - level_t *level; - array_foreach(level, secretlevels) - { - if (level->episode == episode && level->map == map) - { - return true; - } - } - return false; -} diff --git a/src/u_mapinfo.h b/src/u_mapinfo.h deleted file mode 100644 index ea6d6a019..000000000 --- a/src/u_mapinfo.h +++ /dev/null @@ -1,87 +0,0 @@ -//----------------------------------------------------------------------------- -// -// Copyright 2017 Christoph Oelckers -// Copyright 2019 Fernando Carmona Varo -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT 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, see http://www.gnu.org/licenses/ -// -//----------------------------------------------------------------------------- - -#ifndef __UMAPINFO_H -#define __UMAPINFO_H - -#include "doomtype.h" - -typedef struct -{ - int type; - int special; - int tag; -} bossaction_t; - -typedef enum -{ - MapInfo_Episode = 0x0001, - MapInfo_Endgame = 0x0002, -} mapinfo_flags_t; - -typedef struct mapentry_s -{ - char *mapname; - char *levelname; - char *label; - char *intertext; - char *intertextsecret; - char *author; - char levelpic[9]; - char nextmap[9]; - char nextsecret[9]; - char music[9]; - char skytexture[9]; - char endpic[9]; - char exitpic[9]; - char enterpic[9]; - char exitanim[9]; - char enteranim[9]; - char interbackdrop[9]; - char intermusic[9]; - int partime; - mapinfo_flags_t flags; - boolean nointermission; - int numbossactions; - bossaction_t *bossactions; -} mapentry_t; - -typedef struct -{ - unsigned int mapcount; - mapentry_t *maps; -} umapinfo_t; - -extern umapinfo_t U_mapinfo; -extern umapinfo_t default_mapinfo; - -extern boolean EpiCustom; - -mapentry_t *G_LookupMapinfo(int episode, int map); - -boolean U_CheckField(char *str); - -void U_ParseMapDefInfo(int lumpnum); - -void U_ParseMapInfo(int lumpnum); - -boolean U_IsSecretMap(int episode, int map); - -#endif diff --git a/src/u_scanner.c b/src/u_scanner.c deleted file mode 100644 index 5d308484d..000000000 --- a/src/u_scanner.c +++ /dev/null @@ -1,909 +0,0 @@ -// Copyright (c) 2019, Fernando Carmona Varo <ferkiwi@gmail.com> -// Copyright (c) 2010, Braden "Blzut3" Obrzut <admin@maniacsvault.net> -// 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 <organization> 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 <COPYRIGHT HOLDER> 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. - -#include <ctype.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> - -#include "doomtype.h" -#include "i_system.h" -#include "m_misc.h" -#include "u_scanner.h" - -static const char *U_TokenNames[TK_NumSpecialTokens] = -{ - "Identifier", // case insensitive identifier, beginning with a letter and - // may contain [a-z0-9_] - "String Constant", - "Integer Constant", - "Float Constant", - "Boolean Constant", - "Logical And", - "Logical Or", - "Equals", - "Not Equals", - "Greater Than or Equals", - "Less Than or Equals", - "Left Shift", - "Right Shift" -}; - -static void U_CheckForWhitespace(u_scanner_t *scanner); -static void U_ExpandState(u_scanner_t *scanner); -static void U_Unescape(char *str); -static void U_SetString(char **ptr, const char *start, int length); - -u_scanner_t *U_ScanOpen(const char *data, int length, const char *name) -{ - u_scanner_t *s = calloc(1, sizeof(*s)); - s->line = s->tokenLine = 1; - s->needNext = true; - s->string = NULL; - s->nextState.string = NULL; - s->name = name; - - if (length == -1) - { - length = strlen(data); - } - s->length = length; - s->data = malloc(length); - memcpy(s->data, data, length); - - U_CheckForWhitespace(s); - - return s; -} - -void U_ScanClose(u_scanner_t *s) -{ - if (s->nextState.string != NULL) - { - free(s->nextState.string); - } - if (s->data != NULL) - { - free(s->data); - } - free(s); -} - -static void U_IncrementLine(u_scanner_t *s) -{ - s->line++; - s->lineStart = s->scanPos; -} - -static void U_CheckForWhitespace(u_scanner_t *s) -{ - int comment = 0; // 1 = till next new line, 2 = till end block - while (s->scanPos < s->length) - { - char cur = s->data[s->scanPos]; - char next = (s->scanPos + 1 < s->length) ? s->data[s->scanPos + 1] : 0; - if (comment == 2) - { - if (cur != '*' || next != '/') - { - if (cur == '\n' || cur == '\r') - { - s->scanPos++; - - // Do a quick check for Windows style new line - if (cur == '\r' && next == '\n') - { - s->scanPos++; - } - U_IncrementLine(s); - } - else - { - s->scanPos++; - } - } - else - { - comment = 0; - s->scanPos += 2; - } - continue; - } - - if (cur == ' ' || cur == '\t' || cur == 0) - { - s->scanPos++; - } - else if (cur == '\n' || cur == '\r') - { - s->scanPos++; - if (comment == 1) - { - comment = 0; - } - - // Do a quick check for Windows style new line - if (cur == '\r' && next == '\n') - { - s->scanPos++; - } - U_IncrementLine(s); - } - else if (cur == '/' && comment == 0) - { - switch (next) - { - case '/': - comment = 1; - break; - case '*': - comment = 2; - break; - default: - return; - } - s->scanPos += 2; - } - else - { - if (comment == 0) - { - return; - } - else - { - s->scanPos++; - } - } - } -} - -boolean U_CheckToken(u_scanner_t *s, char token) -{ - if (s->needNext) - { - if (!U_GetNextToken(s, false)) - { - return false; - } - } - - // An int can also be a float. - if ((s->nextState).token == token - || ((s->nextState).token == TK_IntConst && s->token == TK_FloatConst)) - { - s->needNext = true; - U_ExpandState(s); - return true; - } - s->needNext = false; - return false; -} - -static void U_ExpandState(u_scanner_t *s) -{ - s->logicalPosition = s->scanPos; - U_CheckForWhitespace(s); - - U_SetString(&(s->string), s->nextState.string, -1); - s->number = s->nextState.number; - s->decimal = s->nextState.decimal; - s->sc_boolean = s->nextState.sc_boolean; - s->token = s->nextState.token; - s->tokenLine = s->nextState.tokenLine; - s->tokenLinePosition = s->nextState.tokenLinePosition; -} - - // NOLINTBEGIN(clang-analyzer-unix.Malloc) -static void U_SaveState(u_scanner_t *s, u_scanner_t savedstate) -{ - // This saves the entire parser state except for the data pointer. - if (savedstate.string != NULL) - { - free(savedstate.string); - } - if (savedstate.nextState.string != NULL) - { - free(savedstate.nextState.string); - } - - memcpy(&savedstate, s, sizeof(*s)); - savedstate.string = strdup(s->string); - savedstate.nextState.string = strdup(s->nextState.string); - savedstate.data = NULL; -} -// NOLINTEND(clang-analyzer-unix.Malloc) - -static void U_RestoreState(u_scanner_t *s, u_scanner_t savedstate) -{ - if (savedstate.data == NULL) - { - char *saveddata = s->data; - U_SaveState(&savedstate, *s); - s->data = saveddata; - } -} - -boolean U_GetString(u_scanner_t *s) -{ - unsigned int start; - char cur; - u_parserstate_t *nextState = &s->nextState; - - if (!s->needNext) - { - s->needNext = true; - U_ExpandState(s); - return true; - } - - nextState->tokenLine = s->line; - nextState->tokenLinePosition = s->scanPos - s->lineStart; - nextState->token = TK_NoToken; - if (s->scanPos >= s->length) - { - U_ExpandState(s); - return false; - } - - start = s->scanPos; - s->scanPos++; - - while (s->scanPos < s->length) - { - cur = s->data[s->scanPos]; - - if (cur == ' ' || cur == '\t' || cur == '\n' || cur == '\r' || cur == 0) - { - break; - } - else - { - s->scanPos++; - } - } - - U_SetString(&(nextState->string), s->data + start, s->scanPos - start); - U_ExpandState(s); - return true; -} - -boolean U_GetNextToken(u_scanner_t *s, boolean expandState) -{ - unsigned int start; - unsigned int end; - char cur; - int integerBase = 10; - boolean floatHasDecimal = false; - boolean floatHasExponent = false; - // Strings are the only things that can have 0 length tokens. - boolean stringFinished = false; - u_parserstate_t *nextState = &s->nextState; - - if (!s->needNext) - { - s->needNext = true; - if (expandState) - { - U_ExpandState(s); - } - return true; - } - - nextState->tokenLine = s->line; - nextState->tokenLinePosition = s->scanPos - s->lineStart; - nextState->token = TK_NoToken; - if (s->scanPos >= s->length) - { - if (expandState) - { - U_ExpandState(s); - } - return false; - } - - start = s->scanPos; - end = s->scanPos; - cur = s->data[s->scanPos++]; - - // Determine by first character - if (cur == '_' || (cur >= 'A' && cur <= 'Z') || (cur >= 'a' && cur <= 'z')) - { - nextState->token = TK_Identifier; - } - else if (cur >= '0' && cur <= '9') - { - if (cur == '0') - { - integerBase = 8; - } - nextState->token = TK_IntConst; - } - else if (cur == '.') - { - floatHasDecimal = true; - nextState->token = TK_FloatConst; - } - else if (cur == '"') - { - end = ++start; // Move the start up one character so we don't have to - // trim it later. - nextState->token = TK_StringConst; - } - else - { - end = s->scanPos; - nextState->token = cur; - - // Now check for operator tokens - if (s->scanPos < s->length) - { - char next = s->data[s->scanPos]; - if (cur == '&' && next == '&') - { - nextState->token = TK_AndAnd; - } - else if (cur == '|' && next == '|') - { - nextState->token = TK_OrOr; - } - else if (cur == '<' && next == '<') - { - nextState->token = TK_ShiftLeft; - } - else if (cur == '>' && next == '>') - { - nextState->token = TK_ShiftRight; - } - // else if(cur == '#' && next == '#') - // nextState.token = TK_MacroConcat; - else if (next == '=') - { - switch (cur) - { - case '=': - nextState->token = TK_EqEq; - break; - case '!': - nextState->token = TK_NotEq; - break; - case '>': - nextState->token = TK_GtrEq; - break; - case '<': - nextState->token = TK_LessEq; - break; - default: - break; - } - } - if (nextState->token != cur) - { - s->scanPos++; - end = s->scanPos; - } - } - } - - if (start == end) - { - while (s->scanPos < s->length) - { - cur = s->data[s->scanPos]; - switch (nextState->token) - { - default: - break; - case TK_Identifier: - if (cur != '_' && (cur < 'A' || cur > 'Z') - && (cur < 'a' || cur > 'z') && (cur < '0' || cur > '9')) - { - end = s->scanPos; - } - break; - case TK_IntConst: - if (cur == '.' || (s->scanPos - 1 != start && cur == 'e')) - { - nextState->token = TK_FloatConst; - } - else if ((cur == 'x' || cur == 'X') - && s->scanPos - 1 == start) - { - integerBase = 16; - break; - } - else - { - switch (integerBase) - { - default: - if (cur < '0' || cur > '9') - { - end = s->scanPos; - } - break; - case 8: - if (cur < '0' || cur > '7') - { - end = s->scanPos; - } - break; - case 16: - if ((cur < '0' || cur > '9') - && (cur < 'A' || cur > 'F') - && (cur < 'a' || cur > 'f')) - { - end = s->scanPos; - } - break; - } - break; - } - case TK_FloatConst: - if (cur < '0' || cur > '9') - { - if (!floatHasDecimal && cur == '.') - { - floatHasDecimal = true; - break; - } - else if (!floatHasExponent && cur == 'e') - { - floatHasDecimal = true; - floatHasExponent = true; - if (s->scanPos + 1 < s->length) - { - char next = s->data[s->scanPos + 1]; - if ((next < '0' || next > '9') && next != '+' - && next != '-') - { - end = s->scanPos; - } - else - { - s->scanPos++; - } - } - break; - } - end = s->scanPos; - } - break; - case TK_StringConst: - if (cur == '"') - { - stringFinished = true; - end = s->scanPos; - s->scanPos++; - } - else if (cur == '\\') - { - s->scanPos++; // Will add two since the loop - // automatically adds one - } - break; - } - if (start == end && !stringFinished) - { - s->scanPos++; - } - else - { - break; - } - } - // If we reached end of input while reading, set it as the end of token - if (s->scanPos == s->length && start == end) - { - end = s->length; - } - } - - if (end - start > 0 || stringFinished) - { - U_SetString(&(nextState->string), s->data + start, end - start); - if (nextState->token == TK_FloatConst) - { - nextState->decimal = atof(nextState->string); - nextState->number = (int)(nextState->decimal); - nextState->sc_boolean = (nextState->number != 0); - } - else if (nextState->token == TK_IntConst) - { - nextState->number = strtol(nextState->string, NULL, integerBase); - nextState->decimal = nextState->number; - nextState->sc_boolean = (nextState->number != 0); - } - else if (nextState->token == TK_Identifier) - { - // Identifiers should be case insensitive. - char *p = nextState->string; - while (*p) - { - *p = M_ToLower(*p); - p++; - } - // Check for a boolean constant. - if (strcmp(nextState->string, "true") == 0) - { - nextState->token = TK_BoolConst; - nextState->sc_boolean = true; - } - else if (strcmp(nextState->string, "false") == 0) - { - nextState->token = TK_BoolConst; - nextState->sc_boolean = false; - } - } - else if (nextState->token == TK_StringConst) - { - U_Unescape(nextState->string); - } - if (expandState) - { - U_ExpandState(s); - } - return true; - } - nextState->token = TK_NoToken; - if (expandState) - { - U_ExpandState(s); - } - return false; -} - -// Skips all Tokens in current line and parses the first token on the next -// line. -boolean U_GetNextLineToken(u_scanner_t *s) -{ - unsigned int line = s->line; - boolean retval = false; - - do - { - retval = U_GetNextToken(s, true); - } while (retval && s->line == line); - - return retval; -} - -void U_ErrorToken(u_scanner_t *s, int token) -{ - if (token < TK_NumSpecialTokens && s->token >= TK_Identifier - && s->token < TK_NumSpecialTokens) - { - U_Error(s, "Expected %s but got %s '%s' instead.", U_TokenNames[token], - U_TokenNames[(int)s->token], s->string); - } - else if (token < TK_NumSpecialTokens && s->token >= TK_NumSpecialTokens) - { - U_Error(s, "Expected %s but got '%c' instead.", U_TokenNames[token], - s->token); - } - else if (token < TK_NumSpecialTokens && s->token == TK_NoToken) - { - U_Error(s, "Expected %s", U_TokenNames[token]); - } - else if (token >= TK_NumSpecialTokens && s->token >= TK_Identifier - && s->token < TK_NumSpecialTokens) - { - U_Error(s, "Expected '%c' but got %s '%s' instead.", token, - U_TokenNames[(int)s->token], s->string); - } - else - { - U_Error(s, "Expected '%c' but got '%c' instead.", token, s->token); - } -} - -void U_ErrorString(u_scanner_t *s, const char *mustget) -{ - if (s->token < TK_NumSpecialTokens) - { - U_Error(s, "Expected '%s' but got %s '%s' instead.", mustget, - U_TokenNames[(int)s->token], s->string); - } - else - { - U_Error(s, "Expected '%s' but got '%c' instead.", mustget, s->token); - } -} - -void PRINTF_ATTR(2, 0) U_Error(u_scanner_t *s, const char *msg, ...) -{ - char buffer[1024]; - va_list ap; - va_start(ap, msg); - M_vsnprintf(buffer, 1024, msg, ap); - va_end(ap); - I_Error("%s:%d:%d:%s", s->name, s->tokenLine, s->tokenLinePosition, buffer); -} - -boolean U_MustGetToken(u_scanner_t *s, char token) -{ - if (!U_CheckToken(s, token)) - { - U_ExpandState(s); - U_ErrorToken(s, token); - return false; - } - return true; -} - -boolean U_MustGetIdentifier(u_scanner_t *s, const char *ident) -{ - if (!U_CheckToken(s, TK_Identifier) || strcasecmp(s->string, ident)) - { - U_ErrorString(s, ident); - return false; - } - return true; -} - -void U_Unget(u_scanner_t *s) -{ - s->needNext = false; -} - -// Convenience helpers that parse an entire number including a leading minus or -// plus sign -static boolean U_ScanInteger(u_scanner_t *s) -{ - boolean neg = false; - if (!U_GetNextToken(s, true)) - { - return false; - } - if (s->token == '-') - { - if (!U_GetNextToken(s, true)) - { - return false; - } - neg = true; - } - else if (s->token == '+') - { - if (!U_GetNextToken(s, true)) - { - return false; - } - } - if (s->token != TK_IntConst) - { - return false; - } - if (neg) - { - s->number = -(s->number); - s->decimal = -(s->decimal); - } - return true; -} - -static boolean U_ScanFloat(u_scanner_t *s) -{ - boolean neg = false; - if (!U_GetNextToken(s, true)) - { - return false; - } - if (s->token == '-') - { - if (!U_GetNextToken(s, true)) - { - return false; - } - neg = true; - } - else if (s->token == '+') - { - if (!U_GetNextToken(s, true)) - { - return false; - } - } - if (s->token != TK_IntConst && s->token != TK_FloatConst) - { - return false; - } - if (neg) - { - s->number = -(s->number); - s->decimal = -(s->decimal); - } - return true; -} - -boolean U_CheckInteger(u_scanner_t *s) -{ - boolean res; - u_scanner_t savedstate = {0}; - U_SaveState(s, savedstate); - res = U_ScanInteger(s); - if (!res) - { - U_RestoreState(s, savedstate); - } - return res; -} - -boolean U_CheckFloat(u_scanner_t *s) -{ - boolean res; - u_scanner_t savedstate = {0}; - U_SaveState(s, savedstate); - res = U_ScanFloat(s); - if (!res) - { - U_RestoreState(s, savedstate); - } - return res; -} - -boolean U_MustGetInteger(u_scanner_t *s) -{ - if (!U_ScanInteger(s)) - { - U_ErrorToken(s, TK_IntConst); - return false; - } - return true; -} - -boolean U_MustGetFloat(u_scanner_t *s) -{ - if (!U_ScanFloat(s)) - { - U_ErrorToken(s, TK_FloatConst); - return false; - } - return true; -} - -boolean U_HasTokensLeft(u_scanner_t *s) -{ - return (s->scanPos < s->length); -} - -// This is taken from ZDoom's strbin function which can do a lot more than just -// unescaping backslashes and quotation marks. -void U_Unescape(char *str) -{ - char *p = str, c; - int i; - - while ((c = *p++)) - { - if (c != '\\') - { - *str++ = c; - } - else - { - switch (*p) - { - case 'a': - *str++ = '\a'; - break; - case 'b': - *str++ = '\b'; - break; - case 'f': - *str++ = '\f'; - break; - case 'n': - *str++ = '\n'; - break; - case 't': - *str++ = '\t'; - break; - case 'r': - *str++ = '\r'; - break; - case 'v': - *str++ = '\v'; - break; - case '?': - *str++ = '\?'; - break; - case '\n': - break; - case 'x': - case 'X': - c = 0; - for (i = 0; i < 2; i++) - { - p++; - if (*p >= '0' && *p <= '9') - { - c = (c << 4) + *p - '0'; - } - else if (*p >= 'a' && *p <= 'f') - { - c = (c << 4) + 10 + *p - 'a'; - } - else if (*p >= 'A' && *p <= 'F') - { - c = (c << 4) + 10 + *p - 'A'; - } - else - { - p--; - break; - } - } - *str++ = c; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - c = *p - '0'; - for (i = 0; i < 2; i++) - { - p++; - if (*p >= '0' && *p <= '7') - { - c = (c << 3) + *p - '0'; - } - else - { - p--; - break; - } - } - *str++ = c; - break; - default: - *str++ = *p; - break; - } - p++; - } - } - *str = 0; -} - -static void U_SetString(char **ptr, const char *start, int length) -{ - if (length == -1) - { - length = strlen(start); - } - if (*ptr != NULL) - { - free(*ptr); - } - *ptr = (char *)malloc(length + 1); - memcpy(*ptr, start, length); - (*ptr)[length] = '\0'; -} diff --git a/src/u_scanner.h b/src/u_scanner.h deleted file mode 100644 index bdbef6247..000000000 --- a/src/u_scanner.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2010, Braden "Blzut3" Obrzut <admin@maniacsvault.net> -// Copyright (c) 2019, Fernando Carmona Varo <ferkiwi@gmail.com> -// 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 <organization> 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 <COPYRIGHT HOLDER> 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. - -#ifndef __U_SCANNER_H__ -#define __U_SCANNER_H__ - -#include "doomtype.h" - -enum -{ - TK_Identifier, // Ex: SomeIdentifier - TK_StringConst, // Ex: "Some String" - TK_IntConst, // Ex: 27 - TK_FloatConst, // Ex: 1.5 - TK_BoolConst, // Ex: true - TK_AndAnd, // && - TK_OrOr, // || - TK_EqEq, // == - TK_NotEq, // != - TK_GtrEq, // >= - TK_LessEq, // <= - TK_ShiftLeft, // << - TK_ShiftRight, // >> - - TK_NumSpecialTokens, - - TK_NoToken = -1 -}; - -typedef struct -{ - char *string; - int number; - double decimal; - boolean sc_boolean; - char token; - unsigned int tokenLine; - unsigned int tokenLinePosition; -} u_parserstate_t; - -typedef struct -{ - const char *name; - - u_parserstate_t nextState; - - char *data; - unsigned int length; - - unsigned int line; - unsigned int lineStart; - unsigned int logicalPosition; - unsigned int tokenLine; - unsigned int tokenLinePosition; - unsigned int scanPos; - - boolean needNext; // If checkToken returns false this will be false. - - char *string; - int number; - double decimal; - boolean sc_boolean; - char token; - -} u_scanner_t; - -u_scanner_t *U_ScanOpen(const char *data, int length, const char *name); -void U_ScanClose(u_scanner_t *s); -boolean U_GetNextToken(u_scanner_t *s, boolean expandState); -boolean U_GetNextLineToken(u_scanner_t *s); -boolean U_HasTokensLeft(u_scanner_t *s); -boolean U_MustGetToken(u_scanner_t *s, char token); -boolean U_MustGetIdentifier(u_scanner_t *s, const char *ident); -boolean U_MustGetInteger(u_scanner_t *s); -boolean U_MustGetFloat(u_scanner_t *s); -boolean U_CheckToken(u_scanner_t *s, char token); -boolean U_CheckInteger(u_scanner_t *s); -boolean U_CheckFloat(u_scanner_t *s); -void U_Unget(u_scanner_t *s); -boolean U_GetString(u_scanner_t *s); - -void PRINTF_ATTR(2, 0) U_Error(u_scanner_t *s, const char *msg, ...); -void U_ErrorToken(u_scanner_t *s, int token); -void U_ErrorString(u_scanner_t *s, const char *mustget); - -#endif /* __U_SCANNER_H__ */ diff --git a/src/v_video.c b/src/v_video.c index a6b499300..bee247164 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -480,7 +480,7 @@ static void DrawPatchInternal(int x, int y, patch_t *patch, boolean flipped) } else // too far off-screen { - x1 = (x1 * video.xscale) >> FRACBITS; + x1 = -(DIV_ROUND_FLOOR(video.width * (-x1 - 1), video.unscaledw)); } if (x2 < video.unscaledw) diff --git a/src/w_wad.h b/src/w_wad.h index 0b78632b0..1a55781ed 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -65,11 +65,13 @@ typedef enum ns_hires // [Woof!] namespace to avoid conflicts with high-resolution textures } namespace_t; +typedef struct archive_s archive_t; + typedef struct { union { - void *zip; + archive_t *archive; const char *base_path; int descriptor; } p1; diff --git a/src/w_zip.c b/src/w_zip.c index ba415af23..2befb39e4 100644 --- a/src/w_zip.c +++ b/src/w_zip.c @@ -11,6 +11,8 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. +#include <stdlib.h> + #include "doomtype.h" #include "i_printf.h" #include "m_array.h" @@ -21,6 +23,20 @@ #include "miniz.h" +typedef struct +{ + int index; + const char *filename; +} record_t; + +struct archive_s +{ + mz_zip_archive *zip; + record_t *directory; +}; + +static archive_t *archives; + static void ConvertSlashes(char *path) { for (char *p = path; *p; ++p) @@ -37,7 +53,7 @@ static void AddWadInMem(w_handle_t handle, const char *name, int index, { I_Printf(VB_INFO, " - adding %s", name); - mz_zip_archive *zip = handle.p1.zip; + mz_zip_archive *zip = handle.p1.archive->zip; byte *data = malloc(data_size); @@ -108,7 +124,9 @@ static void AddWadInMem(w_handle_t handle, const char *name, int index, static boolean W_ZIP_AddDir(w_handle_t handle, const char *path, const char *start_marker, const char *end_marker) { - mz_zip_archive *zip = handle.p1.zip; + archive_t *archive = handle.p1.archive; + + mz_zip_archive *zip = archive->zip; boolean is_root = (path[0] == '.'); @@ -117,32 +135,34 @@ static boolean W_ZIP_AddDir(w_handle_t handle, const char *path, int startlump = numlumps; - for (int index = 0 ; index < mz_zip_reader_get_num_files(zip); ++index) + for (int i = 0; i < mz_zip_reader_get_num_files(zip); ++i) { + const record_t record = archive->directory[i]; + mz_zip_archive_file_stat stat; - mz_zip_reader_file_stat(zip, index, &stat); + mz_zip_reader_file_stat(zip, record.index, &stat); if (stat.m_is_directory) { continue; } - if (is_root && M_StringCaseEndsWith(stat.m_filename, ".wad")) + char *name = M_DirName(record.filename); + if (strcasecmp(name, dir)) { - AddWadInMem(handle, M_BaseName(stat.m_filename), index, - stat.m_uncomp_size); + free(name); continue; } + free(name); - char *name = M_DirName(stat.m_filename); - if (strcasecmp(name, dir)) + if (is_root && M_StringCaseEndsWith(record.filename, ".wad")) { - free(name); + AddWadInMem(handle, M_BaseName(record.filename), record.index, + stat.m_uncomp_size); continue; } - free(name); - if (W_SkipFile(stat.m_filename)) + if (W_SkipFile(record.filename)) { continue; } @@ -158,7 +178,8 @@ static boolean W_ZIP_AddDir(w_handle_t handle, const char *path, item.size = stat.m_uncomp_size; item.module = &w_zip_module; - w_handle_t local_handle = {.p1.zip = zip, .p2.index = index, + w_handle_t local_handle = {.p1.archive = archive, + .p2.index = record.index, .priority = handle.priority}; item.handle = local_handle; @@ -175,29 +196,49 @@ static boolean W_ZIP_AddDir(w_handle_t handle, const char *path, return true; } -static mz_zip_archive **zips = NULL; +static int compare_records(const void *a, const void *b) +{ + const record_t *arg1 = a; + const record_t *arg2 = b; + + return strcasecmp(arg1->filename, arg2->filename); +} static w_type_t W_ZIP_Open(const char *path, w_handle_t *handle) { mz_zip_archive *zip = calloc(1, sizeof(*zip)); - if (!mz_zip_reader_init_file(zip, path, 0)) + if (!mz_zip_reader_init_file(zip, path, MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) { free(zip); return W_NONE; } + const int num_files = mz_zip_reader_get_num_files(zip); + record_t *directory = malloc(num_files * sizeof(*directory)); + for (int i = 0; i < num_files; ++i) + { + directory[i].index = i; + int size = mz_zip_reader_get_filename(zip, i, NULL, 0); + char *filename = malloc(size); + mz_zip_reader_get_filename(zip, i, filename, size); + directory[i].filename = filename; + } + qsort(directory, num_files, sizeof(*directory), compare_records); + I_Printf(VB_INFO, " adding %s", path); - handle->p1.zip = zip; - array_push(zips, zip); + archive_t archive = {zip, directory}; + array_push(archives, archive); + handle->p1.archive = array_end(archives) - 1; + return W_DIR; } static void W_ZIP_Read(w_handle_t handle, void *dest, int size) { boolean result = mz_zip_reader_extract_to_mem( - handle.p1.zip, handle.p2.index, dest, size, 0); + handle.p1.archive->zip, handle.p2.index, dest, size, 0); if (!result) { @@ -207,9 +248,9 @@ static void W_ZIP_Read(w_handle_t handle, void *dest, int size) static void W_ZIP_Close(void) { - for (int i = 0; i < array_size(zips); ++i) + for (int i = 0; i < array_size(archives); ++i) { - mz_zip_reader_end(zips[i]); + mz_zip_reader_end(archives[i].zip); } } diff --git a/src/wi_stuff.c b/src/wi_stuff.c index 6d9c3eb1c..e23fb03de 100644 --- a/src/wi_stuff.c +++ b/src/wi_stuff.c @@ -26,6 +26,7 @@ #include "doomdef.h" #include "doomstat.h" #include "doomtype.h" +#include "g_umapinfo.h" #include "g_game.h" #include "i_printf.h" #include "m_misc.h" @@ -37,7 +38,6 @@ #include "st_sbardef.h" #include "st_stuff.h" #include "sounds.h" -#include "u_mapinfo.h" #include "v_fmt.h" #include "v_video.h" #include "w_wad.h" @@ -485,7 +485,7 @@ static boolean CheckConditions(interlevelcond_t *conditions, break; case AnimCondition_MapNotSecret: - conditionsmet &= !U_IsSecretMap(episode, map); + conditionsmet &= !G_IsSecretMap(episode, map); break; case AnimCondition_SecretVisited: @@ -717,26 +717,38 @@ static boolean SetupMusic(boolean enteringcondition) // void WI_slamBackground(void) { - char name[32]; + // [Nugget] Alt. intermission background + if (alt_interpic_on) + { + R_RenderPlayerView(&players[displayplayer]); + V_ShadeScreen(17); + return; + } - // [Nugget] Alt. intermission background - if (alt_interpic_on) { - R_RenderPlayerView(&players[displayplayer]); - V_ShadeScreen(17); - return; - } + const char *name; - if (state != StatCount && enterpic) - strcpy(name, enterpic); - else if (exitpic) - strcpy(name, exitpic); - // with UMAPINFO it is possible that wbs->epsd > 3 - else if (gamemode == commercial || wbs->epsd >= 3) - strcpy(name, "INTERPIC"); - else - M_snprintf(name, sizeof(name), "WIMAP%d", wbs->epsd); + char lump[9] = {0}; + + if (state != StatCount && enterpic) + { + name = enterpic; + } + else if (exitpic) + { + name = exitpic; + } + // with UMAPINFO it is possible that wbs->epsd > 3 + else if (gamemode == commercial || wbs->epsd >= 3) + { + name = "INTERPIC"; + } + else + { + M_snprintf(lump, sizeof(lump), "WIMAP%d", wbs->epsd); + name = lump; + } - V_DrawPatchFullScreen(V_CachePatchName(name, PU_CACHE)); + V_DrawPatchFullScreen(V_CachePatchName(name, PU_CACHE)); } // ==================================================================== @@ -766,50 +778,45 @@ static void WI_DrawString(int y, const char* str) // static void WI_drawLF(void) { - int y = WI_TITLEY; - - // The level defines a new name but no texture for the name. - if (wbs->lastmapinfo && wbs->lastmapinfo->levelname && wbs->lastmapinfo->levelpic[0] == 0) - { - WI_DrawString(y, wbs->lastmapinfo->levelname); + int y = WI_TITLEY; - y += (5 * SHORT(hu_font['A' - HU_FONTSTART]->height) / 4); + const mapentry_t *mapinfo = wbs->lastmapinfo; - if (wbs->lastmapinfo->author) + // The level defines a new name but no texture for the name. + if (mapinfo && mapinfo->levelname && !mapinfo->levelpic[0]) { - WI_DrawString(y, wbs->lastmapinfo->author); + WI_DrawString(y, mapinfo->levelname); + + y += (5 * SHORT(hu_font['A' - HU_FONTSTART]->height) / 4); + + if (mapinfo->author) + { + WI_DrawString(y, mapinfo->author); - y += (5 * SHORT(hu_font['A' - HU_FONTSTART]->height) / 4); + y += (5 * SHORT(hu_font['A' - HU_FONTSTART]->height) / 4); + } } - } - else if (wbs->lastmapinfo && wbs->lastmapinfo->levelpic[0]) - { - patch_t* lpic = V_CachePatchName(wbs->lastmapinfo->levelpic, PU_CACHE); + else if (mapinfo && mapinfo->levelpic[0]) + { + patch_t *patch = V_CachePatchName(mapinfo->levelpic, PU_CACHE); - // [Nugget] HUD/menu shadows - V_DrawPatchSH((SCREENWIDTH - SHORT(lpic->width))/2, - y, lpic); + V_DrawPatchSH((SCREENWIDTH - SHORT(patch->width)) / 2, y, patch); - y += (5 * SHORT(lpic->height)) / 4; - } - else - // [FG] prevent crashes for levels without name graphics - if (wbs->last >= 0 && wbs->last < num_lnames && lnames[wbs->last] != NULL ) - { - // draw <LevelName> - // [Nugget] HUD/menu shadows - V_DrawPatchSH((SCREENWIDTH - SHORT(lnames[wbs->last]->width))/2, - y, lnames[wbs->last]); + y += (5 * SHORT(patch->height)) / 4; + } + // [FG] prevent crashes for levels without name graphics + else if (wbs->last >= 0 && wbs->last < num_lnames && lnames[wbs->last]) + { + // draw <LevelName> + V_DrawPatchSH((SCREENWIDTH - SHORT(lnames[wbs->last]->width)) / 2, y, + lnames[wbs->last]); - // draw "Finished!" - y += (5*SHORT(lnames[wbs->last]->height))/4; - } - - // [Nugget] HUD/menu shadows - V_DrawPatchSH((SCREENWIDTH - SHORT(finished->width))/2, - y, finished); -} + // draw "Finished!" + y += (5 * SHORT(lnames[wbs->last]->height)) / 4; + } + V_DrawPatchSH((SCREENWIDTH - SHORT(finished->width)) / 2, y, finished); +} // ==================================================================== // WI_drawEL @@ -819,52 +826,53 @@ static void WI_drawLF(void) // static void WI_drawEL(void) { - int y = WI_TITLEY; - - // draw "Entering" - // [Nugget] HUD/menu shadows - V_DrawPatchSH((SCREENWIDTH - SHORT(entering->width))/2, - y, entering); + int y = WI_TITLEY; - // The level defines a new name but no texture for the name - if (wbs->nextmapinfo && wbs->nextmapinfo->levelname && wbs->nextmapinfo->levelpic[0] == 0) - { - y += (5 * SHORT(entering->height)) / 4; + // draw "Entering" + V_DrawPatchSH((SCREENWIDTH - SHORT(entering->width)) / 2, y, entering); - WI_DrawString(y, wbs->nextmapinfo->levelname); + const mapentry_t *mapinfo = wbs->nextmapinfo; - if (wbs->nextmapinfo->author) + // The level defines a new name but no texture for the name + if (mapinfo && mapinfo->levelname && !mapinfo->levelpic[0]) { - y += (5 * SHORT(hu_font['A' - HU_FONTSTART]->height) / 4); + y += (5 * SHORT(entering->height)) / 4; + + WI_DrawString(y, mapinfo->levelname); - WI_DrawString(y, wbs->nextmapinfo->author); + if (mapinfo->author) + { + y += (5 * SHORT(hu_font['A' - HU_FONTSTART]->height) / 4); + + WI_DrawString(y, mapinfo->author); + } } - } - else if (wbs->nextmapinfo && wbs->nextmapinfo->levelpic[0]) - { - patch_t* lpic = V_CachePatchName(wbs->nextmapinfo->levelpic, PU_CACHE); + else if (mapinfo && mapinfo->levelpic[0]) + { + patch_t *patch = V_CachePatchName(mapinfo->levelpic, PU_CACHE); - if (SHORT(lpic->height) < SCREENHEIGHT) - y += (5 * SHORT(lpic->height)) / 4; + if (SHORT(patch->height) < SCREENHEIGHT) + { + y += (5 * SHORT(patch->height)) / 4; + } - // [Nugget] HUD/menu shadows - V_DrawPatchSH((SCREENWIDTH - SHORT(lpic->width))/2, y, lpic); - } - // [FG] prevent crashes for levels without name graphics - else if (wbs->next >= 0 && wbs->next < num_lnames && lnames[wbs->next] != NULL) - { - // draw level - // haleyjd: corrected to use height of entering, not map name - if (SHORT(lnames[wbs->next]->height) < SCREENHEIGHT) - y += (5 * SHORT(entering->height)) / 4; + V_DrawPatchSH((SCREENWIDTH - SHORT(patch->width)) / 2, y, patch); + } + // [FG] prevent crashes for levels without name graphics + else if (wbs->next >= 0 && wbs->next < num_lnames && lnames[wbs->next]) + { + // draw level + // haleyjd: corrected to use height of entering, not map name + if (SHORT(lnames[wbs->next]->height) < SCREENHEIGHT) + { + y += (5 * SHORT(entering->height)) / 4; + } - // [Nugget] HUD/menu shadows - V_DrawPatchSH((SCREENWIDTH - SHORT(lnames[wbs->next]->width))/2, - y, lnames[wbs->next]); - } + V_DrawPatchSH((SCREENWIDTH - SHORT(lnames[wbs->next]->width)) / 2, y, + lnames[wbs->next]); + } } - // ==================================================================== // WI_drawOnLnode // Purpose: Draw patches at a location based on episode/map @@ -934,9 +942,13 @@ static void WI_initAnimatedBack(boolean firstcall) } if (exitpic) - return; - if (enterpic && entering) - return; + { + return; + } + if (enterpic && state != StatCount) + { + return; + } if (gamemode == commercial) // no animation for DOOM2 return; @@ -985,9 +997,13 @@ static void WI_updateAnimatedBack(void) } if (exitpic) - return; + { + return; + } if (enterpic && state != StatCount) - return; + { + return; + } if (gamemode == commercial) return; @@ -1054,9 +1070,13 @@ static void WI_drawAnimatedBack(void) } if (exitpic) - return; + { + return; + } if (enterpic && state != StatCount) - return; + { + return; + } if (gamemode==commercial) //jff 4/25/98 Someone forgot commercial an enum return; @@ -1352,22 +1372,23 @@ static void WI_initShowNextLoc(void) if (gamemapinfo) { - if (gamemapinfo->endpic[0]) - { - G_WorldDone(); - return; - } - state = ShowNextLoc; + if (gamemapinfo->flags & MapInfo_EndGame) + { + G_WorldDone(); + return; + } - // episode change - if (wbs->epsd != wbs->nextep) - { - void WI_loadData(void); + state = ShowNextLoc; - wbs->epsd = wbs->nextep; - wbs->last = wbs->next - 1; - WI_loadData(); - } + // episode change + if (wbs->epsd != wbs->nextep) + { + void WI_loadData(void); + + wbs->epsd = wbs->nextep; + wbs->last = wbs->next - 1; + WI_loadData(); + } } state = ShowNextLoc; @@ -1406,9 +1427,9 @@ static void WI_drawShowNextLoc(void) int i; int last; - if (gamemapinfo && U_CheckField(gamemapinfo->endpic)) + if (gamemapinfo && gamemapinfo->flags & MapInfo_EndGame) { - return; + return; } WI_slamBackground(); @@ -2212,29 +2233,32 @@ static void WI_drawStats(void) V_DrawPatchSH(SP_STATSX, SP_STATSY+2*lh, sp_secret); WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+2*lh, cnt_secret[0]); + const boolean draw_partime = (W_IsIWADLump(maplump) || deh_pars || um_pars) && + (wbs->epsd < 3 || um_pars); + // [FG] choose x-position depending on width of time string + const boolean wide_total = (wbs->totaltimes / TICRATE > 61*59) || + (SP_TIMEX + SHORT(total->width) >= SCREENWIDTH/4); + const boolean wide_time = (wide_total && !draw_partime); + V_DrawPatchSH(SP_TIMEX, SP_TIMEY, witime); - WI_drawTime(SCREENWIDTH/2 - SP_TIMEX, SP_TIMEY, cnt_time, true); + WI_drawTime((wide_time ? SCREENWIDTH : SCREENWIDTH/2) - SP_TIMEX, + SP_TIMEY, cnt_time, true); // Ty 04/11/98: redid logic: should skip only if with pwad but // without deh patch // killough 2/22/98: skip drawing par times on pwads // Ty 03/17/98: unless pars changed with deh patch - if (W_IsIWADLump(maplump) || deh_pars || um_pars) - if (wbs->epsd < 3 || um_pars) - { - V_DrawPatchSH(SCREENWIDTH/2 + SP_TIMEX, SP_TIMEY, par); - WI_drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cnt_par, true); - } - - // [FG] draw total time alongside level time and par time + if (draw_partime) { - const boolean wide = (wbs->totaltimes / TICRATE > 61*59) || (SP_TIMEX + SHORT(total->width) >= SCREENWIDTH/4); - - V_DrawPatchSH(SP_TIMEX, SP_TIMEY + 16, total); - // [FG] choose x-position depending on width of time string - WI_drawTime((wide ? SCREENWIDTH : SCREENWIDTH/2) - SP_TIMEX, SP_TIMEY + 16, cnt_total_time, false); + V_DrawPatchSH(SCREENWIDTH/2 + SP_TIMEX, SP_TIMEY, par); + WI_drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cnt_par, true); } + + // [FG] draw total time alongside level time and par time + V_DrawPatchSH(SP_TIMEX, SP_TIMEY + 16, total); + WI_drawTime((wide_total ? SCREENWIDTH : SCREENWIDTH/2) - SP_TIMEX, + SP_TIMEY + 16, cnt_total_time, false); } // ====================================================================