diff --git a/libs/libopenmpt/SRB2NOTE.md b/libs/libopenmpt/SRB2NOTE.md index d664ddd7e..7eac9183b 100644 --- a/libs/libopenmpt/SRB2NOTE.md +++ b/libs/libopenmpt/SRB2NOTE.md @@ -1,6 +1,6 @@ # libopenmpt mingw-w64 binary info -Current built version as of 2019/05/23 is 0.4.4+r11531.pkg +Current built version as of 2019/09/27 is 0.4.7+r12088.pkg * mingw binaries (.dll): `bin/[x86 or x86_64]/mingw` * mingw import libraries (.dll.a): `lib/[x86 or x86_64]/mingw` diff --git a/libs/libopenmpt/bin/x86/libopenmpt.dll b/libs/libopenmpt/bin/x86/libopenmpt.dll index 0fc9e7656..8ad64fdfd 100644 Binary files a/libs/libopenmpt/bin/x86/libopenmpt.dll and b/libs/libopenmpt/bin/x86/libopenmpt.dll differ diff --git a/libs/libopenmpt/bin/x86/mingw/libopenmpt.dll b/libs/libopenmpt/bin/x86/mingw/libopenmpt.dll index 5fa364256..945b475e6 100644 Binary files a/libs/libopenmpt/bin/x86/mingw/libopenmpt.dll and b/libs/libopenmpt/bin/x86/mingw/libopenmpt.dll differ diff --git a/libs/libopenmpt/bin/x86/openmpt-mpg123.dll b/libs/libopenmpt/bin/x86/openmpt-mpg123.dll index 79148a40e..b068ddd0c 100644 Binary files a/libs/libopenmpt/bin/x86/openmpt-mpg123.dll and b/libs/libopenmpt/bin/x86/openmpt-mpg123.dll differ diff --git a/libs/libopenmpt/bin/x86/openmpt-ogg.dll b/libs/libopenmpt/bin/x86/openmpt-ogg.dll index 6b5a42e8f..a5b460063 100644 Binary files a/libs/libopenmpt/bin/x86/openmpt-ogg.dll and b/libs/libopenmpt/bin/x86/openmpt-ogg.dll differ diff --git a/libs/libopenmpt/bin/x86/openmpt-vorbis.dll b/libs/libopenmpt/bin/x86/openmpt-vorbis.dll index 486b30731..1ebed9b0e 100644 Binary files a/libs/libopenmpt/bin/x86/openmpt-vorbis.dll and b/libs/libopenmpt/bin/x86/openmpt-vorbis.dll differ diff --git a/libs/libopenmpt/bin/x86/openmpt-zlib.dll b/libs/libopenmpt/bin/x86/openmpt-zlib.dll index b6e028ab4..41bc22d2f 100644 Binary files a/libs/libopenmpt/bin/x86/openmpt-zlib.dll and b/libs/libopenmpt/bin/x86/openmpt-zlib.dll differ diff --git a/libs/libopenmpt/bin/x86_64/libopenmpt.dll b/libs/libopenmpt/bin/x86_64/libopenmpt.dll index 536492798..ffbb4b19a 100644 Binary files a/libs/libopenmpt/bin/x86_64/libopenmpt.dll and b/libs/libopenmpt/bin/x86_64/libopenmpt.dll differ diff --git a/libs/libopenmpt/bin/x86_64/mingw/libopenmpt.dll b/libs/libopenmpt/bin/x86_64/mingw/libopenmpt.dll index 3f6bea95f..018ae8276 100644 Binary files a/libs/libopenmpt/bin/x86_64/mingw/libopenmpt.dll and b/libs/libopenmpt/bin/x86_64/mingw/libopenmpt.dll differ diff --git a/libs/libopenmpt/bin/x86_64/openmpt-mpg123.dll b/libs/libopenmpt/bin/x86_64/openmpt-mpg123.dll index f96d446f2..9a0fca874 100644 Binary files a/libs/libopenmpt/bin/x86_64/openmpt-mpg123.dll and b/libs/libopenmpt/bin/x86_64/openmpt-mpg123.dll differ diff --git a/libs/libopenmpt/bin/x86_64/openmpt-ogg.dll b/libs/libopenmpt/bin/x86_64/openmpt-ogg.dll index 3fd951414..4bc1a336b 100644 Binary files a/libs/libopenmpt/bin/x86_64/openmpt-ogg.dll and b/libs/libopenmpt/bin/x86_64/openmpt-ogg.dll differ diff --git a/libs/libopenmpt/bin/x86_64/openmpt-vorbis.dll b/libs/libopenmpt/bin/x86_64/openmpt-vorbis.dll index 56047c82f..ebe8ef9b3 100644 Binary files a/libs/libopenmpt/bin/x86_64/openmpt-vorbis.dll and b/libs/libopenmpt/bin/x86_64/openmpt-vorbis.dll differ diff --git a/libs/libopenmpt/bin/x86_64/openmpt-zlib.dll b/libs/libopenmpt/bin/x86_64/openmpt-zlib.dll index 562d8e6a9..319b646ff 100644 Binary files a/libs/libopenmpt/bin/x86_64/openmpt-zlib.dll and b/libs/libopenmpt/bin/x86_64/openmpt-zlib.dll differ diff --git a/libs/libopenmpt/changelog.md b/libs/libopenmpt/changelog.md index 9847be119..0b7279558 100644 --- a/libs/libopenmpt/changelog.md +++ b/libs/libopenmpt/changelog.md @@ -5,6 +5,44 @@ Changelog {#changelog} For fully detailed change log, please see the source repository directly. This is just a high-level summary. +### libopenmpt 0.4.7 (2019-09-23) + + * [**Bug**] Compilation fix for various platforms that do not provide + `std::aligned_alloc` in C++17 mode. The problematic dependency has been + removed. This should fix build problems on MinGW, OpenBSD, Haiku, and others + for good. + + * J2B: Ignore notes with non-existing instrument (fixes Ending.j2b). + + * mpg123: Update to v1.25.13 (2019-08-24). + * ogg: Update to v1.3.4. (2019-08-31). + * flac: Update to v1.3.3. (2019-08-04). + +### libopenmpt 0.4.6 (2019-08-10) + + * [**Bug**] Compilation fix for OpenBSD. + * [**Bug**] Compilation fix for NO_PLUGINS being defined. + + * in_openmpt: Correct documentation. `openmpt-mpg123.dll` must be placed into + the Winamp directory. + + * Detect IT files unpacked with early UNMO3 versions. + + * mpg123: Update to v1.25.11 (2019-07-18). + * minimp3: Update to commit 977514a6dfc4960d819a103f43b358e58ac6c28f + (2019-07-24). + * miniz: Update to v2.1.0 (2019-05-05). + * stb_vorbis: Update to v1.17 (2019-08-09). + +### libopenmpt 0.4.5 (2019-05-27) + + * [**Sec**] Possible crash during playback due out-of-bounds read in XM and + MT2 files (r11608). + + * Breaking out of a sustain loop through Note-Off sometimes didn't continue in + the regular sample loop. + * Seeking did not stop notes playing with XM Key Off (Kxx) effect. + ### libopenmpt 0.4.4 (2019-04-07) * [**Bug**] Channel VU meters were swapped. diff --git a/libs/libopenmpt/inc/libopenmpt/libopenmpt_version.h b/libs/libopenmpt/inc/libopenmpt/libopenmpt_version.h index 5ca7f21d0..4bb90278c 100644 --- a/libs/libopenmpt/inc/libopenmpt/libopenmpt_version.h +++ b/libs/libopenmpt/inc/libopenmpt/libopenmpt_version.h @@ -19,7 +19,7 @@ /*! \brief libopenmpt minor version number */ #define OPENMPT_API_VERSION_MINOR 4 /*! \brief libopenmpt patch version number */ -#define OPENMPT_API_VERSION_PATCH 4 +#define OPENMPT_API_VERSION_PATCH 7 /*! \brief libopenmpt pre-release tag */ #define OPENMPT_API_VERSION_PREREL "" /*! \brief libopenmpt pre-release flag */ diff --git a/libs/libopenmpt/lib/x86/mingw/libopenmpt.dll.a b/libs/libopenmpt/lib/x86/mingw/libopenmpt.dll.a index e3fa0c58f..1d7637253 100644 Binary files a/libs/libopenmpt/lib/x86/mingw/libopenmpt.dll.a and b/libs/libopenmpt/lib/x86/mingw/libopenmpt.dll.a differ diff --git a/libs/libopenmpt/lib/x86_64/mingw/libopenmpt.dll.a b/libs/libopenmpt/lib/x86_64/mingw/libopenmpt.dll.a index 729403722..c6eda119f 100644 Binary files a/libs/libopenmpt/lib/x86_64/mingw/libopenmpt.dll.a and b/libs/libopenmpt/lib/x86_64/mingw/libopenmpt.dll.a differ diff --git a/src/b_bot.c b/src/b_bot.c index 17211b353..651aeb03d 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -140,6 +140,9 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd) void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward, boolean left, boolean right, boolean strafeleft, boolean straferight, boolean jump, boolean spin) { + // don't try to do stuff if your sonic is in a minecart or something + if (players[consoleplayer].powers[pw_carry]) + return; // Turn the virtual keypresses into ticcmd_t. if (twodlevel || mo->flags2 & MF2_TWOD) { if (players[consoleplayer].climbing @@ -218,7 +221,12 @@ boolean B_CheckRespawn(player_t *player) return false; // Low ceiling, do not want! - if (sonic->ceilingz - sonic->z < 2*sonic->height) + if (sonic->eflags & MFE_VERTICALFLIP) + { + if (sonic->z - sonic->floorz < (sonic->player->exiting ? 5 : 2)*sonic->height) + return false; + } + else if (sonic->ceilingz - sonic->z < (sonic->player->exiting ? 6 : 3)*sonic->height) return false; // If you're dead, wait a few seconds to respawn. @@ -252,11 +260,11 @@ void B_RespawnBot(INT32 playernum) y = sonic->y; if (sonic->eflags & MFE_VERTICALFLIP) { tails->eflags |= MFE_VERTICALFLIP; - z = sonic->z - FixedMul(512*FRACUNIT,sonic->scale); + z = sonic->z - (512*sonic->scale); if (z < sonic->floorz) z = sonic->floorz; } else { - z = sonic->z + sonic->height + FixedMul(512*FRACUNIT,sonic->scale); + z = sonic->z + sonic->height + (512*sonic->scale); if (z > sonic->ceilingz - sonic->height) z = sonic->ceilingz - sonic->height; } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index bd57c2481..1e69d371e 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -363,7 +363,7 @@ consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL consvar_t cv_pause = {"pausepermission", "Server", CV_NETVAR, pause_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_sleep = {"cpusleep", "-1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL}; +consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL}; INT16 gametype = GT_COOP; boolean splitscreen = false; @@ -1186,12 +1186,12 @@ static void SendNameAndColor(void) && !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name)) return; + players[consoleplayer].availabilities = R_GetSkinAvailabilities(); + // We'll handle it later if we're not playing. if (!Playing()) return; - players[consoleplayer].availabilities = R_GetSkinAvailabilities(); - // If you're not in a netgame, merely update the skin, color, and name. if (!netgame) { @@ -1304,12 +1304,12 @@ static void SendNameAndColor2(void) CV_StealthSet(&cv_playercolor2, cv_playercolor2.defaultvalue); } + players[secondplaya].availabilities = R_GetSkinAvailabilities(); + // We'll handle it later if we're not playing. if (!Playing()) return; - players[secondplaya].availabilities = R_GetSkinAvailabilities(); - // If you're not in a netgame, merely update the skin, color, and name. if (botingame) { diff --git a/src/d_player.h b/src/d_player.h index 69080bd9d..ff8c31203 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -234,7 +234,9 @@ typedef enum CR_ZOOMTUBE, CR_ROPEHANG, CR_MACESPIN, - CR_MINECART + CR_MINECART, + CR_ROLLOUT, + CR_PTERABYTE } carrytype_t; // pw_carry // Player powers. (don't edit this comment) diff --git a/src/dehacked.c b/src/dehacked.c index b37a8241d..d4f27b61c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2456,6 +2456,14 @@ static actionpointer_t actionpointers[] = {{A_SaloonDoorSpawn}, "A_SALOONDOORSPAWN"}, {{A_MinecartSparkThink}, "A_MINECARTSPARKTHINK"}, {{A_ModuloToState}, "A_MODULOTOSTATE"}, + {{A_LavafallRocks}, "A_LAVAFALLROCKS"}, + {{A_LavafallLava}, "A_LAVAFALLLAVA"}, + {{A_FallingLavaCheck}, "A_FALLINGLAVACHECK"}, + {{A_FireShrink}, "A_FIRESHRINK"}, + {{A_SpawnPterabytes}, "A_SPAWNPTERABYTES"}, + {{A_PterabyteHover}, "A_PTERABYTEHOVER"}, + {{A_RolloutSpawn}, "A_ROLLOUTSPAWN"}, + {{A_RolloutRock}, "A_ROLLOUTROCK"}, {{NULL}, "NONE"}, // This NULL entry must be the last in the list @@ -4627,6 +4635,22 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_CANARIVOREGAS_7", "S_CANARIVOREGAS_8", + // Pyre Fly + "S_PYREFLY_FLY", + "S_PYREFLY_BURN", + "S_PYREFIRE1", + "S_PYREFIRE2", + + // Pterabyte + "S_PTERABYTESPAWNER", + "S_PTERABYTEWAYPOINT", + "S_PTERABYTE_FLY1", + "S_PTERABYTE_FLY2", + "S_PTERABYTE_FLY3", + "S_PTERABYTE_FLY4", + "S_PTERABYTE_SWOOPDOWN", + "S_PTERABYTE_SWOOPUP", + // Boss Explosion "S_BOSSEXPLODE", @@ -5870,7 +5894,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Saloon door "S_SALOONDOOR", - "S_SALOONDOORTHINKER", + "S_SALOONDOORCENTER", // Train cameo "S_TRAINCAMEOSPAWNER_1", @@ -5903,6 +5927,28 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FLAMEJETFLAMEB2", "S_FLAMEJETFLAMEB3", + // Lavafall + "S_LAVAFALL_DORMANT", + "S_LAVAFALL_TELL", + "S_LAVAFALL_SHOOT", + "S_LAVAFALL_LAVA1", + "S_LAVAFALL_LAVA2", + "S_LAVAFALL_LAVA3", + "S_LAVAFALLROCK", + + // Rollout Rock + "S_ROLLOUTSPAWN", + "S_ROLLOUTROCK", + + // RVZ scenery + "S_BIGFERNLEAF", + "S_BIGFERN1", + "S_BIGFERN2", + "S_JUNGLEPALM", + "S_TORCHFLOWER", + "S_WALLVINE_LONG", + "S_WALLVINE_SHORT", + // Trapgoyles "S_TRAPGOYLE", "S_TRAPGOYLE_CHECK", @@ -5954,6 +6000,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_LAMPPOST1", // normal "S_LAMPPOST2", // with snow "S_HANGSTAR", + "S_MISTLETOE", // Xmas GFZ bushes "S_XMASBLUEBERRYBUSH", "S_XMASBERRYBUSH", @@ -5961,6 +6008,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // FHZ "S_FHZICE1", "S_FHZICE2", + "S_ROSY_IDLE1", + "S_ROSY_IDLE2", + "S_ROSY_IDLE3", + "S_ROSY_IDLE4", + "S_ROSY_JUMP", + "S_ROSY_WALK", + "S_ROSY_HUG", + "S_ROSY_PAIN", + "S_ROSY_STND", + "S_ROSY_UNHAPPY", // Halloween Scenery // Pumpkins @@ -6632,6 +6689,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SPLISH8", "S_SPLISH9", + // Lava splish + "S_LAVASPLISH", + // added water splash "S_SPLASH1", "S_SPLASH2", @@ -7282,6 +7342,11 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_UNIBALL", // Unidus Ball "MT_CANARIVORE", // Canarivore "MT_CANARIVORE_GAS", // Canarivore gas + "MT_PYREFLY", // Pyre Fly + "MT_PYREFLY_FIRE", // Pyre Fly fire + "MT_PTERABYTESPAWNER", // Pterabyte spawner + "MT_PTERABYTEWAYPOINT", // Pterabyte waypoint + "MT_PTERABYTE", // Pterabyte // Generic Boss Items "MT_BOSSEXPLODE", @@ -7610,7 +7675,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_MINECARTSIDEMARK", "MT_MINECARTSPARK", "MT_SALOONDOOR", - "MT_SALOONDOORTHINKER", + "MT_SALOONDOORCENTER", "MT_TRAINCAMEOSPAWNER", "MT_TRAINSEG", "MT_TRAINDUSTSPAWNER", @@ -7627,6 +7692,20 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_FLAMEJETFLAMEB", // Blade's flame + "MT_LAVAFALL", + "MT_LAVAFALL_LAVA", + "MT_LAVAFALLROCK", + + "MT_ROLLOUTSPAWN", + "MT_ROLLOUTROCK", + + "MT_BIGFERNLEAF", + "MT_BIGFERN", + "MT_JUNGLEPALM", + "MT_TORCHFLOWER", + "MT_WALLVINE_LONG", + "MT_WALLVINE_SHORT", + // Dark City Scenery // Egg Rock Scenery @@ -7658,6 +7737,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_LAMPPOST1", // normal "MT_LAMPPOST2", // with snow "MT_HANGSTAR", + "MT_MISTLETOE", // Xmas GFZ bushes "MT_XMASBLUEBERRYBUSH", "MT_XMASBERRYBUSH", @@ -7665,6 +7745,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // FHZ "MT_FHZICE1", "MT_FHZICE2", + "MT_ROSY", + "MT_CDLHRT", // Halloween Scenery // Pumpkins @@ -7793,6 +7875,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_RAIN", // Rain "MT_SNOWFLAKE", // Snowflake "MT_SPLISH", // Water splish! + "MT_LAVASPLISH", // Lava splish! "MT_SMOKE", "MT_SMALLBUBBLE", // small bubble "MT_MEDIUMBUBBLE", // medium bubble @@ -8618,6 +8701,8 @@ struct { {"CR_ROPEHANG",CR_ROPEHANG}, {"CR_MACESPIN",CR_MACESPIN}, {"CR_MINECART",CR_MINECART}, + {"CR_ROLLOUT", CR_ROLLOUT}, + {"CR_PTERABYTE",CR_PTERABYTE}, // Ring weapons (ringweapons_t) // Useful for A_GiveWeapon diff --git a/src/f_finale.c b/src/f_finale.c index 5d8c97c02..eb1415042 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -638,6 +638,7 @@ static void F_IntroDrawScene(void) } else { + menuanimtimer = animtimer; // Reusing this variable for the intro to fix the scrolling sky, better than changing the function around. F_SkyScroll(80*4, 0, "TITLESKY"); if (timetonext == 6) { diff --git a/src/g_input.c b/src/g_input.c index 45c517e1a..afefbcc3b 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -709,8 +709,8 @@ void G_DefineDefaultControls(void) for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0) { - gamecontroldefault[i][gc_weaponnext ][0] = 'e'; - gamecontroldefault[i][gc_weaponprev ][0] = 'q'; + gamecontroldefault[i][gc_weaponnext ][0] = KEY_MOUSEWHEELUP+0; + gamecontroldefault[i][gc_weaponprev ][0] = KEY_MOUSEWHEELDOWN+0; gamecontroldefault[i][gc_wepslot1 ][0] = '1'; gamecontroldefault[i][gc_wepslot2 ][0] = '2'; gamecontroldefault[i][gc_wepslot3 ][0] = '3'; diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index e2fa90eb0..e0507bc70 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -47,6 +47,7 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal, RGBA_t *pgamma); EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl); EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color); EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags); +EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform); EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); @@ -89,6 +90,7 @@ struct hwdriver_s FinishUpdate pfnFinishUpdate; Draw2DLine pfnDraw2DLine; DrawPolygon pfnDrawPolygon; + RenderSkyDome pfnRenderSkyDome; SetBlend pfnSetBlend; ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index b613fdae1..f4637ff7f 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -180,6 +180,8 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_UNID &lspr[NOLIGHT], // SPR_CANA &lspr[NOLIGHT], // SPR_CANG + &lspr[NOLIGHT], // SPR_PYRE + &lspr[NOLIGHT], // SPR_PTER // Generic Boos Items &lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes @@ -260,6 +262,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_WSPB &lspr[NOLIGHT], // SPR_STPT &lspr[NOLIGHT], // SPR_BMNE + &lspr[NOLIGHT], // SPR_PUMI // Monitor Boxes &lspr[NOLIGHT], // SPR_MSTV @@ -377,6 +380,10 @@ light_t *t_lspr[NUMSPRITES] = // Red Volcano Scenery &lspr[REDBALL_L], // SPR_FLME &lspr[REDBALL_L], // SPR_DFLM + &lspr[NOLIGHT], // SPR_LFAL + &lspr[NOLIGHT], // SPR_JPLA + &lspr[NOLIGHT], // SPR_TFLO + &lspr[NOLIGHT], // SPR_WVIN // Dark City Scenery @@ -388,7 +395,9 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_XMS3 &lspr[NOLIGHT], // SPR_XMS4 &lspr[NOLIGHT], // SPR_XMS5 + &lspr[NOLIGHT], // SPR_XMS6 &lspr[NOLIGHT], // SPR_FHZI + &lspr[NOLIGHT], // SPR_ROSY // Halloween Scenery &lspr[RINGLIGHT_L], // SPR_PUMK @@ -474,6 +483,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_RAIN &lspr[NOLIGHT], // SPR_SNO1 &lspr[NOLIGHT], // SPR_SPLH + &lspr[NOLIGHT], // SPR_LSPL &lspr[NOLIGHT], // SPR_SPLA &lspr[NOLIGHT], // SPR_SMOK &lspr[NOLIGHT], // SPR_BUBL diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 4a075d376..f2658707d 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5454,7 +5454,7 @@ static void HWR_AddSprites(sector_t *sec) #ifdef HWPRECIP precipmobj_t *precipthing; #endif - fixed_t approx_dist, limit_dist; + fixed_t approx_dist, limit_dist, hoop_limit_dist; // BSP is traversed by subsector. // A sector might have been split into several @@ -5471,7 +5471,9 @@ static void HWR_AddSprites(sector_t *sec) // Handle all things in sector. // If a limit exists, handle things a tiny bit different. - if ((limit_dist = (fixed_t)((maptol & TOL_NIGHTS) ? cv_drawdist_nights.value : cv_drawdist.value) << FRACBITS)) + limit_dist = (fixed_t)(cv_drawdist.value) << FRACBITS; + hoop_limit_dist = (fixed_t)(cv_drawdist_nights.value) << FRACBITS; + if (limit_dist || hoop_limit_dist) { for (thing = sec->thinglist; thing; thing = thing->snext) { @@ -5480,8 +5482,16 @@ static void HWR_AddSprites(sector_t *sec) approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); - if (approx_dist > limit_dist) - continue; + if (thing->sprite == SPR_HOOP) + { + if (hoop_limit_dist && approx_dist > hoop_limit_dist) + continue; + } + else + { + if (limit_dist && approx_dist > limit_dist) + continue; + } HWR_ProjectSprite(thing); } @@ -5711,6 +5721,13 @@ static void HWR_ProjectSprite(mobj_t *thing) return; } + if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) + { + // bodge support - not nearly as comprehensive as r_things.c, but better than nothing + if (thing->tracer->sprite == SPR_NULL || thing->tracer->flags2 & MF2_DONTDRAW) + return; + } + // store information in a vissprite vis = HWR_NewVisSprite(); vis->x1 = x1; @@ -5724,7 +5741,7 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->z2 = z2; //Hurdler: 25/04/2000: now support colormap in hardware mode - if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" + if ((vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); @@ -5869,86 +5886,122 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) // ========================================================================== // // ========================================================================== -static void HWR_DrawSkyBackground(void) +static void HWR_DrawSkyBackground(player_t *player) { - FOutVector v[4]; - angle_t angle; - float dimensionmultiply; - float aspectratio; - float angleturn; - - HWR_GetTexture(texturetranslation[skytexture]); - aspectratio = (float)vid.width/(float)vid.height; - - //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 - // because it's called just after clearing the screen - // and thus, the near clipping plane is set to 3.99 - // Sryder: Just use the near clipping plane value then - - // 3--2 - // | /| - // |/ | - // 0--1 - v[0].x = v[3].x = -ZCLIP_PLANE-1; - v[1].x = v[2].x = ZCLIP_PLANE+1; - v[0].y = v[1].y = -ZCLIP_PLANE-1; - v[2].y = v[3].y = ZCLIP_PLANE+1; - - v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1; - - // X - - // NOTE: This doesn't work right with texture widths greater than 1024 - // software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly - // The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture - - angle = (dup_viewangle + gr_xtoviewangle[0]); - - dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); - - v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left - v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f) - // use +angle and -1.0f above instead if you wanted old backwards behavior - - // Y - angle = aimingangle; - dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio)); - - if (splitscreen) + if (cv_grskydome.value) { - dimensionmultiply *= 2; - angle *= 2; - } + FTransform transform; + const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); + postimg_t *type; - // Middle of the sky should always be at angle 0 - // need to keep correct aspect ratio with X - if (atransform.flip) - { - // During vertical flip the sky should be flipped and it's y movement should also be flipped obviously - v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top - v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f) + if (splitscreen && player == &players[secondarydisplayplayer]) + type = &postimgtype2; + else + type = &postimgtype; + + memset(&transform, 0x00, sizeof(FTransform)); + + //04/01/2000: Hurdler: added for T&L + // It should replace all other gr_viewxxx when finished + transform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + transform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + + if (*type == postimg_flip) + transform.flip = true; + else + transform.flip = false; + + transform.scalex = 1; + transform.scaley = (float)vid.width/vid.height; + transform.scalez = 1; + transform.fovxangle = fpov; // Tails + transform.fovyangle = fpov; // Tails + transform.splitscreen = splitscreen; + + HWR_GetTexture(texturetranslation[skytexture]); + HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, transform); } else { - v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom - v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f) - } + FOutVector v[4]; + angle_t angle; + float dimensionmultiply; + float aspectratio; + float angleturn; - angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; + HWR_GetTexture(texturetranslation[skytexture]); + aspectratio = (float)vid.width/(float)vid.height; - if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa - { - angle = InvAngle(angle); - v[3].tow = v[2].tow += ((float) angle / angleturn); - v[0].tow = v[1].tow += ((float) angle / angleturn); - } - else - { - v[3].tow = v[2].tow -= ((float) angle / angleturn); - v[0].tow = v[1].tow -= ((float) angle / angleturn); - } + //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 + // because it's called just after clearing the screen + // and thus, the near clipping plane is set to 3.99 + // Sryder: Just use the near clipping plane value then - HWD.pfnDrawPolygon(NULL, v, 4, 0); + // 3--2 + // | /| + // |/ | + // 0--1 + v[0].x = v[3].x = -ZCLIP_PLANE-1; + v[1].x = v[2].x = ZCLIP_PLANE+1; + v[0].y = v[1].y = -ZCLIP_PLANE-1; + v[2].y = v[3].y = ZCLIP_PLANE+1; + + v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1; + + // X + + // NOTE: This doesn't work right with texture widths greater than 1024 + // software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly + // The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture + + angle = (dup_viewangle + gr_xtoviewangle[0]); + + dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); + + v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left + v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f) + // use +angle and -1.0f above instead if you wanted old backwards behavior + + // Y + angle = aimingangle; + dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio)); + + if (splitscreen) + { + dimensionmultiply *= 2; + angle *= 2; + } + + // Middle of the sky should always be at angle 0 + // need to keep correct aspect ratio with X + if (atransform.flip) + { + // During vertical flip the sky should be flipped and it's y movement should also be flipped obviously + v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top + v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f) + } + else + { + v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom + v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f) + } + + angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; + + if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa + { + angle = InvAngle(angle); + v[3].tow = v[2].tow += ((float) angle / angleturn); + v[0].tow = v[1].tow += ((float) angle / angleturn); + } + else + { + v[3].tow = v[2].tow -= ((float) angle / angleturn); + v[0].tow = v[1].tow -= ((float) angle / angleturn); + } + + HWD.pfnDrawPolygon(NULL, v, 4, 0); + } } @@ -6100,7 +6153,7 @@ if (0) } if (drawsky) - HWR_DrawSkyBackground(); + HWR_DrawSkyBackground(player); //Hurdler: it doesn't work in splitscreen mode drawsky = splitscreen; @@ -6317,7 +6370,7 @@ if (0) } if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox - HWR_DrawSkyBackground(); + HWR_DrawSkyBackground(player); //Hurdler: it doesn't work in splitscreen mode drawsky = splitscreen; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index f8524990f..31e97cc13 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -98,6 +98,7 @@ extern consvar_t cv_voodoocompatibility; extern consvar_t cv_grfovchange; extern consvar_t cv_grsolvetjoin; extern consvar_t cv_grspritebillboarding; +extern consvar_t cv_grskydome; extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index cd1b957f0..b847fdbc3 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1277,6 +1277,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) // MD2 colormap fix // colormap test + if (spr->mobj->subsector) { sector_t *sector = spr->mobj->subsector->sector; UINT8 lightlevel = 255; @@ -1308,6 +1309,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr) else Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); } + else + Surf.FlatColor.rgba = 0xFFFFFFFF; // Look at HWR_ProjectSprite for more { diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index dfee19857..ac989613a 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1427,6 +1427,219 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, Clamp2D(GL_TEXTURE_WRAP_T); } +typedef struct vbo_vertex_s +{ + float x, y, z; + float u, v; + unsigned char r, g, b, a; +} vbo_vertex_t; + +typedef struct +{ + int mode; + int vertexcount; + int vertexindex; + int use_texture; +} GLSkyLoopDef; + +typedef struct +{ + int id; + int rows, columns; + int loopcount; + GLSkyLoopDef *loops; + vbo_vertex_t *data; +} GLSkyVBO; + +// The texture offset to be applied to the texture coordinates in SkyVertex(). +static int rows, columns; +static boolean yflip; +static int texw, texh; +static boolean foglayer; +static float delta = 0.0f; + +static int gl_sky_detail = 16; + +static INT32 lasttex = -1; + +#define MAP_COEFF 128.0f + +static void SkyVertex(vbo_vertex_t *vbo, int r, int c) +{ + const float radians = (M_PIl / 180.0f); + const float scale = 10000.0f; + const float maxSideAngle = 60.0f; + + float topAngle = (c / (float)columns * 360.0f); + float sideAngle = (maxSideAngle * (rows - r) / rows); + float height = sin(sideAngle * radians); + float realRadius = scale * cos(sideAngle * radians); + float x = realRadius * cos(topAngle * radians); + float y = (!yflip) ? scale * height : -scale * height; + float z = realRadius * sin(topAngle * radians); + float timesRepeat = (4 * (256.0f / texw)); + if (fpclassify(timesRepeat) == FP_ZERO) + timesRepeat = 1.0f; + + if (!foglayer) + { + vbo->r = 255; + vbo->g = 255; + vbo->b = 255; + vbo->a = (r == 0 ? 0 : 255); + + // And the texture coordinates. + vbo->u = (-timesRepeat * c / (float)columns); + if (!yflip) // Flipped Y is for the lower hemisphere. + vbo->v = (r / (float)rows) + 0.5f; + else + vbo->v = 1.0f + ((rows - r) / (float)rows) + 0.5f; + } + + if (r != 4) + { + y += 300.0f; + } + + // And finally the vertex. + vbo->x = x; + vbo->y = y + delta; + vbo->z = z; +} + +static GLSkyVBO sky_vbo; + +static void gld_BuildSky(int row_count, int col_count) +{ + int c, r; + vbo_vertex_t *vertex_p; + int vertex_count = 2 * row_count * (col_count * 2 + 2) + col_count * 2; + + GLSkyVBO *vbo = &sky_vbo; + + if ((vbo->columns != col_count) || (vbo->rows != row_count)) + { + free(vbo->loops); + free(vbo->data); + memset(vbo, 0, sizeof(&vbo)); + } + + if (!vbo->data) + { + memset(vbo, 0, sizeof(&vbo)); + vbo->loops = malloc((row_count * 2 + 2) * sizeof(vbo->loops[0])); + // create vertex array + vbo->data = malloc(vertex_count * sizeof(vbo->data[0])); + } + + vbo->columns = col_count; + vbo->rows = row_count; + + vertex_p = &vbo->data[0]; + vbo->loopcount = 0; + + for (yflip = 0; yflip < 2; yflip++) + { + vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_FAN; + vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0]; + vbo->loops[vbo->loopcount].vertexcount = col_count; + vbo->loops[vbo->loopcount].use_texture = false; + vbo->loopcount++; + + delta = 0.0f; + foglayer = true; + for (c = 0; c < col_count; c++) + { + SkyVertex(vertex_p, 1, c); + vertex_p->r = 255; + vertex_p->g = 255; + vertex_p->b = 255; + vertex_p->a = 255; + vertex_p++; + } + foglayer = false; + + delta = (yflip ? 5.0f : -5.0f) / MAP_COEFF; + + for (r = 0; r < row_count; r++) + { + vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_STRIP; + vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0]; + vbo->loops[vbo->loopcount].vertexcount = 2 * col_count + 2; + vbo->loops[vbo->loopcount].use_texture = true; + vbo->loopcount++; + + for (c = 0; c <= col_count; c++) + { + SkyVertex(vertex_p++, r + (yflip ? 1 : 0), (c ? c : 0)); + SkyVertex(vertex_p++, r + (yflip ? 0 : 1), (c ? c : 0)); + } + } + } +} + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +static void RenderDome(INT32 skytexture) +{ + int i, j; + GLSkyVBO *vbo = &sky_vbo; + + pglRotatef(270.0f, 0.0f, 1.0f, 0.0f); + + rows = 4; + columns = 4 * gl_sky_detail; + + if (lasttex != skytexture) + { + lasttex = skytexture; + gld_BuildSky(rows, columns); + } + + pglScalef(1.0f, (float)texh / 230.0f, 1.0f); + + for (j = 0; j < 2; j++) + { + for (i = 0; i < vbo->loopcount; i++) + { + GLSkyLoopDef *loop = &vbo->loops[i]; + + if (j == 0 ? loop->use_texture : !loop->use_texture) + continue; + else + { + int k; + pglBegin(loop->mode); + for (k = loop->vertexindex; k < (loop->vertexindex + loop->vertexcount); k++) + { + vbo_vertex_t *v = &vbo->data[k]; + if (loop->use_texture) + pglTexCoord2f(v->u, v->v); + pglColor4f(v->r, v->g, v->b, v->a); + pglVertex3f(v->x, v->y, v->z); + } + pglEnd(); + } + } + } + + pglScalef(1.0f, 1.0f, 1.0f); + pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); +} + +EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform) +{ + SetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated); + SetTransform(&transform); + texw = texture_width; + texh = texture_height; + RenderDome(tex); + SetBlend(0); +} // ========================================================================== // diff --git a/src/info.c b/src/info.c index 5fb4d3070..dd5338ef0 100644 --- a/src/info.c +++ b/src/info.c @@ -68,6 +68,8 @@ char sprnames[NUMSPRITES + 1][5] = "UNID", // Unidus "CANA", // Canarivore "CANG", // Canarivore gas + "PYRE", // Pyre Fly + "PTER", // Pterabyte // Generic Boss Items "JETF", // Boss jet fumes @@ -149,6 +151,7 @@ char sprnames[NUMSPRITES + 1][5] = "WSPB", // Wall spike base "STPT", // Starpost "BMNE", // Big floating mine + "PUMI", // Rollout Rock // Monitor Boxes "MSTV", // MiSc TV sprites @@ -263,7 +266,6 @@ char sprnames[NUMSPRITES + 1][5] = "ADST", // Arid dust "MCRT", // Minecart "MCSP", // Minecart spark - "NON2", // Saloon door thinker "SALD", // Saloon door "TRAE", // Train cameo locomotive "TRAI", // Train cameo wagon @@ -272,6 +274,10 @@ char sprnames[NUMSPRITES + 1][5] = // Red Volcano Scenery "FLME", // Flame jet "DFLM", // Blade's flame + "LFAL", // Lavafall + "JPLA", // Jungle palm + "TFLO", // Torch flower + "WVIN", // Wall vines // Dark City Scenery @@ -283,7 +289,9 @@ char sprnames[NUMSPRITES + 1][5] = "XMS3", // Snowman "XMS4", // Lamppost "XMS5", // Hanging Star + "XMS6", // Mistletoe "FHZI", // FHZ ice + "ROSY", // Halloween Scenery "PUMK", // Pumpkins @@ -369,6 +377,7 @@ char sprnames[NUMSPRITES + 1][5] = "RAIN", // Rain "SNO1", // Snowflake "SPLH", // Water Splish + "LSPL", // Lava Splish "SPLA", // Water Splash "SMOK", "BUBL", // Bubble @@ -1184,6 +1193,22 @@ state_t states[NUMSTATES] = {SPR_CANG, 0|FF_TRANS80, 10, {NULL}, 0, 0, S_CANARIVOREGAS_8}, // S_CANARIVOREGAS_7 {SPR_CANG, 0|FF_TRANS90, 10, {NULL}, 0, 0, S_NULL}, // S_CANARIVOREGAS_8 + // Pyre Fly + {SPR_PYRE, FF_ANIMATE, -1, {NULL}, 3, 2, S_NULL}, // S_PYREFLY_FLY + {SPR_PYRE, 4|FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 3, 2, S_NULL}, // S_PYREFLY_BURN + {SPR_FLAM, FF_FULLBRIGHT, 10, {NULL}, 0, 0, S_PYREFIRE2}, // S_PYREFIRE1 + {SPR_FLAM, 1|FF_FULLBRIGHT, 10, {A_FireShrink}, 0, 16, S_NULL}, // S_PYREFIRE2 + + // Pterabyte + {SPR_NULL, 0, -1, {A_SpawnPterabytes}, 0, 0, S_PTERABYTESPAWNER}, // S_PTERABYTESPAWNER + {SPR_NULL, 0, 1, {A_PterabyteHover}, 0, 0, S_PTERABYTEWAYPOINT}, // S_PTERABYTEWAYPOINT + {SPR_PTER, 0, 6, {NULL}, 0, 0, S_PTERABYTE_FLY2}, // S_PTERABYTE_FLY1 + {SPR_PTER, 1, 2, {NULL}, 0, 0, S_PTERABYTE_FLY3}, // S_PTERABYTE_FLY2 + {SPR_PTER, 2, 6, {NULL}, 0, 0, S_PTERABYTE_FLY4}, // S_PTERABYTE_FLY3 + {SPR_PTER, 3, 2, {NULL}, 0, 0, S_PTERABYTE_FLY1}, // S_PTERABYTE_FLY4 + {SPR_PTER, 4, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPDOWN}, // S_PTERABYTE_SWOOPDOWN + {SPR_PTER, 0, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPUP}, // S_PTERABYTE_SWOOPUP + // Boss Explosion {SPR_BOM2, FF_FULLBRIGHT|FF_ANIMATE, (5*7), {NULL}, 6, 5, S_NULL}, // S_BOSSEXPLODE @@ -2462,8 +2487,8 @@ state_t states[NUMSTATES] = {SPR_MCSP, FF_FULLBRIGHT, 1, {A_MinecartSparkThink}, 0, 0, S_MINECARTSPARK}, // S_MINECARTSPARK // Saloon door - {SPR_SALD, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SALOONDOOR - {SPR_NON2, 0, -1, {A_SaloonDoorSpawn}, 0, 0, S_NULL}, // S_SALONDOORTHINKER + {SPR_SALD, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SALOONDOOR + {SPR_NULL, 0, -1, {A_SaloonDoorSpawn}, MT_SALOONDOOR, 48, S_NULL}, // S_SALOONDOORCENTER // Train cameo {SPR_NULL, 0, -1, {NULL}, 0, 0, S_TRAINCAMEOSPAWNER_2}, // S_TRAINCAMEOSPAWNER_1 @@ -2498,6 +2523,28 @@ state_t states[NUMSTATES] = {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40, 1, {A_MoveRelative}, 0, 7, S_FLAMEJETFLAMEB3}, // S_FLAMEJETFLAMEB2 {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|FF_ANIMATE, (12*7), {NULL}, 7, 12, S_NULL}, // S_FLAMEJETFLAMEB3 + // Lavafall + {SPR_LFAL, 5, 1, {NULL}, 0, 0, S_LAVAFALL_DORMANT}, // S_LAVAFALL_DORMANT + {SPR_LFAL, 6|FF_ANIMATE, 4, {A_LavafallRocks}, 1, 2, S_LAVAFALL_TELL}, // S_LAVAFALL_TELL + {SPR_LFAL, 9|FF_FULLBRIGHT|FF_ANIMATE, 2, {A_LavafallLava}, 1, 1, S_LAVAFALL_SHOOT}, // S_LAVAFALL_SHOOT + {SPR_LFAL, FF_FULLBRIGHT, 1, {A_FallingLavaCheck}, 0, 0, S_LAVAFALL_LAVA2}, // S_LAVAFALL_LAVA1 + {SPR_LFAL, FF_FULLBRIGHT, 1, {A_FallingLavaCheck}, 0, 0, S_LAVAFALL_LAVA1}, // S_LAVAFALL_LAVA2 + {SPR_LFAL, 2|FF_FULLBRIGHT|FF_ANIMATE, 9, {NULL}, 2, 3, S_NULL}, // S_LAVAFALL_LAVA3 + {SPR_LFAL, 11|FF_ANIMATE|FF_RANDOMANIM, 12, {NULL}, 3, 3, S_LAVAFALLROCK}, // S_LAVAFALLROCK + + // Rollout Rock + {SPR_NULL, 0, 1, {A_RolloutSpawn}, 256*FRACUNIT, MT_ROLLOUTROCK, S_ROLLOUTSPAWN}, // S_ROLLOUTSPAWN + {SPR_PUMI, 0, 1, {A_RolloutRock}, 63*FRACUNIT/64, 7*FRACUNIT/10, S_ROLLOUTROCK}, // S_ROLLOUTROCK + + // RVZ scenery + {SPR_JPLA, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BIGFERNLEAF + {SPR_JPLA, 1, 1, {NULL}, 0, 0, S_BIGFERN2}, // S_BIGFERN1 + {SPR_JPLA, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BIGFERN2 + {SPR_JPLA, 2, -1, {NULL}, 0, 0, S_NULL}, // S_JUNGLEPALM + {SPR_TFLO, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_TORCHFLOWER}, // S_TORCHFLOWER + {SPR_WVIN, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_LONG + {SPR_WVIN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_SHORT + // Trapgoyles {SPR_GARG, 0, 67, {NULL}, 0, 0, S_TRAPGOYLE_CHECK}, // S_TRAPGOYLE {SPR_GARG, 0, 3, {NULL}, 0, 0, S_TRAPGOYLE_FIRE1}, // S_TRAPGOYLE_CHECK @@ -2552,6 +2599,7 @@ state_t states[NUMSTATES] = {SPR_XMS4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LAMPPOST1 {SPR_XMS4, 1, -1, {NULL}, 0, 0, S_NULL}, // S_LAMPPOST2 {SPR_XMS5, 0, -1, {NULL}, 0, 0, S_NULL}, // S_HANGSTAR + {SPR_XMS6, 0, -1, {NULL}, 0, 0, S_NULL}, // S_MISTLETOE // Xmas GFZ bushes {SPR_BUS3, 1, -1, {NULL}, 0, 0, S_NULL}, // S_XMASBLUEBERRYBUSH {SPR_BUS1, 1, -1, {NULL}, 0, 0, S_NULL}, // S_XMASBERRYBUSH @@ -2559,6 +2607,16 @@ state_t states[NUMSTATES] = // FHZ {SPR_FHZI, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FHZICE1 {SPR_FHZI, 1, -1, {NULL}, 0, 0, S_NULL}, // S_FHZICE2 + {SPR_ROSY, 16, 8, {NULL}, 0, 0, S_ROSY_IDLE2}, // S_ROSY_IDLE1 + {SPR_ROSY, 17, 4, {NULL}, 0, 0, S_ROSY_IDLE3}, // S_ROSY_IDLE2 + {SPR_ROSY, 18, 8, {NULL}, 0, 0, S_ROSY_IDLE4}, // S_ROSY_IDLE3 + {SPR_ROSY, 17, 4, {NULL}, 0, 0, S_ROSY_IDLE1}, // S_ROSY_IDLE4 + {SPR_ROSY, 14, -1, {NULL}, 1, 0, S_NULL}, // S_ROSY_JUMP + {SPR_ROSY, 5, -1, {NULL}, 7, 0, S_NULL}, // S_ROSY_WALK + {SPR_ROSY, 19, -1, {NULL}, 0, 0, S_NULL}, // S_ROSY_HUG + {SPR_ROSY, 13, -1, {NULL}, 0, 0, S_NULL}, // S_ROSY_PAIN + {SPR_ROSY, 1|FF_ANIMATE, -1, {NULL}, 3, 16, S_NULL}, // S_ROSY_STND + {SPR_ROSY, 20|FF_ANIMATE, TICRATE, {NULL}, 3, 4, S_ROSY_WALK}, // S_ROSY_UNHAPPY // Halloween Scenery // Pumpkins @@ -3234,6 +3292,9 @@ state_t states[NUMSTATES] = {SPR_SPLH, FF_TRANS50|7, 2, {NULL}, 0, 0, S_SPLISH9}, // S_SPLISH8 {SPR_SPLH, FF_TRANS50|8, 2, {NULL}, 0, 0, S_NULL}, // S_SPLISH9 + // Lava splish + {SPR_LSPL, FF_ANIMATE, 16, {NULL}, 7, 2, S_NULL}, // S_LAVASPLISH + // Water Splash {SPR_SPLA, FF_TRANS50 , 3, {NULL}, 0, 0, S_SPLASH2}, // S_SPLASH1 {SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3}, // S_SPLASH2 @@ -3545,7 +3606,7 @@ state_t states[NUMSTATES] = // Puma (Mario fireball) {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_START2}, // S_PUMA_START1 - {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_PlaySound}, sfx_s3k70, 1, S_PUMA_UP1}, // S_PUMA_START2 + {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_PlaySound}, sfx_s3k70, 1 + (1<<16), S_PUMA_UP1}, // S_PUMA_START2 {SPR_PUMA, FF_FULLBRIGHT , 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP2}, // S_PUMA_UP1 {SPR_PUMA, FF_FULLBRIGHT|1, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP3}, // S_PUMA_UP2 {SPR_PUMA, FF_FULLBRIGHT|2, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP1}, // S_PUMA_UP3 @@ -4780,7 +4841,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_SCENERY|MF_PAIN|MF_NOCLIPHEIGHT|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + MF_SCENERY|MF_PAIN|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags S_SNAPPER_LEGRAISE // raisestate }, @@ -4807,7 +4868,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_PAIN|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + MF_PAIN|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags S_NULL // raisestate }, @@ -5027,6 +5088,141 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_PYREFLY + 136, // doomednum + S_PYREFLY_FLY, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_PYREFLY_BURN, // meleestate + S_NULL, // missilestate + S_XPLD_FLICKY, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 1, // speed + 24*FRACUNIT, // radius + 34*FRACUNIT, // height + 0, // display offset + DMG_FIRE, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_SLIDEME, // flags + S_NULL // raisestate + }, + + { // MT_PYREFLY_FIRE + -1, // doomednum + S_PYREFIRE1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 24*FRACUNIT, // radius + 34*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOBLOCKMAP|MF_FIRE|MF_PAIN, // flags + S_NULL // raisestate + }, + + { // MT_PTERABYTESPAWNER + 135, // doomednum + S_PTERABYTESPAWNER, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPTHING|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_PTERABYTEWAYPOINT + -1, // doomednum + S_PTERABYTEWAYPOINT, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 4*FRACUNIT, // speed + 24*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPTHING|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_PTERABYTE + -1, // doomednum + S_PTERABYTE_FLY1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_pscree, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_XPLD_FLICKY, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 4*FRACUNIT, // speed + 24*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_NOGRAVITY|MF_SLIDEME, // flags + S_NULL // raisestate + }, + { // MT_BOSSEXPLODE -1, // doomednum S_BOSSEXPLODE, // spawnstate @@ -12199,7 +12395,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_ENEMY|MF_PUSHABLE, // flags + MF_SOLID|MF_SHOOTABLE|MF_PUSHABLE, // flags S_NULL // raisestate }, @@ -12527,9 +12723,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_SALOONDOORTHINKER + { // MT_SALOONDOORCENTER 1221, // doomednum - S_SALOONDOORTHINKER, // spawnstate + S_SALOONDOORCENTER, // spawnstate 1, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -12550,7 +12746,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags + MF_SOLID|MF_NOGRAVITY|MF_RUNSPAWNFUNC|MF_PAPERCOLLISION|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -12851,6 +13047,303 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_LAVAFALL + 1304, // doomednum + S_LAVAFALL_DORMANT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_lvfal1, // seesound + 8, // reactiontime + sfx_s3kd5l, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 30*FRACUNIT, // radius + 32*FRACUNIT, // height + 1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_SPAWNCEILING, // flags + S_NULL // raisestate + }, + + { // MT_LAVAFALL_LAVA + -1, // doomednum + S_LAVAFALL_LAVA1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_LAVAFALL_LAVA3, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 30*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_PAIN|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_LAVAFALLROCK + -1, // doomednum + S_LAVAFALLROCK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_ROLLOUTSPAWN + 1305, // doomednum + S_ROLLOUTSPAWN, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SPAWNCEILING, // flags + S_NULL // raisestate + }, + + { // MT_ROLLOUTROCK + -1, // doomednum + S_ROLLOUTROCK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime (sets number of frames the rock cycles through) + sfx_None, // attacksound + S_NULL, // painstate + 12*TICRATE, // painchance (sets how long an unridden rock should last before disappearing - set to 0 to disable) + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 32*FRACUNIT, // speed + 30*FRACUNIT, // radius + 60*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_PUSHABLE|MF_SOLID|MF_SLIDEME, // flags + S_NULL // raisestate + }, + + { // MT_BIGFERNLEAF + -1, // doomednum + S_BIGFERNLEAF, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_BIGFERN + 1306, // doomednum + S_BIGFERN1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_JUNGLEPALM + 1307, // doomednum + S_JUNGLEPALM, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_TORCHFLOWER + 1308, // doomednum + S_TORCHFLOWER, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 14*FRACUNIT, // radius + 110*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_WALLVINE_LONG + 1309, // doomednum + S_WALLVINE_LONG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 1*FRACUNIT, // radius + 288*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP, // flags + S_NULL // raisestate + }, + + { // MT_WALLVINE_SHORT + 1310, // doomednum + S_WALLVINE_SHORT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 1*FRACUNIT, // radius + 288*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP, // flags + S_NULL // raisestate + }, + { // MT_TRAPGOYLE 1500, // doomednum S_TRAPGOYLE, // spawnstate @@ -13445,6 +13938,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_MISTLETOE + 2105, // doomednum + S_MISTLETOE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 52*FRACUNIT, // radius + 106*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_SPAWNCEILING|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_XMASBLUEBERRYBUSH 1859, // doomednum S_XMASBLUEBERRYBUSH, // spawnstate @@ -13580,6 +14100,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_ROSY + 2104, // doomednum + S_ROSY_IDLE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_ENEMY|MF_SLIDEME, // flags -- "enemy" may seem weird but it doesn't have any unintended consequences in context because no MF_SHOOTABLE|MF_SPECIAL + S_NULL // raisestate + }, + + { // MT_CDLHRT + -1, // doomednum + S_LHRT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 4*FRACUNIT, // speed + 4*FRACUNIT, // radius + 4*FRACUNIT, // height + 1, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_JACKO1 2006, // doomednum S_JACKO1, // spawnstate @@ -16635,6 +17209,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_LAVASPLISH + -1, // doomednum + S_LAVASPLISH, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 6*FRACUNIT, // radius + 1*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_SMOKE -1, // doomednum S_SMOKE1, // spawnstate diff --git a/src/info.h b/src/info.h index b5a13046e..1e7652557 100644 --- a/src/info.h +++ b/src/info.h @@ -268,6 +268,14 @@ void A_SnapperThinker(); void A_SaloonDoorSpawn(); void A_MinecartSparkThink(); void A_ModuloToState(); +void A_LavafallRocks(); +void A_LavafallLava(); +void A_FallingLavaCheck(); +void A_FireShrink(); +void A_SpawnPterabytes(); +void A_PterabyteHover(); +void A_RolloutSpawn(); +void A_RolloutRock(); // ratio of states to sprites to mobj types is roughly 6 : 1 : 1 #define NUMMOBJFREESLOTS 512 @@ -316,6 +324,8 @@ typedef enum sprite SPR_UNID, // Unidus SPR_CANA, // Canarivore SPR_CANG, // Canarivore gas + SPR_PYRE, // Pyre Fly + SPR_PTER, // Pterabyte // Generic Boss Items SPR_JETF, // Boss jet fumes @@ -397,6 +407,7 @@ typedef enum sprite SPR_WSPB, // Wall spike base SPR_STPT, // Starpost SPR_BMNE, // Big floating mine + SPR_PUMI, // Rollout Rock // Monitor Boxes SPR_MSTV, // MiSc TV sprites @@ -511,7 +522,6 @@ typedef enum sprite SPR_ADST, // Arid dust SPR_MCRT, // Minecart SPR_MCSP, // Minecart spark - SPR_NON2, // Saloon door thinker SPR_SALD, // Saloon door SPR_TRAE, // Train cameo locomotive SPR_TRAI, // Train cameo wagon @@ -520,6 +530,10 @@ typedef enum sprite // Red Volcano Scenery SPR_FLME, // Flame jet SPR_DFLM, // Blade's flame + SPR_LFAL, // Lavafall + SPR_JPLA, // Jungle palm + SPR_TFLO, // Torch flower + SPR_WVIN, // Wall vines // Dark City Scenery @@ -531,7 +545,9 @@ typedef enum sprite SPR_XMS3, // Snowman SPR_XMS4, // Lamppost SPR_XMS5, // Hanging Star + SPR_XMS6, // Mistletoe SPR_FHZI, // FHZ Ice + SPR_ROSY, // Halloween Scenery SPR_PUMK, // Pumpkins @@ -617,6 +633,7 @@ typedef enum sprite SPR_RAIN, // Rain SPR_SNO1, // Snowflake SPR_SPLH, // Water Splish + SPR_LSPL, // Lava Splish SPR_SPLA, // Water Splash SPR_SMOK, SPR_BUBL, // Bubble @@ -1340,6 +1357,22 @@ typedef enum state S_CANARIVOREGAS_7, S_CANARIVOREGAS_8, + // Pyre Fly + S_PYREFLY_FLY, + S_PYREFLY_BURN, + S_PYREFIRE1, + S_PYREFIRE2, + + // Pterabyte + S_PTERABYTESPAWNER, + S_PTERABYTEWAYPOINT, + S_PTERABYTE_FLY1, + S_PTERABYTE_FLY2, + S_PTERABYTE_FLY3, + S_PTERABYTE_FLY4, + S_PTERABYTE_SWOOPDOWN, + S_PTERABYTE_SWOOPUP, + // Boss Explosion S_BOSSEXPLODE, @@ -2583,7 +2616,7 @@ typedef enum state // Saloon door S_SALOONDOOR, - S_SALOONDOORTHINKER, + S_SALOONDOORCENTER, // Train cameo S_TRAINCAMEOSPAWNER_1, @@ -2616,6 +2649,28 @@ typedef enum state S_FLAMEJETFLAMEB2, S_FLAMEJETFLAMEB3, + // Lavafall + S_LAVAFALL_DORMANT, + S_LAVAFALL_TELL, + S_LAVAFALL_SHOOT, + S_LAVAFALL_LAVA1, + S_LAVAFALL_LAVA2, + S_LAVAFALL_LAVA3, + S_LAVAFALLROCK, + + // Rollout Rock + S_ROLLOUTSPAWN, + S_ROLLOUTROCK, + + // RVZ scenery + S_BIGFERNLEAF, + S_BIGFERN1, + S_BIGFERN2, + S_JUNGLEPALM, + S_TORCHFLOWER, + S_WALLVINE_LONG, + S_WALLVINE_SHORT, + // Trapgoyles S_TRAPGOYLE, S_TRAPGOYLE_CHECK, @@ -2667,6 +2722,7 @@ typedef enum state S_LAMPPOST1, // normal S_LAMPPOST2, // with snow S_HANGSTAR, + S_MISTLETOE, // Xmas GFZ bushes S_XMASBLUEBERRYBUSH, S_XMASBERRYBUSH, @@ -2674,6 +2730,16 @@ typedef enum state // FHZ S_FHZICE1, S_FHZICE2, + S_ROSY_IDLE1, + S_ROSY_IDLE2, + S_ROSY_IDLE3, + S_ROSY_IDLE4, + S_ROSY_JUMP, + S_ROSY_WALK, + S_ROSY_HUG, + S_ROSY_PAIN, + S_ROSY_STND, + S_ROSY_UNHAPPY, // Halloween Scenery // Pumpkins @@ -3345,6 +3411,9 @@ typedef enum state S_SPLISH8, S_SPLISH9, + // Lava Splish + S_LAVASPLISH, + // added water splash S_SPLASH1, S_SPLASH2, @@ -4017,6 +4086,11 @@ typedef enum mobj_type MT_UNIBALL, // Unidus Ball MT_CANARIVORE, // Canarivore MT_CANARIVORE_GAS, // Canarivore gas + MT_PYREFLY, // Pyre Fly + MT_PYREFLY_FIRE, // Pyre Fly fire + MT_PTERABYTESPAWNER, // Pterabyte spawner + MT_PTERABYTEWAYPOINT, // Pterabyte waypoint + MT_PTERABYTE, // Pterabyte // Generic Boss Items MT_BOSSEXPLODE, @@ -4345,7 +4419,7 @@ typedef enum mobj_type MT_MINECARTSIDEMARK, MT_MINECARTSPARK, MT_SALOONDOOR, - MT_SALOONDOORTHINKER, + MT_SALOONDOORCENTER, MT_TRAINCAMEOSPAWNER, MT_TRAINSEG, MT_TRAINDUSTSPAWNER, @@ -4362,6 +4436,20 @@ typedef enum mobj_type MT_FLAMEJETFLAMEB, // Blade's flame + MT_LAVAFALL, + MT_LAVAFALL_LAVA, + MT_LAVAFALLROCK, + + MT_ROLLOUTSPAWN, + MT_ROLLOUTROCK, + + MT_BIGFERNLEAF, + MT_BIGFERN, + MT_JUNGLEPALM, + MT_TORCHFLOWER, + MT_WALLVINE_LONG, + MT_WALLVINE_SHORT, + // Dark City Scenery // Egg Rock Scenery @@ -4393,6 +4481,7 @@ typedef enum mobj_type MT_LAMPPOST1, // normal MT_LAMPPOST2, // with snow MT_HANGSTAR, + MT_MISTLETOE, // Xmas GFZ bushes MT_XMASBLUEBERRYBUSH, MT_XMASBERRYBUSH, @@ -4400,6 +4489,8 @@ typedef enum mobj_type // FHZ MT_FHZICE1, MT_FHZICE2, + MT_ROSY, + MT_CDLHRT, // Halloween Scenery // Pumpkins @@ -4528,6 +4619,7 @@ typedef enum mobj_type MT_RAIN, // Rain MT_SNOWFLAKE, // Snowflake MT_SPLISH, // Water splish! + MT_LAVASPLISH, // Lava splish! MT_SMOKE, MT_SMALLBUBBLE, // small bubble MT_MEDIUMBUBBLE, // medium bubble diff --git a/src/lua_baselib.c b/src/lua_baselib.c index a69e8a188..8f173e32e 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -816,15 +816,12 @@ static int lib_pCheckDeathPitCollide(lua_State *L) static int lib_pCheckSolidLava(lua_State *L) { - mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); //HUDSAFE INLEVEL - if (!mo) - return LUA_ErrInvalid(L, "mobj_t"); if (!rover) return LUA_ErrInvalid(L, "ffloor_t"); - lua_pushboolean(L, P_CheckSolidLava(mo, rover)); + lua_pushboolean(L, P_CheckSolidLava(rover)); return 1; } diff --git a/src/m_menu.c b/src/m_menu.c index 7cd998330..894b2956c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -256,6 +256,7 @@ menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef; // Single Player static void M_StartTutorial(INT32 choice); static void M_LoadGame(INT32 choice); +static void M_HandleTimeAttackLevelSelect(INT32 choice); static void M_TimeAttackLevelSelect(INT32 choice); static void M_TimeAttack(INT32 choice); static void M_NightsAttackLevelSelect(INT32 choice); @@ -752,7 +753,7 @@ static menuitem_t SP_TimeAttackLevelSelectMenu[] = // Single Player Time Attack static menuitem_t SP_TimeAttackMenu[] = { - {IT_STRING|IT_CALL, NULL, "Level Select...", &M_TimeAttackLevelSelect, 52}, + {IT_STRING|IT_KEYHANDLER, NULL, "Level Select...", M_HandleTimeAttackLevelSelect, 52}, {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 62}, {IT_DISABLED, NULL, "Guest Option...", &SP_GuestReplayDef, 100}, @@ -1233,7 +1234,7 @@ static menuitem_t OP_VideoOptionsMenu[] = {IT_HEADER, NULL, "Level", NULL, 155}, {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 161}, {IT_STRING | IT_CVAR, NULL, "Weather Draw Dist.", &cv_drawdist_precip, 166}, - {IT_STRING | IT_CVAR, NULL, "NiGHTS mode Draw Dist.", &cv_drawdist_nights, 171}, + {IT_STRING | IT_CVAR, NULL, "NiGHTS Hoop Draw Dist.", &cv_drawdist_nights, 171}, {IT_HEADER, NULL, "Diagnostic", NULL, 180}, {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 186}, @@ -8645,7 +8646,18 @@ void M_DrawTimeAttackMenu(void) else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); + y = 32+lsheadingheight; + V_DrawSmallScaledPatch(208, y, 0, PictureOfLevel); + + if (itemOn == talevel) + { + /* Draw arrows !! */ + y = y + 25 - 4; + V_DrawCharacter(208 - 10 - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(208 + 80 + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); @@ -8719,6 +8731,39 @@ void M_DrawTimeAttackMenu(void) V_DrawString(104-72, 180, V_TRANSLUCENT, M_GetText("Press ESC to exit")); } +static void M_HandleTimeAttackLevelSelect(INT32 choice) +{ + switch (choice) + { + case KEY_DOWNARROW: + M_NextOpt(); + break; + case KEY_UPARROW: + M_PrevOpt(); + break; + + case KEY_LEFTARROW: + CV_AddValue(&cv_nextmap, -1); + break; + case KEY_RIGHTARROW: + CV_AddValue(&cv_nextmap, 1); + break; + + case KEY_ENTER: + M_TimeAttackLevelSelect(0); + break; + + case KEY_ESCAPE: + noFurtherInput = true; + M_GoBack(0); + return; + + default: + return; + } + S_StartSound(NULL, sfx_menu1); +} + static void M_TimeAttackLevelSelect(INT32 choice) { (void)choice; diff --git a/src/p_enemy.c b/src/p_enemy.c index 000b5cbfb..314e97606 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -298,6 +298,14 @@ void A_SnapperThinker(mobj_t *actor); void A_SaloonDoorSpawn(mobj_t *actor); void A_MinecartSparkThink(mobj_t *actor); void A_ModuloToState(mobj_t *actor); +void A_LavafallRocks(mobj_t *actor); +void A_LavafallLava(mobj_t *actor); +void A_FallingLavaCheck(mobj_t *actor); +void A_FireShrink(mobj_t *actor); +void A_SpawnPterabytes(mobj_t *actor); +void A_PterabyteHover(mobj_t *actor); +void A_RolloutSpawn(mobj_t *actor); +void A_RolloutRock(mobj_t *actor); //for p_enemy.c @@ -5343,20 +5351,22 @@ static mobj_t *minus; static boolean PIT_MinusCarry(mobj_t *thing) { + if (minus->tracer) + return true; + if (minus->type == thing->type) return true; - if (!(thing->flags & MF_SHOOTABLE) || !(thing->flags & MF_ENEMY)) + if (!(thing->flags & (MF_PUSHABLE|MF_ENEMY))) return true; - if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius * 3) + if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius*3) return true; if (abs(thing->z - minus->z) > minus->height) return true; P_SetTarget(&minus->tracer, thing); - minus->tracer->flags &= ~MF_PUSHABLE; return true; } @@ -5420,6 +5430,9 @@ void A_MinusDigging(mobj_t *actor) A_Chase(actor); // Carry over shit, maybe + if (P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) + P_SetTarget(&actor->tracer, NULL); + if (!actor->tracer) { fixed_t radius = 3*actor->radius; @@ -5469,7 +5482,6 @@ void A_MinusPopup(mobj_t *actor) else actor->momz = 10*FRACUNIT; - actor->flags |= MF_SPECIAL|MF_SHOOTABLE; S_StartSound(actor, sfx_s3k82); for (i = 1; i <= num; i++) { @@ -5482,6 +5494,7 @@ void A_MinusPopup(mobj_t *actor) if (actor->tracer) P_DamageMobj(actor->tracer, actor, actor, 1, 0); + actor->flags = (actor->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE; } // Function: A_MinusCheck @@ -8408,8 +8421,8 @@ void A_ChangeAngleAbsolute(mobj_t *actor) // // var1 = sound # to play // var2: -// 0 = Play sound without an origin -// 1 = Play sound using calling object as origin +// lower 16 bits = If 1, play sound using calling object as origin. If 0, play sound without an origin +// upper 16 bits = If 1, do not play sound during preticker. // void A_PlaySound(mobj_t *actor) { @@ -8420,7 +8433,10 @@ void A_PlaySound(mobj_t *actor) return; #endif - S_StartSound(locvar2 ? actor : NULL, locvar1); + if (leveltime < 2 && (locvar2 >> 16)) + return; + + S_StartSound((locvar2 & 65535) ? actor : NULL, locvar1); } // Function: A_FindTarget @@ -12197,7 +12213,7 @@ void A_MineExplode(mobj_t *actor) #undef dist if (actor->watertop != INT32_MAX) - P_SpawnMobj(actor->x, actor->y, actor->watertop, MT_SPLISH); + P_SpawnMobj(actor->x, actor->y, actor->watertop, (actor->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH); } } @@ -12237,7 +12253,6 @@ void A_ConnectToGround(mobj_t *actor) mobj_t *work; fixed_t workz; fixed_t workh; - SINT8 dir; angle_t ang; INT32 locvar1 = var1; INT32 locvar2 = var2; @@ -12251,23 +12266,17 @@ void A_ConnectToGround(mobj_t *actor) P_AdjustMobjFloorZ_FFloors(actor, actor->subsector->sector, 2); if (actor->flags2 & MF2_OBJECTFLIP) - { - workz = actor->ceilingz - (actor->z + actor->height); - dir = -1; - } + workz = (actor->z + actor->height) - actor->ceilingz; else - { workz = actor->floorz - actor->z; - dir = 1; - } if (locvar2) { workh = FixedMul(mobjinfo[locvar2].height, actor->scale); if (actor->flags2 & MF2_OBJECTFLIP) - workz -= workh; + workz += workh; work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar2); - workz += dir*workh; + workz += workh; } if (!locvar1) @@ -12276,21 +12285,18 @@ void A_ConnectToGround(mobj_t *actor) if (!(workh = FixedMul(mobjinfo[locvar1].height, actor->scale))) return; - if (actor->flags2 & MF2_OBJECTFLIP) - workz -= workh; - ang = actor->angle + ANGLE_45; - while (dir*workz < 0) + while (workz < 0) { work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar1); if (work) work->angle = ang; ang += ANGLE_90; - workz += dir*workh; + workz += workh; } if (workz != 0) - actor->z += workz; + actor->z += P_MobjFlip(actor)*workz; } // Function: A_SpawnParticleRelative @@ -13455,6 +13461,13 @@ void A_TNTExplode(mobj_t *actor) if (LUA_CallAction("A_TNTExplode", actor)) return; #endif + + if (actor->tracer) + { + P_SetTarget(&actor->tracer->tracer, NULL); + P_SetTarget(&actor->tracer, NULL); + } + P_UnsetThingPosition(actor); if (sector_list) { @@ -13668,8 +13681,6 @@ void A_KillSegments(mobj_t *actor) static void P_SnapperLegPlace(mobj_t *mo) { mobj_t *seg = mo->tracer; - fixed_t x0 = mo->x; - fixed_t y0 = mo->y; angle_t a = mo->angle; angle_t fa = (a >> ANGLETOFINESHIFT) & FINEMASK; fixed_t c = FINECOSINE(fa); @@ -13684,7 +13695,8 @@ static void P_SnapperLegPlace(mobj_t *mo) fixed_t rad = mo->radius; INT32 necklen = (32*(mo->info->reactiontime - mo->reactiontime))/mo->info->reactiontime; // Not in FU - P_TeleportMove(seg, mo->x + FixedMul(c, rad) + necklen*c, mo->y + FixedMul(s, rad) + necklen*s, mo->z + mo->height/3); + seg->z = mo->z + ((mo->eflags & MFE_VERTICALFLIP) ? (((mo->height<<1)/3) - seg->height) : mo->height/3); + P_TryMove(seg, mo->x + FixedMul(c, rad) + necklen*c, mo->y + FixedMul(s, rad) + necklen*s, true); seg->angle = a; // Move as many legs as available. @@ -13704,13 +13716,14 @@ static void P_SnapperLegPlace(mobj_t *mo) { x = c*o2 + s*o1; y = s*o2 - c*o1; - P_TryMove(seg, x0 + x, y0 + y, true); + seg->z = mo->z + (((mo->eflags & MFE_VERTICALFLIP) ? (mo->height - seg->height) : 0)); + P_TryMove(seg, mo->x + x, mo->y + y, true); P_SetMobjState(seg, seg->info->raisestate); } else P_SetMobjState(seg, seg->info->spawnstate); - seg->angle = R_PointToAngle2(x0, y0, seg->x, seg->y); + seg->angle = R_PointToAngle2(mo->x, mo->y, seg->x, seg->y); seg = seg->tracer; } while (seg); @@ -13738,14 +13751,14 @@ void A_SnapperSpawn(mobj_t *actor) #endif // It spawns 1 head. - seg = P_SpawnMobj(actor->x, actor->y, actor->z, headtype); + seg = P_SpawnMobjFromMobj(actor, 0, 0, 0, headtype); P_SetTarget(&ptr->tracer, seg); ptr = seg; // It spawns 4 legs which will be handled in the thinker function. for (i = 1; i <= 4; i++) { - seg = P_SpawnMobj(actor->x, actor->y, actor->z, legtype); + seg = P_SpawnMobjFromMobj(actor, 0, 0, 0, legtype); P_SetTarget(&ptr->tracer, seg); ptr = seg; @@ -13893,51 +13906,43 @@ void A_SnapperThinker(mobj_t *actor) // // Description: Spawns a saloon door. // -// var1 = unused -// var2 = unused +// var1 = mobjtype for sides +// var2 = distance sides should be placed apart // void A_SaloonDoorSpawn(mobj_t *actor) { + INT32 locvar1 = var1; + INT32 locvar2 = var2; angle_t ang = actor->angle; angle_t fa = (ang >> ANGLETOFINESHIFT) & FINEMASK; - fixed_t c = FINECOSINE(fa); - fixed_t s = FINESINE(fa); - INT32 d = 48; - fixed_t x = actor->x; - fixed_t y = actor->y; - fixed_t z = actor->z; + fixed_t c = FINECOSINE(fa)*locvar2; + fixed_t s = FINESINE(fa)*locvar2; mobj_t *door; + mobjflag2_t ambush = (actor->flags & MF2_AMBUSH); #ifdef HAVE_BLUA if (LUA_CallAction("A_SaloonDoorSpawn", actor)) return; #endif - //Front - door = P_SpawnMobj(x + c*d, y + s*d, z, MT_SALOONDOOR); + if (!locvar1) + return; + + // One door... + if (!(door = P_SpawnMobjFromMobj(actor, c, s, 0, locvar1))) return; door->angle = ang + ANGLE_180; + door->extravalue1 = AngleFixed(door->angle); // Origin angle + door->extravalue2 = 0; // Angular speed + P_SetTarget(&door->tracer, actor); // Origin door + door->flags2 |= ambush; // Can be opened by normal players? - // Origin angle - door->extravalue1 = AngleFixed(door->angle); - - // Angular speed - door->extravalue2 = 0; - - // Origin door - P_SetTarget(&door->tracer, actor); - - //Back - door = P_SpawnMobj(x - c*d, y - s*d, z, MT_SALOONDOOR); + // ...two door! + if (!(door = P_SpawnMobjFromMobj(actor, -c, -s, 0, locvar1))) return; door->angle = ang; - - // Origin angle - door->extravalue1 = AngleFixed(door->angle); - - // Angular speed - door->extravalue2 = 0; - - // Origin door - P_SetTarget(&door->tracer, actor); + door->extravalue1 = AngleFixed(door->angle); // Origin angle + door->extravalue2 = 0; // Angular speed + P_SetTarget(&door->tracer, actor); // Origin door + door->flags2 |= ambush; // Can be opened by normal players? } // Function: A_MinecartSparkThink @@ -13998,3 +14003,290 @@ void A_ModuloToState(mobj_t *actor) P_SetMobjState(actor, (locvar2)); modulothing++; } + +// Function: A_LavafallRocks +// +// Description: Spawn random rock particles. +// +// var1 = unused +// var2 = unused +// +void A_LavafallRocks(mobj_t *actor) +{ + UINT8 i; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_LavafallRocks", actor)) + return; +#endif + + // Don't spawn rocks unless a player is relatively close by. + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (1600 << FRACBITS)) + break; // Stop looking. + + if (i < MAXPLAYERS) + { + angle_t fa = (FixedAngle(P_RandomKey(360) << FRACBITS) >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t offset = P_RandomRange(4, 12) << FRACBITS; + fixed_t xoffs = FixedMul(FINECOSINE(fa), actor->radius + offset); + fixed_t yoffs = FixedMul(FINESINE(fa), actor->radius + offset); + P_SpawnMobjFromMobj(actor, xoffs, yoffs, 0, MT_LAVAFALLROCK); + } +} + +// Function: A_LavafallLava +// +// Description: Spawn lava from lavafall. +// +// var1 = unused +// var2 = unused +// +void A_LavafallLava(mobj_t *actor) +{ + mobj_t *lavafall; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_LavafallLava", actor)) + return; +#endif + + if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS))) + return; + + lavafall = P_SpawnMobjFromMobj(actor, 0, 0, -8*FRACUNIT, MT_LAVAFALL_LAVA); + lavafall->momz = -P_MobjFlip(actor)*25*FRACUNIT; +} + +// Function: A_FallingLavaCheck +// +// Description: If actor hits the ground or a water surface, enter the death animation. +// +// var1 = unused +// var2 = unused +// +void A_FallingLavaCheck(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FallingLavaCheck", actor)) + return; +#endif + + if (actor->eflags & MFE_TOUCHWATER || P_IsObjectOnGround(actor)) + { + actor->flags = MF_NOGRAVITY|MF_NOCLIPTHING; + actor->momz = 0; + if (actor->eflags & MFE_TOUCHWATER) + actor->z = (actor->eflags & MFE_VERTICALFLIP) ? actor->waterbottom : actor->watertop; + P_SetMobjState(actor, actor->info->deathstate); + } +} + +// Function: A_FireShrink +// +// Description: Shrink the actor down to the specified scale at the specified speed. +// +// var1 = Scale to shrink to +// var2 = Shrinking speed +// +void A_FireShrink(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FireShrink", actor)) + return; +#endif + + actor->destscale = locvar1; + actor->scalespeed = FRACUNIT/locvar2; +} + +// Function: A_SpawnPterabytes +// +// Description: Spawn Pterabytes around the actor in a circle. +// +// var1 = unused +// var2 = unused +// +void A_SpawnPterabytes(mobj_t *actor) +{ + mobj_t *waypoint, *ptera; + fixed_t c, s; + fixed_t rad = 280*FRACUNIT; + angle_t ang = 0; + angle_t interval, fa; + UINT8 amount = 1; + UINT8 i; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SpawnPterabytes", actor)) + return; +#endif + + if (actor->spawnpoint) + amount = actor->spawnpoint->extrainfo + 1; + + interval = FixedAngle(FRACUNIT*360/amount); + + for (i = 0; i < amount; i++) + { + fa = (ang >> ANGLETOFINESHIFT) & FINEMASK; + c = FINECOSINE(fa); + s = FINESINE(fa); + waypoint = P_SpawnMobjFromMobj(actor, FixedMul(c, rad), FixedMul(s, rad), 0, MT_PTERABYTEWAYPOINT); + waypoint->angle = ang + ANGLE_90; + P_SetTarget(&waypoint->tracer, actor); + ptera = P_SpawnMobjFromMobj(waypoint, 0, 0, 0, MT_PTERABYTE); + ptera->angle = waypoint->angle; + P_SetTarget(&ptera->tracer, waypoint); + ptera->extravalue1 = 0; + ang += interval; + } +} + +// Function: A_PterabyteHover +// +// Description: Hover in a circular fashion, bobbing up and down slightly. +// +// var1 = unused +// var2 = unused +// +void A_PterabyteHover(mobj_t *actor) +{ + angle_t ang, fa; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_PterabyteHover", actor)) + return; +#endif + + P_InstaThrust(actor, actor->angle, actor->info->speed); + actor->angle += ANG1; + actor->extravalue1 = (actor->extravalue1 + 3) % 360; + ang = actor->extravalue1*ANG1; + fa = (ang >> ANGLETOFINESHIFT) & FINEMASK; + actor->z += FINESINE(fa); +} +// Function: A_RolloutSpawn +// +// Description: Spawns a new Rollout Rock when the currently spawned rock is destroyed or moves far enough away. +// +// var1 = Distance currently spawned rock should travel before spawning a new one +// var2 = Object type to spawn +// +void A_RolloutSpawn(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RolloutSpawn", actor)) + return; +#endif + + if (!(actor->target) + || P_MobjWasRemoved(actor->target) + || P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) > locvar1) + { + actor->target = P_SpawnMobj(actor->x, actor->y, actor->z, locvar2); + actor->target->flags2 |= (actor->flags2 & (MF2_AMBUSH | MF2_OBJECTFLIP)) | MF2_SLIDEPUSH; + actor->target->eflags |= (actor->eflags & MFE_VERTICALFLIP); + + if (actor->target->flags2 & MF2_AMBUSH) + { + actor->target->color = SKINCOLOR_SUPERRUST3; + actor->target->colorized = true; + } + } +} + +// Function: A_RolloutRock +// +// Description: Thinker for Rollout Rock. +// +// var1 = Drag +// var2 = Vertical bobbing speed factor +// +void A_RolloutRock(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RolloutRock", actor)) + return; +#endif + + UINT8 maxframes = actor->info->reactiontime; // number of frames the mobj cycles through + fixed_t pi = (22*FRACUNIT/7); + fixed_t circumference = FixedMul(2 * pi, actor->radius); // used to calculate when to change frame + fixed_t speed = P_AproxDistance(actor->momx, actor->momy), topspeed = FixedMul(actor->info->speed, actor->scale); + boolean inwater = actor->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER); + + actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves + + if (actor->threshold) + actor->threshold--; + + if (inwater && !(actor->flags2 & MF2_AMBUSH)) // buoyancy in water (or lava) + { + UINT8 flip = P_MobjFlip(actor); + fixed_t prevmomz = actor->momz; + actor->momz = FixedMul(actor->momz, locvar2); + actor->momz += flip * FixedMul(locvar2, actor->scale); + if (flip*prevmomz < 0 && flip*actor->momz >= 0 && !actor->threshold) + { + if (actor->eflags & MFE_UNDERWATER) + S_StartSound(actor, sfx_splash); + else if (!actor->threshold) + S_StartSound(actor, sfx_splish); + actor->threshold = max((topspeed - speed) >> FRACBITS, 8); + } + } + + if (speed > topspeed) // cap speed + { + actor->momx = FixedMul(FixedDiv(actor->momx, speed), topspeed); + actor->momy = FixedMul(FixedDiv(actor->momy, speed), topspeed); + } + + if (P_IsObjectOnGround(actor) || inwater) // apply drag to speed (compensates for lack of friction but also works in liquids) + { + actor->momx = FixedMul(actor->momx, locvar1); + actor->momy = FixedMul(actor->momy, locvar1); + } + + speed = P_AproxDistance(actor->momx, actor->momy); // recalculate speed for visual rolling + + if (speed < actor->scale >> 1) // stop moving if speed is insignificant + { + actor->momx = 0; + actor->momy = 0; + } + else if (speed > actor->scale) + { + actor->movecount = 1; // rock has moved; fuse should be set so we don't have a trillion rocks lying around + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); // set rock's angle to movement direction + actor->movefactor += speed; + if (actor->movefactor > circumference / maxframes) // if distance moved is enough to change frame, change it! + { + actor->reactiontime++; + actor->reactiontime %= maxframes; + actor->movefactor = 0; + } + } + + actor->frame = actor->reactiontime % maxframes; // set frame + + if (!(actor->flags & MF_PUSHABLE)) // if being ridden, don't disappear + actor->fuse = 0; + else if (!actor->fuse && actor->movecount == 1) // otherwise if rock has moved, set its fuse + actor->fuse = actor->info->painchance; + + if (actor->fuse && actor->fuse < 2*TICRATE) + actor->flags2 ^= MF2_DONTDRAW; + +} diff --git a/src/p_floor.c b/src/p_floor.c index 7887dc530..19b7611b8 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1778,6 +1778,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_RAIN: case MT_SNOWFLAKE: case MT_SPLISH: + case MT_LAVASPLISH: case MT_SMOKE: case MT_SMALLBUBBLE: case MT_MEDIUMBUBBLE: diff --git a/src/p_inter.c b/src/p_inter.c index 60d355bb1..c94a0b7f9 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -428,7 +428,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) || special->state == &states[S_FANG_BOUNCE4] || special->state == &states[S_FANG_PINCHBOUNCE3] || special->state == &states[S_FANG_PINCHBOUNCE4]) - && P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > -(special->height/4)) + && P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > (special->height/4)) { P_DamageMobj(toucher, special, special, 1, 0); P_SetTarget(&special->tracer, toucher); @@ -450,12 +450,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } } break; + case MT_PYREFLY: + if (special->extravalue2 == 2 && P_DamageMobj(player->mo, special, special, 1, DMG_FIRE)) + return; default: break; } if (P_PlayerCanDamage(player, special)) // Do you possess the ability to subdue the object? { + if (special->type == MT_PTERABYTE && special->target == player->mo && special->extravalue1 == 1) + return; // Can't hurt a Pterabyte if it's trying to pick you up + if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1)) { if (elementalpierce == 2) @@ -477,7 +483,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_TwinSpinRejuvenate(player, player->thokitem); } else + { + if (special->type == MT_PTERABYTE && special->target == player->mo) + return; // Don't hurt the player you're trying to grab + P_DamageMobj(toucher, special, special, 1, 0); + } return; } @@ -1074,7 +1085,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->exiting) return; - if (player->bumpertime < TICRATE/4) + if (player->bumpertime <= (TICRATE/2)-5) { S_StartSound(toucher, special->info->seesound); if (player->powers[pw_carry] == CR_NIGHTSMODE) @@ -1765,7 +1776,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_MINECARTSPAWNER: - if (!special->fuse || player->powers[pw_carry] != CR_MINECART) + if (!player->bot && (special->fuse < TICRATE || player->powers[pw_carry] != CR_MINECART)) { mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART); P_SetTarget(&mcart->target, toucher); @@ -1775,7 +1786,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_ResetPlayer(player); player->pflags |= PF_JUMPDOWN; player->powers[pw_carry] = CR_MINECART; - toucher->player->pflags &= ~PF_APPLYAUTOBRAKE; + player->pflags &= ~PF_APPLYAUTOBRAKE; P_SetTarget(&toucher->tracer, mcart); toucher->momx = toucher->momy = toucher->momz = 0; diff --git a/src/p_local.h b/src/p_local.h index 4a5865027..02f497850 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -303,7 +303,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover); boolean P_CheckDeathPitCollide(mobj_t *mo); -boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover); +boolean P_CheckSolidLava(ffloor_t *rover); void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype); mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type); diff --git a/src/p_map.c b/src/p_map.c index 8035d64a5..810d85e34 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -208,7 +208,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) { angle_t nightsangle = 0; - if (object->player->bumpertime >= TICRATE/4) + if (object->player->bumpertime > (TICRATE/2)-5) return false; if ((object->player->pflags & PF_TRANSFERTOCLOSEST) && object->player->axis1 && object->player->axis2) @@ -490,6 +490,42 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) } } +static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera) +{ + if (player->powers[pw_carry] && players->powers[pw_carry] != CR_ROLLOUT) + return; + if (ptera->extravalue1 != 1) + return; // Not swooping + if (ptera->target != player->mo) + return; // Not swooping for you! + + if (player->spectator) + return; + + if ((player->mo->eflags & MFE_VERTICALFLIP) != (ptera->eflags & MFE_VERTICALFLIP)) + return; // Both should be in same gravity + + if (ptera->eflags & MFE_VERTICALFLIP) + { + if (ptera->ceilingz - (ptera->z + ptera->height) < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale)) + return; + } + else if (ptera->z - ptera->floorz < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale)) + return; // No room to pick up this guy! + + P_ResetPlayer(player); + P_SetTarget(&player->mo->tracer, ptera); + player->pflags &= ~PF_APPLYAUTOBRAKE; + player->powers[pw_carry] = CR_PTERABYTE; + S_StartSound(player->mo, sfx_s3k4a); + P_UnsetThingPosition(player->mo); + player->mo->x = ptera->x; + player->mo->y = ptera->y; + P_SetThingPosition(player->mo); + ptera->movefactor = 3*TICRATE; + ptera->watertop = ptera->waterbottom = ptera->cusval = 0; +} + static void P_DoTailsCarry(player_t *sonic, player_t *tails) { INT32 p; @@ -604,6 +640,34 @@ static void P_SlapStick(mobj_t *fang, mobj_t *pole) P_SetTarget(&pole->tracer, NULL); } +static void P_PlayerBarrelCollide(mobj_t *toucher, mobj_t *barrel) +{ + if (toucher->momz < 0) + { + if (toucher->z + toucher->momz > barrel->z + barrel->height) + return; + } + else + { + if (toucher->z > barrel->z + barrel->height) + return; + } + + if (toucher->momz > 0) + { + if (toucher->z + toucher->height + toucher->momz < barrel->z) + return; + } + else + { + if (toucher->z + toucher->height < barrel->z) + return; + } + + if (P_PlayerCanDamage(toucher->player, barrel)) + P_DamageMobj(barrel, toucher, toucher, 1, 0); +} + // // PIT_CheckThing // @@ -854,6 +918,15 @@ static boolean PIT_CheckThing(mobj_t *thing) } #endif + if (tmthing->type == MT_LAVAFALL_LAVA && (thing->type == MT_RING || thing->type == MT_REDTEAMRING || thing->type == MT_BLUETEAMRING || thing->type == MT_FLINGRING)) + { + //height check + if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !(thing->health)) + return true; + + P_KillMobj(thing, tmthing, tmthing, DMG_FIRE); + } + if (tmthing->type == MT_MINECART) { //height check @@ -872,12 +945,11 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->type == MT_SALOONDOOR && tmthing->player) { - if (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer) && tmthing->tracer->health) + mobj_t *ref = (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)) ? tmthing->tracer : tmthing; + if ((thing->flags & MF2_AMBUSH) || ref != tmthing) { - fixed_t dx = tmthing->tracer->momx; - fixed_t dy = tmthing->tracer->momy; - fixed_t dm = min(FixedHypot(dx, dy), 16*FRACUNIT); - angle_t ang = R_PointToAngle2(0, 0, dx, dy) - thing->angle; + fixed_t dm = min(FixedHypot(ref->momx, ref->momy), 16*FRACUNIT); + angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle; fixed_t s = FINESINE((ang >> ANGLETOFINESHIFT) & FINEMASK); S_StartSound(tmthing, thing->info->activesound); thing->extravalue2 += 2*FixedMul(s, dm)/3; @@ -885,41 +957,73 @@ static boolean PIT_CheckThing(mobj_t *thing) } } - if (thing->type == MT_TNTBARREL && tmthing->player) + if (thing->type == MT_SALOONDOORCENTER && tmthing->player) { - if (tmthing->momz < 0) - { - if (tmthing->z + tmthing->momz > thing->z + thing->height) - return true; - } - else - { - if (tmthing->z > thing->z + thing->height) - return true; - } - - if (tmthing->momz > 0) - { - if (tmthing->z + tmthing->height + tmthing->momz < thing->z) - return true; - } - else - { - if (tmthing->z + tmthing->height < thing->z) - return true; - } - - if ((tmthing->player->pflags & (PF_SPINNING | PF_GLIDING)) - || ((tmthing->player->pflags & PF_JUMPED) - && (!(tmthing->player->pflags & PF_NOJUMPDAMAGE) - || (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) - || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) - || ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING) - && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height / 2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0)) - || (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY))) - P_DamageMobj(thing, tmthing, tmthing, 1, 0); + if ((thing->flags & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer))) + return true; } + if (thing->type == MT_ROLLOUTROCK && tmthing->player && tmthing->health) + { + if (tmthing->player->powers[pw_carry] == CR_ROLLOUT) + { + return true; + } + if ((thing->flags & MF_PUSHABLE) // not carrying a player + && (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something + && ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP)) + && (P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < (thing->radius)) + && (P_MobjFlip(tmthing)*tmthing->momz <= 0) + && ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2)) + || (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2)))) + { + thing->flags &= ~MF_PUSHABLE; // prevent riding player from applying pushable movement logic + thing->flags2 &= ~MF2_DONTDRAW; // don't leave the rock invisible if it was flashing prior to boarding + P_SetTarget(&thing->tracer, tmthing); + P_ResetPlayer(tmthing->player); + P_SetPlayerMobjState(tmthing, S_PLAY_WALK); + tmthing->player->powers[pw_carry] = CR_ROLLOUT; + P_SetTarget(&tmthing->tracer, thing); + P_SetObjectMomZ(thing, tmthing->momz, true); + return true; + } + } + else if (tmthing->type == MT_ROLLOUTROCK) + { + if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !thing->health) + return true; + + if (thing == tmthing->tracer) // don't collide with rider + return true; + + if (thing->flags & MF_SPRING) // bounce on springs + { + P_DoSpring(thing, tmthing); + return true; + } + else if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) == (MF_MONITOR|MF_SHOOTABLE) && !(tmthing->flags & MF_PUSHABLE)) // pop monitors while carrying a player + { + P_KillMobj(thing, tmthing, tmthing->tracer, 0); + return true; + } + + if (thing->type == tmthing->type // bounce against other rollout rocks + && (tmthing->momx || tmthing->momy || thing->momx || thing->momy)) + { + fixed_t tempmomx = thing->momx, tempmomy = thing->momy; + thing->momx = tmthing->momx; + thing->momy = tmthing->momy; + tmthing->momx = tempmomx; + tmthing->momy = tempmomy; + } + } + + if (thing->type == MT_PTERABYTE && tmthing->player) + P_DoPterabyteCarry(tmthing->player, thing); + + if (thing->type == MT_TNTBARREL && tmthing->player) + P_PlayerBarrelCollide(tmthing, thing); + if (thing->type == MT_VULTURE && tmthing->type == MT_VULTURE) { fixed_t dx = thing->x - tmthing->x; @@ -1560,8 +1664,8 @@ static boolean PIT_CheckThing(mobj_t *thing) } } - if ((!tmthing->player) && (thing->player)) - ; // no solid thing should ever be able to step up onto a player + if ((tmthing->flags & MF_SPRING || tmthing->type == MT_STEAM) && (thing->player)) + ; // springs and gas jets should never be able to step up onto a player // z checking at last // Treat noclip things as non-solid! else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID @@ -1964,7 +2068,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) continue; } - if (thing->player && (P_CheckSolidLava(thing, rover) || P_CanRunOnWater(thing->player, rover))) + if (thing->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(thing->player, rover))) ; else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)) ; @@ -2629,8 +2733,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) thing->eflags |= MFE_JUSTSTEPPEDDOWN; } #ifdef ESLOPE - // HACK TO FIX DSZ2: apply only if slopes are involved - else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep) + else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep) { thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; thing->ceilingrover = tmceilingrover; @@ -2645,8 +2748,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) thing->eflags |= MFE_JUSTSTEPPEDDOWN; } #ifdef ESLOPE - // HACK TO FIX DSZ2: apply only if slopes are involved - else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep) + else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep) { thing->z = thing->floorz = tmfloorz; thing->floorrover = tmfloorrover; @@ -3479,6 +3581,64 @@ stairstep: goto retry; } +static void P_CheckLavaWall(mobj_t *mo, sector_t *sec) +{ + ffloor_t *rover; + fixed_t topheight, bottomheight; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!(rover->flags & FF_SWIMMABLE)) + continue; + + if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 3) + continue; + + if (rover->master->flags & ML_BLOCKMONSTERS) + continue; + + topheight = +#ifdef ESLOPE + *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : +#endif + *rover->topheight; + + if (mo->eflags & MFE_VERTICALFLIP) + { + if (topheight < mo->z - mo->height) + continue; + } + else + { + if (topheight < mo->z) + continue; + } + + bottomheight = +#ifdef ESLOPE + *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : +#endif + *rover->bottomheight; + + if (mo->eflags & MFE_VERTICALFLIP) + { + if (bottomheight > mo->z) + continue; + } + else + { + if (bottomheight > mo->z + mo->height) + continue; + } + + P_DamageMobj(mo, NULL, NULL, 1, DMG_FIRE); + return; + } +} + // // P_SlideMove // The momx / momy move is bad, so try to slide @@ -3639,6 +3799,12 @@ retry: P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy, PT_ADDLINES, PTR_SlideTraverse); + if (bestslideline && mo->player && bestslideline->sidenum[1] != 0xffff) + { + sector_t *sec = P_PointOnLineSide(mo->x, mo->y, bestslideline) ? bestslideline->frontsector : bestslideline->backsector; + P_CheckLavaWall(mo, sec); + } + // Some walls are bouncy even if you're not if (bestslideline && bestslideline->flags & ML_BOUNCY) { diff --git a/src/p_maputl.c b/src/p_maputl.c index 45fc82fbf..22998c60e 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -662,7 +662,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) + if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover))) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) @@ -708,7 +708,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) + if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover))) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) diff --git a/src/p_mobj.c b/src/p_mobj.c index 5c4609f04..7fa51111d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1578,7 +1578,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) // Goop has slower, reversed gravity if (goopgravity) - gravityadd = -gravityadd/5; + gravityadd = -((gravityadd/5) + (gravityadd/8)); gravityadd = FixedMul(gravityadd, mo->scale); @@ -2222,7 +2222,7 @@ void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype) topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); - if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should stand on lava or run on water + if (mo->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mo->player, rover))) // only the player should stand on lava or run on water ; else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only continue; @@ -2369,9 +2369,9 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) return false; if (((mo->z <= mo->subsector->sector->floorheight - && !(mo->eflags & MFE_VERTICALFLIP) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_FLOOR)) + && ((mo->subsector->sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_FLOOR)) || (mo->z + mo->height >= mo->subsector->sector->ceilingheight - && (mo->eflags & MFE_VERTICALFLIP) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_CEILING))) + && ((mo->subsector->sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_CEILING))) && (GETSECSPECIAL(mo->subsector->sector->special, 1) == 6 || GETSECSPECIAL(mo->subsector->sector->special, 1) == 7)) return true; @@ -2379,43 +2379,11 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) return false; } -boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover) +boolean P_CheckSolidLava(ffloor_t *rover) { - fixed_t topheight; - - I_Assert(mo != NULL); - I_Assert(!P_MobjWasRemoved(mo)); - - // not a lava block with solid planes - if (!(rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 - && !(rover->master->flags & ML_BLOCKMONSTERS))) - return false; - - // is solid from the sides - if (rover->master->flags & ML_EFFECT3) - return true; - - if (mo->eflags & MFE_VERTICALFLIP) - { - topheight = - #ifdef ESLOPE - *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : - #endif - *rover->bottomheight; - - if (mo->z+mo->height-mo->momz < topheight + FixedMul(16*FRACUNIT, mo->scale)) - return true; - return false; - } - - topheight = - #ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : - #endif - *rover->topheight; - - if (mo->z-mo->momz > topheight - FixedMul(16*FRACUNIT, mo->scale)) - return true; + if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 + && !(rover->master->flags & ML_BLOCKMONSTERS)) + return true; return false; } @@ -3350,7 +3318,7 @@ void P_MobjCheckWater(mobj_t *mobj) mobj->watertop = mobj->waterbottom = mobj->z - 1000*FRACUNIT; // Reset water state. - mobj->eflags &= ~(MFE_UNDERWATER|MFE_TOUCHWATER|MFE_GOOWATER); + mobj->eflags &= ~(MFE_UNDERWATER|MFE_TOUCHWATER|MFE_GOOWATER|MFE_TOUCHLAVA); for (rover = sector->ffloors; rover; rover = rover->next) { @@ -3391,16 +3359,18 @@ void P_MobjCheckWater(mobj_t *mobj) // Just touching the water? if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - height < bottomheight) || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + height > topheight)) - { mobj->eflags |= MFE_TOUCHWATER; - if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY)) - mobj->eflags |= MFE_GOOWATER; - } + // Actually in the water? if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - (height>>1) > bottomheight) || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + (height>>1) < topheight)) - { mobj->eflags |= MFE_UNDERWATER; + + if (mobj->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) + { + if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 3) + mobj->eflags |= MFE_TOUCHLAVA; + if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY)) mobj->eflags |= MFE_GOOWATER; } @@ -3464,9 +3434,18 @@ void P_MobjCheckWater(mobj_t *mobj) || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->ceilingz-mobj->waterbottom <= height>>1)) return; - if (!wasgroundpounding && (mobj->eflags & MFE_GOOWATER || wasingoo)) { // Decide what happens to your momentum when you enter/leave goopy water. - if (P_MobjFlip(mobj)*mobj->momz < 0) // You are entering the goo? - mobj->momz = FixedMul(mobj->momz, FixedDiv(2*FRACUNIT, 5*FRACUNIT)); // kill momentum significantly, to make the goo feel thick. + if (mobj->eflags & MFE_GOOWATER || wasingoo) { // Decide what happens to your momentum when you enter/leave goopy water. + if (P_MobjFlip(mobj)*mobj->momz > 0) + { + mobj->momz -= (mobj->momz/8); // cut momentum a little bit to prevent multiple bobs + //CONS_Printf("leaving\n"); + } + else + { + if (!wasgroundpounding) + mobj->momz >>= 1; // kill momentum significantly, to make the goo feel thick. + //CONS_Printf("entering\n"); + } } else if (wasinwater && P_MobjFlip(mobj)*mobj->momz > 0) mobj->momz = FixedMul(mobj->momz, FixedDiv(780*FRACUNIT, 457*FRACUNIT)); // Give the mobj a little out-of-water boost. @@ -3478,14 +3457,15 @@ void P_MobjCheckWater(mobj_t *mobj) { // Spawn a splash mobj_t *splish; + mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; if (mobj->eflags & MFE_VERTICALFLIP) { - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[MT_SPLISH].height, mobj->scale), MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype); splish->flags2 |= MF2_OBJECTFLIP; splish->eflags |= MFE_VERTICALFLIP; } else - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); splish->destscale = mobj->scale; P_SetScale(splish, mobj->scale); } @@ -3513,14 +3493,15 @@ void P_MobjCheckWater(mobj_t *mobj) { // Spawn a splash mobj_t *splish; + mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; if (mobj->eflags & MFE_VERTICALFLIP) { - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[MT_SPLISH].height, mobj->scale), MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype); splish->flags2 |= MF2_OBJECTFLIP; splish->eflags |= MFE_VERTICALFLIP; } else - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); splish->destscale = mobj->scale; P_SetScale(splish, mobj->scale); } @@ -3536,6 +3517,8 @@ void P_MobjCheckWater(mobj_t *mobj) if (mobj->eflags & MFE_GOOWATER || wasingoo) S_StartSound(mobj, sfx_ghit); + else if (mobj->eflags & MFE_TOUCHLAVA) + S_StartSound(mobj, sfx_splash); else S_StartSound(mobj, sfx_splish); // And make a sound! @@ -4146,6 +4129,45 @@ void P_RainThinker(precipmobj_t *mobj) P_SetPrecipMobjState(mobj, S_SPLASH1); } +static void P_KillRingsInLava(mobj_t *mo) +{ + msecnode_t *node; + I_Assert(mo != NULL); + I_Assert(!P_MobjWasRemoved(mo)); + + // go through all sectors being touched by the ring + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (!node->m_sector) + break; + + if (node->m_sector->ffloors) + { + ffloor_t *rover; + fixed_t topheight, bottomheight; + + for (rover = node->m_sector->ffloors; rover; rover = rover->next) // go through all fofs in the sector + { + if (!(rover->flags & FF_EXISTS)) continue; // fof must be real + + if (!(rover->flags & FF_SWIMMABLE // fof must be water + && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3)) // fof must be lava water + continue; + + // find heights of FOF + topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); + bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); + + if (mo->z <= topheight && mo->z + mo->height >= bottomheight) // if ring touches it, KILL IT + { + P_KillMobj(mo, NULL, NULL, DMG_FIRE); + return; + } + } + } + } +} + static void P_RingThinker(mobj_t *mobj) { if (mobj->momx || mobj->momy) @@ -7054,6 +7076,16 @@ void P_HandleMinecartSegments(mobj_t *mobj) P_UpdateMinecartSegments(mobj); } +static void P_PyreFlyBurn(mobj_t *mobj, fixed_t hoffs, INT16 vrange, mobjtype_t mobjtype, fixed_t momz) +{ + angle_t fa = (FixedAngle(P_RandomKey(360)*FRACUNIT) >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t xoffs = FixedMul(FINECOSINE(fa), mobj->radius + hoffs); + fixed_t yoffs = FixedMul(FINESINE(fa), mobj->radius + hoffs); + fixed_t zoffs = P_RandomRange(-vrange, vrange)*FRACUNIT; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, zoffs, mobjtype); + particle->momz = momz; +} + // // P_MobjThinker // @@ -7619,6 +7651,7 @@ void P_MobjThinker(mobj_t *mobj) case MT_ROCKCRUMBLE16: case MT_WOODDEBRIS: case MT_BRICKDEBRIS: + case MT_BROKENROBOT: if (mobj->z <= P_FloorzAtPos(mobj->x, mobj->y, mobj->z, mobj->height) && mobj->state != &states[mobj->info->deathstate]) { @@ -7683,6 +7716,237 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->movedir) mobj->angle += mobj->movedir; break; + case MT_ROSY: + { + UINT8 i; + fixed_t pdist = 1700*mobj->scale, work, actualwork; + player_t *player = NULL; + statenum_t stat = (mobj->state-states); + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + if (!players[i].mo) + continue; + if (players[i].bot) + continue; + if (!players[i].mo->health) + continue; + actualwork = work = FixedHypot(mobj->x-players[i].mo->x, mobj->y-players[i].mo->y); + if (player) + { + if (players[i].skin == 0 || players[i].skin == 3) + work = (2*work)/3; + if (work >= pdist) + continue; + } + pdist = actualwork; + player = &players[i]; + } + + if (stat == S_ROSY_JUMP || stat == S_ROSY_PAIN) + { + if (P_IsObjectOnGround(mobj)) + { + mobj->momx = mobj->momy = 0; + if (player && mobj->cvmem < (-2*TICRATE)) + stat = S_ROSY_UNHAPPY; + else + stat = S_ROSY_WALK; + P_SetMobjState(mobj, stat); + } + else if (P_MobjFlip(mobj)*mobj->momz < 0) + mobj->frame = mobj->state->frame+mobj->state->var1; + } + + if (!player) + { + if ((stat < S_ROSY_IDLE1 || stat > S_ROSY_IDLE4) && stat != S_ROSY_JUMP) + { + mobj->momx = mobj->momy = 0; + P_SetMobjState(mobj, S_ROSY_IDLE1); + } + } + else + { + boolean dojump = false, targonground, love, makeheart = false; + if (mobj->target != player->mo) + P_SetTarget(&mobj->target, player->mo); + targonground = (P_IsObjectOnGround(mobj->target) && (player->panim == PA_IDLE || player->panim == PA_WALK || player->panim == PA_RUN)); + love = (player->skin == 0 || player->skin == 3); + + switch (stat) + { + case S_ROSY_IDLE1: + case S_ROSY_IDLE2: + case S_ROSY_IDLE3: + case S_ROSY_IDLE4: + dojump = true; + break; + case S_ROSY_JUMP: + case S_ROSY_PAIN: + // handled above + break; + case S_ROSY_WALK: + { + fixed_t x = mobj->x, y = mobj->y, z = mobj->z; + angle_t angletoplayer = R_PointToAngle2(x, y, mobj->target->x, mobj->target->y); + boolean allowed = P_TryMove(mobj, mobj->target->x, mobj->target->y, false); + + P_UnsetThingPosition(mobj); + mobj->x = x; + mobj->y = y; + mobj->z = z; + P_SetThingPosition(mobj); + + if (allowed) + { + fixed_t mom, max; + P_Thrust(mobj, angletoplayer, (3*FRACUNIT)>>1); + mom = FixedHypot(mobj->momx, mobj->momy); + max = pdist; + if ((--mobj->extravalue1) <= 0) + { + if (++mobj->frame > mobj->state->frame+mobj->state->var1) + mobj->frame = mobj->state->frame; + if (mom > 12*mobj->scale) + mobj->extravalue1 = 2; + else if (mom > 6*mobj->scale) + mobj->extravalue1 = 3; + else + mobj->extravalue1 = 4; + } + if (max < (mobj->radius + mobj->target->radius)) + { + mobj->momx = mobj->target->player->cmomx; + mobj->momy = mobj->target->player->cmomy; + if ((mobj->cvmem > TICRATE && !player->exiting) || !targonground) + P_SetMobjState(mobj, (stat = S_ROSY_STND)); + else + { + mobj->target->momx = mobj->momx; + mobj->target->momy = mobj->momy; + P_SetMobjState(mobj, (stat = S_ROSY_HUG)); + S_StartSound(mobj, sfx_cdpcm6); + mobj->angle = angletoplayer; + } + } + else + { + max /= 3; + if (max > 30*mobj->scale) + max = 30*mobj->scale; + if (mom > max && max > mobj->scale) + { + max = FixedDiv(max, mom); + mobj->momx = FixedMul(mobj->momx, max); + mobj->momy = FixedMul(mobj->momy, max); + } + if (abs(mobj->momx) > mobj->scale || abs(mobj->momy) > mobj->scale) + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); + } + } + else + dojump = true; + } + break; + case S_ROSY_HUG: + if (targonground) + { + player->pflags |= PF_STASIS; + if (mobj->cvmem < 5*TICRATE) + mobj->cvmem++; + if (love && !(leveltime & 7)) + makeheart = true; + } + else + { + if (mobj->cvmem < (love ? 5*TICRATE : 0)) + { + P_SetMobjState(mobj, (stat = S_ROSY_PAIN)); + S_StartSound(mobj, sfx_cdpcm7); + } + else + P_SetMobjState(mobj, (stat = S_ROSY_JUMP)); + var1 = var2 = 0; + A_DoNPCPain(mobj); + mobj->cvmem -= TICRATE; + } + break; + case S_ROSY_STND: + if ((pdist > (mobj->radius + mobj->target->radius + 3*(mobj->scale + mobj->target->scale)))) + P_SetMobjState(mobj, (stat = S_ROSY_WALK)); + else if (!targonground) + ; + else + { + if (love && !(leveltime & 15)) + makeheart = true; + if (player->exiting || --mobj->cvmem < TICRATE) + { + P_SetMobjState(mobj, (stat = S_ROSY_HUG)); + S_StartSound(mobj, sfx_cdpcm6); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + mobj->target->momx = mobj->momx; + mobj->target->momy = mobj->momy; + } + } + break; + case S_ROSY_UNHAPPY: + default: + break; + } + + if (stat == S_ROSY_HUG) + { + if (player->panim != PA_IDLE) + P_SetPlayerMobjState(mobj->target, S_PLAY_STND); + player->pflags |= PF_STASIS; + } + + if (dojump) + { + P_SetMobjState(mobj, S_ROSY_JUMP); + mobj->z += P_MobjFlip(mobj); + mobj->momx = mobj->momy = 0; + P_SetObjectMomZ(mobj, 6<height, MT_CDLHRT); + cdlhrt->destscale = (5*mobj->scale)>>4; + P_SetScale(cdlhrt, cdlhrt->destscale); + cdlhrt->fuse = (5*TICRATE)>>1; + cdlhrt->momz = mobj->scale; + P_SetTarget(&cdlhrt->target, mobj); + cdlhrt->extravalue1 = mobj->x; + cdlhrt->extravalue2 = mobj->y; + } + } + } + break; + case MT_CDLHRT: + { + if (mobj->cvmem < 24) + mobj->cvmem++; + mobj->movedir += ANG10; + P_UnsetThingPosition(mobj); + mobj->x = mobj->extravalue1 + P_ReturnThrustX(mobj, mobj->movedir, mobj->cvmem*mobj->scale); + mobj->y = mobj->extravalue2 + P_ReturnThrustY(mobj, mobj->movedir, mobj->cvmem*mobj->scale); + P_SetThingPosition(mobj); + if ((--mobj->fuse) < 6) + { + if (!mobj->fuse) + { + P_RemoveMobj(mobj); + return; + } + mobj->frame = (mobj->frame & ~FF_TRANSMASK)|((10-(mobj->fuse*2))<<(FF_TRANSSHIFT)); + } + } + break; case MT_VWREF: case MT_VWREB: { @@ -8896,13 +9160,17 @@ void P_MobjThinker(mobj_t *mobj) } break; case MT_RING: + case MT_REDTEAMRING: + case MT_BLUETEAMRING: + P_KillRingsInLava(mobj); + if (P_MobjWasRemoved(mobj)) + return; + /* FALLTHRU */ case MT_COIN: case MT_BLUESPHERE: case MT_BOMBSPHERE: case MT_NIGHTSCHIP: case MT_NIGHTSSTAR: - case MT_REDTEAMRING: - case MT_BLUETEAMRING: // No need to check water. Who cares? P_RingThinker(mobj); if (mobj->flags2 & MF2_NIGHTSPULL) @@ -8912,6 +9180,10 @@ void P_MobjThinker(mobj_t *mobj) return; // Flung items case MT_FLINGRING: + P_KillRingsInLava(mobj); + if (P_MobjWasRemoved(mobj)) + return; + /* FALLTHRU */ case MT_FLINGCOIN: case MT_FLINGBLUESPHERE: case MT_FLINGNIGHTSCHIP: @@ -9113,6 +9385,159 @@ void P_MobjThinker(mobj_t *mobj) } mobj->flags2 ^= MF2_DONTDRAW; break; + case MT_LAVAFALLROCK: + if (P_IsObjectOnGround(mobj)) + P_RemoveMobj(mobj); + break; + case MT_PYREFLY: + { + fixed_t hdist; + + mobj->extravalue1 = (mobj->extravalue1 + 3) % 360; + mobj->z += FINESINE(((mobj->extravalue1*ANG1) >> ANGLETOFINESHIFT) & FINEMASK); + + if (!(mobj->flags2 & MF2_BOSSNOTRAP)) + P_LookForPlayers(mobj, true, false, 1500*FRACUNIT); + + if (!mobj->target) + break; + + if (mobj->extravalue2 == 1) + P_PyreFlyBurn(mobj, 0, 20, MT_SMOKE, 4*FRACUNIT); + else if (mobj->extravalue2 == 2) + { + INT32 fireradius = min(100 - mobj->fuse, 52); + P_PyreFlyBurn(mobj, P_RandomRange(0, fireradius)*FRACUNIT, 20, MT_FLAMEPARTICLE, 4*FRACUNIT); + P_PyreFlyBurn(mobj, fireradius*FRACUNIT, 40, MT_PYREFLY_FIRE, 0); + } + + hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + + if (!(mobj->flags2 & MF2_BOSSNOTRAP) && hdist <= 450*FRACUNIT) + mobj->flags2 |= MF2_BOSSNOTRAP; + + if (!(mobj->flags2 & MF2_BOSSNOTRAP)) + break; + + if (hdist < 1000*FRACUNIT) + { + //Aim for player z position. If too close to floor/ceiling, aim just above/below them. + fixed_t destz = min(max(mobj->target->z, mobj->target->floorz + 70*FRACUNIT), mobj->target->ceilingz - 80*FRACUNIT - mobj->height); + fixed_t dist = P_AproxDistance(hdist, destz - mobj->z); + P_InstaThrust(mobj, R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y), 2*FRACUNIT); + mobj->momz = FixedMul(FixedDiv(destz - mobj->z, dist), 2*FRACUNIT); + } + else + { + mobj->momx = 0; + mobj->momy = 0; + mobj->momz = 0; + if (hdist >= 1500*FRACUNIT) + { + mobj->flags2 &= ~MF2_BOSSNOTRAP; + P_SetTarget(&mobj->target, NULL); + } + } + break; + } + case MT_PTERABYTE: + { + if (mobj->extravalue1 & 4) // Cooldown after grabbing + { + if (mobj->movefactor) + mobj->movefactor--; + else + { + P_SetTarget(&mobj->target, NULL); + mobj->extravalue1 &= 3; + } + } + + if ((mobj->extravalue1 & 3) == 0) // Hovering + { + fixed_t vdist, hdist, time; + fixed_t hspeed = 3*mobj->info->speed; + angle_t fa; + + var1 = 1; + var2 = 0; + A_CapeChase(mobj); + + if (mobj->target) + break; // Still carrying a player or in cooldown + + P_LookForPlayers(mobj, true, false, 256*FRACUNIT); + + if (!mobj->target) + break; + + if (mobj->target->player->powers[pw_flashing]) + { + P_SetTarget(&mobj->target, NULL); + break; + } + + vdist = mobj->z - mobj->target->z - mobj->target->height; + if (P_MobjFlip(mobj)*vdist <= 0) + { + P_SetTarget(&mobj->target, NULL); + break; + } + + hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + if (hdist > 450*FRACUNIT) + { + P_SetTarget(&mobj->target, NULL); + break; + } + + P_SetMobjState(mobj, S_PTERABYTE_SWOOPDOWN); + mobj->extravalue1++; + S_StartSound(mobj, mobj->info->attacksound); + time = FixedDiv(hdist, hspeed); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + fa = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK; + mobj->momx = FixedMul(FINECOSINE(fa), hspeed); + mobj->momy = FixedMul(FINESINE(fa), hspeed); + mobj->momz = -2*FixedDiv(vdist, time); + mobj->extravalue2 = -FixedDiv(mobj->momz, time); //Z accel + mobj->movecount = time >> FRACBITS; + mobj->reactiontime = mobj->movecount; + } + else if ((mobj->extravalue1 & 3) == 1) // Swooping + { + mobj->reactiontime--; + mobj->momz += mobj->extravalue2; + if (mobj->reactiontime) + break; + + if (mobj->state - states == S_PTERABYTE_SWOOPDOWN) + { + P_SetMobjState(mobj, S_PTERABYTE_SWOOPUP); + mobj->reactiontime = mobj->movecount; + } + else if (mobj->state - states == S_PTERABYTE_SWOOPUP) + { + P_SetMobjState(mobj, S_PTERABYTE_FLY1); + mobj->extravalue1++; + if (mobj->target && mobj->target->tracer != mobj) + P_SetTarget(&mobj->target, NULL); // Failed to grab the target + mobj->momx = mobj->momy = mobj->momz = 0; + } + } + else // Returning + { + var1 = 2*mobj->info->speed; + var2 = 1; + A_HomingChase(mobj); + if (P_AproxDistance(mobj->x - mobj->tracer->x, mobj->y - mobj->tracer->y) <= mobj->info->speed) + { + mobj->extravalue1 -= 2; + mobj->momx = mobj->momy = mobj->momz = 0; + } + } + break; + } case MT_SPINFIRE: if (mobj->flags & MF_NOGRAVITY) { @@ -9343,6 +9768,52 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s case MT_NIGHTSCORE: P_RemoveMobj(mobj); return; + case MT_LAVAFALL: + if (mobj->state - states == S_LAVAFALL_DORMANT) + { + mobj->fuse = 30; + P_SetMobjState(mobj, S_LAVAFALL_TELL); + S_StartSound(mobj, mobj->info->seesound); + } + else if (mobj->state - states == S_LAVAFALL_TELL) + { + mobj->fuse = 40; + P_SetMobjState(mobj, S_LAVAFALL_SHOOT); + S_StopSound(mobj); + S_StartSound(mobj, mobj->info->attacksound); + } + else + { + mobj->fuse = 30; + P_SetMobjState(mobj, S_LAVAFALL_DORMANT); + S_StopSound(mobj); + } + return; + case MT_PYREFLY: + if (mobj->health <= 0) + break; + + mobj->extravalue2 = (mobj->extravalue2 + 1) % 3; + if (mobj->extravalue2 == 0) + { + P_SetMobjState(mobj, mobj->info->spawnstate); + mobj->fuse = 100; + S_StopSound(mobj); + S_StartSound(mobj, sfx_s3k8c); + } + else if (mobj->extravalue2 == 1) + { + mobj->fuse = 50; + S_StartSound(mobj, sfx_s3ka3); + } + else + { + P_SetMobjState(mobj, mobj->info->meleestate); + mobj->fuse = 100; + S_StopSound(mobj); + S_StartSound(mobj, sfx_s3kc2l); + } + return; case MT_PLAYER: break; // don't remove default: @@ -9900,6 +10371,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_FANG: sc = 4; break; + case MT_ROSY: + sc = 5; + break; case MT_CORK: mobj->flags2 |= MF2_SUPERFIRE; break; @@ -9915,11 +10389,23 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) } case MT_TNTBARREL: mobj->momx = 1; //stack hack + mobj->flags2 |= MF2_INVERTAIMABLE; break; case MT_MINECARTEND: P_SetTarget(&mobj->tracer, P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID)); mobj->tracer->angle = mobj->angle + ANGLE_90; break; + case MT_TORCHFLOWER: + { + mobj_t *fire = P_SpawnMobjFromMobj(mobj, 0, 0, 46*FRACUNIT, MT_FLAME); + P_SetTarget(&mobj->target, fire); + break; + } + case MT_PYREFLY: + mobj->extravalue1 = (FixedHypot(mobj->x, mobj->y)/FRACUNIT) % 360; + mobj->extravalue2 = 0; + mobj->fuse = 100; + break; default: break; } @@ -10237,7 +10723,7 @@ void P_SpawnPrecipitation(void) if (curWeather == PRECIP_SNOW) { // Not in a sector with visible sky -- exception for NiGHTS. - if (!(maptol & TOL_NIGHTS) && precipsector->sector->ceilingpic != skyflatnum) + if ((!(maptol & TOL_NIGHTS) && (precipsector->sector->ceilingpic != skyflatnum)) == !(precipsector->sector->flags & SF_INVERTPRECIP)) continue; rainmo = P_SpawnSnowMobj(x, y, height, MT_SNOWFLAKE); @@ -10250,7 +10736,7 @@ void P_SpawnPrecipitation(void) else // everything else. { // Not in a sector with visible sky. - if (precipsector->sector->ceilingpic != skyflatnum) + if ((precipsector->sector->ceilingpic != skyflatnum) == !(precipsector->sector->flags & SF_INVERTPRECIP)) continue; rainmo = P_SpawnRainMobj(x, y, height, MT_RAIN); @@ -11070,6 +11556,14 @@ You should think about modifying the deathmatch starts to take full advantage of // They're likely facets of the level's design and therefore required to progress. } + if (i == MT_ROSY) + { + if (mariomode) + i = MT_TOAD; // don't remove on penalty of death + else if (!(netgame || multiplayer) && players[consoleplayer].skin == 5) + return; // no doubles + } + if (i == MT_TOKEN && ((gametype != GT_COOP && gametype != GT_COMPETITION) || ultimatemode || tokenbits == 30 || tokenlist & (1 << tokenbits++))) return; // you already got this token, or there are too many, or the gametype's not right @@ -11283,9 +11777,10 @@ You should think about modifying the deathmatch starts to take full advantage of else mobj->health = FixedMul(ss->sector->ceilingheight-ss->sector->floorheight, 3*(FRACUNIT/4))>>FRACBITS; break; - case MT_FANG: case MT_METALSONIC_RACE: case MT_METALSONIC_BATTLE: + case MT_FANG: + case MT_ROSY: if (mthing->options & MTF_EXTRA) { mobj->color = SKINCOLOR_SILVER; @@ -11957,6 +12452,38 @@ ML_EFFECT5 : Don't stop thinking when too far away if (mthing->angle > 0) mobj->tics += mthing->angle; break; + case MT_LAVAFALL: + mobj->fuse = 30 + mthing->angle; + if (mthing->options & MTF_AMBUSH) + { + P_SetScale(mobj, 2*mobj->scale); + mobj->destscale = mobj->scale; + } + break; + case MT_PYREFLY: + //start on fire if Ambush flag is set, otherwise behave normally + if (mthing->options & MTF_AMBUSH) + { + P_SetMobjState(mobj, mobj->info->meleestate); + mobj->extravalue2 = 2; + S_StartSound(mobj, sfx_s3kc2l); + } + break; + case MT_BIGFERN: + { + angle_t angle = FixedAngle(mthing->angle << FRACBITS); + UINT8 j; + for (j = 0; j < 8; j++) + { + angle_t fa = (angle >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t xoffs = FINECOSINE(fa); + fixed_t yoffs = FINESINE(fa); + mobj_t *leaf = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, 0, MT_BIGFERNLEAF); + leaf->angle = angle; + angle += ANGLE_45; + } + break; + } default: break; } diff --git a/src/p_mobj.h b/src/p_mobj.h index a9d5244b0..94fcc2987 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -233,15 +233,17 @@ typedef enum MFE_VERTICALFLIP = 1<<5, // Goo water MFE_GOOWATER = 1<<6, + // The mobj is touching a lava block + MFE_TOUCHLAVA = 1<<7, // Mobj was already pushed this tic - MFE_PUSHED = 1<<7, + MFE_PUSHED = 1<<8, // Mobj was already sprung this tic - MFE_SPRUNG = 1<<8, + MFE_SPRUNG = 1<<9, // Platform movement - MFE_APPLYPMOMZ = 1<<9, + MFE_APPLYPMOMZ = 1<<10, // Compute and trigger on mobj angle relative to tracer // See Linedef Exec 457 (Track mobj angle to point) - MFE_TRACERANGLE = 1<<10, + MFE_TRACERANGLE = 1<<11, // free: to and including 1<<15 } mobjeflag_t; diff --git a/src/p_spec.c b/src/p_spec.c index 256ca3453..5b8e25050 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4174,26 +4174,11 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n // Check the 3D floor's type... if (rover->flags & FF_BLOCKPLAYER) { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); // Thing must be on top of the floor to be affected... - if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) - { - if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight) - continue; - } - else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(player->mo->eflags & MFE_VERTICALFLIP) - || player->mo->z + player->mo->height != bottomheight) - continue; - } - else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight) - || (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight))) - continue; - } + if (!(floorallowed || ceilingallowed)) + continue; } else { @@ -4234,26 +4219,11 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n // Check the 3D floor's type... if (rover->flags & FF_BLOCKPLAYER) { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); // Thing must be on top of the floor to be affected... - if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) - { - if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight) - continue; - } - else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(player->mo->eflags & MFE_VERTICALFLIP) - || player->mo->z + player->mo->height != bottomheight) - continue; - } - else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight) - || (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight))) - continue; - } + if (!(floorallowed || ceilingallowed)) + continue; } else { @@ -4304,26 +4274,11 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar // Check the 3D floor's type... if (rover->flags & FF_BLOCKPLAYER) { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == top)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottom)); // Thing must be on top of the floor to be affected... - if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) - { - if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != top) - return false; - } - else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(mo->eflags & MFE_VERTICALFLIP) - || mo->z + mo->height != bottom) - return false; - } - else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottom) - || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == top))) - return false; - } + if (!(floorallowed || ceilingallowed)) + continue; } else { @@ -4345,10 +4300,10 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar // static boolean P_MobjReadyToTrigger(mobj_t *mo, sector_t *sec) { - if (mo->eflags & MFE_VERTICALFLIP) - return (mo->z+mo->height == P_GetSpecialTopZ(mo, sec, sec) && sec->flags & SF_FLIPSPECIAL_CEILING); - else - return (mo->z == P_GetSpecialBottomZ(mo, sec, sec) && sec->flags & SF_FLIPSPECIAL_FLOOR); + boolean floorallowed = ((sec->flags & SF_FLIPSPECIAL_FLOOR) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == P_GetSpecialBottomZ(mo, sec, sec))); + boolean ceilingallowed = ((sec->flags & SF_FLIPSPECIAL_CEILING) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == P_GetSpecialTopZ(mo, sec, sec))); + // Thing must be on top of the floor to be affected... + return (floorallowed || ceilingallowed); } /** Applies a sector special to a player. @@ -5312,26 +5267,11 @@ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) if (((rover->flags & FF_BLOCKPLAYER) && mo->player) || ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == topheight)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottomheight)); // Thing must be on top of the floor to be affected... - if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) - { - if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != topheight) - continue; - } - else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(mo->eflags & MFE_VERTICALFLIP) - || mo->z + mo->height != bottomheight) - continue; - } - else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottomheight) - || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == topheight))) - continue; - } + if (!(floorallowed || ceilingallowed)) + continue; } else { @@ -5374,26 +5314,11 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) // Check the 3D floor's type... if (rover->flags & FF_BLOCKPLAYER) { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); // Thing must be on top of the floor to be affected... - if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) - { - if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight) - continue; - } - else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(player->mo->eflags & MFE_VERTICALFLIP) - || player->mo->z + player->mo->height != bottomheight) - continue; - } - else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight) - || (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight))) - continue; - } + if (!(floorallowed || ceilingallowed)) + continue; } else { @@ -5450,38 +5375,16 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) } if (!(po->flags & POF_TESTHEIGHT)) // Don't do height checking - { - } + ; else if (po->flags & POF_SOLID) { + boolean floorallowed = ((polysec->flags & SF_FLIPSPECIAL_FLOOR) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == polysec->ceilingheight)); + boolean ceilingallowed = ((polysec->flags & SF_FLIPSPECIAL_CEILING) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == polysec->floorheight)); // Thing must be on top of the floor to be affected... - if ((polysec->flags & SF_FLIPSPECIAL_FLOOR) - && !(polysec->flags & SF_FLIPSPECIAL_CEILING)) + if (!(floorallowed || ceilingallowed)) { - if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != polysec->ceilingheight) - { - po = (polyobj_t *)(po->link.next); - continue; - } - } - else if ((polysec->flags & SF_FLIPSPECIAL_CEILING) - && !(polysec->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(player->mo->eflags & MFE_VERTICALFLIP) - || player->mo->z + player->mo->height != polysec->floorheight) - { - po = (polyobj_t *)(po->link.next); - continue; - } - } - else if (polysec->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == polysec->floorheight) - || (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == polysec->ceilingheight))) - { - po = (polyobj_t *)(po->link.next); - continue; - } + po = (polyobj_t *)(po->link.next); + continue; } } else @@ -5580,17 +5483,13 @@ static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector) f_affectpoint = P_GetSpecialBottomZ(player->mo, sector, sector); c_affectpoint = P_GetSpecialTopZ(player->mo, sector, sector); - // Only go further if on the ground - if ((sector->flags & SF_FLIPSPECIAL_FLOOR) && !(sector->flags & SF_FLIPSPECIAL_CEILING) && player->mo->z != f_affectpoint) - return; - - if ((sector->flags & SF_FLIPSPECIAL_CEILING) && !(sector->flags & SF_FLIPSPECIAL_FLOOR) && player->mo->z + player->mo->height != c_affectpoint) - return; - - if ((sector->flags & SF_FLIPSPECIAL_BOTH) - && player->mo->z != f_affectpoint - && player->mo->z + player->mo->height != c_affectpoint) - return; + { + boolean floorallowed = ((sector->flags & SF_FLIPSPECIAL_FLOOR) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == f_affectpoint)); + boolean ceilingallowed = ((sector->flags & SF_FLIPSPECIAL_CEILING) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == c_affectpoint)); + // Thing must be on top of the floor to be affected... + if (!(floorallowed || ceilingallowed)) + return; + } P_ProcessSpecialSector(player, sector, NULL); } @@ -6683,6 +6582,11 @@ void P_SpawnSpecials(INT32 fromnetsave) if (lines[i].flags & ML_EFFECT3) sectors[s].flags |= SF_TRIGGERSPECIAL_TOUCH; + if (lines[i].flags & ML_EFFECT2) + sectors[s].flags |= SF_TRIGGERSPECIAL_HEADBUMP; + + if (lines[i].flags & ML_EFFECT1) + sectors[s].flags |= SF_INVERTPRECIP; if (lines[i].frontsector && GETSECSPECIAL(lines[i].frontsector->special, 4) == 12) sectors[s].camsec = sides[*lines[i].sidenum].sector-sectors; diff --git a/src/p_tick.c b/src/p_tick.c index c6a20acc5..0a14d5fbd 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -484,7 +484,7 @@ static inline void P_DoSpecialStageStuff(void) countspheres += players[i].spheres; // If in water, deplete timer 6x as fast. - if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) + if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(players[i].powers[pw_shield] & SH_PROTECTWATER)) players[i].nightstime -= 5; if (--players[i].nightstime > 6) { diff --git a/src/p_user.c b/src/p_user.c index e4792c107..33f84e2db 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -898,7 +898,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) if (player->mo->target) { player->angle_pos = R_PointToAngle2(player->mo->target->x, player->mo->target->y, player->mo->x, player->mo->y); - player->drawangle = player->mo->angle = player->angle_pos + player->drawangle = player->angle_pos + ((player->mo->target->flags2 & MF2_AMBUSH) ? // if axis is invert, take the opposite right angle -ANGLE_90 : ANGLE_90); // flyangle is always 0 here, below is kept for posterity /*(player->flyangle > 90 && player->flyangle < 270 ? ANGLE_90 : -ANGLE_90) @@ -1031,6 +1031,17 @@ void P_ResetPlayer(player_t *player) { player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_THOKKED|PF_CANCARRY|PF_SHIELDABILITY|PF_BOUNCING); + if (player->powers[pw_carry] == CR_ROLLOUT) + { + if (player->mo->tracer && !P_MobjWasRemoved(player->mo->tracer)) + { + player->mo->tracer->flags |= MF_PUSHABLE; + P_SetTarget(&player->mo->tracer->tracer, NULL); + } + P_SetTarget(&player->mo->tracer, NULL); + player->powers[pw_carry] = CR_NONE; + } + if (!(player->powers[pw_carry] == CR_NIGHTSMODE || player->powers[pw_carry] == CR_NIGHTSFALL || player->powers[pw_carry] == CR_BRAKGOOP || player->powers[pw_carry] == CR_MINECART)) player->powers[pw_carry] = CR_NONE; @@ -2249,7 +2260,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) else if (!player->skidtime) player->pflags &= ~PF_GLIDING; } - else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) + else if (player->charability2 == CA2_MELEE && ((player->panim == PA_ABILITY2) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) { if (player->mo->state-states != S_PLAY_MELEE_LANDING) { @@ -3689,7 +3700,7 @@ static void P_DoTeeter(player_t *player) bottomheight = *rover->bottomheight; #endif - if (P_CheckSolidLava(player->mo, rover)) + if (P_CheckSolidLava(rover)) ; else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND)) continue; // intangible 3d floor @@ -4311,6 +4322,16 @@ void P_DoJump(player_t *player, boolean soundandstate) if (player->mo->ceilingz-player->mo->floorz <= player->mo->height-1) return; + if (player->powers[pw_carry] == CR_PTERABYTE) + { + S_StartSound(player->mo, sfx_s3kd7s); + player->mo->tracer->cusval += 10; + player->mo->tracer->watertop = P_RandomRange(-player->mo->tracer->cusval, player->mo->tracer->cusval) << (FRACBITS - 1); + player->mo->tracer->waterbottom = P_RandomRange(-player->mo->tracer->cusval, player->mo->tracer->cusval) << (FRACBITS - 1); + player->mo->tracer->cvmem = P_RandomRange(-player->mo->tracer->cusval, player->mo->tracer->cusval) << (FRACBITS - 1); + return; + } + // Jump this high. if (player->powers[pw_carry] == CR_PLAYER) { @@ -4324,6 +4345,8 @@ void P_DoJump(player_t *player, boolean soundandstate) { player->mo->momz = 9*FRACUNIT; player->powers[pw_carry] = CR_NONE; + player->mo->tracer->flags |= MF_PUSHABLE; + P_SetTarget(&player->mo->tracer->target, NULL); P_SetTarget(&player->mo->tracer, NULL); } else if (player->powers[pw_carry] == CR_ROPEHANG) @@ -4332,6 +4355,14 @@ void P_DoJump(player_t *player, boolean soundandstate) player->powers[pw_carry] = CR_NONE; P_SetTarget(&player->mo->tracer, NULL); } + else if (player->powers[pw_carry] == CR_ROLLOUT) + { + player->mo->momz = 9*FRACUNIT + player->mo->tracer->momz; + player->powers[pw_carry] = CR_NONE; + player->mo->tracer->flags |= MF_PUSHABLE; + P_SetTarget(&player->mo->tracer->tracer, NULL); + P_SetTarget(&player->mo->tracer, NULL); + } else if (player->mo->eflags & MFE_GOOWATER) { player->mo->momz = 7*FRACUNIT; @@ -4643,8 +4674,9 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (player->speed < FixedMul(player->maxdash, player->mo->scale)) #endif { - player->drawangle = player->mo->angle; - P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->maxdash, player->mo->scale)); + if (player->panim == PA_IDLE) + player->drawangle = player->mo->angle; + P_InstaThrust(player->mo, player->drawangle, FixedMul(player->maxdash, player->mo->scale)); } player->mo->momx += player->cmomx; player->mo->momy += player->cmomy; @@ -5842,35 +5874,28 @@ static void P_3dMovement(player_t *player) else topspeed = normalspd; } - else if (player->powers[pw_super] || player->powers[pw_sneakers]) - { - thrustfactor = player->thrustfactor*2; - acceleration = player->accelstart/2 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration/2; - - if (player->powers[pw_tailsfly]) - topspeed = normalspd; - else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER)) - { - topspeed = normalspd; - acceleration = 2*acceleration/3; - } - else - topspeed = normalspd * 2; - } else { - thrustfactor = player->thrustfactor; - acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration; - - if (player->powers[pw_tailsfly]) - topspeed = normalspd/2; - else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER)) + if (player->powers[pw_super] || player->powers[pw_sneakers]) { - topspeed = normalspd/2; - acceleration = 2*acceleration/3; + topspeed = 5 * normalspd / 3; // 1.67x + thrustfactor = player->thrustfactor*2; + acceleration = player->accelstart/2 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration/2; } else + { topspeed = normalspd; + thrustfactor = player->thrustfactor; + acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration; + } + + if (player->powers[pw_tailsfly]) + topspeed >>= 1; + else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER)) + { + topspeed >>= 1; + acceleration = 2*acceleration/3; + } } if (spin) // Prevent gaining speed whilst rolling! @@ -7350,10 +7375,13 @@ static void P_NiGHTSMovement(player_t *player) && player->mo->z + player->mo->height - P_GetPlayerHeight(player) <= player->mo->waterbottom && player->mo->z + player->mo->height >= player->mo->waterbottom)) && player->speed > 9000 && leveltime % (TICRATE/7) == 0 && !player->spectator) { + mobjtype_t splishtype = (player->mo->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; mobj_t *water = P_SpawnMobj(player->mo->x, player->mo->y, - ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_SPLISH].height, player->mo->scale) : player->mo->watertop), MT_SPLISH); + ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[splishtype].height, player->mo->scale) : player->mo->watertop), splishtype); if (player->mo->eflags & MFE_GOOWATER) S_StartSound(water, sfx_ghit); + else if (player->mo->eflags & MFE_TOUCHLAVA) + S_StartSound(water, sfx_splash); else S_StartSound(water, sfx_wslap); if (player->mo->eflags & MFE_VERTICALFLIP) @@ -8115,10 +8143,13 @@ static void P_MovePlayer(player_t *player) && (player->speed > runspd || (player->pflags & PF_STARTDASH)) && leveltime % (TICRATE/7) == 0 && player->mo->momz == 0 && !(player->pflags & PF_SLIDING) && !player->spectator) { + mobjtype_t splishtype = (player->mo->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; mobj_t *water = P_SpawnMobj(player->mo->x - P_ReturnThrustX(NULL, player->mo->angle, player->mo->radius), player->mo->y - P_ReturnThrustY(NULL, player->mo->angle, player->mo->radius), - ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_SPLISH].height, player->mo->scale) : player->mo->watertop), MT_SPLISH); + ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[splishtype].height, player->mo->scale) : player->mo->watertop), splishtype); if (player->mo->eflags & MFE_GOOWATER) S_StartSound(water, sfx_ghit); + else if (player->mo->eflags & MFE_TOUCHLAVA) + S_StartSound(water, sfx_splash); else S_StartSound(water, sfx_wslap); if (player->mo->eflags & MFE_VERTICALFLIP) @@ -8855,7 +8886,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) continue; if (mo->type == MT_MINUS && !(mo->flags & (MF_SPECIAL|MF_SHOOTABLE))) - mo->flags |= MF_SPECIAL|MF_SHOOTABLE; + mo->flags = (mo->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE; if (mo->type == MT_EGGGUARD && mo->tracer) //nuke Egg Guard's shield! P_KillMobj(mo->tracer, inflictor, source, DMG_NUKE); @@ -10254,7 +10285,7 @@ static sector_t *P_GetMinecartSector(fixed_t x, fixed_t y, fixed_t z, fixed_t *n ffloor_t *rover; for (rover = sec->ffloors; rover; rover = rover->next) { - if (!(rover->flags & FF_EXISTS)) + if (!(rover->flags & (FF_EXISTS|FF_BLOCKOTHERS))) continue; *nz = *rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : *rover->topheight; @@ -11240,6 +11271,8 @@ void P_PlayerThink(player_t *player) // deez New User eXperiences. { + angle_t diff = 0; + UINT8 factor; // Directionchar! // Camera angle stuff. if (player->exiting // no control, no modification @@ -11266,8 +11299,16 @@ void P_PlayerThink(player_t *player) /* FALLTHRU */ case CR_MINECART: case CR_GENERIC: + case CR_PTERABYTE: player->drawangle = player->mo->tracer->angle; break; + case CR_ROLLOUT: + if (cmd->forwardmove || cmd->sidemove) // only when you're pressing movement keys + { // inverse direction! + diff = ((player->mo->angle + R_PointToAngle2(0, 0, -cmd->forwardmove<sidemove<drawangle); + factor = 4; + } + break; /* -- in case we wanted to have the camera freely movable during zoom tubes case CR_ZOOMTUBE:*/ case CR_ROPEHANG: @@ -11288,9 +11329,6 @@ void P_PlayerThink(player_t *player) ; else { - angle_t diff; - UINT8 factor; - if (player->pflags & PF_SLIDING) { #if 0 // fun hydrocity style horizontal spin @@ -11326,15 +11364,15 @@ void P_PlayerThink(player_t *player) diff = (player->mo->angle - player->drawangle); factor = 8; } + } - if (diff) - { - if (diff > ANGLE_180) - diff = InvAngle(InvAngle(diff)/factor); - else - diff /= factor; - player->drawangle += diff; - } + if (diff) + { + if (diff > ANGLE_180) + diff = InvAngle(InvAngle(diff)/factor); + else + diff /= factor; + player->drawangle += diff; } // Autobrake! check ST_drawInput if you modify this @@ -11653,6 +11691,36 @@ void P_PlayerThink(player_t *player) }*/ } +// Checks if the mobj is above lava. Used by Pterabyte. +static boolean P_MobjAboveLava(mobj_t *mobj) +{ + sector_t *sector = mobj->subsector->sector; + + if (sector->ffloors) + { + ffloor_t *rover; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || GETSECSPECIAL(rover->master->frontsector->special, 1) != 3) + continue; + + if (mobj->eflags & MFE_VERTICALFLIP) + { + if (*rover->bottomheight <= mobj->ceilingz && *rover->bottomheight >= mobj->z) + return true; + } + else + { + if (*rover->topheight >= mobj->floorz && *rover->topheight <= mobj->z) + return true; + } + } + } + + return false; +} + // // P_PlayerAfterThink // @@ -11968,6 +12036,114 @@ void P_PlayerAfterThink(player_t *player) } break; } + case CR_ROLLOUT: + { + mobj_t *mo = player->mo, *rock = player->mo->tracer; + UINT8 walktics = mo->state->tics - P_GetPlayerControlDirection(player); + + if (!rock || P_MobjWasRemoved(rock)) + { + P_SetTarget(&player->mo->tracer, NULL); + player->powers[pw_carry] = CR_NONE; + break; + } + + if (player->cmd.forwardmove || player->cmd.sidemove) + { + rock->movedir = (player->cmd.angleturn << FRACBITS) + R_PointToAngle2(0, 0, player->cmd.forwardmove << FRACBITS, -player->cmd.sidemove << FRACBITS); + P_Thrust(rock, rock->movedir, rock->scale >> 1); + } + + mo->momx = rock->momx; + mo->momy = rock->momy; + mo->momz = 0; + + if (player->panim == PA_IDLE && (mo->momx || mo->momy)) + { + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + } + + if (player->panim == PA_WALK && mo->tics > walktics) + { + mo->tics = walktics; + } + + P_TeleportMove(player->mo, rock->x, rock->y, rock->z + rock->height); + break; + } + case CR_PTERABYTE: // being carried by a Pterabyte + { + mobj_t *ptera = player->mo->tracer; + mobj_t *spawnpoint = ptera->tracer->tracer; + player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14 * FRACUNIT, 10 * FRACUNIT)); + + if (ptera->health <= 0) + goto dropoff; + + if (P_MobjAboveLava(ptera) && ptera->movefactor <= 3*TICRATE - 10) + goto dropoff; + + if (player->mo->eflags & MFE_VERTICALFLIP) + { + if ((ptera->z + ptera->height + player->mo->height + FixedMul(FRACUNIT, player->mo->scale)) <= ptera->ceilingz + && (ptera->eflags & MFE_VERTICALFLIP)) // Reverse gravity check for the carrier - Flame + player->mo->z = ptera->z + ptera->height + FixedMul(FRACUNIT, player->mo->scale); + + if (ptera->ceilingz - ptera->z > spawnpoint->ceilingz - spawnpoint->z + 512*FRACUNIT && ptera->movefactor <= 3 * TICRATE - 10) + goto dropoff; + } + else + { + if ((ptera->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale)) >= ptera->floorz + && !(ptera->eflags & MFE_VERTICALFLIP)) // Correct gravity check for the carrier - Flame + player->mo->z = ptera->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale); + + if (ptera->z - ptera->floorz > spawnpoint->z - spawnpoint->floorz + 512 * FRACUNIT && ptera->movefactor <= 3 * TICRATE - 10) + goto dropoff; + } + + ptera->movefactor--; + if (!ptera->movefactor) + goto dropoff; + + if (ptera->cusval >= 50) + { + player->powers[pw_carry] = CR_NONE; + P_SetTarget(&player->mo->tracer, NULL); + P_KillMobj(ptera, player->mo, player->mo, 0); + player->mo->momz = 9*FRACUNIT; + player->pflags |= PF_APPLYAUTOBRAKE|PF_JUMPED|PF_THOKKED; + P_SetMobjState(player->mo, S_PLAY_ROLL); + break; + } + + if (ptera->cusval) + ptera->cusval--; + + P_TryMove(player->mo, ptera->x + ptera->watertop, ptera->y + ptera->waterbottom, true); + player->mo->z += ptera->cvmem; + player->mo->momx = ptera->momx; + player->mo->momy = ptera->momy; + player->mo->momz = ptera->momz; + + if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > player->mo->radius) + goto dropoff; + + ptera->watertop >>= 1; + ptera->waterbottom >>= 1; + ptera->cvmem >>= 1; + + if (player->mo->state-states != S_PLAY_FALL) + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + break; + + dropoff: + player->powers[pw_carry] = CR_NONE; + P_SetTarget(&player->mo->tracer, NULL); + ptera->movefactor = TICRATE; + ptera->extravalue1 |= 4; + break; + } default: break; } diff --git a/src/r_defs.h b/src/r_defs.h index def7b46f3..6aeb0671c 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -263,10 +263,15 @@ typedef struct pslope_s typedef enum { - SF_FLIPSPECIAL_FLOOR = 1, - SF_FLIPSPECIAL_CEILING = 2, - SF_FLIPSPECIAL_BOTH = 3, - SF_TRIGGERSPECIAL_TOUCH = 4, + // flipspecial - planes with effect + SF_FLIPSPECIAL_FLOOR = 1, + SF_FLIPSPECIAL_CEILING = 1<<1, + SF_FLIPSPECIAL_BOTH = (SF_FLIPSPECIAL_FLOOR|SF_FLIPSPECIAL_CEILING), + // triggerspecial - conditions under which plane touch causes effect + SF_TRIGGERSPECIAL_TOUCH = 1<<2, + SF_TRIGGERSPECIAL_HEADBUMP = 1<<3, + // invertprecip - inverts presence of precipitation + SF_INVERTPRECIP = 1<<4, } sectorflags_t; // diff --git a/src/r_main.c b/src/r_main.c index 9cce41288..9d9d1c39a 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1219,6 +1219,7 @@ void R_RegisterEngineStuff(void) #endif CV_RegisterVar(&cv_grmd2); CV_RegisterVar(&cv_grspritebillboarding); + CV_RegisterVar(&cv_grskydome); #endif #ifdef HWRENDER diff --git a/src/r_things.c b/src/r_things.c index 43e006a30..5c99edcec 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1230,7 +1230,7 @@ static void R_ProjectSprite(mobj_t *thing) else range = 1; - scalestep = (yscale2 - yscale)/range; + scalestep = (yscale2 - yscale)/range ?: 1; // The following two are alternate sorting methods which might be more applicable in some circumstances. TODO - maybe enable via MF2? // sortscale = max(yscale, yscale2); @@ -1637,7 +1637,7 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) mobj_t *thing; precipmobj_t *precipthing; // Tails 08-25-2002 INT32 lightnum; - fixed_t approx_dist, limit_dist; + fixed_t approx_dist, limit_dist, hoop_limit_dist; if (rendermode != render_soft) return; @@ -1668,7 +1668,9 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) // Handle all things in sector. // If a limit exists, handle things a tiny bit different. - if ((limit_dist = (fixed_t)((maptol & TOL_NIGHTS) ? cv_drawdist_nights.value : cv_drawdist.value) << FRACBITS)) + limit_dist = (fixed_t)(cv_drawdist.value) << FRACBITS; + hoop_limit_dist = (fixed_t)(cv_drawdist_nights.value) << FRACBITS; + if (limit_dist || hoop_limit_dist) { for (thing = sec->thinglist; thing; thing = thing->snext) { @@ -1677,8 +1679,16 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); - if (approx_dist > limit_dist) - continue; + if (thing->sprite == SPR_HOOP) + { + if (hoop_limit_dist && approx_dist > hoop_limit_dist) + continue; + } + else + { + if (limit_dist && approx_dist > limit_dist) + continue; + } R_ProjectSprite(thing); } @@ -2786,9 +2796,9 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) } if (P_IsLocalPlayer(player)) - CONS_Alert(CONS_WARNING, M_GetText("Requested skin not found\n")); + CONS_Alert(CONS_WARNING, M_GetText("Requested skin %d not found\n"), skinnum); else if(server || IsPlayerAdmin(consoleplayer)) - CONS_Alert(CONS_WARNING, "Player %d (%s) skin not found\n", playernum, player_names[playernum]); + CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin } diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 05ac6450e..103398405 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -79,6 +79,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(Init); GETFUNC(Draw2DLine); GETFUNC(DrawPolygon); + GETFUNC(RenderSkyDome); GETFUNC(SetBlend); GETFUNC(ClearBuffer); GETFUNC(SetTexture); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 46c05aea9..f5c7e3714 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1629,6 +1629,7 @@ void I_StartupGraphics(void) HWD.pfnFinishUpdate = NULL; HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); + HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); HWD.pfnSetBlend = hwSym("SetBlend",NULL); HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index d94010d9a..c4b2f98f4 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -878,7 +878,11 @@ boolean I_SetSongSpeed(float speed) #ifdef HAVE_OPENMPT if (openmpt_mhandle) { - char modspd[16]; + char modspd[13]; + + if (speed > 4.0f) + speed = 4.0f; // Limit this to 4x to prevent crashing, stupid fix but... ~SteelT 27/9/19 + sprintf(modspd, "%g", speed); openmpt_module_ctl_set(openmpt_mhandle, "play.tempo_factor", modspd); return true; diff --git a/src/sounds.c b/src/sounds.c index 6940cd9ee..e5dfeec8a 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -218,6 +218,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"chuchu", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Train horn"}, {"bsnipe", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Home-run smash"}, {"sprong", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power spring"}, + {"lvfal1", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rumble"}, + {"pscree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "SCREE!"}, // Menu, interface {"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"}, @@ -504,7 +506,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s3k6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical damage"}, {"s3k6f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, - {"s3k70", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, + {"s3k70", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, {"s3k71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Basic Shield"}, {"s3k72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Movement"}, {"s3k73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"}, @@ -555,7 +557,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3ka0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"}, {"s3ka1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s3ka2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"}, - {"s3ka3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lift"}, + {"s3ka3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising charge"}, {"s3ka4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"}, {"s3ka5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s3ka6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction fizzle"}, diff --git a/src/sounds.h b/src/sounds.h index e5568b59a..9f6e0bab6 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -267,6 +267,8 @@ typedef enum sfx_chuchu, sfx_bsnipe, sfx_sprong, + sfx_lvfal1, + sfx_pscree, // Menu, interface sfx_chchng, diff --git a/src/st_stuff.c b/src/st_stuff.c index c69fce5c1..392cb1c03 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1474,12 +1474,9 @@ static void ST_drawNightsRecords(void) if (P_HasGrades(gamemap, stplyr->lastmare + 1)) { - if (aflag) - V_DrawTranslucentPatch(BASEVIDWIDTH/2 + 60, 160, aflag, - ngradeletters[P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare)]); - else - V_DrawScaledPatch(BASEVIDWIDTH/2 + 60, 160, 0, - ngradeletters[P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare)]); + UINT8 grade = P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare); + if (modeattacking || grade >= GRADE_A) + V_DrawTranslucentPatch(BASEVIDWIDTH/2 + 60, 160, aflag, ngradeletters[grade]); } break; } @@ -1857,7 +1854,8 @@ static void ST_drawNiGHTSHUD(void) numbersize = 48/2; if ((oldspecialstage && leveltime & 2) - && (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))) + && (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) + && !(stplyr->powers[pw_shield] & SH_PROTECTWATER)) col = SKINCOLOR_ORANGE; ST_DrawNightsOverlayNum((160 + numbersize)<