From d27a5d7992f284f057ee27e1cacf230b97943130 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 3e9e57b3b3e3360e29a755ee2c03d4a333ac8340 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 940c36ef2433cc805ce777f1da61ebe8e1b057e7 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 3214ad0b3ae3a49d02c4cb5f6b32f5a006c656a7 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 5b61af47b07aef0bd585292ef3b127566af9e02c 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 be3234a4e8c033a1393f7c2af0c6c8bfe540a62b 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 a57ead226e4968dce07125396d861caaee914198 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 23c0c8f68ee5c642ef797b1bd0721947e4050919 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 ffb11a6bedacb405cff4b5cf8fb7be1634b6fed5 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 03dab2ae5eed48b03da179185032aa6ad11a2781 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 ea6becb8761295f5ad6cee39c9ae95acfb5ecb91 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 22392eaa5fc7288663bb14eb7c9cbaf615aaa53c 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 b9f99792db2cfee6ae2a0392bbac1ad1fd85d7b1 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 576ad30c24584b1111085618a7fda63c842077e2 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 935a1d182c5f5c2388638049e20f772b4c1c0c45 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 9ab93730841f247eb83c57866d71ab87275140b4 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 2e1460cb5c8b371c326583dc758fef070fdcddc8 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 3da7a69d0b65c8bf539e83388a46433c9194b7d7 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 2d526c9a3b418fd3ca06d19b687e0b16a8c0e419 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 a7f501615d80a401c59bdad9c2410c1d873f7685 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 eff34fc970dea25650c0d6704aab821e2f1496ef 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 e3dbbfe34a3df9819940e0b0d818df6954689f0d 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 7fba63d1faa9554de7d9c0b82ab20ce9ecb08d43 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 71767b7d1113cf90574dca46e2adf208f2ffbf40 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 f223446e2e3b1b73d5d899072364d39c8c1b0a50 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 e1df80adacd1e4a0738a8f7dfd4383a3cff4da33 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 3c9354991e868f34fd2ff3b975d3f3aa3abfbc92 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 a144523a42f42747b2e9790a9acf63d2633d2455 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 b0a42140e60646ddf375a9c992b6be545290485d 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 3022d559c84c9c8b72094b14faf8409df590a24b 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 06f02e81ddc3a48599c063dc8b5118295943bce2 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 6797e328bb71fb39d2787aee297411527efaf636 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 889bbdf96d8aa3bc85ffb71187c52396bc788c0a 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 be227cc58c227ee83e91b0b16c5b6885d1f7ce4d 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 44ae8fdb6a96c0dc21f2ff1f4e4a4b352f2aa22c 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 9916c88baa7273a405af24fc79e24f3eb67622b3 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 a91077278bdf361370bb9ca337eebfd15ef5358f 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 607d066c01a43f766072103bbb2ea6351582ca67 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 d0f86284ceda9129ac827545789b0180c9b57c89 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 d7cb14d38e400569a6365a5d341e05aaf504f3d2 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 448494e19bc6734d2d206e0402d36d8d4f755ebf 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 45d67e8ae95f059643b82ad895a0539bc7fbe6ca 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 789e881abc37f0e49043b94cfde763c3a63f0555 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 29d316fd74ab437f3b365996c9a5c512da3dd34d 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 31f3299bc29125d593db958d12a31e22589c9be9 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 ecf9bdda4e1a97d82b55e107b6ec8f22dfc5c8e9 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 c11865e7e9b6ec9f73177522940044c51e111988 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 164c1b15e740b4e60ee04af3c12d20be094783c5 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 30be9e29e5103ce2c981e96cef1c538d14695313 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 b6b98cd46475563ee770e3fa051956b4e7610367 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 c75d0efce974c6daef744d001e0ff13cd2c7ce9c 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 a0cee9b35f055a6cca84280c38c576d689017412 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 9b900e6fc79c2e75c96b162128718ed17e89eadd 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 a82a5e664c59683422e5ad1c978b5f5f7e16c20e 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 78f4997164a082b0c88a027e7a914342004477b3 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 8f4ea4a11eee427d1534eefcf618147987ec62bd 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 0323205a9a7652c2ed24a061e9b95ae6a7a1f815 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 968d1bb875d97b40450e40d5b7e0ff71fe769a39 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 79f7bf2276d3bc11a097e24edb6c052995c30ca0 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 9c5a3b637c7688b98bfec7dd43b7cf914080f82c 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 52cc04ef7884934582f53e360f96f6338ba8ee91 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 d29bce1a21bdfd72083e1a8094eda14f35564ecd 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 4fecde58b9d8e3ee5927a1897603e1ff707f1cbb 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 97db6162e8114da9520ce8152af74addefd41464 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 35f783ab240177964fc89b02566ae2eb3a99d8a4 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 0e3bf527a29a4b583cdcdf5d65ac82de3b9a2a89 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 156d5fd37f733ea925289e6e3ba45af1bc903f20 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 24f546d9925a8c7221563fd13409c0214cc4f982 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 25481512e70c1d69b95f525cc516c71f05759d54 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 f9bbcfc0f3a367cb8612d88ec922879b24c07a8c 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 782643564fdb66ec483df6677578036ca8335b92 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 a0993baa0b45434de79d15ae04b2f805bc6ad158 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 e47f171533534b24ca45e0f35be34ef452b3e116 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 ac74a2a0202c7d7792132c33c7455b800c13bc66 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 b65c6e3745415460e6426516fd93bde9ed9f2457 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 861fa5bb23ada1823cfeff0a52902813917030c0 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 29b819015a4f62f64405eed7f90288f1a110dd0d 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 4be3a0706c7dd82666350004b8c8c5ce77241551 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 920d99976ce18cc1fdc481e6dcfde69d0809c092 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 8bd0fc842fed625de8ff1fa3c7595823fe8e51a4 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 6c2b62a795f3cd97192f3f75ec27ef9937d7f4bd 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 108129b2221c4464b0f56817f529db185beebe02 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 9b1d5db5f8b74450fdc8764a3f4c7ff83d207ad4 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 18235cd6722aba1875953480a73fe359b35ef0d5 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 063d4d0d866bc807dfb3f149c0725c8e327ce25b 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 a4ce7e908d6eda5fd0db029010f75df5b292d339 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 f94cfb59291b3f57570f9322ffd2404ec0d2d2e7 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 b8671edef43f6ca73eb818177155ef33074b690f 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 2eec0b6a9bb94b2ff994b64a74921697e8fb863f 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 d80a6e11e70acc49958bee643648ce1cd0dc3f17 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 644d0d86ad32c5e5b6e740f123b526b14eded2f9 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 14673656c3b8387eb519bef33e3851645195cd56 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 5281c4404295f30828c2db34abf03c0ee363345a 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 0fd9596e3c2450dc39cf75938f9b12a0710ee53b 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 2e802dde5ca25bd8bad7e65aae987d4a209a94b2 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 75cbfe9e54b8c1b28f5c447a2ae58b9d5e5548b9 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 783b2fbb3c8139cab98a739ebe95bd332eb5e4d5 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 7be95c1999d5a3475be804cd8a809be937f00f45 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 26d80c2b12e035d97863978aa533c120dff88ae8 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 befe33e239ba95403ff6f031466af4ea01e29c51 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 63e078286b240d69646be20c02be5b960614dc0b 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 0fa8936966beafb3c98206d88e827139a3b62d6d 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 81c95779959d9791107faf2f1a19ba102edbc9ec 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 b1344fd8f02e1ef88eaea874276c6c3c3e7baf59 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 a99a307ed4bb17ddcd92626d479e5037e6f2f699 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 d3ac0a305ac8466c58084700063ae093bf31edbd 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 06bbfb11d8818439933fa52fb56bbe067d4a67d3 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 2cac61dd28d567a713014634813af9ce189d77a7 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 4d5cb2ddf8f8de801ee1cfb6003fcdf83a6d08a1 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 39321e8637b7a971f4de416791b756f553b2acf1 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 d822fad7884f299bd3da0dd36a812dde39a08529 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 c52edb6eff17eacfaa2db4afa21f6a01d77e67c3 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 15a403c39bb84c171ae71c5c238f510419d8ec52 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 6a5d68a9795ce02e952e4c969f98bc3cd40af462 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 4ebbe4e5180ed4bb1fe9aff855615bac9eaca76a 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 1edc72a3b89c6b03cd77c87d1355bc94bc2a21f4 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 aa0081f70b8fc0958cace089b7ab9521e38073d2 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 1809cb8e82bd59664635b183b79b516687bf9677 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 60cf1e1837d1ed1e9e552fb7be675459a00cfb8c 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 62f2fcc57e45c81d54e84b1e14c9a9caa139c464 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 ba5516b99f99c4fc21ccfb11ee48b1f287a5a7c7 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 73bb0567cc4765abd9514469515309e793dd7eea 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 7dc370d7864ca0669c0b618be5721d7d66a9a441 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 c832d26ee9dc3f8add3de4c411b40ef0ba77a8a8 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 b1add480639ab0403c5a08124198a2e90b7cc4b4 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 d146594895bca12cefd52b8b08ecce230eb07c5c 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 463f2619ec072cc5ad99a97304419ff1584d283d 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 23d7b726d41da79521447a3f3ba11d188fd7e42f 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 cb4fbaa59661c12894a01c3a6a85216d7bb195d2 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 e6608f451989d1a892b0801f2d91a08235f6321b 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 196e76cece297a3df559210c83693537fa0be5f9 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 1d6e6b70725f473875b41a57c85f566f0c04b7f3 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 68238107f81b91ac6cd015b9ab4911d38f0615d6 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 dac90147864fa0ec669fc6f1f44fdc6b66543652 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 464a476a54b3f9c4258771eb944df1b9e93d353a 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 a4adb0d873da2861079a07aa78a95ce26007cc78 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 418cc50bbc71075e89da32faac053c84abce55a6 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 4f54da125d2f6134db8185cd2b4464f892fb7e54 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 c76154d3a12dbf51afd76cff809a845b07856e64 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 c6dd9f016e1bdbfb7584515354a459c10f81886d 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 debacf34bbc30ba209ffa26a3f67f8bcb8b9eaff 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 edd6f743ec0886abf46014a42f6847e80f009fa1 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 caa080021397e0b71db9dc33688cafa1a5e2de83 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 ffa78e15314035ab0c2aa3b48cfdc0fccd3f3e3f 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 86381d31bfb338c61892cc44872a2383d30d1a19 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 14086ce86d9defdd1470ea4f60241fbbfaef4058 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 8647d2784bcadf10bf981443b990af7d27a9f404 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 721f3c037322423554fd1f2e5c499f53447178c9 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 07ec13b3090a8683966359639fedee383466352a 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 69539e640b11aa751f3c4a708cf7d5195735dd76 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 b5d6c40d68cefdf50b31d2a60d5a92bac00ae6c5 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 1db2f6447d5de54f6dcb09e8450a07f7f9e89dd0 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 27361fbf4327f38590383c4b31b56da40c549cae 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 c4a6424642a429026cf6ec843c707e64ef80ae90 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 d2e7e6cd9c220de2eb1ade77fccb613d1cd768a6 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 bdacaa64ab95b2e10454333a94530bd2bc55d4cf 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 12f0e584b27b2f90087488eecede750dec35eb14 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 14fed1f64476ff99938252d427cd247de3e0f12a 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 c1b52069e32215d9b5f94a56074e7f7611993976 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 64792ab9fd3c9fd129c4ce4dab5ecaa440ab27f2 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 176b853b017728142581babe3c71719c37723607 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 015f3a36d2334bc8050d1b718a8664d0ac673ef1 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 92ca7e9f24440a6d6ffab9dc21b6b3c9059d3044 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 b1a43c7c4abdbd1abc1c7a8d863e74d06c550a75 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 f34261041383a29e425d2b60914c2fabbb9ae053 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 3bafa90b7a5f405b28bd8fafea37ebbc3cd34919 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 f65ac6feabb6662b1dc4f5f36426eba23933b2eb 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 a1875381570f2f068ca4bc4a5653fb616b96e87f 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 a88b0bffe717aef4feae518c293561606f3da4a7 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 c8e08ec617c462e3e50e510c2421b23a48bac113 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 c92378fab71e51d5369844c247c7b33112b828c0 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 5b715fa11a9ce32457d3fadd7de8f9366d3b7eff 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 be323975629af6e08be003febacfd3ce3dc49bc4 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 adb34258f1863d2e84b0078241de1f41f37d4957 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 ca3941f5b87331c0902480c220f264f38ea299fd 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 5e328d6d332980376dae47e1f69c6f932f1aac0b 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 964125c8cfc49d55453199aa1f688a71d159864e 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 203f4c50a0516f26f2eac8e61be9340558c31c6e 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 8a3b47e1a9519cfb46340631e7c59538a5655263 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 3ce02b813557f7b5214229a2c8efb18c023f18be 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 ad56f5e36278894ec05c6c6f530375e2a5649842 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 6092c5774e9e15d6d209cf232c89cce8d21596c3 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 58c1adf3ef0cd585a7f23c493b08c13cbd75d3c8 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 ff80c4ef4dc4316fda0e62b8a86af65027224c82 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 62d79eef2a3e6ffc0c042ab9c2ebc1fa048349de 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 142875cf3df93ec49503d05049fb0adb1c1c39a4 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 9ede8f7c2edba4d5d6f47138de4537af97a2cc7d 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 7d4c00affbc8fb17a47d78065789da04547e2f0a 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 821e1cf618c18b6c50d5cf0e7d38cb85b2dd29af 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 655de1aca8d43cec9fe172a3996ed8a039d04320 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 12fbaf85f8b6f41239aae4822c2b1e04ca7de4c7 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 f67ff6d97e56b0e62b9c99913cef88b4ed98e5b4 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 9b81821d44557ea5b0cf9fbb887145319db480b9 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 d00a9a42a1c143423881fc0bbfd2b3e300693bef 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 e3955ed4f39522b33951e117290f1c7649495c79 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 d085296cbe4a3c972c9ada4b1f6079d06390949b 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 af85de53d751653cb08a24f41408d9b3035b8450 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 45359f830b42f2d83259d9ba4f8eb8dd07e1866b 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 04dcc177ea31ce58b831d63729490096c1bfcb46 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 06bcb74b37485ecfb34bf67cbd8e107371b42b71 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 8646f6061c259c68cb166d4c9059e36aa0508556 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 532a1bbfb77c39c9e2461e608b95bd322d9cda16 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 f06184b46676c130f56c2f1de2469d110f398d5c 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 40d45d92218c2338f1d094f075cc13d296e90a4d 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 ea402eea0963bab12dc5d4be9fa858cd3e61a2a2 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 411b1e17d97836659234473db711df3bbfd5beb0 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 65c5f7f5710a9a7ce54756ae69c51688abd7cf2e 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 a7fa90d11d5d4cc67e24f75b4b3cf9c25e15ed02 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 63132da7e0a8f5800cec911b10b30dd82137030f 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 41e5789e04827598ca4656838572ddcec0f08ecc 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 d16563487096127106b0fdb48e98c09188f522ae 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 8f0d5bf46872c3b041cb4ad5eeff382c30b57906 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 e5e4b4891a1d90b1a225896c0ab73965d94bd8ed 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 4dafc59133d315c7425b5aef50bcdf1d837437b0 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 37b1953a143fbc843339adc5db670e46aa010d85 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 31b03fadcd070596b0ae436e8d6971ae5fd6c1a4 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 efad84a2d5adbd4e0013a1b474accac0502b0db0 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 196e76cece297a3df559210c83693537fa0be5f9. --- 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 0ecbd0baec329796cd008ee96b023b0bdeff2492 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 1fc2a4755a9c68c60ef500ae0054418668c97d4f 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 2cf9408a7dafa6d084ef349c3d0fbd134fa873a4 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 1e3a06f420c5c987ff9eac77c48bae6fa09b5f7f 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 d689e06c6a8ae3f996416742a935317a34d3b6ba 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 ae66bbda2423853d51072bbac4d2073a6bb05e7e 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 464c2b04de6f5a822403ab32ef39f1995f7c816b 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 ac6c61e419900b8fb852e4d553fb57579e7a2d9d 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 39f3a1e88d0b922e82ff7fa3b80e346df4a3d3a1 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 3a02aa1c4e702dd2ddf5f28f0e6459ba70151cd8 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 2925030f8f1e4d605fe068e9aa02e9efc2048599 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 a73dc9a4d034762b00244bac4e0bf5768dc87eb0 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 039219d47890bbad8af036fe72dbf3c94f7523b7 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 9ccd74e99ade514bea213270d0adacaaed2c002b 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 3a123654b49c17f24c0d6de90d8227aecbf47fb7 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 24acac6fe2e1c1a11ce48adf4feecc656140987f 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 f74798f02027235e4915db1fb02c102d870eadf4 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 24acac6fe2e1c1a11ce48adf4feecc656140987f. --- 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 108af9935e9c895dbdd6d136a0cb7de7eed732ed 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 2f6ec18562636d827eb4fe82b6df26d46b2437da 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 d01fb277dce5cb4770b564cc9447bf843e3358f9 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 e4d1b9491c1137530e2b4b9d34e5f94d2bad10ac 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 6e8a023fddbc9e90f48b1b3ccf3f79dc4e6a32b8 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 69663fe87257d69c1871cbeb91017a564543c97b 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 dd66aa9a14f491da04e7ff80fafb6b671bcbc0c0 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 71d13d1a67d676bf0b5ea53107ac26d10ce3c721 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 ac814630317796dbd2613dd016fc655662a746a4 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 fadebabc78b8fcb10071cdf06b81f6a55fe5b2d6 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 6fe6cfad1a10cadea2039184619853672a9063dd 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 014d2f63582f89549ee58805723392ffd766f874 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 9c07bde69ca9b1f5e2b8a79bbf23b0f228df1563 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 dd56500ed06aaf864735f294368ce5a9efd96c75 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 8756b81fa01768dd908447a6d5d8dba3a0c5fede 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 0edb23eaf7efb795426c6586b1bec3a3cdc82e13 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 73698c70aa89cfe37f32a1a661caa9db362e45cd 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 839718499dd348a5de9b44e5dec786d8553b9943 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 b22460bd325cae8c37857f23f9a8da510bd3b2d9 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 dff1e92ba8e2accdc516e311385f37157c8cf376 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 1654119ae91f52a9d268975bb3a991b742ba879b 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 2e8f83b79c476d8ec69bc8ab0b9da3ecf3fbab9f 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 4456ff50abfb3207dadd9a033e6f3e1e3ee73c92 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 20494c4c427f111add919437b87cf833a6196504 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 ee0e68d8dca67e34d81d7e2b2ee8cac05725e911 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 5cf362dd87794e1f7e1647c641f4ab63048bd417 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 15d4829e19c48ed5b70af5067b91dc644bf50fb6 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 50ffcba552abdc825c88fdeaf6cda28b64fa5817 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 6d042c4d3f4e986df6329bc2cc123cf9d3658c79 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 93d5a9a17485a592ad7f5e975873627ea84fe2bd 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 aaa18750401d2ff27412f43df92433a4ba849c81 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 9f5283f84154fbc28ff8286d811ebb71b9fd4945 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 2f8033c42621206a3e24a682d1e9cdb9130427c5 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 8132905436933172b655d3c9c2481ed4648ec11d 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 b575e7ab471840747e1aaeaba7298eb7d4e7fee1 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 24e4552d5b0c64e3645258202902c95327a9e8ba 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 77d6601e8b3f65a296acee2e87f1a7639728f410 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 a8110211127dfe03513fe5533ad3c2c4b9ea284a 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 402b58ce4287ebc9d6f99882ef824156f0bd1555 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 df9809f3d71f964dd9358c67061111610886fd96 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 9219699b422feed7e351f40ef1a008c138f6f4c0 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 dda18dd0803b6fa43d8797ba2337b5ba2cd0165c 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 b425f913f2014f1bdd6a67cf1f9108755839133d 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 3fc97493163f04179d55a928e5532ccb7f01b8f8 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 699de06c05de18dced2d98e7db4cfd845214ff32 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 9da0b78666f9f73b0480d5c90d99ab2e382ec94e 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 0ac318cd78a856473d656b0623131ce2c0c88f3f 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 97c54bc5f0b9cc422d5a297b5e1d43aae11d92be 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 0ab6fe1fd84101ba55d90020da81e14fc9e7627d 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 edb5cc7f9739816c933c6236e069842f4e92021c 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 14207f32979c39c1f2819489b6fab6d31716f0b7 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 f09ff4ca8d1699d696ab8e0c524828ef770a9f36 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 33044e0a976adf0e134aac6501c410af4780e4f6 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 79b1559925399318b6d55a8af8dde16a6306bd2d 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 6bca318fa8f5fcd5fef24ef64ba8d03e26603e4a 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 9a3e2c7911ee236548111be32897228b8ad61fc7 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 275f07e05fe53976d45a381453be54e48dfd30fe 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 ab63d3e33f014307d462a673f0a23885a05b14c7 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 764a8ad43f04e85cb011debaea9dc3ca471f3696 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 89eda2fa9bf11114630698c03028aeac64bd3523 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 ce45746d02e4c82b4b4605200b354e85e86a6f7d 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 a50549aa7cea0849fb7d7cfdce59b99b1e84afd0 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 33c35230c2ec028cbc87fe7d7a3d458fcd83d1ae 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 ca130c43130d570872845570b63a866ff0753337 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 30683f5bdd5fb1ff1805a6e02c811e9a5c9098af 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)