From 8ea7dd418a917d2677356d49c1e456567b1aa1ca Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 9 Dec 2019 13:26:31 +0100 Subject: [PATCH 001/312] Move the axis spawning code out of the mapthing read function, and read the mapthing z in the mapthing read function. --- src/p_setup.c | 55 ++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 3c45509ee..552617dbd 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1009,35 +1009,27 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum) static void P_PrepareRawThings(UINT8 *data, size_t i) { mapthing_t *mt; + sector_t *mtsector; nummapthings = i / (5 * sizeof (INT16)); mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); - // Spawn axis points first so they are - // at the front of the list for fast searching. - mt = mapthings; - for (i = 0; i < nummapthings; i++, mt++) + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { mt->x = READINT16(data); mt->y = READINT16(data); + // Z for objects + mtsector = R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector; + mt->z = (INT16)( +#ifdef ESLOPE + mtsector->f_slope ? P_GetZAt(mtsector->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : +#endif + mtsector->floorheight)>>FRACBITS; mt->angle = READINT16(data); mt->type = READUINT16(data); mt->options = READUINT16(data); mt->extrainfo = (UINT8)(mt->type >> 12); - mt->type &= 4095; - - switch (mt->type) - { - case 1700: // MT_AXIS - case 1701: // MT_AXISTRANSFER - case 1702: // MT_AXISTRANSFERLINE - mt->mobj = NULL; - P_SpawnMapThing(mt); - break; - default: - break; - } } } @@ -1053,21 +1045,26 @@ static void P_LoadThings(boolean loademblems) size_t i; mapthing_t *mt; - // Loading the things lump itself into memory is now handled in P_PrepareThings, above - - mt = mapthings; - numhuntemeralds = 0; - for (i = 0; i < nummapthings; i++, mt++) + // Spawn axis points first so they are at the front of the list for fast searching. + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { - sector_t *mtsector = R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector; + switch (mt->type) + { + case 1700: // MT_AXIS + case 1701: // MT_AXISTRANSFER + case 1702: // MT_AXISTRANSFERLINE + mt->mobj = NULL; + P_SpawnMapThing(mt); + break; + default: + break; + } + } - // Z for objects - mt->z = (INT16)( -#ifdef ESLOPE - mtsector->f_slope ? P_GetZAt(mtsector->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : -#endif - mtsector->floorheight)>>FRACBITS; + numhuntemeralds = 0; + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) + { if (mt->type == 1700 // MT_AXIS || mt->type == 1701 // MT_AXISTRANSFER || mt->type == 1702) // MT_AXISTRANSFERLINE From 6fe6db8e18dbe2907680e5d9c7805fc946679c29 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 9 Dec 2019 14:05:22 +0100 Subject: [PATCH 002/312] Removed seemingly redundant (and incorrect) mapthing Z load code. The proper code seems to sit inside P_SpawnMapThing() and the SpawnHoop functions. Time will tell if I've actually commited an atrocity. --- src/p_setup.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 552617dbd..d082e95b2 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1009,7 +1009,6 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum) static void P_PrepareRawThings(UINT8 *data, size_t i) { mapthing_t *mt; - sector_t *mtsector; nummapthings = i / (5 * sizeof (INT16)); mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); @@ -1018,13 +1017,8 @@ static void P_PrepareRawThings(UINT8 *data, size_t i) { mt->x = READINT16(data); mt->y = READINT16(data); - // Z for objects - mtsector = R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector; - mt->z = (INT16)( -#ifdef ESLOPE - mtsector->f_slope ? P_GetZAt(mtsector->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : -#endif - mtsector->floorheight)>>FRACBITS; + mt->z = 0; + mt->angle = READINT16(data); mt->type = READUINT16(data); mt->options = READUINT16(data); @@ -1137,11 +1131,6 @@ static void P_LoadThings(boolean loademblems) || mt->type == 1705 || mt->type == 1713) // hoops { mt->mobj = NULL; - - // Z for objects Tails 05-26-2002 - mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS) - ->sector->floorheight>>FRACBITS); - P_SpawnHoopsAndRings(mt, false); } } From 3dfa526eead55b4407576b6954c51d3c1a23c876 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Tue, 10 Dec 2019 14:21:08 +0100 Subject: [PATCH 003/312] Separate Emerald Hunt emerald spawning into another function. --- src/p_setup.c | 96 ++++++++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index d082e95b2..86cc9d810 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1017,13 +1017,18 @@ static void P_PrepareRawThings(UINT8 *data, size_t i) { mt->x = READINT16(data); mt->y = READINT16(data); - mt->z = 0; mt->angle = READINT16(data); mt->type = READUINT16(data); mt->options = READUINT16(data); mt->extrainfo = (UINT8)(mt->type >> 12); + mt->type &= 4095; + + if (mt->type == 1705 || (mt->type == 750 && mt->extrainfo)) // NiGHTS Hoops + mt->z = mthing->options; + else + mt->z = mthing->options >> ZSHIFT; } } @@ -1034,6 +1039,51 @@ static void P_PrepareThings(lumpnum_t lumpnum) Z_Free(data); } +static void SpawnEmeraldHunt (void) +{ + INT32 emer1, emer2, emer3; + INT32 timeout = 0; // keeps from getting stuck + + emer1 = emer2 = emer3 = 0; + + //increment spawn numbers because zero is valid. + emer1 = (P_RandomKey(numhuntemeralds)) + 1; + while (timeout++ < 100) + { + emer2 = (P_RandomKey(numhuntemeralds)) + 1; + + if (emer2 != emer1) + break; + } + + timeout = 0; + while (timeout++ < 100) + { + emer3 = (P_RandomKey(numhuntemeralds)) + 1; + + if (emer3 != emer2 && emer3 != emer1) + break; + } + + //decrement spawn values to the actual number because zero is valid. + if (emer1--) + P_SpawnMobj(huntemeralds[emer1]->x<y<z<x<y<z<x<y<z<x<y<z<x<y<z<x<y<z< Date: Tue, 10 Dec 2019 18:03:15 +0100 Subject: [PATCH 004/312] Move mobj spawn Z calculating to a separate function. --- src/p_mobj.c | 181 +++++++++++++++++++++----------------------------- src/p_setup.c | 6 +- 2 files changed, 79 insertions(+), 108 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index dea4a7a4d..e64fb1537 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11550,6 +11550,80 @@ void P_MovePlayerToStarpost(INT32 playernum) mapthing_t *huntemeralds[MAXHUNTEMERALDS]; INT32 numhuntemeralds; + +static fixed_t GetMobjSpawnHeight (const mobjtype_t i, const mapthing_t* mthing, const fixed_t x, const fixed_t y) +{ + subsector_t *ss = R_PointInSubsector(x, y); + fixed_t z; + fixed_t extraoffset = 0; + fixed_t heightoffset = 0; + boolean flip; + + switch (i) + { + // Bumpers never spawn flipped. + case MT_NIGHTSBUMPER: + flip = false; + break; + + // Axis objects snap to the floor. + case MT_AXIS: + case MT_AXISTRANSFER: + case MT_AXISTRANSFERLINE: + return ONFLOORZ; + + // Objects with a non-zero default height. + case MT_CRAWLACOMMANDER: + case MT_DETON: + case MT_JETTBOMBER: + case MT_JETTGUNNER: + case MT_EGGMOBILE2: + heightoffset = mthing->z ? 0 : 33*FRACUNIT; + goto atend; + case MT_EGGMOBILE: + heightoffset = mthing->z ? 0 : 128*FRACUNIT; + goto atend; + case MT_GOLDBUZZ: + case MT_REDBUZZ: + heightoffset = mthing->z ? 0 : 288*FRACUNIT; + goto atend; + + // Ring-like items, may float additional units with MTF_AMBUSH. + case MT_SPIKEBALL: + case MT_EMERALDSPAWN: + case MT_TOKEN: + case MT_EMBLEM: + weaponfloat: + flip = mthing->options & MTF_OBJECTFLIP; + extraoffset = mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; + heightoffset = mthing->z*FRACUNIT; + break; + + // Remaining objects. + default: + if (P_WeaponOrPanel(i)) + goto weaponfloat; // Ring-like items don't use MF_SPAWNCEILING to consider flips. + + atend: + heightoffset = mthing->z*FRACUNIT; + flip = (!!(mobjinfo[i].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); + } + + // Establish height. + if (flip) + return ( +#ifdef ESLOPE + ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : +#endif + ss->sector->ceilingheight) - extraoffset - mobjinfo[i].height; + else + return ( +#ifdef ESLOPE + ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : +#endif + ss->sector->floorheight) + extraoffset + heightoffset; +} + // // P_SpawnMapThing // The fields of the mapthing should @@ -11560,7 +11634,6 @@ void P_SpawnMapThing(mapthing_t *mthing) mobjtype_t i; mobj_t *mobj; fixed_t x, y, z; - subsector_t *ss; boolean doangle = true; if (!mthing->type) @@ -11685,13 +11758,6 @@ You should think about modifying the deathmatch starts to take full advantage of if (gametype != GT_COOP) return; - ss = R_PointInSubsector(mthing->x << FRACBITS, mthing->y << FRACBITS); - mthing->z = (INT16)((( -#ifdef ESLOPE - ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, mthing->x << FRACBITS, mthing->y << FRACBITS) : -#endif - ss->sector->floorheight)>>FRACBITS) + (mthing->options >> ZSHIFT)); - if (numhuntemeralds < MAXHUNTEMERALDS) huntemeralds[numhuntemeralds++] = mthing; return; @@ -11820,102 +11886,7 @@ You should think about modifying the deathmatch starts to take full advantage of // spawn it x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; - ss = R_PointInSubsector(x, y); - - if (i == MT_NIGHTSBUMPER) - z = ( -#ifdef ESLOPE - ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : -#endif - ss->sector->floorheight) + ((mthing->options >> ZSHIFT) << FRACBITS); - else if (i == MT_AXIS || i == MT_AXISTRANSFER || i == MT_AXISTRANSFERLINE) - z = ONFLOORZ; - else if (i == MT_SPIKEBALL || P_WeaponOrPanel(i) || i == MT_EMERALDSPAWN || i == MT_TOKEN || i == MT_EMBLEM) - { - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : -#endif - ss->sector->ceilingheight); - - if (mthing->options & MTF_AMBUSH) // Special flag for rings - z -= 24*FRACUNIT; - if (mthing->options >> ZSHIFT) - z -= (mthing->options >> ZSHIFT)*FRACUNIT; - - z -= mobjinfo[i].height; //Don't forget the height! - } - else - { - z = ( -#ifdef ESLOPE - ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : -#endif - ss->sector->floorheight); - - if (mthing->options & MTF_AMBUSH) // Special flag for rings - z += 24*FRACUNIT; - if (mthing->options >> ZSHIFT) - z += (mthing->options >> ZSHIFT)*FRACUNIT; - } - - if (z == ONFLOORZ) - mthing->z = 0; - else - mthing->z = (INT16)(z>>FRACBITS); - } - else - { - fixed_t offset = 0; - boolean flip = (!!(mobjinfo[i].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); - - // base positions - if (flip) - z = ( -#ifdef ESLOPE - ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : -#endif - ss->sector->ceilingheight) - mobjinfo[i].height; - else - z = ( -#ifdef ESLOPE - ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : -#endif - ss->sector->floorheight); - - // offsetting - if (mthing->options >> ZSHIFT) - offset = ((mthing->options >> ZSHIFT) << FRACBITS); - else if (i == MT_CRAWLACOMMANDER || i == MT_DETON || i == MT_JETTBOMBER || i == MT_JETTGUNNER || i == MT_EGGMOBILE2) - offset = 33*FRACUNIT; - else if (i == MT_EGGMOBILE) - offset = 128*FRACUNIT; - else if (i == MT_GOLDBUZZ || i == MT_REDBUZZ) - offset = 288*FRACUNIT; - - // applying offsets! (if any) - if (flip) - { - if (offset) - z -= offset; - else - z = ONCEILINGZ; - } - else - { - if (offset) - z += offset; - else - z = ONFLOORZ; - } - - if (z == ONFLOORZ) - mthing->z = 0; - else - mthing->z = (INT16)(z>>FRACBITS); - } + z = GetMobjSpawnHeight(i, mthing, x, y); mobj = P_SpawnMobj(x, y, z, i); mobj->spawnpoint = mthing; @@ -12019,7 +11990,7 @@ You should think about modifying the deathmatch starts to take full advantage of if (mthing->angle) mobj->health = mthing->angle; else - mobj->health = FixedMul(ss->sector->ceilingheight-ss->sector->floorheight, 3*(FRACUNIT/4))>>FRACBITS; + mobj->health = FixedMul(mobj->subsector->sector->ceilingheight - mobj->subsector->sector->floorheight, 3*(FRACUNIT/4))>>FRACBITS; break; case MT_METALSONIC_RACE: case MT_METALSONIC_BATTLE: diff --git a/src/p_setup.c b/src/p_setup.c index 86cc9d810..d40c728ab 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1025,10 +1025,10 @@ static void P_PrepareRawThings(UINT8 *data, size_t i) mt->type &= 4095; - if (mt->type == 1705 || (mt->type == 750 && mt->extrainfo)) // NiGHTS Hoops - mt->z = mthing->options; + if (mt->type == 1705 || (mt->type == 750 && mt->extrainfo)) + mt->z = mt->options; // NiGHTS Hoops use the full flags bits to set the height. else - mt->z = mthing->options >> ZSHIFT; + mt->z = mt->options >> ZSHIFT; } } From ca6a7ffbb3e720cc99c1355a58a51f15fdd97282 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Tue, 10 Dec 2019 18:53:49 +0100 Subject: [PATCH 005/312] Fix NiGHTS bumpers height. --- src/p_mobj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index e64fb1537..3321107c7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11563,6 +11563,7 @@ static fixed_t GetMobjSpawnHeight (const mobjtype_t i, const mapthing_t* mthing, { // Bumpers never spawn flipped. case MT_NIGHTSBUMPER: + heightoffset = mthing->z*FRACUNIT; flip = false; break; From 07316fc5bd81e986295cb1b7c00a9a709f5f05d3 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Tue, 10 Dec 2019 23:55:52 -0600 Subject: [PATCH 006/312] Stop characters from being able to activate their abilities when doing a shield ability! Fixes #61. --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index ea42a2c36..d409f6bcd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -5273,7 +5273,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->secondjump = 0; player->pflags &= ~PF_THOKKED; } - else if (player->pflags & PF_SLIDING || (gametype == GT_CTF && player->gotflag)) + else if (player->pflags & PF_SLIDING || (gametype == GT_CTF && player->gotflag) || player->pflags & PF_SHIELDABILITY) ; /*else if (P_SuperReady(player)) { From 584348b91e67371719dba6ed017bdda20a7431a4 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 11 Dec 2019 10:13:52 +0100 Subject: [PATCH 007/312] Do not use mapthing flags to spawn hoops and rings; use the the previously set mapthing Z instead. --- src/p_mobj.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 3321107c7..34d33f788 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13077,7 +13077,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) mobj_t *hoopcenter; INT16 spewangle; - z = mthing->options << FRACBITS; + z = mthing->z << FRACBITS; hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); @@ -13217,8 +13217,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) INT32 hoopsize; INT32 hoopplacement; - // Save our flags! - z = (mthing->options>>ZSHIFT) << FRACBITS; + z = mthing->z << FRACBITS; hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); hoopcenter->spawnpoint = mthing; @@ -13360,8 +13359,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : #endif sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); + if (mthing->z) + z -= (mthing->z << FRACBITS); } else { @@ -13370,8 +13369,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : #endif sec->floorheight); - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); + if (mthing->z) + z += (mthing->z << FRACBITS); } for (r = 1; r <= 5; r++) @@ -13420,8 +13419,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : #endif sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); + if (mthing->z) + z -= (mthing->z << FRACBITS); } else { @@ -13430,8 +13429,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : #endif sec->floorheight); - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); + if (mthing->z) + z += (mthing->z << FRACBITS); } for (r = 1; r <= iterations; r++) @@ -13477,8 +13476,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : #endif sec->floorheight; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); + if (mthing->z) + z += (mthing->z << FRACBITS); closestangle = FixedAngle(mthing->angle*FRACUNIT); @@ -13582,8 +13581,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : #endif sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); + if (mthing->z) + z -= (mthing->z << FRACBITS); } else { @@ -13592,8 +13591,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : #endif sec->floorheight; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); + if (mthing->z) + z += (mthing->z << FRACBITS); } if (mthing->options & MTF_AMBUSH) // Special flag for rings From d2cbdd4fb1ebaf0a2ef2c093197e0a4c6f59a35f Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 11 Dec 2019 10:57:24 +0100 Subject: [PATCH 008/312] Do not overwrite the mapthing Z when spawning rings and similars, as it now causes them to respawn in wrong places because it is being actually used now. --- src/p_mobj.c | 3 --- src/p_setup.c | 4 ---- 2 files changed, 7 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 34d33f788..3d26b28f3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11554,7 +11554,6 @@ INT32 numhuntemeralds; static fixed_t GetMobjSpawnHeight (const mobjtype_t i, const mapthing_t* mthing, const fixed_t x, const fixed_t y) { subsector_t *ss = R_PointInSubsector(x, y); - fixed_t z; fixed_t extraoffset = 0; fixed_t heightoffset = 0; boolean flip; @@ -13603,8 +13602,6 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) z += 24*FRACUNIT; } - mthing->z = (INT16)(z>>FRACBITS); - mobj = P_SpawnMobj(x, y, z, ringthing); mobj->spawnpoint = mthing; diff --git a/src/p_setup.c b/src/p_setup.c index d40c728ab..628292fe0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -906,10 +906,6 @@ void P_ReloadRings(void) { mt->mobj = NULL; - // Z for objects Tails 05-26-2002 - mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS) - ->sector->floorheight>>FRACBITS); - P_SpawnHoopsAndRings(mt, true); } } From 854d50f479f1ab775bfe1e8a3e86aeeb3edb06d6 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 11 Dec 2019 11:44:46 +0100 Subject: [PATCH 009/312] Added 'virtual resource' mechanism for temporary memory loaded lump lists. If you can come up with a better name then I'm all ears. --- src/w_wad.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/w_wad.h | 19 +++++++++++ 2 files changed, 114 insertions(+) diff --git a/src/w_wad.c b/src/w_wad.c index 801f50edd..2e2d00516 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1888,3 +1888,98 @@ int W_VerifyNMUSlumps(const char *filename) }; return W_VerifyFile(filename, NMUSlist, false); } + +/** \brief Generates a virtual resource used for level data loading. + * + * \param lumpnum_t reference + * \return Virtual resource + * + */ +virtres_t* vres_GetMap (lumpnum_t lumpnum) +{ + UINT32 i; + virtres_t* vres = NULL; + virtlump_t* vlumps = NULL; + size_t numlumps = 0; + + if (W_IsLumpWad(lumpnum)) + { + // Remember that we're assuming that the WAD will have a specific set of lumps in a specific order. + UINT8 *wadData = W_CacheLumpNum(lumpnum, PU_LEVEL); + filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); + numlumps = ((wadinfo_t *)wadData)->numlumps; + vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL); + + // Build the lumps. + for (i = 0; i < numlumps; i++) + { + vlumps[i].size = (size_t)(((filelump_t *)(fileinfo + i))->size); + // Play it safe with the name in this case. + memcpy(vlumps[i].name, (fileinfo + i)->name, 8); + vlumps[i].name[8] = '\0'; + vlumps[i].data = Z_Malloc(vlumps[i].size, PU_LEVEL, NULL); // This is memory inefficient, sorry about that. + memcpy(vlumps[i].data, wadData + (fileinfo + i)->filepos, vlumps[i].size); + } + + Z_Free(wadData); + } + else + { + // Count number of lumps until the end of resource OR up until next "MAPXX" lump. + lumpnum_t lumppos = lumpnum + 1; + for (i = LUMPNUM(lumppos); i < wadfiles[WADFILENUM(lumpnum)]->numlumps; i++, lumppos++, numlumps++) + if (memcmp(W_CheckNameForNum(lumppos), "MAP", 3) == 0) + break; + numlumps++; + + vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL); + for (i = 0; i < numlumps; i++, lumpnum++) + { + vlumps[i].size = W_LumpLength(lumpnum); + memcpy(vlumps[i].name, W_CheckNameForNum(lumpnum), 8); + vlumps[i].name[8] = '\0'; + vlumps[i].data = W_CacheLumpNum(lumpnum, PU_LEVEL); + } + } + vres = Z_Malloc(sizeof(virtres_t), PU_LEVEL, NULL); + vres->vlumps = vlumps; + vres->numlumps = numlumps; + return vres; +} + +/** \brief Frees zone memory for a given virtual resource. + * + * \param Virtual resource + */ +void vres_Free (virtres_t* vres) +{ + while (vres->numlumps--) + Z_Free(vres->vlumps[vres->numlumps].data); + Z_Free(vres->vlumps); + Z_Free(vres); +} + +/** (Debug) Prints lumps from a virtual resource into console. + */ +static void vres_Diag (const virtres_t* vres) +{ + UINT32 i; + for (i = 0; i < vres->numlumps; i++) + CONS_Printf("%s\n", vres->vlumps[i].name); +} + +/** \brief Finds a lump in a given virtual resource. + * + * \param Virtual resource + * \param Lump name to look for + * \return Virtual lump if found, NULL otherwise + * + */ +virtlump_t* vres_Find(const virtres_t* vres, const char* name) +{ + UINT32 i; + for (i = 0; i < vres->numlumps; i++) + if (fastcmp(name, vres->vlumps[i].name)) + return &vres->vlumps[i]; + return NULL; +} diff --git a/src/w_wad.h b/src/w_wad.h index a8be13ece..a265d78a9 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -72,6 +72,25 @@ typedef struct compmethod compression; // lump compression method } lumpinfo_t; +// ========================================================================= +// 'VIRTUAL' RESOURCES +// ========================================================================= + +typedef struct { + char name[9]; + UINT8* data; + size_t size; +} virtlump_t; + +typedef struct { + size_t numlumps; + virtlump_t* vlumps; +} virtres_t; + +virtres_t* vres_GetMap (lumpnum_t); +void vres_Free (virtres_t*); +virtlump_t* vres_Find (const virtres_t*, const char*); + // ========================================================================= // DYNAMIC WAD LOADING // ========================================================================= From f7c69f0c1cb81206f45db21ec93d15329b8ff188 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 11 Dec 2019 12:48:41 +0100 Subject: [PATCH 010/312] P_SetupLevel() no longer makes distinction on whether the map is a WAD in a PK3 or not. --- src/p_setup.c | 128 ++++++++++++++------------------------------------ 1 file changed, 34 insertions(+), 94 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 3c45509ee..74d33f8f5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1950,7 +1950,7 @@ static boolean P_LoadBlockMap(lumpnum_t lumpnum) // because making both the WAD and PK3 loading code use // the same functions is trickier than it looks for blockmap // -- Monster Iestyn 09/01/18 -static boolean P_LoadRawBlockMap(UINT8 *data, size_t count, const char *lumpname) +static boolean P_LoadRawBlockMap(UINT8 *data, size_t count) { #if 0 (void)data; @@ -1958,12 +1958,6 @@ static boolean P_LoadRawBlockMap(UINT8 *data, size_t count, const char *lumpname (void)lumpname; return false; #else - // Check if the lump is named "BLOCKMAP" - if (!lumpname || memcmp(lumpname, "BLOCKMAP", 8) != 0) - { - CONS_Printf("No blockmap lump found for pk3!\n"); - return false; - } if (!count || count >= 0x20000) return false; @@ -2120,16 +2114,8 @@ static void P_LoadReject(lumpnum_t lumpnum) // PK3 version // -- Monster Iestyn 09/01/18 -static void P_LoadRawReject(UINT8 *data, size_t count, const char *lumpname) +static void P_LoadRawReject(UINT8 *data, size_t count) { - // Check if the lump is named "REJECT" - if (!lumpname || memcmp(lumpname, "REJECT\0\0", 8) != 0) - { - rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadRawReject: No valid REJECT lump found\n"); - return; - } - if (!count) // zero length, someone probably used ZDBSP { rejectmatrix = NULL; @@ -2892,51 +2878,42 @@ boolean P_SetupLevel(boolean skipprecip) P_MakeMapMD5(lastloadedmaplumpnum, &mapmd5); - // HACK ALERT: Cache the WAD, get the map data into the tables, free memory. - // As it is implemented right now, we're assuming an uncompressed WAD. - // (As in, a normal PWAD, not ZWAD or anything. The lump itself can be compressed.) - // We're not accounting for extra lumps and scrambled lump positions. Any additional data will cause an error. - if (W_IsLumpWad(lastloadedmaplumpnum)) + if (lastloadedmaplumpnum) { - // Remember that we're assuming that the WAD will have a specific set of lumps in a specific order. - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - //filelump_t *fileinfo = wadData + ((wadinfo_t *)wadData)->infotableofs; - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); - UINT32 numlumps = ((wadinfo_t *)wadData)->numlumps; + virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); + virtlump_t* virtthings = vres_Find(virt, "THINGS"); + virtlump_t* virtvertexes = vres_Find(virt, "VERTEXES"); + virtlump_t* virtsectors = vres_Find(virt, "SECTORS"); + virtlump_t* virtsidedefs = vres_Find(virt, "SIDEDEFS"); + virtlump_t* virtlinedefs = vres_Find(virt, "LINEDEFS"); - if (numlumps < ML_REJECT) // at least 9 lumps should be in the wad for a map to be loaded - { - I_Error("Bad WAD file for map %s!\n", maplumpname); - } + virtlump_t* virtssectors = vres_Find(virt, "SSECTORS"); + virtlump_t* virtsegs = vres_Find(virt, "SEGS"); + virtlump_t* virtnodes = vres_Find(virt, "NODES"); - if (numlumps > ML_BLOCKMAP) // enough room for a BLOCKMAP lump at least - { - loadedbm = P_LoadRawBlockMap( - wadData + (fileinfo + ML_BLOCKMAP)->filepos, - (fileinfo + ML_BLOCKMAP)->size, - (fileinfo + ML_BLOCKMAP)->name); - } - P_LoadRawVertexes(wadData + (fileinfo + ML_VERTEXES)->filepos, (fileinfo + ML_VERTEXES)->size); - P_LoadRawSectors(wadData + (fileinfo + ML_SECTORS)->filepos, (fileinfo + ML_SECTORS)->size); - P_LoadRawSideDefs((fileinfo + ML_SIDEDEFS)->size); - P_LoadRawLineDefs(wadData + (fileinfo + ML_LINEDEFS)->filepos, (fileinfo + ML_LINEDEFS)->size); - P_LoadRawSideDefs2(wadData + (fileinfo + ML_SIDEDEFS)->filepos); - P_LoadRawSubsectors(wadData + (fileinfo + ML_SSECTORS)->filepos, (fileinfo + ML_SSECTORS)->size); - P_LoadRawNodes(wadData + (fileinfo + ML_NODES)->filepos, (fileinfo + ML_NODES)->size); - P_LoadRawSegs(wadData + (fileinfo + ML_SEGS)->filepos, (fileinfo + ML_SEGS)->size); - if (numlumps > ML_REJECT) // enough room for a REJECT lump at least - { - P_LoadRawReject( - wadData + (fileinfo + ML_REJECT)->filepos, - (fileinfo + ML_REJECT)->size, - (fileinfo + ML_REJECT)->name); - } + virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP"); + virtlump_t* virtreject = vres_Find(virt, "REJECT"); + + P_LoadRawVertexes(virtvertexes->data, virtvertexes->size); + P_LoadRawSectors(virtsectors->data, virtsectors->size); + P_LoadRawSideDefs(virtsidedefs->size); + P_LoadRawLineDefs(virtlinedefs->data, virtlinedefs->size); + P_LoadRawSideDefs2(virtsidedefs->data); + P_LoadRawSubsectors(virtssectors->data, virtssectors->size); + P_LoadRawNodes(virtnodes->data, virtnodes->size); + P_LoadRawSegs(virtsegs->data, virtsegs->size); + + if (virtreject) + P_LoadRawReject(virtreject->data, virtreject->size); + else + rejectmatrix = NULL; + + if (!(virtblockmap && P_LoadRawBlockMap(virtblockmap->data, virtblockmap->size))) + P_CreateBlockMap(); - // Important: take care of the ordering of the next functions. - if (!loadedbm) - P_CreateBlockMap(); // Graue 02-29-2004 P_LoadLineDefs2(); P_GroupLines(); + numdmstarts = numredctfstarts = numbluectfstarts = 0; // reset the player starts @@ -2954,46 +2931,9 @@ boolean P_SetupLevel(boolean skipprecip) P_MapStart(); - P_PrepareRawThings(wadData + (fileinfo + ML_THINGS)->filepos, (fileinfo + ML_THINGS)->size); - Z_Free(wadData); - } - else - { - // Important: take care of the ordering of the next functions. - loadedbm = P_LoadBlockMap(lastloadedmaplumpnum + ML_BLOCKMAP); - P_LoadVertexes(lastloadedmaplumpnum + ML_VERTEXES); - P_LoadSectors(lastloadedmaplumpnum + ML_SECTORS); - P_LoadSideDefs(lastloadedmaplumpnum + ML_SIDEDEFS); - P_LoadLineDefs(lastloadedmaplumpnum + ML_LINEDEFS); - P_LoadSideDefs2(lastloadedmaplumpnum + ML_SIDEDEFS); - P_LoadSubsectors(lastloadedmaplumpnum + ML_SSECTORS); - P_LoadNodes(lastloadedmaplumpnum + ML_NODES); - P_LoadSegs(lastloadedmaplumpnum + ML_SEGS); - P_LoadReject(lastloadedmaplumpnum + ML_REJECT); + P_PrepareRawThings(virtthings->data, virtthings->size); - // Important: take care of the ordering of the next functions. - if (!loadedbm) - P_CreateBlockMap(); // Graue 02-29-2004 - P_LoadLineDefs2(); - P_GroupLines(); - numdmstarts = numredctfstarts = numbluectfstarts = 0; - - // reset the player starts - for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; - - for (i = 0; i < MAX_DM_STARTS; i++) - deathmatchstarts[i] = NULL; - - for (i = 0; i < 2; i++) - skyboxmo[i] = NULL; - - for (i = 0; i < 16; i++) - skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; - - P_MapStart(); - - P_PrepareThings(lastloadedmaplumpnum + ML_THINGS); + vres_Free(virt); } // init gravity, tag lists, From bf5a2c68d594c09d802f8f99720845b9b4e96029 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 11 Dec 2019 12:48:41 +0100 Subject: [PATCH 011/312] P_SetupLevel() no longer makes distinction on whether the map is a WAD in a PK3 or not. --- src/p_saveg.c | 28 ++--------- src/p_setup.c | 128 ++++++++++++++------------------------------------ 2 files changed, 39 insertions(+), 117 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 89447db80..c876713e4 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -781,9 +781,10 @@ static void P_NetArchiveWorld(void) UINT8 *put; // reload the map just to see difference - mapsector_t *ms; - mapsidedef_t *msd; - maplinedef_t *mld; + virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); + mapsector_t *ms = (mapsector_t*) vres_Find(virt, "SECTORS")->data; + mapsidedef_t *msd = (mapsidedef_t*) vres_Find(virt, "SIDEDEFS")->data; + maplinedef_t *mld = (maplinedef_t*) vres_Find(virt, "LINEDEFS")->data; const sector_t *ss = sectors; UINT8 diff, diff2, diff3; @@ -793,26 +794,6 @@ static void P_NetArchiveWorld(void) WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); put = save_p; - if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3 - { // HACK: Open wad file rather quickly so we can get the data from the relevant lumps - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); -#define retrieve_mapdata(d, f)\ - d = Z_Malloc((f)->size, PU_CACHE, NULL); \ - M_Memcpy(d, wadData + (f)->filepos, (f)->size) - retrieve_mapdata(ms, fileinfo + ML_SECTORS); - retrieve_mapdata(mld, fileinfo + ML_LINEDEFS); - retrieve_mapdata(msd, fileinfo + ML_SIDEDEFS); -#undef retrieve_mapdata - Z_Free(wadData); // we're done with this now - } - else // phew it's just a WAD - { - ms = W_CacheLumpNum(lastloadedmaplumpnum+ML_SECTORS, PU_CACHE); - mld = W_CacheLumpNum(lastloadedmaplumpnum+ML_LINEDEFS, PU_CACHE); - msd = W_CacheLumpNum(lastloadedmaplumpnum+ML_SIDEDEFS, PU_CACHE); - } - for (i = 0; i < numsectors; i++, ss++, ms++) { diff = diff2 = diff3 = 0; @@ -1037,6 +1018,7 @@ static void P_NetArchiveWorld(void) WRITEUINT16(put, 0xffff); R_ClearTextureNumCache(false); + vres_Free(virt); save_p = put; } diff --git a/src/p_setup.c b/src/p_setup.c index 3c45509ee..74d33f8f5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1950,7 +1950,7 @@ static boolean P_LoadBlockMap(lumpnum_t lumpnum) // because making both the WAD and PK3 loading code use // the same functions is trickier than it looks for blockmap // -- Monster Iestyn 09/01/18 -static boolean P_LoadRawBlockMap(UINT8 *data, size_t count, const char *lumpname) +static boolean P_LoadRawBlockMap(UINT8 *data, size_t count) { #if 0 (void)data; @@ -1958,12 +1958,6 @@ static boolean P_LoadRawBlockMap(UINT8 *data, size_t count, const char *lumpname (void)lumpname; return false; #else - // Check if the lump is named "BLOCKMAP" - if (!lumpname || memcmp(lumpname, "BLOCKMAP", 8) != 0) - { - CONS_Printf("No blockmap lump found for pk3!\n"); - return false; - } if (!count || count >= 0x20000) return false; @@ -2120,16 +2114,8 @@ static void P_LoadReject(lumpnum_t lumpnum) // PK3 version // -- Monster Iestyn 09/01/18 -static void P_LoadRawReject(UINT8 *data, size_t count, const char *lumpname) +static void P_LoadRawReject(UINT8 *data, size_t count) { - // Check if the lump is named "REJECT" - if (!lumpname || memcmp(lumpname, "REJECT\0\0", 8) != 0) - { - rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadRawReject: No valid REJECT lump found\n"); - return; - } - if (!count) // zero length, someone probably used ZDBSP { rejectmatrix = NULL; @@ -2892,51 +2878,42 @@ boolean P_SetupLevel(boolean skipprecip) P_MakeMapMD5(lastloadedmaplumpnum, &mapmd5); - // HACK ALERT: Cache the WAD, get the map data into the tables, free memory. - // As it is implemented right now, we're assuming an uncompressed WAD. - // (As in, a normal PWAD, not ZWAD or anything. The lump itself can be compressed.) - // We're not accounting for extra lumps and scrambled lump positions. Any additional data will cause an error. - if (W_IsLumpWad(lastloadedmaplumpnum)) + if (lastloadedmaplumpnum) { - // Remember that we're assuming that the WAD will have a specific set of lumps in a specific order. - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - //filelump_t *fileinfo = wadData + ((wadinfo_t *)wadData)->infotableofs; - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); - UINT32 numlumps = ((wadinfo_t *)wadData)->numlumps; + virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); + virtlump_t* virtthings = vres_Find(virt, "THINGS"); + virtlump_t* virtvertexes = vres_Find(virt, "VERTEXES"); + virtlump_t* virtsectors = vres_Find(virt, "SECTORS"); + virtlump_t* virtsidedefs = vres_Find(virt, "SIDEDEFS"); + virtlump_t* virtlinedefs = vres_Find(virt, "LINEDEFS"); - if (numlumps < ML_REJECT) // at least 9 lumps should be in the wad for a map to be loaded - { - I_Error("Bad WAD file for map %s!\n", maplumpname); - } + virtlump_t* virtssectors = vres_Find(virt, "SSECTORS"); + virtlump_t* virtsegs = vres_Find(virt, "SEGS"); + virtlump_t* virtnodes = vres_Find(virt, "NODES"); - if (numlumps > ML_BLOCKMAP) // enough room for a BLOCKMAP lump at least - { - loadedbm = P_LoadRawBlockMap( - wadData + (fileinfo + ML_BLOCKMAP)->filepos, - (fileinfo + ML_BLOCKMAP)->size, - (fileinfo + ML_BLOCKMAP)->name); - } - P_LoadRawVertexes(wadData + (fileinfo + ML_VERTEXES)->filepos, (fileinfo + ML_VERTEXES)->size); - P_LoadRawSectors(wadData + (fileinfo + ML_SECTORS)->filepos, (fileinfo + ML_SECTORS)->size); - P_LoadRawSideDefs((fileinfo + ML_SIDEDEFS)->size); - P_LoadRawLineDefs(wadData + (fileinfo + ML_LINEDEFS)->filepos, (fileinfo + ML_LINEDEFS)->size); - P_LoadRawSideDefs2(wadData + (fileinfo + ML_SIDEDEFS)->filepos); - P_LoadRawSubsectors(wadData + (fileinfo + ML_SSECTORS)->filepos, (fileinfo + ML_SSECTORS)->size); - P_LoadRawNodes(wadData + (fileinfo + ML_NODES)->filepos, (fileinfo + ML_NODES)->size); - P_LoadRawSegs(wadData + (fileinfo + ML_SEGS)->filepos, (fileinfo + ML_SEGS)->size); - if (numlumps > ML_REJECT) // enough room for a REJECT lump at least - { - P_LoadRawReject( - wadData + (fileinfo + ML_REJECT)->filepos, - (fileinfo + ML_REJECT)->size, - (fileinfo + ML_REJECT)->name); - } + virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP"); + virtlump_t* virtreject = vres_Find(virt, "REJECT"); + + P_LoadRawVertexes(virtvertexes->data, virtvertexes->size); + P_LoadRawSectors(virtsectors->data, virtsectors->size); + P_LoadRawSideDefs(virtsidedefs->size); + P_LoadRawLineDefs(virtlinedefs->data, virtlinedefs->size); + P_LoadRawSideDefs2(virtsidedefs->data); + P_LoadRawSubsectors(virtssectors->data, virtssectors->size); + P_LoadRawNodes(virtnodes->data, virtnodes->size); + P_LoadRawSegs(virtsegs->data, virtsegs->size); + + if (virtreject) + P_LoadRawReject(virtreject->data, virtreject->size); + else + rejectmatrix = NULL; + + if (!(virtblockmap && P_LoadRawBlockMap(virtblockmap->data, virtblockmap->size))) + P_CreateBlockMap(); - // Important: take care of the ordering of the next functions. - if (!loadedbm) - P_CreateBlockMap(); // Graue 02-29-2004 P_LoadLineDefs2(); P_GroupLines(); + numdmstarts = numredctfstarts = numbluectfstarts = 0; // reset the player starts @@ -2954,46 +2931,9 @@ boolean P_SetupLevel(boolean skipprecip) P_MapStart(); - P_PrepareRawThings(wadData + (fileinfo + ML_THINGS)->filepos, (fileinfo + ML_THINGS)->size); - Z_Free(wadData); - } - else - { - // Important: take care of the ordering of the next functions. - loadedbm = P_LoadBlockMap(lastloadedmaplumpnum + ML_BLOCKMAP); - P_LoadVertexes(lastloadedmaplumpnum + ML_VERTEXES); - P_LoadSectors(lastloadedmaplumpnum + ML_SECTORS); - P_LoadSideDefs(lastloadedmaplumpnum + ML_SIDEDEFS); - P_LoadLineDefs(lastloadedmaplumpnum + ML_LINEDEFS); - P_LoadSideDefs2(lastloadedmaplumpnum + ML_SIDEDEFS); - P_LoadSubsectors(lastloadedmaplumpnum + ML_SSECTORS); - P_LoadNodes(lastloadedmaplumpnum + ML_NODES); - P_LoadSegs(lastloadedmaplumpnum + ML_SEGS); - P_LoadReject(lastloadedmaplumpnum + ML_REJECT); + P_PrepareRawThings(virtthings->data, virtthings->size); - // Important: take care of the ordering of the next functions. - if (!loadedbm) - P_CreateBlockMap(); // Graue 02-29-2004 - P_LoadLineDefs2(); - P_GroupLines(); - numdmstarts = numredctfstarts = numbluectfstarts = 0; - - // reset the player starts - for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; - - for (i = 0; i < MAX_DM_STARTS; i++) - deathmatchstarts[i] = NULL; - - for (i = 0; i < 2; i++) - skyboxmo[i] = NULL; - - for (i = 0; i < 16; i++) - skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; - - P_MapStart(); - - P_PrepareThings(lastloadedmaplumpnum + ML_THINGS); + vres_Free(virt); } // init gravity, tag lists, From 4d86dc11a639043e44794fd2159dd6ed954a522d Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 11 Dec 2019 13:54:15 +0100 Subject: [PATCH 012/312] 'prepare' mapthings using virtres in P_LevelInitStuff(). Whether 'preparing' them or not is actually necessary is another matter. --- src/p_setup.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 74d33f8f5..587b0b55a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2303,6 +2303,8 @@ void P_LoadThingsOnly(void) // Search through all the thinkers. thinker_t *think; INT32 i, viewid = -1, centerid = -1; // for skyboxes + virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); + virtlump_t* vth = vres_Find(virt, "THINGS"); // check if these are any of the normal viewpoint/centerpoint mobjs in the level or not if (skyboxmo[0] || skyboxmo[1]) @@ -2314,7 +2316,6 @@ void P_LoadThingsOnly(void) centerid = i; // save id just in case } - for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) @@ -2324,18 +2325,11 @@ void P_LoadThingsOnly(void) P_LevelInitStuff(); - if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3 - { // HACK: Open wad file rather quickly so we can use the things lump - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); - fileinfo += ML_THINGS; // we only need the THINGS lump - P_PrepareRawThings(wadData + fileinfo->filepos, fileinfo->size); - Z_Free(wadData); // we're done with this now - } - else // phew it's just a WAD - P_PrepareThings(lastloadedmaplumpnum + ML_THINGS); + P_PrepareRawThings(vth->data, vth->size); P_LoadThings(true); + vres_Free(virt); + // restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that skyboxmo[0] = skyboxviewpnts[(viewid >= 0) ? viewid : 0]; skyboxmo[1] = skyboxcenterpnts[(centerid >= 0) ? centerid : 0]; From 14ad3b938e7ece8aee71ba4c856ff1b3780186c6 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 11 Dec 2019 14:04:09 +0100 Subject: [PATCH 013/312] Use virtres in P_SpawnSpecials(). Whether accessing the lump again here is right or not is also a different question. --- src/p_spec.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index dba4e17b5..8ec1646ce 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6425,7 +6425,7 @@ void P_SpawnSpecials(INT32 fromnetsave) INT32 j; thinkerlist_t *secthinkers; thinker_t *th; - + virtres_t* virt = NULL; // This used to be used, and *should* be used in the future, // but currently isn't. (void)fromnetsave; @@ -7177,17 +7177,10 @@ void P_SpawnSpecials(INT32 fromnetsave) UINT8 *data; UINT16 b; - if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3 - { // HACK: Open wad file rather quickly so we can get the data from the sidedefs lump - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); - fileinfo += ML_SIDEDEFS; // we only need the SIDEDEFS lump - data = Z_Malloc(fileinfo->size, PU_STATIC, NULL); - M_Memcpy(data, wadData + fileinfo->filepos, fileinfo->size); // copy data - Z_Free(wadData); // we're done with this now - } - else // phew it's just a WAD - data = W_CacheLumpNum(lastloadedmaplumpnum + ML_SIDEDEFS,PU_STATIC); + if (!virt) + virt = vres_GetMap(lastloadedmaplumpnum); + + data = (UINT8*) vres_Find(virt, "SIDEDEFS")->data; for (b = 0; b < (INT16)numsides; b++) { @@ -7433,6 +7426,9 @@ void P_SpawnSpecials(INT32 fromnetsave) } } + if (virt) + vres_Free(virt); + // Allocate each list for (i = 0; i < numsectors; i++) if(secthinkers[i].thinkers) From 9952bae5ee5174c2c1a63da4db435c9eeeb3982b Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 11 Dec 2019 14:20:08 +0100 Subject: [PATCH 014/312] P_MakeMapMD5() now uses virtres. --- src/p_setup.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 587b0b55a..e2d67581b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2361,7 +2361,7 @@ static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock) #endif } -static void P_MakeMapMD5(lumpnum_t maplumpnum, void *dest) +static void P_MakeMapMD5(virtres_t* virt, void *dest) { unsigned char linemd5[16]; unsigned char sectormd5[16]; @@ -2372,20 +2372,15 @@ static void P_MakeMapMD5(lumpnum_t maplumpnum, void *dest) // Create a hash for the current map // get the actual lumps! - UINT8 *datalines = W_CacheLumpNum(maplumpnum + ML_LINEDEFS, PU_CACHE); - UINT8 *datasectors = W_CacheLumpNum(maplumpnum + ML_SECTORS, PU_CACHE); - UINT8 *datathings = W_CacheLumpNum(maplumpnum + ML_THINGS, PU_CACHE); - UINT8 *datasides = W_CacheLumpNum(maplumpnum + ML_SIDEDEFS, PU_CACHE); + virtlump_t* virtlines = vres_Find(virt, "LINEDEFS"); + virtlump_t* virtsectors = vres_Find(virt, "SECTORS"); + virtlump_t* virtmthings = vres_Find(virt, "THINGS"); + virtlump_t* virtsides = vres_Find(virt, "SIDEDEFS"); - P_MakeBufferMD5((char*)datalines, W_LumpLength(maplumpnum + ML_LINEDEFS), linemd5); - P_MakeBufferMD5((char*)datasectors, W_LumpLength(maplumpnum + ML_SECTORS), sectormd5); - P_MakeBufferMD5((char*)datathings, W_LumpLength(maplumpnum + ML_THINGS), thingmd5); - P_MakeBufferMD5((char*)datasides, W_LumpLength(maplumpnum + ML_SIDEDEFS), sidedefmd5); - - Z_Free(datalines); - Z_Free(datasectors); - Z_Free(datathings); - Z_Free(datasides); + P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5); + P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5); + P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5); + P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5); for (i = 0; i < 16; i++) resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF; @@ -2870,8 +2865,6 @@ boolean P_SetupLevel(boolean skipprecip) // SRB2 determines the sky texture to be used depending on the map header. P_SetupLevelSky(mapheaderinfo[gamemap-1]->skynum, true); - P_MakeMapMD5(lastloadedmaplumpnum, &mapmd5); - if (lastloadedmaplumpnum) { virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); @@ -2888,6 +2881,8 @@ boolean P_SetupLevel(boolean skipprecip) virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP"); virtlump_t* virtreject = vres_Find(virt, "REJECT"); + P_MakeMapMD5(virt, &mapmd5); + P_LoadRawVertexes(virtvertexes->data, virtvertexes->size); P_LoadRawSectors(virtsectors->data, virtsectors->size); P_LoadRawSideDefs(virtsidedefs->size); From a87a9e6ff6a9844d75d5be29ad70ef2d5b0e2bbe Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 11 Dec 2019 14:40:31 +0100 Subject: [PATCH 015/312] Remove wrappers and dupes for map lump reading, as they are no longer used. --- src/p_setup.c | 168 -------------------------------------------------- 1 file changed, 168 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index e2d67581b..17909ee58 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -397,13 +397,6 @@ static inline void P_LoadRawVertexes(UINT8 *data, size_t i) } } -static inline void P_LoadVertexes(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawVertexes(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - /** Computes the length of a seg in fracunits. * * \param seg Seg to compute length for. @@ -488,14 +481,6 @@ static void P_LoadRawSegs(UINT8 *data, size_t i) } } -static void P_LoadSegs(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSegs(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - - /** Loads the SSECTORS resource from a level. * * \param lump Lump number of the SSECTORS resource. @@ -525,13 +510,6 @@ static inline void P_LoadRawSubsectors(void *data, size_t i) } } -static void P_LoadSubsectors(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSubsectors(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - // // levelflats // @@ -805,13 +783,6 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) P_SetupLevelFlatAnims(); } -static void P_LoadSectors(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSectors(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - // // P_LoadNodes // @@ -844,13 +815,6 @@ static void P_LoadRawNodes(UINT8 *data, size_t i) } } -static void P_LoadNodes(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawNodes(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - // // P_ReloadRings // Used by NiGHTS, clears all ring/wing/etc items and respawns them @@ -1041,13 +1005,6 @@ static void P_PrepareRawThings(UINT8 *data, size_t i) } } -static void P_PrepareThings(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_PrepareRawThings(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - static void P_LoadThings(boolean loademblems) { size_t i; @@ -1300,13 +1257,6 @@ static void P_LoadRawLineDefs(UINT8 *data, size_t i) } } -static void P_LoadLineDefs(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawLineDefs(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - static void P_LoadLineDefs2(void) { size_t i = numlines; @@ -1419,12 +1369,6 @@ static inline void P_LoadRawSideDefs(size_t i) sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); } -static inline void P_LoadSideDefs(lumpnum_t lumpnum) -{ - P_LoadRawSideDefs(W_LumpLength(lumpnum)); -} - - static void P_LoadRawSideDefs2(void *data) { UINT16 i; @@ -1585,15 +1529,6 @@ static void P_LoadRawSideDefs2(void *data) R_ClearTextureNumCache(true); } -// Delay loading texture names until after loaded linedefs. -static void P_LoadSideDefs2(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSideDefs2(data); - Z_Free(data); -} - - static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, fixed_t bx1, fixed_t by1) { fixed_t bbox[4]; @@ -1873,79 +1808,6 @@ static void P_ReadBlockMapLump(INT16 *wadblockmaplump, size_t count) } } -// -// P_LoadBlockMap -// -// Levels might not have a blockmap, so if one does not exist -// this should return false. -static boolean P_LoadBlockMap(lumpnum_t lumpnum) -{ -#if 0 - (void)lumpnum; - return false; -#else - size_t count; - const char *lumpname = W_CheckNameForNum(lumpnum); - - // Check if the lump exists, and if it's named "BLOCKMAP" - if (!lumpname || memcmp(lumpname, "BLOCKMAP", 8) != 0) - { - return false; - } - - count = W_LumpLength(lumpnum); - - if (!count || count >= 0x20000) - return false; - - { - INT16 *wadblockmaplump = malloc(count); //INT16 *wadblockmaplump = W_CacheLumpNum (lump, PU_LEVEL); - if (!wadblockmaplump) - return false; - W_ReadLump(lumpnum, wadblockmaplump); - count /= 2; - P_ReadBlockMapLump(wadblockmaplump, count); - free(wadblockmaplump); - } - - bmaporgx = blockmaplump[0]< Date: Wed, 11 Dec 2019 15:16:56 +0100 Subject: [PATCH 016/312] Oversight, do not free the data yet vres_Free() does it already at the end. --- src/p_spec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 8ec1646ce..b50fc66c0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7200,7 +7200,6 @@ void P_SpawnSpecials(INT32 fromnetsave) I_Error("Make-Your-Own-FOF (tag %d) needs a value in the linedef's second side upper texture field.", lines[i].tag); } } - Z_Free(data); } else I_Error("Make-Your-Own FOF (tag %d) found without a 2nd linedef side!", lines[i].tag); From d34fd4b755f7cf80cf84ca6ed31e337ff2ad762c Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 11 Dec 2019 15:48:44 +0100 Subject: [PATCH 017/312] Epic oversight in upside-down spawn offset. --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 3d26b28f3..dae891afd 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11615,7 +11615,7 @@ static fixed_t GetMobjSpawnHeight (const mobjtype_t i, const mapthing_t* mthing, #ifdef ESLOPE ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : #endif - ss->sector->ceilingheight) - extraoffset - mobjinfo[i].height; + ss->sector->ceilingheight) - extraoffset - heightoffset - mobjinfo[i].height; else return ( #ifdef ESLOPE From edfe053cc304161a8b0cf56b35dc93edbe5d3e6b Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 11 Dec 2019 16:37:41 +0100 Subject: [PATCH 018/312] Treat warnings as errors; comment out unused function. --- src/w_wad.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/w_wad.c b/src/w_wad.c index 2e2d00516..f16e8eb5b 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1944,6 +1944,7 @@ virtres_t* vres_GetMap (lumpnum_t lumpnum) vres = Z_Malloc(sizeof(virtres_t), PU_LEVEL, NULL); vres->vlumps = vlumps; vres->numlumps = numlumps; + return vres; } @@ -1961,12 +1962,14 @@ void vres_Free (virtres_t* vres) /** (Debug) Prints lumps from a virtual resource into console. */ +/* static void vres_Diag (const virtres_t* vres) { UINT32 i; for (i = 0; i < vres->numlumps; i++) CONS_Printf("%s\n", vres->vlumps[i].name); } +*/ /** \brief Finds a lump in a given virtual resource. * From d40359ee02a876efafdec5c77e9122ce166c0e58 Mon Sep 17 00:00:00 2001 From: Tatsuru Date: Wed, 11 Dec 2019 02:07:09 -0300 Subject: [PATCH 019/312] Hugging now requires being in the same Z position Don't try this at home --- src/p_mobj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index dea4a7a4d..a6812ff01 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7833,7 +7833,8 @@ void P_MobjThinker(mobj_t *mobj) 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)); + // Tatsuru: Don't try to hug them if they're above or below you! + targonground = (P_IsObjectOnGround(mobj->target) && (player->panim == PA_IDLE || player->panim == PA_WALK || player->panim == PA_RUN) && player->mo->z == mobj->z); love = (player->skin == 0 || player->skin == 5); switch (stat) From 43cbad200cfb340c4d13ee0b3808570e60c86aa4 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Thu, 12 Dec 2019 10:35:38 +0100 Subject: [PATCH 020/312] Move loading functions around a bit and refactor the stage data allocation code. --- src/p_setup.c | 173 +++++++++++++++++++++++++------------------------- 1 file changed, 87 insertions(+), 86 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 17909ee58..f569c4b73 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -373,21 +373,11 @@ UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade) * \sa ML_VERTEXES */ -static inline void P_LoadRawVertexes(UINT8 *data, size_t i) +static inline void P_LoadRawVertexes(UINT8 *data) { - mapvertex_t *ml; - vertex_t *li; - - numvertexes = i / sizeof (mapvertex_t); - - if (numvertexes <= 0) - I_Error("Level has no vertices"); // instead of crashing - - // Allocate zone memory for buffer. - vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); - - ml = (mapvertex_t *)data; - li = vertexes; + mapvertex_t *ml = (mapvertex_t *)data; + vertex_t *li = vertexes; + size_t i; // Copy and convert vertex coordinates, internal representation as fixed. for (i = 0; i < numvertexes; i++, li++, ml++) @@ -677,19 +667,12 @@ INT32 P_CheckLevelFlat(const char *flatname) // Sets up the ingame sectors structures. // Lumpnum is the lumpnum of a SECTORS lump. -static void P_LoadRawSectors(UINT8 *data, size_t i) +static void P_LoadRawSectors(UINT8 *data) { - mapsector_t *ms; - sector_t *ss; + mapsector_t *ms = (mapsector_t *)data; + sector_t *ss = sectors; levelflat_t *foundflats; - - // We count how many sectors we got. - numsectors = i / sizeof (mapsector_t); - if (numsectors <= 0) - I_Error("Level has no sectors"); - - // Allocate as much memory as we need into the global sectors table. - sectors = Z_Calloc(numsectors*sizeof (*sectors), PU_LEVEL, NULL); + size_t i; // Allocate a big chunk of memory as big as our MAXLEVELFLATS limit. //Fab : FIXME: allocate for whatever number of flats - 512 different flats per level should be plenty @@ -700,8 +683,6 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) numlevelflats = 0; // For each counted sector, copy the sector raw data from our cache pointer ms, to the global table pointer ss. - ms = (mapsector_t *)data; - ss = sectors; for (i = 0; i < numsectors; i++, ss++, ms++) { ss->floorheight = SHORT(ms->floorheight)<flags = SHORT(mld->flags); ld->special = SHORT(mld->special); ld->tag = SHORT(mld->tag); - v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; - v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; - ld->dx = v2->x - v1->x; - ld->dy = v2->y - v1->y; + ld->v1 = &vertexes[SHORT(mld->v1)]; + ld->v2 = &vertexes[SHORT(mld->v2)]; + + ld->sidenum[0] = SHORT(mld->sidenum[0]); + ld->sidenum[1] = SHORT(mld->sidenum[1]); + } +} + +static void SetupLines (void) +{ + line_t *ld = lines; + size_t i; + + for (i = 0; i < numlines; i++, ld++) + { + vertex_t *v1 = ld->v1; + vertex_t *v2 = ld->v2; #ifdef WALLSPLATS ld->splats = NULL; #endif +#ifdef POLYOBJECTS + ld->polyobj = NULL; +#endif + + ld->dx = v2->x - v1->x; + ld->dy = v2->y - v1->y; + if (!ld->dx) ld->slopetype = ST_VERTICAL; else if (!ld->dy) @@ -1208,52 +1202,43 @@ static void P_LoadRawLineDefs(UINT8 *data, size_t i) ld->bbox[BOXTOP] = v1->y; } - ld->sidenum[0] = SHORT(mld->sidenum[0]); - ld->sidenum[1] = SHORT(mld->sidenum[1]); - { // cph 2006/09/30 - fix sidedef errors right away. // cph 2002/07/20 - these errors are fatal if not fixed, so apply them UINT8 j; for (j=0; j < 2; j++) - { if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) { ld->sidenum[j] = 0xffff; CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has out-of-range sidedef number\n", sizeu1(numlines-i-1)); } - } } ld->frontsector = ld->backsector = NULL; ld->validcount = 0; ld->firsttag = ld->nexttag = -1; ld->callcount = 0; - // killough 11/98: fix common wad errors (missing sidedefs): + // killough 11/98: fix common wad errors (missing sidedefs): if (ld->sidenum[0] == 0xffff) { ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s missing first sidedef\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "Linedef %s missing first sidedef\n", sizeu1(numlines-i-1)); } if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) { ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1)); } if (ld->sidenum[0] != 0xffff && ld->special) sides[ld->sidenum[0]].special = ld->special; if (ld->sidenum[1] != 0xffff && ld->special) sides[ld->sidenum[1]].special = ld->special; - -#ifdef POLYOBJECTS - ld->polyobj = NULL; -#endif } } @@ -1359,16 +1344,6 @@ static void P_LoadLineDefs2(void) } } - - -static inline void P_LoadRawSideDefs(size_t i) -{ - numsides = i / sizeof (mapsidedef_t); - if (numsides <= 0) - I_Error("Level has no sidedefs"); - sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); -} - static void P_LoadRawSideDefs2(void *data) { UINT16 i; @@ -2697,6 +2672,23 @@ boolean P_SetupLevel(boolean skipprecip) // SRB2 determines the sky texture to be used depending on the map header. P_SetupLevelSky(mapheaderinfo[gamemap-1]->skynum, true); + numdmstarts = numredctfstarts = numbluectfstarts = 0; + + // reset the player starts + for (i = 0; i < MAXPLAYERS; i++) + playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; + + for (i = 0; i < MAX_DM_STARTS; i++) + deathmatchstarts[i] = NULL; + + for (i = 0; i < 2; i++) + skyboxmo[i] = NULL; + + for (i = 0; i < 16; i++) + skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; + + P_MapStart(); + if (lastloadedmaplumpnum) { virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); @@ -2713,17 +2705,41 @@ boolean P_SetupLevel(boolean skipprecip) virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP"); virtlump_t* virtreject = vres_Find(virt, "REJECT"); - P_MakeMapMD5(virt, &mapmd5); + // Traditional doom map format just assumes the number of elements from the lump sixes. + numvertexes = virtvertexes->size / sizeof (mapvertex_t); + numsectors = virtsectors->size / sizeof (mapsector_t); + numsides = virtsidedefs->size / sizeof (mapsidedef_t); + numlines = virtlinedefs->size / sizeof (maplinedef_t); + nummapthings = virtthings->size / (5 * sizeof (INT16)); - P_LoadRawVertexes(virtvertexes->data, virtvertexes->size); - P_LoadRawSectors(virtsectors->data, virtsectors->size); - P_LoadRawSideDefs(virtsidedefs->size); - P_LoadRawLineDefs(virtlinedefs->data, virtlinedefs->size); + if (numvertexes <= 0) + I_Error("Level has no vertices"); + if (numsectors <= 0) + I_Error("Level has no sectors"); + if (numsides <= 0) + I_Error("Level has no sidedefs"); + if (numlines <= 0) + I_Error("Level has no linedefs"); + + vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); + sectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); + sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); + lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + mapthings= Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + + // Strict map data + P_LoadRawVertexes(virtvertexes->data); + P_LoadRawSectors(virtsectors->data); + P_LoadRawLineDefs(virtlinedefs->data); + SetupLines(); P_LoadRawSideDefs2(virtsidedefs->data); + + // Nodes P_LoadRawSubsectors(virtssectors->data, virtssectors->size); P_LoadRawNodes(virtnodes->data, virtnodes->size); P_LoadRawSegs(virtsegs->data, virtsegs->size); + // Lookup tables if (virtreject) P_LoadRawReject(virtreject->data, virtreject->size); else @@ -2735,25 +2751,10 @@ boolean P_SetupLevel(boolean skipprecip) P_LoadLineDefs2(); P_GroupLines(); - numdmstarts = numredctfstarts = numbluectfstarts = 0; - - // reset the player starts - for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; - - for (i = 0; i < MAX_DM_STARTS; i++) - deathmatchstarts[i] = NULL; - - for (i = 0; i < 2; i++) - skyboxmo[i] = NULL; - - for (i = 0; i < 16; i++) - skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; - - P_MapStart(); - P_PrepareRawThings(virtthings->data, virtthings->size); + P_MakeMapMD5(virt, &mapmd5); + vres_Free(virt); } From ec9f727e531ca11b735bcee2fc390af8e9080e0b Mon Sep 17 00:00:00 2001 From: Nev3r Date: Thu, 12 Dec 2019 11:16:55 +0100 Subject: [PATCH 021/312] Move map data load procedure to separate functions. --- src/p_setup.c | 161 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 63 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index f569c4b73..0430ab997 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -951,16 +951,13 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum) } #endif -static void P_PrepareRawThings(UINT8 *data, size_t i) +static void P_PrepareRawThings(UINT8 *data) { - mapthing_t *mt; - - nummapthings = i / (5 * sizeof (INT16)); - mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + mapthing_t *mt = mapthings; + size_t i; // Spawn axis points first so they are // at the front of the list for fast searching. - mt = mapthings; for (i = 0; i < nummapthings; i++, mt++) { mt->x = READINT16(data); @@ -1936,6 +1933,97 @@ static void P_LoadRawReject(UINT8 *data, size_t count) } } +static void LoadMapBSP (const virtres_t* virt) +{ + virtlump_t* virtssectors = vres_Find(virt, "SSECTORS"); + virtlump_t* virtsegs = vres_Find(virt, "SEGS"); + virtlump_t* virtnodes = vres_Find(virt, "NODES"); + + // Nodes + P_LoadRawSubsectors(virtssectors->data, virtssectors->size); + P_LoadRawNodes(virtnodes->data, virtnodes->size); + P_LoadRawSegs(virtsegs->data, virtsegs->size); +} + +static void LoadMapLUT (const virtres_t* virt) +{ + virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP"); + virtlump_t* virtreject = vres_Find(virt, "REJECT"); + + // Lookup tables + if (virtreject) + P_LoadRawReject(virtreject->data, virtreject->size); + else + rejectmatrix = NULL; + + if (!(virtblockmap && P_LoadRawBlockMap(virtblockmap->data, virtblockmap->size))) + P_CreateBlockMap(); +} + +static void LoadMapData (const virtres_t* virt) +{ + virtlump_t* virtvertexes = NULL, * virtsectors = NULL, * virtsidedefs = NULL, * virtlinedefs = NULL, * virtthings = NULL; + virtlump_t* textmap = vres_Find(virt, "TEXTMAP"); + + // Count map data. + if (textmap) + { + nummapthings = 0; + numlines = 0; + numsides = 0; + numvertexes = 0; + numsectors = 0; + + // Count how many entries for each type we got in textmap. + //TextmapCount(vtextmap->data, vtextmap->size); + } + else + { + virtthings = vres_Find(virt, "THINGS"); + virtvertexes = vres_Find(virt, "VERTEXES"); + virtsectors = vres_Find(virt, "SECTORS"); + virtsidedefs = vres_Find(virt, "SIDEDEFS"); + virtlinedefs = vres_Find(virt, "LINEDEFS"); + + // Traditional doom map format just assumes the number of elements from the lump sixes. + numvertexes = virtvertexes->size / sizeof (mapvertex_t); + numsectors = virtsectors->size / sizeof (mapsector_t); + numsides = virtsidedefs->size / sizeof (mapsidedef_t); + numlines = virtlinedefs->size / sizeof (maplinedef_t); + nummapthings = virtthings->size / (5 * sizeof (INT16)); + } + + if (numvertexes <= 0) + I_Error("Level has no vertices"); + if (numsectors <= 0) + I_Error("Level has no sectors"); + if (numsides <= 0) + I_Error("Level has no sidedefs"); + if (numlines <= 0) + I_Error("Level has no linedefs"); + + vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); + sectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); + sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); + lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + mapthings= Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + + if (textmap) + { + + } + else + { + // Strict map data + P_LoadRawVertexes(virtvertexes->data); + P_LoadRawSectors(virtsectors->data); + P_LoadRawLineDefs(virtlinedefs->data); + SetupLines(); + P_LoadRawSideDefs2(virtsidedefs->data); + P_PrepareRawThings(virtthings->data); + } +} + #if 0 static char *levellumps[] = { @@ -2133,7 +2221,7 @@ void P_LoadThingsOnly(void) P_LevelInitStuff(); - P_PrepareRawThings(vth->data, vth->size); + P_PrepareRawThings(vth->data); P_LoadThings(true); vres_Free(virt); @@ -2692,67 +2780,14 @@ boolean P_SetupLevel(boolean skipprecip) if (lastloadedmaplumpnum) { virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); - virtlump_t* virtthings = vres_Find(virt, "THINGS"); - virtlump_t* virtvertexes = vres_Find(virt, "VERTEXES"); - virtlump_t* virtsectors = vres_Find(virt, "SECTORS"); - virtlump_t* virtsidedefs = vres_Find(virt, "SIDEDEFS"); - virtlump_t* virtlinedefs = vres_Find(virt, "LINEDEFS"); - virtlump_t* virtssectors = vres_Find(virt, "SSECTORS"); - virtlump_t* virtsegs = vres_Find(virt, "SEGS"); - virtlump_t* virtnodes = vres_Find(virt, "NODES"); - - virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP"); - virtlump_t* virtreject = vres_Find(virt, "REJECT"); - - // Traditional doom map format just assumes the number of elements from the lump sixes. - numvertexes = virtvertexes->size / sizeof (mapvertex_t); - numsectors = virtsectors->size / sizeof (mapsector_t); - numsides = virtsidedefs->size / sizeof (mapsidedef_t); - numlines = virtlinedefs->size / sizeof (maplinedef_t); - nummapthings = virtthings->size / (5 * sizeof (INT16)); - - if (numvertexes <= 0) - I_Error("Level has no vertices"); - if (numsectors <= 0) - I_Error("Level has no sectors"); - if (numsides <= 0) - I_Error("Level has no sidedefs"); - if (numlines <= 0) - I_Error("Level has no linedefs"); - - vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); - sectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); - sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); - lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); - mapthings= Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); - - // Strict map data - P_LoadRawVertexes(virtvertexes->data); - P_LoadRawSectors(virtsectors->data); - P_LoadRawLineDefs(virtlinedefs->data); - SetupLines(); - P_LoadRawSideDefs2(virtsidedefs->data); - - // Nodes - P_LoadRawSubsectors(virtssectors->data, virtssectors->size); - P_LoadRawNodes(virtnodes->data, virtnodes->size); - P_LoadRawSegs(virtsegs->data, virtsegs->size); - - // Lookup tables - if (virtreject) - P_LoadRawReject(virtreject->data, virtreject->size); - else - rejectmatrix = NULL; - - if (!(virtblockmap && P_LoadRawBlockMap(virtblockmap->data, virtblockmap->size))) - P_CreateBlockMap(); + LoadMapData(virt); + LoadMapBSP(virt); + LoadMapLUT(virt); P_LoadLineDefs2(); P_GroupLines(); - P_PrepareRawThings(virtthings->data, virtthings->size); - P_MakeMapMD5(virt, &mapmd5); vres_Free(virt); From c64a9d7ae9d0d3756c348397c00b5e8460c504a0 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Thu, 12 Dec 2019 11:37:48 +0100 Subject: [PATCH 022/312] Stop things from becoming Chocapic in THZ3, ACZ2, and special stages. Temporarily revert function call order for mapthings. --- src/p_setup.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 0430ab997..cc53f2d3d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1963,6 +1963,7 @@ static void LoadMapLUT (const virtres_t* virt) static void LoadMapData (const virtres_t* virt) { virtlump_t* virtvertexes = NULL, * virtsectors = NULL, * virtsidedefs = NULL, * virtlinedefs = NULL, * virtthings = NULL; +#ifdef UDMF virtlump_t* textmap = vres_Find(virt, "TEXTMAP"); // Count map data. @@ -1978,6 +1979,7 @@ static void LoadMapData (const virtres_t* virt) //TextmapCount(vtextmap->data, vtextmap->size); } else +#endif { virtthings = vres_Find(virt, "THINGS"); virtvertexes = vres_Find(virt, "VERTEXES"); @@ -2008,11 +2010,13 @@ static void LoadMapData (const virtres_t* virt) lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); mapthings= Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); +#ifdef UDMF if (textmap) { } else +#endif { // Strict map data P_LoadRawVertexes(virtvertexes->data); @@ -2020,7 +2024,6 @@ static void LoadMapData (const virtres_t* virt) P_LoadRawLineDefs(virtlinedefs->data); SetupLines(); P_LoadRawSideDefs2(virtsidedefs->data); - P_PrepareRawThings(virtthings->data); } } @@ -2788,6 +2791,8 @@ boolean P_SetupLevel(boolean skipprecip) P_LoadLineDefs2(); P_GroupLines(); + P_PrepareRawThings(vres_Find(virt, "THINGS")->data); + P_MakeMapMD5(virt, &mapmd5); vres_Free(virt); From c5d8fe47527c9cd1c4d354b8f730f7be5bd3350e Mon Sep 17 00:00:00 2001 From: Nev3r Date: Thu, 12 Dec 2019 15:04:48 +0100 Subject: [PATCH 023/312] Fix oversight on mapthing spawn Z calculation; ONFLOORZ and ONCEILINGZ don't equal to spawning the object at the base plane intersection. --- src/p_mobj.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index dae891afd..ed12407ff 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11609,6 +11609,14 @@ static fixed_t GetMobjSpawnHeight (const mobjtype_t i, const mapthing_t* mthing, flip = (!!(mobjinfo[i].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); } + if (heightoffset + extraoffset == 0) // Snap to the surfaces when there's no offset set. + { + if (flip) + return ONCEILINGZ; + else + return ONFLOORZ; + } + // Establish height. if (flip) return ( From ad776e560c18644d8dadde16aac0dd98fa962633 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Fri, 13 Dec 2019 16:36:33 -0500 Subject: [PATCH 024/312] Rework G_SetCustomExitVars to allow skipstats 2 --- src/lua_baselib.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index b68d16c2a..018529722 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2664,23 +2664,17 @@ static int lib_gSetCustomExitVars(lua_State *L) // Supported: // G_SetCustomExitVars(); [reset to defaults] // G_SetCustomExitVars(int) [nextmap override only] - // G_SetCustomExitVars(bool) [skipstats only] - // G_SetCustomExitVars(int, bool) [both of the above] + // G_SetCustomExitVars(nil, int) [skipstats only] + // G_SetCustomExitVars(int, int) [both of the above] + + nextmapoverride = 0; + skipstats = 0; + if (n >= 1) { - if (lua_isnumber(L, 1) || n >= 2) - { - nextmapoverride = (INT16)luaL_checknumber(L, 1); - lua_remove(L, 1); // remove nextmapoverride; skipstats now 1 if available - } - skipstats = luaL_optinteger(L, 2, 0); + nextmapoverride = (INT16)luaL_optinteger(L, 1, 0); + skipstats = (INT16)luaL_optinteger(L, 2, 0); } - else - { - nextmapoverride = 0; - skipstats = 0; - } - // --- return 0; } From bcfd9fe504464c8186e4c1ca2d83e5b3bb44d8d3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 15 Dec 2019 00:22:17 +0100 Subject: [PATCH 025/312] Cleaned up GetMobjSpawnHeight a bit. Ring-likes no longer ignore MF_SPAWNCEILING, because why should they? --- src/p_mobj.c | 48 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index ed12407ff..9af9f8791 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11551,18 +11551,16 @@ mapthing_t *huntemeralds[MAXHUNTEMERALDS]; INT32 numhuntemeralds; -static fixed_t GetMobjSpawnHeight (const mobjtype_t i, const mapthing_t* mthing, const fixed_t x, const fixed_t y) +static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y) { - subsector_t *ss = R_PointInSubsector(x, y); - fixed_t extraoffset = 0; - fixed_t heightoffset = 0; - boolean flip; + const subsector_t *ss = R_PointInSubsector(x, y); + fixed_t offset = mthing->z << FRACBITS; + boolean flip = (!!(mobjinfo[mobjtype].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); - switch (i) + switch (mobjtype) { // Bumpers never spawn flipped. case MT_NIGHTSBUMPER: - heightoffset = mthing->z*FRACUNIT; flip = false; break; @@ -11578,38 +11576,34 @@ static fixed_t GetMobjSpawnHeight (const mobjtype_t i, const mapthing_t* mthing, case MT_JETTBOMBER: case MT_JETTGUNNER: case MT_EGGMOBILE2: - heightoffset = mthing->z ? 0 : 33*FRACUNIT; - goto atend; + if (!offset) + offset = 33*FRACUNIT; + break; case MT_EGGMOBILE: - heightoffset = mthing->z ? 0 : 128*FRACUNIT; - goto atend; + if (!offset) + offset = 128*FRACUNIT; + break; case MT_GOLDBUZZ: case MT_REDBUZZ: - heightoffset = mthing->z ? 0 : 288*FRACUNIT; - goto atend; + if (!offset) + offset = 288*FRACUNIT; + break; // Ring-like items, may float additional units with MTF_AMBUSH. case MT_SPIKEBALL: case MT_EMERALDSPAWN: case MT_TOKEN: case MT_EMBLEM: - weaponfloat: - flip = mthing->options & MTF_OBJECTFLIP; - extraoffset = mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; - heightoffset = mthing->z*FRACUNIT; + offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; break; // Remaining objects. default: - if (P_WeaponOrPanel(i)) - goto weaponfloat; // Ring-like items don't use MF_SPAWNCEILING to consider flips. - - atend: - heightoffset = mthing->z*FRACUNIT; - flip = (!!(mobjinfo[i].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); + if (P_WeaponOrPanel(mobjtype)) + offset += mthing->options & MTF_AMBUSH ? 24 * FRACUNIT : 0; } - if (heightoffset + extraoffset == 0) // Snap to the surfaces when there's no offset set. + if (!offset) // Snap to the surfaces when there's no offset set. { if (flip) return ONCEILINGZ; @@ -11623,13 +11617,13 @@ static fixed_t GetMobjSpawnHeight (const mobjtype_t i, const mapthing_t* mthing, #ifdef ESLOPE ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : #endif - ss->sector->ceilingheight) - extraoffset - heightoffset - mobjinfo[i].height; + ss->sector->ceilingheight) - offset - mobjinfo[mobjtype].height; else return ( #ifdef ESLOPE ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : #endif - ss->sector->floorheight) + extraoffset + heightoffset; + ss->sector->floorheight) + offset; } // @@ -11894,7 +11888,7 @@ You should think about modifying the deathmatch starts to take full advantage of // spawn it x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; - z = GetMobjSpawnHeight(i, mthing, x, y); + z = P_GetMobjSpawnHeight(i, mthing, x, y); mobj = P_SpawnMobj(x, y, z, i); mobj->spawnpoint = mthing; From 8a6e244e60c0f760be4716346e8f4b6d20946e7f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 15 Dec 2019 09:49:54 +0100 Subject: [PATCH 026/312] SpawnEmeraldHunt() -> P_SpawnEmeraldHunt() --- src/p_setup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 628292fe0..9a546c5b5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1035,7 +1035,7 @@ static void P_PrepareThings(lumpnum_t lumpnum) Z_Free(data); } -static void SpawnEmeraldHunt (void) +static void P_SpawnEmeraldHunt(void) { INT32 emer1, emer2, emer3; INT32 timeout = 0; // keeps from getting stuck @@ -1119,7 +1119,7 @@ static void P_LoadThings(boolean loademblems) // random emeralds for hunt if (numhuntemeralds) - SpawnEmeraldHunt(); + P_SpawnEmeraldHunt(); if (metalrecording) // Metal Sonic gets no rings to distract him. return; From 23b3f5a649fcd43c3eefd46b5ca54ee40559278e Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sun, 15 Dec 2019 04:09:56 -0600 Subject: [PATCH 027/312] Fix a divide by zero crash when mindash and maxdash were the same. Props to rumia1 for finding this and Lach for figuring out this was a divide by zero error. --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index ea42a2c36..2c9a766bc 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4635,7 +4635,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) S_StartSound(player->mo, sfx_spin); break; } - if (player->dashspeed < player->maxdash) + if (player->dashspeed < player->maxdash && player->mindash != player->maxdash) { #define chargecalculation (6*(player->dashspeed - player->mindash))/(player->maxdash - player->mindash) fixed_t soundcalculation = chargecalculation; From 230006553dea1907f9d6ad04e946b725a56c66a9 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 15 Dec 2019 21:43:50 +0100 Subject: [PATCH 028/312] Set mapthing z in OP_CreateNewMapThing --- src/m_cheat.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/m_cheat.c b/src/m_cheat.c index e31ce7869..0451a5fb3 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1106,7 +1106,7 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c #else fixed_t cheight = sec->ceilingheight; #endif - mt->options = (UINT16)((cheight - player->mo->z - player->mo->height)>>FRACBITS); + mt->z = (UINT16)((cheight - player->mo->z - player->mo->height)>>FRACBITS); } else { @@ -1115,12 +1115,11 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c #else fixed_t fheight = sec->floorheight; #endif - mt->options = (UINT16)((player->mo->z - fheight)>>FRACBITS); + mt->z = (UINT16)((player->mo->z - fheight)>>FRACBITS); } - mt->options <<= ZSHIFT; mt->angle = (INT16)(FixedInt(AngleFixed(player->mo->angle))); - mt->options |= (UINT16)cv_opflags.value; + mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value; return mt; } From bb3440d02127af605dbb75ccfa5c7878efebeece Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 16 Dec 2019 00:04:48 +0100 Subject: [PATCH 029/312] Minor cleanup of virtual resources code --- src/p_setup.c | 24 +++++++++--------------- src/w_wad.c | 16 ++++++++-------- src/w_wad.h | 6 +++--- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index cc53f2d3d..f1607c272 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -367,12 +367,7 @@ UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade) return mapheaderinfo[map-1]->grades[mare].grade[grade-1]; } -/** Loads the vertexes for a level. - * - * \param lump VERTEXES lump number. - * \sa ML_VERTEXES - */ - +// Loads the vertexes for a level. static inline void P_LoadRawVertexes(UINT8 *data) { mapvertex_t *ml = (mapvertex_t *)data; @@ -666,7 +661,6 @@ INT32 P_CheckLevelFlat(const char *flatname) } // Sets up the ingame sectors structures. -// Lumpnum is the lumpnum of a SECTORS lump. static void P_LoadRawSectors(UINT8 *data) { mapsector_t *ms = (mapsector_t *)data; @@ -1147,7 +1141,7 @@ static void P_LoadRawLineDefs(UINT8 *data) } } -static void SetupLines (void) +static void P_SetupLines(void) { line_t *ld = lines; size_t i; @@ -1933,7 +1927,7 @@ static void P_LoadRawReject(UINT8 *data, size_t count) } } -static void LoadMapBSP (const virtres_t* virt) +static void P_LoadMapBSP(const virtres_t* virt) { virtlump_t* virtssectors = vres_Find(virt, "SSECTORS"); virtlump_t* virtsegs = vres_Find(virt, "SEGS"); @@ -1945,7 +1939,7 @@ static void LoadMapBSP (const virtres_t* virt) P_LoadRawSegs(virtsegs->data, virtsegs->size); } -static void LoadMapLUT (const virtres_t* virt) +static void P_LoadMapLUT(const virtres_t* virt) { virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP"); virtlump_t* virtreject = vres_Find(virt, "REJECT"); @@ -1960,7 +1954,7 @@ static void LoadMapLUT (const virtres_t* virt) P_CreateBlockMap(); } -static void LoadMapData (const virtres_t* virt) +static void P_LoadMapData(const virtres_t* virt) { virtlump_t* virtvertexes = NULL, * virtsectors = NULL, * virtsidedefs = NULL, * virtlinedefs = NULL, * virtthings = NULL; #ifdef UDMF @@ -2022,7 +2016,7 @@ static void LoadMapData (const virtres_t* virt) P_LoadRawVertexes(virtvertexes->data); P_LoadRawSectors(virtsectors->data); P_LoadRawLineDefs(virtlinedefs->data); - SetupLines(); + P_SetupLines(); P_LoadRawSideDefs2(virtsidedefs->data); } } @@ -2784,9 +2778,9 @@ boolean P_SetupLevel(boolean skipprecip) { virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); - LoadMapData(virt); - LoadMapBSP(virt); - LoadMapLUT(virt); + P_LoadMapData(virt); + P_LoadMapBSP(virt); + P_LoadMapLUT(virt); P_LoadLineDefs2(); P_GroupLines(); diff --git a/src/w_wad.c b/src/w_wad.c index f16e8eb5b..9cedd242f 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1895,12 +1895,12 @@ int W_VerifyNMUSlumps(const char *filename) * \return Virtual resource * */ -virtres_t* vres_GetMap (lumpnum_t lumpnum) +virtres_t* vres_GetMap(lumpnum_t lumpnum) { UINT32 i; - virtres_t* vres = NULL; - virtlump_t* vlumps = NULL; - size_t numlumps = 0; + virtres_t* vres = NULL; + virtlump_t* vlumps = NULL; + size_t numlumps = 0; if (W_IsLumpWad(lumpnum)) { @@ -1942,8 +1942,8 @@ virtres_t* vres_GetMap (lumpnum_t lumpnum) } } vres = Z_Malloc(sizeof(virtres_t), PU_LEVEL, NULL); - vres->vlumps = vlumps; - vres->numlumps = numlumps; + vres->vlumps = vlumps; + vres->numlumps = numlumps; return vres; } @@ -1952,7 +1952,7 @@ virtres_t* vres_GetMap (lumpnum_t lumpnum) * * \param Virtual resource */ -void vres_Free (virtres_t* vres) +void vres_Free(virtres_t* vres) { while (vres->numlumps--) Z_Free(vres->vlumps[vres->numlumps].data); @@ -1963,7 +1963,7 @@ void vres_Free (virtres_t* vres) /** (Debug) Prints lumps from a virtual resource into console. */ /* -static void vres_Diag (const virtres_t* vres) +static void vres_Diag(const virtres_t* vres) { UINT32 i; for (i = 0; i < vres->numlumps; i++) diff --git a/src/w_wad.h b/src/w_wad.h index a265d78a9..8008a577c 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -87,9 +87,9 @@ typedef struct { virtlump_t* vlumps; } virtres_t; -virtres_t* vres_GetMap (lumpnum_t); -void vres_Free (virtres_t*); -virtlump_t* vres_Find (const virtres_t*, const char*); +virtres_t* vres_GetMap(lumpnum_t); +void vres_Free(virtres_t*); +virtlump_t* vres_Find(const virtres_t*, const char*); // ========================================================================= // DYNAMIC WAD LOADING From 79350992dffa88f5982df44174b9a04b608b13be Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 16 Dec 2019 00:17:20 +0100 Subject: [PATCH 030/312] Some more cleanup of map loading code --- src/p_setup.c | 90 ++++++++++++++++++++++----------------------------- 1 file changed, 39 insertions(+), 51 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index f1607c272..ca99c8705 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -413,25 +413,15 @@ static inline float P_SegLengthFloat(seg_t *seg) } #endif -/** Loads the SEGS resource from a level. - * - * \param lump Lump number of the SEGS resource. - * \sa ::ML_SEGS - */ -static void P_LoadRawSegs(UINT8 *data, size_t i) +// Loads the SEGS resource from a level. +static void P_LoadRawSegs(UINT8 *data) { INT32 linedef, side; - mapseg_t *ml; - seg_t *li; + mapseg_t *ml = (mapseg_t*)data; + seg_t *li = segs; line_t *ldef; + size_t i; - numsegs = i / sizeof (mapseg_t); - if (numsegs <= 0) - I_Error("Level has no segs"); // instead of crashing - segs = Z_Calloc(numsegs * sizeof (*segs), PU_LEVEL, NULL); - - ml = (mapseg_t *)data; - li = segs; for (i = 0; i < numsegs; i++, li++, ml++) { li->v1 = &vertexes[SHORT(ml->v1)]; @@ -456,7 +446,7 @@ static void P_LoadRawSegs(UINT8 *data, size_t i) li->side = side = SHORT(ml->side); li->sidedef = &sides[ldef->sidenum[side]]; li->frontsector = sides[ldef->sidenum[side]].sector; - if (ldef-> flags & ML_TWOSIDED) + if (ldef->flags & ML_TWOSIDED) li->backsector = sides[ldef->sidenum[side^1]].sector; else li->backsector = 0; @@ -466,22 +456,12 @@ static void P_LoadRawSegs(UINT8 *data, size_t i) } } -/** Loads the SSECTORS resource from a level. - * - * \param lump Lump number of the SSECTORS resource. - * \sa ::ML_SSECTORS - */ -static inline void P_LoadRawSubsectors(void *data, size_t i) +// Loads the SSECTORS resource from a level. +static inline void P_LoadRawSubsectors(void *data) { - mapsubsector_t *ms; - subsector_t *ss; - - numsubsectors = i / sizeof (mapsubsector_t); - if (numsubsectors <= 0) - I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); - ss = subsectors = Z_Calloc(numsubsectors * sizeof (*subsectors), PU_LEVEL, NULL); - - ms = (mapsubsector_t *)data; + mapsubsector_t *ms = (mapsubsector_t*)data; + subsector_t *ss = subsectors; + size_t i; for (i = 0; i < numsubsectors; i++, ss++, ms++) { @@ -761,19 +741,12 @@ static void P_LoadRawSectors(UINT8 *data) // // P_LoadNodes // -static void P_LoadRawNodes(UINT8 *data, size_t i) +static void P_LoadRawNodes(UINT8 *data) { UINT8 j, k; - mapnode_t *mn; - node_t *no; - - numnodes = i / sizeof (mapnode_t); - if (numnodes <= 0) - I_Error("Level has no nodes"); - nodes = Z_Calloc(numnodes * sizeof (*nodes), PU_LEVEL, NULL); - - mn = (mapnode_t *)data; - no = nodes; + mapnode_t *mn = (mapnode_t*)data; + node_t *no = nodes; + size_t i; for (i = 0; i < numnodes; i++, no++, mn++) { @@ -1933,10 +1906,25 @@ static void P_LoadMapBSP(const virtres_t* virt) virtlump_t* virtsegs = vres_Find(virt, "SEGS"); virtlump_t* virtnodes = vres_Find(virt, "NODES"); + numsubsectors = virtssectors->size / sizeof(mapsubsector_t); + numnodes = virtnodes->size / sizeof(mapnode_t); + numsegs = virtsegs->size / sizeof(mapseg_t); + + if (numsubsectors <= 0) + I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); + if (numnodes <= 0) + I_Error("Level has no nodes"); + if (numsegs <= 0) + I_Error("Level has no segs"); + + subsectors = Z_Calloc(numsubsectors * sizeof(*subsectors), PU_LEVEL, NULL); + nodes = Z_Calloc(numnodes * sizeof(*nodes), PU_LEVEL, NULL); + segs = Z_Calloc(numsegs * sizeof(*segs), PU_LEVEL, NULL); + // Nodes - P_LoadRawSubsectors(virtssectors->data, virtssectors->size); - P_LoadRawNodes(virtnodes->data, virtnodes->size); - P_LoadRawSegs(virtsegs->data, virtsegs->size); + P_LoadRawSubsectors(virtssectors->data); + P_LoadRawNodes(virtnodes->data); + P_LoadRawSegs(virtsegs->data); } static void P_LoadMapLUT(const virtres_t* virt) @@ -1981,7 +1969,7 @@ static void P_LoadMapData(const virtres_t* virt) virtsidedefs = vres_Find(virt, "SIDEDEFS"); virtlinedefs = vres_Find(virt, "LINEDEFS"); - // Traditional doom map format just assumes the number of elements from the lump sixes. + // Traditional doom map format just assumes the number of elements from the lump sizes. numvertexes = virtvertexes->size / sizeof (mapvertex_t); numsectors = virtsectors->size / sizeof (mapsector_t); numsides = virtsidedefs->size / sizeof (mapsidedef_t); @@ -1998,11 +1986,11 @@ static void P_LoadMapData(const virtres_t* virt) if (numlines <= 0) I_Error("Level has no linedefs"); - vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); - sectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); - sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); - lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); - mapthings= Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); + sectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); + sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); + lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); #ifdef UDMF if (textmap) From f028bb021947d4ab9dc69566c2f95efc41a9acdd Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 16 Dec 2019 17:46:27 +0000 Subject: [PATCH 031/312] Fix `numoflines` calculations in sectorlines_* functions by first typecasting seclines (the sector.lines address) to size_t before doing any math on it, then (after the math) typecast the result to size_t * and dereference it. And yes, this time I tested it to make sure it works :) --- src/lua_maplib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0fe1df0b6..b35bb6a41 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -445,7 +445,7 @@ static int sectorlines_get(lua_State *L) // get the "linecount" by shifting our retrieved memory address of "lines" to where "linecount" is in the sector_t, then dereferencing the result // we need this to determine the array's actual size, and therefore also the maximum value allowed as an index // this only works if seclines is actually a pointer to a sector's lines member in memory, oh boy - numoflines = (size_t)(*(seclines - (offsetof(sector_t, lines) - offsetof(sector_t, linecount)))); + numoflines = (size_t)(*(size_t *)(((size_t)seclines) - (offsetof(sector_t, lines) - offsetof(sector_t, linecount)))); /* OLD HACK // check first linedef to figure which of its sectors owns this sector->lines pointer @@ -479,7 +479,7 @@ static int sectorlines_num(lua_State *L) return luaL_error(L, "accessed sector_t.lines doesn't exist anymore."); // see comments in the _get function above - numoflines = (size_t)(*(seclines - (offsetof(sector_t, lines) - offsetof(sector_t, linecount)))); + numoflines = (size_t)(*(size_t *)(((size_t)seclines) - (offsetof(sector_t, lines) - offsetof(sector_t, linecount)))); lua_pushinteger(L, numoflines); return 1; } From 46f431616c51c29af69dc5f42302f63be789eeae Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 16 Dec 2019 20:26:19 +0000 Subject: [PATCH 032/312] Added a lot of SOC-editable variables to Lua, as well as the tutorialmode boolean --- src/dehacked.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 175c1fcfa..938699516 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -10479,12 +10479,84 @@ static inline int lib_getenum(lua_State *L) } else if (fastcmp(word,"paused")) { lua_pushboolean(L, paused); return 1; + // begin map vars + } else if (fastcmp(word,"spstage_start")) { + lua_pushinteger(L, spstage_start); + return 1; + } else if (fastcmp(word,"sstage_start")) { + lua_pushinteger(L, sstage_start); + return 1; + } else if (fastcmp(word,"sstage_end")) { + lua_pushinteger(L, sstage_end); + return 1; + } else if (fastcmp(word,"smpstage_start")) { + lua_pushinteger(L, smpstage_start); + return 1; + } else if (fastcmp(word,"smpstage_end")) { + lua_pushinteger(L, smpstage_end); + return 1; } else if (fastcmp(word,"titlemap")) { lua_pushinteger(L, titlemap); return 1; } else if (fastcmp(word,"titlemapinaction")) { lua_pushboolean(L, (titlemapinaction != TITLEMAP_OFF)); return 1; + } else if (fastcmp(word,"bootmap")) { + lua_pushinteger(L, bootmap); + return 1; + } else if (fastcmp(word,"tutorialmap")) { + lua_pushinteger(L, tutorialmap); + return 1; + } else if (fastcmp(word,"tutorialmode")) { + lua_pushboolean(L, tutorialmode); + return 1; + // end map vars + // begin CTF colors + } else if (fastcmp(word,"skincolor_redteam")) { + lua_pushinteger(L, skincolor_redteam); + return 1; + } else if (fastcmp(word,"skincolor_blueteam")) { + lua_pushinteger(L, skincolor_blueteam); + return 1; + } else if (fastcmp(word,"skincolor_redring")) { + lua_pushinteger(L, skincolor_redring); + return 1; + } else if (fastcmp(word,"skincolor_bluering")) { + lua_pushinteger(L, skincolor_bluering); + return 1; + // end CTF colors + // begin timers + } else if (fastcmp(word,"invulntics")) { + lua_pushinteger(L, invulntics); + return 1; + } else if (fastcmp(word,"sneakertics")) { + lua_pushinteger(L, sneakertics); + return 1; + } else if (fastcmp(word,"flashingtics")) { + lua_pushinteger(L, flashingtics); + return 1; + } else if (fastcmp(word,"tailsflytics")) { + lua_pushinteger(L, tailsflytics); + return 1; + } else if (fastcmp(word,"underwatertics")) { + lua_pushinteger(L, underwatertics); + return 1; + } else if (fastcmp(word,"spacetimetics")) { + lua_pushinteger(L, spacetimetics); + return 1; + } else if (fastcmp(word,"extralifetics")) { + lua_pushinteger(L, extralifetics); + return 1; + } else if (fastcmp(word,"nightslinktics")) { + lua_pushinteger(L, nightslinktics); + return 1; + } else if (fastcmp(word,"gameovertics")) { + lua_pushinteger(L, gameovertics); + return 1; + } else if (fastcmp(word,"ammoremovaltics")) { + lua_pushinteger(L, ammoremovaltics); + return 1; + // end timers } else if (fastcmp(word,"gametype")) { lua_pushinteger(L, gametype); return 1; From 0ab31b3de0136aa66b553ddd2b07c6df6c5cd588 Mon Sep 17 00:00:00 2001 From: Tatsuru Date: Mon, 16 Dec 2019 17:58:00 -0300 Subject: [PATCH 033/312] Let Lua toggle Match/CTF team scores HUD element --- src/lua_hud.h | 1 + src/lua_hudlib.c | 1 + src/st_stuff.c | 45 ++++++++++++++++++++++++++++++++++++++------- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/lua_hud.h b/src/lua_hud.h index abfbba441..23e3ef834 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -21,6 +21,7 @@ enum hud { // Match / CTF / Tag / Ringslinger hud_weaponrings, hud_powerstones, + hud_teamscores, // NiGHTS mode hud_nightslink, hud_nightsdrill, diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index a2f48c4ad..5b5aa3b4b 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -48,6 +48,7 @@ static const char *const hud_disable_options[] = { "weaponrings", "powerstones", + "teamscores", "nightslink", "nightsdrill", diff --git a/src/st_stuff.c b/src/st_stuff.c index 1b8107edb..1b116a7f3 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2320,14 +2320,20 @@ static void ST_drawTeamHUD(void) p = bflagico; else p = bmatcico; - + +#ifdef HAVE_BLUA + if (LUA_HudEnabled(hud_teamscores)) +#endif V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); - + if (gametype == GT_CTF) p = rflagico; else p = rmatcico; - + +#ifdef HAVE_BLUA + if (LUA_HudEnabled(hud_teamscores)) +#endif V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); if (gametype != GT_CTF) @@ -2339,28 +2345,53 @@ static void ST_drawTeamHUD(void) // Show which flags aren't at base. for (i = 0; i < MAXPLAYERS; i++) { - if (players[i].gotflag & GF_BLUEFLAG) // Blue flag isn't at base + if (players[i].gotflag & GF_BLUEFLAG // Blue flag isn't at base +#ifdef HAVE_BLUA + && LUA_HudEnabled(hud_teamscores) +#endif + ) V_DrawScaledPatch(BASEVIDWIDTH/2 - SEP - SHORT(nonicon->width)/2, 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, nonicon); - if (players[i].gotflag & GF_REDFLAG) // Red flag isn't at base + + if (players[i].gotflag & GF_REDFLAG // Red flag isn't at base +#ifdef HAVE_BLUA + && LUA_HudEnabled(hud_teamscores) +#endif + ) V_DrawScaledPatch(BASEVIDWIDTH/2 + SEP - SHORT(nonicon2->width)/2, 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, nonicon2); whichflag |= players[i].gotflag; + if ((whichflag & (GF_REDFLAG|GF_BLUEFLAG)) == (GF_REDFLAG|GF_BLUEFLAG)) break; // both flags were found, let's stop early } // Display a countdown timer showing how much time left until the flag returns to base. { - if (blueflag && blueflag->fuse > 1) + if (blueflag && blueflag->fuse > 1 +#ifdef HAVE_BLUA + && LUA_HudEnabled(hud_teamscores) +#endif + ) V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (blueflag->fuse / TICRATE))); - if (redflag && redflag->fuse > 1) + if (redflag && redflag->fuse > 1 +#ifdef HAVE_BLUA + && LUA_HudEnabled(hud_teamscores) +#endif + ) V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (redflag->fuse / TICRATE))); } } num: +#ifdef HAVE_BLUA + if (LUA_HudEnabled(hud_teamscores)) +#endif V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", bluescore)); + +#ifdef HAVE_BLUA + if (LUA_HudEnabled(hud_teamscores)) +#endif V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", redscore)); #undef SEP From 0e371774c828bd401af02d4f801a2802532a3bb2 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 16 Dec 2019 21:25:41 -0500 Subject: [PATCH 034/312] Fix crash on mapload when removing Dragonbomber with Lua --- src/p_enemy.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 74a11fe67..5361f453b 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -14712,20 +14712,35 @@ void A_DragonWing(mobj_t *actor) void A_DragonSegment(mobj_t *actor) { mobj_t *target = actor->target; - fixed_t dist = P_AproxDistance(P_AproxDistance(actor->x - target->x, actor->y - target->y), actor->z - target->z); - fixed_t radius = actor->radius + target->radius; - angle_t hangle = R_PointToAngle2(target->x, target->y, actor->x, actor->y); - angle_t zangle = R_PointToAngle2(0, target->z, dist, actor->z); - fixed_t hdist = P_ReturnThrustX(target, zangle, radius); - fixed_t xdist = P_ReturnThrustX(target, hangle, hdist); - fixed_t ydist = P_ReturnThrustY(target, hangle, hdist); - fixed_t zdist = P_ReturnThrustY(target, zangle, radius); + fixed_t dist; + fixed_t radius; + angle_t hangle; + angle_t zangle; + fixed_t hdist; + fixed_t xdist; + fixed_t ydist; + fixed_t zdist; #ifdef HAVE_BLUA if (LUA_CallAction("A_DragonSegment", actor)) return; #endif + if (target == NULL || !target->health) + { + P_RemoveMobj(actor); + return; + } + + dist = P_AproxDistance(P_AproxDistance(actor->x - target->x, actor->y - target->y), actor->z - target->z); + radius = actor->radius + target->radius; + hangle = R_PointToAngle2(target->x, target->y, actor->x, actor->y); + zangle = R_PointToAngle2(0, target->z, dist, actor->z); + hdist = P_ReturnThrustX(target, zangle, radius); + xdist = P_ReturnThrustX(target, hangle, hdist); + ydist = P_ReturnThrustY(target, hangle, hdist); + zdist = P_ReturnThrustY(target, zangle, radius); + actor->angle = hangle; P_TeleportMove(actor, target->x + xdist, target->y + ydist, target->z + zdist); } From 6a5ea548e62891cc23db79a14bff5dc44db011dd Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 17 Dec 2019 13:00:50 -0300 Subject: [PATCH 035/312] make ROTANGLES be 360 --- src/doomdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doomdef.h b/src/doomdef.h index d13ff9bc0..026498ca1 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -625,7 +625,7 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Sprite rotation #define ROTSPRITE -#define ROTANGLES 24 // Needs to be a divisor of 360 (45, 60, 90, 120...) +#define ROTANGLES 360 // Needs to be a divisor of 360 (45, 60, 90, 120...) #define ROTANGDIFF (360 / ROTANGLES) #ifndef HAVE_PNG From c6f36fc470f568ed904231862abea974b54c4f2e Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 17 Dec 2019 13:09:25 -0300 Subject: [PATCH 036/312] un-ROTSPRITE rollangle and spriteinfo --- src/d_clisrv.c | 6 ------ src/dehacked.c | 6 ------ src/hardware/hw_defs.h | 2 -- src/hardware/hw_md2.c | 8 -------- src/hardware/r_opengl/r_opengl.c | 2 -- src/info.h | 2 -- src/lua_baselib.c | 2 -- src/lua_infolib.c | 14 +------------- src/lua_libs.h | 2 -- src/lua_mobjlib.c | 8 -------- src/p_enemy.c | 23 ----------------------- src/p_inter.c | 2 -- src/p_mobj.c | 2 -- src/p_mobj.h | 4 ---- src/p_saveg.c | 10 ---------- src/p_user.c | 14 -------------- src/r_patch.c | 6 ------ src/r_patch.h | 4 ---- 18 files changed, 1 insertion(+), 116 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7b6c35eb6..99c922a8a 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -611,11 +611,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->health = LONG(players[i].mo->health); rsp->angle = (angle_t)LONG(players[i].mo->angle); -#ifdef ROTSPRITE rsp->rollangle = (angle_t)LONG(players[i].mo->rollangle); -#else - rsp->rollangle = 0; -#endif rsp->x = LONG(players[i].mo->x); rsp->y = LONG(players[i].mo->y); rsp->z = LONG(players[i].mo->z); @@ -766,9 +762,7 @@ static void resynch_read_player(resynch_pak *rsp) //At this point, the player should have a body, whether they were respawned or not. P_UnsetThingPosition(players[i].mo); players[i].mo->angle = (angle_t)LONG(rsp->angle); -#ifdef ROTSPRITE players[i].mo->rollangle = (angle_t)LONG(rsp->rollangle); -#endif players[i].mo->eflags = (UINT16)SHORT(rsp->eflags); players[i].mo->flags = LONG(rsp->flags); players[i].mo->flags2 = LONG(rsp->flags2); diff --git a/src/dehacked.c b/src/dehacked.c index 175c1fcfa..b9fe96edd 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -863,14 +863,12 @@ static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame) strupr(word); value = atoi(word2); // used for numerical settings -#ifdef ROTSPRITE if (fastcmp(word, "XPIVOT")) sprinfo->pivot[frame].x = value; else if (fastcmp(word, "YPIVOT")) sprinfo->pivot[frame].y = value; else if (fastcmp(word, "ROTAXIS")) sprinfo->pivot[frame].rotaxis = value; -#endif else { f->curpos = lastline; @@ -2673,11 +2671,9 @@ static actionpointer_t actionpointers[] = {{A_SpawnObjectRelative}, "A_SPAWNOBJECTRELATIVE"}, {{A_ChangeAngleRelative}, "A_CHANGEANGLERELATIVE"}, {{A_ChangeAngleAbsolute}, "A_CHANGEANGLEABSOLUTE"}, -#ifdef ROTSPRITE {{A_RollAngle}, "A_ROLLANGLE"}, {{A_ChangeRollAngleRelative},"A_CHANGEROLLANGLERELATIVE"}, {{A_ChangeRollAngleAbsolute},"A_CHANGEROLLANGLEABSOLUTE"}, -#endif {{A_PlaySound}, "A_PLAYSOUND"}, {{A_FindTarget}, "A_FINDTARGET"}, {{A_FindTracer}, "A_FINDTRACER"}, @@ -9412,12 +9408,10 @@ struct { {"DI_SOUTHEAST",DI_SOUTHEAST}, {"NUMDIRS",NUMDIRS}, -#ifdef ROTSPRITE // Sprite rotation axis (rotaxis_t) {"ROTAXIS_X",ROTAXIS_X}, {"ROTAXIS_Y",ROTAXIS_Y}, {"ROTAXIS_Z",ROTAXIS_Z}, -#endif // Buttons (ticcmd_t) {"BT_WEAPONMASK",BT_WEAPONMASK}, //our first four bits. diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 979093dc8..aa483fcef 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -115,13 +115,11 @@ typedef struct FLOAT fovxangle, fovyangle; UINT8 splitscreen; boolean flip; // screenflip -#ifdef ROTSPRITE boolean roll; SINT8 rollflip; FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ UINT8 rotaxis; FLOAT centerx, centery; -#endif #ifdef USE_FTRANSFORM_MIRROR boolean mirror; // SRB2Kart: Encore Mode #endif diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 13ba007ee..9f8537b61 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1148,10 +1148,8 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP)); spritedef_t *sprdef; spriteframe_t *sprframe; -#ifdef ROTSPRITE spriteinfo_t *sprinfo; angle_t ang; -#endif INT32 mod; float finalscale; @@ -1175,16 +1173,12 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) { md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins]; md2->skin = (skin_t*)spr->mobj->skin-skins; -#ifdef ROTSPRITE sprinfo = &((skin_t *)spr->mobj->skin)->sprinfo[spr->mobj->sprite2]; -#endif } else { md2 = &md2_models[spr->mobj->sprite]; -#ifdef ROTSPRITE sprinfo = &spriteinfo[spr->mobj->sprite]; -#endif } if (md2->error) @@ -1384,7 +1378,6 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) p.angley = FIXED_TO_FLOAT(anglef); } -#ifdef ROTSPRITE p.rollangle = 0.0f; p.rollflip = 0; p.rotaxis = 0; @@ -1409,7 +1402,6 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left p.rollflip = -1; } -#endif p.anglex = 0.0f; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 129bf5678..97b3b98be 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2076,7 +2076,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f); -#ifdef ROTSPRITE if (pos->roll) { float roll = (1.0f * pos->rollflip); @@ -2089,7 +2088,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglRotatef(pos->rollangle, roll, 0.0f, 0.0f); pglTranslatef(-pos->centerx, -pos->centery, 0); } -#endif pglScalef(scalex, scaley, scalez); diff --git a/src/info.h b/src/info.h index 26fb1738d..261abbac5 100644 --- a/src/info.h +++ b/src/info.h @@ -155,11 +155,9 @@ void A_SpawnObjectAbsolute(); void A_SpawnObjectRelative(); void A_ChangeAngleRelative(); void A_ChangeAngleAbsolute(); -#ifdef ROTSPRITE void A_RollAngle(); void A_ChangeRollAngleRelative(); void A_ChangeRollAngleAbsolute(); -#endif void A_PlaySound(); void A_FindTarget(); void A_FindTracer(); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index b68d16c2a..0df2ac45c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -144,10 +144,8 @@ static const struct { {META_MOBJINFO, "mobjinfo_t"}, {META_SFXINFO, "sfxinfo_t"}, {META_SPRITEINFO, "spriteinfo_t"}, -#ifdef ROTSPRITE {META_PIVOTLIST, "spriteframepivot_t[]"}, {META_FRAMEPIVOT, "spriteframepivot_t"}, -#endif {META_MOBJ, "mobj_t"}, {META_MAPTHING, "mapthing_t"}, diff --git a/src/lua_infolib.c b/src/lua_infolib.c index b617a7a14..7a2465ef7 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -266,7 +266,6 @@ static int lib_getSpriteInfo(lua_State *L) #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to spriteinfo[] (%s)", e); #define TYPEERROR(f, t1, t2) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t1), lua_typename(L, t2))) -#ifdef ROTSPRITE static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, int idx) { int okcool = 0; @@ -360,7 +359,6 @@ static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk) return 0; } -#endif static int lib_setSpriteInfo(lua_State *L) { @@ -393,14 +391,11 @@ static int lib_setSpriteInfo(lua_State *L) if (lua_isnumber(L, 2)) { i = lua_tointeger(L, 2); -#ifndef ROTSPRITE i++; // shift index in case of missing rotsprite support -#endif } else str = luaL_checkstring(L, 2); -#ifdef ROTSPRITE if (i == 1 || (str && fastcmp(str, "pivot"))) { // pivot[] is a table @@ -409,7 +404,6 @@ static int lib_setSpriteInfo(lua_State *L) else FIELDERROR("pivot", va("%s expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1))) } -#endif lua_pop(L, 1); } @@ -434,7 +428,6 @@ static int spriteinfo_get(lua_State *L) I_Assert(sprinfo != NULL); -#ifdef ROTSPRITE // push spriteframepivot_t userdata if (fastcmp(field, "pivot")) { @@ -448,7 +441,6 @@ static int spriteinfo_get(lua_State *L) return 1; } else -#endif return luaL_error(L, LUA_QL("spriteinfo_t") " has no field named " LUA_QS, field); return 0; @@ -473,6 +465,7 @@ static int spriteinfo_set(lua_State *L) #ifdef ROTSPRITE if (sprites != NULL) R_FreeSingleRotSprite(&sprites[sprinfo-spriteinfo]); +#endif if (fastcmp(field, "pivot")) { @@ -488,7 +481,6 @@ static int spriteinfo_set(lua_State *L) } } else -#endif return luaL_error(L, va("Field %s does not exist in spriteinfo_t", field)); return 0; @@ -506,7 +498,6 @@ static int spriteinfo_num(lua_State *L) } // framepivot_t -#ifdef ROTSPRITE static int pivotlist_get(lua_State *L) { void **userdata; @@ -616,7 +607,6 @@ static int framepivot_num(lua_State *L) lua_pushinteger(L, 2); return 1; } -#endif //////////////// // STATE INFO // @@ -1538,7 +1528,6 @@ int LUA_InfoLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); -#ifdef ROTSPRITE luaL_newmetatable(L, META_PIVOTLIST); lua_pushcfunction(L, pivotlist_get); lua_setfield(L, -2, "__index"); @@ -1560,7 +1549,6 @@ int LUA_InfoLib(lua_State *L) lua_pushcfunction(L, framepivot_num); lua_setfield(L, -2, "__len"); lua_pop(L, 1); -#endif lua_newuserdata(L, 0); lua_createtable(L, 0, 2); diff --git a/src/lua_libs.h b/src/lua_libs.h index 104a1e51c..6a908d03d 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -23,10 +23,8 @@ extern lua_State *gL; #define META_MOBJINFO "MOBJINFO_T*" #define META_SFXINFO "SFXINFO_T*" #define META_SPRITEINFO "SPRITEINFO_T*" -#ifdef ROTSPRITE #define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]" #define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*" -#endif #define META_MOBJ "MOBJ_T*" #define META_MAPTHING "MAPTHING_T*" diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 49f93d29c..222487751 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -32,9 +32,7 @@ enum mobj_e { mobj_snext, mobj_sprev, mobj_angle, -#ifdef ROTSPRITE mobj_rollangle, -#endif mobj_sprite, mobj_frame, mobj_sprite2, @@ -101,9 +99,7 @@ static const char *const mobj_opt[] = { "snext", "sprev", "angle", -#ifdef ROTSPRITE "rollangle", -#endif "sprite", "frame", "sprite2", @@ -205,11 +201,9 @@ static int mobj_get(lua_State *L) case mobj_angle: lua_pushangle(L, mo->angle); break; -#ifdef ROTSPRITE case mobj_rollangle: lua_pushangle(L, mo->rollangle); break; -#endif case mobj_sprite: lua_pushinteger(L, mo->sprite); break; @@ -462,11 +456,9 @@ static int mobj_set(lua_State *L) else if (mo->player == &players[secondarydisplayplayer]) localangle2 = mo->angle; break; -#ifdef ROTSPRITE case mobj_rollangle: mo->rollangle = luaL_checkangle(L, 3); break; -#endif case mobj_sprite: mo->sprite = luaL_checkinteger(L, 3); break; diff --git a/src/p_enemy.c b/src/p_enemy.c index 74a11fe67..9404c5735 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -181,11 +181,9 @@ void A_SpawnObjectAbsolute(mobj_t *actor); void A_SpawnObjectRelative(mobj_t *actor); void A_ChangeAngleRelative(mobj_t *actor); void A_ChangeAngleAbsolute(mobj_t *actor); -#ifdef ROTSPRITE void A_RollAngle(mobj_t *actor); void A_ChangeRollAngleRelative(mobj_t *actor); void A_ChangeRollAngleAbsolute(mobj_t *actor); -#endif // ROTSPRITE void A_PlaySound(mobj_t *actor); void A_FindTarget(mobj_t *actor); void A_FindTracer(mobj_t *actor); @@ -8627,7 +8625,6 @@ void A_ChangeAngleAbsolute(mobj_t *actor) actor->angle = FixedAngle(P_RandomRange(amin, amax)); } -#ifdef ROTSPRITE // Function: A_RollAngle // // Description: Changes the roll angle. @@ -8663,16 +8660,10 @@ void A_RollAngle(mobj_t *actor) // void A_ChangeRollAngleRelative(mobj_t *actor) { - // Oh god, the old code /sucked/. Changed this and the absolute version to get a random range using amin and amax instead of - // getting a random angle from the _entire_ spectrum and then clipping. While we're at it, do the angle conversion to the result - // rather than the ranges, so <0 and >360 work as possible values. -Red INT32 locvar1 = var1; INT32 locvar2 = var2; - //angle_t angle = (P_RandomByte()+1)<<24; const fixed_t amin = locvar1*FRACUNIT; const fixed_t amax = locvar2*FRACUNIT; - //const angle_t amin = FixedAngle(locvar1*FRACUNIT); - //const angle_t amax = FixedAngle(locvar2*FRACUNIT); #ifdef HAVE_BLUA if (LUA_CallAction("A_ChangeRollAngleRelative", actor)) return; @@ -8682,11 +8673,6 @@ void A_ChangeRollAngleRelative(mobj_t *actor) if (amin > amax) I_Error("A_ChangeRollAngleRelative: var1 is greater than var2"); #endif -/* - if (angle < amin) - angle = amin; - if (angle > amax) - angle = amax;*/ actor->rollangle += FixedAngle(P_RandomRange(amin, amax)); } @@ -8702,11 +8688,8 @@ void A_ChangeRollAngleAbsolute(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; - //angle_t angle = (P_RandomByte()+1)<<24; const fixed_t amin = locvar1*FRACUNIT; const fixed_t amax = locvar2*FRACUNIT; - //const angle_t amin = FixedAngle(locvar1*FRACUNIT); - //const angle_t amax = FixedAngle(locvar2*FRACUNIT); #ifdef HAVE_BLUA if (LUA_CallAction("A_ChangeRollAngleAbsolute", actor)) return; @@ -8716,15 +8699,9 @@ void A_ChangeRollAngleAbsolute(mobj_t *actor) if (amin > amax) I_Error("A_ChangeRollAngleAbsolute: var1 is greater than var2"); #endif -/* - if (angle < amin) - angle = amin; - if (angle > amax) - angle = amax;*/ actor->rollangle = FixedAngle(P_RandomRange(amin, amax)); } -#endif // ROTSPRITE // Function: A_PlaySound // diff --git a/src/p_inter.c b/src/p_inter.c index 70fb01fd0..00733bbd3 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3005,9 +3005,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) P_SetPlayerMobjState(target, S_PLAY_NIGHTS_STUN); S_StartSound(target, sfx_nghurt); -#ifdef ROTSPRITE player->mo->rollangle = 0; -#endif if (oldnightstime > 10*TICRATE && player->nightstime < 10*TICRATE) diff --git a/src/p_mobj.c b/src/p_mobj.c index dea4a7a4d..ef6be4844 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9735,14 +9735,12 @@ void P_MobjThinker(mobj_t *mobj) } break; case MT_MINUS: -#ifdef ROTSPRITE { if (P_IsObjectOnGround(mobj)) mobj->rollangle = 0; else mobj->rollangle = R_PointToAngle2(0, 0, mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1)); } -#endif break; case MT_SPINFIRE: if (mobj->flags & MF_NOGRAVITY) diff --git a/src/p_mobj.h b/src/p_mobj.h index 40d850f16..744578d01 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -279,9 +279,7 @@ typedef struct mobj_s // More drawing info: to determine current sprite. angle_t angle; // orientation -#ifdef ROTSPRITE angle_t rollangle; -#endif spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h UINT8 sprite2; // player sprites @@ -402,9 +400,7 @@ typedef struct precipmobj_s // More drawing info: to determine current sprite. angle_t angle; // orientation -#ifdef ROTSPRITE angle_t rollangle; -#endif spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h UINT8 sprite2; // player sprites diff --git a/src/p_saveg.c b/src/p_saveg.c index 89447db80..068ac0295 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1277,9 +1277,7 @@ typedef enum MD2_SLOPE = 1<<11, #endif MD2_COLORIZED = 1<<12, -#ifdef ROTSPRITE MD2_ROLLANGLE = 1<<13, -#endif } mobj_diff2_t; typedef enum @@ -1499,10 +1497,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) #endif if (mobj->colorized) diff2 |= MD2_COLORIZED; -#ifdef ROTSPRITE if (mobj->rollangle) diff2 |= MD2_ROLLANGLE; -#endif if (diff2 != 0) diff |= MD_MORE; @@ -1667,10 +1663,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) #endif if (diff2 & MD2_COLORIZED) WRITEUINT8(save_p, mobj->colorized); -#ifdef ROTSPRITE if (diff2 & MD2_ROLLANGLE) WRITEANGLE(save_p, mobj->rollangle); -#endif WRITEUINT32(save_p, mobj->mobjnum); } @@ -2747,12 +2741,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) #endif if (diff2 & MD2_COLORIZED) mobj->colorized = READUINT8(save_p); -#ifdef ROTSPRITE if (diff2 & MD2_ROLLANGLE) mobj->rollangle = READANGLE(save_p); - else - mobj->rollangle = 0; -#endif if (diff & MD_REDFLAG) { diff --git a/src/p_user.c b/src/p_user.c index ea42a2c36..2968a53bc 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -638,9 +638,7 @@ static void P_DeNightserizePlayer(player_t *player) player->marebonuslap = 0; player->flyangle = 0; player->anotherflyangle = 0; -#ifdef ROTSPRITE player->mo->rollangle = 0; -#endif P_SetTarget(&player->mo->target, NULL); P_SetTarget(&player->axis1, P_SetTarget(&player->axis2, NULL)); @@ -768,9 +766,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->secondjump = 0; player->flyangle = 0; player->anotherflyangle = 0; -#ifdef ROTSPRITE player->mo->rollangle = 0; -#endif player->powers[pw_shield] = SH_NONE; player->powers[pw_super] = 0; @@ -6824,7 +6820,6 @@ static void P_DoNiGHTSCapsule(player_t *player) P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); } -#ifdef ROTSPRITE if (!(player->charflags & SF_NONIGHTSROTATION)) { if ((player->mo->state == &states[S_PLAY_NIGHTS_PULL]) @@ -6833,7 +6828,6 @@ static void P_DoNiGHTSCapsule(player_t *player) else player->mo->rollangle = 0; } -#endif if (G_IsSpecialStage(gamemap)) { // In special stages, share rings. Everyone gives up theirs to the capsule player always, because we can't have any individualism here! @@ -7096,9 +7090,7 @@ static void P_NiGHTSMovement(player_t *player) INT32 i; statenum_t flystate; UINT16 visangle; -#ifdef ROTSPRITE angle_t rollangle = 0; -#endif player->pflags &= ~PF_DRILLING; @@ -7283,9 +7275,7 @@ static void P_NiGHTSMovement(player_t *player) && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]) { player->mo->momx = player->mo->momy = player->mo->momz = 0; -#ifdef ROTSPRITE player->mo->rollangle = 0; -#endif return; } @@ -7611,7 +7601,6 @@ static void P_NiGHTSMovement(player_t *player) flystate += (visangle*2); // S_PLAY_NIGHTS_FLY0-C - the *2 is to skip over drill states #endif } -#ifdef ROTSPRITE else { angle_t a = R_PointToAngle(player->mo->x, player->mo->y) - player->mo->angle; @@ -7629,18 +7618,15 @@ static void P_NiGHTSMovement(player_t *player) rollangle = FixedAngle(visangle<mo->state != &states[flystate]) P_SetPlayerMobjState(player->mo, flystate); -#ifdef ROTSPRITE if (player->charflags & SF_NONIGHTSROTATION) player->mo->rollangle = 0; else player->mo->rollangle = rollangle; -#endif if (player == &players[consoleplayer]) localangle = player->mo->angle; diff --git a/src/r_patch.c b/src/r_patch.c index d4bfa9cbd..e538c1775 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -789,11 +789,9 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) size_t sprinfoTokenLength; char *frameChar = NULL; UINT8 frameFrame = 0xFF; -#ifdef ROTSPRITE INT16 frameXPivot = 0; INT16 frameYPivot = 0; rotaxis_t frameRotAxis = 0; -#endif // Sprite identifier sprinfoToken = M_GetToken(NULL); @@ -828,7 +826,6 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) } while (strcmp(sprinfoToken,"}")!=0) { -#ifdef ROTSPRITE if (stricmp(sprinfoToken, "XPIVOT")==0) { Z_Free(sprinfoToken); @@ -852,7 +849,6 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) else if ((stricmp(sprinfoToken, "Z")==0) || (stricmp(sprinfoToken, "ZAXIS")==0) || (stricmp(sprinfoToken, "YAW")==0)) frameRotAxis = ROTAXIS_Z; } -#endif Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); @@ -866,11 +862,9 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) } // set fields -#ifdef ROTSPRITE info->pivot[frameFrame].x = frameXPivot; info->pivot[frameFrame].y = frameYPivot; info->pivot[frameFrame].rotaxis = frameRotAxis; -#endif } // diff --git a/src/r_patch.h b/src/r_patch.h index 8a8ab5602..c534debdb 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -18,7 +18,6 @@ #include "doomdef.h" // Structs -#ifdef ROTSPRITE typedef enum { ROTAXIS_X, // Roll (the default) @@ -31,13 +30,10 @@ typedef struct INT32 x, y; rotaxis_t rotaxis; } spriteframepivot_t; -#endif typedef struct { -#ifdef ROTSPRITE spriteframepivot_t pivot[64]; -#endif boolean available; } spriteinfo_t; From 8422c88063405162a0a065bef827193120fd80ab Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 17 Dec 2019 13:25:55 -0300 Subject: [PATCH 037/312] optimise R_CacheRotSprite --- src/r_patch.c | 60 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/src/r_patch.c b/src/r_patch.c index e538c1775..e7ee9dd05 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1096,6 +1096,35 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) } } +static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) +{ + fixed_t ofs; + column_t *column; + UINT8 *source; + + if (x < SHORT(patch->width)) + { + INT32 topdelta, prevdelta = -1; + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-x) : x])); + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (UINT8 *)(column) + 3; + for (ofs = 0; ofs < column->length; ofs++) + { + if ((topdelta + ofs) == y) + return source[ofs]; + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } + + return 0xFF00; +} + #ifdef ROTSPRITE // // R_CacheRotSprite @@ -1108,8 +1137,8 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp INT32 angle; patch_t *patch; patch_t *newpatch; - UINT16 *rawsrc, *rawdst; - size_t size, size2; + UINT16 *rawdst; + size_t size; INT32 bflip = (flip != 0x00); #define SPRITE_XCENTER (leftoffset) @@ -1154,16 +1183,6 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp leftoffset = width - leftoffset; } - // Draw the sprite to a temporary buffer. - size = (width*height); - rawsrc = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL); - - // can't memset here - for (i = 0; i < size; i++) - rawsrc[i] = 0xFF00; - - R_PatchToFlat_16bpp(patch, rawsrc, bflip); - // Don't cache angle = 0 for (angle = 1; angle < ROTANGLES; angle++) { @@ -1231,17 +1250,15 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp #undef BOUNDARYADJUST } - size2 = (newwidth * newheight); - if (!size2) - size2 = size; + // Draw the rotated sprite to a temporary buffer. + size = (newwidth * newheight); + if (!size) + size = (width * height); - rawdst = Z_Malloc(size2 * sizeof(UINT16), PU_STATIC, NULL); - - // can't memset here - for (i = 0; i < size2; i++) + rawdst = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL); + for (i = 0; i < size; i++) rawdst[i] = 0xFF00; - // Draw the rotated sprite to a temporary buffer. for (dy = 0; dy < newheight; dy++) { for (dx = 0; dx < newwidth; dx++) @@ -1253,7 +1270,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp sx >>= FRACBITS; sy >>= FRACBITS; if (sx >= 0 && sy >= 0 && sx < width && sy < height) - rawdst[(dy*newwidth)+dx] = rawsrc[(sy*width)+sx]; + rawdst[(dy*newwidth)+dx] = GetPatchPixel(patch, sx, sy, bflip); } } @@ -1290,7 +1307,6 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp sprframe->rotsprite.cached[rot] = true; // free image data - Z_Free(rawsrc); Z_Free(patch); } #undef SPRITE_XCENTER From aff5b52ebaabca852ecdb6759b3d2b06bb8cfbe8 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 17 Dec 2019 13:39:26 -0300 Subject: [PATCH 038/312] change ROTANGLES to 72 --- src/doomdef.h | 2 +- src/r_patch.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 026498ca1..579030a1c 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -625,7 +625,7 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Sprite rotation #define ROTSPRITE -#define ROTANGLES 360 // Needs to be a divisor of 360 (45, 60, 90, 120...) +#define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...) #define ROTANGDIFF (360 / ROTANGLES) #ifndef HAVE_PNG diff --git a/src/r_patch.c b/src/r_patch.c index e7ee9dd05..8d300f041 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1102,7 +1102,7 @@ static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) column_t *column; UINT8 *source; - if (x < SHORT(patch->width)) + if (x >= 0 && x < SHORT(patch->width)) { INT32 topdelta, prevdelta = -1; column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-x) : x])); From e3ab21c85f5f4f328e2aab23c65bc7be44405e7b Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 17 Dec 2019 13:48:48 -0300 Subject: [PATCH 039/312] opengl --- src/hardware/hw_md2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 9f8537b61..c18422145 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1379,7 +1379,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) } p.rollangle = 0.0f; - p.rollflip = 0; + p.rollflip = 1; p.rotaxis = 0; if (spr->mobj->rollangle) { From 254d812901c6ba5c2ba53d70f4d0e8e0d9c14dc2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 00:28:58 -0300 Subject: [PATCH 040/312] More customisable title card Add TitleCardZigZag, TitleCardZigZagText and TitleCardActDiamond fields to SOC. Add the same fields to Lua under their internal names. Turn map header level flags into an UINT16, so that NoTitleCard works. (NOBODY caught this, I'm actually disappointed.) --- src/dehacked.c | 19 ++++++++++++++++++- src/doomstat.h | 7 ++++++- src/lua_maplib.c | 6 ++++++ src/p_setup.c | 3 +++ src/st_stuff.c | 36 ++++++++++++++++++++++++------------ 5 files changed, 57 insertions(+), 14 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 175c1fcfa..c66f3589d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1520,10 +1520,27 @@ static void readlevelheader(MYFILE *f, INT32 num) deh_warning("Level header %d: invalid bonus type number %d", num, i); } + // Title card + else if (fastcmp(word, "TITLECARDZIGZAG")) + { + deh_strlcpy(mapheaderinfo[num-1]->ltzzpatch, word2, + sizeof(mapheaderinfo[num-1]->ltzzpatch), va("Level header %d: title card zigzag patch name", num)); + } + else if (fastcmp(word, "TITLECARDZIGZAGTEXT")) + { + deh_strlcpy(mapheaderinfo[num-1]->ltzztext, word2, + sizeof(mapheaderinfo[num-1]->ltzztext), va("Level header %d: title card zigzag text patch name", num)); + } + else if (fastcmp(word, "TITLECARDACTDIAMOND")) + { + deh_strlcpy(mapheaderinfo[num-1]->ltactdiamond, word2, + sizeof(mapheaderinfo[num-1]->ltactdiamond), va("Level header %d: title card act diamond patch name", num)); + } + else if (fastcmp(word, "MAXBONUSLIVES")) mapheaderinfo[num-1]->maxbonuslives = (SINT8)i; else if (fastcmp(word, "LEVELFLAGS")) - mapheaderinfo[num-1]->levelflags = (UINT8)i; + mapheaderinfo[num-1]->levelflags = (UINT16)i; else if (fastcmp(word, "MENUFLAGS")) mapheaderinfo[num-1]->menuflags = (UINT8)i; diff --git a/src/doomstat.h b/src/doomstat.h index 3c0b4773a..a42591f47 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -310,12 +310,17 @@ typedef struct SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.) SINT8 maxbonuslives; ///< How many bonus lives to award at Intermission? (-1 for unlimited.) - UINT8 levelflags; ///< LF_flags: merged booleans into one UINT8 for space, see below + UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus char selectheading[22]; ///< Level select heading. Allows for controllable grouping. UINT16 startrings; ///< Number of rings players start with. + // Title card. + char ltzzpatch[8]; ///< Zig zag patch. + char ltzztext[8]; ///< Zig zag text. + char ltactdiamond[8]; ///< Act diamond. + // Freed animals stuff. UINT8 numFlickies; ///< Internal. For freed flicky support. mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful. diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0fe1df0b6..dd939c31b 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -2071,6 +2071,12 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->levelselect); else if (fastcmp(field,"bonustype")) lua_pushinteger(L, header->bonustype); + else if (fastcmp(field,"ltzzpatch")) + lua_pushstring(L, header->ltzzpatch); + else if (fastcmp(field,"ltzztext")) + lua_pushstring(L, header->ltzztext); + else if (fastcmp(field,"ltactdiamond")) + lua_pushstring(L, header->ltactdiamond); else if (fastcmp(field,"maxbonuslives")) lua_pushinteger(L, header->maxbonuslives); else if (fastcmp(field,"levelflags")) diff --git a/src/p_setup.c b/src/p_setup.c index bf3493d8c..2bbfe3924 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -210,6 +210,9 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->lvlttl[0] = '\0'; mapheaderinfo[num]->selectheading[0] = '\0'; mapheaderinfo[num]->subttl[0] = '\0'; + mapheaderinfo[num]->ltzzpatch[0] = '\0'; + mapheaderinfo[num]->ltzztext[0] = '\0'; + mapheaderinfo[num]->ltactdiamond[0] = '\0'; mapheaderinfo[num]->actnum = 0; mapheaderinfo[num]->typeoflevel = 0; mapheaderinfo[num]->nextlevel = (INT16)(i + 1); diff --git a/src/st_stuff.c b/src/st_stuff.c index 1b8107edb..ec0590419 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1177,21 +1177,33 @@ tic_t lt_exitticker = 0, lt_endtime = 0; // // Load the graphics for the title card. +// Don't let LJ see this // static void ST_cacheLevelTitle(void) { - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE)) - { - lt_patches[0] = (patch_t *)W_CachePatchName("LTACTBLU", PU_HUDGFX); - lt_patches[1] = (patch_t *)W_CachePatchName("LTZIGZAG", PU_HUDGFX); - lt_patches[2] = (patch_t *)W_CachePatchName("LTZZTEXT", PU_HUDGFX); - } - else // boss map - { - lt_patches[0] = (patch_t *)W_CachePatchName("LTACTRED", PU_HUDGFX); - lt_patches[1] = (patch_t *)W_CachePatchName("LTZIGRED", PU_HUDGFX); - lt_patches[2] = (patch_t *)W_CachePatchName("LTZZWARN", PU_HUDGFX); - } +#define SETPATCH(default, warning, custom, idx) \ +{ \ + lumpnum_t patlumpnum = LUMPERROR; \ + if (mapheaderinfo[gamemap-1]->custom[0] != '\0') \ + { \ + patlumpnum = W_CheckNumForName(mapheaderinfo[gamemap-1]->custom); \ + if (patlumpnum != LUMPERROR) \ + lt_patches[idx] = (patch_t *)W_CachePatchNum(patlumpnum, PU_HUDGFX); \ + } \ + if (patlumpnum == LUMPERROR) \ + { \ + if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE)) \ + lt_patches[idx] = (patch_t *)W_CachePatchName(default, PU_HUDGFX); \ + else \ + lt_patches[idx] = (patch_t *)W_CachePatchName(warning, PU_HUDGFX); \ + } \ +} + + SETPATCH("LTACTBLU", "LTACTRED", ltactdiamond, 0) + SETPATCH("LTZIGZAG", "LTZIGRED", ltzzpatch, 1) + SETPATCH("LTZZTEXT", "LTZZWARN", ltzztext, 2) + +#undef SETPATCH } // From 317191ec7c5416374c79dcc5531bda3dd072029a Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 00:52:50 -0300 Subject: [PATCH 041/312] Freeslot moment! --- src/doomstat.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/doomstat.h b/src/doomstat.h index 3c0b4773a..772f6b3fb 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -386,6 +386,7 @@ enum TypeOfLevel }; // Gametypes +#define NUMGAMETYPEFREESLOTS 512 enum GameType { GT_COOP = 0, // also used in single player @@ -400,6 +401,8 @@ enum GameType GT_CTF, // capture the flag + GT_FIRSTFREESLOT, + GT_LASTFREESLOT = GT_FIRSTFREESLOT + NUMGAMETYPEFREESLOTS - 1, NUMGAMETYPES }; // If you alter this list, update dehacked.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c From 7bfdc2caa0f9473069767aa5e405623940c70841 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 01:25:57 -0300 Subject: [PATCH 042/312] Gametype rules draft, mind the debug command --- src/d_clisrv.c | 4 ++-- src/d_main.c | 4 ++-- src/d_netcmd.c | 12 +++++++++++- src/doomstat.h | 12 ++++++++++++ src/g_game.c | 46 ++++++++++++++++++++++++++++++++++++++++------ src/g_game.h | 1 + 6 files changed, 68 insertions(+), 11 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7b6c35eb6..14901360d 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3461,7 +3461,7 @@ void SV_StartSinglePlayerServer(void) server = true; netgame = false; multiplayer = false; - gametype = GT_COOP; + G_SetGametype(GT_COOP); // no more tic the game with this settings! SV_StopServer(); @@ -3740,7 +3740,7 @@ static void HandlePacketFromAwayNode(SINT8 node) if (client) { maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); - gametype = netbuffer->u.servercfg.gametype; + G_SetGametype(netbuffer->u.servercfg.gametype); modifiedgame = netbuffer->u.servercfg.modifiedgame; for (j = 0; j < MAXPLAYERS; j++) adminplayers[j] = netbuffer->u.servercfg.adminplayers[j]; diff --git a/src/d_main.c b/src/d_main.c index ef6502aec..815136440 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -753,7 +753,7 @@ void D_StartTitle(void) gameaction = ga_nothing; displayplayer = consoleplayer = 0; - gametype = GT_COOP; + G_SetGametype(GT_COOP); paused = false; advancedemo = false; F_InitMenuPresValues(); @@ -1416,7 +1416,7 @@ void D_SRB2Main(void) if (newgametype != -1) { j = gametype; - gametype = newgametype; + G_SetGametype(newgametype); D_GameTypeChanged(j); } } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 00cb6e65e..40d626185 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -125,6 +125,7 @@ static void Command_Version_f(void); static void Command_ModDetails_f(void); #endif static void Command_ShowGametype_f(void); +static void Command_SetGametype_f(void); FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void); static void Command_Playintro_f(void); @@ -381,6 +382,7 @@ char timedemo_csv_id[256]; boolean timedemo_quit; INT16 gametype = GT_COOP; +INT16 gametyperules = 0; boolean splitscreen = false; boolean circuitmap = false; INT32 adminplayers[MAXPLAYERS]; @@ -480,6 +482,7 @@ void D_RegisterServerCommands(void) COM_AddCommand("suicide", Command_Suicide); COM_AddCommand("gametype", Command_ShowGametype_f); + COM_AddCommand("setgametype", Command_SetGametype_f); COM_AddCommand("version", Command_Version_f); #ifdef UPDATE_ALERT COM_AddCommand("mod_details", Command_ModDetails_f); @@ -2065,6 +2068,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) lastgametype = gametype; gametype = READUINT8(*cp); + G_SetGametype(gametype); // I fear putting that macro as an argument if (gametype < 0 || gametype >= NUMGAMETYPES) gametype = lastgametype; @@ -3623,6 +3627,12 @@ static void Command_ShowGametype_f(void) CONS_Printf(M_GetText("Unknown gametype set (%d)\n"), gametype); } +static void Command_SetGametype_f(void) +{ + if (COM_Argc() > 1) + G_SetGametype(atoi(COM_Argv(1))); +} + /** Plays the intro. */ static void Command_Playintro_f(void) @@ -3935,7 +3945,7 @@ void D_GameTypeChanged(INT32 lastgametype) } else if (!multiplayer && !netgame) { - gametype = GT_COOP; + G_SetGametype(GT_COOP); // These shouldn't matter anymore //CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); //CV_SetValue(&cv_itemrespawn, 0); diff --git a/src/doomstat.h b/src/doomstat.h index 772f6b3fb..2b493c917 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -84,6 +84,7 @@ extern boolean addedtogame; // true after the server has added you extern boolean multiplayer; extern INT16 gametype; +extern INT16 gametyperules; extern boolean splitscreen; extern boolean circuitmap; // Does this level have 'circuit mode'? extern boolean fromlevelselect; @@ -407,6 +408,17 @@ enum GameType }; // If you alter this list, update dehacked.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c +// Game type rules +enum GameTypeRules +{ + GTR_PLATFORM = 1, // Co-op, Competition, Race + GTR_TAG = 1<<1, // Tag, Hide and Seek + GTR_RINGSLINGER = 1<<2, // Not Co-op, not Competition, and not Race (overriden by cv_ringslinger) + GTR_SPECTATORS = 1<<3, // Not Co-op, not Competition, and not Race + GTR_TEAMS = 1<<4, // Team Match, CTF + GTR_LIVES = 1<<5, // A lot of special cases in G_GametypeUsesLives actually, but just Co-op and Competition +}; + // String names for gametypes extern const char *Gametype_Names[NUMGAMETYPES]; diff --git a/src/g_game.c b/src/g_game.c index 2a12dd298..d1fc61c35 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3058,6 +3058,34 @@ const char *Gametype_Names[NUMGAMETYPES] = "CTF" // GT_CTF }; +// Game type rules +INT16 gametypedefaultrules[NUMGAMETYPES] = +{ + GTR_PLATFORM|GTR_LIVES, // GT_COOP + GTR_PLATFORM|GTR_LIVES, // GT_COMPETITION + GTR_PLATFORM, // GT_RACE + + GTR_RINGSLINGER|GTR_SPECTATORS, // GT_MATCH + GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS, // GT_TEAMMATCH + + GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS, // GT_TAG + GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS, // GT_HIDEANDSEEK + + GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS // GT_CTF +}; + +// +// G_SetGametype +// +// Set a new gametype, also setting gametype rules accordingly. Yay! +// +void G_SetGametype(INT16 gtype) +{ + gametype = gtype; + gametyperules = gametypedefaultrules[gametype]; + CONS_Printf("Gametype set to %s (%d)\n", Gametype_Names[gametype], gametype); +} + // // G_GetGametypeByName // @@ -3101,7 +3129,8 @@ boolean G_IsSpecialStage(INT32 mapnum) boolean G_GametypeUsesLives(void) { // Coop, Competitive - if ((gametype == GT_COOP || gametype == GT_COMPETITION) + //if ((gametype == GT_COOP || gametype == GT_COMPETITION) + if ((gametyperules & GTR_LIVES) && !(modeattacking || metalrecording) // No lives in Time Attack && !G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)) // No lives in NiGHTS @@ -3117,7 +3146,8 @@ boolean G_GametypeUsesLives(void) // boolean G_GametypeHasTeams(void) { - return (gametype == GT_TEAMMATCH || gametype == GT_CTF); + return (gametyperules & GTR_TEAMS); + //return (gametype == GT_TEAMMATCH || gametype == GT_CTF); } // @@ -3128,7 +3158,8 @@ boolean G_GametypeHasTeams(void) // boolean G_GametypeHasSpectators(void) { - return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE); + return (gametyperules & GTR_SPECTATORS); + //return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE); } // @@ -3139,7 +3170,8 @@ boolean G_GametypeHasSpectators(void) // boolean G_RingSlingerGametype(void) { - return ((gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE) || (cv_ringslinger.value)); + return ((gametyperules & GTR_RINGSLINGER) || (cv_ringslinger.value)); + //return ((gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE) || (cv_ringslinger.value)); } // @@ -3149,7 +3181,8 @@ boolean G_RingSlingerGametype(void) // boolean G_PlatformGametype(void) { - return (gametype == GT_COOP || gametype == GT_RACE || gametype == GT_COMPETITION); + return (gametyperules & GTR_PLATFORM); + //return (gametype == GT_COOP || gametype == GT_RACE || gametype == GT_COMPETITION); } // @@ -3159,7 +3192,8 @@ boolean G_PlatformGametype(void) // boolean G_TagGametype(void) { - return (gametype == GT_TAG || gametype == GT_HIDEANDSEEK); + return (gametyperules & GTR_TAG); + //return (gametype == GT_TAG || gametype == GT_HIDEANDSEEK); } /** Get the typeoflevel flag needed to indicate support of a gametype. diff --git a/src/g_game.h b/src/g_game.h index e7f4a4677..a925e14c1 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -201,6 +201,7 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill); void G_StopDemo(void); boolean G_CheckDemoStatus(void); +void G_SetGametype(INT16 gametype); INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); From ea5e0d28ed117292a64a491c6de7bdc60df81c13 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 01:54:45 -0300 Subject: [PATCH 043/312] More gametype rules yay!! --- src/d_clisrv.c | 2 +- src/d_netcmd.c | 12 ++++++++---- src/doomstat.h | 26 ++++++++++++++++++++------ src/g_game.c | 28 ++++++++++++++++++---------- src/p_inter.c | 2 +- src/p_map.c | 2 +- src/p_mobj.c | 4 ++-- src/p_setup.c | 3 +-- src/p_spec.c | 2 +- src/p_user.c | 24 ++++++++++++------------ src/st_stuff.c | 18 +++++++++--------- 11 files changed, 74 insertions(+), 49 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 14901360d..3786c75d6 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2512,7 +2512,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) if (G_TagGametype()) //Check if you still have a game. Location flexible. =P P_CheckSurvivors(); - else if (gametype == GT_RACE || gametype == GT_COMPETITION) + else if (gametyperules & GTR_RACE) P_CheckRacers(); } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 40d626185..0b7e3de18 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1125,7 +1125,7 @@ UINT8 CanChangeSkin(INT32 playernum) return true; // Can change skin during initial countdown. - if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE) + if ((gametyperules & GTR_RACE) && leveltime < 4*TICRATE) return true; if (G_TagGametype()) @@ -2413,7 +2413,7 @@ static void Command_Teamchange_f(void) } //additional check for hide and seek. Don't allow change of status after hidetime ends. - if (gametype == GT_HIDEANDSEEK && leveltime >= (hidetime * TICRATE)) + if ((gametyperules & GTR_HIDETIMEFROZEN) && leveltime >= (hidetime * TICRATE)) { CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); return; @@ -2510,7 +2510,7 @@ static void Command_Teamchange2_f(void) } //additional check for hide and seek. Don't allow change of status after hidetime ends. - if (gametype == GT_HIDEANDSEEK && leveltime >= (hidetime * TICRATE)) + if ((gametyperules & GTR_HIDETIMEFROZEN) && leveltime >= (hidetime * TICRATE)) { CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); return; @@ -2639,7 +2639,7 @@ static void Command_ServerTeamChange_f(void) } //additional check for hide and seek. Don't allow change of status after hidetime ends. - if (gametype == GT_HIDEANDSEEK && leveltime >= (hidetime * TICRATE)) + if ((gametyperules & GTR_HIDETIMEFROZEN) && leveltime >= (hidetime * TICRATE)) { CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); return; @@ -2728,6 +2728,10 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) return; } + //no status changes after hidetime + if ((gametyperules & GTR_HIDETIMEFROZEN) && (leveltime >= (hidetime * TICRATE))) + error = true; + //Make sure that the right team number is sent. Keep in mind that normal clients cannot change to certain teams in certain gametypes. switch (gametype) { diff --git a/src/doomstat.h b/src/doomstat.h index 2b493c917..90aa185b7 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -411,12 +411,26 @@ enum GameType // Game type rules enum GameTypeRules { - GTR_PLATFORM = 1, // Co-op, Competition, Race - GTR_TAG = 1<<1, // Tag, Hide and Seek - GTR_RINGSLINGER = 1<<2, // Not Co-op, not Competition, and not Race (overriden by cv_ringslinger) - GTR_SPECTATORS = 1<<3, // Not Co-op, not Competition, and not Race - GTR_TEAMS = 1<<4, // Team Match, CTF - GTR_LIVES = 1<<5, // A lot of special cases in G_GametypeUsesLives actually, but just Co-op and Competition + GTR_PLATFORM = 1, // Co-op, Competition, and Race + GTR_TAG = 1<<1, // Tag and Hide and Seek + GTR_RINGSLINGER = 1<<2, // Not Co-op, not Competition, and not Race (overriden by cv_ringslinger) + GTR_SPECTATORS = 1<<3, // Not Co-op, not Competition, and not Race + GTR_TEAMS = 1<<4, // Team Match, CTF + GTR_LIVES = 1<<5, // A lot of special cases in G_GametypeUsesLives actually, but just Co-op and Competition + GTR_RACE = 1<<6, // Race and Competition + + // Lactozilla + // Awesome! Those are new game type rules + // provided by yours truly to allow for more + // flexibility! Those will replace some + // straight-up gametype checks scattered + // around the source code! + GTR_CHASECAM = 1<<7, // Prefer chasecam at map load + GTR_TIMELIMIT = 1<<8, // Ringslinger time limit + GTR_HIDETIME = 1<<9, // Tag and Hide and Seek + GTR_HIDETIMEFROZEN = 1<<10, // Hide and Seek, but not Tag + GTR_BLINDFOLDED = 1<<11, // Blindfolded view for Tag and Hide and Seek + GTR_EMERALDS = 1<<12, // Ringslinger emeralds }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index d1fc61c35..59764e0fc 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1002,7 +1002,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) // why build a ticcmd if we're paused? // Or, for that matter, if we're being reborn. // ...OR if we're blindfolded. No looking into the floor. - if (paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) + if (paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametyperules & GTR_TAG) && (leveltime < hidetime * TICRATE) && (player->pflags & PF_TAGIT))))) { cmd->angleturn = (INT16)(localangle >> 16); @@ -3061,17 +3061,25 @@ const char *Gametype_Names[NUMGAMETYPES] = // Game type rules INT16 gametypedefaultrules[NUMGAMETYPES] = { - GTR_PLATFORM|GTR_LIVES, // GT_COOP - GTR_PLATFORM|GTR_LIVES, // GT_COMPETITION - GTR_PLATFORM, // GT_RACE + // Co-op + GTR_PLATFORM|GTR_LIVES|GTR_CHASECAM, + // Competition + GTR_PLATFORM|GTR_LIVES|GTR_RACE|GTR_CHASECAM, + // Race + GTR_PLATFORM|GTR_RACE|GTR_CHASECAM, - GTR_RINGSLINGER|GTR_SPECTATORS, // GT_MATCH - GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS, // GT_TEAMMATCH + // Match + GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS, + // Team Match + GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_TIMELIMIT, - GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS, // GT_TAG - GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS, // GT_HIDEANDSEEK + // Tag + GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, + // Hide and Seek + GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, - GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS // GT_CTF + // CTF + GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS, }; // @@ -3384,7 +3392,7 @@ static void G_DoCompleted(void) I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1); // wrap around in race - if (nextmap >= 1100-1 && nextmap <= 1102-1 && (gametype == GT_RACE || gametype == GT_COMPETITION)) + if (nextmap >= 1100-1 && nextmap <= 1102-1 && (gametyperules & GTR_RACE)) nextmap = (INT16)(spstage_start-1); if ((gottoken = (gametype == GT_COOP && token))) diff --git a/src/p_inter.c b/src/p_inter.c index 70fb01fd0..7b5839e03 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2978,7 +2978,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) player->flyangle += 180; // Shuffle's BETTERNIGHTSMOVEMENT? player->flyangle %= 360; - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) player->drillmeter -= 5*20; else { diff --git a/src/p_map.c b/src/p_map.c index 2d36f747c..1b6f23cde 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -615,7 +615,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) // Why block opposing teams from tailsflying each other? // Sneaking into the hands of a flying tails player in Race might be a viable strategy, who knows. /* - if (gametype == GT_RACE || gametype == GT_COMPETITION + if ((gametyperules & GTR_RACE) || (netgame && (tails->spectator || sonic->spectator)) || (G_TagGametype() && (!(tails->pflags & PF_TAGIT) != !(sonic->pflags & PF_TAGIT))) || (gametype == GT_MATCH) diff --git a/src/p_mobj.c b/src/p_mobj.c index dea4a7a4d..df89fbfde 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11702,7 +11702,7 @@ You should think about modifying the deathmatch starts to take full advantage of if (!cv_powerstones.value) return; - if (!(gametype == GT_MATCH || gametype == GT_CTF)) + if (!(gametyperules & GTR_EMERALDS)) return; runemeraldmanager = true; @@ -11722,7 +11722,7 @@ You should think about modifying the deathmatch starts to take full advantage of // Yeah, this is a dirty hack. if ((mobjinfo[i].flags & (MF_MONITOR|MF_GRENADEBOUNCE)) == MF_MONITOR) { - if (gametype == GT_COMPETITION || gametype == GT_RACE) + if (gametyperules & GTR_RACE) { // Set powerup boxes to user settings for competition. if (cv_competitionboxes.value == 1) // Mystery diff --git a/src/p_setup.c b/src/p_setup.c index bf3493d8c..7e6bdcc67 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2683,8 +2683,7 @@ boolean P_SetupLevel(boolean skipprecip) // chasecam on in chaos, race, coop // chasecam off in match, tag, capture the flag - chase = (gametype == GT_RACE || gametype == GT_COMPETITION || gametype == GT_COOP) - || (maptol & TOL_2D); + chase = (gametyperules & GTR_CHASECAM) || (maptol & TOL_2D); if (!dedicated) { diff --git a/src/p_spec.c b/src/p_spec.c index dba4e17b5..4bdb99520 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7224,7 +7224,7 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 308: // Race-only linedef executor. Triggers once. - if (gametype != GT_RACE && gametype != GT_COMPETITION) + if (!(gametyperules & GTR_RACE)) lines[i].special = 0; break; diff --git a/src/p_user.c b/src/p_user.c index ea42a2c36..a8ae383cf 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -387,7 +387,7 @@ UINT8 P_FindLowestMare(void) mobj_t *mo2; UINT8 mare = UINT8_MAX; - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) return 0; // scan the thinkers @@ -793,7 +793,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) P_RestoreMusic(player); } - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) { if (player->drillmeter < 48*20) player->drillmeter = 48*20; @@ -2181,7 +2181,7 @@ void P_DoPlayerExit(player_t *player) if (cv_allowexitlevel.value == 0 && !G_PlatformGametype()) return; - else if (gametype == GT_RACE || gametype == GT_COMPETITION) // If in Race Mode, allow + else if (gametyperules & GTR_RACE) // If in Race Mode, allow { if (!countdown) // a 60-second wait ala Sonic 2. countdown = (cv_countdowntime.value - 1)*TICRATE + 1; // Use cv_countdowntime @@ -4670,7 +4670,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (player->powers[pw_carry] == CR_BRAKGOOP) player->dashspeed = 0; - if (!((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE)) + if (!((gametyperules & GTR_RACE) && leveltime < 4*TICRATE)) { if (player->dashspeed) { @@ -7137,7 +7137,7 @@ static void P_NiGHTSMovement(player_t *player) && !player->exiting) player->nightstime--; } - else if (gametype != GT_RACE && gametype != GT_COMPETITION + else if (!(gametyperules & GTR_RACE) && !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]) && !(player->capsule && player->capsule->reactiontime) @@ -7293,7 +7293,7 @@ static void P_NiGHTSMovement(player_t *player) { player->mo->momx = player->mo->momy = 0; - if (gametype != GT_RACE && gametype != GT_COMPETITION) + if (!(gametyperules & GTR_RACE)) P_SetObjectMomZ(player->mo, FRACUNIT/2, (P_MobjFlip(player->mo)*player->mo->momz >= 0)); else player->mo->momz = 0; @@ -9535,12 +9535,12 @@ static void P_DeathThink(player_t *player) player->playerstate = PST_REBORN; } - if (gametype == GT_RACE || gametype == GT_COMPETITION || (gametype == GT_COOP && (multiplayer || netgame))) + if ((gametyperules & GTR_RACE) || (gametype == GT_COOP && (multiplayer || netgame))) { // Keep time rolling in race mode if (!(countdown2 && !countdown) && !player->exiting && !(player->pflags & PF_GAMETYPEOVER) && !stoppedclock) { - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) { if (leveltime >= 4*TICRATE) player->realtime = leveltime - 4*TICRATE; @@ -11372,7 +11372,7 @@ void P_PlayerThink(player_t *player) I_Error("player %s is in PST_REBORN\n", sizeu1(playeri)); #endif - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) { INT32 i; @@ -11435,7 +11435,7 @@ void P_PlayerThink(player_t *player) player->exiting > 0 && player->exiting <= 1*TICRATE && (!multiplayer || gametype == GT_COOP ? !mapheaderinfo[gamemap-1]->musinterfadeout : true) && // don't fade if we're fading during intermission. follows Y_StartIntermission intertype = int_coop - (gametype == GT_RACE || gametype == GT_COMPETITION ? countdown2 == 0 : true) && // don't fade on timeout + ((gametyperules & GTR_RACE) ? countdown2 == 0 : true) && // don't fade on timeout player->lives > 0 && // don't fade on game over (competition) P_IsLocalPlayer(player)) { @@ -11550,7 +11550,7 @@ void P_PlayerThink(player_t *player) player->lives = cv_startinglives.value; } - if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE) + if ((gametyperules & GTR_RACE) && leveltime < 4*TICRATE) { cmd->buttons &= BT_USE; // Remove all buttons except BT_USE cmd->forwardmove = 0; @@ -11560,7 +11560,7 @@ void P_PlayerThink(player_t *player) // Synchronizes the "real" amount of time spent in the level. if (!player->exiting && !stoppedclock) { - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) { if (leveltime >= 4*TICRATE) player->realtime = leveltime - 4*TICRATE; diff --git a/src/st_stuff.c b/src/st_stuff.c index 1b8107edb..6e8c64127 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -694,7 +694,7 @@ static void ST_drawTime(void) else { // Counting down the hidetime? - if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (stplyr->realtime <= (hidetime*TICRATE))) + if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime <= (hidetime*TICRATE))) { tics = (hidetime*TICRATE - stplyr->realtime); if (tics < 3*TICRATE) @@ -705,11 +705,11 @@ static void ST_drawTime(void) else { // Hidetime finish! - if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (stplyr->realtime < ((hidetime+1)*TICRATE))) + if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime < ((hidetime+1)*TICRATE))) ST_drawRaceNum(hidetime*TICRATE - stplyr->realtime); // Time limit? - if (gametype != GT_COOP && gametype != GT_RACE && gametype != GT_COMPETITION && cv_timelimit.value && timelimitintics > 0) + if ((gametyperules & GTR_TIMELIMIT) && cv_timelimit.value && timelimitintics > 0) { if (timelimitintics > stplyr->realtime) { @@ -723,7 +723,7 @@ static void ST_drawTime(void) downwards = true; } // Post-hidetime normal. - else if (gametype == GT_TAG || gametype == GT_HIDEANDSEEK) + else if (gametyperules & GTR_TAG) tics = stplyr->realtime - hidetime*TICRATE; // "Shadow! What are you doing? Hurry and get back here // right now before the island blows up with you on it!" @@ -912,7 +912,7 @@ static void ST_drawLivesArea(void) else if (stplyr->spectator) v_colmap = V_GRAYMAP; // Tag - else if (gametype == GT_TAG || gametype == GT_HIDEANDSEEK) + else if (gametyperules & GTR_TAG) { if (stplyr->pflags & PF_TAGIT) { @@ -1762,7 +1762,7 @@ static void ST_drawNiGHTSHUD(void) ST_drawNiGHTSLink(); } - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) { ST_drawScore(); ST_drawTime(); @@ -2273,7 +2273,7 @@ static void ST_drawTextHUD(void) } } } - else if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator)) + else if ((gametyperules & GTR_TAG) && (!stplyr->spectator)) { if (leveltime < hidetime * TICRATE) { @@ -2648,7 +2648,7 @@ static void ST_overlayDrawer(void) ST_drawMatchHUD(); // Race HUD Stuff - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) ST_drawRaceHUD(); // Emerald Hunt Indicators @@ -2753,7 +2753,7 @@ void ST_Drawer(void) if (rendermode != render_none) ST_doPaletteStuff(); // Blindfold! - if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) + if ((gametyperules & GTR_BLINDFOLDED) && (leveltime < hidetime * TICRATE)) { if (players[displayplayer].pflags & PF_TAGIT) From 185fa2799de073fcea7cc0afeb1667a9d5f0741c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 11:33:56 -0300 Subject: [PATCH 044/312] Update comments --- src/doomstat.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 90aa185b7..5569e3197 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -425,12 +425,12 @@ enum GameTypeRules // flexibility! Those will replace some // straight-up gametype checks scattered // around the source code! - GTR_CHASECAM = 1<<7, // Prefer chasecam at map load - GTR_TIMELIMIT = 1<<8, // Ringslinger time limit + GTR_CHASECAM = 1<<7, // Prefer chasecam at map load (All platform gametypes) + GTR_TIMELIMIT = 1<<8, // Ringslinger time limit (Tag and Hide and Seek) GTR_HIDETIME = 1<<9, // Tag and Hide and Seek GTR_HIDETIMEFROZEN = 1<<10, // Hide and Seek, but not Tag - GTR_BLINDFOLDED = 1<<11, // Blindfolded view for Tag and Hide and Seek - GTR_EMERALDS = 1<<12, // Ringslinger emeralds + GTR_BLINDFOLDED = 1<<11, // Blindfolded view (Tag and Hide and Seek) + GTR_EMERALDS = 1<<12, // Ringslinger emeralds (Match and CTF) }; // String names for gametypes From 299f2bd8cdafcfdfff889c40cb33f7e6975c6b53 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 11:43:50 -0300 Subject: [PATCH 045/312] GTR_TEAMFLAGS --- src/d_clisrv.c | 6 +++--- src/doomstat.h | 1 + src/g_game.c | 4 ++-- src/hu_stuff.c | 4 ++-- src/m_cheat.c | 2 +- src/p_enemy.c | 8 ++++---- src/p_inter.c | 8 ++++---- src/p_mobj.c | 8 ++++---- src/p_spec.c | 6 +++--- src/p_user.c | 8 ++++---- src/st_stuff.c | 12 +++++++----- 11 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3786c75d6..bfc478bd5 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1025,7 +1025,7 @@ static void SV_SendResynch(INT32 node) netbuffer->packettype = PT_RESYNCHEND; netbuffer->u.resynchend.randomseed = P_GetRandSeed(); - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) resynch_write_ctf(&netbuffer->u.resynchend); resynch_write_others(&netbuffer->u.resynchend); @@ -2430,7 +2430,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) } } - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! // If in a special stage, redistribute the player's spheres across @@ -4124,7 +4124,7 @@ static void HandlePacketFromPlayer(SINT8 node) P_SetRandSeed(netbuffer->u.resynchend.randomseed); - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) resynch_read_ctf(&netbuffer->u.resynchend); resynch_read_others(&netbuffer->u.resynchend); diff --git a/src/doomstat.h b/src/doomstat.h index 5569e3197..06e114eb1 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -431,6 +431,7 @@ enum GameTypeRules GTR_HIDETIMEFROZEN = 1<<10, // Hide and Seek, but not Tag GTR_BLINDFOLDED = 1<<11, // Blindfolded view (Tag and Hide and Seek) GTR_EMERALDS = 1<<12, // Ringslinger emeralds (Match and CTF) + GTR_TEAMFLAGS = 1<<13, // Gametype has team flags (CTF) }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 59764e0fc..1f6bde833 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2564,7 +2564,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) // -- CTF -- // Order: CTF->DM->Coop - if (gametype == GT_CTF && players[playernum].ctfteam) + if ((gametyperules & GTR_TEAMFLAGS) && players[playernum].ctfteam) { if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start @@ -3079,7 +3079,7 @@ INT16 gametypedefaultrules[NUMGAMETYPES] = GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, // CTF - GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS, + GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS|GTR_TEAMFLAGS, }; // diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 91a167a60..e67249953 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2541,7 +2541,7 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) | (greycheck ? 0 : V_TRANSLUCENT) | V_ALLOWLOWERCASE, name); - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) { if (players[tab[i].num].gotflag & GF_REDFLAG) // Red V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, rflagico, 0); @@ -2669,7 +2669,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) | (greycheck ? V_TRANSLUCENT : 0) | V_ALLOWLOWERCASE, name); - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) { if (players[tab[i].num].gotflag & GF_REDFLAG) // Red V_DrawSmallScaledPatch(x-28, y-4, 0, rflagico); diff --git a/src/m_cheat.c b/src/m_cheat.c index e31ce7869..1d4fa3b5d 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -778,7 +778,7 @@ void Command_CauseCfail_f(void) P_SetThingPosition(players[consoleplayer].mo); // CTF consistency test - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) { if (blueflag) { P_RemoveMobj(blueflag); diff --git a/src/p_enemy.c b/src/p_enemy.c index 74a11fe67..30284a2dd 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4985,7 +4985,7 @@ void A_ThrownRing(mobj_t *actor) continue; // Don't home in on teammates. - if (gametype == GT_CTF + if ((gametyperules & GTR_TEAMFLAGS) && actor->target->player->ctfteam == player->ctfteam) continue; } @@ -6591,7 +6591,7 @@ void A_OldRingExplode(mobj_t *actor) { if (changecolor) { - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) mo->color = actor->target->color; //copy color else if (actor->target->player->ctfteam == 2) mo->color = skincolor_bluering; @@ -6607,7 +6607,7 @@ void A_OldRingExplode(mobj_t *actor) { if (changecolor) { - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) mo->color = actor->target->color; //copy color else if (actor->target->player->ctfteam == 2) mo->color = skincolor_bluering; @@ -6622,7 +6622,7 @@ void A_OldRingExplode(mobj_t *actor) { if (changecolor) { - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) mo->color = actor->target->color; //copy color else if (actor->target->player->ctfteam == 2) mo->color = skincolor_bluering; diff --git a/src/p_inter.c b/src/p_inter.c index 7b5839e03..33a124133 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3224,7 +3224,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) player->mo->flags2 &= ~MF2_DONTDRAW; P_SetPlayerMobjState(player->mo, player->mo->info->deathstate); - if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) + if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) { P_PlayerFlagBurst(player, false); if (source && source->player) @@ -3349,7 +3349,7 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, else S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss. - if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) + if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) { P_PlayerFlagBurst(player, false); if (source && source->player) @@ -3383,7 +3383,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN P_AddPlayerScore(source->player, 50); } - if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) + if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) { P_PlayerFlagBurst(player, false); if (source && source->player) @@ -3442,7 +3442,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) P_DoPlayerPain(player, inflictor, source); - if (gametype == GT_CTF && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)) + if ((gametyperules & GTR_TEAMFLAGS) && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)) P_PlayerFlagBurst(player, false); if (oldnightstime > 10*TICRATE diff --git a/src/p_mobj.c b/src/p_mobj.c index df89fbfde..193746db8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11179,7 +11179,7 @@ void P_RespawnSpecials(void) } //CTF rings should continue to respawn as normal rings outside of CTF. - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) { if (i == MT_REDTEAMRING || i == MT_BLUETEAMRING) i = MT_RING; @@ -11750,7 +11750,7 @@ You should think about modifying the deathmatch starts to take full advantage of } } - if (gametype != GT_CTF) // CTF specific things + if (!(gametyperules & GTR_TEAMFLAGS)) // CTF specific things { if (i == MT_RING_BLUEBOX || i == MT_RING_REDBOX) i = MT_RING_BOX; @@ -13597,9 +13597,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) else if (mthing->type == mobjinfo[MT_COIN].doomednum) ringthing = MT_COIN; else if (mthing->type == mobjinfo[MT_REDTEAMRING].doomednum) // No team rings in non-CTF - ringthing = (gametype == GT_CTF) ? MT_REDTEAMRING : MT_RING; + ringthing = (gametyperules & GTR_TEAMFLAGS) ? MT_REDTEAMRING : MT_RING; else if (mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum) // Ditto - ringthing = (gametype == GT_CTF) ? MT_BLUETEAMRING : MT_RING; + ringthing = (gametyperules & GTR_TEAMFLAGS) ? MT_BLUETEAMRING : MT_RING; } // Set proper height diff --git a/src/p_spec.c b/src/p_spec.c index 4bdb99520..161d73e0e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4713,7 +4713,7 @@ DoneSection2: break; case 3: // Red Team's Base - if (gametype == GT_CTF && P_IsObjectOnGround(player->mo)) + if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo)) { if (player->ctfteam == 1 && (player->gotflag & GF_BLUEFLAG)) { @@ -4746,7 +4746,7 @@ DoneSection2: break; case 4: // Blue Team's Base - if (gametype == GT_CTF && P_IsObjectOnGround(player->mo)) + if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo)) { if (player->ctfteam == 2 && (player->gotflag & GF_REDFLAG)) { @@ -7231,7 +7231,7 @@ void P_SpawnSpecials(INT32 fromnetsave) // Linedef executor triggers for CTF teams. case 309: case 311: - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) lines[i].special = 0; break; diff --git a/src/p_user.c b/src/p_user.c index a8ae383cf..c94f18af1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3110,7 +3110,7 @@ static void P_DoPlayerHeadSigns(player_t *player) } } } - else if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) // If you have the flag (duh). + else if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) // If you have the flag (duh). { // Spawn a got-flag message over the head of the player that // has it (but not on your own screen if you have the flag). @@ -5048,7 +5048,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { if (onground || player->climbing || player->powers[pw_carry]) ; - else if (gametype == GT_CTF && player->gotflag) + else if ((gametyperules & GTR_TEAMFLAGS) && player->gotflag) ; else if (player->pflags & (PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player has used an ability previously ; @@ -5273,7 +5273,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->secondjump = 0; player->pflags &= ~PF_THOKKED; } - else if (player->pflags & PF_SLIDING || (gametype == GT_CTF && player->gotflag)) + else if (player->pflags & PF_SLIDING || ((gametyperules & GTR_TEAMFLAGS) && player->gotflag)) ; /*else if (P_SuperReady(player)) { @@ -5560,7 +5560,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { player->pflags |= PF_JUMPDOWN; - if ((gametype != GT_CTF || !player->gotflag) && !player->exiting) + if ((!(gametyperules & GTR_TEAMFLAGS) || !player->gotflag) && !player->exiting) { if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP) { diff --git a/src/st_stuff.c b/src/st_stuff.c index 6e8c64127..061189f53 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2279,7 +2279,8 @@ static void ST_drawTextHUD(void) { if (stplyr->pflags & PF_TAGIT) { - textHUDdraw(M_GetText("\x82""You are blindfolded!")) + if (gametyperules & GTR_BLINDFOLDED) + textHUDdraw(M_GetText("\x82""You are blindfolded!")) textHUDdraw(M_GetText("Waiting for players to hide...")) } else if (gametype == GT_HIDEANDSEEK) @@ -2294,7 +2295,8 @@ static void ST_drawTextHUD(void) textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) donef12 = true; } - textHUDdraw(M_GetText("You cannot move while hiding.")) + if (gametyperules & GTR_HIDETIMEFROZEN) + textHUDdraw(M_GetText("You cannot move while hiding.")) } } @@ -2316,21 +2318,21 @@ static void ST_drawTeamHUD(void) if (F_GetPromptHideHud(0)) // y base is 0 return; - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) p = bflagico; else p = bmatcico; V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) p = rflagico; else p = rmatcico; V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) goto num; { INT32 i; From 83732f38a9cb8668c0346552e5d28c6fc94b339c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 12:09:44 -0300 Subject: [PATCH 046/312] GTR_PITYSHIELD --- src/doomstat.h | 1 + src/g_game.c | 6 +++--- src/p_user.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 06e114eb1..743d64282 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -432,6 +432,7 @@ enum GameTypeRules GTR_BLINDFOLDED = 1<<11, // Blindfolded view (Tag and Hide and Seek) GTR_EMERALDS = 1<<12, // Ringslinger emeralds (Match and CTF) GTR_TEAMFLAGS = 1<<13, // Gametype has team flags (CTF) + GTR_PITYSHIELD = 1<<14, // Award pity shield }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 1f6bde833..a9474eb4f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3069,9 +3069,9 @@ INT16 gametypedefaultrules[NUMGAMETYPES] = GTR_PLATFORM|GTR_RACE|GTR_CHASECAM, // Match - GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS, + GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD, // Team Match - GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_TIMELIMIT, + GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_PITYSHIELD, // Tag GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, @@ -3079,7 +3079,7 @@ INT16 gametypedefaultrules[NUMGAMETYPES] = GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, // CTF - GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS|GTR_TEAMFLAGS, + GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD, }; // diff --git a/src/p_user.c b/src/p_user.c index c94f18af1..b8164c173 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10539,7 +10539,7 @@ void P_DoPityCheck(player_t *player) { // No pity outside of match or CTF. if (player->spectator - || !(gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF)) + || !(gametyperules & GTR_PITYSHIELD)) return; // Apply pity shield if available. From da4e759a73928ab9ffdc55874914a2e65396e407 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 12:13:24 -0300 Subject: [PATCH 047/312] GTR_DEATHPENALTY --- src/doomstat.h | 1 + src/g_game.c | 2 +- src/p_inter.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 743d64282..3f76e770e 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -433,6 +433,7 @@ enum GameTypeRules GTR_EMERALDS = 1<<12, // Ringslinger emeralds (Match and CTF) GTR_TEAMFLAGS = 1<<13, // Gametype has team flags (CTF) GTR_PITYSHIELD = 1<<14, // Award pity shield + GTR_DEATHPENALTY = 1<<15, // Death score penalty }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index a9474eb4f..cb25dd954 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3069,7 +3069,7 @@ INT16 gametypedefaultrules[NUMGAMETYPES] = GTR_PLATFORM|GTR_RACE|GTR_CHASECAM, // Match - GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY, // Team Match GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_PITYSHIELD, diff --git a/src/p_inter.c b/src/p_inter.c index 33a124133..21c3d4049 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2389,7 +2389,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget { if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording! G_StopMetalRecording(true); - if (gametype == GT_MATCH // note, no team match suicide penalty + if ((gametyperules & GTR_DEATHPENALTY) // note, no team match suicide penalty && ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player))) { // Suicide penalty if (target->player->score >= 50) From 6660d6302896b54e37a5bdd832e869037955eb73 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 12:14:18 -0300 Subject: [PATCH 048/312] There are only so many bits --- src/d_netcmd.c | 2 +- src/doomstat.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0b7e3de18..a806a1052 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -382,7 +382,7 @@ char timedemo_csv_id[256]; boolean timedemo_quit; INT16 gametype = GT_COOP; -INT16 gametyperules = 0; +UINT32 gametyperules = 0; boolean splitscreen = false; boolean circuitmap = false; INT32 adminplayers[MAXPLAYERS]; diff --git a/src/doomstat.h b/src/doomstat.h index 3f76e770e..c51b98c3f 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -84,7 +84,7 @@ extern boolean addedtogame; // true after the server has added you extern boolean multiplayer; extern INT16 gametype; -extern INT16 gametyperules; +extern UINT32 gametyperules; extern boolean splitscreen; extern boolean circuitmap; // Does this level have 'circuit mode'? extern boolean fromlevelselect; From 15862ed02c888feb74cc2cabd64c546cd503df73 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 12:23:42 -0300 Subject: [PATCH 049/312] G_NewGametype --- src/d_netcmd.c | 2 ++ src/doomstat.h | 2 ++ src/g_game.c | 27 +++++++++++++++++++++++++++ src/g_game.h | 2 ++ 4 files changed, 33 insertions(+) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a806a1052..7b8095555 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -383,6 +383,8 @@ boolean timedemo_quit; INT16 gametype = GT_COOP; UINT32 gametyperules = 0; +INT16 numgametypes = (GT_CTF + 1); + boolean splitscreen = false; boolean circuitmap = false; INT32 adminplayers[MAXPLAYERS]; diff --git a/src/doomstat.h b/src/doomstat.h index c51b98c3f..66f7f3008 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -85,6 +85,8 @@ extern boolean multiplayer; extern INT16 gametype; extern UINT32 gametyperules; +extern INT16 numgametypes; + extern boolean splitscreen; extern boolean circuitmap; // Does this level have 'circuit mode'? extern boolean fromlevelselect; diff --git a/src/g_game.c b/src/g_game.c index cb25dd954..e70d4a6d1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3094,6 +3094,33 @@ void G_SetGametype(INT16 gtype) CONS_Printf("Gametype set to %s (%d)\n", Gametype_Names[gametype], gametype); } +// +// G_NewGametype +// +// Create a new gametype. Returns the new gametype number. +// +INT16 G_NewGametype(UINT32 rules) +{ + INT32 i; + INT16 newgtype = numgametypes; + numgametypes++; + + // Set gametype rules. + gametypedefaultrules[newgtype] = numgametypes; + Gametype_Names[newgtype] = "???"; + + // Update gametype_cons_t accordingly. + for (i = 0; i < numgametypes; i++) + { + gametype_cons_t[i].value = i; + gametype_cons_t[i].strvalue = Gametype_Names[i]; + } + gametype_cons_t[NUMGAMETYPES].value = 0; + gametype_cons_t[NUMGAMETYPES].strvalue = NULL; + + return newgtype; +} + // // G_GetGametypeByName // diff --git a/src/g_game.h b/src/g_game.h index a925e14c1..ef3e9ffab 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -202,6 +202,8 @@ void G_StopDemo(void); boolean G_CheckDemoStatus(void); void G_SetGametype(INT16 gametype); +INT16 G_NewGametype(UINT32 rules); + INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); From 86ac94817af5940a351a2546d632c4f37137086a Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 12:28:01 -0300 Subject: [PATCH 050/312] Spectator HUD tweaks --- src/st_stuff.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 061189f53..54bd36ac0 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2203,9 +2203,10 @@ static void ST_drawTextHUD(void) if (G_IsSpecialStage(gamemap)) textHUDdraw(M_GetText("\x82""Wait for the stage to end...")) - else if (gametype == GT_COOP) + else if (G_PlatformGametype()) { - if (stplyr->lives <= 0 + if (gametype == GT_COOP + && stplyr->lives <= 0 && cv_cooplives.value == 2 && (netgame || multiplayer)) { @@ -2230,7 +2231,7 @@ static void ST_drawTextHUD(void) else textHUDdraw(M_GetText("Wait to respawn...")) } - else + else if (G_GametypeHasSpectators()) textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) } From 78074246335834088fc14a3f80ad133f095a1476 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 12:30:01 -0300 Subject: [PATCH 051/312] NUMGAMETYPES vs gametypecount --- src/d_clisrv.c | 2 +- src/d_main.c | 2 +- src/d_netcmd.c | 14 +++++++------- src/doomstat.h | 2 +- src/g_game.c | 8 ++++---- src/hu_stuff.c | 2 +- src/m_menu.c | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index bfc478bd5..4468502d0 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2114,7 +2114,7 @@ static void CL_ConnectToServer(boolean viams) UINT8 num = serverlist[i].info.gametype; const char *gametypestr = NULL; CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); - if (num < NUMGAMETYPES) + if (num < gametypecount) gametypestr = Gametype_Names[num]; if (gametypestr) CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); diff --git a/src/d_main.c b/src/d_main.c index 815136440..50da0a629 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1409,7 +1409,7 @@ void D_SRB2Main(void) if (newgametype == -1) // reached end of the list with no match { j = atoi(sgametype); // assume they gave us a gametype number, which is okay too - if (j >= 0 && j < NUMGAMETYPES) + if (j >= 0 && j < gametypecount) newgametype = (INT16)j; } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7b8095555..e0cc32914 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -383,7 +383,7 @@ boolean timedemo_quit; INT16 gametype = GT_COOP; UINT32 gametyperules = 0; -INT16 numgametypes = (GT_CTF + 1); +INT16 gametypecount = (GT_CTF + 1); boolean splitscreen = false; boolean circuitmap = false; @@ -1943,7 +1943,7 @@ static void Command_Map_f(void) if (isdigit(gametypename[0])) { d = atoi(gametypename); - if (d >= 0 && d < NUMGAMETYPES) + if (d >= 0 && d < gametypecount) newgametype = d; else { @@ -1951,7 +1951,7 @@ static void Command_Map_f(void) "Gametype number %d is out of range. Use a number between" " 0 and %d inclusive. ...Or just use the name. :v\n", d, - NUMGAMETYPES-1); + gametypecount-1); Z_Free(realmapname); Z_Free(mapname); return; @@ -2072,7 +2072,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) gametype = READUINT8(*cp); G_SetGametype(gametype); // I fear putting that macro as an argument - if (gametype < 0 || gametype >= NUMGAMETYPES) + if (gametype < 0 || gametype >= gametypecount) gametype = lastgametype; else if (gametype != lastgametype) D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype @@ -3624,7 +3624,7 @@ static void Command_ShowGametype_f(void) } // get name string for current gametype - if (gametype >= 0 && gametype < NUMGAMETYPES) + if (gametype >= 0 && gametype < gametypecount) gametypestr = Gametype_Names[gametype]; if (gametypestr) @@ -3891,9 +3891,9 @@ void D_GameTypeChanged(INT32 lastgametype) { const char *oldgt = NULL, *newgt = NULL; - if (lastgametype >= 0 && lastgametype < NUMGAMETYPES) + if (lastgametype >= 0 && lastgametype < gametypecount) oldgt = Gametype_Names[lastgametype]; - if (gametype >= 0 && lastgametype < NUMGAMETYPES) + if (gametype >= 0 && lastgametype < gametypecount) newgt = Gametype_Names[gametype]; if (oldgt && newgt) diff --git a/src/doomstat.h b/src/doomstat.h index 66f7f3008..f51f75fb8 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -85,7 +85,7 @@ extern boolean multiplayer; extern INT16 gametype; extern UINT32 gametyperules; -extern INT16 numgametypes; +extern INT16 gametypecount; extern boolean splitscreen; extern boolean circuitmap; // Does this level have 'circuit mode'? diff --git a/src/g_game.c b/src/g_game.c index e70d4a6d1..619950882 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3102,15 +3102,15 @@ void G_SetGametype(INT16 gtype) INT16 G_NewGametype(UINT32 rules) { INT32 i; - INT16 newgtype = numgametypes; - numgametypes++; + INT16 newgtype = gametypecount; + gametypecount++; // Set gametype rules. - gametypedefaultrules[newgtype] = numgametypes; + gametypedefaultrules[newgtype] = gametypecount; Gametype_Names[newgtype] = "???"; // Update gametype_cons_t accordingly. - for (i = 0; i < numgametypes; i++) + for (i = 0; i < gametypecount; i++) { gametype_cons_t[i].value = i; gametype_cons_t[i].strvalue = Gametype_Names[i]; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index e67249953..1e9b4f14a 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2066,7 +2066,7 @@ static void HU_drawGametype(void) { const char *strvalue = NULL; - if (gametype < 0 || gametype >= NUMGAMETYPES) + if (gametype < 0 || gametype >= gametypecount) return; // not a valid gametype??? strvalue = Gametype_Names[gametype]; diff --git a/src/m_menu.c b/src/m_menu.c index 23dc10701..c257adfd6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9932,7 +9932,7 @@ static void M_DrawConnectMenu(void) va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time))); gt = "Unknown"; - if (serverlist[slindex].info.gametype < NUMGAMETYPES) + if (serverlist[slindex].info.gametype < gametypecount) gt = Gametype_Names[serverlist[slindex].info.gametype]; V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags, From aa619e1b34c6d0481096c4e98e980f5662f27421 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 12:36:02 -0300 Subject: [PATCH 052/312] Rankings tweaks --- src/d_clisrv.c | 2 +- src/hu_stuff.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 4468502d0..d1dee3985 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2111,7 +2111,7 @@ static void CL_ConnectToServer(boolean viams) if (i != -1) { - UINT8 num = serverlist[i].info.gametype; + UINT16 num = serverlist[i].info.gametype; const char *gametypestr = NULL; CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); if (num < gametypecount) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 1e9b4f14a..8cbfa77d3 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -3026,7 +3026,7 @@ static void HU_DrawRankings(void) // draw the current gametype in the lower right HU_drawGametype(); - if (gametype != GT_RACE && gametype != GT_COMPETITION && gametype != GT_COOP) + if (!G_PlatformGametype()) { if (cv_timelimit.value && timelimitintics > 0) { @@ -3083,7 +3083,7 @@ static void HU_DrawRankings(void) if (!playeringame[j]) continue; - if (gametype != GT_COOP && players[j].spectator) + if (!G_PlatformGametype() && players[j].spectator) continue; for (i = 0; i < MAXPLAYERS; i++) @@ -3091,7 +3091,7 @@ static void HU_DrawRankings(void) if (!playeringame[i]) continue; - if (gametype != GT_COOP && players[i].spectator) + if (!G_PlatformGametype() && players[i].spectator) continue; if (gametype == GT_RACE) From 45580ce5576acc7b59e8b67008483e52bb41b050 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 12:36:54 -0300 Subject: [PATCH 053/312] Make NUMGAMETYPEFREESLOTS lower because netcode --- src/doomstat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doomstat.h b/src/doomstat.h index f51f75fb8..4d17b5c79 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -389,7 +389,7 @@ enum TypeOfLevel }; // Gametypes -#define NUMGAMETYPEFREESLOTS 512 +#define NUMGAMETYPEFREESLOTS 128 enum GameType { GT_COOP = 0, // also used in single player From b759ebf62292a2833df742562aea78d66c5fc6b8 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 12:40:46 -0300 Subject: [PATCH 054/312] Death of TOL_CUSTOM --- src/dehacked.c | 3 --- src/doomstat.h | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 175c1fcfa..5cfe953b8 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1114,8 +1114,6 @@ static const struct { {"TAG",TOL_TAG}, {"CTF",TOL_CTF}, - {"CUSTOM",TOL_CUSTOM}, - {"2D",TOL_2D}, {"MARIO",TOL_MARIO}, {"NIGHTS",TOL_NIGHTS}, @@ -9042,7 +9040,6 @@ struct { {"TOL_MATCH",TOL_MATCH}, {"TOL_TAG",TOL_TAG}, {"TOL_CTF",TOL_CTF}, - {"TOL_CUSTOM",TOL_CUSTOM}, {"TOL_2D",TOL_2D}, {"TOL_MARIO",TOL_MARIO}, {"TOL_NIGHTS",TOL_NIGHTS}, diff --git a/src/doomstat.h b/src/doomstat.h index 4d17b5c79..5bc64ae7e 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -287,7 +287,7 @@ typedef struct char lvlttl[22]; ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway) char subttl[33]; ///< Subtitle for level UINT8 actnum; ///< Act number or 0 for none. - UINT16 typeoflevel; ///< Combination of typeoflevel flags. + UINT32 typeoflevel; ///< Combination of typeoflevel flags. INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. char musname[7]; ///< Music track to play. "" for no music. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. @@ -379,7 +379,7 @@ enum TypeOfLevel TOL_CTF = 0x40, ///< Capture the Flag // CTF default = 64 - TOL_CUSTOM = 0x80, ///< Custom (Lua-scripted, etc.) + //TOL_CUSTOM = 0x80, ///< Custom (Lua-scripted, etc.) TOL_2D = 0x0100, ///< 2D TOL_MARIO = 0x0200, ///< Mario From 79d5192b7c8de8d8afe27b431e714d9f76020e3f Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 13:24:10 -0300 Subject: [PATCH 055/312] TOL/Level platter stuff --- src/dehacked.c | 6 ++--- src/doomstat.h | 61 +++++++++++++++++++++++++++-------------------- src/g_game.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++---- src/g_game.h | 7 +++++- src/m_menu.c | 5 +++- src/m_menu.h | 1 + 6 files changed, 109 insertions(+), 35 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 5cfe953b8..3f018bee8 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1095,10 +1095,8 @@ static void readsprite2(MYFILE *f, INT32 num) Z_Free(s); } -static const struct { - const char *name; - const UINT16 flag; -} TYPEOFLEVEL[] = { +INT32 numtolinfo = NUMBASETOL; +tolinfo_t TYPEOFLEVEL[NUMMAXTOL] = { {"SOLO",TOL_SP}, {"SP",TOL_SP}, {"SINGLEPLAYER",TOL_SP}, diff --git a/src/doomstat.h b/src/doomstat.h index 5bc64ae7e..f143151af 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -39,7 +39,7 @@ extern UINT32 mapmusposition; #define MUSIC_FORCERESET 0x4000 // -*-------------- // Use other bits if necessary. -extern INT16 maptol; +extern UINT32 maptol; extern UINT8 globalweather; extern INT32 curWeather; extern INT32 cursaveslot; @@ -364,30 +364,6 @@ typedef struct extern mapheader_t* mapheaderinfo[NUMMAPS]; -enum TypeOfLevel -{ - TOL_SP = 0x01, ///< Single Player - TOL_COOP = 0x02, ///< Cooperative - TOL_COMPETITION = 0x04, ///< Competition - TOL_RACE = 0x08, ///< Race -// Single Player default = 15 - - TOL_MATCH = 0x10, ///< Match - TOL_TAG = 0x20, ///< Tag -// Match/Tag default = 48 - - TOL_CTF = 0x40, ///< Capture the Flag -// CTF default = 64 - - //TOL_CUSTOM = 0x80, ///< Custom (Lua-scripted, etc.) - - TOL_2D = 0x0100, ///< 2D - TOL_MARIO = 0x0200, ///< Mario - TOL_NIGHTS = 0x0400, ///< NiGHTS - TOL_ERZ3 = 0x0800, ///< ERZ3 - TOL_XMAS = 0x1000 ///< Christmas NiGHTS -}; - // Gametypes #define NUMGAMETYPEFREESLOTS 128 enum GameType @@ -441,6 +417,41 @@ enum GameTypeRules // String names for gametypes extern const char *Gametype_Names[NUMGAMETYPES]; +enum TypeOfLevel +{ + TOL_SP = 0x01, ///< Single Player + TOL_COOP = 0x02, ///< Cooperative + TOL_COMPETITION = 0x04, ///< Competition + TOL_RACE = 0x08, ///< Race +// Single Player default = 15 + + TOL_MATCH = 0x10, ///< Match + TOL_TAG = 0x20, ///< Tag +// Match/Tag default = 48 + + TOL_CTF = 0x40, ///< Capture the Flag +// CTF default = 64 + + // 0x80 was here + + TOL_2D = 0x0100, ///< 2D + TOL_MARIO = 0x0200, ///< Mario + TOL_NIGHTS = 0x0400, ///< NiGHTS + TOL_ERZ3 = 0x0800, ///< ERZ3 + TOL_XMAS = 0x1000, ///< Christmas NiGHTS +}; + +#define NUMBASETOL 18 +#define NUMMAXTOL (18 + NUMGAMETYPEFREESLOTS) + +typedef struct +{ + const char *name; + UINT32 flag; +} tolinfo_t; +extern tolinfo_t TYPEOFLEVEL[NUMMAXTOL]; +extern INT32 numtolinfo; + extern tic_t totalplaytime; extern UINT8 stagefailed; diff --git a/src/g_game.c b/src/g_game.c index 619950882..d66a7454f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -79,7 +79,7 @@ UINT16 mapmusflags; // Track and reset bit UINT32 mapmusposition; // Position to jump to INT16 gamemap = 1; -INT16 maptol; +UINT32 maptol; UINT8 globalweather = 0; INT32 curWeather = PRECIP_NONE; INT32 cursaveslot = 0; // Auto-save 1p savegame slot @@ -3095,11 +3095,11 @@ void G_SetGametype(INT16 gtype) } // -// G_NewGametype +// G_AddGametype // -// Create a new gametype. Returns the new gametype number. +// Add a gametype. Returns the new gametype number. // -INT16 G_NewGametype(UINT32 rules) +INT16 G_AddGametype(UINT32 rules) { INT32 i; INT16 newgtype = gametypecount; @@ -3121,6 +3121,59 @@ INT16 G_NewGametype(UINT32 rules) return newgtype; } +// +// G_SetGametypeDescription +// +// Set a description for the specified gametype. +// (Level platter) +// +void G_SetGametypeDescription(INT16 gtype, const char *description, UINT8 leftcolor, UINT8 rightcolor) +{ + strncpy(gametypedesc[gtype].notes, description, 441); + gametypedesc[gtype].col[0] = leftcolor; + gametypedesc[gtype].col[1] = rightcolor; +} + +UINT32 gametypetol[NUMGAMETYPES] = +{ + TOL_COOP, // Co-op + TOL_COMPETITION, // Competition + TOL_RACE, // Race + + TOL_MATCH, // Match + TOL_MATCH, // Team Match + + TOL_TAG, // Tag + TOL_TAG, // Hide and Seek + + TOL_CTF, // CTF +}; + +// +// G_AddTOL +// +// Adds a type of level. +// +void G_AddTOL(UINT32 newtol, const char *tolname) +{ + TYPEOFLEVEL[numtolinfo].name = tolname; + TYPEOFLEVEL[numtolinfo].flag = newtol; + numtolinfo++; + + TYPEOFLEVEL[numtolinfo].name = NULL; + TYPEOFLEVEL[numtolinfo].flag = 0; +} + +// +// G_AddTOL +// +// Assigns a type of level to a gametype. +// +void G_AddGametypeTOL(INT16 gametype, UINT32 newtol) +{ + gametypetol[gametype] = newtol; +} + // // G_GetGametypeByName // @@ -3240,6 +3293,8 @@ boolean G_TagGametype(void) INT16 G_TOLFlag(INT32 pgametype) { if (!multiplayer) return TOL_SP; + return gametypetol[pgametype]; +#if 0 if (pgametype == GT_COOP) return TOL_COOP; if (pgametype == GT_COMPETITION) return TOL_COMPETITION; if (pgametype == GT_RACE) return TOL_RACE; @@ -3251,6 +3306,7 @@ INT16 G_TOLFlag(INT32 pgametype) CONS_Alert(CONS_ERROR, M_GetText("Unknown gametype! %d\n"), pgametype); return INT16_MAX; +#endif } /** Select a random map with the given typeoflevel flags. diff --git a/src/g_game.h b/src/g_game.h index ef3e9ffab..fa2ba95fb 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -201,8 +201,13 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill); void G_StopDemo(void); boolean G_CheckDemoStatus(void); +extern INT16 gametypedefaultrules[NUMGAMETYPES]; +extern UINT32 gametypetol[NUMGAMETYPES]; + void G_SetGametype(INT16 gametype); -INT16 G_NewGametype(UINT32 rules); +INT16 G_AddGametype(UINT32 rules); +void G_AddTOL(UINT32 newtol, const char *tolname); +void G_AddGametypeTOL(INT16 gametype, UINT32 newtol); INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); diff --git a/src/m_menu.c b/src/m_menu.c index c257adfd6..6699ed924 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -605,7 +605,7 @@ static menuitem_t MISC_ChangeTeamMenu[] = {IT_WHITESTRING|IT_CALL, NULL, "Confirm", M_ConfirmTeamChange, 90}, }; -static const gtdesc_t gametypedesc[] = +gtdesc_t gametypedesc[NUMGAMETYPES] = { {{ 54, 54}, "Play through the single-player campaign with your friends, teaming up to beat Dr Eggman's nefarious challenges!"}, {{103, 103}, "Speed your way through the main acts, competing in several different categories to see who's the best."}, @@ -4684,6 +4684,9 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) return true; + if (gt > 0 && gt < gametypecount && (mapheaderinfo[mapnum]->typeoflevel & gametypetol[gt])) + return true; + return false; case LLM_LEVELSELECT: diff --git a/src/m_menu.h b/src/m_menu.h index ce9b422dc..19858e2fc 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -371,6 +371,7 @@ typedef struct UINT8 col[2]; char notes[441]; } gtdesc_t; +extern gtdesc_t gametypedesc[NUMGAMETYPES]; // mode descriptions for video mode menu typedef struct From 1e2331d672f7ca349efe9624a7b9e37526eeeb22 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 14:37:48 -0300 Subject: [PATCH 056/312] SOC stuff --- src/dehacked.c | 246 ++++++++++++++++++++++++++++++++++++++++++++++++- src/doomstat.h | 1 + src/g_game.c | 34 ++++++- src/g_game.h | 2 + 4 files changed, 278 insertions(+), 5 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 3f018bee8..5ade1b2bd 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -76,6 +76,7 @@ static UINT16 get_mus(const char *word, UINT8 dehacked_mode); static hudnum_t get_huditem(const char *word); static menutype_t get_menutype(const char *word); #ifndef HAVE_BLUA +static INT16 get_gametype(const char *word); static powertype_t get_power(const char *word); #endif @@ -1124,6 +1125,145 @@ tolinfo_t TYPEOFLEVEL[NUMMAXTOL] = { {NULL, 0} }; +// copypasted from readPlayer :sleep: +static void readgametype(MYFILE *f, char *gtname) +{ + char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + char *word; + char *word2; + char *tmp; + INT32 i; + + INT16 newgtidx = 0; + UINT32 newgtrules = 0; + UINT32 newgttol = 0; + UINT8 newgtleftcolor = 0; + UINT8 newgtrightcolor = 0; + char gtdescription[441]; + const char *gtnamestring; + + do + { + if (myfgets(s, MAXLINELEN, f)) + { + if (s[0] == '\n') + break; + + word = strtok(s, " "); + if (word) + strupr(word); + else + break; + + if (fastcmp(word, "DESCRIPTION")) + { + char *descr = NULL; + + for (i = 0; i < MAXLINELEN-3; i++) + { + if (s[i] == '=') + { + descr = &s[i+2]; + break; + } + } + if (descr) + { + strcpy(gtdescription, descr); + strcat(gtdescription, myhashfgets(descr, sizeof (gtdescription), f)); + } + else + strcpy(gtdescription, ""); + + // For some reason, cutting the string did not work above. Most likely due to strcpy or strcat... + // It works down here, though. + { + INT32 numline = 0; + for (i = 0; i < MAXLINELEN-1; i++) + { + if (numline < 20 && gtdescription[i] == '\n') + numline++; + + if (numline >= 20 || gtdescription[i] == '\0' || gtdescription[i] == '#') + break; + } + } + gtdescription[strlen(gtdescription)-1] = '\0'; + gtdescription[i] = '\0'; + continue; + } + + word2 = strtok(NULL, " = "); + if (word2) + strupr(word2); + else + break; + + if (word2[strlen(word2)-1] == '\n') + word2[strlen(word2)-1] = '\0'; + i = atoi(word2); + + if (fastcmp(word, "RULES")) + { + // Game type rules (GTR_) + newgtrules = (UINT32)get_number(word2); + } + else if (fastcmp(word, "HEADERCOLOR") || fastcmp(word, "HEADERCOLOUR")) + { + // Level platter + newgtleftcolor = newgtrightcolor = (UINT8)get_number(word2); + } + else if (fastcmp(word, "HEADERLEFTCOLOR") || fastcmp(word, "HEADERLEFTCOLOUR")) + { + // Level platter + newgtleftcolor = (UINT8)get_number(word2); + } + else if (fastcmp(word, "HEADERRIGHTCOLOR") || fastcmp(word, "HEADERRIGHTCOLOUR")) + { + // Level platter + newgtrightcolor = (UINT8)get_number(word2); + } + else if (fastcmp(word, "TYPEOFLEVEL")) + { + if (i) // it's just a number + newgttol = (UINT16)i; + else + { + UINT16 tol = 0; + tmp = strtok(word2,","); + do { + for (i = 0; TYPEOFLEVEL[i].name; i++) + if (fastcmp(tmp, TYPEOFLEVEL[i].name)) + break; + if (!TYPEOFLEVEL[i].name) + deh_warning("readgametype %s: unknown typeoflevel flag %s\n", gtname, tmp); + tol |= TYPEOFLEVEL[i].flag; + } while((tmp = strtok(NULL,",")) != NULL); + newgttol = tol; + } + } + else + deh_warning("readgametype %s: unknown word '%s'", gtname, word); + } + } while (!myfeof(f)); // finish when the line is empty + Z_Free(s); + + // Add the new gametype + newgtidx = G_AddGametype(newgtrules); + G_AddGametypeTOL(newgtidx, newgttol); + G_SetGametypeDescription(newgtidx, gtdescription, newgtleftcolor, newgtrightcolor); + + // Write the new gametype name. + gtnamestring = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + memcpy((void *)gtnamestring, gtname, MAXLINELEN); + Gametype_Names[newgtidx] = gtnamestring; + + // Update gametype_cons_t accordingly. + G_UpdateGametypeSelections(); + + CONS_Printf("Added gametype %s\n", Gametype_Names[newgtidx]); +} + static const struct { const char *name; const mobjtype_t type; @@ -4151,6 +4291,7 @@ static void ignorelines(MYFILE *f) static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + char textline[MAXLINELEN]; char *word; char *word2; INT32 i; @@ -4171,6 +4312,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) char *traverse; myfgets(s, MAXLINELEN, f); + memcpy(textline, s, MAXLINELEN); if (s[0] == '\n' || s[0] == '#') continue; @@ -4359,6 +4501,36 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) ignorelines(f); } } + else if (fastcmp(word, "GAMETYPE")) + { + // Get the gametype name from textline + // instead of word2, so that gametype names + // aren't allcaps + INT32 i; + for (i = 0; i < MAXLINELEN; i++) + { + if (textline[i] == '\0') + break; + if (textline[i] == ' ') + { + char *gtname = (textline+i+1); + if (gtname) + { + // remove funny characters + INT32 j; + for (j = 0; j < (MAXLINELEN - i); j++) + { + if (gtname[j] == '\0') + break; + if (gtname[j] < 32 || gtname[j] > 127) + gtname[j] = '\0'; + } + readgametype(f, gtname); + } + break; + } + } + } else if (fastcmp(word, "CUTSCENE")) { if (i > 0 && i < 129) @@ -8615,6 +8787,26 @@ static const char *const PLAYERFLAG_LIST[] = { NULL // stop loop here. }; +static const char *const GAMETYPERULE_LIST[] = { + "PLATFORM", + "TAG", + "RINGSLINGER", + "SPECTATORS", + "TEAMS", + "LIVES", + "RACE", + "CHASECAM", + "TIMELIMIT", + "HIDETIME", + "HIDETIMEFROZEN", + "BLINDFOLDED", + "EMERALDS", + "TEAMFLAGS", + "PITYSHIELD", + "DEATHPENALTY", + NULL +}; + #ifdef HAVE_BLUA // Linedef flags static const char *const ML_LIST[16] = { @@ -9227,6 +9419,7 @@ struct { {"DMG_DEATHMASK",DMG_DEATHMASK}, // Gametypes, for use with global var "gametype" + // Left them here just in case?? {"GT_COOP",GT_COOP}, {"GT_COMPETITION",GT_COMPETITION}, {"GT_RACE",GT_RACE}, @@ -9679,6 +9872,20 @@ static menutype_t get_menutype(const char *word) } #ifndef HAVE_BLUA +static INT16 get_gametype(const char *word) +{ // Returns the value of GT_ enumerations + INT16 i; + if (*word >= '0' && *word <= '9') + return atoi(word); + if (fastncmp("GT_",word,3)) + word += 3; // take off the GT_ + for (i = 0; i < NUMGAMETYPES; i++) + if (fastcmp(word, Gametype_ConstantNames[i]+3)) + return i; + deh_warning("Couldn't find gametype named 'GT_%s'",word); + return GT_COOP; +} + static powertype_t get_power(const char *word) { // Returns the vlaue of pw_ enumerations powertype_t i; @@ -9842,6 +10049,19 @@ static fixed_t find_const(const char **rword) free(word); return 0; } + else if (fastncmp("GTR_", word, 4)) { + char *p = word+4; + for (i = 0; GAMETYPERULE_LIST[i]; i++) + if (fastcmp(p, GAMETYPERULE_LIST[i])) { + free(word); + return (1< Date: Wed, 18 Dec 2019 14:47:39 -0300 Subject: [PATCH 057/312] GTR_NOSPECTATORSPAWN --- src/d_netcmd.c | 7 ++++++- src/dehacked.c | 1 + src/doomstat.h | 41 ++++++++++++++++++++--------------------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index e0cc32914..959ed875f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3636,7 +3636,11 @@ static void Command_ShowGametype_f(void) static void Command_SetGametype_f(void) { if (COM_Argc() > 1) + { + INT16 oldgametype = gametype; G_SetGametype(atoi(COM_Argv(1))); + D_GameTypeChanged(oldgametype); + } } /** Plays the intro. @@ -3978,6 +3982,7 @@ void D_GameTypeChanged(INT32 lastgametype) // When swapping to a gametype that supports spectators, // make everyone a spectator initially. + // Averted with GTR_NOSPECTATORSPAWN. if (!splitscreen && (G_GametypeHasSpectators())) { INT32 i; @@ -3985,7 +3990,7 @@ void D_GameTypeChanged(INT32 lastgametype) if (playeringame[i]) { players[i].ctfteam = 0; - players[i].spectator = true; + players[i].spectator = (gametyperules & GTR_NOSPECTATORSPAWN) ? false : true; } } diff --git a/src/dehacked.c b/src/dehacked.c index 5ade1b2bd..b316fb40e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8804,6 +8804,7 @@ static const char *const GAMETYPERULE_LIST[] = { "TEAMFLAGS", "PITYSHIELD", "DEATHPENALTY", + "NOSPECTATORSPAWN", NULL }; diff --git a/src/doomstat.h b/src/doomstat.h index 1d6d85017..7d6839e52 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -389,29 +389,28 @@ enum GameType // Game type rules enum GameTypeRules { - GTR_PLATFORM = 1, // Co-op, Competition, and Race - GTR_TAG = 1<<1, // Tag and Hide and Seek - GTR_RINGSLINGER = 1<<2, // Not Co-op, not Competition, and not Race (overriden by cv_ringslinger) - GTR_SPECTATORS = 1<<3, // Not Co-op, not Competition, and not Race - GTR_TEAMS = 1<<4, // Team Match, CTF - GTR_LIVES = 1<<5, // A lot of special cases in G_GametypeUsesLives actually, but just Co-op and Competition - GTR_RACE = 1<<6, // Race and Competition + GTR_PLATFORM = 1, // Co-op, Competition, and Race + GTR_TAG = 1<<1, // Tag and Hide and Seek + GTR_RINGSLINGER = 1<<2, // Not Co-op, not Competition, and not Race (overriden by cv_ringslinger) + GTR_SPECTATORS = 1<<3, // Not Co-op, not Competition, and not Race + GTR_TEAMS = 1<<4, // Team Match, CTF + GTR_LIVES = 1<<5, // A lot of special cases in G_GametypeUsesLives actually, but just Co-op and Competition + GTR_RACE = 1<<6, // Race and Competition // Lactozilla - // Awesome! Those are new game type rules - // provided by yours truly to allow for more - // flexibility! Those will replace some - // straight-up gametype checks scattered - // around the source code! - GTR_CHASECAM = 1<<7, // Prefer chasecam at map load (All platform gametypes) - GTR_TIMELIMIT = 1<<8, // Ringslinger time limit (Tag and Hide and Seek) - GTR_HIDETIME = 1<<9, // Tag and Hide and Seek - GTR_HIDETIMEFROZEN = 1<<10, // Hide and Seek, but not Tag - GTR_BLINDFOLDED = 1<<11, // Blindfolded view (Tag and Hide and Seek) - GTR_EMERALDS = 1<<12, // Ringslinger emeralds (Match and CTF) - GTR_TEAMFLAGS = 1<<13, // Gametype has team flags (CTF) - GTR_PITYSHIELD = 1<<14, // Award pity shield - GTR_DEATHPENALTY = 1<<15, // Death score penalty + // Awesome! Those are new game type rules provided by yours truly to allow for more + // flexibility! Those will replace some straight-up gametype checks scattered around the source code! + + GTR_CHASECAM = 1<<7, // Prefer chasecam at map load (All platform gametypes) + GTR_TIMELIMIT = 1<<8, // Ringslinger time limit (Tag and Hide and Seek) + GTR_HIDETIME = 1<<9, // Tag and Hide and Seek + GTR_HIDETIMEFROZEN = 1<<10, // Hide and Seek, but not Tag + GTR_BLINDFOLDED = 1<<11, // Blindfolded view (Tag and Hide and Seek) + GTR_EMERALDS = 1<<12, // Ringslinger emeralds (Match and CTF) + GTR_TEAMFLAGS = 1<<13, // Gametype has team flags (CTF) + GTR_PITYSHIELD = 1<<14, // Award pity shield + GTR_DEATHPENALTY = 1<<15, // Death score penalty + GTR_NOSPECTATORSPAWN = 1<<16, // For use with GTR_SPECTATORS - spawn in the map instead of with the spectators }; // String names for gametypes From d3d91726f54184969a69463b8fedf70417224af5 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 14:57:42 -0300 Subject: [PATCH 058/312] GTR_EMERALDHUNT and GTR_SPAWNENEMIES --- src/dehacked.c | 2 ++ src/doomstat.h | 2 ++ src/g_game.c | 9 ++++----- src/g_game.h | 2 +- src/p_mobj.c | 4 ++-- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index b316fb40e..7e584cbf8 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8805,6 +8805,8 @@ static const char *const GAMETYPERULE_LIST[] = { "PITYSHIELD", "DEATHPENALTY", "NOSPECTATORSPAWN", + "EMERALDHUNT", + "SPAWNENEMIES", NULL }; diff --git a/src/doomstat.h b/src/doomstat.h index 7d6839e52..a1c347b62 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -411,6 +411,8 @@ enum GameTypeRules GTR_PITYSHIELD = 1<<14, // Award pity shield GTR_DEATHPENALTY = 1<<15, // Death score penalty GTR_NOSPECTATORSPAWN = 1<<16, // For use with GTR_SPECTATORS - spawn in the map instead of with the spectators + GTR_EMERALDHUNT = 1<<17, // Emerald Hunt + GTR_SPAWNENEMIES = 1<<18, // Spawn enemies }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 07a6034bb..1974c271f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3075,14 +3075,14 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = }; // Game type rules -INT16 gametypedefaultrules[NUMGAMETYPES] = +UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Co-op - GTR_PLATFORM|GTR_LIVES|GTR_CHASECAM, + GTR_PLATFORM|GTR_LIVES|GTR_CHASECAM|GTR_EMERALDHUNT|GTR_SPAWNENEMIES, // Competition - GTR_PLATFORM|GTR_LIVES|GTR_RACE|GTR_CHASECAM, + GTR_PLATFORM|GTR_LIVES|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES, // Race - GTR_PLATFORM|GTR_RACE|GTR_CHASECAM, + GTR_PLATFORM|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES, // Match GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY, @@ -3116,7 +3116,6 @@ void G_SetGametype(INT16 gtype) // INT16 G_AddGametype(UINT32 rules) { - INT32 i; INT16 newgtype = gametypecount; gametypecount++; diff --git a/src/g_game.h b/src/g_game.h index e2eea52c1..81998b6e6 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -201,7 +201,7 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill); void G_StopDemo(void); boolean G_CheckDemoStatus(void); -extern INT16 gametypedefaultrules[NUMGAMETYPES]; +extern UINT32 gametypedefaultrules[NUMGAMETYPES]; extern UINT32 gametypetol[NUMGAMETYPES]; void G_SetGametype(INT16 gametype); diff --git a/src/p_mobj.c b/src/p_mobj.c index 193746db8..1913ef91f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11682,7 +11682,7 @@ You should think about modifying the deathmatch starts to take full advantage of if (i == MT_EMERHUNT) { // Emerald Hunt is Coop only. - if (gametype != GT_COOP) + if (!(gametyperules & GTR_EMERALDHUNT)) return; ss = R_PointInSubsector(mthing->x << FRACBITS, mthing->y << FRACBITS); @@ -11708,7 +11708,7 @@ You should think about modifying the deathmatch starts to take full advantage of runemeraldmanager = true; } - if (!G_PlatformGametype()) // No enemies in match or CTF modes + if (!(gametyperules & GTR_SPAWNENEMIES)) // No enemies in match or CTF modes if ((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS)) return; From 7768e2c7f9ff46fcd82bf7bbd3e270fec34b29d2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 15:14:24 -0300 Subject: [PATCH 059/312] More spectator tweaks --- src/p_mobj.c | 6 +++++- src/st_stuff.c | 36 +++++++++++++++++++----------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1913ef91f..12409a18a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11249,8 +11249,12 @@ void P_SpawnPlayer(INT32 playernum) else { p->outofcoop = false; + p->spectator = false; if (netgame && p->jointime < 1) - p->spectator = true; + { + // Averted by GTR_NOSPECTATORSPAWN. + p->spectator = (gametyperules & GTR_NOSPECTATORSPAWN) ? false : true; + } else if (multiplayer && !netgame) { // If you're in a team game and you don't have a team assigned yet... diff --git a/src/st_stuff.c b/src/st_stuff.c index 54bd36ac0..1c9b4614e 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2205,31 +2205,33 @@ static void ST_drawTextHUD(void) textHUDdraw(M_GetText("\x82""Wait for the stage to end...")) else if (G_PlatformGametype()) { - if (gametype == GT_COOP - && stplyr->lives <= 0 - && cv_cooplives.value == 2 - && (netgame || multiplayer)) + if (gametype == GT_COOP) { - INT32 i; - for (i = 0; i < MAXPLAYERS; i++) + if (stplyr->lives <= 0 + && cv_cooplives.value == 2 + && (netgame || multiplayer)) { - if (!playeringame[i]) - continue; + INT32 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; - if (&players[i] == stplyr) - continue; + if (&players[i] == stplyr) + continue; - if (players[i].lives > 1) - break; - } + if (players[i].lives > 1) + break; + } - if (i != MAXPLAYERS) - textHUDdraw(M_GetText("You'll steal a life on respawn...")) + if (i != MAXPLAYERS) + textHUDdraw(M_GetText("You'll steal a life on respawn...")) + else + textHUDdraw(M_GetText("Wait to respawn...")) + } else textHUDdraw(M_GetText("Wait to respawn...")) } - else - textHUDdraw(M_GetText("Wait to respawn...")) } else if (G_GametypeHasSpectators()) textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) From 7c3cde4564c84475514689d0998e75d8e08db12e Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 15:23:41 -0300 Subject: [PATCH 060/312] How did I mess this up? --- src/g_game.c | 2 +- src/p_mobj.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 1974c271f..fe4c93de9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3120,7 +3120,7 @@ INT16 G_AddGametype(UINT32 rules) gametypecount++; // Set gametype rules. - gametypedefaultrules[newgtype] = gametypecount; + gametypedefaultrules[newgtype] = rules; Gametype_Names[newgtype] = "???"; // Update gametype_cons_t accordingly. diff --git a/src/p_mobj.c b/src/p_mobj.c index 12409a18a..8c5497e26 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11249,7 +11249,6 @@ void P_SpawnPlayer(INT32 playernum) else { p->outofcoop = false; - p->spectator = false; if (netgame && p->jointime < 1) { // Averted by GTR_NOSPECTATORSPAWN. From 94f2b8f9709d1e15fc4a6edb60c78c14a196d8b2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 15:41:03 -0300 Subject: [PATCH 061/312] Fix warnings --- src/dehacked.c | 19 ++++++++----------- src/g_game.c | 10 +++++----- src/g_game.h | 6 +++--- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 7e584cbf8..b62f0cfbe 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1140,7 +1140,6 @@ static void readgametype(MYFILE *f, char *gtname) UINT8 newgtleftcolor = 0; UINT8 newgtrightcolor = 0; char gtdescription[441]; - const char *gtnamestring; do { @@ -1254,9 +1253,7 @@ static void readgametype(MYFILE *f, char *gtname) G_SetGametypeDescription(newgtidx, gtdescription, newgtleftcolor, newgtrightcolor); // Write the new gametype name. - gtnamestring = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); - memcpy((void *)gtnamestring, gtname, MAXLINELEN); - Gametype_Names[newgtidx] = gtnamestring; + Gametype_Names[newgtidx] = Z_StrDup((const char *)gtname); // Update gametype_cons_t accordingly. G_UpdateGametypeSelections(); @@ -4506,23 +4503,23 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) // Get the gametype name from textline // instead of word2, so that gametype names // aren't allcaps - INT32 i; - for (i = 0; i < MAXLINELEN; i++) + INT32 c; + for (c = 0; c < MAXLINELEN; c++) { - if (textline[i] == '\0') + if (textline[c] == '\0') break; - if (textline[i] == ' ') + if (textline[c] == ' ') { - char *gtname = (textline+i+1); + char *gtname = (textline+c+1); if (gtname) { // remove funny characters INT32 j; - for (j = 0; j < (MAXLINELEN - i); j++) + for (j = 0; j < (MAXLINELEN - c); j++) { if (gtname[j] == '\0') break; - if (gtname[j] < 32 || gtname[j] > 127) + if (gtname[j] < 32) gtname[j] = '\0'; } readgametype(f, gtname); diff --git a/src/g_game.c b/src/g_game.c index fe4c93de9..aa1d2a174 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3152,9 +3152,9 @@ void G_UpdateGametypeSelections(void) // Set a description for the specified gametype. // (Level platter) // -void G_SetGametypeDescription(INT16 gtype, char *description, UINT8 leftcolor, UINT8 rightcolor) +void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolor, UINT8 rightcolor) { - strncpy(gametypedesc[gtype].notes, description, 441); + strncpy(gametypedesc[gtype].notes, descriptiontext, 441); gametypedesc[gtype].col[0] = leftcolor; gametypedesc[gtype].col[1] = rightcolor; } @@ -3194,9 +3194,9 @@ void G_AddTOL(UINT32 newtol, const char *tolname) // // Assigns a type of level to a gametype. // -void G_AddGametypeTOL(INT16 gametype, UINT32 newtol) +void G_AddGametypeTOL(INT16 gtype, UINT32 newtol) { - gametypetol[gametype] = newtol; + gametypetol[gtype] = newtol; } // @@ -3342,7 +3342,7 @@ INT16 G_TOLFlag(INT32 pgametype) * has those flags. * \author Graue */ -static INT16 RandMap(INT16 tolflags, INT16 pprevmap) +static INT16 RandMap(UINT32 tolflags, INT16 pprevmap) { INT16 *okmaps = Z_Malloc(NUMMAPS * sizeof(INT16), PU_STATIC, NULL); INT32 numokmaps = 0; diff --git a/src/g_game.h b/src/g_game.h index 81998b6e6..6b29ef836 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -206,10 +206,10 @@ extern UINT32 gametypetol[NUMGAMETYPES]; void G_SetGametype(INT16 gametype); INT16 G_AddGametype(UINT32 rules); -void G_UpdateGametypeSelections(); +void G_UpdateGametypeSelections(void); void G_AddTOL(UINT32 newtol, const char *tolname); -void G_AddGametypeTOL(INT16 gametype, UINT32 newtol); -void G_SetGametypeDescription(INT16 gtype, char *description, UINT8 leftcolor, UINT8 rightcolor); +void G_AddGametypeTOL(INT16 gtype, UINT32 newtol); +void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolor, UINT8 rightcolor); INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); From 5b0a094f67fe881934f788b40702c6e186be0e5e Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 16:00:02 -0300 Subject: [PATCH 062/312] TOL stuff --- src/dehacked.c | 9 ++++++++- src/doomstat.h | 1 + src/g_game.c | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index b62f0cfbe..e3685e77c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -591,6 +591,11 @@ static void readfreeslots(MYFILE *f) } else CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n"); } + else if (fastcmp(type, "TOL")) + { + G_AddTOL(lastcustomtol, word); + lastcustomtol <<= 1; + } else deh_warning("Freeslots: unknown enum class '%s' for '%s_%s'", type, type, word); } @@ -1097,6 +1102,8 @@ static void readsprite2(MYFILE *f, INT32 num) } INT32 numtolinfo = NUMBASETOL; +UINT32 lastcustomtol = (TOL_XMAS << 1); + tolinfo_t TYPEOFLEVEL[NUMMAXTOL] = { {"SOLO",TOL_SP}, {"SP",TOL_SP}, @@ -1232,7 +1239,7 @@ static void readgametype(MYFILE *f, char *gtname) tmp = strtok(word2,","); do { for (i = 0; TYPEOFLEVEL[i].name; i++) - if (fastcmp(tmp, TYPEOFLEVEL[i].name)) + if (fasticmp(tmp, TYPEOFLEVEL[i].name)) break; if (!TYPEOFLEVEL[i].name) deh_warning("readgametype %s: unknown typeoflevel flag %s\n", gtname, tmp); diff --git a/src/doomstat.h b/src/doomstat.h index a1c347b62..daf36647c 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -453,6 +453,7 @@ typedef struct } tolinfo_t; extern tolinfo_t TYPEOFLEVEL[NUMMAXTOL]; extern INT32 numtolinfo; +extern UINT32 lastcustomtol; extern tic_t totalplaytime; diff --git a/src/g_game.c b/src/g_game.c index aa1d2a174..a2f95b5d9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3181,7 +3181,7 @@ UINT32 gametypetol[NUMGAMETYPES] = // void G_AddTOL(UINT32 newtol, const char *tolname) { - TYPEOFLEVEL[numtolinfo].name = tolname; + TYPEOFLEVEL[numtolinfo].name = Z_StrDup(tolname); TYPEOFLEVEL[numtolinfo].flag = newtol; numtolinfo++; From e3584e82302da82a18c372fa23789fb55979b382 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 16:52:05 -0300 Subject: [PATCH 063/312] GTR_ALLOWEXIT --- src/dehacked.c | 1 + src/doomstat.h | 1 + src/g_game.c | 6 +++--- src/p_spec.c | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index e3685e77c..9b2c07838 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8811,6 +8811,7 @@ static const char *const GAMETYPERULE_LIST[] = { "NOSPECTATORSPAWN", "EMERALDHUNT", "SPAWNENEMIES", + "ALLOWEXIT", NULL }; diff --git a/src/doomstat.h b/src/doomstat.h index daf36647c..dc551536e 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -413,6 +413,7 @@ enum GameTypeRules GTR_NOSPECTATORSPAWN = 1<<16, // For use with GTR_SPECTATORS - spawn in the map instead of with the spectators GTR_EMERALDHUNT = 1<<17, // Emerald Hunt GTR_SPAWNENEMIES = 1<<18, // Spawn enemies + GTR_ALLOWEXIT = 1<<19, // Allow exit sectors }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index a2f95b5d9..4110bd37e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3078,11 +3078,11 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Co-op - GTR_PLATFORM|GTR_LIVES|GTR_CHASECAM|GTR_EMERALDHUNT|GTR_SPAWNENEMIES, + GTR_PLATFORM|GTR_LIVES|GTR_CHASECAM|GTR_EMERALDHUNT|GTR_SPAWNENEMIES|GTR_ALLOWEXIT, // Competition - GTR_PLATFORM|GTR_LIVES|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES, + GTR_PLATFORM|GTR_LIVES|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT, // Race - GTR_PLATFORM|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES, + GTR_PLATFORM|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT, // Match GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY, diff --git a/src/p_spec.c b/src/p_spec.c index 161d73e0e..2aa91e95e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4678,7 +4678,7 @@ DoneSection2: } case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return - if (player->bot || !G_PlatformGametype()) + if (player->bot || !(gametyperules & GTR_ALLOWEXIT)) break; if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6) { From 5f73d4861490ad336d8ee27042aea55790574740 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 17:13:05 -0300 Subject: [PATCH 064/312] Some sort of intermission tally support. --- src/dehacked.c | 119 ++++++++++++++++++++++++++++++++----------------- src/doomstat.h | 1 + src/g_game.c | 16 +++---- src/y_inter.c | 5 ++- src/y_inter.h | 1 + 5 files changed, 91 insertions(+), 51 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 9b2c07838..4bf0f31ae 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -22,6 +22,7 @@ #include "m_menu.h" #include "m_misc.h" #include "f_finale.h" +#include "y_inter.h" #include "dehacked.h" #include "st_stuff.h" #include "i_system.h" @@ -1137,7 +1138,7 @@ static void readgametype(MYFILE *f, char *gtname) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *word; - char *word2; + char *word2, *word2lwr = NULL; char *tmp; INT32 i; @@ -1146,6 +1147,7 @@ static void readgametype(MYFILE *f, char *gtname) UINT32 newgttol = 0; UINT8 newgtleftcolor = 0; UINT8 newgtrightcolor = 0; + int newgtinttype = 0; char gtdescription[441]; do @@ -1201,7 +1203,12 @@ static void readgametype(MYFILE *f, char *gtname) word2 = strtok(NULL, " = "); if (word2) + { + if (!word2lwr) + word2lwr = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + strcpy(word2lwr, word2); strupr(word2); + } else break; @@ -1229,10 +1236,15 @@ static void readgametype(MYFILE *f, char *gtname) // Level platter newgtrightcolor = (UINT8)get_number(word2); } + else if (fastcmp(word, "INTERMISSIONTYPE")) + { + // Case sensitive + newgtinttype = (int)get_number(word2lwr); + } else if (fastcmp(word, "TYPEOFLEVEL")) { if (i) // it's just a number - newgttol = (UINT16)i; + newgttol = (UINT32)i; else { UINT16 tol = 0; @@ -1253,11 +1265,14 @@ static void readgametype(MYFILE *f, char *gtname) } } while (!myfeof(f)); // finish when the line is empty Z_Free(s); + if (word2lwr) + Z_Free(word2lwr); // Add the new gametype newgtidx = G_AddGametype(newgtrules); G_AddGametypeTOL(newgtidx, newgttol); G_SetGametypeDescription(newgtidx, gtdescription, newgtleftcolor, newgtrightcolor); + intermissiontypes[newgtidx] = newgtinttype; // Write the new gametype name. Gametype_Names[newgtidx] = Z_StrDup((const char *)gtname); @@ -1535,7 +1550,7 @@ static void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word, "TYPEOFLEVEL")) { if (i) // it's just a number - mapheaderinfo[num-1]->typeoflevel = (UINT16)i; + mapheaderinfo[num-1]->typeoflevel = (UINT32)i; else { UINT16 tol = 0; @@ -8812,6 +8827,7 @@ static const char *const GAMETYPERULE_LIST[] = { "EMERALDHUNT", "SPAWNENEMIES", "ALLOWEXIT", + "ROUNDENDMESSAGE", NULL }; @@ -9230,20 +9246,6 @@ struct { {"tr_trans90",tr_trans90}, {"NUMTRANSMAPS",NUMTRANSMAPS}, - // Type of levels - {"TOL_SP",TOL_SP}, - {"TOL_COOP",TOL_COOP}, - {"TOL_COMPETITION",TOL_COMPETITION}, - {"TOL_RACE",TOL_RACE}, - {"TOL_MATCH",TOL_MATCH}, - {"TOL_TAG",TOL_TAG}, - {"TOL_CTF",TOL_CTF}, - {"TOL_2D",TOL_2D}, - {"TOL_MARIO",TOL_MARIO}, - {"TOL_NIGHTS",TOL_NIGHTS}, - {"TOL_ERZ3",TOL_ERZ3}, - {"TOL_XMAS",TOL_XMAS}, - // Level flags {"LF_SCRIPTISFILE",LF_SCRIPTISFILE}, {"LF_SPEEDMUSIC",LF_SPEEDMUSIC}, @@ -9426,16 +9428,16 @@ struct { {"DMG_CANHURTSELF",DMG_CANHURTSELF}, {"DMG_DEATHMASK",DMG_DEATHMASK}, - // Gametypes, for use with global var "gametype" - // Left them here just in case?? - {"GT_COOP",GT_COOP}, - {"GT_COMPETITION",GT_COMPETITION}, - {"GT_RACE",GT_RACE}, - {"GT_MATCH",GT_MATCH}, - {"GT_TEAMMATCH",GT_TEAMMATCH}, - {"GT_TAG",GT_TAG}, - {"GT_HIDEANDSEEK",GT_HIDEANDSEEK}, - {"GT_CTF",GT_CTF}, + // Intermission types + {"int_none",int_none}, + {"int_coop",int_coop}, + {"int_match",int_match}, + {"int_teammatch",int_teammatch}, + //{"int_tag",int_tag}, + {"int_ctf",int_ctf}, + {"int_spec",int_spec}, + {"int_race",int_race}, + {"int_comp",int_comp}, // Jingles (jingletype_t) {"JT_NONE",JT_NONE}, @@ -9728,7 +9730,7 @@ struct { }; static mobjtype_t get_mobjtype(const char *word) -{ // Returns the vlaue of MT_ enumerations +{ // Returns the value of MT_ enumerations mobjtype_t i; if (*word >= '0' && *word <= '9') return atoi(word); @@ -9895,7 +9897,7 @@ static INT16 get_gametype(const char *word) } static powertype_t get_power(const char *word) -{ // Returns the vlaue of pw_ enumerations +{ // Returns the value of pw_ enumerations powertype_t i; if (*word >= '0' && *word <= '9') return atoi(word); @@ -10057,19 +10059,6 @@ static fixed_t find_const(const char **rword) free(word); return 0; } - else if (fastncmp("GTR_", word, 4)) { - char *p = word+4; - for (i = 0; GAMETYPERULE_LIST[i]; i++) - if (fastcmp(p, GAMETYPERULE_LIST[i])) { - free(word); - return (1< Date: Wed, 18 Dec 2019 18:09:56 -0300 Subject: [PATCH 065/312] Intermission HUD hook for Lua --- src/lua_hud.h | 6 +++++- src/lua_hudlib.c | 30 ++++++++++++++++++++++++++++++ src/y_inter.c | 26 +++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/lua_hud.h b/src/lua_hud.h index abfbba441..396ca8988 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -33,6 +33,9 @@ enum hud { hud_coopemeralds, hud_tokens, hud_tabemblems, + // Intermission + hud_intermissiontally, + hud_intermissionmessages, hud_MAX }; @@ -43,4 +46,5 @@ boolean LUA_HudEnabled(enum hud option); void LUAh_GameHUD(player_t *stplyr); void LUAh_ScoresHUD(void); void LUAh_TitleHUD(void); -void LUAh_TitleCardHUD(player_t *stplyr); +void LUAh_TitleCardHUD(player_t *stplayr); +void LUAh_IntermissionHUD(void); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index a2f48c4ad..211c8a828 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -60,6 +60,9 @@ static const char *const hud_disable_options[] = { "coopemeralds", "tokens", "tabemblems", + + "intermissiontally", + "intermissionmessages", NULL}; enum hudinfo { @@ -92,12 +95,14 @@ static const char *const patch_opt[] = { enum hudhook { hudhook_game = 0, hudhook_scores, + hudhook_intermission, hudhook_title, hudhook_titlecard }; static const char *const hudhook_opt[] = { "game", "scores", + "intermission", "title", "titlecard", NULL}; @@ -1228,4 +1233,29 @@ void LUAh_TitleCardHUD(player_t *stplayr) hud_running = false; } +void LUAh_IntermissionHUD(void) +{ + if (!gL || !(hudAvailable & (1< Date: Wed, 18 Dec 2019 18:30:24 -0300 Subject: [PATCH 066/312] Fix lib_getenum. Also, adding gametypes also creates constant names for them. --- src/dehacked.c | 63 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 4bf0f31ae..474ad2de3 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1140,6 +1140,7 @@ static void readgametype(MYFILE *f, char *gtname) char *word; char *word2, *word2lwr = NULL; char *tmp; + char *gtconst; INT32 i; INT16 newgtidx = 0; @@ -1277,6 +1278,53 @@ static void readgametype(MYFILE *f, char *gtname) // Write the new gametype name. Gametype_Names[newgtidx] = Z_StrDup((const char *)gtname); + // Write the constant name. + gtconst = Z_Malloc(strlen((const char *)gtname) + 3, PU_STATIC, NULL); + // Copy GT_ and the gametype name. + strcpy(gtconst, "GT_"); + strcat(gtconst, (const char *)gtname); + // Make uppercase. + strupr(gtconst); + // Remove characters. +#define REMOVECHAR(chr) \ + word = strchr(gtconst, chr); \ + while (word) \ + { \ + *word = '_'; \ + word = strchr(word, chr); \ + } + + // Space + REMOVECHAR(' ') + // Used for operations + REMOVECHAR('+') + REMOVECHAR('-') + REMOVECHAR('*') + REMOVECHAR('/') + REMOVECHAR('%') + REMOVECHAR('^') + // Part of Lua's syntax + REMOVECHAR('#') + REMOVECHAR('=') + REMOVECHAR('~') + REMOVECHAR('<') + REMOVECHAR('>') + REMOVECHAR('(') + REMOVECHAR(')') + REMOVECHAR('{') + REMOVECHAR('}') + REMOVECHAR('[') + REMOVECHAR(']') + REMOVECHAR(':') + REMOVECHAR(';') + REMOVECHAR(',') + REMOVECHAR('.') + +#undef REMOVECHAR + + // Finally, set the constant string. + Gametype_ConstantNames[newgtidx] = gtconst; + // Update gametype_cons_t accordingly. G_UpdateGametypeSelections(); @@ -10441,13 +10489,13 @@ static inline int lib_getenum(lua_State *L) return 0; } else if (fastncmp("GT_", word, 3)) { - p = word+3; + p = word; for (i = 0; Gametype_ConstantNames[i]; i++) if (fastcmp(p, Gametype_ConstantNames[i])) { - lua_pushinteger(L, ((lua_Integer)1< Date: Wed, 18 Dec 2019 18:39:59 -0300 Subject: [PATCH 067/312] GTR_NOTITLECARD --- src/dehacked.c | 1 + src/doomstat.h | 1 + src/g_game.c | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 474ad2de3..5309058c4 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8876,6 +8876,7 @@ static const char *const GAMETYPERULE_LIST[] = { "SPAWNENEMIES", "ALLOWEXIT", "ROUNDENDMESSAGE", + "NOTITLECARD", NULL }; diff --git a/src/doomstat.h b/src/doomstat.h index d9c93553c..ffce0c814 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -415,6 +415,7 @@ enum GameTypeRules GTR_SPAWNENEMIES = 1<<18, // Spawn enemies GTR_ALLOWEXIT = 1<<19, // Allow exit sectors GTR_ROUNDENDMESSAGE = 1<<20, // Prints "The round has ended." into the console + GTR_NOTITLECARD = 1<<21, // Don't show the title card }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 62b2eed82..005d37702 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1809,7 +1809,7 @@ void G_StartTitleCard(void) // The title card has been disabled for this map. // Oh well. - if (mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD) + if ((mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD) || (gametyperules & GTR_NOTITLECARD)) { WipeStageTitle = false; return; From b8d47dbc60baa88b4748804facf3b061dd28816f Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 18:50:04 -0300 Subject: [PATCH 068/312] Accept gametype rules in SOC by just their names as parameters. --- src/dehacked.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 5309058c4..1ea3dd0c4 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1134,6 +1134,7 @@ tolinfo_t TYPEOFLEVEL[NUMMAXTOL] = { }; // copypasted from readPlayer :sleep: +static const char *const GAMETYPERULE_LIST[]; static void readgametype(MYFILE *f, char *gtname) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); @@ -1141,7 +1142,7 @@ static void readgametype(MYFILE *f, char *gtname) char *word2, *word2lwr = NULL; char *tmp; char *gtconst; - INT32 i; + INT32 i, j; INT16 newgtidx = 0; UINT32 newgtrules = 0; @@ -1261,8 +1262,26 @@ static void readgametype(MYFILE *f, char *gtname) newgttol = tol; } } + // The SOC probably provided gametype rules as words, + // instead of using the RULES keyword. + // Like for example "NOSPECTATORSPAWN = 1". + // This is completely valid, and looks better anyway. else - deh_warning("readgametype %s: unknown word '%s'", gtname, word); + { + UINT32 wordgt = 0; + for (j = 0; GAMETYPERULE_LIST[j]; j++) + if (fastcmp(word, GAMETYPERULE_LIST[j])) { + if (!j) // GTR_PLATFORM + wordgt |= 1; + else + wordgt |= (1< Date: Wed, 18 Dec 2019 18:52:10 -0300 Subject: [PATCH 069/312] Fix comment --- src/dehacked.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 1ea3dd0c4..670a16e69 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1264,7 +1264,7 @@ static void readgametype(MYFILE *f, char *gtname) } // The SOC probably provided gametype rules as words, // instead of using the RULES keyword. - // Like for example "NOSPECTATORSPAWN = 1". + // Like for example "NOSPECTATORSPAWN = TRUE". // This is completely valid, and looks better anyway. else { From eadb3dec9e4344e59cbbfe37a4d0b20a35c86ee2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 18:59:47 -0300 Subject: [PATCH 070/312] Limits checking --- src/dehacked.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 670a16e69..29dbd0b19 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -594,8 +594,13 @@ static void readfreeslots(MYFILE *f) } else if (fastcmp(type, "TOL")) { - G_AddTOL(lastcustomtol, word); - lastcustomtol <<= 1; + if (lastcustomtol > 31) + CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n"); + else + { + G_AddTOL((1< Date: Wed, 18 Dec 2019 19:26:45 -0300 Subject: [PATCH 071/312] Ringslinger tweaks --- src/d_netcmd.c | 6 +++--- src/dehacked.c | 5 ++++- src/doomstat.h | 5 ++++- src/g_game.c | 10 +++++----- src/hu_stuff.c | 2 +- src/p_inter.c | 6 +++--- src/st_stuff.c | 2 +- 7 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 959ed875f..67a230289 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3696,7 +3696,7 @@ void ItemFinder_OnChange(void) static void PointLimit_OnChange(void) { // Don't allow pointlimit in Single Player/Co-Op/Race! - if (server && Playing() && G_PlatformGametype()) + if (server && Playing() && !(gametyperules & GTR_POINTLIMIT)) { if (cv_pointlimit.value) CV_StealthSetValue(&cv_pointlimit, 0); @@ -3859,7 +3859,7 @@ UINT32 timelimitintics = 0; static void TimeLimit_OnChange(void) { // Don't allow timelimit in Single Player/Co-Op/Race! - if (server && Playing() && cv_timelimit.value != 0 && G_PlatformGametype()) + if (server && Playing() && cv_timelimit.value != 0 && !(gametyperules & GTR_TIMELIMIT)) { CV_SetValue(&cv_timelimit, 0); return; @@ -3964,7 +3964,7 @@ void D_GameTypeChanged(INT32 lastgametype) // reset timelimit and pointlimit in race/coop, prevent stupid cheats if (server) { - if (G_PlatformGametype()) + if (!(gametyperules & GTR_POINTLIMIT)) { if (cv_timelimit.value) CV_SetValue(&cv_timelimit, 0); diff --git a/src/dehacked.c b/src/dehacked.c index 29dbd0b19..abd0cad7c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8894,7 +8894,7 @@ static const char *const GAMETYPERULE_LIST[] = { "LIVES", "RACE", "CHASECAM", - "TIMELIMIT", + "\x01", // 1<<8, empty "HIDETIME", "HIDETIMEFROZEN", "BLINDFOLDED", @@ -8908,6 +8908,9 @@ static const char *const GAMETYPERULE_LIST[] = { "ALLOWEXIT", "ROUNDENDMESSAGE", "NOTITLECARD", + "POINTLIMIT", + "TIMELIMIT", + "OVERTIME", NULL }; diff --git a/src/doomstat.h b/src/doomstat.h index ffce0c814..de0058766 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -402,7 +402,7 @@ enum GameTypeRules // flexibility! Those will replace some straight-up gametype checks scattered around the source code! GTR_CHASECAM = 1<<7, // Prefer chasecam at map load (All platform gametypes) - GTR_TIMELIMIT = 1<<8, // Ringslinger time limit (Tag and Hide and Seek) + // 1<<8, empty GTR_HIDETIME = 1<<9, // Tag and Hide and Seek GTR_HIDETIMEFROZEN = 1<<10, // Hide and Seek, but not Tag GTR_BLINDFOLDED = 1<<11, // Blindfolded view (Tag and Hide and Seek) @@ -416,6 +416,9 @@ enum GameTypeRules GTR_ALLOWEXIT = 1<<19, // Allow exit sectors GTR_ROUNDENDMESSAGE = 1<<20, // Prints "The round has ended." into the console GTR_NOTITLECARD = 1<<21, // Don't show the title card + GTR_POINTLIMIT = 1<<22, // Ringslinger point limit + GTR_TIMELIMIT = 1<<23, // Ringslinger time limit + GTR_OVERTIME = 1<<24, // Allow overtime }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 005d37702..443ea69a7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3085,17 +3085,17 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = GTR_PLATFORM|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_ROUNDENDMESSAGE, // Match - GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY|GTR_ROUNDENDMESSAGE, // Team Match - GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_PITYSHIELD|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_TEAMS|GTR_POINTLIMIT|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_PITYSHIELD|GTR_ROUNDENDMESSAGE, // Tag - GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_ROUNDENDMESSAGE, // Hide and Seek - GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT||GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_ROUNDENDMESSAGE, // CTF - GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_EMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD|GTR_ROUNDENDMESSAGE, }; // diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 8cbfa77d3..bcad6ebef 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -3026,7 +3026,7 @@ static void HU_DrawRankings(void) // draw the current gametype in the lower right HU_drawGametype(); - if (!G_PlatformGametype()) + if (gametyperules & GTR_POINTLIMIT) { if (cv_timelimit.value && timelimitintics > 0) { diff --git a/src/p_inter.c b/src/p_inter.c index 21c3d4049..1f2390de0 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2093,7 +2093,7 @@ void P_CheckTimeLimit(void) if (!(multiplayer || netgame)) return; - if (G_PlatformGametype()) + if (!(gametyperules & GTR_TIMELIMIT)) return; if (leveltime < timelimitintics) @@ -2124,7 +2124,7 @@ void P_CheckTimeLimit(void) } //Optional tie-breaker for Match/CTF - else if (cv_overtime.value) + else if ((cv_overtime.value) && (gametyperules & GTR_OVERTIME)) { INT32 playerarray[MAXPLAYERS]; INT32 tempplayer = 0; @@ -2206,7 +2206,7 @@ void P_CheckPointLimit(void) if (!(multiplayer || netgame)) return; - if (G_PlatformGametype()) + if (!(gametyperules & GTR_POINTLIMIT)) return; // pointlimit is nonzero, check if it's been reached by this player diff --git a/src/st_stuff.c b/src/st_stuff.c index 1c9b4614e..4c3f57412 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2638,7 +2638,7 @@ static void ST_overlayDrawer(void) } // If you are in overtime, put a big honkin' flashin' message on the screen. - if (G_RingSlingerGametype() && cv_overtime.value + if (((gametyperules & GTR_TIMELIMIT) && (gametyperules & GTR_OVERTIME)) && cv_overtime.value && (leveltime > (timelimitintics + TICRATE/2)) && cv_timelimit.value && (leveltime/TICRATE % 2 == 0)) V_DrawCenteredString(BASEVIDWIDTH/2, 184, V_PERPLAYER, M_GetText("OVERTIME!")); From 04ee98a1a179793835a799b285c4c03ac7148276 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 19:43:12 -0300 Subject: [PATCH 072/312] point limit/time limit --- src/d_netcmd.c | 13 +++++++++++++ src/d_netcmd.h | 5 ++++- src/dehacked.c | 26 ++++++++++++++++---------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 67a230289..aaaf33cb5 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -328,6 +328,10 @@ consvar_t cv_numlaps = {"numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_con static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}}; consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL}; +// Point and time limits for every gametype +INT32 pointlimits[NUMGAMETYPES]; +INT32 timelimits[NUMGAMETYPES]; + // log elemental hazards -- not a netvar, is local to current player consvar_t cv_hazardlog = {"hazardlog", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -3951,6 +3955,15 @@ void D_GameTypeChanged(INT32 lastgametype) if (!cv_itemrespawntime.changed) CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally break; + default: + if (!cv_timelimit.changed && !cv_pointlimit.changed) // user hasn't changed limits + { + CV_SetValue(&cv_timelimit, timelimits[gametype]); + CV_SetValue(&cv_pointlimit, pointlimits[gametype]); + } + if (!cv_itemrespawntime.changed) + CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally + break; } } else if (!multiplayer && !netgame) diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 8f857c6db..cd2efe2e3 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -60,9 +60,12 @@ extern consvar_t cv_flagtime; extern consvar_t cv_touchtag; extern consvar_t cv_hidetime; -extern consvar_t cv_friendlyfire; extern consvar_t cv_pointlimit; extern consvar_t cv_timelimit; +extern INT32 pointlimits[NUMGAMETYPES]; +extern INT32 timelimits[NUMGAMETYPES]; + +extern consvar_t cv_friendlyfire; extern consvar_t cv_numlaps; extern consvar_t cv_basenumlaps; extern UINT32 timelimitintics; diff --git a/src/dehacked.c b/src/dehacked.c index abd0cad7c..cbbbe8d77 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1152,6 +1152,8 @@ static void readgametype(MYFILE *f, char *gtname) INT16 newgtidx = 0; UINT32 newgtrules = 0; UINT32 newgttol = 0; + INT32 newgtpointlimit = 0; + INT32 newgttimelimit = 0; UINT8 newgtleftcolor = 0; UINT8 newgtrightcolor = 0; int newgtinttype = 0; @@ -1223,31 +1225,31 @@ static void readgametype(MYFILE *f, char *gtname) word2[strlen(word2)-1] = '\0'; i = atoi(word2); + // Game type rules if (fastcmp(word, "RULES")) { - // Game type rules (GTR_) + // GTR_ newgtrules = (UINT32)get_number(word2); } + // Point and time limits + else if (fastcmp(word, "DEFAULTPOINTLIMIT")) + newgtpointlimit = (INT32)i; + else if (fastcmp(word, "DEFAULTTIMELIMIT")) + newgttimelimit = (INT32)i; + // Level platter else if (fastcmp(word, "HEADERCOLOR") || fastcmp(word, "HEADERCOLOUR")) - { - // Level platter newgtleftcolor = newgtrightcolor = (UINT8)get_number(word2); - } else if (fastcmp(word, "HEADERLEFTCOLOR") || fastcmp(word, "HEADERLEFTCOLOUR")) - { - // Level platter newgtleftcolor = (UINT8)get_number(word2); - } else if (fastcmp(word, "HEADERRIGHTCOLOR") || fastcmp(word, "HEADERRIGHTCOLOUR")) - { - // Level platter newgtrightcolor = (UINT8)get_number(word2); - } + // Type of intermission else if (fastcmp(word, "INTERMISSIONTYPE")) { // Case sensitive newgtinttype = (int)get_number(word2lwr); } + // Type of level else if (fastcmp(word, "TYPEOFLEVEL")) { if (i) // it's just a number @@ -1304,7 +1306,11 @@ static void readgametype(MYFILE *f, char *gtname) newgtidx = G_AddGametype(newgtrules); G_AddGametypeTOL(newgtidx, newgttol); G_SetGametypeDescription(newgtidx, gtdescription, newgtleftcolor, newgtrightcolor); + + // Not covered by G_AddGametype alone. intermissiontypes[newgtidx] = newgtinttype; + pointlimits[newgtidx] = newgtpointlimit; + timelimits[newgtidx] = newgttimelimit; // Write the new gametype name. Gametype_Names[newgtidx] = Z_StrDup((const char *)gtname); From d0e18444fbc5ba14119b0bfaf53a3e4a18b791e8 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 20:12:52 -0300 Subject: [PATCH 073/312] GTR_FRIENDLYFIRE, renamed GTR_HIDETIMEFROZEN, fixed other mistakes --- src/d_netcmd.c | 8 ++++---- src/d_netcmd.h | 5 +---- src/dehacked.c | 4 ++-- src/doomstat.h | 10 +++++++--- src/g_game.c | 2 +- src/p_inter.c | 12 ++++++------ src/st_stuff.c | 2 +- 7 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index aaaf33cb5..158b1f802 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2419,7 +2419,7 @@ static void Command_Teamchange_f(void) } //additional check for hide and seek. Don't allow change of status after hidetime ends. - if ((gametyperules & GTR_HIDETIMEFROZEN) && leveltime >= (hidetime * TICRATE)) + if ((gametyperules & GTR_HIDEFROZEN) && leveltime >= (hidetime * TICRATE)) { CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); return; @@ -2516,7 +2516,7 @@ static void Command_Teamchange2_f(void) } //additional check for hide and seek. Don't allow change of status after hidetime ends. - if ((gametyperules & GTR_HIDETIMEFROZEN) && leveltime >= (hidetime * TICRATE)) + if ((gametyperules & GTR_HIDEFROZEN) && leveltime >= (hidetime * TICRATE)) { CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); return; @@ -2645,7 +2645,7 @@ static void Command_ServerTeamChange_f(void) } //additional check for hide and seek. Don't allow change of status after hidetime ends. - if ((gametyperules & GTR_HIDETIMEFROZEN) && leveltime >= (hidetime * TICRATE)) + if ((gametyperules & GTR_HIDEFROZEN) && leveltime >= (hidetime * TICRATE)) { CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); return; @@ -2735,7 +2735,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } //no status changes after hidetime - if ((gametyperules & GTR_HIDETIMEFROZEN) && (leveltime >= (hidetime * TICRATE))) + if ((gametyperules & GTR_HIDEFROZEN) && (leveltime >= (hidetime * TICRATE))) error = true; //Make sure that the right team number is sent. Keep in mind that normal clients cannot change to certain teams in certain gametypes. diff --git a/src/d_netcmd.h b/src/d_netcmd.h index cd2efe2e3..8f857c6db 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -60,12 +60,9 @@ extern consvar_t cv_flagtime; extern consvar_t cv_touchtag; extern consvar_t cv_hidetime; +extern consvar_t cv_friendlyfire; extern consvar_t cv_pointlimit; extern consvar_t cv_timelimit; -extern INT32 pointlimits[NUMGAMETYPES]; -extern INT32 timelimits[NUMGAMETYPES]; - -extern consvar_t cv_friendlyfire; extern consvar_t cv_numlaps; extern consvar_t cv_basenumlaps; extern UINT32 timelimitintics; diff --git a/src/dehacked.c b/src/dehacked.c index cbbbe8d77..676d0e144 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8900,9 +8900,9 @@ static const char *const GAMETYPERULE_LIST[] = { "LIVES", "RACE", "CHASECAM", - "\x01", // 1<<8, empty + "FRIENDLYFIRE", "HIDETIME", - "HIDETIMEFROZEN", + "HIDEFROZEN", "BLINDFOLDED", "EMERALDS", "TEAMFLAGS", diff --git a/src/doomstat.h b/src/doomstat.h index de0058766..459bfc88f 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -402,9 +402,9 @@ enum GameTypeRules // flexibility! Those will replace some straight-up gametype checks scattered around the source code! GTR_CHASECAM = 1<<7, // Prefer chasecam at map load (All platform gametypes) - // 1<<8, empty - GTR_HIDETIME = 1<<9, // Tag and Hide and Seek - GTR_HIDETIMEFROZEN = 1<<10, // Hide and Seek, but not Tag + GTR_FRIENDLYFIRE = 1<<8, // Always allow friendly fire + GTR_HIDETIME = 1<<9, // Hide time (Tag and Hide and Seek) + GTR_HIDEFROZEN = 1<<10, // Frozen after hide time (Hide and Seek, but not Tag) GTR_BLINDFOLDED = 1<<11, // Blindfolded view (Tag and Hide and Seek) GTR_EMERALDS = 1<<12, // Ringslinger emeralds (Match and CTF) GTR_TEAMFLAGS = 1<<13, // Gametype has team flags (CTF) @@ -425,6 +425,10 @@ enum GameTypeRules extern const char *Gametype_Names[NUMGAMETYPES]; extern const char *Gametype_ConstantNames[NUMGAMETYPES]; +// Point and time limits for every gametype +extern INT32 pointlimits[NUMGAMETYPES]; +extern INT32 timelimits[NUMGAMETYPES]; + enum TypeOfLevel { TOL_SP = 0x01, ///< Single Player diff --git a/src/g_game.c b/src/g_game.c index 443ea69a7..02b32bd48 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3092,7 +3092,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = // Tag GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_ROUNDENDMESSAGE, // Hide and Seek - GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT||GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_ROUNDENDMESSAGE, // CTF GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD|GTR_ROUNDENDMESSAGE, diff --git a/src/p_inter.c b/src/p_inter.c index 1f2390de0..900435a99 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3042,7 +3042,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou return false; // Ignore IT players shooting each other, unless friendlyfire is on. - if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && + if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) && source && source->player && source->player->pflags & PF_TAGIT))) { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) @@ -3058,7 +3058,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou // Don't allow players on the same team to hurt one another, // unless cv_friendlyfire is on. - if (!(cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT)) + if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT)) { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) { @@ -3143,7 +3143,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj return false; // In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on - if (!cv_friendlyfire.value && (G_PlatformGametype())) + if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && (G_PlatformGametype())) { if (gametype == GT_COOP && inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) // co-op only { @@ -3166,7 +3166,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj { // Don't allow players on the same team to hurt one another, // unless cv_friendlyfire is on. - if (!cv_friendlyfire.value && target->player->ctfteam == source->player->ctfteam) + if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && target->player->ctfteam == source->player->ctfteam) { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) { @@ -3593,7 +3593,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da { if (source == target) return false; // Don't hit yourself with your own paraloop, baka - if (source && source->player && !cv_friendlyfire.value + if (source && source->player && !(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && (gametype == GT_COOP || (G_GametypeHasTeams() && player->ctfteam == source->player->ctfteam))) return false; // Don't run eachother over in special stages and team games and such @@ -3688,7 +3688,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // by friendly fire. Spilling their rings and other items is enough. else if (!force && G_GametypeHasTeams() && source && source->player && (source->player->ctfteam == player->ctfteam) - && cv_friendlyfire.value) + && (cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE))) { damage = 0; P_ShieldDamage(player, inflictor, source, damage, damagetype); diff --git a/src/st_stuff.c b/src/st_stuff.c index 4c3f57412..b822678ff 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2298,7 +2298,7 @@ static void ST_drawTextHUD(void) textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) donef12 = true; } - if (gametyperules & GTR_HIDETIMEFROZEN) + if (gametyperules & GTR_HIDEFROZEN) textHUDdraw(M_GetText("You cannot move while hiding.")) } } From 0421c81e042f89af988d12c83b56cef20eb95986 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 20:43:54 -0300 Subject: [PATCH 074/312] ViewpointSwitch hook for Lua --- src/g_game.c | 10 ++++++++++ src/lua_hook.h | 2 ++ src/lua_hooklib.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 02b32bd48..f84829386 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1956,6 +1956,16 @@ boolean G_Responder(event_t *ev) if (!playeringame[displayplayer]) continue; +#ifdef HAVE_BLUA + { + UINT8 canSwitchView = LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer]); + if (canSwitchView == 1) // Set viewpoint to this player + break; + else if (canSwitchView == 2) // Skip this player + continue; + } +#endif + if (players[displayplayer].spectator) continue; diff --git a/src/lua_hook.h b/src/lua_hook.h index 6617bca93..592a93acc 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -51,6 +51,7 @@ enum hook { hook_PlayerCanDamage, hook_PlayerQuit, hook_IntermissionThinker, + hook_ViewpointSwitch, hook_MAX // last hook }; @@ -93,5 +94,6 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAft UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting void LUAh_IntermissionThinker(void); // Hook for Y_Ticker +UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer); // Hook for spy mode in G_Responder #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index ef87d0b6f..b1f702f7c 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -62,6 +62,7 @@ const char *const hookNames[hook_MAX+1] = { "PlayerCanDamage", "PlayerQuit", "IntermissionThinker", + "ViewpointSwitch", NULL }; @@ -203,6 +204,7 @@ static int lib_addHook(lua_State *L) case hook_PlayerSpawn: case hook_FollowMobj: case hook_PlayerCanDamage: + case hook_ViewpointSwitch: case hook_ShieldSpawn: case hook_ShieldSpecial: lastp = &playerhooks; @@ -1346,4 +1348,49 @@ void LUAh_IntermissionThinker(void) } } +// Hook for spy mode in G_Responder +UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer) +{ + hook_p hookp; + UINT8 canSwitchView = 0; // 0 = default, 1 = force yes, 2 = force no. + if (!gL || !(hooksAvailable[hook_ViewpointSwitch/8] & (1<<(hook_ViewpointSwitch%8)))) + return 0; + + lua_settop(gL, 0); + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_ViewpointSwitch) + continue; + + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, newdisplayplayer, META_PLAYER); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave canSwitchView = 0. + if (lua_toboolean(gL, -1)) + canSwitchView = 1; // Force viewpoint switch + else + canSwitchView = 2; // Skip viewpoint switch + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return canSwitchView; +} + #endif From 5e818e1dab6934be29c55b8f5ae4fb14e353a5cf Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 22:02:37 -0300 Subject: [PATCH 075/312] Custom gametype rankings --- src/dehacked.c | 12 +++++++++++- src/g_game.c | 19 ++++++++++++++++++- src/g_game.h | 1 + src/hu_stuff.c | 24 ++++++++++++------------ 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 676d0e144..254f94ade 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1156,6 +1156,7 @@ static void readgametype(MYFILE *f, char *gtname) INT32 newgttimelimit = 0; UINT8 newgtleftcolor = 0; UINT8 newgtrightcolor = 0; + INT16 newgtrankingstype = -1; int newgtinttype = 0; char gtdescription[441]; @@ -1243,7 +1244,13 @@ static void readgametype(MYFILE *f, char *gtname) newgtleftcolor = (UINT8)get_number(word2); else if (fastcmp(word, "HEADERRIGHTCOLOR") || fastcmp(word, "HEADERRIGHTCOLOUR")) newgtrightcolor = (UINT8)get_number(word2); - // Type of intermission + // Rankings type + else if (fastcmp(word, "RANKINGTYPE")) + { + // Case insensitive + newgtrankingstype = (int)get_number(word2); + } + // Intermission type else if (fastcmp(word, "INTERMISSIONTYPE")) { // Case sensitive @@ -1308,6 +1315,9 @@ static void readgametype(MYFILE *f, char *gtname) G_SetGametypeDescription(newgtidx, gtdescription, newgtleftcolor, newgtrightcolor); // Not covered by G_AddGametype alone. + if (newgtrankingstype == -1) + newgtrankingstype = newgtidx; + gametyperankings[newgtidx] = newgtrankingstype; intermissiontypes[newgtidx] = newgtinttype; pointlimits[newgtidx] = newgtpointlimit; timelimits[newgtidx] = newgttimelimit; diff --git a/src/g_game.c b/src/g_game.c index f84829386..04722acbb 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3084,7 +3084,7 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = "GT_CTF" // GT_CTF }; -// Game type rules +// Gametype rules UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Co-op @@ -3169,6 +3169,23 @@ void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolo gametypedesc[gtype].col[1] = rightcolor; } +// Gametype rankings +INT16 gametyperankings[NUMGAMETYPES] = +{ + GT_COOP, + GT_COMPETITION, + GT_RACE, + + GT_MATCH, + GT_TEAMMATCH, + + GT_TAG, + GT_HIDEANDSEEK, + + GT_CTF, +}; + +// Gametype to TOL (Type Of Level) UINT32 gametypetol[NUMGAMETYPES] = { TOL_COOP, // Co-op diff --git a/src/g_game.h b/src/g_game.h index 6b29ef836..bd0dc0180 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -203,6 +203,7 @@ boolean G_CheckDemoStatus(void); extern UINT32 gametypedefaultrules[NUMGAMETYPES]; extern UINT32 gametypetol[NUMGAMETYPES]; +extern INT16 gametyperankings[NUMGAMETYPES]; void G_SetGametype(INT16 gametype); INT16 G_AddGametype(UINT32 rules); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index bcad6ebef..e95ab7b1b 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2371,7 +2371,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I for (i = 0; i < scorelines; i++) { - if (players[tab[i].num].spectator && gametype != GT_COOP) + if (players[tab[i].num].spectator && gametyperankings[gametype] != GT_COOP) continue; //ignore them. greycheck = greycheckdef; @@ -2434,7 +2434,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I } } - if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives + if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives)); else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) { @@ -2447,7 +2447,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED)) V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); - if (gametype == GT_RACE) + if (gametyperankings[gametype] == GT_RACE) { if (circuitmap) { @@ -2726,7 +2726,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline for (i = 0; i < scorelines; i++) { - if (players[tab[i].num].spectator && gametype != GT_COOP) + if (players[tab[i].num].spectator && gametyperankings[gametype] != GT_COOP) continue; //ignore them. greycheck = greycheckdef; @@ -2743,7 +2743,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline | (greycheck ? V_TRANSLUCENT : 0) | V_ALLOWLOWERCASE, name); - if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives + if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives)); else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) V_DrawSmallScaledPatch(x-28, y-4, 0, tagico); @@ -2792,7 +2792,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline } // All data drawn with thin string for space. - if (gametype == GT_RACE) + if (gametyperankings[gametype] == GT_RACE) { if (circuitmap) { @@ -2832,7 +2832,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor for (i = 0; i < scorelines; i++) { - if (players[tab[i].num].spectator && gametype != GT_COOP) + if (players[tab[i].num].spectator && gametyperankings[gametype] != GT_COOP) continue; //ignore them. greycheck = greycheckdef; @@ -2902,7 +2902,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor } // All data drawn with thin string for space. - if (gametype == GT_RACE) + if (gametyperankings[gametype] == GT_RACE) { if (circuitmap) { @@ -3040,7 +3040,7 @@ static void HU_DrawRankings(void) V_DrawCenteredString(256, 16, 0, va("%d", cv_pointlimit.value)); } } - else if (gametype == GT_COOP) + else if (gametyperankings[gametype] == GT_COOP) { INT32 totalscore = 0; for (i = 0; i < MAXPLAYERS; i++) @@ -3074,7 +3074,7 @@ static void HU_DrawRankings(void) tab[i].num = -1; tab[i].name = 0; - if (gametype == GT_RACE && !circuitmap) + if (gametyperankings[gametype] == GT_RACE && !circuitmap) tab[i].count = INT32_MAX; } @@ -3094,7 +3094,7 @@ static void HU_DrawRankings(void) if (!G_PlatformGametype() && players[i].spectator) continue; - if (gametype == GT_RACE) + if (gametyperankings[gametype] == GT_RACE) { if (circuitmap) { @@ -3117,7 +3117,7 @@ static void HU_DrawRankings(void) } } } - else if (gametype == GT_COMPETITION) + else if (gametyperankings[gametype] == GT_COMPETITION) { // todo put something more fitting for the gametype here, such as current // number of categories led From 9228f99260c329370a9c1a9dc6ed5ca29650c5d3 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 22:23:30 -0300 Subject: [PATCH 076/312] Fix timelimit/pointlimit checks in HU_DrawRankings, organise rules in gametypedefaultrules a bit --- src/g_game.c | 4 ++-- src/hu_stuff.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 04722acbb..2675930a4 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3097,7 +3097,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = // Match GTR_RINGSLINGER|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY|GTR_ROUNDENDMESSAGE, // Team Match - GTR_RINGSLINGER|GTR_TEAMS|GTR_POINTLIMIT|GTR_SPECTATORS|GTR_TIMELIMIT|GTR_PITYSHIELD|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_PITYSHIELD|GTR_ROUNDENDMESSAGE, // Tag GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_ROUNDENDMESSAGE, @@ -3105,7 +3105,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_ROUNDENDMESSAGE, // CTF - GTR_RINGSLINGER|GTR_TEAMS|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD|GTR_ROUNDENDMESSAGE, }; // diff --git a/src/hu_stuff.c b/src/hu_stuff.c index e95ab7b1b..d9801793b 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -3026,15 +3026,15 @@ static void HU_DrawRankings(void) // draw the current gametype in the lower right HU_drawGametype(); - if (gametyperules & GTR_POINTLIMIT) + if (gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT)) { - if (cv_timelimit.value && timelimitintics > 0) + if ((gametyperules & GTR_TIMELIMIT) && cv_timelimit.value && timelimitintics > 0) { V_DrawCenteredString(64, 8, 0, "TIME"); V_DrawCenteredString(64, 16, 0, va("%i:%02i", G_TicsToMinutes(stplyr->realtime, true), G_TicsToSeconds(stplyr->realtime))); } - if (cv_pointlimit.value > 0) + if ((gametyperules & GTR_POINTLIMIT) && cv_pointlimit.value > 0) { V_DrawCenteredString(256, 8, 0, "POINT LIMIT"); V_DrawCenteredString(256, 16, 0, va("%d", cv_pointlimit.value)); From 5daedc70e75057ed1323db4ab9e68f876dbd585d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 22:46:17 -0300 Subject: [PATCH 077/312] Special Stages/token stuff --- src/dehacked.c | 2 ++ src/doomstat.h | 18 ++++++++++-------- src/g_game.c | 6 +++--- src/p_inter.c | 2 +- src/p_mobj.c | 2 +- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 254f94ade..e60bcae5d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8919,6 +8919,8 @@ static const char *const GAMETYPERULE_LIST[] = { "PITYSHIELD", "DEATHPENALTY", "NOSPECTATORSPAWN", + "SPECIALSTAGES", + "EMERALDTOKENS", "EMERALDHUNT", "SPAWNENEMIES", "ALLOWEXIT", diff --git a/src/doomstat.h b/src/doomstat.h index 459bfc88f..b79edb93c 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -411,14 +411,16 @@ enum GameTypeRules GTR_PITYSHIELD = 1<<14, // Award pity shield GTR_DEATHPENALTY = 1<<15, // Death score penalty GTR_NOSPECTATORSPAWN = 1<<16, // For use with GTR_SPECTATORS - spawn in the map instead of with the spectators - GTR_EMERALDHUNT = 1<<17, // Emerald Hunt - GTR_SPAWNENEMIES = 1<<18, // Spawn enemies - GTR_ALLOWEXIT = 1<<19, // Allow exit sectors - GTR_ROUNDENDMESSAGE = 1<<20, // Prints "The round has ended." into the console - GTR_NOTITLECARD = 1<<21, // Don't show the title card - GTR_POINTLIMIT = 1<<22, // Ringslinger point limit - GTR_TIMELIMIT = 1<<23, // Ringslinger time limit - GTR_OVERTIME = 1<<24, // Allow overtime + GTR_SPECIALSTAGES = 1<<17, // Allow special stages + GTR_EMERALDTOKENS = 1<<18, // Spawn emerald tokens + GTR_EMERALDHUNT = 1<<19, // Emerald Hunt + GTR_SPAWNENEMIES = 1<<20, // Spawn enemies + GTR_ALLOWEXIT = 1<<21, // Allow exit sectors + GTR_ROUNDENDMESSAGE = 1<<22, // Prints "The round has ended." into the console + GTR_NOTITLECARD = 1<<23, // Don't show the title card + GTR_POINTLIMIT = 1<<24, // Ringslinger point limit + GTR_TIMELIMIT = 1<<25, // Ringslinger time limit + GTR_OVERTIME = 1<<26, // Allow overtime }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 2675930a4..74fd82be6 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3088,9 +3088,9 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Co-op - GTR_PLATFORM|GTR_LIVES|GTR_CHASECAM|GTR_EMERALDHUNT|GTR_SPAWNENEMIES|GTR_ALLOWEXIT, + GTR_PLATFORM|GTR_LIVES|GTR_CHASECAM|GTR_EMERALDHUNT|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, // Competition - GTR_PLATFORM|GTR_LIVES|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_ROUNDENDMESSAGE, + GTR_PLATFORM|GTR_LIVES|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_ROUNDENDMESSAGE|GTR_EMERALDTOKENS, // Race GTR_PLATFORM|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_ROUNDENDMESSAGE, @@ -3530,7 +3530,7 @@ static void G_DoCompleted(void) if (nextmap >= 1100-1 && nextmap <= 1102-1 && (gametyperules & GTR_RACE)) nextmap = (INT16)(spstage_start-1); - if ((gottoken = (gametype == GT_COOP && token))) + if ((gottoken = ((gametyperules & GTR_SPECIALSTAGES) && token))) { token--; diff --git a/src/p_inter.c b/src/p_inter.c index 900435a99..08e8a62a1 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -625,7 +625,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_AddPlayerScore(player, 1000); - if (gametype != GT_COOP || modeattacking) // score only? + if (!(gametyperules & GTR_SPECIALSTAGES) || modeattacking) // score only? { S_StartSound(toucher, sfx_chchng); break; diff --git a/src/p_mobj.c b/src/p_mobj.c index 8c5497e26..c85d2566c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11811,7 +11811,7 @@ You should think about modifying the deathmatch starts to take full advantage of return; // no doubles } - if (i == MT_TOKEN && ((gametype != GT_COOP && gametype != GT_COMPETITION) || tokenbits == 30 || tokenlist & (1 << tokenbits++))) + if (i == MT_TOKEN && (!(gametyperules & GTR_EMERALDTOKENS) || tokenbits == 30 || tokenlist & (1 << tokenbits++))) return; // you already got this token, or there are too many, or the gametype's not right if (i == MT_EMBLEM && (netgame || multiplayer || (modifiedgame && !savemoddata))) // No cheating!! From ef7e53488db6cf25cf777a530603943597d85116 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 22:50:49 -0300 Subject: [PATCH 078/312] GTR_CAMPAIGN and GTR_NOGAMEEND --- src/doomstat.h | 12 +++++++----- src/g_game.c | 10 +++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index b79edb93c..6730254a2 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -416,11 +416,13 @@ enum GameTypeRules GTR_EMERALDHUNT = 1<<19, // Emerald Hunt GTR_SPAWNENEMIES = 1<<20, // Spawn enemies GTR_ALLOWEXIT = 1<<21, // Allow exit sectors - GTR_ROUNDENDMESSAGE = 1<<22, // Prints "The round has ended." into the console - GTR_NOTITLECARD = 1<<23, // Don't show the title card - GTR_POINTLIMIT = 1<<24, // Ringslinger point limit - GTR_TIMELIMIT = 1<<25, // Ringslinger time limit - GTR_OVERTIME = 1<<26, // Allow overtime + GTR_CAMPAIGN = 1<<22, // Linear Co-op map progression. Don't allow random maps. + GTR_NOGAMEEND = 1<<23, // Don't end the game. That is, wrap around the maps instead of starting the ending. + GTR_ROUNDENDMESSAGE = 1<<24, // Prints "The round has ended." into the console + GTR_NOTITLECARD = 1<<25, // Don't show the title card + GTR_POINTLIMIT = 1<<26, // Ringslinger point limit + GTR_TIMELIMIT = 1<<27, // Ringslinger time limit + GTR_OVERTIME = 1<<28, // Allow overtime }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 74fd82be6..d73df8139 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3088,11 +3088,11 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Co-op - GTR_PLATFORM|GTR_LIVES|GTR_CHASECAM|GTR_EMERALDHUNT|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, + GTR_PLATFORM|GTR_CAMPAIGN|GTR_LIVES|GTR_CHASECAM|GTR_EMERALDHUNT|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, // Competition - GTR_PLATFORM|GTR_LIVES|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_ROUNDENDMESSAGE|GTR_EMERALDTOKENS, + GTR_PLATFORM|GTR_NOGAMEEND|GTR_LIVES|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_ROUNDENDMESSAGE|GTR_EMERALDTOKENS, // Race - GTR_PLATFORM|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_ROUNDENDMESSAGE, + GTR_PLATFORM|GTR_NOGAMEEND|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_ROUNDENDMESSAGE, // Match GTR_RINGSLINGER|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY|GTR_ROUNDENDMESSAGE, @@ -3527,7 +3527,7 @@ static void G_DoCompleted(void) I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1); // wrap around in race - if (nextmap >= 1100-1 && nextmap <= 1102-1 && (gametyperules & GTR_RACE)) + if (nextmap >= 1100-1 && nextmap <= 1102-1 && (gametyperules & GTR_NOGAMEEND)) nextmap = (INT16)(spstage_start-1); if ((gottoken = ((gametyperules & GTR_SPECIALSTAGES) && token))) @@ -3550,7 +3550,7 @@ static void G_DoCompleted(void) automapactive = false; - if (gametype != GT_COOP) + if (!(gametyperules & GTR_CAMPAIGN)) { if (cv_advancemap.value == 0) // Stay on same map. nextmap = prevmap; From b496cc0d62e220d17c40a14da3b5a07569067919 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 23:02:07 -0300 Subject: [PATCH 079/312] Whoops --- src/dehacked.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index e60bcae5d..871fe72a0 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8924,6 +8924,8 @@ static const char *const GAMETYPERULE_LIST[] = { "EMERALDHUNT", "SPAWNENEMIES", "ALLOWEXIT", + "CAMPAIGN", + "NOGAMEEND", "ROUNDENDMESSAGE", "NOTITLECARD", "POINTLIMIT", From 96cf03b716414bfb28c890d6a1c622896465820a Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 18 Dec 2019 21:28:34 -0500 Subject: [PATCH 080/312] Don't uncurl from spin if Elemental Stomp is used --- src/p_user.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index ea42a2c36..78c5137bc 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -5128,11 +5128,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) boolean elem = ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL); player->pflags |= PF_THOKKED|PF_SHIELDABILITY; if (elem) - { - player->pflags |= PF_NOJUMPDAMAGE; - P_SetPlayerMobjState(player->mo, S_PLAY_FALL); S_StartSound(player->mo, sfx_s3k43); - } else { player->pflags &= ~PF_NOJUMPDAMAGE; From be5fd1a0dbd91e402f9f20fb31d4dc74b3973bbb Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 23:40:58 -0300 Subject: [PATCH 081/312] TeamSwitch hook for Lua --- src/d_netcmd.c | 6 ++++++ src/lua_hook.h | 2 ++ src/lua_hooklib.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++ src/p_user.c | 11 ++++++++++- 4 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 158b1f802..807daa9ef 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2734,6 +2734,12 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) return; } +#ifdef HAVE_BLUA + // Don't switch team, just go away, please, go awaayyyy, aaauuauugghhhghgh + if (!LUAh_TeamSwitch(&players[playernum], NetPacket.packet.newteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled)) + return; +#endif + //no status changes after hidetime if ((gametyperules & GTR_HIDEFROZEN) && (leveltime >= (hidetime * TICRATE))) error = true; diff --git a/src/lua_hook.h b/src/lua_hook.h index 592a93acc..524526df2 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -51,6 +51,7 @@ enum hook { hook_PlayerCanDamage, hook_PlayerQuit, hook_IntermissionThinker, + hook_TeamSwitch, hook_ViewpointSwitch, hook_MAX // last hook @@ -94,6 +95,7 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAft UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting void LUAh_IntermissionThinker(void); // Hook for Y_Ticker +boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean autobalance, boolean scrambled); // Hook for team switching in... uh.... UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer); // Hook for spy mode in G_Responder #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index b1f702f7c..08ffeec03 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -62,6 +62,7 @@ const char *const hookNames[hook_MAX+1] = { "PlayerCanDamage", "PlayerQuit", "IntermissionThinker", + "TeamSwitch", "ViewpointSwitch", NULL }; @@ -204,6 +205,7 @@ static int lib_addHook(lua_State *L) case hook_PlayerSpawn: case hook_FollowMobj: case hook_PlayerCanDamage: + case hook_TeamSwitch: case hook_ViewpointSwitch: case hook_ShieldSpawn: case hook_ShieldSpecial: @@ -1348,6 +1350,53 @@ void LUAh_IntermissionThinker(void) } } +// Hook for team switching +// It's just an edit of LUAh_ViewpointSwitch. +boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean autobalance, boolean scrambled) +{ + hook_p hookp; + boolean canSwitchTeam = true; + if (!gL || !(hooksAvailable[hook_TeamSwitch/8] & (1<<(hook_TeamSwitch%8)))) + return 0; + + lua_settop(gL, 0); + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_TeamSwitch) + continue; + + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, player, META_PLAYER); + lua_pushinteger(gL, newteam); + lua_pushboolean(gL, fromspectators); + lua_pushboolean(gL, autobalance); + lua_pushboolean(gL, scrambled); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) + canSwitchTeam = false; // Can't switch team + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return canSwitchTeam; +} + // Hook for spy mode in G_Responder UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer) { diff --git a/src/p_user.c b/src/p_user.c index b8164c173..b6f352450 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10364,6 +10364,11 @@ boolean P_SpectatorJoinGame(player_t *player) else changeto = (P_RandomFixed() & 1) + 1; +#ifdef HAVE_BLUA + if (!LUAh_TeamSwitch(player, changeto, true, false, false)) + return false; +#endif + if (player->mo) { P_RemoveMobj(player->mo); @@ -10389,8 +10394,12 @@ boolean P_SpectatorJoinGame(player_t *player) { // Exception for hide and seek. Don't join a game when you simply // respawn in place and sit there for the rest of the round. - if (!(gametype == GT_HIDEANDSEEK && leveltime > (hidetime * TICRATE))) + if (!((gametyperules & GTR_HIDEFROZEN) && leveltime > (hidetime * TICRATE))) { +#ifdef HAVE_BLUA + if (!LUAh_TeamSwitch(player, 3, true, false, false)) + return false; +#endif if (player->mo) { P_RemoveMobj(player->mo); From 6f857df5e52fc62126b5ff9cd1b90a1a8444d012 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 23:47:17 -0300 Subject: [PATCH 082/312] ViewpointSwitch hack so nobody does anything evil Prints the generic "can't do this in a HUD hook" message. Whatever. I'm tired. --- src/lua_hooklib.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 08ffeec03..9604faf4c 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1406,6 +1406,7 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer) return 0; lua_settop(gL, 0); + hud_running = true; for (hookp = playerhooks; hookp; hookp = hookp->next) { @@ -1439,6 +1440,8 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer) } lua_settop(gL, 0); + hud_running = false; + return canSwitchView; } From 5da55e8b7692ef8bd0ee1147b3578c37469c5950 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 23:53:26 -0300 Subject: [PATCH 083/312] Shadowed variable declarations whoopsie!!! uwu --- src/lua_hook.h | 2 +- src/lua_hooklib.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 524526df2..8d780490e 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -95,7 +95,7 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAft UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting void LUAh_IntermissionThinker(void); // Hook for Y_Ticker -boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean autobalance, boolean scrambled); // Hook for team switching in... uh.... +boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer); // Hook for spy mode in G_Responder #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 9604faf4c..0393a3577 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1352,7 +1352,7 @@ void LUAh_IntermissionThinker(void) // Hook for team switching // It's just an edit of LUAh_ViewpointSwitch. -boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean autobalance, boolean scrambled) +boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble) { hook_p hookp; boolean canSwitchTeam = true; @@ -1371,8 +1371,8 @@ boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, b LUA_PushUserdata(gL, player, META_PLAYER); lua_pushinteger(gL, newteam); lua_pushboolean(gL, fromspectators); - lua_pushboolean(gL, autobalance); - lua_pushboolean(gL, scrambled); + lua_pushboolean(gL, tryingautobalance); + lua_pushboolean(gL, tryingscramble); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); From e4b4b60cb6e38760b6a795795acde922b136c55b Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 00:15:19 -0300 Subject: [PATCH 084/312] Remove this debugging command, as I don't need it anymore. --- src/d_netcmd.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 807daa9ef..2a4bc75a7 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -125,7 +125,6 @@ static void Command_Version_f(void); static void Command_ModDetails_f(void); #endif static void Command_ShowGametype_f(void); -static void Command_SetGametype_f(void); FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void); static void Command_Playintro_f(void); @@ -488,7 +487,6 @@ void D_RegisterServerCommands(void) COM_AddCommand("suicide", Command_Suicide); COM_AddCommand("gametype", Command_ShowGametype_f); - COM_AddCommand("setgametype", Command_SetGametype_f); COM_AddCommand("version", Command_Version_f); #ifdef UPDATE_ALERT COM_AddCommand("mod_details", Command_ModDetails_f); @@ -3643,16 +3641,6 @@ static void Command_ShowGametype_f(void) CONS_Printf(M_GetText("Unknown gametype set (%d)\n"), gametype); } -static void Command_SetGametype_f(void) -{ - if (COM_Argc() > 1) - { - INT16 oldgametype = gametype; - G_SetGametype(atoi(COM_Argv(1))); - D_GameTypeChanged(oldgametype); - } -} - /** Plays the intro. */ static void Command_Playintro_f(void) From 00440224d2d6a25afe5347565d26b7509d2c66fa Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 00:31:13 -0300 Subject: [PATCH 085/312] De-fuck team change --- src/lua_hooklib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 0393a3577..d213bd307 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1357,7 +1357,7 @@ boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, b hook_p hookp; boolean canSwitchTeam = true; if (!gL || !(hooksAvailable[hook_TeamSwitch/8] & (1<<(hook_TeamSwitch%8)))) - return 0; + return true; lua_settop(gL, 0); From d401ba558dea325841bbf9b1112505ae0af7715f Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 19 Dec 2019 12:03:36 +0800 Subject: [PATCH 086/312] Fix pflags not being properly reset when entering dust devil from top --- src/p_enemy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 5361f453b..6b60a697f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -13614,12 +13614,12 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing) } else { //Player on the top of the tornado. + P_ResetPlayer(player); thing->z = dustdevil->z + dustdevil->height; thrust = 20 * FRACUNIT; player->powers[pw_nocontrol] = 0; S_StartSound(thing, sfx_wdjump); P_SetPlayerMobjState(thing, S_PLAY_FALL); - player->pflags &= ~PF_JUMPED; } thing->momz = thrust; From fb6f2fc9b0a232ad4d994757156e82f22459d135 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 02:13:09 -0300 Subject: [PATCH 087/312] Lua! Lua! Lua! Expecting the buildbot to complain --- src/dehacked.c | 61 ++++++---------------- src/g_game.c | 56 ++++++++++++++++++++ src/g_game.h | 1 + src/lua_baselib.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 202 insertions(+), 46 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 871fe72a0..5301bef68 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1146,7 +1146,6 @@ static void readgametype(MYFILE *f, char *gtname) char *word; char *word2, *word2lwr = NULL; char *tmp; - char *gtconst; INT32 i, j; INT16 newgtidx = 0; @@ -1326,51 +1325,7 @@ static void readgametype(MYFILE *f, char *gtname) Gametype_Names[newgtidx] = Z_StrDup((const char *)gtname); // Write the constant name. - gtconst = Z_Malloc(strlen((const char *)gtname) + 3, PU_STATIC, NULL); - // Copy GT_ and the gametype name. - strcpy(gtconst, "GT_"); - strcat(gtconst, (const char *)gtname); - // Make uppercase. - strupr(gtconst); - // Remove characters. -#define REMOVECHAR(chr) \ - word = strchr(gtconst, chr); \ - while (word) \ - { \ - *word = '_'; \ - word = strchr(word, chr); \ - } - - // Space - REMOVECHAR(' ') - // Used for operations - REMOVECHAR('+') - REMOVECHAR('-') - REMOVECHAR('*') - REMOVECHAR('/') - REMOVECHAR('%') - REMOVECHAR('^') - // Part of Lua's syntax - REMOVECHAR('#') - REMOVECHAR('=') - REMOVECHAR('~') - REMOVECHAR('<') - REMOVECHAR('>') - REMOVECHAR('(') - REMOVECHAR(')') - REMOVECHAR('{') - REMOVECHAR('}') - REMOVECHAR('[') - REMOVECHAR(']') - REMOVECHAR(':') - REMOVECHAR(';') - REMOVECHAR(',') - REMOVECHAR('.') - -#undef REMOVECHAR - - // Finally, set the constant string. - Gametype_ConstantNames[newgtidx] = gtconst; + G_AddGametypeConstant(newgtidx, (const char *)gtname); // Update gametype_cons_t accordingly. G_UpdateGametypeSelections(); @@ -10439,6 +10394,20 @@ static inline int lib_freeslot(lua_State *L) } r++; } + else if (fastcmp(type, "TOL")) + { + if (lastcustomtol > 31) + CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n"); + else + { + UINT32 newtol = (1<') + REMOVECHAR('(') + REMOVECHAR(')') + REMOVECHAR('{') + REMOVECHAR('}') + REMOVECHAR('[') + REMOVECHAR(']') + REMOVECHAR(':') + REMOVECHAR(';') + REMOVECHAR(',') + REMOVECHAR('.') + +#undef REMOVECHAR + + // Finally, set the constant string. + Gametype_ConstantNames[gtype] = gtconst; +} + // // G_UpdateGametypeSelections // diff --git a/src/g_game.h b/src/g_game.h index bd0dc0180..de644756f 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -207,6 +207,7 @@ extern INT16 gametyperankings[NUMGAMETYPES]; void G_SetGametype(INT16 gametype); INT16 G_AddGametype(UINT32 rules); +void G_AddGametypeConstant(INT16 gtype, const char *newgtconst); void G_UpdateGametypeSelections(void); void G_AddTOL(UINT32 newtol, const char *tolname); void G_AddGametypeTOL(INT16 gtype, UINT32 newtol); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index b68d16c2a..450da6576 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -12,6 +12,7 @@ #include "doomdef.h" #ifdef HAVE_BLUA +#include "fastcmp.h" #include "p_local.h" #include "p_setup.h" // So we can have P_SetupLevelSky #ifdef ESLOPE @@ -23,6 +24,7 @@ #include "m_random.h" #include "s_sound.h" #include "g_game.h" +#include "y_inter.h" #include "hu_stuff.h" // HU_AddChatText #include "console.h" #include "d_netcmd.h" // IsPlayerAdmin @@ -2632,6 +2634,133 @@ static int lib_sStartMusicCaption(lua_State *L) // G_GAME //////////// +// Copypasted from lib_cvRegisterVar :] +static int lib_gAddGametype(lua_State *L) +{ + const char *k; + lua_Integer i; + + const char *gtname = NULL; + const char *gtdescription = NULL; + INT16 newgtidx = 0; + UINT32 newgtrules = 0; + UINT32 newgttol = 0; + INT32 newgtpointlimit = 0; + INT32 newgttimelimit = 0; + UINT8 newgtleftcolor = 0; + UINT8 newgtrightcolor = 0; + INT16 newgtrankingstype = -1; + int newgtinttype = 0; + + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one. + + if (!lua_lumploading) + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); + +#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("G_AddGametype") " (%s)", e); +#define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1))) + + lua_pushnil(L); + while (lua_next(L, 1)) { + // stack: gametype table, key/index, value + // 1 2 3 + i = 0; + k = NULL; + if (lua_isnumber(L, 2)) + i = lua_tointeger(L, 2); + else if (lua_isstring(L, 2)) + k = lua_tostring(L, 2); + + // Sorry, no gametype rules as key names. + if (i == 1 || (k && fasticmp(k, "name"))) { + if (!lua_isstring(L, 3)) + TYPEERROR("name", LUA_TSTRING) + gtname = Z_StrDup(lua_tostring(L, 3)); + } else if (i == 2 || (k && fasticmp(k, "rules"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("rules", LUA_TNUMBER) + newgtrules = (UINT32)lua_tointeger(L, 3); + } else if (i == 3 || (k && fasticmp(k, "typeoflevel"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("typeoflevel", LUA_TNUMBER) + newgttol = (UINT32)lua_tointeger(L, 3); + } else if (i == 4 || (k && fasticmp(k, "rankingtype"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("rankingtype", LUA_TNUMBER) + newgtrankingstype = (INT16)lua_tointeger(L, 3); + } else if (i == 5 || (k && fasticmp(k, "intermissiontype"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("intermissiontype", LUA_TNUMBER) + newgtinttype = (int)lua_tointeger(L, 3); + } else if (i == 6 || (k && fasticmp(k, "defaultpointlimit"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("defaultpointlimit", LUA_TNUMBER) + newgtpointlimit = (INT32)lua_tointeger(L, 3); + } else if (i == 7 || (k && fasticmp(k, "defaulttimelimit"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("defaulttimelimit", LUA_TNUMBER) + newgttimelimit = (INT32)lua_tointeger(L, 3); + } else if (i == 8 || (k && fasticmp(k, "description"))) { + if (!lua_isstring(L, 3)) + TYPEERROR("description", LUA_TSTRING) + gtdescription = Z_StrDup(lua_tostring(L, 3)); + } else if (i == 9 || (k && fasticmp(k, "headerleftcolor"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("headerleftcolor", LUA_TNUMBER) + newgtleftcolor = (UINT8)lua_tointeger(L, 3); + } else if (i == 10 || (k && fasticmp(k, "headerrightcolor"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("headerrightcolor", LUA_TNUMBER) + newgtrightcolor = (UINT8)lua_tointeger(L, 3); + // Key name specified + } else if ((!i) && (k && fasticmp(k, "headercolor"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("headercolor", LUA_TNUMBER) + newgtleftcolor = newgtrightcolor = (UINT8)lua_tointeger(L, 3); + } + lua_pop(L, 1); + } + +#undef FIELDERROR +#undef TYPEERROR + + // pop gametype table + lua_pop(L, 1); + + // Set defaults + if (gtname == NULL) + gtname = Z_StrDup("Unnamed gametype"); + if (gtdescription == NULL) + gtdescription = Z_StrDup("???"); + + // Add the new gametype + newgtidx = G_AddGametype(newgtrules); + G_AddGametypeTOL(newgtidx, newgttol); + G_SetGametypeDescription(newgtidx, (char *)gtdescription, newgtleftcolor, newgtrightcolor); + + // Not covered by G_AddGametype alone. + if (newgtrankingstype == -1) + newgtrankingstype = newgtidx; + gametyperankings[newgtidx] = newgtrankingstype; + intermissiontypes[newgtidx] = newgtinttype; + pointlimits[newgtidx] = newgtpointlimit; + timelimits[newgtidx] = newgttimelimit; + + // Write the new gametype name. + Gametype_Names[newgtidx] = gtname; + + // Write the constant name. + G_AddGametypeConstant(newgtidx, gtname); + + // Update gametype_cons_t accordingly. + G_UpdateGametypeSelections(); + + // done + CONS_Printf("Added gametype %s\n", Gametype_Names[newgtidx]); + return 0; +} + static int lib_gBuildMapName(lua_State *L) { INT32 map = luaL_optinteger(L, 1, gamemap); @@ -2997,6 +3126,7 @@ static luaL_Reg lib[] = { {"S_StartMusicCaption", lib_sStartMusicCaption}, // g_game + {"G_AddGametype", lib_gAddGametype}, {"G_BuildMapName",lib_gBuildMapName}, {"G_DoReborn",lib_gDoReborn}, {"G_SetCustomExitVars",lib_gSetCustomExitVars}, From 019e52a4f431ad93075a719bab64a4d0d80fa22d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 02:17:03 -0300 Subject: [PATCH 088/312] allow CTF spawns in GTR_TEAMS gametype rule --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 7c00f0131..96a7ed423 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2574,7 +2574,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) // -- CTF -- // Order: CTF->DM->Coop - if ((gametyperules & GTR_TEAMFLAGS) && players[playernum].ctfteam) + if ((gametyperules & (GTR_TEAMFLAGS|GTR_TEAMS)) && players[playernum].ctfteam) { if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start From ebdd9c62572076bcd4dd151ebba1f5bf47d40a1a Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 02:20:49 -0300 Subject: [PATCH 089/312] fix warnings --- src/g_game.c | 3 ++- src/lua_baselib.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 96a7ed423..0c085c84e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3220,7 +3220,8 @@ void G_UpdateGametypeSelections(void) // void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolor, UINT8 rightcolor) { - strncpy(gametypedesc[gtype].notes, descriptiontext, 441); + if (descriptiontext != NULL) + strncpy(gametypedesc[gtype].notes, descriptiontext, 441); gametypedesc[gtype].col[0] = leftcolor; gametypedesc[gtype].col[1] = rightcolor; } diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 7ff967b40..5f9d3dbf6 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -24,6 +24,7 @@ #include "m_random.h" #include "s_sound.h" #include "g_game.h" +#include "m_menu.h" #include "y_inter.h" #include "hu_stuff.h" // HU_AddChatText #include "console.h" @@ -2737,7 +2738,8 @@ static int lib_gAddGametype(lua_State *L) // Add the new gametype newgtidx = G_AddGametype(newgtrules); G_AddGametypeTOL(newgtidx, newgttol); - G_SetGametypeDescription(newgtidx, (char *)gtdescription, newgtleftcolor, newgtrightcolor); + G_SetGametypeDescription(newgtidx, NULL, newgtleftcolor, newgtrightcolor); + strncpy(gametypedesc[newgtidx].notes, gtdescription, 441); // Not covered by G_AddGametype alone. if (newgtrankingstype == -1) From ce0e4201b810c1cdd2d3a19f99bfe485f6d2ac3b Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 02:26:17 -0300 Subject: [PATCH 090/312] GTR_DEATHMATCHSTARTS --- src/dehacked.c | 1 + src/doomstat.h | 25 +++++++++++++------------ src/g_game.c | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 9b4656627..dedeeb87f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8874,6 +8874,7 @@ static const char *const GAMETYPERULE_LIST[] = { "PITYSHIELD", "DEATHPENALTY", "NOSPECTATORSPAWN", + "DEATHMATCHSTARTS", "SPECIALSTAGES", "EMERALDTOKENS", "EMERALDHUNT", diff --git a/src/doomstat.h b/src/doomstat.h index 6730254a2..d24de58f1 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -411,18 +411,19 @@ enum GameTypeRules GTR_PITYSHIELD = 1<<14, // Award pity shield GTR_DEATHPENALTY = 1<<15, // Death score penalty GTR_NOSPECTATORSPAWN = 1<<16, // For use with GTR_SPECTATORS - spawn in the map instead of with the spectators - GTR_SPECIALSTAGES = 1<<17, // Allow special stages - GTR_EMERALDTOKENS = 1<<18, // Spawn emerald tokens - GTR_EMERALDHUNT = 1<<19, // Emerald Hunt - GTR_SPAWNENEMIES = 1<<20, // Spawn enemies - GTR_ALLOWEXIT = 1<<21, // Allow exit sectors - GTR_CAMPAIGN = 1<<22, // Linear Co-op map progression. Don't allow random maps. - GTR_NOGAMEEND = 1<<23, // Don't end the game. That is, wrap around the maps instead of starting the ending. - GTR_ROUNDENDMESSAGE = 1<<24, // Prints "The round has ended." into the console - GTR_NOTITLECARD = 1<<25, // Don't show the title card - GTR_POINTLIMIT = 1<<26, // Ringslinger point limit - GTR_TIMELIMIT = 1<<27, // Ringslinger time limit - GTR_OVERTIME = 1<<28, // Allow overtime + GTR_DEATHMATCHSTARTS = 1<<17, // Use deathmatch starts + GTR_SPECIALSTAGES = 1<<18, // Allow special stages + GTR_EMERALDTOKENS = 1<<19, // Spawn emerald tokens + GTR_EMERALDHUNT = 1<<20, // Emerald Hunt + GTR_SPAWNENEMIES = 1<<21, // Spawn enemies + GTR_ALLOWEXIT = 1<<22, // Allow exit sectors + GTR_CAMPAIGN = 1<<23, // Linear Co-op map progression. Don't allow random maps. + GTR_NOGAMEEND = 1<<24, // Don't end the game. That is, wrap around the maps instead of starting the ending. + GTR_ROUNDENDMESSAGE = 1<<25, // Prints "The round has ended." into the console + GTR_NOTITLECARD = 1<<26, // Don't show the title card + GTR_POINTLIMIT = 1<<27, // Ringslinger point limit + GTR_TIMELIMIT = 1<<28, // Ringslinger time limit + GTR_OVERTIME = 1<<29, // Allow overtime }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 0c085c84e..9c51e4741 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2583,7 +2583,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) // -- DM/Tag/CTF-spectator/etc -- // Order: DM->CTF->Coop - else if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF + else if ((gametyperules & GTR_DEATHMATCHSTARTS) || gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT))) { if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start From 768080977fea335d7d4da77fc434ba495464ca04 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 15:47:37 -0300 Subject: [PATCH 091/312] Remove GTR_ROUNDENDMESSAGE --- src/dehacked.c | 1 - src/doomstat.h | 9 ++++----- src/g_game.c | 16 ++++++++-------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index dedeeb87f..84abc9139 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8882,7 +8882,6 @@ static const char *const GAMETYPERULE_LIST[] = { "ALLOWEXIT", "CAMPAIGN", "NOGAMEEND", - "ROUNDENDMESSAGE", "NOTITLECARD", "POINTLIMIT", "TIMELIMIT", diff --git a/src/doomstat.h b/src/doomstat.h index d24de58f1..58d9d4896 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -419,11 +419,10 @@ enum GameTypeRules GTR_ALLOWEXIT = 1<<22, // Allow exit sectors GTR_CAMPAIGN = 1<<23, // Linear Co-op map progression. Don't allow random maps. GTR_NOGAMEEND = 1<<24, // Don't end the game. That is, wrap around the maps instead of starting the ending. - GTR_ROUNDENDMESSAGE = 1<<25, // Prints "The round has ended." into the console - GTR_NOTITLECARD = 1<<26, // Don't show the title card - GTR_POINTLIMIT = 1<<27, // Ringslinger point limit - GTR_TIMELIMIT = 1<<28, // Ringslinger time limit - GTR_OVERTIME = 1<<29, // Allow overtime + GTR_NOTITLECARD = 1<<25, // Don't show the title card + GTR_POINTLIMIT = 1<<26, // Ringslinger point limit + GTR_TIMELIMIT = 1<<27, // Ringslinger time limit + GTR_OVERTIME = 1<<28, // Allow overtime }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 9c51e4741..80fa42dea 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3036,7 +3036,7 @@ void G_ExitLevel(void) CV_SetValue(&cv_teamscramble, cv_scrambleonchange.value); } - if (gametyperules & GTR_ROUNDENDMESSAGE) + if (!(gametyperules & GTR_CAMPAIGN)) CONS_Printf(M_GetText("The round has ended.\n")); // Remove CEcho text on round end. @@ -3090,22 +3090,22 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = // Co-op GTR_PLATFORM|GTR_CAMPAIGN|GTR_LIVES|GTR_CHASECAM|GTR_EMERALDHUNT|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, // Competition - GTR_PLATFORM|GTR_NOGAMEEND|GTR_LIVES|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_ROUNDENDMESSAGE|GTR_EMERALDTOKENS, + GTR_PLATFORM|GTR_NOGAMEEND|GTR_LIVES|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDTOKENS, // Race - GTR_PLATFORM|GTR_NOGAMEEND|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_ROUNDENDMESSAGE, + GTR_PLATFORM|GTR_NOGAMEEND|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT, // Match - GTR_RINGSLINGER|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY, // Team Match - GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_PITYSHIELD|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_PITYSHIELD, // Tag - GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, // Hide and Seek - GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, // CTF - GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD|GTR_ROUNDENDMESSAGE, + GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD, }; // From 6d7262e9855409b128dbeed1495ba0a2cca39be6 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 16:05:03 -0300 Subject: [PATCH 092/312] Remove GTR_PLATFORM --- src/dehacked.c | 2 +- src/doomstat.h | 2 +- src/g_game.c | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 84abc9139..e078d2f69 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8857,7 +8857,7 @@ static const char *const PLAYERFLAG_LIST[] = { }; static const char *const GAMETYPERULE_LIST[] = { - "PLATFORM", + "\x01", "TAG", "RINGSLINGER", "SPECTATORS", diff --git a/src/doomstat.h b/src/doomstat.h index 58d9d4896..0abc6a467 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -389,7 +389,7 @@ enum GameType // Game type rules enum GameTypeRules { - GTR_PLATFORM = 1, // Co-op, Competition, and Race + GTR_SORRYNOTHING = 1, GTR_TAG = 1<<1, // Tag and Hide and Seek GTR_RINGSLINGER = 1<<2, // Not Co-op, not Competition, and not Race (overriden by cv_ringslinger) GTR_SPECTATORS = 1<<3, // Not Co-op, not Competition, and not Race diff --git a/src/g_game.c b/src/g_game.c index 80fa42dea..2e25b5c2f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3088,11 +3088,11 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Co-op - GTR_PLATFORM|GTR_CAMPAIGN|GTR_LIVES|GTR_CHASECAM|GTR_EMERALDHUNT|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, + GTR_CAMPAIGN|GTR_LIVES|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, // Competition - GTR_PLATFORM|GTR_NOGAMEEND|GTR_LIVES|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDTOKENS, + GTR_RACE|GTR_LIVES|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_ALLOWEXIT|GTR_NOGAMEEND, // Race - GTR_PLATFORM|GTR_NOGAMEEND|GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT, + GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_NOGAMEEND, // Match GTR_RINGSLINGER|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY, @@ -3378,8 +3378,7 @@ boolean G_RingSlingerGametype(void) // boolean G_PlatformGametype(void) { - return (gametyperules & GTR_PLATFORM); - //return (gametype == GT_COOP || gametype == GT_RACE || gametype == GT_COMPETITION); + return (!G_RingSlingerGametype()); } // From f4bb618f9387f1045a7ae03433b2858adead2a84 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 16:12:10 -0300 Subject: [PATCH 093/312] Organise rules --- src/dehacked.c | 19 ++++++++-------- src/doomstat.h | 60 +++++++++++++++++++++++--------------------------- src/g_game.c | 4 ++-- src/p_mobj.c | 2 +- 4 files changed, 39 insertions(+), 46 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index e078d2f69..a4467c699 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8857,19 +8857,21 @@ static const char *const PLAYERFLAG_LIST[] = { }; static const char *const GAMETYPERULE_LIST[] = { - "\x01", - "TAG", + "CAMPAIGN", "RINGSLINGER", "SPECTATORS", - "TEAMS", - "LIVES", - "RACE", - "CHASECAM", "FRIENDLYFIRE", + "LIVES", + "TEAMS", + "RACE", + "TAG", + "POINTLIMIT", + "TIMELIMIT", "HIDETIME", "HIDEFROZEN", "BLINDFOLDED", - "EMERALDS", + "CHASECAM", + "MATCHEMERALDS", "TEAMFLAGS", "PITYSHIELD", "DEATHPENALTY", @@ -8880,11 +8882,8 @@ static const char *const GAMETYPERULE_LIST[] = { "EMERALDHUNT", "SPAWNENEMIES", "ALLOWEXIT", - "CAMPAIGN", "NOGAMEEND", "NOTITLECARD", - "POINTLIMIT", - "TIMELIMIT", "OVERTIME", NULL }; diff --git a/src/doomstat.h b/src/doomstat.h index 0abc6a467..c8d3b492a 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -389,40 +389,34 @@ enum GameType // Game type rules enum GameTypeRules { - GTR_SORRYNOTHING = 1, - GTR_TAG = 1<<1, // Tag and Hide and Seek - GTR_RINGSLINGER = 1<<2, // Not Co-op, not Competition, and not Race (overriden by cv_ringslinger) - GTR_SPECTATORS = 1<<3, // Not Co-op, not Competition, and not Race - GTR_TEAMS = 1<<4, // Team Match, CTF - GTR_LIVES = 1<<5, // A lot of special cases in G_GametypeUsesLives actually, but just Co-op and Competition + GTR_CAMPAIGN = 1, // Linear Co-op map progression. Don't allow random maps. + GTR_RINGSLINGER = 1<<1, // Outside of Co-op, Competition, and Race (overriden by cv_ringslinger) + GTR_SPECTATORS = 1<<2, // Outside of Co-op, Competition, and Race + GTR_FRIENDLYFIRE = 1<<3, // Always allow friendly fire + GTR_LIVES = 1<<4, // Co-op and Competition + GTR_TEAMS = 1<<5, // Team Match, CTF GTR_RACE = 1<<6, // Race and Competition - - // Lactozilla - // Awesome! Those are new game type rules provided by yours truly to allow for more - // flexibility! Those will replace some straight-up gametype checks scattered around the source code! - - GTR_CHASECAM = 1<<7, // Prefer chasecam at map load (All platform gametypes) - GTR_FRIENDLYFIRE = 1<<8, // Always allow friendly fire - GTR_HIDETIME = 1<<9, // Hide time (Tag and Hide and Seek) - GTR_HIDEFROZEN = 1<<10, // Frozen after hide time (Hide and Seek, but not Tag) - GTR_BLINDFOLDED = 1<<11, // Blindfolded view (Tag and Hide and Seek) - GTR_EMERALDS = 1<<12, // Ringslinger emeralds (Match and CTF) - GTR_TEAMFLAGS = 1<<13, // Gametype has team flags (CTF) - GTR_PITYSHIELD = 1<<14, // Award pity shield - GTR_DEATHPENALTY = 1<<15, // Death score penalty - GTR_NOSPECTATORSPAWN = 1<<16, // For use with GTR_SPECTATORS - spawn in the map instead of with the spectators - GTR_DEATHMATCHSTARTS = 1<<17, // Use deathmatch starts - GTR_SPECIALSTAGES = 1<<18, // Allow special stages - GTR_EMERALDTOKENS = 1<<19, // Spawn emerald tokens - GTR_EMERALDHUNT = 1<<20, // Emerald Hunt - GTR_SPAWNENEMIES = 1<<21, // Spawn enemies - GTR_ALLOWEXIT = 1<<22, // Allow exit sectors - GTR_CAMPAIGN = 1<<23, // Linear Co-op map progression. Don't allow random maps. - GTR_NOGAMEEND = 1<<24, // Don't end the game. That is, wrap around the maps instead of starting the ending. - GTR_NOTITLECARD = 1<<25, // Don't show the title card - GTR_POINTLIMIT = 1<<26, // Ringslinger point limit - GTR_TIMELIMIT = 1<<27, // Ringslinger time limit - GTR_OVERTIME = 1<<28, // Allow overtime + GTR_TAG = 1<<7, // Tag and Hide and Seek + GTR_POINTLIMIT = 1<<8, // Ringslinger point limit + GTR_TIMELIMIT = 1<<9, // Ringslinger time limit + GTR_HIDETIME = 1<<10, // Hide time (Tag and Hide and Seek) + GTR_HIDEFROZEN = 1<<11, // Frozen after hide time (Hide and Seek, but not Tag) + GTR_BLINDFOLDED = 1<<12, // Blindfolded view (Tag and Hide and Seek) + GTR_CHASECAM = 1<<13, // Prefer chasecam at map load (All platform gametypes) + GTR_MATCHEMERALDS = 1<<14, // Ringslinger emeralds (Match and CTF) + GTR_TEAMFLAGS = 1<<15, // Gametype has team flags (CTF) + GTR_PITYSHIELD = 1<<16, // Award pity shield + GTR_DEATHPENALTY = 1<<17, // Death score penalty + GTR_NOSPECTATORSPAWN = 1<<18, // For use with GTR_SPECTATORS - spawn in the map instead of with the spectators + GTR_DEATHMATCHSTARTS = 1<<19, // Use deathmatch starts + GTR_SPECIALSTAGES = 1<<20, // Allow special stages + GTR_EMERALDTOKENS = 1<<21, // Spawn emerald tokens + GTR_EMERALDHUNT = 1<<22, // Emerald Hunt + GTR_SPAWNENEMIES = 1<<23, // Spawn enemies + GTR_ALLOWEXIT = 1<<24, // Allow exit sectors + GTR_NOGAMEEND = 1<<25, // Don't end the game. That is, wrap around the maps instead of starting the ending. + GTR_NOTITLECARD = 1<<26, // Don't show the title card + GTR_OVERTIME = 1<<27, // Allow overtime }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 2e25b5c2f..47e1dc9f0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3095,7 +3095,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_NOGAMEEND, // Match - GTR_RINGSLINGER|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY, + GTR_RINGSLINGER|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY, // Team Match GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_PITYSHIELD, @@ -3105,7 +3105,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, // CTF - GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_EMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD, }; // diff --git a/src/p_mobj.c b/src/p_mobj.c index 69d352c5b..dcf3a9127 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11774,7 +11774,7 @@ You should think about modifying the deathmatch starts to take full advantage of if (!cv_powerstones.value) return; - if (!(gametyperules & GTR_EMERALDS)) + if (!(gametyperules & GTR_MATCHEMERALDS)) return; runemeraldmanager = true; From 7efd9662d1c2289451cb54dedefe605a840c9eef Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 16:13:27 -0300 Subject: [PATCH 094/312] Remove GTR_NOGAMEEND --- src/dehacked.c | 1 - src/doomstat.h | 5 ++--- src/g_game.c | 6 +++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index a4467c699..6bad6a6dd 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8882,7 +8882,6 @@ static const char *const GAMETYPERULE_LIST[] = { "EMERALDHUNT", "SPAWNENEMIES", "ALLOWEXIT", - "NOGAMEEND", "NOTITLECARD", "OVERTIME", NULL diff --git a/src/doomstat.h b/src/doomstat.h index c8d3b492a..0ab8c1bff 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -414,9 +414,8 @@ enum GameTypeRules GTR_EMERALDHUNT = 1<<22, // Emerald Hunt GTR_SPAWNENEMIES = 1<<23, // Spawn enemies GTR_ALLOWEXIT = 1<<24, // Allow exit sectors - GTR_NOGAMEEND = 1<<25, // Don't end the game. That is, wrap around the maps instead of starting the ending. - GTR_NOTITLECARD = 1<<26, // Don't show the title card - GTR_OVERTIME = 1<<27, // Allow overtime + GTR_NOTITLECARD = 1<<25, // Don't show the title card + GTR_OVERTIME = 1<<26, // Allow overtime }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 47e1dc9f0..2367f23f4 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3090,9 +3090,9 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = // Co-op GTR_CAMPAIGN|GTR_LIVES|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, // Competition - GTR_RACE|GTR_LIVES|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_ALLOWEXIT|GTR_NOGAMEEND, + GTR_RACE|GTR_LIVES|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_ALLOWEXIT, // Race - GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_NOGAMEEND, + GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT, // Match GTR_RINGSLINGER|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY, @@ -3583,7 +3583,7 @@ static void G_DoCompleted(void) I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1); // wrap around in race - if (nextmap >= 1100-1 && nextmap <= 1102-1 && (gametyperules & GTR_NOGAMEEND)) + if (nextmap >= 1100-1 && nextmap <= 1102-1 && !(gametyperules & GTR_CAMPAIGN)) nextmap = (INT16)(spstage_start-1); if ((gottoken = ((gametyperules & GTR_SPECIALSTAGES) && token))) From a39b6a12861242ce7aaca6a6217eae5dc7e734bb Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 19 Dec 2019 01:14:34 -0500 Subject: [PATCH 095/312] Allow access to bluescore and redscore --- src/dehacked.c | 8 ++++++++ src/lua_script.c | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 6bad6a6dd..8633a31c3 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -10822,6 +10822,12 @@ static inline int lib_getenum(lua_State *L) } else if (fastcmp(word,"paused")) { lua_pushboolean(L, paused); return 1; + } else if (fastcmp(word,"bluescore")) { + lua_pushinteger(L, bluescore); + return 1; + } else if (fastcmp(word,"redscore")) { + lua_pushinteger(L, redscore); + return 1; // begin map vars } else if (fastcmp(word,"spstage_start")) { lua_pushinteger(L, spstage_start); @@ -11035,6 +11041,8 @@ static int lib_getActionName(lua_State *L) return luaL_typerror(L, 1, "action userdata or Lua function"); } + + int LUA_SOCLib(lua_State *L) { lua_register(L,"freeslot",lib_freeslot); diff --git a/src/lua_script.c b/src/lua_script.c index fe3c2f10d..13592815b 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -106,6 +106,17 @@ static int noglobals(lua_State *L) return 0; } + if (fastcmp(csname,"redscore")) + { + redscore = (UINT32)luaL_checkinteger(L, 2); + return 0; + } + else if (fastcmp(csname,"bluescore")) + { + bluescore = (UINT32)luaL_checkinteger(L, 2); + return 0; + } + Z_Free(name); return luaL_error(L, "Implicit global " LUA_QS " prevented. Create a local variable instead.", csname); } From 9b2b526eb49f12e62ed10ea3c9cea7e47f0d04a4 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 16:22:55 -0300 Subject: [PATCH 096/312] Removing commented out code --- src/dehacked.c | 2 +- src/g_game.c | 23 +++-------------------- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 8633a31c3..12014b8b6 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1284,7 +1284,7 @@ static void readgametype(MYFILE *f, char *gtname) UINT32 wordgt = 0; for (j = 0; GAMETYPERULE_LIST[j]; j++) if (fastcmp(word, GAMETYPERULE_LIST[j])) { - if (!j) // GTR_PLATFORM + if (!j) // GTR_CAMPAIGN wordgt |= 1; else wordgt |= (1< Date: Thu, 19 Dec 2019 16:31:38 -0300 Subject: [PATCH 097/312] Make G_PlatformGametype only check the gametype rules, to avoid unintended side effects --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 582d61989..3cc11c4d1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3374,7 +3374,7 @@ boolean G_RingSlingerGametype(void) // boolean G_PlatformGametype(void) { - return (!G_RingSlingerGametype()); + return (!(gametyperules & GTR_RINGSLINGER)); } // From 4ad1727b66770cf9a8467b9c13a4373d31f3ee40 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 17:06:07 -0300 Subject: [PATCH 098/312] Don't spawn End Level Signs without the GTR_ALLOWEXIT rule --- src/p_mobj.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index dcf3a9127..6ee615cdd 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11838,8 +11838,10 @@ You should think about modifying the deathmatch starts to take full advantage of } } - if (!G_PlatformGametype() && (i == MT_SIGN || i == MT_STARPOST)) - return; // Don't spawn exit signs or starposts in wrong game modes + if (!(gametyperules & GTR_ALLOWEXIT) && i == MT_SIGN) + return; // Don't spawn exit signs without the necessary gametype rule + if (!G_PlatformGametype() && i == MT_STARPOST) + return; // Don't spawn starposts in wrong game modes if (modeattacking) // Record Attack special stuff { From 551828607c83eb90cb9f66e90024f563f92192d4 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 17:25:19 -0300 Subject: [PATCH 099/312] Load SPR_ lumps as SpriteInfo --- src/r_patch.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/r_patch.c b/src/r_patch.c index 8d300f041..7c9d0ea83 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1087,12 +1087,9 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) for (i = 0; i < numlumps; i++, lumpinfo++) { name = lumpinfo->name; - // load SPRTINFO lumps - if (!stricmp(name, "SPRTINFO")) + // Load SPRTINFO and SPR_ lumps as SpriteInfo + if (!memcmp(name, "SPRTINFO", 8) || !memcmp(name, "SPR_", 4)) R_ParseSPRTINFOLump(wadnum, i); - // load SPR_ lumps (as DEHACKED lump) - else if (!memcmp(name, "SPR_", 4)) - DEH_LoadDehackedLumpPwad(wadnum, i, false); } } From 6d7bdf8fdbf827d753011bc12ab92b4ff1c86ba8 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 19 Dec 2019 18:27:11 -0300 Subject: [PATCH 100/312] Lua gametyperules --- src/dehacked.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 12014b8b6..e3fac0a4b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -10909,6 +10909,9 @@ static inline int lib_getenum(lua_State *L) } else if (fastcmp(word,"gametype")) { lua_pushinteger(L, gametype); return 1; + } else if (fastcmp(word,"gametyperules")) { + lua_pushinteger(L, gametyperules); + return 1; } else if (fastcmp(word,"leveltime")) { lua_pushinteger(L, leveltime); return 1; From ace202daf08fdce5a1e7d2475403d2f1cf0c32e4 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Fri, 20 Dec 2019 23:22:45 -0500 Subject: [PATCH 101/312] Fix Amy and Fang being able to attack other players in MP Special Stages --- src/p_inter.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/p_inter.c b/src/p_inter.c index 70fb01fd0..4da942f72 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3426,6 +3426,17 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) return; + // Don't allow players to hurt one another, + // unless cv_friendlyfire is on. + if (!cv_friendlyfire.value) + { + if (inflictor->type == MT_LHRT) + return; + + if (source->player->ctfteam == player->ctfteam) + return; + } + if (player->powers[pw_shield] || player->bot) //If One-Hit Shield { P_RemoveShield(player); From de1d25cf08f649cd7c3726aa47b31c252f323ed9 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Fri, 20 Dec 2019 23:45:32 -0500 Subject: [PATCH 102/312] Fix super theme ending early if invincibility expired --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 7a86d9419..2b82ae697 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1600,7 +1600,7 @@ void P_RestoreMusic(player_t *player) P_PlayJingle(player, JT_SUPER); // Invulnerability - else if (player->powers[pw_invulnerability] > 1) + else if (player->powers[pw_invulnerability] > 1 && !player->powers[pw_super]) { strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14); S_StartCaption(sfx_None, -1, player->powers[pw_invulnerability]); From dacd5614f9589fae25ebfffe463eef7e4fa7fafb Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 22 Dec 2019 17:37:54 +0100 Subject: [PATCH 103/312] Make both NiGHTS hoop types use the same spawning code. As a result, the old generic hoops now use 24 sprites instead of 32. --- src/p_mobj.c | 368 ++++++++++++++++----------------------------------- 1 file changed, 114 insertions(+), 254 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index dea4a7a4d..98b640da5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13082,6 +13082,115 @@ ML_EFFECT5 : Don't stop thinking when too far away mthing->mobj = mobj; } +static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, sector_t* sec, INT32 hoopsize, fixed_t sizefactor) +{ + mobj_t *mobj = NULL; + mobj_t *nextmobj = NULL; + mobj_t *hoopcenter; + TMatrix *pitchmatrix, *yawmatrix; + fixed_t radius = hoopsize*sizefactor; + INT32 i; + angle_t fa; + TVector v, *res; + + z += +#ifdef ESLOPE + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : +#endif + sec->floorheight; + + hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); + hoopcenter->spawnpoint = mthing; + hoopcenter->z -= hoopcenter->height/2; + + P_UnsetThingPosition(hoopcenter); + hoopcenter->x = x; + hoopcenter->y = y; + P_SetThingPosition(hoopcenter); + + // Scale 0-255 to 0-359 =( + hoopcenter->movedir = ((mthing->angle & 255)*360)/256; // Pitch + pitchmatrix = RotateXMatrix(FixedAngle(hoopcenter->movedir << FRACBITS)); + hoopcenter->movecount = (((UINT16)mthing->angle >> 8)*360)/256; // Yaw + yawmatrix = RotateZMatrix(FixedAngle(hoopcenter->movecount << FRACBITS)); + + // For the hoop when it flies away + hoopcenter->extravalue1 = hoopsize; + hoopcenter->extravalue2 = radius/12; + + // Create the hoop! + for (i = 0; i < hoopsize; i++) + { + fa = i*(FINEANGLES/hoopsize); + v[0] = FixedMul(FINECOSINE(fa), radius); + v[1] = 0; + v[2] = FixedMul(FINESINE(fa), radius); + v[3] = FRACUNIT; + + res = VectorMatrixMultiply(v, *pitchmatrix); + M_Memcpy(&v, res, sizeof(v)); + res = VectorMatrixMultiply(v, *yawmatrix); + M_Memcpy(&v, res, sizeof(v)); + + mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOP); + mobj->z -= mobj->height/2; + + if (maptol & TOL_XMAS) + P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); + + P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. + mobj->fuse = 0; + + // Link all the sprites in the hoop together + if (nextmobj) + { + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); + } + else + P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); + + nextmobj = mobj; + } + + // Create the collision detectors! + // Create them until the size is less than 8 + // But always create at least ONE set of collision detectors + do + { + if (hoopsize >= 32) + hoopsize -= 16; + else + hoopsize /= 2; + + radius = hoopsize*sizefactor; + + for (i = 0; i < hoopsize; i++) + { + fa = i*(FINEANGLES/hoopsize); + v[0] = FixedMul(FINECOSINE(fa), radius); + v[1] = 0; + v[2] = FixedMul(FINESINE(fa), radius); + v[3] = FRACUNIT; + + res = VectorMatrixMultiply(v, *pitchmatrix); + M_Memcpy(&v, res, sizeof(v)); + res = VectorMatrixMultiply(v, *yawmatrix); + M_Memcpy(&v, res, sizeof(v)); + + mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOPCOLLIDE); + mobj->z -= mobj->height/2; + + // Link all the collision sprites together. + P_SetTarget(&mobj->hnext, NULL); + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); + + nextmobj = mobj; + } + } while (hoopsize >= 8); +} + void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) { mobjtype_t ringthing = MT_RING; @@ -13101,267 +13210,18 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) // NiGHTS hoop! if (mthing->type == 1705) { - mobj_t *nextmobj = NULL; - mobj_t *hoopcenter; - INT16 spewangle; - z = mthing->options << FRACBITS; - - hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); - - hoopcenter->spawnpoint = mthing; - - // Screw these damn hoops, I need this thinker. - //hoopcenter->flags |= MF_NOTHINK; - - z += -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - - hoopcenter->z = z - hoopcenter->height/2; - - P_UnsetThingPosition(hoopcenter); - hoopcenter->x = x; - hoopcenter->y = y; - P_SetThingPosition(hoopcenter); - - // Scale 0-255 to 0-359 =( - closestangle = FixedAngle(FixedMul((mthing->angle>>8)*FRACUNIT, - 360*(FRACUNIT/256))); - - hoopcenter->movedir = FixedInt(FixedMul((mthing->angle&255)*FRACUNIT, - 360*(FRACUNIT/256))); - hoopcenter->movecount = FixedInt(AngleFixed(closestangle)); - - // For the hoop when it flies away - hoopcenter->extravalue1 = 32; - hoopcenter->extravalue2 = 8 * FRACUNIT; - - spewangle = (INT16)hoopcenter->movedir; - - // Create the hoop! - for (i = 0; i < 32; i++) - { - fa = i*(FINEANGLES/32); - v[0] = FixedMul(FINECOSINE(fa),96*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),96*FRACUNIT); - v[3] = FRACUNIT; - - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP); - - if (maptol & TOL_XMAS) - P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); - - mobj->z -= mobj->height/2; - P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. - mobj->fuse = 0; - - // Link all the sprites in the hoop together - if (nextmobj) - { - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - } - else - P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); - - nextmobj = mobj; - } - - // Create the collision detectors! - for (i = 0; i < 16; i++) - { - fa = i*FINEANGLES/16; - v[0] = FixedMul(FINECOSINE(fa),32*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),32*FRACUNIT); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - P_SetTarget(&mobj->hnext, NULL); - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - - nextmobj = mobj; - } - // Create the collision detectors! - for (i = 0; i < 16; i++) - { - fa = i*FINEANGLES/16; - v[0] = FixedMul(FINECOSINE(fa),64*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),64*FRACUNIT); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - P_SetTarget(&mobj->hnext, NULL); - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - - nextmobj = mobj; - } + P_SpawnHoop(mthing, x, y, z, sec, 24, 4*FRACUNIT); return; } // CUSTOMIZABLE NiGHTS hoop! else if (mthing->type == 1713) { - mobj_t *nextmobj = NULL; - mobj_t *hoopcenter; - INT16 spewangle; - INT32 hoopsize; - INT32 hoopplacement; - - // Save our flags! - z = (mthing->options>>ZSHIFT) << FRACBITS; - - hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); - hoopcenter->spawnpoint = mthing; - - z += -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - hoopcenter->z = z - hoopcenter->height/2; - - P_UnsetThingPosition(hoopcenter); - hoopcenter->x = x; - hoopcenter->y = y; - P_SetThingPosition(hoopcenter); - - // Scale 0-255 to 0-359 =( - closestangle = FixedAngle(FixedMul((mthing->angle>>8)*FRACUNIT, - 360*(FRACUNIT/256))); - - hoopcenter->movedir = FixedInt(FixedMul((mthing->angle&255)*FRACUNIT, - 360*(FRACUNIT/256))); - hoopcenter->movecount = FixedInt(AngleFixed(closestangle)); - - spewangle = (INT16)hoopcenter->movedir; - // Super happy fun time - // For each flag add 4 fracunits to the size - // Default (0 flags) is 8 fracunits - hoopsize = 8 + (4 * (mthing->options & 0xF)); - hoopplacement = hoopsize * (4*FRACUNIT); - - // For the hoop when it flies away - hoopcenter->extravalue1 = hoopsize; - hoopcenter->extravalue2 = FixedDiv(hoopplacement, 12*FRACUNIT); - - // Create the hoop! - for (i = 0; i < hoopsize; i++) - { - fa = i*(FINEANGLES/hoopsize); - v[0] = FixedMul(FINECOSINE(fa), hoopplacement); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa), hoopplacement); - v[3] = FRACUNIT; - - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP); - - if (maptol & TOL_XMAS) - P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); - - mobj->z -= mobj->height/2; - P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. - mobj->fuse = 0; - - // Link all the sprites in the hoop together - if (nextmobj) - { - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - } - else - P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); - - nextmobj = mobj; - } - - // Create the collision detectors! - // Create them until the size is less than 8 - // But always create at least ONE set of collision detectors - do - { - if (hoopsize >= 32) - hoopsize -= 16; - else - hoopsize /= 2; - - hoopplacement = hoopsize * (4*FRACUNIT); - - for (i = 0; i < hoopsize; i++) - { - fa = i*FINEANGLES/hoopsize; - v[0] = FixedMul(FINECOSINE(fa), hoopplacement); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa), hoopplacement); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - P_SetTarget(&mobj->hnext, NULL); - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - - nextmobj = mobj; - } - } while (hoopsize >= 8); - + // For each flag add 16 fracunits to the size + // Default (0 flags) is 32 fracunits + z = (mthing->options >> ZSHIFT) << FRACBITS; + P_SpawnHoop(mthing, x, y, z, sec, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); return; } // *** From 579362fd3bd0d5dcbda606680459302e408f9b08 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 22 Dec 2019 23:22:15 +0100 Subject: [PATCH 104/312] P_LoadMapData(): Throw an error if resources are not found. --- src/p_setup.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index 14d2cc9e6..bc736588e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1960,6 +1960,17 @@ static void P_LoadMapData(const virtres_t* virt) virtsidedefs = vres_Find(virt, "SIDEDEFS"); virtlinedefs = vres_Find(virt, "LINEDEFS"); + if (!virtthings) + I_Error("THINGS lump not found"); + if (!virtvertexes) + I_Error("VERTEXES lump not found"); + if (!virtsectors) + I_Error("SECTORS lump not found"); + if (!virtsidedefs) + I_Error("SIDEDEFS lump not found"); + if (!virtlinedefs) + I_Error("LINEDEFS lump not found"); + // Traditional doom map format just assumes the number of elements from the lump sizes. numvertexes = virtvertexes->size / sizeof (mapvertex_t); numsectors = virtsectors->size / sizeof (mapsector_t); From 356b25def45606a61e805f68e486264277c52167 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 23 Dec 2019 00:28:06 -0500 Subject: [PATCH 105/312] Spawn Amy's shields for other players --- src/p_inter.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/p_inter.c b/src/p_inter.c index 4da942f72..5ec1161ea 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3430,6 +3430,15 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) // unless cv_friendlyfire is on. if (!cv_friendlyfire.value) { + if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) + { + if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. + { + P_SwitchShield(player, SH_PINK); + S_StartSound(player->mo, mobjinfo[MT_PITY_ICON].seesound); + } + } + if (inflictor->type == MT_LHRT) return; From efb47b3786ad163faf5116cc5eb39fa4ec149b21 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 12:07:03 +0100 Subject: [PATCH 106/312] Move spawning of ring-like items into its own function, use P_GetMobjSpawnHeight() --- src/p_mobj.c | 129 +++++++++++++++++++++++---------------------------- 1 file changed, 57 insertions(+), 72 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 87ec1fe9f..b74c70dd3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11595,13 +11595,21 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* case MT_EMERALDSPAWN: case MT_TOKEN: case MT_EMBLEM: + case MT_RING: + case MT_REDTEAMRING: + case MT_BLUETEAMRING: + case MT_COIN: + case MT_BLUESPHERE: + case MT_BOMBSPHERE: + case MT_NIGHTSCHIP: + case MT_NIGHTSSTAR: offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; break; // Remaining objects. default: if (P_WeaponOrPanel(mobjtype)) - offset += mthing->options & MTF_AMBUSH ? 24 * FRACUNIT : 0; + offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; } if (!offset) // Snap to the surfaces when there's no offset set. @@ -13165,6 +13173,53 @@ static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, sec } while (hoopsize >= 8); } +static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bonustime, boolean nightsreplace) +{ + mobjtype_t ringthing = MT_RING; + mobj_t *mobj = NULL; + fixed_t z; + + // Which ringthing to use + if (mthing->type == mobjinfo[MT_BLUESPHERE].doomednum) + ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; + else if (mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum) + ringthing = MT_BOMBSPHERE; + else + { + if (ultimatemode) + return; // No rings in Ultimate! + + if (nightsreplace) + ringthing = MT_NIGHTSSTAR; + else if (mthing->type == mobjinfo[MT_COIN].doomednum) + ringthing = MT_COIN; + else if (mthing->type == mobjinfo[MT_REDTEAMRING].doomednum) // No team rings in non-CTF + ringthing = (gametype == GT_CTF) ? MT_REDTEAMRING : MT_RING; + else if (mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum) // Ditto + ringthing = (gametype == GT_CTF) ? MT_BLUETEAMRING : MT_RING; + } + + z = P_GetMobjSpawnHeight(ringthing, mthing, x, y); + mobj = P_SpawnMobj(x, y, z, ringthing); + mobj->spawnpoint = mthing; + + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + } + + mobj->angle = FixedAngle(mthing->angle << FRACBITS); + mthing->mobj = mobj; + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; + + if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) + P_SetMobjState(mobj, mobj->info->raisestate); + else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); +} + void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) { mobjtype_t ringthing = MT_RING; @@ -13414,77 +13469,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) } // All manners of rings and coins else - { - - // Which ringthing to use - if (mthing->type == mobjinfo[MT_BLUESPHERE].doomednum) - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - else if (mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum) - ringthing = MT_BOMBSPHERE; - else - { - if (ultimatemode) - return; // No rings in Ultimate! - - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - else if (mthing->type == mobjinfo[MT_COIN].doomednum) - ringthing = MT_COIN; - else if (mthing->type == mobjinfo[MT_REDTEAMRING].doomednum) // No team rings in non-CTF - ringthing = (gametype == GT_CTF) ? MT_REDTEAMRING : MT_RING; - else if (mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum) // Ditto - ringthing = (gametype == GT_CTF) ? MT_BLUETEAMRING : MT_RING; - } - - // Set proper height - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->z) - z -= (mthing->z << FRACBITS); - } - else - { - z = -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - if (mthing->z) - z += (mthing->z << FRACBITS); - } - - if (mthing->options & MTF_AMBUSH) // Special flag for rings - { - if (mthing->options & MTF_OBJECTFLIP) - z -= 24*FRACUNIT; - else - z += 24*FRACUNIT; - } - - mobj = P_SpawnMobj(x, y, z, ringthing); - mobj->spawnpoint = mthing; - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - mthing->mobj = mobj; - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) - P_SetMobjState(mobj, mobj->info->raisestate); - else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } + P_SpawnRingItem(mthing, x, y, bonustime, nightsreplace); } // From eadf9539571a60b98bea01fda60bb4e65db62e98 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 23 Dec 2019 12:30:01 +0100 Subject: [PATCH 107/312] Store a copy of sectors, lines and sides in memory so that P_NetArchiveWorld() can soon use them instead of relying on re-opening the original lumps. Fix print type issue. --- src/p_setup.c | 12 ++++++++++++ src/r_state.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index bc736588e..529cab798 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -103,6 +103,9 @@ node_t *nodes; line_t *lines; side_t *sides; mapthing_t *mapthings; +sector_t *spawnsectors; +line_t *spawnlines; +side_t *spawnsides; INT32 numstarposts; UINT16 bossdisabled; boolean stoppedclock; @@ -2775,6 +2778,15 @@ boolean P_SetupLevel(boolean skipprecip) P_LoadLineDefs2(); P_GroupLines(); + // Copy relevant map data for NetArchive purposes. + spawnsectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); + spawnlines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + spawnsides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); + + memcpy(spawnsectors, sectors, numsectors * sizeof (*sectors)); + memcpy(spawnlines, lines, numlines * sizeof (*lines)); + memcpy(spawnsides, sides, numsides * sizeof (*sides)); + P_PrepareRawThings(vres_Find(virt, "THINGS")->data); P_MakeMapMD5(virt, &mapmd5); diff --git a/src/r_state.h b/src/r_state.h index 75566923b..4e1eb388e 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -63,6 +63,7 @@ extern seg_t *segs; extern size_t numsectors; extern sector_t *sectors; +extern sector_t *spawnsectors; extern size_t numsubsectors; extern subsector_t *subsectors; @@ -72,9 +73,11 @@ extern node_t *nodes; extern size_t numlines; extern line_t *lines; +extern line_t *spawnlines; extern size_t numsides; extern side_t *sides; +extern side_t *spawnsides; // // POV data. From 21dcbc856cc6ce9f77faf54a149e76195d4815cb Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 12:42:09 +0100 Subject: [PATCH 108/312] Split up P_SpawnHoopsAndRings() into subfunctions --- src/p_mobj.c | 480 ++++++++++++++++++++++++++------------------------- 1 file changed, 248 insertions(+), 232 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index b74c70dd3..459a7c003 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13220,256 +13220,272 @@ static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bo P_SetMobjState(mobj, mobj->info->seestate); } -void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) +static void P_SpawnVerticalSpringRings(mapthing_t *mthing, fixed_t x, fixed_t y, sector_t* sec, boolean nightsreplace) { mobjtype_t ringthing = MT_RING; - mobj_t *mobj = NULL; - INT32 r, i; - fixed_t x, y, z, finalx, finaly, finalz; - sector_t *sec; - TVector v, *res; - angle_t closestangle, fa; - boolean nightsreplace = ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)); + mobj_t* mobj = NULL; + fixed_t z; + INT32 r; - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; + INT32 dist = 64*FRACUNIT; + if (mthing->type == 601) + dist = 128*FRACUNIT; - sec = R_PointInSubsector(x, y)->sector; + if (ultimatemode) + return; // No rings in Ultimate! - // NiGHTS hoop! - if (mthing->type == 1705) + if (nightsreplace) + ringthing = MT_NIGHTSSTAR; + + if (mthing->options & MTF_OBJECTFLIP) { - z = mthing->z << FRACBITS; - P_SpawnHoop(mthing, x, y, z, sec, 24, 4*FRACUNIT); - return; - } - // CUSTOMIZABLE NiGHTS hoop! - else if (mthing->type == 1713) - { - // Super happy fun time - // For each flag add 16 fracunits to the size - // Default (0 flags) is 32 fracunits - z = mthing->z << FRACBITS; - P_SpawnHoop(mthing, x, y, z, sec, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); - return; - } - // *** - // Special placement patterns - // *** - - // Vertical Rings - Stack of 5 (handles both red and yellow) - else if (mthing->type == 600 || mthing->type == 601) - { - INT32 dist = 64*FRACUNIT; - if (mthing->type == 601) - dist = 128*FRACUNIT; - - if (ultimatemode) - return; // No rings in Ultimate! - - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( + z = ( #ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : + sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : #endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->z) - z -= (mthing->z << FRACBITS); - } - else - { - z = ( -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight); - if (mthing->z) - z += (mthing->z << FRACBITS); - } - - for (r = 1; r <= 5; r++) - { - if (mthing->options & MTF_OBJECTFLIP) - z -= dist; - else - z += dist; - - mobj = P_SpawnMobj(x, y, z, ringthing); - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } + sec->ceilingheight) - mobjinfo[ringthing].height; + if (mthing->z) + z -= (mthing->z << FRACBITS); } - // Diagonal rings (handles both types) - else if (mthing->type == 602 || mthing->type == 603) // Diagonal rings (5) + else { - INT32 iterations = 5; - if (mthing->type == 603) - iterations = 10; - - if (ultimatemode) - return; // No rings in Ultimate! - - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - - closestangle = FixedAngle(mthing->angle*FRACUNIT); - fa = (closestangle >> ANGLETOFINESHIFT); - - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->z) - z -= (mthing->z << FRACBITS); - } - else - { - z = ( -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight); - if (mthing->z) - z += (mthing->z << FRACBITS); - } - - for (r = 1; r <= iterations; r++) - { - x += FixedMul(64*FRACUNIT, FINECOSINE(fa)); - y += FixedMul(64*FRACUNIT, FINESINE(fa)); - - if (mthing->options & MTF_OBJECTFLIP) - z -= 64*FRACUNIT; - else - z += 64*FRACUNIT; - - mobj = P_SpawnMobj(x, y, z, ringthing); - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = closestangle; - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } - } - // Rings of items (all six of them) - else if (mthing->type >= 604 && mthing->type <= 609) - { - INT32 numitems = 8; - INT32 size = 96*FRACUNIT; - - if (mthing->type & 1) - { - numitems = 16; - size = 192*FRACUNIT; - } - - z = + z = ( #ifdef ESLOPE sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : #endif - sec->floorheight; + sec->floorheight); if (mthing->z) z += (mthing->z << FRACBITS); - - closestangle = FixedAngle(mthing->angle*FRACUNIT); - - switch (mthing->type) - { - case 604: - case 605: - if (ultimatemode) - return; // No rings in Ultimate! - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - break; - case 608: - case 609: - /*ringthing = (i & 1) ? MT_RING : MT_BLUESPHERE; -- i == 0 is bluesphere - break;*/ - case 606: - case 607: - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - break; - default: - break; - } - - // Create the hoop! - for (i = 0; i < numitems; i++) - { - if (mthing->type == 608 || mthing->type == 609) - { - if (i & 1) - { - if (ultimatemode) - continue; // No rings in Ultimate! - ringthing = (nightsreplace) ? MT_NIGHTSSTAR : MT_RING; - } - else - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - } - - fa = i*FINEANGLES/numitems; - v[0] = FixedMul(FINECOSINE(fa),size); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),size); - v[3] = FRACUNIT; - - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, ringthing); - mobj->z -= mobj->height/2; - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = closestangle; - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) - P_SetMobjState(mobj, mobj->info->raisestate); - else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } } - // All manners of rings and coins + + for (r = 1; r <= 5; r++) + { + if (mthing->options & MTF_OBJECTFLIP) + z -= dist; + else + z += dist; + + mobj = P_SpawnMobj(x, y, z, ringthing); + + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + } + + mobj->angle = FixedAngle(mthing->angle << FRACBITS); + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; + + if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); + } +} + +static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, sector_t* sec, boolean nightsreplace) +{ + mobjtype_t ringthing = MT_RING; + mobj_t *mobj = NULL; + fixed_t z; + INT32 r; + angle_t closestangle, fa; + + INT32 iterations = 5; + if (mthing->type == 603) + iterations = 10; + + if (ultimatemode) + return; // No rings in Ultimate! + + if (nightsreplace) + ringthing = MT_NIGHTSSTAR; + + closestangle = FixedAngle(mthing->angle << FRACBITS); + fa = (closestangle >> ANGLETOFINESHIFT); + + if (mthing->options & MTF_OBJECTFLIP) + { + z = ( +#ifdef ESLOPE + sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : +#endif + sec->ceilingheight) - mobjinfo[ringthing].height; + if (mthing->z) + z -= (mthing->z << FRACBITS); + } else + { + z = ( +#ifdef ESLOPE + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : +#endif + sec->floorheight); + if (mthing->z) + z += (mthing->z << FRACBITS); + } + + for (r = 1; r <= iterations; r++) + { + x += FixedMul(64*FRACUNIT, FINECOSINE(fa)); + y += FixedMul(64*FRACUNIT, FINESINE(fa)); + + if (mthing->options & MTF_OBJECTFLIP) + z -= 64*FRACUNIT; + else + z += 64*FRACUNIT; + + mobj = P_SpawnMobj(x, y, z, ringthing); + + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + } + + mobj->angle = closestangle; + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; + + if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); + } +} + +static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, sector_t* sec, boolean bonustime, boolean nightsreplace) +{ + mobjtype_t ringthing = MT_RING; + mobj_t *mobj = NULL; + fixed_t z, finalx, finaly, finalz; + angle_t closestangle, fa; + INT32 i; + TVector v, *res; + INT32 numitems = 8; + INT32 size = 96*FRACUNIT; + + if (mthing->type & 1) + { + numitems = 16; + size = 192*FRACUNIT; + } + + z = +#ifdef ESLOPE + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : +#endif + sec->floorheight; + if (mthing->z) + z += (mthing->z << FRACBITS); + + closestangle = FixedAngle(mthing->angle << FRACBITS); + + switch (mthing->type) + { + case 604: + case 605: + if (ultimatemode) + return; // No rings in Ultimate! + if (nightsreplace) + ringthing = MT_NIGHTSSTAR; + break; + case 608: + case 609: + /*ringthing = (i & 1) ? MT_RING : MT_BLUESPHERE; -- i == 0 is bluesphere + break;*/ + case 606: + case 607: + ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; + break; + default: + break; + } + + // Create the hoop! + for (i = 0; i < numitems; i++) + { + if (mthing->type == 608 || mthing->type == 609) + { + if (i & 1) + { + if (ultimatemode) + continue; // No rings in Ultimate! + ringthing = (nightsreplace) ? MT_NIGHTSSTAR : MT_RING; + } + else + ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; + } + + fa = i * FINEANGLES/numitems; + v[0] = FixedMul(FINECOSINE(fa), size); + v[1] = 0; + v[2] = FixedMul(FINESINE(fa), size); + v[3] = FRACUNIT; + + res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); + M_Memcpy(&v, res, sizeof(v)); + + finalx = x + v[0]; + finaly = y + v[1]; + finalz = z + v[2]; + + mobj = P_SpawnMobj(finalx, finaly, finalz, ringthing); + mobj->z -= mobj->height/2; + + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + } + + mobj->angle = closestangle; + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; + + if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) + P_SetMobjState(mobj, mobj->info->raisestate); + else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); + } +} + +void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) +{ + fixed_t x = mthing->x << FRACBITS; + fixed_t y = mthing->y << FRACBITS; + fixed_t z = mthing->z << FRACBITS; + sector_t *sec = R_PointInSubsector(x, y)->sector; + boolean nightsreplace = ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)); + + switch (mthing->type) + { + // Special placement patterns + case 600: // 5 vertical rings (yellow spring) + case 601: // 5 vertical rings (red spring) + P_SpawnVerticalSpringRings(mthing, x, y, sec, nightsreplace); + return; + case 602: // 5 diagonal rings (yellow spring) + case 603: // 10 diagonal rings (red spring) + P_SpawnDiagonalSpringRings(mthing, x, y, sec, nightsreplace); + return; + case 604: // Circle of rings (8 items) + case 605: // Circle of rings (16 bits) + case 606: // Circle of blue spheres (8 items) + case 607: // Circle of blue spheres (16 items) + case 608: // Circle of rings and blue spheres (8 items) + case 609: // Circle of rings and blue spheres (16 items) + P_SpawnItemCircle(mthing, x, y, sec, bonustime, nightsreplace); + return; + // Hoops + case 1705: // Generic NiGHTS hoop + P_SpawnHoop(mthing, x, y, z, sec, 24, 4*FRACUNIT); + return; + case 1713: // Customizable NiGHTS hoop + // For each flag add 16 fracunits to the size + // Default (0 flags) is 32 fracunits + P_SpawnHoop(mthing, x, y, z, sec, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); + return; + default: // All manners of rings and coins P_SpawnRingItem(mthing, x, y, bonustime, nightsreplace); + } } // From bb54597552df972c4a4e27144df4876da7757e5c Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 23 Dec 2019 12:42:38 +0100 Subject: [PATCH 109/312] Remove redundant netarchive-related sector vars as they're not used anymore. Replace lump-based difference checks for sectors in P_NetArchiveWorld(), now it uses the mapload-created copy instead. --- src/p_saveg.c | 34 +++++++++++++++++----------------- src/p_setup.c | 4 ---- src/p_spec.c | 12 ++---------- src/r_defs.h | 11 ----------- 4 files changed, 19 insertions(+), 42 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index c876713e4..356d696a5 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -782,10 +782,10 @@ static void P_NetArchiveWorld(void) // reload the map just to see difference virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); - mapsector_t *ms = (mapsector_t*) vres_Find(virt, "SECTORS")->data; mapsidedef_t *msd = (mapsidedef_t*) vres_Find(virt, "SIDEDEFS")->data; maplinedef_t *mld = (maplinedef_t*) vres_Find(virt, "LINEDEFS")->data; const sector_t *ss = sectors; + const sector_t *spawnss = spawnsectors; UINT8 diff, diff2, diff3; // initialize colormap vars because paranoia @@ -794,45 +794,45 @@ static void P_NetArchiveWorld(void) WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); put = save_p; - for (i = 0; i < numsectors; i++, ss++, ms++) + for (i = 0; i < numsectors; i++, ss++, spawnss++) { diff = diff2 = diff3 = 0; - if (ss->floorheight != SHORT(ms->floorheight)<floorheight != spawnss->floorheight) diff |= SD_FLOORHT; - if (ss->ceilingheight != SHORT(ms->ceilingheight)<ceilingheight != spawnss->ceilingheight) diff |= SD_CEILHT; // // flats // - if (ss->floorpic != P_CheckLevelFlat(ms->floorpic)) + if (ss->floorpic != spawnss->floorpic) diff |= SD_FLOORPIC; - if (ss->ceilingpic != P_CheckLevelFlat(ms->ceilingpic)) + if (ss->ceilingpic != spawnss->ceilingpic) diff |= SD_CEILPIC; - if (ss->lightlevel != SHORT(ms->lightlevel)) + if (ss->lightlevel != spawnss->lightlevel) diff |= SD_LIGHT; - if (ss->special != SHORT(ms->special)) + if (ss->special != spawnss->special) diff |= SD_SPECIAL; - if (ss->floor_xoffs != ss->spawn_flr_xoffs) + if (ss->floor_xoffs != spawnss->floor_xoffs) diff2 |= SD_FXOFFS; - if (ss->floor_yoffs != ss->spawn_flr_yoffs) + if (ss->floor_yoffs != spawnss->floor_yoffs) diff2 |= SD_FYOFFS; - if (ss->ceiling_xoffs != ss->spawn_ceil_xoffs) + if (ss->ceiling_xoffs != spawnss->ceiling_xoffs) diff2 |= SD_CXOFFS; - if (ss->ceiling_yoffs != ss->spawn_ceil_yoffs) + if (ss->ceiling_yoffs != spawnss->ceiling_yoffs) diff2 |= SD_CYOFFS; - if (ss->floorpic_angle != ss->spawn_flrpic_angle) + if (ss->floorpic_angle != spawnss->floorpic_angle) diff2 |= SD_FLOORANG; - if (ss->ceilingpic_angle != ss->spawn_flrpic_angle) + if (ss->ceilingpic_angle != spawnss->ceilingpic_angle) diff2 |= SD_CEILANG; - if (ss->tag != SHORT(ms->tag)) + if (ss->tag != spawnss->tag) diff2 |= SD_TAG; - if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) + if (ss->nexttag != spawnss->nexttag || ss->firsttag != spawnss->firsttag) diff3 |= SD_TAGLIST; - if (ss->extra_colormap != ss->spawn_extra_colormap) + if (ss->extra_colormap != spawnss->extra_colormap) diff3 |= SD_COLORMAP; // Check if any of the sector's FOFs differ from how they spawned diff --git a/src/p_setup.c b/src/p_setup.c index 529cab798..6e6c1a72b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -669,11 +669,9 @@ static void P_LoadRawSectors(UINT8 *data) ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); ss->lightlevel = SHORT(ms->lightlevel); - ss->spawn_lightlevel = SHORT(ms->lightlevel); ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); ss->nexttag = ss->firsttag = -1; - ss->spawn_nexttag = ss->spawn_firsttag = -1; memset(&ss->soundorg, 0, sizeof(ss->soundorg)); ss->validcount = 0; @@ -708,9 +706,7 @@ static void P_LoadRawSectors(UINT8 *data) ss->spawn_extra_colormap = NULL; ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0; - ss->spawn_flr_xoffs = ss->spawn_ceil_xoffs = ss->spawn_flr_yoffs = ss->spawn_ceil_yoffs = 0; ss->floorpic_angle = ss->ceilingpic_angle = 0; - ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0; ss->gravity = NULL; ss->cullheight = NULL; ss->verticalflip = false; diff --git a/src/p_spec.c b/src/p_spec.c index bf7f6210a..297c9a427 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1603,8 +1603,6 @@ static inline void P_InitTagLists(void) size_t j = (unsigned)sectors[i].tag % numsectors; sectors[i].nexttag = sectors[j].firsttag; sectors[j].firsttag = (INT32)i; - sectors[i].spawn_nexttag = sectors[i].nexttag; - sectors[j].spawn_firsttag = sectors[j].firsttag; } for (i = numlines - 1; i != (size_t)-1; i--) @@ -6405,22 +6403,16 @@ static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flata { if (!(master->flags & ML_NETONLY)) // Modify floor flat alignment unless ML_NETONLY flag is set { - sector->spawn_flrpic_angle = sector->floorpic_angle = flatangle; + sector->floorpic_angle = flatangle; sector->floor_xoffs += xoffs; sector->floor_yoffs += yoffs; - // saved for netgames - sector->spawn_flr_xoffs = sector->floor_xoffs; - sector->spawn_flr_yoffs = sector->floor_yoffs; } if (!(master->flags & ML_NONET)) // Modify ceiling flat alignment unless ML_NONET flag is set { - sector->spawn_ceilpic_angle = sector->ceilingpic_angle = flatangle; + sector->ceilingpic_angle = flatangle; sector->ceiling_xoffs += xoffs; sector->ceiling_yoffs += yoffs; - // saved for netgames - sector->spawn_ceil_xoffs = sector->ceiling_xoffs; - sector->spawn_ceil_yoffs = sector->ceiling_yoffs; } } diff --git a/src/r_defs.h b/src/r_defs.h index 3cc780545..353dc572b 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -384,17 +384,6 @@ typedef struct sector_s // for fade thinker INT16 spawn_lightlevel; - // these are saved for netgames, so do not let Lua touch these! - INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed - - // offsets sector spawned with (via linedef type 7) - fixed_t spawn_flr_xoffs, spawn_flr_yoffs; - fixed_t spawn_ceil_xoffs, spawn_ceil_yoffs; - - // flag angles sector spawned with (via linedef type 7) - angle_t spawn_flrpic_angle; - angle_t spawn_ceilpic_angle; - // colormap structure extracolormap_t *spawn_extra_colormap; } sector_t; From 1221c108c67db0b16ce21de288eae411fda9e14f Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 23 Dec 2019 12:47:40 +0100 Subject: [PATCH 110/312] Make lines and sides use the mapload copies in P_NetArchiveWorld() too; do no longer use vres stuff there. --- src/p_saveg.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 356d696a5..5af72cd46 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -777,13 +777,11 @@ static void P_NetArchiveWorld(void) size_t i; INT32 statsec = 0, statline = 0; const line_t *li = lines; + const line_t *spawnli = spawnlines; const side_t *si; + const side_t *spawnsi; UINT8 *put; - // reload the map just to see difference - virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); - mapsidedef_t *msd = (mapsidedef_t*) vres_Find(virt, "SIDEDEFS")->data; - maplinedef_t *mld = (maplinedef_t*) vres_Find(virt, "LINEDEFS")->data; const sector_t *ss = sectors; const sector_t *spawnss = spawnsectors; UINT8 diff, diff2, diff3; @@ -936,45 +934,41 @@ static void P_NetArchiveWorld(void) WRITEUINT16(put, 0xffff); // do lines - for (i = 0; i < numlines; i++, mld++, li++) + for (i = 0; i < numlines; i++, spawnli++, li++) { diff = diff2 = diff3 = 0; - if (li->special != SHORT(mld->special)) + if (li->special != spawnli->special) diff |= LD_SPECIAL; - if (SHORT(mld->special) == 321 || SHORT(mld->special) == 322) // only reason li->callcount would be non-zero is if either of these are involved + if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved diff |= LD_CLLCOUNT; if (li->sidenum[0] != 0xffff) { si = &sides[li->sidenum[0]]; - if (si->textureoffset != SHORT(msd[li->sidenum[0]].textureoffset)<sidenum[0]]; + if (si->textureoffset != spawnsi->textureoffset) diff |= LD_S1TEXOFF; //SoM: 4/1/2000: Some textures are colormaps. Don't worry about invalid textures. - if (R_CheckTextureNumForName(msd[li->sidenum[0]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[0]].toptexture)) + if (si->toptexture != spawnsi->toptexture) diff |= LD_S1TOPTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[0]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[0]].bottomtexture)) + if (si->bottomtexture != spawnsi->bottomtexture) diff |= LD_S1BOTTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[0]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[0]].midtexture)) + if (si->midtexture != spawnsi->midtexture) diff |= LD_S1MIDTEX; } if (li->sidenum[1] != 0xffff) { si = &sides[li->sidenum[1]]; - if (si->textureoffset != SHORT(msd[li->sidenum[1]].textureoffset)<sidenum[1]]; + if (si->textureoffset != spawnsi->textureoffset) diff2 |= LD_S2TEXOFF; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[1]].toptexture)) + if (si->toptexture != spawnsi->toptexture) diff2 |= LD_S2TOPTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[1]].bottomtexture)) + if (si->bottomtexture != spawnsi->bottomtexture) diff2 |= LD_S2BOTTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[1]].midtexture)) + if (si->midtexture != spawnsi->midtexture) diff2 |= LD_S2MIDTEX; if (diff2) diff |= LD_DIFF2; @@ -1018,7 +1012,6 @@ static void P_NetArchiveWorld(void) WRITEUINT16(put, 0xffff); R_ClearTextureNumCache(false); - vres_Free(virt); save_p = put; } From 112b15cca2f459559a00b6608af8bed23e624482 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 14:45:43 +0100 Subject: [PATCH 111/312] Add P_GetMobjtype for finding the mobjtype for a given mapthingnum --- src/p_mobj.c | 50 ++++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 459a7c003..112ef67f3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11159,17 +11159,12 @@ void P_RespawnSpecials(void) if (mthing) { - mobjtype_t i; + mobjtype_t i = P_GetMobjtype(mthing->type); x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; ss = R_PointInSubsector(x, y); - // find which type to spawn - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; - - if (i == NUMMOBJTYPES) // prevent creation of objects with this type -- Monster Iestyn 17/12/17 + if (i == MT_UNKNOWN) // prevent creation of objects with this type -- Monster Iestyn 17/12/17 { // 3D Mode start Thing is unlikely to be added to the que, // so don't bother checking for that specific type @@ -11635,6 +11630,19 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* ss->sector->floorheight) + offset; } +/** Returns corresponding mobj type from mapthing number. + * \param mthingtype Mapthing number in question. + * \return Mobj type; MT_UNKNOWN if nothing found. + */ +static mobjtype_t P_GetMobjtype(UINT16 mthingtype) +{ + mobjtype_t i; + for (i = 0; i < NUMMOBJTYPES; i++) + if (mthingtype == mobjinfo[i].doomednum) + return i; + return MT_UNKNOWN; +} + // // P_SpawnMapThing // The fields of the mapthing should @@ -11650,22 +11658,17 @@ void P_SpawnMapThing(mapthing_t *mthing) if (!mthing->type) return; // Ignore type-0 things as NOPs + if (mthing->type == 3328) // 3D Mode start Thing + return; + // Always spawn in objectplace. // Skip all returning code. if (objectplacing) { // find which type to spawn - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; - - if (i == NUMMOBJTYPES) - { - if (mthing->type == 3328) // 3D Mode start Thing - return; + i = P_GetMobjtype(mthing->type); + if (i == MT_UNKNOWN) CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - i = MT_UNKNOWN; - } goto noreturns; } @@ -11734,18 +11737,9 @@ You should think about modifying the deathmatch starts to take full advantage of return; } - // find which type to spawn - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; - - if (i == NUMMOBJTYPES) - { - if (mthing->type == 3328) // 3D Mode start Thing - return; + i = P_GetMobjtype(mthing->type); + if (i == MT_UNKNOWN) CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - i = MT_UNKNOWN; - } if (metalrecording) // Metal Sonic can't use these things. if (mobjinfo[i].flags & (MF_ENEMY|MF_BOSS) || i == MT_TOKEN || i == MT_STARPOST) From 6779c508e743054cccab0de8c883ef3d70c773f8 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 12:17:39 -0300 Subject: [PATCH 112/312] Satisfy rollangle table with a 3deg angle --- src/r_patch.c | 3 +-- src/r_things.c | 8 +++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/r_patch.c b/src/r_patch.c index 7c9d0ea83..69d5ad1a2 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1180,8 +1180,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp leftoffset = width - leftoffset; } - // Don't cache angle = 0 - for (angle = 1; angle < ROTANGLES; angle++) + for (angle = 0; angle < ROTANGLES; angle++) { INT32 newwidth, newheight; diff --git a/src/r_things.c b/src/r_things.c index aa2a73515..d29baa711 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -500,7 +500,7 @@ void R_InitSprites(void) { size_t i; #ifdef ROTSPRITE - INT32 angle, realangle = 0; + INT32 angle, ra; float fa; #endif @@ -510,10 +510,12 @@ void R_InitSprites(void) #ifdef ROTSPRITE for (angle = 0; angle < ROTANGLES; angle++) { - fa = ANG2RAD(FixedAngle(realangle< Date: Mon, 23 Dec 2019 16:36:26 +0100 Subject: [PATCH 113/312] P_PrepareRawThings() is now where it was supposed to be at; moved save and flat & texture caching related functions to the end of P_LoadMapData(). --- src/p_setup.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 6e6c1a72b..7ac713044 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -485,6 +485,7 @@ static inline void P_LoadRawSubsectors(void *data) size_t numlevelflats; levelflat_t *levelflats; +levelflat_t *foundflats; //SoM: Other files want this info. size_t P_PrecacheLevelFlats(void) @@ -648,7 +649,6 @@ static void P_LoadRawSectors(UINT8 *data) { mapsector_t *ms = (mapsector_t *)data; sector_t *ss = sectors; - levelflat_t *foundflats; size_t i; // Allocate a big chunk of memory as big as our MAXLEVELFLATS limit. @@ -725,16 +725,6 @@ static void P_LoadRawSectors(UINT8 *data) ss->lineoutLength = -1.0l; #endif // ----- end special tricks ----- } - - // set the sky flat num - skyflatnum = P_AddLevelFlat(SKYFLATNAME, foundflats); - - // copy table for global usage - levelflats = M_Memcpy(Z_Calloc(numlevelflats * sizeof (*levelflats), PU_LEVEL, NULL), foundflats, numlevelflats * sizeof (levelflat_t)); - free(foundflats); - - // search for animated flats and set up - P_SetupLevelFlatAnims(); } // @@ -1455,7 +1445,6 @@ static void P_LoadRawSideDefs2(void *data) break; } } - R_ClearTextureNumCache(true); } static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, fixed_t bx1, fixed_t by1) @@ -2007,7 +1996,29 @@ static void P_LoadMapData(const virtres_t* virt) P_LoadRawLineDefs(virtlinedefs->data); P_SetupLines(); P_LoadRawSideDefs2(virtsidedefs->data); + P_PrepareRawThings(virtthings->data); } + + R_ClearTextureNumCache(true); + + // set the sky flat num + skyflatnum = P_AddLevelFlat(SKYFLATNAME, foundflats); + + // copy table for global usage + levelflats = M_Memcpy(Z_Calloc(numlevelflats * sizeof (*levelflats), PU_LEVEL, NULL), foundflats, numlevelflats * sizeof (levelflat_t)); + free(foundflats); + + // search for animated flats and set up + P_SetupLevelFlatAnims(); + + // Copy relevant map data for NetArchive purposes. + spawnsectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); + spawnlines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + spawnsides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); + + memcpy(spawnsectors, sectors, numsectors * sizeof (*sectors)); + memcpy(spawnlines, lines, numlines * sizeof (*lines)); + memcpy(spawnsides, sides, numsides * sizeof (*sides)); } #if 0 @@ -2774,17 +2785,6 @@ boolean P_SetupLevel(boolean skipprecip) P_LoadLineDefs2(); P_GroupLines(); - // Copy relevant map data for NetArchive purposes. - spawnsectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); - spawnlines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); - spawnsides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); - - memcpy(spawnsectors, sectors, numsectors * sizeof (*sectors)); - memcpy(spawnlines, lines, numlines * sizeof (*lines)); - memcpy(spawnsides, sides, numsides * sizeof (*sides)); - - P_PrepareRawThings(vres_Find(virt, "THINGS")->data); - P_MakeMapMD5(virt, &mapmd5); vres_Free(virt); From 9a9f72f59899143f1b0483c7d828b5b260de8151 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 23 Dec 2019 16:37:44 +0100 Subject: [PATCH 114/312] Don't reload mapthings in P_LoadThingsOnly() as they should no longer be modified past the mapload procedure. --- src/p_setup.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 7ac713044..f5d4c26e2 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2196,8 +2196,6 @@ void P_LoadThingsOnly(void) // Search through all the thinkers. thinker_t *think; INT32 i, viewid = -1, centerid = -1; // for skyboxes - virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); - virtlump_t* vth = vres_Find(virt, "THINGS"); // check if these are any of the normal viewpoint/centerpoint mobjs in the level or not if (skyboxmo[0] || skyboxmo[1]) @@ -2218,11 +2216,8 @@ void P_LoadThingsOnly(void) P_LevelInitStuff(); - P_PrepareRawThings(vth->data); P_LoadThings(true); - vres_Free(virt); - // restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that skyboxmo[0] = skyboxviewpnts[(viewid >= 0) ? viewid : 0]; skyboxmo[1] = skyboxcenterpnts[(centerid >= 0) ? centerid : 0]; From 6a69aa4ffa7619c4094d922891035831ba5291a3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 16:53:45 +0100 Subject: [PATCH 115/312] Separate handling of non-mobj mapthings in P_SpawnMapThing into its own function --- src/p_mobj.c | 120 +++++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 61 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 112ef67f3..714eef737 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11643,6 +11643,61 @@ static mobjtype_t P_GetMobjtype(UINT16 mthingtype) return MT_UNKNOWN; } +static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) +{ +#if MAXPLAYERS > 32 + You should think about modifying the deathmatch starts to take full advantage of this! +#endif + if (mthing->type <= MAXPLAYERS) // Player starts + { + // save spots for respawning in network games + if (!metalrecording) + playerstarts[mthing->type - 1] = mthing; + return true; + } + else if (mthing->type == 33) // Match starts + { + if (numdmstarts < MAX_DM_STARTS) + { + deathmatchstarts[numdmstarts] = mthing; + mthing->type = 0; + numdmstarts++; + } + return true; + } + else if (mthing->type == 34) // Red CTF starts + { + if (numredctfstarts < MAXPLAYERS) + { + redctfstarts[numredctfstarts] = mthing; + mthing->type = 0; + numredctfstarts++; + } + return true; + } + else if (mthing->type == 35) // Blue CTF starts + { + if (numbluectfstarts < MAXPLAYERS) + { + bluectfstarts[numbluectfstarts] = mthing; + mthing->type = 0; + numbluectfstarts++; + } + return true; + } + else if (metalrecording && mthing->type == mobjinfo[MT_METALSONIC_RACE].doomednum) + { // If recording, you ARE Metal Sonic. Do not spawn it, do not save normal spawnpoints. + playerstarts[0] = mthing; + return true; + } + else if (mthing->type == 750 // Slope vertex point (formerly chaos spawn) + || (mthing->type >= 600 && mthing->type <= 609) // Special placement patterns + || mthing->type == 1705 || mthing->type == 1713) // Hoops + return true; // These are handled elsewhere. + + return false; +} + // // P_SpawnMapThing // The fields of the mapthing should @@ -11672,70 +11727,13 @@ void P_SpawnMapThing(mapthing_t *mthing) goto noreturns; } - // count deathmatch start positions - if (mthing->type == 33) - { - if (numdmstarts < MAX_DM_STARTS) - { - deathmatchstarts[numdmstarts] = mthing; - mthing->type = 0; - numdmstarts++; - } - return; - } - - else if (mthing->type == 34) // Red CTF Starts - { - if (numredctfstarts < MAXPLAYERS) - { - redctfstarts[numredctfstarts] = mthing; - mthing->type = 0; - numredctfstarts++; - } - return; - } - - else if (mthing->type == 35) // Blue CTF Starts - { - if (numbluectfstarts < MAXPLAYERS) - { - bluectfstarts[numbluectfstarts] = mthing; - mthing->type = 0; - numbluectfstarts++; - } - return; - } - - else if (mthing->type == 750) // Slope vertex point (formerly chaos spawn) + if (P_SpawnNonMobjMapThing(mthing)) return; - else if (mthing->type == mobjinfo[MT_RING].doomednum || mthing->type == mobjinfo[MT_COIN].doomednum + if (mthing->type == mobjinfo[MT_RING].doomednum || mthing->type == mobjinfo[MT_COIN].doomednum || mthing->type == mobjinfo[MT_REDTEAMRING].doomednum || mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum - || mthing->type == mobjinfo[MT_BLUESPHERE].doomednum || mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum - || (mthing->type >= 600 && mthing->type <= 609) // circles and diagonals - || mthing->type == 1705 || mthing->type == 1713) // hoops - { - // Don't spawn hoops, wings, or rings yet! - return; - } - - // check for players specially -#if MAXPLAYERS > 32 -You should think about modifying the deathmatch starts to take full advantage of this! -#endif - if (mthing->type > 0 && mthing->type <= MAXPLAYERS) - { - // save spots for respawning in network games - if (!metalrecording) - playerstarts[mthing->type-1] = mthing; - return; - } - - if (metalrecording && mthing->type == mobjinfo[MT_METALSONIC_RACE].doomednum) - { // If recording, you ARE Metal Sonic. Do not spawn it, do not save normal spawnpoints. - playerstarts[0] = mthing; - return; - } + || mthing->type == mobjinfo[MT_BLUESPHERE].doomednum || mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum) // hoops + return; // These are handled in P_SpawnHoopsAndRings(). i = P_GetMobjtype(mthing->type); if (i == MT_UNKNOWN) From e90eb9a5e73c69c7996c2b258a34f42108f63a51 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 16:54:26 +0100 Subject: [PATCH 116/312] Move P_GetMobjtype above first use --- src/p_mobj.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 714eef737..f607fdf8a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11121,6 +11121,19 @@ void P_PrecipitationEffects(void) } } +/** Returns corresponding mobj type from mapthing number. + * \param mthingtype Mapthing number in question. + * \return Mobj type; MT_UNKNOWN if nothing found. + */ +static mobjtype_t P_GetMobjtype(UINT16 mthingtype) +{ + mobjtype_t i; + for (i = 0; i < NUMMOBJTYPES; i++) + if (mthingtype == mobjinfo[i].doomednum) + return i; + return MT_UNKNOWN; +} + // // P_RespawnSpecials // @@ -11630,19 +11643,6 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* ss->sector->floorheight) + offset; } -/** Returns corresponding mobj type from mapthing number. - * \param mthingtype Mapthing number in question. - * \return Mobj type; MT_UNKNOWN if nothing found. - */ -static mobjtype_t P_GetMobjtype(UINT16 mthingtype) -{ - mobjtype_t i; - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthingtype == mobjinfo[i].doomednum) - return i; - return MT_UNKNOWN; -} - static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) { #if MAXPLAYERS > 32 From 8ddd078b20a82e9abe35c177bc997470507d6120 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 17:28:21 +0100 Subject: [PATCH 117/312] P_MapThingSpawn(): Move early returning/substitution code into their own functions --- src/p_mobj.c | 358 ++++++++++++++++++++++++++++----------------------- 1 file changed, 199 insertions(+), 159 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f607fdf8a..c2b40a96b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11698,6 +11698,198 @@ static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) return false; } +static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) +{ + switch (i) + { + case MT_RING: + case MT_COIN: + case MT_REDTEAMRING: + case MT_BLUETEAMRING: + case MT_BLUESPHERE: + case MT_BOMBSPHERE: + case MT_NIGHTSSTAR: + case MT_NIGHTSCHIP: + return false; // These are handled in P_SpawnHoopsAndRings(). + case MT_EMERALD1: + case MT_EMERALD2: + case MT_EMERALD3: + case MT_EMERALD4: + case MT_EMERALD5: + case MT_EMERALD6: + case MT_EMERALD7: + if (gametype != GT_COOP) // Don't place emeralds in non-coop modes + return false; + + if (metalrecording) + return false; // Metal Sonic isn't for collecting emeralds. + + if (emeralds & mobjinfo[i].speed) // You already have this emerald! + return false; + + break; + case MT_EMERHUNT: + // Emerald Hunt is Coop only. + if (gametype != GT_COOP) + return false; + + if (numhuntemeralds < MAXHUNTEMERALDS) + huntemeralds[numhuntemeralds++] = mthing; + return false; + case MT_EMERALDSPAWN: + if (!cv_powerstones.value) + return false; + + if (!(gametype == GT_MATCH || gametype == GT_CTF)) + return false; + + runemeraldmanager = true; + break; + case MT_ROSY: + if (!(gametype == GT_COOP || (mthing->options & MTF_EXTRA))) + return false; // she doesn't hang out here + + if (!mariomode && !(netgame || multiplayer) && players[consoleplayer].skin == 3) + return false; // no doubles + + break; + case MT_TOKEN: + if (gametype != GT_COOP && gametype != GT_COMPETITION) + return false; // Gametype's not right + + if (tokenbits == 30) + return false; // Too many tokens + + if (tokenlist & (1 << tokenbits++)) + return false; // You already got this token + + break; + case MT_EMBLEM: + if (netgame || multiplayer) + return false; // Single player + + if (modifiedgame && !savemoddata) + return false; // No cheating!! + + break; + default: + break; + } + + if (metalrecording) // Metal Sonic can't use these things. + if (mobjinfo[i].flags & (MF_ENEMY|MF_BOSS) || i == MT_TOKEN || i == MT_STARPOST) + return false; + + if (!G_PlatformGametype()) + { + if ((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS)) + return false; // No enemies in ringslinger modes + + if (i == MT_SIGN || i == MT_STARPOST) + return false; // Don't spawn exit signs or starposts in wrong game modes + } + + if (!G_RingSlingerGametype() || !cv_specialrings.value) + if (P_WeaponOrPanel(i)) + return false; // Don't place weapons/panels in non-ringslinger modes + + if (gametype != GT_CTF) // CTF specific things + { + if (i == MT_BLUEFLAG || i == MT_REDFLAG) + return false; // No flags in non-CTF modes! + } + else + { + if ((i == MT_BLUEFLAG && blueflag) || (i == MT_REDFLAG && redflag)) + { + CONS_Alert(CONS_ERROR, M_GetText("Only one flag per team allowed in CTF!\n")); + return false; + } + } + + if (modeattacking) // Record Attack special stuff + { + // Don't spawn starposts that wouldn't be usable + if (i == MT_STARPOST) + return false; + } + + if (ultimatemode) + { + if (i == MT_PITY_BOX || i == MT_ELEMENTAL_BOX || i == MT_ATTRACT_BOX + || i == MT_FORCE_BOX || i == MT_ARMAGEDDON_BOX || i == MT_WHIRLWIND_BOX + || i == MT_FLAMEAURA_BOX || i == MT_BUBBLEWRAP_BOX || i == MT_THUNDERCOIN_BOX + || i == MT_RING_BOX || i == MT_STARPOST) + return false; // No rings or shields in Ultimate mode + + // Don't include the gold repeating boxes here please. + // They're likely facets of the level's design and therefore required to progress. + } + + return true; +} + +static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) +{ + // Altering monitor spawns via cvars + // If MF_GRENADEBOUNCE is set in the monitor's info, + // skip this step. (Used for gold monitors) + // Yeah, this is a dirty hack. + if ((mobjinfo[i].flags & (MF_MONITOR|MF_GRENADEBOUNCE)) == MF_MONITOR) + { + if (gametype == GT_COMPETITION || gametype == GT_RACE) + { + // Set powerup boxes to user settings for competition. + switch (cv_competitionboxes.value) + { + case 1: // Mystery + return MT_MYSTERY_BOX; + case 2: // Teleport + return MT_MIXUP_BOX; + case 3: // None + return MT_NULL; // Don't spawn! + default: + return i; + } + } + // Set powerup boxes to user settings for other netplay modes + else if (gametype != GT_COOP) + { + switch (cv_matchboxes.value) + { + case 1: // Mystery + return MT_MYSTERY_BOX; + case 2: // Unchanging + if (i == MT_MYSTERY_BOX) + return MT_NULL; // don't spawn + mthing->options &= ~(MTF_AMBUSH|MTF_OBJECTSPECIAL); // no random respawning! + return i; + case 3: // Don't spawn + return MT_NULL; + default: + return i; + } + } + } + + if (gametype != GT_CTF && (i == MT_RING_BLUEBOX || i == MT_RING_REDBOX)) + return MT_RING_BOX; + + if (modeattacking && i == MT_1UP_BOX) // 1UPs -->> Score TVs + { + // Either or, doesn't matter which. + if (mthing->options & (MTF_AMBUSH | MTF_OBJECTSPECIAL)) + return MT_SCORE10K_BOX; // 10,000 + else + return MT_SCORE1K_BOX; // 1,000 + } + + if (mariomode && i == MT_ROSY) + return MT_TOAD; // don't remove on penalty of death + + return i; +} + // // P_SpawnMapThing // The fields of the mapthing should @@ -11716,176 +11908,24 @@ void P_SpawnMapThing(mapthing_t *mthing) if (mthing->type == 3328) // 3D Mode start Thing return; - // Always spawn in objectplace. - // Skip all returning code. - if (objectplacing) - { - // find which type to spawn - i = P_GetMobjtype(mthing->type); - if (i == MT_UNKNOWN) - CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - goto noreturns; - } - - if (P_SpawnNonMobjMapThing(mthing)) + if (!objectplacing && P_SpawnNonMobjMapThing(mthing)) return; - if (mthing->type == mobjinfo[MT_RING].doomednum || mthing->type == mobjinfo[MT_COIN].doomednum - || mthing->type == mobjinfo[MT_REDTEAMRING].doomednum || mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum - || mthing->type == mobjinfo[MT_BLUESPHERE].doomednum || mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum) // hoops - return; // These are handled in P_SpawnHoopsAndRings(). - i = P_GetMobjtype(mthing->type); if (i == MT_UNKNOWN) CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - if (metalrecording) // Metal Sonic can't use these things. - if (mobjinfo[i].flags & (MF_ENEMY|MF_BOSS) || i == MT_TOKEN || i == MT_STARPOST) + // Skip all returning/substitution code in objectplace. + if (!objectplacing) + { + if (!P_AllowMobjSpawn(mthing, i)) return; - if (i >= MT_EMERALD1 && i <= MT_EMERALD7) // Pickupable Emeralds - { - if (gametype != GT_COOP) // Don't place emeralds in non-coop modes - return; - - if (metalrecording) - return; // Metal Sonic isn't for collecting emeralds. - - if (emeralds & mobjinfo[i].speed) // You already have this emerald! + i = P_GetMobjtypeSubstitute(mthing, i); + if (i == MT_NULL) // Don't spawn mobj return; } - if (i == MT_EMERHUNT) - { - // Emerald Hunt is Coop only. - if (gametype != GT_COOP) - return; - - if (numhuntemeralds < MAXHUNTEMERALDS) - huntemeralds[numhuntemeralds++] = mthing; - return; - } - - if (i == MT_EMERALDSPAWN) - { - if (!cv_powerstones.value) - return; - - if (!(gametype == GT_MATCH || gametype == GT_CTF)) - return; - - runemeraldmanager = true; - } - - if (!G_PlatformGametype()) // No enemies in match or CTF modes - if ((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS)) - return; - - if (!G_RingSlingerGametype() || !cv_specialrings.value) - if (P_WeaponOrPanel(i)) - return; // Don't place weapons/panels in non-ringslinger modes - - // Altering monitor spawns via cvars - // If MF_GRENADEBOUNCE is set in the monitor's info, - // skip this step. (Used for gold monitors) - // Yeah, this is a dirty hack. - if ((mobjinfo[i].flags & (MF_MONITOR|MF_GRENADEBOUNCE)) == MF_MONITOR) - { - if (gametype == GT_COMPETITION || gametype == GT_RACE) - { - // Set powerup boxes to user settings for competition. - if (cv_competitionboxes.value == 1) // Mystery - i = MT_MYSTERY_BOX; - else if (cv_competitionboxes.value == 2) // Teleport - i = MT_MIXUP_BOX; - else if (cv_competitionboxes.value == 3) // None - return; // Don't spawn! - // default case: normal - } - // Set powerup boxes to user settings for other netplay modes - else if (gametype != GT_COOP) - { - if (cv_matchboxes.value == 1) // Mystery - i = MT_MYSTERY_BOX; - else if (cv_matchboxes.value == 2) // Unchanging - { - if (i == MT_MYSTERY_BOX) - return; // don't spawn - mthing->options &= ~(MTF_AMBUSH|MTF_OBJECTSPECIAL); // no random respawning! - } - else if (cv_matchboxes.value == 3) // Don't spawn - return; - // default case: normal - } - } - - if (gametype != GT_CTF) // CTF specific things - { - if (i == MT_RING_BLUEBOX || i == MT_RING_REDBOX) - i = MT_RING_BOX; - else if (i == MT_BLUEFLAG || i == MT_REDFLAG) - return; // No flags in non-CTF modes! - } - else - { - if ((i == MT_BLUEFLAG && blueflag) || (i == MT_REDFLAG && redflag)) - { - CONS_Alert(CONS_ERROR, M_GetText("Only one flag per team allowed in CTF!\n")); - return; - } - } - - if (!G_PlatformGametype() && (i == MT_SIGN || i == MT_STARPOST)) - return; // Don't spawn exit signs or starposts in wrong game modes - - if (modeattacking) // Record Attack special stuff - { - // Don't spawn starposts that wouldn't be usable - if (i == MT_STARPOST) - return; - - // 1UPs -->> Score TVs - else if (i == MT_1UP_BOX) // 1UP - { - // Either or, doesn't matter which. - if (mthing->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)) - i = MT_SCORE10K_BOX; // 10,000 - else - i = MT_SCORE1K_BOX; // 1,000 - } - } - - if (ultimatemode) - { - if (i == MT_PITY_BOX || i == MT_ELEMENTAL_BOX || i == MT_ATTRACT_BOX - || i == MT_FORCE_BOX || i == MT_ARMAGEDDON_BOX || i == MT_WHIRLWIND_BOX - || i == MT_FLAMEAURA_BOX || i == MT_BUBBLEWRAP_BOX || i == MT_THUNDERCOIN_BOX - || i == MT_RING_BOX || i == MT_STARPOST) - return; // No rings or shields in Ultimate mode - - // Don't include the gold repeating boxes here please. - // They're likely facets of the level's design and therefore required to progress. - } - - if (i == MT_ROSY) - { - if (!(gametype == GT_COOP || (mthing->options & MTF_EXTRA))) - return; // she doesn't hang out here - else if (mariomode) - i = MT_TOAD; // don't remove on penalty of death - else if (!(netgame || multiplayer) && players[consoleplayer].skin == 3) - return; // no doubles - } - - if (i == MT_TOKEN && ((gametype != GT_COOP && gametype != GT_COMPETITION) || tokenbits == 30 || tokenlist & (1 << tokenbits++))) - return; // you already got this token, or there are too many, or the gametype's not right - - if (i == MT_EMBLEM && (netgame || multiplayer || (modifiedgame && !savemoddata))) // No cheating!! - return; - - // Objectplace landing point - noreturns: - // spawn it x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; From e382c2e09464dcb4c6bb8d51e9c1b5d362a53f68 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 18:59:11 +0100 Subject: [PATCH 118/312] P_SpawnMapThing(): Separated the giant post-Lua hook switch-case statement into its own function, and separated some of the larger cases into their own function as well --- src/p_mobj.c | 1539 +++++++++++++++++++++++++------------------------- 1 file changed, 759 insertions(+), 780 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index c2b40a96b..0397451d0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11890,116 +11890,626 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) return i; } -// -// P_SpawnMapThing -// The fields of the mapthing should -// already be in host byte order. -// -void P_SpawnMapThing(mapthing_t *mthing) +static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) { - mobjtype_t i; - mobj_t *mobj; - fixed_t x, y, z; - boolean doangle = true; + INT32 j; + emblem_t* emblem = M_GetLevelEmblems(gamemap); + skincolors_t emcolor; - if (!mthing->type) - return; // Ignore type-0 things as NOPs - - if (mthing->type == 3328) // 3D Mode start Thing - return; - - if (!objectplacing && P_SpawnNonMobjMapThing(mthing)) - return; - - i = P_GetMobjtype(mthing->type); - if (i == MT_UNKNOWN) - CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - - // Skip all returning/substitution code in objectplace. - if (!objectplacing) + while (emblem) { - if (!P_AllowMobjSpawn(mthing, i)) - return; - - i = P_GetMobjtypeSubstitute(mthing, i); - if (i == MT_NULL) // Don't spawn mobj - return; - } - - // spawn it - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - z = P_GetMobjSpawnHeight(i, mthing, x, y); - - mobj = P_SpawnMobj(x, y, z, i); - mobj->spawnpoint = mthing; - -#ifdef HAVE_BLUA - if (LUAh_MapThingSpawn(mobj, mthing)) - { - if (P_MobjWasRemoved(mobj)) - return; - } - else if (P_MobjWasRemoved(mobj)) - return; - else -#endif - switch(mobj->type) - { - case MT_EMBLEM: - { - INT32 j; - emblem_t *emblem = M_GetLevelEmblems(gamemap); - skincolors_t emcolor; - - while (emblem) - { - if ((emblem->type == ET_GLOBAL || emblem->type == ET_SKIN) && emblem->tag == mthing->angle) - break; - - emblem = M_GetLevelEmblems(-1); - } - - if (!emblem) - { - CONS_Debug(DBG_GAMELOGIC, "No map emblem for map %d with tag %d found!\n", gamemap, mthing->angle); + if ((emblem->type == ET_GLOBAL || emblem->type == ET_SKIN) && emblem->tag == mthing->angle) break; - } - j = emblem - emblemlocations; + emblem = M_GetLevelEmblems(-1); + } - I_Assert(emblemlocations[j].sprite >= 'A' && emblemlocations[j].sprite <= 'Z'); - P_SetMobjState(mobj, mobj->info->spawnstate + (emblemlocations[j].sprite - 'A')); + if (!emblem) + { + CONS_Debug(DBG_GAMELOGIC, "No map emblem for map %d with tag %d found!\n", gamemap, mthing->angle); + return false; + } - mobj->health = j + 1; - emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting - mobj->color = (UINT8)emcolor; + j = emblem - emblemlocations; - if (emblemlocations[j].collected - || (emblemlocations[j].type == ET_SKIN && emblemlocations[j].var != players[0].skin)) + I_Assert(emblemlocations[j].sprite >= 'A' && emblemlocations[j].sprite <= 'Z'); + P_SetMobjState(mobj, mobj->info->spawnstate + (emblemlocations[j].sprite - 'A')); + + mobj->health = j + 1; + emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting + mobj->color = (UINT8)emcolor; + + if (emblemlocations[j].collected + || (emblemlocations[j].type == ET_SKIN && emblemlocations[j].var != players[0].skin)) + { + P_UnsetThingPosition(mobj); + mobj->flags |= MF_NOCLIP; + mobj->flags &= ~MF_SPECIAL; + mobj->flags |= MF_NOBLOCKMAP; + mobj->frame |= (tr_trans50 << FF_TRANSSHIFT); + P_SetThingPosition(mobj); + } + else + { + mobj->frame &= ~FF_TRANSMASK; + + if (emblemlocations[j].type == ET_GLOBAL) { - P_UnsetThingPosition(mobj); - mobj->flags |= MF_NOCLIP; - mobj->flags &= ~MF_SPECIAL; - mobj->flags |= MF_NOBLOCKMAP; - mobj->frame |= (tr_trans50 << FF_TRANSSHIFT); - P_SetThingPosition(mobj); + mobj->reactiontime = emblemlocations[j].var; + if (emblemlocations[j].var & GE_NIGHTSITEM) + { + mobj->flags |= MF_NIGHTSITEM; + mobj->flags &= ~MF_SPECIAL; + mobj->flags2 |= MF2_DONTDRAW; + } + } + } + return true; +} + +static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) +{ + fixed_t mlength, mmaxlength, mlengthset, mspeed, mphase, myaw, mpitch, mminlength, mnumspokes, mpinch, mroll, mnumnospokes, mwidth, mwidthset, mmin, msound, radiusfactor, widthfactor; + angle_t mspokeangle; + mobjtype_t chainlink, macetype, firsttype, linktype; + boolean mdosound, mdocenter, mchainlike = false; + mobj_t *spawnee = NULL, *hprev = mobj; + mobjflag_t mflagsapply; + mobjflag2_t mflags2apply; + mobjeflag_t meflagsapply; + INT32 line; + const size_t mthingi = (size_t)(mthing - mapthings); + + // Find the corresponding linedef special, using angle as tag + // P_FindSpecialLineFromTag works here now =D + line = P_FindSpecialLineFromTag(9, mthing->angle, -1); + + if (line == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Mace chain (mapthing #%s) needs to be tagged to a #9 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); + return false; + } + /* + mapthing - + MTF_AMBUSH : + MT_SPRINGBALLPOINT - upgrade from yellow to red spring + anything else - bigger mace/chain theory + MTF_OBJECTSPECIAL - force silent + MTF_GRAVFLIP - flips objects, doesn't affect chain arrangements + Parameter value : number of "spokes" + + linedef - + ML_NOCLIMB : + MT_CHAINPOINT/MT_CHAINMACEPOINT with ML_EFFECT1 applied - Direction not controllable + anything else - no functionality + ML_EFFECT1 : Swings instead of spins + ML_EFFECT2 : Linktype is replaced with macetype for all spokes not ending in chains (inverted for MT_FIREBARPOINT) + ML_EFFECT3 : Spawn a bonus linktype at the hinge point + ML_EFFECT4 : Don't clip inside the ground + ML_EFFECT5 : Don't stop thinking when too far away + */ + mlength = abs(lines[line].dx >> FRACBITS); + mspeed = abs(lines[line].dy >> (FRACBITS - 4)); + mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360; + if ((mminlength = -sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) < 0) + mminlength = 0; + else if (mminlength > mlength - 1) + mminlength = mlength - 1; + mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360; + myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360; + + mnumspokes = mthing->extrainfo + 1; + mspokeangle = FixedAngle((360*FRACUNIT)/mnumspokes) >> ANGLETOFINESHIFT; + + if (lines[line].backsector) + { + mpinch = (lines[line].backsector->floorheight >> FRACBITS) % 360; + mroll = (lines[line].backsector->ceilingheight >> FRACBITS) % 360; + mnumnospokes = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS); + if ((mwidth = sides[lines[line].sidenum[1]].rowoffset >> FRACBITS) < 0) + mwidth = 0; + } + else + mpinch = mroll = mnumnospokes = mwidth = 0; + + CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n" + "Length is %d (minus %d)\n" + "Speed is %d\n" + "Phase is %d\n" + "Yaw is %d\n" + "Pitch is %d\n" + "No. of spokes is %d (%d antispokes)\n" + "Pinch is %d\n" + "Roll is %d\n" + "Width is %d\n", + sizeu1(mthingi), mlength, mminlength, mspeed, mphase, myaw, mpitch, mnumspokes, mnumnospokes, mpinch, mroll, mwidth); + + if (mnumnospokes > 0 && (mnumnospokes < mnumspokes)) + mnumnospokes = mnumspokes/mnumnospokes; + else + mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes) : 0); + + mobj->lastlook = mspeed; + mobj->movecount = mobj->lastlook; + mobj->angle = FixedAngle(myaw << FRACBITS); + *doangle = false; + mobj->threshold = (FixedAngle(mpitch << FRACBITS) >> ANGLETOFINESHIFT); + mobj->movefactor = mpinch; + mobj->movedir = 0; + + // Mobjtype selection + switch (mobj->type) + { + case MT_SPRINGBALLPOINT: + macetype = ((mthing->options & MTF_AMBUSH) + ? MT_REDSPRINGBALL + : MT_YELLOWSPRINGBALL); + chainlink = MT_SMALLMACECHAIN; + break; + case MT_FIREBARPOINT: + macetype = ((mthing->options & MTF_AMBUSH) + ? MT_BIGFIREBAR + : MT_SMALLFIREBAR); + chainlink = MT_NULL; + break; + case MT_CUSTOMMACEPOINT: + macetype = (mobjtype_t)sides[lines[line].sidenum[0]].toptexture; + if (lines[line].backsector) + chainlink = (mobjtype_t)sides[lines[line].sidenum[1]].toptexture; + else + chainlink = MT_NULL; + break; + case MT_CHAINPOINT: + if (mthing->options & MTF_AMBUSH) + { + macetype = MT_BIGGRABCHAIN; + chainlink = MT_BIGMACECHAIN; } else { - mobj->frame &= ~FF_TRANSMASK; + macetype = MT_SMALLGRABCHAIN; + chainlink = MT_SMALLMACECHAIN; + } + mchainlike = true; + break; + default: + if (mthing->options & MTF_AMBUSH) + { + macetype = MT_BIGMACE; + chainlink = MT_BIGMACECHAIN; + } + else + { + macetype = MT_SMALLMACE; + chainlink = MT_SMALLMACECHAIN; + } + break; + } - if (emblemlocations[j].type == ET_GLOBAL) + if (!macetype && !chainlink) + return true; + + if (mobj->type == MT_CHAINPOINT) + { + if (!mlength) + return true; + } + else + mlength++; + + firsttype = macetype; + + // Adjustable direction + if (lines[line].flags & ML_NOCLIMB) + mobj->flags |= MF_SLIDEME; + + // Swinging + if (lines[line].flags & ML_EFFECT1) + { + mobj->flags2 |= MF2_STRONGBOX; + mmin = ((mnumnospokes > 1) ? 1 : 0); + } + else + mmin = mnumspokes; + + // If over distance away, don't move UNLESS this flag is applied + if (lines[line].flags & ML_EFFECT5) + mobj->flags2 |= MF2_BOSSNOTRAP; + + // Make the links the same type as the end - repeated below + if ((mobj->type != MT_CHAINPOINT) && (((lines[line].flags & ML_EFFECT2) == ML_EFFECT2) != (mobj->type == MT_FIREBARPOINT))) // exclusive or + { + linktype = macetype; + radiusfactor = 2; // Double the radius. + } + else + radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); + + if (!mchainlike) + mchainlike = (firsttype == chainlink); + widthfactor = (mchainlike ? 1 : 2); + + mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP | MF_NOCLIPHEIGHT)); + mflags2apply = ((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0); + meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0); + + msound = (mchainlike ? 0 : (mwidth & 1)); + + // Quick and easy preparatory variable setting + mphase = (FixedAngle(mphase << FRACBITS) >> ANGLETOFINESHIFT); + mroll = (FixedAngle(mroll << FRACBITS) >> ANGLETOFINESHIFT); + +#define makemace(mobjtype, dist, moreflags2) {\ + spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\ + P_SetTarget(&spawnee->tracer, mobj);\ + spawnee->threshold = mphase;\ + spawnee->friction = mroll;\ + spawnee->movefactor = mwidthset;\ + spawnee->movecount = dist;\ + spawnee->angle = myaw;\ + spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\ + spawnee->flags2 |= (mflags2apply|moreflags2);\ + spawnee->eflags |= meflagsapply;\ + P_SetTarget(&hprev->hnext, spawnee);\ + P_SetTarget(&spawnee->hprev, hprev);\ + hprev = spawnee;\ +} + + mdosound = (mspeed && !(mthing->options & MTF_OBJECTSPECIAL)); + mdocenter = (macetype && (lines[line].flags & ML_EFFECT3)); + + // The actual spawning of spokes + while (mnumspokes-- > 0) + { + // Offsets + if (lines[line].flags & ML_EFFECT1) // Swinging + mroll = (mroll - mspokeangle) & FINEMASK; + else // Spinning + mphase = (mphase - mspokeangle) & FINEMASK; + + if (mnumnospokes && !(mnumspokes % mnumnospokes)) // Skipping a "missing" spoke + { + if (mobj->type != MT_CHAINMACEPOINT) + continue; + + linktype = chainlink; + firsttype = ((mthing->options & MTF_AMBUSH) ? MT_BIGGRABCHAIN : MT_SMALLGRABCHAIN); + mmaxlength = 1 + (mlength - 1) * radiusfactor; + radiusfactor = widthfactor = 1; + } + else + { + if (mobj->type == MT_CHAINMACEPOINT) { - mobj->reactiontime = emblemlocations[j].var; - if (emblemlocations[j].var & GE_NIGHTSITEM) + // Make the links the same type as the end - repeated above + if (lines[line].flags & ML_EFFECT2) { - mobj->flags |= MF_NIGHTSITEM; - mobj->flags &= ~MF_SPECIAL; - mobj->flags2 |= MF2_DONTDRAW; + linktype = macetype; + radiusfactor = 2; + } + else + radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); + + firsttype = macetype; + widthfactor = 2; + } + + mmaxlength = mlength; + } + + mwidthset = mwidth; + mlengthset = mminlength; + + if (mdocenter) // Innermost link + makemace(linktype, 0, 0); + + // Out from the center... + if (linktype) + { + while ((++mlengthset) < mmaxlength) + makemace(linktype, radiusfactor*mlengthset, 0); + } + else + mlengthset = mmaxlength; + + // Outermost mace/link + if (firsttype) + makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); + + if (!mwidth) + { + if (mdosound && mnumspokes <= mmin) // Can it make a sound? + spawnee->flags2 |= MF2_BOSSNOTRAP; + } + else + { + // Across the bar! + if (!firsttype) + mwidthset = -mwidth; + else if (mwidth > 0) + { + while ((mwidthset -= widthfactor) > -mwidth) + { + makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); + if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound? + spawnee->flags2 |= MF2_BOSSNOTRAP; } } + else + { + while ((mwidthset += widthfactor) < -mwidth) + { + makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); + if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound? + spawnee->flags2 |= MF2_BOSSNOTRAP; + } + } + mwidth = -mwidth; + + // Outermost mace/link again! + if (firsttype) + makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH); + + // ...and then back into the center! + if (linktype) + while (mlengthset > mminlength) + makemace(linktype, radiusfactor*(mlengthset--), 0); + + if (mdocenter) // Innermost link + makemace(linktype, 0, 0); } + } +#undef makemace + return true; +} + +static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj) +{ + fixed_t radius, speed; + INT32 type, numdivisions, anglespeed, ticcount; + angle_t angledivision; + INT32 line; + const size_t mthingi = (size_t)(mthing - mapthings); + + // Find the corresponding linedef special, using angle as tag + line = P_FindSpecialLineFromTag(15, mthing->angle, -1); + + if (line == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Particle generator (mapthing #%s) needs to be tagged to a #15 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); + return false; + } + + if (sides[lines[line].sidenum[0]].toptexture) + type = sides[lines[line].sidenum[0]].toptexture; // Set as object type in p_setup.c... + else + type = (INT32)MT_PARTICLE; + + if (!lines[line].backsector + || (ticcount = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS)) < 1) + ticcount = 3; + + numdivisions = (mthing->options >> ZSHIFT); + + if (numdivisions) + { + radius = R_PointToDist2(lines[line].v1->x, lines[line].v1->y, lines[line].v2->x, lines[line].v2->y); + anglespeed = (sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) % 360; + angledivision = 360/numdivisions; + } + else + { + numdivisions = 1; // Simple trick to make A_ParticleSpawn simpler. + radius = 0; + anglespeed = 0; + angledivision = 0; + } + + speed = abs(sides[lines[line].sidenum[0]].textureoffset); + if (mthing->options & MTF_OBJECTFLIP) + speed *= -1; + + CONS_Debug(DBG_GAMELOGIC, "Particle Generator (mapthing #%s):\n" + "Radius is %d\n" + "Speed is %d\n" + "Anglespeed is %d\n" + "Numdivisions is %d\n" + "Angledivision is %d\n" + "Type is %d\n" + "Tic seperation is %d\n", + sizeu1(mthingi), radius, speed, anglespeed, numdivisions, angledivision, type, ticcount); + + mobj->angle = 0; + mobj->movefactor = speed; + mobj->lastlook = numdivisions; + mobj->movedir = angledivision*ANG1; + mobj->movecount = anglespeed*ANG1; + mobj->friction = radius; + mobj->threshold = type; + mobj->reactiontime = ticcount; + mobj->cvmem = line; + mobj->watertop = mobj->waterbottom = 0; + return true; +} + +static boolean P_SetupNiGHTSDrone(mapthing_t* mthing, mobj_t* mobj) +{ + boolean flip = mthing->options & MTF_OBJECTFLIP; + boolean topaligned = (mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA); + boolean middlealigned = (mthing->options & MTF_EXTRA) && !(mthing->options & MTF_OBJECTSPECIAL); + boolean bottomoffsetted = !(mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA); + + INT16 timelimit = mthing->angle & 0xFFF; + fixed_t hitboxradius = ((mthing->angle & 0xF000) >> 12)*32*FRACUNIT; + fixed_t hitboxheight = mthing->extrainfo*32*FRACUNIT; + fixed_t oldheight = mobj->height; + fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff; + + if (timelimit > 0) + mobj->health = timelimit; + + if (hitboxradius > 0) + mobj->radius = hitboxradius; + + if (hitboxheight > 0) + mobj->height = hitboxheight; + else + mobj->height = mobjinfo[MT_NIGHTSDRONE].height; + + droneboxmandiff = max(mobj->height - mobjinfo[MT_NIGHTSDRONE_MAN].height, 0); + dronemangoaldiff = max(mobjinfo[MT_NIGHTSDRONE_MAN].height - mobjinfo[MT_NIGHTSDRONE_GOAL].height, 0); + + if (flip && mobj->height != oldheight) + P_TeleportMove(mobj, mobj->x, mobj->y, mobj->z - (mobj->height - oldheight)); + + if (!flip) + { + if (topaligned) // Align droneman to top of hitbox + { + dronemanoffset = droneboxmandiff; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (middlealigned) // Align droneman to center of hitbox + { + dronemanoffset = droneboxmandiff/2; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (bottomoffsetted) + { + dronemanoffset = 24*FRACUNIT; + goaloffset = dronemangoaldiff + dronemanoffset; + } + else + { + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + + sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale); + } + else + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + + if (topaligned) // Align droneman to top of hitbox + { + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (middlealigned) // Align droneman to center of hitbox + { + dronemanoffset = droneboxmandiff/2; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (bottomoffsetted) + { + dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); + goaloffset = dronemangoaldiff + dronemanoffset; + } + else + { + dronemanoffset = droneboxmandiff; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + + sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale); + } + + // spawn visual elements + { + mobj_t* goalpost = P_SpawnMobjFromMobj(mobj, 0, 0, goaloffset, MT_NIGHTSDRONE_GOAL); + mobj_t* sparkle = P_SpawnMobjFromMobj(mobj, 0, 0, sparkleoffset, MT_NIGHTSDRONE_SPARKLING); + mobj_t* droneman = P_SpawnMobjFromMobj(mobj, 0, 0, dronemanoffset, MT_NIGHTSDRONE_MAN); + + P_SetTarget(&mobj->target, goalpost); + P_SetTarget(&goalpost->target, sparkle); + P_SetTarget(&goalpost->tracer, droneman); + + // correct Z position + if (flip) + { + P_TeleportMove(goalpost, goalpost->x, goalpost->y, mobj->z + goaloffset); + P_TeleportMove(sparkle, sparkle->x, sparkle->y, mobj->z + sparkleoffset); + P_TeleportMove(droneman, droneman->x, droneman->y, mobj->z + dronemanoffset); + } + + // Remember position preference for later + mobj->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE); + if (topaligned) + mobj->flags |= MF_SLIDEME; + else if (middlealigned) + mobj->flags |= MF_GRENADEBOUNCE; + else if (!bottomoffsetted) + mobj->flags |= MF_SLIDEME|MF_GRENADEBOUNCE; + + // Remember old Z position and flags for correction detection + goalpost->movefactor = mobj->z; + goalpost->friction = mobj->height; + goalpost->threshold = mobj->flags & (MF_SLIDEME|MF_GRENADEBOUNCE); + } + return true; +} + +static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong) +{ + angle_t angle = FixedAngle(mthing->angle << FRACBITS); + fixed_t x1 = FINECOSINE((angle >> ANGLETOFINESHIFT) & FINEMASK); + fixed_t y1 = FINESINE((angle >> ANGLETOFINESHIFT) & FINEMASK); + fixed_t x2 = FINECOSINE(((angle + ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); + fixed_t y2 = FINESINE(((angle + ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); + statenum_t facestate = strong ? S_REDBOOSTERSEG_FACE : S_YELLOWBOOSTERSEG_FACE; + statenum_t leftstate = strong ? S_REDBOOSTERSEG_LEFT : S_YELLOWBOOSTERSEG_LEFT; + statenum_t rightstate = strong ? S_REDBOOSTERSEG_RIGHT : S_YELLOWBOOSTERSEG_RIGHT; + statenum_t rollerstate = strong ? S_REDBOOSTERROLLER : S_YELLOWBOOSTERROLLER; + + mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG); + seg->angle = angle - ANGLE_90; + P_SetMobjState(seg, facestate); + seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG); + seg->angle = angle + ANGLE_90; + P_SetMobjState(seg, facestate); + seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG); + seg->angle = angle; + P_SetMobjState(seg, leftstate); + seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG); + seg->angle = angle; + P_SetMobjState(seg, rightstate); + + seg = P_SpawnMobjFromMobj(mobj, 13*(x1 + x2), 13*(y1 + y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + seg = P_SpawnMobjFromMobj(mobj, 13*(x1 - x2), 13*(y1 - y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + seg = P_SpawnMobjFromMobj(mobj, -13*(x1 + x2), -13*(y1 + y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + seg = P_SpawnMobjFromMobj(mobj, -13*(x1 - x2), -13*(y1 - y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + + return true; +} + +static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) +{ +#ifdef HAVE_BLUA + boolean override = LUAh_MapThingSpawn(mobj, mthing); + + if (P_MobjWasRemoved(mobj)) + return false; + + if (override) + return true; +#endif + + switch (mobj->type) + { + case MT_EMBLEM: + { + if (!P_SetupEmblem(mthing, mobj)) + return false; break; } case MT_SKYBOX: @@ -12033,7 +12543,7 @@ void P_SpawnMapThing(mapthing_t *mthing) if (mthing->angle) mobj->health = mthing->angle; else - mobj->health = FixedMul(mobj->subsector->sector->ceilingheight - mobj->subsector->sector->floorheight, 3*(FRACUNIT/4))>>FRACBITS; + mobj->health = FixedMul(mobj->subsector->sector->ceilingheight - mobj->subsector->sector->floorheight, 3*(FRACUNIT/4)) >> FRACBITS; break; case MT_METALSONIC_RACE: case MT_METALSONIC_BATTLE: @@ -12048,7 +12558,7 @@ void P_SpawnMapThing(mapthing_t *mthing) break; case MT_BALLOON: if (mthing->angle > 0) - mobj->color = ((mthing->angle-1) % (MAXSKINCOLORS-1))+1; + mobj->color = ((mthing->angle - 1) % (MAXSKINCOLORS - 1)) + 1; break; #define makesoftwarecorona(mo, h) \ corona = P_SpawnMobjFromMobj(mo, 0, 0, h<angle) - mobj->tics = 3*TICRATE + mthing->angle; - else - mobj->tics = 3*TICRATE; + mobj->tics = 3*TICRATE + mthing->angle; break; case MT_FLAMEJET: case MT_VERTICALFLAMEJET: @@ -12120,391 +12627,13 @@ void P_SpawnMapThing(mapthing_t *mthing) case MT_CHAINPOINT: case MT_FIREBARPOINT: case MT_CUSTOMMACEPOINT: - { - fixed_t mlength, mmaxlength, mlengthset, mspeed, mphase, myaw, mpitch, mminlength, mnumspokes, mpinch, mroll, mnumnospokes, mwidth, mwidthset, mmin, msound, radiusfactor, widthfactor; - angle_t mspokeangle; - mobjtype_t chainlink, macetype, firsttype, linktype; - boolean mdosound, mdocenter, mchainlike = false; - mobj_t *spawnee = NULL, *hprev = mobj; - mobjflag_t mflagsapply; - mobjflag2_t mflags2apply; - mobjeflag_t meflagsapply; - INT32 line; - const size_t mthingi = (size_t)(mthing - mapthings); - - // Find the corresponding linedef special, using angle as tag - // P_FindSpecialLineFromTag works here now =D - line = P_FindSpecialLineFromTag(9, mthing->angle, -1); - - if (line == -1) - { - CONS_Debug(DBG_GAMELOGIC, "Mace chain (mapthing #%s) needs to be tagged to a #9 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); - return; - } -/* -mapthing - -MTF_AMBUSH : - MT_SPRINGBALLPOINT - upgrade from yellow to red spring - anything else - bigger mace/chain theory -MTF_OBJECTSPECIAL - force silent -MTF_GRAVFLIP - flips objects, doesn't affect chain arrangements -Parameter value : number of "spokes" - -linedef - -ML_NOCLIMB : - MT_CHAINPOINT/MT_CHAINMACEPOINT with ML_EFFECT1 applied - Direction not controllable - anything else - no functionality -ML_EFFECT1 : Swings instead of spins -ML_EFFECT2 : Linktype is replaced with macetype for all spokes not ending in chains (inverted for MT_FIREBARPOINT) -ML_EFFECT3 : Spawn a bonus linktype at the hinge point -ML_EFFECT4 : Don't clip inside the ground -ML_EFFECT5 : Don't stop thinking when too far away -*/ - mlength = abs(lines[line].dx >> FRACBITS); - mspeed = abs(lines[line].dy >> (FRACBITS - 4)); - mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360; - if ((mminlength = -sides[lines[line].sidenum[0]].rowoffset>>FRACBITS) < 0) - mminlength = 0; - else if (mminlength > mlength-1) - mminlength = mlength-1; - mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360; - myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360; - - mnumspokes = mthing->extrainfo + 1; - mspokeangle = FixedAngle((360*FRACUNIT)/mnumspokes)>>ANGLETOFINESHIFT; - - if (lines[line].backsector) - { - mpinch = (lines[line].backsector->floorheight >> FRACBITS) % 360; - mroll = (lines[line].backsector->ceilingheight >> FRACBITS) % 360; - mnumnospokes = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS); - if ((mwidth = sides[lines[line].sidenum[1]].rowoffset >> FRACBITS) < 0) - mwidth = 0; - } - else - mpinch = mroll = mnumnospokes = mwidth = 0; - - CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n" - "Length is %d (minus %d)\n" - "Speed is %d\n" - "Phase is %d\n" - "Yaw is %d\n" - "Pitch is %d\n" - "No. of spokes is %d (%d antispokes)\n" - "Pinch is %d\n" - "Roll is %d\n" - "Width is %d\n", - sizeu1(mthingi), mlength, mminlength, mspeed, mphase, myaw, mpitch, mnumspokes, mnumnospokes, mpinch, mroll, mwidth); - - if (mnumnospokes > 0 && (mnumnospokes < mnumspokes)) - mnumnospokes = mnumspokes/mnumnospokes; - else - mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes) : 0); - - mobj->lastlook = mspeed; - mobj->movecount = mobj->lastlook; - mobj->angle = FixedAngle(myaw*FRACUNIT); - doangle = false; - mobj->threshold = (FixedAngle(mpitch*FRACUNIT)>>ANGLETOFINESHIFT); - mobj->movefactor = mpinch; - mobj->movedir = 0; - - // Mobjtype selection - switch(mobj->type) - { - case MT_SPRINGBALLPOINT: - macetype = ((mthing->options & MTF_AMBUSH) - ? MT_REDSPRINGBALL - : MT_YELLOWSPRINGBALL); - chainlink = MT_SMALLMACECHAIN; - break; - case MT_FIREBARPOINT: - macetype = ((mthing->options & MTF_AMBUSH) - ? MT_BIGFIREBAR - : MT_SMALLFIREBAR); - chainlink = MT_NULL; - break; - case MT_CUSTOMMACEPOINT: - macetype = (mobjtype_t)sides[lines[line].sidenum[0]].toptexture; - if (lines[line].backsector) - chainlink = (mobjtype_t)sides[lines[line].sidenum[1]].toptexture; - else - chainlink = MT_NULL; - break; - case MT_CHAINPOINT: - if (mthing->options & MTF_AMBUSH) - { - macetype = MT_BIGGRABCHAIN; - chainlink = MT_BIGMACECHAIN; - } - else - { - macetype = MT_SMALLGRABCHAIN; - chainlink = MT_SMALLMACECHAIN; - } - mchainlike = true; - break; - default: - if (mthing->options & MTF_AMBUSH) - { - macetype = MT_BIGMACE; - chainlink = MT_BIGMACECHAIN; - } - else - { - macetype = MT_SMALLMACE; - chainlink = MT_SMALLMACECHAIN; - } - break; - } - - if (!macetype && !chainlink) - break; - - if (mobj->type == MT_CHAINPOINT) - { - if (!mlength) - break; - } - else - mlength++; - - firsttype = macetype; - - // Adjustable direction - if (lines[line].flags & ML_NOCLIMB) - mobj->flags |= MF_SLIDEME; - - // Swinging - if (lines[line].flags & ML_EFFECT1) - { - mobj->flags2 |= MF2_STRONGBOX; - mmin = ((mnumnospokes > 1) ? 1 : 0); - } - else - mmin = mnumspokes; - - // If over distance away, don't move UNLESS this flag is applied - if (lines[line].flags & ML_EFFECT5) - mobj->flags2 |= MF2_BOSSNOTRAP; - - // Make the links the same type as the end - repeated below - if ((mobj->type != MT_CHAINPOINT) && (((lines[line].flags & ML_EFFECT2) == ML_EFFECT2) != (mobj->type == MT_FIREBARPOINT))) // exclusive or - { - linktype = macetype; - radiusfactor = 2; // Double the radius. - } - else - radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); - - if (!mchainlike) - mchainlike = (firsttype == chainlink); - widthfactor = (mchainlike ? 1 : 2); - - mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP|MF_NOCLIPHEIGHT)); - mflags2apply = ((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0); - meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0); - - msound = (mchainlike ? 0 : (mwidth & 1)); - - // Quick and easy preparatory variable setting - mphase = (FixedAngle(mphase*FRACUNIT)>>ANGLETOFINESHIFT); - mroll = (FixedAngle(mroll*FRACUNIT)>>ANGLETOFINESHIFT); - -#define makemace(mobjtype, dist, moreflags2) {\ - spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\ - P_SetTarget(&spawnee->tracer, mobj);\ - spawnee->threshold = mphase;\ - spawnee->friction = mroll;\ - spawnee->movefactor = mwidthset;\ - spawnee->movecount = dist;\ - spawnee->angle = myaw;\ - spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\ - spawnee->flags2 |= (mflags2apply|moreflags2);\ - spawnee->eflags |= meflagsapply;\ - P_SetTarget(&hprev->hnext, spawnee);\ - P_SetTarget(&spawnee->hprev, hprev);\ - hprev = spawnee;\ -} - - mdosound = (mspeed && !(mthing->options & MTF_OBJECTSPECIAL)); - mdocenter = (macetype && (lines[line].flags & ML_EFFECT3)); - - // The actual spawning of spokes - while (mnumspokes-- > 0) - { - // Offsets - if (lines[line].flags & ML_EFFECT1) // Swinging - mroll = (mroll - mspokeangle) & FINEMASK; - else // Spinning - mphase = (mphase - mspokeangle) & FINEMASK; - - if (mnumnospokes && !(mnumspokes % mnumnospokes)) // Skipping a "missing" spoke - { - if (mobj->type != MT_CHAINMACEPOINT) - continue; - - linktype = chainlink; - firsttype = ((mthing->options & MTF_AMBUSH) ? MT_BIGGRABCHAIN : MT_SMALLGRABCHAIN); - mmaxlength = 1 + (mlength - 1)*radiusfactor; - radiusfactor = widthfactor = 1; - } - else - { - if (mobj->type == MT_CHAINMACEPOINT) - { - // Make the links the same type as the end - repeated above - if (lines[line].flags & ML_EFFECT2) - { - linktype = macetype; - radiusfactor = 2; - } - else - radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); - - firsttype = macetype; - widthfactor = 2; - } - - mmaxlength = mlength; - } - - mwidthset = mwidth; - mlengthset = mminlength; - - if (mdocenter) // Innermost link - makemace(linktype, 0, 0); - - // Out from the center... - if (linktype) - { - while ((++mlengthset) < mmaxlength) - makemace(linktype, radiusfactor*mlengthset, 0); - } - else - mlengthset = mmaxlength; - - // Outermost mace/link - if (firsttype) - makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); - - if (!mwidth) - { - if (mdosound && mnumspokes <= mmin) // Can it make a sound? - spawnee->flags2 |= MF2_BOSSNOTRAP; - } - else - { - // Across the bar! - if (!firsttype) - mwidthset = -mwidth; - else if (mwidth > 0) - { - while ((mwidthset -= widthfactor) > -mwidth) - { - makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); - if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound? - spawnee->flags2 |= MF2_BOSSNOTRAP; - } - } - else - { - while ((mwidthset += widthfactor) < -mwidth) - { - makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); - if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound? - spawnee->flags2 |= MF2_BOSSNOTRAP; - } - } - mwidth = -mwidth; - - // Outermost mace/link again! - if (firsttype) - makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH); - - // ...and then back into the center! - if (linktype) - while (mlengthset > mminlength) - makemace(linktype, radiusfactor*(mlengthset--), 0); - - if (mdocenter) // Innermost link - makemace(linktype, 0, 0); - } - } - -#undef makemace - + if (!P_SetupMace(mthing, mobj, doangle)) + return false; break; - } case MT_PARTICLEGEN: - { - fixed_t radius, speed; - INT32 type, numdivisions, anglespeed, ticcount; - angle_t angledivision; - INT32 line; - const size_t mthingi = (size_t)(mthing - mapthings); - - // Find the corresponding linedef special, using angle as tag - line = P_FindSpecialLineFromTag(15, mthing->angle, -1); - - if (line == -1) - { - CONS_Debug(DBG_GAMELOGIC, "Particle generator (mapthing #%s) needs to be tagged to a #15 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); - return; - } - - if (sides[lines[line].sidenum[0]].toptexture) - type = sides[lines[line].sidenum[0]].toptexture; // Set as object type in p_setup.c... - else - type = (INT32)MT_PARTICLE; - - if (!lines[line].backsector - || (ticcount = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS)) < 1) - ticcount = 3; - - numdivisions = (mthing->options >> ZSHIFT); - - if (numdivisions) - { - radius = R_PointToDist2(lines[line].v1->x, lines[line].v1->y, lines[line].v2->x, lines[line].v2->y); - anglespeed = (sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) % 360; - angledivision = 360/numdivisions; - } - else - { - numdivisions = 1; // Simple trick to make A_ParticleSpawn simpler. - radius = 0; - anglespeed = 0; - angledivision = 0; - } - - speed = abs(sides[lines[line].sidenum[0]].textureoffset); - if (mthing->options & MTF_OBJECTFLIP) - speed *= -1; - - CONS_Debug(DBG_GAMELOGIC, "Particle Generator (mapthing #%s):\n" - "Radius is %d\n" - "Speed is %d\n" - "Anglespeed is %d\n" - "Numdivisions is %d\n" - "Angledivision is %d\n" - "Type is %d\n" - "Tic seperation is %d\n", - sizeu1(mthingi), radius, speed, anglespeed, numdivisions, angledivision, type, ticcount); - - mobj->angle = 0; - mobj->movefactor = speed; - mobj->lastlook = numdivisions; - mobj->movedir = angledivision*ANG1; - mobj->movecount = anglespeed*ANG1; - mobj->friction = radius; - mobj->threshold = type; - mobj->reactiontime = ticcount; - mobj->cvmem = line; - mobj->watertop = mobj->waterbottom = 0; - + if (!P_SetupParticleGen(mthing, mobj)) + return false; break; - } case MT_ROCKSPAWNER: mobj->threshold = mthing->angle; mobj->movecount = mthing->extrainfo; @@ -12519,7 +12648,7 @@ ML_EFFECT5 : Don't stop thinking when too far away // Lower 4 bits specify the angle of // the bumper in 30 degree increments. mobj->threshold = (mthing->options & 15) % 12; // It loops over, etc - P_SetMobjState(mobj, mobj->info->spawnstate+mobj->threshold); + P_SetMobjState(mobj, mobj->info->spawnstate + mobj->threshold); break; case MT_EGGCAPSULE: if (mthing->angle <= 0) @@ -12536,122 +12665,8 @@ ML_EFFECT5 : Don't stop thinking when too far away mobj->health = mthing->extrainfo; break; case MT_NIGHTSDRONE: - { - boolean flip = mthing->options & MTF_OBJECTFLIP; - boolean topaligned = (mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA); - boolean middlealigned = (mthing->options & MTF_EXTRA) && !(mthing->options & MTF_OBJECTSPECIAL); - boolean bottomoffsetted = !(mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA); - - INT16 timelimit = mthing->angle & 0xFFF; - fixed_t hitboxradius = ((mthing->angle & 0xF000) >> 12) * 32 * FRACUNIT; - fixed_t hitboxheight = mthing->extrainfo * 32 * FRACUNIT; - fixed_t oldheight = mobj->height; - fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff; - - if (timelimit > 0) - mobj->health = timelimit; - - if (hitboxradius > 0) - mobj->radius = hitboxradius; - - if (hitboxheight > 0) - mobj->height = hitboxheight; - else - mobj->height = mobjinfo[MT_NIGHTSDRONE].height; - - droneboxmandiff = max(mobj->height - mobjinfo[MT_NIGHTSDRONE_MAN].height, 0); - dronemangoaldiff = max(mobjinfo[MT_NIGHTSDRONE_MAN].height - mobjinfo[MT_NIGHTSDRONE_GOAL].height, 0); - - if (flip && mobj->height != oldheight) - P_TeleportMove(mobj, mobj->x, mobj->y, mobj->z - (mobj->height - oldheight)); - - if (!flip) - { - if (topaligned) // Align droneman to top of hitbox - { - dronemanoffset = droneboxmandiff; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (middlealigned) // Align droneman to center of hitbox - { - dronemanoffset = droneboxmandiff / 2; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (bottomoffsetted) - { - dronemanoffset = 24*FRACUNIT; - goaloffset = dronemangoaldiff + dronemanoffset; - } - else - { - dronemanoffset = 0; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - - sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale); - } - else - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - - if (topaligned) // Align droneman to top of hitbox - { - dronemanoffset = 0; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (middlealigned) // Align droneman to center of hitbox - { - dronemanoffset = droneboxmandiff / 2; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (bottomoffsetted) - { - dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); - goaloffset = dronemangoaldiff + dronemanoffset; - } - else - { - dronemanoffset = droneboxmandiff; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - - sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale); - } - - // spawn visual elements - { - mobj_t *goalpost = P_SpawnMobjFromMobj(mobj, 0, 0, goaloffset, MT_NIGHTSDRONE_GOAL); - mobj_t *sparkle = P_SpawnMobjFromMobj(mobj, 0, 0, sparkleoffset, MT_NIGHTSDRONE_SPARKLING); - mobj_t *droneman = P_SpawnMobjFromMobj(mobj, 0, 0, dronemanoffset, MT_NIGHTSDRONE_MAN); - - P_SetTarget(&mobj->target, goalpost); - P_SetTarget(&goalpost->target, sparkle); - P_SetTarget(&goalpost->tracer, droneman); - - // correct Z position - if (flip) - { - P_TeleportMove(goalpost, goalpost->x, goalpost->y, mobj->z + goaloffset); - P_TeleportMove(sparkle, sparkle->x, sparkle->y, mobj->z + sparkleoffset); - P_TeleportMove(droneman, droneman->x, droneman->y, mobj->z + dronemanoffset); - } - - // Remember position preference for later - mobj->flags &= ~(MF_SLIDEME | MF_GRENADEBOUNCE); - if (topaligned) - mobj->flags |= MF_SLIDEME; - else if (middlealigned) - mobj->flags |= MF_GRENADEBOUNCE; - else if (!bottomoffsetted) - mobj->flags |= MF_SLIDEME | MF_GRENADEBOUNCE; - - // Remember old Z position and flags for correction detection - goalpost->movefactor = mobj->z; - goalpost->friction = mobj->height; - goalpost->threshold = mobj->flags & (MF_SLIDEME | MF_GRENADEBOUNCE); - } - } + if (!P_SetupNiGHTSDrone(mthing, mobj)) + return false; break; case MT_HIVEELEMENTAL: if (mthing->extrainfo) @@ -12662,7 +12677,7 @@ ML_EFFECT5 : Don't stop thinking when too far away case MT_GLAREGOYLEDOWN: case MT_GLAREGOYLELONG: if (mthing->angle >= 360) - mobj->tics += 7*(mthing->angle / 360) + 1; // starting delay + mobj->tics += 7*(mthing->angle/360) + 1; // starting delay break; case MT_DSZSTALAGMITE: case MT_DSZ2STALAGMITE: @@ -12673,39 +12688,39 @@ ML_EFFECT5 : Don't stop thinking when too far away } break; case MT_THZTREE: - { // Spawn the branches - angle_t mobjangle = FixedAngle((mthing->angle % 113)<angle = mobjangle + ANGLE_22h; - P_SpawnMobjFromMobj(mobj, 0, 1*FRACUNIT, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_157h; - P_SpawnMobjFromMobj(mobj, -1*FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270; - } - break; + { // Spawn the branches + angle_t mobjangle = FixedAngle((mthing->angle % 113) << FRACBITS); + P_SpawnMobjFromMobj(mobj, FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_22h; + P_SpawnMobjFromMobj(mobj, 0, FRACUNIT, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_157h; + P_SpawnMobjFromMobj(mobj, -FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270; + } + break; case MT_CEZPOLE1: case MT_CEZPOLE2: - { // Spawn the banner - angle_t mobjangle = FixedAngle(mthing->angle<type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2))->angle = mobjangle + ANGLE_90; - } - break; + { // Spawn the banner + angle_t mobjangle = FixedAngle(mthing->angle << FRACBITS); + P_SpawnMobjFromMobj(mobj, + P_ReturnThrustX(mobj, mobjangle, 4 << FRACBITS), + P_ReturnThrustY(mobj, mobjangle, 4 << FRACBITS), + 0, ((mobj->type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2))->angle = mobjangle + ANGLE_90; + } + break; case MT_HHZTREE_TOP: - { // Spawn the branches - angle_t mobjangle = FixedAngle(mthing->angle<angle << FRACBITS) & (ANGLE_90 - 1); + mobj_t* leaf; #define doleaf(x, y) \ leaf = P_SpawnMobjFromMobj(mobj, x, y, 0, MT_HHZTREE_PART);\ leaf->angle = mobjangle;\ P_SetMobjState(leaf, leaf->info->seestate);\ mobjangle += ANGLE_90 - doleaf(1*FRACUNIT, 0); - doleaf(0, 1*FRACUNIT); - doleaf(-1*FRACUNIT, 0); - doleaf(0, -1*FRACUNIT); + doleaf(FRACUNIT, 0); + doleaf(0, FRACUNIT); + doleaf(-FRACUNIT, 0); + doleaf(0, -FRACUNIT); #undef doleaf - } - break; + } + break; case MT_SMASHINGSPIKEBALL: if (mthing->angle > 0) mobj->tics += mthing->angle; @@ -12736,94 +12751,27 @@ ML_EFFECT5 : Don't stop thinking when too far away 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); + mobj_t* leaf = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, 0, MT_BIGFERNLEAF); leaf->angle = angle; angle += ANGLE_45; } break; } case MT_REDBOOSTER: - { - angle_t angle = FixedAngle(mthing->angle << FRACBITS); - fixed_t x1 = FINECOSINE((angle >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t y1 = FINESINE((angle >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t x2 = FINECOSINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t y2 = FINESINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); - - mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG); - seg->angle = angle-ANGLE_90; - P_SetMobjState(seg, S_REDBOOSTERSEG_FACE); - seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG); - seg->angle = angle+ANGLE_90; - P_SetMobjState(seg, S_REDBOOSTERSEG_FACE); - seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERSEG_LEFT); - seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERSEG_RIGHT); - - seg = P_SpawnMobjFromMobj(mobj, 13*(x1+x2), 13*(y1+y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, 13*(x1-x2), 13*(y1-y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, -13*(x1+x2), -13*(y1+y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, -13*(x1-x2), -13*(y1-y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERROLLER); - break; - } case MT_YELLOWBOOSTER: - { - angle_t angle = FixedAngle(mthing->angle << FRACBITS); - fixed_t x1 = FINECOSINE((angle >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t y1 = FINESINE((angle >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t x2 = FINECOSINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t y2 = FINESINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); - - mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG); - seg->angle = angle-ANGLE_90; - P_SetMobjState(seg, S_YELLOWBOOSTERSEG_FACE); - seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG); - seg->angle = angle+ANGLE_90; - P_SetMobjState(seg, S_YELLOWBOOSTERSEG_FACE); - seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERSEG_LEFT); - seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERSEG_RIGHT); - - seg = P_SpawnMobjFromMobj(mobj, 13*(x1+x2), 13*(y1+y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, 13*(x1-x2), 13*(y1-y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, -13*(x1+x2), -13*(y1+y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, -13*(x1-x2), -13*(y1-y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERROLLER); + if (!P_SetupBooster(mthing, mobj, mobj->type == MT_REDBOOSTER)) + return false; break; - } - default: - break; - } + case MT_AXIS: + // Inverted if uppermost bit is set + if (mthing->angle & 16384) + mobj->flags2 |= MF2_AMBUSH; - if (mobj->flags & MF_BOSS) - { - if (mthing->options & MTF_OBJECTSPECIAL) // No egg trap for this boss - mobj->flags2 |= MF2_BOSSNOTRAP; - } - - if (i == MT_AXIS || i == MT_AXISTRANSFER || i == MT_AXISTRANSFERLINE) // Axis Points - { + if (mthing->angle > 0) + mobj->radius = (mthing->angle & 16383) << FRACBITS; + // FALLTHRU + case MT_AXISTRANSFER: + case MT_AXISTRANSFERLINE: // Mare it belongs to mobj->threshold = min(mthing->extrainfo, 7); @@ -12831,38 +12779,29 @@ ML_EFFECT5 : Don't stop thinking when too far away mobj->health = mthing->options; mobj->flags2 |= MF2_AXIS; - - if (i == MT_AXIS) - { - // Inverted if uppermost bit is set - if (mthing->angle & 16384) - mobj->flags2 |= MF2_AMBUSH; - - if (mthing->angle > 0) - mobj->radius = (mthing->angle & 16383)*FRACUNIT; - } - } - else if (i == MT_TOKEN) - { + break; + case MT_TOKEN: // We advanced tokenbits earlier due to the return check. // Subtract 1 here for the correct value. mobj->health = 1 << (tokenbits - 1); - } - else if (i == MT_CYBRAKDEMON && mthing->options & MTF_AMBUSH) + break; + case MT_CYBRAKDEMON: + if (mthing->options & MTF_AMBUSH) + { + mobj_t* elecmobj; + elecmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_CYBRAKDEMON_ELECTRIC_BARRIER); + P_SetTarget(&elecmobj->target, mobj); + elecmobj->angle = FixedAngle(mthing->angle << FRACBITS); + elecmobj->destscale = mobj->scale*2; + P_SetScale(elecmobj, elecmobj->destscale); + } + break; + case MT_STARPOST: { - mobj_t *elecmobj; - elecmobj = P_SpawnMobj(x, y, z, MT_CYBRAKDEMON_ELECTRIC_BARRIER); - P_SetTarget(&elecmobj->target, mobj); - elecmobj->angle = FixedAngle(mthing->angle<destscale = mobj->scale*2; - P_SetScale(elecmobj, elecmobj->destscale); - } - else if (i == MT_STARPOST) - { - thinker_t *th; - mobj_t *mo2; + thinker_t* th; + mobj_t* mo2; boolean foundanother = false; - mobj->health = (mthing->angle / 360) + 1; + mobj->health = (mthing->angle/360) + 1; // See if other starposts exist in this level that have the same value. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) @@ -12870,7 +12809,7 @@ ML_EFFECT5 : Don't stop thinking when too far away if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; - mo2 = (mobj_t *)th; + mo2 = (mobj_t*)th; if (mo2 == mobj) continue; @@ -12884,14 +12823,14 @@ ML_EFFECT5 : Don't stop thinking when too far away if (!foundanother) numstarposts++; + break; } - else if (i == MT_SPIKE) - { + case MT_SPIKE: // Pop up spikes! if (mthing->options & MTF_OBJECTSPECIAL) { mobj->flags &= ~MF_SCENERY; - mobj->fuse = (16 - mthing->extrainfo) * (mthing->angle + mobj->info->speed) / 16; + mobj->fuse = (16 - mthing->extrainfo)*(mthing->angle + mobj->info->speed)/16; if (mthing->options & MTF_EXTRA) P_SetMobjState(mobj, mobj->info->meleestate); } @@ -12903,14 +12842,13 @@ ML_EFFECT5 : Don't stop thinking when too far away mobj->flags |= MF_SOLID; P_SetThingPosition(mobj); } - } - else if (i == MT_WALLSPIKE) - { + break; + case MT_WALLSPIKE: // Pop up spikes! if (mthing->options & MTF_OBJECTSPECIAL) { mobj->flags &= ~MF_SCENERY; - mobj->fuse = (16 - mthing->extrainfo) * ((mthing->angle/360) + mobj->info->speed) / 16; + mobj->fuse = (16 - mthing->extrainfo)*((mthing->angle/360) + mobj->info->speed)/16; if (mthing->options & MTF_EXTRA) P_SetMobjState(mobj, mobj->info->meleestate); } @@ -12918,64 +12856,51 @@ ML_EFFECT5 : Don't stop thinking when too far away if (!(mthing->options & MTF_AMBUSH) && !metalrecording) { P_UnsetThingPosition(mobj); - mobj->flags &= ~(MF_NOBLOCKMAP|MF_NOCLIPHEIGHT); + mobj->flags &= ~(MF_NOBLOCKMAP | MF_NOCLIPHEIGHT); mobj->flags |= MF_SOLID; P_SetThingPosition(mobj); } // spawn base { - const angle_t mobjangle = FixedAngle(mthing->angle<angle << FRACBITS); // the mobj's own angle hasn't been set quite yet so... const fixed_t baseradius = mobj->radius - mobj->scale; - mobj_t *base = P_SpawnMobj( - mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius), - mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius), - mobj->z, MT_WALLSPIKEBASE); + mobj_t* base = P_SpawnMobj( + mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius), + mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius), + mobj->z, MT_WALLSPIKEBASE); base->angle = mobjangle + ANGLE_90; base->destscale = mobj->destscale; P_SetScale(base, mobj->scale); P_SetTarget(&base->target, mobj); P_SetTarget(&mobj->tracer, base); } - } - - //count 10 ring boxes into the number of rings equation too. - if (i == MT_RING_BOX && nummaprings >= 0) - nummaprings += 10; - - if (i == MT_BIGTUMBLEWEED || i == MT_LITTLETUMBLEWEED) - { + break; + case MT_RING_BOX: + //count 10 ring boxes into the number of rings equation too. + if (nummaprings >= 0) + nummaprings += 10; + break; + case MT_BIGTUMBLEWEED: + case MT_LITTLETUMBLEWEED: if (mthing->options & MTF_AMBUSH) { - mobj->momz += FixedMul(16*FRACUNIT, mobj->scale); - - if (P_RandomChance(FRACUNIT/2)) - mobj->momx += FixedMul(16*FRACUNIT, mobj->scale); - else - mobj->momx -= FixedMul(16*FRACUNIT, mobj->scale); - - if (P_RandomChance(FRACUNIT/2)) - mobj->momy += FixedMul(16*FRACUNIT, mobj->scale); - else - mobj->momy -= FixedMul(16*FRACUNIT,mobj->scale); + fixed_t offset = FixedMul(16*FRACUNIT, mobj->scale); + mobj->momx += P_RandomChance(FRACUNIT/2) ? offset : -offset; + mobj->momy += P_RandomChance(FRACUNIT/2) ? offset : -offset; + mobj->momz += offset; } - } - - // CTF flag pointers - if (i == MT_REDFLAG) - { + break; + case MT_REDFLAG: redflag = mobj; rflagpoint = mobj->spawnpoint; - } - if (i == MT_BLUEFLAG) - { + break; + case MT_BLUEFLAG: blueflag = mobj; bflagpoint = mobj->spawnpoint; - } - - // special push/pull stuff - if (i == MT_PUSH || i == MT_PULL) - { + break; + case MT_PUSH: + case MT_PULL: mobj->health = 0; // Default behaviour: pushing uses XY, fading uses XYZ if (mthing->options & MTF_AMBUSH) @@ -12984,14 +12909,68 @@ ML_EFFECT5 : Don't stop thinking when too far away mobj->health |= 2; // If object special is set, fade using XY if (G_IsSpecialStage(gamemap)) - { - if (i == MT_PUSH) - P_SetMobjState(mobj, S_GRAVWELLGREEN); - if (i == MT_PULL) - P_SetMobjState(mobj, S_GRAVWELLRED); - } + P_SetMobjState(mobj, (mobj->type == MT_PUSH) ? S_GRAVWELLGREEN : S_GRAVWELLRED); + break; + default: + break; } + if (mobj->flags & MF_BOSS) + { + if (mthing->options & MTF_OBJECTSPECIAL) // No egg trap for this boss + mobj->flags2 |= MF2_BOSSNOTRAP; + } + + return true; +} + +// +// P_SpawnMapThing +// The fields of the mapthing should +// already be in host byte order. +// +void P_SpawnMapThing(mapthing_t *mthing) +{ + mobjtype_t i; + mobj_t *mobj; + fixed_t x, y, z; + boolean doangle = true; + + if (!mthing->type) + return; // Ignore type-0 things as NOPs + + if (mthing->type == 3328) // 3D Mode start Thing + return; + + if (!objectplacing && P_SpawnNonMobjMapThing(mthing)) + return; + + i = P_GetMobjtype(mthing->type); + if (i == MT_UNKNOWN) + CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); + + // Skip all returning/substitution code in objectplace. + if (!objectplacing) + { + if (!P_AllowMobjSpawn(mthing, i)) + return; + + i = P_GetMobjtypeSubstitute(mthing, i); + if (i == MT_NULL) // Don't spawn mobj + return; + } + + // spawn it + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + z = P_GetMobjSpawnHeight(i, mthing, x, y); + + mobj = P_SpawnMobj(x, y, z, i); + mobj->spawnpoint = mthing; + + if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle)) + return; + if (doangle) mobj->angle = FixedAngle(mthing->angle< Date: Mon, 23 Dec 2019 19:08:40 +0100 Subject: [PATCH 119/312] P_SpawnMapThing(): Separate handling of MTF_AMBUSH and MTF_OBJECTSPECIAL in its own functions --- src/p_mobj.c | 120 ++++++++++++++++++++++++++------------------------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 0397451d0..04411f585 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11598,6 +11598,12 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* offset = 288*FRACUNIT; break; + // Horizontal springs, may float additional units with MTF_AMBUSH. + case MT_YELLOWHORIZ: + case MT_REDHORIZ: + case MT_BLUEHORIZ: + offset += mthing->options & MTF_AMBUSH ? 16*FRACUNIT : 0; + // Ring-like items, may float additional units with MTF_AMBUSH. case MT_SPIKEBALL: case MT_EMERALDSPAWN: @@ -12924,6 +12930,59 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean return true; } +static void P_SetAmbush(mobj_t *mobj) +{ + if (mobj->type == MT_YELLOWDIAG || mobj->type == MT_REDDIAG || mobj->type == MT_BLUEDIAG) + mobj->angle += ANGLE_22h; + + if (mobj->flags & MF_NIGHTSITEM) + { + // Spawn already displayed + mobj->flags |= MF_SPECIAL; + mobj->flags &= ~MF_NIGHTSITEM; + } + + if (mobj->flags & MF_PUSHABLE) + mobj->flags &= ~MF_PUSHABLE; + + if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) + { + // flag for strong/weak random boxes + // any monitor with nonzero speed is allowed to respawn like this + mobj->flags2 |= MF2_AMBUSH; + } + + else if (mobj->type != MT_AXIS && + mobj->type != MT_AXISTRANSFER && + mobj->type != MT_AXISTRANSFERLINE && + mobj->type != MT_NIGHTSBUMPER && + mobj->type != MT_STARPOST) + mobj->flags2 |= MF2_AMBUSH; +} + +static void P_SetObjectSpecial(mobj_t *mobj) +{ + if (mobj->type == MT_YELLOWDIAG || mobj->type == MT_REDDIAG || mobj->type == MT_BLUEDIAG) + mobj->flags |= MF_NOGRAVITY; + + if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) + { + // flag for strong/weak random boxes + // any monitor with nonzero speed is allowed to respawn like this + mobj->flags2 |= MF2_STRONGBOX; + } + + // Requires you to be in bonus time to activate + if (mobj->flags & MF_NIGHTSITEM) + mobj->flags2 |= MF2_STRONGBOX; + + // Pushables bounce and slide coolly with object special flag set + if (mobj->flags & MF_PUSHABLE) + { + mobj->flags2 |= MF2_SLIDEPUSH; + mobj->flags |= MF_BOUNCE; + } +} // // P_SpawnMapThing // The fields of the mapthing should @@ -12988,67 +13047,10 @@ void P_SpawnMapThing(mapthing_t *mthing) else { if (mthing->options & MTF_AMBUSH) - { - if (i == MT_YELLOWDIAG || i == MT_REDDIAG || i == MT_BLUEDIAG) - mobj->angle += ANGLE_22h; - - if (i == MT_YELLOWHORIZ || i == MT_REDHORIZ || i == MT_BLUEHORIZ) - { - if (mthing->options & MTF_OBJECTFLIP) - mobj->z -= 16*FRACUNIT; - else - mobj->z += 16*FRACUNIT; - } - - - if (mobj->flags & MF_NIGHTSITEM) - { - // Spawn already displayed - mobj->flags |= MF_SPECIAL; - mobj->flags &= ~MF_NIGHTSITEM; - } - - if (mobj->flags & MF_PUSHABLE) - mobj->flags &= ~MF_PUSHABLE; - - if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) - { - // flag for strong/weak random boxes - // any monitor with nonzero speed is allowed to respawn like this - mobj->flags2 |= MF2_AMBUSH; - } - - else if (mthing->type != mobjinfo[MT_AXIS].doomednum && - mthing->type != mobjinfo[MT_AXISTRANSFER].doomednum && - mthing->type != mobjinfo[MT_AXISTRANSFERLINE].doomednum && - mthing->type != mobjinfo[MT_NIGHTSBUMPER].doomednum && - mthing->type != mobjinfo[MT_STARPOST].doomednum) - mobj->flags2 |= MF2_AMBUSH; - } + P_SetAmbush(mobj); if (mthing->options & MTF_OBJECTSPECIAL) - { - if (i == MT_YELLOWDIAG || i == MT_REDDIAG || i == MT_BLUEDIAG) - mobj->flags |= MF_NOGRAVITY; - - if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) - { - // flag for strong/weak random boxes - // any monitor with nonzero speed is allowed to respawn like this - mobj->flags2 |= MF2_STRONGBOX; - } - - // Requires you to be in bonus time to activate - if (mobj->flags & MF_NIGHTSITEM) - mobj->flags2 |= MF2_STRONGBOX; - - // Pushables bounce and slide coolly with object special flag set - if (mobj->flags & MF_PUSHABLE) - { - mobj->flags2 |= MF2_SLIDEPUSH; - mobj->flags |= MF_BOUNCE; - } - } + P_SetObjectSpecial(mobj); } // Generic reverse gravity for individual objects flag. From 2b3922a8f3a4aefb316b508cfdaaa42eac57d269 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 20:12:45 +0100 Subject: [PATCH 120/312] Set mthing->mobj before the flags handling code, since at this point the setup can't fail anymore --- src/p_mobj.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 04411f585..1acecbb76 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13033,12 +13033,11 @@ void P_SpawnMapThing(mapthing_t *mthing) if (doangle) mobj->angle = FixedAngle(mthing->angle<mobj = mobj; + // ignore MTF_ flags and return early if (i == MT_NIGHTSBUMPER) - { - mthing->mobj = mobj; return; - } if ((mthing->options & MTF_AMBUSH) && (mthing->options & MTF_OBJECTSPECIAL) @@ -13073,8 +13072,6 @@ void P_SpawnMapThing(mapthing_t *mthing) // Final set of not being able to draw nightsitems. if (mobj->flags & MF_NIGHTSITEM) mobj->flags2 |= MF2_DONTDRAW; - - mthing->mobj = mobj; } static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, sector_t* sec, INT32 hoopsize, fixed_t sizefactor) From a5a8d0c77b6368a2247f8b673987105f23b35bd2 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Mon, 23 Dec 2019 14:01:37 -0600 Subject: [PATCH 121/312] Cap dashspeed to at least mindash before revving. --- src/p_user.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index 2b82ae697..003135a90 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4635,6 +4635,8 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) S_StartSound(player->mo, sfx_spin); break; } + if (player->dashspeed < player->mindash) + player->dashspeed = player->mindash; if (player->dashspeed < player->maxdash && player->mindash != player->maxdash) { #define chargecalculation (6*(player->dashspeed - player->mindash))/(player->maxdash - player->mindash) From 24f8d4ef519a8541e24df3b47a2c9293d053ff11 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 21:17:12 +0100 Subject: [PATCH 122/312] Made a mapthing-independent version of P_GetMobjSpawnHeight so P_SpawnHoopsAndRings subfunctions can use it instead of duplicating code. --- src/p_mobj.c | 144 +++++++++++++++++---------------------------------- 1 file changed, 48 insertions(+), 96 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1acecbb76..54e603fe9 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11559,10 +11559,39 @@ void P_MovePlayerToStarpost(INT32 playernum) mapthing_t *huntemeralds[MAXHUNTEMERALDS]; INT32 numhuntemeralds; - -static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y) +static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t offset, const boolean flip) { const subsector_t *ss = R_PointInSubsector(x, y); + + // Axis objects snap to the floor. + if (mobjtype == MT_AXIS || mobjtype == MT_AXISTRANSFER || mobjtype == MT_AXISTRANSFERLINE) + return ONFLOORZ; + + if (!offset) // Snap to the surfaces when there's no offset set. + { + if (flip) + return ONCEILINGZ; + else + return ONFLOORZ; + } + + // Establish height. + if (flip) + return ( +#ifdef ESLOPE + ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : +#endif + ss->sector->ceilingheight) - offset - mobjinfo[mobjtype].height; + else + return ( +#ifdef ESLOPE + ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : +#endif + ss->sector->floorheight) + offset; +} + +static fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y) +{ fixed_t offset = mthing->z << FRACBITS; boolean flip = (!!(mobjinfo[mobjtype].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); @@ -11573,12 +11602,6 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* flip = false; break; - // Axis objects snap to the floor. - case MT_AXIS: - case MT_AXISTRANSFER: - case MT_AXISTRANSFERLINE: - return ONFLOORZ; - // Objects with a non-zero default height. case MT_CRAWLACOMMANDER: case MT_DETON: @@ -11626,27 +11649,7 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; } - if (!offset) // Snap to the surfaces when there's no offset set. - { - if (flip) - return ONCEILINGZ; - else - return ONFLOORZ; - } - - // Establish height. - if (flip) - return ( -#ifdef ESLOPE - ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : -#endif - ss->sector->ceilingheight) - offset - mobjinfo[mobjtype].height; - else - return ( -#ifdef ESLOPE - ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : -#endif - ss->sector->floorheight) + offset; + return P_GetMobjSpawnHeight(mobjtype, x, y, offset, flip); } static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) @@ -13022,7 +13025,7 @@ void P_SpawnMapThing(mapthing_t *mthing) // spawn it x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; - z = P_GetMobjSpawnHeight(i, mthing, x, y); + z = P_GetMapThingSpawnHeight(i, mthing, x, y); mobj = P_SpawnMobj(x, y, z, i); mobj->spawnpoint = mthing; @@ -13074,7 +13077,7 @@ void P_SpawnMapThing(mapthing_t *mthing) mobj->flags2 |= MF2_DONTDRAW; } -static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, sector_t* sec, INT32 hoopsize, fixed_t sizefactor) +static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, INT32 hoopsize, fixed_t sizefactor) { mobj_t *mobj = NULL; mobj_t *nextmobj = NULL; @@ -13085,11 +13088,7 @@ static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, sec angle_t fa; TVector v, *res; - z += -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; + z = P_GetMobjSpawnHeight(MT_HOOP, x, y, z, false); hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); hoopcenter->spawnpoint = mthing; @@ -13209,7 +13208,7 @@ static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bo ringthing = (gametype == GT_CTF) ? MT_BLUETEAMRING : MT_RING; } - z = P_GetMobjSpawnHeight(ringthing, mthing, x, y); + z = P_GetMapThingSpawnHeight(ringthing, mthing, x, y); mobj = P_SpawnMobj(x, y, z, ringthing); mobj->spawnpoint = mthing; @@ -13230,11 +13229,10 @@ static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bo P_SetMobjState(mobj, mobj->info->seestate); } -static void P_SpawnVerticalSpringRings(mapthing_t *mthing, fixed_t x, fixed_t y, sector_t* sec, boolean nightsreplace) +static void P_SpawnVerticalSpringRings(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, boolean nightsreplace) { mobjtype_t ringthing = MT_RING; mobj_t* mobj = NULL; - fixed_t z; INT32 r; INT32 dist = 64*FRACUNIT; @@ -13247,26 +13245,7 @@ static void P_SpawnVerticalSpringRings(mapthing_t *mthing, fixed_t x, fixed_t y, if (nightsreplace) ringthing = MT_NIGHTSSTAR; - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->z) - z -= (mthing->z << FRACBITS); - } - else - { - z = ( -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight); - if (mthing->z) - z += (mthing->z << FRACBITS); - } + z = P_GetMobjSpawnHeight(ringthing, x, y, z, mthing->options & MTF_OBJECTFLIP); for (r = 1; r <= 5; r++) { @@ -13292,11 +13271,10 @@ static void P_SpawnVerticalSpringRings(mapthing_t *mthing, fixed_t x, fixed_t y, } } -static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, sector_t* sec, boolean nightsreplace) +static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, boolean nightsreplace) { mobjtype_t ringthing = MT_RING; mobj_t *mobj = NULL; - fixed_t z; INT32 r; angle_t closestangle, fa; @@ -13313,26 +13291,7 @@ static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, closestangle = FixedAngle(mthing->angle << FRACBITS); fa = (closestangle >> ANGLETOFINESHIFT); - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->z) - z -= (mthing->z << FRACBITS); - } - else - { - z = ( -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight); - if (mthing->z) - z += (mthing->z << FRACBITS); - } + z = P_GetMobjSpawnHeight(ringthing, x, y, z, mthing->options & MTF_OBJECTFLIP); for (r = 1; r <= iterations; r++) { @@ -13361,11 +13320,11 @@ static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, } } -static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, sector_t* sec, boolean bonustime, boolean nightsreplace) +static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, boolean bonustime, boolean nightsreplace) { mobjtype_t ringthing = MT_RING; mobj_t *mobj = NULL; - fixed_t z, finalx, finaly, finalz; + fixed_t finalx, finaly, finalz; angle_t closestangle, fa; INT32 i; TVector v, *res; @@ -13378,13 +13337,7 @@ static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, sector_t size = 192*FRACUNIT; } - z = -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - if (mthing->z) - z += (mthing->z << FRACBITS); + z = P_GetMobjSpawnHeight(ringthing, x, y, z, false); closestangle = FixedAngle(mthing->angle << FRACBITS); @@ -13462,7 +13415,6 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) fixed_t x = mthing->x << FRACBITS; fixed_t y = mthing->y << FRACBITS; fixed_t z = mthing->z << FRACBITS; - sector_t *sec = R_PointInSubsector(x, y)->sector; boolean nightsreplace = ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)); switch (mthing->type) @@ -13470,11 +13422,11 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) // Special placement patterns case 600: // 5 vertical rings (yellow spring) case 601: // 5 vertical rings (red spring) - P_SpawnVerticalSpringRings(mthing, x, y, sec, nightsreplace); + P_SpawnVerticalSpringRings(mthing, x, y, z, nightsreplace); return; case 602: // 5 diagonal rings (yellow spring) case 603: // 10 diagonal rings (red spring) - P_SpawnDiagonalSpringRings(mthing, x, y, sec, nightsreplace); + P_SpawnDiagonalSpringRings(mthing, x, y, z, nightsreplace); return; case 604: // Circle of rings (8 items) case 605: // Circle of rings (16 bits) @@ -13482,16 +13434,16 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) case 607: // Circle of blue spheres (16 items) case 608: // Circle of rings and blue spheres (8 items) case 609: // Circle of rings and blue spheres (16 items) - P_SpawnItemCircle(mthing, x, y, sec, bonustime, nightsreplace); + P_SpawnItemCircle(mthing, x, y, z, bonustime, nightsreplace); return; // Hoops case 1705: // Generic NiGHTS hoop - P_SpawnHoop(mthing, x, y, z, sec, 24, 4*FRACUNIT); + P_SpawnHoop(mthing, x, y, z, 24, 4*FRACUNIT); return; case 1713: // Customizable NiGHTS hoop // For each flag add 16 fracunits to the size // Default (0 flags) is 32 fracunits - P_SpawnHoop(mthing, x, y, z, sec, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); + P_SpawnHoop(mthing, x, y, z, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); return; default: // All manners of rings and coins P_SpawnRingItem(mthing, x, y, bonustime, nightsreplace); From 6939da01641bc950f99b0080055d9729e16c2c3b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 21:35:03 +0100 Subject: [PATCH 123/312] Turned nightsreplace into a macro so we have don't have to keep dragging it along as a function parameter --- src/p_mobj.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 54e603fe9..aa19716df 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13182,7 +13182,9 @@ static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, INT } while (hoopsize >= 8); } -static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bonustime, boolean nightsreplace) +#define nightsreplace ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) + +static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bonustime) { mobjtype_t ringthing = MT_RING; mobj_t *mobj = NULL; @@ -13229,7 +13231,7 @@ static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bo P_SetMobjState(mobj, mobj->info->seestate); } -static void P_SpawnVerticalSpringRings(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, boolean nightsreplace) +static void P_SpawnVerticalSpringRings(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z) { mobjtype_t ringthing = MT_RING; mobj_t* mobj = NULL; @@ -13271,7 +13273,7 @@ static void P_SpawnVerticalSpringRings(mapthing_t *mthing, fixed_t x, fixed_t y, } } -static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, boolean nightsreplace) +static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z) { mobjtype_t ringthing = MT_RING; mobj_t *mobj = NULL; @@ -13320,7 +13322,7 @@ static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, } } -static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, boolean bonustime, boolean nightsreplace) +static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, boolean bonustime) { mobjtype_t ringthing = MT_RING; mobj_t *mobj = NULL; @@ -13415,18 +13417,17 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) fixed_t x = mthing->x << FRACBITS; fixed_t y = mthing->y << FRACBITS; fixed_t z = mthing->z << FRACBITS; - boolean nightsreplace = ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)); switch (mthing->type) { // Special placement patterns case 600: // 5 vertical rings (yellow spring) case 601: // 5 vertical rings (red spring) - P_SpawnVerticalSpringRings(mthing, x, y, z, nightsreplace); + P_SpawnVerticalSpringRings(mthing, x, y, z); return; case 602: // 5 diagonal rings (yellow spring) case 603: // 10 diagonal rings (red spring) - P_SpawnDiagonalSpringRings(mthing, x, y, z, nightsreplace); + P_SpawnDiagonalSpringRings(mthing, x, y, z); return; case 604: // Circle of rings (8 items) case 605: // Circle of rings (16 bits) @@ -13434,7 +13435,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) case 607: // Circle of blue spheres (16 items) case 608: // Circle of rings and blue spheres (8 items) case 609: // Circle of rings and blue spheres (16 items) - P_SpawnItemCircle(mthing, x, y, z, bonustime, nightsreplace); + P_SpawnItemCircle(mthing, x, y, z, bonustime); return; // Hoops case 1705: // Generic NiGHTS hoop @@ -13446,7 +13447,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) P_SpawnHoop(mthing, x, y, z, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); return; default: // All manners of rings and coins - P_SpawnRingItem(mthing, x, y, bonustime, nightsreplace); + P_SpawnRingItem(mthing, x, y, bonustime); } } From d0f7877fd03c75c4a94528d8d9bfb6ce2c8ed09b Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 18:33:39 -0300 Subject: [PATCH 124/312] Turn noglobals into setglobals, move the extra global variable handling to gamestateglobals. --- src/lua_script.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/lua_script.c b/src/lua_script.c index 13592815b..759f858a0 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -79,8 +79,22 @@ FUNCNORETURN static int LUA_Panic(lua_State *L) #endif } +// See lib_getenum in dehacked.c. +static boolean gamestateglobals(const char *csname, lua_State *L) +{ + if (fastcmp(csname,"redscore")) + redscore = (UINT32)luaL_checkinteger(L, 2); + else if (fastcmp(csname,"bluescore")) + bluescore = (UINT32)luaL_checkinteger(L, 2); + else + return false; + + // Global variable set, so return and don't error. + return true; +} + // This function decides which global variables you are allowed to set. -static int noglobals(lua_State *L) +static int setglobals(lua_State *L) { const char *csname; char *name; @@ -106,16 +120,8 @@ static int noglobals(lua_State *L) return 0; } - if (fastcmp(csname,"redscore")) - { - redscore = (UINT32)luaL_checkinteger(L, 2); + if (gamestateglobals(csname, L)) return 0; - } - else if (fastcmp(csname,"bluescore")) - { - bluescore = (UINT32)luaL_checkinteger(L, 2); - return 0; - } Z_Free(name); return luaL_error(L, "Implicit global " LUA_QS " prevented. Create a local variable instead.", csname); @@ -155,7 +161,7 @@ static void LUA_ClearState(void) // lock the global namespace lua_getmetatable(L, LUA_GLOBALSINDEX); - lua_pushcfunction(L, noglobals); + lua_pushcfunction(L, setglobals); lua_setfield(L, -2, "__newindex"); lua_newtable(L); lua_setfield(L, -2, "__metatable"); From 7425591815bb87a962196ab5da13f9398986c6e3 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 18:37:38 -0300 Subject: [PATCH 125/312] Add pointlimit and timelimit to Lua. --- src/dehacked.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index e3fac0a4b..0d8f230e0 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -10828,6 +10828,12 @@ static inline int lib_getenum(lua_State *L) } else if (fastcmp(word,"redscore")) { lua_pushinteger(L, redscore); return 1; + } else if (fastcmp(word,"timelimit")) { + lua_pushinteger(L, cv_timelimit.value); + return 1; + } else if (fastcmp(word,"pointlimit")) { + lua_pushinteger(L, cv_pointlimit.value); + return 1; // begin map vars } else if (fastcmp(word,"spstage_start")) { lua_pushinteger(L, spstage_start); From 5ebd84c3e734feea8099b00ae864b98e6548a0ff Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 18:49:23 -0300 Subject: [PATCH 126/312] Move ALL the Lua global variable stuff into lua_script.c. --- src/dehacked.c | 208 +----------------------------------------- src/lua_script.c | 228 +++++++++++++++++++++++++++++++++++++++++++++-- src/lua_script.h | 2 + 3 files changed, 224 insertions(+), 214 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 0d8f230e0..d1e18a1d7 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -10777,213 +10777,7 @@ static inline int lib_getenum(lua_State *L) // DYNAMIC variables too!! // Try not to add anything that would break netgames or timeattack replays here. // You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime. - if (fastcmp(word,"gamemap")) { - lua_pushinteger(L, gamemap); - return 1; - } else if (fastcmp(word,"maptol")) { - lua_pushinteger(L, maptol); - return 1; - } else if (fastcmp(word,"ultimatemode")) { - lua_pushboolean(L, ultimatemode != 0); - return 1; - } else if (fastcmp(word,"mariomode")) { - lua_pushboolean(L, mariomode != 0); - return 1; - } else if (fastcmp(word,"twodlevel")) { - lua_pushboolean(L, twodlevel != 0); - return 1; - } else if (fastcmp(word,"circuitmap")) { - lua_pushboolean(L, circuitmap); - return 1; - } else if (fastcmp(word,"netgame")) { - lua_pushboolean(L, netgame); - return 1; - } else if (fastcmp(word,"multiplayer")) { - lua_pushboolean(L, multiplayer); - return 1; - } else if (fastcmp(word,"modeattacking")) { - lua_pushboolean(L, modeattacking); - return 1; - } else if (fastcmp(word,"splitscreen")) { - lua_pushboolean(L, splitscreen); - return 1; - } else if (fastcmp(word,"gamecomplete")) { - lua_pushboolean(L, gamecomplete); - return 1; - } else if (fastcmp(word,"devparm")) { - lua_pushboolean(L, devparm); - return 1; - } else if (fastcmp(word,"modifiedgame")) { - lua_pushboolean(L, modifiedgame && !savemoddata); - return 1; - } else if (fastcmp(word,"menuactive")) { - lua_pushboolean(L, menuactive); - return 1; - } else if (fastcmp(word,"paused")) { - lua_pushboolean(L, paused); - return 1; - } else if (fastcmp(word,"bluescore")) { - lua_pushinteger(L, bluescore); - return 1; - } else if (fastcmp(word,"redscore")) { - lua_pushinteger(L, redscore); - return 1; - } else if (fastcmp(word,"timelimit")) { - lua_pushinteger(L, cv_timelimit.value); - return 1; - } else if (fastcmp(word,"pointlimit")) { - lua_pushinteger(L, cv_pointlimit.value); - return 1; - // begin map vars - } else if (fastcmp(word,"spstage_start")) { - lua_pushinteger(L, spstage_start); - return 1; - } else if (fastcmp(word,"sstage_start")) { - lua_pushinteger(L, sstage_start); - return 1; - } else if (fastcmp(word,"sstage_end")) { - lua_pushinteger(L, sstage_end); - return 1; - } else if (fastcmp(word,"smpstage_start")) { - lua_pushinteger(L, smpstage_start); - return 1; - } else if (fastcmp(word,"smpstage_end")) { - lua_pushinteger(L, smpstage_end); - return 1; - } else if (fastcmp(word,"titlemap")) { - lua_pushinteger(L, titlemap); - return 1; - } else if (fastcmp(word,"titlemapinaction")) { - lua_pushboolean(L, (titlemapinaction != TITLEMAP_OFF)); - return 1; - } else if (fastcmp(word,"bootmap")) { - lua_pushinteger(L, bootmap); - return 1; - } else if (fastcmp(word,"tutorialmap")) { - lua_pushinteger(L, tutorialmap); - return 1; - } else if (fastcmp(word,"tutorialmode")) { - lua_pushboolean(L, tutorialmode); - return 1; - // end map vars - // begin CTF colors - } else if (fastcmp(word,"skincolor_redteam")) { - lua_pushinteger(L, skincolor_redteam); - return 1; - } else if (fastcmp(word,"skincolor_blueteam")) { - lua_pushinteger(L, skincolor_blueteam); - return 1; - } else if (fastcmp(word,"skincolor_redring")) { - lua_pushinteger(L, skincolor_redring); - return 1; - } else if (fastcmp(word,"skincolor_bluering")) { - lua_pushinteger(L, skincolor_bluering); - return 1; - // end CTF colors - // begin timers - } else if (fastcmp(word,"invulntics")) { - lua_pushinteger(L, invulntics); - return 1; - } else if (fastcmp(word,"sneakertics")) { - lua_pushinteger(L, sneakertics); - return 1; - } else if (fastcmp(word,"flashingtics")) { - lua_pushinteger(L, flashingtics); - return 1; - } else if (fastcmp(word,"tailsflytics")) { - lua_pushinteger(L, tailsflytics); - return 1; - } else if (fastcmp(word,"underwatertics")) { - lua_pushinteger(L, underwatertics); - return 1; - } else if (fastcmp(word,"spacetimetics")) { - lua_pushinteger(L, spacetimetics); - return 1; - } else if (fastcmp(word,"extralifetics")) { - lua_pushinteger(L, extralifetics); - return 1; - } else if (fastcmp(word,"nightslinktics")) { - lua_pushinteger(L, nightslinktics); - return 1; - } else if (fastcmp(word,"gameovertics")) { - lua_pushinteger(L, gameovertics); - return 1; - } else if (fastcmp(word,"ammoremovaltics")) { - lua_pushinteger(L, ammoremovaltics); - return 1; - // end timers - } else if (fastcmp(word,"gametype")) { - lua_pushinteger(L, gametype); - return 1; - } else if (fastcmp(word,"gametyperules")) { - lua_pushinteger(L, gametyperules); - return 1; - } else if (fastcmp(word,"leveltime")) { - lua_pushinteger(L, leveltime); - return 1; - } else if (fastcmp(word,"curWeather")) { - lua_pushinteger(L, curWeather); - return 1; - } else if (fastcmp(word,"globalweather")) { - lua_pushinteger(L, globalweather); - return 1; - } else if (fastcmp(word,"levelskynum")) { - lua_pushinteger(L, levelskynum); - return 1; - } else if (fastcmp(word,"globallevelskynum")) { - lua_pushinteger(L, globallevelskynum); - return 1; - } else if (fastcmp(word,"mapmusname")) { - lua_pushstring(L, mapmusname); - return 1; - } else if (fastcmp(word,"mapmusflags")) { - lua_pushinteger(L, mapmusflags); - return 1; - } else if (fastcmp(word,"mapmusposition")) { - lua_pushinteger(L, mapmusposition); - return 1; - // local player variables, by popular request - } else if (fastcmp(word,"consoleplayer")) { // player controlling console (aka local player 1) - if (consoleplayer < 0 || !playeringame[consoleplayer]) - return 0; - LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER); - return 1; - } else if (fastcmp(word,"displayplayer")) { // player visible on screen (aka display player 1) - if (displayplayer < 0 || !playeringame[displayplayer]) - return 0; - LUA_PushUserdata(L, &players[displayplayer], META_PLAYER); - return 1; - } else if (fastcmp(word,"secondarydisplayplayer")) { // local/display player 2, for splitscreen - if (!splitscreen || secondarydisplayplayer < 0 || !playeringame[secondarydisplayplayer]) - return 0; - LUA_PushUserdata(L, &players[secondarydisplayplayer], META_PLAYER); - return 1; - // end local player variables - } else if (fastcmp(word,"server")) { - if ((!multiplayer || !netgame) && !playeringame[serverplayer]) - return 0; - LUA_PushUserdata(L, &players[serverplayer], META_PLAYER); - return 1; - } else if (fastcmp(word,"admin")) { // BACKWARDS COMPATIBILITY HACK: This was replaced with IsPlayerAdmin(), but some 2.1 Lua scripts still use the admin variable. It now points to the first admin player in the array. - LUA_Deprecated(L, "admin", "IsPlayerAdmin(player)"); - if (!playeringame[adminplayers[0]] || IsPlayerAdmin(serverplayer)) - return 0; - LUA_PushUserdata(L, &players[adminplayers[0]], META_PLAYER); - return 1; - } else if (fastcmp(word,"emeralds")) { - lua_pushinteger(L, emeralds); - return 1; - } else if (fastcmp(word,"gravity")) { - lua_pushinteger(L, gravity); - return 1; - } else if (fastcmp(word,"VERSIONSTRING")) { - lua_pushstring(L, VERSIONSTRING); - return 1; - } else if (fastcmp(word, "token")) { - lua_pushinteger(L, token); - return 1; - } - return 0; + return LUA_PushGlobals(L, word); } int LUA_EnumLib(lua_State *L) diff --git a/src/lua_script.c b/src/lua_script.c index 759f858a0..4b5e72938 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -18,7 +18,9 @@ #include "w_wad.h" #include "p_setup.h" #include "r_state.h" +#include "r_sky.h" #include "g_game.h" +#include "f_finale.h" #include "byteptr.h" #include "p_saveg.h" #include "p_local.h" @@ -79,18 +81,230 @@ FUNCNORETURN static int LUA_Panic(lua_State *L) #endif } -// See lib_getenum in dehacked.c. -static boolean gamestateglobals(const char *csname, lua_State *L) +// Moved here from lib_getenum. +int LUA_PushGlobals(lua_State *L, const char *word) { - if (fastcmp(csname,"redscore")) + if (fastcmp(word,"gamemap")) { + lua_pushinteger(L, gamemap); + return 1; + } else if (fastcmp(word,"maptol")) { + lua_pushinteger(L, maptol); + return 1; + } else if (fastcmp(word,"ultimatemode")) { + lua_pushboolean(L, ultimatemode != 0); + return 1; + } else if (fastcmp(word,"mariomode")) { + lua_pushboolean(L, mariomode != 0); + return 1; + } else if (fastcmp(word,"twodlevel")) { + lua_pushboolean(L, twodlevel != 0); + return 1; + } else if (fastcmp(word,"circuitmap")) { + lua_pushboolean(L, circuitmap); + return 1; + } else if (fastcmp(word,"netgame")) { + lua_pushboolean(L, netgame); + return 1; + } else if (fastcmp(word,"multiplayer")) { + lua_pushboolean(L, multiplayer); + return 1; + } else if (fastcmp(word,"modeattacking")) { + lua_pushboolean(L, modeattacking); + return 1; + } else if (fastcmp(word,"splitscreen")) { + lua_pushboolean(L, splitscreen); + return 1; + } else if (fastcmp(word,"gamecomplete")) { + lua_pushboolean(L, gamecomplete); + return 1; + } else if (fastcmp(word,"devparm")) { + lua_pushboolean(L, devparm); + return 1; + } else if (fastcmp(word,"modifiedgame")) { + lua_pushboolean(L, modifiedgame && !savemoddata); + return 1; + } else if (fastcmp(word,"menuactive")) { + lua_pushboolean(L, menuactive); + return 1; + } else if (fastcmp(word,"paused")) { + lua_pushboolean(L, paused); + return 1; + } else if (fastcmp(word,"bluescore")) { + lua_pushinteger(L, bluescore); + return 1; + } else if (fastcmp(word,"redscore")) { + lua_pushinteger(L, redscore); + return 1; + } else if (fastcmp(word,"timelimit")) { + lua_pushinteger(L, cv_timelimit.value); + return 1; + } else if (fastcmp(word,"pointlimit")) { + lua_pushinteger(L, cv_pointlimit.value); + return 1; + // begin map vars + } else if (fastcmp(word,"spstage_start")) { + lua_pushinteger(L, spstage_start); + return 1; + } else if (fastcmp(word,"sstage_start")) { + lua_pushinteger(L, sstage_start); + return 1; + } else if (fastcmp(word,"sstage_end")) { + lua_pushinteger(L, sstage_end); + return 1; + } else if (fastcmp(word,"smpstage_start")) { + lua_pushinteger(L, smpstage_start); + return 1; + } else if (fastcmp(word,"smpstage_end")) { + lua_pushinteger(L, smpstage_end); + return 1; + } else if (fastcmp(word,"titlemap")) { + lua_pushinteger(L, titlemap); + return 1; + } else if (fastcmp(word,"titlemapinaction")) { + lua_pushboolean(L, (titlemapinaction != TITLEMAP_OFF)); + return 1; + } else if (fastcmp(word,"bootmap")) { + lua_pushinteger(L, bootmap); + return 1; + } else if (fastcmp(word,"tutorialmap")) { + lua_pushinteger(L, tutorialmap); + return 1; + } else if (fastcmp(word,"tutorialmode")) { + lua_pushboolean(L, tutorialmode); + return 1; + // end map vars + // begin CTF colors + } else if (fastcmp(word,"skincolor_redteam")) { + lua_pushinteger(L, skincolor_redteam); + return 1; + } else if (fastcmp(word,"skincolor_blueteam")) { + lua_pushinteger(L, skincolor_blueteam); + return 1; + } else if (fastcmp(word,"skincolor_redring")) { + lua_pushinteger(L, skincolor_redring); + return 1; + } else if (fastcmp(word,"skincolor_bluering")) { + lua_pushinteger(L, skincolor_bluering); + return 1; + // end CTF colors + // begin timers + } else if (fastcmp(word,"invulntics")) { + lua_pushinteger(L, invulntics); + return 1; + } else if (fastcmp(word,"sneakertics")) { + lua_pushinteger(L, sneakertics); + return 1; + } else if (fastcmp(word,"flashingtics")) { + lua_pushinteger(L, flashingtics); + return 1; + } else if (fastcmp(word,"tailsflytics")) { + lua_pushinteger(L, tailsflytics); + return 1; + } else if (fastcmp(word,"underwatertics")) { + lua_pushinteger(L, underwatertics); + return 1; + } else if (fastcmp(word,"spacetimetics")) { + lua_pushinteger(L, spacetimetics); + return 1; + } else if (fastcmp(word,"extralifetics")) { + lua_pushinteger(L, extralifetics); + return 1; + } else if (fastcmp(word,"nightslinktics")) { + lua_pushinteger(L, nightslinktics); + return 1; + } else if (fastcmp(word,"gameovertics")) { + lua_pushinteger(L, gameovertics); + return 1; + } else if (fastcmp(word,"ammoremovaltics")) { + lua_pushinteger(L, ammoremovaltics); + return 1; + // end timers + } else if (fastcmp(word,"gametype")) { + lua_pushinteger(L, gametype); + return 1; + } else if (fastcmp(word,"gametyperules")) { + lua_pushinteger(L, gametyperules); + return 1; + } else if (fastcmp(word,"leveltime")) { + lua_pushinteger(L, leveltime); + return 1; + } else if (fastcmp(word,"curWeather")) { + lua_pushinteger(L, curWeather); + return 1; + } else if (fastcmp(word,"globalweather")) { + lua_pushinteger(L, globalweather); + return 1; + } else if (fastcmp(word,"levelskynum")) { + lua_pushinteger(L, levelskynum); + return 1; + } else if (fastcmp(word,"globallevelskynum")) { + lua_pushinteger(L, globallevelskynum); + return 1; + } else if (fastcmp(word,"mapmusname")) { + lua_pushstring(L, mapmusname); + return 1; + } else if (fastcmp(word,"mapmusflags")) { + lua_pushinteger(L, mapmusflags); + return 1; + } else if (fastcmp(word,"mapmusposition")) { + lua_pushinteger(L, mapmusposition); + return 1; + // local player variables, by popular request + } else if (fastcmp(word,"consoleplayer")) { // player controlling console (aka local player 1) + if (consoleplayer < 0 || !playeringame[consoleplayer]) + return 0; + LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER); + return 1; + } else if (fastcmp(word,"displayplayer")) { // player visible on screen (aka display player 1) + if (displayplayer < 0 || !playeringame[displayplayer]) + return 0; + LUA_PushUserdata(L, &players[displayplayer], META_PLAYER); + return 1; + } else if (fastcmp(word,"secondarydisplayplayer")) { // local/display player 2, for splitscreen + if (!splitscreen || secondarydisplayplayer < 0 || !playeringame[secondarydisplayplayer]) + return 0; + LUA_PushUserdata(L, &players[secondarydisplayplayer], META_PLAYER); + return 1; + // end local player variables + } else if (fastcmp(word,"server")) { + if ((!multiplayer || !netgame) && !playeringame[serverplayer]) + return 0; + LUA_PushUserdata(L, &players[serverplayer], META_PLAYER); + return 1; + } else if (fastcmp(word,"admin")) { // BACKWARDS COMPATIBILITY HACK: This was replaced with IsPlayerAdmin(), but some 2.1 Lua scripts still use the admin variable. It now points to the first admin player in the array. + LUA_Deprecated(L, "admin", "IsPlayerAdmin(player)"); + if (!playeringame[adminplayers[0]] || IsPlayerAdmin(serverplayer)) + return 0; + LUA_PushUserdata(L, &players[adminplayers[0]], META_PLAYER); + return 1; + } else if (fastcmp(word,"emeralds")) { + lua_pushinteger(L, emeralds); + return 1; + } else if (fastcmp(word,"gravity")) { + lua_pushinteger(L, gravity); + return 1; + } else if (fastcmp(word,"VERSIONSTRING")) { + lua_pushstring(L, VERSIONSTRING); + return 1; + } else if (fastcmp(word, "token")) { + lua_pushinteger(L, token); + return 1; + } + return 0; +} + +// See the above. +int LUA_CheckGlobals(lua_State *L, const char *word) +{ + if (fastcmp(word, "redscore")) redscore = (UINT32)luaL_checkinteger(L, 2); - else if (fastcmp(csname,"bluescore")) + else if (fastcmp(word, "bluescore")) bluescore = (UINT32)luaL_checkinteger(L, 2); else - return false; + return 0; // Global variable set, so return and don't error. - return true; + return 1; } // This function decides which global variables you are allowed to set. @@ -120,7 +334,7 @@ static int setglobals(lua_State *L) return 0; } - if (gamestateglobals(csname, L)) + if (LUA_CheckGlobals(L, csname)) return 0; Z_Free(name); diff --git a/src/lua_script.h b/src/lua_script.h index 4f66d3f8a..8f27dcb4c 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -54,6 +54,8 @@ void LUA_InvalidatePlayer(player_t *player); void LUA_Step(void); void LUA_Archive(void); void LUA_UnArchive(void); +int LUA_PushGlobals(lua_State *L, const char *word); +int LUA_CheckGlobals(lua_State *L, const char *word); void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c void LUA_CVarChanged(const char *name); // lua_consolelib.c int Lua_optoption(lua_State *L, int narg, From edddc3e64e43351e99368605cc4c09edd6cbe289 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 18:54:25 -0300 Subject: [PATCH 127/312] Custom gametype constant support for Lua. --- src/lua_baselib.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 5f9d3dbf6..b0935983e 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2642,6 +2642,7 @@ static int lib_gAddGametype(lua_State *L) lua_Integer i; const char *gtname = NULL; + const char *gtconst = NULL; const char *gtdescription = NULL; INT16 newgtidx = 0; UINT32 newgtrules = 0; @@ -2678,39 +2679,43 @@ static int lib_gAddGametype(lua_State *L) if (!lua_isstring(L, 3)) TYPEERROR("name", LUA_TSTRING) gtname = Z_StrDup(lua_tostring(L, 3)); - } else if (i == 2 || (k && fasticmp(k, "rules"))) { + } else if (i == 2 || (k && fasticmp(k, "identifier"))) { + if (!lua_isstring(L, 3)) + TYPEERROR("identifier", LUA_TSTRING) + gtconst = Z_StrDup(lua_tostring(L, 3)); + } else if (i == 3 || (k && fasticmp(k, "rules"))) { if (!lua_isnumber(L, 3)) TYPEERROR("rules", LUA_TNUMBER) newgtrules = (UINT32)lua_tointeger(L, 3); - } else if (i == 3 || (k && fasticmp(k, "typeoflevel"))) { + } else if (i == 4 || (k && fasticmp(k, "typeoflevel"))) { if (!lua_isnumber(L, 3)) TYPEERROR("typeoflevel", LUA_TNUMBER) newgttol = (UINT32)lua_tointeger(L, 3); - } else if (i == 4 || (k && fasticmp(k, "rankingtype"))) { + } else if (i == 5 || (k && fasticmp(k, "rankingtype"))) { if (!lua_isnumber(L, 3)) TYPEERROR("rankingtype", LUA_TNUMBER) newgtrankingstype = (INT16)lua_tointeger(L, 3); - } else if (i == 5 || (k && fasticmp(k, "intermissiontype"))) { + } else if (i == 6 || (k && fasticmp(k, "intermissiontype"))) { if (!lua_isnumber(L, 3)) TYPEERROR("intermissiontype", LUA_TNUMBER) newgtinttype = (int)lua_tointeger(L, 3); - } else if (i == 6 || (k && fasticmp(k, "defaultpointlimit"))) { + } else if (i == 7 || (k && fasticmp(k, "defaultpointlimit"))) { if (!lua_isnumber(L, 3)) TYPEERROR("defaultpointlimit", LUA_TNUMBER) newgtpointlimit = (INT32)lua_tointeger(L, 3); - } else if (i == 7 || (k && fasticmp(k, "defaulttimelimit"))) { + } else if (i == 8 || (k && fasticmp(k, "defaulttimelimit"))) { if (!lua_isnumber(L, 3)) TYPEERROR("defaulttimelimit", LUA_TNUMBER) newgttimelimit = (INT32)lua_tointeger(L, 3); - } else if (i == 8 || (k && fasticmp(k, "description"))) { + } else if (i == 9 || (k && fasticmp(k, "description"))) { if (!lua_isstring(L, 3)) TYPEERROR("description", LUA_TSTRING) gtdescription = Z_StrDup(lua_tostring(L, 3)); - } else if (i == 9 || (k && fasticmp(k, "headerleftcolor"))) { + } else if (i == 10 || (k && fasticmp(k, "headerleftcolor"))) { if (!lua_isnumber(L, 3)) TYPEERROR("headerleftcolor", LUA_TNUMBER) newgtleftcolor = (UINT8)lua_tointeger(L, 3); - } else if (i == 10 || (k && fasticmp(k, "headerrightcolor"))) { + } else if (i == 11 || (k && fasticmp(k, "headerrightcolor"))) { if (!lua_isnumber(L, 3)) TYPEERROR("headerrightcolor", LUA_TNUMBER) newgtrightcolor = (UINT8)lua_tointeger(L, 3); @@ -2753,7 +2758,9 @@ static int lib_gAddGametype(lua_State *L) Gametype_Names[newgtidx] = gtname; // Write the constant name. - G_AddGametypeConstant(newgtidx, gtname); + if (gtconst == NULL) + gtconst = gtname; + G_AddGametypeConstant(newgtidx, gtconst); // Update gametype_cons_t accordingly. G_UpdateGametypeSelections(); From d050e04dae61594149b2f029f2f872119b6d3f2e Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 18:58:33 -0300 Subject: [PATCH 128/312] Bail out if there are no more free gametype slots. --- src/lua_baselib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index b0935983e..e5d477549 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2734,6 +2734,10 @@ static int lib_gAddGametype(lua_State *L) // pop gametype table lua_pop(L, 1); + // Ran out of gametype slots + if (gametypecount == NUMGAMETYPEFREESLOTS) + return luaL_error(L, "Ran out of free gametype slots!"); + // Set defaults if (gtname == NULL) gtname = Z_StrDup("Unnamed gametype"); From 50dd0a71db5a38ad4ccb1d2c0bee3b112b0ca8bf Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 22:58:58 +0100 Subject: [PATCH 129/312] Turn size and number of items for item circle into function parameters (in preparation for UDMF) --- src/p_mobj.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index aa19716df..b4ac43e21 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13322,7 +13322,7 @@ static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, } } -static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, boolean bonustime) +static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, INT32 numitems, fixed_t size, boolean bonustime) { mobjtype_t ringthing = MT_RING; mobj_t *mobj = NULL; @@ -13330,14 +13330,6 @@ static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t angle_t closestangle, fa; INT32 i; TVector v, *res; - INT32 numitems = 8; - INT32 size = 96*FRACUNIT; - - if (mthing->type & 1) - { - numitems = 16; - size = 192*FRACUNIT; - } z = P_GetMobjSpawnHeight(ringthing, x, y, z, false); @@ -13430,13 +13422,17 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) P_SpawnDiagonalSpringRings(mthing, x, y, z); return; case 604: // Circle of rings (8 items) - case 605: // Circle of rings (16 bits) + case 605: // Circle of rings (16 items) case 606: // Circle of blue spheres (8 items) case 607: // Circle of blue spheres (16 items) case 608: // Circle of rings and blue spheres (8 items) case 609: // Circle of rings and blue spheres (16 items) - P_SpawnItemCircle(mthing, x, y, z, bonustime); + { + INT32 numitems = (mthing->type & 1) ? 16 : 8; + fixed_t size = (mthing->type & 1) ? 192*FRACUNIT : 96*FRACUNIT; + P_SpawnItemCircle(mthing, x, y, z, numitems, size, bonustime); return; + } // Hoops case 1705: // Generic NiGHTS hoop P_SpawnHoop(mthing, x, y, z, 24, 4*FRACUNIT); From bbe946ac1e8d741536d62224fa9c89651eaaa28e Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 19:00:46 -0300 Subject: [PATCH 130/312] Bail out earlier. --- src/lua_baselib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e5d477549..20eaa2048 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2660,6 +2660,10 @@ static int lib_gAddGametype(lua_State *L) if (!lua_lumploading) return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); + // Ran out of gametype slots + if (gametypecount == NUMGAMETYPEFREESLOTS) + return luaL_error(L, "Ran out of free gametype slots!"); + #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("G_AddGametype") " (%s)", e); #define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1))) @@ -2734,10 +2738,6 @@ static int lib_gAddGametype(lua_State *L) // pop gametype table lua_pop(L, 1); - // Ran out of gametype slots - if (gametypecount == NUMGAMETYPEFREESLOTS) - return luaL_error(L, "Ran out of free gametype slots!"); - // Set defaults if (gtname == NULL) gtname = Z_StrDup("Unnamed gametype"); From e9f69b9c6a07c3bbda1aec57def1f20cc2c457d9 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 19:08:57 -0300 Subject: [PATCH 131/312] Add sstimer to LUA_PushGlobals. --- src/lua_script.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 4b5e72938..eb1afaf09 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -228,6 +228,9 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"leveltime")) { lua_pushinteger(L, leveltime); return 1; + } else if (fastcmp(word,"sstimer")) { + lua_pushinteger(L, sstimer); + return 1; } else if (fastcmp(word,"curWeather")) { lua_pushinteger(L, curWeather); return 1; From bb1f43d37458ecb699c7860983f6cc7ea003a86b Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 19:16:10 -0300 Subject: [PATCH 132/312] Add gametyperules to LUA_CheckGlobals. --- src/lua_script.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lua_script.c b/src/lua_script.c index eb1afaf09..18d9a87c2 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -299,7 +299,9 @@ int LUA_PushGlobals(lua_State *L, const char *word) // See the above. int LUA_CheckGlobals(lua_State *L, const char *word) { - if (fastcmp(word, "redscore")) + if (fastcmp(word, "gametyperules")) + gametyperules = (UINT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "redscore")) redscore = (UINT32)luaL_checkinteger(L, 2); else if (fastcmp(word, "bluescore")) bluescore = (UINT32)luaL_checkinteger(L, 2); From 630c06b7b0a40b99d04d04f07903d78d41cab8a7 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 19:24:06 -0300 Subject: [PATCH 133/312] Turn GTR_CHASECAM into GTR_FIRSTPERSON. --- src/dehacked.c | 2 +- src/doomstat.h | 6 +++--- src/g_game.c | 16 ++++++++-------- src/p_setup.c | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index d1e18a1d7..ee079aad1 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8870,7 +8870,7 @@ static const char *const GAMETYPERULE_LIST[] = { "HIDETIME", "HIDEFROZEN", "BLINDFOLDED", - "CHASECAM", + "FIRSTPERSON", "MATCHEMERALDS", "TEAMFLAGS", "PITYSHIELD", diff --git a/src/doomstat.h b/src/doomstat.h index 0ab8c1bff..940d2d60c 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -389,7 +389,7 @@ enum GameType // Game type rules enum GameTypeRules { - GTR_CAMPAIGN = 1, // Linear Co-op map progression. Don't allow random maps. + GTR_CAMPAIGN = 1, // Linear Co-op map progression, don't allow random maps GTR_RINGSLINGER = 1<<1, // Outside of Co-op, Competition, and Race (overriden by cv_ringslinger) GTR_SPECTATORS = 1<<2, // Outside of Co-op, Competition, and Race GTR_FRIENDLYFIRE = 1<<3, // Always allow friendly fire @@ -402,12 +402,12 @@ enum GameTypeRules GTR_HIDETIME = 1<<10, // Hide time (Tag and Hide and Seek) GTR_HIDEFROZEN = 1<<11, // Frozen after hide time (Hide and Seek, but not Tag) GTR_BLINDFOLDED = 1<<12, // Blindfolded view (Tag and Hide and Seek) - GTR_CHASECAM = 1<<13, // Prefer chasecam at map load (All platform gametypes) + GTR_FIRSTPERSON = 1<<13, // First person camera GTR_MATCHEMERALDS = 1<<14, // Ringslinger emeralds (Match and CTF) GTR_TEAMFLAGS = 1<<15, // Gametype has team flags (CTF) GTR_PITYSHIELD = 1<<16, // Award pity shield GTR_DEATHPENALTY = 1<<17, // Death score penalty - GTR_NOSPECTATORSPAWN = 1<<18, // For use with GTR_SPECTATORS - spawn in the map instead of with the spectators + GTR_NOSPECTATORSPAWN = 1<<18, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators GTR_DEATHMATCHSTARTS = 1<<19, // Use deathmatch starts GTR_SPECIALSTAGES = 1<<20, // Allow special stages GTR_EMERALDTOKENS = 1<<21, // Spawn emerald tokens diff --git a/src/g_game.c b/src/g_game.c index b29824b1c..34524c8f9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3167,24 +3167,24 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Co-op - GTR_CAMPAIGN|GTR_LIVES|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, + GTR_CAMPAIGN|GTR_LIVES|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, // Competition - GTR_RACE|GTR_LIVES|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_ALLOWEXIT, + GTR_RACE|GTR_LIVES|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_ALLOWEXIT, // Race - GTR_RACE|GTR_CHASECAM|GTR_SPAWNENEMIES|GTR_ALLOWEXIT, + GTR_RACE|GTR_SPAWNENEMIES|GTR_ALLOWEXIT, // Match - GTR_RINGSLINGER|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY, // Team Match - GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_PITYSHIELD, // Tag - GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, // Hide and Seek - GTR_RINGSLINGER|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, // CTF - GTR_RINGSLINGER|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD, }; // diff --git a/src/p_setup.c b/src/p_setup.c index 821f8bcd5..34f0cf882 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2673,7 +2673,7 @@ boolean P_SetupLevel(boolean skipprecip) // chasecam on in chaos, race, coop // chasecam off in match, tag, capture the flag - chase = (gametyperules & GTR_CHASECAM) || (maptol & TOL_2D); + chase = (!(gametyperules & GTR_FIRSTPERSON)) || (maptol & TOL_2D); if (!dedicated) { From ffd6cf4acad17ba5f1c60a42dcf19d56e2f75db3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 24 Dec 2019 00:10:29 +0100 Subject: [PATCH 134/312] Replaced functions for spawning premade rows of rings with a function for spawning a generic row of rings (groundwork for UDMF) --- src/p_mobj.c | 76 ++++++++++------------------------------------------ 1 file changed, 14 insertions(+), 62 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index b4ac43e21..f25690ed8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13231,58 +13231,13 @@ static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bo P_SetMobjState(mobj, mobj->info->seestate); } -static void P_SpawnVerticalSpringRings(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z) -{ - mobjtype_t ringthing = MT_RING; - mobj_t* mobj = NULL; - INT32 r; - - INT32 dist = 64*FRACUNIT; - if (mthing->type == 601) - dist = 128*FRACUNIT; - - if (ultimatemode) - return; // No rings in Ultimate! - - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - - z = P_GetMobjSpawnHeight(ringthing, x, y, z, mthing->options & MTF_OBJECTFLIP); - - for (r = 1; r <= 5; r++) - { - if (mthing->options & MTF_OBJECTFLIP) - z -= dist; - else - z += dist; - - mobj = P_SpawnMobj(x, y, z, ringthing); - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = FixedAngle(mthing->angle << FRACBITS); - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } -} - -static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z) +static void P_SpawnItemRow(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle) { mobjtype_t ringthing = MT_RING; mobj_t *mobj = NULL; INT32 r; - angle_t closestangle, fa; - - INT32 iterations = 5; - if (mthing->type == 603) - iterations = 10; + angle_t angle = FixedAngle(fixedangle << FRACBITS); + angle_t fineangle = (angle >> ANGLETOFINESHIFT) & FINEMASK; if (ultimatemode) return; // No rings in Ultimate! @@ -13290,20 +13245,13 @@ static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, if (nightsreplace) ringthing = MT_NIGHTSSTAR; - closestangle = FixedAngle(mthing->angle << FRACBITS); - fa = (closestangle >> ANGLETOFINESHIFT); - z = P_GetMobjSpawnHeight(ringthing, x, y, z, mthing->options & MTF_OBJECTFLIP); - for (r = 1; r <= iterations; r++) + for (r = 0; r < numitems; r++) { - x += FixedMul(64*FRACUNIT, FINECOSINE(fa)); - y += FixedMul(64*FRACUNIT, FINESINE(fa)); - - if (mthing->options & MTF_OBJECTFLIP) - z -= 64*FRACUNIT; - else - z += 64*FRACUNIT; + x += FixedMul(horizontalspacing, FINECOSINE(fineangle)); + y += FixedMul(horizontalspacing, FINESINE(fineangle)); + z += (mthing->options & MTF_OBJECTFLIP) ? -verticalspacing : verticalspacing; mobj = P_SpawnMobj(x, y, z, ringthing); @@ -13313,7 +13261,7 @@ static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, mobj->flags2 |= MF2_OBJECTFLIP; } - mobj->angle = closestangle; + mobj->angle = angle; if (mthing->options & MTF_AMBUSH) mobj->flags2 |= MF2_AMBUSH; @@ -13414,12 +13362,16 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) { // Special placement patterns case 600: // 5 vertical rings (yellow spring) + P_SpawnItemRow(mthing, x, y, z, 5, 0, 64*FRACUNIT, 0); + return; case 601: // 5 vertical rings (red spring) - P_SpawnVerticalSpringRings(mthing, x, y, z); + P_SpawnItemRow(mthing, x, y, z, 5, 0, 128*FRACUNIT, 0); return; case 602: // 5 diagonal rings (yellow spring) + P_SpawnItemRow(mthing, x, y, z, 5, 64*FRACUNIT, 64*FRACUNIT, mthing->angle); + return; case 603: // 10 diagonal rings (red spring) - P_SpawnDiagonalSpringRings(mthing, x, y, z); + P_SpawnItemRow(mthing, x, y, z, 10, 64*FRACUNIT, 64*FRACUNIT, mthing->angle); return; case 604: // Circle of rings (8 items) case 605: // Circle of rings (16 items) From a657392d397cb71af3851be3ae08788fd8c338e2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 20:22:57 -0300 Subject: [PATCH 135/312] ViewpointSwitch improvements. --- src/d_clisrv.c | 14 +++++++++++--- src/d_netcmd.c | 8 ++++++++ src/g_game.c | 25 ++++++++++++++++++------- src/lua_hook.h | 2 +- src/lua_hooklib.c | 12 +++++++----- src/p_user.c | 14 ++++++++++++++ 6 files changed, 59 insertions(+), 16 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index c0dec7ff7..cad27f52c 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2486,6 +2486,17 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) (void)reason; #endif + // don't look through someone's view who isn't there + if (playernum == displayplayer) + { +#ifdef HAVE_BLUA + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer], true); +#endif + displayplayer = consoleplayer; + } + // Reset player data CL_ClearPlayer(playernum); @@ -2503,9 +2514,6 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) RemoveAdminPlayer(playernum); // don't stay admin after you're gone } - if (playernum == displayplayer) - displayplayer = consoleplayer; // don't look through someone's view who isn't there - #ifdef HAVE_BLUA LUA_InvalidatePlayer(&players[playernum]); #endif diff --git a/src/d_netcmd.c b/src/d_netcmd.c index be8b90c78..4e14ca25f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2900,7 +2900,15 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) //reset view if you are changed, or viewing someone who was changed. if (playernum == consoleplayer || displayplayer == playernum) + { +#ifdef HAVE_BLUA + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + if (displayplayer != consoleplayer) // You're already viewing yourself. No big deal. + LUAh_ViewpointSwitch(&players[playernum], &players[displayplayer], true); +#endif displayplayer = consoleplayer; + } if (G_GametypeHasTeams()) { diff --git a/src/g_game.c b/src/g_game.c index 34524c8f9..ead7e8c5c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1379,7 +1379,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) //Reset away view if a command is given. if ((cmd->forwardmove || cmd->sidemove || cmd->buttons) && displayplayer != consoleplayer) + { +#ifdef HAVE_BLUA + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUAh_ViewpointSwitch(player, &players[displayplayer], true); +#endif displayplayer = consoleplayer; + } } // like the g_buildticcmd 1 but using mouse2, gamcontrolbis, ... @@ -2021,6 +2028,11 @@ boolean G_Responder(event_t *ev) if (gamestate == GS_LEVEL && ev->type == ev_keydown && (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1])) { + // ViewpointSwitch Lua hook. +#ifdef HAVE_BLUA + UINT8 canSwitchView = 0; +#endif + if (splitscreen || !netgame) displayplayer = consoleplayer; else @@ -2036,13 +2048,12 @@ boolean G_Responder(event_t *ev) continue; #ifdef HAVE_BLUA - { - UINT8 canSwitchView = LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer]); - if (canSwitchView == 1) // Set viewpoint to this player - break; - else if (canSwitchView == 2) // Skip this player - continue; - } + // Call ViewpointSwitch hooks here. + canSwitchView = LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer], false); + if (canSwitchView == 1) // Set viewpoint to this player + break; + else if (canSwitchView == 2) // Skip this player + continue; #endif if (players[displayplayer].spectator) diff --git a/src/lua_hook.h b/src/lua_hook.h index 8d780490e..68efbce93 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -96,6 +96,6 @@ UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_Player void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting void LUAh_IntermissionThinker(void); // Hook for Y_Ticker boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... -UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer); // Hook for spy mode in G_Responder +UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index d213bd307..5383cbf0b 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1397,8 +1397,8 @@ boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, b return canSwitchTeam; } -// Hook for spy mode in G_Responder -UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer) +// Hook for spy mode +UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced) { hook_p hookp; UINT8 canSwitchView = 0; // 0 = default, 1 = force yes, 2 = force no. @@ -1417,12 +1417,14 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer) { LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, newdisplayplayer, META_PLAYER); + lua_pushboolean(gL, forced); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + if (lua_pcall(gL, 3, 1, 0)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); diff --git a/src/p_user.c b/src/p_user.c index c8a329c35..4dbea87e3 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10380,7 +10380,14 @@ boolean P_SpectatorJoinGame(player_t *player) //Reset away view if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) + { +#ifdef HAVE_BLUA + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUAh_ViewpointSwitch(player, &players[displayplayer], true); +#endif displayplayer = consoleplayer; + } if (changeto == 1) CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[player-players], '\x85', M_GetText("Red team"), '\x80'); @@ -10422,7 +10429,14 @@ boolean P_SpectatorJoinGame(player_t *player) //Reset away view if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) + { +#ifdef HAVE_BLUA + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUAh_ViewpointSwitch(player, &players[displayplayer], true); +#endif displayplayer = consoleplayer; + } if (gametype != GT_COOP) CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]); From 40b0c853b7af09216df00fd1bd575c33b90ba6ab Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Dec 2019 23:19:48 -0300 Subject: [PATCH 136/312] Add IDENTIFIER to gametype DeHackEd. --- src/dehacked.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index ee079aad1..12aa8f970 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1158,6 +1158,11 @@ static void readgametype(MYFILE *f, char *gtname) INT16 newgtrankingstype = -1; int newgtinttype = 0; char gtdescription[441]; + char gtconst[MAXLINELEN]; + + // Empty strings. + gtdescription[0] = '\0'; + gtconst[0] = '\0'; do { @@ -1231,6 +1236,12 @@ static void readgametype(MYFILE *f, char *gtname) // GTR_ newgtrules = (UINT32)get_number(word2); } + // Identifier + else if (fastcmp(word, "IDENTIFIER")) + { + // GT_ + strncpy(gtconst, word2, MAXLINELEN); + } // Point and time limits else if (fastcmp(word, "DEFAULTPOINTLIMIT")) newgtpointlimit = (INT32)i; @@ -1297,6 +1308,8 @@ static void readgametype(MYFILE *f, char *gtname) } } } while (!myfeof(f)); // finish when the line is empty + + // Free strings. Z_Free(s); if (word2lwr) Z_Free(word2lwr); @@ -1325,7 +1338,9 @@ static void readgametype(MYFILE *f, char *gtname) Gametype_Names[newgtidx] = Z_StrDup((const char *)gtname); // Write the constant name. - G_AddGametypeConstant(newgtidx, (const char *)gtname); + if (gtconst[0] == '\0') + strncpy(gtconst, gtname, MAXLINELEN); + G_AddGametypeConstant(newgtidx, (const char *)gtconst); // Update gametype_cons_t accordingly. G_UpdateGametypeSelections(); From d76c4eaba8680a9484ad6b8d2c339b073ea868d3 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Dec 2019 00:14:25 -0300 Subject: [PATCH 137/312] Fix Lua HUD library crashes. --- src/lua_hudlib.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 0c0e79261..12ae1b5fc 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1056,13 +1056,16 @@ int LUA_HudLib(lua_State *L) lua_rawseti(L, -2, 2); // HUD[2] = game rendering functions array lua_newtable(L); - lua_rawseti(L, -2, 3); // HUD[2] = scores rendering functions array + lua_rawseti(L, -2, 3); // HUD[3] = scores rendering functions array lua_newtable(L); - lua_rawseti(L, -2, 4); // HUD[3] = title rendering functions array + lua_rawseti(L, -2, 4); // HUD[4] = intermission rendering functions array lua_newtable(L); - lua_rawseti(L, -2, 5); // HUD[4] = title card rendering functions array + lua_rawseti(L, -2, 5); // HUD[5] = title rendering functions array + + lua_newtable(L); + lua_rawseti(L, -2, 6); // HUD[6] = title card rendering functions array lua_setfield(L, LUA_REGISTRYINDEX, "HUD"); luaL_newmetatable(L, META_HUDINFO); From ce3f526a5e2a427b16945dbf93c88388504e9670 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Tue, 24 Dec 2019 10:25:38 +0100 Subject: [PATCH 138/312] Ignore '=' and ';' when tokenizing, for textmap reading's sake. --- src/m_misc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/m_misc.c b/src/m_misc.c index d97383385..847f24905 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1784,6 +1784,7 @@ char *M_GetToken(const char *inputString) || stringToUse[startPos] == '\n' || stringToUse[startPos] == '\0' || stringToUse[startPos] == '"' // we're treating this as whitespace because SLADE likes adding it for no good reason + || stringToUse[startPos] == '=' || stringToUse[startPos] == ';' // UDMF TEXTMAP. || inComment != 0) && startPos < stringLength) { @@ -1852,6 +1853,7 @@ char *M_GetToken(const char *inputString) && stringToUse[endPos] != '{' && stringToUse[endPos] != '}' && stringToUse[endPos] != '"' // see above + && stringToUse[endPos] != '=' && stringToUse[endPos] != ';' // UDMF TEXTMAP. && inComment == 0) && endPos < stringLength) { From 36996c8c9124310fd4a86161a0d3c8238546698f Mon Sep 17 00:00:00 2001 From: Nev3r Date: Tue, 24 Dec 2019 10:27:23 +0100 Subject: [PATCH 139/312] Treat strings inside ""s as a single token. --- src/m_misc.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/m_misc.c b/src/m_misc.c index 847f24905..b12e7371d 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1783,7 +1783,6 @@ char *M_GetToken(const char *inputString) || stringToUse[startPos] == '\r' || stringToUse[startPos] == '\n' || stringToUse[startPos] == '\0' - || stringToUse[startPos] == '"' // we're treating this as whitespace because SLADE likes adding it for no good reason || stringToUse[startPos] == '=' || stringToUse[startPos] == ';' // UDMF TEXTMAP. || inComment != 0) && startPos < stringLength) @@ -1842,6 +1841,23 @@ char *M_GetToken(const char *inputString) texturesToken[1] = '\0'; return texturesToken; } + // Return entire string within quotes, except without the quotes. + else if (stringToUse[startPos] == '"') + { + endPos = ++startPos; + while (stringToUse[endPos] != '"' && endPos < stringLength) + endPos++; + + texturesTokenLength = endPos++ - startPos; + // Assign the memory. Don't forget an extra byte for the end of the string! + texturesToken = (char *)Z_Malloc((texturesTokenLength+1)*sizeof(char),PU_STATIC,NULL); + // Copy the string. + M_Memcpy(texturesToken, stringToUse+startPos, (size_t)texturesTokenLength); + // Make the final character NUL. + texturesToken[texturesTokenLength] = '\0'; + + return texturesToken; + } // Now find the end of the token. This includes several additional characters that are okay to capture as one character, but not trailing at the end of another token. endPos = startPos + 1; @@ -1852,7 +1868,6 @@ char *M_GetToken(const char *inputString) && stringToUse[endPos] != ',' && stringToUse[endPos] != '{' && stringToUse[endPos] != '}' - && stringToUse[endPos] != '"' // see above && stringToUse[endPos] != '=' && stringToUse[endPos] != ';' // UDMF TEXTMAP. && inComment == 0) && endPos < stringLength) From dd01fce1a84710a772a04521378dd6945fac991e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 24 Dec 2019 10:50:49 +0100 Subject: [PATCH 140/312] Separate P_SpawnHoopsAndRings into different functions: -Hoops are spawned in P_SpawnHoop -Item patterns are spawned in P_SpawnItemPattern -Ring-like items are spawned normally via P_SpawnMapThing -Bonus time items are spawned via P_SpawnBonusTimeItem, which is a wrapper for P_SpawnMapThing --- src/m_cheat.c | 32 ++++------- src/p_mobj.c | 152 +++++++++++++++++++++++--------------------------- src/p_mobj.h | 6 +- src/p_saveg.c | 2 +- src/p_setup.c | 43 ++++++-------- 5 files changed, 102 insertions(+), 133 deletions(-) diff --git a/src/m_cheat.c b/src/m_cheat.c index 0451a5fb3..3d1fe5b7e 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1186,7 +1186,7 @@ void OP_NightsObjectplace(player_t *player) mt->options = (mt->options & ~(UINT16)cv_opflags.value) | (UINT16)cv_ophoopflags.value; mt->angle = (INT16)(mt->angle+(INT16)((FixedInt(FixedDiv(temp*FRACUNIT, 360*(FRACUNIT/256))))<<8)); - P_SpawnHoopsAndRings(mt, false); + P_SpawnHoop(mt); } // This places a bumper! @@ -1249,7 +1249,7 @@ void OP_NightsObjectplace(player_t *player) return; mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_BLUESPHERE].doomednum, false); - P_SpawnHoopsAndRings(mt, false); + P_SpawnMapThing(mt); } // This places a ring! @@ -1260,7 +1260,7 @@ void OP_NightsObjectplace(player_t *player) return; mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_RING].doomednum, false); - P_SpawnHoopsAndRings(mt, false); + P_SpawnMapThing(mt); } // This places a custom object as defined in the console cv_mapthingnum. @@ -1292,15 +1292,10 @@ void OP_NightsObjectplace(player_t *player) mt = OP_CreateNewMapThing(player, (UINT16)cv_mapthingnum.value, false); mt->angle = angle; - if (mt->type == 300 // Ring - || mt->type == 308 || mt->type == 309 // Team Rings - || mt->type == 1706 // Sphere - || (mt->type >= 600 && mt->type <= 609) // Placement patterns - || mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops - || mt->type == 1800) // Mario Coin - { - P_SpawnHoopsAndRings(mt, false); - } + if (mt->type >= 600 && mt->type <= 609) // Placement patterns + P_SpawnItemPattern(mt, false); + else if (mt->type == 1705 || mt->type == 1713) // NiGHTS Hoops + P_SpawnHoop(mt); else P_SpawnMapThing(mt); } @@ -1437,15 +1432,10 @@ void OP_ObjectplaceMovement(player_t *player) return; mt = OP_CreateNewMapThing(player, (UINT16)spawnthing, ceiling); - if (mt->type == 300 // Ring - || mt->type == 308 || mt->type == 309 // Team Rings - || mt->type == 1706 // Nights Wing - || (mt->type >= 600 && mt->type <= 609) // Placement patterns - || mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops - || mt->type == 1800) // Mario Coin - { - P_SpawnHoopsAndRings(mt, false); - } + if (mt->type >= 600 && mt->type <= 609) // Placement patterns + P_SpawnItemPattern(mt, false); + else if (mt->type == 1705 || mt->type == 1713) // NiGHTS Hoops + P_SpawnHoop(mt); else P_SpawnMapThing(mt); diff --git a/src/p_mobj.c b/src/p_mobj.c index f25690ed8..606c65014 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11711,15 +11711,6 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) { switch (i) { - case MT_RING: - case MT_COIN: - case MT_REDTEAMRING: - case MT_BLUETEAMRING: - case MT_BLUESPHERE: - case MT_BOMBSPHERE: - case MT_NIGHTSSTAR: - case MT_NIGHTSCHIP: - return false; // These are handled in P_SpawnHoopsAndRings(). case MT_EMERALD1: case MT_EMERALD2: case MT_EMERALD3: @@ -11786,8 +11777,12 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) } if (metalrecording) // Metal Sonic can't use these things. - if (mobjinfo[i].flags & (MF_ENEMY|MF_BOSS) || i == MT_TOKEN || i == MT_STARPOST) + { + if ((mobjinfo[i].flags & (MF_ENEMY|MF_BOSS)) || i == MT_TOKEN || i == MT_STARPOST + || i == MT_RING || i == MT_BLUETEAMRING || i == MT_REDTEAMRING || i == MT_COIN + || i == MT_BLUESPHERE || i == MT_BOMBSPHERE || i == MT_NIGHTSCHIP || i == MT_NIGHTSSTAR) return false; + } if (!G_PlatformGametype()) { @@ -11825,7 +11820,9 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) if (ultimatemode) { - if (i == MT_PITY_BOX || i == MT_ELEMENTAL_BOX || i == MT_ATTRACT_BOX + if (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING + || i == MT_COIN || i == MT_NIGHTSSTAR || i == MT_NIGHTSCHIP + || i == MT_PITY_BOX || i == MT_ELEMENTAL_BOX || i == MT_ATTRACT_BOX || i == MT_FORCE_BOX || i == MT_ARMAGEDDON_BOX || i == MT_WHIRLWIND_BOX || i == MT_FLAMEAURA_BOX || i == MT_BUBBLEWRAP_BOX || i == MT_THUNDERCOIN_BOX || i == MT_RING_BOX || i == MT_STARPOST) @@ -11838,6 +11835,8 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) return true; } +#define nightsreplace ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) + static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) { // Altering monitor spawns via cvars @@ -11881,8 +11880,23 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) } } - if (gametype != GT_CTF && (i == MT_RING_BLUEBOX || i == MT_RING_REDBOX)) - return MT_RING_BOX; + if (nightsreplace) + { + if (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING || i == MT_COIN) + return MT_NIGHTSSTAR; + + if (i == MT_BLUESPHERE) + return MT_NIGHTSCHIP; + } + + if (gametype != GT_CTF) + { + if (i == MT_BLUETEAMRING || i == MT_REDTEAMRING) + return MT_RING; + + if (i == MT_RING_BLUEBOX || i == MT_RING_REDBOX) + return MT_RING_BOX; + } if (modeattacking && i == MT_1UP_BOX) // 1UPs -->> Score TVs { @@ -12920,6 +12934,10 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (G_IsSpecialStage(gamemap)) P_SetMobjState(mobj, (mobj->type == MT_PUSH) ? S_GRAVWELLGREEN : S_GRAVWELLRED); break; + case MT_NIGHTSSTAR: + if (maptol & TOL_XMAS) + P_SetMobjState(mobj, mobj->info->seestate); + break; default: break; } @@ -12991,21 +13009,21 @@ static void P_SetObjectSpecial(mobj_t *mobj) // The fields of the mapthing should // already be in host byte order. // -void P_SpawnMapThing(mapthing_t *mthing) +mobj_t *P_SpawnMapThing(mapthing_t *mthing) { mobjtype_t i; - mobj_t *mobj; + mobj_t *mobj = NULL; fixed_t x, y, z; boolean doangle = true; if (!mthing->type) - return; // Ignore type-0 things as NOPs + return mobj; // Ignore type-0 things as NOPs if (mthing->type == 3328) // 3D Mode start Thing - return; + return mobj; if (!objectplacing && P_SpawnNonMobjMapThing(mthing)) - return; + return mobj; i = P_GetMobjtype(mthing->type); if (i == MT_UNKNOWN) @@ -13015,11 +13033,11 @@ void P_SpawnMapThing(mapthing_t *mthing) if (!objectplacing) { if (!P_AllowMobjSpawn(mthing, i)) - return; + return mobj; i = P_GetMobjtypeSubstitute(mthing, i); if (i == MT_NULL) // Don't spawn mobj - return; + return mobj; } // spawn it @@ -13031,7 +13049,7 @@ void P_SpawnMapThing(mapthing_t *mthing) mobj->spawnpoint = mthing; if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle)) - return; + return mobj; if (doangle) mobj->angle = FixedAngle(mthing->angle<options & MTF_AMBUSH) && (mthing->options & MTF_OBJECTSPECIAL) @@ -13075,9 +13093,11 @@ void P_SpawnMapThing(mapthing_t *mthing) // Final set of not being able to draw nightsitems. if (mobj->flags & MF_NIGHTSITEM) mobj->flags2 |= MF2_DONTDRAW; + + return mobj; } -static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, INT32 hoopsize, fixed_t sizefactor) +static void P_SpawnHoopInternal(mapthing_t *mthing, INT32 hoopsize, fixed_t sizefactor) { mobj_t *mobj = NULL; mobj_t *nextmobj = NULL; @@ -13087,8 +13107,9 @@ static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, INT INT32 i; angle_t fa; TVector v, *res; - - z = P_GetMobjSpawnHeight(MT_HOOP, x, y, z, false); + fixed_t x = mthing->x << FRACBITS; + fixed_t y = mthing->y << FRACBITS; + fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, false); hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); hoopcenter->spawnpoint = mthing; @@ -13182,56 +13203,27 @@ static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, INT } while (hoopsize >= 8); } -#define nightsreplace ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) - -static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bonustime) +void P_SpawnHoop(mapthing_t *mthing) { - mobjtype_t ringthing = MT_RING; - mobj_t *mobj = NULL; - fixed_t z; + if (metalrecording) + return; - // Which ringthing to use - if (mthing->type == mobjinfo[MT_BLUESPHERE].doomednum) - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - else if (mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum) - ringthing = MT_BOMBSPHERE; - else - { - if (ultimatemode) - return; // No rings in Ultimate! - - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - else if (mthing->type == mobjinfo[MT_COIN].doomednum) - ringthing = MT_COIN; - else if (mthing->type == mobjinfo[MT_REDTEAMRING].doomednum) // No team rings in non-CTF - ringthing = (gametype == GT_CTF) ? MT_REDTEAMRING : MT_RING; - else if (mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum) // Ditto - ringthing = (gametype == GT_CTF) ? MT_BLUETEAMRING : MT_RING; - } - - z = P_GetMapThingSpawnHeight(ringthing, mthing, x, y); - mobj = P_SpawnMobj(x, y, z, ringthing); - mobj->spawnpoint = mthing; - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = FixedAngle(mthing->angle << FRACBITS); - mthing->mobj = mobj; - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) - P_SetMobjState(mobj, mobj->info->raisestate); - else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); + if (mthing->type == 1705) // Generic hoop + P_SpawnHoopInternal(mthing, 24, 4*FRACUNIT); + else // Customizable hoop + // For each flag add 16 fracunits to the size + // Default (0 flags) is 32 fracunits + P_SpawnHoopInternal(mthing, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); } -static void P_SpawnItemRow(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle) +void P_SpawnBonusTimeItem(mapthing_t *mthing) +{ + mobj_t *mobj = P_SpawnMapThing(mthing); + if (mobj && (mobj->type == MT_BLUESPHERE || mobj->type == MT_NIGHTSCHIP)) + P_SetMobjState(mobj, mobj->info->raisestate); +} + +static void P_SpawnItemRow(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle) { mobjtype_t ringthing = MT_RING; mobj_t *mobj = NULL; @@ -13270,7 +13262,7 @@ static void P_SpawnItemRow(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, } } -static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, INT32 numitems, fixed_t size, boolean bonustime) +static void P_SpawnItemCircle(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, INT32 numitems, fixed_t size, boolean bonustime) { mobjtype_t ringthing = MT_RING; mobj_t *mobj = NULL; @@ -13352,12 +13344,15 @@ static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t } } -void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) +void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) { fixed_t x = mthing->x << FRACBITS; fixed_t y = mthing->y << FRACBITS; fixed_t z = mthing->z << FRACBITS; + if (metalrecording) + return; + switch (mthing->type) { // Special placement patterns @@ -13385,17 +13380,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) P_SpawnItemCircle(mthing, x, y, z, numitems, size, bonustime); return; } - // Hoops - case 1705: // Generic NiGHTS hoop - P_SpawnHoop(mthing, x, y, z, 24, 4*FRACUNIT); + default: return; - case 1713: // Customizable NiGHTS hoop - // For each flag add 16 fracunits to the size - // Default (0 flags) is 32 fracunits - P_SpawnHoop(mthing, x, y, z, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); - return; - default: // All manners of rings and coins - P_SpawnRingItem(mthing, x, y, bonustime); } } diff --git a/src/p_mobj.h b/src/p_mobj.h index 40d850f16..9b015d23c 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -456,8 +456,10 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing); void P_MovePlayerToStarpost(INT32 playernum); void P_AfterPlayerSpawn(INT32 playernum); -void P_SpawnMapThing(mapthing_t *mthing); -void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime); +mobj_t *P_SpawnMapThing(mapthing_t *mthing); +void P_SpawnHoop(mapthing_t *mthing); +void P_SpawnBonusTimeItem(mapthing_t *mthing); +void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime); void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle); void P_SpawnPrecipitation(void); void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, statenum_t nstate, angle_t rotangle, boolean spawncenter); diff --git a/src/p_saveg.c b/src/p_saveg.c index c876713e4..86224d936 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2545,7 +2545,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case { - P_SpawnHoopsAndRings(&mapthings[spawnpointnum], false); + P_SpawnHoop(&mapthings[spawnpointnum]); return NULL; } diff --git a/src/p_setup.c b/src/p_setup.c index bc736588e..46fe118c4 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -765,7 +765,7 @@ static void P_LoadRawNodes(UINT8 *data) // // P_ReloadRings -// Used by NiGHTS, clears all ring/wing/etc items and respawns them +// Used by NiGHTS, clears all ring/sphere/hoop/etc items and respawns them // void P_ReloadRings(void) { @@ -812,18 +812,21 @@ void P_ReloadRings(void) { // Notice an omission? We handle hoops differently. if (mt->type == mobjinfo[MT_RING].doomednum || mt->type == mobjinfo[MT_COIN].doomednum - || mt->type == mobjinfo[MT_REDTEAMRING].doomednum || mt->type == mobjinfo[MT_BLUETEAMRING].doomednum - || mt->type == mobjinfo[MT_BLUESPHERE].doomednum || mt->type == mobjinfo[MT_BOMBSPHERE].doomednum - || (mt->type >= 600 && mt->type <= 609)) // circles and diagonals + || mt->type == mobjinfo[MT_REDTEAMRING].doomednum || mt->type == mobjinfo[MT_BLUETEAMRING].doomednum + || mt->type == mobjinfo[MT_BLUESPHERE].doomednum || mt->type == mobjinfo[MT_BOMBSPHERE].doomednum) { mt->mobj = NULL; - - P_SpawnHoopsAndRings(mt, true); + P_SpawnBonusTimeItem(mt); + } + else if (mt->type >= 600 && mt->type <= 609) // Item patterns + { + mt->mobj = NULL; + P_SpawnItemPattern(mt, true); } } for (i = 0; i < numHoops; i++) { - P_SpawnHoopsAndRings(hoopsToRespawn[i], false); + P_SpawnHoop(hoopsToRespawn[i]); } } @@ -1017,30 +1020,18 @@ static void P_LoadThings(boolean loademblems) continue; mt->mobj = NULL; - P_SpawnMapThing(mt); + + if (mt->type >= 600 && mt->type <= 609) // item patterns + P_SpawnItemPattern(mt, false); + else if (mt->type == 1705 || mt->type == 1713) // hoops + P_SpawnHoop(mt); + else // Everything else + P_SpawnMapThing(mt); } // random emeralds for hunt if (numhuntemeralds) P_SpawnEmeraldHunt(); - - if (metalrecording) // Metal Sonic gets no rings to distract him. - return; - - // Run through the list of mapthings again to spawn hoops and rings - mt = mapthings; - for (i = 0; i < nummapthings; i++, mt++) - { - if (mt->type == mobjinfo[MT_RING].doomednum || mt->type == mobjinfo[MT_COIN].doomednum - || mt->type == mobjinfo[MT_REDTEAMRING].doomednum || mt->type == mobjinfo[MT_BLUETEAMRING].doomednum - || mt->type == mobjinfo[MT_BLUESPHERE].doomednum || mt->type == mobjinfo[MT_BOMBSPHERE].doomednum - || (mt->type >= 600 && mt->type <= 609) // circles and diagonals - || mt->type == 1705 || mt->type == 1713) // hoops - { - mt->mobj = NULL; - P_SpawnHoopsAndRings(mt, false); - } - } } // Experimental groovy write function! From 75e18610bc8f71e96bdb8314bcea8425b0a4a9b0 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Tue, 24 Dec 2019 11:58:25 +0100 Subject: [PATCH 141/312] Refactor existing configuration into ZDoom-styled format. --- extras/conf/Includes/Game_SRB222.cfg | 77 + extras/conf/Includes/SRB222_common.cfg | 309 ++ extras/conf/Includes/SRB222_linedefs.cfg | 2486 ++++++++++++++++ extras/conf/Includes/SRB222_misc.cfg | 726 +++++ extras/conf/Includes/SRB222_sectors.cfg | 109 + extras/conf/Includes/SRB222_things.cfg | 3398 ++++++++++++++++++++++ extras/conf/SRB2_22Doom.cfg | 38 + extras/conf/SRB2_22UDMF.cfg | 47 + 8 files changed, 7190 insertions(+) create mode 100644 extras/conf/Includes/Game_SRB222.cfg create mode 100644 extras/conf/Includes/SRB222_common.cfg create mode 100644 extras/conf/Includes/SRB222_linedefs.cfg create mode 100644 extras/conf/Includes/SRB222_misc.cfg create mode 100644 extras/conf/Includes/SRB222_sectors.cfg create mode 100644 extras/conf/Includes/SRB222_things.cfg create mode 100644 extras/conf/SRB2_22Doom.cfg create mode 100644 extras/conf/SRB2_22UDMF.cfg diff --git a/extras/conf/Includes/Game_SRB222.cfg b/extras/conf/Includes/Game_SRB222.cfg new file mode 100644 index 000000000..3c4b11e9f --- /dev/null +++ b/extras/conf/Includes/Game_SRB222.cfg @@ -0,0 +1,77 @@ +// Default lump name for new map +defaultlumpname = "MAP01"; +//GZDB specific. Don't try to load lumps that don't exist. +basegame = 0; + +//Sky textures for vanilla maps +defaultskytextures +{ + SKY1 = "MAP01,MAP02,MAP03,MAP33,MAP50,MAP60,MAPF0,MAPM0"; + SKY2 = "MAPM7,MAPMB"; + SKY4 = "MAP04,MAP06,MAP61,MAPF6,MAPM1"; + SKY6 = "MAP05,MAP51,MAPMA"; + SKY7 = "MAPM2,MAPM5"; + SKY8 = "MAP07,MAP08,MAP09,MAP52,MAP62,MAPF1"; + SKY10 = "MAP10,MAP12,MAP53,MAP63,MAPM3"; + SKY11 = "MAP11,MAPF7"; + SKY13 = "MAP13,MAP64"; + SKY14 = "MAP14"; + SKY15 = "MAP15,MAP54"; + SKY17 = "MAP70"; + SKY20 = "MAP32,MAP55,MAP65,MAPF2,MAPF5"; + SKY21 = "MAPM4"; + SKY22 = "MAP22,MAP23,MAP25,MAP26,MAP27,MAP56,MAP66,MAPF4,MAPM6"; + SKY30 = "MAP30"; + SKY31 = "MAP31"; + SKY35 = "MAP42"; + SKY40 = "MAP41,MAP71,MAPM9"; + SKY55 = "MAPF3,MAPM8"; + SKY68 = "MAPF8"; + SKY99 = "MAP57,MAPZ0"; + SKY159 = "MAP16"; + SKY172 = "MAP40"; + SKY300 = "MAP72"; + SKY301 = "MAP73"; +} + +// Skill levels +skills +{ + 1 = "Normal"; +} + +// Skins +skins +{ + Sonic; + Tails; + Knuckles; + Amy; + Fang; + Metalsonic; +} + +// Gametypes +gametypes +{ + -1 = "Single Player"; + 0 = "Co-op"; + 1 = "Competition"; + 2 = "Race"; + 3 = "Match"; + 4 = "Team Match"; + 5 = "Tag"; + 6 = "Hide and Seek"; + 7 = "CTF"; +} + +// Texture loading options +defaultwalltexture = "GFZROCK"; +defaultfloortexture = "GFZFLR01"; +defaultceilingtexture = "F_SKY1"; + +// Default texture sets +// (these are not required, but useful for new users) +texturesets +{ +} \ No newline at end of file diff --git a/extras/conf/Includes/SRB222_common.cfg b/extras/conf/Includes/SRB222_common.cfg new file mode 100644 index 000000000..a832e6cef --- /dev/null +++ b/extras/conf/Includes/SRB222_common.cfg @@ -0,0 +1,309 @@ +common +{ + // Some common settings + + + + // Default testing parameters + testparameters = "-file \"%AP\" \"%F\" -warp %L"; + testshortpaths = true; + + // Action special help (mxd) + actionspecialhelp = "https://wiki.srb2.org/wiki/Linedef_type_%K"; + + // Default nodebuilder configurations + defaultsavecompiler = "zennode_normal"; + defaulttestcompiler = "zennode_fast"; + + // Generalized actions + generalizedlinedefs = false; + generalizedsectors = true; + + mixtexturesflats = true; + defaulttexturescale = 1.0f; + defaultflatscale = 1.0f; + scaledtextureoffsets = true; + + // Thing number for start position in 3D Mode + start3dmode = 3328; + + // Texture sources + textures + { + include("SRB222_misc.cfg", "textures"); + } + + // Patch sources + patches + { + include("SRB222_misc.cfg", "patches"); + } + + // Sprite sources + sprites + { + include("SRB222_misc.cfg", "sprites"); + } + + // Flat sources + flats + { + include("SRB222_misc.cfg", "flats"); + } +} + +mapformat_doom +{ + // The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder + formatinterface = "SRB2MapSetIO"; + + /* + GAME DETECT PATTERN + Used to guess the game for which a WAD file is made. + + 1 = One of these lumps must exist + 2 = None of these lumps must exist + 3 = All of these lumps must exist + */ + + gamedetect + { + EXTENDED = 2; + + + BEHAVIOR = 2; + + E#M# = 2; + + MAP?? = 1; + } + + /* + MAP LUMP NAMES + Map lumps are loaded with the map as long as they are right after each other. When the editor + meets a lump which is not defined in this list it will ignore the map if not satisfied. + The order of items defines the order in which lumps will be written to WAD file on save. + To indicate the map header lump, use ~MAP + + Legenda: + required = Lump is required to exist. + blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use) + nodebuild = The nodebuilder generates this lump. + allowempty = The nodebuilder is allowed to leave this lump empty. + script = This lump is a text-based script. Specify the filename of the script configuration to use. + */ + + maplumpnames + { + include("SRB222_misc.cfg", "doommaplumpnames"); + } + + // When this is set to true, sectors with the same tag will light up when a line is highlighted + linetagindicatesectors = true; + + // Special linedefs + include("SRB222_misc.cfg", "speciallinedefs"); + + // Default flags for first new thing (As far as 2.2 goes, they're empty just like in 2.1) + defaultthingflags + { + } + + // DEFAULT SECTOR BRIGHTNESS LEVELS + sectorbrightness + { + include("SRB222_misc.cfg", "sectorbrightness"); + } + + // SECTOR TYPES----------------------------------------------------------------- + sectortypes + { + include("SRB222_sectors.cfg", "sectortypes"); + } + + // GENERALISED SECTOR TYPES----------------------------------------------------------------- + gen_sectortypes + { + include("SRB222_sectors.cfg", "gen_sectortypes"); + } + + // LINEDEF FLAGS + linedefflags + { + include("SRB222_misc.cfg", "linedefflags"); + } + + // Linedef flags UDMF translation table + // This is needed for copy/paste and prefabs to work properly + // When the UDMF field name is prefixed with ! it is inverted + linedefflagstranslation + { + include("SRB222_misc.cfg", "linedefflagstranslation"); + } + + // LINEDEF ACTIVATIONS + linedefactivations + { + } + + // LINEDEF TYPES + linedeftypes + { + include("SRB222_linedefs.cfg", "doom"); + } + + // THING FLAGS + thingflags + { + include("SRB222_misc.cfg", "thingflags"); + } + + // Thing flags UDMF translation table + // This is needed for copy/paste and prefabs to work properly + // When the UDMF field name is prefixed with ! it is inverted + thingflagstranslation + { + include("SRB222_misc.cfg", "thingflagstranslation"); + } + + // THING FLAGS ERROR MASK + // Mask for the thing flags which indicates the options + // that make the same thing appear in the same modes + thingflagsmask1 = 7; // 1 + 2 + 4 + thingflagsmask2 = 0; +} + +mapformat_udmf +{ + // The format interface handles the map data format + formatinterface = "UniversalMapSetIO"; + + // Enables support for long (> 8 chars) texture names + // WARNING: this should only be enabled for UDMF game configurations! + // WARNING: enabling this will make maps incompatible with Doom Builder 2 and can lead to problems in Slade 3! + longtexturenames = false; + + // Default nodebuilder configurations + defaultsavecompiler = "zdbsp_udmf_normal"; + defaulttestcompiler = "zdbsp_udmf_fast"; + + engine = "srb2"; // override that so that DB2 uses the correct namespace + + maplumpnames + { + include("UDMF_misc.cfg", "udmfmaplumpnames_begin"); + include("SRB222_misc.cfg", "udmfmaplumpnames"); + include("UDMF_misc.cfg", "udmfmaplumpnames_end"); + } + + universalfields + { +// include("SRB222_misc.cfg", "universalfields"); + } + + // When this is set to true, sectors with the same tag will light up when a line is highlighted + linetagindicatesectors = false; + + // Special linedefs + include("SRB222_misc.cfg", "speciallinedefs_udmf"); + + // Default flags for first new thing (As far as 2.2 goes, they're empty just like in 2.1) + defaultthingflags + { + } + + // Generalized actions + generalizedlinedefs = false; + + // SECTOR FLAGS + sectorflags + { +// include("SRB222_misc.cfg", "sectorflags"); + } + + // DEFAULT SECTOR BRIGHTNESS LEVELS + sectorbrightness + { + include("SRB222_misc.cfg", "sectorbrightness"); + } + + // SECTOR TYPES + sectortypes + { + include("SRB222_sectors.cfg", "sectortypes"); + } + + // SECTOR RENSERSTYLES +/* sectorrenderstyles + { + include("SRB222_misc.cfg", "sectorrenderstyles"); + }*/ + + // LINEDEF FLAGS + linedefflags + { + include("SRB222_misc.cfg", "linedefflags_udmf"); + } + + // LINEDEF ACTIVATIONS + linedefactivations + { + include("SRB222_misc.cfg", "linedefactivations_udmf"); + } + + linedefflagstranslation + { + } + + + // LINEDEF RENSERSTYLES + linedefrenderstyles + { + include("SRB222_misc.cfg", "linedefrenderstyles"); + } + + //SIDEDEF FLAGS +/* sidedefflags + { + include("UDMF_misc.cfg", "sidedefflags"); + }*/ + + // THING FLAGS + thingflags + { + include("SRB222_misc.cfg", "thingflags_udmf"); + } + + // Thing flags UDMF translation table + // This is needed for copy/paste and prefabs to work properly + // When the UDMF field name is prefixed with ! it is inverted + thingflagstranslation + { + include("SRB222_misc.cfg", "thingflagstranslation"); + } + + // THING RENSERSTYLES +/* thingrenderstyles + { + include("SRB222_misc.cfg", "thingrenderstyles"); + }*/ + + // How to compare thing flags (for the stuck things error checker) +/* thingflagscompare + { + include("UDMF_misc.cfg", "thingflagscompare"); + }*/ + + //mxd. Thing flags UDMF translation table + // This is needed for copy/paste and prefabs to work properly + // When the UDMF field name is prefixed with ! it is inverted + thingflagstranslation + { + } + + // LINEDEF TYPES + linedeftypes + { + include("SRB222_linedefs.cfg", "udmf"); + } +} \ No newline at end of file diff --git a/extras/conf/Includes/SRB222_linedefs.cfg b/extras/conf/Includes/SRB222_linedefs.cfg new file mode 100644 index 000000000..8bc761dfe --- /dev/null +++ b/extras/conf/Includes/SRB222_linedefs.cfg @@ -0,0 +1,2486 @@ +doom +{ + misc + { + title = "Miscellaneous"; + + 0 + { + title = "None"; + prefix = "(0)"; + } + + 1 + { + title = "Per-Sector Gravity"; + prefix = "(1)"; + flags64text = "[6] Flip in reverse gravity"; + } + + 5 + { + title = "Camera Scanner"; + prefix = "(5)"; + } + + 7 + { + title = "Sector Flat Alignment"; + prefix = "(7)"; + flags2048text = "[11] Don't align floor"; + flags4096text = "[12] Don't align ceiling"; + flags8192text = "[13] Use texture offsets"; + } + + 10 + { + title = "Culling Plane"; + prefix = "(10)"; + flags64text = "[6] Cull only while in sector"; + } + + 13 + { + title = "Heat Wave Effect"; + prefix = "(13)"; + } + + 40 + { + title = "Visual Portal Between Tagged Linedefs"; + prefix = "(40)"; + } + + 41 + { + title = "Horizon Effect"; + prefix = "(41)"; + } + + 50 + { + title = "Instantly Lower Floor on Level Load"; + prefix = "(50)"; + } + + 51 + { + title = "Instantly Raise Ceiling on Level Load"; + prefix = "(51)"; + } + + 63 + { + title = "Fake Floor/Ceiling Planes"; + prefix = "(63)"; + } + + 540 + { + title = "Floor Friction"; + prefix = "(540)"; + } + } + + parameters + { + title = "Parameters"; + + 2 + { + title = "Custom Exit"; + prefix = "(2)"; + flags2text = "[1] Check emeralds"; + flags64text = "[6] Skip score tally"; + } + + 3 + { + title = "Zoom Tube Parameters"; + prefix = "(3)"; + flags512text = "[9] Ignore player direction"; + } + + 4 + { + title = "Speed Pad Parameters"; + prefix = "(4)"; + flags512text = "[9] No teleport to center"; + flags1024text = "[10] Force spinning frames"; + } + + 8 + { + title = "Special Sector Properties"; + prefix = "(8)"; + flags32text = "[5] Invert precipitation"; + flags64text = "[6] Touch only ceiling"; + flags128text = "[7] Allow opposite gravity"; + flags256text = "[8] Touch sector edge"; + flags512text = "[9] Touch floor or ceiling"; + } + + 9 + { + title = "Chain Parameters"; + prefix = "(9)"; + flags32text = "[5] Swing instead of spin"; + flags64text = "[6] Player-turnable chain"; + flags128text = "[7] Make chain from maces"; + flags256text = "[8] Spawn mace at origin"; + flags512text = "[9] Don't clip inside ground"; + flags1024text = "[10] No distance check"; + } + + 11 + { + title = "Rope Hang Parameters"; + prefix = "(11)"; + flags32text = "[5] Don't loop"; + flags64text = "[6] Static"; + } + + 12 + { + title = "Rock Spawner Parameters"; + prefix = "(12)"; + flags64text = "[6] Randomize speed"; + } + + 14 + { + title = "Bustable Block Parameters"; + prefix = "(14)"; + flags32text = "[5] Particles launch from center"; + } + + 15 + { + title = "Fan Particle Spawner Parameters"; + prefix = "(15)"; + } + + 16 + { + title = "Minecart Parameters"; + prefix = "(16)"; + } + + 64 + { + title = "Continuously Appearing/Disappearing FOF"; + prefix = "(64)"; + flags2text = "[1] Use control sector tag"; + flags64text = "[6] No sound effect"; + } + + 65 + { + title = "Bridge Thinker "; + prefix = "(65)"; + } + } + + polyobject + { + title = "PolyObject"; + + 20 + { + title = "First Line"; + prefix = "(20)"; + } + + 21 + { + title = "Explicitly Include Line "; + prefix = "(21)"; + } + + 22 + { + title = "Parameters"; + prefix = "(22)"; + flags64text = "[6] Trigger linedef executor"; + flags128text = "[7] Intangible"; + flags256text = "[8] Stopped by pushables"; + flags512text = "[9] Render flats"; + } + + 30 + { + title = "Waving Flag"; + prefix = "(30)"; + } + + 31 + { + title = "Displacement by Front Sector"; + prefix = "(31)"; + } + + 32 + { + title = "Angular Displacement by Front Sector"; + prefix = "(32)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + } + + planemove + { + title = "Plane Movement"; + + 52 + { + title = "Continuously Falling Sector"; + prefix = "(52)"; + flags64text = "[6] Continuously rising"; + } + + 53 + { + title = "Continuous Floor/Ceiling Mover"; + prefix = "(53)"; + } + + 54 + { + title = "Continuous Floor Mover"; + prefix = "(54)"; + } + + 55 + { + title = "Continuous Ceiling Mover"; + prefix = "(55)"; + } + + 56 + { + title = "Continuous Two-Speed Floor/Ceiling Mover"; + prefix = "(56)"; + } + + 57 + { + title = "Continuous Two-Speed Floor Mover"; + prefix = "(57)"; + } + + 58 + { + title = "Continuous Two-Speed Ceiling Mover"; + prefix = "(58)"; + } + + 59 + { + title = "Activate Moving Platform"; + prefix = "(59)"; + flags64text = "[6] Move upwards at start"; + } + + 60 + { + title = "Activate Moving Platform (Adjustable Speed)"; + prefix = "(60)"; + flags64text = "[6] Move upwards at start"; + } + + 61 + { + title = "Crusher (Ceiling to Floor)"; + prefix = "(61)"; + flags512text = "[9] Double, constant speed"; + } + + 62 + { + title = "Crusher (Floor to Ceiling)"; + prefix = "(62)"; + flags512text = "[9] Double, constant speed"; + } + + 66 + { + title = "Move Floor by Displacement"; + prefix = "(66)"; + flags64text = "[6] Inverse movement"; + } + + 67 + { + title = "Move Ceiling by Displacement"; + prefix = "(67)"; + flags64text = "[6] Inverse movement"; + } + + 68 + { + title = "Move Floor and Ceiling by Displacement"; + prefix = "(68)"; + flags64text = "[6] Inverse movement"; + } + } + + fofsolid + { + title = "FOF (solid)"; + + 100 + { + title = "Solid, Opaque"; + prefix = "(100)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 101 + { + title = "Solid, Opaque, No Shadow"; + prefix = "(101)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1DF"; + } + + 102 + { + title = "Solid, Translucent"; + prefix = "(102)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Render insides"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "195F"; + flags643dfloorflagsadd = "7C80"; + } + + 103 + { + title = "Solid, Sides Only"; + prefix = "(103)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1CF"; + } + + 104 + { + title = "Solid, No Sides"; + prefix = "(104)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1D7"; + flags643dfloorflagsremove = "40"; + } + + 105 + { + title = "Solid, Invisible"; + prefix = "(105)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "47"; + } + + 140 + { + title = "Intangible from Bottom, Opaque"; + prefix = "(140)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "200841F"; + flags643dfloorflagsadd = "40"; + } + + 141 + { + title = "Intangible from Bottom, Translucent"; + prefix = "(141)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "200191F"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 142 + { + title = "Intangible from Bottom, Translucent, No Sides"; + prefix = "(142)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "2001917"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 143 + { + title = "Intangible from Top, Opaque"; + prefix = "(143)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "400841F"; + flags643dfloorflagsadd = "40"; + } + + 144 + { + title = "Intangible from Top, Translucent"; + prefix = "(144)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "400191F"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 145 + { + title = "Intangible from Top, Translucent, No Sides"; + prefix = "(145)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "4001917"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 146 + { + title = "Only Tangible from Sides"; + prefix = "(146)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "600800F"; + } + } + + fofintangible + { + title = "FOF (intangible)"; + + 120 + { + title = "Water, Opaque"; + prefix = "(120)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "8F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 121 + { + title = "Water, Translucent"; + prefix = "(121)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "9F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 122 + { + title = "Water, Opaque, No Sides"; + prefix = "(122)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 123 + { + title = "Water, Translucent, No Sides"; + prefix = "(123)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "1F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 124 + { + title = "Goo Water, Translucent"; + prefix = "(124)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "209F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 125 + { + title = "Goo Water, Translucent, No Sides"; + prefix = "(125)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "201F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 220 + { + title = "Intangible, Opaque"; + prefix = "(220)"; + flags8text = "[3] Slope skew sides"; + 3dfloor = true; + 3dfloorflags = "8F19"; + } + + 221 + { + title = "Intangible, Translucent"; + prefix = "(221)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Cast shadow"; + 3dfloor = true; + 3dfloorflags = "1B59"; + flags643dfloorflagsremove = "40"; + } + + 222 + { + title = "Intangible, Sides Only"; + prefix = "(222)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Cast shadow"; + 3dfloor = true; + 3dfloorflags = "8249"; + flags643dfloorflagsremove = "240"; + } + + 223 + { + title = "Intangible, Invisible"; + prefix = "(223)"; + 3dfloor = true; + 3dfloorflags = "41"; + } + } + + fofmoving + { + title = "FOF (moving)"; + + 150 + { + title = "Air Bobbing"; + prefix = "(150)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 151 + { + title = "Air Bobbing (Adjustable)"; + prefix = "(151)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 152 + { + title = "Reverse Air Bobbing (Adjustable)"; + prefix = "(152)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 160 + { + title = "Floating, Bobbing"; + prefix = "(160)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "4019F"; + } + + 190 + { + title = "Rising Platform, Solid, Opaque"; + prefix = "(190)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 191 + { + title = "Rising Platform, Solid, Opaque, No Shadow"; + prefix = "(191)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1DF"; + } + + 192 + { + title = "Rising Platform, Solid, Translucent"; + prefix = "(192)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "195F"; + } + + 193 + { + title = "Rising Platform, Solid, Invisible"; + prefix = "(193)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "47"; + } + + 194 + { + title = "Rising Platform, Intangible from Bottom, Opaque"; + prefix = "(194)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash, no shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "200841F"; + flags643dfloorflagsadd = "40"; + } + + 195 + { + title = "Rising Platform, Intangible from Bottom, Translucent"; + prefix = "(195)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash, no shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "2009D1F"; + flags643dfloorflagsadd = "40"; + } + } + + fofcrumbling + { + title = "FOF (crumbling)"; + + 170 + { + title = "Crumbling, Respawn"; + prefix = "(170)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "10019F"; + } + + 171 + { + title = "Crumbling, No Respawn"; + prefix = "(171)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "80019F"; + } + + 172 + { + title = "Crumbling, Respawn, Intangible from Bottom"; + prefix = "(172)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "210841F"; + flags643dfloorflagsadd = "40"; + } + + 173 + { + title = "Crumbling, No Respawn, Intangible from Bottom"; + prefix = "(173)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "218841F"; + flags643dfloorflagsadd = "40"; + } + + 174 + { + title = "Crumbling, Respawn, Int. from Bottom, Translucent"; + prefix = "(174)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "210959F"; + flags643dfloorflagsadd = "40"; + } + + 175 + { + title = "Crumbling, No Respawn, Int. from Bottom, Translucent"; + prefix = "(175)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "218959F"; + flags643dfloorflagsadd = "40"; + } + + 176 + { + title = "Crumbling, Respawn, Floating, Bobbing"; + prefix = "(176)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "14019F"; + } + + 177 + { + title = "Crumbling, No Respawn, Floating, Bobbing"; + prefix = "(177)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1C019F"; + } + + 178 + { + title = "Crumbling, Respawn, Floating"; + prefix = "(178)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "14019F"; + } + + 179 + { + title = "Crumbling, No Respawn, Floating"; + prefix = "(179)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1C019F"; + } + + 180 + { + title = "Crumbling, Respawn, Air Bobbing"; + prefix = "(180)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "10019F"; + } + } + + fofspecial + { + title = "FOF (special)"; + + 200 + { + title = "Light Block"; + prefix = "(200)"; + 3dfloor = true; + 3dfloorflags = "20201"; + } + + 201 + { + title = "Half Light Block"; + prefix = "(201)"; + 3dfloor = true; + 3dfloorflags = "201"; + } + + 202 + { + title = "Fog Block"; + prefix = "(202)"; + 3dfloor = true; + 3dfloorflags = "3EF19"; + } + + 250 + { + title = "Mario Block"; + prefix = "(250)"; + flags32text = "[5] Invisible block"; + flags64text = "[6] Brick block"; + 3dfloor = true; + 3dfloorflags = "40019F"; + } + + 251 + { + title = "Thwomp Block"; + prefix = "(251)"; + flags512text = "[9] Custom crushing sound"; + flags1024text = "[10] Custom speed"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 252 + { + title = "Shatter Block"; + prefix = "(252)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Shatter only from below"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "8800019"; + flags643dfloorflagsadd = "200006"; + } + + 253 + { + title = "Shatter Block, Translucent"; + prefix = "(253)"; + flags8text = "[3] Slope skew sides"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "8801019"; + } + + 254 + { + title = "Bustable Block"; + prefix = "(254)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Strong characters only"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "80001F"; + flags643dfloorflagsadd = "20000000"; + } + + 255 + { + title = "Spin-Bustable Block"; + prefix = "(255)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "1080001F"; + } + + 256 + { + title = "Spin-Bustable Block, Translucent"; + prefix = "(256)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "1080101F"; + } + + 257 + { + title = "Quicksand"; + prefix = "(257)"; + flags8text = "[3] Slope skew sides"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "1008219"; + flags10243dfloorflagsadd = "40000000"; + } + + 258 + { + title = "Laser"; + prefix = "(258)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Don't damage bosses"; + 3dfloor = true; + 3dfloorflags = "959"; + } + + 259 + { + title = "Custom FOF"; + prefix = "(259)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorcustom = true; + } + } + + linedeftrigger + { + title = "Linedef Executor Trigger"; + + 300 + { + title = "Continuous"; + prefix = "(300)"; + } + + 301 + { + title = "Each Time"; + prefix = "(301)"; + flags16384text = "[14] Also trigger on exit"; + } + + 302 + { + title = "Once"; + prefix = "(302)"; + } + + 303 + { + title = "Ring Count - Continuous"; + prefix = "(303)"; + flags2text = "[1] Rings greater or equal"; + flags64text = "[6] Rings less or equal"; + flags512text = "[9] Consider all players"; + } + + 304 + { + title = "Ring Count - Once"; + prefix = "(304)"; + flags2text = "[1] Rings greater or equal"; + flags64text = "[6] Rings less or equal"; + flags512text = "[9] Consider all players"; + } + + 305 + { + title = "Character Ability - Continuous"; + prefix = "(305)"; + } + + 306 + { + title = "Character Ability - Each Time"; + prefix = "(306)"; + flags16384text = "[14] Also trigger on exit"; + } + + 307 + { + title = "Character Ability - Once"; + prefix = "(307)"; + } + + 308 + { + title = "Race Only - Once"; + prefix = "(308)"; + } + + 309 + { + title = "CTF Red Team - Continuous"; + prefix = "(309)"; + } + + 310 + { + title = "CTF Red Team - Each Time"; + prefix = "(310)"; + flags16384text = "[14] Also trigger on exit"; + } + + 311 + { + title = "CTF Blue Team - Continuous"; + prefix = "(311)"; + } + + 312 + { + title = "CTF Blue Team - Each Time"; + prefix = "(312)"; + flags16384text = "[14] Also trigger on exit"; + } + + 313 + { + title = "No More Enemies - Once"; + prefix = "(313)"; + } + + 314 + { + title = "Number of Pushables - Continuous"; + prefix = "(314)"; + flags64text = "[6] Number greater or equal"; + flags512text = "[9] Number less"; + } + + 315 + { + title = "Number of Pushables - Once"; + prefix = "(315)"; + flags64text = "[6] Number greater or equal"; + flags512text = "[9] Number less"; + } + + 317 + { + title = "Condition Set Trigger - Continuous"; + prefix = "(317)"; + } + + 318 + { + title = "Condition Set Trigger - Once"; + prefix = "(318)"; + } + + 319 + { + title = "Unlockable - Continuous"; + prefix = "(319)"; + } + + 320 + { + title = "Unlockable - Once"; + prefix = "(320)"; + } + + 321 + { + title = "Trigger After X Calls - Continuous"; + prefix = "(321)"; + flags64text = "[6] Trigger more than once"; + + } + + 322 + { + title = "Trigger After X Calls - Each Time"; + prefix = "(322)"; + flags64text = "[6] Trigger more than once"; + } + + 323 + { + title = "NiGHTSerize - Each Time"; + prefix = "(323)"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run only if player is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Run if no more mares"; + flags32768text = "[15] Run if player is not NiGHTS"; + } + + 324 + { + title = "NiGHTSerize - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run only if player is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Run if no more mares"; + flags32768text = "[15] Run if player is not NiGHTS"; + prefix = "(324)"; + } + + 325 + { + title = "De-NiGHTSerize - Each Time"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run if anyone is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags32768text = "[15] Run if no one is NiGHTS"; + prefix = "(325)"; + } + + 326 + { + title = "De-NiGHTSerize - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run if anyone is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags32768text = "[15] Run if no one is NiGHTS"; + prefix = "(326)"; + } + + 327 + { + title = "NiGHTS Lap - Each Time"; + flags2text = "[1] Mare >= Front X Offset"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + prefix = "(327)"; + } + + 328 + { + title = "NiGHTS Lap - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + prefix = "(328)"; + } + + 329 + { + title = "Ideya Capture Touch - Each Time"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run regardless of spheres"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Only if not enough spheres"; + flags32768text = "[15] Run when entering Capture"; + prefix = "(329)"; + } + + 330 + { + title = "Ideya Capture Touch - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run regardless of spheres"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Only if not enough spheres"; + flags32768text = "[15] Run when entering Capture"; + prefix = "(330)"; + } + + 331 + { + title = "Player Skin - Continuous"; + flags64text = "[6] Disable for this skin"; + prefix = "(331)"; + } + + 332 + { + title = "Player Skin - Each Time"; + flags64text = "[6] Disable for this skin"; + prefix = "(332)"; + } + + 333 + { + title = "Player Skin - Once"; + flags64text = "[6] Disable for this skin"; + prefix = "(333)"; + } + + 399 + { + title = "Level Load"; + prefix = "(399)"; + } + } + + linedefexecsector + { + title = "Linedef Executor (sector)"; + + 400 + { + title = "Set Tagged Sector's Floor Height/Texture"; + prefix = "(400)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Keep floor flat"; + } + + 401 + { + title = "Set Tagged Sector's Ceiling Height/Texture"; + prefix = "(401)"; + flags8text = "[3] Set delay by backside sector"; + } + + 402 + { + title = "Set Tagged Sector's Light Level"; + prefix = "(402)"; + flags8text = "[3] Set delay by backside sector"; + } + + 409 + { + title = "Change Tagged Sector's Tag"; + prefix = "(409)"; + flags8text = "[3] Set delay by backside sector"; + } + + 410 + { + title = "Change Front Sector's Tag"; + prefix = "(410)"; + flags8text = "[3] Set delay by backside sector"; + } + + 416 + { + title = "Start Adjustable Flickering Light"; + prefix = "(416)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 417 + { + title = "Start Adjustable Pulsating Light"; + prefix = "(417)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 418 + { + title = "Start Adjustable Blinking Light (unsynchronized)"; + prefix = "(418)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 419 + { + title = "Start Adjustable Blinking Light (synchronized)"; + prefix = "(419)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 420 + { + title = "Fade Light Level"; + prefix = "(420)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set params by X/Y offsets"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + } + + 421 + { + title = "Stop Lighting Effect"; + prefix = "(421)"; + flags8text = "[3] Set delay by backside sector"; + } + + 435 + { + title = "Change Plane Scroller Direction"; + prefix = "(435)"; + flags8text = "[3] Set delay by backside sector"; + } + } + + linedefexecplane + { + title = "Linedef Executor (plane movement)"; + + 403 + { + title = "Move Tagged Sector's Floor"; + prefix = "(403)"; + flags2text = "[1] Trigger linedef executor"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Change floor flat"; + } + + 404 + { + title = "Move Tagged Sector's Ceiling"; + prefix = "(404)"; + flags2text = "[1] Trigger linedef executor"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Change ceiling flat"; + } + + 405 + { + title = "Move Floor According to Front Texture Offsets"; + prefix = "(405)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move instantly"; + } + + 407 + { + title = "Move Ceiling According to Front Texture Offsets"; + prefix = "(407)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move instantly"; + } + + 411 + { + title = "Stop Plane Movement"; + prefix = "(411)"; + flags8text = "[3] Set delay by backside sector"; + } + + 428 + { + title = "Start Platform Movement"; + prefix = "(428)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move upwards at start"; + } + + 429 + { + title = "Crush Ceiling Once"; + prefix = "(429)"; + flags8text = "[3] Set delay by backside sector"; + flags512text = "[9] Double, constant speed"; + } + + 430 + { + title = "Crush Floor Once"; + prefix = "(430)"; + flags8text = "[3] Set delay by backside sector"; + } + + 431 + { + title = "Crush Floor and Ceiling Once"; + prefix = "(431)"; + flags8text = "[3] Set delay by backside sector"; + flags512text = "[9] Double, constant speed"; + } + } + + linedefexecplayer + { + title = "Linedef Executor (player/object)"; + + 412 + { + title = "Teleporter"; + prefix = "(412)"; + flags2text = "[1] Silent"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Retain angle"; + flags256text = "[8] Relative, silent"; + flags512text = "[9] Retain momentum"; + } + + 425 + { + title = "Change Object State"; + prefix = "(425)"; + flags8text = "[3] Set delay by backside sector"; + } + + 426 + { + title = "Stop Object"; + prefix = "(426)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Teleport to sector center"; + } + + 427 + { + title = "Award Score"; + prefix = "(427)"; + flags8text = "[3] Set delay by backside sector"; + } + + 432 + { + title = "Enable/Disable 2D Mode"; + prefix = "(432)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Return to 3D"; + } + + 433 + { + title = "Enable/Disable Gravity Flip"; + prefix = "(433)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Return to normal"; + } + + 434 + { + title = "Award Power-Up"; + prefix = "(434)"; + flags2text = "[1] Use back upper texture"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] No time limit"; + } + + 437 + { + title = "Disable Player Control"; + prefix = "(437)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Allow jumping"; + } + + 438 + { + title = "Change Object Size"; + prefix = "(438)"; + flags8text = "[3] Set delay by backside sector"; + } + + 442 + { + title = "Change Object Type State"; + prefix = "(442)"; + flags8text = "[3] Set delay by backside sector"; + } + + 457 + { + title = "Track Object's Angle"; + prefix = "(457)"; + flags8text = "[3] Set delay by backside sector"; + flags128text = "[7] Don't stop after first fail"; + } + + 458 + { + title = "Stop Tracking Object's Angle"; + prefix = "(458)"; + flags8text = "[3] Set delay by backside sector"; + } + + 460 + { + title = "Award Rings"; + prefix = "(460)"; + } + + 461 + { + title = "Spawn Object"; + prefix = "(461)"; + flags64text = "[6] Spawn inside a range"; + } + + 462 + { + title = "Stop Timer/Exit Stage in Record Attack"; + prefix = "(462)"; + } + } + + linedefexecmisc + { + title = "Linedef Executor (misc.)"; + + 413 + { + title = "Change Music"; + prefix = "(413)"; + flags2text = "[1] Keep after death"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Seek to current song position"; + flags64text = "[6] For everyone"; + flags128text = "[7] Fade to custom volume"; + flags512text = "[9] Don't loop"; + flags16384text = "[14] Force music reload"; + } + + 414 + { + title = "Play Sound Effect"; + prefix = "(414)"; + flags2text = "[1] From calling sector"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] From nowhere for triggerer"; + flags512text = "[9] For everyone"; + flags1024text = "[10] From tagged sectors"; + } + + 415 + { + title = "Run Script"; + prefix = "(415)"; + flags8text = "[3] Set delay by backside sector"; + } + + 422 + { + title = "Switch to Cut-Away View"; + prefix = "(422)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Adjust pitch"; + } + + 423 + { + title = "Change Sky"; + prefix = "(423)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + } + + 424 + { + title = "Change Weather"; + prefix = "(424)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + } + + 436 + { + title = "Shatter FOF"; + prefix = "(436)"; + flags8text = "[3] Set delay by backside sector"; + } + + 439 + { + title = "Change Tagged Linedef's Textures"; + prefix = "(439)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only existing"; + } + + 440 + { + title = "Start Metal Sonic Race"; + prefix = "(440)"; + flags8text = "[3] Set delay by backside sector"; + } + + 441 + { + title = "Condition Set Trigger"; + prefix = "(441)"; + flags8text = "[3] Set delay by backside sector"; + } + + 443 + { + title = "Call Lua Function"; + prefix = "(443)"; + flags8text = "[3] Set delay by backside sector"; + } + + 444 + { + title = "Earthquake"; + prefix = "(444)"; + flags8text = "[3] Set delay by backside sector"; + } + + + 445 + { + title = "Make FOF Disappear/Reappear"; + prefix = "(445)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Reappear"; + } + + 446 + { + title = "Make FOF Crumble"; + prefix = "(446)"; + flags2text = "[1] Flags determine respawn"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't respawn"; + } + + 447 + { + title = "Change Tagged Sector's Colormap"; + prefix = "(447)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Front X/Y = Alpha"; + flags32text = "[5] Subtract Red value"; + flags64text = "[6] Subtract Green value"; + flags128text = "[7] Subtract Blue value"; + flags256text = "[8] Calc relative values"; + flags32768text = "[15] Use back side colormap"; + } + + 448 + { + title = "Change Skybox"; + prefix = "(448)"; + flags2text = "[1] Change centerpoint"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + flags512text = "[9] Don't change viewpoint"; + } + + 450 + { + title = "Execute Linedef Executor (specific tag)"; + prefix = "(450)"; + flags8text = "[3] Set delay by backside sector"; + } + + 451 + { + title = "Execute Linedef Executor (random tag in range)"; + prefix = "(451)"; + flags8text = "[3] Set delay by backside sector"; + } + + 452 + { + title = "Set FOF Translucency"; + prefix = "(452)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Do not handle FF_TRANS"; + flags256text = "[8] Set relative to current val"; + } + + 453 + { + title = "Fade FOF"; + prefix = "(453)"; + flags2text = "[1] Do not handle FF_EXISTS"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] No collision during fade"; + flags64text = "[6] Do not handle FF_TRANS"; + flags128text = "[7] Do not handle lighting"; + flags256text = "[8] Set relative to current val"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Do not handle collision"; + flags32768text = "[15] Use exact alpha in OGL"; + } + + 454 + { + title = "Stop Fading FOF"; + prefix = "(454)"; + flags2text = "[1] Do not finalize collision"; + flags8text = "[3] Set delay by backside sector"; + } + + 455 + { + title = "Fade Tagged Sector's Colormap"; + prefix = "(455)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Front X/Y = Alpha"; + flags32text = "[5] Subtract Red value"; + flags64text = "[6] Subtract Green value"; + flags128text = "[7] Subtract Blue value"; + flags256text = "[8] Calc relative values"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Fade from invisible black"; + flags32768text = "[15] Use back side colormap"; + } + + 456 + { + title = "Stop Fading Tagged Sector's Colormap"; + prefix = "(456)"; + flags8text = "[3] Set delay by backside sector"; + } + + 459 + { + title = "Control Text Prompt"; + prefix = "(459)"; + flags2text = "[1] Close text prompt"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Run executor tag on close"; + flags64text = "[6] For everyone"; + flags128text = "[7] Do not block controls"; + flags256text = "[8] Do not freeze time"; + flags32768text = "[15] Find prompt by name"; + } + } + + linedefexecpoly + { + title = "Linedef Executor (polyobject)"; + + 480 + { + title = "Door Slide"; + prefix = "(480)"; + flags8text = "[3] Set delay by backside sector"; + } + + 481 + { + title = "Door Swing"; + prefix = "(481)"; + flags8text = "[3] Set delay by backside sector"; + } + + 482 + { + title = "Move"; + prefix = "(482)"; + flags8text = "[3] Set delay by backside sector"; + } + + 483 + { + title = "Move, Override"; + prefix = "(483)"; + flags8text = "[3] Set delay by backside sector"; + } + + 484 + { + title = "Rotate Right"; + prefix = "(484)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 485 + { + title = "Rotate Right, Override"; + prefix = "(485)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 486 + { + title = "Rotate Left"; + prefix = "(486)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 487 + { + title = "Rotate Left, Override"; + prefix = "(487)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 488 + { + title = "Move by Waypoints"; + prefix = "(488)"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Reverse order"; + flags128text = "[7] There and back"; + flags256text = "[8] Return when done"; + flags512text = "[9] Loop movement"; + } + + 489 + { + title = "Turn Invisible, Intangible"; + prefix = "(489)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only invisible"; + } + + 490 + { + title = "Turn Visible, Tangible"; + prefix = "(490)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only visible"; + } + + 491 + { + title = "Set Translucency"; + prefix = "(491)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set raw alpha by Front X"; + flags256text = "[8] Calc relative values"; + } + + 492 + { + title = "Fade Translucency"; + prefix = "(492)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set raw alpha by Front X"; + flags32text = "[5] No collision during fade"; + flags256text = "[8] Calc relative values"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Do not handle collision"; + } + } + + wallscroll + { + title = "Wall Scrolling"; + + 500 + { + title = "Scroll Wall Front Side Left"; + prefix = "(500)"; + } + + 501 + { + title = "Scroll Wall Front Side Right"; + prefix = "(501)"; + } + + 502 + { + title = "Scroll Wall According to Linedef"; + prefix = "(502)"; + } + + 503 + { + title = "Scroll Wall According to Linedef (Accelerative)"; + prefix = "(503)"; + } + + 504 + { + title = "Scroll Wall According to Linedef (Displacement)"; + prefix = "(504)"; + } + + 505 + { + title = "Scroll Texture by Front Side Offsets"; + prefix = "(505)"; + } + + 506 + { + title = "Scroll Texture by Back Side Offsets"; + prefix = "(506)"; + } + } + + planescroll + { + title = "Plane Scrolling"; + + 510 + { + title = "Scroll Floor Texture"; + prefix = "(510)"; + } + + 511 + { + title = "Scroll Floor Texture (Accelerative)"; + prefix = "(511)"; + } + + 512 + { + title = "Scroll Floor Texture (Displacement)"; + prefix = "(512)"; + } + + 513 + { + title = "Scroll Ceiling Texture"; + prefix = "(513)"; + } + + 514 + { + title = "Scroll Ceiling Texture (Accelerative)"; + prefix = "(514)"; + } + + 515 + { + title = "Scroll Ceiling Texture (Displacement)"; + prefix = "(515)"; + } + + 520 + { + title = "Carry Objects on Floor"; + prefix = "(520)"; + } + + 521 + { + title = "Carry Objects on Floor (Accelerative)"; + prefix = "(521)"; + flags64text = "[6] Even across edges"; + } + + 522 + { + title = "Carry Objects on Floor (Displacement)"; + prefix = "(522)"; + } + + 523 + { + title = "Carry Objects on Ceiling"; + prefix = "(523)"; + flags64text = "[6] Even across edges"; + } + + 524 + { + title = "Carry Objects on Ceiling (Accelerative)"; + prefix = "(524)"; + } + + 525 + { + title = "Carry Objects on Ceiling (Displacement)"; + prefix = "(525)"; + } + + 530 + { + title = "Scroll Floor Texture and Carry Objects"; + prefix = "(530)"; + flags64text = "[6] Even across edges"; + } + + 531 + { + title = "Scroll Floor Texture and Carry Objects (Accelerative)"; + prefix = "(531)"; + } + + 532 + { + title = "Scroll Floor Texture and Carry Objects (Displacement)"; + prefix = "(532)"; + } + + 533 + { + title = "Scroll Ceiling Texture and Carry Objects"; + prefix = "(533)"; + flags64text = "[6] Even across edges"; + } + + 534 + { + title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; + prefix = "(534)"; + } + + 535 + { + title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; + prefix = "(535)"; + } + } + + pusher + { + title = "Pusher"; + + 541 + { + title = "Wind"; + prefix = "(541)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 542 + { + title = "Upwards Wind"; + prefix = "(542)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 543 + { + title = "Downwards Wind"; + prefix = "(543)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 544 + { + title = "Current"; + prefix = "(544)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 545 + { + title = "Upwards Current"; + prefix = "(545)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 546 + { + title = "Downwards Current"; + prefix = "(546)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 547 + { + title = "Push/Pull"; + prefix = "(547)"; + } + } + + light + { + title = "Lighting"; + + 600 + { + title = "Floor Lighting"; + prefix = "(600)"; + } + + 601 + { + title = "Ceiling Lighting"; + prefix = "(601)"; + } + + 602 + { + title = "Adjustable Pulsating Light"; + prefix = "(602)"; + } + + 603 + { + title = "Adjustable Flickering Light"; + prefix = "(603)"; + } + + 604 + { + title = "Adjustable Blinking Light (unsynchronized)"; + prefix = "(604)"; + } + + 605 + { + title = "Adjustable Blinking Light (synchronized)"; + prefix = "(605)"; + } + + 606 + { + title = "Colormap"; + prefix = "(606)"; + } + } + + slope + { + title = "Slope"; + + 700 + { + title = "Slope Frontside Floor"; + prefix = "(700)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 1; + } + + 701 + { + title = "Slope Frontside Ceiling"; + prefix = "(701)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 2; + } + + 702 + { + title = "Slope Frontside Floor and Ceiling"; + prefix = "(702)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 3; + } + + 703 + { + title = "Slope Frontside Floor and Backside Ceiling"; + prefix = "(703)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 9; + } + + 704 + { + title = "Slope Frontside Floor by 3 Tagged Vertex Things"; + prefix = "(704)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 0; + } + + 705 + { + title = "Slope Frontside Ceiling by 3 Tagged Vertex Things"; + prefix = "(705)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 1; + } + + 710 + { + title = "Slope Backside Floor"; + prefix = "(710)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 4; + } + + 711 + { + title = "Slope Backside Ceiling"; + prefix = "(711)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 8; + } + + 712 + { + title = "Slope Backside Floor and Ceiling"; + prefix = "(712)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 12; + } + + 713 + { + title = "Slope Backside Floor and Frontside Ceiling"; + prefix = "(713)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 6; + } + + 714 + { + title = "Slope Backside Floor by 3 Tagged Vertex Things"; + prefix = "(714)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 2; + } + + 715 + { + title = "Slope Backside Ceiling by 3 Tagged Vertex Things"; + prefix = "(715)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 3; + } + + 720 + { + title = "Copy Frontside Floor Slope from Line Tag"; + prefix = "(720)"; + slope = "copy"; + slopeargs = 1; + } + + 721 + { + title = "Copy Frontside Ceiling Slope from Line Tag"; + prefix = "(721)"; + slope = "copy"; + slopeargs = 2; + } + + 722 + { + title = "Copy Frontside Floor and Ceiling Slope from Line Tag"; + prefix = "(722)"; + slope = "copy"; + slopeargs = 3; + } + + 799 + { + title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; + prefix = "(799)"; + } + } + + transwall + { + title = "Translucent Wall"; + + 900 + { + title = "90% Opaque"; + prefix = "(900)"; + } + + 901 + { + title = "80% Opaque"; + prefix = "(901)"; + } + + 902 + { + title = "70% Opaque"; + prefix = "(902)"; + } + + 903 + { + title = "60% Opaque"; + prefix = "(903)"; + } + + 904 + { + title = "50% Opaque"; + prefix = "(904)"; + } + + 905 + { + title = "40% Opaque"; + prefix = "(905)"; + } + + 906 + { + title = "30% Opaque"; + prefix = "(906)"; + } + + 907 + { + title = "20% Opaque"; + prefix = "(907)"; + } + + 908 + { + title = "10% Opaque"; + prefix = "(908)"; + } + + 909 + { + title = "Fog Wall"; + prefix = "(909)"; + } + } +} + +udmf +{ + misc + { + title = "Miscellaneous"; + + 0 + { + title = "None"; + prefix = "(0)"; + } + } +} \ No newline at end of file diff --git a/extras/conf/Includes/SRB222_misc.cfg b/extras/conf/Includes/SRB222_misc.cfg new file mode 100644 index 000000000..ce23388b2 --- /dev/null +++ b/extras/conf/Includes/SRB222_misc.cfg @@ -0,0 +1,726 @@ +linedefflags +{ + 1 = "[0] Impassable"; + 2 = "[1] Block Enemies"; + 4 = "[2] Double-Sided"; + 8 = "[3] Upper Unpegged"; + 16 = "[4] Lower Unpegged"; + 32 = "[5] Slope Skew (E1)"; + 64 = "[6] Not Climbable"; + 128 = "[7] No Midtexture Skew (E2)"; + 256 = "[8] Peg Midtexture (E3)"; + 512 = "[9] Solid Midtexture (E4)"; + 1024 = "[10] Repeat Midtexture (E5)"; + 2048 = "[11] Netgame Only"; + 4096 = "[12] No Netgame"; + 8192 = "[13] Effect 6"; + 16384 = "[14] Bouncy Wall"; + 32768 = "[15] Transfer Line"; +} + + +// LINEDEF ACTIVATIONS +// Make sure these are in order from lowest value to highest value +linedefactivations +{ +} + + +// Linedef flags UDMF translation table +// This is needed for copy/paste and prefabs to work properly +// When the UDMF field name is prefixed with ! it is inverted +linedefflagstranslation +{ + 1 = "blocking"; + 2 = "blockmonsters"; + 4 = "twosided"; + 8 = "dontpegtop"; + 16 = "dontpegbottom"; + 32 = "skewtd"; + 64 = "noclimb"; + 128 = "noskew"; + 256 = "midpeg"; + 512 = "midsolid"; + 1024 = "wrapmidtex"; + 2048 = "netonly"; + 4096 = "nonet"; + 8192 = "effect6"; + 16384 = "bouncy"; + 32768 = "transfer"; +} + + +linedefflags_udmf +{ + blocking = "Impassable"; + blockmonsters = "Block Enemies"; + twosided = "Double-Sided"; + dontpegtop = "Upper Unpegged"; + dontpegbottom = "Lower Unpegged"; + skewtd = "Slope Skew"; + noclimb = "Not Climbable"; + noskew = "No Midtexture Skew"; + midpeg = "Peg Midtexture"; + midsolid = "Solid Midtexture"; + wrapmidtex = "Repeat Midtexture"; +// netonly = "Netgame-Only special"; +// nonet = "No netgame special"; +// effect6 = "Effect 6"; + bouncy = "Bouncy Wall"; +// transfer = "Transfer Line"; +} + + +linedefactivations_udmf +{ + notriggerorder = "Out of Order"; + netonly = "Netgame-Only"; + nonet = "No netgame"; +} + +sidedefflags +{ + clipmidtex = "Clip middle texture"; + wrapmidtex = "Wrap middle texture"; + smoothlighting = "Smooth lighting"; + nofakecontrast = "Even lighting"; + nodecals = "No decals"; + lightfog = "Use sidedef brightness on fogged walls"; +} + +//RENDER STYLES +thingrenderstyles +{ +} + +linedefrenderstyles +{ + translucent = "Translucent"; + fog = "Fog"; +} + +sectorrenderstyles +{ +} + +thingflags +{ + 1 = "[1] Extra"; + 2 = "[2] Flip"; + 4 = "[4] Special"; + 8 = "[8] Ambush"; +} + +// THING FLAGS +thingflags_udmf +{ + extra = "Extra"; + flip = "Flip"; + special = "Special"; + ambush = "Ambush"; +} + + +// Thing flags UDMF translation table +// This is needed for copy/paste and prefabs to work properly +// When the UDMF field name is prefixed with ! it is inverted +thingflagstranslation +{ + 1 = "extra"; + 2 = "flip"; + 4 = "special"; + 8 = "ambush"; +} + + +// DEFAULT SECTOR BRIGHTNESS LEVELS +sectorbrightness +{ + 255; + 248; + 240; + 232; + 224; + 216; + 208; + 200; + 192; + 184; + 176; + 168; + 160; + 152; + 144; + 136; + 128; + 120; + 112; + 104; + 96; + 88; + 80; + 72; + 64; + 56; + 48; + 40; + 32; + 24; + 16; + 8; + 0; +} + +/* +TEXTURES AND FLAT SOURCES +This tells Doom Builder where to find the information for textures +and flats in the IWAD file, Addition WAD file and Map WAD file. + +Start and end lumps must be given in a structure (of which the +key name doesnt matter) and any textures or flats in between them +are loaded in either the textures category or flats category. + +For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. +*/ +textures +{ + zdoom1 + { + start = "TX_START"; + end = "TX_END"; + } +} + +/* +ADDITIONAL UNIVERSAL DOOM MAP FORMAT FIELD DEFINITIONS +Only add fields here that Doom Builder does not edit with its own user-interface! +The "default" field must match the UDMF specifications! + +Field data types: +0 = integer * +1 = float +2 = string +3 = bool +4 = linedef action (integer) * +5 = sector effect (integer) * +6 = texture (string) +7 = flat (string) +8 = angle in degrees (integer) +9 = angle in radians (float) +10 = XXRRGGBB color (integer) +11 = enum option (integer) * +12 = enum bits (integer) * +13 = sector tag (integer) * +14 = thing tag (integer) * +15 = linedef tag (integer) * +16 = enum option (string) +17 = angle in degrees (float) +22 = byte angle (integer) +*/ +universalfields +{ + sector + { + friction + { + name = "Friction"; + type = 1; + default = 1; + } + + specialeffectplanes + { + type = 11; + enum = "floorceiling"; + default = 0; + } + + colormapbegin + { + type = 0; + default = 0; + } + + colormapend + { + type = 0; + default = 33; + } + + foglighting + { + type = 3; + default = false; + } + + teambase + { + type = 11; + enum = "ctfteam"; + default = 0; + } + + triggersector + { + type = 3; + default = false; + } + + triggerobject + { + type = 11; + enum = "triggerobjects"; + default = 0; + } + + triggersurface + { + type = 11; + enum = "triggersurfaces"; + default = 0; + } + + ringdrain + { + type = 1; + default = 0; + } + } + + linedef + { + executordelay + { + type = 0; + default = 0; + } + midtexrepetitions + { + type = 0; + default = 0; + } + arg5 + { + type = 0; + default = 0; + } + arg1str + { + type = 2; + default = ""; + } + } + + thing + { + } +} + +/* +MAP LUMP NAMES +Map lumps are loaded with the map as long as they are right after each other. When the editor +meets a lump which is not defined in this list it will ignore the map if not satisfied. +The order of items defines the order in which lumps will be written to WAD file on save. +To indicate the map header lump, use ~MAP + +Legenda: +required = Lump is required to exist. +blindcopy = Lump will be copied along with the map blindly. (useful for lumps Doom Builder doesn't use) +nodebuild = The nodebuilder generates this lump. +allowempty = The nodebuilder is allowed to leave this lump empty. +scriptbuild = This lump is a text-based script, which should be compiled using current script compiler; +script = This lump is a text-based script. Specify the filename of the script configuration to use. +*/ + +doommaplumpnames +{ + ~MAP + { + required = true; + blindcopy = true; + nodebuild = false; + } + + THINGS + { + required = true; + nodebuild = true; + allowempty = true; + } + + LINEDEFS + { + required = true; + nodebuild = true; + allowempty = false; + } + + SIDEDEFS + { + required = true; + nodebuild = true; + allowempty = false; + } + + VERTEXES + { + required = true; + nodebuild = true; + allowempty = false; + } + + SEGS + { + required = false; + nodebuild = true; + allowempty = false; + } + + SSECTORS + { + required = false; + nodebuild = true; + allowempty = false; + } + + NODES + { + required = false; + nodebuild = true; + allowempty = false; + } + + SECTORS + { + required = true; + nodebuild = true; + allowempty = false; + } + + REJECT + { + required = false; + nodebuild = true; + allowempty = false; + } + + BLOCKMAP + { + required = false; + nodebuild = true; + allowempty = true; + } +} + +udmfmaplumpnames +{ + ZNODES + { + required = false; + nodebuild = true; + allowempty = false; + } + + REJECT + { + required = false; + nodebuild = true; + allowempty = false; + } + + BLOCKMAP + { + required = false; + nodebuild = true; + allowempty = true; + } +} + +// ENUMERATIONS +// These are enumerated lists for linedef types and UDMF fields. +// Reserved names are: angledeg, anglerad, color, texture, flat +enums +{ + falsetrue + { + 0 = "False"; + 1 = "True"; + } + + yesno + { + 0 = "Yes"; + 1 = "No"; + } + + noyes + { + 0 = "No"; + 1 = "Yes"; + } + + onoff + { + 0 = "On"; + 1 = "Off"; + } + + offon + { + 0 = "Off"; + 1 = "On"; + } + + updown + { + 0 = "Up"; + 1 = "Down"; + } + + downup + { + 0 = "Down"; + 1 = "Up"; + } + + addset + { + 0 = "Add"; + 1 = "Set"; + } + + floorceiling + { + 0 = "Floor"; + 1 = "Ceiling"; + 2 = "Floor and ceiling"; + } + + triggertype + { + 0 = "Continuous"; + 1 = "Each Time (Enter)"; + 2 = "Each Time (Enter and leave)"; + 3 = "Once"; + } + + frontback + { + 0 = "None"; + 1 = "Front"; + 2 = "Back"; + } + + ctfteam + { + 0 = "None"; + 1 = "Red"; + 2 = "Blue"; + } + + triggerobjects + { + 0 = "Any player"; + 1 = "All players"; + 2 = "Pushable object"; + 3 = "Any object with thinker"; + } + + triggersurfaces + { + 0 = "Floor touch"; + 1 = "Ceiling touch"; + 2 = "Floor or ceiling touch"; + 3 = "Anywhere in sector"; + } + + tangibility + { + 1 = "Intangible from top"; + 2 = "Intangible from bottom"; + 4 = "Don't block players"; + 8 = "Don't block non-players"; + } +} + +//Default things filters +thingsfilters +{ + + filter0 + { + name = "Player starts"; + category = "starts"; + type = -1; + } + + + filter1 + { + name = "Enemies"; + category = "enemies"; + type = -1; + + } + + + filter2 + { + name = "NiGHTS Track"; + category = "nightstrk"; + type = -1; + + } + + + filter3 + { + name = "Normal Gravity"; + category = ""; + type = -1; + + fields + { + 2 = false; + } + + } + + + filter4 + { + name = "Reverse Gravity"; + category = ""; + type = -1; + + fields + { + 2 = true; + } + + } +} + +thingsfilters_udmf +{ +} + +// Special linedefs +speciallinedefs +{ + soundlinedefflag = 64; // See linedefflags + singlesidedflag = 1; // See linedefflags + doublesidedflag = 4; // See linedefflags + impassableflag = 1; + upperunpeggedflag = 8; + lowerunpeggedflag = 16; + repeatmidtextureflag = 1024; + pegmidtextureflag = 256; +} + +speciallinedefs_udmf +{ + soundlinedefflag = "noclimb"; + singlesidedflag = "blocking"; + doublesidedflag = "twosided"; + impassableflag = "blocking"; + upperunpeggedflag = "dontpegtop"; + lowerunpeggedflag = "dontpegbottom"; + repeatmidtextureflag = "wrapmidtex"; + pegmidtextureflag = "midpeg"; +} + +scriptlumpnames +{ + MAINCFG + { + script = "SOC.cfg"; + } + + OBJCTCFG + { + script = "SOC.cfg"; + } + + SOC_ + { + script = "SOC.cfg"; + isprefix = true; + } + + LUA_ + { + script = "Lua.cfg"; + isprefix = true; + } +} + +// Texture sources +textures +{ + zdoom1 + { + start = "TX_START"; + end = "TX_END"; + } +} + +// Patch sources +patches +{ + standard1 + { + start = "P_START"; + end = "P_END"; + } + + standard2 + { + start = "PP_START"; + end = "PP_END"; + } +} + +// Sprite sources +sprites +{ + standard1 + { + start = "S_START"; + end = "S_END"; + } + + standard2 + { + start = "SS_START"; + end = "SS_END"; + } +} + +// Flat sources +flats +{ + standard1 + { + start = "F_START"; + end = "F_END"; + } + + standard2 + { + start = "FF_START"; + end = "FF_END"; + } + + standard3 + { + start = "FF_START"; + end = "F_END"; + } + + standard4 + { + start = "F_START"; + end = "FF_END"; + } +} \ No newline at end of file diff --git a/extras/conf/Includes/SRB222_sectors.cfg b/extras/conf/Includes/SRB222_sectors.cfg new file mode 100644 index 000000000..3bcbeb1b1 --- /dev/null +++ b/extras/conf/Includes/SRB222_sectors.cfg @@ -0,0 +1,109 @@ +sectortypes +{ + 0 = "Normal"; + 1 = "Damage"; + 2 = "Damage (Water)"; + 3 = "Damage (Fire)"; + 4 = "Damage (Electrical)"; + 5 = "Spikes"; + 6 = "Death Pit (Camera Tilt)"; + 7 = "Death Pit (No Camera Tilt)"; + 8 = "Instant Kill"; + 9 = "Ring Drainer (Floor Touch)"; + 10 = "Ring Drainer (Anywhere in Sector)"; + 11 = "Special Stage Damage"; + 12 = "Space Countdown"; + 13 = "Ramp Sector (double step-up/down)"; + 14 = "Non-Ramp Sector (no step-down)"; + 15 = "Bouncy FOF"; + 16 = "Trigger Line Ex. (Pushable Objects)"; + 32 = "Trigger Line Ex. (Anywhere, All Players)"; + 48 = "Trigger Line Ex. (Floor Touch, All Players)"; + 64 = "Trigger Line Ex. (Anywhere in Sector)"; + 80 = "Trigger Line Ex. (Floor Touch)"; + 96 = "Trigger Line Ex. (Emerald Check)"; + 112 = "Trigger Line Ex. (NiGHTS Mare)"; + 128 = "Check for Linedef Executor on FOFs"; + 144 = "Egg Capsule"; + 160 = "Special Stage Time/Rings Parameters"; + 176 = "Custom Global Gravity"; + 512 = "Wind/Current"; + 1024 = "Conveyor Belt"; + 1280 = "Speed Pad"; + 4096 = "Star Post Activator"; + 8192 = "Exit/Special Stage Pit/Return Flag"; + 12288 = "CTF Red Team Base"; + 16384 = "CTF Blue Team Base"; + 20480 = "Fan Sector"; + 24576 = "Super Sonic Transform"; + 28672 = "Force Spin"; + 32768 = "Zoom Tube Start"; + 36864 = "Zoom Tube End"; + 40960 = "Circuit Finish Line"; + 45056 = "Rope Hang"; + 49152 = "Intangible to the Camera"; +} + +gen_sectortypes +{ + first + { + 0 = "Normal"; + 1 = "Damage"; + 2 = "Damage (Water)"; + 3 = "Damage (Fire)"; + 4 = "Damage (Electrical)"; + 5 = "Spikes"; + 6 = "Death Pit (Camera Tilt)"; + 7 = "Death Pit (No Camera Tilt)"; + 8 = "Instant Kill"; + 9 = "Ring Drainer (Floor Touch)"; + 10 = "Ring Drainer (Anywhere in Sector)"; + 11 = "Special Stage Damage"; + 12 = "Space Countdown"; + 13 = "Ramp Sector (double step-up/down)"; + 14 = "Non-Ramp Sector (no step-down)"; + 15 = "Bouncy FOF"; + } + + second + { + 0 = "Normal"; + 16 = "Trigger Line Ex. (Pushable Objects)"; + 32 = "Trigger Line Ex. (Anywhere, All Players)"; + 48 = "Trigger Line Ex. (Floor Touch, All Players)"; + 64 = "Trigger Line Ex. (Anywhere in Sector)"; + 80 = "Trigger Line Ex. (Floor Touch)"; + 96 = "Trigger Line Ex. (Emerald Check)"; + 112 = "Trigger Line Ex. (NiGHTS Mare)"; + 128 = "Check for Linedef Executor on FOFs"; + 144 = "Egg Capsule"; + 160 = "Special Stage Time/Rings Parameters"; + 176 = "Custom Global Gravity"; + } + + third + { + 0 = "Normal"; + 512 = "Wind/Current"; + 1024 = "Conveyor Belt"; + 1280 = "Speed Pad"; + } + + fourth + { + 0 = "Normal"; + 4096 = "Star Post Activator"; + 8192 = "Exit/Special Stage Pit/Return Flag"; + 12288 = "CTF Red Team Base"; + 16384 = "CTF Blue Team Base"; + 20480 = "Fan Sector"; + 24576 = "Super Sonic Transform"; + 28672 = "Force Spin"; + 32768 = "Zoom Tube Start"; + 36864 = "Zoom Tube End"; + 40960 = "Circuit Finish Line"; + 45056 = "Rope Hang"; + 49152 = "Intangible to the Camera"; + } +} \ No newline at end of file diff --git a/extras/conf/Includes/SRB222_things.cfg b/extras/conf/Includes/SRB222_things.cfg new file mode 100644 index 000000000..194e43630 --- /dev/null +++ b/extras/conf/Includes/SRB222_things.cfg @@ -0,0 +1,3398 @@ +// THING TYPES------------------------------------------------------------------ +// Color values: 1-Dark_Blue 2-Dark_Green 3-Turqoise 4-Dark_Red 5-Purple 6-Brown 7-Gray +// 8-Dark_Gray 9-Blue 10-Green 11-Cyan 12-Red 13-Magenta +// 14-Yellow 15-White 16-Pink 17-Orange 18-Gold 19-Cream + +editor +{ + color = 15; // White + arrow = 1; + title = ""; + error = -1; + width = 8; + height = 16; + sort = 1; + + 3328 = "3D Mode Start"; +} + +starts +{ + color = 1; // Blue + arrow = 1; + title = "Player Starts"; + width = 16; + height = 48; + flags8text = "[8] Spawn on ceiling"; + sprite = "PLAYA0"; + + 1 + { + title = "Player 01 Start"; + sprite = "PLAYA0"; + } + 2 + { + title = "Player 02 Start"; + sprite = "PLAYA0"; + } + 3 + { + title = "Player 03 Start"; + sprite = "PLAYA0"; + } + 4 + { + title = "Player 04 Start"; + sprite = "PLAYA0"; + } + 5 + { + title = "Player 05 Start"; + sprite = "PLAYA0"; + } + 6 + { + title = "Player 06 Start"; + sprite = "PLAYA0"; + } + 7 + { + title = "Player 07 Start"; + sprite = "PLAYA0"; + } + 8 + { + title = "Player 08 Start"; + sprite = "PLAYA0"; + } + 9 + { + title = "Player 09 Start"; + sprite = "PLAYA0"; + } + 10 + { + title = "Player 10 Start"; + sprite = "PLAYA0"; + } + 11 + { + title = "Player 11 Start"; + sprite = "PLAYA0"; + } + 12 + { + title = "Player 12 Start"; + sprite = "PLAYA0"; + } + 13 + { + title = "Player 13 Start"; + sprite = "PLAYA0"; + } + 14 + { + title = "Player 14 Start"; + sprite = "PLAYA0"; + } + 15 + { + title = "Player 15 Start"; + sprite = "PLAYA0"; + } + 16 + { + title = "Player 16 Start"; + sprite = "PLAYA0"; + } + 17 + { + title = "Player 17 Start"; + sprite = "PLAYA0"; + } + 18 + { + title = "Player 18 Start"; + sprite = "PLAYA0"; + } + 19 + { + title = "Player 19 Start"; + sprite = "PLAYA0"; + } + 20 + { + title = "Player 20 Start"; + sprite = "PLAYA0"; + } + 21 + { + title = "Player 21 Start"; + sprite = "PLAYA0"; + } + 22 + { + title = "Player 22 Start"; + sprite = "PLAYA0"; + } + 23 + { + title = "Player 23 Start"; + sprite = "PLAYA0"; + } + 24 + { + title = "Player 24 Start"; + sprite = "PLAYA0"; + } + 25 + { + title = "Player 25 Start"; + sprite = "PLAYA0"; + } + 26 + { + title = "Player 26 Start"; + sprite = "PLAYA0"; + } + 27 + { + title = "Player 27 Start"; + sprite = "PLAYA0"; + } + 28 + { + title = "Player 28 Start"; + sprite = "PLAYA0"; + } + 29 + { + title = "Player 29 Start"; + sprite = "PLAYA0"; + } + 30 + { + title = "Player 30 Start"; + sprite = "PLAYA0"; + } + 31 + { + title = "Player 31 Start"; + sprite = "PLAYA0"; + } + 32 + { + title = "Player 32 Start"; + sprite = "PLAYA0"; + } + 33 + { + title = "Match Start"; + sprite = "NDRNA2A8"; + } + 34 + { + title = "CTF Red Team Start"; + sprite = "SIGNG0"; + } + 35 + { + title = "CTF Blue Team Start"; + sprite = "SIGNE0"; + } +} + +enemies +{ + color = 9; // Light_Blue + arrow = 1; + title = "Enemies"; + + 100 + { + title = "Crawla (Blue)"; + sprite = "POSSA1"; + width = 24; + height = 32; + } + 101 + { + title = "Crawla (Red)"; + sprite = "SPOSA1"; + width = 24; + height = 32; + } + 102 + { + title = "Stupid Dumb Unnamed RoboFish"; + sprite = "FISHA0"; + width = 8; + height = 28; + angletext = "Jump strength"; + } + 103 + { + title = "Buzz (Gold)"; + sprite = "BUZZA1"; + width = 28; + height = 40; + flags8text = "[8] Cannot move"; + } + 104 + { + title = "Buzz (Red)"; + sprite = "RBUZA1"; + width = 28; + height = 40; + flags8text = "[8] Cannot move"; + } + 108 + { + title = "Deton"; + sprite = "DETNA1"; + width = 20; + height = 32; + } + 110 + { + title = "Turret"; + sprite = "TRETA1"; + width = 16; + height = 32; + } + 111 + { + title = "Pop-up Turret"; + sprite = "TURRI1"; + width = 12; + height = 64; + angletext = "Firing delay"; + } + 122 + { + title = "Spring Shell (Green)"; + sprite = "SSHLA1"; + width = 24; + height = 40; + } + 125 + { + title = "Spring Shell (Yellow)"; + sprite = "SSHLI1"; + width = 24; + height = 40; + } + 109 + { + title = "Skim"; + sprite = "SKIMA1"; + width = 16; + height = 24; + } + 113 + { + title = "Jet Jaw"; + sprite = "JJAWA3A7"; + width = 12; + height = 20; + } + 126 + { + title = "Crushstacean"; + sprite = "CRABA0"; + width = 24; + height = 32; + flags8text = "[8] Move left from spawn"; + } + 138 + { + title = "Banpyura"; + sprite = "CR2BA0"; + width = 24; + height = 32; + flags8text = "[8] Move left from spawn"; + } + 117 + { + title = "Robo-Hood"; + sprite = "ARCHA1"; + width = 24; + height = 32; + } + 118 + { + title = "Lance-a-Bot"; + sprite = "CBFSA1"; + width = 32; + height = 72; + } + 1113 + { + title = "Suspicious Lance-a-Bot Statue"; + sprite = "CBBSA1"; + width = 32; + height = 72; + } + 119 + { + title = "Egg Guard"; + sprite = "ESHIA1"; + width = 16; + height = 48; + flags1text = "[1] 90 degrees counter-clockwise"; + flags4text = "[4] 90 degrees clockwise"; + flags8text = "[8] Double speed"; + } + 115 + { + title = "Bird Aircraft Strike Hazard"; + sprite = "VLTRF1"; + width = 12; + height = 24; + } + 120 + { + title = "Green Snapper"; + sprite = "GSNPA1"; + width = 24; + height = 24; + } + 121 + { + title = "Minus"; + sprite = "MNUSA0"; + width = 24; + height = 32; + } + 134 + { + title = "Canarivore"; + sprite = "CANAA0"; + width = 12; + height = 80; + hangs = 1; + } + 123 + { + title = "Unidus"; + sprite = "UNIDA1"; + width = 18; + height = 36; + } + 135 + { + title = "Pterabyte Spawner"; + sprite = "PTERA2A8"; + width = 16; + height = 16; + parametertext = "No. Pterabytes"; + } + 136 + { + title = "Pyre Fly"; + sprite = "PYREA0"; + width = 24; + height = 34; + flags8text = "[8] Start on fire"; + } + 137 + { + title = "Dragonbomber"; + sprite = "DRABA1"; + width = 28; + height = 48; + } + 105 + { + title = "Jetty-Syn Bomber"; + sprite = "JETBB1"; + width = 20; + height = 50; + flags8text = "[8] Cannot move"; + } + 106 + { + title = "Jetty-Syn Gunner"; + sprite = "JETGB1"; + width = 20; + height = 48; + flags8text = "[8] Cannot move"; + } + 112 + { + title = "Spincushion"; + sprite = "SHRPA1"; + width = 16; + height = 24; + } + 114 + { + title = "Snailer"; + sprite = "SNLRA3A7"; + width = 24; + height = 48; + } + 129 + { + title = "Penguinator"; + sprite = "PENGA1"; + width = 24; + height = 32; + } + 130 + { + title = "Pophat"; + sprite = "POPHA1"; + width = 24; + height = 32; + } + 107 + { + title = "Crawla Commander"; + sprite = "CCOMA1"; + width = 16; + height = 32; + } + 131 + { + title = "Spinbobert"; + sprite = "SBOBB0"; + width = 32; + height = 32; + } + 132 + { + title = "Cacolantern"; + sprite = "CACOA0"; + width = 32; + height = 32; + flags8text = "[8] Cannot move"; + } + 133 + { + title = "Hangster"; + sprite = "HBATC1"; + width = 24; + height = 24; + hangs = 1; + } + 127 + { + title = "Hive Elemental"; + sprite = "HIVEA0"; + width = 32; + height = 80; + parametertext = "No. bees"; + } + 128 + { + title = "Bumblebore"; + sprite = "BUMBA1"; + width = 16; + height = 32; + } + 124 + { + title = "Buggle"; + sprite = "BBUZA1"; + width = 20; + height = 24; + } + 116 + { + title = "Pointy"; + sprite = "PNTYA1"; + width = 8; + height = 16; + } +} + +bosses +{ + color = 8; // Dark_Gray + arrow = 1; + title = "Bosses"; + + 200 + { + title = "Egg Mobile"; + sprite = "EGGMA1"; + width = 24; + height = 76; + flags4text = "[4] End level on death"; + flags8text = "[8] Alternate laser attack"; + } + 201 + { + title = "Egg Slimer"; + sprite = "EGGNA1"; + width = 24; + height = 76; + flags4text = "[4] End level on death"; + flags8text = "[8] Speed up when hit"; + } + 202 + { + title = "Sea Egg"; + sprite = "EGGOA1"; + width = 32; + height = 116; + flags4text = "[4] End level on death"; + } + 203 + { + title = "Egg Colosseum"; + sprite = "EGGPA1"; + width = 24; + height = 76; + flags4text = "[4] End level on death"; + } + 204 + { + title = "Fang"; + sprite = "FANGA1"; + width = 24; + height = 60; + flags1text = "[1] Grayscale mode"; + flags4text = "[4] End level on death"; + } + 206 + { + title = "Brak Eggman (Old)"; + sprite = "BRAKB1"; + width = 48; + height = 160; + flags4text = "[4] End level on death"; + } + 207 + { + title = "Metal Sonic (Race)"; + sprite = "METLI1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + } + 208 + { + title = "Metal Sonic (Battle)"; + sprite = "METLC1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + flags4text = "[4] End level on death"; + } + 209 + { + title = "Brak Eggman"; + sprite = "BRAK01"; + width = 48; + height = 160; + flags1text = "[1] No origin-fling death"; + flags4text = "[4] End level on death"; + flags8text = "[8] Electric barrier"; + } + 290 + { + arrow = 0; + title = "Boss Escape Point"; + width = 8; + height = 16; + sprite = "internal:eggmanend"; + } + 291 + { + arrow = 0; + title = "Egg Capsule Center"; + width = 8; + height = 16; + sprite = "internal:capsule"; + } + 292 + { + arrow = 0; + title = "Boss Waypoint"; + width = 8; + height = 16; + flags8text = "[8] Sea Egg shooting point"; + sprite = "internal:eggmanway"; + angletext = "No. (Sea Egg)"; + flagsvaluetext = "No. (Brak)"; + parametertext = "Next"; + } + 293 + { + title = "Metal Sonic Gather Point"; + sprite = "internal:metal"; + width = 8; + height = 16; + } + 294 + { + title = "Fang Waypoint"; + flags8text = "[8] Center waypoint"; + sprite = "internal:eggmanway"; + width = 8; + height = 16; + } +} + +rings +{ + color = 14; // Yellow + title = "Rings and Weapon Panels"; + width = 24; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + sprite = "RINGA0"; + + 300 + { + title = "Ring"; + sprite = "RINGA0"; + width = 16; + } + 301 + { + title = "Bounce Ring"; + sprite = "internal:RNGBA0"; + } + 302 + { + title = "Rail Ring"; + sprite = "internal:RNGRA0"; + } + 303 + { + title = "Infinity Ring"; + sprite = "internal:RNGIA0"; + } + 304 + { + title = "Automatic Ring"; + sprite = "internal:RNGAA0"; + } + 305 + { + title = "Explosion Ring"; + sprite = "internal:RNGEA0"; + } + 306 + { + title = "Scatter Ring"; + sprite = "internal:RNGSA0"; + } + 307 + { + title = "Grenade Ring"; + sprite = "internal:RNGGA0"; + } + 308 + { + title = "CTF Team Ring (Red)"; + sprite = "internal:RRNGA0"; + width = 16; + } + 309 + { + title = "CTF Team Ring (Blue)"; + sprite = "internal:BRNGA0"; + width = 16; + } + 330 + { + title = "Bounce Ring Panel"; + sprite = "internal:PIKBA0"; + } + 331 + { + title = "Rail Ring Panel"; + sprite = "internal:PIKRA0"; + } + 332 + { + title = "Automatic Ring Panel"; + sprite = "internal:PIKAA0"; + } + 333 + { + title = "Explosion Ring Panel"; + sprite = "internal:PIKEA0"; + } + 334 + { + title = "Scatter Ring Panel"; + sprite = "internal:PIKSA0"; + } + 335 + { + title = "Grenade Ring Panel"; + sprite = "internal:PIKGA0"; + } +} + +collectibles +{ + color = 10; // Light_Green + title = "Other Collectibles"; + width = 16; + height = 32; + sort = 1; + sprite = "CEMGA0"; + + 310 + { + title = "CTF Red Flag"; + sprite = "RFLGA0"; + width = 24; + height = 64; + } + 311 + { + title = "CTF Blue Flag"; + sprite = "BFLGA0"; + width = 24; + height = 64; + } + 312 + { + title = "Emerald Token"; + sprite = "TOKEA0"; + width = 16; + height = 32; + flags8height = 24; + flags8text = "[8] Float"; + } + 313 + { + title = "Chaos Emerald 1 (Green)"; + sprite = "CEMGA0"; + } + 314 + { + title = "Chaos Emerald 2 (Purple)"; + sprite = "CEMGB0"; + } + 315 + { + title = "Chaos Emerald 3 (Blue)"; + sprite = "CEMGC0"; + } + 316 + { + title = "Chaos Emerald 4 (Cyan)"; + sprite = "CEMGD0"; + } + 317 + { + title = "Chaos Emerald 5 (Orange)"; + sprite = "CEMGE0"; + } + 318 + { + title = "Chaos Emerald 6 (Red)"; + sprite = "CEMGF0"; + } + 319 + { + title = "Chaos Emerald 7 (Gray)"; + sprite = "CEMGG0"; + } + 320 + { + title = "Emerald Hunt Location"; + sprite = "SHRDA0"; + } + 321 + { + title = "Match Chaos Emerald Spawn"; + sprite = "CEMGA0"; + flags8height = 24; + flags8text = "[8] Float"; + } + 322 + { + title = "Emblem"; + sprite = "EMBMA0"; + width = 16; + height = 30; + flags8height = 24; + flags8text = "[8] Float"; + angletext = "Tag"; + } +} + +boxes +{ + color = 7; // Gray + blocking = 2; + title = "Monitors"; + width = 18; + height = 40; + flags1text = "[1] Run Linedef Executor on pop"; + flags4text = "[4] Random (Strong)"; + flags8text = "[8] Random (Weak)"; + + 400 + { + title = "Super Ring (10 Rings)"; + sprite = "TVRIA0"; + } + 401 + { + title = "Pity Shield"; + sprite = "TVPIA0"; + } + 402 + { + title = "Attraction Shield"; + sprite = "TVATA0"; + } + 403 + { + title = "Force Shield"; + sprite = "TVFOA0"; + } + 404 + { + title = "Armageddon Shield"; + sprite = "TVARA0"; + } + 405 + { + title = "Whirlwind Shield"; + sprite = "TVWWA0"; + } + 406 + { + title = "Elemental Shield"; + sprite = "TVELA0"; + } + 407 + { + title = "Super Sneakers"; + sprite = "TVSSA0"; + } + 408 + { + title = "Invincibility"; + sprite = "TVIVA0"; + } + 409 + { + title = "Extra Life"; + sprite = "TV1UA0"; + flags4text = "[4] Random (Strong) / 10k points"; + flags8text = "[8] Random (Weak) / 10k points"; + } + 410 + { + title = "Eggman"; + sprite = "TVEGA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 411 + { + title = "Teleporter"; + sprite = "TVMXA0"; + } + 413 + { + title = "Gravity Boots"; + sprite = "TVGVA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 414 + { + title = "CTF Team Ring Monitor (Red)"; + sprite = "TRRIA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 415 + { + title = "CTF Team Ring Monitor (Blue)"; + sprite = "TBRIA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 416 + { + title = "Recycler"; + sprite = "TVRCA0"; + } + 418 + { + title = "Score (1,000 Points)"; + sprite = "TV1KA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 419 + { + title = "Score (10,000 Points)"; + sprite = "TVTKA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 420 + { + title = "Flame Shield"; + sprite = "TVFLA0"; + } + 421 + { + title = "Water Shield"; + sprite = "TVBBA0"; + } + 422 + { + title = "Lightning Shield"; + sprite = "TVZPA0"; + } +} + +boxes2 +{ + color = 18; // Gold + blocking = 2; + title = "Monitors (Respawning)"; + width = 20; + height = 44; + flags1text = "[1] Run Linedef Executor on pop"; + + 431 + { + title = "Pity Shield (Respawn)"; + sprite = "TVPIB0"; + } + 432 + { + title = "Attraction Shield (Respawn)"; + sprite = "TVATB0"; + } + 433 + { + title = "Force Shield (Respawn)"; + sprite = "TVFOB0"; + } + 434 + { + title = "Armageddon Shield (Respawn)"; + sprite = "TVARB0"; + } + 435 + { + title = "Whirlwind Shield (Respawn)"; + sprite = "TVWWB0"; + } + 436 + { + title = "Elemental Shield (Respawn)"; + sprite = "TVELB0"; + } + 437 + { + title = "Super Sneakers (Respawn)"; + sprite = "TVSSB0"; + } + 438 + { + title = "Invincibility (Respawn)"; + sprite = "TVIVB0"; + } + 440 + { + title = "Eggman (Respawn)"; + sprite = "TVEGB0"; + } + 443 + { + title = "Gravity Boots (Respawn)"; + sprite = "TVGVB0"; + } + 450 + { + title = "Flame Shield (Respawn)"; + sprite = "TVFLB0"; + } + 451 + { + title = "Water Shield (Respawn)"; + sprite = "TVBBB0"; + } + 452 + { + title = "Lightning Shield (Respawn)"; + sprite = "TVZPB0"; + } +} + +generic +{ + color = 11; // Light_Cyan + title = "Generic Items & Hazards"; + + 500 + { + title = "Air Bubble Patch"; + sprite = "BUBLE0"; + width = 8; + height = 16; + flags8text = "[8] No distance check"; + } + 501 + { + title = "Signpost"; + sprite = "SIGND0"; + width = 8; + height = 32; + } + 502 + { + arrow = 1; + title = "Star Post"; + sprite = "STPTA0M0"; + width = 64; + height = 128; + angletext = "Angle/Order"; + } + 520 + { + title = "Bomb Sphere"; + sprite = "SPHRD0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + unflippable = true; + } + 521 + { + title = "Spikeball"; + sprite = "SPIKA0"; + width = 12; + height = 8; + flags8height = 24; + flags8text = "[8] Float"; + } + 522 + { + title = "Wall Spike"; + sprite = "WSPKALAR"; + width = 16; + height = 14; + flags1text = "[1] Start retracted"; + flags4text = "[4] Retractable"; + flags8text = "[8] Intangible"; + parametertext = "Initial delay"; + } + 523 + { + title = "Spike"; + sprite = "USPKA0"; + width = 8; + height = 32; + flags1text = "[1] Start retracted"; + flags4text = "[4] Retractable"; + flags8text = "[8] Intangible"; + angletext = "Retraction interval"; + parametertext = "Initial delay"; + } + 1130 + { + title = "Small Mace"; + sprite = "SMCEA0"; + width = 17; + height = 34; + } + 1131 + { + title = "Big Mace"; + sprite = "BMCEA0"; + width = 34; + height = 68; + } + 1136 + { + title = "Small Fireball"; + sprite = "SFBRA0"; + width = 17; + height = 34; + } + 1137 + { + title = "Large Fireball"; + sprite = "BFBRA0"; + width = 34; + height = 68; + } +} + +springs +{ + color = 12; // Light_Red + title = "Springs and Fans"; + width = 20; + height = 16; + sprite = "RSPRD2"; + + 540 + { + title = "Fan"; + sprite = "FANSA0D0"; + width = 16; + height = 8; + flags4text = "[4] Invisible"; + flags8text = "[8] No distance check"; + angletext = "Lift height"; + } + 541 + { + title = "Gas Jet"; + sprite = "STEMD0"; + flags8text = "[8] No sounds"; + width = 32; + } + 542 + { + title = "Bumper"; + sprite = "BUMPA0"; + width = 32; + height = 64; + angletext = "Strength"; + } + 543 + { + title = "Balloon"; + sprite = "BLONA0"; + width = 32; + height = 64; + flags8text = "[8] Respawn"; + angletext = "Color"; + } + 550 + { + title = "Yellow Spring"; + sprite = "SPRYA0"; + } + 551 + { + title = "Red Spring"; + sprite = "SPRRA0"; + } + 552 + { + title = "Blue Spring"; + sprite = "SPRBA0"; + } + 555 + { + arrow = 1; + title = "Diagonal Yellow Spring"; + sprite = "YSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 556 + { + arrow = 1; + title = "Diagonal Red Spring"; + sprite = "RSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 557 + { + arrow = 1; + title = "Diagonal Blue Spring"; + sprite = "BSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 558 + { + arrow = 1; + title = "Horizontal Yellow Spring"; + sprite = "SSWYD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 559 + { + arrow = 1; + title = "Horizontal Red Spring"; + sprite = "SSWRD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 560 + { + arrow = 1; + title = "Horizontal Blue Spring"; + sprite = "SSWBD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 1134 + { + title = "Yellow Spring Ball"; + sprite = "YSPBA0"; + width = 17; + height = 34; + } + 1135 + { + title = "Red Spring Ball"; + sprite = "RSPBA0"; + width = 17; + height = 34; + } + 544 + { + arrow = 1; + title = "Yellow Boost Panel"; + sprite = "BSTYA0"; + flags8text = "[8] Force spin"; + width = 28; + height = 2; + } + 545 + { + arrow = 1; + title = "Red Boost Panel"; + sprite = "BSTRA0"; + flags8text = "[8] Force spin"; + width = 28; + height = 2; + } +} + +patterns +{ + color = 5; // Magenta + arrow = 1; + title = "Special Placement Patterns"; + width = 16; + height = 384; + sprite = "RINGA0"; + + 600 + { + arrow = 0; + title = "5 Vertical Rings (Yellow Spring)"; + sprite = "RINGA0"; + } + 601 + { + arrow = 0; + title = "5 Vertical Rings (Red Spring)"; + sprite = "RINGA0"; + height = 1024; + } + 602 + { + title = "5 Diagonal Rings (Yellow Spring)"; + sprite = "RINGA0"; + height = 32; + } + 603 + { + title = "10 Diagonal Rings (Red Spring)"; + sprite = "RINGA0"; + height = 32; + } + 604 + { + title = "Circle of Rings"; + sprite = "RINGA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 605 + { + title = "Circle of Rings (Big)"; + sprite = "RINGA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 606 + { + title = "Circle of Blue Spheres"; + sprite = "SPHRA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 607 + { + title = "Circle of Blue Spheres (Big)"; + sprite = "SPHRA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 608 + { + title = "Circle of Rings and Spheres"; + sprite = "SPHRA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 609 + { + title = "Circle of Rings and Spheres (Big)"; + sprite = "SPHRA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } +} + +invisible +{ + color = 15; // White + title = "Misc. Invisible"; + width = 0; + height = 0; + sprite = "UNKNA0"; + sort = 1; + fixedsize = true; + blocking = 0; + + 700 + { + title = "Water Ambience A (Large)"; + sprite = "internal:ambiance"; + } + + 701 + { + title = "Water Ambience B (Large)"; + sprite = "internal:ambiance"; + } + + 702 + { + title = "Water Ambience C (Medium)"; + sprite = "internal:ambiance"; + } + + 703 + { + title = "Water Ambience D (Medium)"; + sprite = "internal:ambiance"; + } + + 704 + { + title = "Water Ambience E (Small)"; + sprite = "internal:ambiance"; + } + + 705 + { + title = "Water Ambience F (Small)"; + sprite = "internal:ambiance"; + } + + 706 + { + title = "Water Ambience G (Extra Large)"; + sprite = "internal:ambiance"; + } + + 707 + { + title = "Water Ambience H (Extra Large)"; + sprite = "internal:ambiance"; + } + + 708 + { + title = "Disco Ambience"; + sprite = "internal:ambiance"; + } + + 709 + { + title = "Volcano Ambience"; + sprite = "internal:ambiance"; + } + + 710 + { + title = "Machine Ambience"; + sprite = "internal:ambiance"; + } + + 750 + { + title = "Slope Vertex"; + sprite = "internal:vertexslope"; + angletext = "Tag"; + } + + 751 + { + arrow = 1; + title = "Teleport Destination"; + sprite = "internal:tele"; + } + + 752 + { + arrow = 1; + title = "Alternate View Point"; + sprite = "internal:view"; + } + + 753 + { + title = "Zoom Tube Waypoint"; + sprite = "internal:zoom"; + angletext = "Order"; + } + + 754 + { + title = "Push Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Push using XYZ"; + sprite = "GWLGA0"; + angletext = "Radius"; + } + 755 + { + title = "Pull Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Pull using XYZ"; + sprite = "GWLRA0"; + angletext = "Radius"; + } + 756 + { + title = "Blast Linedef Executor"; + sprite = "TOADA0"; + width = 32; + height = 16; + } + 757 + { + title = "Fan Particle Generator"; + sprite = "PRTLA0"; + width = 8; + height = 16; + angletext = "Tag"; + } + 758 + { + title = "Object Angle Anchor"; + sprite = "internal:view"; + } + 760 + { + title = "PolyObject Anchor"; + sprite = "internal:polyanchor"; + angletext = "ID"; + } + + 761 + { + title = "PolyObject Spawn Point"; + sprite = "internal:polycenter"; + angletext = "ID"; + } + + 762 + { + title = "PolyObject Spawn Point (Crush)"; + sprite = "internal:polycentercrush"; + angletext = "ID"; + } + 780 + { + title = "Skybox View Point"; + sprite = "internal:skyb"; + flags4text = "[4] In-map centerpoint"; + parametertext = "ID"; + } +} + +greenflower +{ + color = 10; // Green + title = "Greenflower"; + + 800 + { + title = "GFZ Flower"; + sprite = "FWR1A0"; + width = 16; + height = 40; + } + 801 + { + title = "Sunflower"; + sprite = "FWR2A0"; + width = 16; + height = 96; + } + 802 + { + title = "Budding Flower"; + sprite = "FWR3A0"; + width = 8; + height = 32; + } + 803 + { + title = "Blueberry Bush"; + sprite = "BUS3A0"; + width = 16; + height = 32; + } + 804 + { + title = "Berry Bush"; + sprite = "BUS1A0"; + width = 16; + height = 32; + } + 805 + { + title = "Bush"; + sprite = "BUS2A0"; + width = 16; + height = 32; + } + 806 + { + title = "GFZ Tree"; + sprite = "TRE1A0"; + width = 20; + height = 128; + } + 807 + { + title = "GFZ Berry Tree"; + sprite = "TRE1B0"; + width = 20; + height = 128; + } + 808 + { + title = "GFZ Cherry Tree"; + sprite = "TRE1C0"; + width = 20; + height = 128; + } + 809 + { + title = "Checkered Tree"; + sprite = "TRE2A0"; + width = 20; + height = 200; + } + 810 + { + title = "Checkered Tree (Sunset)"; + sprite = "TRE2B0"; + width = 20; + height = 200; + } + 811 + { + title = "Polygon Tree"; + sprite = "TRE4A0"; + width = 20; + height = 200; + } + 812 + { + title = "Bush Tree"; + sprite = "TRE5A0"; + width = 20; + height = 200; + } + 813 + { + title = "Red Bush Tree"; + sprite = "TRE5B0"; + width = 20; + height = 200; + } +} + +technohill +{ + color = 10; // Green + title = "Techno Hill"; + + 900 + { + title = "THZ Steam Flower"; + sprite = "THZPA0"; + width = 8; + height = 32; + } + 901 + { + title = "Alarm"; + sprite = "ALRMA0"; + width = 8; + height = 16; + hangs = 1; + } + 902 + { + title = "THZ Spin Flower (Red)"; + sprite = "FWR5A0"; + width = 16; + height = 64; + } + 903 + { + title = "THZ Spin Flower (Yellow)"; + sprite = "FWR6A0"; + width = 16; + height = 64; + } + 904 + { + arrow = 1; + title = "Whistlebush"; + sprite = "THZTA0"; + width = 16; + height = 64; + } +} + +deepsea +{ + color = 10; // Green + title = "Deep Sea"; + + 1000 + { + arrow = 1; + blocking = 2; + title = "Gargoyle"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1009 + { + arrow = 1; + blocking = 2; + title = "Gargoyle (Big)"; + sprite = "GARGB1"; + width = 32; + height = 80; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1001 + { + title = "Seaweed"; + sprite = "SEWEA0"; + width = 24; + height = 56; + } + 1002 + { + title = "Dripping Water"; + sprite = "DRIPD0"; + width = 8; + height = 16; + hangs = 1; + angletext = "Dripping interval"; + } + 1003 + { + title = "Coral (Green)"; + sprite = "CORLA0"; + width = 29; + height = 40; + } + 1004 + { + title = "Coral (Red)"; + sprite = "CORLB0"; + width = 30; + height = 53; + } + 1005 + { + title = "Coral (Orange)"; + sprite = "CORLC0"; + width = 28; + height = 41; + } + 1006 + { + title = "Blue Crystal"; + sprite = "BCRYA1"; + width = 8; + height = 16; + } + 1007 + { + title = "Kelp"; + sprite = "KELPA0"; + width = 16; + height = 292; + flags4text = "[4] Double size"; + } + 1008 + { + title = "Stalagmite (DSZ1)"; + sprite = "DSTGA0"; + width = 8; + height = 116; + flags4text = "[4] Double size"; + } + 1010 + { + arrow = 1; + title = "Light Beam"; + sprite = "LIBEARAL"; + width = 16; + height = 16; + } + 1011 + { + title = "Stalagmite (DSZ2)"; + sprite = "DSTGA0"; + width = 8; + height = 116; + flags4text = "[4] Double size"; + } + 1012 + { + arrow = 1; + title = "Big Floating Mine"; + width = 28; + height = 56; + sprite = "BMNEA1"; + } + 1013 + { + title = "Animated Kelp"; + sprite = "ALGAA0"; + width = 48; + height = 120; + } + 1014 + { + title = "Large Coral (Brown)"; + sprite = "CORLD0"; + width = 56; + height = 112; + } + 1015 + { + title = "Large Coral (Beige)"; + sprite = "CORLE0"; + width = 56; + height = 112; + } +} + +castleeggman +{ + color = 10; // Green + title = "Castle Eggman"; + + 1100 + { + title = "Chain (Decorative)"; + sprite = "CHANA0"; + width = 4; + height = 128; + hangs = 1; + } + 1101 + { + title = "Torch"; + sprite = "FLAMA0E0"; + width = 8; + height = 32; + flags1text = "[1] Add corona"; + } + 1102 + { + arrow = 1; + blocking = 2; + title = "Eggman Statue"; + sprite = "ESTAA1"; + width = 32; + height = 240; + flags1text = "[1] Solid gold"; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1103 + { + title = "CEZ Flower"; + sprite = "FWR4A0"; + width = 16; + height = 40; + } + 1104 + { + title = "Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1105 + { + title = "Chain with Maces Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1106 + { + title = "Chained Spring Spawnpoint"; + sprite = "YSPBA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Red spring"; + angletext = "Tag"; + } + 1107 + { + title = "Chain Spawnpoint"; + sprite = "BMCHA0"; + width = 17; + height = 34; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1108 + { + arrow = 1; + title = "Hidden Chain Spawnpoint"; + sprite = "internal:chain3"; + width = 17; + height = 34; + flags8text = "[8] Double size"; + } + 1109 + { + title = "Firebar Spawnpoint"; + sprite = "BFBRA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1110 + { + title = "Custom Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + angletext = "Tag"; + } + 1111 + { + arrow = 1; + blocking = 2; + title = "Crawla Statue"; + sprite = "CSTAA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1112 + { + arrow = 1; + blocking = 2; + title = "Lance-a-Bot Statue"; + sprite = "CBBSA1"; + width = 32; + height = 72; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1114 + { + title = "Pine Tree"; + sprite = "PINEA0"; + width = 16; + height = 628; + } + 1115 + { + title = "CEZ Shrub (Small)"; + sprite = "CEZBA0"; + width = 16; + height = 24; + } + 1116 + { + title = "CEZ Shrub (Large)"; + sprite = "CEZBB0"; + width = 32; + height = 48; + } + 1117 + { + arrow = 1; + title = "Pole Banner (Red)"; + sprite = "BANRA0"; + width = 40; + height = 224; + } + 1118 + { + arrow = 1; + title = "Pole Banner (Blue)"; + sprite = "BANRA0"; + width = 40; + height = 224; + } + 1119 + { + title = "Candle"; + sprite = "CNDLA0"; + width = 8; + height = 48; + flags1text = "[1] Add corona"; + } + 1120 + { + title = "Candle Pricket"; + sprite = "CNDLB0"; + width = 8; + height = 176; + flags1text = "[1] Add corona"; + } + 1121 + { + title = "Flame Holder"; + sprite = "FLMHA0"; + width = 24; + height = 80; + flags1text = "[1] Add corona"; + flags4text = "[4] No flame"; + } + 1122 + { + title = "Fire Torch"; + sprite = "CTRCA0"; + width = 16; + height = 80; + } + 1123 + { + title = "Cannonball Launcher"; + sprite = "internal:cannonball"; + width = 8; + height = 16; + } + 1124 + { + blocking = 2; + title = "Cannonball"; + sprite = "CBLLA0"; + width = 20; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1125 + { + title = "Brambles"; + sprite = "CABRALAR"; + width = 48; + height = 32; + } + 1126 + { + title = "Invisible Lockon Object"; + sprite = "LCKNC0"; + width = 16; + height = 32; + } + 1127 + { + title = "Spectator Eggrobo"; + sprite = "EGR1A1"; + width = 20; + height = 72; + } + 1128 + { + arrow = 1; + title = "Waving Flag (Red)"; + sprite = "CFLGA0"; + width = 8; + height = 208; + } + 1129 + { + arrow = 1; + title = "Waving Flag (Blue)"; + sprite = "CFLGA0"; + width = 8; + height = 208; + } +} + +aridcanyon +{ + color = 10; // Green + title = "Arid Canyon"; + + 1200 + { + title = "Tumbleweed (Big)"; + sprite = "BTBLA0"; + width = 24; + height = 48; + flags8text = "[8] Moves perpetually"; + } + 1201 + { + title = "Tumbleweed (Small)"; + sprite = "STBLA0"; + width = 12; + height = 24; + flags8text = "[8] Moves perpetually"; + } + 1202 + { + arrow = 1; + title = "Rock Spawner"; + sprite = "ROIAA0"; + width = 8; + height = 16; + angletext = "Tag"; + } + 1203 + { + title = "Tiny Red Flower Cactus"; + sprite = "CACTA0"; + width = 13; + height = 24; + } + 1204 + { + title = "Small Red Flower Cactus"; + sprite = "CACTB0"; + width = 15; + height = 52; + } + 1205 + { + title = "Tiny Blue Flower Cactus"; + sprite = "CACTC0"; + width = 13; + height = 24; + } + 1206 + { + title = "Small Blue Flower Cactus"; + sprite = "CACTD0"; + width = 15; + height = 52; + } + 1207 + { + title = "Prickly Pear"; + sprite = "CACTE0"; + width = 32; + height = 96; + } + 1208 + { + title = "Barrel Cactus"; + sprite = "CACTF0"; + width = 20; + height = 128; + } + 1209 + { + title = "Tall Barrel Cactus"; + sprite = "CACTG0"; + width = 24; + height = 224; + } + 1210 + { + title = "Armed Cactus"; + sprite = "CACTH0"; + width = 24; + height = 256; + } + 1211 + { + title = "Ball Cactus"; + sprite = "CACTI0"; + width = 48; + height = 96; + } + 1212 + { + title = "Caution Sign"; + sprite = "WWSGAR"; + width = 22; + height = 64; + } + 1213 + { + title = "Cacti Sign"; + sprite = "WWS2AR"; + width = 22; + height = 64; + } + 1214 + { + title = "Sharp Turn Sign"; + sprite = "WWS3ALAR"; + width = 16; + height = 192; + } + 1215 + { + title = "Mine Oil Lamp"; + sprite = "OILLA0"; + width = 22; + height = 64; + hangs = 1; + } + 1216 + { + title = "TNT Barrel"; + sprite = "BARRA1"; + width = 24; + height = 63; + } + 1217 + { + title = "TNT Proximity Shell"; + sprite = "REMTA0"; + width = 64; + height = 40; + } + 1218 + { + title = "Dust Devil"; + sprite = "TAZDCR"; + width = 80; + height = 416; + } + 1219 + { + title = "Minecart Spawner"; + sprite = "MCRTCLFR"; + width = 22; + height = 32; + } + 1220 + { + title = "Minecart Stopper"; + sprite = "MCRTIR"; + width = 32; + height = 32; + } + 1221 + { + title = "Minecart Saloon Door"; + sprite = "SALDARAL"; + width = 96; + height = 160; + flags8text = "[8] Allow non-minecart players"; + } + 1222 + { + title = "Train Cameo Spawner"; + sprite = "TRAEBRBL"; + width = 28; + height = 32; + } + 1223 + { + title = "Train Dust Spawner"; + sprite = "ADSTA0"; + width = 4; + height = 4; + } + 1224 + { + title = "Train Steam Spawner"; + sprite = "STEAA0"; + width = 4; + height = 4; + } + 1229 + { + title = "Minecart Switch Point"; + sprite = "internal:zoom"; + width = 8; + height = 16; + flags8text = "[8] Enable switching"; + } + 1230 + { + title = "Tiny Cactus"; + sprite = "CACTJ0"; + width = 13; + height = 28; + } + 1231 + { + title = "Small Cactus"; + sprite = "CACTK0"; + width = 15; + height = 60; + } +} + +redvolcano +{ + color = 10; // Green + title = "Red Volcano"; + + 1300 + { + arrow = 1; + title = "Flame Jet (Horizontal)"; + sprite = "internal:flameh"; + width = 16; + height = 40; + flags8text = "[8] Waves vertically"; + angletext = "On/Off time"; + parametertext = "Strength"; + } + 1301 + { + title = "Flame Jet (Vertical)"; + sprite = "internal:flamev"; + width = 16; + height = 40; + flags8text = "[8] Shoot downwards"; + angletext = "On/Off time"; + parametertext = "Strength"; + } + 1302 + { + title = "Spinning Flame Jet (Counter-Clockwise)"; + sprite = "internal:flame2"; + width = 16; + height = 24; + } + 1303 + { + title = "Spinning Flame Jet (Clockwise)"; + sprite = "internal:flame1"; + width = 16; + height = 24; + } + 1304 + { + title = "Lavafall"; + sprite = "LFALF0"; + width = 30; + height = 32; + angletext = "Initial delay"; + flags8text = "[8] Double size"; + } + 1305 + { + title = "Rollout Rock"; + sprite = "PUMIA1A5"; + width = 30; + height = 60; + flags8text = "[8] Non-buoyant"; + } + 1306 + { + title = "Big Fern"; + sprite = "JPLAB0"; + width = 32; + height = 48; + } + 1307 + { + title = "Jungle Palm"; + sprite = "JPLAC0"; + width = 32; + height = 48; + } + 1308 + { + title = "Torch Flower"; + sprite = "TFLOA0"; + width = 14; + height = 110; + } + 1309 + { + title = "RVZ1 Wall Vine (Long)"; + sprite = "WVINALAR"; + width = 1; + height = 288; + } + 1310 + { + title = "RVZ1 Wall Vine (Short)"; + sprite = "WVINBLBR"; + width = 1; + height = 288; + } +} + +botanicserenity +{ + color = 10; // Green + title = "Botanic Serenity"; + width = 16; + height = 32; + sprite = "BSZ1A0"; + 1400 + { + title = "Tall Flower (Red)"; + sprite = "BSZ1A0"; + } + 1401 + { + title = "Tall Flower (Purple)"; + sprite = "BSZ1B0"; + } + 1402 + { + title = "Tall Flower (Blue)"; + sprite = "BSZ1C0"; + } + 1403 + { + title = "Tall Flower (Cyan)"; + sprite = "BSZ1D0"; + } + 1404 + { + title = "Tall Flower (Yellow)"; + sprite = "BSZ1E0"; + } + 1405 + { + title = "Tall Flower (Orange)"; + sprite = "BSZ1F0"; + } + 1410 + { + title = "Medium Flower (Red)"; + sprite = "BSZ2A0"; + } + 1411 + { + title = "Medium Flower (Purple)"; + sprite = "BSZ2B0"; + } + 1412 + { + title = "Medium Flower (Blue)"; + sprite = "BSZ2C0"; + } + 1413 + { + title = "Medium Flower (Cyan)"; + sprite = "BSZ2D0"; + } + 1414 + { + title = "Medium Flower (Yellow)"; + sprite = "BSZ2E0"; + } + 1415 + { + title = "Medium Flower (Orange)"; + sprite = "BSZ2F0"; + } + 1420 + { + title = "Short Flower (Red)"; + sprite = "BSZ3A0"; + } + 1421 + { + title = "Short Flower (Purple)"; + sprite = "BSZ3B0"; + } + 1422 + { + title = "Short Flower (Blue)"; + sprite = "BSZ3C0"; + } + 1423 + { + title = "Short Flower (Cyan)"; + sprite = "BSZ3D0"; + } + 1424 + { + title = "Short Flower (Yellow)"; + sprite = "BSZ3E0"; + } + 1425 + { + title = "Short Flower (Orange)"; + sprite = "BSZ3F0"; + } + 1430 + { + title = "Tulip (Red)"; + sprite = "BST1A0"; + } + 1431 + { + title = "Tulip (Purple)"; + sprite = "BST2A0"; + } + 1432 + { + title = "Tulip (Blue)"; + sprite = "BST3A0"; + } + 1433 + { + title = "Tulip (Cyan)"; + sprite = "BST4A0"; + } + 1434 + { + title = "Tulip (Yellow)"; + sprite = "BST5A0"; + } + 1435 + { + title = "Tulip (Orange)"; + sprite = "BST6A0"; + } + 1440 + { + title = "Cluster (Red)"; + sprite = "BSZ5A0"; + } + 1441 + { + title = "Cluster (Purple)"; + sprite = "BSZ5B0"; + } + 1442 + { + title = "Cluster (Blue)"; + sprite = "BSZ5C0"; + } + 1443 + { + title = "Cluster (Cyan)"; + sprite = "BSZ5D0"; + } + 1444 + { + title = "Cluster (Yellow)"; + sprite = "BSZ5E0"; + } + 1445 + { + title = "Cluster (Orange)"; + sprite = "BSZ5F0"; + } + 1450 + { + title = "Bush (Red)"; + sprite = "BSZ6A0"; + } + 1451 + { + title = "Bush (Purple)"; + sprite = "BSZ6B0"; + } + 1452 + { + title = "Bush (Blue)"; + sprite = "BSZ6C0"; + } + 1453 + { + title = "Bush (Cyan)"; + sprite = "BSZ6D0"; + } + 1454 + { + title = "Bush (Yellow)"; + sprite = "BSZ6E0"; + } + 1455 + { + title = "Bush (Orange)"; + sprite = "BSZ6F0"; + } + 1460 + { + title = "Vine (Red)"; + sprite = "BSZ7A0"; + } + 1461 + { + title = "Vine (Purple)"; + sprite = "BSZ7B0"; + } + 1462 + { + title = "Vine (Blue)"; + sprite = "BSZ7C0"; + } + 1463 + { + title = "Vine (Cyan)"; + sprite = "BSZ7D0"; + } + 1464 + { + title = "Vine (Yellow)"; + sprite = "BSZ7E0"; + } + 1465 + { + title = "Vine (Orange)"; + sprite = "BSZ7F0"; + } + 1470 + { + title = "BSZ Shrub"; + sprite = "BSZ8A0"; + } + 1471 + { + title = "BSZ Clover"; + sprite = "BSZ8B0"; + } + 1473 + { + title = "Palm Tree (Big)"; + width = 16; + height = 160; + sprite = "BSZ8D0"; + } + 1475 + { + title = "Palm Tree (Small)"; + width = 16; + height = 80; + sprite = "BSZ8F0"; + } +} + +azuretemple +{ + color = 10; // Green + title = "Azure Temple"; + + 1500 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1501 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Up)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1502 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Down)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1503 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Long)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1504 + { + title = "ATZ Target"; + sprite = "RCRYB0"; + width = 24; + height = 32; + } + 1505 + { + title = "Green Flame"; + sprite = "CFLMA0E0"; + width = 8; + height = 32; + } + 1506 + { + arrow = 1; + blocking = 2; + title = "Blue Gargoyle"; + sprite = "BGARD1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } +} + +dreamhill +{ + color = 10; // Green + title = "Dream Hill"; + + 1600 + { + title = "Spring Tree"; + sprite = "TRE6A0"; + width = 16; + height = 32; + } + 1601 + { + title = "Shleep"; + sprite = "SHLPA0"; + width = 24; + height = 32; + } + 1602 + { + title = "Pian"; + sprite = "NTPNALAR"; + width = 16; + height = 32; + } +} + +nightstrk +{ + color = 13; // Pink + title = "NiGHTS Track"; + width = 8; + height = 4096; + sprite = "UNKNA0"; + + 1700 + { + title = "Axis"; + sprite = "internal:axis1"; + circle = 1; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + angletext = "Radius/Direction"; + parametertext = "Mare"; + } + 1701 + { + title = "Axis Transfer"; + sprite = "internal:axis2"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1702 + { + title = "Axis Transfer Line"; + sprite = "internal:axis3"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1710 + { + title = "Ideya Capture"; + sprite = "CAPSA0"; + width = 72; + height = 144; + angletext = "Rings"; + parametertext = "Mare"; + } +} + +nights +{ + color = 13; // Pink + title = "NiGHTS Items"; + width = 16; + height = 32; + + 1703 + { + title = "Ideya Drone"; + sprite = "NDRNA1"; + width = 16; + height = 56; + flags1text = "[1] Align player to middle"; + flags4text = "[4] Align player to top"; + flags8text = "[8] Die upon time up"; + angletext = "Time limit"; + parametertext = "Height"; + } + 1704 + { + arrow = 1; + title = "NiGHTS Bumper"; + sprite = "NBMPG3G7"; + width = 32; + height = 64; + unflippable = true; + flagsvaluetext = "Pitch"; + angletext = "Yaw"; + } + 1705 + { + arrow = 1; + title = "Hoop (Generic)"; + sprite = "HOOPA0"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + flagsvaluetext = "Height"; + angletext = "Pitch/Yaw"; + } + 1706 + { + title = "Blue Sphere"; + sprite = "SPHRA0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + unflippable = true; + } + 1707 + { + title = "Super Paraloop"; + sprite = "NPRUA0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1708 + { + title = "Drill Refill"; + sprite = "NPRUB0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1709 + { + title = "Nightopian Helper"; + sprite = "NPRUC0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1711 + { + title = "Extra Time"; + sprite = "NPRUD0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1712 + { + title = "Link Freeze"; + sprite = "NPRUE0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1713 + { + arrow = 1; + title = "Hoop (Customizable)"; + flags1text = "[1] Radius +16"; + flags2text = "[2] Radius +32"; + flags4text = "[4] Radius +64"; + flags8text = "[8] Radius +128"; + sprite = "HOOPA0"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + } + 1714 + { + title = "Ideya Anchor Point"; + sprite = "internal:axis1"; + width = 8; + height = 16; + parametertext = "Ideya"; + } +} + +mario +{ + color = 6; // Brown + title = "Mario"; + + 1800 + { + title = "Coin"; + sprite = "COINA0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + } + 1801 + { + arrow = 1; + title = "Goomba"; + sprite = "GOOMA0"; + width = 24; + height = 32; + } + 1802 + { + arrow = 1; + title = "Goomba (Blue)"; + sprite = "BGOMA0"; + width = 24; + height = 32; + } + 1803 + { + title = "Fire Flower"; + sprite = "FFWRB0"; + width = 16; + height = 32; + } + 1804 + { + title = "Koopa Shell"; + sprite = "SHLLA1"; + width = 16; + height = 20; + } + 1805 + { + title = "Puma (Jumping Fireball)"; + sprite = "PUMAA0"; + width = 8; + height = 16; + angletext = "Jump strength"; + } + 1806 + { + title = "King Bowser"; + sprite = "KOOPA0"; + width = 16; + height = 48; + } + 1807 + { + title = "Axe"; + sprite = "MAXEA0"; + width = 8; + height = 16; + } + 1808 + { + title = "Bush (Short)"; + sprite = "MUS1A0"; + width = 16; + height = 32; + } + 1809 + { + title = "Bush (Tall)"; + sprite = "MUS2A0"; + width = 16; + height = 32; + } + 1810 + { + title = "Toad"; + sprite = "TOADA0"; + width = 8; + height = 32; + } +} + +christmasdisco +{ + color = 10; // Green + title = "Christmas & Disco"; + + 1850 + { + title = "Christmas Pole"; + sprite = "XMS1A0"; + width = 16; + height = 40; + } + 1851 + { + title = "Candy Cane"; + sprite = "XMS2A0"; + width = 8; + height = 32; + } + 1852 + { + blocking = 2; + title = "Snowman"; + sprite = "XMS3A0"; + width = 16; + height = 64; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1853 + { + blocking = 2; + title = "Snowman (With Hat)"; + sprite = "XMS3B0"; + width = 16; + height = 80; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1854 + { + title = "Lamp Post"; + sprite = "XMS4A0"; + width = 8; + height = 120; + } + 1855 + { + title = "Lamp Post (Snow)"; + sprite = "XMS4B0"; + width = 8; + height = 120; + } + 1856 + { + title = "Hanging Star"; + sprite = "XMS5A0"; + width = 4; + height = 80; + hangs = 1; + } + 1857 + { + title = "Berry Bush (Snow)"; + sprite = "BUS1B0"; + width = 16; + height = 32; + } + 1858 + { + title = "Bush (Snow)"; + sprite = "BUS2B0"; + width = 16; + height = 32; + } + 1859 + { + title = "Blueberry Bush (Snow)"; + sprite = "BUS3B0"; + width = 16; + height = 32; + } + 1875 + { + title = "Disco Ball"; + sprite = "DBALA0"; + width = 16; + height = 54; + hangs = 1; + } + 1876 + { + arrow = 1; + blocking = 2; + title = "Eggman Disco Statue"; + sprite = "ESTAB1"; + width = 20; + height = 96; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } +} + +stalagmites +{ + color = 10; // Green + title = "Stalagmites"; + width = 16; + height = 40; + + 1900 + { + title = "Brown Stalagmite (Tall)"; + sprite = "STLGA0"; + width = 16; + height = 40; + } + 1901 + { + title = "Brown Stalagmite"; + sprite = "STLGB0"; + width = 16; + height = 40; + } + 1902 + { + title = "Orange Stalagmite (Tall)"; + sprite = "STLGC0"; + width = 16; + height = 40; + } + 1903 + { + title = "Orange Stalagmite"; + sprite = "STLGD0"; + width = 16; + height = 40; + } + 1904 + { + title = "Red Stalagmite (Tall)"; + sprite = "STLGE0"; + width = 16; + height = 40; + } + 1905 + { + title = "Red Stalagmite"; + sprite = "STLGF0"; + width = 16; + height = 40; + } + 1906 + { + title = "Gray Stalagmite (Tall)"; + sprite = "STLGG0"; + width = 24; + height = 96; + } + 1907 + { + title = "Gray Stalagmite"; + sprite = "STLGH0"; + width = 16; + height = 40; + } + 1908 + { + title = "Blue Stalagmite (Tall)"; + sprite = "STLGI0"; + width = 16; + height = 40; + } + 1909 + { + title = "Blue Stalagmite"; + sprite = "STLGJ0"; + width = 16; + height = 40; + } +} + +hauntedheights +{ + color = 10; // Green + title = "Haunted Heights"; + + 2000 + { + title = "Smashing Spikeball"; + sprite = "FMCEA0"; + width = 18; + height = 28; + angletext = "Initial delay"; + } + 2001 + { + title = "HHZ Grass"; + sprite = "HHZMA0"; + width = 16; + height = 40; + } + 2002 + { + title = "HHZ Tentacle 1"; + sprite = "HHZMB0"; + width = 16; + height = 40; + } + 2003 + { + title = "HHZ Tentacle 2"; + sprite = "HHZMC0"; + width = 16; + height = 40; + } + 2004 + { + title = "HHZ Stalagmite (Tall)"; + sprite = "HHZME0"; + width = 16; + height = 40; + } + 2005 + { + title = "HHZ Stalagmite (Short)"; + sprite = "HHZMF0"; + width = 16; + height = 40; + } + 2006 + { + title = "Jack-o'-lantern 1"; + sprite = "PUMKA0"; + width = 16; + height = 40; + flags1text = "Don't flicker"; + } + 2007 + { + title = "Jack-o'-lantern 2"; + sprite = "PUMKB0"; + width = 16; + height = 40; + flags1text = "Don't flicker"; + } + 2008 + { + title = "Jack-o'-lantern 3"; + sprite = "PUMKC0"; + width = 16; + height = 40; + flags1text = "Don't flicker"; + } + 2009 + { + title = "Purple Mushroom"; + sprite = "SHRMD0"; + width = 16; + height = 48; + } + 2010 + { + title = "HHZ Tree"; + sprite = "HHPLC0"; + width = 12; + height = 40; + } +} + +frozenhillside +{ + color = 10; // Green + title = "Frozen Hillside"; + + 2100 + { + title = "Ice Shard (Small)"; + sprite = "FHZIA0"; + width = 8; + height = 32; + } + 2101 + { + title = "Ice Shard (Large)"; + sprite = "FHZIB0"; + width = 8; + height = 32; + } + 2102 + { + title = "Crystal Tree (Aqua)"; + sprite = "TRE3A0"; + width = 20; + height = 200; + } + 2103 + { + title = "Crystal Tree (Pink)"; + sprite = "TRE3B0"; + width = 20; + height = 200; + } + 2104 + { + title = "Amy Cameo"; + sprite = "ROSYA1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + } + 2105 + { + title = "Mistletoe"; + sprite = "XMS6A0"; + width = 52; + height = 106; + } +} + +flickies +{ + color = 10; // Green + title = "Flickies"; + width = 8; + height = 20; + flags1text = "[1] Move aimlessly"; + flags4text = "[4] No movement"; + flags8text = "[8] Hop"; + angletext = "Radius"; + + 2200 + { + title = "Bluebird"; + sprite = "FL01A1"; + } + 2201 + { + title = "Rabbit"; + sprite = "FL02A1"; + } + 2202 + { + title = "Chicken"; + sprite = "FL03A1"; + } + 2203 + { + title = "Seal"; + sprite = "FL04A1"; + } + 2204 + { + title = "Pig"; + sprite = "FL05A1"; + } + 2205 + { + title = "Chipmunk"; + sprite = "FL06A1"; + } + 2206 + { + title = "Penguin"; + sprite = "FL07A1"; + } + 2207 + { + title = "Fish"; + sprite = "FL08A1"; + parametertext = "Color"; + } + 2208 + { + title = "Ram"; + sprite = "FL09A1"; + } + 2209 + { + title = "Puffin"; + sprite = "FL10A1"; + } + 2210 + { + title = "Cow"; + sprite = "FL11A1"; + } + 2211 + { + title = "Rat"; + sprite = "FL12A1"; + } + 2212 + { + title = "Bear"; + sprite = "FL13A1"; + } + 2213 + { + title = "Dove"; + sprite = "FL14A1"; + } + 2214 + { + title = "Cat"; + sprite = "FL15A1"; + } + 2215 + { + title = "Canary"; + sprite = "FL16A1"; + } + 2216 + { + title = "Spider"; + sprite = "FS01A1"; + } + 2217 + { + title = "Bat"; + sprite = "FS02A0"; + } +} \ No newline at end of file diff --git a/extras/conf/SRB2_22Doom.cfg b/extras/conf/SRB2_22Doom.cfg new file mode 100644 index 000000000..65e49d387 --- /dev/null +++ b/extras/conf/SRB2_22Doom.cfg @@ -0,0 +1,38 @@ +/************************************************************************\ + Zone Builder Game Configuration for Sonic Robo Blast 2 Version 2.2 +\************************************************************************/ + +// This is required to prevent accidental use of a different configuration +type = "Doom Builder 2 Game Configuration"; + +// This is the title to show for this game +game = "Sonic Robo Blast 2 - 2.2 (Doom format)"; + +// This is the simplified game engine/sourceport name +engine = "zdoom"; + +// Settings common to all games and all map formats +include("Includes\\SRB222_common.cfg", "common"); + +// Settings common to Doom map format +include("Includes\\SRB222_common.cfg", "mapformat_doom"); + +include("Includes\\Game_SRB222.cfg"); + +// Script lumps detection +scriptlumpnames +{ + include("Includes\\SRB222_misc.cfg", "scriptlumpnames"); +} + +// THING TYPES +thingtypes +{ + include("Includes\\SRB222_things.cfg"); +} + +//Default things filters +thingsfilters +{ + include("Includes\\SRB222_misc.cfg", "thingsfilters"); +} \ No newline at end of file diff --git a/extras/conf/SRB2_22UDMF.cfg b/extras/conf/SRB2_22UDMF.cfg new file mode 100644 index 000000000..52104ed09 --- /dev/null +++ b/extras/conf/SRB2_22UDMF.cfg @@ -0,0 +1,47 @@ +/************************************************************************\ + Zone Builder Game Configuration for Sonic Robo Blast 2 Version 2.2 +\************************************************************************/ + +// This is required to prevent accidental use of a different configuration +type = "Doom Builder 2 Game Configuration"; + +// This is the title to show for this game +game = "Sonic Robo Blast 2 - 2.2 (UDMF)"; + +// This is the simplified game engine/sourceport name +engine = "zdoom"; + +// Settings common to all games and all map formats +include("Includes\\SRB222_common.cfg", "common"); + +// Settings common to Doom map format +include("Includes\\SRB222_common.cfg", "mapformat_udmf"); + +include("Includes\\Game_SRB222.cfg"); + +// Script lumps detection +scriptlumpnames +{ + include("Includes\\SRB222_misc.cfg", "scriptlumpnames"); +} + +// THING TYPES +thingtypes +{ + include("Includes\\SRB222_things.cfg"); +} + +//Default things filters +thingsfilters +{ + include("Includes\\SRB222_misc.cfg", "thingsfilters"); +} + +// ENUMERATIONS +// Each engine has its own additional thing types +// These are enumerated lists for linedef types and UDMF fields. +enums +{ + // Basic game enums + include("Includes\\SRB222_misc.cfg", "enums"); +} \ No newline at end of file From 2cf94ea6aec88827d77e106aa53303276f2398a8 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Tue, 24 Dec 2019 12:02:40 +0100 Subject: [PATCH 142/312] Delete the original configuration file. --- extras/conf/SRB2-22.cfg | 6521 --------------------------------------- 1 file changed, 6521 deletions(-) delete mode 100644 extras/conf/SRB2-22.cfg diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg deleted file mode 100644 index 5bc48211c..000000000 --- a/extras/conf/SRB2-22.cfg +++ /dev/null @@ -1,6521 +0,0 @@ -/*********************************************************\ - Zone Builder Game Configuration - For Sonic Robo Blast 2 Version 2.2 - Contributors (alphabetical): - * Foxboy - * FuriousFox - * JJames19119 - * Kalaron - * Kristos - * MascaraSnake - * mazmazz - * Morpheus - * Neo Chaotikal - * Nev3r - * Oogaland - * Rob - * Shadow Hog - * Spherallic - * SRB2-Playah - * SSNTails - * SteelT - * ST218 - * toaster - * Viola -\*********************************************************/ - -// This is required to prevent accidental use of a different configuration -type = "Doom Builder 2 Game Configuration"; - -// This is the title to show for this game -game = "Sonic Robo Blast 2 - 2.2"; - -//GZDB specific. Don't try to load lumps that don't exist. -basegame = 0; - -// This is the simplified game engine/sourceport name -engine = "zdoom"; - -// When this is set to true, sectors with the same tag will light up when a line is highlighted -linetagindicatesectors = true; - -// The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder -formatinterface = "SRB2MapSetIO"; - -//Sky textures for vanilla maps -defaultskytextures -{ - SKY1 = "MAP01,MAP02,MAP03,MAP33,MAP50,MAP60,MAPF0,MAPM0"; - SKY2 = "MAPM7,MAPMB"; - SKY4 = "MAP04,MAP06,MAP61,MAPF6,MAPM1"; - SKY6 = "MAP05,MAP51,MAPMA"; - SKY7 = "MAPM2,MAPM5"; - SKY8 = "MAP07,MAP08,MAP09,MAP52,MAP62,MAPF1"; - SKY10 = "MAP10,MAP12,MAP53,MAP63,MAPM3"; - SKY11 = "MAP11,MAPF7"; - SKY13 = "MAP13,MAP64"; - SKY14 = "MAP14"; - SKY15 = "MAP15,MAP54"; - SKY17 = "MAP70"; - SKY20 = "MAP32,MAP55,MAP65,MAPF2,MAPF5"; - SKY21 = "MAPM4"; - SKY22 = "MAP22,MAP23,MAP25,MAP26,MAP27,MAP56,MAP66,MAPF4,MAPM6"; - SKY30 = "MAP30"; - SKY31 = "MAP31"; - SKY35 = "MAP42"; - SKY40 = "MAP41,MAP71,MAPM9"; - SKY55 = "MAPF3,MAPM8"; - SKY68 = "MAPF8"; - SKY99 = "MAP57,MAPZ0"; - SKY159 = "MAP16"; - SKY172 = "MAP40"; - SKY300 = "MAP72"; - SKY301 = "MAP73"; -} - -// Default lump name for new map -defaultlumpname = "MAP01"; - -// Default testing parameters -testparameters = "-file \"%AP\" \"%F\" -warp %L"; -testshortpaths = true; - -// Default nodebuilder configurations -defaultsavecompiler = "zennode_normal"; -defaulttestcompiler = "zennode_fast"; - -// Skill levels -skills -{ - 1 = "Normal"; -} - -// Skins -skins -{ - Sonic; - Tails; - Knuckles; - Amy; - Fang; - Metalsonic; -} - -// Gametypes -gametypes -{ - -1 = "Single Player"; - 0 = "Co-op"; - 1 = "Competition"; - 2 = "Race"; - 3 = "Match"; - 4 = "Team Match"; - 5 = "Tag"; - 6 = "Hide and Seek"; - 7 = "CTF"; -} - -// Special linedefs -soundlinedefflag = 64; // See linedefflags -singlesidedflag = 1; // See linedefflags -doublesidedflag = 4; // See linedefflags -impassableflag = 1; -upperunpeggedflag = 8; -lowerunpeggedflag = 16; -repeatmidtextureflag = 1024; -pegmidtextureflag = 256; - -// Generalized actions -generalizedlinedefs = false; -generalizedsectors = true; - -// Texture loading options -defaultwalltexture = "GFZROCK"; -defaultfloortexture = "GFZFLR01"; -defaultceilingtexture = "F_SKY1"; -mixtexturesflats = true; -defaulttexturescale = 1.0f; -defaultflatscale = 1.0f; - -// Thing number for start position in 3D Mode -start3dmode = 3328; - - - - -/* -TEXTURES AND FLAT SOURCES -This tells Doom Builder where to find the information for textures -and flats in the IWAD file, Addition WAD file and Map WAD file. - -Start and end lumps must be given in a structure (of which the -key name doesnt matter) and any textures or flats in between them -are loaded in either the textures category or flats category. - -For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. -Kalaron: and now TX_START -*/ - -// Texture sources -textures -{ - zdoom1 - { - start = "TX_START"; - end = "TX_END"; - } -} - -// Patch sources -patches -{ - standard1 - { - start = "P_START"; - end = "P_END"; - } - - standard2 - { - start = "PP_START"; - end = "PP_END"; - } -} - -// Sprite sources -sprites -{ - standard1 - { - start = "S_START"; - end = "S_END"; - } - - standard2 - { - start = "SS_START"; - end = "SS_END"; - } -} - -// Flat sources -flats -{ - standard1 - { - start = "F_START"; - end = "F_END"; - } - - standard2 - { - start = "FF_START"; - end = "FF_END"; - } - - standard3 - { - start = "FF_START"; - end = "F_END"; - } - - standard4 - { - start = "F_START"; - end = "FF_END"; - } -} - - -/* -GAME DETECT PATTERN -Used to guess the game for which a WAD file is made. - -1 = One of these lumps must exist -2 = None of these lumps must exist -3 = All of these lumps must exist -*/ - -gamedetect -{ - EXTENDED = 2; - - - BEHAVIOR = 2; - - E#M# = 2; - - MAP?? = 1; -} - - -/* -MAP LUMP NAMES -Map lumps are loaded with the map as long as they are right after each other. When the editor -meets a lump which is not defined in this list it will ignore the map if not satisfied. -The order of items defines the order in which lumps will be written to WAD file on save. -To indicate the map header lump, use ~MAP - -Legenda: -required = Lump is required to exist. -blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use) -nodebuild = The nodebuilder generates this lump. -allowempty = The nodebuilder is allowed to leave this lump empty. -script = This lump is a text-based script. Specify the filename of the script configuration to use. -*/ - -maplumpnames -{ - ~MAP - { - required = true; - blindcopy = true; - nodebuild = false; - } - - THINGS - { - required = true; - nodebuild = true; - allowempty = true; - } - - LINEDEFS - { - required = true; - nodebuild = true; - allowempty = false; - } - - SIDEDEFS - { - required = true; - nodebuild = true; - allowempty = false; - } - - VERTEXES - { - required = true; - nodebuild = true; - allowempty = false; - } - - SEGS - { - required = false; - nodebuild = true; - allowempty = false; - } - - SSECTORS - { - required = false; - nodebuild = true; - allowempty = false; - } - - NODES - { - required = false; - nodebuild = true; - allowempty = false; - } - - SECTORS - { - required = true; - nodebuild = true; - allowempty = false; - } - - REJECT - { - required = false; - nodebuild = true; - allowempty = false; - } - - BLOCKMAP - { - required = false; - nodebuild = true; - allowempty = true; - } -} - -scriptlumpnames -{ - MAINCFG - { - script = "SOC.cfg"; - } - - OBJCTCFG - { - script = "SOC.cfg"; - } - - SOC_ - { - script = "SOC.cfg"; - isprefix = true; - } - - LUA_ - { - script = "Lua.cfg"; - isprefix = true; - } -} - -// DEFAULT SECTOR BRIGHTNESS LEVELS -sectorbrightness -{ - 255; - 248; - 240; - 232; - 224; - 216; - 208; - 200; - 192; - 184; - 176; - 168; - 160; - 152; - 144; - 136; - 128; - 120; - 112; - 104; - 96; - 88; - 80; - 72; - 64; - 56; - 48; - 40; - 32; - 24; - 16; - 8; - 0; -} - -// SECTOR TYPES----------------------------------------------------------------- -sectortypes -{ - 0 = "Normal"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Tilt)"; - 7 = "Death Pit (No Camera Tilt)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (Anywhere in Sector)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy FOF"; - 16 = "Trigger Line Ex. (Pushable Objects)"; - 32 = "Trigger Line Ex. (Anywhere, All Players)"; - 48 = "Trigger Line Ex. (Floor Touch, All Players)"; - 64 = "Trigger Line Ex. (Anywhere in Sector)"; - 80 = "Trigger Line Ex. (Floor Touch)"; - 96 = "Trigger Line Ex. (Emerald Check)"; - 112 = "Trigger Line Ex. (NiGHTS Mare)"; - 128 = "Check for Linedef Executor on FOFs"; - 144 = "Egg Capsule"; - 160 = "Special Stage Time/Rings Parameters"; - 176 = "Custom Global Gravity"; - 512 = "Wind/Current"; - 1024 = "Conveyor Belt"; - 1280 = "Speed Pad"; - 4096 = "Star Post Activator"; - 8192 = "Exit/Special Stage Pit/Return Flag"; - 12288 = "CTF Red Team Base"; - 16384 = "CTF Blue Team Base"; - 20480 = "Fan Sector"; - 24576 = "Super Sonic Transform"; - 28672 = "Force Spin"; - 32768 = "Zoom Tube Start"; - 36864 = "Zoom Tube End"; - 40960 = "Circuit Finish Line"; - 45056 = "Rope Hang"; - 49152 = "Intangible to the Camera"; -} - - -// GENERALISED SECTOR TYPES----------------------------------------------------------------- -gen_sectortypes -{ - first - { - 0 = "Normal"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Tilt)"; - 7 = "Death Pit (No Camera Tilt)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (Anywhere in Sector)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy FOF"; - } - - second - { - 0 = "Normal"; - 16 = "Trigger Line Ex. (Pushable Objects)"; - 32 = "Trigger Line Ex. (Anywhere, All Players)"; - 48 = "Trigger Line Ex. (Floor Touch, All Players)"; - 64 = "Trigger Line Ex. (Anywhere in Sector)"; - 80 = "Trigger Line Ex. (Floor Touch)"; - 96 = "Trigger Line Ex. (Emerald Check)"; - 112 = "Trigger Line Ex. (NiGHTS Mare)"; - 128 = "Check for Linedef Executor on FOFs"; - 144 = "Egg Capsule"; - 160 = "Special Stage Time/Rings Parameters"; - 176 = "Custom Global Gravity"; - } - - third - { - 0 = "Normal"; - 512 = "Wind/Current"; - 1024 = "Conveyor Belt"; - 1280 = "Speed Pad"; - } - - fourth - { - 0 = "Normal"; - 4096 = "Star Post Activator"; - 8192 = "Exit/Special Stage Pit/Return Flag"; - 12288 = "CTF Red Team Base"; - 16384 = "CTF Blue Team Base"; - 20480 = "Fan Sector"; - 24576 = "Super Sonic Transform"; - 28672 = "Force Spin"; - 32768 = "Zoom Tube Start"; - 36864 = "Zoom Tube End"; - 40960 = "Circuit Finish Line"; - 45056 = "Rope Hang"; - 49152 = "Intangible to the Camera"; - } -} - -// LINEDEF FLAGS -linedefflags -{ - 1 = "[0] Impassable"; - 2 = "[1] Block Enemies"; - 4 = "[2] Double-Sided"; - 8 = "[3] Upper Unpegged"; - 16 = "[4] Lower Unpegged"; - 32 = "[5] Slope Skew (E1)"; - 64 = "[6] Not Climbable"; - 128 = "[7] No Midtexture Skew (E2)"; - 256 = "[8] Peg Midtexture (E3)"; - 512 = "[9] Solid Midtexture (E4)"; - 1024 = "[10] Repeat Midtexture (E5)"; - 2048 = "[11] Netgame Only"; - 4096 = "[12] No Netgame"; - 8192 = "[13] Effect 6"; - 16384 = "[14] Bouncy Wall"; - 32768 = "[15] Transfer Line"; -} - -// Linedef flags UDMF translation table -// This is needed for copy/paste and prefabs to work properly -// When the UDMF field name is prefixed with ! it is inverted -linedefflagstranslation -{ - 1 = "blocking"; - 2 = "blockmonsters"; - 4 = "twosided"; - 8 = "dontpegtop"; - 16 = "dontpegbottom"; - 32 = "secret"; - 64 = "blocksound"; - 128 = "dontdraw"; - 256 = "mapped"; -} - -// LINEDEF ACTIVATIONS -linedefactivations -{ -} - -// LINEDEF TYPES -linedeftypes -{ - misc - { - title = "Miscellaneous"; - - 0 - { - title = "None"; - prefix = "(0)"; - } - - 1 - { - title = "Per-Sector Gravity"; - prefix = "(1)"; - flags64text = "[6] Flip in reverse gravity"; - } - - 5 - { - title = "Camera Scanner"; - prefix = "(5)"; - } - - 7 - { - title = "Sector Flat Alignment"; - prefix = "(7)"; - flags2048text = "[11] Don't align floor"; - flags4096text = "[12] Don't align ceiling"; - flags8192text = "[13] Use texture offsets"; - } - - 10 - { - title = "Culling Plane"; - prefix = "(10)"; - flags64text = "[6] Cull only while in sector"; - } - - 13 - { - title = "Heat Wave Effect"; - prefix = "(13)"; - } - - 40 - { - title = "Visual Portal Between Tagged Linedefs"; - prefix = "(40)"; - } - - 41 - { - title = "Horizon Effect"; - prefix = "(41)"; - } - - 50 - { - title = "Instantly Lower Floor on Level Load"; - prefix = "(50)"; - } - - 51 - { - title = "Instantly Raise Ceiling on Level Load"; - prefix = "(51)"; - } - - 63 - { - title = "Fake Floor/Ceiling Planes"; - prefix = "(63)"; - } - - 540 - { - title = "Floor Friction"; - prefix = "(540)"; - } - } - - parameters - { - title = "Parameters"; - - 2 - { - title = "Custom Exit"; - prefix = "(2)"; - flags2text = "[1] Check emeralds"; - flags64text = "[6] Skip score tally"; - } - - 3 - { - title = "Zoom Tube Parameters"; - prefix = "(3)"; - flags512text = "[9] Ignore player direction"; - } - - 4 - { - title = "Speed Pad Parameters"; - prefix = "(4)"; - flags512text = "[9] No teleport to center"; - flags1024text = "[10] Force spinning frames"; - } - - 8 - { - title = "Special Sector Properties"; - prefix = "(8)"; - flags32text = "[5] Invert precipitation"; - flags64text = "[6] Touch only ceiling"; - flags128text = "[7] Allow opposite gravity"; - flags256text = "[8] Touch sector edge"; - flags512text = "[9] Touch floor or ceiling"; - } - - 9 - { - title = "Chain Parameters"; - prefix = "(9)"; - flags32text = "[5] Swing instead of spin"; - flags64text = "[6] Player-turnable chain"; - flags128text = "[7] Make chain from maces"; - flags256text = "[8] Spawn mace at origin"; - flags512text = "[9] Don't clip inside ground"; - flags1024text = "[10] No distance check"; - } - - 11 - { - title = "Rope Hang Parameters"; - prefix = "(11)"; - flags32text = "[5] Don't loop"; - flags64text = "[6] Static"; - } - - 12 - { - title = "Rock Spawner Parameters"; - prefix = "(12)"; - flags64text = "[6] Randomize speed"; - } - - 14 - { - title = "Bustable Block Parameters"; - prefix = "(14)"; - flags32text = "[5] Particles launch from center"; - } - - 15 - { - title = "Fan Particle Spawner Parameters"; - prefix = "(15)"; - } - - 16 - { - title = "Minecart Parameters"; - prefix = "(16)"; - } - - 64 - { - title = "Continuously Appearing/Disappearing FOF"; - prefix = "(64)"; - flags2text = "[1] Use control sector tag"; - flags64text = "[6] No sound effect"; - } - - 65 - { - title = "Bridge Thinker "; - prefix = "(65)"; - } - } - - polyobject - { - title = "PolyObject"; - - 20 - { - title = "First Line"; - prefix = "(20)"; - } - - 21 - { - title = "Explicitly Include Line "; - prefix = "(21)"; - } - - 22 - { - title = "Parameters"; - prefix = "(22)"; - flags64text = "[6] Trigger linedef executor"; - flags128text = "[7] Intangible"; - flags256text = "[8] Stopped by pushables"; - flags512text = "[9] Render flats"; - } - - 30 - { - title = "Waving Flag"; - prefix = "(30)"; - } - - 31 - { - title = "Displacement by Front Sector"; - prefix = "(31)"; - } - - 32 - { - title = "Angular Displacement by Front Sector"; - prefix = "(32)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't turn players"; - flags512text = "[9] Turn all objects"; - } - } - - planemove - { - title = "Plane Movement"; - - 52 - { - title = "Continuously Falling Sector"; - prefix = "(52)"; - flags64text = "[6] Continuously rising"; - } - - 53 - { - title = "Continuous Floor/Ceiling Mover"; - prefix = "(53)"; - } - - 54 - { - title = "Continuous Floor Mover"; - prefix = "(54)"; - } - - 55 - { - title = "Continuous Ceiling Mover"; - prefix = "(55)"; - } - - 56 - { - title = "Continuous Two-Speed Floor/Ceiling Mover"; - prefix = "(56)"; - } - - 57 - { - title = "Continuous Two-Speed Floor Mover"; - prefix = "(57)"; - } - - 58 - { - title = "Continuous Two-Speed Ceiling Mover"; - prefix = "(58)"; - } - - 59 - { - title = "Activate Moving Platform"; - prefix = "(59)"; - flags64text = "[6] Move upwards at start"; - } - - 60 - { - title = "Activate Moving Platform (Adjustable Speed)"; - prefix = "(60)"; - flags64text = "[6] Move upwards at start"; - } - - 61 - { - title = "Crusher (Ceiling to Floor)"; - prefix = "(61)"; - flags512text = "[9] Double, constant speed"; - } - - 62 - { - title = "Crusher (Floor to Ceiling)"; - prefix = "(62)"; - flags512text = "[9] Double, constant speed"; - } - - 66 - { - title = "Move Floor by Displacement"; - prefix = "(66)"; - flags64text = "[6] Inverse movement"; - } - - 67 - { - title = "Move Ceiling by Displacement"; - prefix = "(67)"; - flags64text = "[6] Inverse movement"; - } - - 68 - { - title = "Move Floor and Ceiling by Displacement"; - prefix = "(68)"; - flags64text = "[6] Inverse movement"; - } - } - - fofsolid - { - title = "FOF (solid)"; - - 100 - { - title = "Solid, Opaque"; - prefix = "(100)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 101 - { - title = "Solid, Opaque, No Shadow"; - prefix = "(101)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1DF"; - } - - 102 - { - title = "Solid, Translucent"; - prefix = "(102)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Render insides"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "195F"; - flags643dfloorflagsadd = "7C80"; - } - - 103 - { - title = "Solid, Sides Only"; - prefix = "(103)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1CF"; - } - - 104 - { - title = "Solid, No Sides"; - prefix = "(104)"; - flags32text = "[5] Only block player"; - flags64text = "[6] Cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1D7"; - flags643dfloorflagsremove = "40"; - } - - 105 - { - title = "Solid, Invisible"; - prefix = "(105)"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "47"; - } - - 140 - { - title = "Intangible from Bottom, Opaque"; - prefix = "(140)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "200841F"; - flags643dfloorflagsadd = "40"; - } - - 141 - { - title = "Intangible from Bottom, Translucent"; - prefix = "(141)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Render insides/block non-plr"; - 3dfloor = true; - 3dfloorflags = "200191F"; - flags1283dfloorflagsadd = "7C80"; - flags643dfloorflagsadd = "40"; - } - - 142 - { - title = "Intangible from Bottom, Translucent, No Sides"; - prefix = "(142)"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Render insides/block non-plr"; - 3dfloor = true; - 3dfloorflags = "2001917"; - flags1283dfloorflagsadd = "7C80"; - flags643dfloorflagsadd = "40"; - } - - 143 - { - title = "Intangible from Top, Opaque"; - prefix = "(143)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "400841F"; - flags643dfloorflagsadd = "40"; - } - - 144 - { - title = "Intangible from Top, Translucent"; - prefix = "(144)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Render insides/block non-plr"; - 3dfloor = true; - 3dfloorflags = "400191F"; - flags1283dfloorflagsadd = "7C80"; - flags643dfloorflagsadd = "40"; - } - - 145 - { - title = "Intangible from Top, Translucent, No Sides"; - prefix = "(145)"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Render insides/block non-plr"; - 3dfloor = true; - 3dfloorflags = "4001917"; - flags1283dfloorflagsadd = "7C80"; - flags643dfloorflagsadd = "40"; - } - - 146 - { - title = "Only Tangible from Sides"; - prefix = "(146)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "600800F"; - } - } - - fofintangible - { - title = "FOF (intangible)"; - - 120 - { - title = "Water, Opaque"; - prefix = "(120)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "8F39"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 121 - { - title = "Water, Translucent"; - prefix = "(121)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "9F39"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 122 - { - title = "Water, Opaque, No Sides"; - prefix = "(122)"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "F31"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 123 - { - title = "Water, Translucent, No Sides"; - prefix = "(123)"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "1F31"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 124 - { - title = "Goo Water, Translucent"; - prefix = "(124)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "209F39"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 125 - { - title = "Goo Water, Translucent, No Sides"; - prefix = "(125)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "201F31"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 220 - { - title = "Intangible, Opaque"; - prefix = "(220)"; - flags8text = "[3] Slope skew sides"; - 3dfloor = true; - 3dfloorflags = "8F19"; - } - - 221 - { - title = "Intangible, Translucent"; - prefix = "(221)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Cast shadow"; - 3dfloor = true; - 3dfloorflags = "1B59"; - flags643dfloorflagsremove = "40"; - } - - 222 - { - title = "Intangible, Sides Only"; - prefix = "(222)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Cast shadow"; - 3dfloor = true; - 3dfloorflags = "8249"; - flags643dfloorflagsremove = "240"; - } - - 223 - { - title = "Intangible, Invisible"; - prefix = "(223)"; - 3dfloor = true; - 3dfloorflags = "41"; - } - } - - fofmoving - { - title = "FOF (moving)"; - - 150 - { - title = "Air Bobbing"; - prefix = "(150)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 151 - { - title = "Air Bobbing (Adjustable)"; - prefix = "(151)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 152 - { - title = "Reverse Air Bobbing (Adjustable)"; - prefix = "(152)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 160 - { - title = "Floating, Bobbing"; - prefix = "(160)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "4019F"; - } - - 190 - { - title = "Rising Platform, Solid, Opaque"; - prefix = "(190)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 191 - { - title = "Rising Platform, Solid, Opaque, No Shadow"; - prefix = "(191)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1DF"; - } - - 192 - { - title = "Rising Platform, Solid, Translucent"; - prefix = "(192)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "195F"; - } - - 193 - { - title = "Rising Platform, Solid, Invisible"; - prefix = "(193)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "47"; - } - - 194 - { - title = "Rising Platform, Intangible from Bottom, Opaque"; - prefix = "(194)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash, no shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "200841F"; - flags643dfloorflagsadd = "40"; - } - - 195 - { - title = "Rising Platform, Intangible from Bottom, Translucent"; - prefix = "(195)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash, no shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "2009D1F"; - flags643dfloorflagsadd = "40"; - } - } - - fofcrumbling - { - title = "FOF (crumbling)"; - - 170 - { - title = "Crumbling, Respawn"; - prefix = "(170)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "10019F"; - } - - 171 - { - title = "Crumbling, No Respawn"; - prefix = "(171)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "80019F"; - } - - 172 - { - title = "Crumbling, Respawn, Intangible from Bottom"; - prefix = "(172)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "210841F"; - flags643dfloorflagsadd = "40"; - } - - 173 - { - title = "Crumbling, No Respawn, Intangible from Bottom"; - prefix = "(173)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "218841F"; - flags643dfloorflagsadd = "40"; - } - - 174 - { - title = "Crumbling, Respawn, Int. from Bottom, Translucent"; - prefix = "(174)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "210959F"; - flags643dfloorflagsadd = "40"; - } - - 175 - { - title = "Crumbling, No Respawn, Int. from Bottom, Translucent"; - prefix = "(175)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "218959F"; - flags643dfloorflagsadd = "40"; - } - - 176 - { - title = "Crumbling, Respawn, Floating, Bobbing"; - prefix = "(176)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "14019F"; - } - - 177 - { - title = "Crumbling, No Respawn, Floating, Bobbing"; - prefix = "(177)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1C019F"; - } - - 178 - { - title = "Crumbling, Respawn, Floating"; - prefix = "(178)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "14019F"; - } - - 179 - { - title = "Crumbling, No Respawn, Floating"; - prefix = "(179)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1C019F"; - } - - 180 - { - title = "Crumbling, Respawn, Air Bobbing"; - prefix = "(180)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "10019F"; - } - } - - fofspecial - { - title = "FOF (special)"; - - 200 - { - title = "Light Block"; - prefix = "(200)"; - 3dfloor = true; - 3dfloorflags = "20201"; - } - - 201 - { - title = "Half Light Block"; - prefix = "(201)"; - 3dfloor = true; - 3dfloorflags = "201"; - } - - 202 - { - title = "Fog Block"; - prefix = "(202)"; - 3dfloor = true; - 3dfloorflags = "3EF19"; - } - - 250 - { - title = "Mario Block"; - prefix = "(250)"; - flags32text = "[5] Invisible block"; - flags64text = "[6] Brick block"; - 3dfloor = true; - 3dfloorflags = "40019F"; - } - - 251 - { - title = "Thwomp Block"; - prefix = "(251)"; - flags512text = "[9] Custom crushing sound"; - flags1024text = "[10] Custom speed"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 252 - { - title = "Shatter Block"; - prefix = "(252)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Shatter only from below"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorflags = "8800019"; - flags643dfloorflagsadd = "200006"; - } - - 253 - { - title = "Shatter Block, Translucent"; - prefix = "(253)"; - flags8text = "[3] Slope skew sides"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorflags = "8801019"; - } - - 254 - { - title = "Bustable Block"; - prefix = "(254)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Strong characters only"; - flags128text = "[7] Only block non-players"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorflags = "80001F"; - flags643dfloorflagsadd = "20000000"; - } - - 255 - { - title = "Spin-Bustable Block"; - prefix = "(255)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorflags = "1080001F"; - } - - 256 - { - title = "Spin-Bustable Block, Translucent"; - prefix = "(256)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorflags = "1080101F"; - } - - 257 - { - title = "Quicksand"; - prefix = "(257)"; - flags8text = "[3] Slope skew sides"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "1008219"; - flags10243dfloorflagsadd = "40000000"; - } - - 258 - { - title = "Laser"; - prefix = "(258)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Don't damage bosses"; - 3dfloor = true; - 3dfloorflags = "959"; - } - - 259 - { - title = "Custom FOF"; - prefix = "(259)"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorcustom = true; - } - } - - linedeftrigger - { - title = "Linedef Executor Trigger"; - - 300 - { - title = "Continuous"; - prefix = "(300)"; - } - - 301 - { - title = "Each Time"; - prefix = "(301)"; - flags16384text = "[14] Also trigger on exit"; - } - - 302 - { - title = "Once"; - prefix = "(302)"; - } - - 303 - { - title = "Ring Count - Continuous"; - prefix = "(303)"; - flags2text = "[1] Rings greater or equal"; - flags64text = "[6] Rings less or equal"; - flags512text = "[9] Consider all players"; - } - - 304 - { - title = "Ring Count - Once"; - prefix = "(304)"; - flags2text = "[1] Rings greater or equal"; - flags64text = "[6] Rings less or equal"; - flags512text = "[9] Consider all players"; - } - - 305 - { - title = "Character Ability - Continuous"; - prefix = "(305)"; - } - - 306 - { - title = "Character Ability - Each Time"; - prefix = "(306)"; - flags16384text = "[14] Also trigger on exit"; - } - - 307 - { - title = "Character Ability - Once"; - prefix = "(307)"; - } - - 308 - { - title = "Race Only - Once"; - prefix = "(308)"; - } - - 309 - { - title = "CTF Red Team - Continuous"; - prefix = "(309)"; - } - - 310 - { - title = "CTF Red Team - Each Time"; - prefix = "(310)"; - flags16384text = "[14] Also trigger on exit"; - } - - 311 - { - title = "CTF Blue Team - Continuous"; - prefix = "(311)"; - } - - 312 - { - title = "CTF Blue Team - Each Time"; - prefix = "(312)"; - flags16384text = "[14] Also trigger on exit"; - } - - 313 - { - title = "No More Enemies - Once"; - prefix = "(313)"; - } - - 314 - { - title = "Number of Pushables - Continuous"; - prefix = "(314)"; - flags64text = "[6] Number greater or equal"; - flags512text = "[9] Number less"; - } - - 315 - { - title = "Number of Pushables - Once"; - prefix = "(315)"; - flags64text = "[6] Number greater or equal"; - flags512text = "[9] Number less"; - } - - 317 - { - title = "Condition Set Trigger - Continuous"; - prefix = "(317)"; - } - - 318 - { - title = "Condition Set Trigger - Once"; - prefix = "(318)"; - } - - 319 - { - title = "Unlockable - Continuous"; - prefix = "(319)"; - } - - 320 - { - title = "Unlockable - Once"; - prefix = "(320)"; - } - - 321 - { - title = "Trigger After X Calls - Continuous"; - prefix = "(321)"; - flags64text = "[6] Trigger more than once"; - - } - - 322 - { - title = "Trigger After X Calls - Each Time"; - prefix = "(322)"; - flags64text = "[6] Trigger more than once"; - } - - 323 - { - title = "NiGHTSerize - Each Time"; - prefix = "(323)"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run only if player is NiGHTS"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags16384text = "[14] Run if no more mares"; - flags32768text = "[15] Run if player is not NiGHTS"; - } - - 324 - { - title = "NiGHTSerize - Once"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run only if player is NiGHTS"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags16384text = "[14] Run if no more mares"; - flags32768text = "[15] Run if player is not NiGHTS"; - prefix = "(324)"; - } - - 325 - { - title = "De-NiGHTSerize - Each Time"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run if anyone is NiGHTS"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags32768text = "[15] Run if no one is NiGHTS"; - prefix = "(325)"; - } - - 326 - { - title = "De-NiGHTSerize - Once"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run if anyone is NiGHTS"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags32768text = "[15] Run if no one is NiGHTS"; - prefix = "(326)"; - } - - 327 - { - title = "NiGHTS Lap - Each Time"; - flags2text = "[1] Mare >= Front X Offset"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - prefix = "(327)"; - } - - 328 - { - title = "NiGHTS Lap - Once"; - flags2text = "[1] Mare >= Front X Offset"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - prefix = "(328)"; - } - - 329 - { - title = "Ideya Capture Touch - Each Time"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run regardless of spheres"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags16384text = "[14] Only if not enough spheres"; - flags32768text = "[15] Run when entering Capture"; - prefix = "(329)"; - } - - 330 - { - title = "Ideya Capture Touch - Once"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run regardless of spheres"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags16384text = "[14] Only if not enough spheres"; - flags32768text = "[15] Run when entering Capture"; - prefix = "(330)"; - } - - 331 - { - title = "Player Skin - Continuous"; - flags64text = "[6] Disable for this skin"; - prefix = "(331)"; - } - - 332 - { - title = "Player Skin - Each Time"; - flags64text = "[6] Disable for this skin"; - prefix = "(332)"; - } - - 333 - { - title = "Player Skin - Once"; - flags64text = "[6] Disable for this skin"; - prefix = "(333)"; - } - - 399 - { - title = "Level Load"; - prefix = "(399)"; - } - } - - linedefexecsector - { - title = "Linedef Executor (sector)"; - - 400 - { - title = "Set Tagged Sector's Floor Height/Texture"; - prefix = "(400)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Keep floor flat"; - } - - 401 - { - title = "Set Tagged Sector's Ceiling Height/Texture"; - prefix = "(401)"; - flags8text = "[3] Set delay by backside sector"; - } - - 402 - { - title = "Set Tagged Sector's Light Level"; - prefix = "(402)"; - flags8text = "[3] Set delay by backside sector"; - } - - 409 - { - title = "Change Tagged Sector's Tag"; - prefix = "(409)"; - flags8text = "[3] Set delay by backside sector"; - } - - 410 - { - title = "Change Front Sector's Tag"; - prefix = "(410)"; - flags8text = "[3] Set delay by backside sector"; - } - - 416 - { - title = "Start Adjustable Flickering Light"; - prefix = "(416)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Second level from back"; - } - - 417 - { - title = "Start Adjustable Pulsating Light"; - prefix = "(417)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Second level from back"; - } - - 418 - { - title = "Start Adjustable Blinking Light (unsynchronized)"; - prefix = "(418)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Second level from back"; - } - - 419 - { - title = "Start Adjustable Blinking Light (synchronized)"; - prefix = "(419)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Second level from back"; - } - - 420 - { - title = "Fade Light Level"; - prefix = "(420)"; - flags8text = "[3] Set delay by backside sector"; - flags16text = "[4] Set params by X/Y offsets"; - flags512text = "[9] Speed = Tic Duration"; - flags1024text = "[10] Override existing fade"; - } - - 421 - { - title = "Stop Lighting Effect"; - prefix = "(421)"; - flags8text = "[3] Set delay by backside sector"; - } - - 435 - { - title = "Change Plane Scroller Direction"; - prefix = "(435)"; - flags8text = "[3] Set delay by backside sector"; - } - } - - linedefexecplane - { - title = "Linedef Executor (plane movement)"; - - 403 - { - title = "Move Tagged Sector's Floor"; - prefix = "(403)"; - flags2text = "[1] Trigger linedef executor"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Change floor flat"; - } - - 404 - { - title = "Move Tagged Sector's Ceiling"; - prefix = "(404)"; - flags2text = "[1] Trigger linedef executor"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Change ceiling flat"; - } - - 405 - { - title = "Move Floor According to Front Texture Offsets"; - prefix = "(405)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Move instantly"; - } - - 407 - { - title = "Move Ceiling According to Front Texture Offsets"; - prefix = "(407)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Move instantly"; - } - - 411 - { - title = "Stop Plane Movement"; - prefix = "(411)"; - flags8text = "[3] Set delay by backside sector"; - } - - 428 - { - title = "Start Platform Movement"; - prefix = "(428)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Move upwards at start"; - } - - 429 - { - title = "Crush Ceiling Once"; - prefix = "(429)"; - flags8text = "[3] Set delay by backside sector"; - flags512text = "[9] Double, constant speed"; - } - - 430 - { - title = "Crush Floor Once"; - prefix = "(430)"; - flags8text = "[3] Set delay by backside sector"; - } - - 431 - { - title = "Crush Floor and Ceiling Once"; - prefix = "(431)"; - flags8text = "[3] Set delay by backside sector"; - flags512text = "[9] Double, constant speed"; - } - } - - linedefexecplayer - { - title = "Linedef Executor (player/object)"; - - 412 - { - title = "Teleporter"; - prefix = "(412)"; - flags2text = "[1] Silent"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Retain angle"; - flags256text = "[8] Relative, silent"; - flags512text = "[9] Retain momentum"; - } - - 425 - { - title = "Change Object State"; - prefix = "(425)"; - flags8text = "[3] Set delay by backside sector"; - } - - 426 - { - title = "Stop Object"; - prefix = "(426)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Teleport to sector center"; - } - - 427 - { - title = "Award Score"; - prefix = "(427)"; - flags8text = "[3] Set delay by backside sector"; - } - - 432 - { - title = "Enable/Disable 2D Mode"; - prefix = "(432)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Return to 3D"; - } - - 433 - { - title = "Enable/Disable Gravity Flip"; - prefix = "(433)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Return to normal"; - } - - 434 - { - title = "Award Power-Up"; - prefix = "(434)"; - flags2text = "[1] Use back upper texture"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] No time limit"; - } - - 437 - { - title = "Disable Player Control"; - prefix = "(437)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Allow jumping"; - } - - 438 - { - title = "Change Object Size"; - prefix = "(438)"; - flags8text = "[3] Set delay by backside sector"; - } - - 442 - { - title = "Change Object Type State"; - prefix = "(442)"; - flags8text = "[3] Set delay by backside sector"; - } - - 457 - { - title = "Track Object's Angle"; - prefix = "(457)"; - flags8text = "[3] Set delay by backside sector"; - flags128text = "[7] Don't stop after first fail"; - } - - 458 - { - title = "Stop Tracking Object's Angle"; - prefix = "(458)"; - flags8text = "[3] Set delay by backside sector"; - } - - 460 - { - title = "Award Rings"; - prefix = "(460)"; - } - - 461 - { - title = "Spawn Object"; - prefix = "(461)"; - flags64text = "[6] Spawn inside a range"; - } - - 462 - { - title = "Stop Timer/Exit Stage in Record Attack"; - prefix = "(462)"; - } - } - - linedefexecmisc - { - title = "Linedef Executor (misc.)"; - - 413 - { - title = "Change Music"; - prefix = "(413)"; - flags2text = "[1] Keep after death"; - flags8text = "[3] Set delay by backside sector"; - flags32text = "[5] Seek to current song position"; - flags64text = "[6] For everyone"; - flags128text = "[7] Fade to custom volume"; - flags512text = "[9] Don't loop"; - flags16384text = "[14] Force music reload"; - } - - 414 - { - title = "Play Sound Effect"; - prefix = "(414)"; - flags2text = "[1] From calling sector"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] From nowhere for triggerer"; - flags512text = "[9] For everyone"; - flags1024text = "[10] From tagged sectors"; - } - - 415 - { - title = "Run Script"; - prefix = "(415)"; - flags8text = "[3] Set delay by backside sector"; - } - - 422 - { - title = "Switch to Cut-Away View"; - prefix = "(422)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Adjust pitch"; - } - - 423 - { - title = "Change Sky"; - prefix = "(423)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] For everyone"; - } - - 424 - { - title = "Change Weather"; - prefix = "(424)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] For everyone"; - } - - 436 - { - title = "Shatter FOF"; - prefix = "(436)"; - flags8text = "[3] Set delay by backside sector"; - } - - 439 - { - title = "Change Tagged Linedef's Textures"; - prefix = "(439)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Only existing"; - } - - 440 - { - title = "Start Metal Sonic Race"; - prefix = "(440)"; - flags8text = "[3] Set delay by backside sector"; - } - - 441 - { - title = "Condition Set Trigger"; - prefix = "(441)"; - flags8text = "[3] Set delay by backside sector"; - } - - 443 - { - title = "Call Lua Function"; - prefix = "(443)"; - flags8text = "[3] Set delay by backside sector"; - } - - 444 - { - title = "Earthquake"; - prefix = "(444)"; - flags8text = "[3] Set delay by backside sector"; - } - - - 445 - { - title = "Make FOF Disappear/Reappear"; - prefix = "(445)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Reappear"; - } - - 446 - { - title = "Make FOF Crumble"; - prefix = "(446)"; - flags2text = "[1] Flags determine respawn"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't respawn"; - } - - 447 - { - title = "Change Tagged Sector's Colormap"; - prefix = "(447)"; - flags8text = "[3] Set delay by backside sector"; - flags16text = "[4] Front X/Y = Alpha"; - flags32text = "[5] Subtract Red value"; - flags64text = "[6] Subtract Green value"; - flags128text = "[7] Subtract Blue value"; - flags256text = "[8] Calc relative values"; - flags32768text = "[15] Use back side colormap"; - } - - 448 - { - title = "Change Skybox"; - prefix = "(448)"; - flags2text = "[1] Change centerpoint"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] For everyone"; - flags512text = "[9] Don't change viewpoint"; - } - - 450 - { - title = "Execute Linedef Executor (specific tag)"; - prefix = "(450)"; - flags8text = "[3] Set delay by backside sector"; - } - - 451 - { - title = "Execute Linedef Executor (random tag in range)"; - prefix = "(451)"; - flags8text = "[3] Set delay by backside sector"; - } - - 452 - { - title = "Set FOF Translucency"; - prefix = "(452)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Do not handle FF_TRANS"; - flags256text = "[8] Set relative to current val"; - } - - 453 - { - title = "Fade FOF"; - prefix = "(453)"; - flags2text = "[1] Do not handle FF_EXISTS"; - flags8text = "[3] Set delay by backside sector"; - flags32text = "[5] No collision during fade"; - flags64text = "[6] Do not handle FF_TRANS"; - flags128text = "[7] Do not handle lighting"; - flags256text = "[8] Set relative to current val"; - flags512text = "[9] Speed = Tic Duration"; - flags1024text = "[10] Override existing fade"; - flags16384text = "[14] Do not handle collision"; - flags32768text = "[15] Use exact alpha in OGL"; - } - - 454 - { - title = "Stop Fading FOF"; - prefix = "(454)"; - flags2text = "[1] Do not finalize collision"; - flags8text = "[3] Set delay by backside sector"; - } - - 455 - { - title = "Fade Tagged Sector's Colormap"; - prefix = "(455)"; - flags8text = "[3] Set delay by backside sector"; - flags16text = "[4] Front X/Y = Alpha"; - flags32text = "[5] Subtract Red value"; - flags64text = "[6] Subtract Green value"; - flags128text = "[7] Subtract Blue value"; - flags256text = "[8] Calc relative values"; - flags512text = "[9] Speed = Tic Duration"; - flags1024text = "[10] Override existing fade"; - flags16384text = "[14] Fade from invisible black"; - flags32768text = "[15] Use back side colormap"; - } - - 456 - { - title = "Stop Fading Tagged Sector's Colormap"; - prefix = "(456)"; - flags8text = "[3] Set delay by backside sector"; - } - - 459 - { - title = "Control Text Prompt"; - prefix = "(459)"; - flags2text = "[1] Close text prompt"; - flags8text = "[3] Set delay by backside sector"; - flags32text = "[5] Run executor tag on close"; - flags64text = "[6] For everyone"; - flags128text = "[7] Do not block controls"; - flags256text = "[8] Do not freeze time"; - flags32768text = "[15] Find prompt by name"; - } - } - - linedefexecpoly - { - title = "Linedef Executor (polyobject)"; - - 480 - { - title = "Door Slide"; - prefix = "(480)"; - flags8text = "[3] Set delay by backside sector"; - } - - 481 - { - title = "Door Swing"; - prefix = "(481)"; - flags8text = "[3] Set delay by backside sector"; - } - - 482 - { - title = "Move"; - prefix = "(482)"; - flags8text = "[3] Set delay by backside sector"; - } - - 483 - { - title = "Move, Override"; - prefix = "(483)"; - flags8text = "[3] Set delay by backside sector"; - } - - 484 - { - title = "Rotate Right"; - prefix = "(484)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't turn players"; - flags512text = "[9] Turn all objects"; - } - - 485 - { - title = "Rotate Right, Override"; - prefix = "(485)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't turn players"; - flags512text = "[9] Turn all objects"; - } - - 486 - { - title = "Rotate Left"; - prefix = "(486)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't turn players"; - flags512text = "[9] Turn all objects"; - } - - 487 - { - title = "Rotate Left, Override"; - prefix = "(487)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't turn players"; - flags512text = "[9] Turn all objects"; - } - - 488 - { - title = "Move by Waypoints"; - prefix = "(488)"; - flags8text = "[3] Set delay by backside sector"; - flags32text = "[5] Reverse order"; - flags128text = "[7] There and back"; - flags256text = "[8] Return when done"; - flags512text = "[9] Loop movement"; - } - - 489 - { - title = "Turn Invisible, Intangible"; - prefix = "(489)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Only invisible"; - } - - 490 - { - title = "Turn Visible, Tangible"; - prefix = "(490)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Only visible"; - } - - 491 - { - title = "Set Translucency"; - prefix = "(491)"; - flags8text = "[3] Set delay by backside sector"; - flags16text = "[4] Set raw alpha by Front X"; - flags256text = "[8] Calc relative values"; - } - - 492 - { - title = "Fade Translucency"; - prefix = "(492)"; - flags8text = "[3] Set delay by backside sector"; - flags16text = "[4] Set raw alpha by Front X"; - flags32text = "[5] No collision during fade"; - flags256text = "[8] Calc relative values"; - flags512text = "[9] Speed = Tic Duration"; - flags1024text = "[10] Override existing fade"; - flags16384text = "[14] Do not handle collision"; - } - } - - wallscroll - { - title = "Wall Scrolling"; - - 500 - { - title = "Scroll Wall Front Side Left"; - prefix = "(500)"; - } - - 501 - { - title = "Scroll Wall Front Side Right"; - prefix = "(501)"; - } - - 502 - { - title = "Scroll Wall According to Linedef"; - prefix = "(502)"; - } - - 503 - { - title = "Scroll Wall According to Linedef (Accelerative)"; - prefix = "(503)"; - } - - 504 - { - title = "Scroll Wall According to Linedef (Displacement)"; - prefix = "(504)"; - } - - 505 - { - title = "Scroll Texture by Front Side Offsets"; - prefix = "(505)"; - } - - 506 - { - title = "Scroll Texture by Back Side Offsets"; - prefix = "(506)"; - } - } - - planescroll - { - title = "Plane Scrolling"; - - 510 - { - title = "Scroll Floor Texture"; - prefix = "(510)"; - } - - 511 - { - title = "Scroll Floor Texture (Accelerative)"; - prefix = "(511)"; - } - - 512 - { - title = "Scroll Floor Texture (Displacement)"; - prefix = "(512)"; - } - - 513 - { - title = "Scroll Ceiling Texture"; - prefix = "(513)"; - } - - 514 - { - title = "Scroll Ceiling Texture (Accelerative)"; - prefix = "(514)"; - } - - 515 - { - title = "Scroll Ceiling Texture (Displacement)"; - prefix = "(515)"; - } - - 520 - { - title = "Carry Objects on Floor"; - prefix = "(520)"; - } - - 521 - { - title = "Carry Objects on Floor (Accelerative)"; - prefix = "(521)"; - flags64text = "[6] Even across edges"; - } - - 522 - { - title = "Carry Objects on Floor (Displacement)"; - prefix = "(522)"; - } - - 523 - { - title = "Carry Objects on Ceiling"; - prefix = "(523)"; - flags64text = "[6] Even across edges"; - } - - 524 - { - title = "Carry Objects on Ceiling (Accelerative)"; - prefix = "(524)"; - } - - 525 - { - title = "Carry Objects on Ceiling (Displacement)"; - prefix = "(525)"; - } - - 530 - { - title = "Scroll Floor Texture and Carry Objects"; - prefix = "(530)"; - flags64text = "[6] Even across edges"; - } - - 531 - { - title = "Scroll Floor Texture and Carry Objects (Accelerative)"; - prefix = "(531)"; - } - - 532 - { - title = "Scroll Floor Texture and Carry Objects (Displacement)"; - prefix = "(532)"; - } - - 533 - { - title = "Scroll Ceiling Texture and Carry Objects"; - prefix = "(533)"; - flags64text = "[6] Even across edges"; - } - - 534 - { - title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; - prefix = "(534)"; - } - - 535 - { - title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; - prefix = "(535)"; - } - } - - pusher - { - title = "Pusher"; - - 541 - { - title = "Wind"; - prefix = "(541)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 542 - { - title = "Upwards Wind"; - prefix = "(542)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 543 - { - title = "Downwards Wind"; - prefix = "(543)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 544 - { - title = "Current"; - prefix = "(544)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 545 - { - title = "Upwards Current"; - prefix = "(545)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 546 - { - title = "Downwards Current"; - prefix = "(546)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 547 - { - title = "Push/Pull"; - prefix = "(547)"; - } - } - - light - { - title = "Lighting"; - - 600 - { - title = "Floor Lighting"; - prefix = "(600)"; - } - - 601 - { - title = "Ceiling Lighting"; - prefix = "(601)"; - } - - 602 - { - title = "Adjustable Pulsating Light"; - prefix = "(602)"; - } - - 603 - { - title = "Adjustable Flickering Light"; - prefix = "(603)"; - } - - 604 - { - title = "Adjustable Blinking Light (unsynchronized)"; - prefix = "(604)"; - } - - 605 - { - title = "Adjustable Blinking Light (synchronized)"; - prefix = "(605)"; - } - - 606 - { - title = "Colormap"; - prefix = "(606)"; - } - } - - slope - { - title = "Slope"; - - 700 - { - title = "Slope Frontside Floor"; - prefix = "(700)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 1; - } - - 701 - { - title = "Slope Frontside Ceiling"; - prefix = "(701)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 2; - } - - 702 - { - title = "Slope Frontside Floor and Ceiling"; - prefix = "(702)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 3; - } - - 703 - { - title = "Slope Frontside Floor and Backside Ceiling"; - prefix = "(703)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 9; - } - - 704 - { - title = "Slope Frontside Floor by 3 Tagged Vertex Things"; - prefix = "(704)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - flags8192text = "[13] Use tag and offsets"; - slope = "vertex"; - slopeargs = 0; - } - - 705 - { - title = "Slope Frontside Ceiling by 3 Tagged Vertex Things"; - prefix = "(705)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - flags8192text = "[13] Use tag and offsets"; - slope = "vertex"; - slopeargs = 1; - } - - 710 - { - title = "Slope Backside Floor"; - prefix = "(710)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 4; - } - - 711 - { - title = "Slope Backside Ceiling"; - prefix = "(711)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 8; - } - - 712 - { - title = "Slope Backside Floor and Ceiling"; - prefix = "(712)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 12; - } - - 713 - { - title = "Slope Backside Floor and Frontside Ceiling"; - prefix = "(713)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 6; - } - - 714 - { - title = "Slope Backside Floor by 3 Tagged Vertex Things"; - prefix = "(714)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - flags8192text = "[13] Use tag and offsets"; - slope = "vertex"; - slopeargs = 2; - } - - 715 - { - title = "Slope Backside Ceiling by 3 Tagged Vertex Things"; - prefix = "(715)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - flags8192text = "[13] Use tag and offsets"; - slope = "vertex"; - slopeargs = 3; - } - - 720 - { - title = "Copy Frontside Floor Slope from Line Tag"; - prefix = "(720)"; - slope = "copy"; - slopeargs = 1; - } - - 721 - { - title = "Copy Frontside Ceiling Slope from Line Tag"; - prefix = "(721)"; - slope = "copy"; - slopeargs = 2; - } - - 722 - { - title = "Copy Frontside Floor and Ceiling Slope from Line Tag"; - prefix = "(722)"; - slope = "copy"; - slopeargs = 3; - } - - 799 - { - title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; - prefix = "(799)"; - } - } - - transwall - { - title = "Translucent Wall"; - - 900 - { - title = "90% Opaque"; - prefix = "(900)"; - } - - 901 - { - title = "80% Opaque"; - prefix = "(901)"; - } - - 902 - { - title = "70% Opaque"; - prefix = "(902)"; - } - - 903 - { - title = "60% Opaque"; - prefix = "(903)"; - } - - 904 - { - title = "50% Opaque"; - prefix = "(904)"; - } - - 905 - { - title = "40% Opaque"; - prefix = "(905)"; - } - - 906 - { - title = "30% Opaque"; - prefix = "(906)"; - } - - 907 - { - title = "20% Opaque"; - prefix = "(907)"; - } - - 908 - { - title = "10% Opaque"; - prefix = "(908)"; - } - - 909 - { - title = "Fog Wall"; - prefix = "(909)"; - } - } -} - - -// THING FLAGS -thingflags -{ - 1 = "[1] Extra"; - 2 = "[2] Flip"; - 4 = "[4] Special"; - 8 = "[8] Ambush"; -} - -// Thing flags UDMF translation table -// This is needed for copy/paste and prefabs to work properly -// When the UDMF field name is prefixed with ! it is inverted -thingflagstranslation -{ - 1 = "skill1"; - 2 = "skill2"; - 4 = "skill3"; - 8 = "ambush"; -} - -// THING FLAGS ERROR MASK -// Mask for the thing flags which indicates the options -// that make the same thing appear in the same modes -thingflagsmask1 = 7; // 1 + 2 + 4 -thingflagsmask2 = 0; - - -// THING TYPES------------------------------------------------------------------ -// Color values: 1-Dark_Blue 2-Dark_Green 3-Turqoise 4-Dark_Red 5-Purple 6-Brown 7-Gray -// 8-Dark_Gray 9-Blue 10-Green 11-Cyan 12-Red 13-Magenta -// 14-Yellow 15-White 16-Pink 17-Orange 18-Gold 19-Cream -thingtypes -{ - editor - { - color = 15; // White - arrow = 1; - title = ""; - error = -1; - width = 8; - height = 16; - sort = 1; - - 3328 = "3D Mode Start"; - } - - starts - { - color = 1; // Blue - arrow = 1; - title = "Player Starts"; - width = 16; - height = 48; - flags8text = "[8] Spawn on ceiling"; - sprite = "PLAYA0"; - - 1 - { - title = "Player 01 Start"; - sprite = "PLAYA0"; - } - 2 - { - title = "Player 02 Start"; - sprite = "PLAYA0"; - } - 3 - { - title = "Player 03 Start"; - sprite = "PLAYA0"; - } - 4 - { - title = "Player 04 Start"; - sprite = "PLAYA0"; - } - 5 - { - title = "Player 05 Start"; - sprite = "PLAYA0"; - } - 6 - { - title = "Player 06 Start"; - sprite = "PLAYA0"; - } - 7 - { - title = "Player 07 Start"; - sprite = "PLAYA0"; - } - 8 - { - title = "Player 08 Start"; - sprite = "PLAYA0"; - } - 9 - { - title = "Player 09 Start"; - sprite = "PLAYA0"; - } - 10 - { - title = "Player 10 Start"; - sprite = "PLAYA0"; - } - 11 - { - title = "Player 11 Start"; - sprite = "PLAYA0"; - } - 12 - { - title = "Player 12 Start"; - sprite = "PLAYA0"; - } - 13 - { - title = "Player 13 Start"; - sprite = "PLAYA0"; - } - 14 - { - title = "Player 14 Start"; - sprite = "PLAYA0"; - } - 15 - { - title = "Player 15 Start"; - sprite = "PLAYA0"; - } - 16 - { - title = "Player 16 Start"; - sprite = "PLAYA0"; - } - 17 - { - title = "Player 17 Start"; - sprite = "PLAYA0"; - } - 18 - { - title = "Player 18 Start"; - sprite = "PLAYA0"; - } - 19 - { - title = "Player 19 Start"; - sprite = "PLAYA0"; - } - 20 - { - title = "Player 20 Start"; - sprite = "PLAYA0"; - } - 21 - { - title = "Player 21 Start"; - sprite = "PLAYA0"; - } - 22 - { - title = "Player 22 Start"; - sprite = "PLAYA0"; - } - 23 - { - title = "Player 23 Start"; - sprite = "PLAYA0"; - } - 24 - { - title = "Player 24 Start"; - sprite = "PLAYA0"; - } - 25 - { - title = "Player 25 Start"; - sprite = "PLAYA0"; - } - 26 - { - title = "Player 26 Start"; - sprite = "PLAYA0"; - } - 27 - { - title = "Player 27 Start"; - sprite = "PLAYA0"; - } - 28 - { - title = "Player 28 Start"; - sprite = "PLAYA0"; - } - 29 - { - title = "Player 29 Start"; - sprite = "PLAYA0"; - } - 30 - { - title = "Player 30 Start"; - sprite = "PLAYA0"; - } - 31 - { - title = "Player 31 Start"; - sprite = "PLAYA0"; - } - 32 - { - title = "Player 32 Start"; - sprite = "PLAYA0"; - } - 33 - { - title = "Match Start"; - sprite = "NDRNA2A8"; - } - 34 - { - title = "CTF Red Team Start"; - sprite = "SIGNG0"; - } - 35 - { - title = "CTF Blue Team Start"; - sprite = "SIGNE0"; - } - } - - enemies - { - color = 9; // Light_Blue - arrow = 1; - title = "Enemies"; - - 100 - { - title = "Crawla (Blue)"; - sprite = "POSSA1"; - width = 24; - height = 32; - } - 101 - { - title = "Crawla (Red)"; - sprite = "SPOSA1"; - width = 24; - height = 32; - } - 102 - { - title = "Stupid Dumb Unnamed RoboFish"; - sprite = "FISHA0"; - width = 8; - height = 28; - angletext = "Jump strength"; - } - 103 - { - title = "Buzz (Gold)"; - sprite = "BUZZA1"; - width = 28; - height = 40; - flags8text = "[8] Cannot move"; - } - 104 - { - title = "Buzz (Red)"; - sprite = "RBUZA1"; - width = 28; - height = 40; - flags8text = "[8] Cannot move"; - } - 108 - { - title = "Deton"; - sprite = "DETNA1"; - width = 20; - height = 32; - } - 110 - { - title = "Turret"; - sprite = "TRETA1"; - width = 16; - height = 32; - } - 111 - { - title = "Pop-up Turret"; - sprite = "TURRI1"; - width = 12; - height = 64; - angletext = "Firing delay"; - } - 122 - { - title = "Spring Shell (Green)"; - sprite = "SSHLA1"; - width = 24; - height = 40; - } - 125 - { - title = "Spring Shell (Yellow)"; - sprite = "SSHLI1"; - width = 24; - height = 40; - } - 109 - { - title = "Skim"; - sprite = "SKIMA1"; - width = 16; - height = 24; - } - 113 - { - title = "Jet Jaw"; - sprite = "JJAWA3A7"; - width = 12; - height = 20; - } - 126 - { - title = "Crushstacean"; - sprite = "CRABA0"; - width = 24; - height = 32; - flags8text = "[8] Move left from spawn"; - } - 138 - { - title = "Banpyura"; - sprite = "CR2BA0"; - width = 24; - height = 32; - flags8text = "[8] Move left from spawn"; - } - 117 - { - title = "Robo-Hood"; - sprite = "ARCHA1"; - width = 24; - height = 32; - } - 118 - { - title = "Lance-a-Bot"; - sprite = "CBFSA1"; - width = 32; - height = 72; - } - 1113 - { - title = "Suspicious Lance-a-Bot Statue"; - sprite = "CBBSA1"; - width = 32; - height = 72; - } - 119 - { - title = "Egg Guard"; - sprite = "ESHIA1"; - width = 16; - height = 48; - flags1text = "[1] 90 degrees counter-clockwise"; - flags4text = "[4] 90 degrees clockwise"; - flags8text = "[8] Double speed"; - } - 115 - { - title = "Bird Aircraft Strike Hazard"; - sprite = "VLTRF1"; - width = 12; - height = 24; - } - 120 - { - title = "Green Snapper"; - sprite = "GSNPA1"; - width = 24; - height = 24; - } - 121 - { - title = "Minus"; - sprite = "MNUSA0"; - width = 24; - height = 32; - } - 134 - { - title = "Canarivore"; - sprite = "CANAA0"; - width = 12; - height = 80; - hangs = 1; - } - 123 - { - title = "Unidus"; - sprite = "UNIDA1"; - width = 18; - height = 36; - } - 135 - { - title = "Pterabyte Spawner"; - sprite = "PTERA2A8"; - width = 16; - height = 16; - parametertext = "No. Pterabytes"; - } - 136 - { - title = "Pyre Fly"; - sprite = "PYREA0"; - width = 24; - height = 34; - flags8text = "[8] Start on fire"; - } - 137 - { - title = "Dragonbomber"; - sprite = "DRABA1"; - width = 28; - height = 48; - } - 105 - { - title = "Jetty-Syn Bomber"; - sprite = "JETBB1"; - width = 20; - height = 50; - flags8text = "[8] Cannot move"; - } - 106 - { - title = "Jetty-Syn Gunner"; - sprite = "JETGB1"; - width = 20; - height = 48; - flags8text = "[8] Cannot move"; - } - 112 - { - title = "Spincushion"; - sprite = "SHRPA1"; - width = 16; - height = 24; - } - 114 - { - title = "Snailer"; - sprite = "SNLRA3A7"; - width = 24; - height = 48; - } - 129 - { - title = "Penguinator"; - sprite = "PENGA1"; - width = 24; - height = 32; - } - 130 - { - title = "Pophat"; - sprite = "POPHA1"; - width = 24; - height = 32; - } - 107 - { - title = "Crawla Commander"; - sprite = "CCOMA1"; - width = 16; - height = 32; - } - 131 - { - title = "Spinbobert"; - sprite = "SBOBB0"; - width = 32; - height = 32; - } - 132 - { - title = "Cacolantern"; - sprite = "CACOA0"; - width = 32; - height = 32; - flags8text = "[8] Cannot move"; - } - 133 - { - title = "Hangster"; - sprite = "HBATC1"; - width = 24; - height = 24; - hangs = 1; - } - 127 - { - title = "Hive Elemental"; - sprite = "HIVEA0"; - width = 32; - height = 80; - parametertext = "No. bees"; - } - 128 - { - title = "Bumblebore"; - sprite = "BUMBA1"; - width = 16; - height = 32; - } - 124 - { - title = "Buggle"; - sprite = "BBUZA1"; - width = 20; - height = 24; - } - 116 - { - title = "Pointy"; - sprite = "PNTYA1"; - width = 8; - height = 16; - } - } - - bosses - { - color = 8; // Dark_Gray - arrow = 1; - title = "Bosses"; - - 200 - { - title = "Egg Mobile"; - sprite = "EGGMA1"; - width = 24; - height = 76; - flags4text = "[4] End level on death"; - flags8text = "[8] Alternate laser attack"; - } - 201 - { - title = "Egg Slimer"; - sprite = "EGGNA1"; - width = 24; - height = 76; - flags4text = "[4] End level on death"; - flags8text = "[8] Speed up when hit"; - } - 202 - { - title = "Sea Egg"; - sprite = "EGGOA1"; - width = 32; - height = 116; - flags4text = "[4] End level on death"; - } - 203 - { - title = "Egg Colosseum"; - sprite = "EGGPA1"; - width = 24; - height = 76; - flags4text = "[4] End level on death"; - } - 204 - { - title = "Fang"; - sprite = "FANGA1"; - width = 24; - height = 60; - flags1text = "[1] Grayscale mode"; - flags4text = "[4] End level on death"; - } - 206 - { - title = "Brak Eggman (Old)"; - sprite = "BRAKB1"; - width = 48; - height = 160; - flags4text = "[4] End level on death"; - } - 207 - { - title = "Metal Sonic (Race)"; - sprite = "METLI1"; - width = 16; - height = 48; - flags1text = "[1] Grayscale mode"; - } - 208 - { - title = "Metal Sonic (Battle)"; - sprite = "METLC1"; - width = 16; - height = 48; - flags1text = "[1] Grayscale mode"; - flags4text = "[4] End level on death"; - } - 209 - { - title = "Brak Eggman"; - sprite = "BRAK01"; - width = 48; - height = 160; - flags1text = "[1] No origin-fling death"; - flags4text = "[4] End level on death"; - flags8text = "[8] Electric barrier"; - } - 290 - { - arrow = 0; - title = "Boss Escape Point"; - width = 8; - height = 16; - sprite = "internal:eggmanend"; - } - 291 - { - arrow = 0; - title = "Egg Capsule Center"; - width = 8; - height = 16; - sprite = "internal:capsule"; - } - 292 - { - arrow = 0; - title = "Boss Waypoint"; - width = 8; - height = 16; - flags8text = "[8] Sea Egg shooting point"; - sprite = "internal:eggmanway"; - angletext = "No. (Sea Egg)"; - flagsvaluetext = "No. (Brak)"; - parametertext = "Next"; - } - 293 - { - title = "Metal Sonic Gather Point"; - sprite = "internal:metal"; - width = 8; - height = 16; - } - 294 - { - title = "Fang Waypoint"; - flags8text = "[8] Center waypoint"; - sprite = "internal:eggmanway"; - width = 8; - height = 16; - } - } - - rings - { - color = 14; // Yellow - title = "Rings and Weapon Panels"; - width = 24; - height = 24; - flags8height = 24; - flags8text = "[8] Float"; - sprite = "RINGA0"; - - 300 - { - title = "Ring"; - sprite = "RINGA0"; - width = 16; - } - 301 - { - title = "Bounce Ring"; - sprite = "internal:RNGBA0"; - } - 302 - { - title = "Rail Ring"; - sprite = "internal:RNGRA0"; - } - 303 - { - title = "Infinity Ring"; - sprite = "internal:RNGIA0"; - } - 304 - { - title = "Automatic Ring"; - sprite = "internal:RNGAA0"; - } - 305 - { - title = "Explosion Ring"; - sprite = "internal:RNGEA0"; - } - 306 - { - title = "Scatter Ring"; - sprite = "internal:RNGSA0"; - } - 307 - { - title = "Grenade Ring"; - sprite = "internal:RNGGA0"; - } - 308 - { - title = "CTF Team Ring (Red)"; - sprite = "internal:RRNGA0"; - width = 16; - } - 309 - { - title = "CTF Team Ring (Blue)"; - sprite = "internal:BRNGA0"; - width = 16; - } - 330 - { - title = "Bounce Ring Panel"; - sprite = "internal:PIKBA0"; - } - 331 - { - title = "Rail Ring Panel"; - sprite = "internal:PIKRA0"; - } - 332 - { - title = "Automatic Ring Panel"; - sprite = "internal:PIKAA0"; - } - 333 - { - title = "Explosion Ring Panel"; - sprite = "internal:PIKEA0"; - } - 334 - { - title = "Scatter Ring Panel"; - sprite = "internal:PIKSA0"; - } - 335 - { - title = "Grenade Ring Panel"; - sprite = "internal:PIKGA0"; - } - } - - collectibles - { - color = 10; // Light_Green - title = "Other Collectibles"; - width = 16; - height = 32; - sort = 1; - sprite = "CEMGA0"; - - 310 - { - title = "CTF Red Flag"; - sprite = "RFLGA0"; - width = 24; - height = 64; - } - 311 - { - title = "CTF Blue Flag"; - sprite = "BFLGA0"; - width = 24; - height = 64; - } - 312 - { - title = "Emerald Token"; - sprite = "TOKEA0"; - width = 16; - height = 32; - flags8height = 24; - flags8text = "[8] Float"; - } - 313 - { - title = "Chaos Emerald 1 (Green)"; - sprite = "CEMGA0"; - } - 314 - { - title = "Chaos Emerald 2 (Purple)"; - sprite = "CEMGB0"; - } - 315 - { - title = "Chaos Emerald 3 (Blue)"; - sprite = "CEMGC0"; - } - 316 - { - title = "Chaos Emerald 4 (Cyan)"; - sprite = "CEMGD0"; - } - 317 - { - title = "Chaos Emerald 5 (Orange)"; - sprite = "CEMGE0"; - } - 318 - { - title = "Chaos Emerald 6 (Red)"; - sprite = "CEMGF0"; - } - 319 - { - title = "Chaos Emerald 7 (Gray)"; - sprite = "CEMGG0"; - } - 320 - { - title = "Emerald Hunt Location"; - sprite = "SHRDA0"; - } - 321 - { - title = "Match Chaos Emerald Spawn"; - sprite = "CEMGA0"; - flags8height = 24; - flags8text = "[8] Float"; - } - 322 - { - title = "Emblem"; - sprite = "EMBMA0"; - width = 16; - height = 30; - flags8height = 24; - flags8text = "[8] Float"; - angletext = "Tag"; - } - } - - boxes - { - color = 7; // Gray - blocking = 2; - title = "Monitors"; - width = 18; - height = 40; - flags1text = "[1] Run Linedef Executor on pop"; - flags4text = "[4] Random (Strong)"; - flags8text = "[8] Random (Weak)"; - - 400 - { - title = "Super Ring (10 Rings)"; - sprite = "TVRIA0"; - } - 401 - { - title = "Pity Shield"; - sprite = "TVPIA0"; - } - 402 - { - title = "Attraction Shield"; - sprite = "TVATA0"; - } - 403 - { - title = "Force Shield"; - sprite = "TVFOA0"; - } - 404 - { - title = "Armageddon Shield"; - sprite = "TVARA0"; - } - 405 - { - title = "Whirlwind Shield"; - sprite = "TVWWA0"; - } - 406 - { - title = "Elemental Shield"; - sprite = "TVELA0"; - } - 407 - { - title = "Super Sneakers"; - sprite = "TVSSA0"; - } - 408 - { - title = "Invincibility"; - sprite = "TVIVA0"; - } - 409 - { - title = "Extra Life"; - sprite = "TV1UA0"; - flags4text = "[4] Random (Strong) / 10k points"; - flags8text = "[8] Random (Weak) / 10k points"; - } - 410 - { - title = "Eggman"; - sprite = "TVEGA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 411 - { - title = "Teleporter"; - sprite = "TVMXA0"; - } - 413 - { - title = "Gravity Boots"; - sprite = "TVGVA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 414 - { - title = "CTF Team Ring Monitor (Red)"; - sprite = "TRRIA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 415 - { - title = "CTF Team Ring Monitor (Blue)"; - sprite = "TBRIA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 416 - { - title = "Recycler"; - sprite = "TVRCA0"; - } - 418 - { - title = "Score (1,000 Points)"; - sprite = "TV1KA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 419 - { - title = "Score (10,000 Points)"; - sprite = "TVTKA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 420 - { - title = "Flame Shield"; - sprite = "TVFLA0"; - } - 421 - { - title = "Water Shield"; - sprite = "TVBBA0"; - } - 422 - { - title = "Lightning Shield"; - sprite = "TVZPA0"; - } - } - - boxes2 - { - color = 18; // Gold - blocking = 2; - title = "Monitors (Respawning)"; - width = 20; - height = 44; - flags1text = "[1] Run Linedef Executor on pop"; - - 431 - { - title = "Pity Shield (Respawn)"; - sprite = "TVPIB0"; - } - 432 - { - title = "Attraction Shield (Respawn)"; - sprite = "TVATB0"; - } - 433 - { - title = "Force Shield (Respawn)"; - sprite = "TVFOB0"; - } - 434 - { - title = "Armageddon Shield (Respawn)"; - sprite = "TVARB0"; - } - 435 - { - title = "Whirlwind Shield (Respawn)"; - sprite = "TVWWB0"; - } - 436 - { - title = "Elemental Shield (Respawn)"; - sprite = "TVELB0"; - } - 437 - { - title = "Super Sneakers (Respawn)"; - sprite = "TVSSB0"; - } - 438 - { - title = "Invincibility (Respawn)"; - sprite = "TVIVB0"; - } - 440 - { - title = "Eggman (Respawn)"; - sprite = "TVEGB0"; - } - 443 - { - title = "Gravity Boots (Respawn)"; - sprite = "TVGVB0"; - } - 450 - { - title = "Flame Shield (Respawn)"; - sprite = "TVFLB0"; - } - 451 - { - title = "Water Shield (Respawn)"; - sprite = "TVBBB0"; - } - 452 - { - title = "Lightning Shield (Respawn)"; - sprite = "TVZPB0"; - } - } - - generic - { - color = 11; // Light_Cyan - title = "Generic Items & Hazards"; - - 500 - { - title = "Air Bubble Patch"; - sprite = "BUBLE0"; - width = 8; - height = 16; - flags8text = "[8] No distance check"; - } - 501 - { - title = "Signpost"; - sprite = "SIGND0"; - width = 8; - height = 32; - } - 502 - { - arrow = 1; - title = "Star Post"; - sprite = "STPTA0M0"; - width = 64; - height = 128; - angletext = "Angle/Order"; - } - 520 - { - title = "Bomb Sphere"; - sprite = "SPHRD0"; - width = 16; - height = 24; - flags8height = 24; - flags8text = "[8] Float"; - unflippable = true; - } - 521 - { - title = "Spikeball"; - sprite = "SPIKA0"; - width = 12; - height = 8; - flags8height = 24; - flags8text = "[8] Float"; - } - 522 - { - title = "Wall Spike"; - sprite = "WSPKALAR"; - width = 16; - height = 14; - flags1text = "[1] Start retracted"; - flags4text = "[4] Retractable"; - flags8text = "[8] Intangible"; - parametertext = "Initial delay"; - } - 523 - { - title = "Spike"; - sprite = "USPKA0"; - width = 8; - height = 32; - flags1text = "[1] Start retracted"; - flags4text = "[4] Retractable"; - flags8text = "[8] Intangible"; - angletext = "Retraction interval"; - parametertext = "Initial delay"; - } - 1130 - { - title = "Small Mace"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1131 - { - title = "Big Mace"; - sprite = "BMCEA0"; - width = 34; - height = 68; - } - 1136 - { - title = "Small Fireball"; - sprite = "SFBRA0"; - width = 17; - height = 34; - } - 1137 - { - title = "Large Fireball"; - sprite = "BFBRA0"; - width = 34; - height = 68; - } - } - - springs - { - color = 12; // Light_Red - title = "Springs and Fans"; - width = 20; - height = 16; - sprite = "RSPRD2"; - - 540 - { - title = "Fan"; - sprite = "FANSA0D0"; - width = 16; - height = 8; - flags4text = "[4] Invisible"; - flags8text = "[8] No distance check"; - angletext = "Lift height"; - } - 541 - { - title = "Gas Jet"; - sprite = "STEMD0"; - flags8text = "[8] No sounds"; - width = 32; - } - 542 - { - title = "Bumper"; - sprite = "BUMPA0"; - width = 32; - height = 64; - angletext = "Strength"; - } - 543 - { - title = "Balloon"; - sprite = "BLONA0"; - width = 32; - height = 64; - flags8text = "[8] Respawn"; - angletext = "Color"; - } - 550 - { - title = "Yellow Spring"; - sprite = "SPRYA0"; - } - 551 - { - title = "Red Spring"; - sprite = "SPRRA0"; - } - 552 - { - title = "Blue Spring"; - sprite = "SPRBA0"; - } - 555 - { - arrow = 1; - title = "Diagonal Yellow Spring"; - sprite = "YSPRD2"; - width = 16; - flags4text = "[4] Ignore gravity"; - flags8text = "[8] Rotate 22.5° CCW"; - } - 556 - { - arrow = 1; - title = "Diagonal Red Spring"; - sprite = "RSPRD2"; - width = 16; - flags4text = "[4] Ignore gravity"; - flags8text = "[8] Rotate 22.5° CCW"; - } - 557 - { - arrow = 1; - title = "Diagonal Blue Spring"; - sprite = "BSPRD2"; - width = 16; - flags4text = "[4] Ignore gravity"; - flags8text = "[8] Rotate 22.5° CCW"; - } - 558 - { - arrow = 1; - title = "Horizontal Yellow Spring"; - sprite = "SSWYD2D8"; - flags8height = 16; - flags8text = "[8] Float"; - width = 16; - height = 32; - } - 559 - { - arrow = 1; - title = "Horizontal Red Spring"; - sprite = "SSWRD2D8"; - flags8height = 16; - flags8text = "[8] Float"; - width = 16; - height = 32; - } - 560 - { - arrow = 1; - title = "Horizontal Blue Spring"; - sprite = "SSWBD2D8"; - flags8height = 16; - flags8text = "[8] Float"; - width = 16; - height = 32; - } - 1134 - { - title = "Yellow Spring Ball"; - sprite = "YSPBA0"; - width = 17; - height = 34; - } - 1135 - { - title = "Red Spring Ball"; - sprite = "RSPBA0"; - width = 17; - height = 34; - } - 544 - { - arrow = 1; - title = "Yellow Boost Panel"; - sprite = "BSTYA0"; - flags8text = "[8] Force spin"; - width = 28; - height = 2; - } - 545 - { - arrow = 1; - title = "Red Boost Panel"; - sprite = "BSTRA0"; - flags8text = "[8] Force spin"; - width = 28; - height = 2; - } - } - - patterns - { - color = 5; // Magenta - arrow = 1; - title = "Special Placement Patterns"; - width = 16; - height = 384; - sprite = "RINGA0"; - - 600 - { - arrow = 0; - title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; - } - 601 - { - arrow = 0; - title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; - height = 1024; - } - 602 - { - title = "5 Diagonal Rings (Yellow Spring)"; - sprite = "RINGA0"; - height = 32; - } - 603 - { - title = "10 Diagonal Rings (Red Spring)"; - sprite = "RINGA0"; - height = 32; - } - 604 - { - title = "Circle of Rings"; - sprite = "RINGA0"; - width = 96; - height = 192; - unflippable = true; - centerHitbox = true; - } - 605 - { - title = "Circle of Rings (Big)"; - sprite = "RINGA0"; - width = 192; - unflippable = true; - centerHitbox = true; - } - 606 - { - title = "Circle of Blue Spheres"; - sprite = "SPHRA0"; - width = 96; - height = 192; - unflippable = true; - centerHitbox = true; - } - 607 - { - title = "Circle of Blue Spheres (Big)"; - sprite = "SPHRA0"; - width = 192; - unflippable = true; - centerHitbox = true; - } - 608 - { - title = "Circle of Rings and Spheres"; - sprite = "SPHRA0"; - width = 96; - height = 192; - unflippable = true; - centerHitbox = true; - } - 609 - { - title = "Circle of Rings and Spheres (Big)"; - sprite = "SPHRA0"; - width = 192; - unflippable = true; - centerHitbox = true; - } - } - - invisible - { - color = 15; // White - title = "Misc. Invisible"; - width = 8; - height = 16; - sprite = "UNKNA0"; - - 700 - { - title = "Water Ambience A (Large)"; - sprite = "internal:ambiance"; - } - - 701 - { - title = "Water Ambience B (Large)"; - sprite = "internal:ambiance"; - } - - 702 - { - title = "Water Ambience C (Medium)"; - sprite = "internal:ambiance"; - } - - 703 - { - title = "Water Ambience D (Medium)"; - sprite = "internal:ambiance"; - } - - 704 - { - title = "Water Ambience E (Small)"; - sprite = "internal:ambiance"; - } - - 705 - { - title = "Water Ambience F (Small)"; - sprite = "internal:ambiance"; - } - - 706 - { - title = "Water Ambience G (Extra Large)"; - sprite = "internal:ambiance"; - } - - 707 - { - title = "Water Ambience H (Extra Large)"; - sprite = "internal:ambiance"; - } - - 708 - { - title = "Disco Ambience"; - sprite = "internal:ambiance"; - } - - 709 - { - title = "Volcano Ambience"; - sprite = "internal:ambiance"; - } - - 710 - { - title = "Machine Ambience"; - sprite = "internal:ambiance"; - } - - 750 - { - title = "Slope Vertex"; - sprite = "internal:vertexslope"; - angletext = "Tag"; - } - - 751 - { - arrow = 1; - title = "Teleport Destination"; - sprite = "internal:tele"; - } - - 752 - { - arrow = 1; - title = "Alternate View Point"; - sprite = "internal:view"; - } - - 753 - { - title = "Zoom Tube Waypoint"; - sprite = "internal:zoom"; - angletext = "Order"; - } - - 754 - { - title = "Push Point"; - flags4text = "[4] Fades using XY"; - flags8text = "[8] Push using XYZ"; - sprite = "GWLGA0"; - angletext = "Radius"; - } - 755 - { - title = "Pull Point"; - flags4text = "[4] Fades using XY"; - flags8text = "[8] Pull using XYZ"; - sprite = "GWLRA0"; - angletext = "Radius"; - } - 756 - { - title = "Blast Linedef Executor"; - sprite = "TOADA0"; - width = 32; - height = 16; - } - 757 - { - title = "Fan Particle Generator"; - sprite = "PRTLA0"; - width = 8; - height = 16; - angletext = "Tag"; - } - 758 - { - title = "Object Angle Anchor"; - sprite = "internal:view"; - } - 760 - { - title = "PolyObject Anchor"; - sprite = "internal:polyanchor"; - angletext = "ID"; - } - - 761 - { - title = "PolyObject Spawn Point"; - sprite = "internal:polycenter"; - angletext = "ID"; - } - - 762 - { - title = "PolyObject Spawn Point (Crush)"; - sprite = "internal:polycentercrush"; - angletext = "ID"; - } - 780 - { - title = "Skybox View Point"; - sprite = "internal:skyb"; - flags4text = "[4] In-map centerpoint"; - parametertext = "ID"; - } - } - - greenflower - { - color = 10; // Green - title = "Greenflower"; - - 800 - { - title = "GFZ Flower"; - sprite = "FWR1A0"; - width = 16; - height = 40; - } - 801 - { - title = "Sunflower"; - sprite = "FWR2A0"; - width = 16; - height = 96; - } - 802 - { - title = "Budding Flower"; - sprite = "FWR3A0"; - width = 8; - height = 32; - } - 803 - { - title = "Blueberry Bush"; - sprite = "BUS3A0"; - width = 16; - height = 32; - } - 804 - { - title = "Berry Bush"; - sprite = "BUS1A0"; - width = 16; - height = 32; - } - 805 - { - title = "Bush"; - sprite = "BUS2A0"; - width = 16; - height = 32; - } - 806 - { - title = "GFZ Tree"; - sprite = "TRE1A0"; - width = 20; - height = 128; - } - 807 - { - title = "GFZ Berry Tree"; - sprite = "TRE1B0"; - width = 20; - height = 128; - } - 808 - { - title = "GFZ Cherry Tree"; - sprite = "TRE1C0"; - width = 20; - height = 128; - } - 809 - { - title = "Checkered Tree"; - sprite = "TRE2A0"; - width = 20; - height = 200; - } - 810 - { - title = "Checkered Tree (Sunset)"; - sprite = "TRE2B0"; - width = 20; - height = 200; - } - 811 - { - title = "Polygon Tree"; - sprite = "TRE4A0"; - width = 20; - height = 200; - } - 812 - { - title = "Bush Tree"; - sprite = "TRE5A0"; - width = 20; - height = 200; - } - 813 - { - title = "Red Bush Tree"; - sprite = "TRE5B0"; - width = 20; - height = 200; - } - } - - technohill - { - color = 10; // Green - title = "Techno Hill"; - - 900 - { - title = "THZ Steam Flower"; - sprite = "THZPA0"; - width = 8; - height = 32; - } - 901 - { - title = "Alarm"; - sprite = "ALRMA0"; - width = 8; - height = 16; - hangs = 1; - } - 902 - { - title = "THZ Spin Flower (Red)"; - sprite = "FWR5A0"; - width = 16; - height = 64; - } - 903 - { - title = "THZ Spin Flower (Yellow)"; - sprite = "FWR6A0"; - width = 16; - height = 64; - } - 904 - { - arrow = 1; - title = "Whistlebush"; - sprite = "THZTA0"; - width = 16; - height = 64; - } - } - - deepsea - { - color = 10; // Green - title = "Deep Sea"; - - 1000 - { - arrow = 1; - blocking = 2; - title = "Gargoyle"; - sprite = "GARGA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1009 - { - arrow = 1; - blocking = 2; - title = "Gargoyle (Big)"; - sprite = "GARGB1"; - width = 32; - height = 80; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1001 - { - title = "Seaweed"; - sprite = "SEWEA0"; - width = 24; - height = 56; - } - 1002 - { - title = "Dripping Water"; - sprite = "DRIPD0"; - width = 8; - height = 16; - hangs = 1; - angletext = "Dripping interval"; - } - 1003 - { - title = "Coral (Green)"; - sprite = "CORLA0"; - width = 29; - height = 40; - } - 1004 - { - title = "Coral (Red)"; - sprite = "CORLB0"; - width = 30; - height = 53; - } - 1005 - { - title = "Coral (Orange)"; - sprite = "CORLC0"; - width = 28; - height = 41; - } - 1006 - { - title = "Blue Crystal"; - sprite = "BCRYA1"; - width = 8; - height = 16; - } - 1007 - { - title = "Kelp"; - sprite = "KELPA0"; - width = 16; - height = 292; - flags4text = "[4] Double size"; - } - 1008 - { - title = "Stalagmite (DSZ1)"; - sprite = "DSTGA0"; - width = 8; - height = 116; - flags4text = "[4] Double size"; - } - 1010 - { - arrow = 1; - title = "Light Beam"; - sprite = "LIBEARAL"; - width = 16; - height = 16; - } - 1011 - { - title = "Stalagmite (DSZ2)"; - sprite = "DSTGA0"; - width = 8; - height = 116; - flags4text = "[4] Double size"; - } - 1012 - { - arrow = 1; - title = "Big Floating Mine"; - width = 28; - height = 56; - sprite = "BMNEA1"; - } - 1013 - { - title = "Animated Kelp"; - sprite = "ALGAA0"; - width = 48; - height = 120; - } - 1014 - { - title = "Large Coral (Brown)"; - sprite = "CORLD0"; - width = 56; - height = 112; - } - 1015 - { - title = "Large Coral (Beige)"; - sprite = "CORLE0"; - width = 56; - height = 112; - } - } - - castleeggman - { - color = 10; // Green - title = "Castle Eggman"; - - 1100 - { - title = "Chain (Decorative)"; - sprite = "CHANA0"; - width = 4; - height = 128; - hangs = 1; - } - 1101 - { - title = "Torch"; - sprite = "FLAMA0E0"; - width = 8; - height = 32; - flags1text = "[1] Add corona"; - } - 1102 - { - arrow = 1; - blocking = 2; - title = "Eggman Statue"; - sprite = "ESTAA1"; - width = 32; - height = 240; - flags1text = "[1] Solid gold"; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1103 - { - title = "CEZ Flower"; - sprite = "FWR4A0"; - width = 16; - height = 40; - } - 1104 - { - title = "Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - flags4text = "[4] No sounds"; - flags8text = "[8] Double size"; - angletext = "Tag"; - } - 1105 - { - title = "Chain with Maces Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - flags4text = "[4] No sounds"; - flags8text = "[8] Double size"; - angletext = "Tag"; - } - 1106 - { - title = "Chained Spring Spawnpoint"; - sprite = "YSPBA0"; - width = 17; - height = 34; - flags4text = "[4] No sounds"; - flags8text = "[8] Red spring"; - angletext = "Tag"; - } - 1107 - { - title = "Chain Spawnpoint"; - sprite = "BMCHA0"; - width = 17; - height = 34; - flags8text = "[8] Double size"; - angletext = "Tag"; - } - 1108 - { - arrow = 1; - title = "Hidden Chain Spawnpoint"; - sprite = "internal:chain3"; - width = 17; - height = 34; - flags8text = "[8] Double size"; - } - 1109 - { - title = "Firebar Spawnpoint"; - sprite = "BFBRA0"; - width = 17; - height = 34; - flags4text = "[4] No sounds"; - flags8text = "[8] Double size"; - angletext = "Tag"; - } - 1110 - { - title = "Custom Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - flags4text = "[4] No sounds"; - angletext = "Tag"; - } - 1111 - { - arrow = 1; - blocking = 2; - title = "Crawla Statue"; - sprite = "CSTAA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1112 - { - arrow = 1; - blocking = 2; - title = "Lance-a-Bot Statue"; - sprite = "CBBSA1"; - width = 32; - height = 72; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1114 - { - title = "Pine Tree"; - sprite = "PINEA0"; - width = 16; - height = 628; - } - 1115 - { - title = "CEZ Shrub (Small)"; - sprite = "CEZBA0"; - width = 16; - height = 24; - } - 1116 - { - title = "CEZ Shrub (Large)"; - sprite = "CEZBB0"; - width = 32; - height = 48; - } - 1117 - { - arrow = 1; - title = "Pole Banner (Red)"; - sprite = "BANRA0"; - width = 40; - height = 224; - } - 1118 - { - arrow = 1; - title = "Pole Banner (Blue)"; - sprite = "BANRA0"; - width = 40; - height = 224; - } - 1119 - { - title = "Candle"; - sprite = "CNDLA0"; - width = 8; - height = 48; - flags1text = "[1] Add corona"; - } - 1120 - { - title = "Candle Pricket"; - sprite = "CNDLB0"; - width = 8; - height = 176; - flags1text = "[1] Add corona"; - } - 1121 - { - title = "Flame Holder"; - sprite = "FLMHA0"; - width = 24; - height = 80; - flags1text = "[1] Add corona"; - flags4text = "[4] No flame"; - } - 1122 - { - title = "Fire Torch"; - sprite = "CTRCA0"; - width = 16; - height = 80; - } - 1123 - { - title = "Cannonball Launcher"; - sprite = "internal:cannonball"; - width = 8; - height = 16; - } - 1124 - { - blocking = 2; - title = "Cannonball"; - sprite = "CBLLA0"; - width = 20; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1125 - { - title = "Brambles"; - sprite = "CABRALAR"; - width = 48; - height = 32; - } - 1126 - { - title = "Invisible Lockon Object"; - sprite = "LCKNC0"; - width = 16; - height = 32; - } - 1127 - { - title = "Spectator Eggrobo"; - sprite = "EGR1A1"; - width = 20; - height = 72; - } - 1128 - { - arrow = 1; - title = "Waving Flag (Red)"; - sprite = "CFLGA0"; - width = 8; - height = 208; - } - 1129 - { - arrow = 1; - title = "Waving Flag (Blue)"; - sprite = "CFLGA0"; - width = 8; - height = 208; - } - } - - aridcanyon - { - color = 10; // Green - title = "Arid Canyon"; - - 1200 - { - title = "Tumbleweed (Big)"; - sprite = "BTBLA0"; - width = 24; - height = 48; - flags8text = "[8] Moves perpetually"; - } - 1201 - { - title = "Tumbleweed (Small)"; - sprite = "STBLA0"; - width = 12; - height = 24; - flags8text = "[8] Moves perpetually"; - } - 1202 - { - arrow = 1; - title = "Rock Spawner"; - sprite = "ROIAA0"; - width = 8; - height = 16; - angletext = "Tag"; - } - 1203 - { - title = "Tiny Red Flower Cactus"; - sprite = "CACTA0"; - width = 13; - height = 24; - } - 1204 - { - title = "Small Red Flower Cactus"; - sprite = "CACTB0"; - width = 15; - height = 52; - } - 1205 - { - title = "Tiny Blue Flower Cactus"; - sprite = "CACTC0"; - width = 13; - height = 24; - } - 1206 - { - title = "Small Blue Flower Cactus"; - sprite = "CACTD0"; - width = 15; - height = 52; - } - 1207 - { - title = "Prickly Pear"; - sprite = "CACTE0"; - width = 32; - height = 96; - } - 1208 - { - title = "Barrel Cactus"; - sprite = "CACTF0"; - width = 20; - height = 128; - } - 1209 - { - title = "Tall Barrel Cactus"; - sprite = "CACTG0"; - width = 24; - height = 224; - } - 1210 - { - title = "Armed Cactus"; - sprite = "CACTH0"; - width = 24; - height = 256; - } - 1211 - { - title = "Ball Cactus"; - sprite = "CACTI0"; - width = 48; - height = 96; - } - 1212 - { - title = "Caution Sign"; - sprite = "WWSGAR"; - width = 22; - height = 64; - } - 1213 - { - title = "Cacti Sign"; - sprite = "WWS2AR"; - width = 22; - height = 64; - } - 1214 - { - title = "Sharp Turn Sign"; - sprite = "WWS3ALAR"; - width = 16; - height = 192; - } - 1215 - { - title = "Mine Oil Lamp"; - sprite = "OILLA0"; - width = 22; - height = 64; - hangs = 1; - } - 1216 - { - title = "TNT Barrel"; - sprite = "BARRA1"; - width = 24; - height = 63; - } - 1217 - { - title = "TNT Proximity Shell"; - sprite = "REMTA0"; - width = 64; - height = 40; - } - 1218 - { - title = "Dust Devil"; - sprite = "TAZDCR"; - width = 80; - height = 416; - } - 1219 - { - title = "Minecart Spawner"; - sprite = "MCRTCLFR"; - width = 22; - height = 32; - } - 1220 - { - title = "Minecart Stopper"; - sprite = "MCRTIR"; - width = 32; - height = 32; - } - 1221 - { - title = "Minecart Saloon Door"; - sprite = "SALDARAL"; - width = 96; - height = 160; - flags8text = "[8] Allow non-minecart players"; - } - 1222 - { - title = "Train Cameo Spawner"; - sprite = "TRAEBRBL"; - width = 28; - height = 32; - } - 1223 - { - title = "Train Dust Spawner"; - sprite = "ADSTA0"; - width = 4; - height = 4; - } - 1224 - { - title = "Train Steam Spawner"; - sprite = "STEAA0"; - width = 4; - height = 4; - } - 1229 - { - title = "Minecart Switch Point"; - sprite = "internal:zoom"; - width = 8; - height = 16; - flags8text = "[8] Enable switching"; - } - 1230 - { - title = "Tiny Cactus"; - sprite = "CACTJ0"; - width = 13; - height = 28; - } - 1231 - { - title = "Small Cactus"; - sprite = "CACTK0"; - width = 15; - height = 60; - } - } - - redvolcano - { - color = 10; // Green - title = "Red Volcano"; - - 1300 - { - arrow = 1; - title = "Flame Jet (Horizontal)"; - sprite = "internal:flameh"; - width = 16; - height = 40; - flags8text = "[8] Waves vertically"; - angletext = "On/Off time"; - parametertext = "Strength"; - } - 1301 - { - title = "Flame Jet (Vertical)"; - sprite = "internal:flamev"; - width = 16; - height = 40; - flags8text = "[8] Shoot downwards"; - angletext = "On/Off time"; - parametertext = "Strength"; - } - 1302 - { - title = "Spinning Flame Jet (Counter-Clockwise)"; - sprite = "internal:flame2"; - width = 16; - height = 24; - } - 1303 - { - title = "Spinning Flame Jet (Clockwise)"; - sprite = "internal:flame1"; - width = 16; - height = 24; - } - 1304 - { - title = "Lavafall"; - sprite = "LFALF0"; - width = 30; - height = 32; - angletext = "Initial delay"; - flags8text = "[8] Double size"; - } - 1305 - { - title = "Rollout Rock"; - sprite = "PUMIA1A5"; - width = 30; - height = 60; - flags8text = "[8] Non-buoyant"; - } - 1306 - { - title = "Big Fern"; - sprite = "JPLAB0"; - width = 32; - height = 48; - } - 1307 - { - title = "Jungle Palm"; - sprite = "JPLAC0"; - width = 32; - height = 48; - } - 1308 - { - title = "Torch Flower"; - sprite = "TFLOA0"; - width = 14; - height = 110; - } - 1309 - { - title = "RVZ1 Wall Vine (Long)"; - sprite = "WVINALAR"; - width = 1; - height = 288; - } - 1310 - { - title = "RVZ1 Wall Vine (Short)"; - sprite = "WVINBLBR"; - width = 1; - height = 288; - } - } - - botanicserenity - { - color = 10; // Green - title = "Botanic Serenity"; - width = 16; - height = 32; - sprite = "BSZ1A0"; - 1400 - { - title = "Tall Flower (Red)"; - sprite = "BSZ1A0"; - } - 1401 - { - title = "Tall Flower (Purple)"; - sprite = "BSZ1B0"; - } - 1402 - { - title = "Tall Flower (Blue)"; - sprite = "BSZ1C0"; - } - 1403 - { - title = "Tall Flower (Cyan)"; - sprite = "BSZ1D0"; - } - 1404 - { - title = "Tall Flower (Yellow)"; - sprite = "BSZ1E0"; - } - 1405 - { - title = "Tall Flower (Orange)"; - sprite = "BSZ1F0"; - } - 1410 - { - title = "Medium Flower (Red)"; - sprite = "BSZ2A0"; - } - 1411 - { - title = "Medium Flower (Purple)"; - sprite = "BSZ2B0"; - } - 1412 - { - title = "Medium Flower (Blue)"; - sprite = "BSZ2C0"; - } - 1413 - { - title = "Medium Flower (Cyan)"; - sprite = "BSZ2D0"; - } - 1414 - { - title = "Medium Flower (Yellow)"; - sprite = "BSZ2E0"; - } - 1415 - { - title = "Medium Flower (Orange)"; - sprite = "BSZ2F0"; - } - 1420 - { - title = "Short Flower (Red)"; - sprite = "BSZ3A0"; - } - 1421 - { - title = "Short Flower (Purple)"; - sprite = "BSZ3B0"; - } - 1422 - { - title = "Short Flower (Blue)"; - sprite = "BSZ3C0"; - } - 1423 - { - title = "Short Flower (Cyan)"; - sprite = "BSZ3D0"; - } - 1424 - { - title = "Short Flower (Yellow)"; - sprite = "BSZ3E0"; - } - 1425 - { - title = "Short Flower (Orange)"; - sprite = "BSZ3F0"; - } - 1430 - { - title = "Tulip (Red)"; - sprite = "BST1A0"; - } - 1431 - { - title = "Tulip (Purple)"; - sprite = "BST2A0"; - } - 1432 - { - title = "Tulip (Blue)"; - sprite = "BST3A0"; - } - 1433 - { - title = "Tulip (Cyan)"; - sprite = "BST4A0"; - } - 1434 - { - title = "Tulip (Yellow)"; - sprite = "BST5A0"; - } - 1435 - { - title = "Tulip (Orange)"; - sprite = "BST6A0"; - } - 1440 - { - title = "Cluster (Red)"; - sprite = "BSZ5A0"; - } - 1441 - { - title = "Cluster (Purple)"; - sprite = "BSZ5B0"; - } - 1442 - { - title = "Cluster (Blue)"; - sprite = "BSZ5C0"; - } - 1443 - { - title = "Cluster (Cyan)"; - sprite = "BSZ5D0"; - } - 1444 - { - title = "Cluster (Yellow)"; - sprite = "BSZ5E0"; - } - 1445 - { - title = "Cluster (Orange)"; - sprite = "BSZ5F0"; - } - 1450 - { - title = "Bush (Red)"; - sprite = "BSZ6A0"; - } - 1451 - { - title = "Bush (Purple)"; - sprite = "BSZ6B0"; - } - 1452 - { - title = "Bush (Blue)"; - sprite = "BSZ6C0"; - } - 1453 - { - title = "Bush (Cyan)"; - sprite = "BSZ6D0"; - } - 1454 - { - title = "Bush (Yellow)"; - sprite = "BSZ6E0"; - } - 1455 - { - title = "Bush (Orange)"; - sprite = "BSZ6F0"; - } - 1460 - { - title = "Vine (Red)"; - sprite = "BSZ7A0"; - } - 1461 - { - title = "Vine (Purple)"; - sprite = "BSZ7B0"; - } - 1462 - { - title = "Vine (Blue)"; - sprite = "BSZ7C0"; - } - 1463 - { - title = "Vine (Cyan)"; - sprite = "BSZ7D0"; - } - 1464 - { - title = "Vine (Yellow)"; - sprite = "BSZ7E0"; - } - 1465 - { - title = "Vine (Orange)"; - sprite = "BSZ7F0"; - } - 1470 - { - title = "BSZ Shrub"; - sprite = "BSZ8A0"; - } - 1471 - { - title = "BSZ Clover"; - sprite = "BSZ8B0"; - } - 1473 - { - title = "Palm Tree (Big)"; - width = 16; - height = 160; - sprite = "BSZ8D0"; - } - 1475 - { - title = "Palm Tree (Small)"; - width = 16; - height = 80; - sprite = "BSZ8F0"; - } - } - - azuretemple - { - color = 10; // Green - title = "Azure Temple"; - - 1500 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle"; - sprite = "BGARA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1501 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Up)"; - sprite = "BGARA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1502 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Down)"; - sprite = "BGARA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1503 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Long)"; - sprite = "BGARA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1504 - { - title = "ATZ Target"; - sprite = "RCRYB0"; - width = 24; - height = 32; - } - 1505 - { - title = "Green Flame"; - sprite = "CFLMA0E0"; - width = 8; - height = 32; - } - 1506 - { - arrow = 1; - blocking = 2; - title = "Blue Gargoyle"; - sprite = "BGARD1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - } - - dreamhill - { - color = 10; // Green - title = "Dream Hill"; - - 1600 - { - title = "Spring Tree"; - sprite = "TRE6A0"; - width = 16; - height = 32; - } - 1601 - { - title = "Shleep"; - sprite = "SHLPA0"; - width = 24; - height = 32; - } - 1602 - { - title = "Pian"; - sprite = "NTPNALAR"; - width = 16; - height = 32; - } - } - - nightstrk - { - color = 13; // Pink - title = "NiGHTS Track"; - width = 8; - height = 4096; - sprite = "UNKNA0"; - - 1700 - { - title = "Axis"; - sprite = "internal:axis1"; - circle = 1; - unflippable = true; - ignoreZ = true; - flagsvaluetext = "Order"; - angletext = "Radius/Direction"; - parametertext = "Mare"; - } - 1701 - { - title = "Axis Transfer"; - sprite = "internal:axis2"; - unflippable = true; - ignoreZ = true; - flagsvaluetext = "Order"; - parametertext = "Mare"; - } - 1702 - { - title = "Axis Transfer Line"; - sprite = "internal:axis3"; - unflippable = true; - ignoreZ = true; - flagsvaluetext = "Order"; - parametertext = "Mare"; - } - 1710 - { - title = "Ideya Capture"; - sprite = "CAPSA0"; - width = 72; - height = 144; - angletext = "Rings"; - parametertext = "Mare"; - } - } - - nights - { - color = 13; // Pink - title = "NiGHTS Items"; - width = 16; - height = 32; - - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - flags1text = "[1] Align player to middle"; - flags4text = "[4] Align player to top"; - flags8text = "[8] Die upon time up"; - angletext = "Time limit"; - parametertext = "Height"; - } - 1704 - { - arrow = 1; - title = "NiGHTS Bumper"; - sprite = "NBMPG3G7"; - width = 32; - height = 64; - unflippable = true; - flagsvaluetext = "Pitch"; - angletext = "Yaw"; - } - 1705 - { - arrow = 1; - title = "Hoop (Generic)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - unflippable = true; - centerHitbox = true; - flagsvaluetext = "Height"; - angletext = "Pitch/Yaw"; - } - 1706 - { - title = "Blue Sphere"; - sprite = "SPHRA0"; - width = 16; - height = 24; - flags8height = 24; - flags8text = "[8] Float"; - unflippable = true; - } - 1707 - { - title = "Super Paraloop"; - sprite = "NPRUA0"; - flags4text = "[4] Bonus time only"; - flags8text = "[8] Spawn immediately"; - } - 1708 - { - title = "Drill Refill"; - sprite = "NPRUB0"; - flags4text = "[4] Bonus time only"; - flags8text = "[8] Spawn immediately"; - } - 1709 - { - title = "Nightopian Helper"; - sprite = "NPRUC0"; - flags4text = "[4] Bonus time only"; - flags8text = "[8] Spawn immediately"; - } - 1711 - { - title = "Extra Time"; - sprite = "NPRUD0"; - flags4text = "[4] Bonus time only"; - flags8text = "[8] Spawn immediately"; - } - 1712 - { - title = "Link Freeze"; - sprite = "NPRUE0"; - flags4text = "[4] Bonus time only"; - flags8text = "[8] Spawn immediately"; - } - 1713 - { - arrow = 1; - title = "Hoop (Customizable)"; - flags1text = "[1] Radius +16"; - flags2text = "[2] Radius +32"; - flags4text = "[4] Radius +64"; - flags8text = "[8] Radius +128"; - sprite = "HOOPA0"; - width = 80; - height = 160; - unflippable = true; - centerHitbox = true; - } - 1714 - { - title = "Ideya Anchor Point"; - sprite = "internal:axis1"; - width = 8; - height = 16; - parametertext = "Ideya"; - } - } - - mario - { - color = 6; // Brown - title = "Mario"; - - 1800 - { - title = "Coin"; - sprite = "COINA0"; - width = 16; - height = 24; - flags8height = 24; - flags8text = "[8] Float"; - } - 1801 - { - arrow = 1; - title = "Goomba"; - sprite = "GOOMA0"; - width = 24; - height = 32; - } - 1802 - { - arrow = 1; - title = "Goomba (Blue)"; - sprite = "BGOMA0"; - width = 24; - height = 32; - } - 1803 - { - title = "Fire Flower"; - sprite = "FFWRB0"; - width = 16; - height = 32; - } - 1804 - { - title = "Koopa Shell"; - sprite = "SHLLA1"; - width = 16; - height = 20; - } - 1805 - { - title = "Puma (Jumping Fireball)"; - sprite = "PUMAA0"; - width = 8; - height = 16; - angletext = "Jump strength"; - } - 1806 - { - title = "King Bowser"; - sprite = "KOOPA0"; - width = 16; - height = 48; - } - 1807 - { - title = "Axe"; - sprite = "MAXEA0"; - width = 8; - height = 16; - } - 1808 - { - title = "Bush (Short)"; - sprite = "MUS1A0"; - width = 16; - height = 32; - } - 1809 - { - title = "Bush (Tall)"; - sprite = "MUS2A0"; - width = 16; - height = 32; - } - 1810 - { - title = "Toad"; - sprite = "TOADA0"; - width = 8; - height = 32; - } - } - - christmasdisco - { - color = 10; // Green - title = "Christmas & Disco"; - - 1850 - { - title = "Christmas Pole"; - sprite = "XMS1A0"; - width = 16; - height = 40; - } - 1851 - { - title = "Candy Cane"; - sprite = "XMS2A0"; - width = 8; - height = 32; - } - 1852 - { - blocking = 2; - title = "Snowman"; - sprite = "XMS3A0"; - width = 16; - height = 64; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1853 - { - blocking = 2; - title = "Snowman (With Hat)"; - sprite = "XMS3B0"; - width = 16; - height = 80; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1854 - { - title = "Lamp Post"; - sprite = "XMS4A0"; - width = 8; - height = 120; - } - 1855 - { - title = "Lamp Post (Snow)"; - sprite = "XMS4B0"; - width = 8; - height = 120; - } - 1856 - { - title = "Hanging Star"; - sprite = "XMS5A0"; - width = 4; - height = 80; - hangs = 1; - } - 1857 - { - title = "Berry Bush (Snow)"; - sprite = "BUS1B0"; - width = 16; - height = 32; - } - 1858 - { - title = "Bush (Snow)"; - sprite = "BUS2B0"; - width = 16; - height = 32; - } - 1859 - { - title = "Blueberry Bush (Snow)"; - sprite = "BUS3B0"; - width = 16; - height = 32; - } - 1875 - { - title = "Disco Ball"; - sprite = "DBALA0"; - width = 16; - height = 54; - hangs = 1; - } - 1876 - { - arrow = 1; - blocking = 2; - title = "Eggman Disco Statue"; - sprite = "ESTAB1"; - width = 20; - height = 96; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - } - - stalagmites - { - color = 10; // Green - title = "Stalagmites"; - width = 16; - height = 40; - - 1900 - { - title = "Brown Stalagmite (Tall)"; - sprite = "STLGA0"; - width = 16; - height = 40; - } - 1901 - { - title = "Brown Stalagmite"; - sprite = "STLGB0"; - width = 16; - height = 40; - } - 1902 - { - title = "Orange Stalagmite (Tall)"; - sprite = "STLGC0"; - width = 16; - height = 40; - } - 1903 - { - title = "Orange Stalagmite"; - sprite = "STLGD0"; - width = 16; - height = 40; - } - 1904 - { - title = "Red Stalagmite (Tall)"; - sprite = "STLGE0"; - width = 16; - height = 40; - } - 1905 - { - title = "Red Stalagmite"; - sprite = "STLGF0"; - width = 16; - height = 40; - } - 1906 - { - title = "Gray Stalagmite (Tall)"; - sprite = "STLGG0"; - width = 24; - height = 96; - } - 1907 - { - title = "Gray Stalagmite"; - sprite = "STLGH0"; - width = 16; - height = 40; - } - 1908 - { - title = "Blue Stalagmite (Tall)"; - sprite = "STLGI0"; - width = 16; - height = 40; - } - 1909 - { - title = "Blue Stalagmite"; - sprite = "STLGJ0"; - width = 16; - height = 40; - } - } - - hauntedheights - { - color = 10; // Green - title = "Haunted Heights"; - - 2000 - { - title = "Smashing Spikeball"; - sprite = "FMCEA0"; - width = 18; - height = 28; - angletext = "Initial delay"; - } - 2001 - { - title = "HHZ Grass"; - sprite = "HHZMA0"; - width = 16; - height = 40; - } - 2002 - { - title = "HHZ Tentacle 1"; - sprite = "HHZMB0"; - width = 16; - height = 40; - } - 2003 - { - title = "HHZ Tentacle 2"; - sprite = "HHZMC0"; - width = 16; - height = 40; - } - 2004 - { - title = "HHZ Stalagmite (Tall)"; - sprite = "HHZME0"; - width = 16; - height = 40; - } - 2005 - { - title = "HHZ Stalagmite (Short)"; - sprite = "HHZMF0"; - width = 16; - height = 40; - } - 2006 - { - title = "Jack-o'-lantern 1"; - sprite = "PUMKA0"; - width = 16; - height = 40; - flags1text = "Don't flicker"; - } - 2007 - { - title = "Jack-o'-lantern 2"; - sprite = "PUMKB0"; - width = 16; - height = 40; - flags1text = "Don't flicker"; - } - 2008 - { - title = "Jack-o'-lantern 3"; - sprite = "PUMKC0"; - width = 16; - height = 40; - flags1text = "Don't flicker"; - } - 2009 - { - title = "Purple Mushroom"; - sprite = "SHRMD0"; - width = 16; - height = 48; - } - 2010 - { - title = "HHZ Tree"; - sprite = "HHPLC0"; - width = 12; - height = 40; - } - } - - frozenhillside - { - color = 10; // Green - title = "Frozen Hillside"; - - 2100 - { - title = "Ice Shard (Small)"; - sprite = "FHZIA0"; - width = 8; - height = 32; - } - 2101 - { - title = "Ice Shard (Large)"; - sprite = "FHZIB0"; - width = 8; - height = 32; - } - 2102 - { - title = "Crystal Tree (Aqua)"; - sprite = "TRE3A0"; - width = 20; - height = 200; - } - 2103 - { - title = "Crystal Tree (Pink)"; - sprite = "TRE3B0"; - width = 20; - height = 200; - } - 2104 - { - title = "Amy Cameo"; - sprite = "ROSYA1"; - width = 16; - height = 48; - flags1text = "[1] Grayscale mode"; - } - 2105 - { - title = "Mistletoe"; - sprite = "XMS6A0"; - width = 52; - height = 106; - } - } - - flickies - { - color = 10; // Green - title = "Flickies"; - width = 8; - height = 20; - flags1text = "[1] Move aimlessly"; - flags4text = "[4] No movement"; - flags8text = "[8] Hop"; - angletext = "Radius"; - - 2200 - { - title = "Bluebird"; - sprite = "FL01A1"; - } - 2201 - { - title = "Rabbit"; - sprite = "FL02A1"; - } - 2202 - { - title = "Chicken"; - sprite = "FL03A1"; - } - 2203 - { - title = "Seal"; - sprite = "FL04A1"; - } - 2204 - { - title = "Pig"; - sprite = "FL05A1"; - } - 2205 - { - title = "Chipmunk"; - sprite = "FL06A1"; - } - 2206 - { - title = "Penguin"; - sprite = "FL07A1"; - } - 2207 - { - title = "Fish"; - sprite = "FL08A1"; - parametertext = "Color"; - } - 2208 - { - title = "Ram"; - sprite = "FL09A1"; - } - 2209 - { - title = "Puffin"; - sprite = "FL10A1"; - } - 2210 - { - title = "Cow"; - sprite = "FL11A1"; - } - 2211 - { - title = "Rat"; - sprite = "FL12A1"; - } - 2212 - { - title = "Bear"; - sprite = "FL13A1"; - } - 2213 - { - title = "Dove"; - sprite = "FL14A1"; - } - 2214 - { - title = "Cat"; - sprite = "FL15A1"; - } - 2215 - { - title = "Canary"; - sprite = "FL16A1"; - } - 2216 - { - title = "Spider"; - sprite = "FS01A1"; - } - 2217 - { - title = "Bat"; - sprite = "FS02A0"; - } - } -} - -//Default things filters -thingsfilters -{ - - filter0 - { - name = "Player starts"; - category = "starts"; - type = -1; - } - - - filter1 - { - name = "Enemies"; - category = "enemies"; - type = -1; - - } - - - filter2 - { - name = "NiGHTS Track"; - category = "nightstrk"; - type = -1; - - } - - - filter3 - { - name = "Normal Gravity"; - category = ""; - type = -1; - - fields - { - 2 = false; - } - - } - - - filter4 - { - name = "Reverse Gravity"; - category = ""; - type = -1; - - fields - { - 2 = true; - } - - } -} From 2dac47a54c4757871f5b8ee907ddd96b2daaf664 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 24 Dec 2019 12:19:13 +0100 Subject: [PATCH 143/312] Allow P_SpawnItemRow to spawn arbitrary mobjtypes (will be used in UDMF) --- src/p_mobj.c | 173 +++++++++++++++++++++++++++------------------------ 1 file changed, 90 insertions(+), 83 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 606c65014..427f3526d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11567,14 +11567,6 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, if (mobjtype == MT_AXIS || mobjtype == MT_AXISTRANSFER || mobjtype == MT_AXISTRANSFERLINE) return ONFLOORZ; - if (!offset) // Snap to the surfaces when there's no offset set. - { - if (flip) - return ONCEILINGZ; - else - return ONFLOORZ; - } - // Establish height. if (flip) return ( @@ -11649,6 +11641,14 @@ static fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthin offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; } + if (!offset) // Snap to the surfaces when there's no offset set. + { + if (flip) + return ONCEILINGZ; + else + return ONFLOORZ; + } + return P_GetMobjSpawnHeight(mobjtype, x, y, offset, flip); } @@ -11703,6 +11703,13 @@ static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) || (mthing->type >= 600 && mthing->type <= 609) // Special placement patterns || mthing->type == 1705 || mthing->type == 1713) // Hoops return true; // These are handled elsewhere. + else if (mthing->type == mobjinfo[MT_EMERHUNT].doomednum) + { + // Emerald Hunt is Coop only. Don't spawn the emerald yet, but save the spawnpoint for later. + if (gametype == GT_COOP && numhuntemeralds < MAXHUNTEMERALDS) + huntemeralds[numhuntemeralds++] = mthing; + return true; + } return false; } @@ -11728,14 +11735,6 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) return false; break; - case MT_EMERHUNT: - // Emerald Hunt is Coop only. - if (gametype != GT_COOP) - return false; - - if (numhuntemeralds < MAXHUNTEMERALDS) - huntemeralds[numhuntemeralds++] = mthing; - return false; case MT_EMERALDSPAWN: if (!cv_powerstones.value) return false; @@ -13004,47 +13003,12 @@ static void P_SetObjectSpecial(mobj_t *mobj) mobj->flags |= MF_BOUNCE; } } -// -// P_SpawnMapThing -// The fields of the mapthing should -// already be in host byte order. -// -mobj_t *P_SpawnMapThing(mapthing_t *mthing) + +mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, mobjtype_t i) { - mobjtype_t i; mobj_t *mobj = NULL; - fixed_t x, y, z; boolean doangle = true; - if (!mthing->type) - return mobj; // Ignore type-0 things as NOPs - - if (mthing->type == 3328) // 3D Mode start Thing - return mobj; - - if (!objectplacing && P_SpawnNonMobjMapThing(mthing)) - return mobj; - - i = P_GetMobjtype(mthing->type); - if (i == MT_UNKNOWN) - CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - - // Skip all returning/substitution code in objectplace. - if (!objectplacing) - { - if (!P_AllowMobjSpawn(mthing, i)) - return mobj; - - i = P_GetMobjtypeSubstitute(mthing, i); - if (i == MT_NULL) // Don't spawn mobj - return mobj; - } - - // spawn it - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - z = P_GetMapThingSpawnHeight(i, mthing, x, y); - mobj = P_SpawnMobj(x, y, z, i); mobj->spawnpoint = mthing; @@ -13052,7 +13016,7 @@ mobj_t *P_SpawnMapThing(mapthing_t *mthing) return mobj; if (doangle) - mobj->angle = FixedAngle(mthing->angle<angle = FixedAngle(mthing->angle << FRACBITS); mthing->mobj = mobj; @@ -13061,8 +13025,8 @@ mobj_t *P_SpawnMapThing(mapthing_t *mthing) return mobj; if ((mthing->options & MTF_AMBUSH) - && (mthing->options & MTF_OBJECTSPECIAL) - && (mobj->flags & MF_PUSHABLE)) + && (mthing->options & MTF_OBJECTSPECIAL) + && (mobj->flags & MF_PUSHABLE)) mobj->flags2 |= MF2_CLASSICPUSH; else { @@ -13097,6 +13061,47 @@ mobj_t *P_SpawnMapThing(mapthing_t *mthing) return mobj; } +// +// P_SpawnMapThing +// The fields of the mapthing should +// already be in host byte order. +// +mobj_t *P_SpawnMapThing(mapthing_t *mthing) +{ + mobjtype_t i; + mobj_t *mobj = NULL; + fixed_t x, y, z; + + if (!mthing->type) + return mobj; // Ignore type-0 things as NOPs + + if (mthing->type == 3328) // 3D Mode start Thing + return mobj; + + if (!objectplacing && P_SpawnNonMobjMapThing(mthing)) + return mobj; + + i = P_GetMobjtype(mthing->type); + if (i == MT_UNKNOWN) + CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); + + // Skip all returning/substitution code in objectplace. + if (!objectplacing) + { + if (!P_AllowMobjSpawn(mthing, i)) + return mobj; + + i = P_GetMobjtypeSubstitute(mthing, i); + if (i == MT_NULL) // Don't spawn mobj + return mobj; + } + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + z = P_GetMapThingSpawnHeight(i, mthing, x, y); + return P_SpawnMobjFromMapThing(mthing, x, y, z, i); +} + static void P_SpawnHoopInternal(mapthing_t *mthing, INT32 hoopsize, fixed_t sizefactor) { mobj_t *mobj = NULL; @@ -13223,21 +13228,29 @@ void P_SpawnBonusTimeItem(mapthing_t *mthing) P_SetMobjState(mobj, mobj->info->raisestate); } -static void P_SpawnItemRow(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle) +static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t itemtype, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle, boolean bonustime) { - mobjtype_t ringthing = MT_RING; + mapthing_t dummything = *mthing; mobj_t *mobj = NULL; + fixed_t x = mthing->x << FRACBITS; + fixed_t y = mthing->y << FRACBITS; + fixed_t z = mthing->z << FRACBITS; INT32 r; angle_t angle = FixedAngle(fixedangle << FRACBITS); angle_t fineangle = (angle >> ANGLETOFINESHIFT) & FINEMASK; - if (ultimatemode) - return; // No rings in Ultimate! + dummything.type = mobjinfo[itemtype].doomednum; + // Skip all returning/substitution code in objectplace. + if (!objectplacing) + { + if (!P_AllowMobjSpawn(&dummything, itemtype)) + return; - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - - z = P_GetMobjSpawnHeight(ringthing, x, y, z, mthing->options & MTF_OBJECTFLIP); + itemtype = P_GetMobjtypeSubstitute(&dummything, itemtype); + if (itemtype == MT_NULL) // Don't spawn + return; + } + z = P_GetMobjSpawnHeight(itemtype, x, y, z, mthing->options & MTF_OBJECTFLIP); for (r = 0; r < numitems; r++) { @@ -13245,20 +13258,14 @@ static void P_SpawnItemRow(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, y += FixedMul(horizontalspacing, FINESINE(fineangle)); z += (mthing->options & MTF_OBJECTFLIP) ? -verticalspacing : verticalspacing; - mobj = P_SpawnMobj(x, y, z, ringthing); + mobj = P_SpawnMobjFromMapThing(&dummything, x, y, z, itemtype); - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } + if (!mobj) + continue; - mobj->angle = angle; - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); + mobj->spawnpoint = NULL; + if (bonustime && (mobj->type == MT_BLUESPHERE || mobj->type == MT_NIGHTSCHIP)) + P_SetMobjState(mobj, mobj->info->raisestate); } } @@ -13271,6 +13278,9 @@ static void P_SpawnItemCircle(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t INT32 i; TVector v, *res; + if (metalrecording) + return; + z = P_GetMobjSpawnHeight(ringthing, x, y, z, false); closestangle = FixedAngle(mthing->angle << FRACBITS); @@ -13350,23 +13360,20 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) fixed_t y = mthing->y << FRACBITS; fixed_t z = mthing->z << FRACBITS; - if (metalrecording) - return; - switch (mthing->type) { // Special placement patterns case 600: // 5 vertical rings (yellow spring) - P_SpawnItemRow(mthing, x, y, z, 5, 0, 64*FRACUNIT, 0); + P_SpawnItemRow(mthing, MT_RING, 5, 0, 64*FRACUNIT, 0, bonustime); return; case 601: // 5 vertical rings (red spring) - P_SpawnItemRow(mthing, x, y, z, 5, 0, 128*FRACUNIT, 0); + P_SpawnItemRow(mthing, MT_RING, 5, 0, 128*FRACUNIT, 0, bonustime); return; case 602: // 5 diagonal rings (yellow spring) - P_SpawnItemRow(mthing, x, y, z, 5, 64*FRACUNIT, 64*FRACUNIT, mthing->angle); + P_SpawnItemRow(mthing, MT_RING, 5, 64*FRACUNIT, 64*FRACUNIT, mthing->angle, bonustime); return; case 603: // 10 diagonal rings (red spring) - P_SpawnItemRow(mthing, x, y, z, 10, 64*FRACUNIT, 64*FRACUNIT, mthing->angle); + P_SpawnItemRow(mthing, MT_RING, 10, 64*FRACUNIT, 64*FRACUNIT, mthing->angle, bonustime); return; case 604: // Circle of rings (8 items) case 605: // Circle of rings (16 items) From 72a1571937a6c4e33fb80b23969018b241769c71 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 24 Dec 2019 12:38:16 +0100 Subject: [PATCH 144/312] Allow P_SpawnItemCircle to spawn arbitrary mobjtypes (will be used in UDMF) --- src/p_mobj.c | 113 ++++++++++++++++++++------------------------------- 1 file changed, 45 insertions(+), 68 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 427f3526d..a72c59421 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13269,97 +13269,66 @@ static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t itemtype, INT32 numite } } -static void P_SpawnItemCircle(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, INT32 numitems, fixed_t size, boolean bonustime) +static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 numitemtypes, INT32 numitems, fixed_t size, boolean bonustime) { - mobjtype_t ringthing = MT_RING; - mobj_t *mobj = NULL; - fixed_t finalx, finaly, finalz; - angle_t closestangle, fa; + mapthing_t dummything; + mobj_t* mobj = NULL; + fixed_t x = mthing->x << FRACBITS; + fixed_t y = mthing->y << FRACBITS; + fixed_t z = mthing->z << FRACBITS; + angle_t angle = FixedAngle(mthing->angle << FRACBITS); + angle_t fa; INT32 i; TVector v, *res; - if (metalrecording) - return; - - z = P_GetMobjSpawnHeight(ringthing, x, y, z, false); - - closestangle = FixedAngle(mthing->angle << FRACBITS); - - switch (mthing->type) + for (i = 0; i < numitemtypes; i++) { - case 604: - case 605: - if (ultimatemode) - return; // No rings in Ultimate! - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - break; - case 608: - case 609: - /*ringthing = (i & 1) ? MT_RING : MT_BLUESPHERE; -- i == 0 is bluesphere - break;*/ - case 606: - case 607: - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - break; - default: - break; - } + dummything = *mthing; + dummything.type = mobjinfo[itemtypes[i]].doomednum; + // Skip all returning/substitution code in objectplace. + if (!objectplacing) + { + if (!P_AllowMobjSpawn(&dummything, itemtypes[i])) + { + itemtypes[i] = MT_NULL; + continue; + } + + itemtypes[i] = P_GetMobjtypeSubstitute(&dummything, itemtypes[i]); + } + } + z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, false); - // Create the hoop! for (i = 0; i < numitems; i++) { - if (mthing->type == 608 || mthing->type == 609) - { - if (i & 1) - { - if (ultimatemode) - continue; // No rings in Ultimate! - ringthing = (nightsreplace) ? MT_NIGHTSSTAR : MT_RING; - } - else - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - } + mobjtype_t itemtype = itemtypes[i % numitemtypes]; + if (itemtype == MT_NULL) + continue; + dummything.type = mobjinfo[itemtype].doomednum; - fa = i * FINEANGLES/numitems; + fa = i*FINEANGLES/numitems; v[0] = FixedMul(FINECOSINE(fa), size); v[1] = 0; v[2] = FixedMul(FINESINE(fa), size); v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); + res = VectorMatrixMultiply(v, *RotateZMatrix(angle)); M_Memcpy(&v, res, sizeof(v)); - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; + mobj = P_SpawnMobjFromMapThing(&dummything, x + v[0], y + v[1], z + v[2], itemtype); + + if (!mobj) + continue; - mobj = P_SpawnMobj(finalx, finaly, finalz, ringthing); mobj->z -= mobj->height/2; - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = closestangle; - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) + mobj->spawnpoint = NULL; + if (bonustime && (mobj->type == MT_BLUESPHERE || mobj->type == MT_NIGHTSCHIP)) P_SetMobjState(mobj, mobj->info->raisestate); - else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); } } void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) { - fixed_t x = mthing->x << FRACBITS; - fixed_t y = mthing->y << FRACBITS; - fixed_t z = mthing->z << FRACBITS; - switch (mthing->type) { // Special placement patterns @@ -13379,12 +13348,20 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) case 605: // Circle of rings (16 items) case 606: // Circle of blue spheres (8 items) case 607: // Circle of blue spheres (16 items) + { + INT32 numitems = (mthing->type & 1) ? 16 : 8; + fixed_t size = (mthing->type & 1) ? 192*FRACUNIT : 96*FRACUNIT; + mobjtype_t itemtypes[1] = { (mthing->type & 1) ? MT_RING : MT_BLUESPHERE }; + P_SpawnItemCircle(mthing, itemtypes, 1, numitems, size, bonustime); + return; + } case 608: // Circle of rings and blue spheres (8 items) case 609: // Circle of rings and blue spheres (16 items) { INT32 numitems = (mthing->type & 1) ? 16 : 8; fixed_t size = (mthing->type & 1) ? 192*FRACUNIT : 96*FRACUNIT; - P_SpawnItemCircle(mthing, x, y, z, numitems, size, bonustime); + mobjtype_t itemtypes[2] = { MT_RING, MT_BLUESPHERE }; + P_SpawnItemCircle(mthing, itemtypes, 2, numitems, size, bonustime); return; } default: From ac3a57aaf54802b0942c4b4b9c97a940136fbb35 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 24 Dec 2019 12:47:44 +0100 Subject: [PATCH 145/312] Allow P_SpawnItemRow to spawn different item types in the same row --- src/p_mobj.c | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index a72c59421..88397e43b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13228,9 +13228,9 @@ void P_SpawnBonusTimeItem(mapthing_t *mthing) P_SetMobjState(mobj, mobj->info->raisestate); } -static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t itemtype, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle, boolean bonustime) +static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t* itemtypes, UINT8 numitemtypes, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle, boolean bonustime) { - mapthing_t dummything = *mthing; + mapthing_t dummything; mobj_t *mobj = NULL; fixed_t x = mthing->x << FRACBITS; fixed_t y = mthing->y << FRACBITS; @@ -13239,21 +13239,31 @@ static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t itemtype, INT32 numite angle_t angle = FixedAngle(fixedangle << FRACBITS); angle_t fineangle = (angle >> ANGLETOFINESHIFT) & FINEMASK; - dummything.type = mobjinfo[itemtype].doomednum; - // Skip all returning/substitution code in objectplace. - if (!objectplacing) + for (r = 0; r < numitemtypes; r++) { - if (!P_AllowMobjSpawn(&dummything, itemtype)) - return; + dummything = *mthing; + dummything.type = mobjinfo[itemtypes[r]].doomednum; + // Skip all returning/substitution code in objectplace. + if (!objectplacing) + { + if (!P_AllowMobjSpawn(&dummything, itemtypes[r])) + { + itemtypes[r] = MT_NULL; + continue; + } - itemtype = P_GetMobjtypeSubstitute(&dummything, itemtype); - if (itemtype == MT_NULL) // Don't spawn - return; + itemtypes[r] = P_GetMobjtypeSubstitute(&dummything, itemtypes[r]); + } } - z = P_GetMobjSpawnHeight(itemtype, x, y, z, mthing->options & MTF_OBJECTFLIP); + z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, mthing->options & MTF_OBJECTFLIP); for (r = 0; r < numitems; r++) { + mobjtype_t itemtype = itemtypes[r % numitemtypes]; + if (itemtype == MT_NULL) + continue; + dummything.type = mobjinfo[itemtype].doomednum; + x += FixedMul(horizontalspacing, FINECOSINE(fineangle)); y += FixedMul(horizontalspacing, FINESINE(fineangle)); z += (mthing->options & MTF_OBJECTFLIP) ? -verticalspacing : verticalspacing; @@ -13269,6 +13279,12 @@ static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t itemtype, INT32 numite } } +static void P_SpawnSingularItemRow(mapthing_t* mthing, mobjtype_t itemtype, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle, boolean bonustime) +{ + mobjtype_t itemtypes[1] = { itemtype }; + return P_SpawnItemRow(mthing, itemtypes, 1, numitems, horizontalspacing, verticalspacing, fixedangle, bonustime); +} + static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 numitemtypes, INT32 numitems, fixed_t size, boolean bonustime) { mapthing_t dummything; @@ -13333,16 +13349,16 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) { // Special placement patterns case 600: // 5 vertical rings (yellow spring) - P_SpawnItemRow(mthing, MT_RING, 5, 0, 64*FRACUNIT, 0, bonustime); + P_SpawnSingularItemRow(mthing, MT_RING, 5, 0, 64*FRACUNIT, 0, bonustime); return; case 601: // 5 vertical rings (red spring) - P_SpawnItemRow(mthing, MT_RING, 5, 0, 128*FRACUNIT, 0, bonustime); + P_SpawnSingularItemRow(mthing, MT_RING, 5, 0, 128*FRACUNIT, 0, bonustime); return; case 602: // 5 diagonal rings (yellow spring) - P_SpawnItemRow(mthing, MT_RING, 5, 64*FRACUNIT, 64*FRACUNIT, mthing->angle, bonustime); + P_SpawnSingularItemRow(mthing, MT_RING, 5, 64*FRACUNIT, 64*FRACUNIT, mthing->angle, bonustime); return; case 603: // 10 diagonal rings (red spring) - P_SpawnItemRow(mthing, MT_RING, 10, 64*FRACUNIT, 64*FRACUNIT, mthing->angle, bonustime); + P_SpawnSingularItemRow(mthing, MT_RING, 10, 64*FRACUNIT, 64*FRACUNIT, mthing->angle, bonustime); return; case 604: // Circle of rings (8 items) case 605: // Circle of rings (16 items) From a57f903933fd232dea79f3c3e02eaaa28e4ae355 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 24 Dec 2019 12:52:43 +0100 Subject: [PATCH 146/312] Move bonus time handling into new function P_SetBonusTime() --- src/p_mobj.c | 20 ++++++++++++-------- src/p_mobj.h | 2 +- src/p_setup.c | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 88397e43b..866ffaf70 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13221,11 +13221,15 @@ void P_SpawnHoop(mapthing_t *mthing) P_SpawnHoopInternal(mthing, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); } -void P_SpawnBonusTimeItem(mapthing_t *mthing) +void P_SetBonusTime(mobj_t *mobj) { - mobj_t *mobj = P_SpawnMapThing(mthing); - if (mobj && (mobj->type == MT_BLUESPHERE || mobj->type == MT_NIGHTSCHIP)) - P_SetMobjState(mobj, mobj->info->raisestate); + if (!mobj) + return; + + if (mobj->type != MT_BLUESPHERE && mobj->type != MT_NIGHTSCHIP) + return; + + P_SetMobjState(mobj, mobj->info->raisestate); } static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t* itemtypes, UINT8 numitemtypes, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle, boolean bonustime) @@ -13274,8 +13278,8 @@ static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t* itemtypes, UINT8 numi continue; mobj->spawnpoint = NULL; - if (bonustime && (mobj->type == MT_BLUESPHERE || mobj->type == MT_NIGHTSCHIP)) - P_SetMobjState(mobj, mobj->info->raisestate); + if (bonustime) + P_SetBonusTime(mobj); } } @@ -13338,8 +13342,8 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n mobj->z -= mobj->height/2; mobj->spawnpoint = NULL; - if (bonustime && (mobj->type == MT_BLUESPHERE || mobj->type == MT_NIGHTSCHIP)) - P_SetMobjState(mobj, mobj->info->raisestate); + if (bonustime) + P_SetBonusTime(mobj); } } diff --git a/src/p_mobj.h b/src/p_mobj.h index 9b015d23c..a272003c1 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -458,7 +458,7 @@ void P_AfterPlayerSpawn(INT32 playernum); mobj_t *P_SpawnMapThing(mapthing_t *mthing); void P_SpawnHoop(mapthing_t *mthing); -void P_SpawnBonusTimeItem(mapthing_t *mthing); +void P_SetBonusTime(mobj_t *mobj); void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime); void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle); void P_SpawnPrecipitation(void); diff --git a/src/p_setup.c b/src/p_setup.c index 46fe118c4..41d61704f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -816,7 +816,7 @@ void P_ReloadRings(void) || mt->type == mobjinfo[MT_BLUESPHERE].doomednum || mt->type == mobjinfo[MT_BOMBSPHERE].doomednum) { mt->mobj = NULL; - P_SpawnBonusTimeItem(mt); + P_SetBonusTime(P_SpawnMapThing(mt)); } else if (mt->type >= 600 && mt->type <= 609) // Item patterns { From 13eb71e1ee5910f07eeae15931d2873f4ed9d576 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 24 Dec 2019 12:58:12 +0100 Subject: [PATCH 147/312] Fixed missing break in offset handling for horizontal springs --- src/p_mobj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 866ffaf70..13f75b94a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11618,6 +11618,7 @@ static fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthin case MT_REDHORIZ: case MT_BLUEHORIZ: offset += mthing->options & MTF_AMBUSH ? 16*FRACUNIT : 0; + break; // Ring-like items, may float additional units with MTF_AMBUSH. case MT_SPIKEBALL: From 0aa3c9b0a3655ae0ef86b435991a2fa0e9ed1f7d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 24 Dec 2019 13:01:17 +0100 Subject: [PATCH 148/312] Fixed missing break in offset handling for horizontal springs --- src/p_mobj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1acecbb76..e8186b752 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11603,6 +11603,7 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* case MT_REDHORIZ: case MT_BLUEHORIZ: offset += mthing->options & MTF_AMBUSH ? 16*FRACUNIT : 0; + break; // Ring-like items, may float additional units with MTF_AMBUSH. case MT_SPIKEBALL: From b740daf5bfc89b252ed2cf302af423323f77a44f Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Dec 2019 16:09:00 -0300 Subject: [PATCH 149/312] GTR_HURTMESSAGES --- src/dehacked.c | 1 + src/doomstat.h | 1 + src/p_inter.c | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 12aa8f970..18c4077be 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8899,6 +8899,7 @@ static const char *const GAMETYPERULE_LIST[] = { "ALLOWEXIT", "NOTITLECARD", "OVERTIME", + "HURTMESSAGES", NULL }; diff --git a/src/doomstat.h b/src/doomstat.h index 940d2d60c..6a708dc9b 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -416,6 +416,7 @@ enum GameTypeRules GTR_ALLOWEXIT = 1<<24, // Allow exit sectors GTR_NOTITLECARD = 1<<25, // Don't show the title card GTR_OVERTIME = 1<<26, // Allow overtime + GTR_HURTMESSAGES = 1<<27, // Hit and death messages }; // String names for gametypes diff --git a/src/p_inter.c b/src/p_inter.c index 08e8a62a1..8643b4275 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1888,7 +1888,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour char targetname[MAXPLAYERNAME+4]; char sourcename[MAXPLAYERNAME+4]; - if (G_PlatformGametype()) + if (!(gametyperules & (GTR_RINGSLINGER|GTR_HURTMESSAGES))) return; // Not in coop, etc. if (!player) From 5b4d587b1ae9df2e3aed431429ddb617b733b68c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Dec 2019 16:12:05 -0300 Subject: [PATCH 150/312] Don't warn about missing CTF starts if the gametype doesn't have team flags. --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index ead7e8c5c..91e788e1c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2720,7 +2720,7 @@ mapthing_t *G_FindCTFStart(INT32 playernum) if (!numredctfstarts && !numbluectfstarts) //why even bother, eh? { - if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer)) + if ((gametyperules & GTR_TEAMFLAGS) && (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))) CONS_Alert(CONS_WARNING, M_GetText("No CTF starts in this map!\n")); return NULL; } From 9319014d8d5d80420dbcc926c8dfa349f5fc9e9d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Dec 2019 16:22:25 -0300 Subject: [PATCH 151/312] Title card fixes. --- src/g_game.c | 19 ++++++++++++++++++- src/g_game.h | 1 + src/st_stuff.c | 9 +++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 91e788e1c..32d69b301 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1895,7 +1895,7 @@ void G_StartTitleCard(void) // The title card has been disabled for this map. // Oh well. - if ((mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD) || (gametyperules & GTR_NOTITLECARD)) + if (!G_IsTitleCardAvailable()) { WipeStageTitle = false; return; @@ -1938,6 +1938,23 @@ void G_PreLevelTitleCard(void) } } +// +// Returns true if the current level has a title card. +// +boolean G_IsTitleCardAvailable(void) +{ + // The current level header explicitly disabled the title card. + if (mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD) + return false; + + // The current gametype doesn't have a title card. + if (gametyperules & GTR_NOTITLECARD) + return false; + + // The title card is available. + return true; +} + INT32 pausedelay = 0; boolean pausebreakkey = false; static INT32 camtoggledelay, camtoggledelay2 = 0; diff --git a/src/g_game.h b/src/g_game.h index 4e577f51a..238dd1964 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -143,6 +143,7 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, void G_DoLoadLevel(boolean resetplayer); void G_StartTitleCard(void); void G_PreLevelTitleCard(void); +boolean G_IsTitleCardAvailable(void); void G_DeferedPlayDemo(const char *demo); // Can be called by the startup code or M_Responder, calls P_SetupLevel. diff --git a/src/st_stuff.c b/src/st_stuff.c index 6ff73e03a..3299c9d39 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1216,6 +1216,9 @@ void ST_startTitleCard(void) // void ST_preDrawTitleCard(void) { + if (!G_IsTitleCardAvailable()) + return; + if (lt_ticker >= (lt_endtime + TICRATE)) return; @@ -1231,6 +1234,9 @@ void ST_preDrawTitleCard(void) // void ST_runTitleCard(void) { + if (!G_IsTitleCardAvailable()) + return; + if (lt_ticker >= (lt_endtime + TICRATE)) return; @@ -1284,6 +1290,9 @@ void ST_drawTitleCard(void) INT32 zzticker; patch_t *actpat, *zigzag, *zztext; + if (!G_IsTitleCardAvailable()) + return; + #ifdef HAVE_BLUA if (!LUA_HudEnabled(hud_stagetitle)) goto luahook; From c61c1e2514588418d04c410784466cdae7ed9bdc Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Dec 2019 16:30:18 -0300 Subject: [PATCH 152/312] Turn the babysitting deterrent into its own rule. --- src/dehacked.c | 1 + src/doomstat.h | 3 ++- src/g_game.c | 14 +++++++------- src/p_mobj.c | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 18c4077be..b598d40ac 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8900,6 +8900,7 @@ static const char *const GAMETYPERULE_LIST[] = { "NOTITLECARD", "OVERTIME", "HURTMESSAGES", + "SPAWNINVUL", NULL }; diff --git a/src/doomstat.h b/src/doomstat.h index 6a708dc9b..2e3fe9b36 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -386,7 +386,7 @@ enum GameType }; // If you alter this list, update dehacked.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c -// Game type rules +// Gametype rules enum GameTypeRules { GTR_CAMPAIGN = 1, // Linear Co-op map progression, don't allow random maps @@ -417,6 +417,7 @@ enum GameTypeRules GTR_NOTITLECARD = 1<<25, // Don't show the title card GTR_OVERTIME = 1<<26, // Allow overtime GTR_HURTMESSAGES = 1<<27, // Hit and death messages + GTR_SPAWNINVUL = 1<<28, // Babysitting deterrent }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 32d69b301..b39205f50 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3197,22 +3197,22 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = // Co-op GTR_CAMPAIGN|GTR_LIVES|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, // Competition - GTR_RACE|GTR_LIVES|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_ALLOWEXIT, + GTR_RACE|GTR_LIVES|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_SPAWNINVUL|GTR_ALLOWEXIT, // Race - GTR_RACE|GTR_SPAWNENEMIES|GTR_ALLOWEXIT, + GTR_RACE|GTR_SPAWNENEMIES|GTR_SPAWNINVUL|GTR_ALLOWEXIT, // Match - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_PITYSHIELD|GTR_DEATHPENALTY, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD|GTR_DEATHPENALTY, // Team Match - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_SPAWNINVUL|GTR_PITYSHIELD, // Tag - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL, // Hide and Seek - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL, // CTF - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_TEAMFLAGS|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_TEAMFLAGS|GTR_SPAWNINVUL|GTR_PITYSHIELD, }; // diff --git a/src/p_mobj.c b/src/p_mobj.c index a10e6b3ba..d841ede05 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11297,7 +11297,7 @@ void P_SpawnPlayer(INT32 playernum) p->skincolor = skincolor_blueteam; } - if ((netgame || multiplayer) && (gametype != GT_COOP || leveltime) && !p->spectator && !(maptol & TOL_NIGHTS)) + if ((netgame || multiplayer) && ((gametyperules & GTR_SPAWNINVUL) || leveltime) && !p->spectator && !(maptol & TOL_NIGHTS)) p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER); From 25f8f2706bc51a4d65abb4729d7ce44b8b73e8e2 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Tue, 24 Dec 2019 13:55:19 -0600 Subject: [PATCH 153/312] Also cap dashspeed to at most maxdash. --- src/p_user.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index 003135a90..10d55ae0e 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4637,6 +4637,10 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) } if (player->dashspeed < player->mindash) player->dashspeed = player->mindash; + + if (player->dashspeed < player->maxdash) + player->dashspeed = player->maxdash; + if (player->dashspeed < player->maxdash && player->mindash != player->maxdash) { #define chargecalculation (6*(player->dashspeed - player->mindash))/(player->maxdash - player->mindash) From ddccfbd73d58a73d3f35eaa53b09d25289ae402f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 24 Dec 2019 21:07:55 +0100 Subject: [PATCH 154/312] P_MobjThinker(): Separate scale thinking and scenery thinking into their own functions --- src/p_mobj.c | 1714 ++++++++++++++++++++++++++------------------------ 1 file changed, 878 insertions(+), 836 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 13f75b94a..ab435afce 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7143,6 +7143,881 @@ static void P_PyreFlyBurn(mobj_t *mobj, fixed_t hoffs, INT16 vrange, mobjtype_t particle->momz = momz; } +static void P_MobjScaleThink(mobj_t *mobj) +{ + fixed_t oldheight = mobj->height; + UINT8 correctionType = 0; // Don't correct Z position, just gain height + + if ((mobj->flags & MF_NOCLIPHEIGHT || (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz)) + && mobj->type != MT_EGGMOBILE_FIRE) + correctionType = 1; // Correct Z position by centering + else if (mobj->eflags & MFE_VERTICALFLIP) + correctionType = 2; // Correct Z position by moving down + + if (abs(mobj->scale - mobj->destscale) < mobj->scalespeed) + P_SetScale(mobj, mobj->destscale); + else if (mobj->scale < mobj->destscale) + P_SetScale(mobj, mobj->scale + mobj->scalespeed); + else if (mobj->scale > mobj->destscale) + P_SetScale(mobj, mobj->scale - mobj->scalespeed); + + if (correctionType == 1) + mobj->z -= (mobj->height - oldheight)/2; + else if (correctionType == 2) + mobj->z -= mobj->height - oldheight; + + if (mobj->scale == mobj->destscale) + /// \todo Lua hook for "reached destscale"? + switch (mobj->type) + { + case MT_EGGMOBILE_FIRE: + mobj->destscale = FRACUNIT; + mobj->scalespeed = FRACUNIT>>4; + break; + default: + break; + } +} + +static void P_MaceSceneryThink(mobj_t *mobj) +{ + angle_t oldmovedir = mobj->movedir; + + // Always update movedir to prevent desyncing (in the traditional sense, not the netplay sense). + mobj->movedir = (mobj->movedir + mobj->lastlook) & FINEMASK; + + // If too far away and not deliberately spitting in the face of optimisation, don't think! + if (!(mobj->flags2 & MF2_BOSSNOTRAP)) + { + UINT8 i; + // Quick! Look through players! Don't move unless a player is relatively close by. + // The below is selected based on CEZ2's first room. I promise you it is a coincidence that it looks like the weed number. + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(P_AproxDistance(mobj->x - players[i].mo->x, mobj->y - players[i].mo->y), mobj->z - players[i].mo->z) < (4200 << FRACBITS)) + break; // Stop looking. + if (i == MAXPLAYERS) + { + if (!(mobj->flags2 & MF2_BEYONDTHEGRAVE)) + { + mobj_t *ref = mobj; + + // stop/hide all your babies + while ((ref = ref->hnext)) + { + ref->eflags = (((ref->flags & MF_NOTHINK) ? 0 : 1) + | ((ref->flags & MF_NOCLIPTHING) ? 0 : 2) + | ((ref->flags2 & MF2_DONTDRAW) ? 0 : 4)); // oh my god this is nasty. + ref->flags |= MF_NOTHINK|MF_NOCLIPTHING; + ref->flags2 |= MF2_DONTDRAW; + ref->momx = ref->momy = ref->momz = 0; + } + + mobj->flags2 |= MF2_BEYONDTHEGRAVE; + } + return; // don't make bubble! + } + else if (mobj->flags2 & MF2_BEYONDTHEGRAVE) + { + mobj_t *ref = mobj; + + // start/show all your babies + while ((ref = ref->hnext)) + { + if (ref->eflags & 1) + ref->flags &= ~MF_NOTHINK; + if (ref->eflags & 2) + ref->flags &= ~MF_NOCLIPTHING; + if (ref->eflags & 4) + ref->flags2 &= ~MF2_DONTDRAW; + ref->eflags = 0; // le sign + } + + mobj->flags2 &= ~MF2_BEYONDTHEGRAVE; + } + } + + // Okay, time to MOVE + P_MaceRotate(mobj, mobj->movedir, oldmovedir); +} + +static boolean P_DrownNumbersSceneryThink(mobj_t *mobj) +{ + if (!mobj->target) + { + P_RemoveMobj(mobj); + return false; + } + if (!mobj->target->player || !(mobj->target->player->powers[pw_underwater] || mobj->target->player->powers[pw_spacetime])) + { + P_RemoveMobj(mobj); + return false; + } + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + + mobj->destscale = mobj->target->destscale; + P_SetScale(mobj, mobj->target->scale); + + if (mobj->target->eflags & MFE_VERTICALFLIP) + { + mobj->z = mobj->target->z - FixedMul(16*FRACUNIT, mobj->target->scale) - mobj->height; + if (mobj->target->player->pflags & PF_FLIPCAM) + mobj->eflags |= MFE_VERTICALFLIP; + } + else + mobj->z = mobj->target->z + (mobj->target->height) + FixedMul(8*FRACUNIT, mobj->target->scale); // Adjust height for height changes + + if (mobj->threshold <= 35) + mobj->flags2 |= MF2_DONTDRAW; + else + mobj->flags2 &= ~MF2_DONTDRAW; + if (mobj->threshold <= 30) + mobj->threshold = 40; + mobj->threshold--; + return true; +} + +static void P_FlameJetSceneryThink(mobj_t *mobj) +{ + mobj_t *flame; + fixed_t strength; + + if (!(mobj->flags2 & MF2_FIRING)) + return; + + if ((leveltime & 3) == 0) + return; + + // Wave the flames back and forth. Reactiontime determines which direction it's going. + if (mobj->fuse <= -16) + mobj->reactiontime = 1; + else if (mobj->fuse >= 16) + mobj->reactiontime = 0; + + if (mobj->reactiontime) + mobj->fuse += 2; + else + mobj->fuse -= 2; + + flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); + P_SetMobjState(flame, S_FLAMEJETFLAME4); + + flame->angle = mobj->angle; + + if (mobj->flags2 & MF2_AMBUSH) // Wave up and down instead of side-to-side + flame->momz = mobj->fuse << (FRACBITS - 2); + else + flame->angle += FixedAngle(mobj->fuse<movedir; + + P_InstaThrust(flame, flame->angle, strength); + S_StartSound(flame, sfx_fire); +} + +static void P_VerticalFlameJetSceneryThink(mobj_t *mobj) +{ + mobj_t *flame; + fixed_t strength; + + if (!(mobj->flags2 & MF2_FIRING)) + return; + + if ((leveltime & 3) == 0) + return; + + // Wave the flames back and forth. Reactiontime determines which direction it's going. + if (mobj->fuse <= -16) + mobj->reactiontime = 1; + else if (mobj->fuse >= 16) + mobj->reactiontime = 0; + + if (mobj->reactiontime) + mobj->fuse++; + else + mobj->fuse--; + + flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); + + strength = 20*FRACUNIT; + strength -= ((20*FRACUNIT)/16)*mobj->movedir; + + // If deaf'd, the object spawns on the ceiling. + if (mobj->flags2 & MF2_AMBUSH) + { + mobj->z = mobj->ceilingz - mobj->height; + flame->momz = -strength; + } + else + { + flame->momz = strength; + P_SetMobjState(flame, S_FLAMEJETFLAME7); + } + P_InstaThrust(flame, mobj->angle, FixedDiv(mobj->fuse*FRACUNIT, 3*FRACUNIT)); + S_StartSound(flame, sfx_fire); +} + +static boolean P_ParticleGenSceneryThink(mobj_t *mobj) +{ + if (!mobj->lastlook) + return false; + + if (!mobj->threshold) + return false; + + if (--mobj->fuse <= 0) + { + INT32 i = 0; + mobj_t *spawn; + fixed_t bottomheight, topheight; + INT32 type = mobj->threshold, line = mobj->cvmem; + + mobj->fuse = (tic_t)mobj->reactiontime; + + bottomheight = lines[line].frontsector->floorheight; + topheight = lines[line].frontsector->ceilingheight - mobjinfo[(mobjtype_t)type].height; + + if (mobj->waterbottom != bottomheight || mobj->watertop != topheight) + { + if (mobj->movefactor && (topheight > bottomheight)) + mobj->health = (tic_t)(FixedDiv((topheight - bottomheight), abs(mobj->movefactor)) >> FRACBITS); + else + mobj->health = 0; + + mobj->z = ((mobj->flags2 & MF2_OBJECTFLIP) ? topheight : bottomheight); + } + + if (!mobj->health) + return false; + + for (i = 0; i < mobj->lastlook; i++) + { + spawn = P_SpawnMobj( + mobj->x + FixedMul(FixedMul(mobj->friction, mobj->scale), FINECOSINE(mobj->angle >> ANGLETOFINESHIFT)), + mobj->y + FixedMul(FixedMul(mobj->friction, mobj->scale), FINESINE(mobj->angle >> ANGLETOFINESHIFT)), + mobj->z, + (mobjtype_t)mobj->threshold); + P_SetScale(spawn, mobj->scale); + spawn->momz = FixedMul(mobj->movefactor, spawn->scale); + spawn->destscale = spawn->scale/100; + spawn->scalespeed = spawn->scale/mobj->health; + spawn->tics = (tic_t)mobj->health; + spawn->flags2 |= (mobj->flags2 & MF2_OBJECTFLIP); + spawn->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones + + mobj->angle += mobj->movedir; + } + + mobj->angle += (angle_t)mobj->movecount; + } + + return true; +} + +static void P_RosySceneryThink(mobj_t *mobj) +{ + 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 == 5) + 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); + // Tatsuru: Don't try to hug them if they're above or below you! + targonground = (P_IsObjectOnGround(mobj->target) && (player->panim == PA_IDLE || player->panim == PA_WALK || player->panim == PA_RUN) && player->mo->z == mobj->z); + love = (player->skin == 0 || player->skin == 5); + + 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 << FRACBITS, false); + S_StartSound(mobj, sfx_cdfm02); + } + + if (makeheart) + { + mobj_t *cdlhrt = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->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; + } + } +} + +static void P_MobjSceneryThink(mobj_t *mobj) +{ +#ifdef HAVE_BLUA + if (LUAh_MobjThinker(mobj)) + return; + if (P_MobjWasRemoved(mobj)) + return; +#endif + + if ((mobj->flags2 & MF2_SHIELD) && !P_AddShield(mobj)) + return; + + switch (mobj->type) + { + case MT_BOSSJUNK: + mobj->flags2 ^= MF2_DONTDRAW; + break; + case MT_MACEPOINT: + case MT_CHAINMACEPOINT: + case MT_SPRINGBALLPOINT: + case MT_CHAINPOINT: + case MT_FIREBARPOINT: + case MT_CUSTOMMACEPOINT: + case MT_HIDDEN_SLING: + P_MaceSceneryThink(mobj); + break; + case MT_HOOP: + if (mobj->fuse > 1) + P_MoveHoop(mobj); + else if (mobj->fuse == 1) + mobj->movecount = 1; + + if (mobj->movecount) + { + mobj->fuse++; + + if (mobj->fuse > 32) + { + // Don't kill the hoop center. For the sake of respawning. + //if (mobj->target) + // P_RemoveMobj(mobj->target); + + P_RemoveMobj(mobj); + } + } + else + mobj->fuse--; + return; + case MT_NIGHTSPARKLE: + if (mobj->tics != -1) + { + mobj->tics--; + + // you can cycle through multiple states in a tic + if (!mobj->tics) + if (!P_SetMobjState(mobj, mobj->state->nextstate)) + return; // freed itself + } + + P_UnsetThingPosition(mobj); + mobj->x += mobj->momx; + mobj->y += mobj->momy; + mobj->z += mobj->momz; + P_SetThingPosition(mobj); + return; + case MT_NIGHTSLOOPHELPER: + if (--mobj->tics <= 0) + P_RemoveMobj(mobj); + + // Don't touch my fuse! + return; + case MT_OVERLAY: + if (!mobj->target) + { + P_RemoveMobj(mobj); + return; + } + else + P_AddOverlay(mobj); + break; + case MT_PITY_ORB: + case MT_WHIRLWIND_ORB: + case MT_ARMAGEDDON_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + break; + case MT_ATTRACT_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (/*(mobj->target) -- the following is implicit by P_AddShield + && (mobj->target->player) + && */ (mobj->target->player->homing) && (mobj->target->player->pflags & PF_SHIELDABILITY)) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + } + break; + case MT_ELEMENTAL_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL */ + && mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->tracer->state - states) < mobj->info->raisestate + || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + break; + case MT_FORCE_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (/* + && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_FORCE) + && */ (mobj->target->player->pflags & PF_SHIELDABILITY)) + { + mobj_t *whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct + P_SetMobjState(whoosh, mobj->info->raisestate); + whoosh->destscale = whoosh->scale << 1; + whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale); + whoosh->height = 38*whoosh->scale; + whoosh->fuse = 10; + whoosh->flags |= MF_NOCLIPHEIGHT; + whoosh->momz = mobj->target->momz; // Stay reasonably centered for a few frames + mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal whoosh + } + /* FALLTHRU */ + case MT_FLAMEAURA_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if ((statenum_t)(mobj->state - states) < mobj->info->painstate) + mobj->angle = mobj->target->angle; // implicitly okay because of P_AddShield + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_FLAMEAURA */ + && mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->tracer->state - states) < mobj->info->raisestate + || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + break; + case MT_BUBBLEWRAP_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP */ + ) + { + if (mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->state - states) < mobj->info->painstate + || (mobj->state->nextstate < mobj->info->painstate && mobj->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + else if (mobj->target->eflags & MFE_JUSTHITFLOOR + && (statenum_t)(mobj->state - states) == mobj->info->painstate) + { + P_SetMobjState(mobj, mobj->info->painstate + 1); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate + 1); + mobj->tracer->tics++; + } + } + break; + case MT_THUNDERCOIN_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_THUNDERCOIN */ + && (mobj->target->player->pflags & PF_SHIELDABILITY)) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal spark + } + break; + case MT_WATERDROP: + P_SceneryCheckWater(mobj); + if ((mobj->z <= mobj->floorz || mobj->z <= mobj->watertop) + && mobj->health > 0) + { + mobj->health = 0; + P_SetMobjState(mobj, mobj->info->deathstate); + S_StartSound(mobj, mobj->info->deathsound + P_RandomKey(mobj->info->mass)); + return; + } + break; + case MT_BUBBLES: + P_SceneryCheckWater(mobj); + break; + case MT_SMALLBUBBLE: + case MT_MEDIUMBUBBLE: + case MT_EXTRALARGEBUBBLE: // start bubble dissipate + P_SceneryCheckWater(mobj); + if (P_MobjWasRemoved(mobj)) // bubble was removed by not being in water + return; + if (!(mobj->eflags & MFE_UNDERWATER) + || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height >= mobj->ceilingz) + || (mobj->eflags & MFE_VERTICALFLIP && mobj->z <= mobj->floorz) + || (P_CheckDeathPitCollide(mobj)) + || --mobj->fuse <= 0) // Bubbles eventually dissipate if they can't reach the surface. + { + // no playing sound: no point; the object is being removed + P_RemoveMobj(mobj); + return; + } + break; + case MT_LOCKON: + if (!mobj->target) + { + P_RemoveMobj(mobj); + return; + } + + mobj->flags2 &= ~MF2_DONTDRAW; + + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + + mobj->eflags |= (mobj->target->eflags & MFE_VERTICALFLIP); + + mobj->destscale = mobj->target->destscale; + P_SetScale(mobj, mobj->target->scale); + + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z = mobj->target->z + mobj->target->height + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale); + else + mobj->z = mobj->target->z - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale) - mobj->height; + break; + case MT_LOCKONINF: + if (!(mobj->flags2 & MF2_STRONGBOX)) + { + mobj->threshold = mobj->z; + mobj->flags2 |= MF2_STRONGBOX; + } + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z = mobj->threshold + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); + else + mobj->z = mobj->threshold - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); + break; + case MT_DROWNNUMBERS: + if (!P_DrownNumbersSceneryThink(mobj)) + return; + break; + case MT_FLAMEJET: + P_FlameJetSceneryThink(mobj); + break; + case MT_VERTICALFLAMEJET: + P_VerticalFlameJetSceneryThink(mobj); + break; + case MT_FLICKY_01_CENTER: + case MT_FLICKY_02_CENTER: + case MT_FLICKY_03_CENTER: + case MT_FLICKY_04_CENTER: + case MT_FLICKY_05_CENTER: + case MT_FLICKY_06_CENTER: + case MT_FLICKY_07_CENTER: + case MT_FLICKY_08_CENTER: + case MT_FLICKY_09_CENTER: + case MT_FLICKY_10_CENTER: + case MT_FLICKY_11_CENTER: + case MT_FLICKY_12_CENTER: + case MT_FLICKY_13_CENTER: + case MT_FLICKY_14_CENTER: + case MT_FLICKY_15_CENTER: + case MT_FLICKY_16_CENTER: + case MT_SECRETFLICKY_01_CENTER: + case MT_SECRETFLICKY_02_CENTER: + if (mobj->tracer && (mobj->flags & MF_NOCLIPTHING) + && (mobj->flags & MF_GRENADEBOUNCE)) + // for now: only do this bounce routine if flicky is in-place. \todo allow in all movements + { + if (!(mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z <= mobj->tracer->floorz) + mobj->tracer->momz = 7*FRACUNIT; + else if ((mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z >= mobj->tracer->ceilingz - mobj->tracer->height) + mobj->tracer->momz = -7*FRACUNIT; + } + break; + case MT_SEED: + if (P_MobjFlip(mobj)*mobj->momz < mobj->info->speed) + mobj->momz = P_MobjFlip(mobj)*mobj->info->speed; + break; + case MT_ROCKCRUMBLE1: + case MT_ROCKCRUMBLE2: + case MT_ROCKCRUMBLE3: + case MT_ROCKCRUMBLE4: + case MT_ROCKCRUMBLE5: + case MT_ROCKCRUMBLE6: + case MT_ROCKCRUMBLE7: + case MT_ROCKCRUMBLE8: + case MT_ROCKCRUMBLE9: + case MT_ROCKCRUMBLE10: + case MT_ROCKCRUMBLE11: + case MT_ROCKCRUMBLE12: + case MT_ROCKCRUMBLE13: + case MT_ROCKCRUMBLE14: + case MT_ROCKCRUMBLE15: + 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]) + { + P_SetMobjState(mobj, mobj->info->deathstate); + return; + } + break; + case MT_PARTICLEGEN: + if (!P_ParticleGenSceneryThink(mobj)) + return; + break; + case MT_FSGNA: + if (mobj->movedir) + mobj->angle += mobj->movedir; + break; + case MT_ROSY: + P_RosySceneryThink(mobj); + 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: + { + INT32 strength; + ++mobj->movedir; + mobj->frame &= ~FF_TRANSMASK; + strength = min(mobj->fuse, (INT32)mobj->movedir)*3; + if (strength < 10) + mobj->frame |= ((10 - strength) << (FF_TRANSSHIFT)); + } + /* FALLTHRU */ + default: + if (mobj->fuse) + { // Scenery object fuse! Very basic! + mobj->fuse--; + if (!mobj->fuse) + { +#ifdef HAVE_BLUA + if (!LUAh_MobjFuse(mobj)) +#endif + P_RemoveMobj(mobj); + return; + } + } + break; + } + + P_SceneryThinker(mobj); +} + // // P_MobjThinker // @@ -7171,7 +8046,7 @@ void P_MobjThinker(mobj_t *mobj) tmfloorthing = tmhitthing = NULL; - // 970 allows ANY mobj to trigger a linedef exec + // Sector special (2,8) allows ANY mobj to trigger a linedef exec if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8) { sector_t *sec2; @@ -7181,42 +8056,8 @@ void P_MobjThinker(mobj_t *mobj) P_LinedefExecute(sec2->tag, mobj, sec2); } - // Slowly scale up/down to reach your destscale. if (mobj->scale != mobj->destscale) - { - fixed_t oldheight = mobj->height; - UINT8 correctionType = 0; // Don't correct Z position, just gain height - - if ((mobj->flags & MF_NOCLIPHEIGHT || (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz)) - && mobj->type != MT_EGGMOBILE_FIRE) - correctionType = 1; // Correct Z position by centering - else if (mobj->eflags & MFE_VERTICALFLIP) - correctionType = 2; // Correct Z position by moving down - - if (abs(mobj->scale - mobj->destscale) < mobj->scalespeed) - P_SetScale(mobj, mobj->destscale); - else if (mobj->scale < mobj->destscale) - P_SetScale(mobj, mobj->scale + mobj->scalespeed); - else if (mobj->scale > mobj->destscale) - P_SetScale(mobj, mobj->scale - mobj->scalespeed); - - if (correctionType == 1) - mobj->z -= (mobj->height - oldheight)/2; - else if (correctionType == 2) - mobj->z -= mobj->height - oldheight; - - if (mobj->scale == mobj->destscale) - /// \todo Lua hook for "reached destscale"? - switch(mobj->type) - { - case MT_EGGMOBILE_FIRE: - mobj->destscale = FRACUNIT; - mobj->scalespeed = FRACUNIT>>4; - break; - default: - break; - } - } + P_MobjScaleThink(mobj); // Slowly scale up/down to reach your destscale. if ((mobj->type == MT_GHOST || mobj->type == MT_THOK) && mobj->fuse > 0) // Not guaranteed to be MF_SCENERY or not MF_SCENERY! { @@ -7237,806 +8078,7 @@ void P_MobjThinker(mobj_t *mobj) // Special thinker for scenery objects if (mobj->flags & MF_SCENERY) { -#ifdef HAVE_BLUA - if (LUAh_MobjThinker(mobj)) - return; - if (P_MobjWasRemoved(mobj)) - return; -#endif - - if (mobj->flags2 & MF2_SHIELD) - if (!P_AddShield(mobj)) - return; - - switch (mobj->type) - { - case MT_BOSSJUNK: - mobj->flags2 ^= MF2_DONTDRAW; - break; - case MT_MACEPOINT: - case MT_CHAINMACEPOINT: - case MT_SPRINGBALLPOINT: - case MT_CHAINPOINT: - case MT_FIREBARPOINT: - case MT_CUSTOMMACEPOINT: - case MT_HIDDEN_SLING: - { - angle_t oldmovedir = mobj->movedir; - - // Always update movedir to prevent desyncing (in the traditional sense, not the netplay sense). - mobj->movedir = (mobj->movedir + mobj->lastlook) & FINEMASK; - - // If too far away and not deliberately spitting in the face of optimisation, don't think! - if (!(mobj->flags2 & MF2_BOSSNOTRAP)) - { - UINT8 i; - // Quick! Look through players! Don't move unless a player is relatively close by. - // The below is selected based on CEZ2's first room. I promise you it is a coincidence that it looks like the weed number. - for (i = 0; i < MAXPLAYERS; ++i) - if (playeringame[i] && players[i].mo - && P_AproxDistance(P_AproxDistance(mobj->x - players[i].mo->x, mobj->y - players[i].mo->y), mobj->z - players[i].mo->z) < (4200<flags2 & MF2_BEYONDTHEGRAVE)) - { - mobj_t *ref = mobj; - - // stop/hide all your babies - while ((ref = ref->hnext)) - { - ref->eflags = (((ref->flags & MF_NOTHINK) ? 0 : 1) - | ((ref->flags & MF_NOCLIPTHING) ? 0 : 2) - | ((ref->flags2 & MF2_DONTDRAW) ? 0 : 4)); // oh my god this is nasty. - ref->flags |= MF_NOTHINK|MF_NOCLIPTHING; - ref->flags2 |= MF2_DONTDRAW; - ref->momx = ref->momy = ref->momz = 0; - } - - mobj->flags2 |= MF2_BEYONDTHEGRAVE; - } - - break; // don't make bubble! - } - else if (mobj->flags2 & MF2_BEYONDTHEGRAVE) - { - mobj_t *ref = mobj; - - // start/show all your babies - while ((ref = ref->hnext)) - { - if (ref->eflags & 1) - ref->flags &= ~MF_NOTHINK; - if (ref->eflags & 2) - ref->flags &= ~MF_NOCLIPTHING; - if (ref->eflags & 4) - ref->flags2 &= ~MF2_DONTDRAW; - ref->eflags = 0; // le sign - } - - mobj->flags2 &= ~MF2_BEYONDTHEGRAVE; - } - } - - // Okay, time to MOVE - P_MaceRotate(mobj, mobj->movedir, oldmovedir); - } - break; - case MT_HOOP: - if (mobj->fuse > 1) - P_MoveHoop(mobj); - else if (mobj->fuse == 1) - mobj->movecount = 1; - - if (mobj->movecount) - { - mobj->fuse++; - - if (mobj->fuse > 32) - { - // Don't kill the hoop center. For the sake of respawning. - //if (mobj->target) - // P_RemoveMobj(mobj->target); - - P_RemoveMobj(mobj); - } - } - else - mobj->fuse--; - return; - case MT_NIGHTSPARKLE: - if (mobj->tics != -1) - { - mobj->tics--; - - // you can cycle through multiple states in a tic - if (!mobj->tics) - if (!P_SetMobjState(mobj, mobj->state->nextstate)) - return; // freed itself - } - - P_UnsetThingPosition(mobj); - mobj->x += mobj->momx; - mobj->y += mobj->momy; - mobj->z += mobj->momz; - P_SetThingPosition(mobj); - return; - case MT_NIGHTSLOOPHELPER: - if (--mobj->tics <= 0) - P_RemoveMobj(mobj); - - // Don't touch my fuse! - return; - case MT_OVERLAY: - if (!mobj->target) - { - P_RemoveMobj(mobj); - return; - } - else - P_AddOverlay(mobj); - break; - case MT_PITY_ORB: - case MT_WHIRLWIND_ORB: - case MT_ARMAGEDDON_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - break; - case MT_ATTRACT_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if (/*(mobj->target) -- the following is implicit by P_AddShield - && (mobj->target->player) - && */ (mobj->target->player->homing) && (mobj->target->player->pflags & PF_SHIELDABILITY)) - { - P_SetMobjState(mobj, mobj->info->painstate); - mobj->tics++; - } - break; - case MT_ELEMENTAL_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if (mobj->tracer - /* && mobj->target -- the following is implicit by P_AddShield - && mobj->target->player - && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL */ - && mobj->target->player->pflags & PF_SHIELDABILITY - && ((statenum_t)(mobj->tracer->state-states) < mobj->info->raisestate - || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) - { - P_SetMobjState(mobj, mobj->info->painstate); - mobj->tics++; - P_SetMobjState(mobj->tracer, mobj->info->raisestate); - mobj->tracer->tics++; - } - break; - case MT_FORCE_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if (/* - && mobj->target -- the following is implicit by P_AddShield - && mobj->target->player - && (mobj->target->player->powers[pw_shield] & SH_FORCE) - && */ (mobj->target->player->pflags & PF_SHIELDABILITY)) - { - mobj_t *whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct - P_SetMobjState(whoosh, mobj->info->raisestate); - whoosh->destscale = whoosh->scale<<1; - whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale); - whoosh->height = 38*whoosh->scale; - whoosh->fuse = 10; - whoosh->flags |= MF_NOCLIPHEIGHT; - whoosh->momz = mobj->target->momz; // Stay reasonably centered for a few frames - mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal whoosh - } - /* FALLTHRU */ - case MT_FLAMEAURA_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if ((statenum_t)(mobj->state-states) < mobj->info->painstate) - mobj->angle = mobj->target->angle; // implicitly okay because of P_AddShield - if (mobj->tracer - /* && mobj->target -- the following is implicit by P_AddShield - && mobj->target->player - && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_FLAMEAURA */ - && mobj->target->player->pflags & PF_SHIELDABILITY - && ((statenum_t)(mobj->tracer->state-states) < mobj->info->raisestate - || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) - { - P_SetMobjState(mobj, mobj->info->painstate); - mobj->tics++; - P_SetMobjState(mobj->tracer, mobj->info->raisestate); - mobj->tracer->tics++; - } - break; - case MT_BUBBLEWRAP_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if (mobj->tracer - /* && mobj->target -- the following is implicit by P_AddShield - && mobj->target->player - && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP */ - ) - { - if (mobj->target->player->pflags & PF_SHIELDABILITY - && ((statenum_t)(mobj->state-states) < mobj->info->painstate - || (mobj->state->nextstate < mobj->info->painstate && mobj->tics == 1))) - { - P_SetMobjState(mobj, mobj->info->painstate); - mobj->tics++; - P_SetMobjState(mobj->tracer, mobj->info->raisestate); - mobj->tracer->tics++; - } - else if (mobj->target->eflags & MFE_JUSTHITFLOOR - && (statenum_t)(mobj->state-states) == mobj->info->painstate) - { - P_SetMobjState(mobj, mobj->info->painstate+1); - mobj->tics++; - P_SetMobjState(mobj->tracer, mobj->info->raisestate+1); - mobj->tracer->tics++; - } - } - break; - case MT_THUNDERCOIN_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if (mobj->tracer - /* && mobj->target -- the following is implicit by P_AddShield - && mobj->target->player - && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_THUNDERCOIN */ - && (mobj->target->player->pflags & PF_SHIELDABILITY)) - { - P_SetMobjState(mobj, mobj->info->painstate); - mobj->tics++; - P_SetMobjState(mobj->tracer, mobj->info->raisestate); - mobj->tracer->tics++; - mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal spark - } - break; - case MT_WATERDROP: - P_SceneryCheckWater(mobj); - if ((mobj->z <= mobj->floorz || mobj->z <= mobj->watertop) - && mobj->health > 0) - { - mobj->health = 0; - P_SetMobjState(mobj, mobj->info->deathstate); - S_StartSound(mobj, mobj->info->deathsound+P_RandomKey(mobj->info->mass)); - return; - } - break; - case MT_BUBBLES: - P_SceneryCheckWater(mobj); - break; - case MT_SMALLBUBBLE: - case MT_MEDIUMBUBBLE: - case MT_EXTRALARGEBUBBLE: // start bubble dissipate - P_SceneryCheckWater(mobj); - if (P_MobjWasRemoved(mobj)) // bubble was removed by not being in water - return; - if (!(mobj->eflags & MFE_UNDERWATER) - || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height >= mobj->ceilingz) - || (mobj->eflags & MFE_VERTICALFLIP && mobj->z <= mobj->floorz) - || (P_CheckDeathPitCollide(mobj)) - || --mobj->fuse <= 0) // Bubbles eventually dissipate if they can't reach the surface. - { - // no playing sound: no point; the object is being removed - P_RemoveMobj(mobj); - return; - } - break; - case MT_LOCKON: - if (!mobj->target) - { - P_RemoveMobj(mobj); - return; - } - - mobj->flags2 &= ~MF2_DONTDRAW; - - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - - mobj->eflags |= (mobj->target->eflags & MFE_VERTICALFLIP); - - mobj->destscale = mobj->target->destscale; - P_SetScale(mobj, mobj->target->scale); - - if (!(mobj->eflags & MFE_VERTICALFLIP)) - mobj->z = mobj->target->z + mobj->target->height + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale); - else - mobj->z = mobj->target->z - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale) - mobj->height; - break; - case MT_LOCKONINF: - if (!(mobj->flags2 & MF2_STRONGBOX)) - { - mobj->threshold = mobj->z; - mobj->flags2 |= MF2_STRONGBOX; - } - if (!(mobj->eflags & MFE_VERTICALFLIP)) - mobj->z = mobj->threshold + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); - else - mobj->z = mobj->threshold - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); - break; - case MT_DROWNNUMBERS: - if (!mobj->target) - { - P_RemoveMobj(mobj); - return; - } - if (!mobj->target->player || !(mobj->target->player->powers[pw_underwater] || mobj->target->player->powers[pw_spacetime])) - { - P_RemoveMobj(mobj); - return; - } - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - - mobj->destscale = mobj->target->destscale; - P_SetScale(mobj, mobj->target->scale); - - if (mobj->target->eflags & MFE_VERTICALFLIP) - { - mobj->z = mobj->target->z - FixedMul(16*FRACUNIT, mobj->target->scale) - mobj->height; - if (mobj->target->player->pflags & PF_FLIPCAM) - mobj->eflags |= MFE_VERTICALFLIP; - } - else - mobj->z = mobj->target->z + (mobj->target->height) + FixedMul(8*FRACUNIT, mobj->target->scale); // Adjust height for height changes - - if (mobj->threshold <= 35) - mobj->flags2 |= MF2_DONTDRAW; - else - mobj->flags2 &= ~MF2_DONTDRAW; - if (mobj->threshold <= 30) - mobj->threshold = 40; - mobj->threshold--; - break; - case MT_FLAMEJET: - if ((mobj->flags2 & MF2_FIRING) && (leveltime & 3) == 0) - { - mobj_t *flame; - fixed_t strength; - - // Wave the flames back and forth. Reactiontime determines which direction it's going. - if (mobj->fuse <= -16) - mobj->reactiontime = 1; - else if (mobj->fuse >= 16) - mobj->reactiontime = 0; - - if (mobj->reactiontime) - mobj->fuse += 2; - else - mobj->fuse -= 2; - - flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); - P_SetMobjState(flame, S_FLAMEJETFLAME4); - - flame->angle = mobj->angle; - - if (mobj->flags2 & MF2_AMBUSH) // Wave up and down instead of side-to-side - flame->momz = mobj->fuse << (FRACBITS-2); - else - flame->angle += FixedAngle(mobj->fuse*FRACUNIT); - - strength = 20*FRACUNIT; - strength -= ((20*FRACUNIT)/16)*mobj->movedir; - - P_InstaThrust(flame, flame->angle, strength); - S_StartSound(flame, sfx_fire); - } - break; - case MT_VERTICALFLAMEJET: - if ((mobj->flags2 & MF2_FIRING) && (leveltime & 3) == 0) - { - mobj_t *flame; - fixed_t strength; - - // Wave the flames back and forth. Reactiontime determines which direction it's going. - if (mobj->fuse <= -16) - mobj->reactiontime = 1; - else if (mobj->fuse >= 16) - mobj->reactiontime = 0; - - if (mobj->reactiontime) - mobj->fuse++; - else - mobj->fuse--; - - flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); - - strength = 20*FRACUNIT; - strength -= ((20*FRACUNIT)/16)*mobj->movedir; - - // If deaf'd, the object spawns on the ceiling. - if (mobj->flags2 & MF2_AMBUSH) - { - mobj->z = mobj->ceilingz-mobj->height; - flame->momz = -strength; - } - else - { - flame->momz = strength; - P_SetMobjState(flame, S_FLAMEJETFLAME7); - } - P_InstaThrust(flame, mobj->angle, FixedDiv(mobj->fuse*FRACUNIT,3*FRACUNIT)); - S_StartSound(flame, sfx_fire); - } - break; - case MT_FLICKY_01_CENTER: - case MT_FLICKY_02_CENTER: - case MT_FLICKY_03_CENTER: - case MT_FLICKY_04_CENTER: - case MT_FLICKY_05_CENTER: - case MT_FLICKY_06_CENTER: - case MT_FLICKY_07_CENTER: - case MT_FLICKY_08_CENTER: - case MT_FLICKY_09_CENTER: - case MT_FLICKY_10_CENTER: - case MT_FLICKY_11_CENTER: - case MT_FLICKY_12_CENTER: - case MT_FLICKY_13_CENTER: - case MT_FLICKY_14_CENTER: - case MT_FLICKY_15_CENTER: - case MT_FLICKY_16_CENTER: - case MT_SECRETFLICKY_01_CENTER: - case MT_SECRETFLICKY_02_CENTER: - if (mobj->tracer && (mobj->flags & MF_NOCLIPTHING) - && (mobj->flags & MF_GRENADEBOUNCE)) - // for now: only do this bounce routine if flicky is in-place. \todo allow in all movements - { - if (!(mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z <= mobj->tracer->floorz) - mobj->tracer->momz = 7*FRACUNIT; - else if ((mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z >= mobj->tracer->ceilingz - mobj->tracer->height) - mobj->tracer->momz = -7*FRACUNIT; - } - break; - case MT_SEED: - if (P_MobjFlip(mobj)*mobj->momz < mobj->info->speed) - mobj->momz = P_MobjFlip(mobj)*mobj->info->speed; - break; - case MT_ROCKCRUMBLE1: - case MT_ROCKCRUMBLE2: - case MT_ROCKCRUMBLE3: - case MT_ROCKCRUMBLE4: - case MT_ROCKCRUMBLE5: - case MT_ROCKCRUMBLE6: - case MT_ROCKCRUMBLE7: - case MT_ROCKCRUMBLE8: - case MT_ROCKCRUMBLE9: - case MT_ROCKCRUMBLE10: - case MT_ROCKCRUMBLE11: - case MT_ROCKCRUMBLE12: - case MT_ROCKCRUMBLE13: - case MT_ROCKCRUMBLE14: - case MT_ROCKCRUMBLE15: - 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]) - { - P_SetMobjState(mobj, mobj->info->deathstate); - return; - } - break; - case MT_PARTICLEGEN: - if (!mobj->lastlook) - return; - - if (!mobj->threshold) - return; - - if (--mobj->fuse <= 0) - { - INT32 i = 0; - mobj_t *spawn; - fixed_t bottomheight, topheight; - INT32 type = mobj->threshold, line = mobj->cvmem; - - mobj->fuse = (tic_t)mobj->reactiontime; - - bottomheight = lines[line].frontsector->floorheight; - topheight = lines[line].frontsector->ceilingheight - mobjinfo[(mobjtype_t)type].height; - - if (mobj->waterbottom != bottomheight || mobj->watertop != topheight) - { - if (mobj->movefactor && (topheight > bottomheight)) - mobj->health = (tic_t)(FixedDiv((topheight - bottomheight), abs(mobj->movefactor)) >> FRACBITS); - else - mobj->health = 0; - - mobj->z = ((mobj->flags2 & MF2_OBJECTFLIP) ? topheight : bottomheight); - } - - if (!mobj->health) - return; - - for (i = 0; i < mobj->lastlook; i++) - { - spawn = P_SpawnMobj( - mobj->x + FixedMul(FixedMul(mobj->friction, mobj->scale), FINECOSINE(mobj->angle>>ANGLETOFINESHIFT)), - mobj->y + FixedMul(FixedMul(mobj->friction, mobj->scale), FINESINE(mobj->angle>>ANGLETOFINESHIFT)), - mobj->z, - (mobjtype_t)mobj->threshold); - P_SetScale(spawn, mobj->scale); - spawn->momz = FixedMul(mobj->movefactor, spawn->scale); - spawn->destscale = spawn->scale/100; - spawn->scalespeed = spawn->scale/mobj->health; - spawn->tics = (tic_t)mobj->health; - spawn->flags2 |= (mobj->flags2 & MF2_OBJECTFLIP); - spawn->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones - - mobj->angle += mobj->movedir; - } - - mobj->angle += (angle_t)mobj->movecount; - } - break; - case MT_FSGNA: - 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 == 5) - 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); - // Tatsuru: Don't try to hug them if they're above or below you! - targonground = (P_IsObjectOnGround(mobj->target) && (player->panim == PA_IDLE || player->panim == PA_WALK || player->panim == PA_RUN) && player->mo->z == mobj->z); - love = (player->skin == 0 || player->skin == 5); - - 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: - { - INT32 strength; - ++mobj->movedir; - mobj->frame &= ~FF_TRANSMASK; - strength = min(mobj->fuse, (INT32)mobj->movedir)*3; - if (strength < 10) - mobj->frame |= ((10-strength)<<(FF_TRANSSHIFT)); - } - /* FALLTHRU */ - default: - if (mobj->fuse) - { // Scenery object fuse! Very basic! - mobj->fuse--; - if (!mobj->fuse) - { -#ifdef HAVE_BLUA - if (!LUAh_MobjFuse(mobj)) -#endif - P_RemoveMobj(mobj); - return; - } - } - break; - } - - P_SceneryThinker(mobj); + P_MobjSceneryThink(mobj); return; } From b49672e3f91da252ca1cd882e0fb1dc75f1b5ccc Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 24 Dec 2019 17:44:06 -0500 Subject: [PATCH 155/312] Change this condition a bit --- src/p_inter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 5ec1161ea..52b84059f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3439,13 +3439,13 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) } } - if (inflictor->type == MT_LHRT) - return; - if (source->player->ctfteam == player->ctfteam) return; } + if (inflictor->type == MT_LHRT) + return; + if (player->powers[pw_shield] || player->bot) //If One-Hit Shield { P_RemoveShield(player); From 8d8e0ca22c79df5cfee65622e78ca1645ed0cddd Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 24 Dec 2019 17:45:57 -0500 Subject: [PATCH 156/312] Clean up comment --- src/p_inter.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 52b84059f..064551c8c 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3426,8 +3426,6 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) return; - // Don't allow players to hurt one another, - // unless cv_friendlyfire is on. if (!cv_friendlyfire.value) { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) From 5d89e915c6099ec20034ef37212c2dde034b122d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 25 Dec 2019 00:14:53 +0100 Subject: [PATCH 157/312] Continue cutting up P_MobjThinker into multiple functions --- src/p_mobj.c | 3500 ++++++++++++++++++++++++++------------------------ 1 file changed, 1793 insertions(+), 1707 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index ab435afce..84592dcaa 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8018,6 +8018,1791 @@ static void P_MobjSceneryThink(mobj_t *mobj) P_SceneryThinker(mobj); } +static boolean P_MobjPushableThink(mobj_t *mobj) +{ + P_MobjCheckWater(mobj); + P_PushableThinker(mobj); + + // Extinguish fire objects in water. (Yes, it's extraordinarily rare to have a pushable flame object, but Brak uses such a case.) + if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL + && (mobj->eflags & (MFE_UNDERWATER | MFE_TOUCHWATER))) + { + P_KillMobj(mobj, NULL, NULL, 0); + return false; + } + + return true; +} + +static boolean P_MobjBossThink(mobj_t *mobj) +{ +#ifdef HAVE_BLUA + if (LUAh_BossThinker(mobj)) + { + if (P_MobjWasRemoved(mobj)) + return false; + } + else if (P_MobjWasRemoved(mobj)) + return false; + else +#endif + switch (mobj->type) + { + case MT_EGGMOBILE: + if (mobj->health < mobj->info->damage + 1 && leveltime & 2) + { + fixed_t rad = mobj->radius >> FRACBITS; + fixed_t hei = mobj->height >> FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(hei / 2, hei) << FRACBITS, + MT_SMOKE); + P_SetObjectMomZ(particle, 2 << FRACBITS, false); + particle->momz += mobj->momz; + } + if (mobj->flags2 & MF2_SKULLFLY) +#if 1 + P_SpawnGhostMobj(mobj); +#else // all the way back from final demo... MT_THOK isn't even the same size anymore! + { + mobj_t *spawnmobj; + spawnmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->painchance); + P_SetTarget(&spawnmobj->target, mobj); + spawnmobj->color = SKINCOLOR_GREY; + } +#endif + P_Boss1Thinker(mobj); + break; + case MT_EGGMOBILE2: + if (mobj->health < mobj->info->damage + 1 && leveltime & 2) + { + fixed_t rad = mobj->radius >> FRACBITS; + fixed_t hei = mobj->height >> FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(hei/2, hei) << FRACBITS, + MT_SMOKE); + P_SetObjectMomZ(particle, 2 << FRACBITS, false); + particle->momz += mobj->momz; + } + P_Boss2Thinker(mobj); + break; + case MT_EGGMOBILE3: + if (mobj->health < mobj->info->damage + 1 && leveltime & 2) + { + fixed_t rad = mobj->radius >> FRACBITS; + fixed_t hei = mobj->height >> FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(hei/2, hei) << FRACBITS, + MT_SMOKE); + P_SetObjectMomZ(particle, 2 << FRACBITS, false); + particle->momz += mobj->momz; + } + P_Boss3Thinker(mobj); + break; + case MT_EGGMOBILE4: + if (mobj->health < mobj->info->damage + 1 && leveltime & 2) + { + fixed_t rad = mobj->radius >> FRACBITS; + fixed_t hei = mobj->height >> FRACBITS; + mobj_t* particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(hei/2, hei) << FRACBITS, + MT_SMOKE); + P_SetObjectMomZ(particle, 2 << FRACBITS, false); + particle->momz += mobj->momz; + } + P_Boss4Thinker(mobj); + break; + case MT_FANG: + P_Boss5Thinker(mobj); + break; + case MT_BLACKEGGMAN: + P_Boss7Thinker(mobj); + break; + case MT_METALSONIC_BATTLE: + P_Boss9Thinker(mobj); + break; + default: // Generic SOC-made boss + if (mobj->flags2 & MF2_SKULLFLY) + P_SpawnGhostMobj(mobj); + P_GenericBossThinker(mobj); + break; + } + if (mobj->flags2 & MF2_BOSSFLEE) + { + if (mobj->extravalue1) + { + if (!(--mobj->extravalue1)) + { + if (mobj->target) + { + mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, P_AproxDistance(mobj->x - mobj->target->x, mobj->y - mobj->target->y)), mobj->scale << 1); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + } + else + mobj->momz = 8*mobj->scale; + } + else + mobj->angle += mobj->movedir; + } + else if (mobj->target) + P_InstaThrust(mobj, mobj->angle, FixedMul(12*FRACUNIT, mobj->scale)); + } + if (mobj->type == MT_CYBRAKDEMON && !mobj->health) + { + if (!(mobj->tics & 1)) + { + var1 = 2; + var2 = 0; + A_BossScream(mobj); + } + if (P_CheckDeathPitCollide(mobj)) + { + P_RemoveMobj(mobj); + return false; + } + if (mobj->momz && mobj->z + mobj->momz <= mobj->floorz) + { + S_StartSound(mobj, sfx_befall); + if (mobj->state != states + S_CYBRAKDEMON_DIE8) + P_SetMobjState(mobj, S_CYBRAKDEMON_DIE8); + } + } + return true; +} + +static boolean P_MobjDeadThink(mobj_t *mobj) +{ + switch (mobj->type) + { + case MT_BLUESPHERE: + if ((mobj->tics >> 2) + 1 > 0 && (mobj->tics >> 2) + 1 <= tr_trans60) // tr_trans50 through tr_trans90, shifting once every second frame + mobj->frame = (NUMTRANSMAPS - ((mobj->tics >> 2) + 1)) << FF_TRANSSHIFT; + else // tr_trans60 otherwise + mobj->frame = tr_trans60 << FF_TRANSSHIFT; + break; + case MT_EGGCAPSULE: + if (mobj->z <= mobj->floorz) + { + P_RemoveMobj(mobj); + return false; + } + break; + case MT_FAKEMOBILE: + if (mobj->scale == mobj->destscale) + { + if (!mobj->fuse) + { + S_StartSound(mobj, sfx_s3k77); + mobj->flags2 |= MF2_DONTDRAW; + mobj->fuse = TICRATE; + } + return false; + } + if (!mobj->reactiontime) + { + if (P_RandomChance(FRACUNIT/2)) + mobj->movefactor = FRACUNIT; + else + mobj->movefactor = -FRACUNIT; + if (P_RandomChance(FRACUNIT/2)) + mobj->movedir = ANG20; + else + mobj->movedir = -ANG20; + mobj->reactiontime = 5; + } + mobj->momz += mobj->movefactor; + mobj->angle += mobj->movedir; + P_InstaThrust(mobj, mobj->angle, -mobj->info->speed); + mobj->reactiontime--; + break; + case MT_EGGSHIELD: + mobj->flags2 ^= MF2_DONTDRAW; + break; + case MT_EGGTRAP: // Egg Capsule animal release + if (mobj->fuse > 0)// && mobj->fuse < TICRATE-(TICRATE/7)) + { + INT32 i; + fixed_t x, y, z; + fixed_t ns; + mobj_t* mo2; + mobj_t* flicky; + + z = mobj->subsector->sector->floorheight + FRACUNIT + (P_RandomKey(64) << FRACBITS); + for (i = 0; i < 3; i++) + { + const angle_t fa = P_RandomKey(FINEANGLES) & FINEMASK; + ns = 64*FRACUNIT; + x = mobj->x + FixedMul(FINESINE(fa), ns); + y = mobj->y + FixedMul(FINECOSINE(fa), ns); + + mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); + P_SetMobjStateNF(mo2, S_XPLD_EGGTRAP); // so the flickies don't lose their target if they spawn + ns = 4*FRACUNIT; + mo2->momx = FixedMul(FINESINE(fa), ns); + mo2->momy = FixedMul(FINECOSINE(fa), ns); + mo2->angle = fa << ANGLETOFINESHIFT; + + if (!i && !(mobj->fuse & 2)) + S_StartSound(mo2, mobj->info->deathsound); + + flicky = P_InternalFlickySpawn(mo2, 0, 8*FRACUNIT, false, -1); + if (!flicky) + break; + + P_SetTarget(&flicky->target, mo2); + flicky->momx = mo2->momx; + flicky->momy = mo2->momy; + } + + mobj->fuse--; + } + break; + case MT_PLAYER: + /// \todo Have the player's dead body completely finish its animation even if they've already respawned. + if (!mobj->fuse) + { // Go away. + /// \todo Actually go ahead and remove mobj completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it. + mobj->momz = 0; + if (mobj->player) + mobj->flags2 |= MF2_DONTDRAW; + else // safe to remove, nobody's going to complain! + { + P_RemoveMobj(mobj); + return false; + } + } + else // Apply gravity to fall downwards. + { + if (mobj->player && !(mobj->fuse % 8) && (mobj->player->charflags & SF_MACHINE)) + { + fixed_t r = mobj->radius >> FRACBITS; + mobj_t *explosion = P_SpawnMobj( + mobj->x + (P_RandomRange(r, -r) << FRACBITS), + mobj->y + (P_RandomRange(r, -r) << FRACBITS), + mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), + MT_SONIC3KBOSSEXPLODE); + S_StartSound(explosion, sfx_s3kb4); + } + if (mobj->movedir == DMG_DROWNED) + P_SetObjectMomZ(mobj, -FRACUNIT/2, true); // slower fall from drowning + else + P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true); + } + break; + case MT_METALSONIC_RACE: + { + if (!(mobj->fuse % 8)) + { + fixed_t r = mobj->radius >> FRACBITS; + mobj_t *explosion = P_SpawnMobj( + mobj->x + (P_RandomRange(r, -r) << FRACBITS), + mobj->y + (P_RandomRange(r, -r) << FRACBITS), + mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), + MT_SONIC3KBOSSEXPLODE); + S_StartSound(explosion, sfx_s3kb4); + } + P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true); + } + break; + default: + break; + } + return true; +} + +// Angle-to-tracer to trigger a linedef exec +// See Linedef Exec 457 (Track mobj angle to point) +static void P_TracerAngleThink(mobj_t *mobj) +{ + if (!mobj->tracer) + return; + + if (!mobj->extravalue2) + return; + + // mobj->lastlook - Don't disable behavior after first failure + // mobj->extravalue1 - Angle tolerance + // mobj->extravalue2 - Exec tag upon failure + // mobj->cvval - Allowable failure delay + // mobj->cvmem - Failure timer + + angle_t ang = mobj->angle - R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); + + // \todo account for distance between mobj and tracer + // Because closer mobjs can be facing beyond the angle tolerance + // yet tracer is still in the camera view + + // failure state: mobj is not facing tracer + // Reasaonable defaults: ANGLE_67h, ANGLE_292h + if (ang >= (angle_t)mobj->extravalue1 && ang <= ANGLE_MAX - (angle_t)mobj->extravalue1) + { + if (mobj->cvmem) + mobj->cvmem--; + else + { + INT32 exectag = mobj->extravalue2; // remember this before we erase the values + + if (mobj->lastlook) + mobj->cvmem = mobj->cusval; // reset timer for next failure + else + { + // disable after first failure + mobj->eflags &= ~MFE_TRACERANGLE; + mobj->lastlook = mobj->extravalue1 = mobj->extravalue2 = mobj->cvmem = mobj->cusval = 0; + } + + P_LinedefExecute(exectag, mobj, NULL); + } + } + else + mobj->cvmem = mobj->cusval; // reset failure timer +} + +static void P_ArrowThink(mobj_t *mobj) +{ + if (mobj->flags & MF_MISSILE) + { + // Calculate the angle of movement. + /* + momz + / | + / | + / | + 0------dist(momx,momy) + */ + + fixed_t dist = P_AproxDistance(mobj->momx, mobj->momy); + angle_t angle = R_PointToAngle2(0, 0, dist, mobj->momz); + + if (angle > ANG20 && angle <= ANGLE_180) + mobj->frame = 2; + else if (angle < ANG340 && angle > ANGLE_180) + mobj->frame = 0; + else + mobj->frame = 1; + + if (!(mobj->extravalue1) && (mobj->momz < 0)) + { + mobj->extravalue1 = 1; + S_StartSound(mobj, mobj->info->activesound); + } + if (leveltime & 1) + { + mobj_t *dust = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_PARTICLE); + dust->tics = 18; + dust->scalespeed = 4096; + dust->destscale = FRACUNIT/32; + } + } + else + mobj->flags2 ^= MF2_DONTDRAW; +} + +static void P_BumbleboreThink(mobj_t *mobj) +{ + statenum_t st = mobj->state - states; + if (st == S_BUMBLEBORE_FLY1 || st == S_BUMBLEBORE_FLY2) + { + if (!mobj->target) + P_SetMobjState(mobj, mobj->info->spawnstate); + else if (P_MobjFlip(mobj)*((mobj->z + (mobj->height >> 1)) - (mobj->target->z + (mobj->target->height >> 1))) > 0 + && R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) <= 32*FRACUNIT) + { + mobj->momx >>= 1; + mobj->momy >>= 1; + if (++mobj->movefactor == 4) + { + S_StartSound(mobj, mobj->info->seesound); + mobj->momx = mobj->momy = mobj->momz = 0; + mobj->flags = (mobj->flags|MF_PAIN) & ~MF_NOGRAVITY; + P_SetMobjState(mobj, mobj->info->meleestate); + } + } + else + mobj->movefactor = 0; + } + else if (st == S_BUMBLEBORE_RAISE || st == S_BUMBLEBORE_FALL2) // no _FALL1 because it's an 0-tic + { + if (P_IsObjectOnGround(mobj)) + { + S_StopSound(mobj); + S_StartSound(mobj, mobj->info->attacksound); + mobj->flags = (mobj->flags | MF_NOGRAVITY) & ~MF_PAIN; + mobj->momx = mobj->momy = mobj->momz = 0; + P_SetMobjState(mobj, mobj->info->painstate); + } + else + { + mobj->angle += ANGLE_22h; + mobj->frame = mobj->state->frame + ((mobj->tics & 2) >> 1); + } + } + else if (st == S_BUMBLEBORE_STUCK2 && mobj->tics < TICRATE) + mobj->frame = mobj->state->frame + ((mobj->tics & 2) >> 1); +} + +static boolean P_HangsterThink(mobj_t *mobj) +{ + statenum_t st = mobj->state - states; + //ghost image trail when flying down + if (st == S_HANGSTER_SWOOP1 || st == S_HANGSTER_SWOOP2) + { + P_SpawnGhostMobj(mobj); + //curve when in line with target, otherwise curve to avoid crashing into floor + if ((mobj->z - mobj->floorz <= 80*FRACUNIT) || (mobj->target && (mobj->z - mobj->target->z <= 80*FRACUNIT))) + P_SetMobjState(mobj, (st = S_HANGSTER_ARC1)); + } + + //swoop arc movement stuff + if (st == S_HANGSTER_ARC1) + { + A_FaceTarget(mobj); + P_Thrust(mobj, mobj->angle, 1*FRACUNIT); + } + else if (st == S_HANGSTER_ARC2) + P_Thrust(mobj, mobj->angle, 2*FRACUNIT); + else if (st == S_HANGSTER_ARC3) + P_Thrust(mobj, mobj->angle, 4*FRACUNIT); + //if movement has stopped while flying (like hitting a wall), fly up immediately + else if (st == S_HANGSTER_FLY1 && !mobj->momx && !mobj->momy) + { + mobj->extravalue1 = 0; + P_SetMobjState(mobj, S_HANGSTER_ARCUP1); + } + //after swooping back up, check for ceiling + else if ((st == S_HANGSTER_RETURN1 || st == S_HANGSTER_RETURN2) && mobj->momz == 0 && mobj->ceilingz == (mobj->z + mobj->height)) + P_SetMobjState(mobj, (st = S_HANGSTER_RETURN3)); + + //should you roost on a ceiling with F_SKY1 as its flat, disappear forever + if (st == S_HANGSTER_RETURN3 && mobj->momz == 0 && mobj->ceilingz == (mobj->z + mobj->height) + && mobj->subsector->sector->ceilingpic == skyflatnum + && mobj->subsector->sector->ceilingheight == mobj->ceilingz) + { + P_RemoveMobj(mobj); + return false; + } + + return true; +} + +static boolean P_JetFume1Think(mobj_t *mobj) +{ + fixed_t jetx, jety; + + if (!mobj->target // if you have no target + || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now + { // then remove yourself as well! + P_RemoveMobj(mobj); + return false; + } + + jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); + jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); + + if (mobj->fuse == 56) // First one + { + P_UnsetThingPosition(mobj); + mobj->x = jetx; + mobj->y = jety; + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(38*FRACUNIT, mobj->target->scale); + else + mobj->z = mobj->target->z + FixedMul(38*FRACUNIT, mobj->target->scale); + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + } + else if (mobj->fuse == 57) + { + P_UnsetThingPosition(mobj); + mobj->x = jetx + P_ReturnThrustX(mobj->target, mobj->target->angle - ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); + mobj->y = jety + P_ReturnThrustY(mobj->target, mobj->target->angle - ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(12*FRACUNIT, mobj->target->scale); + else + mobj->z = mobj->target->z + FixedMul(12*FRACUNIT, mobj->target->scale); + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + } + else if (mobj->fuse == 58) + { + P_UnsetThingPosition(mobj); + mobj->x = jetx + P_ReturnThrustX(mobj->target, mobj->target->angle + ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); + mobj->y = jety + P_ReturnThrustY(mobj->target, mobj->target->angle + ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(12*FRACUNIT, mobj->target->scale); + else + mobj->z = mobj->target->z + FixedMul(12*FRACUNIT, mobj->target->scale); + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + } + else if (mobj->fuse == 59) + { + boolean dashmod = ((mobj->target->flags & MF_PAIN) && (mobj->target->health <= mobj->target->info->damage)); + jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, -mobj->target->radius); + jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, -mobj->target->radius); + P_UnsetThingPosition(mobj); + mobj->x = jetx; + mobj->y = jety; + mobj->destscale = mobj->target->scale; + if (!(dashmod && mobj->target->state == states + S_METALSONIC_BOUNCE)) + { + mobj->destscale = (mobj->destscale + FixedDiv(R_PointToDist2(0, 0, mobj->target->momx, mobj->target->momy), 36*mobj->target->scale))/3; + } + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2; + else + mobj->z = mobj->target->z + mobj->target->height/2 - mobj->height/2; + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + if (dashmod) + { + mobj->color = SKINCOLOR_SUNSET; + if (mobj->target->movecount == 3 && !mobj->target->reactiontime && (mobj->target->movedir == 0 || mobj->target->movedir == 2)) + P_SpawnGhostMobj(mobj); + } + else + mobj->color = SKINCOLOR_ICY; + } + mobj->fuse++; + return true; +} + +static boolean P_EggRobo1Think(mobj_t *mobj) +{ +#define SPECTATORRADIUS (96*mobj->scale) + if (!(mobj->flags2 & MF2_STRONGBOX)) + { + mobj->cusval = mobj->x; // eat my SOCs, p_mobj.h warning, we have lua now + mobj->cvmem = mobj->y; // ditto + mobj->movedir = mobj->angle; + mobj->threshold = P_MobjFlip(mobj)*10*mobj->scale; + if (mobj->threshold < 0) + mobj->threshold += (mobj->ceilingz - mobj->height); + else + mobj->threshold += mobj->floorz; + var1 = 4; + A_BossJetFume(mobj); + mobj->flags2 |= MF2_STRONGBOX; + } + + if (mobj->state == &states[mobj->info->deathstate]) // todo: make map actually set health to 0 for these + { + if (mobj->movecount) + { + if (!(--mobj->movecount)) + S_StartSound(mobj, mobj->info->deathsound); + } + else + { + mobj->momz += P_MobjFlip(mobj)*mobj->scale; + if (mobj->momz > 0) + { + if (mobj->z + mobj->momz > mobj->ceilingz + (1000 << FRACBITS)) + { + P_RemoveMobj(mobj); + return false; + } + } + else if (mobj->z + mobj->height + mobj->momz < mobj->floorz - (1000 << FRACBITS)) + { + P_RemoveMobj(mobj); + return false; + } + } + } + else + { + fixed_t basex = mobj->cusval, basey = mobj->cvmem; + + if (mobj->spawnpoint && mobj->spawnpoint->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)) + { + angle_t sideang = mobj->movedir + ((mobj->spawnpoint->options & MTF_AMBUSH) ? ANGLE_90 : -ANGLE_90); + fixed_t oscillate = FixedMul(FINESINE(((leveltime * ANG1) >> (ANGLETOFINESHIFT + 2)) & FINEMASK), 250*mobj->scale); + basex += P_ReturnThrustX(mobj, sideang, oscillate); + basey += P_ReturnThrustY(mobj, sideang, oscillate); + } + + mobj->z = mobj->threshold + FixedMul(FINESINE(((leveltime + mobj->movecount)*ANG2 >> (ANGLETOFINESHIFT - 2)) & FINEMASK), 8*mobj->scale); + if (mobj->state != &states[mobj->info->meleestate]) + { + boolean didmove = false; + + if (mobj->state == &states[mobj->info->spawnstate]) + { + UINT8 i; + fixed_t dist = INT32_MAX; + + for (i = 0; i < MAXPLAYERS; i++) + { + fixed_t compdist; + if (!playeringame[i]) + continue; + if (players[i].spectator) + continue; + if (!players[i].mo) + continue; + if (!players[i].mo->health) + continue; + if (P_PlayerInPain(&players[i])) + continue; + if (players[i].mo->z > mobj->z + mobj->height + 8*mobj->scale) + continue; + if (players[i].mo->z + players[i].mo->height < mobj->z - 8*mobj->scale) + continue; + compdist = P_AproxDistance( + players[i].mo->x + players[i].mo->momx - basex, + players[i].mo->y + players[i].mo->momy - basey); + if (compdist >= dist) + continue; + dist = compdist; + P_SetTarget(&mobj->target, players[i].mo); + } + + if (dist < (SPECTATORRADIUS << 1)) + { + didmove = true; + mobj->frame = 3 + ((leveltime & 2) >> 1); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + + if (P_AproxDistance( + mobj->x - basex, + mobj->y - basey) + < mobj->scale) + S_StartSound(mobj, mobj->info->seesound); + + P_TeleportMove(mobj, + (15*(mobj->x >> 4)) + (basex >> 4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS >> 4), + (15*(mobj->y >> 4)) + (basey >> 4) + P_ReturnThrustY(mobj, mobj->angle, SPECTATORRADIUS >> 4), + mobj->z); + } + else + { + angle_t diff = (mobj->movedir - mobj->angle); + if (diff > ANGLE_180) + diff = InvAngle(InvAngle(diff)/8); + else + diff /= 8; + mobj->angle += diff; + + dist = FINECOSINE(((leveltime + mobj->movecount)*ANG2 >> (ANGLETOFINESHIFT - 2)) & FINEMASK); + + if (abs(dist) < FRACUNIT/2) + mobj->frame = 0; + else + mobj->frame = (dist > 0) ? 1 : 2; + } + } + + if (!didmove) + { + if (P_AproxDistance(mobj->x - basex, mobj->y - basey) < mobj->scale) + P_TeleportMove(mobj, basex, basey, mobj->z); + else + P_TeleportMove(mobj, + (15*(mobj->x >> 4)) + (basex >> 4), + (15*(mobj->y >> 4)) + (basey >> 4), + mobj->z); + } + } + } + return true; +#undef SPECTATORRADIUS +} + +static void P_NiGHTSDroneThink(mobj_t *mobj) +{ + { + // variable setup + mobj_t *goalpost = NULL; + mobj_t *sparkle = NULL; + mobj_t *droneman = NULL; + + boolean flip = mobj->flags2 & MF2_OBJECTFLIP; + boolean topaligned = (mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE); + boolean middlealigned = (mobj->flags & MF_GRENADEBOUNCE) && !(mobj->flags & MF_SLIDEME); + boolean bottomoffsetted = !(mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE); + boolean flipchanged = false; + + fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff; + + if (mobj->target && mobj->target->type == MT_NIGHTSDRONE_GOAL) + { + goalpost = mobj->target; + if (goalpost->target && goalpost->target->type == MT_NIGHTSDRONE_SPARKLING) + sparkle = goalpost->target; + if (goalpost->tracer && goalpost->tracer->type == MT_NIGHTSDRONE_MAN) + droneman = goalpost->tracer; + } + + if (!goalpost || !sparkle || !droneman) + return; + + // did NIGHTSDRONE position, scale, flip, or flags change? all elements need to be synced + droneboxmandiff = max(mobj->height - droneman->height, 0); + dronemangoaldiff = max(droneman->height - goalpost->height, 0); + + if (!(goalpost->flags2 & MF2_OBJECTFLIP) && (mobj->flags2 & MF2_OBJECTFLIP)) + { + goalpost->eflags |= MFE_VERTICALFLIP; + goalpost->flags2 |= MF2_OBJECTFLIP; + sparkle->eflags |= MFE_VERTICALFLIP; + sparkle->flags2 |= MF2_OBJECTFLIP; + droneman->eflags |= MFE_VERTICALFLIP; + droneman->flags2 |= MF2_OBJECTFLIP; + flipchanged = true; + } + else if ((goalpost->flags2 & MF2_OBJECTFLIP) && !(mobj->flags2 & MF2_OBJECTFLIP)) + { + goalpost->eflags &= ~MFE_VERTICALFLIP; + goalpost->flags2 &= ~MF2_OBJECTFLIP; + sparkle->eflags &= ~MFE_VERTICALFLIP; + sparkle->flags2 &= ~MF2_OBJECTFLIP; + droneman->eflags &= ~MFE_VERTICALFLIP; + droneman->flags2 &= ~MF2_OBJECTFLIP; + flipchanged = true; + } + + if (goalpost->destscale != mobj->destscale + || goalpost->movefactor != mobj->z + || goalpost->friction != mobj->height + || flipchanged + || goalpost->threshold != (INT32)(mobj->flags & (MF_SLIDEME|MF_GRENADEBOUNCE))) + { + goalpost->destscale = sparkle->destscale = droneman->destscale = mobj->destscale; + + // straight copy-pasta from P_SpawnMapThing, case MT_NIGHTSDRONE + if (!flip) + { + if (topaligned) // Align droneman to top of hitbox + { + dronemanoffset = droneboxmandiff; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (middlealigned) // Align droneman to center of hitbox + { + dronemanoffset = droneboxmandiff/2; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (bottomoffsetted) + { + dronemanoffset = 24*FRACUNIT; + goaloffset = dronemangoaldiff + dronemanoffset; + } + else + { + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + + sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale); + } + else + { + if (topaligned) // Align droneman to top of hitbox + { + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (middlealigned) // Align droneman to center of hitbox + { + dronemanoffset = droneboxmandiff/2; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (bottomoffsetted) + { + dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); + goaloffset = dronemangoaldiff + dronemanoffset; + } + else + { + dronemanoffset = droneboxmandiff; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + + sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale); + } + + P_TeleportMove(goalpost, mobj->x, mobj->y, mobj->z + goaloffset); + P_TeleportMove(sparkle, mobj->x, mobj->y, mobj->z + sparkleoffset); + if (goalpost->movefactor != mobj->z || goalpost->friction != mobj->height) + { + P_TeleportMove(droneman, mobj->x, mobj->y, mobj->z + dronemanoffset); + goalpost->movefactor = mobj->z; + goalpost->friction = mobj->height; + } + goalpost->threshold = mobj->flags & (MF_SLIDEME|MF_GRENADEBOUNCE); + } + else + { + if (goalpost->x != mobj->x || goalpost->y != mobj->y) + { + P_TeleportMove(goalpost, mobj->x, mobj->y, goalpost->z); + P_TeleportMove(sparkle, mobj->x, mobj->y, sparkle->z); + } + + if (droneman->x != mobj->x || droneman->y != mobj->y) + P_TeleportMove(droneman, mobj->x, mobj->y, + droneman->z >= mobj->floorz && droneman->z <= mobj->ceilingz ? droneman->z : mobj->z); + } + + // now toggle states! + // GOAL mode? + if (sparkle->state >= &states[S_NIGHTSDRONE_SPARKLING1] && sparkle->state <= &states[S_NIGHTSDRONE_SPARKLING16]) + { + INT32 i; + boolean bonustime = false; + + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) + { + bonustime = true; + break; + } + + if (!bonustime) + { + CONS_Debug(DBG_NIGHTSBASIC, "Removing goal post\n"); + if (goalpost && goalpost->state != &states[S_INVISIBLE]) + P_SetMobjState(goalpost, S_INVISIBLE); + if (sparkle && sparkle->state != &states[S_INVISIBLE]) + P_SetMobjState(sparkle, S_INVISIBLE); + } + } + // Invisible/bouncing mode. + else + { + INT32 i; + boolean bonustime = false; + fixed_t zcomp; + + // Bouncy bouncy! + if (!flip) + { + if (topaligned) + zcomp = droneboxmandiff + mobj->z; + else if (middlealigned) + zcomp = (droneboxmandiff/2) + mobj->z; + else if (bottomoffsetted) + zcomp = mobj->z + FixedMul(24*FRACUNIT, mobj->scale); + else + zcomp = mobj->z; + } + else + { + if (topaligned) + zcomp = mobj->z; + else if (middlealigned) + zcomp = (droneboxmandiff/2) + mobj->z; + else if (bottomoffsetted) + zcomp = mobj->z + droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); + else + zcomp = mobj->z + droneboxmandiff; + } + + droneman->angle += ANG10; + if (!flip && droneman->z <= zcomp) + droneman->momz = FixedMul(5*FRACUNIT, droneman->scale); + else if (flip && droneman->z >= zcomp) + droneman->momz = FixedMul(-5*FRACUNIT, droneman->scale); + + // state switching logic + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) + { + bonustime = true; + break; + } + + if (bonustime) + { + CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n"); + if (!(droneman->flags2 & MF2_DONTDRAW)) + droneman->flags2 |= MF2_DONTDRAW; + if (goalpost->state == &states[S_INVISIBLE]) + P_SetMobjState(goalpost, mobjinfo[goalpost->type].meleestate); + if (sparkle->state == &states[S_INVISIBLE]) + P_SetMobjState(sparkle, mobjinfo[sparkle->type].meleestate); + } + else if (!G_IsSpecialStage(gamemap)) + { + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].powers[pw_carry] != CR_NIGHTSMODE) + { + bonustime = true; // variable reuse + break; + } + + if (bonustime) + { + // show droneman if at least one player is non-nights + if (goalpost->state != &states[S_INVISIBLE]) + P_SetMobjState(goalpost, S_INVISIBLE); + if (sparkle->state != &states[S_INVISIBLE]) + P_SetMobjState(sparkle, S_INVISIBLE); + if (droneman->state != &states[mobjinfo[droneman->type].meleestate]) + P_SetMobjState(droneman, mobjinfo[droneman->type].meleestate); + if (droneman->flags2 & MF2_DONTDRAW) + droneman->flags2 &= ~MF2_DONTDRAW; + } + else + { + // else, hide it + if (!(droneman->flags2 & MF2_DONTDRAW)) + droneman->flags2 |= MF2_DONTDRAW; + } + } + } + } +} + +static boolean P_TurretThink(mobj_t *mobj) +{ + P_MobjCheckWater(mobj); + P_CheckPosition(mobj, mobj->x, mobj->y); + if (P_MobjWasRemoved(mobj)) + return false; + mobj->floorz = tmfloorz; + mobj->ceilingz = tmceilingz; + mobj->floorrover = tmfloorrover; + mobj->ceilingrover = tmceilingrover; + + if ((mobj->eflags & MFE_UNDERWATER) && mobj->health > 0) + { + P_SetMobjState(mobj, mobj->info->deathstate); + mobj->health = 0; + mobj->flags2 &= ~MF2_FIRING; + } + else if (mobj->health > 0 && mobj->z + mobj->height > mobj->ceilingz) // Crushed + { + INT32 i, j; + fixed_t ns; + fixed_t x, y, z; + mobj_t* mo2; + + z = mobj->subsector->sector->floorheight + FixedMul(64*FRACUNIT, mobj->scale); + for (j = 0; j < 2; j++) + { + for (i = 0; i < 32; i++) + { + const angle_t fa = (i*FINEANGLES/16) & FINEMASK; + ns = FixedMul(64*FRACUNIT, mobj->scale); + x = mobj->x + FixedMul(FINESINE(fa), ns); + y = mobj->y + FixedMul(FINECOSINE(fa), ns); + + mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); + ns = FixedMul(16*FRACUNIT, mobj->scale); + mo2->momx = FixedMul(FINESINE(fa), ns); + mo2->momy = FixedMul(FINECOSINE(fa), ns); + } + z -= FixedMul(32*FRACUNIT, mobj->scale); + } + P_SetMobjState(mobj, mobj->info->deathstate); + mobj->health = 0; + mobj->flags2 &= ~MF2_FIRING; + } + return true; +} + +static void P_SaloonDoorThink(mobj_t *mobj) +{ + fixed_t x = mobj->tracer->x; + fixed_t y = mobj->tracer->y; + fixed_t z = mobj->tracer->z; + angle_t oang = FixedAngle(mobj->extravalue1); + angle_t fa = (oang >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t c0 = -96*FINECOSINE(fa); + fixed_t s0 = -96*FINESINE(fa); + angle_t fma; + fixed_t c, s; + angle_t angdiff; + + // Adjust angular speed + fixed_t da = AngleFixed(mobj->angle - oang); + if (da > 180*FRACUNIT) + da -= 360*FRACUNIT; + mobj->extravalue2 = 8*(mobj->extravalue2 - da/32)/9; + + // Update angle + mobj->angle += FixedAngle(mobj->extravalue2); + + angdiff = mobj->angle - FixedAngle(mobj->extravalue1); + if (angdiff > (ANGLE_90 - ANG2) && angdiff < ANGLE_180) + { + mobj->angle = FixedAngle(mobj->extravalue1) + (ANGLE_90 - ANG2); + mobj->extravalue2 /= 2; + } + else if (angdiff < (ANGLE_270 + ANG2) && angdiff >= ANGLE_180) + { + mobj->angle = FixedAngle(mobj->extravalue1) + (ANGLE_270 + ANG2); + mobj->extravalue2 /= 2; + } + + // Update position + fma = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK; + c = 48*FINECOSINE(fma); + s = 48*FINESINE(fma); + P_TeleportMove(mobj, x + c0 + c, y + s0 + s, z); +} + +static void P_PyreFlyThink(mobj_t *mobj) +{ + 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) + return; + + 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) << FRACBITS, 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 (hdist > 1500*FRACUNIT) + { + mobj->flags2 &= ~MF2_BOSSNOTRAP; + P_SetTarget(&mobj->target, NULL); + return; + } + + if (!(mobj->flags2 & MF2_BOSSNOTRAP) && hdist <= 450*FRACUNIT) + mobj->flags2 |= MF2_BOSSNOTRAP; + + if (!(mobj->flags2 & MF2_BOSSNOTRAP)) + return; + + 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; + } +} + +static void P_PterabyteThink(mobj_t *mobj) +{ + 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) + return; // Still carrying a player or in cooldown + + P_LookForPlayers(mobj, true, false, 256*FRACUNIT); + + if (!mobj->target) + return; + + if (mobj->target->player->powers[pw_flashing]) + { + P_SetTarget(&mobj->target, NULL); + return; + } + + vdist = mobj->z - mobj->target->z - mobj->target->height; + if (P_MobjFlip(mobj)*vdist <= 0) + { + P_SetTarget(&mobj->target, NULL); + return; + } + + hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + if (hdist > 450*FRACUNIT) + { + P_SetTarget(&mobj->target, NULL); + return; + } + + 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) + return; + + 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; + } + } +} + +static void P_DragonbomberThink(mobj_t *mobj) +{ +#define DRAGONTURNSPEED ANG2 + mobj->movecount = (mobj->movecount + 9) % 360; + P_SetObjectMomZ(mobj, 4*FINESINE(((mobj->movecount*ANG1) >> ANGLETOFINESHIFT) & FINEMASK), false); + if (mobj->threshold > 0) // are we dropping mines? + { + mobj->threshold--; + if (mobj->threshold == 0) // if the timer hits 0, look for a mine to drop! + { + mobj_t *segment = mobj; + while (segment->tracer != NULL && !P_MobjWasRemoved(segment->tracer) && segment->tracer->state == &states[segment->tracer->info->spawnstate]) + segment = segment->tracer; + if (segment != mobj) // found an unactivated segment? + { + mobj_t *mine = P_SpawnMobjFromMobj(segment, 0, 0, 0, segment->info->painchance); + mine->angle = segment->angle; + P_InstaThrust(mine, mobj->angle, P_AproxDistance(mobj->momx, mobj->momy) >> 1); + P_SetObjectMomZ(mine, -2*FRACUNIT, true); + S_StartSound(mine, mine->info->seesound); + P_SetMobjState(segment, segment->info->raisestate); + mobj->threshold = mobj->info->painchance; + } + } + } + if (mobj->target) // Are we chasing a player? + { + fixed_t dist = P_AproxDistance(mobj->x - mobj->target->x, mobj->y - mobj->target->y); + if (dist > 2000*mobj->scale) // Not anymore! + P_SetTarget(&mobj->target, NULL); + else + { + fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); + fixed_t z = mobj->target->z + (mobj->height >> 1) + (mobj->flags & MFE_VERTICALFLIP ? -128*mobj->scale : 128*mobj->scale + mobj->target->height); + angle_t diff = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) - mobj->angle; + if (diff > ANGLE_180) + mobj->angle -= DRAGONTURNSPEED; + else + mobj->angle += DRAGONTURNSPEED; + if (!mobj->threshold && dist < 512*mobj->scale) // Close enough to drop bombs + { + mobj->threshold = mobj->info->painchance; + } + mobj->momz += max(min(z - mobj->z, vspeed), -vspeed); + } + } + else // Can we find a player to chase? + { + if (mobj->tracer == NULL || mobj->tracer->state != &states[mobj->tracer->info->spawnstate] + || !P_LookForPlayers(mobj, true, false, 2000*mobj->scale)) // if not, circle around the spawnpoint + { + if (!mobj->spawnpoint) // unless we don't have one, in which case uhhh just circle around wherever we currently are I guess?? + mobj->angle += DRAGONTURNSPEED; + else + { + fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); + fixed_t x = mobj->spawnpoint->x << FRACBITS; + fixed_t y = mobj->spawnpoint->y << FRACBITS; + fixed_t z = mobj->spawnpoint->z << FRACBITS; + angle_t diff = R_PointToAngle2(mobj->x, mobj->y, x, y) - mobj->angle; + if (diff > ANGLE_180) + mobj->angle -= DRAGONTURNSPEED; + else + mobj->angle += DRAGONTURNSPEED; + mobj->momz += max(min(z - mobj->z, vspeed), -vspeed); + } + } + } + P_InstaThrust(mobj, mobj->angle, FixedMul(mobj->info->speed, mobj->scale)); +#undef DRAGONTURNSPEED +} + +static boolean P_MobjRegularThink(mobj_t *mobj) +{ + if ((mobj->flags & MF_ENEMY) && (mobj->state->nextstate == mobj->info->spawnstate && mobj->tics == 1)) + mobj->flags2 &= ~MF2_FRET; + + if (mobj->eflags & MFE_TRACERANGLE) + P_TracerAngleThink(mobj); + + switch (mobj->type) + { + case MT_WALLSPIKEBASE: + if (!mobj->target) { + P_RemoveMobj(mobj); + return false; + } + mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|(mobj->target->frame & FF_FRAMEMASK); +#if 0 + if (mobj->angle != mobj->target->angle + ANGLE_90) // reposition if not the correct angle + { + mobj_t* target = mobj->target; // shortcut + const fixed_t baseradius = target->radius - (target->scale/2); //FixedMul(FRACUNIT/2, target->scale); + P_UnsetThingPosition(mobj); + mobj->x = target->x - P_ReturnThrustX(target, target->angle, baseradius); + mobj->y = target->y - P_ReturnThrustY(target, target->angle, baseradius); + P_SetThingPosition(mobj); + mobj->angle = target->angle + ANGLE_90; + } +#endif + break; + case MT_FALLINGROCK: + // Despawn rocks here in case zmovement code can't do so (blame slopes) + if (!mobj->momx && !mobj->momy && !mobj->momz + && ((mobj->eflags & MFE_VERTICALFLIP) ? + mobj->z + mobj->height >= mobj->ceilingz + : mobj->z <= mobj->floorz)) + { + P_RemoveMobj(mobj); + return false; + } + P_MobjCheckWater(mobj); + break; + case MT_ARROW: + P_ArrowThink(mobj); + break; + case MT_EMERALDSPAWN: + if (mobj->threshold) + { + mobj->threshold--; + + if (!mobj->threshold && !mobj->target && mobj->reactiontime) + { + mobj_t *emerald = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->reactiontime); + emerald->threshold = 42; + P_SetTarget(&mobj->target, emerald); + P_SetTarget(&emerald->target, mobj); + } + } + break; + case MT_BUGGLE: + mobj->eflags |= MFE_UNDERWATER; //P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn + { + if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 + && P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z - mobj->z) <= mobj->radius*16) + { + // Home in on the target. + P_HomingAttack(mobj, mobj->tracer); + + if (mobj->z < mobj->floorz) + mobj->z = mobj->floorz; + + if (leveltime % mobj->info->painchance == 0) + S_StartSound(mobj, mobj->info->activesound); + + if ((statenum_t)(mobj->state - states) != mobj->info->seestate) + P_SetMobjState(mobj, mobj->info->seestate); + } + else + { + // Try to find a player + P_LookForPlayers(mobj, true, true, mobj->radius*16); + mobj->momx >>= 1; + mobj->momy >>= 1; + mobj->momz >>= 1; + if ((statenum_t)(mobj->state - states) != mobj->info->spawnstate) + P_SetMobjState(mobj, mobj->info->spawnstate); + } + } + break; + case MT_BUMBLEBORE: + P_BumbleboreThink(mobj); + break; + case MT_BIGMINE: + mobj->extravalue1 += 3; + mobj->extravalue1 %= 360; + P_UnsetThingPosition(mobj); + mobj->z += FINESINE(mobj->extravalue1*(FINEMASK + 1)/360); + P_SetThingPosition(mobj); + break; + case MT_FLAME: + if (mobj->flags2 & MF2_BOSSNOTRAP) + { + if (!mobj->target || P_MobjWasRemoved(mobj->target)) + { + if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) + P_RemoveMobj(mobj->tracer); + P_RemoveMobj(mobj); + return false; + } + mobj->z = mobj->target->z + mobj->target->momz; + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z += mobj->target->height; + } + if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) + { + mobj->tracer->z = mobj->z + P_MobjFlip(mobj)*20*mobj->scale; + if (mobj->eflags & MFE_VERTICALFLIP) + mobj->tracer->z += mobj->height; + } + break; + case MT_WAVINGFLAG1: + case MT_WAVINGFLAG2: + { + fixed_t base = (leveltime << (FRACBITS + 1)); + mobj_t *seg = mobj->tracer, *prev = mobj; + mobj->movedir = mobj->angle + + ((((FINESINE((FixedAngle(base << 1) >> ANGLETOFINESHIFT) & FINEMASK) + + FINESINE((FixedAngle(base << 4) >> ANGLETOFINESHIFT) & FINEMASK)) >> 1) + + FINESINE((FixedAngle(base*9) >> ANGLETOFINESHIFT) & FINEMASK) + + FINECOSINE(((FixedAngle(base*9)) >> ANGLETOFINESHIFT) & FINEMASK)) << 12); //*2^12 + while (seg) + { + seg->movedir = seg->angle; + seg->angle = prev->movedir; + P_UnsetThingPosition(seg); + seg->x = prev->x + P_ReturnThrustX(prev, prev->angle, prev->radius); + seg->y = prev->y + P_ReturnThrustY(prev, prev->angle, prev->radius); + seg->z = prev->z + prev->height - (seg->scale >> 1); + P_SetThingPosition(seg); + prev = seg; + seg = seg->tracer; + } + } + break; + case MT_SPINCUSHION: + if (mobj->target && mobj->state - states >= S_SPINCUSHION_AIM1 && mobj->state - states <= S_SPINCUSHION_AIM5) + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + break; + case MT_CRUSHCLAW: + if (mobj->state - states == S_CRUSHCLAW_STAY && mobj->target) + { + mobj_t *chain = mobj->target->target; + SINT8 sign = ((mobj->tics & 1) ? mobj->tics : -(SINT8)(mobj->tics)); + while (chain) + { + chain->z = chain->watertop + sign*mobj->scale; + sign = -sign; + chain = chain->target; + } + } + break; + case MT_SMASHINGSPIKEBALL: + mobj->momx = mobj->momy = 0; + if (mobj->state - states == S_SMASHSPIKE_FALL && P_IsObjectOnGround(mobj)) + { + P_SetMobjState(mobj, S_SMASHSPIKE_STOMP1); + S_StartSound(mobj, sfx_spsmsh); + } + else if (mobj->state - states == S_SMASHSPIKE_RISE2 && P_MobjFlip(mobj)*(mobj->z - mobj->movecount) >= 0) + { + mobj->momz = 0; + P_SetMobjState(mobj, S_SMASHSPIKE_FLOAT); + } + break; + case MT_HANGSTER: + if (!P_HangsterThink(mobj)) + return false; + break; + case MT_LHRT: + mobj->momx = FixedMul(mobj->momx, mobj->extravalue2); + mobj->momy = FixedMul(mobj->momy, mobj->extravalue2); + break; + case MT_EGGCAPSULE: + if (!mobj->reactiontime) + { + // Target nearest player on your mare. + // (You can make it float up/down by adding MF_FLOAT, + // but beware level design pitfalls.) + fixed_t shortest = 1024*FRACUNIT; + INT32 i; + P_SetTarget(&mobj->target, NULL); + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].mo + && players[i].mare == mobj->threshold && players[i].spheres > 0) + { + fixed_t dist = P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y); + if (dist < shortest) + { + P_SetTarget(&mobj->target, players[i].mo); + shortest = dist; + } + } + } + break; + case MT_EGGMOBILE2_POGO: + if (!mobj->target + || !mobj->target->health + || mobj->target->state == &states[mobj->target->info->spawnstate] + || mobj->target->state == &states[mobj->target->info->raisestate]) + { + P_RemoveMobj(mobj); + return false; + } + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z - mobj->height); + break; + case MT_HAMMER: + if (mobj->z <= mobj->floorz) + { + P_RemoveMobj(mobj); + return false; + } + break; + case MT_KOOPA: + P_KoopaThinker(mobj); + break; + case MT_FIREBALL: + if (P_AproxDistance(mobj->momx, mobj->momy) <= 16*FRACUNIT) // Once fireballs lose enough speed, kill them + { + P_KillMobj(mobj, NULL, NULL, 0); + return false; + } + break; + case MT_REDRING: + if (((mobj->z < mobj->floorz) || (mobj->z + mobj->height > mobj->ceilingz)) + && mobj->flags & MF_MISSILE) + { + P_ExplodeMissile(mobj); + return false; + } + break; + case MT_BOSSFLYPOINT: + return false; + case MT_NIGHTSCORE: + mobj->color = (UINT8)(leveltime % SKINCOLOR_WHITE); + break; + case MT_JETFUME1: + if (!P_JetFume1Think(mobj)) + return false; + break; + case MT_JETFLAME: + { + if (!mobj->target // if you have no target + || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now + { // then remove yourself as well! + P_RemoveMobj(mobj); + return false; + } + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + mobj->z = mobj->target->z - 50*mobj->target->scale; + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + } + break; + case MT_EGGROBO1: + if (!P_EggRobo1Think(mobj)) + return false; + break; + case MT_EGGROBO1JET: + { + if (!mobj->target || P_MobjWasRemoved(mobj->target) // if you have no target + || (mobj->target->health <= 0)) // or your target isn't a boss and it's popped now + { // then remove yourself as well! + P_RemoveMobj(mobj); + return false; + } + + mobj->flags2 ^= MF2_DONTDRAW; + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x + P_ReturnThrustX(mobj, mobj->target->angle + ANGLE_90, mobj->movefactor*mobj->target->scale) - P_ReturnThrustX(mobj, mobj->target->angle, 19*mobj->target->scale); + mobj->y = mobj->target->y + P_ReturnThrustY(mobj, mobj->target->angle + ANGLE_90, mobj->movefactor*mobj->target->scale) - P_ReturnThrustY(mobj, mobj->target->angle, 19*mobj->target->scale); + mobj->z = mobj->target->z; + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->z += (mobj->target->height - mobj->height); + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + } + break; + case MT_NIGHTSDRONE: + P_NiGHTSDroneThink(mobj); + break; + case MT_PLAYER: + if (mobj->player) + P_PlayerMobjThinker(mobj); + return false; + case MT_SKIM: + // check mobj against possible water content, before movement code + P_MobjCheckWater(mobj); + + // Keep Skim at water surface + if (mobj->z <= mobj->watertop) + { + mobj->flags |= MF_NOGRAVITY; + if (mobj->z < mobj->watertop) + { + if (mobj->watertop - mobj->z <= FixedMul(mobj->info->speed*FRACUNIT, mobj->scale)) + mobj->z = mobj->watertop; + else + mobj->momz = FixedMul(mobj->info->speed*FRACUNIT, mobj->scale); + } + } + else + { + mobj->flags &= ~MF_NOGRAVITY; + if (mobj->z > mobj->watertop && mobj->z - mobj->watertop < FixedMul(MAXSTEPMOVE, mobj->scale)) + mobj->z = mobj->watertop; + } + break; + case MT_RING: + case MT_REDTEAMRING: + case MT_BLUETEAMRING: + P_KillRingsInLava(mobj); + if (P_MobjWasRemoved(mobj)) + return false; + /* FALLTHRU */ + case MT_COIN: + case MT_BLUESPHERE: + case MT_BOMBSPHERE: + case MT_NIGHTSCHIP: + case MT_NIGHTSSTAR: + // No need to check water. Who cares? + P_RingThinker(mobj); + if (mobj->flags2 & MF2_NIGHTSPULL) + P_NightsItemChase(mobj); + else + A_AttractChase(mobj); + return false; + // Flung items + case MT_FLINGRING: + P_KillRingsInLava(mobj); + if (P_MobjWasRemoved(mobj)) + return false; + /* FALLTHRU */ + case MT_FLINGCOIN: + case MT_FLINGBLUESPHERE: + case MT_FLINGNIGHTSCHIP: + if (mobj->flags2 & MF2_NIGHTSPULL) + P_NightsItemChase(mobj); + else + A_AttractChase(mobj); + break; + case MT_EMBLEM: + if (mobj->flags2 & MF2_NIGHTSPULL) + P_NightsItemChase(mobj); + break; + case MT_SHELL: + if (mobj->threshold && mobj->threshold != TICRATE) + mobj->threshold--; + + if (mobj->threshold >= TICRATE) + { + mobj->angle += ((mobj->movedir == 1) ? ANGLE_22h : ANGLE_337h); + P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), (mobj->info->speed*mobj->scale)); + } + break; + case MT_TURRET: + if (!P_TurretThink(mobj)) + return false; + break; + case MT_BLUEFLAG: + case MT_REDFLAG: + { + sector_t* sec2; + sec2 = P_ThingOnSpecial3DFloor(mobj); + if ((sec2 && GETSECSPECIAL(sec2->special, 4) == 2) || (GETSECSPECIAL(mobj->subsector->sector->special, 4) == 2)) + mobj->fuse = 1; // Return to base. + break; + } + case MT_CANNONBALL: +#ifdef FLOORSPLATS + R_AddFloorSplat(mobj->tracer->subsector, mobj->tracer, "TARGET", mobj->tracer->x, + mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE); +#endif + break; + case MT_SPINDUST: // Spindash dust + mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000 + mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same + //mobj->momz = mobj->momz+P_MobjFlip(mobj)/3; // no meaningful change in value to be frank + if (mobj->state >= &states[S_SPINDUST_BUBBLE1] && mobj->state <= &states[S_SPINDUST_BUBBLE4]) // bubble dust! + { + P_MobjCheckWater(mobj); + if (mobj->watertop != mobj->subsector->sector->floorheight - 1000*FRACUNIT + && mobj->z + mobj->height >= mobj->watertop - 5*FRACUNIT) + mobj->flags2 |= MF2_DONTDRAW; + } + break; + case MT_TRAINDUSTSPAWNER: + if (leveltime % 5 == 0) { + mobj_t* traindust = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PARTICLE); + traindust->flags = MF_SCENERY; + P_SetMobjState(traindust, S_TRAINDUST); + traindust->frame = P_RandomRange(0, 8)|FF_TRANS90; + traindust->angle = mobj->angle; + traindust->tics = TICRATE*4; + traindust->destscale = FRACUNIT*64; + traindust->scalespeed = FRACUNIT/24; + P_SetScale(traindust, FRACUNIT*6); + } + break; + case MT_TRAINSTEAMSPAWNER: + if (leveltime % 5 == 0) { + mobj_t *steam = P_SpawnMobj(mobj->x + FRACUNIT*P_SignedRandom()/2, mobj->y + FRACUNIT*P_SignedRandom()/2, mobj->z, MT_PARTICLE); + P_SetMobjState(steam, S_TRAINSTEAM); + steam->frame = P_RandomRange(0, 1)|FF_TRANS90; + steam->tics = TICRATE*8; + steam->destscale = FRACUNIT*64; + steam->scalespeed = FRACUNIT/8; + P_SetScale(steam, FRACUNIT*16); + steam->momx = P_SignedRandom()*32; + steam->momy = -64*FRACUNIT; + steam->momz = 2*FRACUNIT; + } + break; + case MT_CANARIVORE_GAS: + { + fixed_t momz; + + if (mobj->flags2 & MF2_AMBUSH) + { + mobj->momx = FixedMul(mobj->momx, 50*FRACUNIT/51); + mobj->momy = FixedMul(mobj->momy, 50*FRACUNIT/51); + break; + } + + if (mobj->eflags & MFE_VERTICALFLIP) + { + if ((mobj->z + mobj->height + mobj->momz) <= mobj->ceilingz) + break; + } + else + { + if ((mobj->z + mobj->momz) >= mobj->floorz) + break; + } + + momz = abs(mobj->momz); + if (R_PointToDist2(0, 0, mobj->momx, mobj->momy) < momz) + P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), momz); + mobj->flags2 |= MF2_AMBUSH; + break; + } + case MT_SALOONDOOR: + P_SaloonDoorThink(mobj); + break; + case MT_MINECARTSPAWNER: + P_HandleMinecartSegments(mobj); + if (!mobj->fuse || mobj->fuse > TICRATE) + break; + if (mobj->fuse == 2) + { + mobj->fuse = 0; + break; + } + mobj->flags2 ^= MF2_DONTDRAW; + break; + case MT_LAVAFALLROCK: + if (P_IsObjectOnGround(mobj)) + P_RemoveMobj(mobj); + break; + case MT_PYREFLY: + P_PyreFlyThink(mobj); + break; + case MT_PTERABYTE: + P_PterabyteThink(mobj); + break; + case MT_DRAGONBOMBER: + P_DragonbomberThink(mobj); + break; + case MT_MINUS: +#ifdef ROTSPRITE + { + if (P_IsObjectOnGround(mobj)) + mobj->rollangle = 0; + else + mobj->rollangle = R_PointToAngle2(0, 0, mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1)); + } +#endif + break; + case MT_SPINFIRE: + if (mobj->flags & MF_NOGRAVITY) + { + if (mobj->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->ceilingz - mobj->height; + else + mobj->z = mobj->floorz; + } + else if ((!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z <= mobj->floorz) + || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height >= mobj->ceilingz)) + { + mobj->flags |= MF_NOGRAVITY; + mobj->momx = 8; // this is a hack which is used to ensure it still behaves as a missile and can damage others + mobj->momy = mobj->momz = 0; + mobj->z = ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->ceilingz - mobj->height : mobj->floorz); + } + /* FALLTHRU */ + default: + // check mobj against possible water content, before movement code + P_MobjCheckWater(mobj); + + // Extinguish fire objects in water + if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL + && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) + { + P_KillMobj(mobj, NULL, NULL, 0); + return false; + } + break; + } + return true; +} + // // P_MobjThinker // @@ -8101,1722 +9886,23 @@ void P_MobjThinker(mobj_t *mobj) // separate thinker if (mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse)) { - P_MobjCheckWater(mobj); - P_PushableThinker(mobj); - - // Extinguish fire objects in water. (Yes, it's extraordinarily rare to have a pushable flame object, but Brak uses such a case.) - if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL - && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) - { - P_KillMobj(mobj, NULL, NULL, 0); + if (!P_MobjPushableThink(mobj)) return; - } } else if (mobj->flags & MF_BOSS) { -#ifdef HAVE_BLUA - if (LUAh_BossThinker(mobj)) - { - if (P_MobjWasRemoved(mobj)) - return; - } - else if (P_MobjWasRemoved(mobj)) + if (!P_MobjBossThink(mobj)) return; - else -#endif - switch (mobj->type) - { - case MT_EGGMOBILE: - if (mobj->health < mobj->info->damage+1 && leveltime & 2) - { - fixed_t rad = mobj->radius>>FRACBITS; - fixed_t hei = mobj->height>>FRACBITS; - mobj_t *particle = P_SpawnMobjFromMobj(mobj, - P_RandomRange(rad, -rad)<momz += mobj->momz; - } - if (mobj->flags2 & MF2_SKULLFLY) -#if 1 - P_SpawnGhostMobj(mobj); -#else // all the way back from final demo... MT_THOK isn't even the same size anymore! - { - mobj_t *spawnmobj; - spawnmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->painchance); - P_SetTarget(&spawnmobj->target, mobj); - spawnmobj->color = SKINCOLOR_GREY; - } -#endif - P_Boss1Thinker(mobj); - break; - case MT_EGGMOBILE2: - if (mobj->health < mobj->info->damage+1 && leveltime & 2) - { - fixed_t rad = mobj->radius>>FRACBITS; - fixed_t hei = mobj->height>>FRACBITS; - mobj_t *particle = P_SpawnMobjFromMobj(mobj, - P_RandomRange(rad, -rad)<momz += mobj->momz; - } - P_Boss2Thinker(mobj); - break; - case MT_EGGMOBILE3: - if (mobj->health < mobj->info->damage+1 && leveltime & 2) - { - fixed_t rad = mobj->radius>>FRACBITS; - fixed_t hei = mobj->height>>FRACBITS; - mobj_t *particle = P_SpawnMobjFromMobj(mobj, - P_RandomRange(rad, -rad)<momz += mobj->momz; - } - P_Boss3Thinker(mobj); - break; - case MT_EGGMOBILE4: - if (mobj->health < mobj->info->damage+1 && leveltime & 2) - { - fixed_t rad = mobj->radius>>FRACBITS; - fixed_t hei = mobj->height>>FRACBITS; - mobj_t *particle = P_SpawnMobjFromMobj(mobj, - P_RandomRange(rad, -rad)<momz += mobj->momz; - } - P_Boss4Thinker(mobj); - break; - case MT_FANG: - P_Boss5Thinker(mobj); - break; - case MT_BLACKEGGMAN: - P_Boss7Thinker(mobj); - break; - case MT_METALSONIC_BATTLE: - P_Boss9Thinker(mobj); - break; - default: // Generic SOC-made boss - if (mobj->flags2 & MF2_SKULLFLY) - P_SpawnGhostMobj(mobj); - P_GenericBossThinker(mobj); - break; - } - if (mobj->flags2 & MF2_BOSSFLEE) - { - if (mobj->extravalue1) - { - if (!(--mobj->extravalue1)) - { - if (mobj->target) - { - mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, P_AproxDistance(mobj->x-mobj->target->x,mobj->y-mobj->target->y)), mobj->scale<<1); - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - } - else - mobj->momz = 8*mobj->scale; - } - else - mobj->angle += mobj->movedir; - } - else if (mobj->target) - P_InstaThrust(mobj, mobj->angle, FixedMul(12*FRACUNIT, mobj->scale)); - } - if (mobj->type == MT_CYBRAKDEMON && !mobj->health) - { - if (!(mobj->tics & 1)) - { - var1 = 2; - var2 = 0; - A_BossScream(mobj); - } - if (P_CheckDeathPitCollide(mobj)) - { - P_RemoveMobj(mobj); - return; - } - if (mobj->momz && mobj->z+mobj->momz <= mobj->floorz) - { - S_StartSound(mobj, sfx_befall); - if (mobj->state != states+S_CYBRAKDEMON_DIE8) - P_SetMobjState(mobj, S_CYBRAKDEMON_DIE8); - } - } } else if (mobj->health <= 0) // Dead things think differently than the living. - switch (mobj->type) - { - case MT_BLUESPHERE: - if ((mobj->tics>>2)+1 > 0 && (mobj->tics>>2)+1 <= tr_trans60) // tr_trans50 through tr_trans90, shifting once every second frame - mobj->frame = (NUMTRANSMAPS-((mobj->tics>>2)+1))<frame = tr_trans60<z <= mobj->floorz) - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_FAKEMOBILE: - if (mobj->scale == mobj->destscale) - { - if (!mobj->fuse) - { - S_StartSound(mobj, sfx_s3k77); - mobj->flags2 |= MF2_DONTDRAW; - mobj->fuse = TICRATE; - } - return; - } - if (!mobj->reactiontime) - { - if (P_RandomChance(FRACUNIT/2)) - mobj->movefactor = FRACUNIT; - else - mobj->movefactor = -FRACUNIT; - if (P_RandomChance(FRACUNIT/2)) - mobj->movedir = ANG20; - else - mobj->movedir = -ANG20; - mobj->reactiontime = 5; - } - mobj->momz += mobj->movefactor; - mobj->angle += mobj->movedir; - P_InstaThrust(mobj, mobj->angle, -mobj->info->speed); - mobj->reactiontime--; - break; - case MT_EGGSHIELD: - mobj->flags2 ^= MF2_DONTDRAW; - break; - case MT_EGGTRAP: // Egg Capsule animal release - if (mobj->fuse > 0)// && mobj->fuse < TICRATE-(TICRATE/7)) - { - INT32 i; - fixed_t x,y,z; - fixed_t ns; - mobj_t *mo2; - mobj_t *flicky; - - z = mobj->subsector->sector->floorheight + FRACUNIT + (P_RandomKey(64)<x + FixedMul(FINESINE(fa),ns); - y = mobj->y + FixedMul(FINECOSINE(fa),ns); - - mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); - P_SetMobjStateNF(mo2, S_XPLD_EGGTRAP); // so the flickies don't lose their target if they spawn - ns = 4 * FRACUNIT; - mo2->momx = FixedMul(FINESINE(fa),ns); - mo2->momy = FixedMul(FINECOSINE(fa),ns); - mo2->angle = fa << ANGLETOFINESHIFT; - - if (!i && !(mobj->fuse & 2)) - S_StartSound(mo2, mobj->info->deathsound); - - flicky = P_InternalFlickySpawn(mo2, 0, 8*FRACUNIT, false, -1); - if (!flicky) - break; - - P_SetTarget(&flicky->target, mo2); - flicky->momx = mo2->momx; - flicky->momy = mo2->momy; - } - - mobj->fuse--; - } - break; - case MT_PLAYER: - /// \todo Have the player's dead body completely finish its animation even if they've already respawned. - if (!mobj->fuse) - { // Go away. - /// \todo Actually go ahead and remove mobj completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it. - mobj->momz = 0; - if (mobj->player) - mobj->flags2 |= MF2_DONTDRAW; - else // safe to remove, nobody's going to complain! - { - P_RemoveMobj(mobj); - return; - } - } - else // Apply gravity to fall downwards. - { - if (mobj->player && !(mobj->fuse % 8) && (mobj->player->charflags & SF_MACHINE)) - { - fixed_t r = mobj->radius >> FRACBITS; - mobj_t *explosion = P_SpawnMobj( - mobj->x + (P_RandomRange(r, -r) << FRACBITS), - mobj->y + (P_RandomRange(r, -r) << FRACBITS), - mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), - MT_SONIC3KBOSSEXPLODE); - S_StartSound(explosion, sfx_s3kb4); - } - if (mobj->movedir == DMG_DROWNED) - P_SetObjectMomZ(mobj, -FRACUNIT / 2, true); // slower fall from drowning - else - P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true); - } - break; - case MT_METALSONIC_RACE: - { - if (!(mobj->fuse % 8)) - { - fixed_t r = mobj->radius >> FRACBITS; - mobj_t *explosion = P_SpawnMobj( - mobj->x + (P_RandomRange(r, -r) << FRACBITS), - mobj->y + (P_RandomRange(r, -r) << FRACBITS), - mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), - MT_SONIC3KBOSSEXPLODE); - S_StartSound(explosion, sfx_s3kb4); - } - P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true); - } - default: - break; - } + { + if (!P_MobjDeadThink(mobj)) + return; + } else { - if ((mobj->flags & MF_ENEMY) && (mobj->state->nextstate == mobj->info->spawnstate && mobj->tics == 1)) - mobj->flags2 &= ~MF2_FRET; - - // Angle-to-tracer to trigger a linedef exec - // See Linedef Exec 457 (Track mobj angle to point) - if ((mobj->eflags & MFE_TRACERANGLE) && mobj->tracer && mobj->extravalue2) - { - // mobj->lastlook - Don't disable behavior after first failure - // mobj->extravalue1 - Angle tolerance - // mobj->extravalue2 - Exec tag upon failure - // mobj->cvval - Allowable failure delay - // mobj->cvmem - Failure timer - - angle_t ang = mobj->angle - R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); - - // \todo account for distance between mobj and tracer - // Because closer mobjs can be facing beyond the angle tolerance - // yet tracer is still in the camera view - - // failure state: mobj is not facing tracer - // Reasaonable defaults: ANGLE_67h, ANGLE_292h - if (ang >= (angle_t)mobj->extravalue1 && ang <= ANGLE_MAX - (angle_t)mobj->extravalue1) - { - if (mobj->cvmem) - mobj->cvmem--; - else - { - INT32 exectag = mobj->extravalue2; // remember this before we erase the values - - if (mobj->lastlook) - mobj->cvmem = mobj->cusval; // reset timer for next failure - else - { - // disable after first failure - mobj->eflags &= ~MFE_TRACERANGLE; - mobj->lastlook = mobj->extravalue1 = mobj->extravalue2 = mobj->cvmem = mobj->cusval = 0; - } - - P_LinedefExecute(exectag, mobj, NULL); - } - } - else - mobj->cvmem = mobj->cusval; // reset failure timer - } - - switch (mobj->type) - { - case MT_WALLSPIKEBASE: - if (!mobj->target) { - P_RemoveMobj(mobj); - return; - } - mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|(mobj->target->frame & FF_FRAMEMASK); -#if 0 - if (mobj->angle != mobj->target->angle + ANGLE_90) // reposition if not the correct angle - { - mobj_t *target = mobj->target; // shortcut - const fixed_t baseradius = target->radius - (target->scale/2); //FixedMul(FRACUNIT/2, target->scale); - P_UnsetThingPosition(mobj); - mobj->x = target->x - P_ReturnThrustX(target, target->angle, baseradius); - mobj->y = target->y - P_ReturnThrustY(target, target->angle, baseradius); - P_SetThingPosition(mobj); - mobj->angle = target->angle + ANGLE_90; - } -#endif - break; - case MT_FALLINGROCK: - // Despawn rocks here in case zmovement code can't do so (blame slopes) - if (!mobj->momx && !mobj->momy && !mobj->momz - && ((mobj->eflags & MFE_VERTICALFLIP) ? - mobj->z + mobj->height >= mobj->ceilingz - : mobj->z <= mobj->floorz)) - { - P_RemoveMobj(mobj); - return; - } - P_MobjCheckWater(mobj); - break; - case MT_ARROW: - if (mobj->flags & MF_MISSILE) - { - // Calculate the angle of movement. - /* - momz - / | - / | - / | - 0------dist(momx,momy) - */ - - fixed_t dist = P_AproxDistance(mobj->momx, mobj->momy); - angle_t angle = R_PointToAngle2(0, 0, dist, mobj->momz); - - if (angle > ANG20 && angle <= ANGLE_180) - mobj->frame = 2; - else if (angle < ANG340 && angle > ANGLE_180) - mobj->frame = 0; - else - mobj->frame = 1; - - if (!(mobj->extravalue1) && (mobj->momz < 0)) - { - mobj->extravalue1 = 1; - S_StartSound(mobj, mobj->info->activesound); - } - if (leveltime & 1) - { - mobj_t *dust = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_PARTICLE); - dust->tics = 18; - dust->scalespeed = 4096; - dust->destscale = FRACUNIT/32; - } - } - else - mobj->flags2 ^= MF2_DONTDRAW; - break; - case MT_EMERALDSPAWN: - if (mobj->threshold) - { - mobj->threshold--; - - if (!mobj->threshold && !mobj->target && mobj->reactiontime) - { - mobj_t *emerald = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->reactiontime); - emerald->threshold = 42; - P_SetTarget(&mobj->target, emerald); - P_SetTarget(&emerald->target, mobj); - } - } - break; - case MT_BUGGLE: - mobj->eflags |= MFE_UNDERWATER; //P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn - { - if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 - && P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z - mobj->z) <= mobj->radius * 16) - { - // Home in on the target. - P_HomingAttack(mobj, mobj->tracer); - - if (mobj->z < mobj->floorz) - mobj->z = mobj->floorz; - - if (leveltime % mobj->info->painchance == 0) - S_StartSound(mobj, mobj->info->activesound); - - if ((statenum_t)(mobj->state-states) != mobj->info->seestate) - P_SetMobjState(mobj, mobj->info->seestate); - } - else - { - // Try to find a player - P_LookForPlayers(mobj, true, true, mobj->radius * 16); - mobj->momx >>= 1; - mobj->momy >>= 1; - mobj->momz >>= 1; - if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate) - P_SetMobjState(mobj, mobj->info->spawnstate); - } - } - break; - case MT_BUMBLEBORE: - { - statenum_t st = mobj->state-states; - if (st == S_BUMBLEBORE_FLY1 || st == S_BUMBLEBORE_FLY2) - { - if (!mobj->target) - P_SetMobjState(mobj, mobj->info->spawnstate); - else if (P_MobjFlip(mobj)*((mobj->z + (mobj->height>>1)) - (mobj->target->z + (mobj->target->height>>1))) > 0 - && R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) <= 32*FRACUNIT) - { - mobj->momx >>= 1; - mobj->momy >>= 1; - if (++mobj->movefactor == 4) - { - S_StartSound(mobj, mobj->info->seesound); - mobj->momx = mobj->momy = mobj->momz = 0; - mobj->flags = (mobj->flags|MF_PAIN) & ~MF_NOGRAVITY; - P_SetMobjState(mobj, mobj->info->meleestate); - } - } - else - mobj->movefactor = 0; - } - else if (st == S_BUMBLEBORE_RAISE || st == S_BUMBLEBORE_FALL2) // no _FALL1 because it's an 0-tic - { - if (P_IsObjectOnGround(mobj)) - { - S_StopSound(mobj); - S_StartSound(mobj, mobj->info->attacksound); - mobj->flags = (mobj->flags|MF_NOGRAVITY) & ~MF_PAIN; - mobj->momx = mobj->momy = mobj->momz = 0; - P_SetMobjState(mobj, mobj->info->painstate); - } - else - { - mobj->angle += ANGLE_22h; - mobj->frame = mobj->state->frame + ((mobj->tics & 2)>>1); - } - } - else if (st == S_BUMBLEBORE_STUCK2 && mobj->tics < TICRATE) - mobj->frame = mobj->state->frame + ((mobj->tics & 2)>>1); - } - break; - case MT_BIGMINE: - mobj->extravalue1 += 3; - mobj->extravalue1 %= 360; - P_UnsetThingPosition(mobj); - mobj->z += FINESINE(mobj->extravalue1*(FINEMASK+1)/360); - P_SetThingPosition(mobj); - break; - case MT_FLAME: - if (mobj->flags2 & MF2_BOSSNOTRAP) - { - if (!mobj->target || P_MobjWasRemoved(mobj->target)) - { - if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) - P_RemoveMobj(mobj->tracer); - P_RemoveMobj(mobj); - return; - } - mobj->z = mobj->target->z + mobj->target->momz; - if (!(mobj->eflags & MFE_VERTICALFLIP)) - mobj->z += mobj->target->height; - } - if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) - { - mobj->tracer->z = mobj->z + P_MobjFlip(mobj)*20*mobj->scale; - if (mobj->eflags & MFE_VERTICALFLIP) - mobj->tracer->z += mobj->height; - } - break; - case MT_WAVINGFLAG1: - case MT_WAVINGFLAG2: - { - fixed_t base = (leveltime<<(FRACBITS+1)); - mobj_t *seg = mobj->tracer, *prev = mobj; - mobj->movedir = mobj->angle - + ((((FINESINE((FixedAngle(base<<1)>>ANGLETOFINESHIFT) & FINEMASK) - + FINESINE((FixedAngle(base<<4)>>ANGLETOFINESHIFT) & FINEMASK))>>1) - + FINESINE((FixedAngle(base*9)>>ANGLETOFINESHIFT) & FINEMASK) - + FINECOSINE(((FixedAngle(base*9))>>ANGLETOFINESHIFT) & FINEMASK))<<12); //*2^12 - while (seg) - { - seg->movedir = seg->angle; - seg->angle = prev->movedir; - P_UnsetThingPosition(seg); - seg->x = prev->x + P_ReturnThrustX(prev, prev->angle, prev->radius); - seg->y = prev->y + P_ReturnThrustY(prev, prev->angle, prev->radius); - seg->z = prev->z + prev->height - (seg->scale>>1); - P_SetThingPosition(seg); - prev = seg; - seg = seg->tracer; - } - } - break; - case MT_SPINCUSHION: - if (mobj->target && mobj->state-states >= S_SPINCUSHION_AIM1 && mobj->state-states <= S_SPINCUSHION_AIM5) - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - break; - case MT_CRUSHCLAW: - if (mobj->state-states == S_CRUSHCLAW_STAY && mobj->target) - { - mobj_t *chain = mobj->target->target; - SINT8 sign = ((mobj->tics & 1) ? mobj->tics : -(SINT8)(mobj->tics)); - while (chain) - { - chain->z = chain->watertop + sign*mobj->scale; - sign = -sign; - chain = chain->target; - } - } - break; - case MT_SMASHINGSPIKEBALL: - mobj->momx = mobj->momy = 0; - if (mobj->state-states == S_SMASHSPIKE_FALL && P_IsObjectOnGround(mobj)) - { - P_SetMobjState(mobj, S_SMASHSPIKE_STOMP1); - S_StartSound(mobj, sfx_spsmsh); - } - else if (mobj->state-states == S_SMASHSPIKE_RISE2 && P_MobjFlip(mobj)*(mobj->z - mobj->movecount) >= 0) - { - mobj->momz = 0; - P_SetMobjState(mobj, S_SMASHSPIKE_FLOAT); - } - break; - case MT_HANGSTER: - { - statenum_t st = mobj->state-states; - //ghost image trail when flying down - if (st == S_HANGSTER_SWOOP1 || st == S_HANGSTER_SWOOP2) - { - P_SpawnGhostMobj(mobj); - //curve when in line with target, otherwise curve to avoid crashing into floor - if ((mobj->z - mobj->floorz <= 80*FRACUNIT) || (mobj->target && (mobj->z - mobj->target->z <= 80*FRACUNIT))) - P_SetMobjState(mobj, (st = S_HANGSTER_ARC1)); - } - - //swoop arc movement stuff - if (st == S_HANGSTER_ARC1) - { - A_FaceTarget(mobj); - P_Thrust(mobj, mobj->angle, 1*FRACUNIT); - } - else if (st == S_HANGSTER_ARC2) - P_Thrust(mobj, mobj->angle, 2*FRACUNIT); - else if (st == S_HANGSTER_ARC3) - P_Thrust(mobj, mobj->angle, 4*FRACUNIT); - //if movement has stopped while flying (like hitting a wall), fly up immediately - else if (st == S_HANGSTER_FLY1 && !mobj->momx && !mobj->momy) - { - mobj->extravalue1 = 0; - P_SetMobjState(mobj, S_HANGSTER_ARCUP1); - } - //after swooping back up, check for ceiling - else if ((st == S_HANGSTER_RETURN1 || st == S_HANGSTER_RETURN2) && mobj->momz == 0 && mobj->ceilingz == (mobj->z + mobj->height)) - P_SetMobjState(mobj, (st = S_HANGSTER_RETURN3)); - - //should you roost on a ceiling with F_SKY1 as its flat, disappear forever - if (st == S_HANGSTER_RETURN3 && mobj->momz == 0 && mobj->ceilingz == (mobj->z + mobj->height) - && mobj->subsector->sector->ceilingpic == skyflatnum - && mobj->subsector->sector->ceilingheight == mobj->ceilingz) - { - P_RemoveMobj(mobj); - return; - } - } - break; - case MT_LHRT: - mobj->momx = FixedMul(mobj->momx, mobj->extravalue2); - mobj->momy = FixedMul(mobj->momy, mobj->extravalue2); - break; - case MT_EGGCAPSULE: - if (!mobj->reactiontime) - { - // Target nearest player on your mare. - // (You can make it float up/down by adding MF_FLOAT, - // but beware level design pitfalls.) - fixed_t shortest = 1024*FRACUNIT; - INT32 i; - P_SetTarget(&mobj->target, NULL); - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo - && players[i].mare == mobj->threshold && players[i].spheres > 0) - { - fixed_t dist = P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y); - if (dist < shortest) - { - P_SetTarget(&mobj->target, players[i].mo); - shortest = dist; - } - } - } - break; - case MT_EGGMOBILE2_POGO: - if (!mobj->target - || !mobj->target->health - || mobj->target->state == &states[mobj->target->info->spawnstate] - || mobj->target->state == &states[mobj->target->info->raisestate]) - { - P_RemoveMobj(mobj); - return; - } - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z - mobj->height); - break; - case MT_HAMMER: - if (mobj->z <= mobj->floorz) - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_KOOPA: - P_KoopaThinker(mobj); - break; - case MT_FIREBALL: - if (P_AproxDistance(mobj->momx, mobj->momy) <= 16*FRACUNIT) // Once fireballs lose enough speed, kill them - { - P_KillMobj(mobj, NULL, NULL, 0); - return; - } - break; - case MT_REDRING: - if (((mobj->z < mobj->floorz) || (mobj->z + mobj->height > mobj->ceilingz)) - && mobj->flags & MF_MISSILE) - { - P_ExplodeMissile(mobj); - return; - } - break; - case MT_BOSSFLYPOINT: - return; - case MT_NIGHTSCORE: - mobj->color = (UINT8)(leveltime % SKINCOLOR_WHITE); - break; - case MT_JETFUME1: - { - fixed_t jetx, jety; - - if (!mobj->target // if you have no target - || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now - { // then remove yourself as well! - P_RemoveMobj(mobj); - return; - } - - jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); - jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); - - if (mobj->fuse == 56) // First one - { - P_UnsetThingPosition(mobj); - mobj->x = jetx; - mobj->y = jety; - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(38*FRACUNIT, mobj->target->scale); - else - mobj->z = mobj->target->z + FixedMul(38*FRACUNIT, mobj->target->scale); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - else if (mobj->fuse == 57) - { - P_UnsetThingPosition(mobj); - mobj->x = jetx + P_ReturnThrustX(mobj->target, mobj->target->angle-ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - mobj->y = jety + P_ReturnThrustY(mobj->target, mobj->target->angle-ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(12*FRACUNIT, mobj->target->scale); - else - mobj->z = mobj->target->z + FixedMul(12*FRACUNIT, mobj->target->scale); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - else if (mobj->fuse == 58) - { - P_UnsetThingPosition(mobj); - mobj->x = jetx + P_ReturnThrustX(mobj->target, mobj->target->angle+ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - mobj->y = jety + P_ReturnThrustY(mobj->target, mobj->target->angle+ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(12*FRACUNIT, mobj->target->scale); - else - mobj->z = mobj->target->z + FixedMul(12*FRACUNIT, mobj->target->scale); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - else if (mobj->fuse == 59) - { - boolean dashmod = ((mobj->target->flags & MF_PAIN) && (mobj->target->health <= mobj->target->info->damage)); - jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, -mobj->target->radius); - jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, -mobj->target->radius); - P_UnsetThingPosition(mobj); - mobj->x = jetx; - mobj->y = jety; - mobj->destscale = mobj->target->scale; - if (!(dashmod && mobj->target->state == states+S_METALSONIC_BOUNCE)) - { - mobj->destscale = (mobj->destscale + FixedDiv(R_PointToDist2(0, 0, mobj->target->momx, mobj->target->momy), 36*mobj->target->scale))/3; - } - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2; - else - mobj->z = mobj->target->z + mobj->target->height/2 - mobj->height/2; - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - if (dashmod) - { - mobj->color = SKINCOLOR_SUNSET; - if (mobj->target->movecount == 3 && !mobj->target->reactiontime && (mobj->target->movedir == 0 || mobj->target->movedir == 2)) - P_SpawnGhostMobj(mobj); - } - else - mobj->color = SKINCOLOR_ICY; - } - mobj->fuse++; - } - break; - case MT_JETFLAME: - { - if (!mobj->target // if you have no target - || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now - { // then remove yourself as well! - P_RemoveMobj(mobj); - return; - } - - P_UnsetThingPosition(mobj); - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - mobj->z = mobj->target->z - 50*mobj->target->scale; - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - break; - case MT_EGGROBO1: -#define SPECTATORRADIUS (96*mobj->scale) - { - if (!(mobj->flags2 & MF2_STRONGBOX)) - { - mobj->cusval = mobj->x; // eat my SOCs, p_mobj.h warning, we have lua now - mobj->cvmem = mobj->y; // ditto - mobj->movedir = mobj->angle; - mobj->threshold = P_MobjFlip(mobj)*10*mobj->scale; - if (mobj->threshold < 0) - mobj->threshold += (mobj->ceilingz - mobj->height); - else - mobj->threshold += mobj->floorz; - var1 = 4; - A_BossJetFume(mobj); - mobj->flags2 |= MF2_STRONGBOX; - } - - if (mobj->state == &states[mobj->info->deathstate]) // todo: make map actually set health to 0 for these - { - if (mobj->movecount) - { - if (!(--mobj->movecount)) - S_StartSound(mobj, mobj->info->deathsound); - } - else - { - mobj->momz += P_MobjFlip(mobj)*mobj->scale; - if (mobj->momz > 0) - { - if (mobj->z + mobj->momz > mobj->ceilingz + (1000<z + mobj->height + mobj->momz < mobj->floorz - (1000<cusval, basey = mobj->cvmem; - - if (mobj->spawnpoint && mobj->spawnpoint->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)) - { - angle_t sideang = mobj->movedir + ((mobj->spawnpoint->options & MTF_AMBUSH) ? ANGLE_90 : -ANGLE_90); - fixed_t oscillate = FixedMul(FINESINE(((leveltime*ANG1)>>(ANGLETOFINESHIFT+2)) & FINEMASK), 250*mobj->scale); - basex += P_ReturnThrustX(mobj, sideang, oscillate); - basey += P_ReturnThrustY(mobj, sideang, oscillate); - } - - mobj->z = mobj->threshold + FixedMul(FINESINE(((leveltime + mobj->movecount)*ANG2>>(ANGLETOFINESHIFT-2)) & FINEMASK), 8*mobj->scale); - if (mobj->state != &states[mobj->info->meleestate]) - { - boolean didmove = false; - - if (mobj->state == &states[mobj->info->spawnstate]) - { - UINT8 i; - fixed_t dist = INT32_MAX; - - for (i = 0; i < MAXPLAYERS; i++) - { - fixed_t compdist; - if (!playeringame[i]) - continue; - if (players[i].spectator) - continue; - if (!players[i].mo) - continue; - if (!players[i].mo->health) - continue; - if (P_PlayerInPain(&players[i])) - continue; - if (players[i].mo->z > mobj->z + mobj->height + 8*mobj->scale) - continue; - if (players[i].mo->z + players[i].mo->height < mobj->z - 8*mobj->scale) - continue; - compdist = P_AproxDistance( - players[i].mo->x + players[i].mo->momx - basex, - players[i].mo->y + players[i].mo->momy - basey); - if (compdist >= dist) - continue; - dist = compdist; - P_SetTarget(&mobj->target, players[i].mo); - } - - if (dist < (SPECTATORRADIUS<<1)) - { - didmove = true; - mobj->frame = 3 + ((leveltime & 2)>>1); - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - - if (P_AproxDistance( - mobj->x - basex, - mobj->y - basey) - < mobj->scale) - S_StartSound(mobj, mobj->info->seesound); - - P_TeleportMove(mobj, - (15*(mobj->x>>4)) + (basex>>4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS>>4), - (15*(mobj->y>>4)) + (basey>>4) + P_ReturnThrustY(mobj, mobj->angle, SPECTATORRADIUS>>4), - mobj->z); - } - else - { - angle_t diff = (mobj->movedir - mobj->angle); - if (diff > ANGLE_180) - diff = InvAngle(InvAngle(diff)/8); - else - diff /= 8; - mobj->angle += diff; - - dist = FINECOSINE(((leveltime + mobj->movecount)*ANG2>>(ANGLETOFINESHIFT-2)) & FINEMASK); - - if (abs(dist) < FRACUNIT/2) - mobj->frame = 0; - else - mobj->frame = (dist > 0) ? 1 : 2; - } - } - - if (!didmove) - { - if (P_AproxDistance(mobj->x - basex, mobj->y - basey) < mobj->scale) - P_TeleportMove(mobj, basex, basey, mobj->z); - else - P_TeleportMove(mobj, - (15*(mobj->x>>4)) + (basex>>4), - (15*(mobj->y>>4)) + (basey>>4), - mobj->z); - } - } - } - } - break; -#undef SPECTATORRADIUS - case MT_EGGROBO1JET: - { - if (!mobj->target || P_MobjWasRemoved(mobj->target) // if you have no target - || (mobj->target->health <= 0)) // or your target isn't a boss and it's popped now - { // then remove yourself as well! - P_RemoveMobj(mobj); - return; - } - - mobj->flags2 ^= MF2_DONTDRAW; - - P_UnsetThingPosition(mobj); - mobj->x = mobj->target->x + P_ReturnThrustX(mobj, mobj->target->angle+ANGLE_90, mobj->movefactor*mobj->target->scale) - P_ReturnThrustX(mobj, mobj->target->angle, 19*mobj->target->scale); - mobj->y = mobj->target->y + P_ReturnThrustY(mobj, mobj->target->angle+ANGLE_90, mobj->movefactor*mobj->target->scale) - P_ReturnThrustY(mobj, mobj->target->angle, 19*mobj->target->scale); - mobj->z = mobj->target->z; - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z += (mobj->target->height - mobj->height); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - break; - case MT_NIGHTSDRONE: - { - // variable setup - mobj_t *goalpost = NULL; - mobj_t *sparkle = NULL; - mobj_t *droneman = NULL; - - boolean flip = mobj->flags2 & MF2_OBJECTFLIP; - boolean topaligned = (mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE); - boolean middlealigned = (mobj->flags & MF_GRENADEBOUNCE) && !(mobj->flags & MF_SLIDEME); - boolean bottomoffsetted = !(mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE); - boolean flipchanged = false; - - fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff; - - if (mobj->target && mobj->target->type == MT_NIGHTSDRONE_GOAL) - { - goalpost = mobj->target; - if (goalpost->target && goalpost->target->type == MT_NIGHTSDRONE_SPARKLING) - sparkle = goalpost->target; - if (goalpost->tracer && goalpost->tracer->type == MT_NIGHTSDRONE_MAN) - droneman = goalpost->tracer; - } - - if (!goalpost || !sparkle || !droneman) - break; - - // did NIGHTSDRONE position, scale, flip, or flags change? all elements need to be synced - droneboxmandiff = max(mobj->height - droneman->height, 0); - dronemangoaldiff = max(droneman->height - goalpost->height, 0); - - if (!(goalpost->flags2 & MF2_OBJECTFLIP) && (mobj->flags2 & MF2_OBJECTFLIP)) - { - goalpost->eflags |= MFE_VERTICALFLIP; - goalpost->flags2 |= MF2_OBJECTFLIP; - sparkle->eflags |= MFE_VERTICALFLIP; - sparkle->flags2 |= MF2_OBJECTFLIP; - droneman->eflags |= MFE_VERTICALFLIP; - droneman->flags2 |= MF2_OBJECTFLIP; - flipchanged = true; - } - else if ((goalpost->flags2 & MF2_OBJECTFLIP) && !(mobj->flags2 & MF2_OBJECTFLIP)) - { - goalpost->eflags &= ~MFE_VERTICALFLIP; - goalpost->flags2 &= ~MF2_OBJECTFLIP; - sparkle->eflags &= ~MFE_VERTICALFLIP; - sparkle->flags2 &= ~MF2_OBJECTFLIP; - droneman->eflags &= ~MFE_VERTICALFLIP; - droneman->flags2 &= ~MF2_OBJECTFLIP; - flipchanged = true; - } - - if (goalpost->destscale != mobj->destscale - || goalpost->movefactor != mobj->z - || goalpost->friction != mobj->height - || flipchanged - || goalpost->threshold != (INT32)(mobj->flags & (MF_SLIDEME | MF_GRENADEBOUNCE))) - { - goalpost->destscale = sparkle->destscale = droneman->destscale = mobj->destscale; - - // straight copy-pasta from P_SpawnMapThing, case MT_NIGHTSDRONE - if (!flip) - { - if (topaligned) // Align droneman to top of hitbox - { - dronemanoffset = droneboxmandiff; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (middlealigned) // Align droneman to center of hitbox - { - dronemanoffset = droneboxmandiff / 2; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (bottomoffsetted) - { - dronemanoffset = 24*FRACUNIT; - goaloffset = dronemangoaldiff + dronemanoffset; - } - else - { - dronemanoffset = 0; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - - sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale); - } - else - { - if (topaligned) // Align droneman to top of hitbox - { - dronemanoffset = 0; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (middlealigned) // Align droneman to center of hitbox - { - dronemanoffset = droneboxmandiff / 2; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (bottomoffsetted) - { - dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); - goaloffset = dronemangoaldiff + dronemanoffset; - } - else - { - dronemanoffset = droneboxmandiff; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - - sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale); - } - - P_TeleportMove(goalpost, mobj->x, mobj->y, mobj->z + goaloffset); - P_TeleportMove(sparkle, mobj->x, mobj->y, mobj->z + sparkleoffset); - if (goalpost->movefactor != mobj->z || goalpost->friction != mobj->height) - { - P_TeleportMove(droneman, mobj->x, mobj->y, mobj->z + dronemanoffset); - goalpost->movefactor = mobj->z; - goalpost->friction = mobj->height; - } - goalpost->threshold = mobj->flags & (MF_SLIDEME | MF_GRENADEBOUNCE); - } - else - { - if (goalpost->x != mobj->x || goalpost->y != mobj->y) - { - P_TeleportMove(goalpost, mobj->x, mobj->y, goalpost->z); - P_TeleportMove(sparkle, mobj->x, mobj->y, sparkle->z); - } - - if (droneman->x != mobj->x || droneman->y != mobj->y) - P_TeleportMove(droneman, mobj->x, mobj->y, - droneman->z >= mobj->floorz && droneman->z <= mobj->ceilingz ? droneman->z : mobj->z); - } - - // now toggle states! - // GOAL mode? - if (sparkle->state >= &states[S_NIGHTSDRONE_SPARKLING1] && sparkle->state <= &states[S_NIGHTSDRONE_SPARKLING16]) - { - INT32 i; - boolean bonustime = false; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) - { - bonustime = true; - break; - } - - if (!bonustime) - { - CONS_Debug(DBG_NIGHTSBASIC, "Removing goal post\n"); - if (goalpost && goalpost->state != &states[S_INVISIBLE]) - P_SetMobjState(goalpost, S_INVISIBLE); - if (sparkle && sparkle->state != &states[S_INVISIBLE]) - P_SetMobjState(sparkle, S_INVISIBLE); - } - } - // Invisible/bouncing mode. - else - { - INT32 i; - boolean bonustime = false; - fixed_t zcomp; - - // Bouncy bouncy! - if (!flip) - { - if (topaligned) - zcomp = droneboxmandiff + mobj->z; - else if (middlealigned) - zcomp = (droneboxmandiff / 2) + mobj->z; - else if (bottomoffsetted) - zcomp = mobj->z + FixedMul(24*FRACUNIT, mobj->scale); - else - zcomp = mobj->z; - } - else - { - if (topaligned) - zcomp = mobj->z; - else if (middlealigned) - zcomp = (droneboxmandiff / 2) + mobj->z; - else if (bottomoffsetted) - zcomp = mobj->z + droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); - else - zcomp = mobj->z + droneboxmandiff; - } - - droneman->angle += ANG10; - if (!flip && droneman->z <= zcomp) - droneman->momz = FixedMul(5*FRACUNIT, droneman->scale); - else if (flip && droneman->z >= zcomp) - droneman->momz = FixedMul(-5*FRACUNIT, droneman->scale); - - // state switching logic - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) - { - bonustime = true; - break; - } - - if (bonustime) - { - CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n"); - if (!(droneman->flags2 & MF2_DONTDRAW)) - droneman->flags2 |= MF2_DONTDRAW; - if (goalpost->state == &states[S_INVISIBLE]) - P_SetMobjState(goalpost, mobjinfo[goalpost->type].meleestate); - if (sparkle->state == &states[S_INVISIBLE]) - P_SetMobjState(sparkle, mobjinfo[sparkle->type].meleestate); - } - else if (!G_IsSpecialStage(gamemap)) - { - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].powers[pw_carry] != CR_NIGHTSMODE) - { - bonustime = true; // variable reuse - break; - } - - if (bonustime) - { - // show droneman if at least one player is non-nights - if (goalpost->state != &states[S_INVISIBLE]) - P_SetMobjState(goalpost, S_INVISIBLE); - if (sparkle->state != &states[S_INVISIBLE]) - P_SetMobjState(sparkle, S_INVISIBLE); - if (droneman->state != &states[mobjinfo[droneman->type].meleestate]) - P_SetMobjState(droneman, mobjinfo[droneman->type].meleestate); - if (droneman->flags2 & MF2_DONTDRAW) - droneman->flags2 &= ~MF2_DONTDRAW; - } - else - { - // else, hide it - if (!(droneman->flags2 & MF2_DONTDRAW)) - droneman->flags2 |= MF2_DONTDRAW; - } - } - } - } - break; - case MT_PLAYER: - if (mobj->player) - P_PlayerMobjThinker(mobj); - return; - case MT_SKIM: - // check mobj against possible water content, before movement code - P_MobjCheckWater(mobj); - - // Keep Skim at water surface - if (mobj->z <= mobj->watertop) - { - mobj->flags |= MF_NOGRAVITY; - if (mobj->z < mobj->watertop) - { - if (mobj->watertop - mobj->z <= FixedMul(mobj->info->speed*FRACUNIT, mobj->scale)) - mobj->z = mobj->watertop; - else - mobj->momz = FixedMul(mobj->info->speed*FRACUNIT, mobj->scale); - } - } - else - { - mobj->flags &= ~MF_NOGRAVITY; - if (mobj->z > mobj->watertop && mobj->z - mobj->watertop < FixedMul(MAXSTEPMOVE, mobj->scale)) - mobj->z = mobj->watertop; - } - 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: - // No need to check water. Who cares? - P_RingThinker(mobj); - if (mobj->flags2 & MF2_NIGHTSPULL) - P_NightsItemChase(mobj); - else - A_AttractChase(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: - if (mobj->flags2 & MF2_NIGHTSPULL) - P_NightsItemChase(mobj); - else - A_AttractChase(mobj); - break; - case MT_EMBLEM: - if (mobj->flags2 & MF2_NIGHTSPULL) - P_NightsItemChase(mobj); - break; - case MT_SHELL: - if (mobj->threshold && mobj->threshold != TICRATE) - mobj->threshold--; - - if (mobj->threshold >= TICRATE) - { - mobj->angle += ((mobj->movedir == 1) ? ANGLE_22h : ANGLE_337h); - P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), (mobj->info->speed*mobj->scale)); - } - break; - case MT_TURRET: - P_MobjCheckWater(mobj); - P_CheckPosition(mobj, mobj->x, mobj->y); - if (P_MobjWasRemoved(mobj)) - return; - mobj->floorz = tmfloorz; - mobj->ceilingz = tmceilingz; - mobj->floorrover = tmfloorrover; - mobj->ceilingrover = tmceilingrover; - - if ((mobj->eflags & MFE_UNDERWATER) && mobj->health > 0) - { - P_SetMobjState(mobj, mobj->info->deathstate); - mobj->health = 0; - mobj->flags2 &= ~MF2_FIRING; - } - else if (mobj->health > 0 && mobj->z + mobj->height > mobj->ceilingz) // Crushed - { - INT32 i,j; - fixed_t ns; - fixed_t x,y,z; - mobj_t *mo2; - - z = mobj->subsector->sector->floorheight + FixedMul(64*FRACUNIT, mobj->scale); - for (j = 0; j < 2; j++) - { - for (i = 0; i < 32; i++) - { - const angle_t fa = (i*FINEANGLES/16) & FINEMASK; - ns = FixedMul(64 * FRACUNIT, mobj->scale); - x = mobj->x + FixedMul(FINESINE(fa),ns); - y = mobj->y + FixedMul(FINECOSINE(fa),ns); - - mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); - ns = FixedMul(16 * FRACUNIT, mobj->scale); - mo2->momx = FixedMul(FINESINE(fa),ns); - mo2->momy = FixedMul(FINECOSINE(fa),ns); - } - z -= FixedMul(32*FRACUNIT, mobj->scale); - } - P_SetMobjState(mobj, mobj->info->deathstate); - mobj->health = 0; - mobj->flags2 &= ~MF2_FIRING; - } - break; - case MT_BLUEFLAG: - case MT_REDFLAG: - { - sector_t *sec2; - sec2 = P_ThingOnSpecial3DFloor(mobj); - if ((sec2 && GETSECSPECIAL(sec2->special, 4) == 2) || (GETSECSPECIAL(mobj->subsector->sector->special, 4) == 2)) - mobj->fuse = 1; // Return to base. - break; - } - case MT_CANNONBALL: -#ifdef FLOORSPLATS - R_AddFloorSplat(mobj->tracer->subsector, mobj->tracer, "TARGET", mobj->tracer->x, - mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE); -#endif - break; - case MT_SPINDUST: // Spindash dust - mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000 - mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same - //mobj->momz = mobj->momz+P_MobjFlip(mobj)/3; // no meaningful change in value to be frank - if (mobj->state >= &states[S_SPINDUST_BUBBLE1] && mobj->state <= &states[S_SPINDUST_BUBBLE4]) // bubble dust! - { - P_MobjCheckWater(mobj); - if (mobj->watertop != mobj->subsector->sector->floorheight - 1000*FRACUNIT - && mobj->z+mobj->height >= mobj->watertop - 5*FRACUNIT) - mobj->flags2 |= MF2_DONTDRAW; - } - break; - case MT_TRAINDUSTSPAWNER: - if (leveltime % 5 == 0) { - mobj_t *traindust = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PARTICLE); - traindust->flags = MF_SCENERY; - P_SetMobjState(traindust, S_TRAINDUST); - traindust->frame = P_RandomRange(0, 8) | FF_TRANS90; - traindust->angle = mobj->angle; - traindust->tics = TICRATE * 4; - traindust->destscale = FRACUNIT * 64; - traindust->scalespeed = FRACUNIT / 24; - P_SetScale(traindust, FRACUNIT * 6); - } - break; - case MT_TRAINSTEAMSPAWNER: - if (leveltime % 5 == 0) { - mobj_t *steam = P_SpawnMobj(mobj->x + FRACUNIT*P_SignedRandom() / 2, mobj->y + FRACUNIT*P_SignedRandom() / 2, mobj->z, MT_PARTICLE); - P_SetMobjState(steam, S_TRAINSTEAM); - steam->frame = P_RandomRange(0, 1) | FF_TRANS90; - steam->tics = TICRATE * 8; - steam->destscale = FRACUNIT * 64; - steam->scalespeed = FRACUNIT / 8; - P_SetScale(steam, FRACUNIT * 16); - steam->momx = P_SignedRandom() * 32; - steam->momy = -64 * FRACUNIT; - steam->momz = 2 * FRACUNIT; - } - break; - case MT_CANARIVORE_GAS: - { - fixed_t momz; - - if (mobj->flags2 & MF2_AMBUSH) - { - mobj->momx = FixedMul(mobj->momx, 50 * FRACUNIT / 51); - mobj->momy = FixedMul(mobj->momy, 50 * FRACUNIT / 51); - break; - } - - if (mobj->eflags & MFE_VERTICALFLIP) - { - if ((mobj->z + mobj->height + mobj->momz) <= mobj->ceilingz) - break; - } - else - { - if ((mobj->z + mobj->momz) >= mobj->floorz) - break; - } - - momz = abs(mobj->momz); - if (R_PointToDist2(0, 0, mobj->momx, mobj->momy) < momz) - P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), momz); - mobj->flags2 |= MF2_AMBUSH; - break; - } - case MT_SALOONDOOR: - { - fixed_t x = mobj->tracer->x; - fixed_t y = mobj->tracer->y; - fixed_t z = mobj->tracer->z; - angle_t oang = FixedAngle(mobj->extravalue1); - angle_t fa = (oang >> ANGLETOFINESHIFT) & FINEMASK; - fixed_t c0 = -96*FINECOSINE(fa); - fixed_t s0 = -96*FINESINE(fa); - angle_t fma; - fixed_t c, s; - angle_t angdiff; - - // Adjust angular speed - fixed_t da = AngleFixed(mobj->angle - oang); - if (da > 180*FRACUNIT) - da -= 360*FRACUNIT; - mobj->extravalue2 = 8*(mobj->extravalue2 - da/32)/9; - - // Update angle - mobj->angle += FixedAngle(mobj->extravalue2); - - angdiff = mobj->angle - FixedAngle(mobj->extravalue1); - if (angdiff > (ANGLE_90 - ANG2) && angdiff < ANGLE_180) - { - mobj->angle = FixedAngle(mobj->extravalue1) + (ANGLE_90 - ANG2); - mobj->extravalue2 /= 2; - } - else if (angdiff < (ANGLE_270 + ANG2) && angdiff >= ANGLE_180) - { - mobj->angle = FixedAngle(mobj->extravalue1) + (ANGLE_270 + ANG2); - mobj->extravalue2 /= 2; - } - - // Update position - fma = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK; - c = 48*FINECOSINE(fma); - s = 48*FINESINE(fma); - P_TeleportMove(mobj, x + c0 + c, y + s0 + s, z); - break; - } - case MT_MINECARTSPAWNER: - P_HandleMinecartSegments(mobj); - if (!mobj->fuse || mobj->fuse > TICRATE) - break; - if (mobj->fuse == 2) - { - mobj->fuse = 0; - break; - } - 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 (hdist > 1500*FRACUNIT) - { - mobj->flags2 &= ~MF2_BOSSNOTRAP; - P_SetTarget(&mobj->target, NULL); - break; - } - - 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; - } - 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_DRAGONBOMBER: - { -#define DRAGONTURNSPEED ANG2 - mobj->movecount = (mobj->movecount + 9) % 360; - P_SetObjectMomZ(mobj, 4*FINESINE(((mobj->movecount*ANG1) >> ANGLETOFINESHIFT) & FINEMASK), false); - if (mobj->threshold > 0) // are we dropping mines? - { - mobj->threshold--; - if (mobj->threshold == 0) // if the timer hits 0, look for a mine to drop! - { - mobj_t *segment = mobj; - while (segment->tracer != NULL && !P_MobjWasRemoved(segment->tracer) && segment->tracer->state == &states[segment->tracer->info->spawnstate]) - { - segment = segment->tracer; - } - if (segment != mobj) // found an unactivated segment? - { - mobj_t *mine = P_SpawnMobjFromMobj(segment, 0, 0, 0, segment->info->painchance); - mine->angle = segment->angle; - P_InstaThrust(mine, mobj->angle, P_AproxDistance(mobj->momx, mobj->momy) >> 1); - P_SetObjectMomZ(mine, -2*FRACUNIT, true); - S_StartSound(mine, mine->info->seesound); - P_SetMobjState(segment, segment->info->raisestate); - mobj->threshold = mobj->info->painchance; - } - } - } - if (mobj->target != NULL) // Are we chasing a player? - { - fixed_t dist = P_AproxDistance(mobj->x - mobj->target->x, mobj->y - mobj->target->y); - if (dist > 2000 * mobj->scale) // Not anymore! - P_SetTarget(&mobj->target, NULL); - else - { - fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); - fixed_t z = mobj->target->z + (mobj->height >> 1) + (mobj->flags & MFE_VERTICALFLIP ? -128*mobj->scale : 128*mobj->scale + mobj->target->height); - angle_t diff = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) - mobj->angle; - if (diff > ANGLE_180) - mobj->angle -= DRAGONTURNSPEED; - else - mobj->angle += DRAGONTURNSPEED; - if (!mobj->threshold && dist < 512 * mobj->scale) // Close enough to drop bombs - { - mobj->threshold = mobj->info->painchance; - } - mobj->momz += max(min(z - mobj->z, vspeed), -vspeed); - } - } - else // Can we find a player to chase? - { - if (mobj->tracer == NULL || mobj->tracer->state != &states[mobj->tracer->info->spawnstate] - || !P_LookForPlayers(mobj, true, false, 2000*mobj->scale)) // if not, circle around the spawnpoint - { - if (!mobj->spawnpoint) // unless we don't have one, in which case uhhh just circle around wherever we currently are I guess?? - mobj->angle += DRAGONTURNSPEED; - else - { - fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); - fixed_t x = mobj->spawnpoint->x << FRACBITS; - fixed_t y = mobj->spawnpoint->y << FRACBITS; - fixed_t z = mobj->spawnpoint->z << FRACBITS; - angle_t diff = R_PointToAngle2(mobj->x, mobj->y, x, y) - mobj->angle; - if (diff > ANGLE_180) - mobj->angle -= DRAGONTURNSPEED; - else - mobj->angle += DRAGONTURNSPEED; - mobj->momz += max(min(z - mobj->z, vspeed), -vspeed); - } - } - } - P_InstaThrust(mobj, mobj->angle, FixedMul(mobj->info->speed, mobj->scale)); -#undef DRAGONTURNSPEED - } - break; - case MT_MINUS: -#ifdef ROTSPRITE - { - if (P_IsObjectOnGround(mobj)) - mobj->rollangle = 0; - else - mobj->rollangle = R_PointToAngle2(0, 0, mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1)); - } -#endif - break; - case MT_SPINFIRE: - if (mobj->flags & MF_NOGRAVITY) - { - if (mobj->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->ceilingz - mobj->height; - else - mobj->z = mobj->floorz; - } - else if ((!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z <= mobj->floorz) - || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z+mobj->height >= mobj->ceilingz)) - { - mobj->flags |= MF_NOGRAVITY; - mobj->momx = 8; // this is a hack which is used to ensure it still behaves as a missile and can damage others - mobj->momy = mobj->momz = 0; - mobj->z = ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->ceilingz-mobj->height : mobj->floorz); - } - /* FALLTHRU */ - default: - // check mobj against possible water content, before movement code - P_MobjCheckWater(mobj); - - // Extinguish fire objects in water - if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL - && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) - { - P_KillMobj(mobj, NULL, NULL, 0); - return; - } - break; - } + if (!P_MobjRegularThink(mobj)) + return; } if (P_MobjWasRemoved(mobj)) return; From 6032aa3cd1c2d55053971fb2738f6f4753306aa6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 25 Dec 2019 00:18:12 +0100 Subject: [PATCH 158/312] P_MobjThinker: Separate MF2_FIRING handling into its own function --- src/p_mobj.c | 93 ++++++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 84592dcaa..10ca92a2d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9803,6 +9803,55 @@ static boolean P_MobjRegularThink(mobj_t *mobj) return true; } +static void P_FiringThink(mobj_t* mobj) +{ + if (!mobj->target) + return; + + if (mobj->health <= 0) + return; + + if (mobj->state->action.acp1 == (actionf_p1)A_Boss1Laser) + { + if (mobj->state->tics > 1) + { + var1 = mobj->state->var1; + var2 = mobj->state->var2 & 65535; + mobj->state->action.acp1(mobj); + } + } + else if (leveltime & 1) // Fire mode + { + mobj_t *missile; + + if (mobj->target->player && mobj->target->player->powers[pw_carry] == CR_NIGHTSMODE) + { + fixed_t oldval = mobjinfo[mobj->extravalue1].speed; + + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx, mobj->target->y + mobj->target->momy); + mobjinfo[mobj->extravalue1].speed = FixedMul(60*FRACUNIT, mobj->scale); + missile = P_SpawnMissile(mobj, mobj->target, mobj->extravalue1); + mobjinfo[mobj->extravalue1].speed = oldval; + } + else + { + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + missile = P_SpawnMissile(mobj, mobj->target, mobj->extravalue1); + } + + if (missile) + { + if (mobj->flags2 & MF2_SUPERFIRE) + missile->flags2 |= MF2_SUPERFIRE; + + if (mobj->info->attacksound) + S_StartSound(missile, mobj->info->attacksound); + } + } + else + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); +} + // // P_MobjThinker // @@ -9907,48 +9956,8 @@ void P_MobjThinker(mobj_t *mobj) if (P_MobjWasRemoved(mobj)) return; - if (mobj->flags2 & MF2_FIRING && mobj->target && mobj->health > 0) - { - if (mobj->state->action.acp1 == (actionf_p1)A_Boss1Laser) - { - if (mobj->state->tics > 1) - { - var1 = mobj->state->var1; - var2 = mobj->state->var2 & 65535; - mobj->state->action.acp1(mobj); - } - } - else if (leveltime & 1) // Fire mode - { - mobj_t *missile; - - if (mobj->target->player && mobj->target->player->powers[pw_carry] == CR_NIGHTSMODE) - { - fixed_t oldval = mobjinfo[mobj->extravalue1].speed; - - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x+mobj->target->momx, mobj->target->y+mobj->target->momy); - mobjinfo[mobj->extravalue1].speed = FixedMul(60*FRACUNIT, mobj->scale); - missile = P_SpawnMissile(mobj, mobj->target, mobj->extravalue1); - mobjinfo[mobj->extravalue1].speed = oldval; - } - else - { - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - missile = P_SpawnMissile(mobj, mobj->target, mobj->extravalue1); - } - - if (missile) - { - if (mobj->flags2 & MF2_SUPERFIRE) - missile->flags2 |= MF2_SUPERFIRE; - - if (mobj->info->attacksound) - S_StartSound(missile, mobj->info->attacksound); - } - } - else - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - } + if (mobj->flags2 & MF2_FIRING) + P_FiringThink(mobj); if (mobj->flags & MF_AMBIENT) { From f0ef4e3193b94553eebbc8158b43cfebbc51c24e Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 24 Dec 2019 18:31:47 -0500 Subject: [PATCH 159/312] Fix edge case with R_SkinUsable --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index aa2a73515..a4bc14c02 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2839,7 +2839,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) { return ((skinnum == -1) // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... || (!skins[skinnum].availability) - || ((playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) + || (((netgame || multiplayer) && playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) || (modeattacking) // If you have someone else's run you might as well take a look || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. || (netgame && (cv_forceskin.value == skinnum)) // Force 2. From 64df10f7bee74f221fd2a70978948911613a9822 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 25 Dec 2019 00:36:24 +0100 Subject: [PATCH 160/312] P_MobjThinker: Separate fuse handling into its own function --- src/p_mobj.c | 437 ++++++++++++++++++++++++++------------------------- 1 file changed, 226 insertions(+), 211 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 10ca92a2d..292545328 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9803,7 +9803,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) return true; } -static void P_FiringThink(mobj_t* mobj) +static void P_FiringThink(mobj_t *mobj) { if (!mobj->target) return; @@ -9852,6 +9852,229 @@ static void P_FiringThink(mobj_t* mobj) mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); } +static void P_MonitorFuseThink(mobj_t *mobj) +{ + mobj_t *newmobj; + + // Special case for ALL monitors. + // If a box's speed is nonzero, it's allowed to respawn as a WRM/SRM. + if (mobj->info->speed != 0 && (mobj->flags2 & (MF2_AMBUSH|MF2_STRONGBOX))) + { + mobjtype_t spawnchance[64]; + INT32 numchoices = 0, i = 0; + + // This define should make it a lot easier to organize and change monitor weights +#define SETMONITORCHANCES(type, strongboxamt, weakboxamt) \ +for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) spawnchance[numchoices++] = type + + // Type SRM WRM + SETMONITORCHANCES(MT_SNEAKERS_BOX, 0, 10); // Super Sneakers + SETMONITORCHANCES(MT_INVULN_BOX, 2, 0); // Invincibility + SETMONITORCHANCES(MT_WHIRLWIND_BOX, 3, 8); // Whirlwind Shield + SETMONITORCHANCES(MT_ELEMENTAL_BOX, 3, 8); // Elemental Shield + SETMONITORCHANCES(MT_ATTRACT_BOX, 2, 0); // Attraction Shield + SETMONITORCHANCES(MT_FORCE_BOX, 3, 3); // Force Shield + SETMONITORCHANCES(MT_ARMAGEDDON_BOX, 2, 0); // Armageddon Shield + SETMONITORCHANCES(MT_MIXUP_BOX, 0, 1); // Teleporters + SETMONITORCHANCES(MT_RECYCLER_BOX, 0, 1); // Recycler + SETMONITORCHANCES(MT_1UP_BOX, 1, 1); // 1-Up + // ======================================= + // Total 16 32 + +#undef SETMONITORCHANCES + + i = P_RandomKey(numchoices); // Gotta love those random numbers! + newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]); + } + else + newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); + + // Transfer flags2 (ambush, strongbox, objectflip) + newmobj->flags2 = mobj->flags2; + P_RemoveMobj(mobj); // make sure they disappear +} + +static void P_FlagFuseThink(mobj_t *mobj) +{ + subsector_t *ss; + fixed_t x, y, z; + mobj_t* flagmo; + + if (!mobj->spawnpoint) + return; + + x = mobj->spawnpoint->x << FRACBITS; + y = mobj->spawnpoint->y << FRACBITS; + ss = R_PointInSubsector(x, y); + if (mobj->spawnpoint->options & MTF_OBJECTFLIP) + { + z = ss->sector->ceilingheight - mobjinfo[mobj->type].height; + if (mobj->spawnpoint->options >> ZSHIFT) + z -= (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; + } + else + { + z = ss->sector->floorheight; + if (mobj->spawnpoint->options >> ZSHIFT) + z += (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; + } + flagmo = P_SpawnMobj(x, y, z, mobj->type); + flagmo->spawnpoint = mobj->spawnpoint; + if (mobj->spawnpoint->options & MTF_OBJECTFLIP) + { + flagmo->eflags |= MFE_VERTICALFLIP; + flagmo->flags2 |= MF2_OBJECTFLIP; + } + + if (mobj->type == MT_REDFLAG) + { + if (!(mobj->flags2 & MF2_JUSTATTACKED)) + CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x85, M_GetText("Red flag"), 0x80); + + // Assumedly in splitscreen players will be on opposing teams + if (players[consoleplayer].ctfteam == 1 || splitscreen) + S_StartSound(NULL, sfx_hoop1); + else if (players[consoleplayer].ctfteam == 2) + S_StartSound(NULL, sfx_hoop3); + + redflag = flagmo; + } + else // MT_BLUEFLAG + { + if (!(mobj->flags2 & MF2_JUSTATTACKED)) + CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x84, M_GetText("Blue flag"), 0x80); + + // Assumedly in splitscreen players will be on opposing teams + if (players[consoleplayer].ctfteam == 2 || splitscreen) + S_StartSound(NULL, sfx_hoop1); + else if (players[consoleplayer].ctfteam == 1) + S_StartSound(NULL, sfx_hoop3); + + blueflag = flagmo; + } +} + +static boolean P_FuseThink(mobj_t *mobj) +{ + if (mobj->type == MT_SNAPPER_HEAD || mobj->type == MT_SNAPPER_LEG || mobj->type == MT_MINECARTSEG) + mobj->flags2 ^= MF2_DONTDRAW; + + mobj->fuse--; + + if (mobj->fuse) + return true; + +#ifdef HAVE_BLUA + if (LUAh_MobjFuse(mobj) || P_MobjWasRemoved(mobj)) + ; + else +#endif + if (mobj->info->flags & MF_MONITOR) + { + P_MonitorFuseThink(mobj); + return false; + } + else switch (mobj->type) + { + // gargoyle and snowman handled in P_PushableThinker, not here + case MT_THROWNGRENADE: + case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: + P_SetMobjState(mobj, mobj->info->deathstate); + break; + case MT_LHRT: + P_KillMobj(mobj, NULL, NULL, 0); + break; + case MT_BLUEFLAG: + case MT_REDFLAG: + P_FlagFuseThink(mobj); + P_RemoveMobj(mobj); + return false; + case MT_FANG: + if (mobj->flags2 & MF2_SLIDEPUSH) + { + var1 = 0; + var2 = 0; + A_BossDeath(mobj); + return false; + } + P_SetMobjState(mobj, mobj->state->nextstate); + if (P_MobjWasRemoved(mobj)) + return false; + break; + case MT_METALSONIC_BATTLE: + break; // don't remove + case MT_SPIKE: + P_SetMobjState(mobj, mobj->state->nextstate); + mobj->fuse = mobj->info->speed; + if (mobj->spawnpoint) + mobj->fuse += mobj->spawnpoint->angle; + break; + case MT_WALLSPIKE: + P_SetMobjState(mobj, mobj->state->nextstate); + mobj->fuse = mobj->info->speed; + if (mobj->spawnpoint) + mobj->fuse += (mobj->spawnpoint->angle / 360); + break; + case MT_NIGHTSCORE: + P_RemoveMobj(mobj); + return false; + 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 false; + 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 false; + case MT_PLAYER: + break; // don't remove + default: + P_SetMobjState(mobj, mobj->info->xdeathstate); // will remove the mobj if S_NULL. + break; + // Looking for monitors? They moved to a special condition above. + } + + return !P_MobjWasRemoved(mobj); +} + // // P_MobjThinker // @@ -9967,216 +10190,8 @@ void P_MobjThinker(mobj_t *mobj) } // Check fuse - if (mobj->fuse) - { - - if (mobj->type == MT_SNAPPER_HEAD || mobj->type == MT_SNAPPER_LEG || mobj->type == MT_MINECARTSEG) - mobj->flags2 ^= MF2_DONTDRAW; - - mobj->fuse--; - if (!mobj->fuse) - { - subsector_t *ss; - fixed_t x, y, z; - mobj_t *flagmo, *newmobj; - -#ifdef HAVE_BLUA - if (LUAh_MobjFuse(mobj) || P_MobjWasRemoved(mobj)) - ; - else -#endif - if (mobj->info->flags & MF_MONITOR) - { - // Special case for ALL monitors. - // If a box's speed is nonzero, it's allowed to respawn as a WRM/SRM. - if (mobj->info->speed != 0 && (mobj->flags2 & (MF2_AMBUSH|MF2_STRONGBOX))) - { - mobjtype_t spawnchance[64]; - INT32 numchoices = 0, i = 0; - -// This define should make it a lot easier to organize and change monitor weights -#define SETMONITORCHANCES(type, strongboxamt, weakboxamt) \ -for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) spawnchance[numchoices++] = type - - // Type SRM WRM - SETMONITORCHANCES(MT_SNEAKERS_BOX, 0, 10); // Super Sneakers - SETMONITORCHANCES(MT_INVULN_BOX, 2, 0); // Invincibility - SETMONITORCHANCES(MT_WHIRLWIND_BOX, 3, 8); // Whirlwind Shield - SETMONITORCHANCES(MT_ELEMENTAL_BOX, 3, 8); // Elemental Shield - SETMONITORCHANCES(MT_ATTRACT_BOX, 2, 0); // Attraction Shield - SETMONITORCHANCES(MT_FORCE_BOX, 3, 3); // Force Shield - SETMONITORCHANCES(MT_ARMAGEDDON_BOX, 2, 0); // Armageddon Shield - SETMONITORCHANCES(MT_MIXUP_BOX, 0, 1); // Teleporters - SETMONITORCHANCES(MT_RECYCLER_BOX, 0, 1); // Recycler - SETMONITORCHANCES(MT_1UP_BOX, 1, 1); // 1-Up - // ======================================= - // Total 16 32 - -#undef SETMONITORCHANCES - - i = P_RandomKey(numchoices); // Gotta love those random numbers! - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]); - } - else - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); - - // Transfer flags2 (ambush, strongbox, objectflip) - newmobj->flags2 = mobj->flags2; - P_RemoveMobj(mobj); // make sure they disappear - return; - } - else switch (mobj->type) - { - // gargoyle and snowman handled in P_PushableThinker, not here - case MT_THROWNGRENADE: - case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: - P_SetMobjState(mobj, mobj->info->deathstate); - break; - case MT_LHRT: - P_KillMobj(mobj, NULL, NULL, 0); - break; - case MT_BLUEFLAG: - case MT_REDFLAG: - if (mobj->spawnpoint) - { - x = mobj->spawnpoint->x << FRACBITS; - y = mobj->spawnpoint->y << FRACBITS; - ss = R_PointInSubsector(x, y); - if (mobj->spawnpoint->options & MTF_OBJECTFLIP) - { - z = ss->sector->ceilingheight - mobjinfo[mobj->type].height; - if (mobj->spawnpoint->options >> ZSHIFT) - z -= (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; - } - else - { - z = ss->sector->floorheight; - if (mobj->spawnpoint->options >> ZSHIFT) - z += (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; - } - flagmo = P_SpawnMobj(x, y, z, mobj->type); - flagmo->spawnpoint = mobj->spawnpoint; - if (mobj->spawnpoint->options & MTF_OBJECTFLIP) - { - flagmo->eflags |= MFE_VERTICALFLIP; - flagmo->flags2 |= MF2_OBJECTFLIP; - } - - if (mobj->type == MT_REDFLAG) - { - if (!(mobj->flags2 & MF2_JUSTATTACKED)) - CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x85, M_GetText("Red flag"), 0x80); - - // Assumedly in splitscreen players will be on opposing teams - if (players[consoleplayer].ctfteam == 1 || splitscreen) - S_StartSound(NULL, sfx_hoop1); - else if (players[consoleplayer].ctfteam == 2) - S_StartSound(NULL, sfx_hoop3); - - redflag = flagmo; - } - else // MT_BLUEFLAG - { - if (!(mobj->flags2 & MF2_JUSTATTACKED)) - CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x84, M_GetText("Blue flag"), 0x80); - - // Assumedly in splitscreen players will be on opposing teams - if (players[consoleplayer].ctfteam == 2 || splitscreen) - S_StartSound(NULL, sfx_hoop1); - else if (players[consoleplayer].ctfteam == 1) - S_StartSound(NULL, sfx_hoop3); - - blueflag = flagmo; - } - } - P_RemoveMobj(mobj); - return; - case MT_FANG: - if (mobj->flags2 & MF2_SLIDEPUSH) - { - var1 = 0; - var2 = 0; - A_BossDeath(mobj); - return; - } - P_SetMobjState(mobj, mobj->state->nextstate); - if (P_MobjWasRemoved(mobj)) - return; - break; - case MT_METALSONIC_BATTLE: - break; // don't remove - case MT_SPIKE: - P_SetMobjState(mobj, mobj->state->nextstate); - mobj->fuse = mobj->info->speed; - if (mobj->spawnpoint) - mobj->fuse += mobj->spawnpoint->angle; - break; - case MT_WALLSPIKE: - P_SetMobjState(mobj, mobj->state->nextstate); - mobj->fuse = mobj->info->speed; - if (mobj->spawnpoint) - mobj->fuse += (mobj->spawnpoint->angle/360); - break; - 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: - P_SetMobjState(mobj, mobj->info->xdeathstate); // will remove the mobj if S_NULL. - break; - // Looking for monitors? They moved to a special condition above. - } - if (P_MobjWasRemoved(mobj)) - return; - } - } + if (mobj->fuse && !P_FuseThink(mobj)) + return; I_Assert(mobj != NULL); I_Assert(!P_MobjWasRemoved(mobj)); From b9a276f5aaa918bb2cabc54246e259bd7a70c784 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 25 Dec 2019 09:10:20 +0100 Subject: [PATCH 161/312] Make slope vertices use mt->z directly instead of mt->options >> ZSHIFT --- src/p_slopes.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index 89d265fa4..1dc4f9819 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -445,10 +445,9 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag I_Error("MakeViaMapthings: Slope vertex %s (for linedef tag %d) not found!", sizeu1(i), tag1); vx[i].x = mt->x << FRACBITS; vx[i].y = mt->y << FRACBITS; - if (mt->extrainfo) - vx[i].z = mt->options << FRACBITS; - else - vx[i].z = (R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector->floorheight) + ((mt->options >> ZSHIFT) << FRACBITS); + vx[i].z = mt->z << FRACBITS; + if (!mt->extrainfo) + vx[i].z += R_PointInSubsector(vx[i].x, vx[i].y)->sector->floorheight; } ReconfigureViaVertexes(ret, vx[0], vx[1], vx[2]); From 32ef930c04d6a0bd9437ad0a34c2cd23c14e16d8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 25 Dec 2019 09:40:08 +0100 Subject: [PATCH 162/312] Get rid of a few mt->options >> ZSHIFT usages in objectplace --- src/m_cheat.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/m_cheat.c b/src/m_cheat.c index 3d1fe5b7e..52b79f930 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1193,14 +1193,14 @@ void OP_NightsObjectplace(player_t *player) if (cmd->buttons & BT_TOSSFLAG) { UINT16 vertangle = (UINT16)(player->anotherflyangle % 360); - UINT16 newflags, newz; + UINT16 newflags; player->pflags |= PF_ATTACKDOWN; if (!OP_HeightOkay(player, false)) return; mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_NIGHTSBUMPER].doomednum, false); - newz = min((mt->options >> ZSHIFT) - (mobjinfo[MT_NIGHTSBUMPER].height/4), 0); + mt->z = min(mt->z - (mobjinfo[MT_NIGHTSBUMPER].height/4), 0); // height offset: from P_TouchSpecialThing case MT_NIGHTSBUMPER // clockwise @@ -1231,7 +1231,7 @@ void OP_NightsObjectplace(player_t *player) else // forward newflags = 0; - mt->options = (newz << ZSHIFT) | newflags; + mt->options = (mt->z << ZSHIFT) | newflags; // if NiGHTS is facing backwards, orient the Thing angle forwards so that the sprite angle // displays correctly. Backwards movement via the Thing flags is unaffected. @@ -1439,7 +1439,7 @@ void OP_ObjectplaceMovement(player_t *player) else P_SpawnMapThing(mt); - CONS_Printf(M_GetText("Placed object type %d at %d, %d, %d, %d\n"), mt->type, mt->x, mt->y, mt->options>>ZSHIFT, mt->angle); + CONS_Printf(M_GetText("Placed object type %d at %d, %d, %d, %d\n"), mt->type, mt->x, mt->y, mt->z, mt->angle); } } From 12d30b7acc537aa520ff825e266342c872752007 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 25 Dec 2019 09:46:09 +0100 Subject: [PATCH 163/312] Use mthing->z instead of mthing->options >> ZSHIFT in particle generator setup --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 292545328..4be20a81b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12464,7 +12464,7 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj) || (ticcount = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS)) < 1) ticcount = 3; - numdivisions = (mthing->options >> ZSHIFT); + numdivisions = mthing->z; if (numdivisions) { From f4c6068ab1b92d48be8ba73b038b755abc863700 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 25 Dec 2019 10:59:12 +0100 Subject: [PATCH 164/312] P_MovePlayerToSpawn: Use mthing->z instead of mthing->options >> ZSHIFT --- src/p_mobj.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 4be20a81b..bc5121318 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11562,7 +11562,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) fixed_t z; sector_t *sector; - fixed_t floor, ceiling; + fixed_t floor, ceiling, ceilingspawn; player_t *p = &players[playernum]; mobj_t *mobj = p->mo; @@ -11589,23 +11589,18 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) sector->c_slope ? P_GetZAt(sector->c_slope, x, y) : #endif sector->ceilingheight; + ceilingspawn = ceiling - mobjinfo[MT_PLAYER].height; if (mthing) { + fixed_t offset = mthing->z << FRACBITS; + // Flagging a player's ambush will make them start on the ceiling // Objectflip inverts if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP)) - { - z = ceiling - mobjinfo[MT_PLAYER].height; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); - } + z = ceilingspawn - offset; else - { - z = floor; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); - } + z = floor + offset; if (mthing->options & MTF_OBJECTFLIP) // flip the player! { @@ -11622,8 +11617,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) if (z < floor) z = floor; - else if (z > ceiling - mobjinfo[MT_PLAYER].height) - z = ceiling - mobjinfo[MT_PLAYER].height; + else if (z > ceilingspawn) + z = ceilingspawn; mobj->floorz = floor; mobj->ceilingz = ceiling; From de7575416acf6830a0c0858b46e94b38bf632ae1 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 25 Dec 2019 11:17:57 +0100 Subject: [PATCH 165/312] P_FlagFuseThink: Use mt->z instead of mt->options >> ZSHIFT --- src/p_mobj.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index bc5121318..83ab50b35 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9905,19 +9905,12 @@ static void P_FlagFuseThink(mobj_t *mobj) x = mobj->spawnpoint->x << FRACBITS; y = mobj->spawnpoint->y << FRACBITS; + z = mobj->spawnpoint->z << FRACBITS; ss = R_PointInSubsector(x, y); if (mobj->spawnpoint->options & MTF_OBJECTFLIP) - { - z = ss->sector->ceilingheight - mobjinfo[mobj->type].height; - if (mobj->spawnpoint->options >> ZSHIFT) - z -= (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; - } + z = ss->sector->ceilingheight - mobjinfo[mobj->type].height - z; else - { - z = ss->sector->floorheight; - if (mobj->spawnpoint->options >> ZSHIFT) - z += (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; - } + z = ss->sector->floorheight + z; flagmo = P_SpawnMobj(x, y, z, mobj->type); flagmo->spawnpoint = mobj->spawnpoint; if (mobj->spawnpoint->options & MTF_OBJECTFLIP) From c4a017ddf01e6c529df0369bb28e66d9aa0cdf20 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Wed, 25 Dec 2019 12:05:40 +0100 Subject: [PATCH 166/312] Move flat caching code to the map data load function. --- src/p_setup.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index f5d4c26e2..3ae17cc23 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -651,14 +651,6 @@ static void P_LoadRawSectors(UINT8 *data) sector_t *ss = sectors; size_t i; - // Allocate a big chunk of memory as big as our MAXLEVELFLATS limit. - //Fab : FIXME: allocate for whatever number of flats - 512 different flats per level should be plenty - foundflats = calloc(MAXLEVELFLATS, sizeof (*foundflats)); - if (foundflats == NULL) - I_Error("Ran out of memory while loading sectors\n"); - - numlevelflats = 0; - // For each counted sector, copy the sector raw data from our cache pointer ms, to the global table pointer ss. for (i = 0; i < numsectors; i++, ss++, ms++) { @@ -1982,6 +1974,14 @@ static void P_LoadMapData(const virtres_t* virt) lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + // Allocate a big chunk of memory as big as our MAXLEVELFLATS limit. + //Fab : FIXME: allocate for whatever number of flats - 512 different flats per level should be plenty + foundflats = calloc(MAXLEVELFLATS, sizeof (*foundflats)); + if (foundflats == NULL) + I_Error("Ran out of memory while loading sectors\n"); + + numlevelflats = 0; + #ifdef UDMF if (textmap) { From 5241030012cf53746192d8004f21e0118297853f Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 25 Dec 2019 21:48:59 +0000 Subject: [PATCH 167/312] Fix ShouldDamage, MobjDamage and MobjDeath hooks all messing up the pushing of variables to Lua as function args, by adding damagetype support where it was missing! The above issue occured only if you had both a generic hook and a type specific hook for a particular hook type. This way, the stack is never updated to include damagetype at the start, and all pushes of the variables get offsetted by 1 compared to what they should be, once the code *expects* damagetype to be included in it. --- src/lua_hooklib.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index ef87d0b6f..aadba6aba 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -657,14 +657,16 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ); lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 0)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); @@ -745,14 +747,16 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ); lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 0)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); @@ -823,13 +827,15 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 LUA_PushUserdata(gL, target, META_MOBJ); LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damagetype); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 0)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); From 70f08007ebff21a97b10f5978d2765d002ace6d4 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 25 Dec 2019 15:23:19 -0800 Subject: [PATCH 168/312] Correct the check for rings on thing 604 - 607 The original code used a switch case, not AND 1. :V --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 13f75b94a..1882a4e3c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13372,7 +13372,7 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) { INT32 numitems = (mthing->type & 1) ? 16 : 8; fixed_t size = (mthing->type & 1) ? 192*FRACUNIT : 96*FRACUNIT; - mobjtype_t itemtypes[1] = { (mthing->type & 1) ? MT_RING : MT_BLUESPHERE }; + mobjtype_t itemtypes[1] = { (mthing->type < 606) ? MT_RING : MT_BLUESPHERE }; P_SpawnItemCircle(mthing, itemtypes, 1, numitems, size, bonustime); return; } From 6bd383621eee92b215f86c9c4b483934d7e60daa Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 25 Dec 2019 20:44:25 -0800 Subject: [PATCH 169/312] More fine tuned versioning You get a PACKETVERSION, for when some packets change format. You get SRB2APPLICATION, for when you have big fucking mod. --- src/d_clisrv.c | 25 +++++++++++++++++++++++++ src/d_clisrv.h | 23 +++++++++++++++++++++++ src/doomdef.h | 3 +++ 3 files changed, 51 insertions(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 6520a1aa1..5dd879b61 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1271,8 +1271,12 @@ static boolean CL_SendJoin(void) if (splitscreen || botingame) localplayers++; netbuffer->u.clientcfg.localplayers = localplayers; + netbuffer->u.clientcfg._255 = 255; + netbuffer->u.clientcfg.packetversion = PACKETVERSION; netbuffer->u.clientcfg.version = VERSION; netbuffer->u.clientcfg.subversion = SUBVERSION; + strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION, + sizeof netbuffer->u.clientcfg.application); strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME); return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); @@ -1283,8 +1287,12 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) UINT8 *p; netbuffer->packettype = PT_SERVERINFO; + netbuffer->u.serverinfo._255 = 255; + netbuffer->u.serverinfo.packetversion = PACKETVERSION; netbuffer->u.serverinfo.version = VERSION; netbuffer->u.serverinfo.subversion = SUBVERSION; + strncpy(netbuffer->u.serverinfo.application, SRB2APPLICATION, + sizeof netbuffer->u.serverinfo.application); // return back the time value so client can compute their ping netbuffer->u.serverinfo.time = (tic_t)LONG(servertime); netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime); @@ -1718,12 +1726,21 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) if (serverlistcount >= MAXSERVERLIST) return; // list full + if (info->_255 != 255) + return;/* old packet format */ + + if (info->packetversion != PACKETVERSION) + return;/* old new packet format */ + if (info->version != VERSION) return; // Not same version. if (info->subversion != SUBVERSION) return; // Close, but no cigar. + if (strcmp(info->application, SRB2APPLICATION)) + return;/* that's a different mod */ + i = serverlistcount++; } @@ -3507,6 +3524,12 @@ static void HandleConnect(SINT8 node) if (bannednode && bannednode[node]) SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server")); + else if (netbuffer->u.clientcfg._255 != 255 || + netbuffer->u.clientcfg.packetversion != PACKETVERSION) + SV_SendRefuse(node, "Incompatible packet formats."); + else if (strncmp(netbuffer->u.clientcfg.application, SRB2APPLICATION, + sizeof netbuffer->u.clientcfg.application)) + SV_SendRefuse(node, "Different SRB2 modifications\nare not compatible."); else if (netbuffer->u.clientcfg.version != VERSION || netbuffer->u.clientcfg.subversion != SUBVERSION) SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION)); @@ -3629,6 +3652,8 @@ static void HandleServerInfo(SINT8 node) const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE; netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff); netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0; + netbuffer->u.serverinfo.application + [sizeof netbuffer->u.serverinfo.application - 1] = '\0'; SL_InsertServer(&netbuffer->u.serverinfo, node); } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 4ba4ee0eb..49f8afc76 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -19,6 +19,16 @@ #include "tables.h" #include "d_player.h" +/* +The 'packet version' may be used with packets whose +format is expected to change between versions. + +This version is independent of the mod name, and standard +version and subversion. It should only account for the +basic fields of the packet, and change infrequently. +*/ +#define PACKETVERSION 0 + // Network play related stuff. // There is a data struct that stores network // communication related stuff, and another @@ -320,8 +330,13 @@ typedef struct { #pragma warning(default : 4200) #endif +#define MAXAPPLICATION 16 + typedef struct { + UINT8 _255;/* see serverinfo_pak */ + UINT8 packetversion; + char application[MAXAPPLICATION]; UINT8 version; // Different versions don't work UINT8 subversion; // Contains build version UINT8 localplayers; @@ -334,6 +349,14 @@ typedef struct // This packet is too large typedef struct { + /* + In the old packet, 'version' is the first field. Now that field is set + to 255 always, so older versions won't be confused with the new + versions or vice-versa. + */ + UINT8 _255; + UINT8 packetversion; + char application[MAXAPPLICATION]; UINT8 version; UINT8 subversion; UINT8 numberofplayer; diff --git a/src/doomdef.h b/src/doomdef.h index 0da1a1fed..a8b927a73 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -130,6 +130,9 @@ extern FILE *logstream; extern char logfilename[1024]; #endif +/* A mod name to further distinguish versions. */ +#define SRB2APPLICATION "SRB2" + //#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3 #ifdef DEVELOP #define VERSION 0 // Game version From 50379dac858f60057c474806bad160e558c34cb2 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 26 Dec 2019 12:27:15 -0500 Subject: [PATCH 170/312] cleanup buildbot error --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1882a4e3c..bd0927355 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13005,7 +13005,7 @@ static void P_SetObjectSpecial(mobj_t *mobj) } } -mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, mobjtype_t i) +static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, mobjtype_t i) { mobj_t *mobj = NULL; boolean doangle = true; From 4906cd4331f9697e71b6e01949e9e296dd557476 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 26 Dec 2019 12:44:47 -0500 Subject: [PATCH 171/312] ISO C90 fixup --- src/p_mobj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 83ab50b35..88ab45a12 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8321,6 +8321,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj) // See Linedef Exec 457 (Track mobj angle to point) static void P_TracerAngleThink(mobj_t *mobj) { + angle_t ang; if (!mobj->tracer) return; @@ -8333,7 +8334,7 @@ static void P_TracerAngleThink(mobj_t *mobj) // mobj->cvval - Allowable failure delay // mobj->cvmem - Failure timer - angle_t ang = mobj->angle - R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); + ang = mobj->angle - R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); // \todo account for distance between mobj and tracer // Because closer mobjs can be facing beyond the angle tolerance From a1d944fc4d13b1f749e2bdc9288d730aa88c136b Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Thu, 26 Dec 2019 14:02:02 -0500 Subject: [PATCH 172/312] Fix scoreadd not doing anything when modified by Lua This does not change any vanilla behavior, as scoreadd is reset constantly on the ground anyway -- this simply makes the behavior modifiable for Lua scripts. --- src/p_inter.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 70fb01fd0..c82e36c31 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2481,9 +2481,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget P_SetMobjState(scoremobj, scorestate); - // On ground? No chain starts. - if (source->player->powers[pw_invulnerability] || !P_IsObjectOnGround(source)) - source->player->scoreadd = locscoreadd; + source->player->scoreadd = locscoreadd; } } From 855f5da6c9673daa051b387661bee64b0a4f53f1 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 26 Dec 2019 20:13:56 +0100 Subject: [PATCH 173/312] Make P_RespawnSpecials call P_SpawnMapThing instead of trying to do everything itself --- src/p_mobj.c | 60 +--------------------------------------------------- 1 file changed, 1 insertion(+), 59 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 83ab50b35..dde2476a4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11284,9 +11284,6 @@ static mobjtype_t P_GetMobjtype(UINT16 mthingtype) // void P_RespawnSpecials(void) { - fixed_t x, y, z; - subsector_t *ss; - mobj_t *mo = NULL; mapthing_t *mthing = NULL; // only respawn items when cv_itemrespawn is on @@ -11316,63 +11313,8 @@ void P_RespawnSpecials(void) #endif if (mthing) - { - mobjtype_t i = P_GetMobjtype(mthing->type); - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - ss = R_PointInSubsector(x, y); + P_SpawnMapThing(mthing); - if (i == MT_UNKNOWN) // prevent creation of objects with this type -- Monster Iestyn 17/12/17 - { - // 3D Mode start Thing is unlikely to be added to the que, - // so don't bother checking for that specific type - CONS_Alert(CONS_WARNING, M_GetText("P_RespawnSpecials: Unknown thing type %d attempted to respawn at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - // pull it from the que - iquetail = (iquetail+1)&(ITEMQUESIZE-1); - return; - } - - //CTF rings should continue to respawn as normal rings outside of CTF. - if (gametype != GT_CTF) - { - if (i == MT_REDTEAMRING || i == MT_BLUETEAMRING) - i = MT_RING; - } - - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : -#endif - ss->sector->ceilingheight) - (mthing->options >> ZSHIFT) * FRACUNIT; - if (mthing->options & MTF_AMBUSH - && (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING || i == MT_COIN || i == MT_NIGHTSSTAR || P_WeaponOrPanel(i))) - z -= 24*FRACUNIT; - z -= mobjinfo[i].height; // Don't forget the height! - } - else - { - z = ( -#ifdef ESLOPE - ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : -#endif - ss->sector->floorheight) + (mthing->options >> ZSHIFT) * FRACUNIT; - if (mthing->options & MTF_AMBUSH - && (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING || i == MT_COIN || i == MT_NIGHTSSTAR || P_WeaponOrPanel(i))) - z += 24*FRACUNIT; - } - - mo = P_SpawnMobj(x, y, z, i); - mo->spawnpoint = mthing; - mo->angle = ANGLE_45 * (mthing->angle/45); - - if (mthing->options & MTF_OBJECTFLIP) - { - mo->eflags |= MFE_VERTICALFLIP; - mo->flags2 |= MF2_OBJECTFLIP; - } - } // pull it from the que iquetail = (iquetail+1)&(ITEMQUESIZE-1); } From f86c5f13ced5398a63ce2f74f639feb4a4a1565e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 26 Dec 2019 20:48:52 +0100 Subject: [PATCH 174/312] Use mt->z instead of mt->options >> ZSHIFT in Command_Teleport_f --- src/m_cheat.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/m_cheat.c b/src/m_cheat.c index 52b79f930..f4042eba9 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -517,6 +517,7 @@ void Command_Teleport_f(void) if (!starpostnum) // spawnpoints... { mapthing_t *mt; + fixed_t offset; if (starpostpath >= numcoopstarts) { @@ -527,6 +528,7 @@ void Command_Teleport_f(void) mt = playerstarts[starpostpath]; // Given above check, should never be NULL. intx = mt->x<y<z<sector->ceilingheight - ss->sector->floorheight < p->mo->height) @@ -538,17 +540,9 @@ void Command_Teleport_f(void) // Flagging a player's ambush will make them start on the ceiling // Objectflip inverts if (!!(mt->options & MTF_AMBUSH) ^ !!(mt->options & MTF_OBJECTFLIP)) - { - intz = ss->sector->ceilingheight - p->mo->height; - if (mt->options >> ZSHIFT) - intz -= ((mt->options >> ZSHIFT) << FRACBITS); - } + intz = ss->sector->ceilingheight - p->mo->height - offset; else - { - intz = ss->sector->floorheight; - if (mt->options >> ZSHIFT) - intz += ((mt->options >> ZSHIFT) << FRACBITS); - } + intz = ss->sector->floorheight + offset; if (mt->options & MTF_OBJECTFLIP) // flip the player! { From 7ccb695fa16eb550c6fc4e7221162635283bf862 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 26 Dec 2019 20:54:06 +0100 Subject: [PATCH 175/312] Use mthing->z instead of mthing->options >> ZSHIFT in G_AddGhost --- src/g_game.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index cf9b4367d..67424f02a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6629,23 +6629,20 @@ void G_AddGhost(char *defdemoname) I_Assert(mthing); { // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling. fixed_t z,f,c; + fixed_t offset = mthing->z << FRACBITS; gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST); - gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT); + gh->mo->angle = FixedAngle(mthing->angle << FRACBITS); f = gh->mo->floorz; c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height; if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP)) { - z = c; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); + z = c - offset; if (z < f) z = f; } else { - z = f; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); + z = f + offset; if (z > c) z = c; } From 2d90098b6a981761da87739d3dd41fcc2cdfc1f1 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 26 Dec 2019 20:55:29 +0100 Subject: [PATCH 176/312] Use startpos->z instead of startpos->options >> ZSHIFT in F_StartTitleScreen --- src/f_finale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index 1436a159b..124fedc28 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2493,7 +2493,7 @@ void F_StartTitleScreen(void) camera.x = startpos->x << FRACBITS; camera.y = startpos->y << FRACBITS; camera.subsector = R_PointInSubsector(camera.x, camera.y); - camera.z = camera.subsector->sector->floorheight + ((startpos->options >> ZSHIFT) << FRACBITS); + camera.z = camera.subsector->sector->floorheight + (startpos->z << FRACBITS); camera.angle = (startpos->angle % 360)*ANG1; camera.aiming = 0; } From ca5a4d90e0e3445df560a6adc7884eb22df02f3b Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 26 Dec 2019 21:59:09 +0000 Subject: [PATCH 177/312] Fix mixed declaration-and-code compiling error --- src/p_mobj.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index b3705ee44..9ecd1d32a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8321,6 +8321,8 @@ static boolean P_MobjDeadThink(mobj_t *mobj) // See Linedef Exec 457 (Track mobj angle to point) static void P_TracerAngleThink(mobj_t *mobj) { + angle_t ang; + if (!mobj->tracer) return; @@ -8333,7 +8335,7 @@ static void P_TracerAngleThink(mobj_t *mobj) // mobj->cvval - Allowable failure delay // mobj->cvmem - Failure timer - angle_t ang = mobj->angle - R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); + ang = mobj->angle - R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); // \todo account for distance between mobj and tracer // Because closer mobjs can be facing beyond the angle tolerance From 56fd29a42a5f9042611255da92df764e57a84632 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 26 Dec 2019 21:27:30 -0300 Subject: [PATCH 178/312] stuff --- src/hardware/hw_main.c | 11 +++-------- src/r_patch.c | 25 ++++++++++++++++++++----- src/r_patch.h | 5 +++-- src/r_things.c | 20 ++++++++------------ 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 6ef48f222..41e2c5693 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5501,17 +5501,12 @@ static void HWR_ProjectSprite(mobj_t *thing) fixed_t spr_offset, spr_topoffset; #ifdef ROTSPRITE patch_t *rotsprite = NULL; - angle_t arollangle; - UINT32 rollangle; + INT32 rollangle = 0; #endif if (!thing) return; -#ifdef ROTSPRITE - arollangle = thing->rollangle; - rollangle = AngleFixed(arollangle)>>FRACBITS; -#endif this_scale = FIXED_TO_FLOAT(thing->scale); // transform the origin point @@ -5618,11 +5613,11 @@ static void HWR_ProjectSprite(mobj_t *thing) spr_topoffset = spritecachedinfo[lumpoff].topoffset; #ifdef ROTSPRITE - if (rollangle > 0) + if (thing->rollangle) { + rollangle = R_GetRollAngle(thing->rollangle); if (!sprframe->rotsprite.cached[rot]) R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip); - rollangle /= ROTANGDIFF; rotsprite = sprframe->rotsprite.patch[rot][rollangle]; if (rotsprite != NULL) { diff --git a/src/r_patch.c b/src/r_patch.c index 69d5ad1a2..9803d01f0 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -49,8 +49,6 @@ #endif static unsigned char imgbuf[1<<26]; -fixed_t cosang2rad[ROTANGLES]; -fixed_t sinang2rad[ROTANGLES]; // // R_CheckIfPatch @@ -1123,6 +1121,23 @@ static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) } #ifdef ROTSPRITE +// +// R_GetRollAngle +// +// Angles precalculated in R_InitSprites. +// +fixed_t rollcosang[ROTANGLES]; +fixed_t rollsinang[ROTANGLES]; +INT32 R_GetRollAngle(angle_t rollangle) +{ + INT32 ra = AngleFixed(rollangle)>>FRACBITS; +#if (ROTANGDIFF > 1) + ra += (ROTANGDIFF/2); +#endif + ra /= ROTANGDIFF; + return max(0, min(ra, ROTANGLES)); +} + // // R_CacheRotSprite // @@ -1180,12 +1195,12 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp leftoffset = width - leftoffset; } - for (angle = 0; angle < ROTANGLES; angle++) + for (angle = 1; angle < ROTANGLES; angle++) { INT32 newwidth, newheight; - ca = cosang2rad[angle]; - sa = sinang2rad[angle]; + ca = rollcosang[angle]; + sa = rollsinang[angle]; // Find the dimensions of the rotated patch. { diff --git a/src/r_patch.h b/src/r_patch.h index c534debdb..72371f253 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -62,11 +62,12 @@ void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); // Sprite rotation #ifdef ROTSPRITE +INT32 R_GetRollAngle(angle_t rollangle); void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip); void R_FreeSingleRotSprite(spritedef_t *spritedef); void R_FreeSkinRotSprite(size_t skinnum); -extern fixed_t cosang2rad[ROTANGLES]; -extern fixed_t sinang2rad[ROTANGLES]; +extern fixed_t rollcosang[ROTANGLES]; +extern fixed_t rollsinang[ROTANGLES]; #endif #endif // __R_PATCH__ diff --git a/src/r_things.c b/src/r_things.c index d29baa711..465430017 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -500,7 +500,7 @@ void R_InitSprites(void) { size_t i; #ifdef ROTSPRITE - INT32 angle, ra; + INT32 angle; float fa; #endif @@ -508,14 +508,11 @@ void R_InitSprites(void) negonearray[i] = -1; #ifdef ROTSPRITE - for (angle = 0; angle < ROTANGLES; angle++) + for (angle = 1; angle < ROTANGLES; angle++) { - ra = (ROTANGDIFF * angle); - if (!ra) - ra = (ROTANGDIFF / 2) + 1; - fa = ANG2RAD(FixedAngle(ra<rollangle; - UINT32 rollangle = AngleFixed(arollangle)>>FRACBITS; + INT32 rollangle = 0; #endif #ifndef PROPERPAPER @@ -1262,11 +1258,11 @@ static void R_ProjectSprite(mobj_t *thing) spr_topoffset = spritecachedinfo[lump].topoffset; #ifdef ROTSPRITE - if (rollangle > 0) + if (thing->rollangle) { + rollangle = R_GetRollAngle(thing->rollangle); if (!sprframe->rotsprite.cached[rot]) R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip); - rollangle /= ROTANGDIFF; rotsprite = sprframe->rotsprite.patch[rot][rollangle]; if (rotsprite != NULL) { From 4b653a0b12c9f5c6657f7be161690fc797e295ad Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 26 Dec 2019 21:36:35 -0300 Subject: [PATCH 179/312] Remove the min() and max() calls. --- src/r_patch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_patch.c b/src/r_patch.c index 9803d01f0..83593d295 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1135,7 +1135,7 @@ INT32 R_GetRollAngle(angle_t rollangle) ra += (ROTANGDIFF/2); #endif ra /= ROTANGDIFF; - return max(0, min(ra, ROTANGLES)); + return ra; } // From da1718f93c0298575d93dbf6e763d6630806dd50 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 26 Dec 2019 21:49:36 -0300 Subject: [PATCH 180/312] Avoid possible overflows in the rotsprite arrays. --- src/r_patch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/r_patch.c b/src/r_patch.c index 83593d295..0519d6dc9 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1135,6 +1135,7 @@ INT32 R_GetRollAngle(angle_t rollangle) ra += (ROTANGDIFF/2); #endif ra /= ROTANGDIFF; + ra %= ROTANGLES; return ra; } From e49d12b7310ec4f1a9e6ec415a85be1f6143d28f Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 5 Aug 2019 15:00:09 -0700 Subject: [PATCH 181/312] Expose CV_FindVar (cherry picked from commit 0e9d69d6a3759686ca8bb567817be650291ea0e1) --- src/command.c | 4 ++-- src/command.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/command.c b/src/command.c index 33d8ead96..309881382 100644 --- a/src/command.c +++ b/src/command.c @@ -54,7 +54,7 @@ static void COM_Add_f(void); static void CV_EnforceExecVersion(void); static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr); static boolean CV_Command(void); -static consvar_t *CV_FindVar(const char *name); +consvar_t *CV_FindVar(const char *name); static const char *CV_StringValue(const char *var_name); static consvar_t *consvar_vars; // list of registered console variables @@ -1055,7 +1055,7 @@ static const char *cv_null_string = ""; * \return Pointer to the variable if found, or NULL. * \sa CV_FindNetVar */ -static consvar_t *CV_FindVar(const char *name) +consvar_t *CV_FindVar(const char *name) { consvar_t *cvar; diff --git a/src/command.h b/src/command.h index 51e161cd0..54584bb2d 100644 --- a/src/command.h +++ b/src/command.h @@ -140,6 +140,9 @@ void CV_ToggleExecVersion(boolean enable); // register a variable for use at the console void CV_RegisterVar(consvar_t *variable); +// returns a console variable by name +consvar_t *CV_FindVar(const char *name); + // sets changed to 0 for every console variable void CV_ClearChangedFlags(void); From 7df6a3090a41c585bbc9752b3447b9922b5da26f Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 5 Aug 2019 15:00:21 -0700 Subject: [PATCH 182/312] Lua CV_FindVar function (cherry picked from commit b5746c231d17cd7b58c6b633e242d5ad26ad7017) --- src/lua_consolelib.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 58e720c85..65dd553cd 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -427,6 +427,26 @@ static int lib_cvRegisterVar(lua_State *L) return 1; } +static int lib_cvFindVar(lua_State *L) +{ + consvar_t *cv; + if (( cv = CV_FindVar(luaL_checkstring(L,1)) )) + { + lua_settop(L,1);/* We only want one argument in the stack. */ + lua_pushlightuserdata(L, cv);/* Now the second value on stack. */ + luaL_getmetatable(L, META_CVAR); + /* + The metatable is the last value on the stack, so this + applies it to the second value, which is the cvar. + */ + lua_setmetatable(L,2); + lua_pushvalue(L,2); + return 1; + } + else + return 0; +} + // CONS_Printf for a single player // Use 'print' in baselib for a global message. static int lib_consPrintf(lua_State *L) @@ -466,6 +486,7 @@ static luaL_Reg lib[] = { {"COM_BufAddText", lib_comBufAddText}, {"COM_BufInsertText", lib_comBufInsertText}, {"CV_RegisterVar", lib_cvRegisterVar}, + {"CV_FindVar", lib_cvFindVar}, {"CONS_Printf", lib_consPrintf}, {NULL, NULL} }; From 855e61f59e858b70631d5b178d0772ffd669efbc Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 26 Dec 2019 19:27:25 -0800 Subject: [PATCH 183/312] Pop monitors properly so Metal doesn't destroy enemy team's monitors --- src/p_map.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 1b6f23cde..96fb8ee07 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -829,13 +829,10 @@ static boolean PIT_CheckThing(mobj_t *thing) for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext) if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale)) P_KillMobj(iter, tmthing, tmthing, 0); + return true; } else - { - thing->health = 0; - P_KillMobj(thing, tmthing, tmthing, 0); - } - return true; + return P_DamageMobj(thing, tmthing, tmthing, 1, 0); } // vectorise metal - done in a special case as at this point neither has the right flags for touching From 51404130af736868d7474beaf388bcdef706e6d1 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 01:44:27 -0300 Subject: [PATCH 184/312] Respawn delay gametype rule --- src/dehacked.c | 1 + src/doomstat.h | 1 + src/g_game.c | 10 +++++----- src/p_user.c | 25 ++++++++++++++----------- src/st_stuff.c | 2 +- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index b77939c2a..939e8c8cf 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8928,6 +8928,7 @@ static const char *const GAMETYPERULE_LIST[] = { "OVERTIME", "HURTMESSAGES", "SPAWNINVUL", + "RESPAWNDELAY", NULL }; diff --git a/src/doomstat.h b/src/doomstat.h index b7bb7a362..5dc3a6eb9 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -423,6 +423,7 @@ enum GameTypeRules GTR_OVERTIME = 1<<26, // Allow overtime GTR_HURTMESSAGES = 1<<27, // Hit and death messages GTR_SPAWNINVUL = 1<<28, // Babysitting deterrent + GTR_RESPAWNDELAY = 1<<29, // Respawn delay }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 19b18ef8c..3f1441922 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3201,17 +3201,17 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = GTR_RACE|GTR_SPAWNENEMIES|GTR_SPAWNINVUL|GTR_ALLOWEXIT, // Match - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD|GTR_DEATHPENALTY, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD|GTR_DEATHPENALTY, // Team Match - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_SPAWNINVUL|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, // Tag - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, // Hide and Seek - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, // CTF - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, }; // diff --git a/src/p_user.c b/src/p_user.c index fbcc17d24..a85457ad4 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9462,19 +9462,22 @@ static void P_DeathThink(player_t *player) // Respawn with jump button, force respawn time (3 second default, cheat protected) in shooter modes. if (cmd->buttons & BT_JUMP) { + // You're a spectator, so respawn right away. if (gametype != GT_COOP && player->spectator) player->playerstate = PST_REBORN; - else switch(gametype) { - case GT_COOP: - case GT_COMPETITION: - case GT_RACE: - if (player->deadtimer > TICRATE) - player->playerstate = PST_REBORN; - break; - default: - if (player->deadtimer > cv_respawntime.value*TICRATE) - player->playerstate = PST_REBORN; - break; + else + { + // Give me one second. + INT32 respawndelay = TICRATE; + + // Non-platform gametypes + if (gametyperules & GTR_RESPAWNDELAY) + respawndelay = (cv_respawntime.value*TICRATE); + + // You've been dead for enough time. + // You may now respawn. + if (player->deadtimer > respawndelay) + player->playerstate = PST_REBORN; } } diff --git a/src/st_stuff.c b/src/st_stuff.c index 5e05030c3..d8b9a8059 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2202,7 +2202,7 @@ static void ST_drawTextHUD(void) donef12 = true; } } - else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) // Death overrides spectator text. + else if ((gametyperules & GTR_RESPAWNDELAY) && stplyr->playerstate == PST_DEAD && stplyr->lives) // Death overrides spectator text. { INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE; From 56e94182d5de9d497307cb12e886275a4edf8eb6 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 02:07:13 -0300 Subject: [PATCH 185/312] P_SetupCamera funny --- src/p_setup.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 9acc4adb3..39f2ef545 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2447,17 +2447,10 @@ static void P_SetupCamera(void) { mapthing_t *thing; - switch (gametype) - { - case GT_MATCH: - case GT_TAG: + if ((gametyperules & GTR_DEATHMATCHSTARTS) || (gametype == GT_MATCH || gametype == GT_TAG)) thing = deathmatchstarts[0]; - break; - - default: + else thing = playerstarts[0]; - break; - } if (thing) { From 9613bdeca69bde37ecd452ec3649c5798b02f6c0 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 12:14:33 -0300 Subject: [PATCH 186/312] use GTR_DEATHMATCHSTARTS --- src/g_game.c | 13 ++++++------- src/p_setup.c | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 3f1441922..3ba3ab40f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2689,8 +2689,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) // -- DM/Tag/CTF-spectator/etc -- // Order: DM->CTF->Coop - else if ((gametyperules & GTR_DEATHMATCHSTARTS) || gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF - || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT))) + else if ((gametyperules & GTR_DEATHMATCHSTARTS) && !(players[playernum].pflags & PF_TAGIT)) { if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start && !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start @@ -3201,17 +3200,17 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = GTR_RACE|GTR_SPAWNENEMIES|GTR_SPAWNINVUL|GTR_ALLOWEXIT, // Match - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD|GTR_DEATHPENALTY, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD|GTR_DEATHPENALTY, // Team Match - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, // Tag - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, // Hide and Seek - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, // CTF - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, }; // diff --git a/src/p_setup.c b/src/p_setup.c index 39f2ef545..5fc740191 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2447,7 +2447,7 @@ static void P_SetupCamera(void) { mapthing_t *thing; - if ((gametyperules & GTR_DEATHMATCHSTARTS) || (gametype == GT_MATCH || gametype == GT_TAG)) + if (gametyperules & GTR_DEATHMATCHSTARTS) thing = deathmatchstarts[0]; else thing = playerstarts[0]; From 1d0d40492272db90d9f0a12278c247e78a5a5c0c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 12:17:38 -0300 Subject: [PATCH 187/312] check if the gametype allows spectators to allow jump key respawn --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index a85457ad4..e9c32813a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9463,7 +9463,7 @@ static void P_DeathThink(player_t *player) if (cmd->buttons & BT_JUMP) { // You're a spectator, so respawn right away. - if (gametype != GT_COOP && player->spectator) + if ((gametyperules & GTR_SPECTATORS) && player->spectator) player->playerstate = PST_REBORN; else { From 5c023739e6e80cc6f1faeac5ecaa39ceb89d5b6f Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 12:23:50 -0300 Subject: [PATCH 188/312] change this > to >= --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index b3ff8ce71..5e405156c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4690,7 +4690,7 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) return true; - if (gt > 0 && gt < gametypecount && (mapheaderinfo[mapnum]->typeoflevel & gametypetol[gt])) + if (gt >= 0 && gt < gametypecount && (mapheaderinfo[mapnum]->typeoflevel & gametypetol[gt])) return true; return false; From f8eed7171a8d63176bf2e43b8662d58befbf0758 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 12:28:00 -0300 Subject: [PATCH 189/312] add G_CompetitionGametype(void) --- src/g_game.c | 10 ++++++++++ src/g_game.h | 1 + src/p_setup.c | 2 +- src/p_user.c | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 3ba3ab40f..28de6693f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3492,6 +3492,16 @@ boolean G_TagGametype(void) return (gametyperules & GTR_TAG); } +// +// G_CompetitionGametype +// +// For gametypes that are race gametypes, and have lives. +// +boolean G_CompetitionGametype(void) +{ + return ((gametyperules & GTR_RACE) && (gametyperules & GTR_LIVES)); +} + /** Get the typeoflevel flag needed to indicate support of a gametype. * In single-player, this always returns TOL_SP. * \param gametype The gametype for which support is desired. diff --git a/src/g_game.h b/src/g_game.h index 238dd1964..6916bba6e 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -223,6 +223,7 @@ boolean G_GametypeHasSpectators(void); boolean G_RingSlingerGametype(void); boolean G_PlatformGametype(void); boolean G_TagGametype(void); +boolean G_CompetitionGametype(void); boolean G_EnoughPlayersFinished(void); void G_ExitLevel(void); void G_NextLevel(void); diff --git a/src/p_setup.c b/src/p_setup.c index 5fc740191..3f49a1680 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2159,7 +2159,7 @@ static void P_LevelInitStuff(void) { G_PlayerReborn(i, true); - if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0)) + if (canresetlives && (netgame || multiplayer) && playeringame[i] && (G_CompetitionGametype() || players[i].lives <= 0)) { // In Co-Op, replenish a user's lives if they are depleted. players[i].lives = cv_startinglives.value; diff --git a/src/p_user.c b/src/p_user.c index e9c32813a..ff6ffc677 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9491,7 +9491,7 @@ static void P_DeathThink(player_t *player) INT32 i, deadtimercheck = INT32_MAX; // In a net/multiplayer game, and out of lives - if (gametype == GT_COMPETITION) + if (G_CompetitionGametype()) { for (i = 0; i < MAXPLAYERS; i++) { From f0d58368f912941c9a46edf29cab87fc76be8a1b Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 12:29:21 -0300 Subject: [PATCH 190/312] look for GTR_LIVES rule instead of coop/competition gametype --- src/p_user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index ff6ffc677..3f407d6a9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1230,7 +1230,7 @@ void P_GivePlayerLives(player_t *player, INT32 numlives) if (gamestate == GS_LEVEL) { - if (player->lives == INFLIVES || (gametype != GT_COOP && gametype != GT_COMPETITION)) + if (player->lives == INFLIVES || !(gametyperules & GTR_LIVES)) { P_GivePlayerRings(player, 100*numlives); return; @@ -1395,7 +1395,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) player->score = MAXSCORE; // check for extra lives every 50000 pts - if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametype == GT_COMPETITION || gametype == GT_COOP)) + if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametyperules & GTR_LIVES)) { P_GivePlayerLives(player, (player->score/50000) - (oldscore/50000)); P_PlayLivesJingle(player); From 6b8839d5aaee3212b3c0a7f6976504fb235759f7 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 12:34:35 -0300 Subject: [PATCH 191/312] burst emeralds with GTR_MATCHEMERALDS --- src/p_inter.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 56a76b15c..a8b169db5 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3201,10 +3201,12 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) player->powers[pw_carry] = CR_NONE; // Burst weapons and emeralds in Match/CTF only - if (source && (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF)) + if (source) { - P_PlayerRingBurst(player, player->rings); - P_PlayerEmeraldBurst(player, false); + if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF) + P_PlayerRingBurst(player, player->rings); + if (gametyperules & GTR_MATCHEMERALDS) + P_PlayerEmeraldBurst(player, false); } // Get rid of shield From 282fe7667ccd831e41a2d7f18599deba6457b833 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 27 Dec 2019 19:10:14 +0000 Subject: [PATCH 192/312] added a "target" pointer to polywaypoint_t, so the polyobj waypoint thinker doesn't have to re-find the next waypoint every tic --- src/p_polyobj.c | 8 ++++++++ src/p_polyobj.h | 2 ++ src/p_saveg.c | 16 ++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index c37926adf..d7105ee5a 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1815,6 +1815,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) if (po->thinker == NULL) po->thinker = &th->thinker; +/* // Find out target first. // We redo this each tic to make savegame compatibility easier. for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) @@ -1833,6 +1834,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th) break; } } +*/ + + target = th->target; if (!target) { @@ -2015,6 +2019,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th) target = waypoint; th->pointnum = target->health; + // Set the mobj as your target! -- Monster Iestyn 27/12/19 + th->target = target; // calculate MOMX/MOMY/MOMZ for next waypoint // change slope @@ -2641,6 +2647,8 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Set pointnum th->pointnum = target->health; + // Set the mobj as your target! -- Monster Iestyn 27/12/19 + th->target = target; // We don't deal with the mirror crap here, we'll // handle that in the T_Thinker function. diff --git a/src/p_polyobj.h b/src/p_polyobj.h index ffacf628b..339390c0a 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -161,6 +161,8 @@ typedef struct polywaypoint_s fixed_t diffx; fixed_t diffy; fixed_t diffz; + + mobj_t *target; // next waypoint mobj } polywaypoint_t; typedef struct polyslidedoor_s diff --git a/src/p_saveg.c b/src/p_saveg.c index 85efacf88..092eca8a4 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2055,6 +2055,7 @@ static void SavePolywaypointThinker(const thinker_t *th, UINT8 type) WRITEFIXED(save_p, ht->diffx); WRITEFIXED(save_p, ht->diffy); WRITEFIXED(save_p, ht->diffz); + WRITEUINT32(save_p, SaveMobjnum(ht->target)); } // @@ -3244,6 +3245,7 @@ static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker) ht->diffx = READFIXED(save_p); ht->diffy = READFIXED(save_p); ht->diffz = READFIXED(save_p); + ht->target = LoadMobj(READUINT32(save_p)); return &ht->thinker; } @@ -3538,6 +3540,7 @@ static void P_NetUnArchiveThinkers(void) case tc_polywaypoint: th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint); + restoreNum = true; break; case tc_polyslidedoor: @@ -3599,9 +3602,9 @@ static void P_NetUnArchiveThinkers(void) if (restoreNum) { executor_t *delay = NULL; + polywaypoint_t *polywp = NULL; UINT32 mobjnum; - for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; - currentthinker = currentthinker->next) + for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next) { if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay) continue; @@ -3610,6 +3613,15 @@ static void P_NetUnArchiveThinkers(void) continue; delay->caller = P_FindNewPosition(mobjnum); } + for (currentthinker = thlist[THINK_POLYOBJ].next; currentthinker != &thlist[THINK_POLYOBJ]; currentthinker = currentthinker->next) + { + if (currentthinker->function.acp1 != (actionf_p1)T_PolyObjWaypoint) + continue; + polywp = (void *)currentthinker; + if (!(mobjnum = (UINT32)(size_t)polywp->target)) + continue; + polywp->target = P_FindNewPosition(mobjnum); + } } } From 1d04001fdfcdb434082395036476c4c10b37ec5d Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 27 Dec 2019 19:24:00 +0000 Subject: [PATCH 193/312] use P_SetTarget to assign a value to th->target --- src/p_polyobj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index d7105ee5a..be5673093 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2020,7 +2020,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) target = waypoint; th->pointnum = target->health; // Set the mobj as your target! -- Monster Iestyn 27/12/19 - th->target = target; + P_SetTarget(&th->target, target); // calculate MOMX/MOMY/MOMZ for next waypoint // change slope @@ -2648,7 +2648,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Set pointnum th->pointnum = target->health; // Set the mobj as your target! -- Monster Iestyn 27/12/19 - th->target = target; + P_SetTarget(&th->target, target); // We don't deal with the mirror crap here, we'll // handle that in the T_Thinker function. From ed29efd9ebf1ccd90ded05742dcdad5a5de04249 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 16:58:55 -0300 Subject: [PATCH 194/312] ST_drawLivesArea stuff. --- src/st_stuff.c | 134 ++++++++++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 57 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index d8b9a8059..02b559cbf 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -845,69 +845,13 @@ static void ST_drawLivesArea(void) hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, faceprefix[stplyr->skin], colormap); } - // Lives number + // Metal Sonic recording if (metalrecording) { if (((2*leveltime)/TICRATE) & 1) V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, hudinfo[HUD_LIVES].f|V_PERPLAYER|V_REDMAP|V_HUDTRANS, "REC"); } - else if (G_GametypeUsesLives() || gametype == GT_RACE) - { - // x - V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10, - hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, stlivex); - - // lives number - if (gametype == GT_RACE) - { - livescount = INFLIVES; - notgreyedout = true; - } - else if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 3) - { - INT32 i; - livescount = 0; - notgreyedout = (stplyr->lives > 0); - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - if (players[i].lives < 1) - continue; - - if (players[i].lives > 1) - notgreyedout = true; - - if (players[i].lives == INFLIVES) - { - livescount = INFLIVES; - break; - } - else if (livescount < 99) - livescount += (players[i].lives); - } - } - else - { - livescount = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives); - notgreyedout = true; - } - - if (livescount == INFLIVES) - V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8, - '\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false); - else - { - if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1))) - livescount++; - if (livescount > 99) - livescount = 99; - V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, - hudinfo[HUD_LIVES].f|V_PERPLAYER|(notgreyedout ? V_HUDTRANS : V_HUDTRANSHALF), va("%d",livescount)); - } - } // Spectator else if (stplyr->spectator) v_colmap = V_GRAYMAP; @@ -934,6 +878,82 @@ static void ST_drawLivesArea(void) v_colmap = V_BLUEMAP; } } + // Lives number + else + { + boolean candrawlives = true; + + // Co-op and Competition, normal life counter + if (G_GametypeUsesLives()) + { + // Handle cooplives here + if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 3) + { + INT32 i; + livescount = 0; + notgreyedout = (stplyr->lives > 0); + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (players[i].lives < 1) + continue; + + if (players[i].lives > 1) + notgreyedout = true; + + if (players[i].lives == INFLIVES) + { + livescount = INFLIVES; + break; + } + else if (livescount < 99) + livescount += (players[i].lives); + } + } + else + { + livescount = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives); + notgreyedout = true; + } + } + // Infinity symbol (Race) + else if (G_PlatformGametype() && !(gametyperules & GTR_LIVES)) + { + livescount = INFLIVES; + notgreyedout = true; + } + // Otherwise nothing, sorry. + // Special Stages keep not showing lives, + // as G_GametypeUsesLives() returns false in + // Special Stages, and the infinity symbol + // cannot show up because Special Stages + // still have the GTR_LIVES gametype rule + // by default. + else + candrawlives = false; + + // Draw the lives counter here. + if (candrawlives) + { + // x + V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10, hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, stlivex); + if (livescount == INFLIVES) + V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8, + '\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false); + else + { + if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1))) + livescount++; + if (livescount > 99) + livescount = 99; + V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, + hudinfo[HUD_LIVES].f|V_PERPLAYER|(notgreyedout ? V_HUDTRANS : V_HUDTRANSHALF), va("%d",livescount)); + } + } +#undef ST_drawLivesX + } // name v_colmap |= (V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER); From 1f96f701730ab80348097852523b9b7d94e22892 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 17:08:20 -0300 Subject: [PATCH 195/312] Preparing for the inevitable gametype rule that will handle cooplives... --- src/d_netcmd.c | 2 +- src/g_game.c | 14 ++++++++++++++ src/g_game.h | 1 + src/hu_stuff.c | 4 ++-- src/lua_baselib.c | 18 ++++++++++++++++++ src/p_inter.c | 4 ++-- src/p_user.c | 6 +++--- src/st_stuff.c | 8 ++++---- src/y_inter.c | 4 ++-- 9 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4e14ca25f..77cb3bcd0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3800,7 +3800,7 @@ static void CoopLives_OnChange(void) { INT32 i; - if (!(netgame || multiplayer) || gametype != GT_COOP) + if (!(netgame || multiplayer) || !G_GametypeUsesCoopLives()) return; switch (cv_cooplives.value) diff --git a/src/g_game.c b/src/g_game.c index 28de6693f..08422ee58 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3439,6 +3439,20 @@ boolean G_GametypeUsesLives(void) return false; } +// +// G_GametypeUsesCoopLives +// +// Returns true if the current gametype uses +// the cooplives CVAR. False otherwise. +// +boolean G_GametypeUsesCoopLives(void) +{ + // Preparing for the inevitable + // gametype rule that will + // handle cooplives... + return (gametype == GT_COOP); +} + // // G_GametypeHasTeams // diff --git a/src/g_game.h b/src/g_game.h index 6916bba6e..8e25554ab 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -218,6 +218,7 @@ void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolo INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); +boolean G_GametypeUsesCoopLives(void); boolean G_GametypeHasTeams(void); boolean G_GametypeHasSpectators(void); boolean G_RingSlingerGametype(void); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index d9801793b..3844cf903 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2434,7 +2434,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I } } - if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives + if (G_GametypeUsesLives() && !(G_GametypeUsesCoopLives() && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives)); else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) { @@ -2743,7 +2743,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline | (greycheck ? V_TRANSLUCENT : 0) | V_ALLOWLOWERCASE, name); - if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives + if (G_GametypeUsesLives() && !(G_GametypeUsesCoopLives() && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives)); else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) V_DrawSmallScaledPatch(x-28, y-4, 0, tagico); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 695e9367e..e3ded8256 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2854,6 +2854,14 @@ static int lib_gGametypeUsesLives(lua_State *L) return 1; } +static int lib_gGametypeUsesCoopLives(lua_State *L) +{ + //HUDSAFE + INLEVEL + lua_pushboolean(L, G_GametypeUsesCoopLives()); + return 1; +} + static int lib_gGametypeHasTeams(lua_State *L) { //HUDSAFE @@ -2894,6 +2902,14 @@ static int lib_gTagGametype(lua_State *L) return 1; } +static int lib_gCompetitionGametype(lua_State *L) +{ + //HUDSAFE + INLEVEL + lua_pushboolean(L, G_CompetitionGametype()); + return 1; +} + static int lib_gTicsToHours(lua_State *L) { tic_t rtic = luaL_checkinteger(L, 1); @@ -3139,11 +3155,13 @@ static luaL_Reg lib[] = { {"G_ExitLevel",lib_gExitLevel}, {"G_IsSpecialStage",lib_gIsSpecialStage}, {"G_GametypeUsesLives",lib_gGametypeUsesLives}, + {"G_GametypeUsesCoopLives",lib_gGametypeUsesCoopLives}, {"G_GametypeHasTeams",lib_gGametypeHasTeams}, {"G_GametypeHasSpectators",lib_gGametypeHasSpectators}, {"G_RingSlingerGametype",lib_gRingSlingerGametype}, {"G_PlatformGametype",lib_gPlatformGametype}, {"G_TagGametype",lib_gTagGametype}, + {"G_CompetitionGametype",lib_gCompetitionGametype}, {"G_TicsToHours",lib_gTicsToHours}, {"G_TicsToMinutes",lib_gTicsToMinutes}, {"G_TicsToSeconds",lib_gTicsToSeconds}, diff --git a/src/p_inter.c b/src/p_inter.c index a8b169db5..6fd0c91d1 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2523,7 +2523,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->colorized = false; G_GhostAddColor(GHC_NORMAL); - if ((target->player->lives <= 1) && (netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value == 0)) + if ((target->player->lives <= 1) && (netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value == 0)) ; else if (!target->player->bot && !target->player->spectator && (target->player->lives != INFLIVES) && G_GametypeUsesLives()) @@ -2533,7 +2533,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (target->player->lives <= 0) // Tails 03-14-2000 { boolean gameovermus = false; - if ((netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value != 1)) + if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value != 1)) { INT32 i; for (i = 0; i < MAXPLAYERS; i++) diff --git a/src/p_user.c b/src/p_user.c index 3f407d6a9..38560fe97 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1236,7 +1236,7 @@ void P_GivePlayerLives(player_t *player, INT32 numlives) return; } - if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) + if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) { P_GivePlayerRings(player, 100*numlives); if (player->lives - prevlives >= numlives) @@ -1267,7 +1267,7 @@ docooprespawn: void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound) { - if (!((netgame || multiplayer) && gametype == GT_COOP)) + if (!((netgame || multiplayer) && G_GametypeUsesCoopLives())) { P_GivePlayerLives(player, numlives); if (sound) @@ -9298,7 +9298,7 @@ boolean P_GetLives(player_t *player) { INT32 i, maxlivesplayer = -1, livescheck = 1; if (!(netgame || multiplayer) - || (gametype != GT_COOP) + || !G_GametypeUsesCoopLives() || (player->lives == INFLIVES)) return true; diff --git a/src/st_stuff.c b/src/st_stuff.c index 02b559cbf..9e761b1ab 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -887,7 +887,7 @@ static void ST_drawLivesArea(void) if (G_GametypeUsesLives()) { // Handle cooplives here - if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 3) + if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 3) { INT32 i; livescount = 0; @@ -914,7 +914,7 @@ static void ST_drawLivesArea(void) } else { - livescount = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives); + livescount = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives); notgreyedout = true; } } @@ -2246,7 +2246,7 @@ static void ST_drawTextHUD(void) textHUDdraw(M_GetText("\x82""Wait for the stage to end...")) else if (G_PlatformGametype()) { - if (gametype == GT_COOP) + if (G_GametypeUsesCoopLives()) { if (stplyr->lives <= 0 && cv_cooplives.value == 2 @@ -2657,7 +2657,7 @@ static void ST_overlayDrawer(void) INT32 i = MAXPLAYERS; INT32 deadtimer = stplyr->spectator ? TICRATE : (stplyr->deadtimer-(TICRATE<<1)); - if ((gametype == GT_COOP) + if (G_GametypeUsesCoopLives() && (netgame || multiplayer) && (cv_cooplives.value != 1)) { diff --git a/src/y_inter.c b/src/y_inter.c index b26c0797e..62b3d553d 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1977,7 +1977,7 @@ static void Y_AwardCoopBonuses(void) if (i == consoleplayer) { - data.coop.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives); + data.coop.gotlife = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? 0 : ptlives); M_Memcpy(&data.coop.bonuses, &localbonuses, sizeof(data.coop.bonuses)); } } @@ -2032,7 +2032,7 @@ static void Y_AwardSpecialStageBonus(void) if (i == consoleplayer) { - data.spec.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives); + data.spec.gotlife = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? 0 : ptlives); M_Memcpy(&data.spec.bonuses, &localbonuses, sizeof(data.spec.bonuses)); // Continues related From 3b341245f13cdf2a5e3ef425e2b73aaea6cf5d27 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 17:14:56 -0300 Subject: [PATCH 196/312] Same deal, but for starposts. --- src/g_game.c | 24 +++++++++++++++++++----- src/g_game.h | 1 + src/lua_baselib.c | 9 +++++++++ src/p_inter.c | 2 +- src/p_setup.c | 4 ++-- src/p_user.c | 4 ++-- 6 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 08422ee58..2d9f2663e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2890,11 +2890,11 @@ void G_DoReborn(INT32 playernum) if (countdowntimeup || (!(netgame || multiplayer) && gametype == GT_COOP)) resetlevel = true; - else if (gametype == GT_COOP && (netgame || multiplayer) && !G_IsSpecialStage(gamemap)) + else if ((G_GametypeUsesCoopLives() || G_GametypeUsesCoopStarposts()) && (netgame || multiplayer) && !G_IsSpecialStage(gamemap)) { boolean notgameover = true; - if (cv_cooplives.value != 0 && player->lives <= 0) // consider game over first + if (G_GametypeUsesCoopLives() && (cv_cooplives.value != 0 && player->lives <= 0)) // consider game over first { for (i = 0; i < MAXPLAYERS; i++) { @@ -2929,7 +2929,7 @@ void G_DoReborn(INT32 playernum) } } - if (notgameover && cv_coopstarposts.value == 2) + if (G_GametypeUsesCoopStarposts() && (notgameover && cv_coopstarposts.value == 2)) { for (i = 0; i < MAXPLAYERS; i++) { @@ -3005,7 +3005,7 @@ void G_DoReborn(INT32 playernum) } // restore time in netgame (see also p_setup.c) - if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) + if ((netgame || multiplayer) && G_GametypeUsesCoopStarposts() && cv_coopstarposts.value == 2) { // is this a hack? maybe tic_t maxstarposttime = 0; @@ -3076,7 +3076,7 @@ void G_AddPlayer(INT32 playernum) if (!players[i].exiting) notexiting++; - if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum))) + if (!(cv_coopstarposts.value && G_GametypeUsesCoopStarposts() && (p->starpostnum < players[i].starpostnum))) continue; p->starpostscale = players[i].starpostscale; @@ -3453,6 +3453,20 @@ boolean G_GametypeUsesCoopLives(void) return (gametype == GT_COOP); } +// +// G_GametypeUsesCoopStarposts +// +// Returns true if the current gametype uses +// the coopstarposts CVAR. False otherwise. +// +boolean G_GametypeUsesCoopStarposts(void) +{ + // Preparing for the inevitable + // gametype rule that will + // handle coopstarposts... + return (gametype == GT_COOP); +} + // // G_GametypeHasTeams // diff --git a/src/g_game.h b/src/g_game.h index 8e25554ab..68e78789f 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -219,6 +219,7 @@ INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); boolean G_GametypeUsesCoopLives(void); +boolean G_GametypeUsesCoopStarposts(void); boolean G_GametypeHasTeams(void); boolean G_GametypeHasSpectators(void); boolean G_RingSlingerGametype(void); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e3ded8256..2a82ec512 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2862,6 +2862,14 @@ static int lib_gGametypeUsesCoopLives(lua_State *L) return 1; } +static int lib_gGametypeUsesCoopStarposts(lua_State *L) +{ + //HUDSAFE + INLEVEL + lua_pushboolean(L, G_GametypeUsesCoopStarposts()); + return 1; +} + static int lib_gGametypeHasTeams(lua_State *L) { //HUDSAFE @@ -3156,6 +3164,7 @@ static luaL_Reg lib[] = { {"G_IsSpecialStage",lib_gIsSpecialStage}, {"G_GametypeUsesLives",lib_gGametypeUsesLives}, {"G_GametypeUsesCoopLives",lib_gGametypeUsesCoopLives}, + {"G_GametypeUsesCoopStarposts",lib_gGametypeUsesCoopStarposts}, {"G_GametypeHasTeams",lib_gGametypeHasTeams}, {"G_GametypeHasSpectators",lib_gGametypeHasSpectators}, {"G_RingSlingerGametype",lib_gRingSlingerGametype}, diff --git a/src/p_inter.c b/src/p_inter.c index 6fd0c91d1..f2d34bd7d 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1451,7 +1451,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->starpostnum >= special->health) return; // Already hit this post - if (cv_coopstarposts.value && gametype == GT_COOP && (netgame || multiplayer)) + if (cv_coopstarposts.value && G_GametypeUsesCoopStarposts() && (netgame || multiplayer)) { for (i = 0; i < MAXPLAYERS; i++) { diff --git a/src/p_setup.c b/src/p_setup.c index 3f49a1680..e09ecf6c3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2141,7 +2141,7 @@ static void P_LevelInitStuff(void) // earthquake camera memset(&quake,0,sizeof(struct quake)); - if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) + if ((netgame || multiplayer) && G_GametypeUsesCoopStarposts() && cv_coopstarposts.value == 2) { for (i = 0; i < MAXPLAYERS; i++) { @@ -2848,7 +2848,7 @@ boolean P_SetupLevel(boolean skipprecip) } // restore time in netgame (see also g_game.c) - if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) + if ((netgame || multiplayer) && G_GametypeUsesCoopStarposts() && cv_coopstarposts.value == 2) { // is this a hack? maybe tic_t maxstarposttime = 0; diff --git a/src/p_user.c b/src/p_user.c index 38560fe97..9ad85cac1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9447,7 +9447,7 @@ static void P_DeathThink(player_t *player) player->playerstate = PST_REBORN; else if ((player->lives > 0 || j != MAXPLAYERS) && !(!(netgame || multiplayer) && G_IsSpecialStage(gamemap))) // Don't allow "click to respawn" in special stages! { - if (gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2) + if (G_GametypeUsesCoopStarposts() && (netgame || multiplayer) && cv_coopstarposts.value == 2) { P_ConsiderAllGone(); if ((player->deadtimer > TICRATE<<1) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))) @@ -11537,7 +11537,7 @@ void P_PlayerThink(player_t *player) #else if (player->spectator && #endif - gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2) + G_GametypeUsesCoopStarposts() && (netgame || multiplayer) && cv_coopstarposts.value == 2) P_ConsiderAllGone(); if (player->playerstate == PST_DEAD) From 4b2c88fab8bc2645b744385c6b827006a48801ab Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 17:15:23 -0300 Subject: [PATCH 197/312] Fix CoopLives_OnChange. --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 77cb3bcd0..154bcb625 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3745,7 +3745,7 @@ static void CoopStarposts_OnChange(void) { INT32 i; - if (!(netgame || multiplayer) || gametype != GT_COOP) + if (!(netgame || multiplayer) || !G_GametypeUsesCoopStarposts()) return; switch (cv_coopstarposts.value) From e03eaa554bff41f31538be11b66e9b36a9a3989e Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 17:22:55 -0300 Subject: [PATCH 198/312] In P_KillPlayer, check for the gametype's rules, instead of the gametype itself, before bursting rings. --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index f2d34bd7d..87b0c0a43 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3203,7 +3203,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) // Burst weapons and emeralds in Match/CTF only if (source) { - if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF) + if ((gametyperules & GTR_RINGSLINGER) && !(gametyperules & GTR_TAG)) P_PlayerRingBurst(player, player->rings); if (gametyperules & GTR_MATCHEMERALDS) P_PlayerEmeraldBurst(player, false); From 1fb244d87fde7662f5808d6450eb146d58f56680 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 27 Dec 2019 18:24:08 -0300 Subject: [PATCH 199/312] GTR_HIDETIME, not GTR_TAG --- src/st_stuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 9e761b1ab..35dd861c5 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -723,7 +723,7 @@ static void ST_drawTime(void) downwards = true; } // Post-hidetime normal. - else if (gametyperules & GTR_TAG) + else if (gametyperules & GTR_HIDETIME) tics = stplyr->realtime - hidetime*TICRATE; // "Shadow! What are you doing? Hurry and get back here // right now before the island blows up with you on it!" From afc78fb56a7efff53fbd55a1edeff8c2f3fcd859 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 27 Dec 2019 14:48:55 -0800 Subject: [PATCH 200/312] Only return if we damaged the monitor --- src/p_map.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 96fb8ee07..f859c8c77 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -832,7 +832,10 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } else - return P_DamageMobj(thing, tmthing, tmthing, 1, 0); + { + if (P_DamageMobj(thing, tmthing, tmthing, 1, 0)) + return true; + } } // vectorise metal - done in a special case as at this point neither has the right flags for touching From f62579811bdab4f9b1ca6388c5c0603cd2a66867 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Fri, 27 Dec 2019 23:51:13 -0600 Subject: [PATCH 201/312] Fixed messed up comparison. --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 10d55ae0e..a9e6cd1a1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4638,7 +4638,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (player->dashspeed < player->mindash) player->dashspeed = player->mindash; - if (player->dashspeed < player->maxdash) + if (player->dashspeed > player->maxdash) player->dashspeed = player->maxdash; if (player->dashspeed < player->maxdash && player->mindash != player->maxdash) From 08895ef751049b7110a2b0d58d862c8d915c4f75 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 08:43:27 +0100 Subject: [PATCH 202/312] Fixed/clarified some flag descriptions in the ZB config --- extras/conf/Includes/SRB222_linedefs.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/conf/Includes/SRB222_linedefs.cfg b/extras/conf/Includes/SRB222_linedefs.cfg index 8bc761dfe..fdf191850 100644 --- a/extras/conf/Includes/SRB222_linedefs.cfg +++ b/extras/conf/Includes/SRB222_linedefs.cfg @@ -126,8 +126,8 @@ doom prefix = "(9)"; flags32text = "[5] Swing instead of spin"; flags64text = "[6] Player-turnable chain"; - flags128text = "[7] Make chain from maces"; - flags256text = "[8] Spawn mace at origin"; + flags128text = "[7] Make chain from end item"; + flags256text = "[8] Spawn link at origin"; flags512text = "[9] Don't clip inside ground"; flags1024text = "[10] No distance check"; } From 319ed09c0021bac170e559209d7add5609279f9f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 11:30:39 +0100 Subject: [PATCH 203/312] Rename P_SetupLevel to the more accurate P_LoadLevel and separate out some of its content into subfunctions --- src/d_main.c | 2 +- src/g_game.c | 2 +- src/p_saveg.c | 2 +- src/p_setup.c | 557 +++++++++++++++++++++++++++----------------------- src/p_setup.h | 2 +- 5 files changed, 306 insertions(+), 259 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index e25ef998e..0654e0927 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1462,7 +1462,7 @@ void D_SRB2Main(void) { levelstarttic = gametic; G_SetGamestate(GS_LEVEL); - if (!P_SetupLevel(false)) + if (!P_LoadLevel(false)) I_Quit(); // fail so reset game stuff } } diff --git a/src/g_game.c b/src/g_game.c index 19b18ef8c..e6a28aa41 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1847,7 +1847,7 @@ void G_DoLoadLevel(boolean resetplayer) } // Setup the level. - if (!P_SetupLevel(false)) // this never returns false? + if (!P_LoadLevel(false)) // this never returns false? { // fail so reset game stuff Command_ExitGame_f(); diff --git a/src/p_saveg.c b/src/p_saveg.c index 85efacf88..4cfeab6f8 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -4064,7 +4064,7 @@ static inline boolean P_NetUnArchiveMisc(void) tokenlist = READUINT32(save_p); - if (!P_SetupLevel(true)) + if (!P_LoadLevel(true)) return false; // get the time diff --git a/src/p_setup.c b/src/p_setup.c index 9acc4adb3..1ec811e62 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -970,7 +970,7 @@ static void P_SpawnEmeraldHunt(void) mobjinfo[MT_EMERHUNT].spawnstate+2); } -static void P_LoadThings(boolean loademblems) +static void P_SpawnMapThings(boolean spawnemblems) { size_t i; mapthing_t *mt; @@ -1000,7 +1000,7 @@ static void P_LoadThings(boolean loademblems) || mt->type == 1702) // MT_AXISTRANSFERLINE continue; // These were already spawned - if (!loademblems && mt->type == mobjinfo[MT_EMBLEM].doomednum) + if (!spawnemblems && mt->type == mobjinfo[MT_EMBLEM].doomednum) continue; mt->mobj = NULL; @@ -2015,6 +2015,75 @@ static void P_LoadMapData(const virtres_t* virt) memcpy(spawnsides, sides, numsides * sizeof (*sides)); } +/** Compute MD5 message digest for bytes read from memory source + * + * The resulting message digest number will be written into the 16 bytes + * beginning at RESBLOCK. + * + * \param filename path of file + * \param resblock resulting MD5 checksum + * \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found + */ +static INT32 P_MakeBufferMD5(const char* buffer, size_t len, void* resblock) +{ +#ifdef NOMD5 + (void)buffer; + (void)len; + memset(resblock, 0x00, 16); + return 1; +#else + tic_t t = I_GetTime(); + CONS_Debug(DBG_SETUP, "Making MD5\n"); + if (md5_buffer(buffer, len, resblock) == NULL) + return 1; + CONS_Debug(DBG_SETUP, "MD5 calc took %f seconds\n", (float)(I_GetTime() - t)/NEWTICRATE); + return 0; +#endif +} + +static void P_MakeMapMD5(virtres_t* virt, void* dest) +{ + unsigned char linemd5[16]; + unsigned char sectormd5[16]; + unsigned char thingmd5[16]; + unsigned char sidedefmd5[16]; + unsigned char resmd5[16]; + UINT8 i; + + // Create a hash for the current map + // get the actual lumps! + virtlump_t *virtlines = vres_Find(virt, "LINEDEFS"); + virtlump_t *virtsectors = vres_Find(virt, "SECTORS"); + virtlump_t *virtmthings = vres_Find(virt, "THINGS"); + virtlump_t *virtsides = vres_Find(virt, "SIDEDEFS"); + + P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5); + P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5); + P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5); + P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5); + + for (i = 0; i < 16; i++) + resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF; + + M_Memcpy(dest, &resmd5, 16); +} + +static void P_LoadMapFromFile(void) +{ + virtres_t *virt = vres_GetMap(lastloadedmaplumpnum); + + P_LoadMapData(virt); + P_LoadMapBSP(virt); + P_LoadMapLUT(virt); + + P_LoadLineDefs2(); + P_GroupLines(); + + P_MakeMapMD5(virt, &mapmd5); + + vres_Free(virt); +} + #if 0 static char *levellumps[] = { @@ -2210,66 +2279,13 @@ void P_LoadThingsOnly(void) P_LevelInitStuff(); - P_LoadThings(true); + P_SpawnMapThings(true); // restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that skyboxmo[0] = skyboxviewpnts[(viewid >= 0) ? viewid : 0]; skyboxmo[1] = skyboxcenterpnts[(centerid >= 0) ? centerid : 0]; } -/** Compute MD5 message digest for bytes read from memory source - * - * The resulting message digest number will be written into the 16 bytes - * beginning at RESBLOCK. - * - * \param filename path of file - * \param resblock resulting MD5 checksum - * \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found - */ -static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock) -{ -#ifdef NOMD5 - (void)buffer; - (void)len; - memset(resblock, 0x00, 16); - return 1; -#else - tic_t t = I_GetTime(); - CONS_Debug(DBG_SETUP, "Making MD5\n"); - if (md5_buffer(buffer, len, resblock) == NULL) - return 1; - CONS_Debug(DBG_SETUP, "MD5 calc took %f seconds\n", (float)(I_GetTime() - t)/NEWTICRATE); - return 0; -#endif -} - -static void P_MakeMapMD5(virtres_t* virt, void *dest) -{ - unsigned char linemd5[16]; - unsigned char sectormd5[16]; - unsigned char thingmd5[16]; - unsigned char sidedefmd5[16]; - unsigned char resmd5[16]; - UINT8 i; - - // Create a hash for the current map - // get the actual lumps! - virtlump_t* virtlines = vres_Find(virt, "LINEDEFS"); - virtlump_t* virtsectors = vres_Find(virt, "SECTORS"); - virtlump_t* virtmthings = vres_Find(virt, "THINGS"); - virtlump_t* virtsides = vres_Find(virt, "SIDEDEFS"); - - P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5); - P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5); - P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5); - P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5); - - for (i = 0; i < 16; i++) - resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF; - - M_Memcpy(dest, &resmd5, 16); -} - static void P_RunLevelScript(const char *scriptname) { if (!(mapheaderinfo[gamemap-1]->levelflags & LF_SCRIPTISFILE)) @@ -2433,6 +2449,45 @@ static void P_LoadNightsGhosts(void) free(gpath); } +static void P_InitTagGametype(void) +{ + UINT8 i; + INT32 realnumplayers = 0; + INT32 playersactive[MAXPLAYERS]; + + //I just realized how problematic this code can be. + //D_NumPlayers() will not always cover the scope of the netgame. + //What if one player is node 0 and the other node 31? + //The solution? Make a temp array of all players that are currently playing and pick from them. + //Future todo? When a player leaves, shift all nodes down so D_NumPlayers() can be used as intended? + //Also, you'd never have to loop through all 32 players slots to find anything ever again. + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !players[i].spectator) + { + playersactive[realnumplayers] = i; //stores the player's node in the array. + realnumplayers++; + } + } + + if (!realnumplayers) //this should also fix the dedicated crash bug. You only pick a player if one exists to be picked. + { + CONS_Printf(M_GetText("No player currently available to become IT. Awaiting available players.\n")); + return; + } + + i = P_RandomKey(realnumplayers); + players[playersactive[i]].pflags |= PF_TAGIT; //choose our initial tagger before map starts. + + // Taken and modified from G_DoReborn() + // Remove the player so he can respawn elsewhere. + // first disassociate the corpse + if (players[playersactive[i]].mo) + P_RemoveMobj(players[playersactive[i]].mo); + + G_SpawnPlayer(playersactive[i], false); //respawn the lucky player in his dedicated spawn location. +} + static void P_SetupCamera(void) { if (players[displayplayer].mo && (server || addedtogame)) @@ -2470,6 +2525,52 @@ static void P_SetupCamera(void) } } +static void P_InitCamera(void) +{ + if (!dedicated) + { + P_SetupCamera(); + + // Salt: CV_ClearChangedFlags() messes with your settings :( + /*if (!cv_cam_height.changed) + CV_Set(&cv_cam_height, cv_cam_height.defaultvalue); + if (!cv_cam2_height.changed) + CV_Set(&cv_cam2_height, cv_cam2_height.defaultvalue); + + if (!cv_cam_dist.changed) + CV_Set(&cv_cam_dist, cv_cam_dist.defaultvalue); + if (!cv_cam2_dist.changed) + CV_Set(&cv_cam2_dist, cv_cam2_dist.defaultvalue);*/ + + // Though, I don't think anyone would care about cam_rotate being reset back to the only value that makes sense :P + if (!cv_cam_rotate.changed) + CV_Set(&cv_cam_rotate, cv_cam_rotate.defaultvalue); + if (!cv_cam2_rotate.changed) + CV_Set(&cv_cam2_rotate, cv_cam2_rotate.defaultvalue); + + if (!cv_analog.changed) + CV_SetValue(&cv_analog, 0); + if (!cv_analog2.changed) + CV_SetValue(&cv_analog2, 0); + + displayplayer = consoleplayer; // Start with your OWN view, please! + } + + if (twodlevel) + { + CV_SetValue(&cv_analog, false); + CV_SetValue(&cv_analog2, false); + } + else + { + if (cv_useranalog.value) + CV_SetValue(&cv_analog, true); + + if ((splitscreen && cv_useranalog2.value) || botingame) + CV_SetValue(&cv_analog2, true); + } +} + static boolean CanSaveLevel(INT32 mapnum) { if (ultimatemode) // never save in ultimate (probably redundant with cursaveslot also being checked) @@ -2485,18 +2586,152 @@ static boolean CanSaveLevel(INT32 mapnum) return (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME || gamecomplete || !lastmaploaded); } +static void P_RunSpecialStageWipe(void) +{ + tic_t starttime = I_GetTime(); + tic_t endtime = starttime + (3*TICRATE)/2; + tic_t nowtime; + + S_StartSound(NULL, sfx_s3kaf); + + // Fade music! Time it to S3KAF: 0.25 seconds is snappy. + if (RESETMUSIC || + strnicmp(S_MusicName(), + (mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap - 1]->musname : mapmusname, 7)) + S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE) + + F_WipeStartScreen(); + wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE); + +#ifdef HWRENDER + // uh.......... + if (rendermode == render_opengl) + F_WipeColorFill(0); +#endif + + F_WipeEndScreen(); + F_RunWipe(wipedefs[wipe_speclevel_towhite], false); + + I_OsPolling(); + I_FinishUpdate(); // page flip or blit buffer + if (moviemode) + M_SaveFrame(); + + nowtime = lastwipetic; + + // Hold on white for extra effect. + while (nowtime < endtime) + { + // wait loop + while (!((nowtime = I_GetTime()) - lastwipetic)) + I_Sleep(); + lastwipetic = nowtime; + if (moviemode) // make sure we save frames for the white hold too + M_SaveFrame(); + } +} + +static void P_RunLevelWipe(void) +{ + F_WipeStartScreen(); + wipestyleflags |= WSF_FADEOUT; + +#ifdef HWRENDER + // uh.......... + if (rendermode == render_opengl) + F_WipeColorFill(31); +#endif + + F_WipeEndScreen(); + // for titlemap: run a specific wipe if specified + // needed for exiting time attack + if (wipetypepre != INT16_MAX) + F_RunWipe( + (wipetypepre >= 0 && F_WipeExists(wipetypepre)) ? wipetypepre : wipedefs[wipe_level_toblack], + false); + wipetypepre = -1; +} + +static void P_InitPlayers(void) +{ + UINT8 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + // Start players with pity shields if possible + players[i].pity = -1; + + players[i].mo = NULL; + + if (!G_PlatformGametype()) + G_DoReborn(i); + else // gametype is GT_COOP or GT_RACE + { + G_SpawnPlayer(i, players[i].starposttime); + if (players[i].starposttime) + P_ClearStarPost(players[i].starpostnum); + } + } +} + +static void P_WriteLetter(void) +{ + char *buf, *b; + + if (!unlockables[27].unlocked) // pandora's box + return; + + if (modeattacking) + return; + +#ifndef DEVELOP + if (modifiedgame) + return; +#endif + + if (netgame || multiplayer) + return; + + if (gamemap != 0x1d35 - 016464) + return; + + P_SpawnMobj(0640370000, 0x11000000, 0x3180000, MT_LETTER)->angle = ANGLE_90; + + if (textprompts[199]->page[1].backcolor == 259) + return; + + buf = W_CacheLumpName("WATERMAP", PU_STATIC); + b = buf; + + while ((*b != 65) && (b - buf < 256)) + { + *b = (*b - 65) & 255; + b++; + } + *b = '\0'; + + Z_Free(textprompts[199]->page[1].text); + textprompts[199]->page[1].text = Z_StrDup(buf); + textprompts[199]->page[1].lines = 4; + textprompts[199]->page[1].backcolor = 259; + Z_Free(buf); +} + /** Loads a level from a lump or external wad. * * \param skipprecip If true, don't spawn precipitation. * \todo Clean up, refactor, split up; get rid of the bloat. */ -boolean P_SetupLevel(boolean skipprecip) +boolean P_LoadLevel(boolean skipprecip) { // use gamemap to get map number. // 99% of the things already did, so. // Map header should always be in place at this point INT32 i, loadprecip = 1, ranspecialwipe = 0; - INT32 loademblems = 1; + boolean spawnemblems = true; INT32 fromnetsave = 0; sector_t *ss; boolean chase; @@ -2569,48 +2804,7 @@ boolean P_SetupLevel(boolean skipprecip) ranspecialwipe = 2; else if (rendermode != render_none && G_IsSpecialStage(gamemap)) { - tic_t starttime = I_GetTime(); - tic_t endtime = starttime + (3*TICRATE)/2; - tic_t nowtime; - - S_StartSound(NULL, sfx_s3kaf); - - // Fade music! Time it to S3KAF: 0.25 seconds is snappy. - if (RESETMUSIC || - strnicmp(S_MusicName(), - (mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7)) - S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE) - - F_WipeStartScreen(); - wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE); - -#ifdef HWRENDER - // uh.......... - if (rendermode == render_opengl) - F_WipeColorFill(0); -#endif - - F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_speclevel_towhite], false); - - I_OsPolling(); - I_FinishUpdate(); // page flip or blit buffer - if (moviemode) - M_SaveFrame(); - - nowtime = lastwipetic; - - // Hold on white for extra effect. - while (nowtime < endtime) - { - // wait loop - while (!((nowtime = I_GetTime()) - lastwipetic)) - I_Sleep(); - lastwipetic = nowtime; - if (moviemode) // make sure we save frames for the white hold too - M_SaveFrame(); - } - + P_RunSpecialStageWipe(); ranspecialwipe = 1; } @@ -2636,25 +2830,7 @@ boolean P_SetupLevel(boolean skipprecip) // Let's fade to black here // But only if we didn't do the special stage wipe if (rendermode != render_none && !ranspecialwipe) - { - F_WipeStartScreen(); - wipestyleflags |= WSF_FADEOUT; - -#ifdef HWRENDER - // uh.......... - if (rendermode == render_opengl) - F_WipeColorFill(31); -#endif - - F_WipeEndScreen(); - // for titlemap: run a specific wipe if specified - // needed for exiting time attack - if (wipetypepre != INT16_MAX) - F_RunWipe( - (wipetypepre >= 0 && F_WipeExists(wipetypepre)) ? wipetypepre : wipedefs[wipe_level_toblack], - false); - wipetypepre = -1; - } + P_RunLevelWipe(); if (!titlemapinaction) { @@ -2717,7 +2893,7 @@ boolean P_SetupLevel(boolean skipprecip) { fromnetsave = 1; loadprecip = 0; - loademblems = 0; + spawnemblems = false; } else if (savedata.lives > 0) { @@ -2763,20 +2939,7 @@ boolean P_SetupLevel(boolean skipprecip) P_MapStart(); if (lastloadedmaplumpnum) - { - virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); - - P_LoadMapData(virt); - P_LoadMapBSP(virt); - P_LoadMapLUT(virt); - - P_LoadLineDefs2(); - P_GroupLines(); - - P_MakeMapMD5(virt, &mapmd5); - - vres_Free(virt); - } + P_LoadMapFromFile(); // init gravity, tag lists, // anything that P_ResetDynamicSlopes/P_LoadThings needs to know @@ -2786,7 +2949,7 @@ boolean P_SetupLevel(boolean skipprecip) P_ResetDynamicSlopes(fromnetsave); #endif - P_LoadThings(loademblems); + P_SpawnMapThings(spawnemblems); skyboxmo[0] = skyboxviewpnts[0]; skyboxmo[1] = skyboxcenterpnts[0]; @@ -2829,30 +2992,7 @@ boolean P_SetupLevel(boolean skipprecip) goto netgameskip; // ========== - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - // Start players with pity shields if possible - players[i].pity = -1; - - if (!G_PlatformGametype()) - { - players[i].mo = NULL; - G_DoReborn(i); - } - else // gametype is GT_COOP or GT_RACE - { - players[i].mo = NULL; - - if (players[i].starposttime) - { - G_SpawnPlayer(i, true); - P_ClearStarPost(players[i].starpostnum); - } - else - G_SpawnPlayer(i, false); - } - } + P_InitPlayers(); // restore time in netgame (see also g_game.c) if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) @@ -2867,24 +3007,7 @@ boolean P_SetupLevel(boolean skipprecip) leveltime = maxstarposttime; } - if (unlockables[27].unlocked && !modeattacking // pandora's box -#ifndef DEVELOP - && !modifiedgame -#endif - && !(netgame || multiplayer) && gamemap == 0x1d35-016464) - { - P_SpawnMobj(0640370000, 0x11000000, 0x3180000, MT_LETTER)->angle = ANGLE_90; - if (textprompts[199]->page[1].backcolor != 259) - { - char *buf = W_CacheLumpName("WATERMAP", PU_STATIC), *b = buf; - while ((*b != 65) && (b-buf < 256)) { *b = (*b - 65)&255; b++; } *b = '\0'; - Z_Free(textprompts[199]->page[1].text); - textprompts[199]->page[1].text = Z_StrDup(buf); - textprompts[199]->page[1].lines = 4; - textprompts[199]->page[1].backcolor = 259; - Z_Free(buf); - } - } + P_WriteLetter(); if (modeattacking == ATTACKING_RECORD && !demoplayback) P_LoadRecordGhosts(); @@ -2892,42 +3015,7 @@ boolean P_SetupLevel(boolean skipprecip) P_LoadNightsGhosts(); if (G_TagGametype()) - { - INT32 realnumplayers = 0; - INT32 playersactive[MAXPLAYERS]; - - //I just realized how problematic this code can be. - //D_NumPlayers() will not always cover the scope of the netgame. - //What if one player is node 0 and the other node 31? - //The solution? Make a temp array of all players that are currently playing and pick from them. - //Future todo? When a player leaves, shift all nodes down so D_NumPlayers() can be used as intended? - //Also, you'd never have to loop through all 32 players slots to find anything ever again. - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && !players[i].spectator) - { - playersactive[realnumplayers] = i; //stores the player's node in the array. - realnumplayers++; - } - } - - if (realnumplayers) //this should also fix the dedicated crash bug. You only pick a player if one exists to be picked. - { - i = P_RandomKey(realnumplayers); - players[playersactive[i]].pflags |= PF_TAGIT; //choose our initial tagger before map starts. - - // Taken and modified from G_DoReborn() - // Remove the player so he can respawn elsewhere. - // first dissasociate the corpse - if (players[playersactive[i]].mo) - P_RemoveMobj(players[playersactive[i]].mo); - - G_SpawnPlayer(playersactive[i], false); //respawn the lucky player in his dedicated spawn location. - } - else - CONS_Printf(M_GetText("No player currently available to become IT. Awaiting available players.\n")); - - } + P_InitTagGametype(); else if (gametype == GT_RACE && server) CV_StealthSetValue(&cv_numlaps, (cv_basenumlaps.value) @@ -2938,48 +3026,7 @@ boolean P_SetupLevel(boolean skipprecip) // landing point for netgames. netgameskip: - if (!dedicated) - { - P_SetupCamera(); - - // Salt: CV_ClearChangedFlags() messes with your settings :( - /*if (!cv_cam_height.changed) - CV_Set(&cv_cam_height, cv_cam_height.defaultvalue); - if (!cv_cam2_height.changed) - CV_Set(&cv_cam2_height, cv_cam2_height.defaultvalue); - - if (!cv_cam_dist.changed) - CV_Set(&cv_cam_dist, cv_cam_dist.defaultvalue); - if (!cv_cam2_dist.changed) - CV_Set(&cv_cam2_dist, cv_cam2_dist.defaultvalue);*/ - - // Though, I don't think anyone would care about cam_rotate being reset back to the only value that makes sense :P - if (!cv_cam_rotate.changed) - CV_Set(&cv_cam_rotate, cv_cam_rotate.defaultvalue); - if (!cv_cam2_rotate.changed) - CV_Set(&cv_cam2_rotate, cv_cam2_rotate.defaultvalue); - - if (!cv_analog.changed) - CV_SetValue(&cv_analog, 0); - if (!cv_analog2.changed) - CV_SetValue(&cv_analog2, 0); - - displayplayer = consoleplayer; // Start with your OWN view, please! - } - - if (cv_useranalog.value) - CV_SetValue(&cv_analog, true); - - if (splitscreen && cv_useranalog2.value) - CV_SetValue(&cv_analog2, true); - else if (botingame) - CV_SetValue(&cv_analog2, true); - - if (twodlevel) - { - CV_SetValue(&cv_analog2, false); - CV_SetValue(&cv_analog, false); - } + P_InitCamera(); // clear special respawning que iquehead = iquetail = 0; diff --git a/src/p_setup.h b/src/p_setup.h index c95dd0f63..0751cf7b9 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -97,7 +97,7 @@ void P_SetupLevelSky(INT32 skynum, boolean global); void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); #endif void P_LoadThingsOnly(void); -boolean P_SetupLevel(boolean skipprecip); +boolean P_LoadLevel(boolean skipprecip); boolean P_AddWadFile(const char *wadfilename); boolean P_RunSOC(const char *socfilename); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); From c0591469370a1943753bb07356412398d4e58a91 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 11:37:56 +0100 Subject: [PATCH 204/312] Move more P_LoadLevel parts into subfunctions --- src/p_setup.c | 109 +++++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 51 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 1ec811e62..0b443c939 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2350,6 +2350,26 @@ static void P_ForceCharacter(const char *forcecharskin) } } +static void P_ResetSpawnpoints(void) +{ + UINT8 i; + + numdmstarts = numredctfstarts = numbluectfstarts = 0; + + // reset the player starts + for (i = 0; i < MAXPLAYERS; i++) + playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; + + for (i = 0; i < MAX_DM_STARTS; i++) + deathmatchstarts[i] = NULL; + + for (i = 0; i < 2; i++) + skyboxmo[i] = NULL; + + for (i = 0; i < 16; i++) + skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; +} + static void P_LoadRecordGhosts(void) { const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; @@ -2720,6 +2740,41 @@ static void P_WriteLetter(void) Z_Free(buf); } +static void P_InitGametype(void) +{ + UINT8 i; + + P_InitPlayers(); + + // restore time in netgame (see also g_game.c) + if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) + { + // is this a hack? maybe + tic_t maxstarposttime = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && players[i].starposttime > maxstarposttime) + maxstarposttime = players[i].starposttime; + } + leveltime = maxstarposttime; + } + + P_WriteLetter(); + + if (modeattacking == ATTACKING_RECORD && !demoplayback) + P_LoadRecordGhosts(); + else if (modeattacking == ATTACKING_NIGHTS && !demoplayback) + P_LoadNightsGhosts(); + + if (G_TagGametype()) + P_InitTagGametype(); + else if (gametype == GT_RACE && server) + CV_StealthSetValue(&cv_numlaps, + (cv_basenumlaps.value) + ? cv_basenumlaps.value + : mapheaderinfo[gamemap - 1]->numlaps); +} + /** Loads a level from a lump or external wad. * * \param skipprecip If true, don't spawn precipitation. @@ -2921,20 +2976,7 @@ boolean P_LoadLevel(boolean skipprecip) // SRB2 determines the sky texture to be used depending on the map header. P_SetupLevelSky(mapheaderinfo[gamemap-1]->skynum, true); - numdmstarts = numredctfstarts = numbluectfstarts = 0; - - // reset the player starts - for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; - - for (i = 0; i < MAX_DM_STARTS; i++) - deathmatchstarts[i] = NULL; - - for (i = 0; i < 2; i++) - skyboxmo[i] = NULL; - - for (i = 0; i < 16; i++) - skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; + P_ResetSpawnpoints(); P_MapStart(); @@ -2988,43 +3030,8 @@ boolean P_LoadLevel(boolean skipprecip) // none of this needs to be done because it's not the beginning of the map when // a netgame save is being loaded, and could actively be harmful by messing with // the client's view of the data.) - if (fromnetsave) - goto netgameskip; - // ========== - - P_InitPlayers(); - - // restore time in netgame (see also g_game.c) - if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) - { - // is this a hack? maybe - tic_t maxstarposttime = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && players[i].starposttime > maxstarposttime) - maxstarposttime = players[i].starposttime; - } - leveltime = maxstarposttime; - } - - P_WriteLetter(); - - if (modeattacking == ATTACKING_RECORD && !demoplayback) - P_LoadRecordGhosts(); - else if (modeattacking == ATTACKING_NIGHTS && !demoplayback) - P_LoadNightsGhosts(); - - if (G_TagGametype()) - P_InitTagGametype(); - else if (gametype == GT_RACE && server) - CV_StealthSetValue(&cv_numlaps, - (cv_basenumlaps.value) - ? cv_basenumlaps.value - : mapheaderinfo[gamemap - 1]->numlaps); - - // =========== - // landing point for netgames. - netgameskip: + if (!fromnetsave) + P_InitGametype(); P_InitCamera(); From e9376a8353c69c25938914a2f54d190eaa809098 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 12:48:32 +0100 Subject: [PATCH 205/312] Cleaned up some more stuff in P_LoadLevel() --- src/p_setup.c | 39 +++++++++++++-------------------------- src/p_setup.h | 2 +- src/p_slopes.c | 9 +++------ src/p_slopes.h | 2 +- src/p_spec.c | 2 +- src/p_spec.h | 2 +- 6 files changed, 20 insertions(+), 36 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 0b443c939..9dba341b7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2152,7 +2152,7 @@ lumpnum_t lastloadedmaplumpnum; // for comparative savegame // // Some player initialization for map start. // -static void P_LevelInitStuff(void) +static void P_InitLevelSettings(void) { INT32 i; boolean canresetlives = true; @@ -2277,7 +2277,7 @@ void P_LoadThingsOnly(void) P_RemoveMobj((mobj_t *)think); } - P_LevelInitStuff(); + P_InitLevelSettings(); P_SpawnMapThings(true); @@ -2777,19 +2777,16 @@ static void P_InitGametype(void) /** Loads a level from a lump or external wad. * - * \param skipprecip If true, don't spawn precipitation. + * \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot. * \todo Clean up, refactor, split up; get rid of the bloat. */ -boolean P_LoadLevel(boolean skipprecip) +boolean P_LoadLevel(boolean fromnetsave) { // use gamemap to get map number. // 99% of the things already did, so. // Map header should always be in place at this point - INT32 i, loadprecip = 1, ranspecialwipe = 0; - boolean spawnemblems = true; - INT32 fromnetsave = 0; + INT32 i, ranspecialwipe = 0; sector_t *ss; - boolean chase; levelloading = true; // This is needed. Don't touch. @@ -2820,19 +2817,18 @@ boolean P_LoadLevel(boolean skipprecip) if (cv_runscripts.value && mapheaderinfo[gamemap-1]->scriptname[0] != '#') P_RunLevelScript(mapheaderinfo[gamemap-1]->scriptname); - P_LevelInitStuff(); + P_InitLevelSettings(); postimgtype = postimgtype2 = postimg_none; if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0') P_ForceCharacter(mapheaderinfo[gamemap-1]->forcecharacter); - // chasecam on in chaos, race, coop - // chasecam off in match, tag, capture the flag - chase = (!(gametyperules & GTR_FIRSTPERSON)) || (maptol & TOL_2D); - if (!dedicated) { + // chasecam on in first-person gametypes and 2D + boolean chase = (!(gametyperules & GTR_FIRSTPERSON)) || (maptol & TOL_2D); + // Salt: CV_ClearChangedFlags() messes with your settings :( /*if (!cv_cam_speed.changed) CV_Set(&cv_cam_speed, cv_cam_speed.defaultvalue);*/ @@ -2943,14 +2939,7 @@ boolean P_LoadLevel(boolean skipprecip) P_InitThinkers(); P_InitCachedActions(); - /// \note for not spawning precipitation, etc. when loading netgame snapshots - if (skipprecip) - { - fromnetsave = 1; - loadprecip = 0; - spawnemblems = false; - } - else if (savedata.lives > 0) + if (!fromnetsave && savedata.lives > 0) { numgameovers = savedata.numgameovers; players[consoleplayer].continues = savedata.continues; @@ -2964,9 +2953,7 @@ boolean P_LoadLevel(boolean skipprecip) // internal game map maplumpname = G_BuildMapName(gamemap); - //lastloadedmaplumpnum = LUMPERROR; lastloadedmaplumpnum = W_CheckNumForName(maplumpname); - if (lastloadedmaplumpnum == INT16_MAX) I_Error("Map %s not found.\n", maplumpname); @@ -2991,7 +2978,7 @@ boolean P_LoadLevel(boolean skipprecip) P_ResetDynamicSlopes(fromnetsave); #endif - P_SpawnMapThings(spawnemblems); + P_SpawnMapThings(!fromnetsave); skyboxmo[0] = skyboxviewpnts[0]; skyboxmo[1] = skyboxcenterpnts[0]; @@ -3002,7 +2989,7 @@ boolean P_LoadLevel(boolean skipprecip) // set up world state P_SpawnSpecials(fromnetsave); - if (loadprecip) // ugly hack for P_NetUnArchiveMisc (and P_LoadNetGame) + if (!fromnetsave) // ugly hack for P_NetUnArchiveMisc (and P_LoadNetGame) P_SpawnPrecipitation(); #ifdef HWRENDER // not win32 only 19990829 by Kin @@ -3068,7 +3055,7 @@ boolean P_LoadLevel(boolean skipprecip) lastmaploaded = gamemap; // HAS to be set after saving!! - if (loadprecip) // uglier hack + if (!fromnetsave) // uglier hack { // to make a newly loaded level start on the second frame. INT32 buf = gametic % BACKUPTICS; for (i = 0; i < MAXPLAYERS; i++) diff --git a/src/p_setup.h b/src/p_setup.h index 0751cf7b9..de791677c 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -97,7 +97,7 @@ void P_SetupLevelSky(INT32 skynum, boolean global); void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); #endif void P_LoadThingsOnly(void); -boolean P_LoadLevel(boolean skipprecip); +boolean P_LoadLevel(boolean fromnetsave); boolean P_AddWadFile(const char *wadfilename); boolean P_RunSOC(const char *socfilename); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); diff --git a/src/p_slopes.c b/src/p_slopes.c index 89d265fa4..f35e7d732 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -553,11 +553,8 @@ pslope_t *P_SlopeById(UINT16 id) } /// Reset slopes and read them from special lines. -void P_ResetDynamicSlopes(const UINT32 fromsave) { +void P_ResetDynamicSlopes(const boolean fromsave) { size_t i; - - boolean spawnthinkers = !(boolean)fromsave; - slopelist = NULL; slopecount = 0; @@ -574,14 +571,14 @@ void P_ResetDynamicSlopes(const UINT32 fromsave) { case 711: case 712: case 713: - line_SpawnViaLine(i, spawnthinkers); + line_SpawnViaLine(i, !fromsave); break; case 704: case 705: case 714: case 715: - line_SpawnViaVertexes(i, spawnthinkers); + line_SpawnViaVertexes(i, !fromsave); break; default: diff --git a/src/p_slopes.h b/src/p_slopes.h index 076fd8796..96764051b 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -23,7 +23,7 @@ extern UINT16 slopecount; void P_LinkSlopeThinkers (void); void P_CalculateSlopeNormal(pslope_t *slope); -void P_ResetDynamicSlopes(const UINT32 fromsave); +void P_ResetDynamicSlopes(const boolean fromsave); // // P_CopySectorSlope diff --git a/src/p_spec.c b/src/p_spec.c index 0b0ba940d..20f1c8278 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6426,7 +6426,7 @@ static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flata * as they'll just be erased by UnArchiveThinkers. * \sa P_SpawnPrecipitation, P_SpawnFriction, P_SpawnPushers, P_SpawnScrollers */ -void P_SpawnSpecials(INT32 fromnetsave) +void P_SpawnSpecials(boolean fromnetsave) { sector_t *sector; size_t i; diff --git a/src/p_spec.h b/src/p_spec.h index 14d3ebb59..630bcb3de 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -35,7 +35,7 @@ void P_SetupLevelFlatAnims(void); // at map load void P_InitSpecials(void); -void P_SpawnSpecials(INT32 fromnetsave); +void P_SpawnSpecials(boolean fromnetsave); // every tic void P_UpdateSpecials(void); From ceca99e3c5bdc0a1dfcb378af70b1f99b0feb02c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 13:58:23 +0100 Subject: [PATCH 206/312] Fix accidental removal of sector_t's spawn_lightlevel initialization --- src/p_setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_setup.c b/src/p_setup.c index 9acc4adb3..ce6027c4e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -664,6 +664,7 @@ static void P_LoadRawSectors(UINT8 *data) ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); ss->lightlevel = SHORT(ms->lightlevel); + ss->spawn_lightlevel = ss->lightlevel; ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); ss->nexttag = ss->firsttag = -1; From 3971067cf3c8c41c53416f9f26df158f6b61d0ac Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 14:03:48 +0100 Subject: [PATCH 207/312] Remove some old #if 0'd code --- src/p_setup.c | 44 -------------------------------------------- 1 file changed, 44 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 2605faa0d..0e298a954 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1719,13 +1719,6 @@ static void P_ReadBlockMapLump(INT16 *wadblockmaplump, size_t count) // -- Monster Iestyn 09/01/18 static boolean P_LoadRawBlockMap(UINT8 *data, size_t count) { -#if 0 - (void)data; - (void)count; - (void)lumpname; - return false; -#else - if (!count || count >= 0x20000) return false; @@ -2085,43 +2078,6 @@ static void P_LoadMapFromFile(void) vres_Free(virt); } -#if 0 -static char *levellumps[] = -{ - "label", // ML_LABEL, A separator, name, MAPxx - "THINGS", // ML_THINGS, Enemies, items.. - "LINEDEFS", // ML_LINEDEFS, Linedefs, from editing - "SIDEDEFS", // ML_SIDEDEFS, Sidedefs, from editing - "VERTEXES", // ML_VERTEXES, Vertices, edited and BSP splits generated - "SEGS", // ML_SEGS, Linesegs, from linedefs split by BSP - "SSECTORS", // ML_SSECTORS, Subsectors, list of linesegs - "NODES", // ML_NODES, BSP nodes - "SECTORS", // ML_SECTORS, Sectors, from editing - "REJECT", // ML_REJECT, LUT, sector-sector visibility -}; - -/** Checks a lump and returns whether it is a valid start-of-level marker. - * - * \param lumpnum Lump number to check. - * \return True if the lump is a valid level marker, false if not. - */ -static inline boolean P_CheckLevel(lumpnum_t lumpnum) -{ - UINT16 file, lump; - size_t i; - - for (i = ML_THINGS; i <= ML_REJECT; i++) - { - file = WADFILENUM(lumpnum); - lump = LUMPNUM(lumpnum+1); - if (file > numwadfiles || lump < LUMPNUM(lumpnum) || lump > wadfiles[file]->numlumps || - memcmp(wadfiles[file]->lumpinfo[lump].name, levellumps[i], 8) != 0) - return false; - } - return true; // all right -} -#endif - /** Sets up a sky texture to use for the level. * The sky texture is used instead of F_SKY1. */ From 559034304310f1bf89c868655d918228b6e5d04d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 14:13:26 +0100 Subject: [PATCH 208/312] Rename P_LoadThingsOnly to P_RespawnThings to make it clearer that it doesn't actually reload the things from the file, it just respawns them. --- src/g_game.c | 2 +- src/p_setup.c | 8 ++------ src/p_setup.h | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index e6a28aa41..7ce68b497 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2965,7 +2965,7 @@ void G_DoReborn(INT32 playernum) } if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD)) { - P_LoadThingsOnly(); + P_RespawnThings(); for (i = 0; i < MAXPLAYERS; i++) { diff --git a/src/p_setup.c b/src/p_setup.c index 0e298a954..ad1ae12ae 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2206,12 +2206,8 @@ static void P_InitLevelSettings(void) CV_SetValue(&cv_analog2, true); } -// -// P_LoadThingsOnly -// -// "Reloads" a level, but only reloads all of the mobjs. -// -void P_LoadThingsOnly(void) +// Respawns all the mapthings and mobjs in the map from the already loaded map data. +void P_RespawnThings(void) { // Search through all the thinkers. thinker_t *think; diff --git a/src/p_setup.h b/src/p_setup.h index de791677c..be3d220d8 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -96,7 +96,7 @@ void P_SetupLevelSky(INT32 skynum, boolean global); #ifdef SCANTHINGS void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); #endif -void P_LoadThingsOnly(void); +void P_RespawnThings(void); boolean P_LoadLevel(boolean fromnetsave); boolean P_AddWadFile(const char *wadfilename); boolean P_RunSOC(const char *socfilename); From b1854b5c96301fc182ce12a53ba1265fcd179372 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 14:50:00 +0100 Subject: [PATCH 209/312] Remove stray #endif --- src/p_setup.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index ad1ae12ae..6abbd9576 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1744,7 +1744,6 @@ static boolean P_LoadRawBlockMap(UINT8 *data, size_t count) polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL); #endif return true; -#endif } // From 21b7507aee1540a15d27a0e68c957e19238b7253 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 16:40:35 +0100 Subject: [PATCH 210/312] Reorganize and partially rename map loading functions --- src/p_setup.c | 1107 +++++++++++++++++++++++++------------------------ 1 file changed, 554 insertions(+), 553 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 6abbd9576..1884b6de3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -373,114 +373,6 @@ UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade) return mapheaderinfo[map-1]->grades[mare].grade[grade-1]; } -// Loads the vertexes for a level. -static inline void P_LoadRawVertexes(UINT8 *data) -{ - mapvertex_t *ml = (mapvertex_t *)data; - vertex_t *li = vertexes; - size_t i; - - // Copy and convert vertex coordinates, internal representation as fixed. - for (i = 0; i < numvertexes; i++, li++, ml++) - { - li->x = SHORT(ml->x)<y = SHORT(ml->y)<v2->x - seg->v1->x)>>1; - INT64 dy = (seg->v2->y - seg->v1->y)>>1; - return FixedHypot(dx, dy)<<1; -} - -#ifdef HWRENDER -/** Computes the length of a seg as a float. - * This is needed for OpenGL. - * - * \param seg Seg to compute length for. - * \return Length as a float. - */ -static inline float P_SegLengthFloat(seg_t *seg) -{ - float dx, dy; - - // make a vector (start at origin) - dx = FIXED_TO_FLOAT(seg->v2->x - seg->v1->x); - dy = FIXED_TO_FLOAT(seg->v2->y - seg->v1->y); - - return (float)hypot(dx, dy); -} -#endif - -// Loads the SEGS resource from a level. -static void P_LoadRawSegs(UINT8 *data) -{ - INT32 linedef, side; - mapseg_t *ml = (mapseg_t*)data; - seg_t *li = segs; - line_t *ldef; - size_t i; - - for (i = 0; i < numsegs; i++, li++, ml++) - { - li->v1 = &vertexes[SHORT(ml->v1)]; - li->v2 = &vertexes[SHORT(ml->v2)]; - - li->length = P_SegLength(li); -#ifdef HWRENDER - if (rendermode == render_opengl) - { - li->flength = P_SegLengthFloat(li); - //Hurdler: 04/12/2000: for now, only used in hardware mode - li->lightmaps = NULL; // list of static lightmap for this seg - } - li->pv1 = li->pv2 = NULL; -#endif - - li->angle = (SHORT(ml->angle))<offset = (SHORT(ml->offset))<linedef); - ldef = &lines[linedef]; - li->linedef = ldef; - li->side = side = SHORT(ml->side); - li->sidedef = &sides[ldef->sidenum[side]]; - li->frontsector = sides[ldef->sidenum[side]].sector; - if (ldef->flags & ML_TWOSIDED) - li->backsector = sides[ldef->sidenum[side^1]].sector; - else - li->backsector = 0; - - li->numlights = 0; - li->rlights = NULL; - } -} - -// Loads the SSECTORS resource from a level. -static inline void P_LoadRawSubsectors(void *data) -{ - mapsubsector_t *ms = (mapsubsector_t*)data; - subsector_t *ss = subsectors; - size_t i; - - for (i = 0; i < numsubsectors; i++, ss++, ms++) - { - ss->sector = NULL; - ss->numlines = SHORT(ms->numsegs); - ss->firstline = SHORT(ms->firstseg); -#ifdef FLOORSPLATS - ss->splats = NULL; -#endif - ss->validcount = 0; - } -} - // // levelflats // @@ -647,107 +539,6 @@ INT32 P_CheckLevelFlat(const char *flatname) return (INT32)i; } -// Sets up the ingame sectors structures. -static void P_LoadRawSectors(UINT8 *data) -{ - mapsector_t *ms = (mapsector_t *)data; - sector_t *ss = sectors; - size_t i; - - // For each counted sector, copy the sector raw data from our cache pointer ms, to the global table pointer ss. - for (i = 0; i < numsectors; i++, ss++, ms++) - { - ss->floorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<floorpic = P_AddLevelFlat(ms->floorpic, foundflats); - ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); - - ss->lightlevel = SHORT(ms->lightlevel); - ss->spawn_lightlevel = ss->lightlevel; - ss->special = SHORT(ms->special); - ss->tag = SHORT(ms->tag); - ss->nexttag = ss->firsttag = -1; - - memset(&ss->soundorg, 0, sizeof(ss->soundorg)); - ss->validcount = 0; - - ss->thinglist = NULL; - ss->touching_thinglist = NULL; - ss->preciplist = NULL; - ss->touching_preciplist = NULL; - - ss->floordata = NULL; - ss->ceilingdata = NULL; - ss->lightingdata = NULL; - - ss->linecount = 0; - ss->lines = NULL; - - ss->heightsec = -1; - ss->camsec = -1; - ss->floorlightsec = -1; - ss->ceilinglightsec = -1; - ss->crumblestate = 0; - ss->ffloors = NULL; - ss->lightlist = NULL; - ss->numlights = 0; - ss->attached = NULL; - ss->attachedsolid = NULL; - ss->numattached = 0; - ss->maxattached = 1; - ss->moved = true; - - ss->extra_colormap = NULL; - ss->spawn_extra_colormap = NULL; - - ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0; - ss->floorpic_angle = ss->ceilingpic_angle = 0; - ss->gravity = NULL; - ss->cullheight = NULL; - ss->verticalflip = false; - ss->flags = 0; - ss->flags |= SF_FLIPSPECIAL_FLOOR; - - ss->floorspeed = 0; - ss->ceilspeed = 0; - -#ifdef HWRENDER // ----- for special tricks with HW renderer ----- - ss->pseudoSector = false; - ss->virtualFloor = false; - ss->virtualCeiling = false; - ss->sectorLines = NULL; - ss->stackList = NULL; - ss->lineoutLength = -1.0l; -#endif // ----- end special tricks ----- - } -} - -// -// P_LoadNodes -// -static void P_LoadRawNodes(UINT8 *data) -{ - UINT8 j, k; - mapnode_t *mn = (mapnode_t*)data; - node_t *no = nodes; - size_t i; - - for (i = 0; i < numnodes; i++, no++, mn++) - { - no->x = SHORT(mn->x)<y = SHORT(mn->y)<dx = SHORT(mn->dx)<dy = SHORT(mn->dy)<children[j] = SHORT(mn->children[j]); - for (k = 0; k < 4; k++) - no->bbox[j][k] = SHORT(mn->bbox[j][k])<x = READINT16(data); - mt->y = READINT16(data); - - mt->angle = READINT16(data); - mt->type = READUINT16(data); - mt->options = READUINT16(data); - mt->extrainfo = (UINT8)(mt->type >> 12); - - mt->type &= 4095; - - if (mt->type == 1705 || (mt->type == 750 && mt->extrainfo)) - mt->z = mt->options; // NiGHTS Hoops use the full flags bits to set the height. - else - mt->z = mt->options >> ZSHIFT; - } -} - static void P_SpawnEmeraldHunt(void) { INT32 emer1, emer2, emer3; @@ -1062,7 +829,100 @@ void P_WriteThings(lumpnum_t lumpnum) CONS_Printf(M_GetText("newthings%d.lmp saved.\n"), gamemap); } -static void P_LoadRawLineDefs(UINT8 *data) +// +// MAP LOADING FUNCTIONS +// + +static void P_LoadVertices(UINT8 *data) +{ + mapvertex_t *ml = (mapvertex_t *)data; + vertex_t *li = vertexes; + size_t i; + + // Copy and convert vertex coordinates, internal representation as fixed. + for (i = 0; i < numvertexes; i++, li++, ml++) + { + li->x = SHORT(ml->x)<y = SHORT(ml->y)<floorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<floorpic = P_AddLevelFlat(ms->floorpic, foundflats); + ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); + + ss->lightlevel = SHORT(ms->lightlevel); + ss->spawn_lightlevel = ss->lightlevel; + ss->special = SHORT(ms->special); + ss->tag = SHORT(ms->tag); + ss->nexttag = ss->firsttag = -1; + + memset(&ss->soundorg, 0, sizeof(ss->soundorg)); + ss->validcount = 0; + + ss->thinglist = NULL; + ss->touching_thinglist = NULL; + ss->preciplist = NULL; + ss->touching_preciplist = NULL; + + ss->floordata = NULL; + ss->ceilingdata = NULL; + ss->lightingdata = NULL; + + ss->linecount = 0; + ss->lines = NULL; + + ss->heightsec = -1; + ss->camsec = -1; + ss->floorlightsec = -1; + ss->ceilinglightsec = -1; + ss->crumblestate = 0; + ss->ffloors = NULL; + ss->lightlist = NULL; + ss->numlights = 0; + ss->attached = NULL; + ss->attachedsolid = NULL; + ss->numattached = 0; + ss->maxattached = 1; + ss->moved = true; + + ss->extra_colormap = NULL; + ss->spawn_extra_colormap = NULL; + + ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0; + ss->floorpic_angle = ss->ceilingpic_angle = 0; + ss->gravity = NULL; + ss->cullheight = NULL; + ss->verticalflip = false; + ss->flags = 0; + ss->flags |= SF_FLIPSPECIAL_FLOOR; + + ss->floorspeed = 0; + ss->ceilspeed = 0; + +#ifdef HWRENDER // ----- for special tricks with HW renderer ----- + ss->pseudoSector = false; + ss->virtualFloor = false; + ss->virtualCeiling = false; + ss->sectorLines = NULL; + ss->stackList = NULL; + ss->lineoutLength = -1.0l; +#endif // ----- end special tricks ----- + } +} + +static void P_LoadLinedefs(UINT8 *data) { maplinedef_t *mld = (maplinedef_t *)data; line_t *ld = lines; @@ -1142,7 +1002,7 @@ static void P_SetupLines(void) if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) { ld->sidenum[j] = 0xffff; - CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has out-of-range sidedef number\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has out-of-range sidedef number\n", sizeu1(numlines-i-1)); } } @@ -1156,14 +1016,14 @@ static void P_SetupLines(void) { ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "Linedef %s missing first sidedef\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s missing first sidedef\n", sizeu1(numlines-i-1)); } if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) { ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1)); } if (ld->sidenum[0] != 0xffff && ld->special) @@ -1173,109 +1033,7 @@ static void P_SetupLines(void) } } -static void P_LoadLineDefs2(void) -{ - size_t i = numlines; - register line_t *ld = lines; - for (;i--;ld++) - { - ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here - ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; - - // Repeat count for midtexture - if ((ld->flags & ML_EFFECT5) && (ld->sidenum[1] != 0xffff) - && !(ld->special >= 300 && ld->special < 500)) // exempt linedef exec specials - { - sides[ld->sidenum[0]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) >> 12); - sides[ld->sidenum[0]].textureoffset = (((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) & 2047) << FRACBITS; - sides[ld->sidenum[1]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[1]].textureoffset >> FRACBITS) >> 12); - sides[ld->sidenum[1]].textureoffset = (((unsigned)sides[ld->sidenum[1]].textureoffset >> FRACBITS) & 2047) << FRACBITS; - } - - // Compile linedef 'text' from both sidedefs 'text' for appropriate specials. - switch(ld->special) - { - case 331: // Trigger linedef executor: Skin - Continuous - case 332: // Trigger linedef executor: Skin - Each time - case 333: // Trigger linedef executor: Skin - Once - case 443: // Calls a named Lua function - if (sides[ld->sidenum[0]].text) - { - size_t len = strlen(sides[ld->sidenum[0]].text)+1; - if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) - len += strlen(sides[ld->sidenum[1]].text); - ld->text = Z_Malloc(len, PU_LEVEL, NULL); - M_Memcpy(ld->text, sides[ld->sidenum[0]].text, strlen(sides[ld->sidenum[0]].text)+1); - if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) - M_Memcpy(ld->text+strlen(ld->text)+1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text)+1); - } - break; - } - } - - // Optimize sidedefs - if (M_CheckParm("-compress")) - { - side_t *newsides; - size_t numnewsides = 0; - size_t z; - - for (i = 0; i < numsides; i++) - { - size_t j, k; - if (sides[i].sector == NULL) - continue; - - for (k = numlines, ld = lines; k--; ld++) - { - if (ld->sidenum[0] == i) - ld->sidenum[0] = (UINT16)numnewsides; - - if (ld->sidenum[1] == i) - ld->sidenum[1] = (UINT16)numnewsides; - } - - for (j = i+1; j < numsides; j++) - { - if (sides[j].sector == NULL) - continue; - - if (!memcmp(&sides[i], &sides[j], sizeof(side_t))) - { - // Find the linedefs that belong to this one - for (k = numlines, ld = lines; k--; ld++) - { - if (ld->sidenum[0] == j) - ld->sidenum[0] = (UINT16)numnewsides; - - if (ld->sidenum[1] == j) - ld->sidenum[1] = (UINT16)numnewsides; - } - sides[j].sector = NULL; // Flag for deletion - } - } - numnewsides++; - } - - // We're loading crap into this block anyhow, so no point in zeroing it out. - newsides = Z_Malloc(numnewsides * sizeof(*newsides), PU_LEVEL, NULL); - - // Copy the sides to their new block of memory. - for (i = 0, z = 0; i < numsides; i++) - { - if (sides[i].sector != NULL) - M_Memcpy(&newsides[z++], &sides[i], sizeof(side_t)); - } - - CONS_Debug(DBG_SETUP, "Old sides is %s, new sides is %s\n", sizeu1(numsides), sizeu1(numnewsides)); - - Z_Free(sides); - sides = newsides; - numsides = numnewsides; - } -} - -static void P_LoadRawSideDefs2(void *data) +static void P_LoadSidedefs(UINT8 *data) { UINT16 i; @@ -1293,7 +1051,7 @@ static void P_LoadRawSideDefs2(void *data) if (sector_num >= numsectors) { - CONS_Debug(DBG_SETUP, "P_LoadRawSideDefs2: sidedef %u has out-of-range sector num %u\n", i, sector_num); + CONS_Debug(DBG_SETUP, "P_LoadSidedefs: sidedef %u has out-of-range sector num %u\n", i, sector_num); sector_num = 0; } sd->sector = sec = §ors[sector_num]; @@ -1434,6 +1192,335 @@ static void P_LoadRawSideDefs2(void *data) } } +static void P_LoadThings(UINT8 *data) +{ + mapthing_t *mt; + size_t i; + + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) + { + mt->x = READINT16(data); + mt->y = READINT16(data); + + mt->angle = READINT16(data); + mt->type = READUINT16(data); + mt->options = READUINT16(data); + mt->extrainfo = (UINT8)(mt->type >> 12); + + mt->type &= 4095; + + if (mt->type == 1705 || (mt->type == 750 && mt->extrainfo)) + mt->z = mt->options; // NiGHTS Hoops use the full flags bits to set the height. + else + mt->z = mt->options >> ZSHIFT; + } +} + +static void P_LoadMapData(const virtres_t *virt) +{ + virtlump_t* virtvertexes = NULL, * virtsectors = NULL, * virtsidedefs = NULL, * virtlinedefs = NULL, * virtthings = NULL; +#ifdef UDMF + virtlump_t* textmap = vres_Find(virt, "TEXTMAP"); + + // Count map data. + if (textmap) + { + nummapthings = 0; + numlines = 0; + numsides = 0; + numvertexes = 0; + numsectors = 0; + + // Count how many entries for each type we got in textmap. + //TextmapCount(vtextmap->data, vtextmap->size); + } + else +#endif + { + virtthings = vres_Find(virt, "THINGS"); + virtvertexes = vres_Find(virt, "VERTEXES"); + virtsectors = vres_Find(virt, "SECTORS"); + virtsidedefs = vres_Find(virt, "SIDEDEFS"); + virtlinedefs = vres_Find(virt, "LINEDEFS"); + + if (!virtthings) + I_Error("THINGS lump not found"); + if (!virtvertexes) + I_Error("VERTEXES lump not found"); + if (!virtsectors) + I_Error("SECTORS lump not found"); + if (!virtsidedefs) + I_Error("SIDEDEFS lump not found"); + if (!virtlinedefs) + I_Error("LINEDEFS lump not found"); + + // Traditional doom map format just assumes the number of elements from the lump sizes. + numvertexes = virtvertexes->size / sizeof (mapvertex_t); + numsectors = virtsectors->size / sizeof (mapsector_t); + numsides = virtsidedefs->size / sizeof (mapsidedef_t); + numlines = virtlinedefs->size / sizeof (maplinedef_t); + nummapthings = virtthings->size / (5 * sizeof (INT16)); + } + + if (numvertexes <= 0) + I_Error("Level has no vertices"); + if (numsectors <= 0) + I_Error("Level has no sectors"); + if (numsides <= 0) + I_Error("Level has no sidedefs"); + if (numlines <= 0) + I_Error("Level has no linedefs"); + + vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); + sectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); + sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); + lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + + // Allocate a big chunk of memory as big as our MAXLEVELFLATS limit. + //Fab : FIXME: allocate for whatever number of flats - 512 different flats per level should be plenty + foundflats = calloc(MAXLEVELFLATS, sizeof (*foundflats)); + if (foundflats == NULL) + I_Error("Ran out of memory while loading sectors\n"); + + numlevelflats = 0; + +#ifdef UDMF + if (textmap) + { + + } + else +#endif + { + // Strict map data + P_LoadVertices(virtvertexes->data); + P_LoadSectors(virtsectors->data); + P_LoadLinedefs(virtlinedefs->data); + P_SetupLines(); + P_LoadSidedefs(virtsidedefs->data); + P_LoadThings(virtthings->data); + } + + R_ClearTextureNumCache(true); + + // set the sky flat num + skyflatnum = P_AddLevelFlat(SKYFLATNAME, foundflats); + + // copy table for global usage + levelflats = M_Memcpy(Z_Calloc(numlevelflats * sizeof (*levelflats), PU_LEVEL, NULL), foundflats, numlevelflats * sizeof (levelflat_t)); + free(foundflats); + + // search for animated flats and set up + P_SetupLevelFlatAnims(); + + // Copy relevant map data for NetArchive purposes. + spawnsectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); + spawnlines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + spawnsides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); + + memcpy(spawnsectors, sectors, numsectors * sizeof (*sectors)); + memcpy(spawnlines, lines, numlines * sizeof (*lines)); + memcpy(spawnsides, sides, numsides * sizeof (*sides)); +} + +static inline void P_LoadSubsectors(UINT8 *data) +{ + mapsubsector_t *ms = (mapsubsector_t*)data; + subsector_t *ss = subsectors; + size_t i; + + for (i = 0; i < numsubsectors; i++, ss++, ms++) + { + ss->sector = NULL; + ss->numlines = SHORT(ms->numsegs); + ss->firstline = SHORT(ms->firstseg); +#ifdef FLOORSPLATS + ss->splats = NULL; +#endif + ss->validcount = 0; + } +} + +static void P_LoadNodes(UINT8 *data) +{ + UINT8 j, k; + mapnode_t *mn = (mapnode_t*)data; + node_t *no = nodes; + size_t i; + + for (i = 0; i < numnodes; i++, no++, mn++) + { + no->x = SHORT(mn->x)<y = SHORT(mn->y)<dx = SHORT(mn->dx)<dy = SHORT(mn->dy)<children[j] = SHORT(mn->children[j]); + for (k = 0; k < 4; k++) + no->bbox[j][k] = SHORT(mn->bbox[j][k])<v2->x - seg->v1->x)>>1; + INT64 dy = (seg->v2->y - seg->v1->y)>>1; + return FixedHypot(dx, dy)<<1; +} + +#ifdef HWRENDER +/** Computes the length of a seg as a float. + * This is needed for OpenGL. + * + * \param seg Seg to compute length for. + * \return Length as a float. + */ +static inline float P_SegLengthFloat(seg_t *seg) +{ + float dx, dy; + + // make a vector (start at origin) + dx = FIXED_TO_FLOAT(seg->v2->x - seg->v1->x); + dy = FIXED_TO_FLOAT(seg->v2->y - seg->v1->y); + + return (float)hypot(dx, dy); +} +#endif + +static void P_LoadSegs(UINT8 *data) +{ + INT32 linedef, side; + mapseg_t *ml = (mapseg_t*)data; + seg_t *li = segs; + line_t *ldef; + size_t i; + + for (i = 0; i < numsegs; i++, li++, ml++) + { + li->v1 = &vertexes[SHORT(ml->v1)]; + li->v2 = &vertexes[SHORT(ml->v2)]; + + li->length = P_SegLength(li); +#ifdef HWRENDER + if (rendermode == render_opengl) + { + li->flength = P_SegLengthFloat(li); + //Hurdler: 04/12/2000: for now, only used in hardware mode + li->lightmaps = NULL; // list of static lightmap for this seg + } + li->pv1 = li->pv2 = NULL; +#endif + + li->angle = (SHORT(ml->angle))<offset = (SHORT(ml->offset))<linedef); + ldef = &lines[linedef]; + li->linedef = ldef; + li->side = side = SHORT(ml->side); + li->sidedef = &sides[ldef->sidenum[side]]; + li->frontsector = sides[ldef->sidenum[side]].sector; + if (ldef->flags & ML_TWOSIDED) + li->backsector = sides[ldef->sidenum[side^1]].sector; + else + li->backsector = 0; + + li->numlights = 0; + li->rlights = NULL; + } +} + +static void P_LoadMapBSP(const virtres_t *virt) +{ + virtlump_t* virtssectors = vres_Find(virt, "SSECTORS"); + virtlump_t* virtsegs = vres_Find(virt, "SEGS"); + virtlump_t* virtnodes = vres_Find(virt, "NODES"); + + numsubsectors = virtssectors->size / sizeof(mapsubsector_t); + numnodes = virtnodes->size / sizeof(mapnode_t); + numsegs = virtsegs->size / sizeof(mapseg_t); + + if (numsubsectors <= 0) + I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); + if (numnodes <= 0) + I_Error("Level has no nodes"); + if (numsegs <= 0) + I_Error("Level has no segs"); + + subsectors = Z_Calloc(numsubsectors * sizeof(*subsectors), PU_LEVEL, NULL); + nodes = Z_Calloc(numnodes * sizeof(*nodes), PU_LEVEL, NULL); + segs = Z_Calloc(numsegs * sizeof(*segs), PU_LEVEL, NULL); + + // Nodes + P_LoadSubsectors(virtssectors->data); + P_LoadNodes(virtnodes->data); + P_LoadSegs(virtsegs->data); +} + +// Split from P_LoadBlockMap for convenience +// -- Monster Iestyn 08/01/18 +static void P_ReadBlockMapLump(INT16 *wadblockmaplump, size_t count) +{ + size_t i; + blockmaplump = Z_Calloc(sizeof (*blockmaplump) * count, PU_LEVEL, NULL); + + // killough 3/1/98: Expand wad blockmap into larger internal one, + // by treating all offsets except -1 as unsigned and zero-extending + // them. This potentially doubles the size of blockmaps allowed, + // because Doom originally considered the offsets as always signed. + + blockmaplump[0] = SHORT(wadblockmaplump[0]); + blockmaplump[1] = SHORT(wadblockmaplump[1]); + blockmaplump[2] = (INT32)(SHORT(wadblockmaplump[2])) & 0xffff; + blockmaplump[3] = (INT32)(SHORT(wadblockmaplump[3])) & 0xffff; + + for (i = 4; i < count; i++) + { + INT16 t = SHORT(wadblockmaplump[i]); // killough 3/1/98 + blockmaplump[i] = t == -1 ? (INT32)-1 : (INT32) t & 0xffff; + } +} + +// This needs to be a separate function +// because making both the WAD and PK3 loading code use +// the same functions is trickier than it looks for blockmap +// -- Monster Iestyn 09/01/18 +static boolean P_LoadBlockMap(UINT8 *data, size_t count) +{ + if (!count || count >= 0x20000) + return false; + + //CONS_Printf("Reading blockmap lump for pk3...\n"); + + // no need to malloc anything, assume the data is uncompressed for now + count /= 2; + P_ReadBlockMapLump((INT16 *)data, count); + + bmaporgx = blockmaplump[0]<= 0x20000) - return false; + virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP"); + virtlump_t* virtreject = vres_Find(virt, "REJECT"); - //CONS_Printf("Reading blockmap lump for pk3...\n"); + // Lookup tables + if (virtreject) + P_LoadReject(virtreject->data, virtreject->size); + else + rejectmatrix = NULL; - // no need to malloc anything, assume the data is uncompressed for now - count /= 2; - P_ReadBlockMapLump((INT16 *)data, count); + if (!(virtblockmap && P_LoadBlockMap(virtblockmap->data, virtblockmap->size))) + P_CreateBlockMap(); +} - bmaporgx = blockmaplump[0]<frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here + ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; - // clear out mobj chains - count = sizeof (*blocklinks)* bmapwidth*bmapheight; - blocklinks = Z_Calloc(count, PU_LEVEL, NULL); - blockmap = blockmaplump+4; + // Repeat count for midtexture + if ((ld->flags & ML_EFFECT5) && (ld->sidenum[1] != 0xffff) + && !(ld->special >= 300 && ld->special < 500)) // exempt linedef exec specials + { + sides[ld->sidenum[0]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) >> 12); + sides[ld->sidenum[0]].textureoffset = (((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) & 2047) << FRACBITS; + sides[ld->sidenum[1]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[1]].textureoffset >> FRACBITS) >> 12); + sides[ld->sidenum[1]].textureoffset = (((unsigned)sides[ld->sidenum[1]].textureoffset >> FRACBITS) & 2047) << FRACBITS; + } -#ifdef POLYOBJECTS - // haleyjd 2/22/06: setup polyobject blockmap - count = sizeof(*polyblocklinks) * bmapwidth * bmapheight; - polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL); -#endif - return true; + // Compile linedef 'text' from both sidedefs 'text' for appropriate specials. + switch(ld->special) + { + case 331: // Trigger linedef executor: Skin - Continuous + case 332: // Trigger linedef executor: Skin - Each time + case 333: // Trigger linedef executor: Skin - Once + case 443: // Calls a named Lua function + if (sides[ld->sidenum[0]].text) + { + size_t len = strlen(sides[ld->sidenum[0]].text)+1; + if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) + len += strlen(sides[ld->sidenum[1]].text); + ld->text = Z_Malloc(len, PU_LEVEL, NULL); + M_Memcpy(ld->text, sides[ld->sidenum[0]].text, strlen(sides[ld->sidenum[0]].text)+1); + if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) + M_Memcpy(ld->text+strlen(ld->text)+1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text)+1); + } + break; + } + } + + // Optimize sidedefs + if (M_CheckParm("-compress")) + { + side_t *newsides; + size_t numnewsides = 0; + size_t z; + + for (i = 0; i < numsides; i++) + { + size_t j, k; + if (sides[i].sector == NULL) + continue; + + for (k = numlines, ld = lines; k--; ld++) + { + if (ld->sidenum[0] == i) + ld->sidenum[0] = (UINT16)numnewsides; + + if (ld->sidenum[1] == i) + ld->sidenum[1] = (UINT16)numnewsides; + } + + for (j = i+1; j < numsides; j++) + { + if (sides[j].sector == NULL) + continue; + + if (!memcmp(&sides[i], &sides[j], sizeof(side_t))) + { + // Find the linedefs that belong to this one + for (k = numlines, ld = lines; k--; ld++) + { + if (ld->sidenum[0] == j) + ld->sidenum[0] = (UINT16)numnewsides; + + if (ld->sidenum[1] == j) + ld->sidenum[1] = (UINT16)numnewsides; + } + sides[j].sector = NULL; // Flag for deletion + } + } + numnewsides++; + } + + // We're loading crap into this block anyhow, so no point in zeroing it out. + newsides = Z_Malloc(numnewsides * sizeof(*newsides), PU_LEVEL, NULL); + + // Copy the sides to their new block of memory. + for (i = 0, z = 0; i < numsides; i++) + { + if (sides[i].sector != NULL) + M_Memcpy(&newsides[z++], &sides[i], sizeof(side_t)); + } + + CONS_Debug(DBG_SETUP, "Old sides is %s, new sides is %s\n", sizeu1(numsides), sizeu1(numnewsides)); + + Z_Free(sides); + sides = newsides; + numsides = numnewsides; + } } // @@ -1842,172 +2005,6 @@ static void P_GroupLines(void) } } -// PK3 version -// -- Monster Iestyn 09/01/18 -static void P_LoadRawReject(UINT8 *data, size_t count) -{ - if (!count) // zero length, someone probably used ZDBSP - { - rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadRawReject: REJECT lump has size 0, will not be loaded\n"); - } - else - { - rejectmatrix = Z_Malloc(count, PU_LEVEL, NULL); // allocate memory for the reject matrix - M_Memcpy(rejectmatrix, data, count); // copy the data into it - } -} - -static void P_LoadMapBSP(const virtres_t* virt) -{ - virtlump_t* virtssectors = vres_Find(virt, "SSECTORS"); - virtlump_t* virtsegs = vres_Find(virt, "SEGS"); - virtlump_t* virtnodes = vres_Find(virt, "NODES"); - - numsubsectors = virtssectors->size / sizeof(mapsubsector_t); - numnodes = virtnodes->size / sizeof(mapnode_t); - numsegs = virtsegs->size / sizeof(mapseg_t); - - if (numsubsectors <= 0) - I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); - if (numnodes <= 0) - I_Error("Level has no nodes"); - if (numsegs <= 0) - I_Error("Level has no segs"); - - subsectors = Z_Calloc(numsubsectors * sizeof(*subsectors), PU_LEVEL, NULL); - nodes = Z_Calloc(numnodes * sizeof(*nodes), PU_LEVEL, NULL); - segs = Z_Calloc(numsegs * sizeof(*segs), PU_LEVEL, NULL); - - // Nodes - P_LoadRawSubsectors(virtssectors->data); - P_LoadRawNodes(virtnodes->data); - P_LoadRawSegs(virtsegs->data); -} - -static void P_LoadMapLUT(const virtres_t* virt) -{ - virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP"); - virtlump_t* virtreject = vres_Find(virt, "REJECT"); - - // Lookup tables - if (virtreject) - P_LoadRawReject(virtreject->data, virtreject->size); - else - rejectmatrix = NULL; - - if (!(virtblockmap && P_LoadRawBlockMap(virtblockmap->data, virtblockmap->size))) - P_CreateBlockMap(); -} - -static void P_LoadMapData(const virtres_t* virt) -{ - virtlump_t* virtvertexes = NULL, * virtsectors = NULL, * virtsidedefs = NULL, * virtlinedefs = NULL, * virtthings = NULL; -#ifdef UDMF - virtlump_t* textmap = vres_Find(virt, "TEXTMAP"); - - // Count map data. - if (textmap) - { - nummapthings = 0; - numlines = 0; - numsides = 0; - numvertexes = 0; - numsectors = 0; - - // Count how many entries for each type we got in textmap. - //TextmapCount(vtextmap->data, vtextmap->size); - } - else -#endif - { - virtthings = vres_Find(virt, "THINGS"); - virtvertexes = vres_Find(virt, "VERTEXES"); - virtsectors = vres_Find(virt, "SECTORS"); - virtsidedefs = vres_Find(virt, "SIDEDEFS"); - virtlinedefs = vres_Find(virt, "LINEDEFS"); - - if (!virtthings) - I_Error("THINGS lump not found"); - if (!virtvertexes) - I_Error("VERTEXES lump not found"); - if (!virtsectors) - I_Error("SECTORS lump not found"); - if (!virtsidedefs) - I_Error("SIDEDEFS lump not found"); - if (!virtlinedefs) - I_Error("LINEDEFS lump not found"); - - // Traditional doom map format just assumes the number of elements from the lump sizes. - numvertexes = virtvertexes->size / sizeof (mapvertex_t); - numsectors = virtsectors->size / sizeof (mapsector_t); - numsides = virtsidedefs->size / sizeof (mapsidedef_t); - numlines = virtlinedefs->size / sizeof (maplinedef_t); - nummapthings = virtthings->size / (5 * sizeof (INT16)); - } - - if (numvertexes <= 0) - I_Error("Level has no vertices"); - if (numsectors <= 0) - I_Error("Level has no sectors"); - if (numsides <= 0) - I_Error("Level has no sidedefs"); - if (numlines <= 0) - I_Error("Level has no linedefs"); - - vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); - sectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); - sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); - lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); - mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); - - // Allocate a big chunk of memory as big as our MAXLEVELFLATS limit. - //Fab : FIXME: allocate for whatever number of flats - 512 different flats per level should be plenty - foundflats = calloc(MAXLEVELFLATS, sizeof (*foundflats)); - if (foundflats == NULL) - I_Error("Ran out of memory while loading sectors\n"); - - numlevelflats = 0; - -#ifdef UDMF - if (textmap) - { - - } - else -#endif - { - // Strict map data - P_LoadRawVertexes(virtvertexes->data); - P_LoadRawSectors(virtsectors->data); - P_LoadRawLineDefs(virtlinedefs->data); - P_SetupLines(); - P_LoadRawSideDefs2(virtsidedefs->data); - P_PrepareRawThings(virtthings->data); - } - - R_ClearTextureNumCache(true); - - // set the sky flat num - skyflatnum = P_AddLevelFlat(SKYFLATNAME, foundflats); - - // copy table for global usage - levelflats = M_Memcpy(Z_Calloc(numlevelflats * sizeof (*levelflats), PU_LEVEL, NULL), foundflats, numlevelflats * sizeof (levelflat_t)); - free(foundflats); - - // search for animated flats and set up - P_SetupLevelFlatAnims(); - - // Copy relevant map data for NetArchive purposes. - spawnsectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); - spawnlines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); - spawnsides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); - - memcpy(spawnsectors, sectors, numsectors * sizeof (*sectors)); - memcpy(spawnlines, lines, numlines * sizeof (*lines)); - memcpy(spawnsides, sides, numsides * sizeof (*sides)); -} - /** Compute MD5 message digest for bytes read from memory source * * The resulting message digest number will be written into the 16 bytes @@ -2017,7 +2014,7 @@ static void P_LoadMapData(const virtres_t* virt) * \param resblock resulting MD5 checksum * \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found */ -static INT32 P_MakeBufferMD5(const char* buffer, size_t len, void* resblock) +static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock) { #ifdef NOMD5 (void)buffer; @@ -2034,7 +2031,7 @@ static INT32 P_MakeBufferMD5(const char* buffer, size_t len, void* resblock) #endif } -static void P_MakeMapMD5(virtres_t* virt, void* dest) +static void P_MakeMapMD5(virtres_t *virt, void *dest) { unsigned char linemd5[16]; unsigned char sectormd5[16]; @@ -2077,6 +2074,10 @@ static void P_LoadMapFromFile(void) vres_Free(virt); } +// +// LEVEL INITIALIZATION FUNCTIONS +// + /** Sets up a sky texture to use for the level. * The sky texture is used instead of F_SKY1. */ From 86d1fb73f4336ecaa691d8fa09d496499571479d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 16:49:56 +0100 Subject: [PATCH 211/312] Split P_LoadLineDefs2 into P_ProcessLinedefsWithSidedefs and P_CompressSidedefs --- src/p_setup.c | 104 ++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 50 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 1884b6de3..b581e16d3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1807,7 +1807,7 @@ static void P_LoadMapLUT(const virtres_t *virt) P_CreateBlockMap(); } -static void P_LoadLineDefs2(void) +static void P_ProcessLinedefsWithSidedefs(void) { size_t i = numlines; register line_t *ld = lines; @@ -1846,67 +1846,69 @@ static void P_LoadLineDefs2(void) break; } } +} - // Optimize sidedefs - if (M_CheckParm("-compress")) +static void P_CompressSidedefs(void) +{ + side_t *newsides; + size_t numnewsides = 0; + size_t z; + size_t i; + + for (i = 0; i < numsides; i++) { - side_t *newsides; - size_t numnewsides = 0; - size_t z; + size_t j, k; + line_t *ld; - for (i = 0; i < numsides; i++) + if (!sides[i].sector) + continue; + + for (k = numlines, ld = lines; k--; ld++) { - size_t j, k; - if (sides[i].sector == NULL) + if (ld->sidenum[0] == i) + ld->sidenum[0] = (UINT16)numnewsides; + + if (ld->sidenum[1] == i) + ld->sidenum[1] = (UINT16)numnewsides; + } + + for (j = i + 1; j < numsides; j++) + { + if (!sides[j].sector) continue; - for (k = numlines, ld = lines; k--; ld++) + if (!memcmp(&sides[i], &sides[j], sizeof(side_t))) { - if (ld->sidenum[0] == i) - ld->sidenum[0] = (UINT16)numnewsides; - - if (ld->sidenum[1] == i) - ld->sidenum[1] = (UINT16)numnewsides; - } - - for (j = i+1; j < numsides; j++) - { - if (sides[j].sector == NULL) - continue; - - if (!memcmp(&sides[i], &sides[j], sizeof(side_t))) + // Find the linedefs that belong to this one + for (k = numlines, ld = lines; k--; ld++) { - // Find the linedefs that belong to this one - for (k = numlines, ld = lines; k--; ld++) - { - if (ld->sidenum[0] == j) - ld->sidenum[0] = (UINT16)numnewsides; + if (ld->sidenum[0] == j) + ld->sidenum[0] = (UINT16)numnewsides; - if (ld->sidenum[1] == j) - ld->sidenum[1] = (UINT16)numnewsides; - } - sides[j].sector = NULL; // Flag for deletion + if (ld->sidenum[1] == j) + ld->sidenum[1] = (UINT16)numnewsides; } + sides[j].sector = NULL; // Flag for deletion } - numnewsides++; } - - // We're loading crap into this block anyhow, so no point in zeroing it out. - newsides = Z_Malloc(numnewsides * sizeof(*newsides), PU_LEVEL, NULL); - - // Copy the sides to their new block of memory. - for (i = 0, z = 0; i < numsides; i++) - { - if (sides[i].sector != NULL) - M_Memcpy(&newsides[z++], &sides[i], sizeof(side_t)); - } - - CONS_Debug(DBG_SETUP, "Old sides is %s, new sides is %s\n", sizeu1(numsides), sizeu1(numnewsides)); - - Z_Free(sides); - sides = newsides; - numsides = numnewsides; + numnewsides++; } + + // We're loading crap into this block anyhow, so no point in zeroing it out. + newsides = Z_Malloc(numnewsides*sizeof(*newsides), PU_LEVEL, NULL); + + // Copy the sides to their new block of memory. + for (i = 0, z = 0; i < numsides; i++) + { + if (sides[i].sector) + M_Memcpy(&newsides[z++], &sides[i], sizeof(side_t)); + } + + CONS_Debug(DBG_SETUP, "P_CompressSidedefs: Old sides is %s, new sides is %s\n", sizeu1(numsides), sizeu1(numnewsides)); + + Z_Free(sides); + sides = newsides; + numsides = numnewsides; } // @@ -2066,7 +2068,9 @@ static void P_LoadMapFromFile(void) P_LoadMapBSP(virt); P_LoadMapLUT(virt); - P_LoadLineDefs2(); + P_ProcessLinedefsWithSidedefs(); + if (M_CheckParm("-compress")) + P_CompressSidedefs(); P_GroupLines(); P_MakeMapMD5(virt, &mapmd5); From 85de3614cb71c6f9fdab4fbab3d7e38a4b08e3bd Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 16:58:48 +0100 Subject: [PATCH 212/312] Standardize P_LoadVertices and P_LoadSidedefs --- src/p_setup.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index b581e16d3..a3d186ba6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -835,15 +835,15 @@ void P_WriteThings(lumpnum_t lumpnum) static void P_LoadVertices(UINT8 *data) { - mapvertex_t *ml = (mapvertex_t *)data; - vertex_t *li = vertexes; + mapvertex_t *mv = (mapvertex_t *)data; + vertex_t *v = vertexes; size_t i; // Copy and convert vertex coordinates, internal representation as fixed. - for (i = 0; i < numvertexes; i++, li++, ml++) + for (i = 0; i < numvertexes; i++, v++, mv++) { - li->x = SHORT(ml->x)<y = SHORT(ml->y)<x = SHORT(mv->x)<y = SHORT(mv->y)<textureoffset = SHORT(msd->textureoffset)<rowoffset = SHORT(msd->rowoffset)<sector); - - if (sector_num >= numsectors) - { - CONS_Debug(DBG_SETUP, "P_LoadSidedefs: sidedef %u has out-of-range sector num %u\n", i, sector_num); - sector_num = 0; - } - sd->sector = sec = §ors[sector_num]; + // cph 2006/09/30 - catch out-of-range sector numbers; use sector 0 instead + sector_num = SHORT(msd->sector); + if (sector_num >= numsectors) + { + CONS_Debug(DBG_SETUP, "P_LoadSidedefs: sidedef %u has out-of-range sector num %u\n", i, sector_num); + sector_num = 0; } - - sd->sector = sec = §ors[SHORT(msd->sector)]; + sd->sector = §ors[sector_num]; sd->colormap_data = NULL; - // Colormaps! + // Special info stored in texture fields! switch (sd->special) { - case 63: // variable colormap via 242 linedef + case 63: // Fake floor/ceiling planes case 606: //SoM: 4/4/2000: Just colormap transfer case 447: // Change colormap of tagged sectors! -- Monster Iestyn 14/06/18 case 455: // Fade colormaps! mazmazz 9/12/2018 (:flag_us:) From 1ca25224c26581b94c1b1f4562de5627b2bcde08 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 17:05:04 +0100 Subject: [PATCH 213/312] Fix P_SetupLines printing the wrong line number --- src/p_setup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index a3d186ba6..4cb20d453 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1002,7 +1002,7 @@ static void P_SetupLines(void) if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) { ld->sidenum[j] = 0xffff; - CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has out-of-range sidedef number\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has out-of-range sidedef number\n", sizeu1(i)); } } @@ -1016,14 +1016,14 @@ static void P_SetupLines(void) { ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s missing first sidedef\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s missing first sidedef\n", sizeu1(i)); } if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) { ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(i)); } if (ld->sidenum[0] != 0xffff && ld->special) From 54fe91b1cc0e48737d74f6183f8d3a1ddaa03f36 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 17:21:31 +0100 Subject: [PATCH 214/312] Refactor P_SetupLines into P_InitializeLinedef --- src/p_setup.c | 160 +++++++++++++++++++++----------------------------- 1 file changed, 68 insertions(+), 92 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 4cb20d453..05386a96b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -922,6 +922,73 @@ static void P_LoadSectors(UINT8 *data) } } +static void P_InitializeLinedef(line_t *ld) +{ + vertex_t *v1 = ld->v1; + vertex_t *v2 = ld->v2; + UINT8 j; + + ld->dx = v2->x - v1->x; + ld->dy = v2->y - v1->y; + + ld->bbox[BOXLEFT] = min(v1->x, v2->x); + ld->bbox[BOXRIGHT] = max(v1->x, v2->x); + ld->bbox[BOXBOTTOM] = min(v1->y, v2->y); + ld->bbox[BOXTOP] = max(v1->y, v2->y); + + if (!ld->dx) + ld->slopetype = ST_VERTICAL; + else if (!ld->dy) + ld->slopetype = ST_HORIZONTAL; + else if ((ld->dy > 0) == (ld->dx > 0)) + ld->slopetype = ST_POSITIVE; + else + ld->slopetype = ST_NEGATIVE; + + ld->frontsector = ld->backsector = NULL; + + ld->validcount = 0; +#ifdef WALLSPLATS + ld->splats = NULL; +#endif + ld->firsttag = ld->nexttag = -1; +#ifdef POLYOBJECTS + ld->polyobj = NULL; +#endif + + ld->text = NULL; + ld->callcount = 0; + + // cph 2006/09/30 - fix sidedef errors right away. + // cph 2002/07/20 - these errors are fatal if not fixed, so apply them + for (j = 0; j < 2; j++) + if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) + { + ld->sidenum[j] = 0xffff; + CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has out-of-range sidedef number\n", sizeu1((size_t)(ld - lines))); + } + + // killough 11/98: fix common wad errors (missing sidedefs): + if (ld->sidenum[0] == 0xffff) + { + ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side + // cph - print a warning about the bug + CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s missing first sidedef\n", sizeu1((size_t)(ld - lines))); + } + + if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) + { + ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side + // cph - print a warning about the bug + CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1((size_t)(ld - lines))); + } + + if (ld->sidenum[0] != 0xffff && ld->special) + sides[ld->sidenum[0]].special = ld->special; + if (ld->sidenum[1] != 0xffff && ld->special) + sides[ld->sidenum[1]].special = ld->special; +} + static void P_LoadLinedefs(UINT8 *data) { maplinedef_t *mld = (maplinedef_t *)data; @@ -938,98 +1005,8 @@ static void P_LoadLinedefs(UINT8 *data) ld->sidenum[0] = SHORT(mld->sidenum[0]); ld->sidenum[1] = SHORT(mld->sidenum[1]); - } -} -static void P_SetupLines(void) -{ - line_t *ld = lines; - size_t i; - - for (i = 0; i < numlines; i++, ld++) - { - vertex_t *v1 = ld->v1; - vertex_t *v2 = ld->v2; - -#ifdef WALLSPLATS - ld->splats = NULL; -#endif - -#ifdef POLYOBJECTS - ld->polyobj = NULL; -#endif - - ld->dx = v2->x - v1->x; - ld->dy = v2->y - v1->y; - - if (!ld->dx) - ld->slopetype = ST_VERTICAL; - else if (!ld->dy) - ld->slopetype = ST_HORIZONTAL; - else if ((ld->dy > 0) == (ld->dx > 0)) - ld->slopetype = ST_POSITIVE; - else - ld->slopetype = ST_NEGATIVE; - - if (v1->x < v2->x) - { - ld->bbox[BOXLEFT] = v1->x; - ld->bbox[BOXRIGHT] = v2->x; - } - else - { - ld->bbox[BOXLEFT] = v2->x; - ld->bbox[BOXRIGHT] = v1->x; - } - - if (v1->y < v2->y) - { - ld->bbox[BOXBOTTOM] = v1->y; - ld->bbox[BOXTOP] = v2->y; - } - else - { - ld->bbox[BOXBOTTOM] = v2->y; - ld->bbox[BOXTOP] = v1->y; - } - - { - // cph 2006/09/30 - fix sidedef errors right away. - // cph 2002/07/20 - these errors are fatal if not fixed, so apply them - UINT8 j; - - for (j=0; j < 2; j++) - if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) - { - ld->sidenum[j] = 0xffff; - CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has out-of-range sidedef number\n", sizeu1(i)); - } - } - - ld->frontsector = ld->backsector = NULL; - ld->validcount = 0; - ld->firsttag = ld->nexttag = -1; - ld->callcount = 0; - - // killough 11/98: fix common wad errors (missing sidedefs): - if (ld->sidenum[0] == 0xffff) - { - ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side - // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s missing first sidedef\n", sizeu1(i)); - } - - if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) - { - ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side - // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(i)); - } - - if (ld->sidenum[0] != 0xffff && ld->special) - sides[ld->sidenum[0]].special = ld->special; - if (ld->sidenum[1] != 0xffff && ld->special) - sides[ld->sidenum[1]].special = ld->special; + P_InitializeLinedef(ld); } } @@ -1293,7 +1270,6 @@ static void P_LoadMapData(const virtres_t *virt) P_LoadVertices(virtvertexes->data); P_LoadSectors(virtsectors->data); P_LoadLinedefs(virtlinedefs->data); - P_SetupLines(); P_LoadSidedefs(virtsidedefs->data); P_LoadThings(virtthings->data); } From d38ee51d494142cd88e1eb99f14bf79714d9cebf Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 17:29:58 +0100 Subject: [PATCH 215/312] Separate setting of sector field defaults into P_InitializeSector --- src/p_setup.c | 131 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 53 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 05386a96b..6c126b1e8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -844,9 +844,86 @@ static void P_LoadVertices(UINT8 *data) { v->x = SHORT(mv->x)<y = SHORT(mv->y)<z = 0; } } +static void P_InitializeSector(sector_t *ss) +{ + ss->nexttag = ss->firsttag = -1; + + memset(&ss->soundorg, 0, sizeof(ss->soundorg)); + + ss->validcount = 0; + + ss->thinglist = NULL; + + ss->floordata = NULL; + ss->ceilingdata = NULL; + ss->lightingdata = NULL; + ss->fadecolormapdata = NULL; + + ss->floor_xoffs = ss->floor_yoffs = 0; + ss->ceiling_xoffs = ss->ceiling_yoffs = 0; + + ss->floorpic_angle = ss->ceilingpic_angle = 0; + + ss->heightsec = -1; + ss->camsec = -1; + + ss->floorlightsec = ss->ceilinglightsec = -1; + ss->crumblestate = 0; + + ss->touching_thinglist = NULL; + + ss->linecount = 0; + ss->lines = NULL; + ss->tagline = NULL; + + ss->ffloors = NULL; + ss->attached = NULL; + ss->attachedsolid = NULL; + ss->numattached = 0; + ss->maxattached = 1; + ss->lightlist = NULL; + ss->numlights = 0; + ss->moved = true; + + ss->extra_colormap = NULL; + +#ifdef HWRENDER // ----- for special tricks with HW renderer ----- + ss->pseudoSector = false; + ss->virtualFloor = false; + ss->virtualFloorheight = 0; + ss->virtualCeiling = false; + ss->virtualCeilingheight = 0; + ss->sectorLines = NULL; + ss->stackList = NULL; + ss->lineoutLength = -1.0l; +#endif // ----- end special tricks ----- + + ss->gravity = NULL; + ss->verticalflip = false; + ss->flags = SF_FLIPSPECIAL_FLOOR; + + ss->cullheight = NULL; + + ss->floorspeed = ss->ceilspeed = 0; + + ss->preciplist = NULL; + ss->touching_preciplist = NULL; + +#ifdef ESLOPE + ss->f_slope = NULL; + ss->c_slope = NULL; + ss->hasslope = false; +#endif + + ss->spawn_lightlevel = ss->lightlevel; + + ss->spawn_extra_colormap = NULL; +} + static void P_LoadSectors(UINT8 *data) { mapsector_t *ms = (mapsector_t *)data; @@ -863,62 +940,10 @@ static void P_LoadSectors(UINT8 *data) ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); ss->lightlevel = SHORT(ms->lightlevel); - ss->spawn_lightlevel = ss->lightlevel; ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); - ss->nexttag = ss->firsttag = -1; - memset(&ss->soundorg, 0, sizeof(ss->soundorg)); - ss->validcount = 0; - - ss->thinglist = NULL; - ss->touching_thinglist = NULL; - ss->preciplist = NULL; - ss->touching_preciplist = NULL; - - ss->floordata = NULL; - ss->ceilingdata = NULL; - ss->lightingdata = NULL; - - ss->linecount = 0; - ss->lines = NULL; - - ss->heightsec = -1; - ss->camsec = -1; - ss->floorlightsec = -1; - ss->ceilinglightsec = -1; - ss->crumblestate = 0; - ss->ffloors = NULL; - ss->lightlist = NULL; - ss->numlights = 0; - ss->attached = NULL; - ss->attachedsolid = NULL; - ss->numattached = 0; - ss->maxattached = 1; - ss->moved = true; - - ss->extra_colormap = NULL; - ss->spawn_extra_colormap = NULL; - - ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0; - ss->floorpic_angle = ss->ceilingpic_angle = 0; - ss->gravity = NULL; - ss->cullheight = NULL; - ss->verticalflip = false; - ss->flags = 0; - ss->flags |= SF_FLIPSPECIAL_FLOOR; - - ss->floorspeed = 0; - ss->ceilspeed = 0; - -#ifdef HWRENDER // ----- for special tricks with HW renderer ----- - ss->pseudoSector = false; - ss->virtualFloor = false; - ss->virtualCeiling = false; - ss->sectorLines = NULL; - ss->stackList = NULL; - ss->lineoutLength = -1.0l; -#endif // ----- end special tricks ----- + P_InitializeSector(ss); } } From 7e5b87ce42b8ca45b1a5dc4835a3dc30b92743e8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 17:37:32 +0100 Subject: [PATCH 216/312] Fix debug prints --- src/p_setup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 6c126b1e8..ed22a56a8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -990,7 +990,7 @@ static void P_InitializeLinedef(line_t *ld) if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) { ld->sidenum[j] = 0xffff; - CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has out-of-range sidedef number\n", sizeu1((size_t)(ld - lines))); + CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s has out-of-range sidedef number\n", sizeu1((size_t)(ld - lines))); } // killough 11/98: fix common wad errors (missing sidedefs): @@ -998,14 +998,14 @@ static void P_InitializeLinedef(line_t *ld) { ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s missing first sidedef\n", sizeu1((size_t)(ld - lines))); + CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s missing first sidedef\n", sizeu1((size_t)(ld - lines))); } if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) { ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_SetupLines: Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1((size_t)(ld - lines))); + CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1((size_t)(ld - lines))); } if (ld->sidenum[0] != 0xffff && ld->special) @@ -1052,7 +1052,7 @@ static void P_LoadSidedefs(UINT8 *data) sector_num = SHORT(msd->sector); if (sector_num >= numsectors) { - CONS_Debug(DBG_SETUP, "P_LoadSidedefs: sidedef %u has out-of-range sector num %u\n", i, sector_num); + CONS_Debug(DBG_SETUP, "P_LoadSidedefs: sidedef %s has out-of-range sector num %u\n", sizeu1(i), sector_num); sector_num = 0; } sd->sector = §ors[sector_num]; From bd7765227eebc29c03c9218bb4832c5af02d07b7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 28 Dec 2019 17:40:08 +0100 Subject: [PATCH 217/312] Rename P_GroupLines to the more apt P_LinkMapData --- src/p_setup.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index ed22a56a8..8d92c3e87 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1909,11 +1909,11 @@ static void P_CompressSidedefs(void) } // -// P_GroupLines +// P_LinkMapData // Builds sector line lists and subsector sector numbers. // Finds block bounding boxes for sectors. // -static void P_GroupLines(void) +static void P_LinkMapData(void) { size_t i, j; line_t *li; @@ -1927,20 +1927,20 @@ static void P_GroupLines(void) for (i = 0; i < numsubsectors; i++, ss++) { if (ss->firstline >= numsegs) - CorruptMapError(va("P_GroupLines: ss->firstline invalid " + CorruptMapError(va("P_LinkMapData: ss->firstline invalid " "(subsector %s, firstline refers to %d of %s)", sizeu1(i), ss->firstline, sizeu2(numsegs))); seg = &segs[ss->firstline]; sidei = (size_t)(seg->sidedef - sides); if (!seg->sidedef) - CorruptMapError(va("P_GroupLines: seg->sidedef is NULL " + CorruptMapError(va("P_LinkMapData: seg->sidedef is NULL " "(subsector %s, firstline is %d)", sizeu1(i), ss->firstline)); if (seg->sidedef - sides < 0 || seg->sidedef - sides > (UINT16)numsides) - CorruptMapError(va("P_GroupLines: seg->sidedef refers to sidedef %s of %s " + CorruptMapError(va("P_LinkMapData: seg->sidedef refers to sidedef %s of %s " "(subsector %s, firstline is %d)", sizeu1(sidei), sizeu2(numsides), sizeu3(i), ss->firstline)); if (!seg->sidedef->sector) - CorruptMapError(va("P_GroupLines: seg->sidedef->sector is NULL " + CorruptMapError(va("P_LinkMapData: seg->sidedef->sector is NULL " "(subsector %s, firstline is %d, sidedef is %s)", sizeu1(i), ss->firstline, sizeu1(sidei))); ss->sector = seg->sidedef->sector; @@ -1961,7 +1961,7 @@ static void P_GroupLines(void) if (sector->linecount == 0) // no lines found? { sector->lines = NULL; - CONS_Debug(DBG_SETUP, "P_GroupLines: sector %s has no lines\n", sizeu1(i)); + CONS_Debug(DBG_SETUP, "P_LinkMapData: sector %s has no lines\n", sizeu1(i)); } else { @@ -2068,7 +2068,7 @@ static void P_LoadMapFromFile(void) P_ProcessLinedefsWithSidedefs(); if (M_CheckParm("-compress")) P_CompressSidedefs(); - P_GroupLines(); + P_LinkMapData(); P_MakeMapMD5(virt, &mapmd5); From 5ed1dc5410158fc3086797d7dada645c7c1de4e5 Mon Sep 17 00:00:00 2001 From: lachwright Date: Sun, 29 Dec 2019 03:01:09 +0800 Subject: [PATCH 218/312] Remove MF_NOTHINK from join-breaking referenced objects --- src/info.c | 8 ++++---- src/p_enemy.c | 2 +- src/p_mobj.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/info.c b/src/info.c index dd808349e..30f3e96d0 100644 --- a/src/info.c +++ b/src/info.c @@ -4492,7 +4492,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags S_NULL // raisestate }, @@ -6273,7 +6273,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOTHINK, // flags + MF_NOGRAVITY|MF_NOBLOCKMAP|MF_SCENERY, // flags S_NULL // raisestate }, @@ -11992,7 +11992,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags S_NULL // raisestate }, @@ -12019,7 +12019,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags S_NULL // raisestate }, diff --git a/src/p_enemy.c b/src/p_enemy.c index f15ad86ae..31c1f76c7 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2261,7 +2261,7 @@ void A_CrushclawLaunch(mobj_t *actor) while (chain) { P_TeleportMove(chain, actor->target->x + idx, actor->target->y + idy, actor->target->z + idz); - chain->watertop = chain->z; + chain->movefactor = chain->z; idx += dx; idy += dy; idz += dz; diff --git a/src/p_mobj.c b/src/p_mobj.c index 75bc174a5..8880e5827 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9434,7 +9434,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) SINT8 sign = ((mobj->tics & 1) ? mobj->tics : -(SINT8)(mobj->tics)); while (chain) { - chain->z = chain->watertop + sign*mobj->scale; + chain->z = chain->movefactor + sign*mobj->scale; sign = -sign; chain = chain->target; } From 4b604328d56af04201c1e3edfef9147705bf041c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 28 Dec 2019 19:47:03 -0300 Subject: [PATCH 219/312] Rename GTR_HIDETIME to GTR_STARTCOUNTDOWN. --- src/dehacked.c | 2 +- src/doomstat.h | 2 +- src/g_game.c | 4 ++-- src/st_stuff.c | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 939e8c8cf..5023f55ee 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8909,7 +8909,7 @@ static const char *const GAMETYPERULE_LIST[] = { "TAG", "POINTLIMIT", "TIMELIMIT", - "HIDETIME", + "STARTCOUNTDOWN", "HIDEFROZEN", "BLINDFOLDED", "FIRSTPERSON", diff --git a/src/doomstat.h b/src/doomstat.h index 5dc3a6eb9..faedf48d5 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -404,7 +404,7 @@ enum GameTypeRules GTR_TAG = 1<<7, // Tag and Hide and Seek GTR_POINTLIMIT = 1<<8, // Ringslinger point limit GTR_TIMELIMIT = 1<<9, // Ringslinger time limit - GTR_HIDETIME = 1<<10, // Hide time (Tag and Hide and Seek) + GTR_STARTCOUNTDOWN = 1<<10, // Hide time countdown (Tag and Hide and Seek) GTR_HIDEFROZEN = 1<<11, // Frozen after hide time (Hide and Seek, but not Tag) GTR_BLINDFOLDED = 1<<12, // Blindfolded view (Tag and Hide and Seek) GTR_FIRSTPERSON = 1<<13, // First person camera diff --git a/src/g_game.c b/src/g_game.c index 2d9f2663e..4adc0d604 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3205,9 +3205,9 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, // Tag - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, // Hide and Seek - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, // CTF GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, diff --git a/src/st_stuff.c b/src/st_stuff.c index 35dd861c5..960953b1b 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -694,7 +694,7 @@ static void ST_drawTime(void) else { // Counting down the hidetime? - if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime <= (hidetime*TICRATE))) + if ((gametyperules & GTR_STARTCOUNTDOWN) && (stplyr->realtime <= (hidetime*TICRATE))) { tics = (hidetime*TICRATE - stplyr->realtime); if (tics < 3*TICRATE) @@ -705,7 +705,7 @@ static void ST_drawTime(void) else { // Hidetime finish! - if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime < ((hidetime+1)*TICRATE))) + if ((gametyperules & GTR_STARTCOUNTDOWN) && (stplyr->realtime < ((hidetime+1)*TICRATE))) ST_drawRaceNum(hidetime*TICRATE - stplyr->realtime); // Time limit? @@ -723,7 +723,7 @@ static void ST_drawTime(void) downwards = true; } // Post-hidetime normal. - else if (gametyperules & GTR_HIDETIME) + else if (gametyperules & GTR_STARTCOUNTDOWN) tics = stplyr->realtime - hidetime*TICRATE; // "Shadow! What are you doing? Hurry and get back here // right now before the island blows up with you on it!" From 45af6d889906401067abe72fc73ae338934995ab Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 28 Dec 2019 19:49:34 -0300 Subject: [PATCH 220/312] Rename GTR_MATCHEMERALDS to GTR_POWERSTONES. --- src/dehacked.c | 2 +- src/doomstat.h | 2 +- src/g_game.c | 4 ++-- src/p_inter.c | 2 +- src/p_mobj.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 5023f55ee..3c7fe25aa 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8913,7 +8913,7 @@ static const char *const GAMETYPERULE_LIST[] = { "HIDEFROZEN", "BLINDFOLDED", "FIRSTPERSON", - "MATCHEMERALDS", + "POWERSTONES", "TEAMFLAGS", "PITYSHIELD", "DEATHPENALTY", diff --git a/src/doomstat.h b/src/doomstat.h index faedf48d5..8046b5ed9 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -408,7 +408,7 @@ enum GameTypeRules GTR_HIDEFROZEN = 1<<11, // Frozen after hide time (Hide and Seek, but not Tag) GTR_BLINDFOLDED = 1<<12, // Blindfolded view (Tag and Hide and Seek) GTR_FIRSTPERSON = 1<<13, // First person camera - GTR_MATCHEMERALDS = 1<<14, // Ringslinger emeralds (Match and CTF) + GTR_POWERSTONES = 1<<14, // Power stones (Match and CTF) GTR_TEAMFLAGS = 1<<15, // Gametype has team flags (CTF) GTR_PITYSHIELD = 1<<16, // Award pity shield GTR_DEATHPENALTY = 1<<17, // Death score penalty diff --git a/src/g_game.c b/src/g_game.c index 4adc0d604..c8e185f56 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3200,7 +3200,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = GTR_RACE|GTR_SPAWNENEMIES|GTR_SPAWNINVUL|GTR_ALLOWEXIT, // Match - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD|GTR_DEATHPENALTY, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD|GTR_DEATHPENALTY, // Team Match GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, @@ -3210,7 +3210,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, // CTF - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, }; // diff --git a/src/p_inter.c b/src/p_inter.c index 87b0c0a43..2bbfafdb7 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3205,7 +3205,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) { if ((gametyperules & GTR_RINGSLINGER) && !(gametyperules & GTR_TAG)) P_PlayerRingBurst(player, player->rings); - if (gametyperules & GTR_MATCHEMERALDS) + if (gametyperules & GTR_POWERSTONES) P_PlayerEmeraldBurst(player, false); } diff --git a/src/p_mobj.c b/src/p_mobj.c index 75bc174a5..b6ec5df83 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11893,7 +11893,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) if (!cv_powerstones.value) return false; - if (!(gametyperules & GTR_MATCHEMERALDS)) + if (!(gametyperules & GTR_POWERSTONES)) return false; runemeraldmanager = true; From 093a1baf1d134ddac3fec5724552dc75f9390cb1 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 28 Dec 2019 19:50:14 -0300 Subject: [PATCH 221/312] Remove debugging stuff. --- src/lua_script.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lua_script.c b/src/lua_script.c index 18d9a87c2..eb1afaf09 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -299,9 +299,7 @@ int LUA_PushGlobals(lua_State *L, const char *word) // See the above. int LUA_CheckGlobals(lua_State *L, const char *word) { - if (fastcmp(word, "gametyperules")) - gametyperules = (UINT32)luaL_checkinteger(L, 2); - else if (fastcmp(word, "redscore")) + if (fastcmp(word, "redscore")) redscore = (UINT32)luaL_checkinteger(L, 2); else if (fastcmp(word, "bluescore")) bluescore = (UINT32)luaL_checkinteger(L, 2); From 7a00b3a331d86a06c6a27999999623c1308bc088 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 28 Dec 2019 19:56:18 -0300 Subject: [PATCH 222/312] Add GTR_FRIENDLY. --- src/dehacked.c | 1 + src/doomstat.h | 49 +++++++++++++++++++++++++------------------------ src/g_game.c | 12 +++--------- 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 3c7fe25aa..799428455 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8905,6 +8905,7 @@ static const char *const GAMETYPERULE_LIST[] = { "FRIENDLYFIRE", "LIVES", "TEAMS", + "FRIENDLY", "RACE", "TAG", "POINTLIMIT", diff --git a/src/doomstat.h b/src/doomstat.h index 8046b5ed9..42c05ba63 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -400,30 +400,31 @@ enum GameTypeRules GTR_FRIENDLYFIRE = 1<<3, // Always allow friendly fire GTR_LIVES = 1<<4, // Co-op and Competition GTR_TEAMS = 1<<5, // Team Match, CTF - GTR_RACE = 1<<6, // Race and Competition - GTR_TAG = 1<<7, // Tag and Hide and Seek - GTR_POINTLIMIT = 1<<8, // Ringslinger point limit - GTR_TIMELIMIT = 1<<9, // Ringslinger time limit - GTR_STARTCOUNTDOWN = 1<<10, // Hide time countdown (Tag and Hide and Seek) - GTR_HIDEFROZEN = 1<<11, // Frozen after hide time (Hide and Seek, but not Tag) - GTR_BLINDFOLDED = 1<<12, // Blindfolded view (Tag and Hide and Seek) - GTR_FIRSTPERSON = 1<<13, // First person camera - GTR_POWERSTONES = 1<<14, // Power stones (Match and CTF) - GTR_TEAMFLAGS = 1<<15, // Gametype has team flags (CTF) - GTR_PITYSHIELD = 1<<16, // Award pity shield - GTR_DEATHPENALTY = 1<<17, // Death score penalty - GTR_NOSPECTATORSPAWN = 1<<18, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators - GTR_DEATHMATCHSTARTS = 1<<19, // Use deathmatch starts - GTR_SPECIALSTAGES = 1<<20, // Allow special stages - GTR_EMERALDTOKENS = 1<<21, // Spawn emerald tokens - GTR_EMERALDHUNT = 1<<22, // Emerald Hunt - GTR_SPAWNENEMIES = 1<<23, // Spawn enemies - GTR_ALLOWEXIT = 1<<24, // Allow exit sectors - GTR_NOTITLECARD = 1<<25, // Don't show the title card - GTR_OVERTIME = 1<<26, // Allow overtime - GTR_HURTMESSAGES = 1<<27, // Hit and death messages - GTR_SPAWNINVUL = 1<<28, // Babysitting deterrent - GTR_RESPAWNDELAY = 1<<29, // Respawn delay + GTR_FRIENDLY = 1<<6, // Co-op + GTR_RACE = 1<<7, // Race and Competition + GTR_TAG = 1<<8, // Tag and Hide and Seek + GTR_POINTLIMIT = 1<<9, // Ringslinger point limit + GTR_TIMELIMIT = 1<<10, // Ringslinger time limit + GTR_STARTCOUNTDOWN = 1<<11, // Hide time countdown (Tag and Hide and Seek) + GTR_HIDEFROZEN = 1<<12, // Frozen after hide time (Hide and Seek, but not Tag) + GTR_BLINDFOLDED = 1<<13, // Blindfolded view (Tag and Hide and Seek) + GTR_FIRSTPERSON = 1<<14, // First person camera + GTR_POWERSTONES = 1<<15, // Power stones (Match and CTF) + GTR_TEAMFLAGS = 1<<16, // Gametype has team flags (CTF) + GTR_PITYSHIELD = 1<<17, // Award pity shield + GTR_DEATHPENALTY = 1<<18, // Death score penalty + GTR_NOSPECTATORSPAWN = 1<<19, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators + GTR_DEATHMATCHSTARTS = 1<<20, // Use deathmatch starts + GTR_SPECIALSTAGES = 1<<21, // Allow special stages + GTR_EMERALDTOKENS = 1<<22, // Spawn emerald tokens + GTR_EMERALDHUNT = 1<<23, // Emerald Hunt + GTR_SPAWNENEMIES = 1<<24, // Spawn enemies + GTR_ALLOWEXIT = 1<<25, // Allow exit sectors + GTR_NOTITLECARD = 1<<26, // Don't show the title card + GTR_OVERTIME = 1<<27, // Allow overtime + GTR_HURTMESSAGES = 1<<28, // Hit and death messages + GTR_SPAWNINVUL = 1<<29, // Babysitting deterrent + GTR_RESPAWNDELAY = 1<<30, // Respawn delay }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index c8e185f56..67b6c2098 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3193,7 +3193,7 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Co-op - GTR_CAMPAIGN|GTR_LIVES|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, + GTR_CAMPAIGN|GTR_LIVES|GTR_FRIENDLY|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, // Competition GTR_RACE|GTR_LIVES|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_SPAWNINVUL|GTR_ALLOWEXIT, // Race @@ -3447,10 +3447,7 @@ boolean G_GametypeUsesLives(void) // boolean G_GametypeUsesCoopLives(void) { - // Preparing for the inevitable - // gametype rule that will - // handle cooplives... - return (gametype == GT_COOP); + return (gametyperules & (GTR_LIVES|GTR_FRIENDLY)) == (GTR_LIVES|GTR_FRIENDLY); } // @@ -3461,10 +3458,7 @@ boolean G_GametypeUsesCoopLives(void) // boolean G_GametypeUsesCoopStarposts(void) { - // Preparing for the inevitable - // gametype rule that will - // handle coopstarposts... - return (gametype == GT_COOP); + return (gametyperules & GTR_FRIENDLY); } // From ae0acfba0feeba6aaed4dd1ca247c0e9a3bd2774 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 28 Dec 2019 20:18:21 -0300 Subject: [PATCH 223/312] Organise gametype ruleset again. --- src/dehacked.c | 22 ++++++++++---------- src/doomstat.h | 56 +++++++++++++++++++++++++------------------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 799428455..d71ed854c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8902,34 +8902,34 @@ static const char *const GAMETYPERULE_LIST[] = { "CAMPAIGN", "RINGSLINGER", "SPECTATORS", - "FRIENDLYFIRE", "LIVES", "TEAMS", + "FIRSTPERSON", + "POWERSTONES", + "TEAMFLAGS", "FRIENDLY", + "SPECIALSTAGES", + "EMERALDTOKENS", + "EMERALDHUNT", "RACE", "TAG", "POINTLIMIT", "TIMELIMIT", + "OVERTIME", + "HURTMESSAGES", + "FRIENDLYFIRE", "STARTCOUNTDOWN", "HIDEFROZEN", "BLINDFOLDED", - "FIRSTPERSON", - "POWERSTONES", - "TEAMFLAGS", + "RESPAWNDELAY", "PITYSHIELD", "DEATHPENALTY", "NOSPECTATORSPAWN", "DEATHMATCHSTARTS", - "SPECIALSTAGES", - "EMERALDTOKENS", - "EMERALDHUNT", + "SPAWNINVUL", "SPAWNENEMIES", "ALLOWEXIT", "NOTITLECARD", - "OVERTIME", - "HURTMESSAGES", - "SPAWNINVUL", - "RESPAWNDELAY", NULL }; diff --git a/src/doomstat.h b/src/doomstat.h index 42c05ba63..1e0eb4815 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -397,34 +397,34 @@ enum GameTypeRules GTR_CAMPAIGN = 1, // Linear Co-op map progression, don't allow random maps GTR_RINGSLINGER = 1<<1, // Outside of Co-op, Competition, and Race (overriden by cv_ringslinger) GTR_SPECTATORS = 1<<2, // Outside of Co-op, Competition, and Race - GTR_FRIENDLYFIRE = 1<<3, // Always allow friendly fire - GTR_LIVES = 1<<4, // Co-op and Competition - GTR_TEAMS = 1<<5, // Team Match, CTF - GTR_FRIENDLY = 1<<6, // Co-op - GTR_RACE = 1<<7, // Race and Competition - GTR_TAG = 1<<8, // Tag and Hide and Seek - GTR_POINTLIMIT = 1<<9, // Ringslinger point limit - GTR_TIMELIMIT = 1<<10, // Ringslinger time limit - GTR_STARTCOUNTDOWN = 1<<11, // Hide time countdown (Tag and Hide and Seek) - GTR_HIDEFROZEN = 1<<12, // Frozen after hide time (Hide and Seek, but not Tag) - GTR_BLINDFOLDED = 1<<13, // Blindfolded view (Tag and Hide and Seek) - GTR_FIRSTPERSON = 1<<14, // First person camera - GTR_POWERSTONES = 1<<15, // Power stones (Match and CTF) - GTR_TEAMFLAGS = 1<<16, // Gametype has team flags (CTF) - GTR_PITYSHIELD = 1<<17, // Award pity shield - GTR_DEATHPENALTY = 1<<18, // Death score penalty - GTR_NOSPECTATORSPAWN = 1<<19, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators - GTR_DEATHMATCHSTARTS = 1<<20, // Use deathmatch starts - GTR_SPECIALSTAGES = 1<<21, // Allow special stages - GTR_EMERALDTOKENS = 1<<22, // Spawn emerald tokens - GTR_EMERALDHUNT = 1<<23, // Emerald Hunt - GTR_SPAWNENEMIES = 1<<24, // Spawn enemies - GTR_ALLOWEXIT = 1<<25, // Allow exit sectors - GTR_NOTITLECARD = 1<<26, // Don't show the title card - GTR_OVERTIME = 1<<27, // Allow overtime - GTR_HURTMESSAGES = 1<<28, // Hit and death messages - GTR_SPAWNINVUL = 1<<29, // Babysitting deterrent - GTR_RESPAWNDELAY = 1<<30, // Respawn delay + GTR_LIVES = 1<<3, // Co-op and Competition + GTR_TEAMS = 1<<4, // Team Match, CTF + GTR_FIRSTPERSON = 1<<5, // First person camera + GTR_POWERSTONES = 1<<6, // Power stones (Match and CTF) + GTR_TEAMFLAGS = 1<<7, // Gametype has team flags (CTF) + GTR_FRIENDLY = 1<<8, // Co-op + GTR_SPECIALSTAGES = 1<<9, // Allow special stages + GTR_EMERALDTOKENS = 1<<10, // Spawn emerald tokens + GTR_EMERALDHUNT = 1<<11, // Emerald Hunt + GTR_RACE = 1<<12, // Race and Competition + GTR_TAG = 1<<13, // Tag and Hide and Seek + GTR_POINTLIMIT = 1<<14, // Ringslinger point limit + GTR_TIMELIMIT = 1<<15, // Ringslinger time limit + GTR_OVERTIME = 1<<16, // Allow overtime + GTR_HURTMESSAGES = 1<<17, // Hit and death messages + GTR_FRIENDLYFIRE = 1<<18, // Always allow friendly fire + GTR_STARTCOUNTDOWN = 1<<19, // Hide time countdown (Tag and Hide and Seek) + GTR_HIDEFROZEN = 1<<20, // Frozen after hide time (Hide and Seek, but not Tag) + GTR_BLINDFOLDED = 1<<21, // Blindfolded view (Tag and Hide and Seek) + GTR_RESPAWNDELAY = 1<<22, // Respawn delay + GTR_PITYSHIELD = 1<<23, // Award pity shield + GTR_DEATHPENALTY = 1<<24, // Death score penalty + GTR_NOSPECTATORSPAWN = 1<<25, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators + GTR_DEATHMATCHSTARTS = 1<<26, // Use deathmatch starts + GTR_SPAWNINVUL = 1<<27, // Babysitting deterrent + GTR_SPAWNENEMIES = 1<<28, // Spawn enemies + GTR_ALLOWEXIT = 1<<29, // Allow exit sectors + GTR_NOTITLECARD = 1<<30, // Don't show the title card }; // String names for gametypes From 216657192002bcfc74de14b1251ff52f25b8b3b1 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 28 Dec 2019 20:33:28 -0300 Subject: [PATCH 224/312] Add GTR_CUTSCENES. And I ran out of rule slots. Cool. --- src/d_main.c | 2 +- src/dehacked.c | 1 + src/doomstat.h | 1 + src/g_game.c | 8 ++++---- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index e25ef998e..e79234730 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -715,7 +715,7 @@ void D_StartTitle(void) if (netgame) { - if (gametype == GT_COOP) + if (gametyperules & GTR_CAMPAIGN) { G_SetGamestate(GS_WAITINGPLAYERS); // hack to prevent a command repeat diff --git a/src/dehacked.c b/src/dehacked.c index d71ed854c..9a4e0d499 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8930,6 +8930,7 @@ static const char *const GAMETYPERULE_LIST[] = { "SPAWNENEMIES", "ALLOWEXIT", "NOTITLECARD", + "CUTSCENES", NULL }; diff --git a/src/doomstat.h b/src/doomstat.h index 1e0eb4815..6d1d6eb36 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -425,6 +425,7 @@ enum GameTypeRules GTR_SPAWNENEMIES = 1<<28, // Spawn enemies GTR_ALLOWEXIT = 1<<29, // Allow exit sectors GTR_NOTITLECARD = 1<<30, // Don't show the title card + GTR_CUTSCENES = 1<<31, // Play cutscenes, ending, credits, and evaluation }; // String names for gametypes diff --git a/src/g_game.c b/src/g_game.c index 67b6c2098..e201faf6a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3193,7 +3193,7 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Co-op - GTR_CAMPAIGN|GTR_LIVES|GTR_FRIENDLY|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, + GTR_CAMPAIGN|GTR_LIVES|GTR_FRIENDLY|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES|GTR_CUTSCENES, // Competition GTR_RACE|GTR_LIVES|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_SPAWNINVUL|GTR_ALLOWEXIT, // Race @@ -3765,7 +3765,7 @@ void G_AfterIntermission(void) HU_ClearCEcho(); - if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene. + if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); else { @@ -3875,7 +3875,7 @@ static void G_DoContinued(void) void G_EndGame(void) { // Only do evaluation and credits in coop games. - if (gametype == GT_COOP) + if (gametyperules & GTR_CUTSCENES) { if (nextmap == 1103-1) // end game with ending { @@ -4578,7 +4578,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean automapactive = false; imcontinuing = false; - if (!skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene. + if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer); else G_DoLoadLevel(resetplayer); From 5b1b5569469e0cf30ae9297342e6f873217dcc89 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 28 Dec 2019 20:54:22 -0300 Subject: [PATCH 225/312] Remove characters that will not be allowed in the constant string. --- src/g_game.c | 96 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index e201faf6a..37dd292f9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3251,50 +3251,64 @@ INT16 G_AddGametype(UINT32 rules) // void G_AddGametypeConstant(INT16 gtype, const char *newgtconst) { - char *gtconst = Z_Malloc(strlen(newgtconst) + 3, PU_STATIC, NULL); - // Copy GT_ and the gametype name. - strcpy(gtconst, "GT_"); - strcat(gtconst, newgtconst); + size_t r = 0; // read + size_t w = 0; // write + char *gtconst = Z_Calloc(strlen(newgtconst) + 3, PU_STATIC, NULL); + char *tmpconst = Z_Calloc(strlen(newgtconst), PU_STATIC, NULL); + + // Copy the gametype name. + strcpy(tmpconst, newgtconst); + // Make uppercase. - strupr(gtconst); - // Remove characters. -#define REMOVECHAR(chr) \ - { \ - char *chrfind = strchr(gtconst, chr); \ - while (chrfind) \ - { \ - *chrfind = '_'; \ - chrfind = strchr(chrfind, chr); \ - } \ + strupr(tmpconst); + + // Prepare to write the new constant string now. + strcpy(gtconst, "GT_"); + + // Remove characters that will not be allowed in the constant string. + for (; r < strlen(tmpconst); r++) + { + boolean writechar = true; + char rc = tmpconst[r]; + switch (rc) + { + // Space + case ' ': + // Used for operations + case '+': + case '-': + case '*': + case '/': + case '%': + case '^': + // Part of Lua's syntax + case '#': + case '=': + case '~': + case '<': + case '>': + case '(': + case ')': + case '{': + case '}': + case '[': + case ']': + case ':': + case ';': + case ',': + case '.': + writechar = false; + break; + } + if (writechar) + { + gtconst[3 + w] = rc; + w++; + } } - // Space - REMOVECHAR(' ') - // Used for operations - REMOVECHAR('+') - REMOVECHAR('-') - REMOVECHAR('*') - REMOVECHAR('/') - REMOVECHAR('%') - REMOVECHAR('^') - // Part of Lua's syntax - REMOVECHAR('#') - REMOVECHAR('=') - REMOVECHAR('~') - REMOVECHAR('<') - REMOVECHAR('>') - REMOVECHAR('(') - REMOVECHAR(')') - REMOVECHAR('{') - REMOVECHAR('}') - REMOVECHAR('[') - REMOVECHAR(']') - REMOVECHAR(':') - REMOVECHAR(';') - REMOVECHAR(',') - REMOVECHAR('.') - -#undef REMOVECHAR + // Free the temporary string. + Z_Free(tmpconst); // Finally, set the constant string. Gametype_ConstantNames[gtype] = gtconst; From dede51fc4c86343efb031ec67e6e09def5fb0fd6 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 28 Dec 2019 21:05:42 -0300 Subject: [PATCH 226/312] Disallow few more characters. --- src/g_game.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 37dd292f9..779592713 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3272,8 +3272,10 @@ void G_AddGametypeConstant(INT16 gtype, const char *newgtconst) char rc = tmpconst[r]; switch (rc) { - // Space + // Space, at sign and question mark case ' ': + case '@': + case '?': // Used for operations case '+': case '-': @@ -3281,6 +3283,8 @@ void G_AddGametypeConstant(INT16 gtype, const char *newgtconst) case '/': case '%': case '^': + case '&': + case '!': // Part of Lua's syntax case '#': case '=': From 0237dc8ca27569616cc06eb8d085cf1735654231 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 28 Dec 2019 17:52:22 -0800 Subject: [PATCH 227/312] Add MFE_TOUCHLAVA and MFE_TRACERANGLE to Lua and SOC --- src/dehacked.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index b77939c2a..4c90211cc 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8824,9 +8824,11 @@ static const char *const MOBJEFLAG_LIST[] = { "JUSTSTEPPEDDOWN", // used for ramp sectors "VERTICALFLIP", // Vertically flip sprite/allow upside-down physics "GOOWATER", // Goo water + "TOUCHLAVA", // The mobj is touching a lava block "PUSHED", // Mobj was already pushed this tic "SPRUNG", // Mobj was already sprung this tic "APPLYPMOMZ", // Platform movement + "TRACERANGLE", // Compute and trigger on mobj angle relative to tracer NULL }; From 2acb4f9840bce85ac49b0e96485d8b30c1d6dde1 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 28 Dec 2019 21:43:10 -0500 Subject: [PATCH 228/312] Revert "Delete the original configuration file." This reverts commit 2cf94ea6aec88827d77e106aa53303276f2398a8. --- extras/conf/SRB2-22.cfg | 6521 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 6521 insertions(+) create mode 100644 extras/conf/SRB2-22.cfg diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg new file mode 100644 index 000000000..5bc48211c --- /dev/null +++ b/extras/conf/SRB2-22.cfg @@ -0,0 +1,6521 @@ +/*********************************************************\ + Zone Builder Game Configuration + For Sonic Robo Blast 2 Version 2.2 + Contributors (alphabetical): + * Foxboy + * FuriousFox + * JJames19119 + * Kalaron + * Kristos + * MascaraSnake + * mazmazz + * Morpheus + * Neo Chaotikal + * Nev3r + * Oogaland + * Rob + * Shadow Hog + * Spherallic + * SRB2-Playah + * SSNTails + * SteelT + * ST218 + * toaster + * Viola +\*********************************************************/ + +// This is required to prevent accidental use of a different configuration +type = "Doom Builder 2 Game Configuration"; + +// This is the title to show for this game +game = "Sonic Robo Blast 2 - 2.2"; + +//GZDB specific. Don't try to load lumps that don't exist. +basegame = 0; + +// This is the simplified game engine/sourceport name +engine = "zdoom"; + +// When this is set to true, sectors with the same tag will light up when a line is highlighted +linetagindicatesectors = true; + +// The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder +formatinterface = "SRB2MapSetIO"; + +//Sky textures for vanilla maps +defaultskytextures +{ + SKY1 = "MAP01,MAP02,MAP03,MAP33,MAP50,MAP60,MAPF0,MAPM0"; + SKY2 = "MAPM7,MAPMB"; + SKY4 = "MAP04,MAP06,MAP61,MAPF6,MAPM1"; + SKY6 = "MAP05,MAP51,MAPMA"; + SKY7 = "MAPM2,MAPM5"; + SKY8 = "MAP07,MAP08,MAP09,MAP52,MAP62,MAPF1"; + SKY10 = "MAP10,MAP12,MAP53,MAP63,MAPM3"; + SKY11 = "MAP11,MAPF7"; + SKY13 = "MAP13,MAP64"; + SKY14 = "MAP14"; + SKY15 = "MAP15,MAP54"; + SKY17 = "MAP70"; + SKY20 = "MAP32,MAP55,MAP65,MAPF2,MAPF5"; + SKY21 = "MAPM4"; + SKY22 = "MAP22,MAP23,MAP25,MAP26,MAP27,MAP56,MAP66,MAPF4,MAPM6"; + SKY30 = "MAP30"; + SKY31 = "MAP31"; + SKY35 = "MAP42"; + SKY40 = "MAP41,MAP71,MAPM9"; + SKY55 = "MAPF3,MAPM8"; + SKY68 = "MAPF8"; + SKY99 = "MAP57,MAPZ0"; + SKY159 = "MAP16"; + SKY172 = "MAP40"; + SKY300 = "MAP72"; + SKY301 = "MAP73"; +} + +// Default lump name for new map +defaultlumpname = "MAP01"; + +// Default testing parameters +testparameters = "-file \"%AP\" \"%F\" -warp %L"; +testshortpaths = true; + +// Default nodebuilder configurations +defaultsavecompiler = "zennode_normal"; +defaulttestcompiler = "zennode_fast"; + +// Skill levels +skills +{ + 1 = "Normal"; +} + +// Skins +skins +{ + Sonic; + Tails; + Knuckles; + Amy; + Fang; + Metalsonic; +} + +// Gametypes +gametypes +{ + -1 = "Single Player"; + 0 = "Co-op"; + 1 = "Competition"; + 2 = "Race"; + 3 = "Match"; + 4 = "Team Match"; + 5 = "Tag"; + 6 = "Hide and Seek"; + 7 = "CTF"; +} + +// Special linedefs +soundlinedefflag = 64; // See linedefflags +singlesidedflag = 1; // See linedefflags +doublesidedflag = 4; // See linedefflags +impassableflag = 1; +upperunpeggedflag = 8; +lowerunpeggedflag = 16; +repeatmidtextureflag = 1024; +pegmidtextureflag = 256; + +// Generalized actions +generalizedlinedefs = false; +generalizedsectors = true; + +// Texture loading options +defaultwalltexture = "GFZROCK"; +defaultfloortexture = "GFZFLR01"; +defaultceilingtexture = "F_SKY1"; +mixtexturesflats = true; +defaulttexturescale = 1.0f; +defaultflatscale = 1.0f; + +// Thing number for start position in 3D Mode +start3dmode = 3328; + + + + +/* +TEXTURES AND FLAT SOURCES +This tells Doom Builder where to find the information for textures +and flats in the IWAD file, Addition WAD file and Map WAD file. + +Start and end lumps must be given in a structure (of which the +key name doesnt matter) and any textures or flats in between them +are loaded in either the textures category or flats category. + +For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. +Kalaron: and now TX_START +*/ + +// Texture sources +textures +{ + zdoom1 + { + start = "TX_START"; + end = "TX_END"; + } +} + +// Patch sources +patches +{ + standard1 + { + start = "P_START"; + end = "P_END"; + } + + standard2 + { + start = "PP_START"; + end = "PP_END"; + } +} + +// Sprite sources +sprites +{ + standard1 + { + start = "S_START"; + end = "S_END"; + } + + standard2 + { + start = "SS_START"; + end = "SS_END"; + } +} + +// Flat sources +flats +{ + standard1 + { + start = "F_START"; + end = "F_END"; + } + + standard2 + { + start = "FF_START"; + end = "FF_END"; + } + + standard3 + { + start = "FF_START"; + end = "F_END"; + } + + standard4 + { + start = "F_START"; + end = "FF_END"; + } +} + + +/* +GAME DETECT PATTERN +Used to guess the game for which a WAD file is made. + +1 = One of these lumps must exist +2 = None of these lumps must exist +3 = All of these lumps must exist +*/ + +gamedetect +{ + EXTENDED = 2; + + + BEHAVIOR = 2; + + E#M# = 2; + + MAP?? = 1; +} + + +/* +MAP LUMP NAMES +Map lumps are loaded with the map as long as they are right after each other. When the editor +meets a lump which is not defined in this list it will ignore the map if not satisfied. +The order of items defines the order in which lumps will be written to WAD file on save. +To indicate the map header lump, use ~MAP + +Legenda: +required = Lump is required to exist. +blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use) +nodebuild = The nodebuilder generates this lump. +allowempty = The nodebuilder is allowed to leave this lump empty. +script = This lump is a text-based script. Specify the filename of the script configuration to use. +*/ + +maplumpnames +{ + ~MAP + { + required = true; + blindcopy = true; + nodebuild = false; + } + + THINGS + { + required = true; + nodebuild = true; + allowempty = true; + } + + LINEDEFS + { + required = true; + nodebuild = true; + allowempty = false; + } + + SIDEDEFS + { + required = true; + nodebuild = true; + allowempty = false; + } + + VERTEXES + { + required = true; + nodebuild = true; + allowempty = false; + } + + SEGS + { + required = false; + nodebuild = true; + allowempty = false; + } + + SSECTORS + { + required = false; + nodebuild = true; + allowempty = false; + } + + NODES + { + required = false; + nodebuild = true; + allowempty = false; + } + + SECTORS + { + required = true; + nodebuild = true; + allowempty = false; + } + + REJECT + { + required = false; + nodebuild = true; + allowempty = false; + } + + BLOCKMAP + { + required = false; + nodebuild = true; + allowempty = true; + } +} + +scriptlumpnames +{ + MAINCFG + { + script = "SOC.cfg"; + } + + OBJCTCFG + { + script = "SOC.cfg"; + } + + SOC_ + { + script = "SOC.cfg"; + isprefix = true; + } + + LUA_ + { + script = "Lua.cfg"; + isprefix = true; + } +} + +// DEFAULT SECTOR BRIGHTNESS LEVELS +sectorbrightness +{ + 255; + 248; + 240; + 232; + 224; + 216; + 208; + 200; + 192; + 184; + 176; + 168; + 160; + 152; + 144; + 136; + 128; + 120; + 112; + 104; + 96; + 88; + 80; + 72; + 64; + 56; + 48; + 40; + 32; + 24; + 16; + 8; + 0; +} + +// SECTOR TYPES----------------------------------------------------------------- +sectortypes +{ + 0 = "Normal"; + 1 = "Damage"; + 2 = "Damage (Water)"; + 3 = "Damage (Fire)"; + 4 = "Damage (Electrical)"; + 5 = "Spikes"; + 6 = "Death Pit (Camera Tilt)"; + 7 = "Death Pit (No Camera Tilt)"; + 8 = "Instant Kill"; + 9 = "Ring Drainer (Floor Touch)"; + 10 = "Ring Drainer (Anywhere in Sector)"; + 11 = "Special Stage Damage"; + 12 = "Space Countdown"; + 13 = "Ramp Sector (double step-up/down)"; + 14 = "Non-Ramp Sector (no step-down)"; + 15 = "Bouncy FOF"; + 16 = "Trigger Line Ex. (Pushable Objects)"; + 32 = "Trigger Line Ex. (Anywhere, All Players)"; + 48 = "Trigger Line Ex. (Floor Touch, All Players)"; + 64 = "Trigger Line Ex. (Anywhere in Sector)"; + 80 = "Trigger Line Ex. (Floor Touch)"; + 96 = "Trigger Line Ex. (Emerald Check)"; + 112 = "Trigger Line Ex. (NiGHTS Mare)"; + 128 = "Check for Linedef Executor on FOFs"; + 144 = "Egg Capsule"; + 160 = "Special Stage Time/Rings Parameters"; + 176 = "Custom Global Gravity"; + 512 = "Wind/Current"; + 1024 = "Conveyor Belt"; + 1280 = "Speed Pad"; + 4096 = "Star Post Activator"; + 8192 = "Exit/Special Stage Pit/Return Flag"; + 12288 = "CTF Red Team Base"; + 16384 = "CTF Blue Team Base"; + 20480 = "Fan Sector"; + 24576 = "Super Sonic Transform"; + 28672 = "Force Spin"; + 32768 = "Zoom Tube Start"; + 36864 = "Zoom Tube End"; + 40960 = "Circuit Finish Line"; + 45056 = "Rope Hang"; + 49152 = "Intangible to the Camera"; +} + + +// GENERALISED SECTOR TYPES----------------------------------------------------------------- +gen_sectortypes +{ + first + { + 0 = "Normal"; + 1 = "Damage"; + 2 = "Damage (Water)"; + 3 = "Damage (Fire)"; + 4 = "Damage (Electrical)"; + 5 = "Spikes"; + 6 = "Death Pit (Camera Tilt)"; + 7 = "Death Pit (No Camera Tilt)"; + 8 = "Instant Kill"; + 9 = "Ring Drainer (Floor Touch)"; + 10 = "Ring Drainer (Anywhere in Sector)"; + 11 = "Special Stage Damage"; + 12 = "Space Countdown"; + 13 = "Ramp Sector (double step-up/down)"; + 14 = "Non-Ramp Sector (no step-down)"; + 15 = "Bouncy FOF"; + } + + second + { + 0 = "Normal"; + 16 = "Trigger Line Ex. (Pushable Objects)"; + 32 = "Trigger Line Ex. (Anywhere, All Players)"; + 48 = "Trigger Line Ex. (Floor Touch, All Players)"; + 64 = "Trigger Line Ex. (Anywhere in Sector)"; + 80 = "Trigger Line Ex. (Floor Touch)"; + 96 = "Trigger Line Ex. (Emerald Check)"; + 112 = "Trigger Line Ex. (NiGHTS Mare)"; + 128 = "Check for Linedef Executor on FOFs"; + 144 = "Egg Capsule"; + 160 = "Special Stage Time/Rings Parameters"; + 176 = "Custom Global Gravity"; + } + + third + { + 0 = "Normal"; + 512 = "Wind/Current"; + 1024 = "Conveyor Belt"; + 1280 = "Speed Pad"; + } + + fourth + { + 0 = "Normal"; + 4096 = "Star Post Activator"; + 8192 = "Exit/Special Stage Pit/Return Flag"; + 12288 = "CTF Red Team Base"; + 16384 = "CTF Blue Team Base"; + 20480 = "Fan Sector"; + 24576 = "Super Sonic Transform"; + 28672 = "Force Spin"; + 32768 = "Zoom Tube Start"; + 36864 = "Zoom Tube End"; + 40960 = "Circuit Finish Line"; + 45056 = "Rope Hang"; + 49152 = "Intangible to the Camera"; + } +} + +// LINEDEF FLAGS +linedefflags +{ + 1 = "[0] Impassable"; + 2 = "[1] Block Enemies"; + 4 = "[2] Double-Sided"; + 8 = "[3] Upper Unpegged"; + 16 = "[4] Lower Unpegged"; + 32 = "[5] Slope Skew (E1)"; + 64 = "[6] Not Climbable"; + 128 = "[7] No Midtexture Skew (E2)"; + 256 = "[8] Peg Midtexture (E3)"; + 512 = "[9] Solid Midtexture (E4)"; + 1024 = "[10] Repeat Midtexture (E5)"; + 2048 = "[11] Netgame Only"; + 4096 = "[12] No Netgame"; + 8192 = "[13] Effect 6"; + 16384 = "[14] Bouncy Wall"; + 32768 = "[15] Transfer Line"; +} + +// Linedef flags UDMF translation table +// This is needed for copy/paste and prefabs to work properly +// When the UDMF field name is prefixed with ! it is inverted +linedefflagstranslation +{ + 1 = "blocking"; + 2 = "blockmonsters"; + 4 = "twosided"; + 8 = "dontpegtop"; + 16 = "dontpegbottom"; + 32 = "secret"; + 64 = "blocksound"; + 128 = "dontdraw"; + 256 = "mapped"; +} + +// LINEDEF ACTIVATIONS +linedefactivations +{ +} + +// LINEDEF TYPES +linedeftypes +{ + misc + { + title = "Miscellaneous"; + + 0 + { + title = "None"; + prefix = "(0)"; + } + + 1 + { + title = "Per-Sector Gravity"; + prefix = "(1)"; + flags64text = "[6] Flip in reverse gravity"; + } + + 5 + { + title = "Camera Scanner"; + prefix = "(5)"; + } + + 7 + { + title = "Sector Flat Alignment"; + prefix = "(7)"; + flags2048text = "[11] Don't align floor"; + flags4096text = "[12] Don't align ceiling"; + flags8192text = "[13] Use texture offsets"; + } + + 10 + { + title = "Culling Plane"; + prefix = "(10)"; + flags64text = "[6] Cull only while in sector"; + } + + 13 + { + title = "Heat Wave Effect"; + prefix = "(13)"; + } + + 40 + { + title = "Visual Portal Between Tagged Linedefs"; + prefix = "(40)"; + } + + 41 + { + title = "Horizon Effect"; + prefix = "(41)"; + } + + 50 + { + title = "Instantly Lower Floor on Level Load"; + prefix = "(50)"; + } + + 51 + { + title = "Instantly Raise Ceiling on Level Load"; + prefix = "(51)"; + } + + 63 + { + title = "Fake Floor/Ceiling Planes"; + prefix = "(63)"; + } + + 540 + { + title = "Floor Friction"; + prefix = "(540)"; + } + } + + parameters + { + title = "Parameters"; + + 2 + { + title = "Custom Exit"; + prefix = "(2)"; + flags2text = "[1] Check emeralds"; + flags64text = "[6] Skip score tally"; + } + + 3 + { + title = "Zoom Tube Parameters"; + prefix = "(3)"; + flags512text = "[9] Ignore player direction"; + } + + 4 + { + title = "Speed Pad Parameters"; + prefix = "(4)"; + flags512text = "[9] No teleport to center"; + flags1024text = "[10] Force spinning frames"; + } + + 8 + { + title = "Special Sector Properties"; + prefix = "(8)"; + flags32text = "[5] Invert precipitation"; + flags64text = "[6] Touch only ceiling"; + flags128text = "[7] Allow opposite gravity"; + flags256text = "[8] Touch sector edge"; + flags512text = "[9] Touch floor or ceiling"; + } + + 9 + { + title = "Chain Parameters"; + prefix = "(9)"; + flags32text = "[5] Swing instead of spin"; + flags64text = "[6] Player-turnable chain"; + flags128text = "[7] Make chain from maces"; + flags256text = "[8] Spawn mace at origin"; + flags512text = "[9] Don't clip inside ground"; + flags1024text = "[10] No distance check"; + } + + 11 + { + title = "Rope Hang Parameters"; + prefix = "(11)"; + flags32text = "[5] Don't loop"; + flags64text = "[6] Static"; + } + + 12 + { + title = "Rock Spawner Parameters"; + prefix = "(12)"; + flags64text = "[6] Randomize speed"; + } + + 14 + { + title = "Bustable Block Parameters"; + prefix = "(14)"; + flags32text = "[5] Particles launch from center"; + } + + 15 + { + title = "Fan Particle Spawner Parameters"; + prefix = "(15)"; + } + + 16 + { + title = "Minecart Parameters"; + prefix = "(16)"; + } + + 64 + { + title = "Continuously Appearing/Disappearing FOF"; + prefix = "(64)"; + flags2text = "[1] Use control sector tag"; + flags64text = "[6] No sound effect"; + } + + 65 + { + title = "Bridge Thinker "; + prefix = "(65)"; + } + } + + polyobject + { + title = "PolyObject"; + + 20 + { + title = "First Line"; + prefix = "(20)"; + } + + 21 + { + title = "Explicitly Include Line "; + prefix = "(21)"; + } + + 22 + { + title = "Parameters"; + prefix = "(22)"; + flags64text = "[6] Trigger linedef executor"; + flags128text = "[7] Intangible"; + flags256text = "[8] Stopped by pushables"; + flags512text = "[9] Render flats"; + } + + 30 + { + title = "Waving Flag"; + prefix = "(30)"; + } + + 31 + { + title = "Displacement by Front Sector"; + prefix = "(31)"; + } + + 32 + { + title = "Angular Displacement by Front Sector"; + prefix = "(32)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + } + + planemove + { + title = "Plane Movement"; + + 52 + { + title = "Continuously Falling Sector"; + prefix = "(52)"; + flags64text = "[6] Continuously rising"; + } + + 53 + { + title = "Continuous Floor/Ceiling Mover"; + prefix = "(53)"; + } + + 54 + { + title = "Continuous Floor Mover"; + prefix = "(54)"; + } + + 55 + { + title = "Continuous Ceiling Mover"; + prefix = "(55)"; + } + + 56 + { + title = "Continuous Two-Speed Floor/Ceiling Mover"; + prefix = "(56)"; + } + + 57 + { + title = "Continuous Two-Speed Floor Mover"; + prefix = "(57)"; + } + + 58 + { + title = "Continuous Two-Speed Ceiling Mover"; + prefix = "(58)"; + } + + 59 + { + title = "Activate Moving Platform"; + prefix = "(59)"; + flags64text = "[6] Move upwards at start"; + } + + 60 + { + title = "Activate Moving Platform (Adjustable Speed)"; + prefix = "(60)"; + flags64text = "[6] Move upwards at start"; + } + + 61 + { + title = "Crusher (Ceiling to Floor)"; + prefix = "(61)"; + flags512text = "[9] Double, constant speed"; + } + + 62 + { + title = "Crusher (Floor to Ceiling)"; + prefix = "(62)"; + flags512text = "[9] Double, constant speed"; + } + + 66 + { + title = "Move Floor by Displacement"; + prefix = "(66)"; + flags64text = "[6] Inverse movement"; + } + + 67 + { + title = "Move Ceiling by Displacement"; + prefix = "(67)"; + flags64text = "[6] Inverse movement"; + } + + 68 + { + title = "Move Floor and Ceiling by Displacement"; + prefix = "(68)"; + flags64text = "[6] Inverse movement"; + } + } + + fofsolid + { + title = "FOF (solid)"; + + 100 + { + title = "Solid, Opaque"; + prefix = "(100)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 101 + { + title = "Solid, Opaque, No Shadow"; + prefix = "(101)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1DF"; + } + + 102 + { + title = "Solid, Translucent"; + prefix = "(102)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Render insides"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "195F"; + flags643dfloorflagsadd = "7C80"; + } + + 103 + { + title = "Solid, Sides Only"; + prefix = "(103)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1CF"; + } + + 104 + { + title = "Solid, No Sides"; + prefix = "(104)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1D7"; + flags643dfloorflagsremove = "40"; + } + + 105 + { + title = "Solid, Invisible"; + prefix = "(105)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "47"; + } + + 140 + { + title = "Intangible from Bottom, Opaque"; + prefix = "(140)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "200841F"; + flags643dfloorflagsadd = "40"; + } + + 141 + { + title = "Intangible from Bottom, Translucent"; + prefix = "(141)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "200191F"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 142 + { + title = "Intangible from Bottom, Translucent, No Sides"; + prefix = "(142)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "2001917"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 143 + { + title = "Intangible from Top, Opaque"; + prefix = "(143)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "400841F"; + flags643dfloorflagsadd = "40"; + } + + 144 + { + title = "Intangible from Top, Translucent"; + prefix = "(144)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "400191F"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 145 + { + title = "Intangible from Top, Translucent, No Sides"; + prefix = "(145)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "4001917"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 146 + { + title = "Only Tangible from Sides"; + prefix = "(146)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "600800F"; + } + } + + fofintangible + { + title = "FOF (intangible)"; + + 120 + { + title = "Water, Opaque"; + prefix = "(120)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "8F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 121 + { + title = "Water, Translucent"; + prefix = "(121)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "9F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 122 + { + title = "Water, Opaque, No Sides"; + prefix = "(122)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 123 + { + title = "Water, Translucent, No Sides"; + prefix = "(123)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "1F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 124 + { + title = "Goo Water, Translucent"; + prefix = "(124)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "209F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 125 + { + title = "Goo Water, Translucent, No Sides"; + prefix = "(125)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "201F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 220 + { + title = "Intangible, Opaque"; + prefix = "(220)"; + flags8text = "[3] Slope skew sides"; + 3dfloor = true; + 3dfloorflags = "8F19"; + } + + 221 + { + title = "Intangible, Translucent"; + prefix = "(221)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Cast shadow"; + 3dfloor = true; + 3dfloorflags = "1B59"; + flags643dfloorflagsremove = "40"; + } + + 222 + { + title = "Intangible, Sides Only"; + prefix = "(222)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Cast shadow"; + 3dfloor = true; + 3dfloorflags = "8249"; + flags643dfloorflagsremove = "240"; + } + + 223 + { + title = "Intangible, Invisible"; + prefix = "(223)"; + 3dfloor = true; + 3dfloorflags = "41"; + } + } + + fofmoving + { + title = "FOF (moving)"; + + 150 + { + title = "Air Bobbing"; + prefix = "(150)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 151 + { + title = "Air Bobbing (Adjustable)"; + prefix = "(151)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 152 + { + title = "Reverse Air Bobbing (Adjustable)"; + prefix = "(152)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 160 + { + title = "Floating, Bobbing"; + prefix = "(160)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "4019F"; + } + + 190 + { + title = "Rising Platform, Solid, Opaque"; + prefix = "(190)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 191 + { + title = "Rising Platform, Solid, Opaque, No Shadow"; + prefix = "(191)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1DF"; + } + + 192 + { + title = "Rising Platform, Solid, Translucent"; + prefix = "(192)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "195F"; + } + + 193 + { + title = "Rising Platform, Solid, Invisible"; + prefix = "(193)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "47"; + } + + 194 + { + title = "Rising Platform, Intangible from Bottom, Opaque"; + prefix = "(194)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash, no shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "200841F"; + flags643dfloorflagsadd = "40"; + } + + 195 + { + title = "Rising Platform, Intangible from Bottom, Translucent"; + prefix = "(195)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash, no shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "2009D1F"; + flags643dfloorflagsadd = "40"; + } + } + + fofcrumbling + { + title = "FOF (crumbling)"; + + 170 + { + title = "Crumbling, Respawn"; + prefix = "(170)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "10019F"; + } + + 171 + { + title = "Crumbling, No Respawn"; + prefix = "(171)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "80019F"; + } + + 172 + { + title = "Crumbling, Respawn, Intangible from Bottom"; + prefix = "(172)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "210841F"; + flags643dfloorflagsadd = "40"; + } + + 173 + { + title = "Crumbling, No Respawn, Intangible from Bottom"; + prefix = "(173)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "218841F"; + flags643dfloorflagsadd = "40"; + } + + 174 + { + title = "Crumbling, Respawn, Int. from Bottom, Translucent"; + prefix = "(174)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "210959F"; + flags643dfloorflagsadd = "40"; + } + + 175 + { + title = "Crumbling, No Respawn, Int. from Bottom, Translucent"; + prefix = "(175)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "218959F"; + flags643dfloorflagsadd = "40"; + } + + 176 + { + title = "Crumbling, Respawn, Floating, Bobbing"; + prefix = "(176)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "14019F"; + } + + 177 + { + title = "Crumbling, No Respawn, Floating, Bobbing"; + prefix = "(177)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1C019F"; + } + + 178 + { + title = "Crumbling, Respawn, Floating"; + prefix = "(178)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "14019F"; + } + + 179 + { + title = "Crumbling, No Respawn, Floating"; + prefix = "(179)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1C019F"; + } + + 180 + { + title = "Crumbling, Respawn, Air Bobbing"; + prefix = "(180)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "10019F"; + } + } + + fofspecial + { + title = "FOF (special)"; + + 200 + { + title = "Light Block"; + prefix = "(200)"; + 3dfloor = true; + 3dfloorflags = "20201"; + } + + 201 + { + title = "Half Light Block"; + prefix = "(201)"; + 3dfloor = true; + 3dfloorflags = "201"; + } + + 202 + { + title = "Fog Block"; + prefix = "(202)"; + 3dfloor = true; + 3dfloorflags = "3EF19"; + } + + 250 + { + title = "Mario Block"; + prefix = "(250)"; + flags32text = "[5] Invisible block"; + flags64text = "[6] Brick block"; + 3dfloor = true; + 3dfloorflags = "40019F"; + } + + 251 + { + title = "Thwomp Block"; + prefix = "(251)"; + flags512text = "[9] Custom crushing sound"; + flags1024text = "[10] Custom speed"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 252 + { + title = "Shatter Block"; + prefix = "(252)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Shatter only from below"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "8800019"; + flags643dfloorflagsadd = "200006"; + } + + 253 + { + title = "Shatter Block, Translucent"; + prefix = "(253)"; + flags8text = "[3] Slope skew sides"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "8801019"; + } + + 254 + { + title = "Bustable Block"; + prefix = "(254)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Strong characters only"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "80001F"; + flags643dfloorflagsadd = "20000000"; + } + + 255 + { + title = "Spin-Bustable Block"; + prefix = "(255)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "1080001F"; + } + + 256 + { + title = "Spin-Bustable Block, Translucent"; + prefix = "(256)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "1080101F"; + } + + 257 + { + title = "Quicksand"; + prefix = "(257)"; + flags8text = "[3] Slope skew sides"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "1008219"; + flags10243dfloorflagsadd = "40000000"; + } + + 258 + { + title = "Laser"; + prefix = "(258)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Don't damage bosses"; + 3dfloor = true; + 3dfloorflags = "959"; + } + + 259 + { + title = "Custom FOF"; + prefix = "(259)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorcustom = true; + } + } + + linedeftrigger + { + title = "Linedef Executor Trigger"; + + 300 + { + title = "Continuous"; + prefix = "(300)"; + } + + 301 + { + title = "Each Time"; + prefix = "(301)"; + flags16384text = "[14] Also trigger on exit"; + } + + 302 + { + title = "Once"; + prefix = "(302)"; + } + + 303 + { + title = "Ring Count - Continuous"; + prefix = "(303)"; + flags2text = "[1] Rings greater or equal"; + flags64text = "[6] Rings less or equal"; + flags512text = "[9] Consider all players"; + } + + 304 + { + title = "Ring Count - Once"; + prefix = "(304)"; + flags2text = "[1] Rings greater or equal"; + flags64text = "[6] Rings less or equal"; + flags512text = "[9] Consider all players"; + } + + 305 + { + title = "Character Ability - Continuous"; + prefix = "(305)"; + } + + 306 + { + title = "Character Ability - Each Time"; + prefix = "(306)"; + flags16384text = "[14] Also trigger on exit"; + } + + 307 + { + title = "Character Ability - Once"; + prefix = "(307)"; + } + + 308 + { + title = "Race Only - Once"; + prefix = "(308)"; + } + + 309 + { + title = "CTF Red Team - Continuous"; + prefix = "(309)"; + } + + 310 + { + title = "CTF Red Team - Each Time"; + prefix = "(310)"; + flags16384text = "[14] Also trigger on exit"; + } + + 311 + { + title = "CTF Blue Team - Continuous"; + prefix = "(311)"; + } + + 312 + { + title = "CTF Blue Team - Each Time"; + prefix = "(312)"; + flags16384text = "[14] Also trigger on exit"; + } + + 313 + { + title = "No More Enemies - Once"; + prefix = "(313)"; + } + + 314 + { + title = "Number of Pushables - Continuous"; + prefix = "(314)"; + flags64text = "[6] Number greater or equal"; + flags512text = "[9] Number less"; + } + + 315 + { + title = "Number of Pushables - Once"; + prefix = "(315)"; + flags64text = "[6] Number greater or equal"; + flags512text = "[9] Number less"; + } + + 317 + { + title = "Condition Set Trigger - Continuous"; + prefix = "(317)"; + } + + 318 + { + title = "Condition Set Trigger - Once"; + prefix = "(318)"; + } + + 319 + { + title = "Unlockable - Continuous"; + prefix = "(319)"; + } + + 320 + { + title = "Unlockable - Once"; + prefix = "(320)"; + } + + 321 + { + title = "Trigger After X Calls - Continuous"; + prefix = "(321)"; + flags64text = "[6] Trigger more than once"; + + } + + 322 + { + title = "Trigger After X Calls - Each Time"; + prefix = "(322)"; + flags64text = "[6] Trigger more than once"; + } + + 323 + { + title = "NiGHTSerize - Each Time"; + prefix = "(323)"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run only if player is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Run if no more mares"; + flags32768text = "[15] Run if player is not NiGHTS"; + } + + 324 + { + title = "NiGHTSerize - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run only if player is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Run if no more mares"; + flags32768text = "[15] Run if player is not NiGHTS"; + prefix = "(324)"; + } + + 325 + { + title = "De-NiGHTSerize - Each Time"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run if anyone is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags32768text = "[15] Run if no one is NiGHTS"; + prefix = "(325)"; + } + + 326 + { + title = "De-NiGHTSerize - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run if anyone is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags32768text = "[15] Run if no one is NiGHTS"; + prefix = "(326)"; + } + + 327 + { + title = "NiGHTS Lap - Each Time"; + flags2text = "[1] Mare >= Front X Offset"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + prefix = "(327)"; + } + + 328 + { + title = "NiGHTS Lap - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + prefix = "(328)"; + } + + 329 + { + title = "Ideya Capture Touch - Each Time"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run regardless of spheres"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Only if not enough spheres"; + flags32768text = "[15] Run when entering Capture"; + prefix = "(329)"; + } + + 330 + { + title = "Ideya Capture Touch - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run regardless of spheres"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Only if not enough spheres"; + flags32768text = "[15] Run when entering Capture"; + prefix = "(330)"; + } + + 331 + { + title = "Player Skin - Continuous"; + flags64text = "[6] Disable for this skin"; + prefix = "(331)"; + } + + 332 + { + title = "Player Skin - Each Time"; + flags64text = "[6] Disable for this skin"; + prefix = "(332)"; + } + + 333 + { + title = "Player Skin - Once"; + flags64text = "[6] Disable for this skin"; + prefix = "(333)"; + } + + 399 + { + title = "Level Load"; + prefix = "(399)"; + } + } + + linedefexecsector + { + title = "Linedef Executor (sector)"; + + 400 + { + title = "Set Tagged Sector's Floor Height/Texture"; + prefix = "(400)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Keep floor flat"; + } + + 401 + { + title = "Set Tagged Sector's Ceiling Height/Texture"; + prefix = "(401)"; + flags8text = "[3] Set delay by backside sector"; + } + + 402 + { + title = "Set Tagged Sector's Light Level"; + prefix = "(402)"; + flags8text = "[3] Set delay by backside sector"; + } + + 409 + { + title = "Change Tagged Sector's Tag"; + prefix = "(409)"; + flags8text = "[3] Set delay by backside sector"; + } + + 410 + { + title = "Change Front Sector's Tag"; + prefix = "(410)"; + flags8text = "[3] Set delay by backside sector"; + } + + 416 + { + title = "Start Adjustable Flickering Light"; + prefix = "(416)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 417 + { + title = "Start Adjustable Pulsating Light"; + prefix = "(417)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 418 + { + title = "Start Adjustable Blinking Light (unsynchronized)"; + prefix = "(418)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 419 + { + title = "Start Adjustable Blinking Light (synchronized)"; + prefix = "(419)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 420 + { + title = "Fade Light Level"; + prefix = "(420)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set params by X/Y offsets"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + } + + 421 + { + title = "Stop Lighting Effect"; + prefix = "(421)"; + flags8text = "[3] Set delay by backside sector"; + } + + 435 + { + title = "Change Plane Scroller Direction"; + prefix = "(435)"; + flags8text = "[3] Set delay by backside sector"; + } + } + + linedefexecplane + { + title = "Linedef Executor (plane movement)"; + + 403 + { + title = "Move Tagged Sector's Floor"; + prefix = "(403)"; + flags2text = "[1] Trigger linedef executor"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Change floor flat"; + } + + 404 + { + title = "Move Tagged Sector's Ceiling"; + prefix = "(404)"; + flags2text = "[1] Trigger linedef executor"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Change ceiling flat"; + } + + 405 + { + title = "Move Floor According to Front Texture Offsets"; + prefix = "(405)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move instantly"; + } + + 407 + { + title = "Move Ceiling According to Front Texture Offsets"; + prefix = "(407)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move instantly"; + } + + 411 + { + title = "Stop Plane Movement"; + prefix = "(411)"; + flags8text = "[3] Set delay by backside sector"; + } + + 428 + { + title = "Start Platform Movement"; + prefix = "(428)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move upwards at start"; + } + + 429 + { + title = "Crush Ceiling Once"; + prefix = "(429)"; + flags8text = "[3] Set delay by backside sector"; + flags512text = "[9] Double, constant speed"; + } + + 430 + { + title = "Crush Floor Once"; + prefix = "(430)"; + flags8text = "[3] Set delay by backside sector"; + } + + 431 + { + title = "Crush Floor and Ceiling Once"; + prefix = "(431)"; + flags8text = "[3] Set delay by backside sector"; + flags512text = "[9] Double, constant speed"; + } + } + + linedefexecplayer + { + title = "Linedef Executor (player/object)"; + + 412 + { + title = "Teleporter"; + prefix = "(412)"; + flags2text = "[1] Silent"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Retain angle"; + flags256text = "[8] Relative, silent"; + flags512text = "[9] Retain momentum"; + } + + 425 + { + title = "Change Object State"; + prefix = "(425)"; + flags8text = "[3] Set delay by backside sector"; + } + + 426 + { + title = "Stop Object"; + prefix = "(426)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Teleport to sector center"; + } + + 427 + { + title = "Award Score"; + prefix = "(427)"; + flags8text = "[3] Set delay by backside sector"; + } + + 432 + { + title = "Enable/Disable 2D Mode"; + prefix = "(432)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Return to 3D"; + } + + 433 + { + title = "Enable/Disable Gravity Flip"; + prefix = "(433)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Return to normal"; + } + + 434 + { + title = "Award Power-Up"; + prefix = "(434)"; + flags2text = "[1] Use back upper texture"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] No time limit"; + } + + 437 + { + title = "Disable Player Control"; + prefix = "(437)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Allow jumping"; + } + + 438 + { + title = "Change Object Size"; + prefix = "(438)"; + flags8text = "[3] Set delay by backside sector"; + } + + 442 + { + title = "Change Object Type State"; + prefix = "(442)"; + flags8text = "[3] Set delay by backside sector"; + } + + 457 + { + title = "Track Object's Angle"; + prefix = "(457)"; + flags8text = "[3] Set delay by backside sector"; + flags128text = "[7] Don't stop after first fail"; + } + + 458 + { + title = "Stop Tracking Object's Angle"; + prefix = "(458)"; + flags8text = "[3] Set delay by backside sector"; + } + + 460 + { + title = "Award Rings"; + prefix = "(460)"; + } + + 461 + { + title = "Spawn Object"; + prefix = "(461)"; + flags64text = "[6] Spawn inside a range"; + } + + 462 + { + title = "Stop Timer/Exit Stage in Record Attack"; + prefix = "(462)"; + } + } + + linedefexecmisc + { + title = "Linedef Executor (misc.)"; + + 413 + { + title = "Change Music"; + prefix = "(413)"; + flags2text = "[1] Keep after death"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Seek to current song position"; + flags64text = "[6] For everyone"; + flags128text = "[7] Fade to custom volume"; + flags512text = "[9] Don't loop"; + flags16384text = "[14] Force music reload"; + } + + 414 + { + title = "Play Sound Effect"; + prefix = "(414)"; + flags2text = "[1] From calling sector"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] From nowhere for triggerer"; + flags512text = "[9] For everyone"; + flags1024text = "[10] From tagged sectors"; + } + + 415 + { + title = "Run Script"; + prefix = "(415)"; + flags8text = "[3] Set delay by backside sector"; + } + + 422 + { + title = "Switch to Cut-Away View"; + prefix = "(422)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Adjust pitch"; + } + + 423 + { + title = "Change Sky"; + prefix = "(423)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + } + + 424 + { + title = "Change Weather"; + prefix = "(424)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + } + + 436 + { + title = "Shatter FOF"; + prefix = "(436)"; + flags8text = "[3] Set delay by backside sector"; + } + + 439 + { + title = "Change Tagged Linedef's Textures"; + prefix = "(439)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only existing"; + } + + 440 + { + title = "Start Metal Sonic Race"; + prefix = "(440)"; + flags8text = "[3] Set delay by backside sector"; + } + + 441 + { + title = "Condition Set Trigger"; + prefix = "(441)"; + flags8text = "[3] Set delay by backside sector"; + } + + 443 + { + title = "Call Lua Function"; + prefix = "(443)"; + flags8text = "[3] Set delay by backside sector"; + } + + 444 + { + title = "Earthquake"; + prefix = "(444)"; + flags8text = "[3] Set delay by backside sector"; + } + + + 445 + { + title = "Make FOF Disappear/Reappear"; + prefix = "(445)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Reappear"; + } + + 446 + { + title = "Make FOF Crumble"; + prefix = "(446)"; + flags2text = "[1] Flags determine respawn"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't respawn"; + } + + 447 + { + title = "Change Tagged Sector's Colormap"; + prefix = "(447)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Front X/Y = Alpha"; + flags32text = "[5] Subtract Red value"; + flags64text = "[6] Subtract Green value"; + flags128text = "[7] Subtract Blue value"; + flags256text = "[8] Calc relative values"; + flags32768text = "[15] Use back side colormap"; + } + + 448 + { + title = "Change Skybox"; + prefix = "(448)"; + flags2text = "[1] Change centerpoint"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + flags512text = "[9] Don't change viewpoint"; + } + + 450 + { + title = "Execute Linedef Executor (specific tag)"; + prefix = "(450)"; + flags8text = "[3] Set delay by backside sector"; + } + + 451 + { + title = "Execute Linedef Executor (random tag in range)"; + prefix = "(451)"; + flags8text = "[3] Set delay by backside sector"; + } + + 452 + { + title = "Set FOF Translucency"; + prefix = "(452)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Do not handle FF_TRANS"; + flags256text = "[8] Set relative to current val"; + } + + 453 + { + title = "Fade FOF"; + prefix = "(453)"; + flags2text = "[1] Do not handle FF_EXISTS"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] No collision during fade"; + flags64text = "[6] Do not handle FF_TRANS"; + flags128text = "[7] Do not handle lighting"; + flags256text = "[8] Set relative to current val"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Do not handle collision"; + flags32768text = "[15] Use exact alpha in OGL"; + } + + 454 + { + title = "Stop Fading FOF"; + prefix = "(454)"; + flags2text = "[1] Do not finalize collision"; + flags8text = "[3] Set delay by backside sector"; + } + + 455 + { + title = "Fade Tagged Sector's Colormap"; + prefix = "(455)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Front X/Y = Alpha"; + flags32text = "[5] Subtract Red value"; + flags64text = "[6] Subtract Green value"; + flags128text = "[7] Subtract Blue value"; + flags256text = "[8] Calc relative values"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Fade from invisible black"; + flags32768text = "[15] Use back side colormap"; + } + + 456 + { + title = "Stop Fading Tagged Sector's Colormap"; + prefix = "(456)"; + flags8text = "[3] Set delay by backside sector"; + } + + 459 + { + title = "Control Text Prompt"; + prefix = "(459)"; + flags2text = "[1] Close text prompt"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Run executor tag on close"; + flags64text = "[6] For everyone"; + flags128text = "[7] Do not block controls"; + flags256text = "[8] Do not freeze time"; + flags32768text = "[15] Find prompt by name"; + } + } + + linedefexecpoly + { + title = "Linedef Executor (polyobject)"; + + 480 + { + title = "Door Slide"; + prefix = "(480)"; + flags8text = "[3] Set delay by backside sector"; + } + + 481 + { + title = "Door Swing"; + prefix = "(481)"; + flags8text = "[3] Set delay by backside sector"; + } + + 482 + { + title = "Move"; + prefix = "(482)"; + flags8text = "[3] Set delay by backside sector"; + } + + 483 + { + title = "Move, Override"; + prefix = "(483)"; + flags8text = "[3] Set delay by backside sector"; + } + + 484 + { + title = "Rotate Right"; + prefix = "(484)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 485 + { + title = "Rotate Right, Override"; + prefix = "(485)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 486 + { + title = "Rotate Left"; + prefix = "(486)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 487 + { + title = "Rotate Left, Override"; + prefix = "(487)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 488 + { + title = "Move by Waypoints"; + prefix = "(488)"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Reverse order"; + flags128text = "[7] There and back"; + flags256text = "[8] Return when done"; + flags512text = "[9] Loop movement"; + } + + 489 + { + title = "Turn Invisible, Intangible"; + prefix = "(489)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only invisible"; + } + + 490 + { + title = "Turn Visible, Tangible"; + prefix = "(490)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only visible"; + } + + 491 + { + title = "Set Translucency"; + prefix = "(491)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set raw alpha by Front X"; + flags256text = "[8] Calc relative values"; + } + + 492 + { + title = "Fade Translucency"; + prefix = "(492)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set raw alpha by Front X"; + flags32text = "[5] No collision during fade"; + flags256text = "[8] Calc relative values"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Do not handle collision"; + } + } + + wallscroll + { + title = "Wall Scrolling"; + + 500 + { + title = "Scroll Wall Front Side Left"; + prefix = "(500)"; + } + + 501 + { + title = "Scroll Wall Front Side Right"; + prefix = "(501)"; + } + + 502 + { + title = "Scroll Wall According to Linedef"; + prefix = "(502)"; + } + + 503 + { + title = "Scroll Wall According to Linedef (Accelerative)"; + prefix = "(503)"; + } + + 504 + { + title = "Scroll Wall According to Linedef (Displacement)"; + prefix = "(504)"; + } + + 505 + { + title = "Scroll Texture by Front Side Offsets"; + prefix = "(505)"; + } + + 506 + { + title = "Scroll Texture by Back Side Offsets"; + prefix = "(506)"; + } + } + + planescroll + { + title = "Plane Scrolling"; + + 510 + { + title = "Scroll Floor Texture"; + prefix = "(510)"; + } + + 511 + { + title = "Scroll Floor Texture (Accelerative)"; + prefix = "(511)"; + } + + 512 + { + title = "Scroll Floor Texture (Displacement)"; + prefix = "(512)"; + } + + 513 + { + title = "Scroll Ceiling Texture"; + prefix = "(513)"; + } + + 514 + { + title = "Scroll Ceiling Texture (Accelerative)"; + prefix = "(514)"; + } + + 515 + { + title = "Scroll Ceiling Texture (Displacement)"; + prefix = "(515)"; + } + + 520 + { + title = "Carry Objects on Floor"; + prefix = "(520)"; + } + + 521 + { + title = "Carry Objects on Floor (Accelerative)"; + prefix = "(521)"; + flags64text = "[6] Even across edges"; + } + + 522 + { + title = "Carry Objects on Floor (Displacement)"; + prefix = "(522)"; + } + + 523 + { + title = "Carry Objects on Ceiling"; + prefix = "(523)"; + flags64text = "[6] Even across edges"; + } + + 524 + { + title = "Carry Objects on Ceiling (Accelerative)"; + prefix = "(524)"; + } + + 525 + { + title = "Carry Objects on Ceiling (Displacement)"; + prefix = "(525)"; + } + + 530 + { + title = "Scroll Floor Texture and Carry Objects"; + prefix = "(530)"; + flags64text = "[6] Even across edges"; + } + + 531 + { + title = "Scroll Floor Texture and Carry Objects (Accelerative)"; + prefix = "(531)"; + } + + 532 + { + title = "Scroll Floor Texture and Carry Objects (Displacement)"; + prefix = "(532)"; + } + + 533 + { + title = "Scroll Ceiling Texture and Carry Objects"; + prefix = "(533)"; + flags64text = "[6] Even across edges"; + } + + 534 + { + title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; + prefix = "(534)"; + } + + 535 + { + title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; + prefix = "(535)"; + } + } + + pusher + { + title = "Pusher"; + + 541 + { + title = "Wind"; + prefix = "(541)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 542 + { + title = "Upwards Wind"; + prefix = "(542)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 543 + { + title = "Downwards Wind"; + prefix = "(543)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 544 + { + title = "Current"; + prefix = "(544)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 545 + { + title = "Upwards Current"; + prefix = "(545)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 546 + { + title = "Downwards Current"; + prefix = "(546)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 547 + { + title = "Push/Pull"; + prefix = "(547)"; + } + } + + light + { + title = "Lighting"; + + 600 + { + title = "Floor Lighting"; + prefix = "(600)"; + } + + 601 + { + title = "Ceiling Lighting"; + prefix = "(601)"; + } + + 602 + { + title = "Adjustable Pulsating Light"; + prefix = "(602)"; + } + + 603 + { + title = "Adjustable Flickering Light"; + prefix = "(603)"; + } + + 604 + { + title = "Adjustable Blinking Light (unsynchronized)"; + prefix = "(604)"; + } + + 605 + { + title = "Adjustable Blinking Light (synchronized)"; + prefix = "(605)"; + } + + 606 + { + title = "Colormap"; + prefix = "(606)"; + } + } + + slope + { + title = "Slope"; + + 700 + { + title = "Slope Frontside Floor"; + prefix = "(700)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 1; + } + + 701 + { + title = "Slope Frontside Ceiling"; + prefix = "(701)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 2; + } + + 702 + { + title = "Slope Frontside Floor and Ceiling"; + prefix = "(702)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 3; + } + + 703 + { + title = "Slope Frontside Floor and Backside Ceiling"; + prefix = "(703)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 9; + } + + 704 + { + title = "Slope Frontside Floor by 3 Tagged Vertex Things"; + prefix = "(704)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 0; + } + + 705 + { + title = "Slope Frontside Ceiling by 3 Tagged Vertex Things"; + prefix = "(705)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 1; + } + + 710 + { + title = "Slope Backside Floor"; + prefix = "(710)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 4; + } + + 711 + { + title = "Slope Backside Ceiling"; + prefix = "(711)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 8; + } + + 712 + { + title = "Slope Backside Floor and Ceiling"; + prefix = "(712)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 12; + } + + 713 + { + title = "Slope Backside Floor and Frontside Ceiling"; + prefix = "(713)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 6; + } + + 714 + { + title = "Slope Backside Floor by 3 Tagged Vertex Things"; + prefix = "(714)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 2; + } + + 715 + { + title = "Slope Backside Ceiling by 3 Tagged Vertex Things"; + prefix = "(715)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 3; + } + + 720 + { + title = "Copy Frontside Floor Slope from Line Tag"; + prefix = "(720)"; + slope = "copy"; + slopeargs = 1; + } + + 721 + { + title = "Copy Frontside Ceiling Slope from Line Tag"; + prefix = "(721)"; + slope = "copy"; + slopeargs = 2; + } + + 722 + { + title = "Copy Frontside Floor and Ceiling Slope from Line Tag"; + prefix = "(722)"; + slope = "copy"; + slopeargs = 3; + } + + 799 + { + title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; + prefix = "(799)"; + } + } + + transwall + { + title = "Translucent Wall"; + + 900 + { + title = "90% Opaque"; + prefix = "(900)"; + } + + 901 + { + title = "80% Opaque"; + prefix = "(901)"; + } + + 902 + { + title = "70% Opaque"; + prefix = "(902)"; + } + + 903 + { + title = "60% Opaque"; + prefix = "(903)"; + } + + 904 + { + title = "50% Opaque"; + prefix = "(904)"; + } + + 905 + { + title = "40% Opaque"; + prefix = "(905)"; + } + + 906 + { + title = "30% Opaque"; + prefix = "(906)"; + } + + 907 + { + title = "20% Opaque"; + prefix = "(907)"; + } + + 908 + { + title = "10% Opaque"; + prefix = "(908)"; + } + + 909 + { + title = "Fog Wall"; + prefix = "(909)"; + } + } +} + + +// THING FLAGS +thingflags +{ + 1 = "[1] Extra"; + 2 = "[2] Flip"; + 4 = "[4] Special"; + 8 = "[8] Ambush"; +} + +// Thing flags UDMF translation table +// This is needed for copy/paste and prefabs to work properly +// When the UDMF field name is prefixed with ! it is inverted +thingflagstranslation +{ + 1 = "skill1"; + 2 = "skill2"; + 4 = "skill3"; + 8 = "ambush"; +} + +// THING FLAGS ERROR MASK +// Mask for the thing flags which indicates the options +// that make the same thing appear in the same modes +thingflagsmask1 = 7; // 1 + 2 + 4 +thingflagsmask2 = 0; + + +// THING TYPES------------------------------------------------------------------ +// Color values: 1-Dark_Blue 2-Dark_Green 3-Turqoise 4-Dark_Red 5-Purple 6-Brown 7-Gray +// 8-Dark_Gray 9-Blue 10-Green 11-Cyan 12-Red 13-Magenta +// 14-Yellow 15-White 16-Pink 17-Orange 18-Gold 19-Cream +thingtypes +{ + editor + { + color = 15; // White + arrow = 1; + title = ""; + error = -1; + width = 8; + height = 16; + sort = 1; + + 3328 = "3D Mode Start"; + } + + starts + { + color = 1; // Blue + arrow = 1; + title = "Player Starts"; + width = 16; + height = 48; + flags8text = "[8] Spawn on ceiling"; + sprite = "PLAYA0"; + + 1 + { + title = "Player 01 Start"; + sprite = "PLAYA0"; + } + 2 + { + title = "Player 02 Start"; + sprite = "PLAYA0"; + } + 3 + { + title = "Player 03 Start"; + sprite = "PLAYA0"; + } + 4 + { + title = "Player 04 Start"; + sprite = "PLAYA0"; + } + 5 + { + title = "Player 05 Start"; + sprite = "PLAYA0"; + } + 6 + { + title = "Player 06 Start"; + sprite = "PLAYA0"; + } + 7 + { + title = "Player 07 Start"; + sprite = "PLAYA0"; + } + 8 + { + title = "Player 08 Start"; + sprite = "PLAYA0"; + } + 9 + { + title = "Player 09 Start"; + sprite = "PLAYA0"; + } + 10 + { + title = "Player 10 Start"; + sprite = "PLAYA0"; + } + 11 + { + title = "Player 11 Start"; + sprite = "PLAYA0"; + } + 12 + { + title = "Player 12 Start"; + sprite = "PLAYA0"; + } + 13 + { + title = "Player 13 Start"; + sprite = "PLAYA0"; + } + 14 + { + title = "Player 14 Start"; + sprite = "PLAYA0"; + } + 15 + { + title = "Player 15 Start"; + sprite = "PLAYA0"; + } + 16 + { + title = "Player 16 Start"; + sprite = "PLAYA0"; + } + 17 + { + title = "Player 17 Start"; + sprite = "PLAYA0"; + } + 18 + { + title = "Player 18 Start"; + sprite = "PLAYA0"; + } + 19 + { + title = "Player 19 Start"; + sprite = "PLAYA0"; + } + 20 + { + title = "Player 20 Start"; + sprite = "PLAYA0"; + } + 21 + { + title = "Player 21 Start"; + sprite = "PLAYA0"; + } + 22 + { + title = "Player 22 Start"; + sprite = "PLAYA0"; + } + 23 + { + title = "Player 23 Start"; + sprite = "PLAYA0"; + } + 24 + { + title = "Player 24 Start"; + sprite = "PLAYA0"; + } + 25 + { + title = "Player 25 Start"; + sprite = "PLAYA0"; + } + 26 + { + title = "Player 26 Start"; + sprite = "PLAYA0"; + } + 27 + { + title = "Player 27 Start"; + sprite = "PLAYA0"; + } + 28 + { + title = "Player 28 Start"; + sprite = "PLAYA0"; + } + 29 + { + title = "Player 29 Start"; + sprite = "PLAYA0"; + } + 30 + { + title = "Player 30 Start"; + sprite = "PLAYA0"; + } + 31 + { + title = "Player 31 Start"; + sprite = "PLAYA0"; + } + 32 + { + title = "Player 32 Start"; + sprite = "PLAYA0"; + } + 33 + { + title = "Match Start"; + sprite = "NDRNA2A8"; + } + 34 + { + title = "CTF Red Team Start"; + sprite = "SIGNG0"; + } + 35 + { + title = "CTF Blue Team Start"; + sprite = "SIGNE0"; + } + } + + enemies + { + color = 9; // Light_Blue + arrow = 1; + title = "Enemies"; + + 100 + { + title = "Crawla (Blue)"; + sprite = "POSSA1"; + width = 24; + height = 32; + } + 101 + { + title = "Crawla (Red)"; + sprite = "SPOSA1"; + width = 24; + height = 32; + } + 102 + { + title = "Stupid Dumb Unnamed RoboFish"; + sprite = "FISHA0"; + width = 8; + height = 28; + angletext = "Jump strength"; + } + 103 + { + title = "Buzz (Gold)"; + sprite = "BUZZA1"; + width = 28; + height = 40; + flags8text = "[8] Cannot move"; + } + 104 + { + title = "Buzz (Red)"; + sprite = "RBUZA1"; + width = 28; + height = 40; + flags8text = "[8] Cannot move"; + } + 108 + { + title = "Deton"; + sprite = "DETNA1"; + width = 20; + height = 32; + } + 110 + { + title = "Turret"; + sprite = "TRETA1"; + width = 16; + height = 32; + } + 111 + { + title = "Pop-up Turret"; + sprite = "TURRI1"; + width = 12; + height = 64; + angletext = "Firing delay"; + } + 122 + { + title = "Spring Shell (Green)"; + sprite = "SSHLA1"; + width = 24; + height = 40; + } + 125 + { + title = "Spring Shell (Yellow)"; + sprite = "SSHLI1"; + width = 24; + height = 40; + } + 109 + { + title = "Skim"; + sprite = "SKIMA1"; + width = 16; + height = 24; + } + 113 + { + title = "Jet Jaw"; + sprite = "JJAWA3A7"; + width = 12; + height = 20; + } + 126 + { + title = "Crushstacean"; + sprite = "CRABA0"; + width = 24; + height = 32; + flags8text = "[8] Move left from spawn"; + } + 138 + { + title = "Banpyura"; + sprite = "CR2BA0"; + width = 24; + height = 32; + flags8text = "[8] Move left from spawn"; + } + 117 + { + title = "Robo-Hood"; + sprite = "ARCHA1"; + width = 24; + height = 32; + } + 118 + { + title = "Lance-a-Bot"; + sprite = "CBFSA1"; + width = 32; + height = 72; + } + 1113 + { + title = "Suspicious Lance-a-Bot Statue"; + sprite = "CBBSA1"; + width = 32; + height = 72; + } + 119 + { + title = "Egg Guard"; + sprite = "ESHIA1"; + width = 16; + height = 48; + flags1text = "[1] 90 degrees counter-clockwise"; + flags4text = "[4] 90 degrees clockwise"; + flags8text = "[8] Double speed"; + } + 115 + { + title = "Bird Aircraft Strike Hazard"; + sprite = "VLTRF1"; + width = 12; + height = 24; + } + 120 + { + title = "Green Snapper"; + sprite = "GSNPA1"; + width = 24; + height = 24; + } + 121 + { + title = "Minus"; + sprite = "MNUSA0"; + width = 24; + height = 32; + } + 134 + { + title = "Canarivore"; + sprite = "CANAA0"; + width = 12; + height = 80; + hangs = 1; + } + 123 + { + title = "Unidus"; + sprite = "UNIDA1"; + width = 18; + height = 36; + } + 135 + { + title = "Pterabyte Spawner"; + sprite = "PTERA2A8"; + width = 16; + height = 16; + parametertext = "No. Pterabytes"; + } + 136 + { + title = "Pyre Fly"; + sprite = "PYREA0"; + width = 24; + height = 34; + flags8text = "[8] Start on fire"; + } + 137 + { + title = "Dragonbomber"; + sprite = "DRABA1"; + width = 28; + height = 48; + } + 105 + { + title = "Jetty-Syn Bomber"; + sprite = "JETBB1"; + width = 20; + height = 50; + flags8text = "[8] Cannot move"; + } + 106 + { + title = "Jetty-Syn Gunner"; + sprite = "JETGB1"; + width = 20; + height = 48; + flags8text = "[8] Cannot move"; + } + 112 + { + title = "Spincushion"; + sprite = "SHRPA1"; + width = 16; + height = 24; + } + 114 + { + title = "Snailer"; + sprite = "SNLRA3A7"; + width = 24; + height = 48; + } + 129 + { + title = "Penguinator"; + sprite = "PENGA1"; + width = 24; + height = 32; + } + 130 + { + title = "Pophat"; + sprite = "POPHA1"; + width = 24; + height = 32; + } + 107 + { + title = "Crawla Commander"; + sprite = "CCOMA1"; + width = 16; + height = 32; + } + 131 + { + title = "Spinbobert"; + sprite = "SBOBB0"; + width = 32; + height = 32; + } + 132 + { + title = "Cacolantern"; + sprite = "CACOA0"; + width = 32; + height = 32; + flags8text = "[8] Cannot move"; + } + 133 + { + title = "Hangster"; + sprite = "HBATC1"; + width = 24; + height = 24; + hangs = 1; + } + 127 + { + title = "Hive Elemental"; + sprite = "HIVEA0"; + width = 32; + height = 80; + parametertext = "No. bees"; + } + 128 + { + title = "Bumblebore"; + sprite = "BUMBA1"; + width = 16; + height = 32; + } + 124 + { + title = "Buggle"; + sprite = "BBUZA1"; + width = 20; + height = 24; + } + 116 + { + title = "Pointy"; + sprite = "PNTYA1"; + width = 8; + height = 16; + } + } + + bosses + { + color = 8; // Dark_Gray + arrow = 1; + title = "Bosses"; + + 200 + { + title = "Egg Mobile"; + sprite = "EGGMA1"; + width = 24; + height = 76; + flags4text = "[4] End level on death"; + flags8text = "[8] Alternate laser attack"; + } + 201 + { + title = "Egg Slimer"; + sprite = "EGGNA1"; + width = 24; + height = 76; + flags4text = "[4] End level on death"; + flags8text = "[8] Speed up when hit"; + } + 202 + { + title = "Sea Egg"; + sprite = "EGGOA1"; + width = 32; + height = 116; + flags4text = "[4] End level on death"; + } + 203 + { + title = "Egg Colosseum"; + sprite = "EGGPA1"; + width = 24; + height = 76; + flags4text = "[4] End level on death"; + } + 204 + { + title = "Fang"; + sprite = "FANGA1"; + width = 24; + height = 60; + flags1text = "[1] Grayscale mode"; + flags4text = "[4] End level on death"; + } + 206 + { + title = "Brak Eggman (Old)"; + sprite = "BRAKB1"; + width = 48; + height = 160; + flags4text = "[4] End level on death"; + } + 207 + { + title = "Metal Sonic (Race)"; + sprite = "METLI1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + } + 208 + { + title = "Metal Sonic (Battle)"; + sprite = "METLC1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + flags4text = "[4] End level on death"; + } + 209 + { + title = "Brak Eggman"; + sprite = "BRAK01"; + width = 48; + height = 160; + flags1text = "[1] No origin-fling death"; + flags4text = "[4] End level on death"; + flags8text = "[8] Electric barrier"; + } + 290 + { + arrow = 0; + title = "Boss Escape Point"; + width = 8; + height = 16; + sprite = "internal:eggmanend"; + } + 291 + { + arrow = 0; + title = "Egg Capsule Center"; + width = 8; + height = 16; + sprite = "internal:capsule"; + } + 292 + { + arrow = 0; + title = "Boss Waypoint"; + width = 8; + height = 16; + flags8text = "[8] Sea Egg shooting point"; + sprite = "internal:eggmanway"; + angletext = "No. (Sea Egg)"; + flagsvaluetext = "No. (Brak)"; + parametertext = "Next"; + } + 293 + { + title = "Metal Sonic Gather Point"; + sprite = "internal:metal"; + width = 8; + height = 16; + } + 294 + { + title = "Fang Waypoint"; + flags8text = "[8] Center waypoint"; + sprite = "internal:eggmanway"; + width = 8; + height = 16; + } + } + + rings + { + color = 14; // Yellow + title = "Rings and Weapon Panels"; + width = 24; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + sprite = "RINGA0"; + + 300 + { + title = "Ring"; + sprite = "RINGA0"; + width = 16; + } + 301 + { + title = "Bounce Ring"; + sprite = "internal:RNGBA0"; + } + 302 + { + title = "Rail Ring"; + sprite = "internal:RNGRA0"; + } + 303 + { + title = "Infinity Ring"; + sprite = "internal:RNGIA0"; + } + 304 + { + title = "Automatic Ring"; + sprite = "internal:RNGAA0"; + } + 305 + { + title = "Explosion Ring"; + sprite = "internal:RNGEA0"; + } + 306 + { + title = "Scatter Ring"; + sprite = "internal:RNGSA0"; + } + 307 + { + title = "Grenade Ring"; + sprite = "internal:RNGGA0"; + } + 308 + { + title = "CTF Team Ring (Red)"; + sprite = "internal:RRNGA0"; + width = 16; + } + 309 + { + title = "CTF Team Ring (Blue)"; + sprite = "internal:BRNGA0"; + width = 16; + } + 330 + { + title = "Bounce Ring Panel"; + sprite = "internal:PIKBA0"; + } + 331 + { + title = "Rail Ring Panel"; + sprite = "internal:PIKRA0"; + } + 332 + { + title = "Automatic Ring Panel"; + sprite = "internal:PIKAA0"; + } + 333 + { + title = "Explosion Ring Panel"; + sprite = "internal:PIKEA0"; + } + 334 + { + title = "Scatter Ring Panel"; + sprite = "internal:PIKSA0"; + } + 335 + { + title = "Grenade Ring Panel"; + sprite = "internal:PIKGA0"; + } + } + + collectibles + { + color = 10; // Light_Green + title = "Other Collectibles"; + width = 16; + height = 32; + sort = 1; + sprite = "CEMGA0"; + + 310 + { + title = "CTF Red Flag"; + sprite = "RFLGA0"; + width = 24; + height = 64; + } + 311 + { + title = "CTF Blue Flag"; + sprite = "BFLGA0"; + width = 24; + height = 64; + } + 312 + { + title = "Emerald Token"; + sprite = "TOKEA0"; + width = 16; + height = 32; + flags8height = 24; + flags8text = "[8] Float"; + } + 313 + { + title = "Chaos Emerald 1 (Green)"; + sprite = "CEMGA0"; + } + 314 + { + title = "Chaos Emerald 2 (Purple)"; + sprite = "CEMGB0"; + } + 315 + { + title = "Chaos Emerald 3 (Blue)"; + sprite = "CEMGC0"; + } + 316 + { + title = "Chaos Emerald 4 (Cyan)"; + sprite = "CEMGD0"; + } + 317 + { + title = "Chaos Emerald 5 (Orange)"; + sprite = "CEMGE0"; + } + 318 + { + title = "Chaos Emerald 6 (Red)"; + sprite = "CEMGF0"; + } + 319 + { + title = "Chaos Emerald 7 (Gray)"; + sprite = "CEMGG0"; + } + 320 + { + title = "Emerald Hunt Location"; + sprite = "SHRDA0"; + } + 321 + { + title = "Match Chaos Emerald Spawn"; + sprite = "CEMGA0"; + flags8height = 24; + flags8text = "[8] Float"; + } + 322 + { + title = "Emblem"; + sprite = "EMBMA0"; + width = 16; + height = 30; + flags8height = 24; + flags8text = "[8] Float"; + angletext = "Tag"; + } + } + + boxes + { + color = 7; // Gray + blocking = 2; + title = "Monitors"; + width = 18; + height = 40; + flags1text = "[1] Run Linedef Executor on pop"; + flags4text = "[4] Random (Strong)"; + flags8text = "[8] Random (Weak)"; + + 400 + { + title = "Super Ring (10 Rings)"; + sprite = "TVRIA0"; + } + 401 + { + title = "Pity Shield"; + sprite = "TVPIA0"; + } + 402 + { + title = "Attraction Shield"; + sprite = "TVATA0"; + } + 403 + { + title = "Force Shield"; + sprite = "TVFOA0"; + } + 404 + { + title = "Armageddon Shield"; + sprite = "TVARA0"; + } + 405 + { + title = "Whirlwind Shield"; + sprite = "TVWWA0"; + } + 406 + { + title = "Elemental Shield"; + sprite = "TVELA0"; + } + 407 + { + title = "Super Sneakers"; + sprite = "TVSSA0"; + } + 408 + { + title = "Invincibility"; + sprite = "TVIVA0"; + } + 409 + { + title = "Extra Life"; + sprite = "TV1UA0"; + flags4text = "[4] Random (Strong) / 10k points"; + flags8text = "[8] Random (Weak) / 10k points"; + } + 410 + { + title = "Eggman"; + sprite = "TVEGA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 411 + { + title = "Teleporter"; + sprite = "TVMXA0"; + } + 413 + { + title = "Gravity Boots"; + sprite = "TVGVA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 414 + { + title = "CTF Team Ring Monitor (Red)"; + sprite = "TRRIA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 415 + { + title = "CTF Team Ring Monitor (Blue)"; + sprite = "TBRIA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 416 + { + title = "Recycler"; + sprite = "TVRCA0"; + } + 418 + { + title = "Score (1,000 Points)"; + sprite = "TV1KA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 419 + { + title = "Score (10,000 Points)"; + sprite = "TVTKA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 420 + { + title = "Flame Shield"; + sprite = "TVFLA0"; + } + 421 + { + title = "Water Shield"; + sprite = "TVBBA0"; + } + 422 + { + title = "Lightning Shield"; + sprite = "TVZPA0"; + } + } + + boxes2 + { + color = 18; // Gold + blocking = 2; + title = "Monitors (Respawning)"; + width = 20; + height = 44; + flags1text = "[1] Run Linedef Executor on pop"; + + 431 + { + title = "Pity Shield (Respawn)"; + sprite = "TVPIB0"; + } + 432 + { + title = "Attraction Shield (Respawn)"; + sprite = "TVATB0"; + } + 433 + { + title = "Force Shield (Respawn)"; + sprite = "TVFOB0"; + } + 434 + { + title = "Armageddon Shield (Respawn)"; + sprite = "TVARB0"; + } + 435 + { + title = "Whirlwind Shield (Respawn)"; + sprite = "TVWWB0"; + } + 436 + { + title = "Elemental Shield (Respawn)"; + sprite = "TVELB0"; + } + 437 + { + title = "Super Sneakers (Respawn)"; + sprite = "TVSSB0"; + } + 438 + { + title = "Invincibility (Respawn)"; + sprite = "TVIVB0"; + } + 440 + { + title = "Eggman (Respawn)"; + sprite = "TVEGB0"; + } + 443 + { + title = "Gravity Boots (Respawn)"; + sprite = "TVGVB0"; + } + 450 + { + title = "Flame Shield (Respawn)"; + sprite = "TVFLB0"; + } + 451 + { + title = "Water Shield (Respawn)"; + sprite = "TVBBB0"; + } + 452 + { + title = "Lightning Shield (Respawn)"; + sprite = "TVZPB0"; + } + } + + generic + { + color = 11; // Light_Cyan + title = "Generic Items & Hazards"; + + 500 + { + title = "Air Bubble Patch"; + sprite = "BUBLE0"; + width = 8; + height = 16; + flags8text = "[8] No distance check"; + } + 501 + { + title = "Signpost"; + sprite = "SIGND0"; + width = 8; + height = 32; + } + 502 + { + arrow = 1; + title = "Star Post"; + sprite = "STPTA0M0"; + width = 64; + height = 128; + angletext = "Angle/Order"; + } + 520 + { + title = "Bomb Sphere"; + sprite = "SPHRD0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + unflippable = true; + } + 521 + { + title = "Spikeball"; + sprite = "SPIKA0"; + width = 12; + height = 8; + flags8height = 24; + flags8text = "[8] Float"; + } + 522 + { + title = "Wall Spike"; + sprite = "WSPKALAR"; + width = 16; + height = 14; + flags1text = "[1] Start retracted"; + flags4text = "[4] Retractable"; + flags8text = "[8] Intangible"; + parametertext = "Initial delay"; + } + 523 + { + title = "Spike"; + sprite = "USPKA0"; + width = 8; + height = 32; + flags1text = "[1] Start retracted"; + flags4text = "[4] Retractable"; + flags8text = "[8] Intangible"; + angletext = "Retraction interval"; + parametertext = "Initial delay"; + } + 1130 + { + title = "Small Mace"; + sprite = "SMCEA0"; + width = 17; + height = 34; + } + 1131 + { + title = "Big Mace"; + sprite = "BMCEA0"; + width = 34; + height = 68; + } + 1136 + { + title = "Small Fireball"; + sprite = "SFBRA0"; + width = 17; + height = 34; + } + 1137 + { + title = "Large Fireball"; + sprite = "BFBRA0"; + width = 34; + height = 68; + } + } + + springs + { + color = 12; // Light_Red + title = "Springs and Fans"; + width = 20; + height = 16; + sprite = "RSPRD2"; + + 540 + { + title = "Fan"; + sprite = "FANSA0D0"; + width = 16; + height = 8; + flags4text = "[4] Invisible"; + flags8text = "[8] No distance check"; + angletext = "Lift height"; + } + 541 + { + title = "Gas Jet"; + sprite = "STEMD0"; + flags8text = "[8] No sounds"; + width = 32; + } + 542 + { + title = "Bumper"; + sprite = "BUMPA0"; + width = 32; + height = 64; + angletext = "Strength"; + } + 543 + { + title = "Balloon"; + sprite = "BLONA0"; + width = 32; + height = 64; + flags8text = "[8] Respawn"; + angletext = "Color"; + } + 550 + { + title = "Yellow Spring"; + sprite = "SPRYA0"; + } + 551 + { + title = "Red Spring"; + sprite = "SPRRA0"; + } + 552 + { + title = "Blue Spring"; + sprite = "SPRBA0"; + } + 555 + { + arrow = 1; + title = "Diagonal Yellow Spring"; + sprite = "YSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 556 + { + arrow = 1; + title = "Diagonal Red Spring"; + sprite = "RSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 557 + { + arrow = 1; + title = "Diagonal Blue Spring"; + sprite = "BSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 558 + { + arrow = 1; + title = "Horizontal Yellow Spring"; + sprite = "SSWYD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 559 + { + arrow = 1; + title = "Horizontal Red Spring"; + sprite = "SSWRD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 560 + { + arrow = 1; + title = "Horizontal Blue Spring"; + sprite = "SSWBD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 1134 + { + title = "Yellow Spring Ball"; + sprite = "YSPBA0"; + width = 17; + height = 34; + } + 1135 + { + title = "Red Spring Ball"; + sprite = "RSPBA0"; + width = 17; + height = 34; + } + 544 + { + arrow = 1; + title = "Yellow Boost Panel"; + sprite = "BSTYA0"; + flags8text = "[8] Force spin"; + width = 28; + height = 2; + } + 545 + { + arrow = 1; + title = "Red Boost Panel"; + sprite = "BSTRA0"; + flags8text = "[8] Force spin"; + width = 28; + height = 2; + } + } + + patterns + { + color = 5; // Magenta + arrow = 1; + title = "Special Placement Patterns"; + width = 16; + height = 384; + sprite = "RINGA0"; + + 600 + { + arrow = 0; + title = "5 Vertical Rings (Yellow Spring)"; + sprite = "RINGA0"; + } + 601 + { + arrow = 0; + title = "5 Vertical Rings (Red Spring)"; + sprite = "RINGA0"; + height = 1024; + } + 602 + { + title = "5 Diagonal Rings (Yellow Spring)"; + sprite = "RINGA0"; + height = 32; + } + 603 + { + title = "10 Diagonal Rings (Red Spring)"; + sprite = "RINGA0"; + height = 32; + } + 604 + { + title = "Circle of Rings"; + sprite = "RINGA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 605 + { + title = "Circle of Rings (Big)"; + sprite = "RINGA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 606 + { + title = "Circle of Blue Spheres"; + sprite = "SPHRA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 607 + { + title = "Circle of Blue Spheres (Big)"; + sprite = "SPHRA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 608 + { + title = "Circle of Rings and Spheres"; + sprite = "SPHRA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 609 + { + title = "Circle of Rings and Spheres (Big)"; + sprite = "SPHRA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + } + + invisible + { + color = 15; // White + title = "Misc. Invisible"; + width = 8; + height = 16; + sprite = "UNKNA0"; + + 700 + { + title = "Water Ambience A (Large)"; + sprite = "internal:ambiance"; + } + + 701 + { + title = "Water Ambience B (Large)"; + sprite = "internal:ambiance"; + } + + 702 + { + title = "Water Ambience C (Medium)"; + sprite = "internal:ambiance"; + } + + 703 + { + title = "Water Ambience D (Medium)"; + sprite = "internal:ambiance"; + } + + 704 + { + title = "Water Ambience E (Small)"; + sprite = "internal:ambiance"; + } + + 705 + { + title = "Water Ambience F (Small)"; + sprite = "internal:ambiance"; + } + + 706 + { + title = "Water Ambience G (Extra Large)"; + sprite = "internal:ambiance"; + } + + 707 + { + title = "Water Ambience H (Extra Large)"; + sprite = "internal:ambiance"; + } + + 708 + { + title = "Disco Ambience"; + sprite = "internal:ambiance"; + } + + 709 + { + title = "Volcano Ambience"; + sprite = "internal:ambiance"; + } + + 710 + { + title = "Machine Ambience"; + sprite = "internal:ambiance"; + } + + 750 + { + title = "Slope Vertex"; + sprite = "internal:vertexslope"; + angletext = "Tag"; + } + + 751 + { + arrow = 1; + title = "Teleport Destination"; + sprite = "internal:tele"; + } + + 752 + { + arrow = 1; + title = "Alternate View Point"; + sprite = "internal:view"; + } + + 753 + { + title = "Zoom Tube Waypoint"; + sprite = "internal:zoom"; + angletext = "Order"; + } + + 754 + { + title = "Push Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Push using XYZ"; + sprite = "GWLGA0"; + angletext = "Radius"; + } + 755 + { + title = "Pull Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Pull using XYZ"; + sprite = "GWLRA0"; + angletext = "Radius"; + } + 756 + { + title = "Blast Linedef Executor"; + sprite = "TOADA0"; + width = 32; + height = 16; + } + 757 + { + title = "Fan Particle Generator"; + sprite = "PRTLA0"; + width = 8; + height = 16; + angletext = "Tag"; + } + 758 + { + title = "Object Angle Anchor"; + sprite = "internal:view"; + } + 760 + { + title = "PolyObject Anchor"; + sprite = "internal:polyanchor"; + angletext = "ID"; + } + + 761 + { + title = "PolyObject Spawn Point"; + sprite = "internal:polycenter"; + angletext = "ID"; + } + + 762 + { + title = "PolyObject Spawn Point (Crush)"; + sprite = "internal:polycentercrush"; + angletext = "ID"; + } + 780 + { + title = "Skybox View Point"; + sprite = "internal:skyb"; + flags4text = "[4] In-map centerpoint"; + parametertext = "ID"; + } + } + + greenflower + { + color = 10; // Green + title = "Greenflower"; + + 800 + { + title = "GFZ Flower"; + sprite = "FWR1A0"; + width = 16; + height = 40; + } + 801 + { + title = "Sunflower"; + sprite = "FWR2A0"; + width = 16; + height = 96; + } + 802 + { + title = "Budding Flower"; + sprite = "FWR3A0"; + width = 8; + height = 32; + } + 803 + { + title = "Blueberry Bush"; + sprite = "BUS3A0"; + width = 16; + height = 32; + } + 804 + { + title = "Berry Bush"; + sprite = "BUS1A0"; + width = 16; + height = 32; + } + 805 + { + title = "Bush"; + sprite = "BUS2A0"; + width = 16; + height = 32; + } + 806 + { + title = "GFZ Tree"; + sprite = "TRE1A0"; + width = 20; + height = 128; + } + 807 + { + title = "GFZ Berry Tree"; + sprite = "TRE1B0"; + width = 20; + height = 128; + } + 808 + { + title = "GFZ Cherry Tree"; + sprite = "TRE1C0"; + width = 20; + height = 128; + } + 809 + { + title = "Checkered Tree"; + sprite = "TRE2A0"; + width = 20; + height = 200; + } + 810 + { + title = "Checkered Tree (Sunset)"; + sprite = "TRE2B0"; + width = 20; + height = 200; + } + 811 + { + title = "Polygon Tree"; + sprite = "TRE4A0"; + width = 20; + height = 200; + } + 812 + { + title = "Bush Tree"; + sprite = "TRE5A0"; + width = 20; + height = 200; + } + 813 + { + title = "Red Bush Tree"; + sprite = "TRE5B0"; + width = 20; + height = 200; + } + } + + technohill + { + color = 10; // Green + title = "Techno Hill"; + + 900 + { + title = "THZ Steam Flower"; + sprite = "THZPA0"; + width = 8; + height = 32; + } + 901 + { + title = "Alarm"; + sprite = "ALRMA0"; + width = 8; + height = 16; + hangs = 1; + } + 902 + { + title = "THZ Spin Flower (Red)"; + sprite = "FWR5A0"; + width = 16; + height = 64; + } + 903 + { + title = "THZ Spin Flower (Yellow)"; + sprite = "FWR6A0"; + width = 16; + height = 64; + } + 904 + { + arrow = 1; + title = "Whistlebush"; + sprite = "THZTA0"; + width = 16; + height = 64; + } + } + + deepsea + { + color = 10; // Green + title = "Deep Sea"; + + 1000 + { + arrow = 1; + blocking = 2; + title = "Gargoyle"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1009 + { + arrow = 1; + blocking = 2; + title = "Gargoyle (Big)"; + sprite = "GARGB1"; + width = 32; + height = 80; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1001 + { + title = "Seaweed"; + sprite = "SEWEA0"; + width = 24; + height = 56; + } + 1002 + { + title = "Dripping Water"; + sprite = "DRIPD0"; + width = 8; + height = 16; + hangs = 1; + angletext = "Dripping interval"; + } + 1003 + { + title = "Coral (Green)"; + sprite = "CORLA0"; + width = 29; + height = 40; + } + 1004 + { + title = "Coral (Red)"; + sprite = "CORLB0"; + width = 30; + height = 53; + } + 1005 + { + title = "Coral (Orange)"; + sprite = "CORLC0"; + width = 28; + height = 41; + } + 1006 + { + title = "Blue Crystal"; + sprite = "BCRYA1"; + width = 8; + height = 16; + } + 1007 + { + title = "Kelp"; + sprite = "KELPA0"; + width = 16; + height = 292; + flags4text = "[4] Double size"; + } + 1008 + { + title = "Stalagmite (DSZ1)"; + sprite = "DSTGA0"; + width = 8; + height = 116; + flags4text = "[4] Double size"; + } + 1010 + { + arrow = 1; + title = "Light Beam"; + sprite = "LIBEARAL"; + width = 16; + height = 16; + } + 1011 + { + title = "Stalagmite (DSZ2)"; + sprite = "DSTGA0"; + width = 8; + height = 116; + flags4text = "[4] Double size"; + } + 1012 + { + arrow = 1; + title = "Big Floating Mine"; + width = 28; + height = 56; + sprite = "BMNEA1"; + } + 1013 + { + title = "Animated Kelp"; + sprite = "ALGAA0"; + width = 48; + height = 120; + } + 1014 + { + title = "Large Coral (Brown)"; + sprite = "CORLD0"; + width = 56; + height = 112; + } + 1015 + { + title = "Large Coral (Beige)"; + sprite = "CORLE0"; + width = 56; + height = 112; + } + } + + castleeggman + { + color = 10; // Green + title = "Castle Eggman"; + + 1100 + { + title = "Chain (Decorative)"; + sprite = "CHANA0"; + width = 4; + height = 128; + hangs = 1; + } + 1101 + { + title = "Torch"; + sprite = "FLAMA0E0"; + width = 8; + height = 32; + flags1text = "[1] Add corona"; + } + 1102 + { + arrow = 1; + blocking = 2; + title = "Eggman Statue"; + sprite = "ESTAA1"; + width = 32; + height = 240; + flags1text = "[1] Solid gold"; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1103 + { + title = "CEZ Flower"; + sprite = "FWR4A0"; + width = 16; + height = 40; + } + 1104 + { + title = "Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1105 + { + title = "Chain with Maces Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1106 + { + title = "Chained Spring Spawnpoint"; + sprite = "YSPBA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Red spring"; + angletext = "Tag"; + } + 1107 + { + title = "Chain Spawnpoint"; + sprite = "BMCHA0"; + width = 17; + height = 34; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1108 + { + arrow = 1; + title = "Hidden Chain Spawnpoint"; + sprite = "internal:chain3"; + width = 17; + height = 34; + flags8text = "[8] Double size"; + } + 1109 + { + title = "Firebar Spawnpoint"; + sprite = "BFBRA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1110 + { + title = "Custom Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + angletext = "Tag"; + } + 1111 + { + arrow = 1; + blocking = 2; + title = "Crawla Statue"; + sprite = "CSTAA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1112 + { + arrow = 1; + blocking = 2; + title = "Lance-a-Bot Statue"; + sprite = "CBBSA1"; + width = 32; + height = 72; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1114 + { + title = "Pine Tree"; + sprite = "PINEA0"; + width = 16; + height = 628; + } + 1115 + { + title = "CEZ Shrub (Small)"; + sprite = "CEZBA0"; + width = 16; + height = 24; + } + 1116 + { + title = "CEZ Shrub (Large)"; + sprite = "CEZBB0"; + width = 32; + height = 48; + } + 1117 + { + arrow = 1; + title = "Pole Banner (Red)"; + sprite = "BANRA0"; + width = 40; + height = 224; + } + 1118 + { + arrow = 1; + title = "Pole Banner (Blue)"; + sprite = "BANRA0"; + width = 40; + height = 224; + } + 1119 + { + title = "Candle"; + sprite = "CNDLA0"; + width = 8; + height = 48; + flags1text = "[1] Add corona"; + } + 1120 + { + title = "Candle Pricket"; + sprite = "CNDLB0"; + width = 8; + height = 176; + flags1text = "[1] Add corona"; + } + 1121 + { + title = "Flame Holder"; + sprite = "FLMHA0"; + width = 24; + height = 80; + flags1text = "[1] Add corona"; + flags4text = "[4] No flame"; + } + 1122 + { + title = "Fire Torch"; + sprite = "CTRCA0"; + width = 16; + height = 80; + } + 1123 + { + title = "Cannonball Launcher"; + sprite = "internal:cannonball"; + width = 8; + height = 16; + } + 1124 + { + blocking = 2; + title = "Cannonball"; + sprite = "CBLLA0"; + width = 20; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1125 + { + title = "Brambles"; + sprite = "CABRALAR"; + width = 48; + height = 32; + } + 1126 + { + title = "Invisible Lockon Object"; + sprite = "LCKNC0"; + width = 16; + height = 32; + } + 1127 + { + title = "Spectator Eggrobo"; + sprite = "EGR1A1"; + width = 20; + height = 72; + } + 1128 + { + arrow = 1; + title = "Waving Flag (Red)"; + sprite = "CFLGA0"; + width = 8; + height = 208; + } + 1129 + { + arrow = 1; + title = "Waving Flag (Blue)"; + sprite = "CFLGA0"; + width = 8; + height = 208; + } + } + + aridcanyon + { + color = 10; // Green + title = "Arid Canyon"; + + 1200 + { + title = "Tumbleweed (Big)"; + sprite = "BTBLA0"; + width = 24; + height = 48; + flags8text = "[8] Moves perpetually"; + } + 1201 + { + title = "Tumbleweed (Small)"; + sprite = "STBLA0"; + width = 12; + height = 24; + flags8text = "[8] Moves perpetually"; + } + 1202 + { + arrow = 1; + title = "Rock Spawner"; + sprite = "ROIAA0"; + width = 8; + height = 16; + angletext = "Tag"; + } + 1203 + { + title = "Tiny Red Flower Cactus"; + sprite = "CACTA0"; + width = 13; + height = 24; + } + 1204 + { + title = "Small Red Flower Cactus"; + sprite = "CACTB0"; + width = 15; + height = 52; + } + 1205 + { + title = "Tiny Blue Flower Cactus"; + sprite = "CACTC0"; + width = 13; + height = 24; + } + 1206 + { + title = "Small Blue Flower Cactus"; + sprite = "CACTD0"; + width = 15; + height = 52; + } + 1207 + { + title = "Prickly Pear"; + sprite = "CACTE0"; + width = 32; + height = 96; + } + 1208 + { + title = "Barrel Cactus"; + sprite = "CACTF0"; + width = 20; + height = 128; + } + 1209 + { + title = "Tall Barrel Cactus"; + sprite = "CACTG0"; + width = 24; + height = 224; + } + 1210 + { + title = "Armed Cactus"; + sprite = "CACTH0"; + width = 24; + height = 256; + } + 1211 + { + title = "Ball Cactus"; + sprite = "CACTI0"; + width = 48; + height = 96; + } + 1212 + { + title = "Caution Sign"; + sprite = "WWSGAR"; + width = 22; + height = 64; + } + 1213 + { + title = "Cacti Sign"; + sprite = "WWS2AR"; + width = 22; + height = 64; + } + 1214 + { + title = "Sharp Turn Sign"; + sprite = "WWS3ALAR"; + width = 16; + height = 192; + } + 1215 + { + title = "Mine Oil Lamp"; + sprite = "OILLA0"; + width = 22; + height = 64; + hangs = 1; + } + 1216 + { + title = "TNT Barrel"; + sprite = "BARRA1"; + width = 24; + height = 63; + } + 1217 + { + title = "TNT Proximity Shell"; + sprite = "REMTA0"; + width = 64; + height = 40; + } + 1218 + { + title = "Dust Devil"; + sprite = "TAZDCR"; + width = 80; + height = 416; + } + 1219 + { + title = "Minecart Spawner"; + sprite = "MCRTCLFR"; + width = 22; + height = 32; + } + 1220 + { + title = "Minecart Stopper"; + sprite = "MCRTIR"; + width = 32; + height = 32; + } + 1221 + { + title = "Minecart Saloon Door"; + sprite = "SALDARAL"; + width = 96; + height = 160; + flags8text = "[8] Allow non-minecart players"; + } + 1222 + { + title = "Train Cameo Spawner"; + sprite = "TRAEBRBL"; + width = 28; + height = 32; + } + 1223 + { + title = "Train Dust Spawner"; + sprite = "ADSTA0"; + width = 4; + height = 4; + } + 1224 + { + title = "Train Steam Spawner"; + sprite = "STEAA0"; + width = 4; + height = 4; + } + 1229 + { + title = "Minecart Switch Point"; + sprite = "internal:zoom"; + width = 8; + height = 16; + flags8text = "[8] Enable switching"; + } + 1230 + { + title = "Tiny Cactus"; + sprite = "CACTJ0"; + width = 13; + height = 28; + } + 1231 + { + title = "Small Cactus"; + sprite = "CACTK0"; + width = 15; + height = 60; + } + } + + redvolcano + { + color = 10; // Green + title = "Red Volcano"; + + 1300 + { + arrow = 1; + title = "Flame Jet (Horizontal)"; + sprite = "internal:flameh"; + width = 16; + height = 40; + flags8text = "[8] Waves vertically"; + angletext = "On/Off time"; + parametertext = "Strength"; + } + 1301 + { + title = "Flame Jet (Vertical)"; + sprite = "internal:flamev"; + width = 16; + height = 40; + flags8text = "[8] Shoot downwards"; + angletext = "On/Off time"; + parametertext = "Strength"; + } + 1302 + { + title = "Spinning Flame Jet (Counter-Clockwise)"; + sprite = "internal:flame2"; + width = 16; + height = 24; + } + 1303 + { + title = "Spinning Flame Jet (Clockwise)"; + sprite = "internal:flame1"; + width = 16; + height = 24; + } + 1304 + { + title = "Lavafall"; + sprite = "LFALF0"; + width = 30; + height = 32; + angletext = "Initial delay"; + flags8text = "[8] Double size"; + } + 1305 + { + title = "Rollout Rock"; + sprite = "PUMIA1A5"; + width = 30; + height = 60; + flags8text = "[8] Non-buoyant"; + } + 1306 + { + title = "Big Fern"; + sprite = "JPLAB0"; + width = 32; + height = 48; + } + 1307 + { + title = "Jungle Palm"; + sprite = "JPLAC0"; + width = 32; + height = 48; + } + 1308 + { + title = "Torch Flower"; + sprite = "TFLOA0"; + width = 14; + height = 110; + } + 1309 + { + title = "RVZ1 Wall Vine (Long)"; + sprite = "WVINALAR"; + width = 1; + height = 288; + } + 1310 + { + title = "RVZ1 Wall Vine (Short)"; + sprite = "WVINBLBR"; + width = 1; + height = 288; + } + } + + botanicserenity + { + color = 10; // Green + title = "Botanic Serenity"; + width = 16; + height = 32; + sprite = "BSZ1A0"; + 1400 + { + title = "Tall Flower (Red)"; + sprite = "BSZ1A0"; + } + 1401 + { + title = "Tall Flower (Purple)"; + sprite = "BSZ1B0"; + } + 1402 + { + title = "Tall Flower (Blue)"; + sprite = "BSZ1C0"; + } + 1403 + { + title = "Tall Flower (Cyan)"; + sprite = "BSZ1D0"; + } + 1404 + { + title = "Tall Flower (Yellow)"; + sprite = "BSZ1E0"; + } + 1405 + { + title = "Tall Flower (Orange)"; + sprite = "BSZ1F0"; + } + 1410 + { + title = "Medium Flower (Red)"; + sprite = "BSZ2A0"; + } + 1411 + { + title = "Medium Flower (Purple)"; + sprite = "BSZ2B0"; + } + 1412 + { + title = "Medium Flower (Blue)"; + sprite = "BSZ2C0"; + } + 1413 + { + title = "Medium Flower (Cyan)"; + sprite = "BSZ2D0"; + } + 1414 + { + title = "Medium Flower (Yellow)"; + sprite = "BSZ2E0"; + } + 1415 + { + title = "Medium Flower (Orange)"; + sprite = "BSZ2F0"; + } + 1420 + { + title = "Short Flower (Red)"; + sprite = "BSZ3A0"; + } + 1421 + { + title = "Short Flower (Purple)"; + sprite = "BSZ3B0"; + } + 1422 + { + title = "Short Flower (Blue)"; + sprite = "BSZ3C0"; + } + 1423 + { + title = "Short Flower (Cyan)"; + sprite = "BSZ3D0"; + } + 1424 + { + title = "Short Flower (Yellow)"; + sprite = "BSZ3E0"; + } + 1425 + { + title = "Short Flower (Orange)"; + sprite = "BSZ3F0"; + } + 1430 + { + title = "Tulip (Red)"; + sprite = "BST1A0"; + } + 1431 + { + title = "Tulip (Purple)"; + sprite = "BST2A0"; + } + 1432 + { + title = "Tulip (Blue)"; + sprite = "BST3A0"; + } + 1433 + { + title = "Tulip (Cyan)"; + sprite = "BST4A0"; + } + 1434 + { + title = "Tulip (Yellow)"; + sprite = "BST5A0"; + } + 1435 + { + title = "Tulip (Orange)"; + sprite = "BST6A0"; + } + 1440 + { + title = "Cluster (Red)"; + sprite = "BSZ5A0"; + } + 1441 + { + title = "Cluster (Purple)"; + sprite = "BSZ5B0"; + } + 1442 + { + title = "Cluster (Blue)"; + sprite = "BSZ5C0"; + } + 1443 + { + title = "Cluster (Cyan)"; + sprite = "BSZ5D0"; + } + 1444 + { + title = "Cluster (Yellow)"; + sprite = "BSZ5E0"; + } + 1445 + { + title = "Cluster (Orange)"; + sprite = "BSZ5F0"; + } + 1450 + { + title = "Bush (Red)"; + sprite = "BSZ6A0"; + } + 1451 + { + title = "Bush (Purple)"; + sprite = "BSZ6B0"; + } + 1452 + { + title = "Bush (Blue)"; + sprite = "BSZ6C0"; + } + 1453 + { + title = "Bush (Cyan)"; + sprite = "BSZ6D0"; + } + 1454 + { + title = "Bush (Yellow)"; + sprite = "BSZ6E0"; + } + 1455 + { + title = "Bush (Orange)"; + sprite = "BSZ6F0"; + } + 1460 + { + title = "Vine (Red)"; + sprite = "BSZ7A0"; + } + 1461 + { + title = "Vine (Purple)"; + sprite = "BSZ7B0"; + } + 1462 + { + title = "Vine (Blue)"; + sprite = "BSZ7C0"; + } + 1463 + { + title = "Vine (Cyan)"; + sprite = "BSZ7D0"; + } + 1464 + { + title = "Vine (Yellow)"; + sprite = "BSZ7E0"; + } + 1465 + { + title = "Vine (Orange)"; + sprite = "BSZ7F0"; + } + 1470 + { + title = "BSZ Shrub"; + sprite = "BSZ8A0"; + } + 1471 + { + title = "BSZ Clover"; + sprite = "BSZ8B0"; + } + 1473 + { + title = "Palm Tree (Big)"; + width = 16; + height = 160; + sprite = "BSZ8D0"; + } + 1475 + { + title = "Palm Tree (Small)"; + width = 16; + height = 80; + sprite = "BSZ8F0"; + } + } + + azuretemple + { + color = 10; // Green + title = "Azure Temple"; + + 1500 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1501 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Up)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1502 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Down)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1503 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Long)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1504 + { + title = "ATZ Target"; + sprite = "RCRYB0"; + width = 24; + height = 32; + } + 1505 + { + title = "Green Flame"; + sprite = "CFLMA0E0"; + width = 8; + height = 32; + } + 1506 + { + arrow = 1; + blocking = 2; + title = "Blue Gargoyle"; + sprite = "BGARD1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + } + + dreamhill + { + color = 10; // Green + title = "Dream Hill"; + + 1600 + { + title = "Spring Tree"; + sprite = "TRE6A0"; + width = 16; + height = 32; + } + 1601 + { + title = "Shleep"; + sprite = "SHLPA0"; + width = 24; + height = 32; + } + 1602 + { + title = "Pian"; + sprite = "NTPNALAR"; + width = 16; + height = 32; + } + } + + nightstrk + { + color = 13; // Pink + title = "NiGHTS Track"; + width = 8; + height = 4096; + sprite = "UNKNA0"; + + 1700 + { + title = "Axis"; + sprite = "internal:axis1"; + circle = 1; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + angletext = "Radius/Direction"; + parametertext = "Mare"; + } + 1701 + { + title = "Axis Transfer"; + sprite = "internal:axis2"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1702 + { + title = "Axis Transfer Line"; + sprite = "internal:axis3"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1710 + { + title = "Ideya Capture"; + sprite = "CAPSA0"; + width = 72; + height = 144; + angletext = "Rings"; + parametertext = "Mare"; + } + } + + nights + { + color = 13; // Pink + title = "NiGHTS Items"; + width = 16; + height = 32; + + 1703 + { + title = "Ideya Drone"; + sprite = "NDRNA1"; + width = 16; + height = 56; + flags1text = "[1] Align player to middle"; + flags4text = "[4] Align player to top"; + flags8text = "[8] Die upon time up"; + angletext = "Time limit"; + parametertext = "Height"; + } + 1704 + { + arrow = 1; + title = "NiGHTS Bumper"; + sprite = "NBMPG3G7"; + width = 32; + height = 64; + unflippable = true; + flagsvaluetext = "Pitch"; + angletext = "Yaw"; + } + 1705 + { + arrow = 1; + title = "Hoop (Generic)"; + sprite = "HOOPA0"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + flagsvaluetext = "Height"; + angletext = "Pitch/Yaw"; + } + 1706 + { + title = "Blue Sphere"; + sprite = "SPHRA0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + unflippable = true; + } + 1707 + { + title = "Super Paraloop"; + sprite = "NPRUA0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1708 + { + title = "Drill Refill"; + sprite = "NPRUB0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1709 + { + title = "Nightopian Helper"; + sprite = "NPRUC0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1711 + { + title = "Extra Time"; + sprite = "NPRUD0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1712 + { + title = "Link Freeze"; + sprite = "NPRUE0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1713 + { + arrow = 1; + title = "Hoop (Customizable)"; + flags1text = "[1] Radius +16"; + flags2text = "[2] Radius +32"; + flags4text = "[4] Radius +64"; + flags8text = "[8] Radius +128"; + sprite = "HOOPA0"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + } + 1714 + { + title = "Ideya Anchor Point"; + sprite = "internal:axis1"; + width = 8; + height = 16; + parametertext = "Ideya"; + } + } + + mario + { + color = 6; // Brown + title = "Mario"; + + 1800 + { + title = "Coin"; + sprite = "COINA0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + } + 1801 + { + arrow = 1; + title = "Goomba"; + sprite = "GOOMA0"; + width = 24; + height = 32; + } + 1802 + { + arrow = 1; + title = "Goomba (Blue)"; + sprite = "BGOMA0"; + width = 24; + height = 32; + } + 1803 + { + title = "Fire Flower"; + sprite = "FFWRB0"; + width = 16; + height = 32; + } + 1804 + { + title = "Koopa Shell"; + sprite = "SHLLA1"; + width = 16; + height = 20; + } + 1805 + { + title = "Puma (Jumping Fireball)"; + sprite = "PUMAA0"; + width = 8; + height = 16; + angletext = "Jump strength"; + } + 1806 + { + title = "King Bowser"; + sprite = "KOOPA0"; + width = 16; + height = 48; + } + 1807 + { + title = "Axe"; + sprite = "MAXEA0"; + width = 8; + height = 16; + } + 1808 + { + title = "Bush (Short)"; + sprite = "MUS1A0"; + width = 16; + height = 32; + } + 1809 + { + title = "Bush (Tall)"; + sprite = "MUS2A0"; + width = 16; + height = 32; + } + 1810 + { + title = "Toad"; + sprite = "TOADA0"; + width = 8; + height = 32; + } + } + + christmasdisco + { + color = 10; // Green + title = "Christmas & Disco"; + + 1850 + { + title = "Christmas Pole"; + sprite = "XMS1A0"; + width = 16; + height = 40; + } + 1851 + { + title = "Candy Cane"; + sprite = "XMS2A0"; + width = 8; + height = 32; + } + 1852 + { + blocking = 2; + title = "Snowman"; + sprite = "XMS3A0"; + width = 16; + height = 64; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1853 + { + blocking = 2; + title = "Snowman (With Hat)"; + sprite = "XMS3B0"; + width = 16; + height = 80; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1854 + { + title = "Lamp Post"; + sprite = "XMS4A0"; + width = 8; + height = 120; + } + 1855 + { + title = "Lamp Post (Snow)"; + sprite = "XMS4B0"; + width = 8; + height = 120; + } + 1856 + { + title = "Hanging Star"; + sprite = "XMS5A0"; + width = 4; + height = 80; + hangs = 1; + } + 1857 + { + title = "Berry Bush (Snow)"; + sprite = "BUS1B0"; + width = 16; + height = 32; + } + 1858 + { + title = "Bush (Snow)"; + sprite = "BUS2B0"; + width = 16; + height = 32; + } + 1859 + { + title = "Blueberry Bush (Snow)"; + sprite = "BUS3B0"; + width = 16; + height = 32; + } + 1875 + { + title = "Disco Ball"; + sprite = "DBALA0"; + width = 16; + height = 54; + hangs = 1; + } + 1876 + { + arrow = 1; + blocking = 2; + title = "Eggman Disco Statue"; + sprite = "ESTAB1"; + width = 20; + height = 96; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + } + + stalagmites + { + color = 10; // Green + title = "Stalagmites"; + width = 16; + height = 40; + + 1900 + { + title = "Brown Stalagmite (Tall)"; + sprite = "STLGA0"; + width = 16; + height = 40; + } + 1901 + { + title = "Brown Stalagmite"; + sprite = "STLGB0"; + width = 16; + height = 40; + } + 1902 + { + title = "Orange Stalagmite (Tall)"; + sprite = "STLGC0"; + width = 16; + height = 40; + } + 1903 + { + title = "Orange Stalagmite"; + sprite = "STLGD0"; + width = 16; + height = 40; + } + 1904 + { + title = "Red Stalagmite (Tall)"; + sprite = "STLGE0"; + width = 16; + height = 40; + } + 1905 + { + title = "Red Stalagmite"; + sprite = "STLGF0"; + width = 16; + height = 40; + } + 1906 + { + title = "Gray Stalagmite (Tall)"; + sprite = "STLGG0"; + width = 24; + height = 96; + } + 1907 + { + title = "Gray Stalagmite"; + sprite = "STLGH0"; + width = 16; + height = 40; + } + 1908 + { + title = "Blue Stalagmite (Tall)"; + sprite = "STLGI0"; + width = 16; + height = 40; + } + 1909 + { + title = "Blue Stalagmite"; + sprite = "STLGJ0"; + width = 16; + height = 40; + } + } + + hauntedheights + { + color = 10; // Green + title = "Haunted Heights"; + + 2000 + { + title = "Smashing Spikeball"; + sprite = "FMCEA0"; + width = 18; + height = 28; + angletext = "Initial delay"; + } + 2001 + { + title = "HHZ Grass"; + sprite = "HHZMA0"; + width = 16; + height = 40; + } + 2002 + { + title = "HHZ Tentacle 1"; + sprite = "HHZMB0"; + width = 16; + height = 40; + } + 2003 + { + title = "HHZ Tentacle 2"; + sprite = "HHZMC0"; + width = 16; + height = 40; + } + 2004 + { + title = "HHZ Stalagmite (Tall)"; + sprite = "HHZME0"; + width = 16; + height = 40; + } + 2005 + { + title = "HHZ Stalagmite (Short)"; + sprite = "HHZMF0"; + width = 16; + height = 40; + } + 2006 + { + title = "Jack-o'-lantern 1"; + sprite = "PUMKA0"; + width = 16; + height = 40; + flags1text = "Don't flicker"; + } + 2007 + { + title = "Jack-o'-lantern 2"; + sprite = "PUMKB0"; + width = 16; + height = 40; + flags1text = "Don't flicker"; + } + 2008 + { + title = "Jack-o'-lantern 3"; + sprite = "PUMKC0"; + width = 16; + height = 40; + flags1text = "Don't flicker"; + } + 2009 + { + title = "Purple Mushroom"; + sprite = "SHRMD0"; + width = 16; + height = 48; + } + 2010 + { + title = "HHZ Tree"; + sprite = "HHPLC0"; + width = 12; + height = 40; + } + } + + frozenhillside + { + color = 10; // Green + title = "Frozen Hillside"; + + 2100 + { + title = "Ice Shard (Small)"; + sprite = "FHZIA0"; + width = 8; + height = 32; + } + 2101 + { + title = "Ice Shard (Large)"; + sprite = "FHZIB0"; + width = 8; + height = 32; + } + 2102 + { + title = "Crystal Tree (Aqua)"; + sprite = "TRE3A0"; + width = 20; + height = 200; + } + 2103 + { + title = "Crystal Tree (Pink)"; + sprite = "TRE3B0"; + width = 20; + height = 200; + } + 2104 + { + title = "Amy Cameo"; + sprite = "ROSYA1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + } + 2105 + { + title = "Mistletoe"; + sprite = "XMS6A0"; + width = 52; + height = 106; + } + } + + flickies + { + color = 10; // Green + title = "Flickies"; + width = 8; + height = 20; + flags1text = "[1] Move aimlessly"; + flags4text = "[4] No movement"; + flags8text = "[8] Hop"; + angletext = "Radius"; + + 2200 + { + title = "Bluebird"; + sprite = "FL01A1"; + } + 2201 + { + title = "Rabbit"; + sprite = "FL02A1"; + } + 2202 + { + title = "Chicken"; + sprite = "FL03A1"; + } + 2203 + { + title = "Seal"; + sprite = "FL04A1"; + } + 2204 + { + title = "Pig"; + sprite = "FL05A1"; + } + 2205 + { + title = "Chipmunk"; + sprite = "FL06A1"; + } + 2206 + { + title = "Penguin"; + sprite = "FL07A1"; + } + 2207 + { + title = "Fish"; + sprite = "FL08A1"; + parametertext = "Color"; + } + 2208 + { + title = "Ram"; + sprite = "FL09A1"; + } + 2209 + { + title = "Puffin"; + sprite = "FL10A1"; + } + 2210 + { + title = "Cow"; + sprite = "FL11A1"; + } + 2211 + { + title = "Rat"; + sprite = "FL12A1"; + } + 2212 + { + title = "Bear"; + sprite = "FL13A1"; + } + 2213 + { + title = "Dove"; + sprite = "FL14A1"; + } + 2214 + { + title = "Cat"; + sprite = "FL15A1"; + } + 2215 + { + title = "Canary"; + sprite = "FL16A1"; + } + 2216 + { + title = "Spider"; + sprite = "FS01A1"; + } + 2217 + { + title = "Bat"; + sprite = "FS02A0"; + } + } +} + +//Default things filters +thingsfilters +{ + + filter0 + { + name = "Player starts"; + category = "starts"; + type = -1; + } + + + filter1 + { + name = "Enemies"; + category = "enemies"; + type = -1; + + } + + + filter2 + { + name = "NiGHTS Track"; + category = "nightstrk"; + type = -1; + + } + + + filter3 + { + name = "Normal Gravity"; + category = ""; + type = -1; + + fields + { + 2 = false; + } + + } + + + filter4 + { + name = "Reverse Gravity"; + category = ""; + type = -1; + + fields + { + 2 = true; + } + + } +} From 0d15f27026291644f1cfcf99e098d2d4346e450c Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 28 Dec 2019 21:57:29 -0500 Subject: [PATCH 229/312] Fix emerald hunt not working properly --- src/g_game.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 19b18ef8c..518b5564e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1854,8 +1854,7 @@ void G_DoLoadLevel(boolean resetplayer) return; } - if (!resetplayer) - P_FindEmerald(); + P_FindEmerald(); displayplayer = consoleplayer; // view the guy you are playing if (!splitscreen && !botingame) From cfadbb0f360034ca5cbbd06cf491219251dd55d8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 09:39:50 +0100 Subject: [PATCH 230/312] -Add linedef pointer to side_t, so sidedefs are able to tell if they're a front or back sidedef during setup -Fix a broken condition during setup of texture fields for the change music linedef --- src/lua_maplib.c | 5 +++++ src/p_setup.c | 16 ++++++++++++---- src/r_defs.h | 13 ++++++------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 8ad66d04f..8ce6551f7 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -134,6 +134,7 @@ enum side_e { side_toptexture, side_bottomtexture, side_midtexture, + side_line, side_sector, side_special, side_repeatcnt, @@ -869,6 +870,9 @@ static int side_get(lua_State *L) case side_midtexture: lua_pushinteger(L, side->midtexture); return 1; + case side_line: + LUA_PushUserdata(L, side->line, META_LINE); + return 1; case side_sector: LUA_PushUserdata(L, side->sector, META_SECTOR); return 1; @@ -902,6 +906,7 @@ static int side_set(lua_State *L) switch(field) { case side_valid: // valid + case side_line: case side_sector: case side_special: case side_text: diff --git a/src/p_setup.c b/src/p_setup.c index 8d92c3e87..52c79e1ce 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1008,10 +1008,18 @@ static void P_InitializeLinedef(line_t *ld) CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1((size_t)(ld - lines))); } - if (ld->sidenum[0] != 0xffff && ld->special) + if (ld->sidenum[0] != 0xffff) + { sides[ld->sidenum[0]].special = ld->special; - if (ld->sidenum[1] != 0xffff && ld->special) + sides[ld->sidenum[0]].line = ld; + + } + if (ld->sidenum[1] != 0xffff) + { sides[ld->sidenum[1]].special = ld->special; + sides[ld->sidenum[1]].line = ld; + + } } static void P_LoadLinedefs(UINT8 *data) @@ -1044,6 +1052,7 @@ static void P_LoadSidedefs(UINT8 *data) for (i = 0; i < numsides; i++, sd++, msd++) { UINT16 sector_num; + boolean isfrontside = !sd->line || sd->line->sidenum[0] == i; sd->textureoffset = SHORT(msd->textureoffset)<rowoffset = SHORT(msd->rowoffset)<midtexture = get_number(process); } - // always process if back sidedef, because we need that - symbol sd->text = Z_Malloc(7, PU_LEVEL, NULL); - if (i == 1 || msd->toptexture[0] != '-' || msd->toptexture[1] != '\0') + if (isfrontside && !(msd->toptexture[0] == '-' && msd->toptexture[1] == '\0')) { M_Memcpy(process,msd->toptexture,8); process[8] = '\0'; diff --git a/src/r_defs.h b/src/r_defs.h index 353dc572b..4cb02f4f5 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -436,14 +436,10 @@ typedef struct line_s polyobj_t *polyobj; // Belongs to a polyobject? #endif - char *text; // a concatination of all front and back texture names, for linedef specials that require a string. + char *text; // a concatenation of all front and back texture names, for linedef specials that require a string. INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0 } line_t; -// -// The SideDef. -// - typedef struct { // add this to the calculated texture column @@ -456,13 +452,16 @@ typedef struct // We do not maintain names here. INT32 toptexture, bottomtexture, midtexture; - // Sector the SideDef is facing. + // Linedef the sidedef belongs to + line_t *line; + + // Sector the sidedef is facing. sector_t *sector; INT16 special; // the special of the linedef this side belongs to INT16 repeatcnt; // # of times to repeat midtexture - char *text; // a concatination of all top, bottom, and mid texture names, for linedef specials that require a string. + char *text; // a concatenation of all top, bottom, and mid texture names, for linedef specials that require a string. extracolormap_t *colormap_data; // storage for colormaps; not applied to sectors. } side_t; From abdfe60aa7a05297cc7f4c325c37b4a35913267f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 12:01:41 +0100 Subject: [PATCH 231/312] Store custom FOF flags directly in back toptexture field at map load instead of re-reading the sidedefs data later on --- src/p_setup.c | 14 ++++++++++++++ src/p_spec.c | 32 ++++---------------------------- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 52c79e1ce..ea61a2ec7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1179,6 +1179,20 @@ static void P_LoadSidedefs(UINT8 *data) break; } + case 259: // Custom FOF + if (!isfrontside) + { + if ((msd->toptexture[0] >= '0' && msd->toptexture[0] <= '9') + || (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F')) + sd->toptexture = axtoi(msd->toptexture); + else + I_Error("Custom FOF (tag %d) needs a value in the linedef's back side upper texture field.", sd->line->tag); + + sd->midtexture = R_TextureNumForName(msd->midtexture); + sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); + break; + } + // FALLTHRU default: // normal cases if (msd->toptexture[0] == '#') { diff --git a/src/p_spec.c b/src/p_spec.c index 20f1c8278..7915956c8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7179,38 +7179,14 @@ void P_SpawnSpecials(boolean fromnetsave) EV_AddLaserThinker(§ors[s], §ors[sec], lines + i, secthinkers); break; - case 259: // Make-Your-Own FOF! + case 259: // Custom FOF if (lines[i].sidenum[1] != 0xffff) { - UINT8 *data; - UINT16 b; - - if (!virt) - virt = vres_GetMap(lastloadedmaplumpnum); - - data = (UINT8*) vres_Find(virt, "SIDEDEFS")->data; - - for (b = 0; b < (INT16)numsides; b++) - { - register mapsidedef_t *msd = (mapsidedef_t *)data + b; - - if (b == lines[i].sidenum[1]) - { - if ((msd->toptexture[0] >= '0' && msd->toptexture[0] <= '9') - || (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F')) - { - ffloortype_e FOF_Flags = axtoi(msd->toptexture); - - P_AddFakeFloorsByLine(i, FOF_Flags, secthinkers); - break; - } - else - I_Error("Make-Your-Own-FOF (tag %d) needs a value in the linedef's second side upper texture field.", lines[i].tag); - } - } + ffloortype_e fofflags = sides[lines[i].sidenum[1]].toptexture; + P_AddFakeFloorsByLine(i, fofflags, secthinkers); } else - I_Error("Make-Your-Own FOF (tag %d) found without a 2nd linedef side!", lines[i].tag); + I_Error("Custom FOF (tag %d) found without a linedef back side!", lines[i].tag); break; case 300: // Linedef executor (combines with sector special 974/975) and commands From c43a83dc04e2457ab017b8dc5b813c5f9f5824e8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 12:26:02 +0100 Subject: [PATCH 232/312] Remove virtres_t pointer in P_SpawnSpecials that's no longer needed --- src/p_spec.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 7915956c8..4de488654 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6433,7 +6433,6 @@ void P_SpawnSpecials(boolean fromnetsave) INT32 j; thinkerlist_t *secthinkers; thinker_t *th; - virtres_t* virt = NULL; // This used to be used, and *should* be used in the future, // but currently isn't. (void)fromnetsave; @@ -7409,9 +7408,6 @@ void P_SpawnSpecials(boolean fromnetsave) } } - if (virt) - vres_Free(virt); - // Allocate each list for (i = 0; i < numsectors; i++) if(secthinkers[i].thinkers) From 389b9e35c481a9c26e1f968e6b1d8d28e89284d9 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 29 Dec 2019 14:17:51 +0100 Subject: [PATCH 233/312] Add XNOD, XGLN and XGL3 BSP formats recognition and support. --- src/hardware/hw_main.c | 2 + src/p_polyobj.c | 10 ++ src/p_setup.c | 313 ++++++++++++++++++++++++++++++++++++++--- src/r_bsp.c | 4 +- src/r_defs.h | 1 + src/r_segs.c | 4 + 6 files changed, 317 insertions(+), 17 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 41e2c5693..48e66e114 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2714,6 +2714,8 @@ static void HWR_AddLine(seg_t * line) static sector_t tempsec; fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t + if (line->glseg) + return; #ifdef POLYOBJECTS if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES)) return; diff --git a/src/p_polyobj.c b/src/p_polyobj.c index c37926adf..4709e5e6f 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -400,6 +400,8 @@ static void Polyobj_findSegs(polyobj_t *po, seg_t *seg) // Find backfacings for (s = 0; s < numsegs; s++) { + if (segs[s].glseg) + continue; if (segs[s].linedef == seg->linedef && segs[s].side == 1) { @@ -436,6 +438,8 @@ newseg: // seg's ending vertex. for (i = 0; i < numsegs; ++i) { + if (segs[i].glseg) + continue; if (segs[i].side != 0) // needs to be frontfacing continue; if (segs[i].v1->x == seg->v2->x && segs[i].v1->y == seg->v2->y) @@ -460,6 +464,9 @@ newseg: // Find backfacings for (q = 0; q < numsegs; q++) { + if (segs[q].glseg) + continue; + if (segs[q].linedef == segs[i].linedef && segs[q].side == 1) { @@ -606,6 +613,9 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id) INT32 poflags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES; INT32 parentID = 0, potrans = 0; + if (seg->glseg) + continue; + if (seg->side != 0) // needs to be frontfacing continue; diff --git a/src/p_setup.c b/src/p_setup.c index ea61a2ec7..b74bf83a2 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1456,31 +1456,312 @@ static void P_LoadSegs(UINT8 *data) } } +// Auxiliary function: Shrink node ID from 32-bit to 16-bit. +static UINT16 ShrinkNodeID(UINT32 x) { + UINT16 mask = (x >> 16) & 0xC000; + UINT16 result = x; + return result | mask; +} + +typedef enum { + NT_DOOM, + NT_XNOD, + NT_ZNOD, + NT_XGLN, + NT_ZGLN, + NT_XGL2, + NT_ZGL2, + NT_XGL3, + NT_ZGL3, + NT_UNSUPPORTED +} nodetype_t; + static void P_LoadMapBSP(const virtres_t *virt) { virtlump_t* virtssectors = vres_Find(virt, "SSECTORS"); virtlump_t* virtsegs = vres_Find(virt, "SEGS"); virtlump_t* virtnodes = vres_Find(virt, "NODES"); - numsubsectors = virtssectors->size / sizeof(mapsubsector_t); - numnodes = virtnodes->size / sizeof(mapnode_t); - numsegs = virtsegs->size / sizeof(mapseg_t); + nodetype_t nodetype = NT_UNSUPPORTED; - if (numsubsectors <= 0) - I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); - if (numnodes <= 0) - I_Error("Level has no nodes"); - if (numsegs <= 0) - I_Error("Level has no segs"); + // Find out the BSP format. + if (vres_Find(virt, "TEXTMAP")) + { + virtnodes = vres_Find(virt, "ZNODES"); + if (!memcmp(virtnodes->data, "XGLN", 4)) + nodetype = NT_XGLN; + else if (!memcmp(virtnodes->data, "XGL3", 4)) + nodetype = NT_XGL3; + } + else + { + if (!virtsegs || !virtsegs->size) + { + // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature. + if (!virtssectors || !virtssectors->size) + { + if (!memcmp(virtnodes->data, "XNOD", 4)) + nodetype = NT_XNOD; + else if (!memcmp(virtnodes->data, "ZNOD", 4)) // Compressed variant. + nodetype = NT_ZNOD; + } + // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature. + else + { + if (!memcmp(virtssectors->data, "XGLN", 4)) + { + virtnodes = virtssectors; + nodetype = NT_XGLN; + } + else if (!memcmp(virtssectors->data, "ZGLN", 4)) // Compressed variant. + { + virtnodes = virtssectors; + nodetype = NT_ZGLN; + } + else if (!memcmp(virtssectors->data, "XGL3", 4)) // Compressed variant. + { + virtnodes = virtssectors; + nodetype = NT_XGL3; + } + } + } + else // Traditional map format BSP tree. + nodetype = NT_DOOM; + } - subsectors = Z_Calloc(numsubsectors * sizeof(*subsectors), PU_LEVEL, NULL); - nodes = Z_Calloc(numnodes * sizeof(*nodes), PU_LEVEL, NULL); - segs = Z_Calloc(numsegs * sizeof(*segs), PU_LEVEL, NULL); + switch (nodetype) + { + case NT_DOOM: + numsubsectors = virtssectors->size / sizeof(mapsubsector_t); + numnodes = virtnodes->size / sizeof(mapnode_t); + numsegs = virtsegs->size / sizeof(mapseg_t); - // Nodes - P_LoadSubsectors(virtssectors->data); - P_LoadNodes(virtnodes->data); - P_LoadSegs(virtsegs->data); + if (numsubsectors <= 0) + I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); + if (numnodes <= 0) + I_Error("Level has no nodes"); + if (numsegs <= 0) + I_Error("Level has no segs"); + + subsectors = Z_Calloc(numsubsectors * sizeof(*subsectors), PU_LEVEL, NULL); + nodes = Z_Calloc(numnodes * sizeof(*nodes), PU_LEVEL, NULL); + segs = Z_Calloc(numsegs * sizeof(*segs), PU_LEVEL, NULL); + + P_LoadSubsectors(virtssectors->data); + P_LoadNodes(virtnodes->data); + P_LoadSegs(virtsegs->data); + break; + + case NT_XNOD: + case NT_XGLN: + case NT_XGL3: + { + size_t i, j, k; + INT16 m; + UINT8* data = virtnodes->data + 4; + + /// Extended node formats feature additional vertexes; useful for OpenGL, but totally useless in gamelogic. + UINT32 orivtx, xtrvtx; + orivtx = READUINT32(data); + xtrvtx = READUINT32(data); + + if (numvertexes != orivtx) /// If native vertex count doesn't match node original vertex count, bail out (broken data?). + { + CONS_Alert(CONS_WARNING, "Vertex count in map data and nodes differ!\n"); + return; + } + + if (xtrvtx) /// If extra vertexes were generated, reallocate the vertex array and fix the pointers. + { + line_t* ld = lines; + size_t oldpos = (size_t) vertexes; + ssize_t offset; + numvertexes+= xtrvtx; + vertexes = Z_Realloc(vertexes, numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); + offset = ((size_t) vertexes) - oldpos; + + for (i = 0, ld = lines; i < numlines; i++, ld++) + { + ld->v1 = (vertex_t*) ((size_t) ld->v1 + offset); + ld->v2 = (vertex_t*) ((size_t) ld->v2 + offset); + } + } + + // Read vertex data. + for (i = orivtx; i < numvertexes; i++) + { + vertexes[i].x = READFIXED(data); + vertexes[i].y = READFIXED(data); + } + + // Subsectors + numsubsectors = READUINT32(data); + subsectors = Z_Calloc(numsubsectors * sizeof (*subsectors), PU_LEVEL, NULL); + + for (i = 0; i < numsubsectors; i++) + subsectors[i].numlines = READUINT32(data); + + // Segs + numsegs = READUINT32(data); + segs = Z_Calloc(numsegs * sizeof (*segs), PU_LEVEL, NULL); + + for (i = 0, k = 0; i < numsubsectors; i++) + { + subsectors[i].firstline = k; + + switch (nodetype) + { + case NT_XGLN: + for (m = 0; m < subsectors[i].numlines; m++, k++) + { + UINT16 linenum; + UINT32 vert; + vert = READUINT32(data); + segs[k].v1 = &vertexes[vert]; + if (m == 0) + segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert]; + else + segs[k - 1].v2 = segs[k].v1; + data += 4;// partner; can be ignored by software renderer; + linenum = READUINT16(data); + if (linenum == 0xFFFF) + { + segs[k].glseg = true; + segs[k].linedef = NULL; + } + else + { + segs[k].glseg = false; + segs[k].linedef = &lines[linenum]; + } + segs[k].side = READUINT8(data); + } + break; + + case NT_XGL3: + for (m = 0; m < subsectors[i].numlines; m++, k++) + { + UINT32 linenum; + UINT32 vert; + vert = READUINT32(data); + segs[k].v1 = &vertexes[vert]; + if (m == 0) + segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert]; + else + segs[k - 1].v2 = segs[k].v1; + data += 4;// partner; can be ignored by software renderer; + linenum = READUINT32(data); + if (linenum == 0xFFFFFFFF) + { + segs[k].glseg = true; + segs[k].linedef = NULL; + } + else + { + segs[k].glseg = false; + segs[k].linedef = NULL; + } + segs[k].side = READUINT8(data); + } + break; + + case NT_XNOD: + for (m = 0; m < subsectors[i].numlines; m++, k++) + { + segs[k].v1 = &vertexes[READUINT32(data)]; + segs[k].v2 = &vertexes[READUINT32(data)]; + segs[k].linedef = &lines[READUINT16(data)]; + segs[k].side = READUINT8(data); + } + break; + + default: + return; + } + } + + { + INT32 side; + seg_t *li; + + for (i = 0, li = segs; i < numsegs; i++, li++) + { + vertex_t *v1 = li->v1; + vertex_t *v2 = li->v2; + li->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y); + li->offset = FixedHypot(v1->x - li->linedef->v1->x, v1->y - li->linedef->v1->y); + side = li->side; + li->sidedef = &sides[li->linedef->sidenum[side]]; + + li->frontsector = sides[li->linedef->sidenum[side]].sector; + if (li->linedef->flags & ML_TWOSIDED) + li->backsector = sides[li->linedef->sidenum[side^1]].sector; + else + li->backsector = 0; + + segs[i].numlights = 0; + segs[i].rlights = NULL; + } + } + + // Nodes + numnodes = READINT32(data); + nodes = Z_Calloc(numnodes * sizeof (*nodes), PU_LEVEL, NULL); + if (nodetype == NT_XGL3) + { + UINT32 x, y, dx, dy; + UINT32 c0, c1; + node_t *mn; + for (i = 0, mn = nodes; i < numnodes; i++, mn++) + { + // Splitter. + x = READINT32(data); + y = READINT32(data); + dx = READINT32(data); + dy = READINT32(data); + mn->x = x; + mn->y = y; + mn->dx = dx; + mn->dy = dy; + + // Bounding boxes and children. + for (j = 0; j < 2; j++) + for (k = 0; k < 4; k++) + mn->bbox[j][k] = READINT16(data)<children[0] = ShrinkNodeID(c0); /// \todo Use UINT32 for node children in a future, instead? + mn->children[1] = ShrinkNodeID(c1); + } + } + else + { + UINT32 c0, c1; + node_t *mn; + for (i = 0, mn = nodes; i < numnodes; i++, mn++) + { + // Splitter. + mn->x = READINT16(data)<y = READINT16(data)<dx = READINT16(data)<dy = READINT16(data)<bbox[j][k] = READINT16(data)<children[0] = ShrinkNodeID(c0); /// \todo Use UINT32 for node children in a future, instead? + mn->children[1] = ShrinkNodeID(c1); + } + } + } + break; + default: + CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n"); + return; + } + return; } // Split from P_LoadBlockMap for convenience diff --git a/src/r_bsp.c b/src/r_bsp.c index 51d9bd3fd..6b4667aee 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -1169,9 +1169,11 @@ static void R_Subsector(size_t num) while (count--) { // CONS_Debug(DBG_GAMELOGIC, "Adding normal line %d...(%d)\n", line->linedef-lines, leveltime); + if (!line->glseg #ifdef POLYOBJECTS - if (!line->polyseg) // ignore segs that belong to polyobjects + && !line->polyseg // ignore segs that belong to polyobjects #endif + ) R_AddLine(line); line++; curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so stuff doesn't try using it for other things */ diff --git a/src/r_defs.h b/src/r_defs.h index 4cb02f4f5..ceb694c57 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -586,6 +586,7 @@ typedef struct seg_s polyobj_t *polyseg; boolean dontrenderme; #endif + boolean glseg; } seg_t; // diff --git a/src/r_segs.c b/src/r_segs.c index 29120ebb8..0fc91a823 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -308,6 +308,10 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // for horizontal / vertical / diagonal. Diagonal? // OPTIMIZE: get rid of LIGHTSEGSHIFT globally curline = ds->curline; + + if (curline->glseg) + return; + frontsector = curline->frontsector; backsector = curline->backsector; texnum = R_GetTextureNum(curline->sidedef->midtexture); From 8032054a47bcb41d17e25870eb2c671525c0ad90 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 15:15:32 +0100 Subject: [PATCH 234/312] Separate loading of extended nodes into its own file --- src/p_setup.c | 404 +++++++++++++++++++++++++------------------------- 1 file changed, 203 insertions(+), 201 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index b74bf83a2..a0eb52bc8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1476,6 +1476,208 @@ typedef enum { NT_UNSUPPORTED } nodetype_t; +static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) +{ + size_t i, j, k; + INT16 m; + + /// Extended node formats feature additional vertexes; useful for OpenGL, but totally useless in gamelogic. + UINT32 orivtx, xtrvtx; + orivtx = READUINT32(data); + xtrvtx = READUINT32(data); + + if (numvertexes != orivtx) /// If native vertex count doesn't match node original vertex count, bail out (broken data?). + { + CONS_Alert(CONS_WARNING, "Vertex count in map data and nodes differ!\n"); + return; + } + + if (xtrvtx) /// If extra vertexes were generated, reallocate the vertex array and fix the pointers. + { + line_t *ld = lines; + size_t oldpos = (size_t)vertexes; + ssize_t offset; + numvertexes += xtrvtx; + vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL); + offset = ((size_t)vertexes) - oldpos; + + for (i = 0, ld = lines; i < numlines; i++, ld++) + { + ld->v1 = (vertex_t*)((size_t)ld->v1 + offset); + ld->v2 = (vertex_t*)((size_t)ld->v2 + offset); + } + } + + // Read vertex data. + for (i = orivtx; i < numvertexes; i++) + { + vertexes[i].x = READFIXED(data); + vertexes[i].y = READFIXED(data); + } + + // Subsectors + numsubsectors = READUINT32(data); + subsectors = Z_Calloc(numsubsectors*sizeof(*subsectors), PU_LEVEL, NULL); + + for (i = 0; i < numsubsectors; i++) + subsectors[i].numlines = READUINT32(data); + + // Segs + numsegs = READUINT32(data); + segs = Z_Calloc(numsegs*sizeof(*segs), PU_LEVEL, NULL); + + for (i = 0, k = 0; i < numsubsectors; i++) + { + subsectors[i].firstline = k; + + switch (nodetype) + { + case NT_XGLN: + for (m = 0; m < subsectors[i].numlines; m++, k++) + { + UINT16 linenum; + UINT32 vert; + vert = READUINT32(data); + segs[k].v1 = &vertexes[vert]; + if (m == 0) + segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert]; + else + segs[k - 1].v2 = segs[k].v1; + data += 4;// partner; can be ignored by software renderer; + linenum = READUINT16(data); + if (linenum == 0xFFFF) + { + segs[k].glseg = true; + segs[k].linedef = NULL; + } + else + { + segs[k].glseg = false; + segs[k].linedef = &lines[linenum]; + } + segs[k].side = READUINT8(data); + } + break; + + case NT_XGL3: + for (m = 0; m < subsectors[i].numlines; m++, k++) + { + UINT32 linenum; + UINT32 vert; + vert = READUINT32(data); + segs[k].v1 = &vertexes[vert]; + if (m == 0) + segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert]; + else + segs[k - 1].v2 = segs[k].v1; + data += 4;// partner; can be ignored by software renderer; + linenum = READUINT32(data); + if (linenum == 0xFFFFFFFF) + { + segs[k].glseg = true; + segs[k].linedef = NULL; + } + else + { + segs[k].glseg = false; + segs[k].linedef = NULL; + } + segs[k].side = READUINT8(data); + } + break; + + case NT_XNOD: + for (m = 0; m < subsectors[i].numlines; m++, k++) + { + segs[k].v1 = &vertexes[READUINT32(data)]; + segs[k].v2 = &vertexes[READUINT32(data)]; + segs[k].linedef = &lines[READUINT16(data)]; + segs[k].side = READUINT8(data); + } + break; + + default: + return; + } + } + + { + INT32 side; + seg_t *li; + + for (i = 0, li = segs; i < numsegs; i++, li++) + { + vertex_t *v1 = li->v1; + vertex_t *v2 = li->v2; + li->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y); + li->offset = FixedHypot(v1->x - li->linedef->v1->x, v1->y - li->linedef->v1->y); + side = li->side; + li->sidedef = &sides[li->linedef->sidenum[side]]; + + li->frontsector = sides[li->linedef->sidenum[side]].sector; + if (li->linedef->flags & ML_TWOSIDED) + li->backsector = sides[li->linedef->sidenum[side ^ 1]].sector; + else + li->backsector = 0; + + segs[i].numlights = 0; + segs[i].rlights = NULL; + } + } + + // Nodes + numnodes = READINT32(data); + nodes = Z_Calloc(numnodes*sizeof(*nodes), PU_LEVEL, NULL); + if (nodetype == NT_XGL3) + { + UINT32 x, y, dx, dy; + UINT32 c0, c1; + node_t *mn; + for (i = 0, mn = nodes; i < numnodes; i++, mn++) + { + // Splitter. + x = READINT32(data); + y = READINT32(data); + dx = READINT32(data); + dy = READINT32(data); + mn->x = x; + mn->y = y; + mn->dx = dx; + mn->dy = dy; + + // Bounding boxes and children. + for (j = 0; j < 2; j++) + for (k = 0; k < 4; k++) + mn->bbox[j][k] = READINT16(data) << FRACBITS; + c0 = READUINT32(data); + c1 = READUINT32(data); + mn->children[0] = ShrinkNodeID(c0); /// \todo Use UINT32 for node children in a future, instead? + mn->children[1] = ShrinkNodeID(c1); + } + } + else + { + UINT32 c0, c1; + node_t *mn; + for (i = 0, mn = nodes; i < numnodes; i++, mn++) + { + // Splitter. + mn->x = READINT16(data) << FRACBITS; + mn->y = READINT16(data) << FRACBITS; + mn->dx = READINT16(data) << FRACBITS; + mn->dy = READINT16(data) << FRACBITS; + // Bounding boxes and children. + for (j = 0; j < 2; j++) + for (k = 0; k < 4; k++) + mn->bbox[j][k] = READINT16(data) << FRACBITS; + c0 = READUINT32(data); + c1 = READUINT32(data); + mn->children[0] = ShrinkNodeID(c0); /// \todo Use UINT32 for node children in a future, instead? + mn->children[1] = ShrinkNodeID(c1); + } + } +} + static void P_LoadMapBSP(const virtres_t *virt) { virtlump_t* virtssectors = vres_Find(virt, "SSECTORS"); @@ -1555,207 +1757,7 @@ static void P_LoadMapBSP(const virtres_t *virt) case NT_XNOD: case NT_XGLN: case NT_XGL3: - { - size_t i, j, k; - INT16 m; - UINT8* data = virtnodes->data + 4; - - /// Extended node formats feature additional vertexes; useful for OpenGL, but totally useless in gamelogic. - UINT32 orivtx, xtrvtx; - orivtx = READUINT32(data); - xtrvtx = READUINT32(data); - - if (numvertexes != orivtx) /// If native vertex count doesn't match node original vertex count, bail out (broken data?). - { - CONS_Alert(CONS_WARNING, "Vertex count in map data and nodes differ!\n"); - return; - } - - if (xtrvtx) /// If extra vertexes were generated, reallocate the vertex array and fix the pointers. - { - line_t* ld = lines; - size_t oldpos = (size_t) vertexes; - ssize_t offset; - numvertexes+= xtrvtx; - vertexes = Z_Realloc(vertexes, numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); - offset = ((size_t) vertexes) - oldpos; - - for (i = 0, ld = lines; i < numlines; i++, ld++) - { - ld->v1 = (vertex_t*) ((size_t) ld->v1 + offset); - ld->v2 = (vertex_t*) ((size_t) ld->v2 + offset); - } - } - - // Read vertex data. - for (i = orivtx; i < numvertexes; i++) - { - vertexes[i].x = READFIXED(data); - vertexes[i].y = READFIXED(data); - } - - // Subsectors - numsubsectors = READUINT32(data); - subsectors = Z_Calloc(numsubsectors * sizeof (*subsectors), PU_LEVEL, NULL); - - for (i = 0; i < numsubsectors; i++) - subsectors[i].numlines = READUINT32(data); - - // Segs - numsegs = READUINT32(data); - segs = Z_Calloc(numsegs * sizeof (*segs), PU_LEVEL, NULL); - - for (i = 0, k = 0; i < numsubsectors; i++) - { - subsectors[i].firstline = k; - - switch (nodetype) - { - case NT_XGLN: - for (m = 0; m < subsectors[i].numlines; m++, k++) - { - UINT16 linenum; - UINT32 vert; - vert = READUINT32(data); - segs[k].v1 = &vertexes[vert]; - if (m == 0) - segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert]; - else - segs[k - 1].v2 = segs[k].v1; - data += 4;// partner; can be ignored by software renderer; - linenum = READUINT16(data); - if (linenum == 0xFFFF) - { - segs[k].glseg = true; - segs[k].linedef = NULL; - } - else - { - segs[k].glseg = false; - segs[k].linedef = &lines[linenum]; - } - segs[k].side = READUINT8(data); - } - break; - - case NT_XGL3: - for (m = 0; m < subsectors[i].numlines; m++, k++) - { - UINT32 linenum; - UINT32 vert; - vert = READUINT32(data); - segs[k].v1 = &vertexes[vert]; - if (m == 0) - segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert]; - else - segs[k - 1].v2 = segs[k].v1; - data += 4;// partner; can be ignored by software renderer; - linenum = READUINT32(data); - if (linenum == 0xFFFFFFFF) - { - segs[k].glseg = true; - segs[k].linedef = NULL; - } - else - { - segs[k].glseg = false; - segs[k].linedef = NULL; - } - segs[k].side = READUINT8(data); - } - break; - - case NT_XNOD: - for (m = 0; m < subsectors[i].numlines; m++, k++) - { - segs[k].v1 = &vertexes[READUINT32(data)]; - segs[k].v2 = &vertexes[READUINT32(data)]; - segs[k].linedef = &lines[READUINT16(data)]; - segs[k].side = READUINT8(data); - } - break; - - default: - return; - } - } - - { - INT32 side; - seg_t *li; - - for (i = 0, li = segs; i < numsegs; i++, li++) - { - vertex_t *v1 = li->v1; - vertex_t *v2 = li->v2; - li->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y); - li->offset = FixedHypot(v1->x - li->linedef->v1->x, v1->y - li->linedef->v1->y); - side = li->side; - li->sidedef = &sides[li->linedef->sidenum[side]]; - - li->frontsector = sides[li->linedef->sidenum[side]].sector; - if (li->linedef->flags & ML_TWOSIDED) - li->backsector = sides[li->linedef->sidenum[side^1]].sector; - else - li->backsector = 0; - - segs[i].numlights = 0; - segs[i].rlights = NULL; - } - } - - // Nodes - numnodes = READINT32(data); - nodes = Z_Calloc(numnodes * sizeof (*nodes), PU_LEVEL, NULL); - if (nodetype == NT_XGL3) - { - UINT32 x, y, dx, dy; - UINT32 c0, c1; - node_t *mn; - for (i = 0, mn = nodes; i < numnodes; i++, mn++) - { - // Splitter. - x = READINT32(data); - y = READINT32(data); - dx = READINT32(data); - dy = READINT32(data); - mn->x = x; - mn->y = y; - mn->dx = dx; - mn->dy = dy; - - // Bounding boxes and children. - for (j = 0; j < 2; j++) - for (k = 0; k < 4; k++) - mn->bbox[j][k] = READINT16(data)<children[0] = ShrinkNodeID(c0); /// \todo Use UINT32 for node children in a future, instead? - mn->children[1] = ShrinkNodeID(c1); - } - } - else - { - UINT32 c0, c1; - node_t *mn; - for (i = 0, mn = nodes; i < numnodes; i++, mn++) - { - // Splitter. - mn->x = READINT16(data)<y = READINT16(data)<dx = READINT16(data)<dy = READINT16(data)<bbox[j][k] = READINT16(data)<children[0] = ShrinkNodeID(c0); /// \todo Use UINT32 for node children in a future, instead? - mn->children[1] = ShrinkNodeID(c1); - } - } - } + P_LoadExtendedNodes(virtnodes->data + 4, nodetype); break; default: CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n"); From 0aed60f4de10349e6f746eb1d89ecea6677efca1 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 15:50:53 +0100 Subject: [PATCH 235/312] Separate retrieval of nodetype and nodes lump into its own function (Function. Not file. Sorry.) --- src/p_setup.c | 115 +++++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 53 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index a0eb52bc8..4f9b89c5c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1473,9 +1473,62 @@ typedef enum { NT_ZGL2, NT_XGL3, NT_ZGL3, - NT_UNSUPPORTED + NT_UNSUPPORTED, + NUMNODETYPES } nodetype_t; +// Find out the BSP format. +static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t *virtnodes) +{ + boolean supported[NUMNODETYPES]; + nodetype_t nodetype = NT_UNSUPPORTED; + char signature[4 + 1]; + + if (vres_Find(virt, "TEXTMAP")) + { + virtnodes = vres_Find(virt, "ZNODES"); + supported[NT_XGLN] = supported[NT_XGL3] = true; + } + else + { + virtlump_t *virtsegs = vres_Find(virt, "SEGS"); + virtlump_t *virtssectors; + + if (virtsegs && virtsegs->size) + return NT_DOOM; // Traditional map format BSP tree. + + virtssectors = vres_Find(virt, "SSECTORS"); + + if (virtssectors && virtssectors->size) + { // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature. + virtnodes = virtssectors; + supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL3] = true; + } + else + { // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature. + virtnodes = vres_Find(virt, "NODES"); + supported[NT_XNOD] = supported[NT_ZNOD] = true; + } + + M_Memcpy(signature, virtnodes->data, 4); + signature[4] = '\0'; + virtnodes->data += 4; + } + + if (!strcmp(signature, "XNOD")) + nodetype = NT_XNOD; + else if (!strcmp(signature, "ZNOD")) + nodetype = NT_ZNOD; + else if (!strcmp(signature, "XGLN")) + nodetype = NT_XGLN; + else if (!strcmp(signature, "ZGLN")) + nodetype = NT_ZGLN; + else if (!strcmp(signature, "XGL3")) + nodetype = NT_XGL3; + + return supported[nodetype] ? nodetype : NT_UNSUPPORTED; +} + static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) { size_t i, j, k; @@ -1680,60 +1733,16 @@ static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) static void P_LoadMapBSP(const virtres_t *virt) { - virtlump_t* virtssectors = vres_Find(virt, "SSECTORS"); - virtlump_t* virtsegs = vres_Find(virt, "SEGS"); - virtlump_t* virtnodes = vres_Find(virt, "NODES"); - - nodetype_t nodetype = NT_UNSUPPORTED; - - // Find out the BSP format. - if (vres_Find(virt, "TEXTMAP")) - { - virtnodes = vres_Find(virt, "ZNODES"); - if (!memcmp(virtnodes->data, "XGLN", 4)) - nodetype = NT_XGLN; - else if (!memcmp(virtnodes->data, "XGL3", 4)) - nodetype = NT_XGL3; - } - else - { - if (!virtsegs || !virtsegs->size) - { - // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature. - if (!virtssectors || !virtssectors->size) - { - if (!memcmp(virtnodes->data, "XNOD", 4)) - nodetype = NT_XNOD; - else if (!memcmp(virtnodes->data, "ZNOD", 4)) // Compressed variant. - nodetype = NT_ZNOD; - } - // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature. - else - { - if (!memcmp(virtssectors->data, "XGLN", 4)) - { - virtnodes = virtssectors; - nodetype = NT_XGLN; - } - else if (!memcmp(virtssectors->data, "ZGLN", 4)) // Compressed variant. - { - virtnodes = virtssectors; - nodetype = NT_ZGLN; - } - else if (!memcmp(virtssectors->data, "XGL3", 4)) // Compressed variant. - { - virtnodes = virtssectors; - nodetype = NT_XGL3; - } - } - } - else // Traditional map format BSP tree. - nodetype = NT_DOOM; - } + virtlump_t *virtnodes = NULL; + nodetype_t nodetype = P_GetNodetype(virt, virtnodes); switch (nodetype) { case NT_DOOM: + { + virtlump_t *virtssectors = vres_Find(virt, "SSECTORS"); + virtlump_t *virtsegs = vres_Find(virt, "SEGS"); + numsubsectors = virtssectors->size / sizeof(mapsubsector_t); numnodes = virtnodes->size / sizeof(mapnode_t); numsegs = virtsegs->size / sizeof(mapseg_t); @@ -1753,11 +1762,11 @@ static void P_LoadMapBSP(const virtres_t *virt) P_LoadNodes(virtnodes->data); P_LoadSegs(virtsegs->data); break; - + } case NT_XNOD: case NT_XGLN: case NT_XGL3: - P_LoadExtendedNodes(virtnodes->data + 4, nodetype); + P_LoadExtendedNodes(virtnodes->data, nodetype); break; default: CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n"); From 9d009edfc800e87934abf919091bd2a9bf5eec4c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 15:59:15 +0100 Subject: [PATCH 236/312] Move copying of the nodes signature out of the else case --- src/p_setup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 4f9b89c5c..5725c6db1 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1509,12 +1509,12 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t *virtnodes) virtnodes = vres_Find(virt, "NODES"); supported[NT_XNOD] = supported[NT_ZNOD] = true; } - - M_Memcpy(signature, virtnodes->data, 4); - signature[4] = '\0'; - virtnodes->data += 4; } + M_Memcpy(signature, virtnodes->data, 4); + signature[4] = '\0'; + virtnodes->data += 4; + if (!strcmp(signature, "XNOD")) nodetype = NT_XNOD; else if (!strcmp(signature, "ZNOD")) From 45ca959f97a7becbfef0ce3fdaa300d8296ce1fa Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 17:52:49 +0100 Subject: [PATCH 237/312] -Move reading of actual extended nodes into separate function, cutting down on code duplication in the process -Fix a typo in the segs reading --- src/p_setup.c | 112 ++++++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 68 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 5725c6db1..74ba5c5bd 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1456,13 +1456,6 @@ static void P_LoadSegs(UINT8 *data) } } -// Auxiliary function: Shrink node ID from 32-bit to 16-bit. -static UINT16 ShrinkNodeID(UINT32 x) { - UINT16 mask = (x >> 16) & 0xC000; - UINT16 result = x; - return result | mask; -} - typedef enum { NT_DOOM, NT_XNOD, @@ -1529,28 +1522,58 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t *virtnodes) return supported[nodetype] ? nodetype : NT_UNSUPPORTED; } -static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) +// Auxiliary function: Shrink node ID from 32-bit to 16-bit. +static UINT16 ShrinkNodeID(UINT32 x) { + UINT16 mask = (x >> 16) & 0xC000; + UINT16 result = x; + return result | mask; +} + +static void P_LoadExtendedNodes(UINT8 *data, boolean xgl3) +{ + node_t *mn; + size_t i, j, k; + + for (i = 0, mn = nodes; i < numnodes; i++, mn++) + { + // Splitter + mn->x = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + mn->y = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + mn->dx = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + mn->dy = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + + // Bounding boxes + for (j = 0; j < 2; j++) + for (k = 0; k < 4; k++) + mn->bbox[j][k] = READINT16(data) << FRACBITS; + + //Children + mn->children[0] = ShrinkNodeID(READUINT32(data)); /// \todo Use UINT32 for node children in a future, instead? + mn->children[1] = ShrinkNodeID(READUINT32(data)); + } +} + +static void P_LoadExtendedBSP(UINT8 *data, nodetype_t nodetype) { size_t i, j, k; INT16 m; - /// Extended node formats feature additional vertexes; useful for OpenGL, but totally useless in gamelogic. - UINT32 orivtx, xtrvtx; - orivtx = READUINT32(data); - xtrvtx = READUINT32(data); + // Extended node formats feature additional vertexes; useful for OpenGL, but totally useless in gamelogic. + UINT32 origvrtx = READUINT32(data); + UINT32 xtrvrtx = READUINT32(data); - if (numvertexes != orivtx) /// If native vertex count doesn't match node original vertex count, bail out (broken data?). + if (numvertexes != origvrtx) // If native vertex count doesn't match node original vertex count, bail out (broken data?). { CONS_Alert(CONS_WARNING, "Vertex count in map data and nodes differ!\n"); return; } - if (xtrvtx) /// If extra vertexes were generated, reallocate the vertex array and fix the pointers. + if (xtrvrtx) // If extra vertexes were generated, reallocate the vertex array and fix the pointers. { line_t *ld = lines; size_t oldpos = (size_t)vertexes; ssize_t offset; - numvertexes += xtrvtx; + numvertexes += xtrvrtx; vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL); offset = ((size_t)vertexes) - oldpos; @@ -1562,7 +1585,7 @@ static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) } // Read vertex data. - for (i = orivtx; i < numvertexes; i++) + for (i = origvrtx; i < numvertexes; i++) { vertexes[i].x = READFIXED(data); vertexes[i].y = READFIXED(data); @@ -1596,7 +1619,7 @@ static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert]; else segs[k - 1].v2 = segs[k].v1; - data += 4;// partner; can be ignored by software renderer; + data += 4; // partner; can be ignored by software renderer; linenum = READUINT16(data); if (linenum == 0xFFFF) { @@ -1623,7 +1646,7 @@ static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert]; else segs[k - 1].v2 = segs[k].v1; - data += 4;// partner; can be ignored by software renderer; + data += 4; // partner; can be ignored by software renderer; linenum = READUINT32(data); if (linenum == 0xFFFFFFFF) { @@ -1633,7 +1656,7 @@ static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) else { segs[k].glseg = false; - segs[k].linedef = NULL; + segs[k].linedef = &lines[linenum]; } segs[k].side = READUINT8(data); } @@ -1681,54 +1704,7 @@ static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) // Nodes numnodes = READINT32(data); nodes = Z_Calloc(numnodes*sizeof(*nodes), PU_LEVEL, NULL); - if (nodetype == NT_XGL3) - { - UINT32 x, y, dx, dy; - UINT32 c0, c1; - node_t *mn; - for (i = 0, mn = nodes; i < numnodes; i++, mn++) - { - // Splitter. - x = READINT32(data); - y = READINT32(data); - dx = READINT32(data); - dy = READINT32(data); - mn->x = x; - mn->y = y; - mn->dx = dx; - mn->dy = dy; - - // Bounding boxes and children. - for (j = 0; j < 2; j++) - for (k = 0; k < 4; k++) - mn->bbox[j][k] = READINT16(data) << FRACBITS; - c0 = READUINT32(data); - c1 = READUINT32(data); - mn->children[0] = ShrinkNodeID(c0); /// \todo Use UINT32 for node children in a future, instead? - mn->children[1] = ShrinkNodeID(c1); - } - } - else - { - UINT32 c0, c1; - node_t *mn; - for (i = 0, mn = nodes; i < numnodes; i++, mn++) - { - // Splitter. - mn->x = READINT16(data) << FRACBITS; - mn->y = READINT16(data) << FRACBITS; - mn->dx = READINT16(data) << FRACBITS; - mn->dy = READINT16(data) << FRACBITS; - // Bounding boxes and children. - for (j = 0; j < 2; j++) - for (k = 0; k < 4; k++) - mn->bbox[j][k] = READINT16(data) << FRACBITS; - c0 = READUINT32(data); - c1 = READUINT32(data); - mn->children[0] = ShrinkNodeID(c0); /// \todo Use UINT32 for node children in a future, instead? - mn->children[1] = ShrinkNodeID(c1); - } - } + P_LoadExtendedNodes(data, nodetype == NT_XGL3); } static void P_LoadMapBSP(const virtres_t *virt) @@ -1766,7 +1742,7 @@ static void P_LoadMapBSP(const virtres_t *virt) case NT_XNOD: case NT_XGLN: case NT_XGL3: - P_LoadExtendedNodes(virtnodes->data, nodetype); + P_LoadExtendedBSP(virtnodes->data, nodetype); break; default: CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n"); From 3839e95d633704ff52179a6cf98cb2a3deba9901 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 18:07:44 +0100 Subject: [PATCH 238/312] Move reading of extra vertices into separate function --- src/p_setup.c | 74 +++++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 74ba5c5bd..bd68d72cc 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1522,6 +1522,46 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t *virtnodes) return supported[nodetype] ? nodetype : NT_UNSUPPORTED; } +// Extended node formats feature additional vertices; useful for OpenGL, but totally useless in gamelogic. +static boolean P_LoadExtraVertices(UINT8 *data) +{ + UINT32 origvrtx = READUINT32(data); + UINT32 xtrvrtx = READUINT32(data); + line_t* ld = lines; + vertex_t *oldpos = vertexes; + ssize_t offset; + size_t i; + + if (numvertexes != origvrtx) // If native vertex count doesn't match node original vertex count, bail out (broken data?). + { + CONS_Alert(CONS_WARNING, "Vertex count in map data and nodes differ!\n"); + return false; + } + + if (!xtrvrtx) + return true; + + // If extra vertexes were generated, reallocate the vertex array and fix the pointers. + numvertexes += xtrvrtx; + vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL); + offset = (size_t)(vertexes - oldpos); + + for (i = 0, ld = lines; i < numlines; i++, ld++) + { + ld->v1 += offset; + ld->v2 += offset; + } + + // Read extra vertex data. + for (i = origvrtx; i < numvertexes; i++) + { + vertexes[i].x = READFIXED(data); + vertexes[i].y = READFIXED(data); + } + + return true; +} + // Auxiliary function: Shrink node ID from 32-bit to 16-bit. static UINT16 ShrinkNodeID(UINT32 x) { UINT16 mask = (x >> 16) & 0xC000; @@ -1555,41 +1595,11 @@ static void P_LoadExtendedNodes(UINT8 *data, boolean xgl3) static void P_LoadExtendedBSP(UINT8 *data, nodetype_t nodetype) { - size_t i, j, k; + size_t i, k; INT16 m; - // Extended node formats feature additional vertexes; useful for OpenGL, but totally useless in gamelogic. - UINT32 origvrtx = READUINT32(data); - UINT32 xtrvrtx = READUINT32(data); - - if (numvertexes != origvrtx) // If native vertex count doesn't match node original vertex count, bail out (broken data?). - { - CONS_Alert(CONS_WARNING, "Vertex count in map data and nodes differ!\n"); + if (!P_LoadExtraVertices(data)) return; - } - - if (xtrvrtx) // If extra vertexes were generated, reallocate the vertex array and fix the pointers. - { - line_t *ld = lines; - size_t oldpos = (size_t)vertexes; - ssize_t offset; - numvertexes += xtrvrtx; - vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL); - offset = ((size_t)vertexes) - oldpos; - - for (i = 0, ld = lines; i < numlines; i++, ld++) - { - ld->v1 = (vertex_t*)((size_t)ld->v1 + offset); - ld->v2 = (vertex_t*)((size_t)ld->v2 + offset); - } - } - - // Read vertex data. - for (i = origvrtx; i < numvertexes; i++) - { - vertexes[i].x = READFIXED(data); - vertexes[i].y = READFIXED(data); - } // Subsectors numsubsectors = READUINT32(data); From c287b86fabf7098f19eea92d717dd289b1744cff Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 19:04:50 +0100 Subject: [PATCH 239/312] Get rid of duplicated code in the extended seg parsing --- src/p_setup.c | 42 +++++------------------------------------- 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index bd68d72cc..c11f216b1 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1619,6 +1619,7 @@ static void P_LoadExtendedBSP(UINT8 *data, nodetype_t nodetype) switch (nodetype) { case NT_XGLN: + case NT_XGL3: for (m = 0; m < subsectors[i].numlines; m++, k++) { UINT16 linenum; @@ -1630,44 +1631,11 @@ static void P_LoadExtendedBSP(UINT8 *data, nodetype_t nodetype) else segs[k - 1].v2 = segs[k].v1; data += 4; // partner; can be ignored by software renderer; + if (nodetype == NT_XGL3) + data += 2; // Line number is 32-bit in XGL3, but we're limited to 16 bits. linenum = READUINT16(data); - if (linenum == 0xFFFF) - { - segs[k].glseg = true; - segs[k].linedef = NULL; - } - else - { - segs[k].glseg = false; - segs[k].linedef = &lines[linenum]; - } - segs[k].side = READUINT8(data); - } - break; - - case NT_XGL3: - for (m = 0; m < subsectors[i].numlines; m++, k++) - { - UINT32 linenum; - UINT32 vert; - vert = READUINT32(data); - segs[k].v1 = &vertexes[vert]; - if (m == 0) - segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert]; - else - segs[k - 1].v2 = segs[k].v1; - data += 4; // partner; can be ignored by software renderer; - linenum = READUINT32(data); - if (linenum == 0xFFFFFFFF) - { - segs[k].glseg = true; - segs[k].linedef = NULL; - } - else - { - segs[k].glseg = false; - segs[k].linedef = &lines[linenum]; - } + segs[k].glseg = (linenum == 0xFFFF); + segs[k].linedef = (linenum == 0xFFFF) ? NULL : &lines[linenum]; segs[k].side = READUINT8(data); } break; From 36f86077da25fcd1a66e5e70bc7a1ce3828aebcf Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 19:54:04 +0100 Subject: [PATCH 240/312] Move loading of extended subsectors and segs into its own function --- src/p_setup.c | 126 +++++++++++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index c11f216b1..6315ea859 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1343,6 +1343,15 @@ static void P_LoadMapData(const virtres_t *virt) memcpy(spawnsides, sides, numsides * sizeof (*sides)); } +static void P_InitializeSubsector(subsector_t *ss) +{ + ss->sector = NULL; +#ifdef FLOORSPLATS + ss->splats = NULL; +#endif + ss->validcount = 0; +} + static inline void P_LoadSubsectors(UINT8 *data) { mapsubsector_t *ms = (mapsubsector_t*)data; @@ -1351,13 +1360,9 @@ static inline void P_LoadSubsectors(UINT8 *data) for (i = 0; i < numsubsectors; i++, ss++, ms++) { - ss->sector = NULL; ss->numlines = SHORT(ms->numsegs); ss->firstline = SHORT(ms->firstseg); -#ifdef FLOORSPLATS - ss->splats = NULL; -#endif - ss->validcount = 0; + P_InitializeSubsector(ss); } } @@ -1562,44 +1567,11 @@ static boolean P_LoadExtraVertices(UINT8 *data) return true; } -// Auxiliary function: Shrink node ID from 32-bit to 16-bit. -static UINT16 ShrinkNodeID(UINT32 x) { - UINT16 mask = (x >> 16) & 0xC000; - UINT16 result = x; - return result | mask; -} - -static void P_LoadExtendedNodes(UINT8 *data, boolean xgl3) -{ - node_t *mn; - size_t i, j, k; - - for (i = 0, mn = nodes; i < numnodes; i++, mn++) - { - // Splitter - mn->x = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); - mn->y = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); - mn->dx = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); - mn->dy = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); - - // Bounding boxes - for (j = 0; j < 2; j++) - for (k = 0; k < 4; k++) - mn->bbox[j][k] = READINT16(data) << FRACBITS; - - //Children - mn->children[0] = ShrinkNodeID(READUINT32(data)); /// \todo Use UINT32 for node children in a future, instead? - mn->children[1] = ShrinkNodeID(READUINT32(data)); - } -} - -static void P_LoadExtendedBSP(UINT8 *data, nodetype_t nodetype) +static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 *data, nodetype_t nodetype) { size_t i, k; INT16 m; - - if (!P_LoadExtraVertices(data)) - return; + seg_t *seg; // Subsectors numsubsectors = READUINT32(data); @@ -1615,6 +1587,7 @@ static void P_LoadExtendedBSP(UINT8 *data, nodetype_t nodetype) for (i = 0, k = 0; i < numsubsectors; i++) { subsectors[i].firstline = k; + P_InitializeSubsector(&subsectors[i]); switch (nodetype) { @@ -1655,34 +1628,57 @@ static void P_LoadExtendedBSP(UINT8 *data, nodetype_t nodetype) } } + for (i = 0, seg = segs; i < numsegs; i++, seg++) { - INT32 side; - seg_t *li; + vertex_t *v1 = seg->v1; + vertex_t *v2 = seg->v2; + seg->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y); + seg->offset = FixedHypot(v1->x - seg->linedef->v1->x, v1->y - seg->linedef->v1->y); + seg->sidedef = &sides[seg->linedef->sidenum[seg->side]]; + seg->frontsector = seg->sidedef->sector; + if (seg->linedef->flags & ML_TWOSIDED) + seg->backsector = sides[seg->linedef->sidenum[seg->side ^ 1]].sector; + else + seg->backsector = 0; - for (i = 0, li = segs; i < numsegs; i++, li++) - { - vertex_t *v1 = li->v1; - vertex_t *v2 = li->v2; - li->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y); - li->offset = FixedHypot(v1->x - li->linedef->v1->x, v1->y - li->linedef->v1->y); - side = li->side; - li->sidedef = &sides[li->linedef->sidenum[side]]; - - li->frontsector = sides[li->linedef->sidenum[side]].sector; - if (li->linedef->flags & ML_TWOSIDED) - li->backsector = sides[li->linedef->sidenum[side ^ 1]].sector; - else - li->backsector = 0; - - segs[i].numlights = 0; - segs[i].rlights = NULL; - } + seg->numlights = 0; + seg->rlights = NULL; } +} + +// Auxiliary function: Shrink node ID from 32-bit to 16-bit. +static UINT16 ShrinkNodeID(UINT32 x) { + UINT16 mask = (x >> 16) & 0xC000; + UINT16 result = x; + return result | mask; +} + +static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) +{ + node_t *mn; + size_t i, j, k; + boolean xgl3 = (nodetype == NT_XGL3); - // Nodes numnodes = READINT32(data); nodes = Z_Calloc(numnodes*sizeof(*nodes), PU_LEVEL, NULL); - P_LoadExtendedNodes(data, nodetype == NT_XGL3); + + for (i = 0, mn = nodes; i < numnodes; i++, mn++) + { + // Splitter + mn->x = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + mn->y = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + mn->dx = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + mn->dy = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + + // Bounding boxes + for (j = 0; j < 2; j++) + for (k = 0; k < 4; k++) + mn->bbox[j][k] = READINT16(data) << FRACBITS; + + //Children + mn->children[0] = ShrinkNodeID(READUINT32(data)); /// \todo Use UINT32 for node children in a future, instead? + mn->children[1] = ShrinkNodeID(READUINT32(data)); + } } static void P_LoadMapBSP(const virtres_t *virt) @@ -1720,7 +1716,11 @@ static void P_LoadMapBSP(const virtres_t *virt) case NT_XNOD: case NT_XGLN: case NT_XGL3: - P_LoadExtendedBSP(virtnodes->data, nodetype); + if (!P_LoadExtraVertices(virtnodes->data)) + return; + if (!P_LoadExtendedSubsectorsAndSegs(virtnodes->data, nodetype)) + return; + P_LoadExtendedNodes(virtnodes->data, nodetype); break; default: CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n"); From 882e8ef7b89e9f9300c616d53cd386b199d87bc7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 20:24:14 +0100 Subject: [PATCH 241/312] Separate shared parts of seg initialization into P_InitializeSeg --- src/p_setup.c | 96 +++++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 6315ea859..0e2f1faa3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1419,45 +1419,54 @@ static inline float P_SegLengthFloat(seg_t *seg) } #endif -static void P_LoadSegs(UINT8 *data) +static void P_InitializeSeg(seg_t *seg) { - INT32 linedef, side; - mapseg_t *ml = (mapseg_t*)data; - seg_t *li = segs; - line_t *ldef; - size_t i; + seg->sidedef = &sides[seg->linedef->sidenum[seg->side]]; - for (i = 0; i < numsegs; i++, li++, ml++) - { - li->v1 = &vertexes[SHORT(ml->v1)]; - li->v2 = &vertexes[SHORT(ml->v2)]; + seg->frontsector = seg->sidedef->sector; + seg->backsector = (seg->linedef->flags & ML_TWOSIDED) ? sides[seg->linedef->sidenum[seg->side ^ 1]].sector : NULL; - li->length = P_SegLength(li); #ifdef HWRENDER - if (rendermode == render_opengl) - { - li->flength = P_SegLengthFloat(li); - //Hurdler: 04/12/2000: for now, only used in hardware mode - li->lightmaps = NULL; // list of static lightmap for this seg - } - li->pv1 = li->pv2 = NULL; + seg->pv1 = seg->pv2 = NULL; + + //Hurdler: 04/12/2000: for now, only used in hardware mode + seg->lightmaps = NULL; // list of static lightmap for this seg #endif - li->angle = (SHORT(ml->angle))<offset = (SHORT(ml->offset))<linedef); - ldef = &lines[linedef]; - li->linedef = ldef; - li->side = side = SHORT(ml->side); - li->sidedef = &sides[ldef->sidenum[side]]; - li->frontsector = sides[ldef->sidenum[side]].sector; - if (ldef->flags & ML_TWOSIDED) - li->backsector = sides[ldef->sidenum[side^1]].sector; - else - li->backsector = 0; + seg->numlights = 0; + seg->rlights = NULL; +#ifdef POLYOBJECTS + seg->polyseg = NULL; + seg->dontrenderme = false; +#endif +} - li->numlights = 0; - li->rlights = NULL; +static void P_LoadSegs(UINT8 *data) +{ + mapseg_t *ms = (mapseg_t*)data; + seg_t *seg = segs; + size_t i; + + for (i = 0; i < numsegs; i++, seg++, ms++) + { + seg->v1 = &vertexes[SHORT(ms->v1)]; + seg->v2 = &vertexes[SHORT(ms->v2)]; + + seg->side = SHORT(ms->side); + + seg->offset = (SHORT(ms->offset)) << FRACBITS; + + seg->angle = (SHORT(ms->angle)) << FRACBITS; + + seg->linedef = &lines[SHORT(ms->linedef)]; + + seg->length = P_SegLength(seg); +#ifdef HWRENDER + seg->flength = (rendermode == render_opengl) ? P_SegLengthFloat(seg) : 0; +#endif + + seg->glseg = false; + P_InitializeSeg(seg); } } @@ -1596,16 +1605,18 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 *data, nodetype_t nodetype) for (m = 0; m < subsectors[i].numlines; m++, k++) { UINT16 linenum; - UINT32 vert; - vert = READUINT32(data); + UINT32 vert = READUINT32(data); + segs[k].v1 = &vertexes[vert]; if (m == 0) segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert]; else segs[k - 1].v2 = segs[k].v1; - data += 4; // partner; can be ignored by software renderer; + + data += 4; // partner, can be ignored by software renderer if (nodetype == NT_XGL3) data += 2; // Line number is 32-bit in XGL3, but we're limited to 16 bits. + linenum = READUINT16(data); segs[k].glseg = (linenum == 0xFFFF); segs[k].linedef = (linenum == 0xFFFF) ? NULL : &lines[linenum]; @@ -1620,11 +1631,12 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 *data, nodetype_t nodetype) segs[k].v2 = &vertexes[READUINT32(data)]; segs[k].linedef = &lines[READUINT16(data)]; segs[k].side = READUINT8(data); + segs[k].glseg = false; } break; default: - return; + return false; } } @@ -1632,18 +1644,12 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 *data, nodetype_t nodetype) { vertex_t *v1 = seg->v1; vertex_t *v2 = seg->v2; + P_InitializeSeg(seg); seg->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y); seg->offset = FixedHypot(v1->x - seg->linedef->v1->x, v1->y - seg->linedef->v1->y); - seg->sidedef = &sides[seg->linedef->sidenum[seg->side]]; - seg->frontsector = seg->sidedef->sector; - if (seg->linedef->flags & ML_TWOSIDED) - seg->backsector = sides[seg->linedef->sidenum[seg->side ^ 1]].sector; - else - seg->backsector = 0; - - seg->numlights = 0; - seg->rlights = NULL; } + + return true; } // Auxiliary function: Shrink node ID from 32-bit to 16-bit. From dd02fe0d78371ef72705ea279734c48c9795fd97 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 20:43:41 +0100 Subject: [PATCH 242/312] P_GetNodetype: Set virtnodes for traditional Doom format --- src/p_setup.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index 0e2f1faa3..7b5cfc4c8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1502,7 +1502,10 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t *virtnodes) virtlump_t *virtssectors; if (virtsegs && virtsegs->size) + { + virtnodes = vres_Find(virt, "NODES"); return NT_DOOM; // Traditional map format BSP tree. + } virtssectors = vres_Find(virt, "SSECTORS"); From e88556efe13ab4818abfc0d2dd19173d06e49164 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 21:00:20 +0100 Subject: [PATCH 243/312] P_GetNodetype: The virtnodes pointer is supposed to be the output parameter, so we have to pass a pointer to that pointer --- src/p_setup.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 7b5cfc4c8..16a192c36 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1485,7 +1485,7 @@ typedef enum { } nodetype_t; // Find out the BSP format. -static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t *virtnodes) +static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t **virtnodes) { boolean supported[NUMNODETYPES]; nodetype_t nodetype = NT_UNSUPPORTED; @@ -1493,7 +1493,7 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t *virtnodes) if (vres_Find(virt, "TEXTMAP")) { - virtnodes = vres_Find(virt, "ZNODES"); + *virtnodes = vres_Find(virt, "ZNODES"); supported[NT_XGLN] = supported[NT_XGL3] = true; } else @@ -1503,7 +1503,7 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t *virtnodes) if (virtsegs && virtsegs->size) { - virtnodes = vres_Find(virt, "NODES"); + *virtnodes = vres_Find(virt, "NODES"); return NT_DOOM; // Traditional map format BSP tree. } @@ -1511,19 +1511,19 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t *virtnodes) if (virtssectors && virtssectors->size) { // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature. - virtnodes = virtssectors; + *virtnodes = virtssectors; supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL3] = true; } else { // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature. - virtnodes = vres_Find(virt, "NODES"); + *virtnodes = vres_Find(virt, "NODES"); supported[NT_XNOD] = supported[NT_ZNOD] = true; } } - M_Memcpy(signature, virtnodes->data, 4); + M_Memcpy(signature, (*virtnodes)->data, 4); signature[4] = '\0'; - virtnodes->data += 4; + (*virtnodes)->data += 4; if (!strcmp(signature, "XNOD")) nodetype = NT_XNOD; @@ -1693,7 +1693,7 @@ static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) static void P_LoadMapBSP(const virtres_t *virt) { virtlump_t *virtnodes = NULL; - nodetype_t nodetype = P_GetNodetype(virt, virtnodes); + nodetype_t nodetype = P_GetNodetype(virt, &virtnodes); switch (nodetype) { From cfc6428569b0d397e21b9554e7fc969abf00276f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 21:42:16 +0100 Subject: [PATCH 244/312] Pass along virtnodes to extended nodes loading functions to make sure virtnodes->data is moved correctly --- src/p_setup.c | 60 +++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 16a192c36..597a03232 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1540,10 +1540,10 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t **virtnodes) } // Extended node formats feature additional vertices; useful for OpenGL, but totally useless in gamelogic. -static boolean P_LoadExtraVertices(UINT8 *data) +static boolean P_LoadExtraVertices(virtlump_t *virtnodes) { - UINT32 origvrtx = READUINT32(data); - UINT32 xtrvrtx = READUINT32(data); + UINT32 origvrtx = READUINT32(virtnodes->data); + UINT32 xtrvrtx = READUINT32(virtnodes->data); line_t* ld = lines; vertex_t *oldpos = vertexes; ssize_t offset; @@ -1572,28 +1572,28 @@ static boolean P_LoadExtraVertices(UINT8 *data) // Read extra vertex data. for (i = origvrtx; i < numvertexes; i++) { - vertexes[i].x = READFIXED(data); - vertexes[i].y = READFIXED(data); + vertexes[i].x = READFIXED(virtnodes->data); + vertexes[i].y = READFIXED(virtnodes->data); } return true; } -static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 *data, nodetype_t nodetype) +static boolean P_LoadExtendedSubsectorsAndSegs(virtlump_t *virtnodes, nodetype_t nodetype) { size_t i, k; INT16 m; seg_t *seg; // Subsectors - numsubsectors = READUINT32(data); + numsubsectors = READUINT32(virtnodes->data); subsectors = Z_Calloc(numsubsectors*sizeof(*subsectors), PU_LEVEL, NULL); for (i = 0; i < numsubsectors; i++) - subsectors[i].numlines = READUINT32(data); + subsectors[i].numlines = READUINT32(virtnodes->data); // Segs - numsegs = READUINT32(data); + numsegs = READUINT32(virtnodes->data); segs = Z_Calloc(numsegs*sizeof(*segs), PU_LEVEL, NULL); for (i = 0, k = 0; i < numsubsectors; i++) @@ -1608,7 +1608,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 *data, nodetype_t nodetype) for (m = 0; m < subsectors[i].numlines; m++, k++) { UINT16 linenum; - UINT32 vert = READUINT32(data); + UINT32 vert = READUINT32(virtnodes->data); segs[k].v1 = &vertexes[vert]; if (m == 0) @@ -1616,24 +1616,24 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 *data, nodetype_t nodetype) else segs[k - 1].v2 = segs[k].v1; - data += 4; // partner, can be ignored by software renderer + virtnodes->data += 4; // partner, can be ignored by software renderer if (nodetype == NT_XGL3) - data += 2; // Line number is 32-bit in XGL3, but we're limited to 16 bits. + virtnodes->data += 2; // Line number is 32-bit in XGL3, but we're limited to 16 bits. - linenum = READUINT16(data); + linenum = READUINT16(virtnodes->data); segs[k].glseg = (linenum == 0xFFFF); segs[k].linedef = (linenum == 0xFFFF) ? NULL : &lines[linenum]; - segs[k].side = READUINT8(data); + segs[k].side = READUINT8(virtnodes->data); } break; case NT_XNOD: for (m = 0; m < subsectors[i].numlines; m++, k++) { - segs[k].v1 = &vertexes[READUINT32(data)]; - segs[k].v2 = &vertexes[READUINT32(data)]; - segs[k].linedef = &lines[READUINT16(data)]; - segs[k].side = READUINT8(data); + segs[k].v1 = &vertexes[READUINT32(virtnodes->data)]; + segs[k].v2 = &vertexes[READUINT32(virtnodes->data)]; + segs[k].linedef = &lines[READUINT16(virtnodes->data)]; + segs[k].side = READUINT8(virtnodes->data); segs[k].glseg = false; } break; @@ -1662,31 +1662,31 @@ static UINT16 ShrinkNodeID(UINT32 x) { return result | mask; } -static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) +static void P_LoadExtendedNodes(virtlump_t *virtnodes, nodetype_t nodetype) { node_t *mn; size_t i, j, k; boolean xgl3 = (nodetype == NT_XGL3); - numnodes = READINT32(data); + numnodes = READINT32(virtnodes->data); nodes = Z_Calloc(numnodes*sizeof(*nodes), PU_LEVEL, NULL); for (i = 0, mn = nodes; i < numnodes; i++, mn++) { // Splitter - mn->x = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); - mn->y = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); - mn->dx = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); - mn->dy = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + mn->x = xgl3 ? READINT32(virtnodes->data) : (READINT16(virtnodes->data) << FRACBITS); + mn->y = xgl3 ? READINT32(virtnodes->data) : (READINT16(virtnodes->data) << FRACBITS); + mn->dx = xgl3 ? READINT32(virtnodes->data) : (READINT16(virtnodes->data) << FRACBITS); + mn->dy = xgl3 ? READINT32(virtnodes->data) : (READINT16(virtnodes->data) << FRACBITS); // Bounding boxes for (j = 0; j < 2; j++) for (k = 0; k < 4; k++) - mn->bbox[j][k] = READINT16(data) << FRACBITS; + mn->bbox[j][k] = READINT16(virtnodes->data) << FRACBITS; //Children - mn->children[0] = ShrinkNodeID(READUINT32(data)); /// \todo Use UINT32 for node children in a future, instead? - mn->children[1] = ShrinkNodeID(READUINT32(data)); + mn->children[0] = ShrinkNodeID(READUINT32(virtnodes->data)); /// \todo Use UINT32 for node children in a future, instead? + mn->children[1] = ShrinkNodeID(READUINT32(virtnodes->data)); } } @@ -1725,11 +1725,11 @@ static void P_LoadMapBSP(const virtres_t *virt) case NT_XNOD: case NT_XGLN: case NT_XGL3: - if (!P_LoadExtraVertices(virtnodes->data)) + if (!P_LoadExtraVertices(virtnodes)) return; - if (!P_LoadExtendedSubsectorsAndSegs(virtnodes->data, nodetype)) + if (!P_LoadExtendedSubsectorsAndSegs(virtnodes, nodetype)) return; - P_LoadExtendedNodes(virtnodes->data, nodetype); + P_LoadExtendedNodes(virtnodes, nodetype); break; default: CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n"); From 81422c4e6d9ec7beef6b03da77bd5875b4103f97 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 21:57:47 +0100 Subject: [PATCH 245/312] Revert "Pass along virtnodes to extended nodes loading functions to make sure virtnodes->data is moved correctly" This reverts commit cfc6428569b0d397e21b9554e7fc969abf00276f. --- src/p_setup.c | 60 +++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 597a03232..16a192c36 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1540,10 +1540,10 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t **virtnodes) } // Extended node formats feature additional vertices; useful for OpenGL, but totally useless in gamelogic. -static boolean P_LoadExtraVertices(virtlump_t *virtnodes) +static boolean P_LoadExtraVertices(UINT8 *data) { - UINT32 origvrtx = READUINT32(virtnodes->data); - UINT32 xtrvrtx = READUINT32(virtnodes->data); + UINT32 origvrtx = READUINT32(data); + UINT32 xtrvrtx = READUINT32(data); line_t* ld = lines; vertex_t *oldpos = vertexes; ssize_t offset; @@ -1572,28 +1572,28 @@ static boolean P_LoadExtraVertices(virtlump_t *virtnodes) // Read extra vertex data. for (i = origvrtx; i < numvertexes; i++) { - vertexes[i].x = READFIXED(virtnodes->data); - vertexes[i].y = READFIXED(virtnodes->data); + vertexes[i].x = READFIXED(data); + vertexes[i].y = READFIXED(data); } return true; } -static boolean P_LoadExtendedSubsectorsAndSegs(virtlump_t *virtnodes, nodetype_t nodetype) +static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 *data, nodetype_t nodetype) { size_t i, k; INT16 m; seg_t *seg; // Subsectors - numsubsectors = READUINT32(virtnodes->data); + numsubsectors = READUINT32(data); subsectors = Z_Calloc(numsubsectors*sizeof(*subsectors), PU_LEVEL, NULL); for (i = 0; i < numsubsectors; i++) - subsectors[i].numlines = READUINT32(virtnodes->data); + subsectors[i].numlines = READUINT32(data); // Segs - numsegs = READUINT32(virtnodes->data); + numsegs = READUINT32(data); segs = Z_Calloc(numsegs*sizeof(*segs), PU_LEVEL, NULL); for (i = 0, k = 0; i < numsubsectors; i++) @@ -1608,7 +1608,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(virtlump_t *virtnodes, nodetype_t for (m = 0; m < subsectors[i].numlines; m++, k++) { UINT16 linenum; - UINT32 vert = READUINT32(virtnodes->data); + UINT32 vert = READUINT32(data); segs[k].v1 = &vertexes[vert]; if (m == 0) @@ -1616,24 +1616,24 @@ static boolean P_LoadExtendedSubsectorsAndSegs(virtlump_t *virtnodes, nodetype_t else segs[k - 1].v2 = segs[k].v1; - virtnodes->data += 4; // partner, can be ignored by software renderer + data += 4; // partner, can be ignored by software renderer if (nodetype == NT_XGL3) - virtnodes->data += 2; // Line number is 32-bit in XGL3, but we're limited to 16 bits. + data += 2; // Line number is 32-bit in XGL3, but we're limited to 16 bits. - linenum = READUINT16(virtnodes->data); + linenum = READUINT16(data); segs[k].glseg = (linenum == 0xFFFF); segs[k].linedef = (linenum == 0xFFFF) ? NULL : &lines[linenum]; - segs[k].side = READUINT8(virtnodes->data); + segs[k].side = READUINT8(data); } break; case NT_XNOD: for (m = 0; m < subsectors[i].numlines; m++, k++) { - segs[k].v1 = &vertexes[READUINT32(virtnodes->data)]; - segs[k].v2 = &vertexes[READUINT32(virtnodes->data)]; - segs[k].linedef = &lines[READUINT16(virtnodes->data)]; - segs[k].side = READUINT8(virtnodes->data); + segs[k].v1 = &vertexes[READUINT32(data)]; + segs[k].v2 = &vertexes[READUINT32(data)]; + segs[k].linedef = &lines[READUINT16(data)]; + segs[k].side = READUINT8(data); segs[k].glseg = false; } break; @@ -1662,31 +1662,31 @@ static UINT16 ShrinkNodeID(UINT32 x) { return result | mask; } -static void P_LoadExtendedNodes(virtlump_t *virtnodes, nodetype_t nodetype) +static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) { node_t *mn; size_t i, j, k; boolean xgl3 = (nodetype == NT_XGL3); - numnodes = READINT32(virtnodes->data); + numnodes = READINT32(data); nodes = Z_Calloc(numnodes*sizeof(*nodes), PU_LEVEL, NULL); for (i = 0, mn = nodes; i < numnodes; i++, mn++) { // Splitter - mn->x = xgl3 ? READINT32(virtnodes->data) : (READINT16(virtnodes->data) << FRACBITS); - mn->y = xgl3 ? READINT32(virtnodes->data) : (READINT16(virtnodes->data) << FRACBITS); - mn->dx = xgl3 ? READINT32(virtnodes->data) : (READINT16(virtnodes->data) << FRACBITS); - mn->dy = xgl3 ? READINT32(virtnodes->data) : (READINT16(virtnodes->data) << FRACBITS); + mn->x = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + mn->y = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + mn->dx = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + mn->dy = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); // Bounding boxes for (j = 0; j < 2; j++) for (k = 0; k < 4; k++) - mn->bbox[j][k] = READINT16(virtnodes->data) << FRACBITS; + mn->bbox[j][k] = READINT16(data) << FRACBITS; //Children - mn->children[0] = ShrinkNodeID(READUINT32(virtnodes->data)); /// \todo Use UINT32 for node children in a future, instead? - mn->children[1] = ShrinkNodeID(READUINT32(virtnodes->data)); + mn->children[0] = ShrinkNodeID(READUINT32(data)); /// \todo Use UINT32 for node children in a future, instead? + mn->children[1] = ShrinkNodeID(READUINT32(data)); } } @@ -1725,11 +1725,11 @@ static void P_LoadMapBSP(const virtres_t *virt) case NT_XNOD: case NT_XGLN: case NT_XGL3: - if (!P_LoadExtraVertices(virtnodes)) + if (!P_LoadExtraVertices(virtnodes->data)) return; - if (!P_LoadExtendedSubsectorsAndSegs(virtnodes, nodetype)) + if (!P_LoadExtendedSubsectorsAndSegs(virtnodes->data, nodetype)) return; - P_LoadExtendedNodes(virtnodes, nodetype); + P_LoadExtendedNodes(virtnodes->data, nodetype); break; default: CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n"); From 136c656cc09fa3ac27d6a3fe56dbd5d8b6dfc718 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 29 Dec 2019 22:11:15 +0100 Subject: [PATCH 246/312] Properly pass nodes data along to functions that need it without breaking the original data pointer --- src/p_setup.c | 79 ++++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 16a192c36..a043c1e51 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1485,7 +1485,7 @@ typedef enum { } nodetype_t; // Find out the BSP format. -static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t **virtnodes) +static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) { boolean supported[NUMNODETYPES]; nodetype_t nodetype = NT_UNSUPPORTED; @@ -1493,7 +1493,7 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t **virtnodes) if (vres_Find(virt, "TEXTMAP")) { - *virtnodes = vres_Find(virt, "ZNODES"); + *nodedata = vres_Find(virt, "ZNODES")->data; supported[NT_XGLN] = supported[NT_XGL3] = true; } else @@ -1503,7 +1503,7 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t **virtnodes) if (virtsegs && virtsegs->size) { - *virtnodes = vres_Find(virt, "NODES"); + *nodedata = vres_Find(virt, "NODES")->data; return NT_DOOM; // Traditional map format BSP tree. } @@ -1511,19 +1511,19 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t **virtnodes) if (virtssectors && virtssectors->size) { // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature. - *virtnodes = virtssectors; + *nodedata = virtssectors->data; supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL3] = true; } else { // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature. - *virtnodes = vres_Find(virt, "NODES"); + *nodedata = vres_Find(virt, "NODES")->data; supported[NT_XNOD] = supported[NT_ZNOD] = true; } } - M_Memcpy(signature, (*virtnodes)->data, 4); + M_Memcpy(signature, *nodedata, 4); signature[4] = '\0'; - (*virtnodes)->data += 4; + (*nodedata) += 4; if (!strcmp(signature, "XNOD")) nodetype = NT_XNOD; @@ -1540,10 +1540,10 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, virtlump_t **virtnodes) } // Extended node formats feature additional vertices; useful for OpenGL, but totally useless in gamelogic. -static boolean P_LoadExtraVertices(UINT8 *data) +static boolean P_LoadExtraVertices(UINT8 **data) { - UINT32 origvrtx = READUINT32(data); - UINT32 xtrvrtx = READUINT32(data); + UINT32 origvrtx = READUINT32((*data)); + UINT32 xtrvrtx = READUINT32((*data)); line_t* ld = lines; vertex_t *oldpos = vertexes; ssize_t offset; @@ -1572,28 +1572,28 @@ static boolean P_LoadExtraVertices(UINT8 *data) // Read extra vertex data. for (i = origvrtx; i < numvertexes; i++) { - vertexes[i].x = READFIXED(data); - vertexes[i].y = READFIXED(data); + vertexes[i].x = READFIXED((*data)); + vertexes[i].y = READFIXED((*data)); } return true; } -static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 *data, nodetype_t nodetype) +static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype) { size_t i, k; INT16 m; seg_t *seg; // Subsectors - numsubsectors = READUINT32(data); + numsubsectors = READUINT32((*data)); subsectors = Z_Calloc(numsubsectors*sizeof(*subsectors), PU_LEVEL, NULL); for (i = 0; i < numsubsectors; i++) - subsectors[i].numlines = READUINT32(data); + subsectors[i].numlines = READUINT32((*data)); // Segs - numsegs = READUINT32(data); + numsegs = READUINT32((*data)); segs = Z_Calloc(numsegs*sizeof(*segs), PU_LEVEL, NULL); for (i = 0, k = 0; i < numsubsectors; i++) @@ -1608,7 +1608,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 *data, nodetype_t nodetype) for (m = 0; m < subsectors[i].numlines; m++, k++) { UINT16 linenum; - UINT32 vert = READUINT32(data); + UINT32 vert = READUINT32((*data)); segs[k].v1 = &vertexes[vert]; if (m == 0) @@ -1616,24 +1616,24 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 *data, nodetype_t nodetype) else segs[k - 1].v2 = segs[k].v1; - data += 4; // partner, can be ignored by software renderer + (*data) += 4; // partner, can be ignored by software renderer if (nodetype == NT_XGL3) - data += 2; // Line number is 32-bit in XGL3, but we're limited to 16 bits. + (*data) += 2; // Line number is 32-bit in XGL3, but we're limited to 16 bits. - linenum = READUINT16(data); + linenum = READUINT16((*data)); segs[k].glseg = (linenum == 0xFFFF); segs[k].linedef = (linenum == 0xFFFF) ? NULL : &lines[linenum]; - segs[k].side = READUINT8(data); + segs[k].side = READUINT8((*data)); } break; case NT_XNOD: for (m = 0; m < subsectors[i].numlines; m++, k++) { - segs[k].v1 = &vertexes[READUINT32(data)]; - segs[k].v2 = &vertexes[READUINT32(data)]; - segs[k].linedef = &lines[READUINT16(data)]; - segs[k].side = READUINT8(data); + segs[k].v1 = &vertexes[READUINT32((*data))]; + segs[k].v2 = &vertexes[READUINT32((*data))]; + segs[k].linedef = &lines[READUINT16((*data))]; + segs[k].side = READUINT8((*data)); segs[k].glseg = false; } break; @@ -1662,44 +1662,45 @@ static UINT16 ShrinkNodeID(UINT32 x) { return result | mask; } -static void P_LoadExtendedNodes(UINT8 *data, nodetype_t nodetype) +static void P_LoadExtendedNodes(UINT8 **data, nodetype_t nodetype) { node_t *mn; size_t i, j, k; boolean xgl3 = (nodetype == NT_XGL3); - numnodes = READINT32(data); + numnodes = READINT32((*data)); nodes = Z_Calloc(numnodes*sizeof(*nodes), PU_LEVEL, NULL); for (i = 0, mn = nodes; i < numnodes; i++, mn++) { // Splitter - mn->x = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); - mn->y = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); - mn->dx = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); - mn->dy = xgl3 ? READINT32(data) : (READINT16(data) << FRACBITS); + mn->x = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS); + mn->y = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS); + mn->dx = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS); + mn->dy = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS); // Bounding boxes for (j = 0; j < 2; j++) for (k = 0; k < 4; k++) - mn->bbox[j][k] = READINT16(data) << FRACBITS; + mn->bbox[j][k] = READINT16((*data)) << FRACBITS; //Children - mn->children[0] = ShrinkNodeID(READUINT32(data)); /// \todo Use UINT32 for node children in a future, instead? - mn->children[1] = ShrinkNodeID(READUINT32(data)); + mn->children[0] = ShrinkNodeID(READUINT32((*data))); /// \todo Use UINT32 for node children in a future, instead? + mn->children[1] = ShrinkNodeID(READUINT32((*data))); } } static void P_LoadMapBSP(const virtres_t *virt) { - virtlump_t *virtnodes = NULL; - nodetype_t nodetype = P_GetNodetype(virt, &virtnodes); + UINT8 *nodedata = NULL; + nodetype_t nodetype = P_GetNodetype(virt, &nodedata); switch (nodetype) { case NT_DOOM: { virtlump_t *virtssectors = vres_Find(virt, "SSECTORS"); + virtlump_t* virtnodes = vres_Find(virt, "NODES"); virtlump_t *virtsegs = vres_Find(virt, "SEGS"); numsubsectors = virtssectors->size / sizeof(mapsubsector_t); @@ -1725,11 +1726,11 @@ static void P_LoadMapBSP(const virtres_t *virt) case NT_XNOD: case NT_XGLN: case NT_XGL3: - if (!P_LoadExtraVertices(virtnodes->data)) + if (!P_LoadExtraVertices(&nodedata)) return; - if (!P_LoadExtendedSubsectorsAndSegs(virtnodes->data, nodetype)) + if (!P_LoadExtendedSubsectorsAndSegs(&nodedata, nodetype)) return; - P_LoadExtendedNodes(virtnodes->data, nodetype); + P_LoadExtendedNodes(&nodedata, nodetype); break; default: CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n"); From 97c5e63dc331f838e951bd10fed7fb8d69ea420f Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 29 Dec 2019 16:52:39 -0800 Subject: [PATCH 247/312] Initialize 'supported' array --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index a043c1e51..99da5ccee 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1487,7 +1487,7 @@ typedef enum { // Find out the BSP format. static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) { - boolean supported[NUMNODETYPES]; + boolean supported[NUMNODETYPES] = {0}; nodetype_t nodetype = NT_UNSUPPORTED; char signature[4 + 1]; From 3d724f302df688f26e6e4c0ce180a5fa23633721 Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Mon, 30 Dec 2019 01:16:50 -0300 Subject: [PATCH 248/312] Fix saloon doors not letting players through when marked with the Ambush flag --- src/p_enemy.c | 2 +- src/p_map.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 74a11fe67..08aeac383 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -14248,7 +14248,7 @@ void A_SaloonDoorSpawn(mobj_t *actor) fixed_t c = FINECOSINE(fa)*locvar2; fixed_t s = FINESINE(fa)*locvar2; mobj_t *door; - mobjflag2_t ambush = (actor->flags & MF2_AMBUSH); + mobjflag2_t ambush = (actor->flags2 & MF2_AMBUSH); #ifdef HAVE_BLUA if (LUA_CallAction("A_SaloonDoorSpawn", actor)) diff --git a/src/p_map.c b/src/p_map.c index 2d36f747c..462694fe2 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -995,7 +995,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->type == MT_SALOONDOOR && tmthing->player) { 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) + if ((thing->flags2 & MF2_AMBUSH) || ref != tmthing) { fixed_t dm = min(FixedHypot(ref->momx, ref->momy), 16*FRACUNIT); angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle; @@ -1008,7 +1008,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->type == MT_SALOONDOORCENTER && tmthing->player) { - if ((thing->flags & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer))) + if ((thing->flags2 & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer))) return true; } From 58dd578b094639405d452593562e0f8cb2b482ce Mon Sep 17 00:00:00 2001 From: Nami <50415197+namishere@users.noreply.github.com> Date: Sun, 29 Dec 2019 20:36:24 -0800 Subject: [PATCH 249/312] Let's try this again! --- src/dehacked.c | 3 +++ src/lua_blockmaplib.c | 40 ++++++++++++++++++---------------------- src/lua_hook.h | 6 ++++-- src/lua_hooklib.c | 34 +++++++++++++++++++++++++++++----- src/p_tick.c | 8 ++++++-- 5 files changed, 60 insertions(+), 31 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 4c90211cc..450e33c16 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9824,6 +9824,9 @@ struct { {"TC_RAINBOW",TC_RAINBOW}, {"TC_BLINK",TC_BLINK}, {"TC_DASHMODE",TC_DASHMODE}, + + {"OPT_LINES", 1}, + {"OPT_MOBJS", 1<<1}, #endif {NULL,0} diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index 7f7dc9560..2130e9333 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -18,11 +18,6 @@ #include "lua_libs.h" //#include "lua_hud.h" // hud_running errors -static const char *const search_opt[] = { - "objects", - "lines", - NULL}; - // a quickly-made function pointer typedef used by lib_searchBlockmap... // return values: // 0 - normal, no interruptions @@ -179,29 +174,18 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th // false = searching of at least one block stopped mid-way (including if the whole search was stopped) static int lib_searchBlockmap(lua_State *L) { - int searchtype = luaL_checkoption(L, 1, "objects", search_opt); int n; mobj_t *mobj; INT32 xl, xh, yl, yh, bx, by; fixed_t x1, x2, y1, y2; boolean retval = true; + boolean repeat = false; UINT8 funcret = 0; - blockmap_func searchFunc; - lua_remove(L, 1); // remove searchtype, stack is now function, mobj, [x1, x2, y1, y2] + UINT32 flags = luaL_checkinteger(L, 1); + lua_remove(L, 1); // remove flags, stack is now function, mobj, [x1, x2, y1, y2] luaL_checktype(L, 1, LUA_TFUNCTION); - switch (searchtype) - { - case 0: // "objects" - default: - searchFunc = lib_searchBlockmap_Objects; - break; - case 1: // "lines" - searchFunc = lib_searchBlockmap_Lines; - break; - } - // the mobj we are searching around, the "calling" mobj we could say mobj = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); if (!mobj) @@ -240,8 +224,14 @@ static int lib_searchBlockmap(lua_State *L) validcount++; for (bx = xl; bx <= xh; bx++) for (by = yl; by <= yh; by++) - { - funcret = searchFunc(L, bx, by, mobj); + { + if (flags & (OPT_LINES|OPT_MOBJS)) + repeat = true; + if (flags & OPT_LINES) + funcret = lib_searchBlockmap_Lines(L, bx, by, mobj); + else + funcret = lib_searchBlockmap_Objects(L, bx, by, mobj); + doitagain: // return value of searchFunc determines searchFunc's return value and/or when to stop if (funcret == 2){ // stop whole search lua_pushboolean(L, false); // return false @@ -254,6 +244,12 @@ static int lib_searchBlockmap(lua_State *L) lua_pushboolean(L, false); // in which case we have to stop now regardless return 1; } + if (repeat) + { + funcret = lib_searchBlockmap_Objects(L, bx, by, mobj); + repeat = false; + goto doitagain; + } } lua_pushboolean(L, retval); return 1; @@ -265,4 +261,4 @@ int LUA_BlockmapLib(lua_State *L) return 0; } -#endif +#endif \ No newline at end of file diff --git a/src/lua_hook.h b/src/lua_hook.h index 68efbce93..620a7b307 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -20,7 +20,8 @@ enum hook { hook_MapChange, hook_MapLoad, hook_PlayerJoin, - hook_ThinkFrame, + hook_PreThinkFrame, + hook_PostThinkFrame, hook_MobjSpawn, hook_MobjCollide, hook_MobjMoveCollide, @@ -61,7 +62,8 @@ extern const char *const hookNames[]; void LUAh_MapChange(INT16 mapnumber); // Hook for map change (before load) void LUAh_MapLoad(void); // Hook for map load void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer -void LUAh_ThinkFrame(void); // Hook for frame (after mobj and player thinkers) +void LUAh_PreThinkFrame(void); // Hook for frame (before mobj and player thinkers) +void LUAh_PostThinkFrame(void); // Hook for frame (after mobj and player thinkers) boolean LUAh_MobjHook(mobj_t *mo, enum hook which); boolean LUAh_PlayerHook(player_t *plr, enum hook which); #define LUAh_MobjSpawn(mo) LUAh_MobjHook(mo, hook_MobjSpawn) // Hook for P_SpawnMobj by mobj type diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 91b4c6992..ace0f14d5 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -31,7 +31,8 @@ const char *const hookNames[hook_MAX+1] = { "MapChange", "MapLoad", "PlayerJoin", - "ThinkFrame", + "PreThinkFrame", + "PostThinkFrame", "MobjSpawn", "MobjCollide", "MobjMoveCollide", @@ -411,16 +412,39 @@ void LUAh_PlayerJoin(int playernum) lua_settop(gL, 0); } -// Hook for frame (after mobj and player thinkers) -void LUAh_ThinkFrame(void) +// Hook for frame (before mobj and player thinkers) +void LUAh_PreThinkFrame(void) { hook_p hookp; - if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8)))) + if (!gL || !(hooksAvailable[hook_PreThinkFrame/8] & (1<<(hook_PreThinkFrame%8)))) return; for (hookp = roothook; hookp; hookp = hookp->next) { - if (hookp->type != hook_ThinkFrame) + if (hookp->type != hook_PreThinkFrame) + continue; + + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + if (lua_pcall(gL, 0, 0, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + } + } +} + +// Hook for frame (after mobj and player thinkers) +void LUAh_PostThinkFrame(void) +{ + hook_p hookp; + if (!gL || !(hooksAvailable[hook_PostThinkFrame/8] & (1<<(hook_PostThinkFrame%8)))) + return; + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_PostThinkFrame) continue; lua_pushfstring(gL, FMT_HOOKID, hookp->id); diff --git a/src/p_tick.c b/src/p_tick.c index e0f60bd22..b92465fe4 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -646,6 +646,10 @@ void P_Ticker(boolean run) if (run) { + #ifdef HAVE_BLUA + LUAh_PreThinkFrame(); + #endif + P_RunThinkers(); // Run any "after all the other thinkers" stuff @@ -654,7 +658,7 @@ void P_Ticker(boolean run) P_PlayerAfterThink(&players[i]); #ifdef HAVE_BLUA - LUAh_ThinkFrame(); + LUAh_PostThinkFrame(); #endif } @@ -769,7 +773,7 @@ void P_PreTicker(INT32 frames) P_PlayerAfterThink(&players[i]); #ifdef HAVE_BLUA - LUAh_ThinkFrame(); + LUAh_PostThinkFrame(); #endif // Run shield positioning From aaef412823945719c30231d4c41d3fb9053dc0fb Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 30 Dec 2019 11:33:22 +0100 Subject: [PATCH 250/312] Add basic textmap support; currently crashes when trying to free the virtres, at vres_free(). --- src/doomdef.h | 2 + src/m_misc.c | 14 ++ src/p_setup.c | 371 +++++++++++++++++++++++++++++++++++++++++++++++++- src/w_wad.c | 2 + 4 files changed, 382 insertions(+), 7 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 51a15bd64..0d673a426 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -461,6 +461,8 @@ extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL; char *va(const char *format, ...) FUNCPRINTF; char *M_GetToken(const char *inputString); void M_UnGetToken(void); +UINT32 M_GetTokenPos(void); +void M_SetTokenPos(UINT32 newPos); char *sizeu1(size_t num); char *sizeu2(size_t num); char *sizeu3(size_t num); diff --git a/src/m_misc.c b/src/m_misc.c index b0a1fb8c5..edb24ab1e 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1908,6 +1908,20 @@ void M_UnGetToken(void) endPos = oldendPos; } +/** Returns the current token's position. + */ +UINT32 M_GetTokenPos(void) +{ + return endPos; +} + +/** Sets the current token's position. + */ +void M_SetTokenPos(UINT32 newPos) +{ + endPos = newPos; +} + /** Count bits in a number. */ UINT8 M_CountBits(UINT32 num, UINT8 size) diff --git a/src/p_setup.c b/src/p_setup.c index 99da5ccee..c7eb50382 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -83,6 +83,8 @@ #include "p_slopes.h" #endif +#include "fastcmp.h" // textmap parsing + // // Map MD5, calculated on level load. // Sent to clients in PT_SERVERINFO. @@ -1236,10 +1238,367 @@ static void P_LoadThings(UINT8 *data) } } +// Stores positions for relevant map data spread through a TEXTMAP. +UINT32 mapthingsPos[UINT16_MAX]; +UINT32 linesPos[UINT16_MAX]; +UINT32 sidesPos[UINT16_MAX]; +UINT32 vertexesPos[UINT16_MAX]; +UINT32 sectorsPos[UINT16_MAX]; + +static boolean TextmapCount (UINT8 *data, size_t size) +{ + char *nsp1 = M_GetToken((char *)data); + boolean ret = true; + + // Determine total amount of map data in TEXTMAP. + // Look for namespace at the beginning. + if (fastcmp(nsp1, "namespace")) + { + char *nsp2 = M_GetToken(NULL); + char *tkn = M_GetToken(NULL); + + // Check if namespace is valid. + if (!fastcmp(nsp2, "srb2")) + CONS_Alert(CONS_WARNING, "Invalid namespace '%s', only 'srb2' is supported.\n", nsp2); + Z_Free(nsp2); + + while (tkn != NULL && M_GetTokenPos() < size) + { + // Avoid anything inside bracketed stuff, only look for external keywords. + // Assuming there's only one level of bracket nesting. + if (fastcmp(tkn, "{")) + { + Z_Free(tkn); + while (!fastcmp(tkn, "}")) + { + Z_Free(tkn); + tkn = M_GetToken(NULL); + } + } + // Check for valid fields. + else if (fastcmp(tkn, "thing")) + mapthingsPos[nummapthings++] = M_GetTokenPos(); + else if (fastcmp(tkn, "linedef")) + linesPos[numlines++] = M_GetTokenPos(); + else if (fastcmp(tkn, "sidedef")) + sidesPos[numsides++] = M_GetTokenPos(); + else if (fastcmp(tkn, "vertex")) + vertexesPos[numvertexes++] = M_GetTokenPos(); + else if (fastcmp(tkn, "sector")) + sectorsPos[numsectors++] = M_GetTokenPos(); + else + CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn); + + Z_Free(tkn); + tkn = M_GetToken(NULL); + } + } + else + { + CONS_Alert(CONS_WARNING, "No namespace at beginning of lump!\n"); + ret = false; + } + + Z_Free(nsp1); + return ret; +} + +static char* dat; + +/** Auxiliary function for TextmapParse. + * + * \param Vertex number. + * \param Parameter string. + */ +static void TextmapVertex(UINT32 i, char *param) +{ + if (fastcmp(param, "x")) + vertexes[i].x = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); + else if (fastcmp(param, "y")) + vertexes[i].y = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); +} + +/** Auxiliary function for TextmapParse. + * + * \param Sector number. + * \param Parameter string. + */ +static void TextmapSector(UINT32 i, char *param) +{ + if (fastcmp(param, "heightfloor")) + sectors[i].floorheight = atol(dat = M_GetToken(NULL)) << FRACBITS; + else if (fastcmp(param, "heightceiling")) + sectors[i].ceilingheight = atol(dat = M_GetToken(NULL)) << FRACBITS; + if (fastcmp(param, "texturefloor")) + sectors[i].floorpic = P_AddLevelFlat(dat = M_GetToken(NULL), foundflats); + else if (fastcmp(param, "textureceiling")) + sectors[i].ceilingpic = P_AddLevelFlat(dat = M_GetToken(NULL), foundflats); + else if (fastcmp(param, "lightlevel")) + sectors[i].lightlevel = atol(dat = M_GetToken(NULL)); + else if (fastcmp(param, "special")) + sectors[i].special = atol(dat = M_GetToken(NULL)); + else if (fastcmp(param, "id")) + sectors[i].tag = atol(dat = M_GetToken(NULL)); +} + +/** Auxiliary function for TextmapParse. + * + * \param Side number. + * \param Parameter string. + */ +static void TextmapSide(UINT32 i, char *param) +{ + if (fastcmp(param, "offsetx")) + sides[i].textureoffset = atol(dat = M_GetToken(NULL))<z = 0; + + TextmapParse(vertexesPos[i], i, TextmapVertex); + } + + for (i = 0, sc = sectors; i < numsectors; i++, sc++) + { + // Defaults. + sc->floorheight = 0; + sc->ceilingheight = 0; + + sc->floorpic = 0; + sc->ceilingpic = 0; + + sc->lightlevel = 255; + + sc->special = 0; + sc->tag = 0; + + sc->floor_xoffs = sc->floor_yoffs = sc->ceiling_xoffs = sc->ceiling_yoffs = 0; + sc->floorpic_angle = sc->ceilingpic_angle = 0; + + TextmapParse(sectorsPos[i], i, TextmapSector); + + P_InitializeSector(sc); + } + + for (i = 0, ld = lines; i < numlines; i++, ld++) + { + // Defaults. + ld->tag = 0; + ld->special = 0; + ld->sidenum[1] = 0xffff; + + TextmapParse(linesPos[i], i, TextmapLine); + + P_InitializeLinedef(ld); + } + + for (i = 0, sd = sides; i < numsides; i++, sd++) + { + // Defaults. + sd->rowoffset = 0; + sd->textureoffset = 0; + + sd->toptexture = R_TextureNumForName("-"); + sd->midtexture = R_TextureNumForName("-"); + sd->bottomtexture = R_TextureNumForName("-"); + sd->repeatcnt = 0; + + TextmapParse(sidesPos[i], i, TextmapSide); + } + + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) + { + // Defaults. + mt->z = 0; + mt->angle = 0; + + TextmapParse(mapthingsPos[i], i, TextmapThing); + } +} + +/** Provides a fix to the flat alignment coordinate transform from standard Textmaps. + */ +static void TextmapFixFlatOffsets (void) +{ + fixed_t pc, ps; + fixed_t xoffs, yoffs; + size_t i; + sector_t* sec = sectors; + for (i = 0; i < numsectors; i++, sec++) + { + if (sec->floorpic_angle) + { + pc = FINECOSINE(sec->floorpic_angle>>ANGLETOFINESHIFT); + ps = FINESINE (sec->floorpic_angle>>ANGLETOFINESHIFT); + xoffs = sec->floor_xoffs; + yoffs = sec->floor_yoffs; + #define MAXFLATSIZE (2048<floor_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + sec->floor_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + #undef MAXFLATSIZE + } + + if (sec->ceilingpic_angle) + { + pc = FINECOSINE(sec->ceilingpic_angle>>ANGLETOFINESHIFT); + ps = FINESINE (sec->ceilingpic_angle>>ANGLETOFINESHIFT); + xoffs = sec->ceiling_xoffs; + yoffs = sec->ceiling_yoffs; + #define MAXFLATSIZE (2048<ceiling_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + sec->ceiling_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + #undef MAXFLATSIZE + } + } +} + static void P_LoadMapData(const virtres_t *virt) { virtlump_t* virtvertexes = NULL, * virtsectors = NULL, * virtsidedefs = NULL, * virtlinedefs = NULL, * virtthings = NULL; -#ifdef UDMF virtlump_t* textmap = vres_Find(virt, "TEXTMAP"); // Count map data. @@ -1252,10 +1611,9 @@ static void P_LoadMapData(const virtres_t *virt) numsectors = 0; // Count how many entries for each type we got in textmap. - //TextmapCount(vtextmap->data, vtextmap->size); + TextmapCount(textmap->data, textmap->size); } else -#endif { virtthings = vres_Find(virt, "THINGS"); virtvertexes = vres_Find(virt, "VERTEXES"); @@ -1305,15 +1663,14 @@ static void P_LoadMapData(const virtres_t *virt) numlevelflats = 0; -#ifdef UDMF + // Load map data. if (textmap) { - + P_LoadTextmap(); + TextmapFixFlatOffsets(); } else -#endif { - // Strict map data P_LoadVertices(virtvertexes->data); P_LoadSectors(virtsectors->data); P_LoadLinedefs(virtlinedefs->data); diff --git a/src/w_wad.c b/src/w_wad.c index 62992441a..47c3f42d0 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1942,6 +1942,8 @@ void vres_Free(virtres_t* vres) Z_Free(vres->vlumps[vres->numlumps].data); Z_Free(vres->vlumps); Z_Free(vres); + + CONS_Printf("A A A\n"); } /** (Debug) Prints lumps from a virtual resource into console. From 0839287609c3639e7f35057743c48175130a64eb Mon Sep 17 00:00:00 2001 From: lachwright Date: Mon, 30 Dec 2019 19:00:45 +0800 Subject: [PATCH 251/312] Add unused sounds and remove unused sound slots --- src/sounds.c | 42 +++++++++++++++++++++++++----------------- src/sounds.h | 42 +++++++++++++++++++++++++----------------- 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/src/sounds.c b/src/sounds.c index 175bd8960..720ba851e 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -187,6 +187,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"shield", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pity Shield"}, // generic GET! {"wirlsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Whirlwind Shield"}, // Whirlwind GET! {"forcsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Force Shield"}, // Force GET! + {"frcssg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Weak Force Shield"}, // Force GET...? (consider making a custom shield with this instead of a single-hit force shield!) {"elemsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Elemental Shield"}, // Elemental GET! {"armasg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon Shield"}, // Armaggeddon GET! {"attrsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction Shield"}, // Attract GET! @@ -220,6 +221,9 @@ sfxinfo_t S_sfx[NUMSFX] = {"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!"}, + {"iceb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ice crack"}, + {"shattr", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Shattering"}, + {"antiri", true, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Depletion"}, // Menu, interface {"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"}, @@ -233,6 +237,9 @@ sfxinfo_t S_sfx[NUMSFX] = {"wepchg", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Weapon change"}, // Weapon switch is identical to menu for now {"wtrdng", true, 212, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"}, // make sure you can hear the DING DING! Tails 03-08-2000 {"zelda", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"}, + {"adderr", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Error"}, + {"notadd", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Reject"}, + {"addfil", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Accept"}, // NiGHTS {"ideya", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Success"}, @@ -427,24 +434,9 @@ sfxinfo_t S_sfx[NUMSFX] = {"s25e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s25f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s260", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s261", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s262", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s263", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s264", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s265", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s266", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s267", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s268", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s269", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s270", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // S3&K sounds + {"s3k2b", true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Emerald"}, // Got Emerald! {"s3k33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // stereo in original game, identical to latter {"s3k34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // mono in original game, identical to previous {"s3k35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"}, @@ -566,6 +558,21 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3ka9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"}, {"s3kaa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, {"s3kab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kaba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabe", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, {"s3kac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Continue"}, {"s3kad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "GO!"}, {"s3kae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pinball flipper"}, @@ -604,7 +611,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kc5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Revving up"}, // ditto {"s3kc6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, {"s3kc6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, // ditto - {"s3kc7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, + {"s3kc7s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, + {"s3kc7l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, // ditto {"s3kc8s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding"}, {"s3kc8l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding"}, // ditto {"s3kc9s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Swinging"}, diff --git a/src/sounds.h b/src/sounds.h index e520c6243..039349d4f 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -236,6 +236,7 @@ typedef enum sfx_shield, sfx_wirlsg, sfx_forcsg, + sfx_frcssg, sfx_elemsg, sfx_armasg, sfx_attrsg, @@ -269,6 +270,9 @@ typedef enum sfx_sprong, sfx_lvfal1, sfx_pscree, + sfx_iceb, + sfx_shattr, + sfx_antiri, // Menu, interface sfx_chchng, @@ -282,6 +286,9 @@ typedef enum sfx_wepchg, sfx_wtrdng, sfx_zelda, + sfx_adderr, + sfx_notadd, + sfx_addfil, // NiGHTS sfx_ideya, @@ -476,24 +483,9 @@ typedef enum sfx_s25e, sfx_s25f, sfx_s260, - sfx_s261, - sfx_s262, - sfx_s263, - sfx_s264, - sfx_s265, - sfx_s266, - sfx_s267, - sfx_s268, - sfx_s269, - sfx_s26a, - sfx_s26b, - sfx_s26c, - sfx_s26d, - sfx_s26e, - sfx_s26f, - sfx_s270, // S3&K sounds + sfx_s3k2b, sfx_s3k33, sfx_s3k34, sfx_s3k35, @@ -615,6 +607,21 @@ typedef enum sfx_s3ka9, sfx_s3kaa, sfx_s3kab, + sfx_s3kab1, + sfx_s3kab2, + sfx_s3kab3, + sfx_s3kab4, + sfx_s3kab5, + sfx_s3kab6, + sfx_s3kab7, + sfx_s3kab8, + sfx_s3kab9, + sfx_s3kaba, + sfx_s3kabb, + sfx_s3kabc, + sfx_s3kabd, + sfx_s3kabe, + sfx_s3kabf, sfx_s3kac, sfx_s3kad, sfx_s3kae, @@ -653,7 +660,8 @@ typedef enum sfx_s3kc5l, sfx_s3kc6s, sfx_s3kc6l, - sfx_s3kc7, + sfx_s3kc7s, + sfx_s3kc7l, sfx_s3kc8s, sfx_s3kc8l, sfx_s3kc9s, From ed114f655bd84576d8f3eea314921b9cc611b49e Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 30 Dec 2019 12:07:02 +0100 Subject: [PATCH 252/312] Fixed missing M_GetToken(NULL); --- src/p_setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_setup.c b/src/p_setup.c index c7eb50382..71d1ca880 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1269,6 +1269,7 @@ static boolean TextmapCount (UINT8 *data, size_t size) if (fastcmp(tkn, "{")) { Z_Free(tkn); + tkn = M_GetToken(NULL); while (!fastcmp(tkn, "}")) { Z_Free(tkn); From f49b8de5fd8999965f28bc7fcec5ff666ac1b3d3 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 30 Dec 2019 12:07:54 +0100 Subject: [PATCH 253/312] Adapt P_MakeMapMD5() for textmaps. --- src/p_setup.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 71d1ca880..198b8ae6a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2668,27 +2668,34 @@ static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock) static void P_MakeMapMD5(virtres_t *virt, void *dest) { - unsigned char linemd5[16]; - unsigned char sectormd5[16]; - unsigned char thingmd5[16]; - unsigned char sidedefmd5[16]; + virtlump_t* textmap = vres_Find(virt, "TEXTMAP"); unsigned char resmd5[16]; - UINT8 i; - // Create a hash for the current map - // get the actual lumps! - virtlump_t *virtlines = vres_Find(virt, "LINEDEFS"); - virtlump_t *virtsectors = vres_Find(virt, "SECTORS"); - virtlump_t *virtmthings = vres_Find(virt, "THINGS"); - virtlump_t *virtsides = vres_Find(virt, "SIDEDEFS"); + if (textmap) + P_MakeBufferMD5((char*)textmap->data, textmap->size, resmd5); + else + { + unsigned char linemd5[16]; + unsigned char sectormd5[16]; + unsigned char thingmd5[16]; + unsigned char sidedefmd5[16]; + UINT8 i; - P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5); - P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5); - P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5); - P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5); + // Create a hash for the current map + // get the actual lumps! + virtlump_t* virtlines = vres_Find(virt, "LINEDEFS"); + virtlump_t* virtsectors = vres_Find(virt, "SECTORS"); + virtlump_t* virtmthings = vres_Find(virt, "THINGS"); + virtlump_t* virtsides = vres_Find(virt, "SIDEDEFS"); - for (i = 0; i < 16; i++) - resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF; + P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5); + P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5); + P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5); + P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5); + + for (i = 0; i < 16; i++) + resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF; + } M_Memcpy(dest, &resmd5, 16); } From 493c6c8ae2e725870ceded26f97ed5b936ff4bea Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 30 Dec 2019 12:23:31 +0100 Subject: [PATCH 254/312] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA --- src/w_wad.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 47c3f42d0..62992441a 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1942,8 +1942,6 @@ void vres_Free(virtres_t* vres) Z_Free(vres->vlumps[vres->numlumps].data); Z_Free(vres->vlumps); Z_Free(vres); - - CONS_Printf("A A A\n"); } /** (Debug) Prints lumps from a virtual resource into console. From f9aabe753e76bb028746251b7ab867b297285c23 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 30 Dec 2019 12:31:55 +0100 Subject: [PATCH 255/312] Refactor TextmapFixFlatOffsets(). --- src/p_setup.c | 53 +++++++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 198b8ae6a..2334a9a03 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1523,6 +1523,7 @@ static void P_LoadTextmap (void) TextmapParse(sectorsPos[i], i, TextmapSector); P_InitializeSector(sc); + TextmapFixFlatOffsets(sc); } for (i = 0, ld = lines; i < numlines; i++, ld++) @@ -1563,37 +1564,30 @@ static void P_LoadTextmap (void) /** Provides a fix to the flat alignment coordinate transform from standard Textmaps. */ -static void TextmapFixFlatOffsets (void) +static void TextmapFixFlatOffsets (sector_t* sec) { - fixed_t pc, ps; - fixed_t xoffs, yoffs; - size_t i; - sector_t* sec = sectors; - for (i = 0; i < numsectors; i++, sec++) + if (sec->floorpic_angle) { - if (sec->floorpic_angle) - { - pc = FINECOSINE(sec->floorpic_angle>>ANGLETOFINESHIFT); - ps = FINESINE (sec->floorpic_angle>>ANGLETOFINESHIFT); - xoffs = sec->floor_xoffs; - yoffs = sec->floor_yoffs; - #define MAXFLATSIZE (2048<floor_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); - sec->floor_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); - #undef MAXFLATSIZE - } + fixed_t pc = FINECOSINE(sec->floorpic_angle>>ANGLETOFINESHIFT); + fixed_t ps = FINESINE (sec->floorpic_angle>>ANGLETOFINESHIFT); + fixed_t xoffs = sec->floor_xoffs; + fixed_t yoffs = sec->floor_yoffs; + #define MAXFLATSIZE (2048<floor_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + sec->floor_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + #undef MAXFLATSIZE + } - if (sec->ceilingpic_angle) - { - pc = FINECOSINE(sec->ceilingpic_angle>>ANGLETOFINESHIFT); - ps = FINESINE (sec->ceilingpic_angle>>ANGLETOFINESHIFT); - xoffs = sec->ceiling_xoffs; - yoffs = sec->ceiling_yoffs; - #define MAXFLATSIZE (2048<ceiling_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); - sec->ceiling_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); - #undef MAXFLATSIZE - } + if (sec->ceilingpic_angle) + { + fixed_t pc = FINECOSINE(sec->ceilingpic_angle>>ANGLETOFINESHIFT); + fixed_t ps = FINESINE (sec->ceilingpic_angle>>ANGLETOFINESHIFT); + fixed_t xoffs = sec->ceiling_xoffs; + fixed_t yoffs = sec->ceiling_yoffs; + #define MAXFLATSIZE (2048<ceiling_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + sec->ceiling_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + #undef MAXFLATSIZE } } @@ -1666,10 +1660,7 @@ static void P_LoadMapData(const virtres_t *virt) // Load map data. if (textmap) - { P_LoadTextmap(); - TextmapFixFlatOffsets(); - } else { P_LoadVertices(virtvertexes->data); From e43df2993fd06e7e3acefdb58a08a8f47b7b4e68 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 30 Dec 2019 12:33:24 +0100 Subject: [PATCH 256/312] Move TextmapFixFlatOffsets() above P_LoadTextmap() so that it can compile. --- src/p_setup.c | 58 +++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 2334a9a03..09ef07c1a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1478,6 +1478,35 @@ static void TextmapParse(UINT32 dataPos, size_t num, void (*parser)(UINT32, char Z_Free(open); } +/** Provides a fix to the flat alignment coordinate transform from standard Textmaps. + */ +static void TextmapFixFlatOffsets (sector_t* sec) +{ + if (sec->floorpic_angle) + { + fixed_t pc = FINECOSINE(sec->floorpic_angle>>ANGLETOFINESHIFT); + fixed_t ps = FINESINE (sec->floorpic_angle>>ANGLETOFINESHIFT); + fixed_t xoffs = sec->floor_xoffs; + fixed_t yoffs = sec->floor_yoffs; + #define MAXFLATSIZE (2048<floor_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + sec->floor_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + #undef MAXFLATSIZE + } + + if (sec->ceilingpic_angle) + { + fixed_t pc = FINECOSINE(sec->ceilingpic_angle>>ANGLETOFINESHIFT); + fixed_t ps = FINESINE (sec->ceilingpic_angle>>ANGLETOFINESHIFT); + fixed_t xoffs = sec->ceiling_xoffs; + fixed_t yoffs = sec->ceiling_yoffs; + #define MAXFLATSIZE (2048<ceiling_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + sec->ceiling_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + #undef MAXFLATSIZE + } +} + /** Loads the textmap data, after obtaining the elements count and allocating their respective space. */ static void P_LoadTextmap (void) @@ -1562,35 +1591,6 @@ static void P_LoadTextmap (void) } } -/** Provides a fix to the flat alignment coordinate transform from standard Textmaps. - */ -static void TextmapFixFlatOffsets (sector_t* sec) -{ - if (sec->floorpic_angle) - { - fixed_t pc = FINECOSINE(sec->floorpic_angle>>ANGLETOFINESHIFT); - fixed_t ps = FINESINE (sec->floorpic_angle>>ANGLETOFINESHIFT); - fixed_t xoffs = sec->floor_xoffs; - fixed_t yoffs = sec->floor_yoffs; - #define MAXFLATSIZE (2048<floor_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); - sec->floor_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); - #undef MAXFLATSIZE - } - - if (sec->ceilingpic_angle) - { - fixed_t pc = FINECOSINE(sec->ceilingpic_angle>>ANGLETOFINESHIFT); - fixed_t ps = FINESINE (sec->ceilingpic_angle>>ANGLETOFINESHIFT); - fixed_t xoffs = sec->ceiling_xoffs; - fixed_t yoffs = sec->ceiling_yoffs; - #define MAXFLATSIZE (2048<ceiling_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); - sec->ceiling_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); - #undef MAXFLATSIZE - } -} - static void P_LoadMapData(const virtres_t *virt) { virtlump_t* virtvertexes = NULL, * virtsectors = NULL, * virtsidedefs = NULL, * virtlinedefs = NULL, * virtthings = NULL; From 7c9b1ee2cbc8fc528d53f37e98d940afd600a3c4 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 30 Dec 2019 11:49:01 +0000 Subject: [PATCH 257/312] Fix P_SetTarget crash by setting th->target to NULL first --- src/p_polyobj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index be5673093..f6f666061 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2647,6 +2647,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Set pointnum th->pointnum = target->health; + th->target = NULL; // set to NULL first so the below doesn't go wrong // Set the mobj as your target! -- Monster Iestyn 27/12/19 P_SetTarget(&th->target, target); From 4aee4e3684ce3f70e6a6e60fc427eb998ddb0b9c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 30 Dec 2019 13:27:05 +0100 Subject: [PATCH 258/312] Refactor TextmapCount --- src/p_setup.c | 107 +++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 09ef07c1a..ccb528687 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1245,63 +1245,71 @@ UINT32 sidesPos[UINT16_MAX]; UINT32 vertexesPos[UINT16_MAX]; UINT32 sectorsPos[UINT16_MAX]; -static boolean TextmapCount (UINT8 *data, size_t size) +// Determine total amount of map data in TEXTMAP. +static boolean TextmapCount(UINT8 *data, size_t size) { - char *nsp1 = M_GetToken((char *)data); - boolean ret = true; + char *tkn = M_GetToken((char *)data); + + nummapthings = 0; + numlines = 0; + numsides = 0; + numvertexes = 0; + numsectors = 0; - // Determine total amount of map data in TEXTMAP. // Look for namespace at the beginning. - if (fastcmp(nsp1, "namespace")) + if (!fastcmp(tkn, "namespace")) { - char *nsp2 = M_GetToken(NULL); - char *tkn = M_GetToken(NULL); + Z_Free(tkn); + CONS_Alert(CONS_WARNING, "No namespace at beginning of lump!\n"); + return false; + } + Z_Free(tkn); - // Check if namespace is valid. - if (!fastcmp(nsp2, "srb2")) - CONS_Alert(CONS_WARNING, "Invalid namespace '%s', only 'srb2' is supported.\n", nsp2); - Z_Free(nsp2); + // Check if namespace is valid. + tkn = M_GetToken(NULL); + if (!fastcmp(tkn, "srb2")) + CONS_Alert(CONS_WARNING, "Invalid namespace '%s', only 'srb2' is supported.\n", tkn); + Z_Free(tkn); - while (tkn != NULL && M_GetTokenPos() < size) + tkn = M_GetToken(NULL); + while (tkn && M_GetTokenPos() < size) + { + // Avoid anything inside bracketed stuff, only look for external keywords. + // Assuming there's only one level of bracket nesting. + if (fastcmp(tkn, "{")) { - // Avoid anything inside bracketed stuff, only look for external keywords. - // Assuming there's only one level of bracket nesting. - if (fastcmp(tkn, "{")) + do { Z_Free(tkn); tkn = M_GetToken(NULL); - while (!fastcmp(tkn, "}")) + if (!tkn || M_GetTokenPos() >= size) { Z_Free(tkn); - tkn = M_GetToken(NULL); + CONS_Alert(CONS_WARNING, "Opening bracket not closed!\n"); + return false; } - } - // Check for valid fields. - else if (fastcmp(tkn, "thing")) - mapthingsPos[nummapthings++] = M_GetTokenPos(); - else if (fastcmp(tkn, "linedef")) - linesPos[numlines++] = M_GetTokenPos(); - else if (fastcmp(tkn, "sidedef")) - sidesPos[numsides++] = M_GetTokenPos(); - else if (fastcmp(tkn, "vertex")) - vertexesPos[numvertexes++] = M_GetTokenPos(); - else if (fastcmp(tkn, "sector")) - sectorsPos[numsectors++] = M_GetTokenPos(); - else - CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn); - - Z_Free(tkn); - tkn = M_GetToken(NULL); + } while (!fastcmp(tkn, "}")); } - } - else - { - CONS_Alert(CONS_WARNING, "No namespace at beginning of lump!\n"); - ret = false; + // Check for valid fields. + else if (fastcmp(tkn, "thing")) + mapthingsPos[nummapthings++] = M_GetTokenPos(); + else if (fastcmp(tkn, "linedef")) + linesPos[numlines++] = M_GetTokenPos(); + else if (fastcmp(tkn, "sidedef")) + sidesPos[numsides++] = M_GetTokenPos(); + else if (fastcmp(tkn, "vertex")) + vertexesPos[numvertexes++] = M_GetTokenPos(); + else if (fastcmp(tkn, "sector")) + sectorsPos[numsectors++] = M_GetTokenPos(); + else + CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn); + + Z_Free(tkn); + tkn = M_GetToken(NULL); } - Z_Free(nsp1); - return ret; + Z_Free(tkn); + return true; } static char* dat; @@ -1593,21 +1601,12 @@ static void P_LoadTextmap (void) static void P_LoadMapData(const virtres_t *virt) { - virtlump_t* virtvertexes = NULL, * virtsectors = NULL, * virtsidedefs = NULL, * virtlinedefs = NULL, * virtthings = NULL; - virtlump_t* textmap = vres_Find(virt, "TEXTMAP"); + virtlump_t *virtvertexes = NULL, *virtsectors = NULL, *virtsidedefs = NULL, *virtlinedefs = NULL, *virtthings = NULL; + virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); // Count map data. - if (textmap) - { - nummapthings = 0; - numlines = 0; - numsides = 0; - numvertexes = 0; - numsectors = 0; - - // Count how many entries for each type we got in textmap. + if (textmap) // Count how many entries for each type we got in textmap. TextmapCount(textmap->data, textmap->size); - } else { virtthings = vres_Find(virt, "THINGS"); @@ -2659,7 +2658,7 @@ static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock) static void P_MakeMapMD5(virtres_t *virt, void *dest) { - virtlump_t* textmap = vres_Find(virt, "TEXTMAP"); + virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); unsigned char resmd5[16]; if (textmap) From c6c00aa7d5e5ba923b28c3fa8ad53fb5eed501ad Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 30 Dec 2019 13:38:52 +0100 Subject: [PATCH 259/312] Tweak TextmapCount()'s bracket detection to account for multiple levels, if that ever happens. --- src/p_setup.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index ccb528687..55f0b4f3e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1249,6 +1249,7 @@ UINT32 sectorsPos[UINT16_MAX]; static boolean TextmapCount(UINT8 *data, size_t size) { char *tkn = M_GetToken((char *)data); + UINT8 brackets = 0; nummapthings = 0; numlines = 0; @@ -1275,21 +1276,13 @@ static boolean TextmapCount(UINT8 *data, size_t size) while (tkn && M_GetTokenPos() < size) { // Avoid anything inside bracketed stuff, only look for external keywords. - // Assuming there's only one level of bracket nesting. - if (fastcmp(tkn, "{")) + if (brackets) { - do - { - Z_Free(tkn); - tkn = M_GetToken(NULL); - if (!tkn || M_GetTokenPos() >= size) - { - Z_Free(tkn); - CONS_Alert(CONS_WARNING, "Opening bracket not closed!\n"); - return false; - } - } while (!fastcmp(tkn, "}")); + if (fastcmp(tkn, "}")) + brackets--; } + else if (fastcmp(tkn, "{")) + brackets++; // Check for valid fields. else if (fastcmp(tkn, "thing")) mapthingsPos[nummapthings++] = M_GetTokenPos(); From ea87af007678a8ca516437b4bd713d9242240eaa Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 30 Dec 2019 14:33:41 +0100 Subject: [PATCH 260/312] Refactor TextmapParse --- src/p_setup.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 55f0b4f3e..16cb785ab 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1455,33 +1455,35 @@ static void TextmapThing(UINT32 i, char *param) */ static void TextmapParse(UINT32 dataPos, size_t num, void (*parser)(UINT32, char *)) { - char *open; + char *tkn; M_SetTokenPos(dataPos); - open = M_GetToken(NULL); - if (fastcmp(open, "{")) + tkn = M_GetToken(NULL); + if (!fastcmp(tkn, "{")) { - char *tkn = M_GetToken(NULL); - while (!fastcmp(tkn, "}")) - { - dat = NULL; - parser(num, tkn); - if (dat) - Z_Free(dat); - - Z_Free(tkn); - tkn = M_GetToken(NULL); - } Z_Free(tkn); - } - else CONS_Alert(CONS_WARNING, "Invalid UDMF data capsule!\n"); - Z_Free(open); + return; + } + + Z_Free(tkn); + tkn = M_GetToken(NULL); + while (!fastcmp(tkn, "}")) + { + dat = NULL; + parser(num, tkn); + if (dat) + Z_Free(dat); + + Z_Free(tkn); + tkn = M_GetToken(NULL); + } + Z_Free(tkn); } /** Provides a fix to the flat alignment coordinate transform from standard Textmaps. */ -static void TextmapFixFlatOffsets (sector_t* sec) +static void TextmapFixFlatOffsets(sector_t *sec) { if (sec->floorpic_angle) { @@ -1510,7 +1512,7 @@ static void TextmapFixFlatOffsets (sector_t* sec) /** Loads the textmap data, after obtaining the elements count and allocating their respective space. */ -static void P_LoadTextmap (void) +static void P_LoadTextmap(void) { UINT32 i; From 7ae2143c9102c798c7db9d2583aadbc3b77f2631 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 30 Dec 2019 14:42:41 +0100 Subject: [PATCH 261/312] Add a disclaimer when loading textmaps/UDMF. --- src/p_setup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index 55f0b4f3e..839e583c8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1520,6 +1520,8 @@ static void P_LoadTextmap (void) side_t *sd; mapthing_t *mt; + CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n"); + /// Given the UDMF specs, some fields are given a default value. /// If an element's field has a default value set, it is ommited /// from the textmap, and therefore we have to account for it by From f9d6e26558aa6fd4439edfcb5380691b0074c495 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 30 Dec 2019 14:45:39 +0100 Subject: [PATCH 262/312] Replace INT16_MAX with LUMPERROR in lump check. --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 839e583c8..73c3b44f6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3536,7 +3536,7 @@ boolean P_LoadLevel(boolean fromnetsave) // internal game map maplumpname = G_BuildMapName(gamemap); lastloadedmaplumpnum = W_CheckNumForName(maplumpname); - if (lastloadedmaplumpnum == INT16_MAX) + if (lastloadedmaplumpnum == LUMPERROR) I_Error("Map %s not found.\n", maplumpname); R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette); From 4a5498473c3ff07feb45006943e59ec0b504282a Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 30 Dec 2019 14:47:48 +0100 Subject: [PATCH 263/312] Make P_LoadMapData() a return a boolean as well as P_LoadMapFromFile(); if they fail to load, they return false, and thus P_SetupLevel() will also return false. TextmapCount() also now returns false if brackets are left open inside a textmap. --- src/p_setup.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 73c3b44f6..f9ca4dcf0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1261,7 +1261,7 @@ static boolean TextmapCount(UINT8 *data, size_t size) if (!fastcmp(tkn, "namespace")) { Z_Free(tkn); - CONS_Alert(CONS_WARNING, "No namespace at beginning of lump!\n"); + CONS_Alert(CONS_ERROR, "No namespace at beginning of lump!\n"); return false; } Z_Free(tkn); @@ -1302,6 +1302,13 @@ static boolean TextmapCount(UINT8 *data, size_t size) } Z_Free(tkn); + + if (brackets) + { + CONS_Alert(CONS_ERROR, "Unclosed brackets detected in textmap lump.\n"); + return false; + } + return true; } @@ -1594,14 +1601,17 @@ static void P_LoadTextmap (void) } } -static void P_LoadMapData(const virtres_t *virt) +static boolean P_LoadMapData(const virtres_t *virt) { virtlump_t *virtvertexes = NULL, *virtsectors = NULL, *virtsidedefs = NULL, *virtlinedefs = NULL, *virtthings = NULL; virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); // Count map data. if (textmap) // Count how many entries for each type we got in textmap. - TextmapCount(textmap->data, textmap->size); + { + if (!TextmapCount(textmap->data, textmap->size)) + return false; + } else { virtthings = vres_Find(virt, "THINGS"); @@ -1684,6 +1694,8 @@ static void P_LoadMapData(const virtres_t *virt) memcpy(spawnsectors, sectors, numsectors * sizeof (*sectors)); memcpy(spawnlines, lines, numlines * sizeof (*lines)); memcpy(spawnsides, sides, numsides * sizeof (*sides)); + + return true; } static void P_InitializeSubsector(subsector_t *ss) @@ -2685,11 +2697,12 @@ static void P_MakeMapMD5(virtres_t *virt, void *dest) M_Memcpy(dest, &resmd5, 16); } -static void P_LoadMapFromFile(void) +static boolean P_LoadMapFromFile(void) { virtres_t *virt = vres_GetMap(lastloadedmaplumpnum); - P_LoadMapData(virt); + if (!P_LoadMapData(virt)) + return false; P_LoadMapBSP(virt); P_LoadMapLUT(virt); @@ -2701,6 +2714,7 @@ static void P_LoadMapFromFile(void) P_MakeMapMD5(virt, &mapmd5); vres_Free(virt); + return true; } // @@ -3549,8 +3563,8 @@ boolean P_LoadLevel(boolean fromnetsave) P_MapStart(); - if (lastloadedmaplumpnum) - P_LoadMapFromFile(); + if (!P_LoadMapFromFile()) + return false; // init gravity, tag lists, // anything that P_ResetDynamicSlopes/P_LoadThings needs to know From 72bb67320969b17d116c18392a2781751d19af58 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 30 Dec 2019 16:28:22 +0100 Subject: [PATCH 264/312] Some minor refactoring of textmap loading code --- src/p_setup.c | 54 +++++++++++++++------------------------------------ 1 file changed, 16 insertions(+), 38 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 78792f306..4d4eaff6d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1314,12 +1314,7 @@ static boolean TextmapCount(UINT8 *data, size_t size) static char* dat; -/** Auxiliary function for TextmapParse. - * - * \param Vertex number. - * \param Parameter string. - */ -static void TextmapVertex(UINT32 i, char *param) +static void ParseTextmapVertexParameter(UINT32 i, char *param) { if (fastcmp(param, "x")) vertexes[i].x = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); @@ -1327,12 +1322,7 @@ static void TextmapVertex(UINT32 i, char *param) vertexes[i].y = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); } -/** Auxiliary function for TextmapParse. - * - * \param Sector number. - * \param Parameter string. - */ -static void TextmapSector(UINT32 i, char *param) +static void ParseTextmapSectorParameter(UINT32 i, char *param) { if (fastcmp(param, "heightfloor")) sectors[i].floorheight = atol(dat = M_GetToken(NULL)) << FRACBITS; @@ -1350,12 +1340,7 @@ static void TextmapSector(UINT32 i, char *param) sectors[i].tag = atol(dat = M_GetToken(NULL)); } -/** Auxiliary function for TextmapParse. - * - * \param Side number. - * \param Parameter string. - */ -static void TextmapSide(UINT32 i, char *param) +static void ParseTextmapSidedefParameter(UINT32 i, char *param) { if (fastcmp(param, "offsetx")) sides[i].textureoffset = atol(dat = M_GetToken(NULL))<floorpic_angle>>ANGLETOFINESHIFT); fixed_t xoffs = sec->floor_xoffs; fixed_t yoffs = sec->floor_yoffs; - #define MAXFLATSIZE (2048<floor_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); sec->floor_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); - #undef MAXFLATSIZE } if (sec->ceilingpic_angle) @@ -1510,13 +1488,13 @@ static void TextmapFixFlatOffsets(sector_t *sec) fixed_t ps = FINESINE (sec->ceilingpic_angle>>ANGLETOFINESHIFT); fixed_t xoffs = sec->ceiling_xoffs; fixed_t yoffs = sec->ceiling_yoffs; - #define MAXFLATSIZE (2048<ceiling_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); sec->ceiling_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); - #undef MAXFLATSIZE } } +#undef MAXFLATSIZE + /** Loads the textmap data, after obtaining the elements count and allocating their respective space. */ static void P_LoadTextmap(void) @@ -1532,7 +1510,7 @@ static void P_LoadTextmap(void) CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n"); /// Given the UDMF specs, some fields are given a default value. - /// If an element's field has a default value set, it is ommited + /// If an element's field has a default value set, it is omitted /// from the textmap, and therefore we have to account for it by /// preemptively setting that value beforehand. @@ -1541,7 +1519,7 @@ static void P_LoadTextmap(void) // Defaults. vt->z = 0; - TextmapParse(vertexesPos[i], i, TextmapVertex); + TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter); } for (i = 0, sc = sectors; i < numsectors; i++, sc++) @@ -1561,7 +1539,7 @@ static void P_LoadTextmap(void) sc->floor_xoffs = sc->floor_yoffs = sc->ceiling_xoffs = sc->ceiling_yoffs = 0; sc->floorpic_angle = sc->ceilingpic_angle = 0; - TextmapParse(sectorsPos[i], i, TextmapSector); + TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); P_InitializeSector(sc); TextmapFixFlatOffsets(sc); @@ -1574,7 +1552,7 @@ static void P_LoadTextmap(void) ld->special = 0; ld->sidenum[1] = 0xffff; - TextmapParse(linesPos[i], i, TextmapLine); + TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter); P_InitializeLinedef(ld); } @@ -1590,7 +1568,7 @@ static void P_LoadTextmap(void) sd->bottomtexture = R_TextureNumForName("-"); sd->repeatcnt = 0; - TextmapParse(sidesPos[i], i, TextmapSide); + TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter); } for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) @@ -1599,7 +1577,7 @@ static void P_LoadTextmap(void) mt->z = 0; mt->angle = 0; - TextmapParse(mapthingsPos[i], i, TextmapThing); + TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter); } } From 05a97530c18a5f8e87fc47d27187b6a3a3542eb5 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 30 Dec 2019 17:28:10 +0100 Subject: [PATCH 265/312] Add support for flat offset and rotation fields in UDMF --- src/p_setup.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 4d4eaff6d..e4b73570f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1338,6 +1338,18 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param) sectors[i].special = atol(dat = M_GetToken(NULL)); else if (fastcmp(param, "id")) sectors[i].tag = atol(dat = M_GetToken(NULL)); + else if (fastcmp(param, "xpanningfloor")) + sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); + else if (fastcmp(param, "ypanningfloor")) + sectors[i].floor_yoffs = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); + else if (fastcmp(param, "xpanningceiling")) + sectors[i].ceiling_xoffs = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); + else if (fastcmp(param, "ypanningceiling")) + sectors[i].ceiling_yoffs = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); + else if (fastcmp(param, "rotationfloor")) + sectors[i].floorpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL)))); + else if (fastcmp(param, "rotationceiling")) + sectors[i].ceilingpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL)))); } static void ParseTextmapSidedefParameter(UINT32 i, char *param) @@ -1536,12 +1548,8 @@ static void P_LoadTextmap(void) sc->special = 0; sc->tag = 0; - sc->floor_xoffs = sc->floor_yoffs = sc->ceiling_xoffs = sc->ceiling_yoffs = 0; - sc->floorpic_angle = sc->ceilingpic_angle = 0; - - TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); - P_InitializeSector(sc); + TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); TextmapFixFlatOffsets(sc); } From 013f1f70d91dff68e496e481357dfa1d9f9b426f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 30 Dec 2019 21:23:00 +0100 Subject: [PATCH 266/312] -Set defaults for vertex and mapthing fields in textmap -Fix P_InitializeSector being called too early (band-aid fix for now, will reorganize this properly later) --- src/p_setup.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index e4b73570f..a48cfe909 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -865,11 +865,6 @@ static void P_InitializeSector(sector_t *ss) ss->lightingdata = NULL; ss->fadecolormapdata = NULL; - ss->floor_xoffs = ss->floor_yoffs = 0; - ss->ceiling_xoffs = ss->ceiling_yoffs = 0; - - ss->floorpic_angle = ss->ceilingpic_angle = 0; - ss->heightsec = -1; ss->camsec = -1; @@ -945,6 +940,11 @@ static void P_LoadSectors(UINT8 *data) ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); + ss->floor_xoffs = ss->floor_yoffs = 0; + ss->ceiling_xoffs = ss->ceiling_yoffs = 0; + + ss->floorpic_angle = ss->ceilingpic_angle = 0; + P_InitializeSector(ss); } } @@ -1235,6 +1235,8 @@ static void P_LoadThings(UINT8 *data) mt->z = mt->options; // NiGHTS Hoops use the full flags bits to set the height. else mt->z = mt->options >> ZSHIFT; + + mt->mobj = NULL; } } @@ -1529,7 +1531,7 @@ static void P_LoadTextmap(void) for (i = 0, vt = vertexes; i < numvertexes; i++, vt++) { // Defaults. - vt->z = 0; + vt->x = vt->y = vt->z = 0; TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter); } @@ -1548,8 +1550,13 @@ static void P_LoadTextmap(void) sc->special = 0; sc->tag = 0; - P_InitializeSector(sc); + sc->floor_xoffs = sc->floor_yoffs = 0; + sc->ceiling_xoffs = sc->ceiling_yoffs = 0; + + sc->floorpic_angle = sc->ceilingpic_angle = 0; + TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); + P_InitializeSector(sc); TextmapFixFlatOffsets(sc); } @@ -1582,8 +1589,13 @@ static void P_LoadTextmap(void) for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { // Defaults. - mt->z = 0; + mt->x = mt->y = 0; mt->angle = 0; + mt->type = 0; + mt->options = 0; + mt->z = 0; + mt->extrainfo = 0; + mt->mobj = NULL; TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter); } From 5e94ca07bcd8e8ce652601d01ecbbc497dc1f44b Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 30 Dec 2019 17:57:18 -0800 Subject: [PATCH 267/312] Use gametypecount in G_GetGametypeByName --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index efb580f21..96e7559ee 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3398,7 +3398,7 @@ INT32 G_GetGametypeByName(const char *gametypestr) { INT32 i; - for (i = 0; i < NUMGAMETYPES; i++) + for (i = 0; i < gametypecount; i++) if (!stricmp(gametypestr, Gametype_Names[i])) return i; From a36920808b74e068d582dda5a3b75bdf64246463 Mon Sep 17 00:00:00 2001 From: Nami <50415197+namishere@users.noreply.github.com> Date: Mon, 30 Dec 2019 19:04:27 -0800 Subject: [PATCH 268/312] Revert changes to searchBlockmap because on reflection, the benefits didn't outweigh breaking every current usage of it Readd ThinkFrame in its original position PostThinkFrame now runs at the end of P_Ticker, only MapEnd runs after it --- src/dehacked.c | 3 --- src/lua_blockmaplib.c | 40 ++++++++++++++++++++++------------------ src/lua_hook.h | 4 +++- src/lua_hooklib.c | 25 +++++++++++++++++++++++++ src/p_tick.c | 20 +++++++++++++++----- 5 files changed, 65 insertions(+), 27 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 450e33c16..4c90211cc 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9824,9 +9824,6 @@ struct { {"TC_RAINBOW",TC_RAINBOW}, {"TC_BLINK",TC_BLINK}, {"TC_DASHMODE",TC_DASHMODE}, - - {"OPT_LINES", 1}, - {"OPT_MOBJS", 1<<1}, #endif {NULL,0} diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index 2130e9333..7f7dc9560 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -18,6 +18,11 @@ #include "lua_libs.h" //#include "lua_hud.h" // hud_running errors +static const char *const search_opt[] = { + "objects", + "lines", + NULL}; + // a quickly-made function pointer typedef used by lib_searchBlockmap... // return values: // 0 - normal, no interruptions @@ -174,18 +179,29 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th // false = searching of at least one block stopped mid-way (including if the whole search was stopped) static int lib_searchBlockmap(lua_State *L) { + int searchtype = luaL_checkoption(L, 1, "objects", search_opt); int n; mobj_t *mobj; INT32 xl, xh, yl, yh, bx, by; fixed_t x1, x2, y1, y2; boolean retval = true; - boolean repeat = false; UINT8 funcret = 0; + blockmap_func searchFunc; - UINT32 flags = luaL_checkinteger(L, 1); - lua_remove(L, 1); // remove flags, stack is now function, mobj, [x1, x2, y1, y2] + lua_remove(L, 1); // remove searchtype, stack is now function, mobj, [x1, x2, y1, y2] luaL_checktype(L, 1, LUA_TFUNCTION); + switch (searchtype) + { + case 0: // "objects" + default: + searchFunc = lib_searchBlockmap_Objects; + break; + case 1: // "lines" + searchFunc = lib_searchBlockmap_Lines; + break; + } + // the mobj we are searching around, the "calling" mobj we could say mobj = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); if (!mobj) @@ -224,14 +240,8 @@ static int lib_searchBlockmap(lua_State *L) validcount++; for (bx = xl; bx <= xh; bx++) for (by = yl; by <= yh; by++) - { - if (flags & (OPT_LINES|OPT_MOBJS)) - repeat = true; - if (flags & OPT_LINES) - funcret = lib_searchBlockmap_Lines(L, bx, by, mobj); - else - funcret = lib_searchBlockmap_Objects(L, bx, by, mobj); - doitagain: + { + funcret = searchFunc(L, bx, by, mobj); // return value of searchFunc determines searchFunc's return value and/or when to stop if (funcret == 2){ // stop whole search lua_pushboolean(L, false); // return false @@ -244,12 +254,6 @@ static int lib_searchBlockmap(lua_State *L) lua_pushboolean(L, false); // in which case we have to stop now regardless return 1; } - if (repeat) - { - funcret = lib_searchBlockmap_Objects(L, bx, by, mobj); - repeat = false; - goto doitagain; - } } lua_pushboolean(L, retval); return 1; @@ -261,4 +265,4 @@ int LUA_BlockmapLib(lua_State *L) return 0; } -#endif \ No newline at end of file +#endif diff --git a/src/lua_hook.h b/src/lua_hook.h index 620a7b307..d035be097 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -21,6 +21,7 @@ enum hook { hook_MapLoad, hook_PlayerJoin, hook_PreThinkFrame, + hook_ThinkFrame, hook_PostThinkFrame, hook_MobjSpawn, hook_MobjCollide, @@ -63,7 +64,8 @@ void LUAh_MapChange(INT16 mapnumber); // Hook for map change (before load) void LUAh_MapLoad(void); // Hook for map load void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer void LUAh_PreThinkFrame(void); // Hook for frame (before mobj and player thinkers) -void LUAh_PostThinkFrame(void); // Hook for frame (after mobj and player thinkers) +void LUAh_ThinkFrame(void); // Hook for frame (after mobj and player thinkers) +void LUAh_PostThinkFrame(void); // Hook for frame (at end of tick, ie after overlays, precipitation, specials) boolean LUAh_MobjHook(mobj_t *mo, enum hook which); boolean LUAh_PlayerHook(player_t *plr, enum hook which); #define LUAh_MobjSpawn(mo) LUAh_MobjHook(mo, hook_MobjSpawn) // Hook for P_SpawnMobj by mobj type diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index ace0f14d5..d548f6a65 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -32,6 +32,7 @@ const char *const hookNames[hook_MAX+1] = { "MapLoad", "PlayerJoin", "PreThinkFrame", + "ThinkFrame", "PostThinkFrame", "MobjSpawn", "MobjCollide", @@ -436,6 +437,30 @@ void LUAh_PreThinkFrame(void) } // Hook for frame (after mobj and player thinkers) +void LUAh_ThinkFrame(void) +{ + hook_p hookp; + if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8)))) + return; + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_ThinkFrame) + continue; + + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + if (lua_pcall(gL, 0, 0, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + } + } +} + + +// Hook for frame (at end of tick, ie after overlays, precipitation, specials) void LUAh_PostThinkFrame(void) { hook_p hookp; diff --git a/src/p_tick.c b/src/p_tick.c index b92465fe4..e266f7013 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -646,9 +646,9 @@ void P_Ticker(boolean run) if (run) { - #ifdef HAVE_BLUA +#ifdef HAVE_BLUA LUAh_PreThinkFrame(); - #endif +#endif P_RunThinkers(); @@ -658,7 +658,7 @@ void P_Ticker(boolean run) P_PlayerAfterThink(&players[i]); #ifdef HAVE_BLUA - LUAh_PostThinkFrame(); + LUAh_ThinkFrame(); #endif } @@ -730,6 +730,10 @@ void P_Ticker(boolean run) G_ConsGhostTic(); if (modeattacking) G_GhostTicker(); + +#ifdef HAVE_BLUA + LUAh_PostThinkFrame(); +#endif } P_MapEnd(); @@ -764,7 +768,9 @@ void P_PreTicker(INT32 frames) memcpy(&players[i].cmd, &temptic, sizeof(ticcmd_t)); } - +#ifdef HAVE_BLUA + LUAh_PreThinkFrame(); +#endif P_RunThinkers(); // Run any "after all the other thinkers" stuff @@ -773,7 +779,7 @@ void P_PreTicker(INT32 frames) P_PlayerAfterThink(&players[i]); #ifdef HAVE_BLUA - LUAh_PostThinkFrame(); + LUAh_ThinkFrame(); #endif // Run shield positioning @@ -783,6 +789,10 @@ void P_PreTicker(INT32 frames) P_UpdateSpecials(); P_RespawnSpecials(); +#ifdef HAVE_BLUA + LUAh_PostThinkFrame(); +#endif + P_MapEnd(); } } From 41c902b819ac8fdef173c4ba76a8c50ad8107190 Mon Sep 17 00:00:00 2001 From: Nami <50415197+namishere@users.noreply.github.com> Date: Mon, 30 Dec 2019 19:11:49 -0800 Subject: [PATCH 269/312] Move PreThinkFrame hook back a bit, now runs before PlayerThink --- src/p_tick.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/p_tick.c b/src/p_tick.c index e266f7013..13209c3f9 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -629,6 +629,10 @@ void P_Ticker(boolean run) if (demoplayback) G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); + #ifdef HAVE_BLUA + LUAh_PreThinkFrame(); + #endif + for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerThink(&players[i]); @@ -753,6 +757,9 @@ void P_PreTicker(INT32 frames) { P_MapStart(); +#ifdef HAVE_BLUA + LUAh_PreThinkFrame(); +#endif for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) { @@ -768,9 +775,7 @@ void P_PreTicker(INT32 frames) memcpy(&players[i].cmd, &temptic, sizeof(ticcmd_t)); } -#ifdef HAVE_BLUA - LUAh_PreThinkFrame(); -#endif + P_RunThinkers(); // Run any "after all the other thinkers" stuff From 60928db0e0b08fee7ceddd5515adf2246bb655c3 Mon Sep 17 00:00:00 2001 From: Nami <50415197+namishere@users.noreply.github.com> Date: Mon, 30 Dec 2019 19:22:12 -0800 Subject: [PATCH 270/312] I removed a hook I left behind and forgot to save the change before committing :upside_down: --- src/p_tick.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/p_tick.c b/src/p_tick.c index 13209c3f9..9b56ee1c2 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -650,10 +650,6 @@ void P_Ticker(boolean run) if (run) { -#ifdef HAVE_BLUA - LUAh_PreThinkFrame(); -#endif - P_RunThinkers(); // Run any "after all the other thinkers" stuff From 47b096a35748cc0ef20819daabdf561c011c9c25 Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Tue, 31 Dec 2019 00:38:09 -0300 Subject: [PATCH 271/312] Disable Minecart Spawners for players already riding a minecart --- src/p_inter.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 70fb01fd0..4804905f5 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1807,23 +1807,27 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_MINECARTSPAWNER: - 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); - mcart->angle = toucher->angle = player->drawangle = special->angle; - mcart->friction = FRACUNIT; + if (player->bot) + return; + if (special->fuse > TICRATE) + return; + if (player->powers[pw_carry] == CR_MINECART) + return; + + mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART); + P_SetTarget(&mcart->target, toucher); + mcart->angle = toucher->angle = player->drawangle = special->angle; + mcart->friction = FRACUNIT; - P_ResetPlayer(player); - player->pflags |= PF_JUMPDOWN; - player->powers[pw_carry] = CR_MINECART; - player->pflags &= ~PF_APPLYAUTOBRAKE; - P_SetTarget(&toucher->tracer, mcart); - toucher->momx = toucher->momy = toucher->momz = 0; + P_ResetPlayer(player); + player->pflags |= PF_JUMPDOWN; + player->powers[pw_carry] = CR_MINECART; + player->pflags &= ~PF_APPLYAUTOBRAKE; + P_SetTarget(&toucher->tracer, mcart); + toucher->momx = toucher->momy = toucher->momz = 0; - special->fuse = 3*TICRATE; - special->flags2 |= MF2_DONTDRAW; - } + special->fuse = 3*TICRATE; + special->flags2 |= MF2_DONTDRAW; return; case MT_MINECARTEND: From 2d0cdbe34f5cdccc1395df84a66085f4b7e6bbe2 Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Tue, 31 Dec 2019 01:20:11 -0300 Subject: [PATCH 272/312] Appease the C90 entity --- src/p_inter.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 4804905f5..b28b98758 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1813,21 +1813,23 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; if (player->powers[pw_carry] == CR_MINECART) return; - - mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART); - P_SetTarget(&mcart->target, toucher); - mcart->angle = toucher->angle = player->drawangle = special->angle; - mcart->friction = FRACUNIT; + else + { + mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART); + P_SetTarget(&mcart->target, toucher); + mcart->angle = toucher->angle = player->drawangle = special->angle; + mcart->friction = FRACUNIT; - P_ResetPlayer(player); - player->pflags |= PF_JUMPDOWN; - player->powers[pw_carry] = CR_MINECART; - player->pflags &= ~PF_APPLYAUTOBRAKE; - P_SetTarget(&toucher->tracer, mcart); - toucher->momx = toucher->momy = toucher->momz = 0; + P_ResetPlayer(player); + player->pflags |= PF_JUMPDOWN; + player->powers[pw_carry] = CR_MINECART; + player->pflags &= ~PF_APPLYAUTOBRAKE; + P_SetTarget(&toucher->tracer, mcart); + toucher->momx = toucher->momy = toucher->momz = 0; - special->fuse = 3*TICRATE; - special->flags2 |= MF2_DONTDRAW; + special->fuse = 3*TICRATE; + special->flags2 |= MF2_DONTDRAW; + } return; case MT_MINECARTEND: From b68a629a7118cfeb39caea8c10443933c16dcd7e Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Tue, 31 Dec 2019 01:48:50 -0300 Subject: [PATCH 273/312] Small --- src/p_inter.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index b28b98758..67d5a8a3f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1807,13 +1807,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_MINECARTSPAWNER: - if (player->bot) - return; - if (special->fuse > TICRATE) - return; - if (player->powers[pw_carry] == CR_MINECART) - return; - else + 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); From 281f30c4fd8f6ae2630df8570d81a6780666a714 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 30 Dec 2019 22:18:55 -0800 Subject: [PATCH 274/312] Replace gametype with gametypename in SERVERINFO PACKETVERSION 1 --- src/d_clisrv.c | 14 +++++++------- src/d_clisrv.h | 4 ++-- src/m_menu.c | 18 ++++++++++++------ 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index af2be129f..302294557 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1293,7 +1293,8 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers(); netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value; - netbuffer->u.serverinfo.gametype = (UINT8)gametype; + strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype], + sizeof netbuffer->u.serverinfo.gametypename); netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); netbuffer->u.serverinfo.isdedicated = (UINT8)dedicated; @@ -2122,13 +2123,10 @@ static void CL_ConnectToServer(boolean viams) if (i != -1) { - UINT16 num = serverlist[i].info.gametype; - const char *gametypestr = NULL; + char *gametypestr = serverlist[i].info.gametypename; CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); - if (num < gametypecount) - gametypestr = Gametype_Names[num]; - if (gametypestr) - CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); + gametypestr[sizeof serverlist[i].info.gametypename - 1] = '\0'; + CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100, serverlist[i].info.version%100, serverlist[i].info.subversion); } @@ -3656,6 +3654,8 @@ static void HandleServerInfo(SINT8 node) netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0; netbuffer->u.serverinfo.application [sizeof netbuffer->u.serverinfo.application - 1] = '\0'; + netbuffer->u.serverinfo.gametypename + [sizeof netbuffer->u.serverinfo.gametypename - 1] = '\0'; SL_InsertServer(&netbuffer->u.serverinfo, node); } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 49f8afc76..c797e5ca8 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -27,7 +27,7 @@ This version is independent of the mod name, and standard version and subversion. It should only account for the basic fields of the packet, and change infrequently. */ -#define PACKETVERSION 0 +#define PACKETVERSION 1 // Network play related stuff. // There is a data struct that stores network @@ -361,7 +361,7 @@ typedef struct UINT8 subversion; UINT8 numberofplayer; UINT8 maxplayer; - UINT8 gametype; + char gametypename[24]; UINT8 modifiedgame; UINT8 cheatsenabled; UINT8 isdedicated; diff --git a/src/m_menu.c b/src/m_menu.c index 6ef9a5e19..a199b0ae3 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9971,7 +9971,7 @@ static void M_DrawRoomMenu(void) static void M_DrawConnectMenu(void) { UINT16 i; - const char *gt = "Unknown"; + char *gt; INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE; for (i = FIRSTSERVERLINE; i < min(localservercount, SERVERS_PER_PAGE)+FIRSTSERVERLINE; i++) @@ -10015,9 +10015,7 @@ static void M_DrawConnectMenu(void) V_DrawSmallString(currentMenu->x, S_LINEY(i)+8, globalflags, va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time))); - gt = "Unknown"; - if (serverlist[slindex].info.gametype < gametypecount) - gt = Gametype_Names[serverlist[slindex].info.gametype]; + gt = serverlist[slindex].info.gametypename; V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags, va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer)); @@ -10063,7 +10061,15 @@ SERVER_LIST_ENTRY_COMPARATOR(time) SERVER_LIST_ENTRY_COMPARATOR(numberofplayer) SERVER_LIST_ENTRY_COMPARATOR_REVERSE(numberofplayer) SERVER_LIST_ENTRY_COMPARATOR_REVERSE(maxplayer) -SERVER_LIST_ENTRY_COMPARATOR(gametype) + +static int ServerListEntryComparator_gametypename(const void *entry1, const void *entry2) +{ + const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; + int c; + if (( c = strcasecmp(sa->info.gametypename, sb->info.gametypename) )) + return c; + return strcmp(sa->info.servername, sb->info.servername); \ +} // Special one for modified state. static int ServerListEntryComparator_modified(const void *entry1, const void *entry2) @@ -10103,7 +10109,7 @@ void M_SortServerList(void) qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_maxplayer_reverse); break; case 5: // Gametype. - qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametype); + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametypename); break; } #endif From b4ebb01e2d9d080f66416bb36588c5b377495e41 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 30 Dec 2019 22:23:19 -0800 Subject: [PATCH 275/312] Truncate gametype name in server list if it's too long --- src/m_menu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index a199b0ae3..282e2fe1b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -10020,7 +10020,12 @@ static void M_DrawConnectMenu(void) V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags, va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer)); - V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, va("Gametype: %s", gt)); + if (strlen(gt) > 11) + gt = va("Gametype: %.11s...", gt); + else + gt = va("Gametype: %s", gt); + + V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, gt); MP_ConnectMenu[i+FIRSTSERVERLINE].status = IT_STRING | IT_CALL; } From d3c56cd80754ea289c0c9ce6f25179388e05656a Mon Sep 17 00:00:00 2001 From: lachwright Date: Tue, 31 Dec 2019 16:48:29 +0800 Subject: [PATCH 276/312] Remove flight indicator when AI Tails is taken over by second player --- src/b_bot.c | 48 +++++++++++++++++++++++++++--------------------- src/b_bot.h | 1 + src/g_game.c | 1 + 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/b_bot.c b/src/b_bot.c index dfb5ee1cf..dba156b27 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -335,27 +335,6 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) jump_last = jump; spin_last = spin; - // ******** - // Thinkfly overlay - if (thinkfly) - { - if (!tails->hnext) - { - P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY)); - if (tails->hnext) - { - P_SetTarget(&tails->hnext->target, tails); - P_SetTarget(&tails->hnext->hprev, tails); - P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR); - } - } - } - else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR) - { - P_RemoveMobj(tails->hnext); - P_SetTarget(&tails->hnext, NULL); - } - // Turn the virtual keypresses into ticcmd_t. B_KeysToTiccmd(tails, cmd, forward, backward, left, right, false, false, jump, spin); @@ -565,3 +544,30 @@ void B_RespawnBot(INT32 playernum) P_SetScale(tails, sonic->scale); tails->destscale = sonic->destscale; } + +void B_HandleFlightIndicator(player_t *player) +{ + mobj_t *tails = player->mo + + if (!tails) + return; + + if (thinkfly && player->bot == 1) + { + if (!tails->hnext) + { + P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY)); + if (tails->hnext) + { + P_SetTarget(&tails->hnext->target, tails); + P_SetTarget(&tails->hnext->hprev, tails); + P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR); + } + } + } + else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR) + { + P_RemoveMobj(tails->hnext); + P_SetTarget(&tails->hnext, NULL); + } +} diff --git a/src/b_bot.h b/src/b_bot.h index b42577c5c..54ef300a3 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -15,3 +15,4 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward boolean B_CheckRespawn(player_t *player); void B_MoveBlocked(player_t *player); void B_RespawnBot(INT32 playernum); +void B_HandleFlightIndicator(player_t *player); diff --git a/src/g_game.c b/src/g_game.c index 144975177..79ea2c70b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1718,6 +1718,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver B_BuildTiccmd(player, cmd); } + B_HandleFlightIndicator(player); } if (cv_analog2.value) { From 1a78b3548c29b1814c48c4538b20f71e8379087b Mon Sep 17 00:00:00 2001 From: lachwright Date: Tue, 31 Dec 2019 16:54:52 +0800 Subject: [PATCH 277/312] Remove flight indicator on death as well --- src/b_bot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/b_bot.c b/src/b_bot.c index dba156b27..64cb00e7e 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -552,7 +552,7 @@ void B_HandleFlightIndicator(player_t *player) if (!tails) return; - if (thinkfly && player->bot == 1) + if (thinkfly && player->bot == 1 && tails->health) { if (!tails->hnext) { From 342d80198c20717863268ae7754f15abbc8b0961 Mon Sep 17 00:00:00 2001 From: lachwright Date: Tue, 31 Dec 2019 16:55:36 +0800 Subject: [PATCH 278/312] Add missed semicolon, oops --- src/b_bot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/b_bot.c b/src/b_bot.c index 64cb00e7e..51dc4d2f2 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -547,7 +547,7 @@ void B_RespawnBot(INT32 playernum) void B_HandleFlightIndicator(player_t *player) { - mobj_t *tails = player->mo + mobj_t *tails = player->mo; if (!tails) return; From 10b71d40b8fb8c3220ef0b1f0e6ff05f718a8ba5 Mon Sep 17 00:00:00 2001 From: lachwright Date: Tue, 31 Dec 2019 17:26:35 +0800 Subject: [PATCH 279/312] Make Metal Sonic's jet fume opaque when re-emerging from water --- src/p_user.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index 02dd77668..bc4589751 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11250,7 +11250,10 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) if (panim == PA_WALK) { if (stat != fume->info->spawnstate) + { + fume->threshold = 0; P_SetMobjState(fume, fume->info->spawnstate); + } return; } } @@ -11281,6 +11284,12 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) if (underwater) { fume->frame = (fume->frame & FF_FRAMEMASK) | FF_ANIMATE | (P_RandomRange(0, 9) * FF_TRANS10); + fume->threshold = 1; + } + else if (fume->threshold) + { + fume->frame = (fume->frame & FF_FRAMEMASK) | fume->state->frame; + fume->threshold = 0; } } From e5e96cb2717ca470e969e24f5d576c4f420a8e18 Mon Sep 17 00:00:00 2001 From: lachwright Date: Tue, 31 Dec 2019 18:06:40 +0800 Subject: [PATCH 280/312] Make elemental crop circle flames obey player gravity --- src/p_user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_user.c b/src/p_user.c index 02dd77668..36bc0a2fc 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7786,6 +7786,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle) flame->fuse = TICRATE*7; // takes about an extra second to hit the ground flame->destscale = player->mo->scale; P_SetScale(flame, player->mo->scale); + flame->flags2 = (flame->flags2 & ~MF2_OBJECTFLIP)|(player->mo->flags2 & MF2_OBJECTFLIP); flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); P_InstaThrust(flame, flame->angle, FixedMul(3*FRACUNIT, flame->scale)); P_SetObjectMomZ(flame, 3*FRACUNIT, false); From 79f18a3c19232c4b6e231adcbb8d38c14f1a6bef Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Tue, 31 Dec 2019 11:19:54 -0300 Subject: [PATCH 281/312] Got rid of the uhh --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 67d5a8a3f..ff68cdf69 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1808,7 +1808,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) case MT_MINECARTSPAWNER: 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); mcart->angle = toucher->angle = player->drawangle = special->angle; From cd1cc9a222efee42628976136173f09af7f88357 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 31 Dec 2019 14:00:25 -0300 Subject: [PATCH 282/312] Fix desynch --- src/p_setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_setup.c b/src/p_setup.c index 5a7a5cb93..366fc5372 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3016,6 +3016,7 @@ boolean P_LoadLevel(boolean fromnetsave) // This is needed. Don't touch. maptol = mapheaderinfo[gamemap-1]->typeoflevel; + gametyperules = gametypedefaultrules[gametype]; CON_Drawer(); // let the user know what we are going to do I_FinishUpdate(); // page flip or blit buffer From 1c048275da96aa07b244e6295485fe4ac0b9d558 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 31 Dec 2019 14:37:45 -0300 Subject: [PATCH 283/312] **NEW!** hook_SeenPlayer --- src/lua_hook.h | 4 ++++ src/lua_hooklib.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++- src/p_map.c | 11 ++++++++--- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 68efbce93..24e61c20c 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -53,6 +53,7 @@ enum hook { hook_IntermissionThinker, hook_TeamSwitch, hook_ViewpointSwitch, + hook_SeenPlayer, hook_MAX // last hook }; @@ -97,5 +98,8 @@ void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting void LUAh_IntermissionThinker(void); // Hook for Y_Ticker boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode +#ifdef SEENAMES +boolean LUAh_SeenPlayer(player_t *player, player_t *seenplayer); // Hook for MT_NAMECHECK +#endif #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 91b4c6992..fc9d74f08 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -64,6 +64,7 @@ const char *const hookNames[hook_MAX+1] = { "IntermissionThinker", "TeamSwitch", "ViewpointSwitch", + "SeenPlayer", NULL }; @@ -207,6 +208,7 @@ static int lib_addHook(lua_State *L) case hook_PlayerCanDamage: case hook_TeamSwitch: case hook_ViewpointSwitch: + case hook_SeenPlayer: case hook_ShieldSpawn: case hook_ShieldSpecial: lastp = &playerhooks; @@ -1412,7 +1414,7 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean return 0; lua_settop(gL, 0); - hud_running = true; + hud_running = true; // local hook for (hookp = playerhooks; hookp; hookp = hookp->next) { @@ -1453,4 +1455,49 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean return canSwitchView; } +// Hook for MT_NAMECHECK +#ifdef SEENAMES +boolean LUAh_SeenPlayer(player_t *player, player_t *seenplayer) +{ + hook_p hookp; + boolean hasSeenPlayer = true; + if (!gL || !(hooksAvailable[hook_SeenPlayer/8] & (1<<(hook_SeenPlayer%8)))) + return 0; + + lua_settop(gL, 0); + hud_running = true; // local hook + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_SeenPlayer) + continue; + + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, seenplayer, META_PLAYER); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) + hasSeenPlayer = false; // Hasn't seen player + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + hud_running = false; + + return hasSeenPlayer; +} +#endif // SEENAMES + #endif diff --git a/src/p_map.c b/src/p_map.c index 25da9c58d..4a965998e 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -745,9 +745,8 @@ static boolean PIT_CheckThing(mobj_t *thing) // So that NOTHING ELSE can see MT_NAMECHECK because it is client-side. if (tmthing->type == MT_NAMECHECK) { - // Ignore things that aren't players, ignore spectators, ignore yourself. - // (also don't bother to check that tmthing->target->player is non-NULL because we're not actually using it here.) - if (!thing->player || thing->player->spectator || (tmthing->target && thing->player == tmthing->target->player)) + // Ignore things that aren't players, ignore spectators, ignore yourself. + if (!thing->player || !(tmthing->target && tmthing->target->player) || thing->player->spectator || (tmthing->target && thing->player == tmthing->target->player)) return true; // Now check that you actually hit them. @@ -760,6 +759,12 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath +#ifdef HAVE_BLUA + // REX HAS SEEN YOU + if (!LUAh_SeenPlayer(tmthing->target->player, thing->player)) + return false; +#endif + seenplayer = thing->player; return false; } From 6e330348bcc0ec895ca32e70d6d9a1d3c4d4948c Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Tue, 31 Dec 2019 19:38:11 -0300 Subject: [PATCH 284/312] Fix MP Special Stages crashing if a player is being carried when it ends --- src/p_user.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index ea42a2c36..292bad2af 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -347,6 +347,11 @@ void P_GiveEmerald(boolean spawnObj) continue; P_SetTarget(&emmo->target, players[i].mo); P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); + + // Make sure we're not being carried before our tracer is changed + if (players[i].powers[pw_carry] != CR_NONE) + players[i].powers[pw_carry] = CR_NONE; + P_SetTarget(&players[i].mo->tracer, emmo); if (pnum == 255) From 83467a7b3d584b72329e57d23638e61f6019bbbb Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Tue, 31 Dec 2019 20:13:16 -0300 Subject: [PATCH 285/312] The dumbass forgot NiGHTS mode is also a carry power --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 292bad2af..f8d1dbbc1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -349,7 +349,7 @@ void P_GiveEmerald(boolean spawnObj) P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); // Make sure we're not being carried before our tracer is changed - if (players[i].powers[pw_carry] != CR_NONE) + if (players[i].powers[pw_carry] == CR_PLAYER) players[i].powers[pw_carry] = CR_NONE; P_SetTarget(&players[i].mo->tracer, emmo); From ef4840555e2c52a781e69ade5c56a88f70963af9 Mon Sep 17 00:00:00 2001 From: Nami <50415197+namishere@users.noreply.github.com> Date: Tue, 31 Dec 2019 15:17:02 -0800 Subject: [PATCH 286/312] Add MobjLineCollide hook --- src/lua_hook.h | 3 ++ src/lua_hooklib.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++ src/p_map.c | 11 +++++++ 3 files changed, 95 insertions(+) diff --git a/src/lua_hook.h b/src/lua_hook.h index d035be097..6f8805708 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -25,6 +25,7 @@ enum hook { hook_PostThinkFrame, hook_MobjSpawn, hook_MobjCollide, + hook_MobjLineCollide, hook_MobjMoveCollide, hook_TouchSpecial, hook_MobjFuse, @@ -70,7 +71,9 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which); boolean LUAh_PlayerHook(player_t *plr, enum hook which); #define LUAh_MobjSpawn(mo) LUAh_MobjHook(mo, hook_MobjSpawn) // Hook for P_SpawnMobj by mobj type UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which); +UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which); #define LUAh_MobjCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjCollide) // Hook for PIT_CheckThing by (thing) mobj type +#define LUAh_MobjLineCollide(thing, line) LUAh_MobjLineCollideHook(thing, line, hook_MobjLineCollide) // Hook for PIT_CheckThing by (thing) mobj type #define LUAh_MobjMoveCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjMoveCollide) // Hook for PIT_CheckThing by (tmthing) mobj type boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher); // Hook for P_TouchSpecialThing by mobj type #define LUAh_MobjFuse(mo) LUAh_MobjHook(mo, hook_MobjFuse) // Hook for mobj->fuse == 0 by mobj type diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index d548f6a65..2d9a98c4b 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -36,6 +36,7 @@ const char *const hookNames[hook_MAX+1] = { "PostThinkFrame", "MobjSpawn", "MobjCollide", + "MobjLineCollide", "MobjMoveCollide", "TouchSpecial", "MobjFuse", @@ -125,6 +126,7 @@ static int lib_addHook(lua_State *L) // Take a mobjtype enum which this hook is specifically for. case hook_MobjSpawn: case hook_MobjCollide: + case hook_MobjLineCollide: case hook_MobjMoveCollide: case hook_TouchSpecial: case hook_MobjFuse: @@ -184,6 +186,7 @@ static int lib_addHook(lua_State *L) lastp = &mobjthinkerhooks[hook.s.mt]; break; case hook_MobjCollide: + case hook_MobjLineCollide: case hook_MobjMoveCollide: lastp = &mobjcollidehooks[hook.s.mt]; break; @@ -562,6 +565,84 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which) return shouldCollide; } +UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which) +{ + hook_p hookp; + UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. + if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) + return 0; + + I_Assert(thing->type < NUMMOBJTYPES); + + lua_settop(gL, 0); + + // Look for all generic mobj collision hooks + for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next) + { + if (hookp->type != which) + continue; + + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, thing, META_MOBJ); + LUA_PushUserdata(gL, line, META_LINE); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave shouldCollide = 0. + if (lua_toboolean(gL, -1)) + shouldCollide = 1; // Force yes + else + shouldCollide = 2; // Force no + } + lua_pop(gL, 1); + } + + for (hookp = mobjcollidehooks[thing->type]; hookp; hookp = hookp->next) + { + if (hookp->type != which) + continue; + + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, thing, META_MOBJ); + LUA_PushUserdata(gL, line, META_LINE); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave shouldCollide = 0. + if (lua_toboolean(gL, -1)) + shouldCollide = 1; // Force yes + else + shouldCollide = 2; // Force no + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return shouldCollide; +} + // Hook for mobj thinkers boolean LUAh_MobjThinker(mobj_t *mo) { diff --git a/src/p_map.c b/src/p_map.c index 1b6f23cde..628268bff 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1988,6 +1988,17 @@ static boolean PIT_CheckLine(line_t *ld) if (lowfloor < tmdropoffz) tmdropoffz = lowfloor; +#ifdef HAVE_BLUA + { + UINT8 shouldCollide = LUAh_MobjLineCollide(tmthing, ld); // checks hook for thing's type + if (P_MobjWasRemoved(tmthing)) + return true; // one of them was removed??? + if (shouldCollide == 1) + return false; // force collide + else if (shouldCollide == 2) + return true; // force no collide + } +#endif return true; } From caf47019cee70fabab2530969fcabf5c41c05ee5 Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Tue, 31 Dec 2019 20:20:30 -0300 Subject: [PATCH 287/312] Or is it better like this? --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index f8d1dbbc1..586c8b022 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -349,7 +349,7 @@ void P_GiveEmerald(boolean spawnObj) P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); // Make sure we're not being carried before our tracer is changed - if (players[i].powers[pw_carry] == CR_PLAYER) + if (players[i].powers[pw_carry] != CR_NIGHTSMODE) players[i].powers[pw_carry] = CR_NONE; P_SetTarget(&players[i].mo->tracer, emmo); From 24d68ba07e862ce4b36633d416b00868c72b6607 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 1 Jan 2020 13:40:17 +0100 Subject: [PATCH 288/312] P_LoadTextmap: Set defaults for all linedef and sidedef fields that UDMF is allowed to set --- src/p_setup.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index a48cfe909..e71d6094f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1563,8 +1563,11 @@ static void P_LoadTextmap(void) for (i = 0, ld = lines; i < numlines; i++, ld++) { // Defaults. - ld->tag = 0; + ld->v1 = ld->v2 = NULL; + ld->flags = 0; ld->special = 0; + ld->tag = 0; + ld->sidenum[0] = 0xffff; ld->sidenum[1] = 0xffff; TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter); @@ -1575,12 +1578,12 @@ static void P_LoadTextmap(void) for (i = 0, sd = sides; i < numsides; i++, sd++) { // Defaults. - sd->rowoffset = 0; sd->textureoffset = 0; - + sd->rowoffset = 0; sd->toptexture = R_TextureNumForName("-"); sd->midtexture = R_TextureNumForName("-"); sd->bottomtexture = R_TextureNumForName("-"); + sd->sector = NULL; sd->repeatcnt = 0; TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter); From b59532bccaa332182b56087d6a3ca1e2fe1455a2 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 1 Jan 2020 14:13:24 +0100 Subject: [PATCH 289/312] Setup repeatcnt in P_LoadSidedefs instead of P_ProcessLinedefsWithSidedefs, since UDMF can set it directly --- src/p_setup.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index e71d6094f..d00eebfc8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1014,13 +1014,11 @@ static void P_InitializeLinedef(line_t *ld) { sides[ld->sidenum[0]].special = ld->special; sides[ld->sidenum[0]].line = ld; - } if (ld->sidenum[1] != 0xffff) { sides[ld->sidenum[1]].special = ld->special; sides[ld->sidenum[1]].line = ld; - } } @@ -1053,10 +1051,30 @@ static void P_LoadSidedefs(UINT8 *data) for (i = 0; i < numsides; i++, sd++, msd++) { + INT16 textureoffset = SHORT(msd->textureoffset); UINT16 sector_num; - boolean isfrontside = !sd->line || sd->line->sidenum[0] == i; + boolean isfrontside; - sd->textureoffset = SHORT(msd->textureoffset)<line) + { + CONS_Debug(DBG_SETUP, "P_LoadSidedefs: Sidedef %s is not used by any linedef\n", sizeu1((size_t)(sd - sides))); + sd->line = &lines[0]; + } + + isfrontside = sd->line->sidenum[0] == i; + + // Repeat count for midtexture + if (((sd->line->flags & (ML_TWOSIDED|ML_EFFECT5)) == (ML_TWOSIDED|ML_EFFECT5)) + && !(sd->special >= 300 && sd->special < 500)) // exempt linedef exec specials + { + sd->repeatcnt = (INT16)(((unsigned)textureoffset) >> 12); + sd->textureoffset = (((unsigned)textureoffset) & 2047) << FRACBITS; + } + else + { + sd->repeatcnt = 0; + sd->textureoffset = textureoffset << FRACBITS; + } sd->rowoffset = SHORT(msd->rowoffset)<frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; - // Repeat count for midtexture - if ((ld->flags & ML_EFFECT5) && (ld->sidenum[1] != 0xffff) - && !(ld->special >= 300 && ld->special < 500)) // exempt linedef exec specials - { - sides[ld->sidenum[0]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) >> 12); - sides[ld->sidenum[0]].textureoffset = (((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) & 2047) << FRACBITS; - sides[ld->sidenum[1]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[1]].textureoffset >> FRACBITS) >> 12); - sides[ld->sidenum[1]].textureoffset = (((unsigned)sides[ld->sidenum[1]].textureoffset >> FRACBITS) & 2047) << FRACBITS; - } - // Compile linedef 'text' from both sidedefs 'text' for appropriate specials. switch(ld->special) { From fe198b8a324e9cadee99ffcccf69b4102a4c3609 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 1 Jan 2020 14:27:01 +0100 Subject: [PATCH 290/312] Check if certain mandatory linedef and sidedef fields are set, and use fallback values if not --- src/p_setup.c | 70 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index d00eebfc8..c915000d9 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1022,6 +1022,26 @@ static void P_InitializeLinedef(line_t *ld) } } +static void P_SetLinedefV1(size_t i, UINT16 vertex_num) +{ + if (vertex_num >= numvertexes) + { + CONS_Debug(DBG_SETUP, "P_SetLinedefV1: linedef %s has out-of-range v1 num %u\n", sizeu1(i), vertex_num); + vertex_num = 0; + } + lines[i].v1 = &vertexes[vertex_num]; +} + +static void P_SetLinedefV2(size_t i, UINT16 vertex_num) +{ + if (vertex_num >= numvertexes) + { + CONS_Debug(DBG_SETUP, "P_SetLinedefV2: linedef %s has out-of-range v2 num %u\n", sizeu1(i), vertex_num); + vertex_num = 0; + } + lines[i].v2 = &vertexes[vertex_num]; +} + static void P_LoadLinedefs(UINT8 *data) { maplinedef_t *mld = (maplinedef_t *)data; @@ -1033,8 +1053,8 @@ static void P_LoadLinedefs(UINT8 *data) ld->flags = SHORT(mld->flags); ld->special = SHORT(mld->special); ld->tag = SHORT(mld->tag); - ld->v1 = &vertexes[SHORT(mld->v1)]; - ld->v2 = &vertexes[SHORT(mld->v2)]; + P_SetLinedefV1(i, SHORT(mld->v1)); + P_SetLinedefV2(i, SHORT(mld->v2)); ld->sidenum[0] = SHORT(mld->sidenum[0]); ld->sidenum[1] = SHORT(mld->sidenum[1]); @@ -1043,6 +1063,17 @@ static void P_LoadLinedefs(UINT8 *data) } } +static void P_SetSidedefSector(size_t i, UINT16 sector_num) +{ + // cph 2006/09/30 - catch out-of-range sector numbers; use sector 0 instead + if (sector_num >= numsectors) + { + CONS_Debug(DBG_SETUP, "P_SetSidedefSector: sidedef %s has out-of-range sector num %u\n", sizeu1(i), sector_num); + sector_num = 0; + } + sides[i].sector = §ors[sector_num]; +} + static void P_LoadSidedefs(UINT8 *data) { mapsidedef_t *msd = (mapsidedef_t*)data; @@ -1052,12 +1083,11 @@ static void P_LoadSidedefs(UINT8 *data) for (i = 0; i < numsides; i++, sd++, msd++) { INT16 textureoffset = SHORT(msd->textureoffset); - UINT16 sector_num; boolean isfrontside; if (!sd->line) { - CONS_Debug(DBG_SETUP, "P_LoadSidedefs: Sidedef %s is not used by any linedef\n", sizeu1((size_t)(sd - sides))); + CONS_Debug(DBG_SETUP, "P_LoadSidedefs: Sidedef %s is not used by any linedef\n", sizeu1(i)); sd->line = &lines[0]; } @@ -1077,14 +1107,7 @@ static void P_LoadSidedefs(UINT8 *data) } sd->rowoffset = SHORT(msd->rowoffset)<sector); - if (sector_num >= numsectors) - { - CONS_Debug(DBG_SETUP, "P_LoadSidedefs: sidedef %s has out-of-range sector num %u\n", sizeu1(i), sector_num); - sector_num = 0; - } - sd->sector = §ors[sector_num]; + P_SetSidedefSector(i, SHORT(msd->sector)); sd->colormap_data = NULL; @@ -1385,7 +1408,7 @@ static void ParseTextmapSidedefParameter(UINT32 i, char *param) else if (fastcmp(param, "texturemiddle")) sides[i].midtexture = R_TextureNumForName(dat = M_GetToken(NULL)); else if (fastcmp(param, "sector")) - sides[i].sector = §ors[atol(dat = M_GetToken(NULL))]; + P_SetSidedefSector(i, atol(dat = M_GetToken(NULL))); else if (fastcmp(param, "repeatcnt")) sides[i].repeatcnt = atol(dat = M_GetToken(NULL)); } @@ -1397,9 +1420,9 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param) else if (fastcmp(param, "special")) lines[i].special = atol(dat = M_GetToken(NULL)); else if (fastcmp(param, "v1")) - lines[i].v1 = &vertexes[atol(dat = M_GetToken(NULL))]; + P_SetLinedefV1(i, atol(dat = M_GetToken(NULL))); else if (fastcmp(param, "v2")) - lines[i].v2 = &vertexes[atol(dat = M_GetToken(NULL))]; + P_SetLinedefV2(i, atol(dat = M_GetToken(NULL))); else if (fastcmp(param, "sidefront")) lines[i].sidenum[0] = atol(dat = M_GetToken(NULL)); else if (fastcmp(param, "sideback")) @@ -1589,7 +1612,16 @@ static void P_LoadTextmap(void) ld->sidenum[1] = 0xffff; TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter); - + if (!ld->v1) + { + CONS_Debug(DBG_SETUP, "P_LoadTextmap: linedef %s has no v1 set; defaulting to 0\n", sizeu1(i)); + ld->v1 = &vertexes[0]; + } + if (!ld->v2) + { + CONS_Debug(DBG_SETUP, "P_LoadTextmap: linedef %s has no v2 set; defaulting to 0\n", sizeu1(i)); + ld->v2 = &vertexes[0]; + } P_InitializeLinedef(ld); } @@ -1605,6 +1637,12 @@ static void P_LoadTextmap(void) sd->repeatcnt = 0; TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter); + + if (!sd->sector) + { + CONS_Debug(DBG_SETUP, "P_LoadTextmap: sidedef %s has no sector set; defaulting to 0\n", sizeu1(i)); + sd->sector = §ors[0]; + } } for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) From a41c6405591fd6ba8bd3f4081620be321f3dfc06 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 1 Jan 2020 15:10:41 +0100 Subject: [PATCH 291/312] Move shared parts of sidedef initialization into P_InitializeSidedef --- src/p_setup.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index c915000d9..e2ae29cf7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1074,6 +1074,19 @@ static void P_SetSidedefSector(size_t i, UINT16 sector_num) sides[i].sector = §ors[sector_num]; } +static void P_InitializeSidedef(side_t *sd) +{ + if (!sd->line) + { + CONS_Debug(DBG_SETUP, "P_LoadSidedefs: Sidedef %s is not used by any linedef\n", sizeu1(i)); + sd->line = &lines[0]; + sd->special = sd->line->special; + } + + sd->text = NULL; + sd->colormap_data = NULL; +} + static void P_LoadSidedefs(UINT8 *data) { mapsidedef_t *msd = (mapsidedef_t*)data; @@ -1085,11 +1098,7 @@ static void P_LoadSidedefs(UINT8 *data) INT16 textureoffset = SHORT(msd->textureoffset); boolean isfrontside; - if (!sd->line) - { - CONS_Debug(DBG_SETUP, "P_LoadSidedefs: Sidedef %s is not used by any linedef\n", sizeu1(i)); - sd->line = &lines[0]; - } + P_InitializeSidedef(sd); isfrontside = sd->line->sidenum[0] == i; @@ -1109,8 +1118,6 @@ static void P_LoadSidedefs(UINT8 *data) P_SetSidedefSector(i, SHORT(msd->sector)); - sd->colormap_data = NULL; - // Special info stored in texture fields! switch (sd->special) { @@ -1643,6 +1650,7 @@ static void P_LoadTextmap(void) CONS_Debug(DBG_SETUP, "P_LoadTextmap: sidedef %s has no sector set; defaulting to 0\n", sizeu1(i)); sd->sector = §ors[0]; } + P_InitializeSidedef(sd); } for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) From 6724b11c368ced28b65315942de1bd5b6003df98 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 1 Jan 2020 15:11:39 +0100 Subject: [PATCH 292/312] Whoops --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index e2ae29cf7..f72e25da0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1078,7 +1078,7 @@ static void P_InitializeSidedef(side_t *sd) { if (!sd->line) { - CONS_Debug(DBG_SETUP, "P_LoadSidedefs: Sidedef %s is not used by any linedef\n", sizeu1(i)); + CONS_Debug(DBG_SETUP, "P_LoadSidedefs: Sidedef %s is not used by any linedef\n", sizeu1((size_t)(sd - sides))); sd->line = &lines[0]; sd->special = sd->line->special; } From 9cda82d896a47179f307c0177525e390494c9219 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 1 Jan 2020 15:52:59 +0100 Subject: [PATCH 293/312] Rework textmap parser to always read a parameter's value, even if it doesn't recognize the parameter --- src/p_setup.c | 151 +++++++++++++++++++++++++------------------------- 1 file changed, 75 insertions(+), 76 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index f72e25da0..dc115ed19 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1362,135 +1362,133 @@ static boolean TextmapCount(UINT8 *data, size_t size) return true; } -static char* dat; - -static void ParseTextmapVertexParameter(UINT32 i, char *param) +static void ParseTextmapVertexParameter(UINT32 i, char *param, char *val) { if (fastcmp(param, "x")) - vertexes[i].x = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); + vertexes[i].x = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "y")) - vertexes[i].y = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); + vertexes[i].y = FLOAT_TO_FIXED(atof(val)); } -static void ParseTextmapSectorParameter(UINT32 i, char *param) +static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) { if (fastcmp(param, "heightfloor")) - sectors[i].floorheight = atol(dat = M_GetToken(NULL)) << FRACBITS; + sectors[i].floorheight = atol(val) << FRACBITS; else if (fastcmp(param, "heightceiling")) - sectors[i].ceilingheight = atol(dat = M_GetToken(NULL)) << FRACBITS; + sectors[i].ceilingheight = atol(val) << FRACBITS; if (fastcmp(param, "texturefloor")) - sectors[i].floorpic = P_AddLevelFlat(dat = M_GetToken(NULL), foundflats); + sectors[i].floorpic = P_AddLevelFlat(val, foundflats); else if (fastcmp(param, "textureceiling")) - sectors[i].ceilingpic = P_AddLevelFlat(dat = M_GetToken(NULL), foundflats); + sectors[i].ceilingpic = P_AddLevelFlat(val, foundflats); else if (fastcmp(param, "lightlevel")) - sectors[i].lightlevel = atol(dat = M_GetToken(NULL)); + sectors[i].lightlevel = atol(val); else if (fastcmp(param, "special")) - sectors[i].special = atol(dat = M_GetToken(NULL)); + sectors[i].special = atol(val); else if (fastcmp(param, "id")) - sectors[i].tag = atol(dat = M_GetToken(NULL)); + sectors[i].tag = atol(val); else if (fastcmp(param, "xpanningfloor")) - sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); + sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "ypanningfloor")) - sectors[i].floor_yoffs = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); + sectors[i].floor_yoffs = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "xpanningceiling")) - sectors[i].ceiling_xoffs = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); + sectors[i].ceiling_xoffs = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "ypanningceiling")) - sectors[i].ceiling_yoffs = FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL))); + sectors[i].ceiling_yoffs = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "rotationfloor")) - sectors[i].floorpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL)))); + sectors[i].floorpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val))); else if (fastcmp(param, "rotationceiling")) - sectors[i].ceilingpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(dat = M_GetToken(NULL)))); + sectors[i].ceilingpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val))); } -static void ParseTextmapSidedefParameter(UINT32 i, char *param) +static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val) { if (fastcmp(param, "offsetx")) - sides[i].textureoffset = atol(dat = M_GetToken(NULL))< Date: Wed, 1 Jan 2020 16:01:07 +0100 Subject: [PATCH 294/312] Move MAXFLATSIZE define to p_spec.h so p_spec.c doesn't have to redefine it --- src/p_setup.c | 4 ---- src/p_spec.c | 3 --- src/p_spec.h | 3 +++ 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index dc115ed19..8b82e8c69 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1527,8 +1527,6 @@ static void TextmapParse(UINT32 dataPos, size_t num, void (*parser)(UINT32, char } } -#define MAXFLATSIZE (2048<> ((j-1)*4))&15) +// This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize. +#define MAXFLATSIZE (2048< Date: Wed, 1 Jan 2020 23:49:29 +0800 Subject: [PATCH 295/312] Allow 6-letter character names to be drawn with the thick font --- src/st_stuff.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/st_stuff.c b/src/st_stuff.c index 9c4f0abd5..ea868b5a5 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -939,6 +939,8 @@ static void ST_drawLivesArea(void) v_colmap |= (V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER); if (strlen(skins[stplyr->skin].hudname) <= 5) V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); + else if (V_StringWidth(skins[stplyr->skin].hudname, v_colmap) <= 48) + V_DrawString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); else if (V_ThinStringWidth(skins[stplyr->skin].hudname, v_colmap) <= 40) V_DrawRightAlignedThinString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); else From 35ff383a4a7ce23039422c356e7073204f3fc8f8 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 1 Jan 2020 15:17:29 -0300 Subject: [PATCH 296/312] Rename ``seenplayer`` to ``seenfriend`` --- src/lua_hook.h | 2 +- src/lua_hooklib.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 24e61c20c..023090897 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -99,7 +99,7 @@ void LUAh_IntermissionThinker(void); // Hook for Y_Ticker boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode #ifdef SEENAMES -boolean LUAh_SeenPlayer(player_t *player, player_t *seenplayer); // Hook for MT_NAMECHECK +boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK #endif #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index fc9d74f08..5faa625b3 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1457,7 +1457,7 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean // Hook for MT_NAMECHECK #ifdef SEENAMES -boolean LUAh_SeenPlayer(player_t *player, player_t *seenplayer) +boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend) { hook_p hookp; boolean hasSeenPlayer = true; @@ -1475,7 +1475,7 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenplayer) if (lua_gettop(gL) == 0) { LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, seenplayer, META_PLAYER); + LUA_PushUserdata(gL, seenfriend, META_PLAYER); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); From 2da9c3cf8199ac0ef0206354bbcd84789cf9b00c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 1 Jan 2020 23:52:30 +0100 Subject: [PATCH 297/312] P_LoadTextmap: Bail out if certain mandatory fields are not set --- src/p_setup.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 8b82e8c69..de6503dca 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1574,9 +1574,15 @@ static void P_LoadTextmap(void) for (i = 0, vt = vertexes; i < numvertexes; i++, vt++) { // Defaults. - vt->x = vt->y = vt->z = 0; + vt->x = vt->y = INT32_MAX; + vt->z = 0; TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter); + + if (vt->x == INT32_MAX) + I_Error("P_LoadTextmap: vertex %s has no x value set!\n", sizeu1(i)); + if (vt->y == INT32_MAX) + I_Error("P_LoadTextmap: vertex %s has no y value set!\n", sizeu1(i)); } for (i = 0, sc = sectors; i < numsectors; i++, sc++) @@ -1614,16 +1620,14 @@ static void P_LoadTextmap(void) ld->sidenum[1] = 0xffff; TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter); + if (!ld->v1) - { - CONS_Debug(DBG_SETUP, "P_LoadTextmap: linedef %s has no v1 set; defaulting to 0\n", sizeu1(i)); - ld->v1 = &vertexes[0]; - } + I_Error("P_LoadTextmap: linedef %s has no v1 value set!\n", sizeu1(i)); if (!ld->v2) - { - CONS_Debug(DBG_SETUP, "P_LoadTextmap: linedef %s has no v2 set; defaulting to 0\n", sizeu1(i)); - ld->v2 = &vertexes[0]; - } + I_Error("P_LoadTextmap: linedef %s has no v2 value set!\n", sizeu1(i)); + if (ld->sidenum[0] == 0xffff) + I_Error("P_LoadTextmap: linedef %s has no sidefront value set!\n", sizeu1(i)); + P_InitializeLinedef(ld); } @@ -1641,10 +1645,8 @@ static void P_LoadTextmap(void) TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter); if (!sd->sector) - { - CONS_Debug(DBG_SETUP, "P_LoadTextmap: sidedef %s has no sector set; defaulting to 0\n", sizeu1(i)); - sd->sector = §ors[0]; - } + I_Error("P_LoadTextmap: sidedef %s has no sector value set!\n", sizeu1(i)); + P_InitializeSidedef(sd); } From 02acf6222be72d9c594f55792ad6324221e4bc52 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 2 Jan 2020 00:32:29 +0100 Subject: [PATCH 298/312] P_LoadExtendedSubsectorsAndSegs: Slightly simplify the seg vertex reading code --- src/p_setup.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index de6503dca..d83b7adaa 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2027,13 +2027,8 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype for (m = 0; m < subsectors[i].numlines; m++, k++) { UINT16 linenum; - UINT32 vert = READUINT32((*data)); - segs[k].v1 = &vertexes[vert]; - if (m == 0) - segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert]; - else - segs[k - 1].v2 = segs[k].v1; + segs[k - 1 + ((m == 0) ? 0 : subsectors[i].numlines)].v2 = segs[k].v1 = &vertexes[READUINT32((*data))]; (*data) += 4; // partner, can be ignored by software renderer if (nodetype == NT_XGL3) From ad610ba4aa65ead17d1a9696bbc76077ea3dd830 Mon Sep 17 00:00:00 2001 From: Nami <50415197+namishere@users.noreply.github.com> Date: Wed, 1 Jan 2020 19:38:48 -0800 Subject: [PATCH 299/312] Move MobjLineCollide up a bit to where we first know for sure that we hit a line --- src/p_map.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 628268bff..4cc591330 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1943,6 +1943,19 @@ static boolean PIT_CheckLine(line_t *ld) // this line is out of the if so upper and lower textures can be hit by a splat blockingline = ld; + +#ifdef HAVE_BLUA + { + UINT8 shouldCollide = LUAh_MobjLineCollide(tmthing, blockingline); // checks hook for thing's type + if (P_MobjWasRemoved(tmthing)) + return true; // one of them was removed??? + if (shouldCollide == 1) + return false; // force collide + else if (shouldCollide == 2) + return true; // force no collide + } +#endif + if (!ld->backsector) // one sided line { if (P_PointOnLineSide(tmthing->x, tmthing->y, ld)) @@ -1987,18 +2000,7 @@ static boolean PIT_CheckLine(line_t *ld) if (lowfloor < tmdropoffz) tmdropoffz = lowfloor; - -#ifdef HAVE_BLUA - { - UINT8 shouldCollide = LUAh_MobjLineCollide(tmthing, ld); // checks hook for thing's type - if (P_MobjWasRemoved(tmthing)) - return true; // one of them was removed??? - if (shouldCollide == 1) - return false; // force collide - else if (shouldCollide == 2) - return true; // force no collide - } -#endif + return true; } From 5ba179ad7c53a82cdb5810c1f292d2a0e00ed2b1 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 2 Jan 2020 09:51:07 +0100 Subject: [PATCH 300/312] Fix two bugs in extended segs loading, and add some error checking while I'm at it --- src/p_setup.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index d83b7adaa..4de5fedc8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1840,10 +1840,13 @@ static inline float P_SegLengthFloat(seg_t *seg) static void P_InitializeSeg(seg_t *seg) { - seg->sidedef = &sides[seg->linedef->sidenum[seg->side]]; + if (seg->linedef) + { + seg->sidedef = &sides[seg->linedef->sidenum[seg->side]]; - seg->frontsector = seg->sidedef->sector; - seg->backsector = (seg->linedef->flags & ML_TWOSIDED) ? sides[seg->linedef->sidenum[seg->side ^ 1]].sector : NULL; + seg->frontsector = seg->sidedef->sector; + seg->backsector = (seg->linedef->flags & ML_TWOSIDED) ? sides[seg->linedef->sidenum[seg->side ^ 1]].sector : NULL; + } #ifdef HWRENDER seg->pv1 = seg->pv2 = NULL; @@ -2026,15 +2029,21 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype case NT_XGL3: for (m = 0; m < subsectors[i].numlines; m++, k++) { + UINT32 vertexnum = READUINT32((*data)); UINT16 linenum; - segs[k - 1 + ((m == 0) ? 0 : subsectors[i].numlines)].v2 = segs[k].v1 = &vertexes[READUINT32((*data))]; + if (vertexnum >= numvertexes) + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %d in subsector %d has invalid vertex %d!\n", k, m, vertexnum); - (*data) += 4; // partner, can be ignored by software renderer + segs[k - 1 + ((m == 0) ? subsectors[i].numlines : 0)].v2 = segs[k].v1 = &vertexes[vertexnum]; + + READUINT32((*data)); // partner, can be ignored by software renderer if (nodetype == NT_XGL3) - (*data) += 2; // Line number is 32-bit in XGL3, but we're limited to 16 bits. + READUINT16((*data)); // Line number is 32-bit in XGL3, but we're limited to 16 bits. linenum = READUINT16((*data)); + if (linenum != 0xFFFF && linenum >= numlines) + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %d in subsector %d has invalid linedef %d!\n", k, m, linenum); segs[k].glseg = (linenum == 0xFFFF); segs[k].linedef = (linenum == 0xFFFF) ? NULL : &lines[linenum]; segs[k].side = READUINT8((*data)); @@ -2044,9 +2053,20 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype case NT_XNOD: for (m = 0; m < subsectors[i].numlines; m++, k++) { - segs[k].v1 = &vertexes[READUINT32((*data))]; - segs[k].v2 = &vertexes[READUINT32((*data))]; - segs[k].linedef = &lines[READUINT16((*data))]; + UINT32 v1num = READUINT32((*data)); + UINT32 v2num = READUINT32((*data)); + UINT16 linenum = READUINT16((*data)); + + if (v1num >= numvertexes) + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %d in subsector %d has invalid v1 %d!\n", k, m, v1num); + if (v2num >= numvertexes) + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %d in subsector %d has invalid v2 %d!\n", k, m, v2num); + if (linenum >= numlines) + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %d in subsector %d has invalid linedef %d!\n", k, m, linenum); + + segs[k].v1 = &vertexes[v1num]; + segs[k].v2 = &vertexes[v2num]; + segs[k].linedef = &lines[linenum]; segs[k].side = READUINT8((*data)); segs[k].glseg = false; } @@ -2063,7 +2083,8 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype vertex_t *v2 = seg->v2; P_InitializeSeg(seg); seg->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y); - seg->offset = FixedHypot(v1->x - seg->linedef->v1->x, v1->y - seg->linedef->v1->y); + if (seg->linedef) + segs[i].offset = FixedHypot(v1->x - seg->linedef->v1->x, v1->y - seg->linedef->v1->y); } return true; From dc0c17dbb85ebd06cf0e659ac33cc7ff2add7cc7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 2 Jan 2020 22:28:32 +0100 Subject: [PATCH 301/312] P_LoadExtendedSubsectorsAndSegs: Print size_t with %s --- src/p_setup.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 4de5fedc8..e3a7e1e58 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2033,7 +2033,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype UINT16 linenum; if (vertexnum >= numvertexes) - I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %d in subsector %d has invalid vertex %d!\n", k, m, vertexnum); + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid vertex %d!\n", sizeu1(k), m, vertexnum); segs[k - 1 + ((m == 0) ? subsectors[i].numlines : 0)].v2 = segs[k].v1 = &vertexes[vertexnum]; @@ -2043,7 +2043,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype linenum = READUINT16((*data)); if (linenum != 0xFFFF && linenum >= numlines) - I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %d in subsector %d has invalid linedef %d!\n", k, m, linenum); + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid linedef %d!\n", sizeu1(k), m, linenum); segs[k].glseg = (linenum == 0xFFFF); segs[k].linedef = (linenum == 0xFFFF) ? NULL : &lines[linenum]; segs[k].side = READUINT8((*data)); @@ -2058,11 +2058,11 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype UINT16 linenum = READUINT16((*data)); if (v1num >= numvertexes) - I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %d in subsector %d has invalid v1 %d!\n", k, m, v1num); + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid v1 %d!\n", sizeu1(k), m, v1num); if (v2num >= numvertexes) - I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %d in subsector %d has invalid v2 %d!\n", k, m, v2num); + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid v2 %d!\n", sizeu1(k), m, v2num); if (linenum >= numlines) - I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %d in subsector %d has invalid linedef %d!\n", k, m, linenum); + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid linedef %d!\n", sizeu1(k), m, linenum); segs[k].v1 = &vertexes[v1num]; segs[k].v2 = &vertexes[v2num]; From 26bb0b3c67d6e05d4b3ccc54891d10e348bdcc04 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 3 Jan 2020 21:50:27 +0100 Subject: [PATCH 302/312] Compressing sidedefs can break both special effects and netgame syncing, so let's get rid of it --- src/p_setup.c | 65 --------------------------------------------------- 1 file changed, 65 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index dcb2a0ae4..bd1c53104 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2548,69 +2548,6 @@ static void P_ProcessLinedefsWithSidedefs(void) } } -static void P_CompressSidedefs(void) -{ - side_t *newsides; - size_t numnewsides = 0; - size_t z; - size_t i; - - for (i = 0; i < numsides; i++) - { - size_t j, k; - line_t *ld; - - if (!sides[i].sector) - continue; - - for (k = numlines, ld = lines; k--; ld++) - { - if (ld->sidenum[0] == i) - ld->sidenum[0] = (UINT16)numnewsides; - - if (ld->sidenum[1] == i) - ld->sidenum[1] = (UINT16)numnewsides; - } - - for (j = i + 1; j < numsides; j++) - { - if (!sides[j].sector) - continue; - - if (!memcmp(&sides[i], &sides[j], sizeof(side_t))) - { - // Find the linedefs that belong to this one - for (k = numlines, ld = lines; k--; ld++) - { - if (ld->sidenum[0] == j) - ld->sidenum[0] = (UINT16)numnewsides; - - if (ld->sidenum[1] == j) - ld->sidenum[1] = (UINT16)numnewsides; - } - sides[j].sector = NULL; // Flag for deletion - } - } - numnewsides++; - } - - // We're loading crap into this block anyhow, so no point in zeroing it out. - newsides = Z_Malloc(numnewsides*sizeof(*newsides), PU_LEVEL, NULL); - - // Copy the sides to their new block of memory. - for (i = 0, z = 0; i < numsides; i++) - { - if (sides[i].sector) - M_Memcpy(&newsides[z++], &sides[i], sizeof(side_t)); - } - - CONS_Debug(DBG_SETUP, "P_CompressSidedefs: Old sides is %s, new sides is %s\n", sizeu1(numsides), sizeu1(numnewsides)); - - Z_Free(sides); - sides = newsides; - numsides = numnewsides; -} - // // P_LinkMapData // Builds sector line lists and subsector sector numbers. @@ -2777,8 +2714,6 @@ static boolean P_LoadMapFromFile(void) P_LoadMapLUT(virt); P_ProcessLinedefsWithSidedefs(); - if (M_CheckParm("-compress")) - P_CompressSidedefs(); P_LinkMapData(); P_MakeMapMD5(virt, &mapmd5); From 1e42dc7ee519ba800354ff2d78d15bcaa8c23ec0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 4 Jan 2020 11:08:05 +0100 Subject: [PATCH 303/312] Move P_ProcessLinedefsAfterSidedefs into P_LoadMapData, but move map data copying after everything else --- src/p_setup.c | 83 ++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index bd1c53104..a4e6707c0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1665,6 +1665,37 @@ static void P_LoadTextmap(void) } } +static void P_ProcessLinedefsAfterSidedefs(void) +{ + size_t i = numlines; + register line_t *ld = lines; + for (; i--; ld++) + { + ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here + ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; + + // Compile linedef 'text' from both sidedefs 'text' for appropriate specials. + switch (ld->special) + { + case 331: // Trigger linedef executor: Skin - Continuous + case 332: // Trigger linedef executor: Skin - Each time + case 333: // Trigger linedef executor: Skin - Once + case 443: // Calls a named Lua function + if (sides[ld->sidenum[0]].text) + { + size_t len = strlen(sides[ld->sidenum[0]].text) + 1; + if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) + len += strlen(sides[ld->sidenum[1]].text); + ld->text = Z_Malloc(len, PU_LEVEL, NULL); + M_Memcpy(ld->text, sides[ld->sidenum[0]].text, strlen(sides[ld->sidenum[0]].text) + 1); + if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) + M_Memcpy(ld->text + strlen(ld->text) + 1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text) + 1); + } + break; + } + } +} + static boolean P_LoadMapData(const virtres_t *virt) { virtlump_t *virtvertexes = NULL, *virtsectors = NULL, *virtsidedefs = NULL, *virtlinedefs = NULL, *virtthings = NULL; @@ -1738,6 +1769,8 @@ static boolean P_LoadMapData(const virtres_t *virt) P_LoadThings(virtthings->data); } + P_ProcessLinedefsAfterSidedefs(); + R_ClearTextureNumCache(true); // set the sky flat num @@ -1750,15 +1783,6 @@ static boolean P_LoadMapData(const virtres_t *virt) // search for animated flats and set up P_SetupLevelFlatAnims(); - // Copy relevant map data for NetArchive purposes. - spawnsectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); - spawnlines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); - spawnsides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); - - memcpy(spawnsectors, sectors, numsectors * sizeof (*sectors)); - memcpy(spawnlines, lines, numlines * sizeof (*lines)); - memcpy(spawnsides, sides, numsides * sizeof (*sides)); - return true; } @@ -2517,37 +2541,6 @@ static void P_LoadMapLUT(const virtres_t *virt) P_CreateBlockMap(); } -static void P_ProcessLinedefsWithSidedefs(void) -{ - size_t i = numlines; - register line_t *ld = lines; - for (;i--;ld++) - { - ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here - ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; - - // Compile linedef 'text' from both sidedefs 'text' for appropriate specials. - switch(ld->special) - { - case 331: // Trigger linedef executor: Skin - Continuous - case 332: // Trigger linedef executor: Skin - Each time - case 333: // Trigger linedef executor: Skin - Once - case 443: // Calls a named Lua function - if (sides[ld->sidenum[0]].text) - { - size_t len = strlen(sides[ld->sidenum[0]].text)+1; - if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) - len += strlen(sides[ld->sidenum[1]].text); - ld->text = Z_Malloc(len, PU_LEVEL, NULL); - M_Memcpy(ld->text, sides[ld->sidenum[0]].text, strlen(sides[ld->sidenum[0]].text)+1); - if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) - M_Memcpy(ld->text+strlen(ld->text)+1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text)+1); - } - break; - } - } -} - // // P_LinkMapData // Builds sector line lists and subsector sector numbers. @@ -2713,9 +2706,17 @@ static boolean P_LoadMapFromFile(void) P_LoadMapBSP(virt); P_LoadMapLUT(virt); - P_ProcessLinedefsWithSidedefs(); P_LinkMapData(); + // Copy relevant map data for NetArchive purposes. + spawnsectors = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL); + spawnlines = Z_Calloc(numlines * sizeof(*lines), PU_LEVEL, NULL); + spawnsides = Z_Calloc(numsides * sizeof(*sides), PU_LEVEL, NULL); + + memcpy(spawnsectors, sectors, numsectors * sizeof(*sectors)); + memcpy(spawnlines, lines, numlines * sizeof(*lines)); + memcpy(spawnsides, sides, numsides * sizeof(*sides)); + P_MakeMapMD5(virt, &mapmd5); vres_Free(virt); From 49667689c1e43908c0f88bc120be13bd4f09539b Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 4 Jan 2020 11:17:54 +0100 Subject: [PATCH 304/312] Provide a fix for "non-sloped" slopes launch/land behavior by checking the normal's components. --- src/p_slopes.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index e66d7ed21..2cf2c74ba 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -50,10 +50,10 @@ static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const v // Set some defaults for a non-sloped "slope" if (vec1.z == 0 && vec2.z == 0) { - /// \todo Fix fully flat cases. - slope->zangle = slope->xydirection = 0; slope->zdelta = slope->d.x = slope->d.y = 0; + slope->normal.x = slope->normal.y = 0; + slope->normal.z = FRACUNIT; } else { @@ -653,7 +653,9 @@ void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) // Handles slope ejection for objects void P_SlopeLaunch(mobj_t *mo) { - if (!(mo->standingslope->flags & SL_NOPHYSICS)) // If there's physics, time for launching. + if (!(mo->standingslope->flags & SL_NOPHYSICS) // If there's physics, time for launching. + && (mo->standingslope->normal.x != 0 + || mo->standingslope->normal.y != 0)) { // Double the pre-rotation Z, then halve the post-rotation Z. This reduces the // vertical launch given from slopes while increasing the horizontal launch @@ -710,8 +712,7 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) { vector3_t mom; // Ditto. - - if (slope->flags & SL_NOPHYSICS) { // No physics, no need to make anything complicated. + if (slope->flags & SL_NOPHYSICS || (slope->normal.x == 0 && slope->normal.y == 0)) { // No physics, no need to make anything complicated. if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope { thing->standingslope = slope; From 91222f75271aa6bf92362ba01b6993880c325e70 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 4 Jan 2020 18:05:03 +0100 Subject: [PATCH 305/312] Adapt P_ClosestPointOnLine3D() to be much like FV3_ClosestPointOnLine() and use vector3_t's as args, save for the hypotenuse calculation, which remains the same; the output should be the same as before. Adapt the rope hang snapping to the new function's form. --- src/p_maputl.c | 65 +++++++++++++------------------------------------- src/p_maputl.h | 2 +- src/p_spec.c | 43 +++++++++++++++------------------ 3 files changed, 37 insertions(+), 73 deletions(-) diff --git a/src/p_maputl.c b/src/p_maputl.c index f598595e2..afa020504 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -78,68 +78,37 @@ void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result) return; } -// -// P_ClosestPointOnLine3D -// Finds the closest point on a given line to the supplied point IN 3D!!! -// -void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result) +/// Similar to FV3_ClosestPointOnLine() except it actually works. +void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *Line, vector3_t *result) { - fixed_t startx = line->v1->x; - fixed_t starty = line->v1->y; - fixed_t startz = line->v1->z; - fixed_t dx = line->dx; - fixed_t dy = line->dy; - fixed_t dz = line->v2->z - line->v1->z; + const vector3_t* v1 = &Line[0]; + const vector3_t* v2 = &Line[1]; + vector3_t c, V, n; + fixed_t t, d; + FV3_SubEx(v2, v1, &V); + FV3_SubEx(p, v1, &c); - // Determine t (the length of the vector from �Line[0]� to �p�) - fixed_t cx, cy, cz; - fixed_t vx, vy, vz; - fixed_t magnitude; - fixed_t t; + d = R_PointToDist2(0, v2->z, R_PointToDist2(v2->x, v2->y, v1->x, v1->y), v1->z); + FV3_Copy(&n, &V); + FV3_Divide(&n, d); - //Sub (p, &Line[0], &c); - cx = x - startx; - cy = y - starty; - cz = z - startz; - - //Sub (&Line[1], &Line[0], &V); - vx = dx; - vy = dy; - vz = dz; - - //Normalize (&V, &V); - magnitude = R_PointToDist2(0, line->v2->z, R_PointToDist2(line->v2->x, line->v2->y, startx, starty), startz); - vx = FixedDiv(vx, magnitude); - vy = FixedDiv(vy, magnitude); - vz = FixedDiv(vz, magnitude); - - t = (FixedMul(vx, cx) + FixedMul(vy, cy) + FixedMul(vz, cz)); + t = FV3_Dot(&n, &c); // Set closest point to the end if it extends past -Red if (t <= 0) { - result->x = line->v1->x; - result->y = line->v1->y; - result->z = line->v1->z; + FV3_Copy(result, v1); return; } - else if (t >= magnitude) + else if (t >= d) { - result->x = line->v2->x; - result->y = line->v2->y; - result->z = line->v2->z; + FV3_Copy(result, v2); return; } - // Return the point between �Line[0]� and �Line[1]� - vx = FixedMul(vx, t); - vy = FixedMul(vy, t); - vz = FixedMul(vz, t); + FV3_Mul(&n, t); - //Add (&Line[0], &V, out); - result->x = startx + vx; - result->y = starty + vy; - result->z = startz + vz; + FV3_AddEx(v1, &n, result); return; } diff --git a/src/p_maputl.h b/src/p_maputl.h index 2ca718779..16cfc834e 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -43,7 +43,7 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, FUNCMATH fixed_t P_AproxDistance(fixed_t dx, fixed_t dy); void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result); -void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result); +void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *line, vector3_t *result); INT32 P_PointOnLineSide(fixed_t x, fixed_t y, line_t *line); void P_MakeDivline(line_t *li, divline_t *dl); void P_CameraLineOpening(line_t *plinedef); diff --git a/src/p_spec.c b/src/p_spec.c index a97d1f92f..00a71602b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5038,8 +5038,7 @@ DoneSection2: mobj_t *waypointlow = NULL; mobj_t *mo2; mobj_t *closest = NULL; - line_t junk; - vertex_t v1, v2, resulthigh, resultlow; + vector3_t p, line[2], resulthigh, resultlow; mobj_t *highest = NULL; if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG) @@ -5186,38 +5185,34 @@ DoneSection2: // Next, we need to find the closest point on the line between each set, and determine which one we're // closest to. + p.x = player->mo->x; + p.y = player->mo->y; + p.z = player->mo->z; + // Waypointmid and Waypointlow: if (waypointlow) { - v1.x = waypointmid->x; - v1.y = waypointmid->y; - v1.z = waypointmid->z; - v2.x = waypointlow->x; - v2.y = waypointlow->y; - v2.z = waypointlow->z; - junk.v1 = &v1; - junk.v2 = &v2; - junk.dx = v2.x - v1.x; - junk.dy = v2.y - v1.y; + line[0].x = waypointmid->x; + line[0].y = waypointmid->y; + line[0].z = waypointmid->z; + line[1].x = waypointlow->x; + line[1].y = waypointlow->y; + line[1].z = waypointlow->z; - P_ClosestPointOnLine3D(player->mo->x, player->mo->y, player->mo->z, &junk, &resultlow); + P_ClosestPointOnLine3D(&p, line, &resultlow); } // Waypointmid and Waypointhigh: if (waypointhigh) { - v1.x = waypointmid->x; - v1.y = waypointmid->y; - v1.z = waypointmid->z; - v2.x = waypointhigh->x; - v2.y = waypointhigh->y; - v2.z = waypointhigh->z; - junk.v1 = &v1; - junk.v2 = &v2; - junk.dx = v2.x - v1.x; - junk.dy = v2.y - v1.y; + line[0].x = waypointmid->x; + line[0].y = waypointmid->y; + line[0].z = waypointmid->z; + line[1].x = waypointhigh->x; + line[1].y = waypointhigh->y; + line[1].z = waypointhigh->z; - P_ClosestPointOnLine3D(player->mo->x, player->mo->y, player->mo->z, &junk, &resulthigh); + P_ClosestPointOnLine3D(&p, line, &resulthigh); } // 3D support now available. Disregard the previous notice here. -Red From 9999be2d6e14fd605d55ac3fe4f28c088e497880 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 4 Jan 2020 18:29:02 +0100 Subject: [PATCH 306/312] Remove vertex_t's z variable. --- src/lua_maplib.c | 7 +------ src/p_setup.c | 2 -- src/r_defs.h | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 8ce6551f7..309ba86a1 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -157,15 +157,13 @@ static const char *const side_opt[] = { enum vertex_e { vertex_valid = 0, vertex_x, - vertex_y, - vertex_z + vertex_y }; static const char *const vertex_opt[] = { "valid", "x", "y", - "z", NULL}; enum ffloor_e { @@ -970,9 +968,6 @@ static int vertex_get(lua_State *L) case vertex_y: lua_pushfixed(L, vertex->y); return 1; - case vertex_z: - lua_pushfixed(L, vertex->z); - return 1; } return 0; } diff --git a/src/p_setup.c b/src/p_setup.c index bd1c53104..fa60fcf6d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -846,7 +846,6 @@ static void P_LoadVertices(UINT8 *data) { v->x = SHORT(mv->x)<y = SHORT(mv->y)<z = 0; } } @@ -1575,7 +1574,6 @@ static void P_LoadTextmap(void) { // Defaults. vt->x = vt->y = INT32_MAX; - vt->z = 0; TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter); diff --git a/src/r_defs.h b/src/r_defs.h index 96ef953ce..c7c198d66 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -83,7 +83,7 @@ typedef struct extracolormap_s */ typedef struct { - fixed_t x, y, z; + fixed_t x, y; } vertex_t; // Forward of linedefs, for sectors. From 664bce71deae6135cbb58c840ba2293a61ab7ea7 Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Sun, 5 Jan 2020 23:18:38 -0300 Subject: [PATCH 307/312] :amybruh: --- src/p_mobj.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index e8461957f..713a4d476 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7977,15 +7977,18 @@ static void P_MobjSceneryThink(mobj_t *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) + + // :amybruh: + if (!mobj->fuse) { - P_RemoveMobj(mobj); +#ifdef HAVE_BLUA + if (!LUAh_MobjFuse(mobj)) +#endif + P_RemoveMobj(mobj); return; } + if ((--mobj->fuse) < 6) mobj->frame = (mobj->frame & ~FF_TRANSMASK) | ((10 - (mobj->fuse*2)) << (FF_TRANSSHIFT)); - } } break; case MT_VWREF: From fce1313517658f86b7865d823a2e42af6dbba919 Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Sun, 5 Jan 2020 23:19:52 -0300 Subject: [PATCH 308/312] No comments --- src/p_mobj.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 713a4d476..05a535175 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7978,7 +7978,6 @@ static void P_MobjSceneryThink(mobj_t *mobj) mobj->y = mobj->extravalue2 + P_ReturnThrustY(mobj, mobj->movedir, mobj->cvmem*mobj->scale); P_SetThingPosition(mobj); - // :amybruh: if (!mobj->fuse) { #ifdef HAVE_BLUA From 07f9ddc45a169e3ab23aa528428482df58f142b6 Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Sun, 5 Jan 2020 23:41:22 -0300 Subject: [PATCH 309/312] Don't fuck with the fuse if it's negative --- src/p_mobj.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 05a535175..fbfbaab00 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7986,6 +7986,8 @@ static void P_MobjSceneryThink(mobj_t *mobj) P_RemoveMobj(mobj); return; } + if (mobj->fuse < 0) + return; if ((--mobj->fuse) < 6) mobj->frame = (mobj->frame & ~FF_TRANSMASK) | ((10 - (mobj->fuse*2)) << (FF_TRANSSHIFT)); } From 759b1c82e28325530deec9c4720b31ca33965c96 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 6 Jan 2020 14:40:59 +0100 Subject: [PATCH 310/312] Add missing glseg checks (and remove a superfluous one) --- src/hardware/hw_bsp.c | 6 +++++- src/hardware/hw_main.c | 7 ++++--- src/p_sight.c | 3 +++ src/r_main.c | 12 +++++++++--- src/r_segs.c | 3 --- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index f8d4f43d9..6f3dd9fbd 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -449,8 +449,12 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly) // for each seg of the subsector for (; count--; lseg++) { - //x,y,dx,dy (like a divline) line_t *line = lseg->linedef; + + if (lseg->glseg) + continue; + + //x,y,dx,dy (like a divline) p1.x = FIXED_TO_FLOAT(lseg->side ? line->v2->x : line->v1->x); p1.y = FIXED_TO_FLOAT(lseg->side ? line->v2->y : line->v1->y); p2.x = FIXED_TO_FLOAT(lseg->side ? line->v1->x : line->v2->x); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 276a66670..8c36eeded 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2714,8 +2714,6 @@ static void HWR_AddLine(seg_t * line) static sector_t tempsec; fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t - if (line->glseg) - return; #ifdef POLYOBJECTS if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES)) return; @@ -3773,9 +3771,12 @@ static void HWR_Subsector(size_t num) while (count--) { + + if (!line->glseg #ifdef POLYOBJECTS - if (!line->polyseg) // ignore segs that belong to polyobjects + && !line->polyseg // ignore segs that belong to polyobjects #endif + ) HWR_AddLine(line); line++; } diff --git a/src/p_sight.c b/src/p_sight.c index 499d4a095..07dfabbc1 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -222,6 +222,9 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) fixed_t fracx, fracy; #endif + if (seg->glseg) + continue; + // already checked other side? if (line->validcount == validcount) continue; diff --git a/src/r_main.c b/src/r_main.c index a5f4bc118..22061b407 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -698,6 +698,7 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y) INT32 side, i; size_t nodenum; subsector_t *ret; + seg_t *seg; // single subsector is a special case if (numnodes == 0) @@ -713,10 +714,15 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y) } ret = &subsectors[nodenum & ~NF_SUBSECTOR]; - for (i = 0; i < ret->numlines; i++) - //if (R_PointOnSegSide(x, y, &segs[ret->firstline + i])) -- breaks in ogl because polyvertex_t cast over vertex pointers - if (P_PointOnLineSide(x, y, segs[ret->firstline + i].linedef) != segs[ret->firstline + i].side) + for (i = 0, seg = &segs[ret->firstline]; i < ret->numlines; i++, seg++) + { + if (seg->glseg) + continue; + + //if (R_PointOnSegSide(x, y, seg)) -- breaks in ogl because polyvertex_t cast over vertex pointers + if (P_PointOnLineSide(x, y, seg->linedef) != seg->side) return 0; + } return ret; } diff --git a/src/r_segs.c b/src/r_segs.c index 1af1cb2a2..dcb5fc160 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -309,9 +309,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // OPTIMIZE: get rid of LIGHTSEGSHIFT globally curline = ds->curline; - if (curline->glseg) - return; - frontsector = curline->frontsector; backsector = curline->backsector; texnum = R_GetTextureNum(curline->sidedef->midtexture); From 21c224fce0a2a72f5a6be2477fe6a892120161fe Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Mon, 6 Jan 2020 09:58:05 -0500 Subject: [PATCH 311/312] idented hell --- src/hardware/hw_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 8c36eeded..2f986085a 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3774,11 +3774,13 @@ static void HWR_Subsector(size_t num) if (!line->glseg #ifdef POLYOBJECTS - && !line->polyseg // ignore segs that belong to polyobjects + && !line->polyseg // ignore segs that belong to polyobjects #endif - ) + ) + { HWR_AddLine(line); - line++; + } + line++; } } From 360e8f28b4da34062eaf1845855070af8c3e4492 Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+Ikkarin@users.noreply.github.com> Date: Tue, 7 Jan 2020 01:24:04 -0300 Subject: [PATCH 312/312] ifdefs make indenting confusing --- src/p_mobj.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index fbfbaab00..3d8d81d9b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7979,13 +7979,13 @@ static void P_MobjSceneryThink(mobj_t *mobj) P_SetThingPosition(mobj); if (!mobj->fuse) - { + { #ifdef HAVE_BLUA - if (!LUAh_MobjFuse(mobj)) + if (!LUAh_MobjFuse(mobj)) #endif - P_RemoveMobj(mobj); - return; - } + P_RemoveMobj(mobj); + return; + } if (mobj->fuse < 0) return; if ((--mobj->fuse) < 6)