From a9866f84ad7232b0d6113d473162b5dca44caabd Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 20 Mar 2020 16:03:48 +0100 Subject: [PATCH 001/326] Implemented FOF types 100-105 --- src/p_setup.c | 47 ++++++++++++++++++++++++++++++ src/p_spec.c | 81 +++++++++++++++++++++++++-------------------------- 2 files changed, 86 insertions(+), 42 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 56bfb2444..635c220f5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2803,6 +2803,44 @@ static void P_ConvertBinaryMap(void) { switch (lines[i].special) { + case 100: //FOF: solid, opaque, shadowcasting + case 101: //FOF: solid, opaque, non-shadowcasting + case 102: //FOF: solid, translucent + case 103: //FOF: solid, sides only + case 104: //FOF: solid, no sides + case 105: //FOF: solid, invisible + lines[i].args[0] = lines[i].tag; + + //Visibility + if (lines[i].special == 105) + lines[i].args[1] = 3; + else if (lines[i].special == 104) + lines[i].args[1] = 2; + else if (lines[i].special == 103) + lines[i].args[1] = 1; + + //Translucency + if (lines[i].special == 102) + { + lines[i].args[2] = (lines[i].flags & ML_NOCLIMB) ? 2 : 1; + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + else + lines[i].alpha = FRACUNIT/2; + } + + //Tangibility + if (lines[i].flags & ML_EFFECT1) + lines[i].args[3] |= 8; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[3] |= 4; + + //Shadow? + if (lines[i].special != 100 && (lines[i].special != 104 || !(lines[i].flags & ML_NOCLIMB))) + lines[i].args[4] = 1; + + lines[i].special = 100; + break; case 443: //Call Lua function if (lines[i].text) { @@ -2942,6 +2980,15 @@ static void P_ConvertBinaryMap(void) lines[i].alpha = ((909 - lines[i].special) << FRACBITS)/10; break; default: + // \todo Remove once all FOF types are converted + if (lines[i].special >= 100 && lines[i].special < 300) + { + lines[i].args[0] = lines[i].tag; + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + else + lines[i].alpha = FRACUNIT/2; + } break; } } diff --git a/src/p_spec.c b/src/p_spec.c index 1b41ae015..5522ea84c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5760,7 +5760,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f { fixed_t tempceiling = sec2->ceilingheight; //flip the sector around and print an error instead of crashing 12.1.08 -Inuyasha - CONS_Alert(CONS_ERROR, M_GetText("A FOF tagged %d has a top height below its bottom.\n"), master->tag); + CONS_Alert(CONS_ERROR, M_GetText("A FOF tagged %d has a top height below its bottom.\n"), master->args[0]); sec2->ceilingheight = sec2->floorheight; sec2->floorheight = tempceiling; } @@ -5820,6 +5820,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f sec->hasslope = true; #endif + // \todo Remove once all FOFs are adapted if ((flags & FF_SOLID) && (master->flags & ML_EFFECT1)) // Block player only flags &= ~FF_BLOCKOTHERS; @@ -5881,17 +5882,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f else th = th->next; } - - if (flags & FF_TRANSLUCENT) - { - if (sides[master->sidenum[0]].toptexture > 0) - fflr->alpha = sides[master->sidenum[0]].toptexture; // for future reference, "#0" is 1, and "#255" is 256. Be warned - else - fflr->alpha = 0x80; - } - else - fflr->alpha = 0xff; - + fflr->alpha = (flags & FF_TRANSLUCENT) ? (master->alpha * 0xff) >> FRACBITS : 0xff; fflr->spawnalpha = fflr->alpha; // save for netgames if (flags & FF_QUICKSAND) @@ -6772,44 +6763,50 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddPlaneDisplaceThinker(pd_both, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); break; - case 100: // FOF (solid, opaque, shadows) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - break; + case 100: // FOF (solid) + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; - case 101: // FOF (solid, opaque, no shadows) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_CUTLEVEL, secthinkers); - break; + //Visibility settings + if (lines[i].args[1] & 1) + ffloorflags &= ~FF_RENDERPLANES; + if (lines[i].args[1] & 2) + ffloorflags &= ~FF_RENDERSIDES; - case 102: // TL block: FOF (solid, translucent) - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - - // Draw the 'insides' of the block too - if (lines[i].flags & ML_NOCLIMB) + //Translucency settings are irrelevant for invisible FOFs + if (lines[i].args[1] != 3) { - ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; - ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); + if (lines[i].args[2] == 0) //Opaque + { + if (lines[i].args[3] & 7) + { + //At least partially intangible: You can see it from the inside + ffloorflags |= FF_ALLSIDES; + //Unless the planes are invisible, render both sides. + if (!(lines[i].args[1] & 1)) + ffloorflags |= FF_BOTHPLANES; + } + else + ffloorflags |= FF_CUTLEVEL; + } + if (lines[i].args[2] == 1) //Translucent, don't render insides + ffloorflags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; + if (lines[i].args[2] == 2) //Translucent, render insides + ffloorflags |= FF_TRANSLUCENT|FF_CUTEXTRA|FF_BOTHPLANES|FF_ALLSIDES; } - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 103: // Solid FOF with no floor/ceiling (quite possibly useless) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERSIDES|FF_NOSHADE|FF_CUTLEVEL, secthinkers); - break; - - case 104: // 3D Floor type that doesn't draw sides - // If line has no-climb set, give it shadows, otherwise don't - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERPLANES|FF_CUTLEVEL; - if (!(lines[i].flags & ML_NOCLIMB)) + if (lines[i].args[3] & 1) + ffloorflags |= FF_REVERSEPLATFORM; + if (lines[i].args[3] & 2) + ffloorflags |= FF_PLATFORM; + if (lines[i].args[3] & 4) + ffloorflags &= ~FF_BLOCKPLAYER; + if (lines[i].args[3] & 8) + ffloorflags &= ~FF_BLOCKOTHERS; + if (lines[i].args[4]) ffloorflags |= FF_NOSHADE; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; - case 105: // FOF (solid, invisible) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_NOSHADE, secthinkers); - break; - case 120: // Opaque water ffloorflags = FF_EXISTS|FF_RENDERALL|FF_SWIMMABLE|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; if (lines[i].flags & ML_NOCLIMB) @@ -7495,7 +7492,7 @@ static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinker INT32 s; size_t sec = sides[*lines[line].sidenum].sector-sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines+line, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[line].args[0], s)) >= 0 ;) P_AddFakeFloor(§ors[s], §ors[sec], lines+line, ffloorflags, secthinkers); } From 1e306dc7b407def50ee2df6697d6487a08b00c58 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 20 Mar 2020 16:08:48 +0100 Subject: [PATCH 002/326] Implement linedef type 100-146 --- src/p_setup.c | 39 ++++++++++++++++++++++++ src/p_spec.c | 84 --------------------------------------------------- 2 files changed, 39 insertions(+), 84 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 635c220f5..e23b52357 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2839,6 +2839,45 @@ static void P_ConvertBinaryMap(void) if (lines[i].special != 100 && (lines[i].special != 104 || !(lines[i].flags & ML_NOCLIMB))) lines[i].args[4] = 1; + lines[i].special = 100; + break; + case 140: //FOF: intangible from bottom, opaque + case 141: //FOF: intangible from bottom, translucent + case 142: //FOF: intangible from bottom, translucent, no sides + case 143: //FOF: intangible from top, opaque + case 144: //FOF: intangible from top, translucent + case 145: //FOF: intangible from top, translucent, no sides + case 146: //FOF: only tangible from sides + lines[i].args[0] = lines[i].tag; + + //Visibility + if (lines[i].special == 142 || lines[i].special == 145) + lines[i].args[1] = 2; + else if (lines[i].special == 146) + lines[i].args[1] = 1; + + //Translucency + if (lines[i].special == 141 || lines[i].special == 142 || lines[i].special == 144 || lines[i].special == 145) + { + lines[i].args[2] = (lines[i].flags & ML_EFFECT2) ? 2 : 1; + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + else + lines[i].alpha = FRACUNIT/2; + } + + //Tangibility + if (lines[i].special <= 142) + lines[i].args[3] |= 2; + else if (lines[i].special <= 145) + lines[i].args[3] |= 1; + else + lines[i].args[3] |= 3; + + //Shadow? + if (lines[i].special != 146 && (lines[i].flags & ML_NOCLIMB)) + lines[i].args[4] = 1; + lines[i].special = 100; break; case 443: //Call Lua function diff --git a/src/p_spec.c b/src/p_spec.c index 5522ea84c..121e1c11d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6873,90 +6873,6 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; - case 140: // 'Platform' - You can jump up through it - // If line has no-climb set, don't give it shadows, otherwise do - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_BOTHPLANES|FF_ALLSIDES; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_NOSHADE; - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 141: // Translucent "platform" - // If line has no-climb set, don't give it shadows, otherwise do - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_NOSHADE; - - // Draw the 'insides' of the block too - if (lines[i].flags & ML_EFFECT2) - { - ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; - ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); - } - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 142: // Translucent "platform" with no sides - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERPLANES|FF_TRANSLUCENT|FF_PLATFORM|FF_EXTRA|FF_CUTEXTRA; - if (lines[i].flags & ML_NOCLIMB) // shade it unless no-climb - ffloorflags |= FF_NOSHADE; - - // Draw the 'insides' of the block too - if (lines[i].flags & ML_EFFECT2) - { - ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; - ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); - } - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 143: // 'Reverse platform' - You fall through it - // If line has no-climb set, don't give it shadows, otherwise do - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_REVERSEPLATFORM|FF_BOTHPLANES|FF_ALLSIDES; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_NOSHADE; - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 144: // Translucent "reverse platform" - // If line has no-climb set, don't give it shadows, otherwise do - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_REVERSEPLATFORM|FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_NOSHADE; - - // Draw the 'insides' of the block too - if (lines[i].flags & ML_EFFECT2) - { - ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; - ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); - } - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 145: // Translucent "reverse platform" with no sides - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERPLANES|FF_TRANSLUCENT|FF_REVERSEPLATFORM|FF_EXTRA|FF_CUTEXTRA; - if (lines[i].flags & ML_NOCLIMB) // shade it unless no-climb - ffloorflags |= FF_NOSHADE; - - // Draw the 'insides' of the block too - if (lines[i].flags & ML_EFFECT2) - { - ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; - ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); - } - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 146: // Intangible floor/ceiling with solid sides (fences/hoops maybe?) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERSIDES|FF_ALLSIDES|FF_INTANGIBLEFLATS, secthinkers); - break; - case 150: // Air bobbing platform case 151: // Adjustable air bobbing platform P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); From 6e8760524c9a0c7f12f001823a012656bca3bf37 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 20 Mar 2020 16:15:39 +0100 Subject: [PATCH 003/326] Implement water FOF types --- src/p_setup.c | 37 +++++++++++++++++++++++++++ src/p_spec.c | 69 ++++++++------------------------------------------- 2 files changed, 47 insertions(+), 59 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index e23b52357..6f4d1c317 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2841,6 +2841,43 @@ static void P_ConvertBinaryMap(void) lines[i].special = 100; break; + case 120: //FOF: water, opaque + case 121: //FOF: water, translucent + case 122: //FOF: water, opaque, no sides + case 123: //FOF: water, translucent, no sides + case 124: //FOF: goo water, translucent + case 125: //FOF: goo water, translucent, no sides + lines[i].args[0] = lines[i].tag; + + //Opaque? + if (lines[i].special == 120 || lines[i].special == 122) + lines[i].args[1] |= 1; + else + { + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + else + lines[i].alpha = FRACUNIT/2; + } + + //No sides? + if (lines[i].special == 122 || lines[i].special == 123 || lines[i].special == 125) + lines[i].args[1] |= 2; + + //Flags + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[1] |= 4; + if (lines[i].flags & ML_EFFECT4) + lines[i].args[1] |= 8; + if (!(lines[i].flags & ML_EFFECT5)) + lines[i].args[1] |= 16; + + //Goo? + if (lines[i].special >= 124) + lines[i].args[1] |= 32; + + lines[i].special = 120; + break; case 140: //FOF: intangible from bottom, opaque case 141: //FOF: intangible from bottom, translucent case 142: //FOF: intangible from bottom, translucent, no sides diff --git a/src/p_spec.c b/src/p_spec.c index 121e1c11d..a558499be 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6807,69 +6807,20 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; - case 120: // Opaque water - ffloorflags = FF_EXISTS|FF_RENDERALL|FF_SWIMMABLE|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_DOUBLESHADOW; - if (lines[i].flags & ML_EFFECT4) - ffloorflags |= FF_COLORMAPONLY; - if (lines[i].flags & ML_EFFECT5) - ffloorflags |= FF_RIPPLE; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 121: // TL water - ffloorflags = FF_EXISTS|FF_RENDERALL|FF_TRANSLUCENT|FF_SWIMMABLE|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_DOUBLESHADOW; - if (lines[i].flags & ML_EFFECT4) - ffloorflags |= FF_COLORMAPONLY; - if (lines[i].flags & ML_EFFECT5) - ffloorflags |= FF_RIPPLE; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 122: // Opaque water, no sides + case 120: // FOF (water) ffloorflags = FF_EXISTS|FF_RENDERPLANES|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - if (lines[i].flags & ML_NOCLIMB) + if (!(lines[i].args[1] & 1)) + ffloorflags |= FF_TRANSLUCENT; + if (!(lines[i].args[1] & 2)) + ffloorflags |= FF_RENDERSIDES|FF_ALLSIDES; + if (lines[i].args[1] & 4) ffloorflags |= FF_DOUBLESHADOW; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].args[1] & 8) ffloorflags |= FF_COLORMAPONLY; - if (lines[i].flags & ML_EFFECT5) - ffloorflags |= FF_RIPPLE; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 123: // TL water, no sides - ffloorflags = FF_EXISTS|FF_RENDERPLANES|FF_TRANSLUCENT|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_DOUBLESHADOW; - if (lines[i].flags & ML_EFFECT4) - ffloorflags |= FF_COLORMAPONLY; - if (lines[i].flags & ML_EFFECT5) - ffloorflags |= FF_RIPPLE; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 124: // goo water - ffloorflags = FF_EXISTS|FF_RENDERALL|FF_TRANSLUCENT|FF_SWIMMABLE|FF_GOOWATER|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_DOUBLESHADOW; - if (lines[i].flags & ML_EFFECT4) - ffloorflags |= FF_COLORMAPONLY; - if (lines[i].flags & ML_EFFECT5) - ffloorflags |= FF_RIPPLE; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 125: // goo water, no sides - ffloorflags = FF_EXISTS|FF_RENDERPLANES|FF_TRANSLUCENT|FF_SWIMMABLE|FF_GOOWATER|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_DOUBLESHADOW; - if (lines[i].flags & ML_EFFECT4) - ffloorflags |= FF_COLORMAPONLY; - if (lines[i].flags & ML_EFFECT5) + if (!(lines[i].args[1] & 16)) ffloorflags |= FF_RIPPLE; + if (lines[i].args[1] & 32) + ffloorflags |= FF_GOOWATER; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; From 61d903cb5be19e8eaed8a9962148c993ed1136ae Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Apr 2020 01:34:11 +0200 Subject: [PATCH 004/326] Revise setup of solid FOFs --- src/p_setup.c | 45 ++++++++++++++++++++++++----------------- src/p_spec.c | 55 ++++++++++++++++++++++++++------------------------- 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 8ecfceeae..6eeeac5cd 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2813,25 +2813,27 @@ static void P_ConvertBinaryMap(void) else if (lines[i].special == 103) lines[i].args[1] = 1; + //Tangibility + if (lines[i].flags & ML_EFFECT1) + lines[i].args[2] |= 8; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[2] |= 4; + //Translucency if (lines[i].special == 102) { - lines[i].args[2] = (lines[i].flags & ML_NOCLIMB) ? 2 : 1; + lines[i].args[3] |= 1; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[1] |= 4; if (sides[lines[i].sidenum[0]].toptexture > 0) lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; else lines[i].alpha = FRACUNIT/2; } - //Tangibility - if (lines[i].flags & ML_EFFECT1) - lines[i].args[3] |= 8; - if (lines[i].flags & ML_EFFECT2) - lines[i].args[3] |= 4; - //Shadow? if (lines[i].special != 100 && (lines[i].special != 104 || !(lines[i].flags & ML_NOCLIMB))) - lines[i].args[4] = 1; + lines[i].args[3] |= 1; lines[i].special = 100; break; @@ -2887,27 +2889,34 @@ static void P_ConvertBinaryMap(void) else if (lines[i].special == 146) lines[i].args[1] = 1; + //Tangibility + if (lines[i].special <= 142) + lines[i].args[2] |= 2; + else if (lines[i].special <= 145) + lines[i].args[2] |= 1; + else + lines[i].args[2] |= 3; + + if (lines[i].flags & ML_EFFECT1) + lines[i].args[2] |= 8; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[2] |= 4; + //Translucency if (lines[i].special == 141 || lines[i].special == 142 || lines[i].special == 144 || lines[i].special == 145) { - lines[i].args[2] = (lines[i].flags & ML_EFFECT2) ? 2 : 1; + lines[i].args[3] |= 1; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[1] |= 4; if (sides[lines[i].sidenum[0]].toptexture > 0) lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; else lines[i].alpha = FRACUNIT/2; } - //Tangibility - if (lines[i].special <= 142) - lines[i].args[3] |= 2; - else if (lines[i].special <= 145) - lines[i].args[3] |= 1; - else - lines[i].args[3] |= 3; - //Shadow? if (lines[i].special != 146 && (lines[i].flags & ML_NOCLIMB)) - lines[i].args[4] = 1; + lines[i].args[3] |= 2; lines[i].special = 100; break; diff --git a/src/p_spec.c b/src/p_spec.c index 95addfbb8..ac45b6d07 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6757,43 +6757,44 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; //Visibility settings - if (lines[i].args[1] & 1) + if (lines[i].args[1] & 1) //Don't render planes ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[1] & 2) + if (lines[i].args[1] & 2) //Don't render sides ffloorflags &= ~FF_RENDERSIDES; - - //Translucency settings are irrelevant for invisible FOFs - if (lines[i].args[1] != 3) + if (lines[i].args[1] & 4) //Render insides { - if (lines[i].args[2] == 0) //Opaque - { - if (lines[i].args[3] & 7) - { - //At least partially intangible: You can see it from the inside - ffloorflags |= FF_ALLSIDES; - //Unless the planes are invisible, render both sides. - if (!(lines[i].args[1] & 1)) - ffloorflags |= FF_BOTHPLANES; - } - else - ffloorflags |= FF_CUTLEVEL; - } - if (lines[i].args[2] == 1) //Translucent, don't render insides - ffloorflags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - if (lines[i].args[2] == 2) //Translucent, render insides - ffloorflags |= FF_TRANSLUCENT|FF_CUTEXTRA|FF_BOTHPLANES|FF_ALLSIDES; + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_BOTHPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_ALLSIDES; } - if (lines[i].args[3] & 1) + //Tangibility settings + if (lines[i].args[2] & 1) //Intangible from top ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[3] & 2) + if (lines[i].args[2] & 2) //Intangible from bottom ffloorflags |= FF_PLATFORM; - if (lines[i].args[3] & 4) + if (lines[i].args[2] & 4) //Don't block player ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[3] & 8) + if (lines[i].args[2] & 8) //Don't block others ffloorflags &= ~FF_BLOCKOTHERS; - if (lines[i].args[4]) + + //Appearance settings + if ((lines[i].args[3] & 1) && (ffloorflags & FF_RENDERALL)) //Translucent + ffloorflags |= FF_TRANSLUCENT; + if (lines[i].args[3] & 2) //Don't cast shadow ffloorflags |= FF_NOSHADE; + + //Cutting options + if (ffloorflags & FF_RENDERALL) + { + //If translucent or player can enter it, cut inner walls + if ((ffloorflags & FF_TRANSLUCENT) || (lines[i].args[2] & 7)) + ffloorflags |= FF_CUTEXTRA|FF_EXTRA; + else + ffloorflags |= FF_CUTLEVEL; + } + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; From 7f889532eac4d4eb63b3ef0491ed74213f92a776 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Apr 2020 09:00:26 +0200 Subject: [PATCH 005/326] Adapt solid FOF setup in UDB config --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 24 ++++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 707396078..64bc00450 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1537,30 +1537,24 @@ udmf { 1 = "Don't render planes"; 2 = "Don't render sides"; + 4 = "Render insides"; } } arg2 - { - title = "Translucency"; - type = 11; - enum - { - 0 = "Opaque"; - 1 = "Translucent, no insides"; - 2 = "Translucent, render insides"; - } - } - arg3 { title = "Tangibility"; type = 12; enum = "tangibility"; } - arg4 + arg3 { - title = "Cast shadow?"; - type = 11; - enum = "yesno"; + title = "Appearance"; + type = 12; + enum + { + 1 = "Translucent"; + 2 = "No shadow"; + } } } From 60e589e92a2f5cc59321342d727375008edd2129 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Apr 2020 09:03:00 +0200 Subject: [PATCH 006/326] Implement FOF types 200-201 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 17 +++++++++++++++++ src/p_setup.c | 7 +++++++ src/p_spec.c | 11 +++++------ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 64bc00450..e7d7b4337 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1584,6 +1584,23 @@ udmf } } + 200 + { + title = "Light Block"; + prefix = "(200); + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Expand to bottom?"; + type = 11; + enum = "noyes"; + } + } + linedefexecmisc { title = "Linedef Executor (misc.)"; diff --git a/src/p_setup.c b/src/p_setup.c index 6eeeac5cd..4379425df 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2920,6 +2920,13 @@ static void P_ConvertBinaryMap(void) lines[i].special = 100; break; + case 200: //FOF: Light block + case 201: //FOF: Half light block + lines[i].args[0] = lines[i].tag; + if (lines[i].special == 201) + lines[i].args[1] = 1; + lines[i].special = 200; + break; case 443: //Call Lua function if (lines[i].text) { diff --git a/src/p_spec.c b/src/p_spec.c index ac45b6d07..d10d72a0f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6943,12 +6943,11 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddRaiseThinker(lines[i].frontsector, &lines[i]); break; - case 200: // Double light effect - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_CUTSPRITES|FF_DOUBLESHADOW, secthinkers); - break; - - case 201: // Light effect - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_CUTSPRITES, secthinkers); + case 200: // Light block + ffloorflags = FF_EXISTS|FF_CUTSPRITES; + if (!lines[i].args[1]) + ffloorflags |= FF_DOUBLESHADOW; + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; case 202: // Fog From fdb46e5d14f78df255c02df953790b963b8c61fd Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Apr 2020 09:06:02 +0200 Subject: [PATCH 007/326] Implement FOF types 202 and 223 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 22 ++++++++++++++++++++ src/p_setup.c | 4 ++++ 2 files changed, 26 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index e7d7b4337..1bd5055e2 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1601,6 +1601,28 @@ udmf } } + 202 + { + title = "Fog Block"; + prefix = "(202); + arg0 + { + title = "Target sector tag"; + type = 13; + } + } + + 223 + { + title = "Intangible, Invisible"; + prefix = "(223); + arg0 + { + title = "Target sector tag"; + type = 13; + } + } + linedefexecmisc { title = "Linedef Executor (misc.)"; diff --git a/src/p_setup.c b/src/p_setup.c index 4379425df..cf5dbcbc7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2927,6 +2927,10 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = 1; lines[i].special = 200; break; + case 202: //FOF: Fog block + case 223: //FOF: Intangible, invisible + lines[i].args[0] = lines[i].tag; + break; case 443: //Call Lua function if (lines[i].text) { From 916f831edbeba5f1ec9cd26714342cf2ffd471b4 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Apr 2020 09:14:10 +0200 Subject: [PATCH 008/326] Implement linedef type 250 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 21 ++++++++++++++++++++ src/p_setup.c | 7 +++++++ src/p_spec.c | 4 ++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 1bd5055e2..528690dc4 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1623,6 +1623,27 @@ udmf } } + 250 + { + title = "Mario Block"; + prefix = "(250); + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Block type"; + type = 12; + enum + { + 1 = "Brick"; + 2 = "Invisible"; + } + } + } + linedefexecmisc { title = "Linedef Executor (misc.)"; diff --git a/src/p_setup.c b/src/p_setup.c index cf5dbcbc7..92eaff4b5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2931,6 +2931,13 @@ static void P_ConvertBinaryMap(void) case 223: //FOF: Intangible, invisible lines[i].args[0] = lines[i].tag; break; + case 250: //FOF: Mario block + lines[i].args[0] = lines[i].tag; + if (lines[i].flags & ML_NOCLIMB) //Brick block + lines[i].args[1] |= 1; + if (lines[i].flags & ML_EFFECT1) //Invisible + lines[i].args[1] |= 2; + break; case 443: //Call Lua function if (lines[i].text) { diff --git a/src/p_spec.c b/src/p_spec.c index d10d72a0f..94e6aa936 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6987,9 +6987,9 @@ void P_SpawnSpecials(boolean fromnetsave) case 250: // Mario Block ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO; - if (lines[i].flags & ML_NOCLIMB) + if (lines[i].args[1] & 1) //Brick block ffloorflags |= FF_SHATTERBOTTOM; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].args[1] & 2) // Invisible ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); From 32a1131c68060a6abb33c04132984f26831211a6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Apr 2020 09:43:49 +0200 Subject: [PATCH 009/326] Implement FOF type 251 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 24 ++++++++++++++++++++ src/p_floor.c | 17 ++++---------- src/p_setup.c | 20 ++++++++++++++++ src/p_spec.c | 2 +- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 528690dc4..c63947f65 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1644,6 +1644,30 @@ udmf } } + 251 + { + title = "Thwomp Block"; + prefix = "(251); + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Falling speed"; + } + arg2 + { + title = "Rising speed"; + } + stringarg0 + { + title = "Crushing sound"; + type = 2; + } + } + linedefexecmisc { title = "Linedef Executor (misc.)"; diff --git a/src/p_floor.c b/src/p_floor.c index b8b40df3c..d9b404155 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -11,6 +11,7 @@ /// \file p_floor.c /// \brief Floor animation, elevators +#include "dehacked.h" #include "doomdef.h" #include "doomstat.h" #include "m_random.h" @@ -1885,10 +1886,7 @@ void T_ThwompSector(levelspecthink_t *thwomp) sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture; /// \note this should only have to be done once, but is already done repeatedly, above - if (thwomp->sourceline->flags & ML_EFFECT5) - thwomp->speed = thwomp->sourceline->dx/8; - else - thwomp->speed = 2*FRACUNIT; + thwomp->speed = thwomp->sourceline->args[2] << (FRACBITS - 3); res = T_MovePlane ( @@ -1924,10 +1922,7 @@ void T_ThwompSector(levelspecthink_t *thwomp) // Set the texture from the upper one (angry) sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].toptexture; - if (thwomp->sourceline->flags & ML_EFFECT5) - thwomp->speed = thwomp->sourceline->dy/8; - else - thwomp->speed = 10*FRACUNIT; + thwomp->speed = thwomp->sourceline->args[1] << (FRACBITS - 3); res = T_MovePlane ( @@ -1961,10 +1956,8 @@ void T_ThwompSector(levelspecthink_t *thwomp) if (!rover || (rover->flags & FF_EXISTS)) { - if (thwomp->sourceline->flags & ML_EFFECT4) - S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); - else - S_StartSound(mp, sfx_thwomp); + sfxenum_t sound = (thwomp->sourceline->stringargs[0]) ? get_number(thwomp->sourceline->stringargs[0]) : sfx_thwomp; + S_StartSound(mp, sound); } thwomp->direction = 1; // start heading back up diff --git a/src/p_setup.c b/src/p_setup.c index 92eaff4b5..82671abb0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2938,6 +2938,26 @@ static void P_ConvertBinaryMap(void) if (lines[i].flags & ML_EFFECT1) //Invisible lines[i].args[1] |= 2; break; + case 251: //FOF: Thwomp block + lines[i].args[0] = lines[i].tag; + if (lines[i].flags & ML_EFFECT5) //Custom speeds + { + lines[i].args[1] = lines[i].dy >> FRACBITS; + lines[i].args[2] = lines[i].dx >> FRACBITS; + } + else + { + lines[i].args[1] = 80; + lines[i].args[2] = 16; + } + if (lines[i].flags & ML_EFFECT4) + { + char buffer[6]; + sprintf(buffer, "%d", sides[lines[i].sidenum[0]].textureoffset >> FRACBITS); + lines[i].stringargs[0] = Z_Malloc(strlen(buffer) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], buffer, strlen(buffer) + 1); + } + break; case 443: //Call Lua function if (lines[i].text) { diff --git a/src/p_spec.c b/src/p_spec.c index 94e6aa936..774c7162a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6997,7 +6997,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 251: // A THWOMP! sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) { P_AddThwompThinker(§ors[sec], §ors[s], &lines[i]); P_AddFakeFloor(§ors[s], §ors[sec], lines + i, From 9fc2b5b1b9b324cf03c77a96cb612ab8f8b6e634 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Apr 2020 09:51:48 +0200 Subject: [PATCH 010/326] Implement FOF type 258 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 157 ++++++++++--------- src/p_setup.c | 5 + src/p_spec.c | 4 +- 3 files changed, 94 insertions(+), 72 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index c63947f65..0847826d4 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1582,89 +1582,106 @@ udmf } } } - } - 200 - { - title = "Light Block"; - prefix = "(200); - arg0 + 200 { - title = "Target sector tag"; - type = 13; - } - arg1 - { - title = "Expand to bottom?"; - type = 11; - enum = "noyes"; - } - } - - 202 - { - title = "Fog Block"; - prefix = "(202); - arg0 - { - title = "Target sector tag"; - type = 13; - } - } - - 223 - { - title = "Intangible, Invisible"; - prefix = "(223); - arg0 - { - title = "Target sector tag"; - type = 13; - } - } - - 250 - { - title = "Mario Block"; - prefix = "(250); - arg0 - { - title = "Target sector tag"; - type = 13; - } - arg1 - { - title = "Block type"; - type = 12; - enum + title = "Light Block"; + prefix = "(200); + arg0 { - 1 = "Brick"; - 2 = "Invisible"; + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Expand to bottom?"; + type = 11; + enum = "noyes"; } } - } - 251 - { - title = "Thwomp Block"; - prefix = "(251); - arg0 + 202 { - title = "Target sector tag"; - type = 13; + title = "Fog Block"; + prefix = "(202); + arg0 + { + title = "Target sector tag"; + type = 13; + } } - arg1 + + 223 { - title = "Falling speed"; + title = "Intangible, Invisible"; + prefix = "(223); + arg0 + { + title = "Target sector tag"; + type = 13; + } } - arg2 + + 250 { - title = "Rising speed"; + title = "Mario Block"; + prefix = "(250); + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Block type"; + type = 12; + enum + { + 1 = "Brick"; + 2 = "Invisible"; + } + } } - stringarg0 + + 251 { - title = "Crushing sound"; - type = 2; + title = "Thwomp Block"; + prefix = "(251); + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Falling speed"; + } + arg2 + { + title = "Rising speed"; + } + stringarg0 + { + title = "Crushing sound"; + type = 2; + } + } + + 258 + { + title = "Laser"; + prefix = "(258)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Damage bosses?"; + type = 11; + enum = "yesno"; + } } } diff --git a/src/p_setup.c b/src/p_setup.c index 82671abb0..7c8a8c147 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2958,6 +2958,11 @@ static void P_ConvertBinaryMap(void) M_Memcpy(lines[i].stringargs[0], buffer, strlen(buffer) + 1); } break; + case 258: //FOF: Laser + lines[i].args[0] = lines[i].tag; + if (lines[i].flags & ML_EFFECT1) + lines[i].args[1] = 1; + break; case 443: //Call Lua function if (lines[i].text) { diff --git a/src/p_spec.c b/src/p_spec.c index 774c7162a..5288d2773 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6293,7 +6293,7 @@ void T_LaserFlash(laserthink_t *flash) { thing = node->m_thing; - if ((fflr->master->flags & ML_EFFECT1) + if ((fflr->master->args[1]) && thing->flags & MF_BOSS) continue; // Don't hurt bosses @@ -7045,7 +7045,7 @@ void P_SpawnSpecials(boolean fromnetsave) sec = sides[*lines[i].sidenum].sector - sectors; // No longer totally disrupts netgames - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) EV_AddLaserThinker(§ors[s], §ors[sec], lines + i, secthinkers); break; From f8c51ccde341582e831f19dbd5ece3e68c87a4aa Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Apr 2020 10:13:38 +0200 Subject: [PATCH 011/326] Implement FOF types 220-222 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 32 ++++++++++++++++++ src/p_setup.c | 25 ++++++++++++++ src/p_spec.c | 35 +++++++++++--------- 3 files changed, 76 insertions(+), 16 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 0847826d4..1ee245d08 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1611,6 +1611,38 @@ udmf } } + 220 + { + title = "Intangible"; + prefix = "(220)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Visibility"; + type = 12; + enum + { + 1 = "Don't render planes"; + 2 = "Don't render sides"; + 4 = "Don't render insides"; + } + } + arg2 + { + title = "Appearance"; + type = 12; + enum + { + 1 = "Translucent"; + 2 = "No shadow"; + } + } + } + 223 { title = "Intangible, Invisible"; diff --git a/src/p_setup.c b/src/p_setup.c index 7c8a8c147..55eacc6e4 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2931,6 +2931,31 @@ static void P_ConvertBinaryMap(void) case 223: //FOF: Intangible, invisible lines[i].args[0] = lines[i].tag; break; + case 220: //FOF: Intangible, opaque + case 221: //FOF: Intangible, translucent + case 222: //FOF: Intangible, sides only + lines[i].args[0] = lines[i].tag; + + //Visibility + if (lines[i].special == 222) + lines[i].args[1] |= 1; //Don't render planes + if (lines[i].special != 220) + lines[i].args[1] |= 4; //Don't render insides + + //Appearance + if (lines[i].special == 221) + { + lines[i].args[2] |= 1; //Translucent + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + else + lines[i].alpha = FRACUNIT/2; + } + if (lines[i].special != 220 && !(lines[i].flags & ML_NOCLIMB)) + lines[i].args[2] |= 2; //Don't cast shadow + + lines[i].special = 220; + break; case 250: //FOF: Mario block lines[i].args[0] = lines[i].tag; if (lines[i].flags & ML_NOCLIMB) //Brick block diff --git a/src/p_spec.c b/src/p_spec.c index 5288d2773..2bcd2a9e5 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6959,28 +6959,31 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; - case 220: // Like opaque water, but not swimmable. (Good for snow effect on FOFs) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_RENDERALL|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES, secthinkers); - break; + case 220: //Intangible + ffloorflags = FF_EXISTS|FF_RENDERALL|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - case 221: // FOF (intangible, translucent) - // If line has no-climb set, give it shadows, otherwise don't - ffloorflags = FF_EXISTS|FF_RENDERALL|FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA|FF_CUTSPRITES; - if (!(lines[i].flags & ML_NOCLIMB)) + //Visibility settings + if (lines[i].args[1] & 1) //Don't render planes + ffloorflags &= ~FF_RENDERPLANES; + if (lines[i].args[1] & 2) //Don't render sides + ffloorflags &= ~FF_RENDERSIDES; + if (!(lines[i].args[1] & 4)) //Render insides + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_BOTHPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_ALLSIDES; + } + + //Appearance settings + if ((lines[i].args[2] & 1) && (ffloorflags & FF_RENDERALL)) //Translucent + ffloorflags |= FF_TRANSLUCENT; + if (lines[i].args[2] & 2) //Don't cast shadow ffloorflags |= FF_NOSHADE; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; - case 222: // FOF with no floor/ceiling (good for GFZGRASS effect on FOFs) - // If line has no-climb set, give it shadows, otherwise don't - ffloorflags = FF_EXISTS|FF_RENDERSIDES|FF_ALLSIDES; - if (!(lines[i].flags & ML_NOCLIMB)) - ffloorflags |= FF_NOSHADE|FF_CUTSPRITES; - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - case 223: // FOF (intangible, invisible) - for combining specials in a sector P_AddFakeFloorsByLine(i, FF_EXISTS|FF_NOSHADE, secthinkers); break; From 15defaebeb1bae71c71eafe88f071d8d1631e033 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Apr 2020 10:14:56 +0200 Subject: [PATCH 012/326] Render insides on FOF type 222 --- 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 55eacc6e4..dfaa23c75 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2939,7 +2939,7 @@ static void P_ConvertBinaryMap(void) //Visibility if (lines[i].special == 222) lines[i].args[1] |= 1; //Don't render planes - if (lines[i].special != 220) + if (lines[i].special == 221) lines[i].args[1] |= 4; //Don't render insides //Appearance From e3b86d0c7492665986dc6198d5f2ec36f000d3bc Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Apr 2020 11:45:37 +0200 Subject: [PATCH 013/326] Implement FOF types 252-256 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 45 ++++++++++++++++++ src/p_mobj.c | 4 +- src/p_setup.c | 39 ++++++++++++++++ src/p_spec.c | 49 +++++++++++--------- src/p_user.c | 4 +- 5 files changed, 114 insertions(+), 27 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 1ee245d08..c592b09d9 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1699,6 +1699,51 @@ udmf } } + 252 + { + title = "Bustable Block"; + prefix = "(252)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Bustable type"; + type = 11; + enum + { + 0 = "Touch"; + 1 = "Spin"; + 2 = "Regular"; + 3 = "Strong"; + } + } + arg2 + { + title = "Translucent?" + type = 11; + enum = "noyes"; + } + arg3 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Bustable by pushables"; + 2 = "Trigger linedef executor"; + 4 = "Only bustable from below"; + } + } + arg4 + { + title = "Linedef executor tag"; + type = 15; + } + } + 258 { title = "Laser"; diff --git a/src/p_mobj.c b/src/p_mobj.c index b27d27a76..617c3bdd1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1688,8 +1688,8 @@ static void P_PushableCheckBustables(mobj_t *mo) if (!(rover->flags & FF_BUSTUP)) continue; - // Needs ML_EFFECT4 flag for pushables to break it - if (!(rover->master->flags & ML_EFFECT4)) continue; + // Bustable by pushables? + if (!(rover->master->args[3] & 1)) continue; if (!rover->master->frontsector->crumblestate) { diff --git a/src/p_setup.c b/src/p_setup.c index dfaa23c75..57e12d34c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2983,6 +2983,45 @@ static void P_ConvertBinaryMap(void) M_Memcpy(lines[i].stringargs[0], buffer, strlen(buffer) + 1); } break; + case 252: //FOF: Shatter block + case 253: //FOF: Shatter block, translucent + case 254: //FOF: Bustable block + case 255: //FOF: Spin-bustable block + case 256: //FOF: Spin-bustable block, translucent + lines[i].args[0] = lines[i].tag; + + //Bustable type + if (lines[i].special <= 253) + lines[i].args[1] = 0; + else if (lines[i].special >= 255) + lines[i].args[1] = 1; + else if (lines[i].flags & ML_NOCLIMB) + lines[i].args[1] = 3; + else + lines[i].args[1] = 2; + + //Translucency + if (lines[i].special == 253 || lines[i].special == 256) + { + lines[i].args[2] = 1; + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + else + lines[i].alpha = FRACUNIT/2; + } + + if (lines[i].flags & ML_EFFECT4) + lines[i].args[3] |= 1; //Bustable by pushables + if (lines[i].flags & ML_EFFECT5) + { + lines[i].args[3] |= 2; //Trigger linedef executor + lines[i].args[4] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + } + if (lines[i].special == 252 && lines[i].flags & ML_NOCLIMB) + lines[i].args[4] |= 4; //Bust only from below + + lines[i].special = 254; + break; case 258: //FOF: Laser lines[i].args[0] = lines[i].tag; if (lines[i].flags & ML_EFFECT1) diff --git a/src/p_spec.c b/src/p_spec.c index 2bcd2a9e5..e41e30d05 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7008,34 +7008,37 @@ void P_SpawnSpecials(boolean fromnetsave) } break; - case 252: // Shatter block (breaks when touched) - ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_BLOCKPLAYER|FF_SHATTERBOTTOM; - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 253: // Translucent shatter block (see 76) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER|FF_TRANSLUCENT, secthinkers); - break; - case 254: // Bustable block - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_STRONGBUST; + ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP; + + //Bustable type + switch (lines[i].args[1]) + { + case 0: + ffloorflags |= FF_SHATTER; + break; + case 1: + ffloorflags |= FF_SPINBUST; + break; + case 3: + ffloorflags |= FF_STRONGBUST; + break; + default: + break; + } + + if (lines[i].args[2]) + ffloorflags |= FF_TRANSLUCENT; + + if (lines[i].args[2] & 4) + ffloorflags |= FF_SHATTERBOTTOM; + + if (!(ffloorflags & FF_SHATTER) || ffloorflags & FF_SHATTERBOTTOM) + ffloorflags |= FF_BLOCKPLAYER; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; - case 255: // Spin bust block (breaks when jumped or spun downwards onto) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_SPINBUST, secthinkers); - break; - - case 256: // Translucent spin bust block (see 78) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_SPINBUST|FF_TRANSLUCENT, secthinkers); - break; - case 257: // Quicksand ffloorflags = FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES; if (lines[i].flags & ML_EFFECT5) diff --git a/src/p_user.c b/src/p_user.c index c12bc0c59..aa732bc63 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2659,8 +2659,8 @@ static void P_CheckBustableBlocks(player_t *player) EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? - if (rover->master->flags & ML_EFFECT5) - P_LinedefExecute((INT16)(P_AproxDistance(rover->master->dx, rover->master->dy)>>FRACBITS), player->mo, node->m_sector); + if (rover->master->args[3] & 2) + P_LinedefExecute((INT16)(rover->master->args[4]), player->mo, node->m_sector); goto bustupdone; } From 5389344a32142ff570d1d6de0a1042ef98987a22 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Apr 2020 11:56:11 +0200 Subject: [PATCH 014/326] Implement FOF type 257 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 25 ++++++++++++++++++++ src/p_setup.c | 7 ++++++ src/p_spec.c | 2 +- src/p_user.c | 4 ++-- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index c592b09d9..dcff6927b 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1744,6 +1744,31 @@ udmf } } + 257 + { + title = "Quicksand"; + prefix = "(257)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Ripple effect?"; + type = 11; + enum = "yesno"; + } + arg2 + { + title = "Sinking speed"; + } + arg3 + { + title = "Friction"; + } + } + 258 { title = "Laser"; diff --git a/src/p_setup.c b/src/p_setup.c index 57e12d34c..1af4803d6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3022,6 +3022,13 @@ static void P_ConvertBinaryMap(void) lines[i].special = 254; break; + case 257: //FOF: Quicksand + lines[i].args[0] = lines[i].tag; + if (!(lines[i].flags & ML_EFFECT5)) + lines[i].args[1] = 1; //No ripple effect + lines[i].args[2] = lines[i].dx >> FRACBITS; //Sinking speed + lines[i].args[3] = lines[i].dy >> FRACBITS; //Friction + break; case 258: //FOF: Laser lines[i].args[0] = lines[i].tag; if (lines[i].flags & ML_EFFECT1) diff --git a/src/p_spec.c b/src/p_spec.c index e41e30d05..1a1cb8990 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7041,7 +7041,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 257: // Quicksand ffloorflags = FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES; - if (lines[i].flags & ML_EFFECT5) + if (!(lines[i].args[1])) ffloorflags |= FF_RIPPLE; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); diff --git a/src/p_user.c b/src/p_user.c index aa732bc63..c1ceadad3 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2844,7 +2844,7 @@ static void P_CheckQuicksand(player_t *player) if (topheight >= player->mo->z && bottomheight < player->mo->z + player->mo->height) { - sinkspeed = abs(rover->master->v1->x - rover->master->v2->x)>>1; + sinkspeed = abs(rover->master->args[2]) << (FRACBITS - 1); sinkspeed = FixedDiv(sinkspeed,TICRATE*FRACUNIT); @@ -2873,7 +2873,7 @@ static void P_CheckQuicksand(player_t *player) P_PlayerHitFloor(player, false); } - friction = abs(rover->master->v1->y - rover->master->v2->y)>>6; + friction = abs(rover->master->args[3]) << (FRACBITS - 6); player->mo->momx = FixedMul(player->mo->momx, friction); player->mo->momy = FixedMul(player->mo->momy, friction); From f81559721916a4d6044ffe51ec3dea0c2b19872b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 15 Apr 2020 09:44:33 +0200 Subject: [PATCH 015/326] Implement FOF types 170-180 --- src/p_floor.c | 12 ++--- src/p_setup.c | 28 ++++++++++++ src/p_spec.c | 124 +++++++++++++++++++------------------------------- 3 files changed, 80 insertions(+), 84 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index d9b404155..a88555f9b 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -972,7 +972,7 @@ void T_StartCrumble(elevator_t *elevator) } else if (++elevator->distance == 0) // Reposition back to original spot { - for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->args[0], i)) >= 0 ;) { sector = §ors[i]; @@ -1003,7 +1003,7 @@ void T_StartCrumble(elevator_t *elevator) // Flash to indicate that the platform is about to return. if (elevator->distance > -224 && (leveltime % ((abs(elevator->distance)/8) + 1) == 0)) { - for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->args[0], i)) >= 0 ;) { sector = §ors[i]; @@ -1099,7 +1099,7 @@ void T_StartCrumble(elevator_t *elevator) P_RemoveThinker(&elevator->thinker); } - for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->args[0], i)) >= 0 ;) { sector = §ors[i]; sector->moved = true; @@ -2423,7 +2423,7 @@ void T_RaiseSector(levelspecthink_t *raise) if (raise->sector->crumblestate >= 3 || raise->sector->ceilingdata) return; - for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->args[0], i)) >= 0 ;) { sector = §ors[i]; @@ -2616,7 +2616,7 @@ void T_RaiseSector(levelspecthink_t *raise) raise->sector->ceilspeed = 42; raise->sector->floorspeed = raise->vars[3]*raise->vars[8]; - for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->args[0], i)) >= 0 ;) P_RecalcPrecipInSector(§ors[i]); } @@ -3335,7 +3335,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating, elevator->sector->crumblestate = 2; - for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->args[0], i)) >= 0 ;) { foundsec = §ors[i]; diff --git a/src/p_setup.c b/src/p_setup.c index 1af4803d6..6b7f59327 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2920,6 +2920,34 @@ static void P_ConvertBinaryMap(void) lines[i].special = 100; break; + case 170: //FOF: Crumbling, respawn + case 171: //FOF: Crumbling, no respawn + case 172: //FOF: Crumbling, respawn, intangible from bottom + case 173: //FOF: Crumbling, no respawn, intangible from bottom + case 174: //FOF: Crumbling, respawn, intangible from bottom, translucent + case 175: //FOF: Crumbling, no respawn, intangible from bottom, translucent + case 176: //FOF: Crumbling, respawn, floating, bobbing + case 177: //FOF: Crumbling, no respawn, floating, bobbing + case 178: //FOF: Crumbling, respawn, floating + case 179: //FOF: Crumbling, no respawn, floating + case 180: //FOF: Crumbling, respawn, air bobbing + lines[i].args[0] = lines[i].tag; + if (lines[i].special >= 172 && lines[i].special <= 175) + { + lines[i].args[1] |= 2; //Intangible from below + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] |= 2; //Don't cast shadow + } + if (lines[i].special >= 174 && lines[i].special <= 175) + lines[i].args[2] |= 1; //Translucent + if (lines[i].special % 2 == 1) + lines[i].args[2] |= 4; //Don't respawn + if (lines[i].special == 176 || lines[i].special == 177 || lines[i].special == 180) + lines[i].args[2] |= 8; //Air bobbing + if (lines[i].special >= 176 && lines[i].special <= 179) + lines[i].args[2] |= 16; //Float on water + lines[i].special = 170; + break; case 200: //FOF: Light block case 201: //FOF: Half light block lines[i].args[0] = lines[i].tag; diff --git a/src/p_spec.c b/src/p_spec.c index 1a1cb8990..57e9c22aa 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6093,7 +6093,7 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline) raise->sourceline = sourceline; } -static void P_AddAirbob(sector_t *sec, line_t *sourceline, boolean noadjust, boolean dynamic) +static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean raise, boolean dynamic, boolean spindash) { levelspecthink_t *airbob; @@ -6106,26 +6106,18 @@ static void P_AddAirbob(sector_t *sec, line_t *sourceline, boolean noadjust, boo airbob->sector = sec; // Require a spindash to activate - if (sourceline->flags & ML_NOCLIMB) - airbob->vars[1] = 1; - else - airbob->vars[1] = 0; + airbob->vars[1] = spindash ? 1 : 0; airbob->vars[2] = FRACUNIT; - if (noadjust) - airbob->vars[7] = airbob->sector->ceilingheight-16*FRACUNIT; - else - airbob->vars[7] = airbob->sector->ceilingheight - P_AproxDistance(sourceline->dx, sourceline->dy); + airbob->vars[7] = airbob->sector->ceilingheight - dist; + airbob->vars[6] = airbob->vars[7] - (sec->ceilingheight - sec->floorheight); airbob->vars[3] = airbob->vars[2]; - if (sourceline->flags & ML_BLOCKMONSTERS) - airbob->vars[0] = 1; - else - airbob->vars[0] = 0; + airbob->vars[0] = raise ? 0 : 1; airbob->vars[5] = sec->ceilingheight; airbob->vars[4] = airbob->vars[5] @@ -6817,18 +6809,19 @@ void P_SpawnSpecials(boolean fromnetsave) case 150: // Air bobbing platform case 151: // Adjustable air bobbing platform + { + fixed_t dist = (lines[i].special == 151) ? P_AproxDistance(lines[i].dx, lines[i].dy) : 16*FRACUNIT; P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - lines[i].flags |= ML_BLOCKMONSTERS; - P_AddAirbob(lines[i].frontsector, lines + i, (lines[i].special != 151), false); + P_AddAirbob(lines[i].frontsector, lines + i, dist, false, false, !!(lines[i].flags & ML_NOCLIMB)); break; + } case 152: // Adjustable air bobbing platform in reverse P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - P_AddAirbob(lines[i].frontsector, lines + i, true, false); + P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), true, false, !!(lines[i].flags & ML_NOCLIMB)); break; case 153: // Dynamic Sinking Platform P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - lines[i].flags |= ML_BLOCKMONSTERS; - P_AddAirbob(lines[i].frontsector, lines + i, false, true); + P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), false, true, !!(lines[i].flags & ML_NOCLIMB)); break; case 160: // Float/bob platform @@ -6836,71 +6829,46 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 170: // Crumbling platform - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE, secthinkers); - break; + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE; - case 171: // Crumbling platform that will not return - P_AddFakeFloorsByLine(i, - FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE|FF_NORETURN, secthinkers); - break; + //Tangibility settings + if (lines[i].args[1] & 1) //Intangible from top + ffloorflags |= FF_REVERSEPLATFORM; + if (lines[i].args[1] & 2) //Intangible from bottom + ffloorflags |= FF_PLATFORM; + if (lines[i].args[1] & 4) //Don't block player + ffloorflags &= ~FF_BLOCKPLAYER; + if (lines[i].args[1] & 8) //Don't block others + ffloorflags &= ~FF_BLOCKOTHERS; - case 172: // "Platform" that crumbles and returns - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_CRUMBLE|FF_BOTHPLANES|FF_ALLSIDES; - if (lines[i].flags & ML_NOCLIMB) // shade it unless no-climb + //Flags + if (lines[i].args[2] & 1) //Translucent + ffloorflags |= FF_TRANSLUCENT; + if (lines[i].args[2] & 2) //Don't cast shadow ffloorflags |= FF_NOSHADE; + if (lines[i].args[2] & 4) //Don't respawn + ffloorflags |= FF_NORETURN; + if (lines[i].args[2] & 16) //Float on water + ffloorflags |= FF_FLOATBOB; + + //If translucent or player can enter it, cut inner walls + if ((ffloorflags & FF_TRANSLUCENT) || (lines[i].args[1] & 7)) + ffloorflags |= FF_CUTEXTRA|FF_EXTRA; + else + ffloorflags |= FF_CUTLEVEL; + + //If player can enter it, render insides + if (lines[i].args[1] & 7) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_BOTHPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_ALLSIDES; + } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 173: // "Platform" that crumbles and doesn't return - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_CRUMBLE|FF_NORETURN|FF_BOTHPLANES|FF_ALLSIDES; - if (lines[i].flags & ML_NOCLIMB) // shade it unless no-climb - ffloorflags |= FF_NOSHADE; - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 174: // Translucent "platform" that crumbles and returns - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_PLATFORM|FF_CRUMBLE|FF_TRANSLUCENT|FF_BOTHPLANES|FF_ALLSIDES; - if (lines[i].flags & ML_NOCLIMB) // shade it unless no-climb - ffloorflags |= FF_NOSHADE; - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 175: // Translucent "platform" that crumbles and doesn't return - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_PLATFORM|FF_CRUMBLE|FF_NORETURN|FF_TRANSLUCENT|FF_BOTHPLANES|FF_ALLSIDES; - if (lines[i].flags & ML_NOCLIMB) // shade it unless no-climb - ffloorflags |= FF_NOSHADE; - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - break; - - case 176: // Air bobbing platform that will crumble and bob on the water when it falls and hits - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB|FF_CRUMBLE, secthinkers); - lines[i].flags |= ML_BLOCKMONSTERS; - P_AddAirbob(lines[i].frontsector, lines + i, true, false); - break; - - case 177: // Air bobbing platform that will crumble and bob on - // the water when it falls and hits, then never return - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB|FF_CRUMBLE|FF_NORETURN, secthinkers); - lines[i].flags |= ML_BLOCKMONSTERS; - P_AddAirbob(lines[i].frontsector, lines + i, true, false); - break; - - case 178: // Crumbling platform that will float when it hits water - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE|FF_FLOATBOB, secthinkers); - break; - - case 179: // Crumbling platform that will float when it hits water, but not return - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE|FF_FLOATBOB|FF_NORETURN, secthinkers); - break; - - case 180: // Air bobbing platform that will crumble - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE, secthinkers); - lines[i].flags |= ML_BLOCKMONSTERS; - P_AddAirbob(lines[i].frontsector, lines + i, true, false); + if (lines[i].args[2] & 8) //Air bobbing + P_AddAirbob(lines[i].frontsector, lines + i, 16*FRACUNIT, false, false, false); break; case 190: // Rising Platform FOF (solid, opaque, shadows) From 2e9dc59ca75d38ddd74cd3fb31a7bf7ac4c67ec9 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 15 Apr 2020 09:49:00 +0200 Subject: [PATCH 016/326] Forgot some stuff regarding FOF type 170 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 30 ++++++++++++++++++++ src/p_setup.c | 6 ++++ 2 files changed, 36 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index dcff6927b..32584505d 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1583,6 +1583,36 @@ udmf } } + 170 + { + title = "Crumbling"; + prefix = "(170)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Tangibility"; + type = 12; + enum = "tangibility"; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Translucent"; + 2 = "No shadow"; + 4 = "No respawn"; + 8 = "Air bobbing"; + 16 = "Float on water"; + } + } + } + 200 { title = "Light Block"; diff --git a/src/p_setup.c b/src/p_setup.c index 6b7f59327..8eb2a750c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2939,7 +2939,13 @@ static void P_ConvertBinaryMap(void) lines[i].args[2] |= 2; //Don't cast shadow } if (lines[i].special >= 174 && lines[i].special <= 175) + { lines[i].args[2] |= 1; //Translucent + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + else + lines[i].alpha = FRACUNIT/2; + } if (lines[i].special % 2 == 1) lines[i].args[2] |= 4; //Don't respawn if (lines[i].special == 176 || lines[i].special == 177 || lines[i].special == 180) From 1d3aa7129a2759f90594ea159c826b2de52842b4 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 18 Apr 2020 18:02:43 +0200 Subject: [PATCH 017/326] Add enums for textmap FOF values --- src/p_mobj.c | 2 +- src/p_setup.c | 92 +++++++++++++++++++++++++-------------------------- src/p_spec.c | 76 +++++++++++++++++++++--------------------- src/p_spec.h | 63 +++++++++++++++++++++++++++++++++++ src/p_user.c | 4 +-- 5 files changed, 150 insertions(+), 87 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 8f89ed0b0..39adbc5ab 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1689,7 +1689,7 @@ static void P_PushableCheckBustables(mobj_t *mo) if (!(rover->flags & FF_BUSTUP)) continue; // Bustable by pushables? - if (!(rover->master->args[3] & 1)) continue; + if (!(rover->master->args[3] & TMFB_PUSHABLES)) continue; if (!rover->master->frontsector->crumblestate) { diff --git a/src/p_setup.c b/src/p_setup.c index a09b2d659..e9df4eecd 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2810,24 +2810,24 @@ static void P_ConvertBinaryMap(void) //Visibility if (lines[i].special == 105) - lines[i].args[1] = 3; + lines[i].args[1] = TMFV_NOPLANES|TMFV_NOSIDES; else if (lines[i].special == 104) - lines[i].args[1] = 2; + lines[i].args[1] = TMFV_NOSIDES; else if (lines[i].special == 103) - lines[i].args[1] = 1; + lines[i].args[1] = TMFV_NOPLANES; //Tangibility if (lines[i].flags & ML_EFFECT1) - lines[i].args[2] |= 8; + lines[i].args[2] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[2] |= 4; + lines[i].args[2] |= TMFT_DONTBLOCKPLAYER; //Translucency if (lines[i].special == 102) { - lines[i].args[3] |= 1; + lines[i].args[3] |= TMFA_TRANSLUCENT; if (lines[i].flags & ML_NOCLIMB) - lines[i].args[1] |= 4; + lines[i].args[1] |= TMFV_TOGGLEINSIDES; if (sides[lines[i].sidenum[0]].toptexture > 0) lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; else @@ -2836,7 +2836,7 @@ static void P_ConvertBinaryMap(void) //Shadow? if (lines[i].special != 100 && (lines[i].special != 104 || !(lines[i].flags & ML_NOCLIMB))) - lines[i].args[3] |= 1; + lines[i].args[3] |= TMFA_NOSHADE; lines[i].special = 100; break; @@ -2850,7 +2850,7 @@ static void P_ConvertBinaryMap(void) //Opaque? if (lines[i].special == 120 || lines[i].special == 122) - lines[i].args[1] |= 1; + lines[i].args[1] |= TMFW_OPAQUE; else { if (sides[lines[i].sidenum[0]].toptexture > 0) @@ -2861,19 +2861,19 @@ static void P_ConvertBinaryMap(void) //No sides? if (lines[i].special == 122 || lines[i].special == 123 || lines[i].special == 125) - lines[i].args[1] |= 2; + lines[i].args[1] |= TMFW_NOSIDES; //Flags if (lines[i].flags & ML_NOCLIMB) - lines[i].args[1] |= 4; + lines[i].args[1] |= TMFW_DOUBLESHADOW; if (lines[i].flags & ML_EFFECT4) - lines[i].args[1] |= 8; + lines[i].args[1] |= TMFW_COLORMAPONLY; if (!(lines[i].flags & ML_EFFECT5)) - lines[i].args[1] |= 16; + lines[i].args[1] |= TMFW_NORIPPLE; //Goo? if (lines[i].special >= 124) - lines[i].args[1] |= 32; + lines[i].args[1] |= TMFW_GOOWATER; lines[i].special = 120; break; @@ -2888,29 +2888,29 @@ static void P_ConvertBinaryMap(void) //Visibility if (lines[i].special == 142 || lines[i].special == 145) - lines[i].args[1] = 2; + lines[i].args[1] = TMFV_NOSIDES; else if (lines[i].special == 146) - lines[i].args[1] = 1; + lines[i].args[1] = TMFV_NOPLANES; //Tangibility if (lines[i].special <= 142) - lines[i].args[2] |= 2; + lines[i].args[2] |= TMFT_INTANGIBLEBOTTOM; else if (lines[i].special <= 145) - lines[i].args[2] |= 1; + lines[i].args[2] |= TMFT_INTANGIBLETOP; else - lines[i].args[2] |= 3; + lines[i].args[2] |= TMFT_INTANGIBLEBOTTOM|TMFT_INTANGIBLETOP; if (lines[i].flags & ML_EFFECT1) - lines[i].args[2] |= 8; + lines[i].args[2] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[2] |= 4; + lines[i].args[2] |= TMFT_DONTBLOCKPLAYER; //Translucency if (lines[i].special == 141 || lines[i].special == 142 || lines[i].special == 144 || lines[i].special == 145) { - lines[i].args[3] |= 1; + lines[i].args[3] |= TMFA_TRANSLUCENT; if (lines[i].flags & ML_NOCLIMB) - lines[i].args[1] |= 4; + lines[i].args[1] |= TMFV_TOGGLEINSIDES; if (sides[lines[i].sidenum[0]].toptexture > 0) lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; else @@ -2919,7 +2919,7 @@ static void P_ConvertBinaryMap(void) //Shadow? if (lines[i].special != 146 && (lines[i].flags & ML_NOCLIMB)) - lines[i].args[3] |= 2; + lines[i].args[3] |= TMFA_NOSHADE; lines[i].special = 100; break; @@ -2937,24 +2937,24 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = lines[i].tag; if (lines[i].special >= 172 && lines[i].special <= 175) { - lines[i].args[1] |= 2; //Intangible from below + lines[i].args[1] |= TMFT_INTANGIBLEBOTTOM; if (lines[i].flags & ML_NOCLIMB) - lines[i].args[2] |= 2; //Don't cast shadow + lines[i].args[2] |= TMFC_NOSHADE; } if (lines[i].special >= 174 && lines[i].special <= 175) { - lines[i].args[2] |= 1; //Translucent + lines[i].args[2] |= TMFC_TRANSLUCENT; if (sides[lines[i].sidenum[0]].toptexture > 0) lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; else lines[i].alpha = FRACUNIT/2; } if (lines[i].special % 2 == 1) - lines[i].args[2] |= 4; //Don't respawn + lines[i].args[2] |= TMFC_NORETURN; if (lines[i].special == 176 || lines[i].special == 177 || lines[i].special == 180) - lines[i].args[2] |= 8; //Air bobbing + lines[i].args[2] |= TMFC_AIRBOB; if (lines[i].special >= 176 && lines[i].special <= 179) - lines[i].args[2] |= 16; //Float on water + lines[i].args[2] |= TMFC_FLOATBOB; lines[i].special = 170; break; case 200: //FOF: Light block @@ -2975,30 +2975,30 @@ static void P_ConvertBinaryMap(void) //Visibility if (lines[i].special == 222) - lines[i].args[1] |= 1; //Don't render planes + lines[i].args[1] |= TMFV_NOPLANES; if (lines[i].special == 221) - lines[i].args[1] |= 4; //Don't render insides + lines[i].args[1] |= TMFV_TOGGLEINSIDES; //Appearance if (lines[i].special == 221) { - lines[i].args[2] |= 1; //Translucent + lines[i].args[2] |= TMFA_TRANSLUCENT; if (sides[lines[i].sidenum[0]].toptexture > 0) lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; else lines[i].alpha = FRACUNIT/2; } if (lines[i].special != 220 && !(lines[i].flags & ML_NOCLIMB)) - lines[i].args[2] |= 2; //Don't cast shadow + lines[i].args[2] |= TMFA_NOSHADE; lines[i].special = 220; break; case 250: //FOF: Mario block lines[i].args[0] = lines[i].tag; - if (lines[i].flags & ML_NOCLIMB) //Brick block - lines[i].args[1] |= 1; - if (lines[i].flags & ML_EFFECT1) //Invisible - lines[i].args[1] |= 2; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[1] |= TMFM_BRICK; + if (lines[i].flags & ML_EFFECT1) + lines[i].args[1] |= TMFM_INVISIBLE; break; case 251: //FOF: Thwomp block lines[i].args[0] = lines[i].tag; @@ -3029,18 +3029,18 @@ static void P_ConvertBinaryMap(void) //Bustable type if (lines[i].special <= 253) - lines[i].args[1] = 0; + lines[i].args[1] = TMFB_TOUCH; else if (lines[i].special >= 255) - lines[i].args[1] = 1; + lines[i].args[1] = TMFB_SPIN; else if (lines[i].flags & ML_NOCLIMB) - lines[i].args[1] = 3; + lines[i].args[1] = TMFB_STRONG; else - lines[i].args[1] = 2; + lines[i].args[1] = TMFB_REGULAR; //Translucency if (lines[i].special == 253 || lines[i].special == 256) { - lines[i].args[2] = 1; + lines[i].args[2] = TMFC_TRANSLUCENT; if (sides[lines[i].sidenum[0]].toptexture > 0) lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; else @@ -3048,14 +3048,14 @@ static void P_ConvertBinaryMap(void) } if (lines[i].flags & ML_EFFECT4) - lines[i].args[3] |= 1; //Bustable by pushables + lines[i].args[3] |= TMFB_PUSHABLES; if (lines[i].flags & ML_EFFECT5) { - lines[i].args[3] |= 2; //Trigger linedef executor + lines[i].args[3] |= TMFB_EXECUTOR; lines[i].args[4] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; } if (lines[i].special == 252 && lines[i].flags & ML_NOCLIMB) - lines[i].args[4] |= 4; //Bust only from below + lines[i].args[4] |= TMFB_ONLYBOTTOM; lines[i].special = 254; break; diff --git a/src/p_spec.c b/src/p_spec.c index ff6275889..9f5eed74a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6736,11 +6736,11 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; //Visibility settings - if (lines[i].args[1] & 1) //Don't render planes + if (lines[i].args[1] & TMFV_NOPLANES) ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[1] & 2) //Don't render sides + if (lines[i].args[1] & TMFV_NOSIDES) ffloorflags &= ~FF_RENDERSIDES; - if (lines[i].args[1] & 4) //Render insides + if (lines[i].args[1] & TMFV_TOGGLEINSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; @@ -6749,26 +6749,26 @@ void P_SpawnSpecials(boolean fromnetsave) } //Tangibility settings - if (lines[i].args[2] & 1) //Intangible from top + if (lines[i].args[2] & TMFT_INTANGIBLETOP) ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[2] & 2) //Intangible from bottom + if (lines[i].args[2] & TMFT_INTANGIBLEBOTTOM) ffloorflags |= FF_PLATFORM; - if (lines[i].args[2] & 4) //Don't block player + if (lines[i].args[2] & TMFT_DONTBLOCKPLAYER) ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[2] & 8) //Don't block others + if (lines[i].args[2] & TMFT_DONTBLOCKOTHERS) ffloorflags &= ~FF_BLOCKOTHERS; //Appearance settings - if ((lines[i].args[3] & 1) && (ffloorflags & FF_RENDERALL)) //Translucent + if ((lines[i].args[3] & TMFA_TRANSLUCENT) && (ffloorflags & FF_RENDERALL)) //Translucent ffloorflags |= FF_TRANSLUCENT; - if (lines[i].args[3] & 2) //Don't cast shadow + if (lines[i].args[3] & TMFA_NOSHADE) ffloorflags |= FF_NOSHADE; //Cutting options if (ffloorflags & FF_RENDERALL) { //If translucent or player can enter it, cut inner walls - if ((ffloorflags & FF_TRANSLUCENT) || (lines[i].args[2] & 7)) + if ((ffloorflags & FF_TRANSLUCENT) || (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE)) ffloorflags |= FF_CUTEXTRA|FF_EXTRA; else ffloorflags |= FF_CUTLEVEL; @@ -6779,17 +6779,17 @@ void P_SpawnSpecials(boolean fromnetsave) case 120: // FOF (water) ffloorflags = FF_EXISTS|FF_RENDERPLANES|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - if (!(lines[i].args[1] & 1)) + if (!(lines[i].args[1] & TMFW_OPAQUE)) ffloorflags |= FF_TRANSLUCENT; - if (!(lines[i].args[1] & 2)) + if (!(lines[i].args[1] & TMFW_NOSIDES)) ffloorflags |= FF_RENDERSIDES|FF_ALLSIDES; - if (lines[i].args[1] & 4) + if (lines[i].args[1] & TMFW_DOUBLESHADOW) ffloorflags |= FF_DOUBLESHADOW; - if (lines[i].args[1] & 8) + if (lines[i].args[1] & TMFW_COLORMAPONLY) ffloorflags |= FF_COLORMAPONLY; - if (!(lines[i].args[1] & 16)) + if (!(lines[i].args[1] & TMFW_NORIPPLE)) ffloorflags |= FF_RIPPLE; - if (lines[i].args[1] & 32) + if (lines[i].args[1] & TMFW_GOOWATER) ffloorflags |= FF_GOOWATER; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; @@ -6819,33 +6819,33 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE; //Tangibility settings - if (lines[i].args[1] & 1) //Intangible from top + if (lines[i].args[1] & TMFT_INTANGIBLETOP) ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[1] & 2) //Intangible from bottom + if (lines[i].args[1] & TMFT_INTANGIBLEBOTTOM) ffloorflags |= FF_PLATFORM; - if (lines[i].args[1] & 4) //Don't block player + if (lines[i].args[1] & TMFT_DONTBLOCKPLAYER) ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[1] & 8) //Don't block others + if (lines[i].args[1] & TMFT_DONTBLOCKOTHERS) ffloorflags &= ~FF_BLOCKOTHERS; //Flags - if (lines[i].args[2] & 1) //Translucent + if (lines[i].args[2] & TMFC_TRANSLUCENT) ffloorflags |= FF_TRANSLUCENT; - if (lines[i].args[2] & 2) //Don't cast shadow + if (lines[i].args[2] & TMFC_NOSHADE) ffloorflags |= FF_NOSHADE; - if (lines[i].args[2] & 4) //Don't respawn + if (lines[i].args[2] & TMFC_NORETURN) ffloorflags |= FF_NORETURN; - if (lines[i].args[2] & 16) //Float on water + if (lines[i].args[2] & TMFC_FLOATBOB) ffloorflags |= FF_FLOATBOB; //If translucent or player can enter it, cut inner walls - if ((ffloorflags & FF_TRANSLUCENT) || (lines[i].args[1] & 7)) + if ((ffloorflags & FF_TRANSLUCENT) || (lines[i].args[1] & TMFT_VISIBLEFROMINSIDE)) ffloorflags |= FF_CUTEXTRA|FF_EXTRA; else ffloorflags |= FF_CUTLEVEL; //If player can enter it, render insides - if (lines[i].args[1] & 7) + if (lines[i].args[1] & TMFT_VISIBLEFROMINSIDE) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; @@ -6854,7 +6854,7 @@ void P_SpawnSpecials(boolean fromnetsave) } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - if (lines[i].args[2] & 8) //Air bobbing + if (lines[i].args[2] & TMFC_AIRBOB) P_AddAirbob(lines[i].frontsector, lines + i, 16*FRACUNIT, false, false, false); break; @@ -6918,11 +6918,11 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_RENDERALL|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; //Visibility settings - if (lines[i].args[1] & 1) //Don't render planes + if (lines[i].args[1] & TMFV_NOPLANES) ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[1] & 2) //Don't render sides + if (lines[i].args[1] & TMFV_NOSIDES) ffloorflags &= ~FF_RENDERSIDES; - if (!(lines[i].args[1] & 4)) //Render insides + if (!(lines[i].args[1] & TMFV_TOGGLEINSIDES)) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; @@ -6931,9 +6931,9 @@ void P_SpawnSpecials(boolean fromnetsave) } //Appearance settings - if ((lines[i].args[2] & 1) && (ffloorflags & FF_RENDERALL)) //Translucent + if ((lines[i].args[2] & TMFA_TRANSLUCENT) && (ffloorflags & FF_RENDERALL)) ffloorflags |= FF_TRANSLUCENT; - if (lines[i].args[2] & 2) //Don't cast shadow + if (lines[i].args[2] & TMFA_NOSHADE) ffloorflags |= FF_NOSHADE; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); @@ -6945,9 +6945,9 @@ void P_SpawnSpecials(boolean fromnetsave) case 250: // Mario Block ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO; - if (lines[i].args[1] & 1) //Brick block + if (lines[i].args[1] & TMFM_BRICK) ffloorflags |= FF_SHATTERBOTTOM; - if (lines[i].args[1] & 2) // Invisible + if (lines[i].args[1] & TMFM_INVISIBLE) ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); @@ -6969,13 +6969,13 @@ void P_SpawnSpecials(boolean fromnetsave) //Bustable type switch (lines[i].args[1]) { - case 0: + case TMFB_TOUCH: ffloorflags |= FF_SHATTER; break; - case 1: + case TMFB_SPIN: ffloorflags |= FF_SPINBUST; break; - case 3: + case TMFB_STRONG: ffloorflags |= FF_STRONGBUST; break; default: @@ -6985,7 +6985,7 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[2]) ffloorflags |= FF_TRANSLUCENT; - if (lines[i].args[2] & 4) + if (lines[i].args[3] & TMFB_ONLYBOTTOM) ffloorflags |= FF_SHATTERBOTTOM; if (!(ffloorflags & FF_SHATTER) || ffloorflags & FF_SHATTERBOTTOM) diff --git a/src/p_spec.h b/src/p_spec.h index d756f1942..6d13e9da7 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -21,6 +21,69 @@ extern mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpo extern mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs extern mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs +//FOF flags +typedef enum +{ + TMFV_NOPLANES = 1, + TMFV_NOSIDES = 1<<1, + TMFV_TOGGLEINSIDES = 1<<2, +} textmapfofvisibility_t; + +typedef enum +{ + TMFT_INTANGIBLETOP = 1, + TMFT_INTANGIBLEBOTTOM = 1<<1, + TMFT_DONTBLOCKPLAYER = 1<<2, + TMFT_VISIBLEFROMINSIDE = (TMFT_INTANGIBLETOP|TMFT_INTANGIBLEBOTTOM|TMFT_DONTBLOCKPLAYER), + TMFT_DONTBLOCKOTHERS = 1<<3, +} textmapfoftangibility_t; + +typedef enum +{ + TMFA_TRANSLUCENT = 1, + TMFA_NOSHADE = 1<<1, +} textmapfofappearance_t; + +typedef enum +{ + TMFW_OPAQUE = 1, + TMFW_NOSIDES = 1<<1, + TMFW_DOUBLESHADOW = 1<<2, + TMFW_COLORMAPONLY = 1<<3, + TMFW_NORIPPLE = 1<<4, + TMFW_GOOWATER = 1<<5, +} textmapfofwater_t; + +typedef enum +{ + TMFC_TRANSLUCENT = 1, + TMFC_NOSHADE = 1<<1, + TMFC_NORETURN = 1<<2, + TMFC_AIRBOB = 1<<3, + TMFC_FLOATBOB = 1<<4, +} textmapfofcrumbling_t; + +typedef enum +{ + TMFM_BRICK = 1, + TMFM_INVISIBLE = 1<<1, +} textmapfofmario_t; + +typedef enum +{ + TMFB_TOUCH, + TMFB_SPIN, + TMFB_REGULAR, + TMFB_STRONG, +} textmapfofbusttype_t; + +typedef enum +{ + TMFB_PUSHABLES = 1, + TMFB_EXECUTOR = 1<<1, + TMFB_ONLYBOTTOM = 1<<2, +} textmapfofbustflags_t; + // GETSECSPECIAL (specialval, section) // // Pulls out the special # from a particular section. diff --git a/src/p_user.c b/src/p_user.c index c1dc2676d..8accce238 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2663,7 +2663,7 @@ static void P_CheckBustableBlocks(player_t *player) EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? - if (rover->master->args[3] & 2) + if (rover->master->args[3] & TMFB_EXECUTOR) P_LinedefExecute((INT16)(rover->master->args[4]), player->mo, node->m_sector); goto bustupdone; @@ -12213,7 +12213,7 @@ void P_PlayerThink(player_t *player) player->powers[pw_nocontrol]--; else player->powers[pw_nocontrol] = 0; - + //pw_super acts as a timer now if (player->powers[pw_super] && (player->mo->state < &states[S_PLAY_SUPER_TRANS1] From 0ab01cd4b25c13587c47687d83d3c47dd9331ff7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 25 Apr 2020 09:20:53 +0200 Subject: [PATCH 018/326] Port over thwomp thinker changes manually, to avoid merge conflicts --- src/p_floor.c | 249 ++++++++++++++++++++++++-------------------------- src/p_saveg.c | 46 +++++++++- src/p_spec.c | 36 ++++---- src/p_spec.h | 17 +++- 4 files changed, 197 insertions(+), 151 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index b67f193fa..6f3b459ca 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -11,7 +11,6 @@ /// \file p_floor.c /// \brief Floor animation, elevators -#include "dehacked.h" #include "doomdef.h" #include "doomstat.h" #include "m_random.h" @@ -1266,156 +1265,74 @@ void T_MarioBlockChecker(levelspecthink_t *block) } } +static boolean P_IsPlayerValid(size_t playernum) +{ + if (!playeringame[playernum]) + return false; + + if (!players[playernum].mo) + return false; + + if (players[playernum].mo->health <= 0) + return false; + + if (players[playernum].spectator) + return false; + + return true; +} + // This is the Thwomp's 'brain'. It looks around for players nearby, and if // it finds any, **SMASH**!!! Muahahhaa.... -void T_ThwompSector(levelspecthink_t *thwomp) +void T_ThwompSector(thwomp_t *thwomp) { -#define speed vars[1] -#define direction vars[2] -#define distance vars[3] -#define floorwasheight vars[4] -#define ceilingwasheight vars[5] fixed_t thwompx, thwompy; sector_t *actionsector; ffloor_t *rover = NULL; INT32 secnum; + fixed_t speed; // If you just crashed down, wait a second before coming back up. - if (--thwomp->distance > 0) - { - sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture; + if (--thwomp->delay > 0) return; - } // Just find the first sector with the tag. // Doesn't work with multiple sectors that have different floor/ceiling heights. - secnum = P_FindSectorFromTag((INT16)thwomp->vars[0], -1); + secnum = P_FindSectorFromTag(thwomp->tag, -1); - if (secnum > 0) - { - actionsector = §ors[secnum]; - - // Look for thwomp FFloor - for (rover = actionsector->ffloors; rover; rover = rover->next) - { - if (rover->master == thwomp->sourceline) - break; - } - } - else + if (secnum <= 0) return; // Bad bad bad! + actionsector = §ors[secnum]; + + // Look for thwomp FOF + for (rover = actionsector->ffloors; rover; rover = rover->next) + { + if (rover->master == thwomp->sourceline) + break; + } + + if (!rover) + return; // Didn't find any FOFs, so bail out + thwompx = actionsector->soundorg.x; thwompy = actionsector->soundorg.y; - if (thwomp->direction > 0) // Moving back up.. + if (thwomp->direction == 0) // Not going anywhere, so look for players. { - result_e res = 0; - - // Set the texture from the lower one (normal) - sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture; - /// \note this should only have to be done once, but is already done repeatedly, above - - thwomp->speed = thwomp->sourceline->args[2] << (FRACBITS - 3); - - res = T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - thwomp->floorwasheight, // dest - 0, // crush - 0, // floor or ceiling (0 for floor) - thwomp->direction // direction - ); - - if (res == ok || res == pastdest) - T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - thwomp->ceilingwasheight, // dest - 0, // crush - 1, // floor or ceiling (1 for ceiling) - thwomp->direction // direction - ); - - if (res == pastdest) - thwomp->direction = 0; // stop moving - - thwomp->sector->ceilspeed = 42; - thwomp->sector->floorspeed = thwomp->speed*thwomp->direction; - } - else if (thwomp->direction < 0) // Crashing down! - { - result_e res = 0; - - // Set the texture from the upper one (angry) - sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].toptexture; - - thwomp->speed = thwomp->sourceline->args[1] << (FRACBITS - 3); - - res = T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, - thwomp->sector->ceilingheight - thwomp->sector->floorheight), // dest - 0, // crush - 0, // floor or ceiling (0 for floor) - thwomp->direction // direction - ); - - if (res == ok || res == pastdest) - T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, - thwomp->sector->ceilingheight - - (thwomp->sector->floorheight + thwomp->speed)) - + (thwomp->sector->ceilingheight - - (thwomp->sector->floorheight + thwomp->speed/2)), // dest - 0, // crush - 1, // floor or ceiling (1 for ceiling) - thwomp->direction // direction - ); - - if (res == pastdest) - { - mobj_t *mp = (void *)&actionsector->soundorg; - - if (!rover || (rover->flags & FF_EXISTS)) - { - sfxenum_t sound = (thwomp->sourceline->stringargs[0]) ? get_number(thwomp->sourceline->stringargs[0]) : sfx_thwomp; - S_StartSound(mp, sound); - } - - thwomp->direction = 1; // start heading back up - thwomp->distance = TICRATE; // but only after a small delay - } - - thwomp->sector->ceilspeed = 42; - thwomp->sector->floorspeed = thwomp->speed*thwomp->direction; - } - else // Not going anywhere, so look for players. - { - if (!rover || (rover->flags & FF_EXISTS)) + if (rover->flags & FF_EXISTS) { UINT8 i; // scan the players to find victims! for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i]) - continue; - if (players[i].spectator) - continue; - if (!players[i].mo) - continue; - if (!players[i].mo->health) + if (!P_IsPlayerValid(i)) continue; + if (players[i].mo->z > thwomp->sector->ceilingheight) continue; - if (P_AproxDistance(thwompx - players[i].mo->x, thwompy - players[i].mo->y) > 96 * FRACUNIT) + + if (P_AproxDistance(thwompx - players[i].mo->x, thwompy - players[i].mo->y) > 96*FRACUNIT) continue; thwomp->direction = -1; @@ -1426,13 +1343,89 @@ void T_ThwompSector(levelspecthink_t *thwomp) thwomp->sector->ceilspeed = 0; thwomp->sector->floorspeed = 0; } + else + { + result_e res = 0; + + if (thwomp->direction > 0) //Moving back up.. + { + // Set the texture from the lower one (normal) + sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture; + + speed = thwomp->retractspeed; + + res = T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + thwomp->floorstartheight, // dest + false, // crush + 0, // ceiling? + thwomp->direction // direction + ); + + if (res == ok || res == pastdest) + T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + thwomp->ceilingstartheight, // dest + false, // crush + 1, // ceiling? + thwomp->direction // direction + ); + + if (res == pastdest) + thwomp->direction = 0; // stop moving + } + else // Crashing down! + { + // Set the texture from the upper one (angry) + sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].toptexture; + + speed = thwomp->crushspeed; + + res = T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, + thwomp->sector->ceilingheight - thwomp->sector->floorheight), // dest + false, // crush + 0, // ceiling? + thwomp->direction // direction + ); + + if (res == ok || res == pastdest) + T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, + thwomp->sector->ceilingheight + - (thwomp->sector->floorheight + speed)) + + (thwomp->sector->ceilingheight + - (thwomp->sector->floorheight + speed/2)), // dest + false, // crush + 1, // ceiling? + thwomp->direction // direction + ); + + if (res == pastdest) + { + if (rover->flags & FF_EXISTS) + S_StartSound((void *)&actionsector->soundorg, thwomp->sound); + + thwomp->direction = 1; // start heading back up + thwomp->delay = TICRATE; // but only after a small delay + } + } + + thwomp->sector->ceilspeed = 42; + thwomp->sector->floorspeed = speed*thwomp->direction; + } P_RecalcPrecipInSector(actionsector); -#undef speed -#undef direction -#undef distance -#undef floorwasheight -#undef ceilingwasheight } // diff --git a/src/p_saveg.c b/src/p_saveg.c index 34392886d..23407b2b1 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1745,6 +1745,27 @@ static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, SaveSector(ht->sector)); } +// +// SaveThwompThinker +// +// Saves a thwomp_t thinker +// +static void SaveThwompThinker(const thinker_t *th, const UINT8 type) +{ + const thwomp_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); + WRITEUINT32(save_p, SaveSector(ht->sector)); + WRITEFIXED(save_p, ht->crushspeed); + WRITEFIXED(save_p, ht->retractspeed); + WRITEINT32(save_p, ht->direction); + WRITEFIXED(save_p, ht->floorstartheight); + WRITEFIXED(save_p, ht->ceilingstartheight); + WRITEINT32(save_p, ht->delay); + WRITEINT16(save_p, ht->tag); + WRITEUINT16(save_p, ht->sound); +} + // // SaveCeilingThinker // @@ -2308,7 +2329,7 @@ static void P_NetArchiveThinkers(void) } else if (th->function.acp1 == (actionf_p1)T_ThwompSector) { - SaveSpecialLevelThinker(th, tc_thwomp); + SaveThwompThinker(th, tc_thwomp); continue; } else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector) @@ -2856,6 +2877,27 @@ static thinker_t* LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeili return &ht->thinker; } +// LoadThwompThinker +// +// Loads a thwomp_t from a save game +// +static thinker_t* LoadThwompThinker(actionf_p1 thinker) +{ + thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sourceline = LoadLine(READUINT32(save_p)); + ht->sector = LoadSector(READUINT32(save_p)); + ht->crushspeed = READFIXED(save_p); + ht->retractspeed = READFIXED(save_p); + ht->direction = READINT32(save_p); + ht->floorstartheight = READFIXED(save_p); + ht->ceilingstartheight = READFIXED(save_p); + ht->delay = READINT32(save_p); + ht->tag = READINT16(save_p); + ht->sound = READUINT16(save_p); + return &ht->thinker; +} + // // LoadCeilingThinker // @@ -3522,7 +3564,7 @@ static void P_NetUnArchiveThinkers(void) break; case tc_thwomp: - th = LoadSpecialLevelThinker((actionf_p1)T_ThwompSector, 3); + th = LoadThwompThinker((actionf_p1)T_ThwompSector); break; case tc_noenemies: diff --git a/src/p_spec.c b/src/p_spec.c index 9f5eed74a..7c968f376 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -15,6 +15,7 @@ /// utility functions, etc. /// Line Tag handling. Line and Sector triggers. +#include "dehacked.h" #include "doomdef.h" #include "g_game.h" #include "p_local.h" @@ -6133,12 +6134,7 @@ static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean */ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, line_t *sourceline) { -#define speed vars[1] -#define direction vars[2] -#define distance vars[3] -#define floorwasheight vars[4] -#define ceilingwasheight vars[5] - levelspecthink_t *thwomp; + thwomp_t *thwomp; // You *probably* already have a thwomp in this sector. If you've combined it with something // else that uses the floordata/ceilingdata, you must be weird. @@ -6152,21 +6148,21 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin thwomp->thinker.function.acp1 = (actionf_p1)T_ThwompSector; // set up the fields according to the type of elevator action - thwomp->sector = sec; - thwomp->vars[0] = actionsector->tag; - thwomp->floorwasheight = thwomp->sector->floorheight; - thwomp->ceilingwasheight = thwomp->sector->ceilingheight; - thwomp->direction = 0; - thwomp->distance = 1; thwomp->sourceline = sourceline; - thwomp->sector->floordata = thwomp; - thwomp->sector->ceilingdata = thwomp; - return; -#undef speed -#undef direction -#undef distance -#undef floorwasheight -#undef ceilingwasheight + thwomp->sector = sec; + thwomp->crushspeed = thwomp->sourceline->args[1] << (FRACBITS - 3); + thwomp->retractspeed = thwomp->sourceline->args[2] << (FRACBITS - 3); + thwomp->direction = 0; + thwomp->floorstartheight = sec->floorheight; + thwomp->ceilingstartheight = sec->ceilingheight; + thwomp->delay = 1; + thwomp->tag = actionsector->tag; + thwomp->sound = (thwomp->sourceline->stringargs[0]) ? get_number(thwomp->sourceline->stringargs[0]) : sfx_thwomp; + + sec->floordata = thwomp; + sec->ceilingdata = thwomp; + // Start with 'resting' texture + sides[sourceline->sidenum[0]].midtexture = sides[sourceline->sidenum[0]].bottomtexture; } /** Adds a thinker which checks if any MF_ENEMY objects with health are in the defined area. diff --git a/src/p_spec.h b/src/p_spec.h index 6d13e9da7..083cd0ce6 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -383,6 +383,21 @@ typedef struct sector_t *sector; // Sector the thinker is from } levelspecthink_t; +typedef struct +{ + thinker_t thinker; + line_t *sourceline; + sector_t *sector; + fixed_t crushspeed; + fixed_t retractspeed; + INT32 direction; + fixed_t floorstartheight; + fixed_t ceilingstartheight; + INT32 delay; + INT16 tag; + UINT16 sound; +} thwomp_t; + #define ELEVATORSPEED (FRACUNIT*4) #define FLOORSPEED (FRACUNIT) @@ -418,7 +433,7 @@ void T_MarioBlock(levelspecthink_t *block); void T_SpikeSector(levelspecthink_t *spikes); void T_FloatSector(levelspecthink_t *floater); void T_MarioBlockChecker(levelspecthink_t *block); -void T_ThwompSector(levelspecthink_t *thwomp); +void T_ThwompSector(thwomp_t *thwomp); void T_NoEnemiesSector(levelspecthink_t *nobaddies); void T_EachTimeThinker(levelspecthink_t *eachtime); void T_CameraScanner(elevator_t *elevator); From 1aa90754db8a59b4dd9a552632f1b131e9fe5c73 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 26 Apr 2020 10:33:13 +0200 Subject: [PATCH 019/326] Port over raise thinker changes from next (preparation for merge) --- src/p_saveg.c | 41 +++++++++++++++++++++++++++++++++++++++-- src/p_spec.c | 46 ++++++++++++++++------------------------------ src/p_spec.h | 22 +++++++++++++++++++++- 3 files changed, 76 insertions(+), 33 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 23407b2b1..f9ab4d83c 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1766,6 +1766,24 @@ static void SaveThwompThinker(const thinker_t *th, const UINT8 type) WRITEUINT16(save_p, ht->sound); } +// SaveRaiseThinker +// +// Saves a raise_t thinker +// +static void SaveRaiseThinker(const thinker_t *th, const UINT8 type) +{ + const raise_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); + WRITEUINT32(save_p, SaveSector(ht->sector)); + WRITEFIXED(save_p, ht->ceilingbottom); + WRITEFIXED(save_p, ht->ceilingtop); + WRITEFIXED(save_p, ht->basespeed); + WRITEFIXED(save_p, ht->extraspeed); + WRITEUINT8(save_p, ht->shaketimer); + WRITEUINT8(save_p, ht->flags); +} + // // SaveCeilingThinker // @@ -2344,7 +2362,7 @@ static void P_NetArchiveThinkers(void) } else if (th->function.acp1 == (actionf_p1)T_RaiseSector) { - SaveSpecialLevelThinker(th, tc_raisesector); + SaveRaiseThinker(th, tc_raisesector); continue; } else if (th->function.acp1 == (actionf_p1)T_CameraScanner) @@ -2898,6 +2916,25 @@ static thinker_t* LoadThwompThinker(actionf_p1 thinker) return &ht->thinker; } +// LoadRaiseThinker +// +// Loads a raise_t from a save game +// +static thinker_t* LoadRaiseThinker(actionf_p1 thinker) +{ + raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sourceline = LoadLine(READUINT32(save_p)); + ht->sector = LoadSector(READUINT32(save_p)); + ht->ceilingbottom = READFIXED(save_p); + ht->ceilingtop = READFIXED(save_p); + ht->basespeed = READFIXED(save_p); + ht->extraspeed = READFIXED(save_p); + ht->shaketimer = READUINT8(save_p); + ht->flags = READUINT8(save_p); + return &ht->thinker; +} + // // LoadCeilingThinker // @@ -3576,7 +3613,7 @@ static void P_NetUnArchiveThinkers(void) break; case tc_raisesector: - th = LoadSpecialLevelThinker((actionf_p1)T_RaiseSector, 0); + th = LoadRaiseThinker((actionf_p1)T_RaiseSector); break; /// \todo rewrite all the code that uses an elevator_t but isn't an elevator diff --git a/src/p_spec.c b/src/p_spec.c index 7c968f376..6ffb56776 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6050,42 +6050,28 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline) * \sa P_SpawnSpecials, T_RaiseSector * \author SSNTails */ -static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline) +static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, boolean lower, boolean spindash) { - levelspecthink_t *raise; + raise_t *raise; raise = Z_Calloc(sizeof (*raise), PU_LEVSPEC, NULL); P_AddThinker(THINK_MAIN, &raise->thinker); raise->thinker.function.acp1 = (actionf_p1)T_RaiseSector; - if (sourceline->flags & ML_BLOCKMONSTERS) - raise->vars[0] = 1; - else - raise->vars[0] = 0; - // set up the fields + raise->sourceline = sourceline; raise->sector = sec; - // Require a spindash to activate - if (sourceline->flags & ML_NOCLIMB) - raise->vars[1] = 1; - else - raise->vars[1] = 0; + raise->ceilingtop = P_FindHighestCeilingSurrounding(sec); + raise->ceilingbottom = P_FindLowestCeilingSurrounding(sec); - raise->vars[2] = P_AproxDistance(sourceline->dx, sourceline->dy); - raise->vars[2] = FixedDiv(raise->vars[2], 4*FRACUNIT); - raise->vars[3] = raise->vars[2]; + raise->basespeed = FixedDiv(P_AproxDistance(sourceline->dx, sourceline->dy), 4*FRACUNIT); - raise->vars[5] = P_FindHighestCeilingSurrounding(sec); - raise->vars[4] = raise->vars[5] - - (sec->ceilingheight - sec->floorheight); - - raise->vars[7] = P_FindLowestCeilingSurrounding(sec); - raise->vars[6] = raise->vars[7] - - (sec->ceilingheight - sec->floorheight); - - raise->sourceline = sourceline; + if (lower) + raise->flags |= RF_REVERSE; + if (spindash) + raise->flags |= RF_SPINDASH; } static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean raise, boolean dynamic, boolean spindash) @@ -6856,22 +6842,22 @@ void P_SpawnSpecials(boolean fromnetsave) case 190: // Rising Platform FOF (solid, opaque, shadows) P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); + P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); break; case 191: // Rising Platform FOF (solid, opaque, no shadows) P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_CUTLEVEL, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); + P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); break; case 192: // Rising Platform TL block: FOF (solid, translucent) P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); + P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); break; case 193: // Rising Platform FOF (solid, invisible) P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_NOSHADE, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); + P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); break; case 194: // Rising Platform 'Platform' - You can jump up through it @@ -6881,7 +6867,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_NOSHADE; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); + P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); break; case 195: // Rising Platform Translucent "platform" @@ -6891,7 +6877,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_NOSHADE; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); + P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); break; case 200: // Light block diff --git a/src/p_spec.h b/src/p_spec.h index 083cd0ce6..06d4ad266 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -398,6 +398,26 @@ typedef struct UINT16 sound; } thwomp_t; +typedef enum +{ + RF_REVERSE = 1, //Lower when stood on + RF_SPINDASH = 1<<1, //Require spindash to move + RF_DYNAMIC = 1<<2, //Dynamically sinking platform +} raiseflag_t; + +typedef struct +{ + thinker_t thinker; + line_t *sourceline; + sector_t *sector; + fixed_t ceilingbottom; + fixed_t ceilingtop; + fixed_t basespeed; + fixed_t extraspeed; //For dynamically sinking platform + UINT8 shaketimer; //For dynamically sinking platform + UINT8 flags; +} raise_t; + #define ELEVATORSPEED (FRACUNIT*4) #define FLOORSPEED (FRACUNIT) @@ -437,7 +457,7 @@ void T_ThwompSector(thwomp_t *thwomp); void T_NoEnemiesSector(levelspecthink_t *nobaddies); void T_EachTimeThinker(levelspecthink_t *eachtime); void T_CameraScanner(elevator_t *elevator); -void T_RaiseSector(levelspecthink_t *sraise); +void T_RaiseSector(raise_t *raise); typedef struct { From abcc47ac6109d29e50c4ee06c8df66eefc936b35 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 26 Apr 2020 10:35:08 +0200 Subject: [PATCH 020/326] Bring signature of P_AddAirbob in line with next --- src/p_spec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 6ffb56776..24f6e572e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6074,7 +6074,7 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, boolean lower, raise->flags |= RF_SPINDASH; } -static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean raise, boolean dynamic, boolean spindash) +static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean raise, boolean spindash, boolean dynamic) { levelspecthink_t *airbob; @@ -6781,16 +6781,16 @@ void P_SpawnSpecials(boolean fromnetsave) { fixed_t dist = (lines[i].special == 151) ? P_AproxDistance(lines[i].dx, lines[i].dy) : 16*FRACUNIT; P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - P_AddAirbob(lines[i].frontsector, lines + i, dist, false, false, !!(lines[i].flags & ML_NOCLIMB)); + P_AddAirbob(lines[i].frontsector, lines + i, dist, false, !!(lines[i].flags & ML_NOCLIMB), false); break; } case 152: // Adjustable air bobbing platform in reverse P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), true, false, !!(lines[i].flags & ML_NOCLIMB)); + P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), true, !!(lines[i].flags & ML_NOCLIMB), false); break; case 153: // Dynamic Sinking Platform P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), false, true, !!(lines[i].flags & ML_NOCLIMB)); + P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), false, !!(lines[i].flags & ML_NOCLIMB), true); break; case 160: // Float/bob platform From b439fa2b990a91aed3b2126bf8e71f5843edfcb0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 26 Apr 2020 10:37:31 +0200 Subject: [PATCH 021/326] Uh-oh! Forgot to stash a file --- src/p_floor.c | 172 ++++++++++++++++---------------------------------- 1 file changed, 55 insertions(+), 117 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index 6f3b459ca..b831fb78b 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1833,14 +1833,18 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) // Rises up to its topmost position when a // player steps on it. Lowers otherwise. // -void T_RaiseSector(levelspecthink_t *raise) +void T_RaiseSector(raise_t *raise) { msecnode_t *node; mobj_t *thing; sector_t *sector; INT32 i; boolean playeronme = false, active = false; + boolean moveUp; fixed_t ceilingdestination, floordestination; + fixed_t speed, origspeed; + fixed_t distToNearestEndpoint; + INT32 direction; result_e res = 0; if (raise->sector->crumblestate >= 3 || raise->sector->ceilingdata) @@ -1863,7 +1867,7 @@ void T_RaiseSector(levelspecthink_t *raise) continue; // Option to require spindashing. - if (raise->vars[1] && !(thing->player->pflags & PF_STARTDASH)) + if (raise->flags & RF_SPINDASH && !(thing->player->pflags & PF_STARTDASH)) continue; if (!(thing->z == P_GetSpecialTopZ(thing, raise->sector, sector))) @@ -1874,43 +1878,43 @@ void T_RaiseSector(levelspecthink_t *raise) } } - if (raise->vars[9]) // Dynamically Sinking Platform^tm + if (raise->flags & RF_DYNAMIC) // Dynamically Sinking Platform^tm { #define shaketime 10 - if (raise->vars[11] > shaketime) // State: moving + if (raise->shaketimer > shaketime) // State: moving { if (playeronme) // If player is standing on the platform, accelerate { - raise->vars[10] += (FRACUNIT >> 5); + raise->extraspeed += (FRACUNIT >> 5); } else // otherwise, decelerate until inflection { - raise->vars[10] -= FRACUNIT >> 3; - if (raise->vars[10] <= 0) // inflection! + raise->extraspeed -= FRACUNIT >> 3; + if (raise->extraspeed <= 0) // inflection! { - raise->vars[10] = 0; - raise->vars[11] = 0; // allow the shake to occur again (fucks over players attempting to jump-cheese) + raise->extraspeed = 0; + raise->shaketimer = 0; // allow the shake to occur again (fucks over players attempting to jump-cheese) } } - active = raise->vars[10] > 0; + active = raise->extraspeed > 0; } else // State: shaking { - if (playeronme || raise->vars[11]) + if (playeronme || raise->shaketimer) { active = true; - if (++raise->vars[11] > shaketime) + if (++raise->shaketimer > shaketime) { if (playeronme) - raise->vars[10] = FRACUNIT >> 5; + raise->extraspeed = FRACUNIT >> 5; else - raise->vars[10] = FRACUNIT << 1; + raise->extraspeed = FRACUNIT << 1; } else { - raise->vars[10] = ((shaketime/2) - raise->vars[11]) << FRACBITS; - if (raise->vars[10] < -raise->vars[2]/2) - raise->vars[10] = -raise->vars[2]/2; + raise->extraspeed = ((shaketime/2) - raise->shaketimer) << FRACBITS; + if (raise->extraspeed < -raise->basespeed/2) + raise->extraspeed = -raise->basespeed/2; } } } @@ -1919,125 +1923,59 @@ void T_RaiseSector(levelspecthink_t *raise) else // Air bobbing platform (not a Dynamically Sinking Platform^tm) active = playeronme; - if (active) + moveUp = active ^ (raise->flags & RF_REVERSE); + ceilingdestination = moveUp ? raise->ceilingtop : raise->ceilingbottom; + floordestination = ceilingdestination - (raise->sector->ceilingheight - raise->sector->floorheight); + + if ((moveUp && raise->sector->ceilingheight >= ceilingdestination) + || (!moveUp && raise->sector->ceilingheight <= ceilingdestination)) { - raise->vars[3] = raise->vars[2]; - - if (raise->vars[0] == 1) - { - if (raise->sector->ceilingheight <= raise->vars[7]) - { - raise->sector->floorheight = raise->vars[7] - (raise->sector->ceilingheight - raise->sector->floorheight); - raise->sector->ceilingheight = raise->vars[7]; - raise->sector->ceilspeed = 0; - raise->sector->floorspeed = 0; - return; - } - - raise->vars[8] = -1; - ceilingdestination = raise->vars[7]; - floordestination = raise->vars[6]; - } - else // elevateUp - { - if (raise->sector->ceilingheight >= raise->vars[5]) - { - raise->sector->floorheight = raise->vars[5] - (raise->sector->ceilingheight - raise->sector->floorheight); - raise->sector->ceilingheight = raise->vars[5]; - raise->sector->ceilspeed = 0; - raise->sector->floorspeed = 0; - return; - } - - raise->vars[8] = 1; - ceilingdestination = raise->vars[5]; - floordestination = raise->vars[4]; - } + raise->sector->floorheight = floordestination; + raise->sector->ceilingheight = ceilingdestination; + raise->sector->ceilspeed = 0; + raise->sector->floorspeed = 0; + return; } - else - { - raise->vars[3] = raise->vars[2]/2; + direction = moveUp ? 1 : -1; - if (raise->vars[0] == 1) - { - if (raise->sector->ceilingheight >= raise->vars[5]) - { - raise->sector->floorheight = raise->vars[5] - (raise->sector->ceilingheight - raise->sector->floorheight); - raise->sector->ceilingheight = raise->vars[5]; - raise->sector->ceilspeed = 0; - raise->sector->floorspeed = 0; - return; - } - raise->vars[8] = 1; - ceilingdestination = raise->vars[5]; - floordestination = raise->vars[4]; - } - else // elevateUp - { - if (raise->sector->ceilingheight <= raise->vars[7]) - { - raise->sector->floorheight = raise->vars[7] - (raise->sector->ceilingheight - raise->sector->floorheight); - raise->sector->ceilingheight = raise->vars[7]; - raise->sector->ceilspeed = 0; - raise->sector->floorspeed = 0; - return; - } - raise->vars[8] = -1; - ceilingdestination = raise->vars[7]; - floordestination = raise->vars[6]; - } - } + origspeed = raise->basespeed; + if (!active) + origspeed /= 2; - if ((raise->sector->ceilingheight - raise->vars[7]) - < (raise->vars[5] - raise->sector->ceilingheight)) - { - fixed_t origspeed = raise->vars[3]; + // Speed up as you get closer to the middle, then slow down again + distToNearestEndpoint = min(raise->sector->ceilingheight - raise->ceilingbottom, raise->ceilingtop - raise->sector->ceilingheight); + speed = FixedMul(origspeed, FixedDiv(distToNearestEndpoint, (raise->ceilingtop - raise->ceilingbottom) >> 5)); - // Slow down as you get closer to the bottom - raise->vars[3] = FixedMul(raise->vars[3],FixedDiv(raise->sector->ceilingheight - raise->vars[7], (raise->vars[5] - raise->vars[7])>>5)); + if (speed <= origspeed/16) + speed = origspeed/16; + else if (speed > origspeed) + speed = origspeed; - if (raise->vars[3] <= origspeed/16) - raise->vars[3] = origspeed/16; - else if (raise->vars[3] > origspeed) - raise->vars[3] = origspeed; - } - else - { - fixed_t origspeed = raise->vars[3]; - // Slow down as you get closer to the top - raise->vars[3] = FixedMul(raise->vars[3],FixedDiv(raise->vars[5] - raise->sector->ceilingheight, (raise->vars[5] - raise->vars[7])>>5)); - - if (raise->vars[3] <= origspeed/16) - raise->vars[3] = origspeed/16; - else if (raise->vars[3] > origspeed) - raise->vars[3] = origspeed; - } - - raise->vars[3] += raise->vars[10]; + speed += raise->extraspeed; res = T_MovePlane ( - raise->sector, // sector - raise->vars[3], // speed + raise->sector, // sector + speed, // speed ceilingdestination, // dest - 0, // crush - 1, // floor or ceiling (1 for ceiling) - raise->vars[8] // direction + 0, // crush + 1, // floor or ceiling (1 for ceiling) + direction // direction ); if (res == ok || res == pastdest) T_MovePlane ( - raise->sector, // sector - raise->vars[3], // speed + raise->sector, // sector + speed, // speed floordestination, // dest - 0, // crush - 0, // floor or ceiling (0 for floor) - raise->vars[8] // direction + 0, // crush + 0, // floor or ceiling (0 for floor) + direction // direction ); raise->sector->ceilspeed = 42; - raise->sector->floorspeed = raise->vars[3]*raise->vars[8]; + raise->sector->floorspeed = speed*direction; for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->args[0], i)) >= 0 ;) P_RecalcPrecipInSector(§ors[i]); From 607aeb3a525cad0e1fc1f5a957c6405aa105f09d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Apr 2020 10:29:29 +0200 Subject: [PATCH 022/326] Adapt setup of air bobbing FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 32 ++++++++++++++++++ src/p_setup.c | 14 ++++++++ src/p_spec.c | 34 ++++++++++++-------- src/p_spec.h | 7 ++++ 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 506dd1515..d7f904869 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1583,6 +1583,38 @@ udmf } } + 150 + { + title = "Air Bobbing"; + prefix = "(150)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Bobbing distance"; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Raise"; + 2 = "Require spindash"; + 4 = "Dynamic"; + } + } + arg3 + { + title = "Tangibility"; + type = 12; + enum = "tangibility"; + } + } + 170 { title = "Crumbling"; diff --git a/src/p_setup.c b/src/p_setup.c index 10b3ae80b..d8c65f1b8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2931,6 +2931,20 @@ static void P_ConvertBinaryMap(void) lines[i].special = 100; break; + case 150: //FOF: Air bobbing + case 151: //FOF: Air bobbing (adjustable) + case 152: //FOF: Reverse air bobbing (adjustable) + case 153: //FOF: Dynamically sinking platform + lines[i].args[0] = lines[i].tag; + lines[i].args[1] = (lines[i].special == 150) ? 16*FRACUNIT : P_AproxDistance(lines[i].dx, lines[i].dy); + if (lines[i].special == 152) + lines[i].args[2] |= TMFB_REVERSE; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] |= TMFB_SPINDASH; + if (lines[i].special == 153) + lines[i].args[3] |= TMFB_DYNAMIC; + lines[i].special = 150; + break; case 170: //FOF: Crumbling, respawn case 171: //FOF: Crumbling, no respawn case 172: //FOF: Crumbling, respawn, intangible from bottom diff --git a/src/p_spec.c b/src/p_spec.c index b564d4557..352282316 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6735,20 +6735,26 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 150: // Air bobbing platform - case 151: // Adjustable air bobbing platform - { - fixed_t dist = (lines[i].special == 150) ? 16*FRACUNIT : P_AproxDistance(lines[i].dx, lines[i].dy); - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - P_AddAirbob(lines[i].frontsector, lines + i, dist, false, !!(lines[i].flags & ML_NOCLIMB), false); - break; - } - case 152: // Adjustable air bobbing platform in reverse - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), true, !!(lines[i].flags & ML_NOCLIMB), false); - break; - case 153: // Dynamic Sinking Platform - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), false, !!(lines[i].flags & ML_NOCLIMB), true); + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; + + //Tangibility settings + if (lines[i].args[3] & TMFT_INTANGIBLETOP) + ffloorflags |= FF_REVERSEPLATFORM; + if (lines[i].args[3] & TMFT_INTANGIBLEBOTTOM) + ffloorflags |= FF_PLATFORM; + if (lines[i].args[3] & TMFT_DONTBLOCKPLAYER) + ffloorflags &= ~FF_BLOCKPLAYER; + if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) + ffloorflags &= ~FF_BLOCKOTHERS; + + //If player can enter it, cut inner walls + if (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE) + ffloorflags |= FF_CUTEXTRA|FF_EXTRA; + else + ffloorflags |= FF_CUTLEVEL; + + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddAirbob(lines[i].frontsector, lines + i, lines[i].args[1], !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); break; case 160: // Float/bob platform diff --git a/src/p_spec.h b/src/p_spec.h index 34f3c4068..cd3e8f737 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -54,6 +54,13 @@ typedef enum TMFW_GOOWATER = 1<<5, } textmapfofwater_t; +typedef enum +{ + TMFB_REVERSE = 1, + TMFB_SPINDASH = 1<<1, + TMFB_DYNAMIC = 1<<2, +} textmapfofbobbing_t; + typedef enum { TMFC_TRANSLUCENT = 1, From f6b67d8253dc37fa9654ec31b191534c8746f177 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Apr 2020 10:58:38 +0200 Subject: [PATCH 023/326] Some additions/fixes for air bobbing FOFs --- src/p_setup.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index d8c65f1b8..844e50972 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2937,12 +2937,21 @@ static void P_ConvertBinaryMap(void) case 153: //FOF: Dynamically sinking platform lines[i].args[0] = lines[i].tag; lines[i].args[1] = (lines[i].special == 150) ? 16*FRACUNIT : P_AproxDistance(lines[i].dx, lines[i].dy); + + //Flags if (lines[i].special == 152) lines[i].args[2] |= TMFB_REVERSE; if (lines[i].flags & ML_NOCLIMB) lines[i].args[2] |= TMFB_SPINDASH; if (lines[i].special == 153) - lines[i].args[3] |= TMFB_DYNAMIC; + lines[i].args[2] |= TMFB_DYNAMIC; + + //Tangibility + if (lines[i].flags & ML_EFFECT1) + lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; + lines[i].special = 150; break; case 170: //FOF: Crumbling, respawn From 7198cc46fd23947a914642ed619a4e4de38f6315 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Apr 2020 11:05:27 +0200 Subject: [PATCH 024/326] Adapt setup of water bobbing FOF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 19 ++++++++++++- src/p_setup.c | 10 +++++++ src/p_spec.c | 29 +++++++++++++++++--- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index d7f904869..96e711641 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -397,7 +397,7 @@ doom } 160 { - title = "Floating, Bobbing"; + title = "Water Bobbing"; prefix = "(160)"; } 190 @@ -1615,6 +1615,23 @@ udmf } } + 160 + { + title = "Water Bobbing"; + prefix = "(160)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Tangibility"; + type = 12; + enum = "tangibility"; + } + } + 170 { title = "Crumbling"; diff --git a/src/p_setup.c b/src/p_setup.c index 844e50972..30e572982 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2954,6 +2954,16 @@ static void P_ConvertBinaryMap(void) lines[i].special = 150; break; + case 160: //FOF: Water bobbing + lines[i].args[0] = lines[i].tag; + + //Tangibility + if (lines[i].flags & ML_EFFECT1) + lines[i].args[1] |= TMFT_DONTBLOCKOTHERS; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[1] |= TMFT_DONTBLOCKPLAYER; + + break; case 170: //FOF: Crumbling, respawn case 171: //FOF: Crumbling, no respawn case 172: //FOF: Crumbling, respawn, intangible from bottom diff --git a/src/p_spec.c b/src/p_spec.c index 352282316..86bc46f69 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6734,7 +6734,7 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; - case 150: // Air bobbing platform + case 150: // FOF (Air bobbing) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; //Tangibility settings @@ -6757,11 +6757,32 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddAirbob(lines[i].frontsector, lines + i, lines[i].args[1], !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); break; - case 160: // Float/bob platform - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB, secthinkers); + case 160: // FOF (Water bobbing) + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB; + + //Tangibility settings + if (lines[i].args[1] & TMFT_INTANGIBLETOP) + ffloorflags |= FF_REVERSEPLATFORM; + if (lines[i].args[1] & TMFT_INTANGIBLEBOTTOM) + ffloorflags |= FF_PLATFORM; + if (lines[i].args[1] & TMFT_DONTBLOCKPLAYER) + ffloorflags &= ~FF_BLOCKPLAYER; + if (lines[i].args[1] & TMFT_DONTBLOCKOTHERS) + ffloorflags &= ~FF_BLOCKOTHERS; + + //If player can enter it, render insides + if (lines[i].args[1] & TMFT_VISIBLEFROMINSIDE) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_BOTHPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_ALLSIDES; + } + + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; - case 170: // Crumbling platform + case 170: // FOF (Crumbling) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE; //Tangibility settings From d9f761b619209e142c85d2508843e9f4eedd94b6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Apr 2020 11:52:31 +0200 Subject: [PATCH 025/326] Adapt setup of rising FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 52 ++++++++++++++++ src/p_setup.c | 47 ++++++++++++++ src/p_spec.c | 64 +++++++++++++------- src/p_spec.h | 6 ++ 4 files changed, 148 insertions(+), 21 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 96e711641..1043c3bf2 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1661,6 +1661,58 @@ udmf } } } + + 190 + { + title = "Rising"; + prefix = "(190)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Visibility"; + type = 12; + enum + { + 1 = "Don't render planes"; + 2 = "Don't render sides"; + 4 = "Render insides"; + } + } + arg2 + { + title = "Tangibility"; + type = 12; + enum = "tangibility"; + } + arg3 + { + title = "Appearance"; + type = 12; + enum + { + 1 = "Translucent"; + 2 = "No shadow"; + } + } + arg4 + { + title = "Speed"; + } + arg5 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Lower"; + 2 = "Require spindash"; + } + } + } 200 { diff --git a/src/p_setup.c b/src/p_setup.c index 30e572982..06297fd52 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2998,6 +2998,53 @@ static void P_ConvertBinaryMap(void) lines[i].args[2] |= TMFC_FLOATBOB; lines[i].special = 170; break; + case 190: // FOF: Rising, solid, opaque, shadowcasting + case 191: // FOF: Rising, solid, opaque, non-shadowcasting + case 192: // FOF: Rising, solid, translucent + case 193: // FOF: Rising, solid, invisible + case 194: // FOF: Rising, intangible from bottom, opaque + case 195: // FOF: Rising, intangible from bottom, translucent + lines[i].args[0] = lines[i].tag; + + //Visibility + if (lines[i].special == 193) + lines[i].args[1] = TMFV_NOPLANES|TMFV_NOSIDES; + if (lines[i].special >= 194) + lines[i].args[1] = TMFV_TOGGLEINSIDES; + + //Tangibility + if (lines[i].flags & ML_EFFECT1) + lines[i].args[2] |= TMFT_DONTBLOCKOTHERS; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[2] |= TMFT_DONTBLOCKPLAYER; + if (lines[i].special >= 194) + lines[i].args[2] |= TMFT_INTANGIBLEBOTTOM; + + //Translucency + if (lines[i].special == 192 || lines[i].special == 195) + { + lines[i].args[3] |= TMFA_TRANSLUCENT; + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + else + lines[i].alpha = FRACUNIT/2; + } + + //Shadow? + if (lines[i].special != 190 && (lines[i].special <= 193 || lines[i].flags & ML_NOCLIMB)) + lines[i].args[3] |= TMFA_NOSHADE; + + //Speed + lines[i].args[4] = FixedDiv(P_AproxDistance(lines[i].dx, lines[i].dy), 4*FRACUNIT) >> FRACBITS; + + //Flags + if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[5] |= TMFR_REVERSE; + if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[5] |= TMFR_SPINDASH; + + lines[i].special = 190; + break; case 200: //FOF: Light block case 201: //FOF: Half light block lines[i].args[0] = lines[i].tag; diff --git a/src/p_spec.c b/src/p_spec.c index 5f07b9529..240015ad7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6825,34 +6825,56 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddAirbob(lines[i].frontsector, lines + i, 16*FRACUNIT, false, false, false); break; - case 190: // Rising Platform FOF (solid, opaque, shadows) - case 191: // Rising Platform FOF (solid, opaque, no shadows) - case 192: // Rising Platform TL block: FOF (solid, translucent) - case 193: // Rising Platform FOF (solid, invisible) - case 194: // Rising Platform 'Platform' - You can jump up through it - case 195: // Rising Platform Translucent "platform" + case 190: // FOF (Rising) { - fixed_t speed = FixedDiv(P_AproxDistance(lines[i].dx, lines[i].dy), 4*FRACUNIT); fixed_t ceilingtop = P_FindHighestCeilingSurrounding(lines[i].frontsector); fixed_t ceilingbottom = P_FindLowestCeilingSurrounding(lines[i].frontsector); - ffloorflags = FF_EXISTS|FF_SOLID; - if (lines[i].special != 193) - ffloorflags |= FF_RENDERALL; - if (lines[i].special <= 191) - ffloorflags |= FF_CUTLEVEL; - if (lines[i].special == 192 || lines[i].special == 195) - ffloorflags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; - if (lines[i].special >= 194) - ffloorflags |= FF_PLATFORM|FF_BOTHPLANES|FF_ALLSIDES; - if (lines[i].special != 190 && (lines[i].special <= 193 || lines[i].flags & ML_NOCLIMB)) - ffloorflags |= FF_NOSHADE; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; - P_AddRaiseThinker(lines[i].frontsector, &lines[i], speed, ceilingtop, ceilingbottom, !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); + //Visibility settings + if (lines[i].args[1] & TMFV_NOPLANES) + ffloorflags &= ~FF_RENDERPLANES; + if (lines[i].args[1] & TMFV_NOSIDES) + ffloorflags &= ~FF_RENDERSIDES; + if (lines[i].args[1] & TMFV_TOGGLEINSIDES) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_BOTHPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_ALLSIDES; + } + + //Tangibility settings + if (lines[i].args[2] & TMFT_INTANGIBLETOP) + ffloorflags |= FF_REVERSEPLATFORM; + if (lines[i].args[2] & TMFT_INTANGIBLEBOTTOM) + ffloorflags |= FF_PLATFORM; + if (lines[i].args[2] & TMFT_DONTBLOCKPLAYER) + ffloorflags &= ~FF_BLOCKPLAYER; + if (lines[i].args[2] & TMFT_DONTBLOCKOTHERS) + ffloorflags &= ~FF_BLOCKOTHERS; + + //Appearance settings + if ((lines[i].args[3] & TMFA_TRANSLUCENT) && (ffloorflags & FF_RENDERALL)) //Translucent + ffloorflags |= FF_TRANSLUCENT; + if (lines[i].args[3] & TMFA_NOSHADE) + ffloorflags |= FF_NOSHADE; + + //Cutting options + if (ffloorflags & FF_RENDERALL) + { + //If translucent or player can enter it, cut inner walls + if ((ffloorflags & FF_TRANSLUCENT) || (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE)) + ffloorflags |= FF_CUTEXTRA|FF_EXTRA; + else + ffloorflags |= FF_CUTLEVEL; + } + + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddRaiseThinker(lines[i].frontsector, &lines[i], lines[i].args[4] << FRACBITS, ceilingtop, ceilingbottom, !!(lines[i].args[5] & TMFR_REVERSE), !!(lines[i].args[5] & TMFR_SPINDASH)); break; } - case 200: // Light block ffloorflags = FF_EXISTS|FF_CUTSPRITES; if (!lines[i].args[1]) diff --git a/src/p_spec.h b/src/p_spec.h index cd3e8f737..83f7d9978 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -70,6 +70,12 @@ typedef enum TMFC_FLOATBOB = 1<<4, } textmapfofcrumbling_t; +typedef enum +{ + TMFR_REVERSE = 1, + TMFR_SPINDASH = 1<<1, +} textmapfofrising_t; + typedef enum { TMFM_BRICK = 1, From c702e697b610c37fd0a7a8da7468ef54b2c018aa Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Apr 2020 11:55:05 +0200 Subject: [PATCH 026/326] Fix bobbing FOF speed --- src/p_setup.c | 2 +- src/p_spec.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 06297fd52..91bce3e2e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2936,7 +2936,7 @@ static void P_ConvertBinaryMap(void) case 152: //FOF: Reverse air bobbing (adjustable) case 153: //FOF: Dynamically sinking platform lines[i].args[0] = lines[i].tag; - lines[i].args[1] = (lines[i].special == 150) ? 16*FRACUNIT : P_AproxDistance(lines[i].dx, lines[i].dy); + lines[i].args[1] = (lines[i].special == 150) ? 16 : (P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS); //Flags if (lines[i].special == 152) diff --git a/src/p_spec.c b/src/p_spec.c index 240015ad7..dcc6de697 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6754,7 +6754,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_CUTLEVEL; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - P_AddAirbob(lines[i].frontsector, lines + i, lines[i].args[1], !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); + P_AddAirbob(lines[i].frontsector, lines + i, lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); break; case 160: // FOF (Water bobbing) From 863ac48c9b16e7681aea7838eaa68955fb6775f4 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Apr 2020 11:56:29 +0200 Subject: [PATCH 027/326] Fix rising FOF speed --- src/p_setup.c | 2 +- src/p_spec.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 91bce3e2e..0aa9d3eab 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3035,7 +3035,7 @@ static void P_ConvertBinaryMap(void) lines[i].args[3] |= TMFA_NOSHADE; //Speed - lines[i].args[4] = FixedDiv(P_AproxDistance(lines[i].dx, lines[i].dy), 4*FRACUNIT) >> FRACBITS; + lines[i].args[4] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; //Flags if (lines[i].flags & ML_BLOCKMONSTERS) diff --git a/src/p_spec.c b/src/p_spec.c index dcc6de697..63abf8bc7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6038,7 +6038,7 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, fixed_t speed, raise->ceilingtop = ceilingtop; raise->ceilingbottom = ceilingbottom; - raise->basespeed = speed; + raise->basespeed = speed >> 2; if (lower) raise->flags |= RF_REVERSE; From 3a05d7b33351dcf030dbe9b02933b9458a183b62 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 1 May 2020 14:55:20 +0200 Subject: [PATCH 028/326] Fix ZB config typo --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 1043c3bf2..267e52845 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1717,7 +1717,7 @@ udmf 200 { title = "Light Block"; - prefix = "(200); + prefix = "(200)"; arg0 { title = "Target sector tag"; From f2011cc99b159adb1c97726164b671430fc4139b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 1 May 2020 14:59:08 +0200 Subject: [PATCH 029/326] More config fixes --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 267e52845..53a82aa0a 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1734,7 +1734,7 @@ udmf 202 { title = "Fog Block"; - prefix = "(202); + prefix = "(202)"; arg0 { title = "Target sector tag"; @@ -1777,7 +1777,7 @@ udmf 223 { title = "Intangible, Invisible"; - prefix = "(223); + prefix = "(223)"; arg0 { title = "Target sector tag"; @@ -1788,7 +1788,7 @@ udmf 250 { title = "Mario Block"; - prefix = "(250); + prefix = "(250)"; arg0 { title = "Target sector tag"; @@ -1809,7 +1809,7 @@ udmf 251 { title = "Thwomp Block"; - prefix = "(251); + prefix = "(251)"; arg0 { title = "Target sector tag"; @@ -1853,7 +1853,7 @@ udmf } arg2 { - title = "Translucent?" + title = "Translucent?"; type = 11; enum = "noyes"; } From d7363ff87a7c3e70aa4a5a35bdca7b8435835165 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 1 May 2020 19:07:29 +0200 Subject: [PATCH 030/326] Implement linedef type that adds a raise thinker to an FOF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 25 ++++++++++++++++++++ src/p_spec.c | 21 ++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 53a82aa0a..a356a2df7 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1916,6 +1916,31 @@ udmf enum = "yesno"; } } + + 260 + { + title = "Add Raise Thinker"; + prefix = "(260)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Destination height"; + } + arg3 + { + title = "Require spindash?"; + type = 11; + enum = "noyes"; + } + } } linedefexecmisc diff --git a/src/p_spec.c b/src/p_spec.c index 72b8ebbb4..128f84a73 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6450,6 +6450,7 @@ void P_SpawnSpecials(boolean fromnetsave) switch (lines[i].special) { INT32 s; + INT32 l; size_t sec; ffloortype_e ffloorflags; @@ -6968,6 +6969,26 @@ void P_SpawnSpecials(boolean fromnetsave) I_Error("Custom FOF (tag %d) found without a linedef back side!", lines[i].tag); break; + case 260: // Add raise thinker to FOF + if (udmf) + { + fixed_t destheight = lines[i].args[2] << FRACBITS; + fixed_t startheight, topheight, bottomheight; + + for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + startheight = lines[l].frontsector->ceilingheight; + topheight = max(startheight, destheight); + bottomheight = min(startheight, destheight); + + P_AddRaiseThinker(lines[l].frontsector, lines[l].args[0], lines[i].args[1] << FRACBITS, topheight, bottomheight, (destheight < startheight), !!(lines[i].args[3])); + } + } + break; + case 300: // Linedef executor (combines with sector special 974/975) and commands case 302: case 303: From cada0d2928838e0309e10d1dbf9a787e68f2f7e9 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 1 May 2020 19:29:19 +0200 Subject: [PATCH 031/326] Implement "add airbob thinker to FOF" linedef type --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 26 ++++++++++++++++++++ src/p_spec.c | 13 ++++++++++ 2 files changed, 39 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index a356a2df7..9b520a56e 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1941,6 +1941,32 @@ udmf enum = "noyes"; } } + + 261 + { + title = "Add Air Bobbing Thinker"; + prefix = "(261)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Bobbing distance"; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Raise"; + 2 = "Require spindash"; + 4 = "Dynamic"; + } + } + } } linedefexecmisc diff --git a/src/p_spec.c b/src/p_spec.c index 128f84a73..3b86857d2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6989,6 +6989,19 @@ void P_SpawnSpecials(boolean fromnetsave) } break; + case 261: // Add air bob thinker to FOF + if (udmf) + { + for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + P_AddAirbob(lines[l].frontsector, lines[l].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); + } + } + break; + case 300: // Linedef executor (combines with sector special 974/975) and commands case 302: case 303: From 7000c203a23966b6f44defd3f3017f83ac239d91 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 1 May 2020 19:41:52 +0200 Subject: [PATCH 032/326] Implement "add thwomp thinker to FOF" linedef type --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 24 ++++++++++++++++++++ src/p_spec.c | 15 ++++++++++++ 2 files changed, 39 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 9b520a56e..e46f533f7 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1967,6 +1967,30 @@ udmf } } } + + 262 + { + title = "Thwomp Block"; + prefix = "(262)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Falling speed"; + } + arg2 + { + title = "Rising speed"; + } + stringarg0 + { + title = "Crushing sound"; + type = 2; + } + } } linedefexecmisc diff --git a/src/p_spec.c b/src/p_spec.c index 3b86857d2..0526d34ff 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7002,6 +7002,21 @@ void P_SpawnSpecials(boolean fromnetsave) } break; + case 262: // Add thwomp thinker to FOF + if (udmf) + { + UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; + + for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + P_AddThwompThinker(lines[l].frontsector, lines[l].args[0], &lines[l], lines[i].args[1] << FRACBITS, lines[i].args[2] << FRACBITS, sound); + } + } + break; + case 300: // Linedef executor (combines with sector special 974/975) and commands case 302: case 303: From 3b0fc857c8a1881beb7499398b8c60ee95476c93 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 1 May 2020 19:43:44 +0200 Subject: [PATCH 033/326] UDB config fix --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index e46f533f7..8c093052f 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1970,12 +1970,12 @@ udmf 262 { - title = "Thwomp Block"; + title = "Add Thwomp Thinker"; prefix = "(262)"; arg0 { - title = "Target sector tag"; - type = 13; + title = "Control linedef tag"; + type = 15; } arg1 { From 312a2def3d8a2cc84f38dc298007feacd9888b1f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 2 May 2020 10:30:21 +0200 Subject: [PATCH 034/326] Implement "add laser thinker to FOF" linedef type --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 17 +++++++++++++++++ src/p_spec.c | 13 +++++++++++++ 2 files changed, 30 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 8c093052f..87ef6db33 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1991,6 +1991,23 @@ udmf type = 2; } } + + 263 + { + title = "Add Laser Thinker"; + prefix = "(263)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Damage bosses?"; + type = 11; + enum = "yesno"; + } + } } linedefexecmisc diff --git a/src/p_spec.c b/src/p_spec.c index a207b0fad..e5e50d73e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6999,6 +6999,19 @@ void P_SpawnSpecials(boolean fromnetsave) } break; + case 263: // Add laser thinker to FOF + if (udmf) + { + for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + P_AddLaserThinker(lines[l].args[0], lines + l, !!(lines[i].args[1])); + } + } + break; + case 300: // Linedef executor (combines with sector special 974/975) and commands case 302: case 303: From 538c81676bb8b08d7c3e806d933c213bb562717c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 2 May 2020 10:40:35 +0200 Subject: [PATCH 035/326] Recognize ML_EFFECT1 and ML_EFFECT2 on crumbling FOFs --- src/p_setup.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index 0aa9d3eab..c2f6e8e10 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2996,6 +2996,12 @@ static void P_ConvertBinaryMap(void) lines[i].args[2] |= TMFC_AIRBOB; if (lines[i].special >= 176 && lines[i].special <= 179) lines[i].args[2] |= TMFC_FLOATBOB; + + if (lines[i].flags & ML_EFFECT1) + lines[i].args[1] |= TMFT_DONTBLOCKOTHERS; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[1] |= TMFT_DONTBLOCKPLAYER; + lines[i].special = 170; break; case 190: // FOF: Rising, solid, opaque, shadowcasting From 21eccc15d8bfd129325e2688e46a8430ec1220da Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 2 May 2020 14:51:03 +0200 Subject: [PATCH 036/326] Bustable blocks: Forgot to adapt linedef executor triggering for pushables --- src/p_mobj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1e9346bf1..a13299c71 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1732,8 +1732,8 @@ static void P_PushableCheckBustables(mobj_t *mo) EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? - if (rover->master->flags & ML_EFFECT5) - P_LinedefExecute((INT16)(P_AproxDistance(rover->master->dx, rover->master->dy)>>FRACBITS), mo, node->m_sector); + if (rover->master->args[3] & TMFB_EXECUTOR) + P_LinedefExecute((INT16)(rover->master->args[4]), mo, node->m_sector); goto bustupdone; } From be92ed7091c29b473143d26b8105c6a1f99b73e0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 2 May 2020 20:24:17 +0200 Subject: [PATCH 037/326] UDB config fix --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 87ef6db33..cacff27e1 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1830,10 +1830,10 @@ udmf } } - 252 + 254 { title = "Bustable Block"; - prefix = "(252)"; + prefix = "(254)"; arg0 { title = "Target sector tag"; From 1f041496c7748f9d9430245af2843733e0631727 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 2 May 2020 21:19:55 +0200 Subject: [PATCH 038/326] Store bustable FOF data directly in ffloor_t instead of referring to master line --- src/dehacked.c | 18 ++++-- src/lua_maplib.c | 15 +++++ src/p_mobj.c | 57 ++++++++++--------- src/p_spec.c | 41 ++++++++++---- src/p_user.c | 144 ++++++++++++++++++++++++----------------------- src/r_defs.h | 26 +++++++-- 6 files changed, 182 insertions(+), 119 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index e9d029be0..3051b92d1 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9688,20 +9688,26 @@ struct { {"FF_FLOATBOB",FF_FLOATBOB}, ///< Floats on water and bobs if you step on it. {"FF_NORETURN",FF_NORETURN}, ///< Used with ::FF_CRUMBLE. Will not return to its original position after falling. {"FF_CRUMBLE",FF_CRUMBLE}, ///< Falls 2 seconds after being stepped on, and randomly brings all touching crumbling 3dfloors down with it, providing their master sectors share the same tag (allows crumble platforms above or below, to also exist). - {"FF_SHATTERBOTTOM",FF_SHATTERBOTTOM}, ///< Used with ::FF_BUSTUP. Like FF_SHATTER, but only breaks from the bottom. Good for springing up through rubble. + {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. {"FF_MARIO",FF_MARIO}, ///< Acts like a question block when hit from underneath. Goodie spawned at top is determined by master sector. - {"FF_BUSTUP",FF_BUSTUP}, ///< You can spin through/punch this block and it will crumble! {"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand! {"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top. {"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity. {"FF_INTANGIBLEFLATS",FF_INTANGIBLEFLATS}, ///< Both flats are intangible, but the sides are still solid. {"FF_INTANGABLEFLATS",FF_INTANGIBLEFLATS}, ///< Both flats are intangable, but the sides are still solid. - {"FF_SHATTER",FF_SHATTER}, ///< Used with ::FF_BUSTUP. Bustable on mere touch. - {"FF_SPINBUST",FF_SPINBUST}, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames. - {"FF_STRONGBUST",FF_STRONGBUST}, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee). {"FF_RIPPLE",FF_RIPPLE}, ///< Ripple the flats {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel - {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. + + // Bustable FOF type + {"BT_TOUCH",BT_TOUCH}, + {"BT_SPIN",BT_SPIN}, + {"BT_REGULAR",BT_REGULAR}, + {"BT_STRONG",BT_STRONG}, + + // Bustable FOF flags + {"BF_PUSHABLES",BF_PUSHABLES}, + {"BF_EXECUTOR",BF_EXECUTOR}, + {"BF_ONLYBOTTOM",BF_ONLYBOTTOM}, #ifdef HAVE_LUA_SEGS // Node flags diff --git a/src/lua_maplib.c b/src/lua_maplib.c index a3bdd9aa8..6ea82e2bf 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -187,6 +187,9 @@ enum ffloor_e { ffloor_next, ffloor_prev, ffloor_alpha, + ffloor_busttype, + ffloor_bustflags, + ffloor_busttag, }; static const char *const ffloor_opt[] = { @@ -205,6 +208,9 @@ static const char *const ffloor_opt[] = { "next", "prev", "alpha", + "busttype", + "bustflags", + "busttag", NULL}; #ifdef HAVE_LUA_SEGS @@ -1752,6 +1758,15 @@ static int ffloor_get(lua_State *L) case ffloor_alpha: lua_pushinteger(L, ffloor->alpha); return 1; + case ffloor_busttype: + lua_pushinteger(L, ffloor->busttype); + return 1; + case ffloor_bustflags: + lua_pushinteger(L, ffloor->bustflags); + return 1; + case ffloor_busttag: + lua_pushinteger(L, ffloor->busttag); + return 1; } return 0; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 8acd1bec4..62aa7770a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1691,8 +1691,7 @@ static void P_PushableCheckBustables(mobj_t *mo) if (!(rover->flags & FF_BUSTUP)) continue; - // Bustable by pushables? - if (!(rover->master->args[3] & TMFB_PUSHABLES)) + if (!(rover->bustflags & BF_PUSHABLES)) continue; if (rover->master->frontsector->crumblestate != CRUMBLE_NONE) @@ -1702,7 +1701,7 @@ static void P_PushableCheckBustables(mobj_t *mo) bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); // Height checks - if (rover->flags & FF_SHATTERBOTTOM) + if (rover->bustflags & BF_ONLYBOTTOM) { if (mo->z + mo->momz + mo->height < bottomheight) continue; @@ -1710,36 +1709,42 @@ static void P_PushableCheckBustables(mobj_t *mo) if (mo->z + mo->height > bottomheight) continue; } - else if (rover->flags & FF_SPINBUST) - { - if (mo->z + mo->momz > topheight) - continue; - - if (mo->z + mo->height < bottomheight) - continue; - } - else if (rover->flags & FF_SHATTER) - { - if (mo->z + mo->momz > topheight) - continue; - - if (mo->z + mo->momz + mo->height < bottomheight) - continue; - } else { - if (mo->z >= topheight) - continue; + switch (rover->busttype) + { + case BT_TOUCH: + if (mo->z + mo->momz > topheight) + continue; - if (mo->z + mo->height < bottomheight) - continue; + if (mo->z + mo->momz + mo->height < bottomheight) + continue; + + break; + case BT_SPIN: + if (mo->z + mo->momz > topheight) + continue; + + if (mo->z + mo->height < bottomheight) + continue; + + break; + default: + if (mo->z >= topheight) + continue; + + if (mo->z + mo->height < bottomheight) + continue; + + break; + } } EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? - if (rover->master->args[3] & TMFB_EXECUTOR) - P_LinedefExecute((INT16)(rover->master->args[4]), mo, node->m_sector); + if (rover->bustflags & BF_EXECUTOR) + P_LinedefExecute(rover->busttag, mo, node->m_sector); goto bustupdone; } @@ -2831,7 +2836,7 @@ static void P_CheckMarioBlocks(mobj_t *mo) if (*rover->bottomheight != mo->ceilingz) continue; - if (rover->flags & FF_SHATTERBOTTOM) // Brick block! + if (rover->flags & FF_GOOWATER) // Brick block! EV_CrumbleChain(node->m_sector, rover); else // Question block! EV_MarioBlock(rover, node->m_sector, mo); diff --git a/src/p_spec.c b/src/p_spec.c index adfe8b314..e17da83a8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5867,12 +5867,12 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f if (flags & FF_QUICKSAND) CheckForQuicksand = true; - if ((flags & FF_BUSTUP) || (flags & FF_SHATTER) || (flags & FF_SPINBUST)) + if (flags & FF_BUSTUP) CheckForBustableBlocks = true; if ((flags & FF_MARIO)) { - if (!(flags & FF_SHATTERBOTTOM)) // Don't change the textures of a brick block, just a question block + if (!(flags & FF_GOOWATER)) // Don't change the textures of a brick block, just a question block P_AddBlockThinker(sec2, master); CheckForMarioBlocks = true; } @@ -6875,7 +6875,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 250: // Mario Block ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO; if (lines[i].args[1] & TMFM_BRICK) - ffloorflags |= FF_SHATTERBOTTOM; + ffloorflags |= FF_GOOWATER; if (lines[i].args[1] & TMFM_INVISIBLE) ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); @@ -6891,36 +6891,53 @@ void P_SpawnSpecials(boolean fromnetsave) } case 254: // Bustable block + { + UINT8 busttype = BT_REGULAR; + UINT8 bustflags = 0; + ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP; //Bustable type switch (lines[i].args[1]) { case TMFB_TOUCH: - ffloorflags |= FF_SHATTER; + busttype = BT_TOUCH; break; case TMFB_SPIN: - ffloorflags |= FF_SPINBUST; + busttype = BT_SPIN; + break; + case TMFB_REGULAR: + busttype = BT_REGULAR; break; case TMFB_STRONG: - ffloorflags |= FF_STRONGBUST; - break; - default: + busttype = BT_STRONG; break; } + //Translucent? if (lines[i].args[2]) ffloorflags |= FF_TRANSLUCENT; + //Flags + if (lines[i].args[3] & TMFB_PUSHABLES) + bustflags |= BF_PUSHABLES; + if (lines[i].args[3] & TMFB_EXECUTOR) + bustflags |= BF_EXECUTOR; if (lines[i].args[3] & TMFB_ONLYBOTTOM) - ffloorflags |= FF_SHATTERBOTTOM; + bustflags |= BF_ONLYBOTTOM; - if (!(ffloorflags & FF_SHATTER) || ffloorflags & FF_SHATTERBOTTOM) + if (busttype != BT_TOUCH || bustflags & BF_ONLYBOTTOM) ffloorflags |= FF_BLOCKPLAYER; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) + { + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, ffloorflags, secthinkers); + fflr->busttype = busttype; + fflr->bustflags = bustflags; + fflr->busttag = lines[i].args[4]; + } break; - + } case 257: // Quicksand ffloorflags = FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES; if (!(lines[i].args[1])) diff --git a/src/p_user.c b/src/p_user.c index 562448151..14e466fde 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2543,58 +2543,56 @@ static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover) /*if (rover->master->frontsector->crumblestate != CRUMBLE_NONE) return false;*/ - // If it's an FF_SHATTER, you can break it just by touching it. - if (rover->flags & FF_SHATTER) - return true; - - // If it's an FF_SPINBUST, you can break it if you are in your spinning frames - // (either from jumping or spindashing). - if (rover->flags & FF_SPINBUST) + switch (rover->busttype) { + case BT_TOUCH: // Shatters on contact + return true; + case BT_SPIN: // Can be busted by spinning (either from jumping or spindashing) if ((player->pflags & PF_SPINNING) && !(player->pflags & PF_STARTDASH)) return true; if ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE)) return true; + + /* FALLTHRU */ + case BT_REGULAR: + // Spinning (and not jumping) + if ((player->pflags & PF_SPINNING) && !(player->pflags & PF_JUMPED)) + return true; + + // Super + if (player->powers[pw_super]) + return true; + + // Dashmode + if ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) && player->dashmode >= DASHMODE_THRESHOLD) + return true; + + // NiGHTS drill + if (player->pflags & PF_DRILLING) + return true; + + // Recording for Metal Sonic + if (metalrecording) + return true; + + /* FALLTHRU */ + case BT_STRONG: // Requires a "strong ability" + if (player->charability == CA_GLIDEANDCLIMB) + return true; + + if (player->pflags & PF_BOUNCING) + return true; + + if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY) + return true; + + if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) + return true; + + break; } - // Strong abilities can break even FF_STRONGBUST. - if (player->charability == CA_GLIDEANDCLIMB) - return true; - - if (player->pflags & PF_BOUNCING) - return true; - - if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY) - return true; - - if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) - return true; - - // Everyone else is out of luck. - if (rover->flags & FF_STRONGBUST) - return false; - - // Spinning (and not jumping) - if ((player->pflags & PF_SPINNING) && !(player->pflags & PF_JUMPED)) - return true; - - // Super - if (player->powers[pw_super]) - return true; - - // Dashmode - if ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) && player->dashmode >= DASHMODE_THRESHOLD) - return true; - - // NiGHTS drill - if (player->pflags & PF_DRILLING) - return true; - - // Recording for Metal Sonic - if (metalrecording) - return true; - return false; } @@ -2645,7 +2643,7 @@ static void P_CheckBustableBlocks(player_t *player) } // Height checks - if (rover->flags & FF_SHATTERBOTTOM) + if (rover->bustflags & BF_ONLYBOTTOM) { if (player->mo->z + player->mo->momz + player->mo->height < bottomheight) continue; @@ -2653,35 +2651,41 @@ static void P_CheckBustableBlocks(player_t *player) if (player->mo->z + player->mo->height > bottomheight) continue; } - else if (rover->flags & FF_SPINBUST) - { - if (player->mo->z + player->mo->momz > topheight) - continue; - - if (player->mo->z + player->mo->height < bottomheight) - continue; - } - else if (rover->flags & FF_SHATTER) - { - if (player->mo->z + player->mo->momz > topheight) - continue; - - if (player->mo->z + player->mo->momz + player->mo->height < bottomheight) - continue; - } else { - if (player->mo->z >= topheight) - continue; + switch (rover->busttype) + { + case BT_TOUCH: + if (player->mo->z + player->mo->momz > topheight) + continue; - if (player->mo->z + player->mo->height < bottomheight) - continue; + if (player->mo->z + player->mo->momz + player->mo->height < bottomheight) + continue; + + break; + case BT_SPIN: + if (player->mo->z + player->mo->momz > topheight) + continue; + + if (player->mo->z + player->mo->height < bottomheight) + continue; + + break; + default: + if (player->mo->z >= topheight) + continue; + + if (player->mo->z + player->mo->height < bottomheight) + continue; + + break; + } } // Impede the player's fall a bit - if (((rover->flags & FF_SPINBUST) || (rover->flags & FF_SHATTER)) && player->mo->z >= topheight) + if (((rover->busttype == BT_TOUCH) || (rover->busttype == BT_SPIN)) && player->mo->z >= topheight) player->mo->momz >>= 1; - else if (rover->flags & FF_SHATTER) + else if (rover->busttype == BT_TOUCH) { player->mo->momx >>= 1; player->mo->momy >>= 1; @@ -2693,8 +2697,8 @@ static void P_CheckBustableBlocks(player_t *player) EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? - if (rover->master->args[3] & TMFB_EXECUTOR) - P_LinedefExecute((INT16)(rover->master->args[4]), player->mo, node->m_sector); + if (rover->bustflags & BF_EXECUTOR) + P_LinedefExecute(rover->busttag, player->mo, node->m_sector); goto bustupdone; } @@ -8669,7 +8673,7 @@ static void P_MovePlayer(player_t *player) #endif // Look for blocks to bust up - // Because of FF_SHATTER, we should look for blocks constantly, + // Because of BT_TOUCH, we should look for blocks constantly, // not just when spinning or playing as Knuckles if (CheckForBustableBlocks) P_CheckBustableBlocks(player); diff --git a/src/r_defs.h b/src/r_defs.h index 73c6d0513..38f80954a 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -137,21 +137,32 @@ typedef enum FF_FLOATBOB = 0x40000, ///< Floats on water and bobs if you step on it. FF_NORETURN = 0x80000, ///< Used with ::FF_CRUMBLE. Will not return to its original position after falling. FF_CRUMBLE = 0x100000, ///< Falls 2 seconds after being stepped on, and randomly brings all touching crumbling 3dfloors down with it, providing their master sectors share the same tag (allows crumble platforms above or below, to also exist). - FF_SHATTERBOTTOM = 0x200000, ///< Used with ::FF_BUSTUP. Like FF_SHATTER, but only breaks from the bottom. Good for springing up through rubble. + FF_GOOWATER = 0x200000, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. FF_MARIO = 0x400000, ///< Acts like a question block when hit from underneath. Goodie spawned at top is determined by master sector. FF_BUSTUP = 0x800000, ///< You can spin through/punch this block and it will crumble! FF_QUICKSAND = 0x1000000, ///< Quicksand! FF_PLATFORM = 0x2000000, ///< You can jump up through this to the top. FF_REVERSEPLATFORM = 0x4000000, ///< A fall-through floor in normal gravity, a platform in reverse gravity. FF_INTANGIBLEFLATS = 0x6000000, ///< Both flats are intangible, but the sides are still solid. - FF_SHATTER = 0x8000000, ///< Used with ::FF_BUSTUP. Bustable on mere touch. - FF_SPINBUST = 0x10000000, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames. - FF_STRONGBUST = 0x20000000, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee). FF_RIPPLE = 0x40000000, ///< Ripple the flats FF_COLORMAPONLY = 0x80000000, ///< Only copy the colormap, not the lightlevel - FF_GOOWATER = FF_SHATTERBOTTOM, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. } ffloortype_e; +typedef enum +{ + BT_TOUCH, + BT_SPIN, + BT_REGULAR, + BT_STRONG, +} busttype_e; + +typedef enum +{ + BF_PUSHABLES = 1, + BF_EXECUTOR = 1<<1, + BF_ONLYBOTTOM = 1<<2, +} bustflags_e; + typedef struct ffloor_s { fixed_t *topheight; @@ -184,6 +195,11 @@ typedef struct ffloor_s INT32 alpha; tic_t norender; // for culling + // Only relevant for FF_BUSTUP + UINT8 busttype; + UINT8 bustflags; + INT16 busttag; + // these are saved for netgames, so do not let Lua touch these! ffloortype_e spawnflags; // flags the 3D floor spawned with INT32 spawnalpha; // alpha the 3D floor spawned with From 16936893058bab2a10c75e7026d87bdac9bd771d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 2 May 2020 21:50:49 +0200 Subject: [PATCH 039/326] Implement "make FOF bustable" linedef type --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 39 ++++++++++++ src/p_spec.c | 67 ++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index cacff27e1..d1696df2e 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2008,6 +2008,45 @@ udmf enum = "yesno"; } } + + 264 + { + title = "Make FOF Bustable"; + prefix = "(264)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Bustable type"; + type = 11; + enum + { + 0 = "Touch"; + 1 = "Spin"; + 2 = "Regular"; + 3 = "Strong"; + } + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Bustable by pushables"; + 2 = "Trigger linedef executor"; + 4 = "Only bustable from below"; + } + } + arg3 + { + title = "Linedef executor tag"; + type = 15; + } + } } linedefexecmisc diff --git a/src/p_spec.c b/src/p_spec.c index e17da83a8..2d8b1e48a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7267,6 +7267,73 @@ void P_SpawnSpecials(boolean fromnetsave) } } + // And another round, this time with all FOFs already created + for (i = 0; i < numlines; i++) + { + switch (lines[i].special) + { + INT32 s; + INT32 l; + + case 264: // Make FOF bustable + { + UINT8 busttype = BT_REGULAR; + UINT8 bustflags = 0; + + if (!udmf) + break; + + switch (lines[i].args[1]) + { + case TMFB_TOUCH: + busttype = BT_TOUCH; + break; + case TMFB_SPIN: + busttype = BT_SPIN; + break; + case TMFB_REGULAR: + busttype = BT_REGULAR; + break; + case TMFB_STRONG: + busttype = BT_STRONG; + break; + } + + if (lines[i].args[2] & TMFB_PUSHABLES) + bustflags |= BF_PUSHABLES; + if (lines[i].args[2] & TMFB_EXECUTOR) + bustflags |= BF_EXECUTOR; + if (lines[i].args[2] & TMFB_ONLYBOTTOM) + bustflags |= BF_ONLYBOTTOM; + + for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + for (s = -1; (s = P_FindSectorFromTag(lines[l].args[0], s)) >= 0 ;) + { + ffloor_t *rover; + + for (rover = sectors[s].ffloors; rover; rover = rover->next) + { + if (rover->master != lines + l) + continue; + + rover->flags |= FF_BUSTUP; + rover->busttype = busttype; + rover->bustflags = bustflags; + rover->busttag = lines[i].args[3]; + CheckForBustableBlocks = true; + break; + } + } + } + break; + } + } + } + // Allocate each list for (i = 0; i < numsectors; i++) if(secthinkers[i].thinkers) From 25219b614ed7d2fb3c071fa572578cdf194362cb Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 2 May 2020 22:07:42 +0200 Subject: [PATCH 040/326] Implement "Make FOF quicksand" linedef type --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 19 +++++++++++++++++++ src/lua_maplib.c | 10 ++++++++++ src/p_spec.c | 7 ++++++- src/p_user.c | 12 ++++-------- src/r_defs.h | 4 ++++ 5 files changed, 43 insertions(+), 9 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index d1696df2e..99ec6ec79 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2047,6 +2047,25 @@ udmf type = 15; } } + + 265 + { + title = "Make FOF Quicksand"; + prefix = "(265)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Sinking speed"; + } + arg2 + { + title = "Friction"; + } + } } linedefexecmisc diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 6ea82e2bf..282605b19 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -190,6 +190,8 @@ enum ffloor_e { ffloor_busttype, ffloor_bustflags, ffloor_busttag, + ffloor_sinkspeed, + ffloor_friction, }; static const char *const ffloor_opt[] = { @@ -211,6 +213,8 @@ static const char *const ffloor_opt[] = { "busttype", "bustflags", "busttag", + "sinkspeed", + "friction", NULL}; #ifdef HAVE_LUA_SEGS @@ -1767,6 +1771,12 @@ static int ffloor_get(lua_State *L) case ffloor_busttag: lua_pushinteger(L, ffloor->busttag); return 1; + case ffloor_sinkspeed: + lua_pushfixed(L, ffloor->sinkspeed); + return 1; + case ffloor_friction: + lua_pushfixed(L, ffloor->friction); + return 1; } return 0; } diff --git a/src/p_spec.c b/src/p_spec.c index 2d8b1e48a..a324e5a15 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6943,7 +6943,12 @@ void P_SpawnSpecials(boolean fromnetsave) if (!(lines[i].args[1])) ffloorflags |= FF_RIPPLE; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) + { + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, ffloorflags, secthinkers); + fflr->sinkspeed = abs(lines[i].args[2]) << (FRACBITS - 1); + fflr->fricttion = abs(lines[i].args[3]) << (FRACBITS - 6); + } break; case 258: // Laser block diff --git a/src/p_user.c b/src/p_user.c index 14e466fde..07fa00566 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2862,7 +2862,7 @@ bouncydone: static void P_CheckQuicksand(player_t *player) { ffloor_t *rover; - fixed_t sinkspeed, friction; + fixed_t sinkspeed; fixed_t topheight, bottomheight; if (!(player->mo->subsector->sector->ffloors && player->mo->momz <= 0)) @@ -2880,9 +2880,7 @@ static void P_CheckQuicksand(player_t *player) if (topheight >= player->mo->z && bottomheight < player->mo->z + player->mo->height) { - sinkspeed = abs(rover->master->args[2]) << (FRACBITS - 1); - - sinkspeed = FixedDiv(sinkspeed,TICRATE*FRACUNIT); + sinkspeed = FixedDiv(rover->sinkspeed,TICRATE*FRACUNIT); if (player->mo->eflags & MFE_VERTICALFLIP) { @@ -2909,10 +2907,8 @@ static void P_CheckQuicksand(player_t *player) P_PlayerHitFloor(player, false); } - friction = abs(rover->master->args[3]) << (FRACBITS - 6); - - player->mo->momx = FixedMul(player->mo->momx, friction); - player->mo->momy = FixedMul(player->mo->momy, friction); + player->mo->momx = FixedMul(player->mo->momx, rover->friction); + player->mo->momy = FixedMul(player->mo->momy, rover->friction); } } } diff --git a/src/r_defs.h b/src/r_defs.h index 38f80954a..508b1f062 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -200,6 +200,10 @@ typedef struct ffloor_s UINT8 bustflags; INT16 busttag; + // Only relevant for FF_QUICKSAND + fixed_t sinkspeed; + fixed_t friction; + // these are saved for netgames, so do not let Lua touch these! ffloortype_e spawnflags; // flags the 3D floor spawned with INT32 spawnalpha; // alpha the 3D floor spawned with From 0d4d7bfc3873e9f127c645cba635debd1e65a81f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 2 May 2020 23:00:22 +0200 Subject: [PATCH 041/326] Adapt custom FOF setup --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 48 +++++++++++++ src/p_setup.c | 14 ++++ src/p_spec.c | 74 ++++++++++++++++++-- src/r_defs.h | 6 ++ 4 files changed, 136 insertions(+), 6 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 99ec6ec79..54ddd17bb 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1917,6 +1917,54 @@ udmf } } + 259 + { + title = "Custom"; + prefix = "(259)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Exists"; + 2 = "Block player"; + 4 = "Block others"; + 8 = "Render sides"; + 16 = "Render planes"; + 32 = "Water"; + 64 = "No shadow"; + 128 = "Cut solid walls"; + 256 = "Cut extra walls"; + 512 = "Split sprites"; + 1024 = "Render inside planes"; + 2048 = "Extra"; + 4096 = "Translucent"; + 8192 = "Fog"; + 16384 = "Only render inside planes"; + 32768 = "Render inside walls"; + 65536 = "Only render inside walls"; + 131072 = "Double shadow"; + 262144 = "Water bobbing"; + 524288 = "Don't respawn"; + 1048576 = "Crumbling"; + 2097152 = "Goo water"; + 4194304 = "Mario block"; + 8388608 = "Bustable"; + 16777216 = "Quicksand"; + 33554432 = "Intangible from below"; + 67108864 = "Intangible from above"; + 1073741824 = "Ripple effect"; + 2147483648 = "Don't copy light level"; + } + } + } + 260 { title = "Add Raise Thinker"; diff --git a/src/p_setup.c b/src/p_setup.c index a3876888b..2b47464ff 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3157,6 +3157,20 @@ static void P_ConvertBinaryMap(void) if (lines[i].flags & ML_EFFECT1) lines[i].args[1] = 1; break; + case 259: //Custom FOF + if (lines[i].sidenum[1] == 0xffff) + I_Error("Custom FOF (tag %d) found without a linedef back side!", lines[i].tag); + + lines[i].args[0] = lines[i].tag; + lines[i].args[1] = sides[lines[i].sidenum[1]].toptexture; + if (lines[i].args[1] & FF_TRANSLUCENT) + { + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + else + lines[i].alpha = FRACUNIT/2; + } + break; case 443: //Call Lua function if (lines[i].text) { diff --git a/src/p_spec.c b/src/p_spec.c index a324e5a15..6040ac6eb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6947,7 +6947,7 @@ void P_SpawnSpecials(boolean fromnetsave) { ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, ffloorflags, secthinkers); fflr->sinkspeed = abs(lines[i].args[2]) << (FRACBITS - 1); - fflr->fricttion = abs(lines[i].args[3]) << (FRACBITS - 6); + fflr->friction = abs(lines[i].args[3]) << (FRACBITS - 6); } break; @@ -6957,13 +6957,39 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 259: // Custom FOF - if (lines[i].sidenum[1] != 0xffff) + for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) { - ffloortype_e fofflags = sides[lines[i].sidenum[1]].toptexture; - P_AddFakeFloorsByLine(i, fofflags, secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], secthinkers); + if (!udmf) // Ugly backwards compatibility stuff + { + if (lines[i].args[1] & FF_QUICKSAND) + { + fflr->sinkspeed = abs(lines[i].dx) >> 1; + fflr->friction = abs(lines[i].dy) >> 6; + } + if (lines[i].args[1] & FF_BUSTUP) + { + if (lines[i].args[1] & BFF_SHATTER) + fflr->busttype = BT_TOUCH; + else if (lines[i].args[1] & BFF_SPINBUST) + fflr->busttype = BT_SPIN; + else if (lines[i].args[1] & BFF_STRONGBUST) + fflr->busttype = BT_STRONG; + else + fflr->busttype = BT_REGULAR; + + if (lines[i].args[1] & BFF_SHATTERBOTTOM) + fflr->bustflags |= BF_ONLYBOTTOM; + if (lines[i].flags & ML_EFFECT4) + fflr->bustflags |= BF_PUSHABLES; + if (lines[i].flags & ML_EFFECT5) + { + fflr->bustflags |= BF_EXECUTOR; + fflr->busttag = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + } + } + } } - else - I_Error("Custom FOF (tag %d) found without a linedef back side!", lines[i].tag); break; case 260: // Add raise thinker to FOF @@ -7326,6 +7352,7 @@ void P_SpawnSpecials(boolean fromnetsave) continue; rover->flags |= FF_BUSTUP; + rover->spawnflags |= FF_BUSTUP; rover->busttype = busttype; rover->bustflags = bustflags; rover->busttag = lines[i].args[3]; @@ -7336,9 +7363,44 @@ void P_SpawnSpecials(boolean fromnetsave) } break; } + + case 265: // Make FOF quicksand + { + if (!udmf) + break; + + for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + for (s = -1; (s = P_FindSectorFromTag(lines[l].args[0], s)) >= 0 ;) + { + ffloor_t *rover; + + for (rover = sectors[s].ffloors; rover; rover = rover->next) + { + if (rover->master != lines + l) + continue; + + rover->flags |= FF_QUICKSAND; + rover->spawnflags |= FF_QUICKSAND; + rover->sinkspeed = abs(lines[i].args[1]) << (FRACBITS - 1); + rover->friction = abs(lines[i].args[2]) << (FRACBITS - 6); + CheckForQuicksand = true; + break; + } + } + } + break; + } } } + + + + // Allocate each list for (i = 0; i < numsectors; i++) if(secthinkers[i].thinkers) diff --git a/src/r_defs.h b/src/r_defs.h index 508b1f062..c791117ba 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -148,6 +148,12 @@ typedef enum FF_COLORMAPONLY = 0x80000000, ///< Only copy the colormap, not the lightlevel } ffloortype_e; +//Binary map format ffloor flags, for backwards compatibility only +#define BFF_SHATTERBOTTOM 0x200000 +#define BFF_SHATTER 0x8000000 +#define BFF_SPINBUST 0x10000000 +#define BFF_STRONGBUST 0x20000000 + typedef enum { BT_TOUCH, From f8f773d6e702988eb38b07ab1a683d9d1a1e43fa Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 2 May 2020 23:06:44 +0200 Subject: [PATCH 042/326] Remove "bustable" and "quicksand" flags from custom FOF in the UDB config, since you're not supposed to set them that way --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 2 -- 1 file changed, 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 54ddd17bb..0494ae544 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1955,8 +1955,6 @@ udmf 1048576 = "Crumbling"; 2097152 = "Goo water"; 4194304 = "Mario block"; - 8388608 = "Bustable"; - 16777216 = "Quicksand"; 33554432 = "Intangible from below"; 67108864 = "Intangible from above"; 1073741824 = "Ripple effect"; From 6949b70dbf63aec524134d550ca78e7f26c24678 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 2 May 2020 23:33:07 +0200 Subject: [PATCH 043/326] Remove temporary FOF setup code --- src/p_setup.c | 11 ----------- src/p_spec.c | 7 ------- 2 files changed, 18 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 2b47464ff..6551f3b4a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3309,17 +3309,6 @@ static void P_ConvertBinaryMap(void) case 908: //Translucent wall (90%) lines[i].alpha = ((909 - lines[i].special) << FRACBITS)/10; break; - default: - // \todo Remove once all FOF types are converted - if (lines[i].special >= 100 && lines[i].special < 300) - { - lines[i].args[0] = lines[i].tag; - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; - else - lines[i].alpha = FRACUNIT/2; - } - break; } } diff --git a/src/p_spec.c b/src/p_spec.c index 6040ac6eb..ddd09f173 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5807,13 +5807,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f if (sec2->hasslope) sec->hasslope = true; - // \todo Remove once all FOFs are adapted - if ((flags & FF_SOLID) && (master->flags & ML_EFFECT1)) // Block player only - flags &= ~FF_BLOCKOTHERS; - - if ((flags & FF_SOLID) && (master->flags & ML_EFFECT2)) // Block all BUT player - flags &= ~FF_BLOCKPLAYER; - fflr->spawnflags = fflr->flags = flags; fflr->master = master; fflr->norender = INFTICS; From 96a464c8817845c11955702c42ef642a2b55f722 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 3 May 2020 08:43:16 +0200 Subject: [PATCH 044/326] Move FOF modifier linedef type to the 70s range, to avoid being considered FOFs themselves --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 305 ++++++++++--------- src/p_spec.c | 126 ++++---- 2 files changed, 218 insertions(+), 213 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 0494ae544..2b70e9a7d 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1516,6 +1516,161 @@ udmf } } + fofmodifiers + { + title = "FOF Modifiers"; + + 70 + { + title = "Add Raise Thinker"; + prefix = "(70)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Destination height"; + } + arg3 + { + title = "Require spindash?"; + type = 11; + enum = "noyes"; + } + } + + 71 + { + title = "Add Air Bobbing Thinker"; + prefix = "(71)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Bobbing distance"; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Raise"; + 2 = "Require spindash"; + 4 = "Dynamic"; + } + } + } + + 72 + { + title = "Add Thwomp Thinker"; + prefix = "(72)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Falling speed"; + } + arg2 + { + title = "Rising speed"; + } + stringarg0 + { + title = "Crushing sound"; + type = 2; + } + } + + 73 + { + title = "Add Laser Thinker"; + prefix = "(73)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Damage bosses?"; + type = 11; + enum = "yesno"; + } + } + + 74 + { + title = "Make FOF Bustable"; + prefix = "(74)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Bustable type"; + type = 11; + enum + { + 0 = "Touch"; + 1 = "Spin"; + 2 = "Regular"; + 3 = "Strong"; + } + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Bustable by pushables"; + 2 = "Trigger linedef executor"; + 4 = "Only bustable from below"; + } + } + arg3 + { + title = "Linedef executor tag"; + type = 15; + } + } + + 75 + { + title = "Make FOF Quicksand"; + prefix = "(75)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Sinking speed"; + } + arg2 + { + title = "Friction"; + } + } + } + fof { title = "FOF"; @@ -1962,156 +2117,6 @@ udmf } } } - - 260 - { - title = "Add Raise Thinker"; - prefix = "(260)"; - arg0 - { - title = "Control linedef tag"; - type = 15; - } - arg1 - { - title = "Speed"; - } - arg2 - { - title = "Destination height"; - } - arg3 - { - title = "Require spindash?"; - type = 11; - enum = "noyes"; - } - } - - 261 - { - title = "Add Air Bobbing Thinker"; - prefix = "(261)"; - arg0 - { - title = "Control linedef tag"; - type = 15; - } - arg1 - { - title = "Bobbing distance"; - } - arg2 - { - title = "Flags"; - type = 12; - enum - { - 1 = "Raise"; - 2 = "Require spindash"; - 4 = "Dynamic"; - } - } - } - - 262 - { - title = "Add Thwomp Thinker"; - prefix = "(262)"; - arg0 - { - title = "Control linedef tag"; - type = 15; - } - arg1 - { - title = "Falling speed"; - } - arg2 - { - title = "Rising speed"; - } - stringarg0 - { - title = "Crushing sound"; - type = 2; - } - } - - 263 - { - title = "Add Laser Thinker"; - prefix = "(263)"; - arg0 - { - title = "Control linedef tag"; - type = 15; - } - arg1 - { - title = "Damage bosses?"; - type = 11; - enum = "yesno"; - } - } - - 264 - { - title = "Make FOF Bustable"; - prefix = "(264)"; - arg0 - { - title = "Control linedef tag"; - type = 15; - } - arg1 - { - title = "Bustable type"; - type = 11; - enum - { - 0 = "Touch"; - 1 = "Spin"; - 2 = "Regular"; - 3 = "Strong"; - } - } - arg2 - { - title = "Flags"; - type = 12; - enum - { - 1 = "Bustable by pushables"; - 2 = "Trigger linedef executor"; - 4 = "Only bustable from below"; - } - } - arg3 - { - title = "Linedef executor tag"; - type = 15; - } - } - - 265 - { - title = "Make FOF Quicksand"; - prefix = "(265)"; - arg0 - { - title = "Control linedef tag"; - type = 15; - } - arg1 - { - title = "Sinking speed"; - } - arg2 - { - title = "Friction"; - } - } } linedefexecmisc diff --git a/src/p_spec.c b/src/p_spec.c index ddd09f173..a7d773e20 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6617,6 +6617,67 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddPlaneDisplaceThinker(pd_both, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); break; + case 70: // Add raise thinker to FOF + if (udmf) + { + fixed_t destheight = lines[i].args[2] << FRACBITS; + fixed_t startheight, topheight, bottomheight; + + for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + startheight = lines[l].frontsector->ceilingheight; + topheight = max(startheight, destheight); + bottomheight = min(startheight, destheight); + + P_AddRaiseThinker(lines[l].frontsector, lines[l].args[0], lines[i].args[1] << FRACBITS, topheight, bottomheight, (destheight < startheight), !!(lines[i].args[3])); + } + } + break; + + case 71: // Add air bob thinker to FOF + if (udmf) + { + for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + P_AddAirbob(lines[l].frontsector, lines[l].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); + } + } + break; + + case 72: // Add thwomp thinker to FOF + if (udmf) + { + UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; + + for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + P_AddThwompThinker(lines[l].frontsector, lines[l].args[0], &lines[l], lines[i].args[1] << FRACBITS, lines[i].args[2] << FRACBITS, sound); + } + } + break; + + case 73: // Add laser thinker to FOF + if (udmf) + { + for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + P_AddLaserThinker(lines[l].args[0], lines + l, !!(lines[i].args[1])); + } + } + break; + case 100: // FOF (solid) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; @@ -6985,67 +7046,6 @@ void P_SpawnSpecials(boolean fromnetsave) } break; - case 260: // Add raise thinker to FOF - if (udmf) - { - fixed_t destheight = lines[i].args[2] << FRACBITS; - fixed_t startheight, topheight, bottomheight; - - for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) - { - if (lines[l].special < 100 || lines[l].special >= 300) - continue; - - startheight = lines[l].frontsector->ceilingheight; - topheight = max(startheight, destheight); - bottomheight = min(startheight, destheight); - - P_AddRaiseThinker(lines[l].frontsector, lines[l].args[0], lines[i].args[1] << FRACBITS, topheight, bottomheight, (destheight < startheight), !!(lines[i].args[3])); - } - } - break; - - case 261: // Add air bob thinker to FOF - if (udmf) - { - for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) - { - if (lines[l].special < 100 || lines[l].special >= 300) - continue; - - P_AddAirbob(lines[l].frontsector, lines[l].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); - } - } - break; - - case 262: // Add thwomp thinker to FOF - if (udmf) - { - UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; - - for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) - { - if (lines[l].special < 100 || lines[l].special >= 300) - continue; - - P_AddThwompThinker(lines[l].frontsector, lines[l].args[0], &lines[l], lines[i].args[1] << FRACBITS, lines[i].args[2] << FRACBITS, sound); - } - } - break; - - case 263: // Add laser thinker to FOF - if (udmf) - { - for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) - { - if (lines[l].special < 100 || lines[l].special >= 300) - continue; - - P_AddLaserThinker(lines[l].args[0], lines + l, !!(lines[i].args[1])); - } - } - break; - case 300: // Linedef executor (combines with sector special 974/975) and commands case 302: case 303: @@ -7299,7 +7299,7 @@ void P_SpawnSpecials(boolean fromnetsave) INT32 s; INT32 l; - case 264: // Make FOF bustable + case 74: // Make FOF bustable { UINT8 busttype = BT_REGULAR; UINT8 bustflags = 0; @@ -7357,7 +7357,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; } - case 265: // Make FOF quicksand + case 75: // Make FOF quicksand { if (!udmf) break; From 35e9e5b33ca75bb35eb76998008286bf76ef9fce Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 3 May 2020 09:13:14 +0200 Subject: [PATCH 045/326] Rearrange FOF flags and improve custom FOF backwards compatibility --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 4 ++-- src/p_setup.c | 1 + src/p_spec.c | 25 +++++++++++++------- src/r_defs.h | 10 ++------ 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 2b70e9a7d..a6682cd07 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2112,8 +2112,8 @@ udmf 4194304 = "Mario block"; 33554432 = "Intangible from below"; 67108864 = "Intangible from above"; - 1073741824 = "Ripple effect"; - 2147483648 = "Don't copy light level"; + 134217728 = "Ripple effect"; + 268435456 = "Don't copy light level"; } } } diff --git a/src/p_setup.c b/src/p_setup.c index 6551f3b4a..e21cc150c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3163,6 +3163,7 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = lines[i].tag; lines[i].args[1] = sides[lines[i].sidenum[1]].toptexture; + lines[i].args[2] = sides[lines[i].sidenum[1]].midtexture; if (lines[i].args[1] & FF_TRANSLUCENT) { if (sides[lines[i].sidenum[0]].toptexture > 0) diff --git a/src/p_spec.c b/src/p_spec.c index a7d773e20..77bc2407f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7023,16 +7023,23 @@ void P_SpawnSpecials(boolean fromnetsave) } if (lines[i].args[1] & FF_BUSTUP) { - if (lines[i].args[1] & BFF_SHATTER) - fflr->busttype = BT_TOUCH; - else if (lines[i].args[1] & BFF_SPINBUST) - fflr->busttype = BT_SPIN; - else if (lines[i].args[1] & BFF_STRONGBUST) - fflr->busttype = BT_STRONG; - else - fflr->busttype = BT_REGULAR; + switch (lines[i].args[2] % TMFB_ONLYBOTTOM) + { + case TMFB_TOUCH: + fflr->busttype = BT_TOUCH; + break; + case TMFB_SPIN: + fflr->busttype = BT_SPIN; + break; + case TMFB_REGULAR: + fflr->busttype = BT_REGULAR; + break; + case TMFB_STRONG: + fflr->busttype = BT_STRONG; + break; + } - if (lines[i].args[1] & BFF_SHATTERBOTTOM) + if (lines[i].args[2] & TMFB_ONLYBOTTOM) fflr->bustflags |= BF_ONLYBOTTOM; if (lines[i].flags & ML_EFFECT4) fflr->bustflags |= BF_PUSHABLES; diff --git a/src/r_defs.h b/src/r_defs.h index c791117ba..2f7b5622c 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -144,16 +144,10 @@ typedef enum FF_PLATFORM = 0x2000000, ///< You can jump up through this to the top. FF_REVERSEPLATFORM = 0x4000000, ///< A fall-through floor in normal gravity, a platform in reverse gravity. FF_INTANGIBLEFLATS = 0x6000000, ///< Both flats are intangible, but the sides are still solid. - FF_RIPPLE = 0x40000000, ///< Ripple the flats - FF_COLORMAPONLY = 0x80000000, ///< Only copy the colormap, not the lightlevel + FF_RIPPLE = 0x8000000, ///< Ripple the flats + FF_COLORMAPONLY = 0x10000000, ///< Only copy the colormap, not the lightlevel } ffloortype_e; -//Binary map format ffloor flags, for backwards compatibility only -#define BFF_SHATTERBOTTOM 0x200000 -#define BFF_SHATTER 0x8000000 -#define BFF_SPINBUST 0x10000000 -#define BFF_STRONGBUST 0x20000000 - typedef enum { BT_TOUCH, From 1aafc2f463e20eebfe929c9c7edf951ce891b9e7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 3 May 2020 12:44:30 +0200 Subject: [PATCH 046/326] Replace "bouncy FOF" sector type with "make FOF bouncy" linedef type --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 27 +++++++ extras/conf/udb/Includes/SRB222_sectors.cfg | 2 - src/dehacked.c | 13 ++-- src/lua_maplib.c | 15 ++-- src/p_mobj.c | 6 +- src/p_setup.c | 6 ++ src/p_spec.c | 81 +++++++++++++++----- src/p_user.c | 21 +++-- src/r_defs.h | 24 ++++-- 9 files changed, 142 insertions(+), 53 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index a6682cd07..fcf342e3d 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -130,6 +130,11 @@ doom title = "Bridge Thinker "; prefix = "(65)"; } + 76 + { + title = "Make FOF Bouncy"; + prefix = "(76)"; + } } polyobject @@ -1669,6 +1674,27 @@ udmf title = "Friction"; } } + + 76 + { + title = "Make FOF Bouncy"; + prefix = "(76)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Bounce strength"; + } + arg2 + { + title = "Dampen?"; + type = 11; + enum = "noyes"; + } + } } fof @@ -2114,6 +2140,7 @@ udmf 67108864 = "Intangible from above"; 134217728 = "Ripple effect"; 268435456 = "Don't copy light level"; + 536870912 = "Bouncy"; } } } diff --git a/extras/conf/udb/Includes/SRB222_sectors.cfg b/extras/conf/udb/Includes/SRB222_sectors.cfg index 5cc14ad0f..aebc8fa29 100644 --- a/extras/conf/udb/Includes/SRB222_sectors.cfg +++ b/extras/conf/udb/Includes/SRB222_sectors.cfg @@ -15,7 +15,6 @@ sectortypes 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)"; @@ -63,7 +62,6 @@ gen_sectortypes 12 = "Space Countdown"; 13 = "Ramp Sector (double step-up/down)"; 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy FOF"; } second diff --git a/src/dehacked.c b/src/dehacked.c index 3051b92d1..8edf0103d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9697,6 +9697,14 @@ struct { {"FF_INTANGABLEFLATS",FF_INTANGIBLEFLATS}, ///< Both flats are intangable, but the sides are still solid. {"FF_RIPPLE",FF_RIPPLE}, ///< Ripple the flats {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel + {"FF_BOUNCY",FF_BOUNCY}, ///< Bounces players + + // FOF special flags + {"FS_PUSHABLES",FS_PUSHABLES}, + {"FS_EXECUTOR",FS_EXECUTOR}, + {"FS_ONLYBOTTOM",FS_ONLYBOTTOM}, + {"FS_BUSTMASK",FS_BUSTMASK}, + {"FS_DAMPEN",FS_DAMPEN}, // Bustable FOF type {"BT_TOUCH",BT_TOUCH}, @@ -9704,11 +9712,6 @@ struct { {"BT_REGULAR",BT_REGULAR}, {"BT_STRONG",BT_STRONG}, - // Bustable FOF flags - {"BF_PUSHABLES",BF_PUSHABLES}, - {"BF_EXECUTOR",BF_EXECUTOR}, - {"BF_ONLYBOTTOM",BF_ONLYBOTTOM}, - #ifdef HAVE_LUA_SEGS // Node flags {"NF_SUBSECTOR",NF_SUBSECTOR}, // Indicate a leaf. diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 282605b19..e5de3de37 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -187,11 +187,12 @@ enum ffloor_e { ffloor_next, ffloor_prev, ffloor_alpha, + ffloor_specialflags, ffloor_busttype, - ffloor_bustflags, ffloor_busttag, ffloor_sinkspeed, ffloor_friction, + ffloor_bouncestrength, }; static const char *const ffloor_opt[] = { @@ -210,11 +211,12 @@ static const char *const ffloor_opt[] = { "next", "prev", "alpha", + "specialflags", "busttype", - "bustflags", "busttag", "sinkspeed", "friction", + "bouncestrength", NULL}; #ifdef HAVE_LUA_SEGS @@ -1762,12 +1764,12 @@ static int ffloor_get(lua_State *L) case ffloor_alpha: lua_pushinteger(L, ffloor->alpha); return 1; + case ffloor_specialflags: + lua_pushinteger(L, ffloor->specialflags); + return 1; case ffloor_busttype: lua_pushinteger(L, ffloor->busttype); return 1; - case ffloor_bustflags: - lua_pushinteger(L, ffloor->bustflags); - return 1; case ffloor_busttag: lua_pushinteger(L, ffloor->busttag); return 1; @@ -1777,6 +1779,9 @@ static int ffloor_get(lua_State *L) case ffloor_friction: lua_pushfixed(L, ffloor->friction); return 1; + case ffloor_bouncestrength: + lua_pushfixed(L, ffloor->bouncestrength); + return 1; } return 0; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 62aa7770a..97cc76667 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1691,7 +1691,7 @@ static void P_PushableCheckBustables(mobj_t *mo) if (!(rover->flags & FF_BUSTUP)) continue; - if (!(rover->bustflags & BF_PUSHABLES)) + if (!(rover->specialflags & FS_PUSHABLES)) continue; if (rover->master->frontsector->crumblestate != CRUMBLE_NONE) @@ -1701,7 +1701,7 @@ static void P_PushableCheckBustables(mobj_t *mo) bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); // Height checks - if (rover->bustflags & BF_ONLYBOTTOM) + if (rover->specialflags & FS_ONLYBOTTOM) { if (mo->z + mo->momz + mo->height < bottomheight) continue; @@ -1743,7 +1743,7 @@ static void P_PushableCheckBustables(mobj_t *mo) EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? - if (rover->bustflags & BF_EXECUTOR) + if (rover->specialflags & FS_EXECUTOR) P_LinedefExecute(rover->busttag, mo, node->m_sector); goto bustupdone; diff --git a/src/p_setup.c b/src/p_setup.c index e21cc150c..bd312652a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2800,6 +2800,12 @@ static void P_ConvertBinaryMap(void) { switch (lines[i].special) { + case 76: //Make FOF bouncy + lines[i].args[0] = lines[i].tag; + lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + if (lines[i].flags & ML_BOUNCY) + lines[i].args[2] = 1; + break; case 100: //FOF: solid, opaque, shadowcasting case 101: //FOF: solid, opaque, non-shadowcasting case 102: //FOF: solid, translucent diff --git a/src/p_spec.c b/src/p_spec.c index 77bc2407f..0262bc0e9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4443,7 +4443,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers break; case 13: // Ramp Sector (Increase step-up/down) case 14: // Non-Ramp Sector (Don't step-down) - case 15: // Bouncy Sector (FOF Control Only) + case 15: // Unused break; } @@ -6287,6 +6287,36 @@ static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flata } +static void P_MakeFOFBouncy(line_t *paramline, line_t *masterline) +{ + INT32 s; + + if (masterline->special < 100 || masterline->special >= 300) + return; + + for (s = -1; (s = P_FindSectorFromTag(masterline->args[0], s)) >= 0 ;) + { + ffloor_t *rover; + + for (rover = sectors[s].ffloors; rover; rover = rover->next) + { + if (rover->master != masterline) + continue; + + rover->flags |= FF_BOUNCY; + rover->spawnflags |= FF_BOUNCY; + rover->bouncestrength = (paramline->args[1]<< FRACBITS)/100; + if (paramline->args[2]) + rover->specialflags |= FS_DAMPEN; + else + rover->specialflags &= ~FS_DAMPEN; + CheckForBouncySector = true; + break; + } + } + +} + /** After the map has loaded, scans for specials that spawn 3Dfloors and * thinkers. * @@ -6327,10 +6357,6 @@ void P_SpawnSpecials(boolean fromnetsave) //Yes, this also affects other specials on the same sector. Sorry. sector->flags |= SF_TRIGGERSPECIAL_TOUCH; break; - - case 15: // Bouncy sector - CheckForBouncySector = true; - break; } // Process Section 2 @@ -6947,7 +6973,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 254: // Bustable block { UINT8 busttype = BT_REGULAR; - UINT8 bustflags = 0; + ffloorspecialflags_e bustflags = 0; ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP; @@ -6974,20 +7000,20 @@ void P_SpawnSpecials(boolean fromnetsave) //Flags if (lines[i].args[3] & TMFB_PUSHABLES) - bustflags |= BF_PUSHABLES; + bustflags |= FS_PUSHABLES; if (lines[i].args[3] & TMFB_EXECUTOR) - bustflags |= BF_EXECUTOR; + bustflags |= FS_EXECUTOR; if (lines[i].args[3] & TMFB_ONLYBOTTOM) - bustflags |= BF_ONLYBOTTOM; + bustflags |= FS_ONLYBOTTOM; - if (busttype != BT_TOUCH || bustflags & BF_ONLYBOTTOM) + if (busttype != BT_TOUCH || bustflags & FS_ONLYBOTTOM) ffloorflags |= FF_BLOCKPLAYER; for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) { ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, ffloorflags, secthinkers); fflr->busttype = busttype; - fflr->bustflags = bustflags; + fflr->specialflags = bustflags; fflr->busttag = lines[i].args[4]; } break; @@ -7040,12 +7066,12 @@ void P_SpawnSpecials(boolean fromnetsave) } if (lines[i].args[2] & TMFB_ONLYBOTTOM) - fflr->bustflags |= BF_ONLYBOTTOM; + fflr->specialflags |= FS_ONLYBOTTOM; if (lines[i].flags & ML_EFFECT4) - fflr->bustflags |= BF_PUSHABLES; + fflr->specialflags |= FS_PUSHABLES; if (lines[i].flags & ML_EFFECT5) { - fflr->bustflags |= BF_EXECUTOR; + fflr->specialflags |= FS_EXECUTOR; fflr->busttag = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; } } @@ -7309,7 +7335,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 74: // Make FOF bustable { UINT8 busttype = BT_REGULAR; - UINT8 bustflags = 0; + ffloorspecialflags_e bustflags = 0; if (!udmf) break; @@ -7331,11 +7357,11 @@ void P_SpawnSpecials(boolean fromnetsave) } if (lines[i].args[2] & TMFB_PUSHABLES) - bustflags |= BF_PUSHABLES; + bustflags |= FS_PUSHABLES; if (lines[i].args[2] & TMFB_EXECUTOR) - bustflags |= BF_EXECUTOR; + bustflags |= FS_EXECUTOR; if (lines[i].args[2] & TMFB_ONLYBOTTOM) - bustflags |= BF_ONLYBOTTOM; + bustflags |= FS_ONLYBOTTOM; for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) { @@ -7354,7 +7380,8 @@ void P_SpawnSpecials(boolean fromnetsave) rover->flags |= FF_BUSTUP; rover->spawnflags |= FF_BUSTUP; rover->busttype = busttype; - rover->bustflags = bustflags; + rover->specialflags &= ~FS_BUSTMASK; + rover->specialflags |= bustflags; rover->busttag = lines[i].args[3]; CheckForBustableBlocks = true; break; @@ -7394,6 +7421,22 @@ void P_SpawnSpecials(boolean fromnetsave) } break; } + + case 76: // Make FOF bouncy + { + if (udmf) + { + for (l = -1; (l = P_FindLineFromTag(lines[i].args[0], l)) >= 0 ;) + P_MakeFOFBouncy(lines + i, lines + l); + } + else + { + for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) + for (j = 0; (unsigned)j < sectors[s].linecount; j++) + P_MakeFOFBouncy(lines + i, sectors[s].lines[j]); + } + break; + } } } diff --git a/src/p_user.c b/src/p_user.c index 8d16b0e7a..26dfb7a91 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2643,7 +2643,7 @@ static void P_CheckBustableBlocks(player_t *player) } // Height checks - if (rover->bustflags & BF_ONLYBOTTOM) + if (rover->specialflags & FS_ONLYBOTTOM) { if (player->mo->z + player->mo->momz + player->mo->height < bottomheight) continue; @@ -2697,7 +2697,7 @@ static void P_CheckBustableBlocks(player_t *player) EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? - if (rover->bustflags & BF_EXECUTOR) + if (rover->specialflags & FS_EXECUTOR) P_LinedefExecute(rover->busttag, player->mo, node->m_sector); goto bustupdone; @@ -2743,14 +2743,13 @@ static void P_CheckBouncySectors(player_t *player) for (rover = node->m_sector->ffloors; rover; rover = rover->next) { - fixed_t bouncestrength; fixed_t topheight, bottomheight; if (!(rover->flags & FF_EXISTS)) continue; // FOFs should not be bouncy if they don't even "exist" - if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 15) - continue; // this sector type is required for FOFs to be bouncy + if (!(rover->flags & FF_BOUNCY)) + continue; topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); @@ -2761,13 +2760,13 @@ static void P_CheckBouncySectors(player_t *player) if (player->mo->z + player->mo->height < bottomheight) continue; - bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100; + //bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100; if (oldz < P_GetFOFTopZ(player->mo, node->m_sector, rover, oldx, oldy, NULL) && oldz + player->mo->height > P_GetFOFBottomZ(player->mo, node->m_sector, rover, oldx, oldy, NULL)) { - player->mo->momx = -FixedMul(player->mo->momx,bouncestrength); - player->mo->momy = -FixedMul(player->mo->momy,bouncestrength); + player->mo->momx = -FixedMul(player->mo->momx,rover->bouncestrength); + player->mo->momy = -FixedMul(player->mo->momy,rover->bouncestrength); if (player->pflags & PF_SPINNING) { @@ -2788,12 +2787,12 @@ static void P_CheckBouncySectors(player_t *player) if (slope) P_ReverseQuantizeMomentumToSlope(&momentum, slope); - newmom = momentum.z = -FixedMul(momentum.z,bouncestrength)/2; + newmom = momentum.z = -FixedMul(momentum.z,rover->bouncestrength)/2; - if (abs(newmom) < (bouncestrength*2)) + if (abs(newmom) < (rover->bouncestrength*2)) goto bouncydone; - if (!(rover->master->flags & ML_BOUNCY)) + if (!(rover->specialflags & FS_DAMPEN)) { if (newmom > 0) { diff --git a/src/r_defs.h b/src/r_defs.h index 2f7b5622c..160bcac2a 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -146,8 +146,18 @@ typedef enum FF_INTANGIBLEFLATS = 0x6000000, ///< Both flats are intangible, but the sides are still solid. FF_RIPPLE = 0x8000000, ///< Ripple the flats FF_COLORMAPONLY = 0x10000000, ///< Only copy the colormap, not the lightlevel + FF_BOUNCY = 0x20000000, ///< Bounces players } ffloortype_e; +typedef enum +{ + FS_PUSHABLES = 0x1, // FF_BUSTABLE: Bustable by pushables + FS_EXECUTOR = 0x2, // FF_BUSTABLE: Trigger linedef executor + FS_ONLYBOTTOM = 0x4, // FF_BUSTABLE: Only bustable from below + FS_BUSTMASK = 0x7, + FS_DAMPEN = 0x8, // FF_BOUNCY: Dampen bounce +} ffloorspecialflags_e; + typedef enum { BT_TOUCH, @@ -156,13 +166,6 @@ typedef enum BT_STRONG, } busttype_e; -typedef enum -{ - BF_PUSHABLES = 1, - BF_EXECUTOR = 1<<1, - BF_ONLYBOTTOM = 1<<2, -} bustflags_e; - typedef struct ffloor_s { fixed_t *topheight; @@ -195,15 +198,20 @@ typedef struct ffloor_s INT32 alpha; tic_t norender; // for culling + // Flags that are only relevant for special ffloor types + ffloorspecialflags_e specialflags; + // Only relevant for FF_BUSTUP UINT8 busttype; - UINT8 bustflags; INT16 busttag; // Only relevant for FF_QUICKSAND fixed_t sinkspeed; fixed_t friction; + // Only relevant for FF_BOUNCY + fixed_t bouncestrength; + // these are saved for netgames, so do not let Lua touch these! ffloortype_e spawnflags; // flags the 3D floor spawned with INT32 spawnalpha; // alpha the 3D floor spawned with From a79862285e1b62edc0e96cf00a442e53407448ea Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 08:16:50 +0200 Subject: [PATCH 047/326] Step 1 in refactoring FOF alpha setup: Pass alpha value to FOF adding functions as a parameter --- src/p_spec.c | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 5cbb4727c..6d260758d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -117,7 +117,7 @@ static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, ext static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); -static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinkerlist_t *secthinkers); +static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorflags, thinkerlist_t *secthinkers); static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec); static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer); static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee, UINT8 reverse); @@ -5617,12 +5617,13 @@ static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *fflr) * \param sec Target sector. * \param sec2 Control sector. * \param master Control linedef. + * \param alpha Alpha value (0-255). * \param flags Options affecting this 3Dfloor. * \param secthinkers List of relevant thinkers sorted by sector. May be NULL. * \return Pointer to the new 3Dfloor. * \sa P_AddFFloor, P_AddFakeFloorsByLine, P_SpawnSpecials */ -static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, ffloortype_e flags, thinkerlist_t *secthinkers) +static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, INT32 alpha, ffloortype_e flags, thinkerlist_t *secthinkers) { ffloor_t *fflr; thinker_t *th; @@ -5743,7 +5744,12 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f else th = th->next; } - fflr->alpha = (flags & FF_TRANSLUCENT) ? (master->alpha * 0xff) >> FRACBITS : 0xff; + fflr->alpha = max(0, min(0xff, alpha)); + if (fflr->alpha == 0xff) + { + fflr->flags |= FF_TRANSLUCENT; + fflr->spawnflags = fflr->flags; + } fflr->spawnalpha = fflr->alpha; // save for netgames if (flags & FF_QUICKSAND) @@ -6633,7 +6639,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_CUTLEVEL; } - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); break; case 120: // FOF (water) @@ -6650,7 +6656,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_RIPPLE; if (lines[i].args[1] & TMFW_GOOWATER) ffloorflags |= FF_GOOWATER; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); break; case 150: // FOF (Air bobbing) @@ -6672,7 +6678,7 @@ void P_SpawnSpecials(boolean fromnetsave) else ffloorflags |= FF_CUTLEVEL; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); break; @@ -6698,7 +6704,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_ALLSIDES; } - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); break; case 170: // FOF (Crumbling) @@ -6739,7 +6745,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_ALLSIDES; } - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); if (lines[i].args[2] & TMFC_AIRBOB) P_AddAirbob(lines[i].frontsector, lines[i].args[0], 16*FRACUNIT, false, false, false); break; @@ -6790,7 +6796,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_CUTLEVEL; } - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); P_AddRaiseThinker(lines[i].frontsector, lines[i].args[0], lines[i].args[4] << FRACBITS, ceilingtop, ceilingbottom, !!(lines[i].args[5] & TMFR_REVERSE), !!(lines[i].args[5] & TMFR_SPINDASH)); break; } @@ -6798,7 +6804,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_CUTSPRITES; if (!lines[i].args[1]) ffloorflags |= FF_DOUBLESHADOW; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); break; case 202: // Fog @@ -6807,7 +6813,7 @@ void P_SpawnSpecials(boolean fromnetsave) // SoM: Because it's fog, check for an extra colormap and set the fog flag... if (sectors[sec].extra_colormap) sectors[sec].extra_colormap->flags = CMF_FOG; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); break; case 220: //Intangible @@ -6832,11 +6838,11 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[2] & TMFA_NOSHADE) ffloorflags |= FF_NOSHADE; - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); break; case 223: // FOF (intangible, invisible) - for combining specials in a sector - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_NOSHADE, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_NOSHADE, secthinkers); break; case 250: // Mario Block @@ -6846,14 +6852,14 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[1] & TMFM_INVISIBLE) ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); break; case 251: // A THWOMP! { UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; P_AddThwompThinker(lines[i].frontsector, lines[i].args[0], &lines[i], lines[i].args[1] << FRACBITS, lines[i].args[2] << FRACBITS, sound); - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); break; } @@ -6898,7 +6904,7 @@ void P_SpawnSpecials(boolean fromnetsave) for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, ffloorflags, secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); fflr->busttype = busttype; fflr->specialflags = bustflags; fflr->busttag = lines[i].args[4]; @@ -6912,7 +6918,7 @@ void P_SpawnSpecials(boolean fromnetsave) for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, ffloorflags, secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, ffloorflags, secthinkers); fflr->sinkspeed = abs(lines[i].args[2]) << (FRACBITS - 1); fflr->friction = abs(lines[i].args[3]) << (FRACBITS - 6); } @@ -6920,13 +6926,13 @@ void P_SpawnSpecials(boolean fromnetsave) case 258: // Laser block P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[1])); - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT, secthinkers); + P_AddFakeFloorsByLine(i, (lines[i].alpha * 0xff) >> FRACBITS, FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT, secthinkers); break; case 259: // Custom FOF for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, (lines[i].args[1] & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, lines[i].args[1], secthinkers); if (!udmf) // Ugly backwards compatibility stuff { if (lines[i].args[1] & FF_QUICKSAND) @@ -7368,18 +7374,19 @@ void P_SpawnSpecials(boolean fromnetsave) /** Adds 3Dfloors as appropriate based on a common control linedef. * * \param line Control linedef to use. + * \param alpha Alpha value (0-255). * \param ffloorflags 3Dfloor flags to use. * \param secthkiners Lists of thinkers sorted by sector. May be NULL. * \sa P_SpawnSpecials, P_AddFakeFloor * \author Graue */ -static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinkerlist_t *secthinkers) +static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorflags, thinkerlist_t *secthinkers) { INT32 s; size_t sec = sides[*lines[line].sidenum].sector-sectors; for (s = -1; (s = P_FindSectorFromTag(lines[line].args[0], s)) >= 0 ;) - P_AddFakeFloor(§ors[s], §ors[sec], lines+line, ffloorflags, secthinkers); + P_AddFakeFloor(§ors[s], §ors[sec], lines+line, alpha, ffloorflags, secthinkers); } /* From 8dd3c78b053162df58bfb107b1b729bfc7ecb662 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 08:27:10 +0200 Subject: [PATCH 048/326] Add FOF flag for splat flat rendering --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 1 + src/dehacked.c | 1 + src/p_spec.c | 2 ++ src/r_defs.h | 1 + src/r_plane.c | 2 +- 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 4f45c12c1..cdf9bdd40 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2186,6 +2186,7 @@ udmf 134217728 = "Ripple effect"; 268435456 = "Don't copy light level"; 536870912 = "Bouncy"; + 1073741824 = "Cut cyan flat pixels"; } } } diff --git a/src/dehacked.c b/src/dehacked.c index b416eed4d..a55362ec0 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9820,6 +9820,7 @@ struct { {"FF_RIPPLE",FF_RIPPLE}, ///< Ripple the flats {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel {"FF_BOUNCY",FF_BOUNCY}, ///< Bounces players + {"FF_SPLAT",FF_SPLAT}, ///< Use splat flat renderer (treat cyan pixels as invisible) // FOF special flags {"FS_PUSHABLES",FS_PUSHABLES}, diff --git a/src/p_spec.c b/src/p_spec.c index 6d260758d..b39594ee7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5697,6 +5697,8 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I if (sec2->hasslope) sec->hasslope = true; + if (!udmf && master->flags & ML_EFFECT6) + fflr->flags |= FF_SPLAT; //TODO: Temporary fflr->spawnflags = fflr->flags = flags; fflr->master = master; fflr->norender = INFTICS; diff --git a/src/r_defs.h b/src/r_defs.h index ff65a5dc5..0e0adb7c6 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -147,6 +147,7 @@ typedef enum FF_RIPPLE = 0x8000000, ///< Ripple the flats FF_COLORMAPONLY = 0x10000000, ///< Only copy the colormap, not the lightlevel FF_BOUNCY = 0x20000000, ///< Bounces players + FF_SPLAT = 0x40000000, ///< Use splat flat renderer (treat cyan pixels as invisible) } ffloortype_e; typedef enum diff --git a/src/r_plane.c b/src/r_plane.c index 92795d0fb..7f91d7465 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -984,7 +984,7 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->ffloor->flags & FF_TRANSLUCENT) { - spanfunctype = (pl->ffloor->master->flags & ML_EFFECT6) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS; + spanfunctype = (pl->ffloor->flags & FF_SPLAT) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS; // Hacked up support for alpha value in software mode Tails 09-24-2002 if (pl->ffloor->alpha < 12) From 1ad8f75538dc11b282a4a4e7b8a01f055bd2311a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 09:00:06 +0200 Subject: [PATCH 049/326] Revamp alpha setup for water FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 17 +++++++++------ src/p_setup.c | 22 ++++++++++++-------- src/p_spec.c | 18 ++++++++-------- src/p_spec.h | 12 +++++------ 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index cdf9bdd40..884865f95 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1794,17 +1794,22 @@ udmf type = 13; } arg1 + { + title = "Alpha"; + default = 128; + } + arg2 { title = "Flags"; type = 12; enum { - 1 = "Opaque"; - 2 = "Don't render sides"; - 4 = "Render separate light level"; - 8 = "Use target light level"; - 16 = "No ripple effect"; - 32 = "Goo physics"; + 1 = "Don't render sides"; + 2 = "Render separate light level"; + 4 = "Use target light level"; + 8 = "No ripple effect"; + 16 = "Goo physics"; + 32 = "Cut cyan flat pixels"; } } } diff --git a/src/p_setup.c b/src/p_setup.c index 26132251c..0ef1a9793 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3056,32 +3056,36 @@ static void P_ConvertBinaryMap(void) case 125: //FOF: goo water, translucent, no sides lines[i].args[0] = lines[i].tag; - //Opaque? + //Alpha if (lines[i].special == 120 || lines[i].special == 122) - lines[i].args[1] |= TMFW_OPAQUE; + lines[i].args[1] = 255; else { if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else - lines[i].alpha = FRACUNIT/2; + lines[i].args[1] = 128; } //No sides? if (lines[i].special == 122 || lines[i].special == 123 || lines[i].special == 125) - lines[i].args[1] |= TMFW_NOSIDES; + lines[i].args[2] |= TMFW_NOSIDES; //Flags if (lines[i].flags & ML_NOCLIMB) - lines[i].args[1] |= TMFW_DOUBLESHADOW; + lines[i].args[2] |= TMFW_DOUBLESHADOW; if (lines[i].flags & ML_EFFECT4) - lines[i].args[1] |= TMFW_COLORMAPONLY; + lines[i].args[2] |= TMFW_COLORMAPONLY; if (!(lines[i].flags & ML_EFFECT5)) - lines[i].args[1] |= TMFW_NORIPPLE; + lines[i].args[2] |= TMFW_NORIPPLE; //Goo? if (lines[i].special >= 124) - lines[i].args[1] |= TMFW_GOOWATER; + lines[i].args[2] |= TMFW_GOOWATER; + + //Splat rendering? + if (lines[i].flags & ML_EFFECT6) + lines[i].args[2] |= TMFW_SPLAT; lines[i].special = 120; break; diff --git a/src/p_spec.c b/src/p_spec.c index b39594ee7..84d399a55 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5747,7 +5747,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I } fflr->alpha = max(0, min(0xff, alpha)); - if (fflr->alpha == 0xff) + if (fflr->alpha < 0xff) { fflr->flags |= FF_TRANSLUCENT; fflr->spawnflags = fflr->flags; @@ -6646,19 +6646,19 @@ void P_SpawnSpecials(boolean fromnetsave) case 120: // FOF (water) ffloorflags = FF_EXISTS|FF_RENDERPLANES|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - if (!(lines[i].args[1] & TMFW_OPAQUE)) - ffloorflags |= FF_TRANSLUCENT; - if (!(lines[i].args[1] & TMFW_NOSIDES)) + if (!(lines[i].args[2] & TMFW_NOSIDES)) ffloorflags |= FF_RENDERSIDES|FF_ALLSIDES; - if (lines[i].args[1] & TMFW_DOUBLESHADOW) + if (lines[i].args[2] & TMFW_DOUBLESHADOW) ffloorflags |= FF_DOUBLESHADOW; - if (lines[i].args[1] & TMFW_COLORMAPONLY) + if (lines[i].args[2] & TMFW_COLORMAPONLY) ffloorflags |= FF_COLORMAPONLY; - if (!(lines[i].args[1] & TMFW_NORIPPLE)) + if (!(lines[i].args[2] & TMFW_NORIPPLE)) ffloorflags |= FF_RIPPLE; - if (lines[i].args[1] & TMFW_GOOWATER) + if (lines[i].args[2] & TMFW_GOOWATER) ffloorflags |= FF_GOOWATER; - P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); + if (lines[i].args[2] & TMFW_SPLAT) + ffloorflags |= FF_SPLAT; + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); break; case 150: // FOF (Air bobbing) diff --git a/src/p_spec.h b/src/p_spec.h index ef69e83ea..16f992780 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -46,12 +46,12 @@ typedef enum typedef enum { - TMFW_OPAQUE = 1, - TMFW_NOSIDES = 1<<1, - TMFW_DOUBLESHADOW = 1<<2, - TMFW_COLORMAPONLY = 1<<3, - TMFW_NORIPPLE = 1<<4, - TMFW_GOOWATER = 1<<5, + TMFW_NOSIDES = 1, + TMFW_DOUBLESHADOW = 1<<1, + TMFW_COLORMAPONLY = 1<<2, + TMFW_NORIPPLE = 1<<3, + TMFW_GOOWATER = 1<<4, + TMFW_SPLAT = 1<<5, } textmapfofwater_t; typedef enum From ac549eddeb4d6b145a29485c57585a0649aedbc1 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 09:28:41 +0200 Subject: [PATCH 050/326] Revamp alpha setup for crumbling FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 17 +++++---- src/p_setup.c | 37 ++++++++++++-------- src/p_spec.c | 26 +++++++------- src/p_spec.h | 10 +++--- 4 files changed, 51 insertions(+), 39 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 884865f95..95986acc7 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1873,22 +1873,27 @@ udmf type = 13; } arg1 + { + title = "Alpha"; + default = 255; + } + arg2 { title = "Tangibility"; type = 12; enum = "tangibility"; } - arg2 + arg3 { title = "Flags"; type = 12; enum { - 1 = "Translucent"; - 2 = "No shadow"; - 4 = "No respawn"; - 8 = "Air bobbing"; - 16 = "Float on water"; + 1 = "No shadow"; + 2 = "No respawn"; + 4 = "Air bobbing"; + 8 = "Float on water"; + 16 = "Cut cyan flat pixels"; } } } diff --git a/src/p_setup.c b/src/p_setup.c index 0ef1a9793..e0f64fcba 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3180,31 +3180,38 @@ static void P_ConvertBinaryMap(void) case 179: //FOF: Crumbling, no respawn, floating case 180: //FOF: Crumbling, respawn, air bobbing lines[i].args[0] = lines[i].tag; - if (lines[i].special >= 172 && lines[i].special <= 175) - { - lines[i].args[1] |= TMFT_INTANGIBLEBOTTOM; - if (lines[i].flags & ML_NOCLIMB) - lines[i].args[2] |= TMFC_NOSHADE; - } + + //Alpha if (lines[i].special >= 174 && lines[i].special <= 175) { - lines[i].args[2] |= TMFC_TRANSLUCENT; if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else - lines[i].alpha = FRACUNIT/2; + lines[i].args[1] = 128; } + else + lines[i].args[1] = 255; + + if (lines[i].special >= 172 && lines[i].special <= 175) + { + lines[i].args[2] |= TMFT_INTANGIBLEBOTTOM; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[3] |= TMFC_NOSHADE; + } + if (lines[i].special % 2 == 1) - lines[i].args[2] |= TMFC_NORETURN; + lines[i].args[3] |= TMFC_NORETURN; if (lines[i].special == 176 || lines[i].special == 177 || lines[i].special == 180) - lines[i].args[2] |= TMFC_AIRBOB; + lines[i].args[3] |= TMFC_AIRBOB; if (lines[i].special >= 176 && lines[i].special <= 179) - lines[i].args[2] |= TMFC_FLOATBOB; + lines[i].args[3] |= TMFC_FLOATBOB; + if (lines[i].flags & ML_EFFECT6) + lines[i].args[3] |= TMFC_SPLAT; if (lines[i].flags & ML_EFFECT1) - lines[i].args[1] |= TMFT_DONTBLOCKOTHERS; + lines[i].args[2] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[1] |= TMFT_DONTBLOCKPLAYER; + lines[i].args[2] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 170; break; @@ -3338,7 +3345,7 @@ static void P_ConvertBinaryMap(void) //Translucency if (lines[i].special == 253 || lines[i].special == 256) { - lines[i].args[2] = TMFC_TRANSLUCENT; + lines[i].args[2] = 1; if (sides[lines[i].sidenum[0]].toptexture > 0) lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; else diff --git a/src/p_spec.c b/src/p_spec.c index 84d399a55..2e7290271 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6713,33 +6713,33 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE; //Tangibility settings - if (lines[i].args[1] & TMFT_INTANGIBLETOP) + if (lines[i].args[2] & TMFT_INTANGIBLETOP) ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[1] & TMFT_INTANGIBLEBOTTOM) + if (lines[i].args[2] & TMFT_INTANGIBLEBOTTOM) ffloorflags |= FF_PLATFORM; - if (lines[i].args[1] & TMFT_DONTBLOCKPLAYER) + if (lines[i].args[2] & TMFT_DONTBLOCKPLAYER) ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[1] & TMFT_DONTBLOCKOTHERS) + if (lines[i].args[2] & TMFT_DONTBLOCKOTHERS) ffloorflags &= ~FF_BLOCKOTHERS; //Flags - if (lines[i].args[2] & TMFC_TRANSLUCENT) - ffloorflags |= FF_TRANSLUCENT; - if (lines[i].args[2] & TMFC_NOSHADE) + if (lines[i].args[3] & TMFC_NOSHADE) ffloorflags |= FF_NOSHADE; - if (lines[i].args[2] & TMFC_NORETURN) + if (lines[i].args[3] & TMFC_NORETURN) ffloorflags |= FF_NORETURN; - if (lines[i].args[2] & TMFC_FLOATBOB) + if (lines[i].args[3] & TMFC_FLOATBOB) ffloorflags |= FF_FLOATBOB; + if (lines[i].args[3] & TMFC_SPLAT) + ffloorflags |= FF_SPLAT; //If translucent or player can enter it, cut inner walls - if ((ffloorflags & FF_TRANSLUCENT) || (lines[i].args[1] & TMFT_VISIBLEFROMINSIDE)) + if (lines[i].args[1] < 0xff || (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE)) ffloorflags |= FF_CUTEXTRA|FF_EXTRA; else ffloorflags |= FF_CUTLEVEL; //If player can enter it, render insides - if (lines[i].args[1] & TMFT_VISIBLEFROMINSIDE) + if (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; @@ -6747,8 +6747,8 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_ALLSIDES; } - P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); - if (lines[i].args[2] & TMFC_AIRBOB) + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + if (lines[i].args[3] & TMFC_AIRBOB) P_AddAirbob(lines[i].frontsector, lines[i].args[0], 16*FRACUNIT, false, false, false); break; diff --git a/src/p_spec.h b/src/p_spec.h index 16f992780..59aeb9f4d 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -63,11 +63,11 @@ typedef enum typedef enum { - TMFC_TRANSLUCENT = 1, - TMFC_NOSHADE = 1<<1, - TMFC_NORETURN = 1<<2, - TMFC_AIRBOB = 1<<3, - TMFC_FLOATBOB = 1<<4, + TMFC_NOSHADE = 1, + TMFC_NORETURN = 1<<1, + TMFC_AIRBOB = 1<<2, + TMFC_FLOATBOB = 1<<3, + TMFC_SPLAT = 1<<4, } textmapfofcrumbling_t; typedef enum From d6a104f8a5eec263652610754172d78ca0a48e5a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 09:57:56 +0200 Subject: [PATCH 051/326] Revamp alpha setup for custom FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 6 +++++- src/p_setup.c | 14 +++++++++----- src/p_spec.c | 10 +++++----- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 95986acc7..b0e7543aa 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2163,6 +2163,11 @@ udmf type = 13; } arg1 + { + title = "Alpha"; + default = 255; + } + arg2 { title = "Flags"; type = 12; @@ -2180,7 +2185,6 @@ udmf 512 = "Split sprites"; 1024 = "Render inside planes"; 2048 = "Extra"; - 4096 = "Translucent"; 8192 = "Fog"; 16384 = "Only render inside planes"; 32768 = "Render inside walls"; diff --git a/src/p_setup.c b/src/p_setup.c index e0f64fcba..a75cf7cb3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3381,15 +3381,19 @@ static void P_ConvertBinaryMap(void) I_Error("Custom FOF (tag %d) found without a linedef back side!", lines[i].tag); lines[i].args[0] = lines[i].tag; - lines[i].args[1] = sides[lines[i].sidenum[1]].toptexture; - lines[i].args[2] = sides[lines[i].sidenum[1]].midtexture; - if (lines[i].args[1] & FF_TRANSLUCENT) + lines[i].args[2] = sides[lines[i].sidenum[1]].toptexture; + if (lines[i].flags & ML_EFFECT6) + lines[i].args[2] |= FF_SPLAT; + lines[i].args[3] = sides[lines[i].sidenum[1]].midtexture; + if (lines[i].args[2] & FF_TRANSLUCENT) { if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else - lines[i].alpha = FRACUNIT/2; + lines[i].args[1] = 128; } + else + lines[i].args[1] = 255; break; case 443: //Call Lua function if (lines[i].text) diff --git a/src/p_spec.c b/src/p_spec.c index 2e7290271..ce01cb669 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6934,17 +6934,17 @@ void P_SpawnSpecials(boolean fromnetsave) case 259: // Custom FOF for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, (lines[i].args[1] & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, lines[i].args[1], secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], lines[i].args[2], secthinkers); if (!udmf) // Ugly backwards compatibility stuff { - if (lines[i].args[1] & FF_QUICKSAND) + if (lines[i].args[2] & FF_QUICKSAND) { fflr->sinkspeed = abs(lines[i].dx) >> 1; fflr->friction = abs(lines[i].dy) >> 6; } - if (lines[i].args[1] & FF_BUSTUP) + if (lines[i].args[2] & FF_BUSTUP) { - switch (lines[i].args[2] % TMFB_ONLYBOTTOM) + switch (lines[i].args[3] % TMFB_ONLYBOTTOM) { case TMFB_TOUCH: fflr->busttype = BT_TOUCH; @@ -6960,7 +6960,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; } - if (lines[i].args[2] & TMFB_ONLYBOTTOM) + if (lines[i].args[3] & TMFB_ONLYBOTTOM) fflr->specialflags |= FS_ONLYBOTTOM; if (lines[i].flags & ML_EFFECT4) fflr->specialflags |= FS_PUSHABLES; From cadb03fd12f8be18386f318809f2092a85475cb6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 10:03:27 +0200 Subject: [PATCH 052/326] Revamp alpha setup for laser FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 5 +++++ src/p_setup.c | 6 +++++- src/p_spec.c | 4 ++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index b0e7543aa..448e98dc7 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2146,6 +2146,11 @@ udmf type = 13; } arg1 + { + title = "Alpha"; + default = 128; + } + arg2 { title = "Damage bosses?"; type = 11; diff --git a/src/p_setup.c b/src/p_setup.c index a75cf7cb3..c72887c7a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3373,8 +3373,12 @@ static void P_ConvertBinaryMap(void) break; case 258: //FOF: Laser lines[i].args[0] = lines[i].tag; + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; + else + lines[i].args[1] = 128; if (lines[i].flags & ML_EFFECT1) - lines[i].args[1] = 1; + lines[i].args[2] = 1; break; case 259: //Custom FOF if (lines[i].sidenum[1] == 0xffff) diff --git a/src/p_spec.c b/src/p_spec.c index ce01cb669..214e7e1c0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6927,8 +6927,8 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 258: // Laser block - P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[1])); - P_AddFakeFloorsByLine(i, (lines[i].alpha * 0xff) >> FRACBITS, FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT, secthinkers); + P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[2])); + P_AddFakeFloorsByLine(i, lines[i].args[1], FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT, secthinkers); break; case 259: // Custom FOF From cc6820187cee5b7b351dc4fc2292bc7b16e760e0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 10:17:52 +0200 Subject: [PATCH 053/326] Handle splat flag for laser FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 10 +++++++--- src/p_setup.c | 9 ++++++++- src/p_spec.c | 7 +++++-- src/p_spec.h | 6 ++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 448e98dc7..84ff06385 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2152,9 +2152,13 @@ udmf } arg2 { - title = "Damage bosses?"; - type = 11; - enum = "yesno"; + title = "Flags"; + type = 12; + enum + { + 1 = "Don't damage bosses"; + 2 = "Cut cyan flat pixels"; + } } } diff --git a/src/p_setup.c b/src/p_setup.c index c72887c7a..2ae01f869 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3373,12 +3373,19 @@ static void P_ConvertBinaryMap(void) break; case 258: //FOF: Laser lines[i].args[0] = lines[i].tag; + + //Alpha if (sides[lines[i].sidenum[0]].toptexture > 0) lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else lines[i].args[1] = 128; + + //Flags if (lines[i].flags & ML_EFFECT1) - lines[i].args[2] = 1; + lines[i].args[2] = TMFL_NOBOSSES; + if (lines[i].flags & ML_EFFECT6) + lines[i].args[2] = TMFL_SPLAT; + break; case 259: //Custom FOF if (lines[i].sidenum[1] == 0xffff) diff --git a/src/p_spec.c b/src/p_spec.c index 214e7e1c0..66ad1893a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6927,8 +6927,11 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 258: // Laser block - P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[2])); - P_AddFakeFloorsByLine(i, lines[i].args[1], FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT, secthinkers); + ffloorflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT; + P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[2] & TMFL_NOBOSSES)); + if (lines[i].args[2] & TMFL_SPLAT) + ffloorflags |= FF_SPLAT; + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); break; case 259: // Custom FOF diff --git a/src/p_spec.h b/src/p_spec.h index 59aeb9f4d..661b74738 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -97,6 +97,12 @@ typedef enum TMFB_ONLYBOTTOM = 1<<2, } textmapfofbustflags_t; +typedef enum +{ + TMFL_NOBOSSES = 1, + TMFL_SPLAT = 1<<1, +} textmapfoflaserflags_t; + // GETSECSPECIAL (specialval, section) // // Pulls out the special # from a particular section. From f4e28f5cc4b1684091e9f2d05d6c1872efe17c48 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 10:23:16 +0200 Subject: [PATCH 054/326] Revamp alpha setup for quicksand FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 17 +++++++++++++---- src/p_setup.c | 9 ++++++--- src/p_spec.c | 10 ++++++---- src/p_spec.h | 6 ++++++ 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 84ff06385..50d59f1a4 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2122,15 +2122,24 @@ udmf } arg1 { - title = "Ripple effect?"; - type = 11; - enum = "yesno"; + title = "Alpha"; + default = 255; } arg2 { - title = "Sinking speed"; + title = "Ripple effect?"; + type = 12; + enum + { + 1 = "No ripple effect"; + 2 = "Cut cyan flat pixels"; + } } arg3 + { + title = "Sinking speed"; + } + arg4 { title = "Friction"; } diff --git a/src/p_setup.c b/src/p_setup.c index 2ae01f869..79a030e6d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3366,10 +3366,13 @@ static void P_ConvertBinaryMap(void) break; case 257: //FOF: Quicksand lines[i].args[0] = lines[i].tag; + lines[i].args[1] = 255; if (!(lines[i].flags & ML_EFFECT5)) - lines[i].args[1] = 1; //No ripple effect - lines[i].args[2] = lines[i].dx >> FRACBITS; //Sinking speed - lines[i].args[3] = lines[i].dy >> FRACBITS; //Friction + lines[i].args[2] |= TMFQ_NORIPPLE; + if (lines[i].flags & ML_EFFECT6) + lines[i].args[2] |= TMFQ_SPLAT; + lines[i].args[3] = lines[i].dx >> FRACBITS; //Sinking speed + lines[i].args[4] = lines[i].dy >> FRACBITS; //Friction break; case 258: //FOF: Laser lines[i].args[0] = lines[i].tag; diff --git a/src/p_spec.c b/src/p_spec.c index 66ad1893a..86f153bce 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6915,14 +6915,16 @@ void P_SpawnSpecials(boolean fromnetsave) } case 257: // Quicksand ffloorflags = FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES; - if (!(lines[i].args[1])) + if (!(lines[i].args[2] & TMFQ_NORIPPLE)) ffloorflags |= FF_RIPPLE; + if (lines[i].args[2] & TMFQ_SPLAT) + ffloorflags |= FF_SPLAT; for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, ffloorflags, secthinkers); - fflr->sinkspeed = abs(lines[i].args[2]) << (FRACBITS - 1); - fflr->friction = abs(lines[i].args[3]) << (FRACBITS - 6); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers); + fflr->sinkspeed = abs(lines[i].args[3]) << (FRACBITS - 1); + fflr->friction = abs(lines[i].args[4]) << (FRACBITS - 6); } break; diff --git a/src/p_spec.h b/src/p_spec.h index 661b74738..ef4c003a8 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -97,6 +97,12 @@ typedef enum TMFB_ONLYBOTTOM = 1<<2, } textmapfofbustflags_t; +typedef enum +{ + TMFQ_NORIPPLE = 1, + TMFQ_SPLAT = 1<<1, +} textmapfofquicksandflags_t; + typedef enum { TMFL_NOBOSSES = 1, From 3317827151c443395ff6ca7675c194b1bdb32c29 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 10:31:26 +0200 Subject: [PATCH 055/326] Revamp alpha setup for bustable FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 12 +++---- src/p_setup.c | 34 +++++++++++--------- src/p_spec.c | 10 +++--- src/p_spec.h | 1 + 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 50d59f1a4..1ab8ba927 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2076,6 +2076,11 @@ udmf type = 13; } arg1 + { + title = "Alpha"; + default = 255; + } + arg2 { title = "Bustable type"; type = 11; @@ -2087,12 +2092,6 @@ udmf 3 = "Strong"; } } - arg2 - { - title = "Translucent?"; - type = 11; - enum = "noyes"; - } arg3 { title = "Flags"; @@ -2102,6 +2101,7 @@ udmf 1 = "Bustable by pushables"; 2 = "Trigger linedef executor"; 4 = "Only bustable from below"; + 8 = "Cut cyan flat pixels"; } } arg4 diff --git a/src/p_setup.c b/src/p_setup.c index 79a030e6d..1c2550200 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3332,26 +3332,28 @@ static void P_ConvertBinaryMap(void) case 256: //FOF: Spin-bustable block, translucent lines[i].args[0] = lines[i].tag; - //Bustable type - if (lines[i].special <= 253) - lines[i].args[1] = TMFB_TOUCH; - else if (lines[i].special >= 255) - lines[i].args[1] = TMFB_SPIN; - else if (lines[i].flags & ML_NOCLIMB) - lines[i].args[1] = TMFB_STRONG; - else - lines[i].args[1] = TMFB_REGULAR; - - //Translucency + //Alpha if (lines[i].special == 253 || lines[i].special == 256) { - lines[i].args[2] = 1; if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else - lines[i].alpha = FRACUNIT/2; + lines[i].args[1] = 128; } + else + lines[i].args[1] = 255; + //Bustable type + if (lines[i].special <= 253) + lines[i].args[2] = TMFB_TOUCH; + else if (lines[i].special >= 255) + lines[i].args[2] = TMFB_SPIN; + else if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] = TMFB_STRONG; + else + lines[i].args[2] = TMFB_REGULAR; + + //Flags if (lines[i].flags & ML_EFFECT4) lines[i].args[3] |= TMFB_PUSHABLES; if (lines[i].flags & ML_EFFECT5) @@ -3360,7 +3362,9 @@ static void P_ConvertBinaryMap(void) lines[i].args[4] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; } if (lines[i].special == 252 && lines[i].flags & ML_NOCLIMB) - lines[i].args[4] |= TMFB_ONLYBOTTOM; + lines[i].args[3] |= TMFB_ONLYBOTTOM; + if (lines[i].flags & ML_EFFECT6) + lines[i].args[3] |= TMFB_SPLAT; lines[i].special = 254; break; diff --git a/src/p_spec.c b/src/p_spec.c index 86f153bce..e03ec3205 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6873,7 +6873,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP; //Bustable type - switch (lines[i].args[1]) + switch (lines[i].args[2]) { case TMFB_TOUCH: busttype = BT_TOUCH; @@ -6889,10 +6889,6 @@ void P_SpawnSpecials(boolean fromnetsave) break; } - //Translucent? - if (lines[i].args[2]) - ffloorflags |= FF_TRANSLUCENT; - //Flags if (lines[i].args[3] & TMFB_PUSHABLES) bustflags |= FS_PUSHABLES; @@ -6900,13 +6896,15 @@ void P_SpawnSpecials(boolean fromnetsave) bustflags |= FS_EXECUTOR; if (lines[i].args[3] & TMFB_ONLYBOTTOM) bustflags |= FS_ONLYBOTTOM; + if (lines[i].args[3] & TMFB_SPLAT) + ffloorflags |= FF_SPLAT; if (busttype != BT_TOUCH || bustflags & FS_ONLYBOTTOM) ffloorflags |= FF_BLOCKPLAYER; for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers); fflr->busttype = busttype; fflr->specialflags = bustflags; fflr->busttag = lines[i].args[4]; diff --git a/src/p_spec.h b/src/p_spec.h index ef4c003a8..a5717e1d1 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -95,6 +95,7 @@ typedef enum TMFB_PUSHABLES = 1, TMFB_EXECUTOR = 1<<1, TMFB_ONLYBOTTOM = 1<<2, + TMFB_SPLAT = 1<<3, } textmapfofbustflags_t; typedef enum From 6521496d8ab30704c33f0dff6366d18d43d86e1d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 10:53:27 +0200 Subject: [PATCH 056/326] Revamp alpha setup for bobbing FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 26 ++++++++- src/p_setup.c | 34 +++++++----- src/p_spec.c | 58 +++++++++++--------- 3 files changed, 75 insertions(+), 43 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 1ab8ba927..934e60962 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1825,9 +1825,20 @@ udmf } arg1 { - title = "Bobbing distance"; + title = "Alpha"; + default = 255; } arg2 + { + title = "Cut cyan flat pixels?"; + type = 11; + enum = "noyes"; + } + arg3 + { + title = "Bobbing distance"; + } + arg4 { title = "Flags"; type = 12; @@ -1838,7 +1849,7 @@ udmf 4 = "Dynamic"; } } - arg3 + arg5 { title = "Tangibility"; type = 12; @@ -1856,6 +1867,17 @@ udmf type = 13; } arg1 + { + title = "Alpha"; + default = 255; + } + arg2 + { + title = "Cut cyan flat pixels?"; + type = 11; + enum = "noyes"; + } + arg3 { title = "Tangibility"; type = 12; diff --git a/src/p_setup.c b/src/p_setup.c index 1c2550200..2eec9820a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3140,15 +3140,30 @@ static void P_ConvertBinaryMap(void) case 152: //FOF: Reverse air bobbing (adjustable) case 153: //FOF: Dynamically sinking platform lines[i].args[0] = lines[i].tag; - lines[i].args[1] = (lines[i].special == 150) ? 16 : (P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS); + lines[i].args[1] = 255; + lines[i].args[2] = !!(lines[i].flags & ML_EFFECT6); + lines[i].args[3] = (lines[i].special == 150) ? 16 : (P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS); //Flags if (lines[i].special == 152) - lines[i].args[2] |= TMFB_REVERSE; + lines[i].args[4] |= TMFB_REVERSE; if (lines[i].flags & ML_NOCLIMB) - lines[i].args[2] |= TMFB_SPINDASH; + lines[i].args[4] |= TMFB_SPINDASH; if (lines[i].special == 153) - lines[i].args[2] |= TMFB_DYNAMIC; + lines[i].args[4] |= TMFB_DYNAMIC; + + //Tangibility + if (lines[i].flags & ML_EFFECT1) + lines[i].args[5] |= TMFT_DONTBLOCKOTHERS; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[5] |= TMFT_DONTBLOCKPLAYER; + + lines[i].special = 150; + break; + case 160: //FOF: Water bobbing + lines[i].args[0] = lines[i].tag; + lines[i].args[1] = 255; + lines[i].args[2] = !!(lines[i].flags & ML_EFFECT6); //Tangibility if (lines[i].flags & ML_EFFECT1) @@ -3156,17 +3171,6 @@ static void P_ConvertBinaryMap(void) if (lines[i].flags & ML_EFFECT2) lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; - lines[i].special = 150; - break; - case 160: //FOF: Water bobbing - lines[i].args[0] = lines[i].tag; - - //Tangibility - if (lines[i].flags & ML_EFFECT1) - lines[i].args[1] |= TMFT_DONTBLOCKOTHERS; - if (lines[i].flags & ML_EFFECT2) - lines[i].args[1] |= TMFT_DONTBLOCKPLAYER; - break; case 170: //FOF: Crumbling, respawn case 171: //FOF: Crumbling, no respawn diff --git a/src/p_spec.c b/src/p_spec.c index e03ec3205..6373478b8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6664,6 +6664,35 @@ void P_SpawnSpecials(boolean fromnetsave) case 150: // FOF (Air bobbing) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; + if (lines[i].args[2]) + ffloorflags |= FF_SPLAT; + + //Tangibility settings + if (lines[i].args[5] & TMFT_INTANGIBLETOP) + ffloorflags |= FF_REVERSEPLATFORM; + if (lines[i].args[5] & TMFT_INTANGIBLEBOTTOM) + ffloorflags |= FF_PLATFORM; + if (lines[i].args[5] & TMFT_DONTBLOCKPLAYER) + ffloorflags &= ~FF_BLOCKPLAYER; + if (lines[i].args[5] & TMFT_DONTBLOCKOTHERS) + ffloorflags &= ~FF_BLOCKOTHERS; + + //If player can enter it, cut inner walls + if (lines[i].args[5] & TMFT_VISIBLEFROMINSIDE) + ffloorflags |= FF_CUTEXTRA|FF_EXTRA; + else + ffloorflags |= FF_CUTLEVEL; + + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[3] << FRACBITS, !!(lines[i].args[4] & TMFB_REVERSE), !!(lines[i].args[4] & TMFB_SPINDASH), !!(lines[i].args[4] & TMFB_DYNAMIC)); + break; + + case 160: // FOF (Water bobbing) + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB; + + if (lines[i].args[2]) + ffloorflags |= FF_SPLAT; + //Tangibility settings if (lines[i].args[3] & TMFT_INTANGIBLETOP) ffloorflags |= FF_REVERSEPLATFORM; @@ -6674,31 +6703,8 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) ffloorflags &= ~FF_BLOCKOTHERS; - //If player can enter it, cut inner walls - if (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE) - ffloorflags |= FF_CUTEXTRA|FF_EXTRA; - else - ffloorflags |= FF_CUTLEVEL; - - P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); - P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); - break; - - case 160: // FOF (Water bobbing) - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB; - - //Tangibility settings - if (lines[i].args[1] & TMFT_INTANGIBLETOP) - ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[1] & TMFT_INTANGIBLEBOTTOM) - ffloorflags |= FF_PLATFORM; - if (lines[i].args[1] & TMFT_DONTBLOCKPLAYER) - ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[1] & TMFT_DONTBLOCKOTHERS) - ffloorflags &= ~FF_BLOCKOTHERS; - //If player can enter it, render insides - if (lines[i].args[1] & TMFT_VISIBLEFROMINSIDE) + if (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; @@ -6706,7 +6712,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_ALLSIDES; } - P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); break; case 170: // FOF (Crumbling) @@ -6927,7 +6933,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 258: // Laser block - ffloorflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT; + ffloorflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA; P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[2] & TMFL_NOBOSSES)); if (lines[i].args[2] & TMFL_SPLAT) ffloorflags |= FF_SPLAT; From 5f9af65aa08ba1936f1d724dfbebfd25283b829e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 16:45:18 +0200 Subject: [PATCH 057/326] Revamp alpha setup for the remaining FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 62 ++++---- src/p_setup.c | 156 ++++++++++--------- src/p_spec.c | 93 ++++++----- src/p_spec.h | 18 +-- 4 files changed, 171 insertions(+), 158 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 934e60962..44da4134b 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1757,31 +1757,29 @@ udmf } arg1 { - title = "Visibility"; + title = "Alpha"; + default = 255; + } + arg2 + { + title = "Appearance"; type = 12; enum { 1 = "Don't render planes"; 2 = "Don't render sides"; 4 = "Render insides"; + 8 = "Render only insides"; + 16 = "No shadow"; + 32 = "Cut cyan flat pixels"; } } - arg2 + arg3 { title = "Tangibility"; type = 12; enum = "tangibility"; } - arg3 - { - title = "Appearance"; - type = 12; - enum - { - 1 = "Translucent"; - 2 = "No shadow"; - } - } } 120 @@ -1931,31 +1929,29 @@ udmf } arg1 { - title = "Visibility"; + title = "Alpha"; + default = 255; + } + arg2 + { + title = "Appearance"; type = 12; enum { 1 = "Don't render planes"; 2 = "Don't render sides"; 4 = "Render insides"; + 8 = "Render only insides"; + 16 = "No shadow"; + 32 = "Cut cyan flat pixels"; } } - arg2 + arg3 { title = "Tangibility"; type = 12; enum = "tangibility"; } - arg3 - { - title = "Appearance"; - type = 12; - enum - { - 1 = "Translucent"; - 2 = "No shadow"; - } - } arg4 { title = "Speed"; @@ -2011,14 +2007,8 @@ udmf } arg1 { - title = "Visibility"; - type = 12; - enum - { - 1 = "Don't render planes"; - 2 = "Don't render sides"; - 4 = "Don't render insides"; - } + title = "Alpha"; + default = 255; } arg2 { @@ -2026,8 +2016,12 @@ udmf type = 12; enum { - 1 = "Translucent"; - 2 = "No shadow"; + 1 = "Don't render planes"; + 2 = "Don't render sides"; + 4 = "Don't render insides"; + 8 = "Render only insides"; + 16 = "No shadow"; + 32 = "Cut cyan flat pixels"; } } } diff --git a/src/p_setup.c b/src/p_setup.c index 2eec9820a..c2df65397 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3016,35 +3016,36 @@ static void P_ConvertBinaryMap(void) case 105: //FOF: solid, invisible lines[i].args[0] = lines[i].tag; - //Visibility + //Alpha + if (lines[i].special == 102) + { + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] |= TMFA_INSIDES; + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; + else + lines[i].args[1] = 128; + } + else + lines[i].args[1] = 255; + + //Appearance if (lines[i].special == 105) - lines[i].args[1] = TMFV_NOPLANES|TMFV_NOSIDES; + lines[i].args[2] = TMFA_NOPLANES|TMFA_NOSIDES; else if (lines[i].special == 104) - lines[i].args[1] = TMFV_NOSIDES; + lines[i].args[2] = TMFA_NOSIDES; else if (lines[i].special == 103) - lines[i].args[1] = TMFV_NOPLANES; + lines[i].args[2] = TMFA_NOPLANES; + if (lines[i].special != 100 && (lines[i].special != 104 || !(lines[i].flags & ML_NOCLIMB))) + lines[i].args[2] |= TMFA_NOSHADE; + if (lines[i].flags & ML_EFFECT6) + lines[i].args[2] |= TMFA_SPLAT; //Tangibility if (lines[i].flags & ML_EFFECT1) - lines[i].args[2] |= TMFT_DONTBLOCKOTHERS; + lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[2] |= TMFT_DONTBLOCKPLAYER; - - //Translucency - if (lines[i].special == 102) - { - lines[i].args[3] |= TMFA_TRANSLUCENT; - if (lines[i].flags & ML_NOCLIMB) - lines[i].args[1] |= TMFV_TOGGLEINSIDES; - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; - else - lines[i].alpha = FRACUNIT/2; - } - - //Shadow? - if (lines[i].special != 100 && (lines[i].special != 104 || !(lines[i].flags & ML_NOCLIMB))) - lines[i].args[3] |= TMFA_NOSHADE; + lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 100; break; @@ -3098,40 +3099,41 @@ static void P_ConvertBinaryMap(void) case 146: //FOF: only tangible from sides lines[i].args[0] = lines[i].tag; - //Visibility + //Alpha + if (lines[i].special == 141 || lines[i].special == 142 || lines[i].special == 144 || lines[i].special == 145) + { + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] |= TMFA_INSIDES; + if (sides[lines[i].sidenum[0]].toptexture > 0) + lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; + else + lines[i].args[1] = 128; + } + else + lines[i].args[1] = 255; + + //Appearance if (lines[i].special == 142 || lines[i].special == 145) - lines[i].args[1] = TMFV_NOSIDES; + lines[i].args[2] = TMFA_NOSIDES; else if (lines[i].special == 146) - lines[i].args[1] = TMFV_NOPLANES; + lines[i].args[2] = TMFA_NOPLANES; + if (lines[i].special != 146 && (lines[i].flags & ML_NOCLIMB)) + lines[i].args[2] |= TMFA_NOSHADE; + if (lines[i].flags & ML_EFFECT6) + lines[i].args[2] |= TMFA_SPLAT; //Tangibility if (lines[i].special <= 142) - lines[i].args[2] |= TMFT_INTANGIBLEBOTTOM; + lines[i].args[3] |= TMFT_INTANGIBLEBOTTOM; else if (lines[i].special <= 145) - lines[i].args[2] |= TMFT_INTANGIBLETOP; + lines[i].args[3] |= TMFT_INTANGIBLETOP; else - lines[i].args[2] |= TMFT_INTANGIBLEBOTTOM|TMFT_INTANGIBLETOP; + lines[i].args[3] |= TMFT_INTANGIBLEBOTTOM|TMFT_INTANGIBLETOP; if (lines[i].flags & ML_EFFECT1) - lines[i].args[2] |= TMFT_DONTBLOCKOTHERS; + lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[2] |= TMFT_DONTBLOCKPLAYER; - - //Translucency - if (lines[i].special == 141 || lines[i].special == 142 || lines[i].special == 144 || lines[i].special == 145) - { - lines[i].args[3] |= TMFA_TRANSLUCENT; - if (lines[i].flags & ML_NOCLIMB) - lines[i].args[1] |= TMFV_TOGGLEINSIDES; - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; - else - lines[i].alpha = FRACUNIT/2; - } - - //Shadow? - if (lines[i].special != 146 && (lines[i].flags & ML_NOCLIMB)) - lines[i].args[3] |= TMFA_NOSHADE; + lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 100; break; @@ -3227,33 +3229,34 @@ static void P_ConvertBinaryMap(void) case 195: // FOF: Rising, intangible from bottom, translucent lines[i].args[0] = lines[i].tag; - //Visibility - if (lines[i].special == 193) - lines[i].args[1] = TMFV_NOPLANES|TMFV_NOSIDES; - if (lines[i].special >= 194) - lines[i].args[1] = TMFV_TOGGLEINSIDES; - - //Tangibility - if (lines[i].flags & ML_EFFECT1) - lines[i].args[2] |= TMFT_DONTBLOCKOTHERS; - if (lines[i].flags & ML_EFFECT2) - lines[i].args[2] |= TMFT_DONTBLOCKPLAYER; - if (lines[i].special >= 194) - lines[i].args[2] |= TMFT_INTANGIBLEBOTTOM; - //Translucency if (lines[i].special == 192 || lines[i].special == 195) { - lines[i].args[3] |= TMFA_TRANSLUCENT; if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else - lines[i].alpha = FRACUNIT/2; + lines[i].args[1] = 128; } + else + lines[i].args[1] = 255; - //Shadow? + //Appearance + if (lines[i].special == 193) + lines[i].args[2] = TMFA_NOPLANES|TMFA_NOSIDES; + if (lines[i].special >= 194) + lines[i].args[2] = TMFA_INSIDES; if (lines[i].special != 190 && (lines[i].special <= 193 || lines[i].flags & ML_NOCLIMB)) - lines[i].args[3] |= TMFA_NOSHADE; + lines[i].args[2] |= TMFA_NOSHADE; + if (lines[i].flags & ML_EFFECT6) + lines[i].args[2] |= TMFA_SPLAT; + + //Tangibility + if (lines[i].flags & ML_EFFECT1) + lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; + if (lines[i].special >= 194) + lines[i].args[3] |= TMFT_INTANGIBLEBOTTOM; //Speed lines[i].args[4] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; @@ -3282,23 +3285,26 @@ static void P_ConvertBinaryMap(void) case 222: //FOF: Intangible, sides only lines[i].args[0] = lines[i].tag; - //Visibility - if (lines[i].special == 222) - lines[i].args[1] |= TMFV_NOPLANES; - if (lines[i].special == 221) - lines[i].args[1] |= TMFV_TOGGLEINSIDES; - - //Appearance + //Alpha if (lines[i].special == 221) { - lines[i].args[2] |= TMFA_TRANSLUCENT; if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].alpha = (sides[lines[i].sidenum[0]].toptexture << FRACBITS)/255; + lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else - lines[i].alpha = FRACUNIT/2; + lines[i].args[1] = 128; } + else + lines[i].args[1] = 255; + + //Appearance + if (lines[i].special == 222) + lines[i].args[2] |= TMFA_NOPLANES; + if (lines[i].special != 221) + lines[i].args[2] |= TMFA_INSIDES; if (lines[i].special != 220 && !(lines[i].flags & ML_NOCLIMB)) lines[i].args[2] |= TMFA_NOSHADE; + if (lines[i].flags & ML_EFFECT6) + lines[i].args[2] |= TMFA_SPLAT; lines[i].special = 220; break; diff --git a/src/p_spec.c b/src/p_spec.c index 6373478b8..1c0a4ce9d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6602,46 +6602,51 @@ void P_SpawnSpecials(boolean fromnetsave) case 100: // FOF (solid) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; - //Visibility settings - if (lines[i].args[1] & TMFV_NOPLANES) + //Appearance settings + if (lines[i].args[2] & TMFA_NOPLANES) ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[1] & TMFV_NOSIDES) + if (lines[i].args[2] & TMFA_NOSIDES) ffloorflags &= ~FF_RENDERSIDES; - if (lines[i].args[1] & TMFV_TOGGLEINSIDES) + if (lines[i].args[2] & TMFA_INSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_ALLSIDES; } + if (lines[i].args[2] & TMFA_ONLYINSIDES) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_INVERTPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_INVERTSIDES; + } + if (lines[i].args[2] & TMFA_NOSHADE) + ffloorflags |= FF_NOSHADE; + if (lines[i].args[2] & TMFA_SPLAT) + ffloorflags |= FF_SPLAT; //Tangibility settings - if (lines[i].args[2] & TMFT_INTANGIBLETOP) + if (lines[i].args[3] & TMFT_INTANGIBLETOP) ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[2] & TMFT_INTANGIBLEBOTTOM) + if (lines[i].args[3] & TMFT_INTANGIBLEBOTTOM) ffloorflags |= FF_PLATFORM; - if (lines[i].args[2] & TMFT_DONTBLOCKPLAYER) + if (lines[i].args[3] & TMFT_DONTBLOCKPLAYER) ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[2] & TMFT_DONTBLOCKOTHERS) + if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) ffloorflags &= ~FF_BLOCKOTHERS; - //Appearance settings - if ((lines[i].args[3] & TMFA_TRANSLUCENT) && (ffloorflags & FF_RENDERALL)) //Translucent - ffloorflags |= FF_TRANSLUCENT; - if (lines[i].args[3] & TMFA_NOSHADE) - ffloorflags |= FF_NOSHADE; - //Cutting options if (ffloorflags & FF_RENDERALL) { //If translucent or player can enter it, cut inner walls - if ((ffloorflags & FF_TRANSLUCENT) || (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE)) + if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) ffloorflags |= FF_CUTEXTRA|FF_EXTRA; else ffloorflags |= FF_CUTLEVEL; } - P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); break; case 120: // FOF (water) @@ -6765,40 +6770,45 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; - //Visibility settings - if (lines[i].args[1] & TMFV_NOPLANES) + //Appearance settings + if (lines[i].args[2] & TMFA_NOPLANES) ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[1] & TMFV_NOSIDES) + if (lines[i].args[2] & TMFA_NOSIDES) ffloorflags &= ~FF_RENDERSIDES; - if (lines[i].args[1] & TMFV_TOGGLEINSIDES) + if (lines[i].args[2] & TMFA_INSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_ALLSIDES; } + if (lines[i].args[2] & TMFA_ONLYINSIDES) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_INVERTPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_INVERTSIDES; + } + if (lines[i].args[2] & TMFA_NOSHADE) + ffloorflags |= FF_NOSHADE; + if (lines[i].args[2] & TMFA_SPLAT) + ffloorflags |= FF_SPLAT; //Tangibility settings - if (lines[i].args[2] & TMFT_INTANGIBLETOP) + if (lines[i].args[3] & TMFT_INTANGIBLETOP) ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[2] & TMFT_INTANGIBLEBOTTOM) + if (lines[i].args[3] & TMFT_INTANGIBLEBOTTOM) ffloorflags |= FF_PLATFORM; - if (lines[i].args[2] & TMFT_DONTBLOCKPLAYER) + if (lines[i].args[3] & TMFT_DONTBLOCKPLAYER) ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[2] & TMFT_DONTBLOCKOTHERS) + if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) ffloorflags &= ~FF_BLOCKOTHERS; - //Appearance settings - if ((lines[i].args[3] & TMFA_TRANSLUCENT) && (ffloorflags & FF_RENDERALL)) //Translucent - ffloorflags |= FF_TRANSLUCENT; - if (lines[i].args[3] & TMFA_NOSHADE) - ffloorflags |= FF_NOSHADE; - //Cutting options if (ffloorflags & FF_RENDERALL) { //If translucent or player can enter it, cut inner walls - if ((ffloorflags & FF_TRANSLUCENT) || (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE)) + if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) ffloorflags |= FF_CUTEXTRA|FF_EXTRA; else ffloorflags |= FF_CUTLEVEL; @@ -6827,24 +6837,29 @@ void P_SpawnSpecials(boolean fromnetsave) case 220: //Intangible ffloorflags = FF_EXISTS|FF_RENDERALL|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - //Visibility settings - if (lines[i].args[1] & TMFV_NOPLANES) + //Appearance settings + if (lines[i].args[2] & TMFA_NOPLANES) ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[1] & TMFV_NOSIDES) + if (lines[i].args[2] & TMFA_NOSIDES) ffloorflags &= ~FF_RENDERSIDES; - if (!(lines[i].args[1] & TMFV_TOGGLEINSIDES)) + if (!(lines[i].args[2] & TMFA_INSIDES)) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_ALLSIDES; } - - //Appearance settings - if ((lines[i].args[2] & TMFA_TRANSLUCENT) && (ffloorflags & FF_RENDERALL)) - ffloorflags |= FF_TRANSLUCENT; + if (lines[i].args[2] & TMFA_ONLYINSIDES) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_INVERTPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_INVERTSIDES; + } if (lines[i].args[2] & TMFA_NOSHADE) ffloorflags |= FF_NOSHADE; + if (lines[i].args[2] & TMFA_SPLAT) + ffloorflags |= FF_SPLAT; P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); break; diff --git a/src/p_spec.h b/src/p_spec.h index a5717e1d1..52dcf6786 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -24,10 +24,13 @@ extern mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs //FOF flags typedef enum { - TMFV_NOPLANES = 1, - TMFV_NOSIDES = 1<<1, - TMFV_TOGGLEINSIDES = 1<<2, -} textmapfofvisibility_t; + TMFA_NOPLANES = 1, + TMFA_NOSIDES = 1<<1, + TMFA_INSIDES = 1<<2, + TMFA_ONLYINSIDES = 1<<3, + TMFA_NOSHADE = 1<<4, + TMFA_SPLAT = 1<<5, +} textmapfofappearance_t; typedef enum { @@ -36,14 +39,9 @@ typedef enum TMFT_DONTBLOCKPLAYER = 1<<2, TMFT_VISIBLEFROMINSIDE = (TMFT_INTANGIBLETOP|TMFT_INTANGIBLEBOTTOM|TMFT_DONTBLOCKPLAYER), TMFT_DONTBLOCKOTHERS = 1<<3, + TMFT_INTANGIBLE = (TMFT_DONTBLOCKPLAYER|TMFT_DONTBLOCKOTHERS), } textmapfoftangibility_t; -typedef enum -{ - TMFA_TRANSLUCENT = 1, - TMFA_NOSHADE = 1<<1, -} textmapfofappearance_t; - typedef enum { TMFW_NOSIDES = 1, From 06b581dcdfb2b08f1c11ae0d99a6ab4f21611600 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 17:48:43 +0200 Subject: [PATCH 058/326] Trim down options for the bobbing FOF preset types --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 36 +------------- src/p_setup.c | 25 ++-------- src/p_spec.c | 51 ++------------------ 3 files changed, 8 insertions(+), 104 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 44da4134b..b88d97aef 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1822,21 +1822,10 @@ udmf type = 13; } arg1 - { - title = "Alpha"; - default = 255; - } - arg2 - { - title = "Cut cyan flat pixels?"; - type = 11; - enum = "noyes"; - } - arg3 { title = "Bobbing distance"; } - arg4 + arg2 { title = "Flags"; type = 12; @@ -1847,12 +1836,6 @@ udmf 4 = "Dynamic"; } } - arg5 - { - title = "Tangibility"; - type = 12; - enum = "tangibility"; - } } 160 @@ -1864,23 +1847,6 @@ udmf title = "Target sector tag"; type = 13; } - arg1 - { - title = "Alpha"; - default = 255; - } - arg2 - { - title = "Cut cyan flat pixels?"; - type = 11; - enum = "noyes"; - } - arg3 - { - title = "Tangibility"; - type = 12; - enum = "tangibility"; - } } 170 diff --git a/src/p_setup.c b/src/p_setup.c index c2df65397..5a2b7e580 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3142,37 +3142,20 @@ static void P_ConvertBinaryMap(void) case 152: //FOF: Reverse air bobbing (adjustable) case 153: //FOF: Dynamically sinking platform lines[i].args[0] = lines[i].tag; - lines[i].args[1] = 255; - lines[i].args[2] = !!(lines[i].flags & ML_EFFECT6); - lines[i].args[3] = (lines[i].special == 150) ? 16 : (P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS); + lines[i].args[1] = (lines[i].special == 150) ? 16 : (P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS); //Flags if (lines[i].special == 152) - lines[i].args[4] |= TMFB_REVERSE; + lines[i].args[2] |= TMFB_REVERSE; if (lines[i].flags & ML_NOCLIMB) - lines[i].args[4] |= TMFB_SPINDASH; + lines[i].args[2] |= TMFB_SPINDASH; if (lines[i].special == 153) - lines[i].args[4] |= TMFB_DYNAMIC; - - //Tangibility - if (lines[i].flags & ML_EFFECT1) - lines[i].args[5] |= TMFT_DONTBLOCKOTHERS; - if (lines[i].flags & ML_EFFECT2) - lines[i].args[5] |= TMFT_DONTBLOCKPLAYER; + lines[i].args[2] |= TMFB_DYNAMIC; lines[i].special = 150; break; case 160: //FOF: Water bobbing lines[i].args[0] = lines[i].tag; - lines[i].args[1] = 255; - lines[i].args[2] = !!(lines[i].flags & ML_EFFECT6); - - //Tangibility - if (lines[i].flags & ML_EFFECT1) - lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; - if (lines[i].flags & ML_EFFECT2) - lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; - break; case 170: //FOF: Crumbling, respawn case 171: //FOF: Crumbling, no respawn diff --git a/src/p_spec.c b/src/p_spec.c index 1c0a4ce9d..2998478d5 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6667,57 +6667,12 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 150: // FOF (Air bobbing) - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; - - if (lines[i].args[2]) - ffloorflags |= FF_SPLAT; - - //Tangibility settings - if (lines[i].args[5] & TMFT_INTANGIBLETOP) - ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[5] & TMFT_INTANGIBLEBOTTOM) - ffloorflags |= FF_PLATFORM; - if (lines[i].args[5] & TMFT_DONTBLOCKPLAYER) - ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[5] & TMFT_DONTBLOCKOTHERS) - ffloorflags &= ~FF_BLOCKOTHERS; - - //If player can enter it, cut inner walls - if (lines[i].args[5] & TMFT_VISIBLEFROMINSIDE) - ffloorflags |= FF_CUTEXTRA|FF_EXTRA; - else - ffloorflags |= FF_CUTLEVEL; - - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[3] << FRACBITS, !!(lines[i].args[4] & TMFB_REVERSE), !!(lines[i].args[4] & TMFB_SPINDASH), !!(lines[i].args[4] & TMFB_DYNAMIC)); + P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL, secthinkers); + P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); break; case 160: // FOF (Water bobbing) - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB; - - if (lines[i].args[2]) - ffloorflags |= FF_SPLAT; - - //Tangibility settings - if (lines[i].args[3] & TMFT_INTANGIBLETOP) - ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[3] & TMFT_INTANGIBLEBOTTOM) - ffloorflags |= FF_PLATFORM; - if (lines[i].args[3] & TMFT_DONTBLOCKPLAYER) - ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) - ffloorflags &= ~FF_BLOCKOTHERS; - - //If player can enter it, render insides - if (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE) - { - if (ffloorflags & FF_RENDERPLANES) - ffloorflags |= FF_BOTHPLANES; - if (ffloorflags & FF_RENDERSIDES) - ffloorflags |= FF_ALLSIDES; - } - - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB, secthinkers); break; case 170: // FOF (Crumbling) From 698c18bd408e80a95946732ce1f2d9604849e705 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 17:57:24 +0200 Subject: [PATCH 059/326] Remove temporary splat rendering special case --- src/p_spec.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 2998478d5..ade4501a6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5697,8 +5697,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I if (sec2->hasslope) sec->hasslope = true; - if (!udmf && master->flags & ML_EFFECT6) - fflr->flags |= FF_SPLAT; //TODO: Temporary fflr->spawnflags = fflr->flags = flags; fflr->master = master; fflr->norender = INFTICS; From 88aad41310b59bb605e0a119d76c1192ca62190f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 12 Jun 2020 18:22:16 +0200 Subject: [PATCH 060/326] Remove unnecessary options from quicksand FOF again --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 17 ++++------------- src/p_setup.c | 9 +++------ src/p_spec.c | 10 ++++------ src/p_spec.h | 6 ------ 4 files changed, 11 insertions(+), 31 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index b88d97aef..a899f9488 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2104,24 +2104,15 @@ udmf } arg1 { - title = "Alpha"; - default = 255; + title = "Ripple effect?"; + type = 11; + enum = "yesno"; } arg2 - { - title = "Ripple effect?"; - type = 12; - enum - { - 1 = "No ripple effect"; - 2 = "Cut cyan flat pixels"; - } - } - arg3 { title = "Sinking speed"; } - arg4 + arg3 { title = "Friction"; } diff --git a/src/p_setup.c b/src/p_setup.c index 5a2b7e580..49b5ffcb5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3363,13 +3363,10 @@ static void P_ConvertBinaryMap(void) break; case 257: //FOF: Quicksand lines[i].args[0] = lines[i].tag; - lines[i].args[1] = 255; if (!(lines[i].flags & ML_EFFECT5)) - lines[i].args[2] |= TMFQ_NORIPPLE; - if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= TMFQ_SPLAT; - lines[i].args[3] = lines[i].dx >> FRACBITS; //Sinking speed - lines[i].args[4] = lines[i].dy >> FRACBITS; //Friction + lines[i].args[1] = 1; //No ripple effect + lines[i].args[2] = lines[i].dx >> FRACBITS; //Sinking speed + lines[i].args[3] = lines[i].dy >> FRACBITS; //Friction break; case 258: //FOF: Laser lines[i].args[0] = lines[i].tag; diff --git a/src/p_spec.c b/src/p_spec.c index ade4501a6..4bc02ba79 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6887,16 +6887,14 @@ void P_SpawnSpecials(boolean fromnetsave) } case 257: // Quicksand ffloorflags = FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES; - if (!(lines[i].args[2] & TMFQ_NORIPPLE)) + if (!(lines[i].args[1])) ffloorflags |= FF_RIPPLE; - if (lines[i].args[2] & TMFQ_SPLAT) - ffloorflags |= FF_SPLAT; for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0 ;) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers); - fflr->sinkspeed = abs(lines[i].args[3]) << (FRACBITS - 1); - fflr->friction = abs(lines[i].args[4]) << (FRACBITS - 6); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, ffloorflags, secthinkers); + fflr->sinkspeed = abs(lines[i].args[2]) << (FRACBITS - 1); + fflr->friction = abs(lines[i].args[3]) << (FRACBITS - 6); } break; diff --git a/src/p_spec.h b/src/p_spec.h index 52dcf6786..94648b840 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -96,12 +96,6 @@ typedef enum TMFB_SPLAT = 1<<3, } textmapfofbustflags_t; -typedef enum -{ - TMFQ_NORIPPLE = 1, - TMFQ_SPLAT = 1<<1, -} textmapfofquicksandflags_t; - typedef enum { TMFL_NOBOSSES = 1, From ac8590132be12a864d8780619c672e36f4a20554 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 13 Jul 2020 11:09:19 +0200 Subject: [PATCH 061/326] Add a provisional GZDoom-esque 3D floor setup for the sake of immediate UDB usability. --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 45 ++++++++++++++ src/p_spec.c | 65 ++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index a899f9488..0b92442e6 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2195,6 +2195,51 @@ udmf } } } + 260 + { + title = "Generalized 3D Floor"; + id = "Sector_Set3dFloor"; + requiresactivation = false; + + arg0 + { + title = "Sector Tag"; + type = 13; + } + arg1 + { + title = "Type"; + type = 26; + default = 1; + enum + { + 1 = "Solid"; + 2 = "Water"; + 3 = "Intangible"; + } + flags + { + 4 = "Render Both Sides"; + 16 = "Invert Sides"; + } + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Disable shadowcast"; + 2 = "Double shadowcast"; + 4 = "Fog block"; + } + } + arg3 + { + title = "Opacity"; + default = 255; + } + } } linedefexecmisc diff --git a/src/p_spec.c b/src/p_spec.c index 5baf99700..c76136fb8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6963,6 +6963,71 @@ void P_SpawnSpecials(boolean fromnetsave) } break; + case 260: // GZDoom-like 3D Floor. + { + UINT8 dtype = lines[i].args[1] & 3; + UINT8 dflags1 = lines[i].args[1] - dtype; + UINT8 dflags2 = lines[i].args[2]; + UINT8 dopacity = lines[i].args[3]; + boolean isfog = false; + + if (dtype == 0) + dtype = 1; + + ffloorflags = FF_EXISTS; + + if (dflags2 & 1) ffloorflags |= FF_NOSHADE; // Disable light effects (Means no shadowcast) + if (dflags2 & 2) ffloorflags |= FF_DOUBLESHADOW; // Restrict light inside (Means doubleshadow) + if (dflags2 & 4) isfog = true; // Fog effect (Explicitly render like a fog block) + + if (dflags1 & 4) ffloorflags |= FF_BOTHPLANES|FF_ALLSIDES; // Render-inside + if (dflags1 & 16) ffloorflags |= FF_INVERTSIDES|FF_INVERTPLANES; // Invert visibility rules + + // Fog block + if (isfog) + ffloorflags |= FF_RENDERALL|FF_CUTEXTRA|FF_CUTSPRITES|FF_BOTHPLANES|FF_EXTRA|FF_FOG|FF_INVERTPLANES|FF_ALLSIDES|FF_INVERTSIDES; + else + { + ffloorflags |= FF_RENDERALL; + + // Solid + if (dtype == 1) + ffloorflags |= FF_SOLID|FF_CUTLEVEL; + // Water + else if (dtype == 2) + ffloorflags |= FF_SWIMMABLE|FF_CUTEXTRA|FF_CUTSPRITES|FF_EXTRA|FF_RIPPLE; + // Intangible + else if (dtype == 3) + ffloorflags |= FF_CUTEXTRA|FF_CUTSPRITES|FF_EXTRA; + } + + // Non-opaque + if (dopacity < 255) + { + // Invisible + if (dopacity == 0) + { + // True invisible + if (ffloorflags & FF_NOSHADE) + ffloorflags &= ~(FF_RENDERALL|FF_CUTEXTRA|FF_CUTSPRITES|FF_EXTRA|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTLEVEL); + // Shadow block + else + { + ffloorflags |= FF_CUTSPRITES; + ffloorflags &= ~(FF_RENDERALL|FF_CUTEXTRA|FF_EXTRA|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTLEVEL); + } + } + else + { + ffloorflags |= FF_TRANSLUCENT|FF_CUTEXTRA|FF_EXTRA; + ffloorflags &= ~FF_CUTLEVEL; + } + } + + P_AddFakeFloorsByLine(i, dopacity, ffloorflags, secthinkers); + } + break; + case 300: // Linedef executor (combines with sector special 974/975) and commands case 302: case 303: From ad9e3411a13e8cd23e22624ab294248c74587a04 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Tue, 27 Oct 2020 22:13:10 +0100 Subject: [PATCH 062/326] Rename bustable type BT_SPIN to BT_SPINBUST to avoid conflicts with next. --- src/dehacked.c | 2 +- src/p_mobj.c | 2 +- src/p_spec.c | 6 +++--- src/p_user.c | 6 +++--- src/r_defs.h | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 5ff4da47a..250fddd0f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9918,7 +9918,7 @@ struct { // Bustable FOF type {"BT_TOUCH",BT_TOUCH}, - {"BT_SPIN",BT_SPIN}, + {"BT_SPINBUST",BT_SPINBUST}, {"BT_REGULAR",BT_REGULAR}, {"BT_STRONG",BT_STRONG}, diff --git a/src/p_mobj.c b/src/p_mobj.c index 603375aba..2ef7452cb 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1722,7 +1722,7 @@ static void P_PushableCheckBustables(mobj_t *mo) continue; break; - case BT_SPIN: + case BT_SPINBUST: if (mo->z + mo->momz > topheight) continue; diff --git a/src/p_spec.c b/src/p_spec.c index c76136fb8..27eb24342 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6867,7 +6867,7 @@ void P_SpawnSpecials(boolean fromnetsave) busttype = BT_TOUCH; break; case TMFB_SPIN: - busttype = BT_SPIN; + busttype = BT_SPINBUST; break; case TMFB_REGULAR: busttype = BT_REGULAR; @@ -6939,7 +6939,7 @@ void P_SpawnSpecials(boolean fromnetsave) fflr->busttype = BT_TOUCH; break; case TMFB_SPIN: - fflr->busttype = BT_SPIN; + fflr->busttype = BT_SPINBUST; break; case TMFB_REGULAR: fflr->busttype = BT_REGULAR; @@ -7298,7 +7298,7 @@ void P_SpawnSpecials(boolean fromnetsave) busttype = BT_TOUCH; break; case TMFB_SPIN: - busttype = BT_SPIN; + busttype = BT_SPINBUST; break; case TMFB_REGULAR: busttype = BT_REGULAR; diff --git a/src/p_user.c b/src/p_user.c index efe03d307..e0b1d69f1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2552,7 +2552,7 @@ static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover) { case BT_TOUCH: // Shatters on contact return true; - case BT_SPIN: // Can be busted by spinning (either from jumping or spindashing) + case BT_SPINBUST: // Can be busted by spinning (either from jumping or spindashing) if ((player->pflags & PF_SPINNING) && !(player->pflags & PF_STARTDASH)) return true; @@ -2668,7 +2668,7 @@ static void P_CheckBustableBlocks(player_t *player) continue; break; - case BT_SPIN: + case BT_SPINBUST: if (player->mo->z + player->mo->momz > topheight) continue; @@ -2688,7 +2688,7 @@ static void P_CheckBustableBlocks(player_t *player) } // Impede the player's fall a bit - if (((rover->busttype == BT_TOUCH) || (rover->busttype == BT_SPIN)) && player->mo->z >= topheight) + if (((rover->busttype == BT_TOUCH) || (rover->busttype == BT_SPINBUST)) && player->mo->z >= topheight) player->mo->momz >>= 1; else if (rover->busttype == BT_TOUCH) { diff --git a/src/r_defs.h b/src/r_defs.h index fd77dd396..4cbcc49e7 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -162,7 +162,7 @@ typedef enum typedef enum { BT_TOUCH, - BT_SPIN, + BT_SPINBUST, BT_REGULAR, BT_STRONG, } busttype_e; From 5df079c65355f0b82aab7e0b1c2afd378af74d4d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 23 Jun 2021 22:21:19 +0200 Subject: [PATCH 063/326] Backwards compatibility: Add back bouncy FOF sector type, but mark it as deprecated --- extras/conf/udb/Includes/SRB222_sectors.cfg | 2 ++ src/p_spec.c | 6 +++++- src/p_user.c | 13 +++++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_sectors.cfg b/extras/conf/udb/Includes/SRB222_sectors.cfg index aebc8fa29..d0b7ba082 100644 --- a/extras/conf/udb/Includes/SRB222_sectors.cfg +++ b/extras/conf/udb/Includes/SRB222_sectors.cfg @@ -15,6 +15,7 @@ sectortypes 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)"; @@ -62,6 +63,7 @@ gen_sectortypes 12 = "Space Countdown"; 13 = "Ramp Sector (double step-up/down)"; 14 = "Non-Ramp Sector (no step-down)"; + 15 = "Bouncy FOF "; } second diff --git a/src/p_spec.c b/src/p_spec.c index 95aa8f8c9..6a5bb9451 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4336,7 +4336,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers break; case 13: // Ramp Sector (Increase step-up/down) case 14: // Non-Ramp Sector (Don't step-down) - case 15: // Unused + case 15: // Bouncy FOF (deprecated) break; } @@ -6140,6 +6140,10 @@ void P_SpawnSpecials(boolean fromnetsave) //Yes, this also affects other specials on the same sector. Sorry. sector->flags |= SF_TRIGGERSPECIAL_TOUCH; break; + case 15: // Bouncy FOF + CONS_Alert(CONS_WARNING, M_GetText("Deprecated bouncy FOF sector type detected. Please use linedef type 76 instead.\n")); + CheckForBouncySector = true; + break; } // Process Section 2 diff --git a/src/p_user.c b/src/p_user.c index 7ef6a8f37..048f2f1f9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2761,6 +2761,17 @@ static void P_CheckBouncySectors(player_t *player) if (!(rover->flags & FF_EXISTS)) continue; // FOFs should not be bouncy if they don't even "exist" + // Handle deprecated bouncy FOF sector type + if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 15) + { + rover->flags |= FF_BOUNCY; + rover->bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100; + if (rover->master->flags & ML_BOUNCY) + rover->specialflags |= FS_DAMPEN; + else + rover->specialflags &= ~FS_DAMPEN; + } + if (!(rover->flags & FF_BOUNCY)) continue; @@ -2773,8 +2784,6 @@ static void P_CheckBouncySectors(player_t *player) if (player->mo->z + player->mo->height < bottomheight) continue; - //bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100; - if (oldz < P_GetFOFTopZ(player->mo, node->m_sector, rover, oldx, oldy, NULL) && oldz + player->mo->height > P_GetFOFBottomZ(player->mo, node->m_sector, rover, oldx, oldy, NULL)) { From ffece845e47cb9b75c25587a0adc5d8953b0dce1 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 23 Jun 2021 23:02:25 +0200 Subject: [PATCH 064/326] UDB config: Add prefix to generalized 3D floor --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 0b92442e6..88a97e6ed 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2198,6 +2198,7 @@ udmf 260 { title = "Generalized 3D Floor"; + prefix = "(260)"; id = "Sector_Set3dFloor"; requiresactivation = false; From 4bedca6ba7673ebaa65c6911e078147e97559de1 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 25 Jun 2021 08:44:35 +0200 Subject: [PATCH 065/326] Rename some of the generalized 3D floor args --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 88a97e6ed..d4f24e4ab 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2204,7 +2204,7 @@ udmf arg0 { - title = "Sector Tag"; + title = "Target sector tag"; type = 13; } arg1 @@ -2220,8 +2220,8 @@ udmf } flags { - 4 = "Render Both Sides"; - 16 = "Invert Sides"; + 4 = "Render insides"; + 16 = "Only render insides"; } } arg2 @@ -2230,14 +2230,14 @@ udmf type = 12; enum { - 1 = "Disable shadowcast"; - 2 = "Double shadowcast"; - 4 = "Fog block"; + 1 = "No shadow"; + 2 = "Double shadow"; + 4 = "Fog"; } } arg3 { - title = "Opacity"; + title = "Alpha"; default = 255; } } From 7025f12d95bd68abbb0680cd5d7c75f26113ea2b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 25 Jun 2021 10:12:16 +0200 Subject: [PATCH 066/326] -Pass tag as argument to EV_ functions -Get rid of junk linedefs for specialized EV_ calls -Store tag in args[0] --- src/p_ceilng.c | 8 +++--- src/p_enemy.c | 21 +++------------ src/p_floor.c | 6 ++--- src/p_inter.c | 8 +----- src/p_setup.c | 42 ++++++++++++++++++++++++++++++ src/p_spec.c | 70 +++++++++++++++++--------------------------------- src/p_spec.h | 8 +++--- 7 files changed, 80 insertions(+), 83 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 43f3cc1d5..6349820bc 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -383,18 +383,18 @@ void T_CrushCeiling(ceiling_t *ceiling) /** Starts a ceiling mover. * + * \param tag Tag. * \param line The source line. * \param type The type of ceiling movement. * \return 1 if at least one ceiling mover was started, 0 otherwise. * \sa EV_DoCrush, EV_DoFloor, EV_DoElevator, T_MoveCeiling */ -INT32 EV_DoCeiling(line_t *line, ceiling_e type) +INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) { INT32 rtn = 0, firstone = 1; INT32 secnum = -1; sector_t *sec; ceiling_t *ceiling; - mtag_t tag = Tag_FGet(&line->tags); TAG_ITER_SECTORS(tag, secnum) { @@ -603,19 +603,19 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type) /** Starts a ceiling crusher. * + * \param tag Tag. * \param line The source line. * \param type The type of ceiling, either ::crushAndRaise or * ::fastCrushAndRaise. * \return 1 if at least one crusher was started, 0 otherwise. * \sa EV_DoCeiling, EV_DoFloor, EV_DoElevator, T_CrushCeiling */ -INT32 EV_DoCrush(line_t *line, ceiling_e type) +INT32 EV_DoCrush(mtag_t tag, line_t *line, ceiling_e type) { INT32 rtn = 0; INT32 secnum = -1; sector_t *sec; ceiling_t *ceiling; - mtag_t tag = Tag_FGet(&line->tags); TAG_ITER_SECTORS(tag, secnum) { diff --git a/src/p_enemy.c b/src/p_enemy.c index 6a92c5d33..09cd82894 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3873,7 +3873,6 @@ void A_BossDeath(mobj_t *mo) { thinker_t *th; mobj_t *mo2; - line_t junk; INT32 i; if (LUA_CallAction(A_BOSSDEATH, mo)) @@ -3925,18 +3924,11 @@ void A_BossDeath(mobj_t *mo) } else { - // Initialize my junk - junk.tags.tags = NULL; - junk.tags.count = 0; - // Bring the egg trap up to the surface // Incredibly shitty code ahead - Tag_FSet(&junk.tags, LE_CAPSULE0); - EV_DoElevator(&junk, elevateHighest, false); - Tag_FSet(&junk.tags, LE_CAPSULE1); - EV_DoElevator(&junk, elevateUp, false); - Tag_FSet(&junk.tags, LE_CAPSULE2); - EV_DoElevator(&junk, elevateHighest, false); + EV_DoElevator(LE_CAPSULE0, NULL, elevateHighest, false); + EV_DoElevator(LE_CAPSULE1, NULL, elevateUp, false); + EV_DoElevator(LE_CAPSULE2, NULL, elevateHighest, false); if (mapheaderinfo[gamemap-1]->muspostbossname[0] && S_MusicExists(mapheaderinfo[gamemap-1]->muspostbossname, !midi_disabled, !digital_disabled)) @@ -4058,12 +4050,7 @@ bossjustdie: } case MT_KOOPA: { - // Initialize my junk - junk.tags.tags = NULL; - junk.tags.count = 0; - - Tag_FSet(&junk.tags, LE_KOOPA); - EV_DoCeiling(&junk, raiseToHighest); + EV_DoCeiling(LE_KOOPA, NULL, raiseToHighest); return; } case MT_FANG: diff --git a/src/p_floor.c b/src/p_floor.c index 102ac67e0..e06f65f5c 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1805,13 +1805,12 @@ void T_PlaneDisplace(planedisplace_t *pd) // (egg capsule button), P_PlayerInSpecialSector (buttons), // and P_SpawnSpecials (continuous floor movers and instant lower). // -void EV_DoFloor(line_t *line, floor_e floortype) +void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) { INT32 firstone = 1; INT32 secnum = -1; sector_t *sec; floormove_t *dofloor; - mtag_t tag = Tag_FGet(&line->tags); TAG_ITER_SECTORS(tag, secnum) { @@ -2022,12 +2021,11 @@ void EV_DoFloor(line_t *line, floor_e floortype) // // jff 2/22/98 new type to move floor and ceiling in parallel // -void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed) +void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype, boolean customspeed) { INT32 secnum = -1; sector_t *sec; elevator_t *elevator; - mtag_t tag = Tag_FGet(&line->tags); // act on all sectors with the same tag as the triggering linedef TAG_ITER_SECTORS(tag, secnum) diff --git a/src/p_inter.c b/src/p_inter.c index 89989d1af..33052c3b8 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1381,19 +1381,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_AXE: { - line_t junk; thinker_t *th; mobj_t *mo2; if (player->bot) return; - // Initialize my junk - junk.tags.tags = NULL; - junk.tags.count = 0; - - Tag_FSet(&junk.tags, LE_AXE); - EV_DoElevator(&junk, bridgeFall, false); + EV_DoElevator(LE_AXE, NULL, bridgeFall, false); // scan the remaining thinkers to find koopa for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) diff --git a/src/p_setup.c b/src/p_setup.c index b0488dbbb..9bea8f868 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3081,6 +3081,28 @@ static void P_ConvertBinaryMap(void) break; } + case 50: //Instantly lower floor on level load + case 51: //Instantly raise ceiling on level load + lines[i].args[0] = tag; + break; + case 53: //Continuous floor/ceiling mover + case 54: //Continuous floor mover + case 55: //Continuous ceiling mover + lines[i].args[0] = tag; + break; + case 56: //Continuous two-speed floor/ceiling mover + case 57: //Continuous two-speed floor mover + case 58: //Continuous two-speed ceiling mover + lines[i].args[0] = tag; + break; + case 59: //Activate moving platform + case 60: //Activate moving platform (adjustable speed) + lines[i].args[0] = tag; + break; + case 61: //Crusher (Ceiling to floor) + case 62: //Crusher (Floor to ceiling) + lines[i].args[0] = tag; + break; case 76: //Make FOF bouncy lines[i].args[0] = tag; lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; @@ -3482,6 +3504,26 @@ static void P_ConvertBinaryMap(void) else lines[i].args[1] = 255; break; + case 400: //Set tagged sector's floor height/texture + case 401: //Set tagged sector's ceiling height/texture + lines[i].args[0] = tag; + break; + case 403: //Move tagged sector's floor + case 404: //Move tagged sector's ceiling + lines[i].args[0] = tag; + break; + case 405: //Move floor according to front texture offsets + case 407: //Move ceiling according to front texture offsets + lines[i].args[0] = tag; + break; + case 428: //Start platform movement + lines[i].args[0] = tag; + break; + case 429: //Crush ceiling once + case 430: //Crush floor once + case 431: //Crush floor and ceiling once + lines[i].args[0] = tag; + break; case 443: //Call Lua function if (lines[i].text) { diff --git a/src/p_spec.c b/src/p_spec.c index 6a5bb9451..936551e0e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2234,11 +2234,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) switch (line->special) { case 400: // Set tagged sector's floor height/pic - EV_DoFloor(line, instantMoveFloorByFrontSector); + EV_DoFloor(line->args[0], line, instantMoveFloorByFrontSector); break; case 401: // Set tagged sector's ceiling height/pic - EV_DoCeiling(line, instantMoveCeilingByFrontSector); + EV_DoCeiling(line->args[0], line, instantMoveCeilingByFrontSector); break; case 402: // Set tagged sector's light level @@ -2272,37 +2272,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 403: // Move floor, linelen = speed, frontsector floor = dest height - EV_DoFloor(line, moveFloorByFrontSector); + EV_DoFloor(line->args[0], line, moveFloorByFrontSector); break; case 404: // Move ceiling, linelen = speed, frontsector ceiling = dest height - EV_DoCeiling(line, moveCeilingByFrontSector); + EV_DoCeiling(line->args[0], line, moveCeilingByFrontSector); break; case 405: // Move floor by front side texture offsets, offset x = speed, offset y = amount to raise/lower - EV_DoFloor(line, moveFloorByFrontTexture); + EV_DoFloor(line->args[0], line, moveFloorByFrontTexture); break; case 407: // Move ceiling by front side texture offsets, offset x = speed, offset y = amount to raise/lower - EV_DoCeiling(line, moveCeilingByFrontTexture); + EV_DoCeiling(line->args[0], line, moveCeilingByFrontTexture); break; -/* case 405: // Lower floor by line, dx = speed, dy = amount to lower - EV_DoFloor(line, lowerFloorByLine); - break; - - case 406: // Raise floor by line, dx = speed, dy = amount to raise - EV_DoFloor(line, raiseFloorByLine); - break; - - case 407: // Lower ceiling by line, dx = speed, dy = amount to lower - EV_DoCeiling(line, lowerCeilingByLine); - break; - - case 408: // Raise ceiling by line, dx = speed, dy = amount to raise - EV_DoCeiling(line, raiseCeilingByLine); - break;*/ - case 409: // Change tagged sectors' tag // (formerly "Change calling sectors' tag", but behavior was changed) { @@ -2886,19 +2870,19 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 428: // Start floating platform movement - EV_DoElevator(line, elevateContinuous, true); + EV_DoElevator(line->args[0], line, elevateContinuous, true); break; case 429: // Crush Ceiling Down Once - EV_DoCrush(line, crushCeilOnce); + EV_DoCrush(line->args[0], line, crushCeilOnce); break; case 430: // Crush Floor Up Once - EV_DoFloor(line, crushFloorOnce); + EV_DoFloor(line->args[0], line, crushFloorOnce); break; case 431: // Crush Floor & Ceiling to middle Once - EV_DoCrush(line, crushBothOnce); + EV_DoCrush(line->args[0], line, crushBothOnce); break; case 432: // Enable 2D Mode (Disable if noclimb) @@ -4414,7 +4398,6 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers { thinker_t *th; mobj_t *mo2; - line_t junk; if (player->bot || sector->ceilingdata || sector->floordata) return; @@ -4434,20 +4417,13 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers // clear the special so you can't push the button twice. sector->special = 0; - // Initialize my junk - junk.tags.tags = NULL; - junk.tags.count = 0; - // Move the button down - Tag_FSet(&junk.tags, LE_CAPSULE0); - EV_DoElevator(&junk, elevateDown, false); + EV_DoElevator(LE_CAPSULE0, NULL, elevateDown, false); // Open the top FOF - Tag_FSet(&junk.tags, LE_CAPSULE1); - EV_DoFloor(&junk, raiseFloorToNearestFast); + EV_DoFloor(LE_CAPSULE1, NULL, raiseFloorToNearestFast); // Open the bottom FOF - Tag_FSet(&junk.tags, LE_CAPSULE2); - EV_DoCeiling(&junk, lowerToLowestFast); + EV_DoCeiling(LE_CAPSULE2, NULL, lowerToLowestFast); // Mark all players with the time to exit thingy! for (i = 0; i < MAXPLAYERS; i++) @@ -6342,11 +6318,11 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 50: // Insta-Lower Sector - EV_DoFloor(&lines[i], instantLower); + EV_DoFloor(lines[i].args[0], &lines[i], instantLower); break; case 51: // Instant raise for ceilings - EV_DoCeiling(&lines[i], instantRaise); + EV_DoCeiling(lines[i].args[0], &lines[i], instantRaise); break; case 52: // Continuously Falling sector @@ -6356,20 +6332,20 @@ void P_SpawnSpecials(boolean fromnetsave) case 53: // New super cool and awesome moving floor and ceiling type case 54: // New super cool and awesome moving floor type if (lines[i].backsector) - EV_DoFloor(&lines[i], bounceFloor); + EV_DoFloor(lines[i].args[0], &lines[i], bounceFloor); if (lines[i].special == 54) break; /* FALLTHRU */ case 55: // New super cool and awesome moving ceiling type if (lines[i].backsector) - EV_DoCeiling(&lines[i], bounceCeiling); + EV_DoCeiling(lines[i].args[0], &lines[i], bounceCeiling); break; case 56: // New super cool and awesome moving floor and ceiling crush type case 57: // New super cool and awesome moving floor crush type if (lines[i].backsector) - EV_DoFloor(&lines[i], bounceFloorCrush); + EV_DoFloor(lines[i].args[0], &lines[i], bounceFloorCrush); if (lines[i].special == 57) break; //only move the floor @@ -6377,23 +6353,23 @@ void P_SpawnSpecials(boolean fromnetsave) case 58: // New super cool and awesome moving ceiling crush type if (lines[i].backsector) - EV_DoCeiling(&lines[i], bounceCeilingCrush); + EV_DoCeiling(lines[i].args[0], &lines[i], bounceCeilingCrush); break; case 59: // Activate floating platform - EV_DoElevator(&lines[i], elevateContinuous, false); + EV_DoElevator(lines[i].args[0], &lines[i], elevateContinuous, false); break; case 60: // Floating platform with adjustable speed - EV_DoElevator(&lines[i], elevateContinuous, true); + EV_DoElevator(lines[i].args[0], &lines[i], elevateContinuous, true); break; case 61: // Crusher! - EV_DoCrush(&lines[i], crushAndRaise); + EV_DoCrush(lines[i].args[0], &lines[i], crushAndRaise); break; case 62: // Crusher (up and then down)! - EV_DoCrush(&lines[i], fastCrushAndRaise); + EV_DoCrush(lines[i].args[0], &lines[i], fastCrushAndRaise); break; case 63: // support for drawn heights coming from different sector diff --git a/src/p_spec.h b/src/p_spec.h index 536b6c313..a06c677e3 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -307,9 +307,9 @@ typedef struct #define CEILSPEED (FRACUNIT) -INT32 EV_DoCeiling(line_t *line, ceiling_e type); +INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type); -INT32 EV_DoCrush(line_t *line, ceiling_e type); +INT32 EV_DoCrush(mtag_t tag, line_t *line, ceiling_e type); void T_CrushCeiling(ceiling_t *ceiling); void T_MoveCeiling(ceiling_t *ceiling); @@ -520,8 +520,8 @@ typedef enum result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crush, boolean ceiling, INT32 direction); -void EV_DoFloor(line_t *line, floor_e floortype); -void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed); +void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype); +void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype, boolean customspeed); void EV_CrumbleChain(sector_t *sec, ffloor_t *rover); void EV_BounceSector(sector_t *sector, fixed_t momz, line_t *sourceline); From 259700be3c4b2fc894c7232697dd581c0bc81e3e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 25 Jun 2021 11:11:16 +0200 Subject: [PATCH 067/326] Get rid of customspeed in EV_DoElevator and read speed from args[1] --- src/p_enemy.c | 6 +++--- src/p_floor.c | 33 ++++++-------------------------- src/p_inter.c | 2 +- src/p_setup.c | 7 +++++++ src/p_spec.c | 53 +++++++++++++++++++++------------------------------ src/p_spec.h | 2 +- 6 files changed, 40 insertions(+), 63 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 09cd82894..6fa653c0e 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3926,9 +3926,9 @@ void A_BossDeath(mobj_t *mo) { // Bring the egg trap up to the surface // Incredibly shitty code ahead - EV_DoElevator(LE_CAPSULE0, NULL, elevateHighest, false); - EV_DoElevator(LE_CAPSULE1, NULL, elevateUp, false); - EV_DoElevator(LE_CAPSULE2, NULL, elevateHighest, false); + EV_DoElevator(LE_CAPSULE0, NULL, elevateHighest); + EV_DoElevator(LE_CAPSULE1, NULL, elevateUp); + EV_DoElevator(LE_CAPSULE2, NULL, elevateHighest); if (mapheaderinfo[gamemap-1]->muspostbossname[0] && S_MusicExists(mapheaderinfo[gamemap-1]->muspostbossname, !midi_disabled, !digital_disabled)) diff --git a/src/p_floor.c b/src/p_floor.c index e06f65f5c..604f110ff 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2021,13 +2021,13 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) // // jff 2/22/98 new type to move floor and ceiling in parallel // -void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype, boolean customspeed) +void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype) { INT32 secnum = -1; sector_t *sec; elevator_t *elevator; - // act on all sectors with the same tag as the triggering linedef + // act on all sectors with the given tag TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; @@ -2055,8 +2055,6 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype, boolean custom elevator->sector = sec; elevator->speed = ELEVATORSPEED/2; // half speed elevator->floordestheight = P_FindNextLowestFloor(sec, sec->floorheight); - elevator->ceilingdestheight = elevator->floordestheight - + sec->ceilingheight - sec->floorheight; break; // elevator up to next floor @@ -2065,8 +2063,6 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype, boolean custom elevator->sector = sec; elevator->speed = ELEVATORSPEED/4; // quarter speed elevator->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight); - elevator->ceilingdestheight = elevator->floordestheight - + sec->ceilingheight - sec->floorheight; break; // elevator up to highest floor @@ -2075,8 +2071,6 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype, boolean custom elevator->sector = sec; elevator->speed = ELEVATORSPEED/4; // quarter speed elevator->floordestheight = P_FindHighestFloorSurrounding(sec); - elevator->ceilingdestheight = elevator->floordestheight - + sec->ceilingheight - sec->floorheight; break; // elevator to floor height of activating switch's front sector @@ -2084,23 +2078,12 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype, boolean custom elevator->sector = sec; elevator->speed = ELEVATORSPEED; elevator->floordestheight = line->frontsector->floorheight; - elevator->ceilingdestheight = elevator->floordestheight - + sec->ceilingheight - sec->floorheight; elevator->direction = elevator->floordestheight > sec->floorheight? 1 : -1; break; case elevateContinuous: - if (customspeed) - { - elevator->origspeed = P_AproxDistance(line->dx, line->dy); - elevator->origspeed = FixedDiv(elevator->origspeed,4*FRACUNIT); - elevator->speed = elevator->origspeed; - } - else - { - elevator->speed = ELEVATORSPEED/2; - elevator->origspeed = elevator->speed; - } + elevator->origspeed = line->args[1] << (FRACBITS - 2); + elevator->speed = elevator->origspeed; elevator->sector = sec; elevator->low = !(line->flags & ML_NOCLIMB); // go down first unless noclimb is on @@ -2108,15 +2091,11 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype, boolean custom { elevator->direction = 1; elevator->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight); - elevator->ceilingdestheight = elevator->floordestheight - + sec->ceilingheight - sec->floorheight; } else { elevator->direction = -1; elevator->floordestheight = P_FindNextLowestFloor(sec,sec->floorheight); - elevator->ceilingdestheight = elevator->floordestheight - + sec->ceilingheight - sec->floorheight; } elevator->floorwasheight = elevator->sector->floorheight; elevator->ceilingwasheight = elevator->sector->ceilingheight; @@ -2130,13 +2109,13 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype, boolean custom elevator->sector = sec; elevator->speed = ELEVATORSPEED*4; // quadruple speed elevator->floordestheight = P_FindNextLowestFloor(sec, sec->floorheight); - elevator->ceilingdestheight = elevator->floordestheight - + sec->ceilingheight - sec->floorheight; break; default: break; } + + elevator->ceilingdestheight = elevator->floordestheight + sec->ceilingheight - sec->floorheight; } } diff --git a/src/p_inter.c b/src/p_inter.c index 33052c3b8..6689165ea 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1387,7 +1387,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->bot) return; - EV_DoElevator(LE_AXE, NULL, bridgeFall, false); + EV_DoElevator(LE_AXE, NULL, bridgeFall); // scan the remaining thinkers to find koopa for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) diff --git a/src/p_setup.c b/src/p_setup.c index 9bea8f868..67d5f669f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3089,15 +3089,21 @@ static void P_ConvertBinaryMap(void) case 54: //Continuous floor mover case 55: //Continuous ceiling mover lines[i].args[0] = tag; + lines[i].args[1] = (lines[i].special == 53) ? 2 : lines[i].special - 54; + lines[i].special = 53; break; case 56: //Continuous two-speed floor/ceiling mover case 57: //Continuous two-speed floor mover case 58: //Continuous two-speed ceiling mover lines[i].args[0] = tag; + lines[i].args[1] = (lines[i].special == 56) ? 2 : lines[i].special - 57; + lines[i].special = 56; break; case 59: //Activate moving platform case 60: //Activate moving platform (adjustable speed) lines[i].args[0] = tag; + lines[i].args[1] = (lines[i].special == 60) ? P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS : 8; + lines[i].special = 60; break; case 61: //Crusher (Ceiling to floor) case 62: //Crusher (Floor to ceiling) @@ -3518,6 +3524,7 @@ static void P_ConvertBinaryMap(void) break; case 428: //Start platform movement lines[i].args[0] = tag; + lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; break; case 429: //Crush ceiling once case 430: //Crush floor once diff --git a/src/p_spec.c b/src/p_spec.c index 936551e0e..e72013590 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2870,7 +2870,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 428: // Start floating platform movement - EV_DoElevator(line->args[0], line, elevateContinuous, true); + EV_DoElevator(line->args[0], line, elevateContinuous); break; case 429: // Crush Ceiling Down Once @@ -4418,7 +4418,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers sector->special = 0; // Move the button down - EV_DoElevator(LE_CAPSULE0, NULL, elevateDown, false); + EV_DoElevator(LE_CAPSULE0, NULL, elevateDown); // Open the top FOF EV_DoFloor(LE_CAPSULE1, NULL, raiseFloorToNearestFast); @@ -6318,50 +6318,41 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 50: // Insta-Lower Sector - EV_DoFloor(lines[i].args[0], &lines[i], instantLower); + if (!udmf) + EV_DoFloor(lines[i].args[0], &lines[i], instantLower); break; case 51: // Instant raise for ceilings - EV_DoCeiling(lines[i].args[0], &lines[i], instantRaise); + if (!udmf) + EV_DoCeiling(lines[i].args[1], &lines[i], instantRaise); break; case 52: // Continuously Falling sector EV_DoContinuousFall(lines[i].frontsector, lines[i].backsector, P_AproxDistance(lines[i].dx, lines[i].dy), (lines[i].flags & ML_NOCLIMB)); break; - case 53: // New super cool and awesome moving floor and ceiling type - case 54: // New super cool and awesome moving floor type + case 53: // Continuous plane movement (slowdown) if (lines[i].backsector) - EV_DoFloor(lines[i].args[0], &lines[i], bounceFloor); - if (lines[i].special == 54) - break; - /* FALLTHRU */ - - case 55: // New super cool and awesome moving ceiling type - if (lines[i].backsector) - EV_DoCeiling(lines[i].args[0], &lines[i], bounceCeiling); + { + if (lines[i].args[1] != 1) + EV_DoFloor(lines[i].args[0], &lines[i], bounceFloor); + if (lines[i].args[1] != 0) + EV_DoCeiling(lines[i].args[0], &lines[i], bounceCeiling); + } break; - case 56: // New super cool and awesome moving floor and ceiling crush type - case 57: // New super cool and awesome moving floor crush type + case 56: // Continuous plane movement (constant) if (lines[i].backsector) - EV_DoFloor(lines[i].args[0], &lines[i], bounceFloorCrush); - - if (lines[i].special == 57) - break; //only move the floor - /* FALLTHRU */ - - case 58: // New super cool and awesome moving ceiling crush type - if (lines[i].backsector) - EV_DoCeiling(lines[i].args[0], &lines[i], bounceCeilingCrush); + { + if (lines[i].args[1] != 1) + EV_DoFloor(lines[i].args[0], &lines[i], bounceFloorCrush); + if (lines[i].args[1] != 0) + EV_DoCeiling(lines[i].args[0], &lines[i], bounceCeilingCrush); + } break; - case 59: // Activate floating platform - EV_DoElevator(lines[i].args[0], &lines[i], elevateContinuous, false); - break; - - case 60: // Floating platform with adjustable speed - EV_DoElevator(lines[i].args[0], &lines[i], elevateContinuous, true); + case 60: // Moving platform + EV_DoElevator(lines[i].args[0], &lines[i], elevateContinuous); break; case 61: // Crusher! diff --git a/src/p_spec.h b/src/p_spec.h index a06c677e3..1829188a9 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -521,7 +521,7 @@ typedef enum result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crush, boolean ceiling, INT32 direction); void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype); -void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype, boolean customspeed); +void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype); void EV_CrumbleChain(sector_t *sec, ffloor_t *rover); void EV_BounceSector(sector_t *sector, fixed_t momz, line_t *sourceline); From 770612bc9d4846c6c6b7bea58f3b05f4cb06a77d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 25 Jun 2021 11:33:16 +0200 Subject: [PATCH 068/326] Adapt moving platform linedef specials to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 76 ++++++++++++++++++++ src/p_floor.c | 13 ++-- src/p_setup.c | 6 ++ 3 files changed, 86 insertions(+), 9 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index d4f24e4ab..4c35e8723 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1566,6 +1566,44 @@ udmf } } + planemove + { + title = "Plane Movement"; + + 60 + { + title = "Activate Moving Platform"; + prefix = "(60)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Starting delay"; + } + arg3 + { + title = "Delay before flip"; + } + arg4 + { + title = "Starting direction"; + type = 11; + enum + { + 0 = "Down"; + 1 = "Up"; + } + } + } + } + fofmodifiers { title = "FOF Modifiers"; @@ -2243,6 +2281,44 @@ udmf } } + linedefexecplane + { + title = "Linedef Executor (plane movement)"; + + 428 + { + title = "Start Platform Movement"; + prefix = "(428)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Starting delay"; + } + arg3 + { + title = "Delay before flip"; + } + arg4 + { + title = "Starting direction"; + type = 11; + enum + { + 0 = "Down"; + 1 = "Up"; + } + } + } + } + linedefexecmisc { title = "Linedef Executor (misc.)"; diff --git a/src/p_floor.c b/src/p_floor.c index 604f110ff..4ff319f1a 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2045,6 +2045,7 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype) elevator->type = elevtype; elevator->sourceline = line; elevator->distance = 1; // Always crush unless otherwise + elevator->sector = sec; // set up the fields according to the type of elevator action switch (elevtype) @@ -2052,7 +2053,6 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype) // elevator down to next floor case elevateDown: elevator->direction = -1; - elevator->sector = sec; elevator->speed = ELEVATORSPEED/2; // half speed elevator->floordestheight = P_FindNextLowestFloor(sec, sec->floorheight); break; @@ -2060,7 +2060,6 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype) // elevator up to next floor case elevateUp: elevator->direction = 1; - elevator->sector = sec; elevator->speed = ELEVATORSPEED/4; // quarter speed elevator->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight); break; @@ -2068,14 +2067,12 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype) // elevator up to highest floor case elevateHighest: elevator->direction = 1; - elevator->sector = sec; elevator->speed = ELEVATORSPEED/4; // quarter speed elevator->floordestheight = P_FindHighestFloorSurrounding(sec); break; // elevator to floor height of activating switch's front sector case elevateCurrent: - elevator->sector = sec; elevator->speed = ELEVATORSPEED; elevator->floordestheight = line->frontsector->floorheight; elevator->direction = elevator->floordestheight > sec->floorheight? 1 : -1; @@ -2085,8 +2082,7 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype) elevator->origspeed = line->args[1] << (FRACBITS - 2); elevator->speed = elevator->origspeed; - elevator->sector = sec; - elevator->low = !(line->flags & ML_NOCLIMB); // go down first unless noclimb is on + elevator->low = !line->args[4]; // go down first unless args[4] is set if (elevator->low) { elevator->direction = 1; @@ -2100,13 +2096,12 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype) elevator->floorwasheight = elevator->sector->floorheight; elevator->ceilingwasheight = elevator->sector->ceilingheight; - elevator->delay = sides[line->sidenum[0]].textureoffset >> FRACBITS; - elevator->delaytimer = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Initial delay + elevator->delay = line->args[3]; + elevator->delaytimer = line->args[2]; // Initial delay break; case bridgeFall: elevator->direction = -1; - elevator->sector = sec; elevator->speed = ELEVATORSPEED*4; // quadruple speed elevator->floordestheight = P_FindNextLowestFloor(sec, sec->floorheight); break; diff --git a/src/p_setup.c b/src/p_setup.c index 67d5f669f..324fe5f17 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3103,6 +3103,9 @@ static void P_ConvertBinaryMap(void) case 60: //Activate moving platform (adjustable speed) lines[i].args[0] = tag; lines[i].args[1] = (lines[i].special == 60) ? P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS : 8; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[3] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[4] = (lines[i].flags & ML_NOCLIMB) ? 1 : 0; lines[i].special = 60; break; case 61: //Crusher (Ceiling to floor) @@ -3525,6 +3528,9 @@ static void P_ConvertBinaryMap(void) case 428: //Start platform movement lines[i].args[0] = tag; lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[3] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[4] = (lines[i].flags & ML_NOCLIMB) ? 1 : 0; break; case 429: //Crush ceiling once case 430: //Crush floor once From 825b4b384ae4854153733dfe0456c95036408af7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 25 Jun 2021 11:40:19 +0200 Subject: [PATCH 069/326] Remove unused elevateCurrent elevator type --- src/p_floor.c | 7 ------- src/p_spec.h | 1 - 2 files changed, 8 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index 4ff319f1a..e6d5684e3 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2071,13 +2071,6 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype) elevator->floordestheight = P_FindHighestFloorSurrounding(sec); break; - // elevator to floor height of activating switch's front sector - case elevateCurrent: - elevator->speed = ELEVATORSPEED; - elevator->floordestheight = line->frontsector->floorheight; - elevator->direction = elevator->floordestheight > sec->floorheight? 1 : -1; - break; - case elevateContinuous: elevator->origspeed = line->args[1] << (FRACBITS - 2); elevator->speed = elevator->origspeed; diff --git a/src/p_spec.h b/src/p_spec.h index 1829188a9..4e1e949b2 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -343,7 +343,6 @@ typedef enum { elevateUp, elevateDown, - elevateCurrent, elevateContinuous, elevateBounce, elevateHighest, From 6abcba6876ede5b9c92846a5b3f1057230ee6705 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 25 Jun 2021 18:34:56 +0200 Subject: [PATCH 070/326] Adapt linedef types 400-401 to UDMF + some EV_ cleanup --- src/p_ceilng.c | 61 +++++++++++++++----------------------------------- src/p_floor.c | 49 +++++----------------------------------- src/p_setup.c | 3 +++ src/p_spec.c | 11 +++++---- src/p_spec.h | 6 ----- 5 files changed, 32 insertions(+), 98 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 6349820bc..418145265 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -80,7 +80,6 @@ void T_MoveCeiling(ceiling_t *ceiling) ceiling->sector->ceilingpic = ceiling->texture; /* FALLTHRU */ case raiseToHighest: -// case raiseCeilingByLine: case moveCeilingByFrontTexture: ceiling->sector->ceilingdata = NULL; ceiling->sector->ceilspeed = 0; @@ -202,10 +201,6 @@ void T_MoveCeiling(ceiling_t *ceiling) /* FALLTHRU */ // in all other cases, just remove the active ceiling - case lowerAndCrush: - case lowerToLowest: - case raiseToLowest: -// case lowerCeilingByLine: case moveCeilingByFrontTexture: ceiling->sector->ceilingdata = NULL; ceiling->sector->ceilspeed = 0; @@ -279,7 +274,6 @@ void T_MoveCeiling(ceiling_t *ceiling) switch (ceiling->type) { case crushAndRaise: - case lowerAndCrush: ceiling->speed = FixedDiv(CEILSPEED,8*FRACUNIT); break; @@ -426,8 +420,6 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) case crushAndRaise: ceiling->crush = true; ceiling->topheight = sec->ceilingheight; - /* FALLTHRU */ - case lowerAndCrush: ceiling->bottomheight = sec->floorheight; ceiling->bottomheight += 4*FRACUNIT; ceiling->direction = -1; @@ -440,19 +432,6 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) ceiling->speed = CEILSPEED; break; - //SoM: 3/6/2000: Added Boom types - case lowerToLowest: - ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec); - ceiling->direction = -1; - ceiling->speed = CEILSPEED; - break; - - case raiseToLowest: // Graue 09-07-2004 - ceiling->topheight = P_FindLowestCeilingSurrounding(sec) - 4*FRACUNIT; - ceiling->direction = 1; - ceiling->speed = line->dx; // hack - break; - case lowerToLowestFast: ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec); ceiling->direction = -1; @@ -502,17 +481,27 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) case instantMoveCeilingByFrontSector: ceiling->speed = INT32_MAX/2; - if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up + if (lines->args[1] & 2) + { + if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up + { + ceiling->direction = 1; + ceiling->topheight = line->frontsector->ceilingheight; + } + else // Move down + { + ceiling->direction = -1; + ceiling->bottomheight = line->frontsector->ceilingheight; + } + } + else { ceiling->direction = 1; - ceiling->topheight = line->frontsector->ceilingheight; + ceiling->topheight = sec->ceilingheight; } - else // Move down - { - ceiling->direction = -1; - ceiling->bottomheight = line->frontsector->ceilingheight; - } - ceiling->texture = line->frontsector->ceilingpic; + + // If flag is set, change ceiling texture after moving + ceiling->texture = (line->args[2] & 2) ? line->frontsector->ceilingpic : -1; break; case moveCeilingByFrontTexture: @@ -531,20 +520,6 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) } break; -/* - case lowerCeilingByLine: - ceiling->speed = FixedDiv(abs(line->dx),8*FRACUNIT); - ceiling->direction = -1; // Move down - ceiling->bottomheight = sec->ceilingheight - abs(line->dy); - break; - - case raiseCeilingByLine: - ceiling->speed = FixedDiv(abs(line->dx),8*FRACUNIT); - ceiling->direction = 1; // Move up - ceiling->topheight = sec->ceilingheight + abs(line->dy); - break; -*/ - case bounceCeiling: ceiling->speed = P_AproxDistance(line->dx, line->dy); // same speed as elevateContinuous ceiling->speed = FixedDiv(ceiling->speed,4*FRACUNIT); diff --git a/src/p_floor.c b/src/p_floor.c index e6d5684e3..0ee70ece7 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1834,23 +1834,15 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) switch (floortype) { - // Lowers a floor to the lowest surrounding floor. - case lowerFloorToLowest: - dofloor->direction = -1; // down - dofloor->speed = FLOORSPEED*2; // 2 fracunits per tic - dofloor->floordestheight = P_FindLowestFloorSurrounding(sec); - break; - - // Used for part of the Egg Capsule, when an FOF with type 666 is - // contacted by the player. + // Used to open the top of an Egg Capsule. case raiseFloorToNearestFast: dofloor->direction = -1; // down dofloor->speed = FLOORSPEED*4; // 4 fracunits per tic dofloor->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight); break; - // Used for sectors tagged to 50 linedefs (effectively - // changing the base height for placing things in that sector). + // Instantly lower floor to surrounding sectors. + // Used as a hack in the binary map format to allow thing heights above 4096. case instantLower: dofloor->direction = -1; // down dofloor->speed = INT32_MAX/2; // "instant" means "takes one tic" @@ -1861,22 +1853,15 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) // Front sector floor = destination height. case instantMoveFloorByFrontSector: dofloor->speed = INT32_MAX/2; // as above, "instant" is one tic - dofloor->floordestheight = line->frontsector->floorheight; + dofloor->floordestheight = (line->args[1] & 1) ? line->frontsector->floorheight : sec->floorheight; if (dofloor->floordestheight >= sec->floorheight) dofloor->direction = 1; // up else dofloor->direction = -1; // down - // New for 1.09: now you can use the no climb flag to - // DISABLE the flat changing. This makes it work - // totally opposite the way linetype 106 does. Yet - // another reason I'll be glad to break backwards - // compatibility for the final. - if (line->flags & ML_NOCLIMB) - dofloor->texture = -1; // don't mess with the floorpic - else - dofloor->texture = line->frontsector->floorpic; + // If flag is set, change floor texture after moving + dofloor->texture = (line->args[2] & 1) ? line->frontsector->floorpic : -1; break; // Linedef executor command, linetype 106. @@ -1923,28 +1908,6 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) dofloor->direction = -1; // down break; -/* - // Linedef executor command, linetype 108. - // dx = speed, dy = amount to lower. - case lowerFloorByLine: - dofloor->direction = -1; // down - dofloor->speed = FixedDiv(abs(line->dx),8*FRACUNIT); - dofloor->floordestheight = sec->floorheight - abs(line->dy); - if (dofloor->floordestheight > sec->floorheight) // wrapped around - I_Error("Can't lower sector %d\n", secnum); - break; - - // Linedef executor command, linetype 109. - // dx = speed, dy = amount to raise. - case raiseFloorByLine: - dofloor->direction = 1; // up - dofloor->speed = FixedDiv(abs(line->dx),8*FRACUNIT); - dofloor->floordestheight = sec->floorheight + abs(line->dy); - if (dofloor->floordestheight < sec->floorheight) // wrapped around - I_Error("Can't raise sector %d\n", secnum); - break; -*/ - // Linetypes 2/3. // Move floor up and down indefinitely like the old elevators. case bounceFloor: diff --git a/src/p_setup.c b/src/p_setup.c index 324fe5f17..97ea643cf 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3516,6 +3516,9 @@ static void P_ConvertBinaryMap(void) case 400: //Set tagged sector's floor height/texture case 401: //Set tagged sector's ceiling height/texture lines[i].args[0] = tag; + lines[i].args[1] = lines[i].special - 399; + lines[i].args[2] = (lines[i].flags & ML_NOCLIMB) ? 0 : lines[i].special - 399; + lines[i].special = 400; break; case 403: //Move tagged sector's floor case 404: //Move tagged sector's ceiling diff --git a/src/p_spec.c b/src/p_spec.c index e72013590..de27718c6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2233,12 +2233,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // note: only commands with linedef types >= 400 && < 500 can be used switch (line->special) { - case 400: // Set tagged sector's floor height/pic - EV_DoFloor(line->args[0], line, instantMoveFloorByFrontSector); - break; - - case 401: // Set tagged sector's ceiling height/pic - EV_DoCeiling(line->args[0], line, instantMoveCeilingByFrontSector); + case 400: // Set tagged sector's heights/flats + if (line->args[1] & 1 || line->args[2] & 1) + EV_DoFloor(line->args[0], line, instantMoveFloorByFrontSector); + if (line->args[1] & 2 || line->args[2] & 2) + EV_DoCeiling(line->args[0], line, instantMoveCeilingByFrontSector); break; case 402: // Set tagged sector's light level diff --git a/src/p_spec.h b/src/p_spec.h index 4e1e949b2..e03f745ce 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -259,13 +259,10 @@ typedef enum typedef enum { raiseToHighest, - lowerToLowest, - raiseToLowest, lowerToLowestFast, instantRaise, // instant-move for ceilings - lowerAndCrush, crushAndRaise, fastCrushAndRaise, crushCeilOnce, @@ -319,9 +316,6 @@ void T_MoveCeiling(ceiling_t *ceiling); // typedef enum { - // lower floor to lowest surrounding floor - lowerFloorToLowest, - // raise floor to next highest surrounding floor raiseFloorToNearestFast, From df965b157882f76caf996125f8618deb95e0b00b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 25 Jun 2021 18:41:14 +0200 Subject: [PATCH 071/326] Fix thwomps going too fast by a factor of 8 --- src/p_spec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 6a5bb9451..a3c356194 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6476,7 +6476,7 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[l].special < 100 || lines[l].special >= 300) continue; - P_AddThwompThinker(lines[l].frontsector, &lines[l], lines[i].args[1] << FRACBITS, lines[i].args[2] << FRACBITS, sound); + P_AddThwompThinker(lines[l].frontsector, &lines[l], lines[i].args[1] << (FRACBITS - 3), lines[i].args[2] << (FRACBITS - 3), sound); } } break; @@ -6731,7 +6731,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 251: // A THWOMP! { UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; - P_AddThwompThinker(lines[i].frontsector, &lines[i], lines[i].args[1] << FRACBITS, lines[i].args[2] << FRACBITS, sound); + P_AddThwompThinker(lines[i].frontsector, &lines[i], lines[i].args[1] << (FRACBITS - 3), lines[i].args[2] << (FRACBITS - 3), sound); P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); break; } From 0eabbf0170d00e1cd06d83707213c21d90f2ba7d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 25 Jun 2021 22:06:04 +0200 Subject: [PATCH 072/326] Instant ceiling movement: Only change texture if it's not -1 --- src/p_ceilng.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 418145265..1debca35b 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -67,7 +67,8 @@ void T_MoveCeiling(ceiling_t *ceiling) switch (ceiling->type) { case instantMoveCeilingByFrontSector: - ceiling->sector->ceilingpic = ceiling->texture; + if (ceiling->texture > -1) // flat changing + ceiling->sector->ceilingpic = ceiling->texture; ceiling->sector->ceilingdata = NULL; ceiling->sector->ceilspeed = 0; P_RemoveThinker(&ceiling->thinker); @@ -185,7 +186,8 @@ void T_MoveCeiling(ceiling_t *ceiling) break; case instantMoveCeilingByFrontSector: - ceiling->sector->ceilingpic = ceiling->texture; + if (ceiling->texture > -1) // flat changing + ceiling->sector->ceilingpic = ceiling->texture; ceiling->sector->ceilingdata = NULL; ceiling->sector->ceilspeed = 0; P_RemoveThinker(&ceiling->thinker); From 53976e4b52f22f529a1715392475bfa9ac9e9f51 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 08:31:59 +0200 Subject: [PATCH 073/326] Adapt linedef types 403-404 to UDMF --- src/p_ceilng.c | 18 +++++------------- src/p_floor.c | 21 +++++---------------- src/p_setup.c | 16 ++++++++++++++++ src/p_spec.c | 11 +++++------ 4 files changed, 31 insertions(+), 35 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 1debca35b..65bdd025b 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -448,8 +448,7 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) // Linedef executor excellence case moveCeilingByFrontSector: - ceiling->speed = P_AproxDistance(line->dx, line->dy); - ceiling->speed = FixedDiv(ceiling->speed,8*FRACUNIT); + ceiling->speed = line->args[2] << (FRACBITS - 3); if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up { ceiling->direction = 1; @@ -462,18 +461,11 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) } // chained linedef executing ability - if (line->flags & ML_BLOCKMONSTERS) - { - // only set it on ONE of the moving sectors (the smallest numbered) - // and front side x offset must be positive - if (firstone && sides[line->sidenum[0]].textureoffset > 0) - ceiling->texture = (sides[line->sidenum[0]].textureoffset>>FRACBITS) - 32769; - else - ceiling->texture = -1; - } - + // only set it on ONE of the moving sectors (the smallest numbered) + if (line->args[3] > 0) + ceiling->texture = firstone ? line->args[3] - INT16_MAX - 2 : -1; // flat changing ability - else if (line->flags & ML_NOCLIMB) + else if (line->args[4]) ceiling->texture = line->frontsector->ceilingpic; else ceiling->texture = -1; diff --git a/src/p_floor.c b/src/p_floor.c index 0ee70ece7..f3d7e036e 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1864,11 +1864,8 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) dofloor->texture = (line->args[2] & 1) ? line->frontsector->floorpic : -1; break; - // Linedef executor command, linetype 106. - // Line length = speed, front sector floor = destination height. case moveFloorByFrontSector: - dofloor->speed = P_AproxDistance(line->dx, line->dy); - dofloor->speed = FixedDiv(dofloor->speed,8*FRACUNIT); + dofloor->speed = line->args[2] << (FRACBITS - 3); dofloor->floordestheight = line->frontsector->floorheight; if (dofloor->floordestheight >= sec->floorheight) @@ -1877,19 +1874,11 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) dofloor->direction = -1; // down // chained linedef executing ability - if (line->flags & ML_BLOCKMONSTERS) - { - // Only set it on one of the moving sectors (the - // smallest numbered) and only if the front side - // x offset is positive, indicating a valid tag. - if (firstone && sides[line->sidenum[0]].textureoffset > 0) - dofloor->texture = (sides[line->sidenum[0]].textureoffset>>FRACBITS) - 32769; - else - dofloor->texture = -1; - } - + // Only set it on one of the moving sectors (the smallest numbered) + if (line->args[3] > 0) + dofloor->texture = firstone ? line->args[3] - INT16_MAX - 2 : -1; // flat changing ability - else if (line->flags & ML_NOCLIMB) + else if (line->args[4]) dofloor->texture = line->frontsector->floorpic; else dofloor->texture = -1; // nothing special to do after movement completes diff --git a/src/p_setup.c b/src/p_setup.c index 97ea643cf..9f7ba9504 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3523,6 +3523,22 @@ static void P_ConvertBinaryMap(void) case 403: //Move tagged sector's floor case 404: //Move tagged sector's ceiling lines[i].args[0] = tag; + lines[i].args[1] = lines[i].special - 403; + lines[i].args[2] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + if (lines[i].flags & ML_BLOCKMONSTERS) + { + if (sides[lines[i].sidenum[0]].textureoffset > 0) + lines[i].args[3] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + else + lines[i].args[3] = 0; + lines[i].args[4] = 0; + } + else + { + lines[i].args[3] = 0; + lines[i].args[4] = !!(lines[i].flags & ML_NOCLIMB); + } + lines[i].special = 403; break; case 405: //Move floor according to front texture offsets case 407: //Move ceiling according to front texture offsets diff --git a/src/p_spec.c b/src/p_spec.c index de27718c6..4141e924f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2270,12 +2270,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; - case 403: // Move floor, linelen = speed, frontsector floor = dest height - EV_DoFloor(line->args[0], line, moveFloorByFrontSector); - break; - - case 404: // Move ceiling, linelen = speed, frontsector ceiling = dest height - EV_DoCeiling(line->args[0], line, moveCeilingByFrontSector); + case 403: // Move planes by front sector + if (line->args[1] != 1) + EV_DoFloor(line->args[0], line, moveFloorByFrontSector); + if (line->args[1] != 0) + EV_DoCeiling(line->args[0], line, moveCeilingByFrontSector); break; case 405: // Move floor by front side texture offsets, offset x = speed, offset y = amount to raise/lower From 8f39e2310583ea9fbe1cfbc9f2ab77f604c4b118 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 08:43:35 +0200 Subject: [PATCH 074/326] Adapt linedef type 405 and 407 to UDMF --- src/p_ceilng.c | 14 +++++++------- src/p_floor.c | 8 ++++---- src/p_setup.c | 5 +++++ src/p_spec.c | 11 +++++------ src/p_spec.h | 4 ++-- 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 65bdd025b..7aa504416 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -81,7 +81,7 @@ void T_MoveCeiling(ceiling_t *ceiling) ceiling->sector->ceilingpic = ceiling->texture; /* FALLTHRU */ case raiseToHighest: - case moveCeilingByFrontTexture: + case moveCeilingByDistance: ceiling->sector->ceilingdata = NULL; ceiling->sector->ceilspeed = 0; P_RemoveThinker(&ceiling->thinker); @@ -203,7 +203,7 @@ void T_MoveCeiling(ceiling_t *ceiling) /* FALLTHRU */ // in all other cases, just remove the active ceiling - case moveCeilingByFrontTexture: + case moveCeilingByDistance: ceiling->sector->ceilingdata = NULL; ceiling->sector->ceilspeed = 0; P_RemoveThinker(&ceiling->thinker); @@ -498,19 +498,19 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) ceiling->texture = (line->args[2] & 2) ? line->frontsector->ceilingpic : -1; break; - case moveCeilingByFrontTexture: - if (line->flags & ML_NOCLIMB) + case moveCeilingByDistance: + if (line->args[4]) ceiling->speed = INT32_MAX/2; // as above, "instant" is one tic else - ceiling->speed = FixedDiv(sides[line->sidenum[0]].textureoffset,8*FRACUNIT); // texture x offset + ceiling->speed = line->args[3] << (FRACBITS - 3); if (sides[line->sidenum[0]].rowoffset > 0) { ceiling->direction = 1; // up - ceiling->topheight = sec->ceilingheight + sides[line->sidenum[0]].rowoffset; // texture y offset + ceiling->topheight = sec->ceilingheight + (line->args[2] << FRACBITS); } else { ceiling->direction = -1; // down - ceiling->bottomheight = sec->ceilingheight + sides[line->sidenum[0]].rowoffset; // texture y offset + ceiling->bottomheight = sec->ceilingheight + (line->args[2] << FRACBITS); } break; diff --git a/src/p_floor.c b/src/p_floor.c index f3d7e036e..c64c1bb20 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1885,12 +1885,12 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) break; - case moveFloorByFrontTexture: - if (line->flags & ML_NOCLIMB) + case moveFloorByDistance: + if (line->args[4]) dofloor->speed = INT32_MAX/2; // as above, "instant" is one tic else - dofloor->speed = FixedDiv(sides[line->sidenum[0]].textureoffset,8*FRACUNIT); // texture x offset - dofloor->floordestheight = sec->floorheight + sides[line->sidenum[0]].rowoffset; // texture y offset + dofloor->speed = line->args[3] << (FRACBITS - 3); + dofloor->floordestheight = sec->floorheight + (line->args[2] << FRACBITS); if (dofloor->floordestheight > sec->floorheight) dofloor->direction = 1; // up else diff --git a/src/p_setup.c b/src/p_setup.c index 9f7ba9504..6e7801618 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3543,6 +3543,11 @@ static void P_ConvertBinaryMap(void) case 405: //Move floor according to front texture offsets case 407: //Move ceiling according to front texture offsets lines[i].args[0] = tag; + lines[i].args[1] = (lines[i].special == 405) ? 0 : 1; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[3] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[4] = !!(lines[i].flags & ML_NOCLIMB); + lines[i].special = 405; break; case 428: //Start platform movement lines[i].args[0] = tag; diff --git a/src/p_spec.c b/src/p_spec.c index 4141e924f..222077e3d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2277,12 +2277,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) EV_DoCeiling(line->args[0], line, moveCeilingByFrontSector); break; - case 405: // Move floor by front side texture offsets, offset x = speed, offset y = amount to raise/lower - EV_DoFloor(line->args[0], line, moveFloorByFrontTexture); - break; - - case 407: // Move ceiling by front side texture offsets, offset x = speed, offset y = amount to raise/lower - EV_DoCeiling(line->args[0], line, moveCeilingByFrontTexture); + case 405: // Move planes by distance + if (line->args[1] != 1) + EV_DoFloor(line->args[0], line, moveFloorByDistance); + if (line->args[1] != 0) + EV_DoCeiling(line->args[0], line, moveCeilingByDistance); break; case 409: // Change tagged sectors' tag diff --git a/src/p_spec.h b/src/p_spec.h index e03f745ce..e6ea5a534 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -271,7 +271,7 @@ typedef enum moveCeilingByFrontSector, instantMoveCeilingByFrontSector, - moveCeilingByFrontTexture, + moveCeilingByDistance, bounceCeiling, bounceCeilingCrush, @@ -325,7 +325,7 @@ typedef enum moveFloorByFrontSector, instantMoveFloorByFrontSector, - moveFloorByFrontTexture, + moveFloorByDistance, bounceFloor, bounceFloorCrush, From d5490132b9973471eca90d1b4f1f51ff4262575e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 09:30:17 +0200 Subject: [PATCH 075/326] Remove crusher types from T_MoveCeiling (they're handled by T_CrushCeiling) --- src/p_ceilng.c | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 7aa504416..272878876 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -88,11 +88,6 @@ void T_MoveCeiling(ceiling_t *ceiling) dontupdate = true; break; - case fastCrushAndRaise: - case crushAndRaise: - ceiling->direction = -1; - break; - case bounceCeiling: { fixed_t dest = ceiling->topheight; @@ -176,15 +171,6 @@ void T_MoveCeiling(ceiling_t *ceiling) { switch (ceiling->type) { - // make platform stop at bottom of all crusher strokes - // except generalized ones, reset speed, start back up - case crushAndRaise: - ceiling->speed = CEILSPEED; - /* FALLTHRU */ - case fastCrushAndRaise: - ceiling->direction = 1; - break; - case instantMoveCeilingByFrontSector: if (ceiling->texture > -1) // flat changing ceiling->sector->ceilingpic = ceiling->texture; @@ -267,18 +253,6 @@ void T_MoveCeiling(ceiling_t *ceiling) break; } - default: - break; - } - } - else if (res == crushed) - { - switch (ceiling->type) - { - case crushAndRaise: - ceiling->speed = FixedDiv(CEILSPEED,8*FRACUNIT); - break; - default: break; } @@ -411,23 +385,6 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) switch (type) { - case fastCrushAndRaise: - ceiling->crush = true; - ceiling->topheight = sec->ceilingheight; - ceiling->bottomheight = sec->floorheight + (8*FRACUNIT); - ceiling->direction = -1; - ceiling->speed = CEILSPEED * 2; - break; - - case crushAndRaise: - ceiling->crush = true; - ceiling->topheight = sec->ceilingheight; - ceiling->bottomheight = sec->floorheight; - ceiling->bottomheight += 4*FRACUNIT; - ceiling->direction = -1; - ceiling->speed = line->dx; - break; - case raiseToHighest: ceiling->topheight = P_FindHighestCeilingSurrounding(sec); ceiling->direction = 1; From de462f12132c0fea3822937341ecc1439316bc25 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 09:43:46 +0200 Subject: [PATCH 076/326] Refactor T_MoveCeiling --- src/p_ceilng.c | 312 +++++++++++++++---------------------------------- 1 file changed, 92 insertions(+), 220 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 272878876..a12d9d56f 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -34,7 +34,6 @@ INT32 ceilmovesound = sfx_None; void T_MoveCeiling(ceiling_t *ceiling) { result_e res; - boolean dontupdate = false; if (ceiling->delaytimer) { @@ -42,227 +41,100 @@ void T_MoveCeiling(ceiling_t *ceiling) return; } - switch (ceiling->direction) + res = T_MovePlane(ceiling->sector, ceiling->speed, (ceiling->direction == 1) ? ceiling->topheight : ceiling->bottomheight, false, true, ceiling->direction); + + if (ceiling->type == bounceCeiling) { - case 0: // IN STASIS - break; - case 1: // UP - res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight, false, true, ceiling->direction); - - if (ceiling->type == bounceCeiling) - { - const fixed_t origspeed = FixedDiv(ceiling->origspeed,(ELEVATORSPEED/2)); - const fixed_t fs = abs(ceiling->sector->ceilingheight - lines[ceiling->texture].frontsector->ceilingheight); - const fixed_t bs = abs(ceiling->sector->ceilingheight - lines[ceiling->texture].backsector->ceilingheight); - if (fs < bs) - ceiling->speed = FixedDiv(fs,25*FRACUNIT) + FRACUNIT/4; - else - ceiling->speed = FixedDiv(bs,25*FRACUNIT) + FRACUNIT/4; - - ceiling->speed = FixedMul(ceiling->speed,origspeed); - } - - if (res == pastdest) - { - switch (ceiling->type) - { - case instantMoveCeilingByFrontSector: - if (ceiling->texture > -1) // flat changing - ceiling->sector->ceilingpic = ceiling->texture; - ceiling->sector->ceilingdata = NULL; - ceiling->sector->ceilspeed = 0; - P_RemoveThinker(&ceiling->thinker); - dontupdate = true; - break; - case moveCeilingByFrontSector: - if (ceiling->texture < -1) // chained linedef executing - P_LinedefExecute((INT16)(ceiling->texture + INT16_MAX + 2), NULL, NULL); - if (ceiling->texture > -1) // flat changing - ceiling->sector->ceilingpic = ceiling->texture; - /* FALLTHRU */ - case raiseToHighest: - case moveCeilingByDistance: - ceiling->sector->ceilingdata = NULL; - ceiling->sector->ceilspeed = 0; - P_RemoveThinker(&ceiling->thinker); - dontupdate = true; - break; - - case bounceCeiling: - { - fixed_t dest = ceiling->topheight; - - if (dest == lines[ceiling->texture].frontsector->ceilingheight) - dest = lines[ceiling->texture].backsector->ceilingheight; - else - dest = lines[ceiling->texture].frontsector->ceilingheight; - - if (dest < ceiling->sector->ceilingheight) // must move down - { - ceiling->direction = -1; - ceiling->bottomheight = dest; - } - else // must move up - { - ceiling->direction = 1; - ceiling->topheight = dest; - } - - ceiling->delaytimer = ceiling->delay; - - // That's it. Do not set dontupdate, do not remove the thinker. - break; - } - - case bounceCeilingCrush: - { - fixed_t dest = ceiling->topheight; - - if (dest == lines[ceiling->texture].frontsector->ceilingheight) - { - dest = lines[ceiling->texture].backsector->ceilingheight; - ceiling->speed = ceiling->origspeed = FixedDiv(abs(lines[ceiling->texture].dy),4*FRACUNIT); // return trip, use dy - } - else - { - dest = lines[ceiling->texture].frontsector->ceilingheight; - ceiling->speed = ceiling->origspeed = FixedDiv(abs(lines[ceiling->texture].dx),4*FRACUNIT); // going frontways, use dx - } - - if (dest < ceiling->sector->ceilingheight) // must move down - { - ceiling->direction = -1; - ceiling->bottomheight = dest; - } - else // must move up - { - ceiling->direction = 1; - ceiling->topheight = dest; - } - - ceiling->delaytimer = ceiling->delay; - - // That's it. Do not set dontupdate, do not remove the thinker. - break; - } - - default: - break; - } - } - break; - - case -1: // DOWN - res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, true, ceiling->direction); - - if (ceiling->type == bounceCeiling) - { - const fixed_t origspeed = FixedDiv(ceiling->origspeed,(ELEVATORSPEED/2)); - const fixed_t fs = abs(ceiling->sector->ceilingheight - lines[ceiling->texture].frontsector->ceilingheight); - const fixed_t bs = abs(ceiling->sector->ceilingheight - lines[ceiling->texture].backsector->ceilingheight); - if (fs < bs) - ceiling->speed = FixedDiv(fs,25*FRACUNIT) + FRACUNIT/4; - else - ceiling->speed = FixedDiv(bs,25*FRACUNIT) + FRACUNIT/4; - ceiling->speed = FixedMul(ceiling->speed,origspeed); - } - - if (res == pastdest) - { - switch (ceiling->type) - { - case instantMoveCeilingByFrontSector: - if (ceiling->texture > -1) // flat changing - ceiling->sector->ceilingpic = ceiling->texture; - ceiling->sector->ceilingdata = NULL; - ceiling->sector->ceilspeed = 0; - P_RemoveThinker(&ceiling->thinker); - dontupdate = true; - break; - - case moveCeilingByFrontSector: - if (ceiling->texture < -1) // chained linedef executing - P_LinedefExecute((INT16)(ceiling->texture + INT16_MAX + 2), NULL, NULL); - if (ceiling->texture > -1) // flat changing - ceiling->sector->ceilingpic = ceiling->texture; - // don't break - /* FALLTHRU */ - - // in all other cases, just remove the active ceiling - case moveCeilingByDistance: - ceiling->sector->ceilingdata = NULL; - ceiling->sector->ceilspeed = 0; - P_RemoveThinker(&ceiling->thinker); - dontupdate = true; - break; - case bounceCeiling: - { - fixed_t dest = ceiling->bottomheight; - - if (dest == lines[ceiling->texture].frontsector->ceilingheight) - dest = lines[ceiling->texture].backsector->ceilingheight; - else - dest = lines[ceiling->texture].frontsector->ceilingheight; - - if (dest < ceiling->sector->ceilingheight) // must move down - { - ceiling->direction = -1; - ceiling->bottomheight = dest; - } - else // must move up - { - ceiling->direction = 1; - ceiling->topheight = dest; - } - - ceiling->delaytimer = ceiling->delay; - - // That's it. Do not set dontupdate, do not remove the thinker. - break; - } - - case bounceCeilingCrush: - { - fixed_t dest = ceiling->bottomheight; - - if (dest == lines[ceiling->texture].frontsector->ceilingheight) - { - dest = lines[ceiling->texture].backsector->ceilingheight; - ceiling->speed = ceiling->origspeed = FixedDiv(abs(lines[ceiling->texture].dy),4*FRACUNIT); // return trip, use dy - } - else - { - dest = lines[ceiling->texture].frontsector->ceilingheight; - ceiling->speed = ceiling->origspeed = FixedDiv(abs(lines[ceiling->texture].dx),4*FRACUNIT); // going frontways, use dx - } - - if (dest < ceiling->sector->ceilingheight) // must move down - { - ceiling->direction = -1; - ceiling->bottomheight = dest; - } - else // must move up - { - ceiling->direction = 1; - ceiling->topheight = dest; - } - - ceiling->delaytimer = ceiling->delay; - - // That's it. Do not set dontupdate, do not remove the thinker. - break; - } - - default: - break; - } - } - break; + const fixed_t origspeed = FixedDiv(ceiling->origspeed, (ELEVATORSPEED/2)); + const fixed_t fs = abs(ceiling->sector->ceilingheight - lines[ceiling->texture].frontsector->ceilingheight); + const fixed_t bs = abs(ceiling->sector->ceilingheight - lines[ceiling->texture].backsector->ceilingheight); + if (fs < bs) + ceiling->speed = FixedDiv(fs, 25*FRACUNIT) + FRACUNIT/4; + else + ceiling->speed = FixedDiv(bs, 25*FRACUNIT) + FRACUNIT/4; + ceiling->speed = FixedMul(ceiling->speed, origspeed); } - if (!dontupdate) - ceiling->sector->ceilspeed = ceiling->speed*ceiling->direction; - else - ceiling->sector->ceilspeed = 0; + + if (res == pastdest) + { + switch (ceiling->type) + { + case instantMoveCeilingByFrontSector: + if (ceiling->texture > -1) // flat changing + ceiling->sector->ceilingpic = ceiling->texture; + ceiling->sector->ceilingdata = NULL; + ceiling->sector->ceilspeed = 0; + P_RemoveThinker(&ceiling->thinker); + return; + case moveCeilingByFrontSector: + if (ceiling->texture < -1) // chained linedef executing + P_LinedefExecute((INT16)(ceiling->texture + INT16_MAX + 2), NULL, NULL); + if (ceiling->texture > -1) // flat changing + ceiling->sector->ceilingpic = ceiling->texture; + /* FALLTHRU */ + case raiseToHighest: + case moveCeilingByDistance: + ceiling->sector->ceilingdata = NULL; + ceiling->sector->ceilspeed = 0; + P_RemoveThinker(&ceiling->thinker); + return; + case bounceCeiling: + { + fixed_t dest = (ceiling->direction == 1) ? ceiling->topheight : ceiling->bottomheight; + + if (dest == lines[ceiling->texture].frontsector->ceilingheight) + dest = lines[ceiling->texture].backsector->ceilingheight; + else + dest = lines[ceiling->texture].frontsector->ceilingheight; + + if (dest < ceiling->sector->ceilingheight) // must move down + { + ceiling->direction = -1; + ceiling->bottomheight = dest; + } + else // must move up + { + ceiling->direction = 1; + ceiling->topheight = dest; + } + + ceiling->delaytimer = ceiling->delay; + break; + } + case bounceCeilingCrush: + { + fixed_t dest = (ceiling->direction == 1) ? ceiling->topheight : ceiling->bottomheight; + + if (dest == lines[ceiling->texture].frontsector->ceilingheight) + { + dest = lines[ceiling->texture].backsector->ceilingheight; + ceiling->speed = ceiling->origspeed = FixedDiv(abs(lines[ceiling->texture].dy), 4*FRACUNIT); // return trip, use dy + } + else + { + dest = lines[ceiling->texture].frontsector->ceilingheight; + ceiling->speed = ceiling->origspeed = FixedDiv(abs(lines[ceiling->texture].dx), 4*FRACUNIT); // going frontways, use dx + } + + if (dest < ceiling->sector->ceilingheight) // must move down + { + ceiling->direction = -1; + ceiling->bottomheight = dest; + } + else // must move up + { + ceiling->direction = 1; + ceiling->topheight = dest; + } + + ceiling->delaytimer = ceiling->delay; + break; + } + default: + break; + } + } + ceiling->sector->ceilspeed = ceiling->speed*ceiling->direction; } /** Moves a ceiling crusher. From 5b1a42af4ca1bcee7193695a948e2deb98c799dd Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 10:00:40 +0200 Subject: [PATCH 077/326] Refactor T_MoveFloor --- src/p_floor.c | 147 +++++++++++++++++--------------------------------- 1 file changed, 50 insertions(+), 97 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index c64c1bb20..ed86140f2 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -162,7 +162,7 @@ result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crus void T_MoveFloor(floormove_t *movefloor) { result_e res = 0; - boolean dontupdate = false; + boolean remove = false; if (movefloor->delaytimer) { @@ -190,113 +190,66 @@ void T_MoveFloor(floormove_t *movefloor) if (res == pastdest) { - if (movefloor->direction == 1) + switch (movefloor->type) { - switch (movefloor->type) - { - case moveFloorByFrontSector: - if (movefloor->texture < -1) // chained linedef executing - P_LinedefExecute((INT16)(movefloor->texture + INT16_MAX + 2), NULL, NULL); - /* FALLTHRU */ - case instantMoveFloorByFrontSector: - if (movefloor->texture > -1) // flat changing - movefloor->sector->floorpic = movefloor->texture; - break; - case bounceFloor: // Graue 03-12-2004 - if (movefloor->floordestheight == lines[movefloor->texture].frontsector->floorheight) - movefloor->floordestheight = lines[movefloor->texture].backsector->floorheight; - else - movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; - movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1; - movefloor->sector->floorspeed = movefloor->speed * movefloor->direction; - movefloor->delaytimer = movefloor->delay; - P_RecalcPrecipInSector(movefloor->sector); - return; // not break, why did this work? Graue 04-03-2004 - case bounceFloorCrush: // Graue 03-27-2004 - if (movefloor->floordestheight == lines[movefloor->texture].frontsector->floorheight) - { - movefloor->floordestheight = lines[movefloor->texture].backsector->floorheight; - movefloor->speed = movefloor->origspeed = FixedDiv(abs(lines[movefloor->texture].dy),4*FRACUNIT); // return trip, use dy - } - else - { - movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; - movefloor->speed = movefloor->origspeed = FixedDiv(abs(lines[movefloor->texture].dx),4*FRACUNIT); // forward again, use dx - } - movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1; - movefloor->sector->floorspeed = movefloor->speed * movefloor->direction; - movefloor->delaytimer = movefloor->delay; - P_RecalcPrecipInSector(movefloor->sector); - return; // not break, why did this work? Graue 04-03-2004 - case crushFloorOnce: + case moveFloorByFrontSector: + if (movefloor->texture < -1) // chained linedef executing + P_LinedefExecute((INT16)(movefloor->texture + INT16_MAX + 2), NULL, NULL); + /* FALLTHRU */ + case instantMoveFloorByFrontSector: + if (movefloor->texture > -1) // flat changing + movefloor->sector->floorpic = movefloor->texture; + remove = true; + break; + case bounceFloor: // Graue 03-12-2004 + if (movefloor->floordestheight == lines[movefloor->texture].frontsector->floorheight) + movefloor->floordestheight = lines[movefloor->texture].backsector->floorheight; + else + movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; + movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1; + movefloor->delaytimer = movefloor->delay; + remove = false; + break; + case bounceFloorCrush: // Graue 03-27-2004 + if (movefloor->floordestheight == lines[movefloor->texture].frontsector->floorheight) + { + movefloor->floordestheight = lines[movefloor->texture].backsector->floorheight; + movefloor->speed = movefloor->origspeed = FixedDiv(abs(lines[movefloor->texture].dy), 4*FRACUNIT); // return trip, use dy + } + else + { + movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; + movefloor->speed = movefloor->origspeed = FixedDiv(abs(lines[movefloor->texture].dx), 4*FRACUNIT); // forward again, use dx + } + movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1; + movefloor->delaytimer = movefloor->delay; + remove = false; + break; + case crushFloorOnce: + if (movefloor->direction == 1) + { movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; movefloor->direction = -1; movefloor->sector->soundorg.z = movefloor->sector->floorheight; - S_StartSound(&movefloor->sector->soundorg,sfx_pstop); - P_RecalcPrecipInSector(movefloor->sector); - return; - default: - break; - } - } - else if (movefloor->direction == -1) - { - switch (movefloor->type) - { - case moveFloorByFrontSector: - if (movefloor->texture < -1) // chained linedef executing - P_LinedefExecute((INT16)(movefloor->texture + INT16_MAX + 2), NULL, NULL); - /* FALLTHRU */ - case instantMoveFloorByFrontSector: - if (movefloor->texture > -1) // flat changing - movefloor->sector->floorpic = movefloor->texture; - break; - case bounceFloor: // Graue 03-12-2004 - if (movefloor->floordestheight == lines[movefloor->texture].frontsector->floorheight) - movefloor->floordestheight = lines[movefloor->texture].backsector->floorheight; - else - movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; - movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1; - movefloor->sector->floorspeed = movefloor->speed * movefloor->direction; - movefloor->delaytimer = movefloor->delay; - P_RecalcPrecipInSector(movefloor->sector); - return; // not break, why did this work? Graue 04-03-2004 - case bounceFloorCrush: // Graue 03-27-2004 - if (movefloor->floordestheight == lines[movefloor->texture].frontsector->floorheight) - { - movefloor->floordestheight = lines[movefloor->texture].backsector->floorheight; - movefloor->speed = movefloor->origspeed = FixedDiv(abs(lines[movefloor->texture].dy),4*FRACUNIT); // return trip, use dy - } - else - { - movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; - movefloor->speed = movefloor->origspeed = FixedDiv(abs(lines[movefloor->texture].dx),4*FRACUNIT); // forward again, use dx - } - movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1; - movefloor->sector->floorspeed = movefloor->speed * movefloor->direction; - movefloor->delaytimer = movefloor->delay; - P_RecalcPrecipInSector(movefloor->sector); - return; // not break, why did this work? Graue 04-03-2004 - case crushFloorOnce: - movefloor->sector->floordata = NULL; // Clear up the thinker so others can use it - P_RemoveThinker(&movefloor->thinker); - movefloor->sector->floorspeed = 0; - P_RecalcPrecipInSector(movefloor->sector); - return; - default: - break; - } + S_StartSound(&movefloor->sector->soundorg, sfx_pstop); + remove = false; + } + else + remove = true; + break; + default: + break; } + } + if (remove) + { movefloor->sector->floordata = NULL; // Clear up the thinker so others can use it movefloor->sector->floorspeed = 0; P_RemoveThinker(&movefloor->thinker); - dontupdate = true; } - if (!dontupdate) - movefloor->sector->floorspeed = movefloor->speed*movefloor->direction; else - movefloor->sector->floorspeed = 0; + movefloor->sector->floorspeed = movefloor->speed*movefloor->direction; P_RecalcPrecipInSector(movefloor->sector); } From c8bb18b389e407caa857256f0934cfa994781227 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 10:23:12 +0200 Subject: [PATCH 078/326] Adapt linedef type 53-58 to UDMF --- src/p_ceilng.c | 54 +++++--------------------------------------------- src/p_floor.c | 43 +++++++--------------------------------- src/p_setup.c | 8 ++++++++ 3 files changed, 20 insertions(+), 85 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index a12d9d56f..6da547b5c 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -79,28 +79,6 @@ void T_MoveCeiling(ceiling_t *ceiling) P_RemoveThinker(&ceiling->thinker); return; case bounceCeiling: - { - fixed_t dest = (ceiling->direction == 1) ? ceiling->topheight : ceiling->bottomheight; - - if (dest == lines[ceiling->texture].frontsector->ceilingheight) - dest = lines[ceiling->texture].backsector->ceilingheight; - else - dest = lines[ceiling->texture].frontsector->ceilingheight; - - if (dest < ceiling->sector->ceilingheight) // must move down - { - ceiling->direction = -1; - ceiling->bottomheight = dest; - } - else // must move up - { - ceiling->direction = 1; - ceiling->topheight = dest; - } - - ceiling->delaytimer = ceiling->delay; - break; - } case bounceCeilingCrush: { fixed_t dest = (ceiling->direction == 1) ? ceiling->topheight : ceiling->bottomheight; @@ -108,12 +86,12 @@ void T_MoveCeiling(ceiling_t *ceiling) if (dest == lines[ceiling->texture].frontsector->ceilingheight) { dest = lines[ceiling->texture].backsector->ceilingheight; - ceiling->speed = ceiling->origspeed = FixedDiv(abs(lines[ceiling->texture].dy), 4*FRACUNIT); // return trip, use dy + ceiling->speed = ceiling->origspeed = lines[ceiling->texture].args[3] << (FRACBITS - 2); // return trip, use args[3] } else { dest = lines[ceiling->texture].frontsector->ceilingheight; - ceiling->speed = ceiling->origspeed = FixedDiv(abs(lines[ceiling->texture].dx), 4*FRACUNIT); // going frontways, use dx + ceiling->speed = ceiling->origspeed = lines[ceiling->texture].args[2] << (FRACBITS - 2); // going frontways, use args[2] } if (dest < ceiling->sector->ceilingheight) // must move down @@ -344,30 +322,8 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) break; case bounceCeiling: - ceiling->speed = P_AproxDistance(line->dx, line->dy); // same speed as elevateContinuous - ceiling->speed = FixedDiv(ceiling->speed,4*FRACUNIT); - ceiling->origspeed = ceiling->speed; - if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up - { - ceiling->direction = 1; - ceiling->topheight = line->frontsector->ceilingheight; - } - else // Move down - { - ceiling->direction = -1; - ceiling->bottomheight = line->frontsector->ceilingheight; - } - - // Any delay? - ceiling->delay = sides[line->sidenum[0]].textureoffset >> FRACBITS; - ceiling->delaytimer = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Initial delay - - ceiling->texture = (fixed_t)(line - lines); // hack: use texture to store sourceline number - break; - case bounceCeilingCrush: - ceiling->speed = abs(line->dx); // same speed as elevateContinuous - ceiling->speed = FixedDiv(ceiling->speed,4*FRACUNIT); + ceiling->speed = line->args[2] << (FRACBITS - 2); // same speed as elevateContinuous ceiling->origspeed = ceiling->speed; if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up { @@ -381,8 +337,8 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) } // Any delay? - ceiling->delay = sides[line->sidenum[0]].textureoffset >> FRACBITS; - ceiling->delaytimer = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Initial delay + ceiling->delay = line->args[5]; + ceiling->delaytimer = line->args[4]; // Initial delay ceiling->texture = (fixed_t)(line - lines); // hack: use texture to store sourceline number break; diff --git a/src/p_floor.c b/src/p_floor.c index ed86140f2..1e7925511 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -202,24 +202,16 @@ void T_MoveFloor(floormove_t *movefloor) remove = true; break; case bounceFloor: // Graue 03-12-2004 - if (movefloor->floordestheight == lines[movefloor->texture].frontsector->floorheight) - movefloor->floordestheight = lines[movefloor->texture].backsector->floorheight; - else - movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; - movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1; - movefloor->delaytimer = movefloor->delay; - remove = false; - break; case bounceFloorCrush: // Graue 03-27-2004 if (movefloor->floordestheight == lines[movefloor->texture].frontsector->floorheight) { movefloor->floordestheight = lines[movefloor->texture].backsector->floorheight; - movefloor->speed = movefloor->origspeed = FixedDiv(abs(lines[movefloor->texture].dy), 4*FRACUNIT); // return trip, use dy + movefloor->speed = movefloor->origspeed = lines[movefloor->texture].args[3] << (FRACBITS - 2); // return trip, use args[3] } else { movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; - movefloor->speed = movefloor->origspeed = FixedDiv(abs(lines[movefloor->texture].dx), 4*FRACUNIT); // forward again, use dx + movefloor->speed = movefloor->origspeed = lines[movefloor->texture].args[2] << (FRACBITS - 2); // forward again, use args[2] } movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1; movefloor->delaytimer = movefloor->delay; @@ -1850,32 +1842,11 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) dofloor->direction = -1; // down break; - // Linetypes 2/3. - // Move floor up and down indefinitely like the old elevators. + // Move floor up and down indefinitely. + // bounceFloor has slowdown at the top and bottom of movement. case bounceFloor: - dofloor->speed = P_AproxDistance(line->dx, line->dy); // same speed as elevateContinuous - dofloor->speed = FixedDiv(dofloor->speed,4*FRACUNIT); - dofloor->origspeed = dofloor->speed; // it gets slowed down at the top and bottom - dofloor->floordestheight = line->frontsector->floorheight; - - if (dofloor->floordestheight >= sec->floorheight) - dofloor->direction = 1; // up - else - dofloor->direction = -1; // down - - // Any delay? - dofloor->delay = sides[line->sidenum[0]].textureoffset >> FRACBITS; - dofloor->delaytimer = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Initial delay - - dofloor->texture = (fixed_t)(line - lines); // hack: store source line number - break; - - // Linetypes 6/7. - // Like 2/3, but no slowdown at the top and bottom of movement, - // and the speed is line->dx the first way, line->dy for the - // return trip. Good for crushers. case bounceFloorCrush: - dofloor->speed = FixedDiv(abs(line->dx),4*FRACUNIT); + dofloor->speed = line->args[2] << (FRACBITS - 2); // same speed as elevateContinuous dofloor->origspeed = dofloor->speed; dofloor->floordestheight = line->frontsector->floorheight; @@ -1885,8 +1856,8 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) dofloor->direction = -1; // down // Any delay? - dofloor->delay = sides[line->sidenum[0]].textureoffset >> FRACBITS; - dofloor->delaytimer = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Initial delay + dofloor->delay = line->args[5]; + dofloor->delaytimer = line->args[4]; // Initial delay dofloor->texture = (fixed_t)(line - lines); // hack: store source line number break; diff --git a/src/p_setup.c b/src/p_setup.c index 6e7801618..af8ec51a0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3090,6 +3090,10 @@ static void P_ConvertBinaryMap(void) case 55: //Continuous ceiling mover lines[i].args[0] = tag; lines[i].args[1] = (lines[i].special == 53) ? 2 : lines[i].special - 54; + lines[i].args[2] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].args[3] = lines[i].args[2]; + lines[i].args[4] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[5] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].special = 53; break; case 56: //Continuous two-speed floor/ceiling mover @@ -3097,6 +3101,10 @@ static void P_ConvertBinaryMap(void) case 58: //Continuous two-speed ceiling mover lines[i].args[0] = tag; lines[i].args[1] = (lines[i].special == 56) ? 2 : lines[i].special - 57; + lines[i].args[2] = abs(lines[i].dx) >> FRACBITS; + lines[i].args[3] = abs(lines[i].dy) >> FRACBITS; + lines[i].args[4] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[5] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].special = 56; break; case 59: //Activate moving platform From 9fdd9060e46a6160c3cabb75b4b2d51d5e387a9d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 12:53:14 +0200 Subject: [PATCH 079/326] Adapt crusher linedefs to UDMF --- src/p_ceilng.c | 38 +++++++++----------------------------- src/p_floor.c | 8 ++------ src/p_setup.c | 24 ++++++++++++++++++++++++ src/p_spec.c | 23 ++++++++--------------- src/p_spec.h | 2 +- 5 files changed, 44 insertions(+), 51 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 6da547b5c..02dea243e 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -140,11 +140,7 @@ void T_CrushCeiling(ceiling_t *ceiling) if (res == pastdest) { ceiling->direction = -1; - - if (lines[ceiling->sourceline].flags & ML_EFFECT4) - ceiling->speed = ceiling->oldspeed; - else - ceiling->speed = ceiling->oldspeed*2; + ceiling->speed = lines[ceiling->sourceline].args[2] << (FRACBITS - 2); if (ceiling->type == crushCeilOnce || ceiling->type == crushBothOnce) @@ -185,12 +181,8 @@ void T_CrushCeiling(ceiling_t *ceiling) ceiling->sector->soundorg.z = ceiling->sector->floorheight; S_StartSound(mp,sfx_pstop); - if (lines[ceiling->sourceline].flags & ML_EFFECT4) - ceiling->speed = ceiling->oldspeed; - else - ceiling->speed = ceiling->oldspeed/2; - ceiling->direction = 1; + ceiling->speed = lines[ceiling->sourceline].args[3] << (FRACBITS - 2); } break; } @@ -387,41 +379,29 @@ INT32 EV_DoCrush(mtag_t tag, line_t *line, ceiling_e type) ceiling->sector = sec; ceiling->crush = true; ceiling->sourceline = (INT32)(line-lines); - - if (line->flags & ML_EFFECT4) - ceiling->oldspeed = FixedDiv(abs(line->dx),4*FRACUNIT); - else - ceiling->oldspeed = (R_PointToDist2(line->v2->x, line->v2->y, line->v1->x, line->v1->y)/16); + ceiling->speed = ceiling->oldspeed = line->args[2] << (FRACBITS - 2); switch(type) { - case fastCrushAndRaise: // Up and then down + case raiseAndCrush: // Up and then down ceiling->topheight = P_FindHighestCeilingSurrounding(sec); ceiling->direction = 1; - ceiling->speed = ceiling->oldspeed; + // Retain stupid behavior for backwards compatibility + if (!udmf && !(line->flags & ML_EFFECT4)) + ceiling->speed /= 2; + else + ceiling->speed = line->args[3] << (FRACBITS - 2); ceiling->bottomheight = sec->floorheight + FRACUNIT; break; case crushBothOnce: ceiling->topheight = sec->ceilingheight; ceiling->bottomheight = sec->floorheight + (sec->ceilingheight-sec->floorheight)/2; ceiling->direction = -1; - - if (line->flags & ML_EFFECT4) - ceiling->speed = ceiling->oldspeed; - else - ceiling->speed = ceiling->oldspeed*2; - break; case crushCeilOnce: default: // Down and then up. ceiling->topheight = sec->ceilingheight; ceiling->direction = -1; - - if (line->flags & ML_EFFECT4) - ceiling->speed = ceiling->oldspeed; - else - ceiling->speed = ceiling->oldspeed*2; - ceiling->bottomheight = sec->floorheight + FRACUNIT; break; } diff --git a/src/p_floor.c b/src/p_floor.c index 1e7925511..73592f7d7 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -222,6 +222,7 @@ void T_MoveFloor(floormove_t *movefloor) { movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; movefloor->direction = -1; + movefloor->speed = lines[movefloor->texture].args[3] << (FRACBITS - 2); movefloor->sector->soundorg.z = movefloor->sector->floorheight; S_StartSound(&movefloor->sector->soundorg, sfx_pstop); remove = false; @@ -1863,8 +1864,7 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) break; case crushFloorOnce: - dofloor->speed = FixedDiv(abs(line->dx),4*FRACUNIT); - dofloor->origspeed = dofloor->speed; + dofloor->speed = dofloor->origspeed = line->args[2] << (FRACBITS - 2); dofloor->floordestheight = line->frontsector->ceilingheight; if (dofloor->floordestheight >= sec->floorheight) @@ -1872,10 +1872,6 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) else dofloor->direction = -1; // down - // Any delay? - dofloor->delay = sides[line->sidenum[0]].textureoffset >> FRACBITS; - dofloor->delaytimer = sides[line->sidenum[0]].rowoffset >> FRACBITS; - dofloor->texture = (fixed_t)(line - lines); // hack: store source line number break; diff --git a/src/p_setup.c b/src/p_setup.c index af8ec51a0..2158af62d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3119,6 +3119,18 @@ static void P_ConvertBinaryMap(void) case 61: //Crusher (Ceiling to floor) case 62: //Crusher (Floor to ceiling) lines[i].args[0] = tag; + lines[i].args[1] = lines[i].special - 61; + if (lines[i].flags & ML_EFFECT4) + { + lines[i].args[2] = abs(lines[i].dx) >> FRACBITS; + lines[i].args[3] = lines[i].args[2]; + } + else + { + lines[i].args[2] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> (FRACBITS + 1); + lines[i].args[3] = lines[i].args[2] / 4; + } + lines[i].special = 61; break; case 76: //Make FOF bouncy lines[i].args[0] = tag; @@ -3568,6 +3580,18 @@ static void P_ConvertBinaryMap(void) case 430: //Crush floor once case 431: //Crush floor and ceiling once lines[i].args[0] = tag; + lines[i].args[1] = (lines[i].special == 429) ? 1 : ((lines[i].special == 430) ? 0 : 2); + if (lines[i].special == 430 || lines[i].flags & ML_EFFECT4) + { + lines[i].args[2] = abs(lines[i].dx) >> FRACBITS; + lines[i].args[3] = lines[i].args[2]; + } + else + { + lines[i].args[2] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> (FRACBITS + 1); + lines[i].args[3] = lines[i].args[2] / 4; + } + lines[i].special = 429; break; case 443: //Call Lua function if (lines[i].text) diff --git a/src/p_spec.c b/src/p_spec.c index 222077e3d..e434d90c0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2870,16 +2870,13 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) EV_DoElevator(line->args[0], line, elevateContinuous); break; - case 429: // Crush Ceiling Down Once - EV_DoCrush(line->args[0], line, crushCeilOnce); - break; - - case 430: // Crush Floor Up Once - EV_DoFloor(line->args[0], line, crushFloorOnce); - break; - - case 431: // Crush Floor & Ceiling to middle Once - EV_DoCrush(line->args[0], line, crushBothOnce); + case 429: // Crush planes once + if (line->args[1] == 0) + EV_DoFloor(line->args[0], line, crushFloorOnce); + else if (line->args[1] == 1) + EV_DoCrush(line->args[0], line, crushCeilOnce); + else + EV_DoCrush(line->args[0], line, crushBothOnce); break; case 432: // Enable 2D Mode (Disable if noclimb) @@ -6353,11 +6350,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 61: // Crusher! - EV_DoCrush(lines[i].args[0], &lines[i], crushAndRaise); - break; - - case 62: // Crusher (up and then down)! - EV_DoCrush(lines[i].args[0], &lines[i], fastCrushAndRaise); + EV_DoCrush(lines[i].args[0], &lines[i], lines[i].args[1] ? raiseAndCrush : crushAndRaise); break; case 63: // support for drawn heights coming from different sector diff --git a/src/p_spec.h b/src/p_spec.h index e6ea5a534..b24d40579 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -264,7 +264,7 @@ typedef enum instantRaise, // instant-move for ceilings crushAndRaise, - fastCrushAndRaise, + raiseAndCrush, crushCeilOnce, crushBothOnce, From 63eafff5fe2ab064af45597985ff2c98071546cb Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 14:53:14 +0200 Subject: [PATCH 080/326] Linedef type 403: Don't run the linedef executor twice --- src/p_ceilng.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 02dea243e..05973dfa8 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -261,7 +261,8 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) // chained linedef executing ability // only set it on ONE of the moving sectors (the smallest numbered) - if (line->args[3] > 0) + // only set it if there isn't also a floor mover + if (line->args[3] > 0 && line->args[1] == 1) ceiling->texture = firstone ? line->args[3] - INT16_MAX - 2 : -1; // flat changing ability else if (line->args[4]) From 446e78b6e2363fd48a5a9ee9d88b0a11d698c5b5 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 15:28:28 +0200 Subject: [PATCH 081/326] Linedef type 403: Allow executor chaining and flat change at the same time --- src/p_ceilng.c | 16 ++++++---------- src/p_floor.c | 15 ++++++--------- src/p_saveg.c | 6 ++++-- src/p_setup.c | 15 ++------------- src/p_spec.h | 3 ++- 5 files changed, 20 insertions(+), 35 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 05973dfa8..39eb07457 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -67,8 +67,8 @@ void T_MoveCeiling(ceiling_t *ceiling) P_RemoveThinker(&ceiling->thinker); return; case moveCeilingByFrontSector: - if (ceiling->texture < -1) // chained linedef executing - P_LinedefExecute((INT16)(ceiling->texture + INT16_MAX + 2), NULL, NULL); + if (ceiling->tag) // chained linedef executing + P_LinedefExecute(ceiling->tag, NULL, NULL); if (ceiling->texture > -1) // flat changing ceiling->sector->ceilingpic = ceiling->texture; /* FALLTHRU */ @@ -262,13 +262,11 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) // chained linedef executing ability // only set it on ONE of the moving sectors (the smallest numbered) // only set it if there isn't also a floor mover - if (line->args[3] > 0 && line->args[1] == 1) - ceiling->texture = firstone ? line->args[3] - INT16_MAX - 2 : -1; + if (line->args[3] && line->args[1] == 1) + ceiling->tag = firstone ? (INT16)line->args[3] : 0; + // flat changing ability - else if (line->args[4]) - ceiling->texture = line->frontsector->ceilingpic; - else - ceiling->texture = -1; + ceiling->texture = line->args[4] ? line->frontsector->ceilingpic : -1; break; // More linedef executor junk @@ -341,7 +339,6 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) } - ceiling->tag = tag; ceiling->type = type; firstone = 0; } @@ -407,7 +404,6 @@ INT32 EV_DoCrush(mtag_t tag, line_t *line, ceiling_e type) break; } - ceiling->tag = tag; ceiling->type = type; } return rtn; diff --git a/src/p_floor.c b/src/p_floor.c index 73592f7d7..4ad78d86c 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -193,8 +193,8 @@ void T_MoveFloor(floormove_t *movefloor) switch (movefloor->type) { case moveFloorByFrontSector: - if (movefloor->texture < -1) // chained linedef executing - P_LinedefExecute((INT16)(movefloor->texture + INT16_MAX + 2), NULL, NULL); + if (movefloor->tag) // chained linedef executing + P_LinedefExecute(movefloor->tag, NULL, NULL); /* FALLTHRU */ case instantMoveFloorByFrontSector: if (movefloor->texture > -1) // flat changing @@ -1821,14 +1821,11 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) // chained linedef executing ability // Only set it on one of the moving sectors (the smallest numbered) - if (line->args[3] > 0) - dofloor->texture = firstone ? line->args[3] - INT16_MAX - 2 : -1; - // flat changing ability - else if (line->args[4]) - dofloor->texture = line->frontsector->floorpic; - else - dofloor->texture = -1; // nothing special to do after movement completes + if (line->args[3]) + dofloor->tag = firstone ? (INT16)line->args[3] : -1; + // flat changing ability + dofloor->texture = line->args[4] ? line->frontsector->floorpic : -1; break; case moveFloorByDistance: diff --git a/src/p_saveg.c b/src/p_saveg.c index 770c641b9..e5c2a1f6a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1991,7 +1991,7 @@ static void SaveCeilingThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, ht->crush); WRITEINT32(save_p, ht->texture); WRITEINT32(save_p, ht->direction); - WRITEINT32(save_p, ht->tag); + WRITEINT16(save_p, ht->tag); WRITEINT32(save_p, ht->olddirection); WRITEFIXED(save_p, ht->origspeed); WRITEFIXED(save_p, ht->sourceline); @@ -2011,6 +2011,7 @@ static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, ht->origspeed); WRITEFIXED(save_p, ht->delay); WRITEFIXED(save_p, ht->delaytimer); + WRITEINT16(save_p, ht->tag); } static void SaveLightflashThinker(const thinker_t *th, const UINT8 type) @@ -3097,7 +3098,7 @@ static thinker_t* LoadCeilingThinker(actionf_p1 thinker) ht->crush = READUINT8(save_p); ht->texture = READINT32(save_p); ht->direction = READINT32(save_p); - ht->tag = READINT32(save_p); + ht->tag = READINT16(save_p); ht->olddirection = READINT32(save_p); ht->origspeed = READFIXED(save_p); ht->sourceline = READFIXED(save_p); @@ -3120,6 +3121,7 @@ static thinker_t* LoadFloormoveThinker(actionf_p1 thinker) ht->origspeed = READFIXED(save_p); ht->delay = READFIXED(save_p); ht->delaytimer = READFIXED(save_p); + ht->tag = READINT16(save_p); if (ht->sector) ht->sector->floordata = ht; return &ht->thinker; diff --git a/src/p_setup.c b/src/p_setup.c index 2158af62d..4679a8dc7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3545,19 +3545,8 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = tag; lines[i].args[1] = lines[i].special - 403; lines[i].args[2] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; - if (lines[i].flags & ML_BLOCKMONSTERS) - { - if (sides[lines[i].sidenum[0]].textureoffset > 0) - lines[i].args[3] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; - else - lines[i].args[3] = 0; - lines[i].args[4] = 0; - } - else - { - lines[i].args[3] = 0; - lines[i].args[4] = !!(lines[i].flags & ML_NOCLIMB); - } + lines[i].args[3] = (lines[i].flags & ML_BLOCKMONSTERS) ? sides[lines[i].sidenum[0]].textureoffset >> FRACBITS : 0; + lines[i].args[4] = !!(lines[i].flags & ML_NOCLIMB); lines[i].special = 403; break; case 405: //Move floor according to front texture offsets diff --git a/src/p_spec.h b/src/p_spec.h index b24d40579..2ae8320fc 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -296,7 +296,7 @@ typedef struct INT32 direction; ///< 1 = up, 0 = waiting, -1 = down. // ID - INT32 tag; + INT16 tag; ///< Tag of linedef executor to run when movement is done. INT32 olddirection; fixed_t origspeed; ///< The original, "real" speed. INT32 sourceline; ///< Index of the source linedef @@ -356,6 +356,7 @@ typedef struct fixed_t origspeed; fixed_t delay; fixed_t delaytimer; + INT16 tag; } floormove_t; typedef struct From 299b2dcff2c685094ea60ca4695d42960a59b9d7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 15:29:42 +0200 Subject: [PATCH 082/326] Fix a small oversight --- src/p_ceilng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 39eb07457..e834c5d1d 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -301,7 +301,7 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) ceiling->speed = INT32_MAX/2; // as above, "instant" is one tic else ceiling->speed = line->args[3] << (FRACBITS - 3); - if (sides[line->sidenum[0]].rowoffset > 0) + if (line->args[2] > 0) { ceiling->direction = 1; // up ceiling->topheight = sec->ceilingheight + (line->args[2] << FRACBITS); From 202c56054e0e28d99b34b1d8a29252707105c067 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 16:15:38 +0200 Subject: [PATCH 083/326] Remove unused ceiling_t variables --- src/p_ceilng.c | 2 +- src/p_saveg.c | 4 ---- src/p_spec.h | 2 -- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index e834c5d1d..83c342712 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -377,7 +377,7 @@ INT32 EV_DoCrush(mtag_t tag, line_t *line, ceiling_e type) ceiling->sector = sec; ceiling->crush = true; ceiling->sourceline = (INT32)(line-lines); - ceiling->speed = ceiling->oldspeed = line->args[2] << (FRACBITS - 2); + ceiling->speed = ceiling->origspeed = line->args[2] << (FRACBITS - 2); switch(type) { diff --git a/src/p_saveg.c b/src/p_saveg.c index e5c2a1f6a..600561c8d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1985,14 +1985,12 @@ static void SaveCeilingThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, ht->bottomheight); WRITEFIXED(save_p, ht->topheight); WRITEFIXED(save_p, ht->speed); - WRITEFIXED(save_p, ht->oldspeed); WRITEFIXED(save_p, ht->delay); WRITEFIXED(save_p, ht->delaytimer); WRITEUINT8(save_p, ht->crush); WRITEINT32(save_p, ht->texture); WRITEINT32(save_p, ht->direction); WRITEINT16(save_p, ht->tag); - WRITEINT32(save_p, ht->olddirection); WRITEFIXED(save_p, ht->origspeed); WRITEFIXED(save_p, ht->sourceline); } @@ -3092,14 +3090,12 @@ static thinker_t* LoadCeilingThinker(actionf_p1 thinker) ht->bottomheight = READFIXED(save_p); ht->topheight = READFIXED(save_p); ht->speed = READFIXED(save_p); - ht->oldspeed = READFIXED(save_p); ht->delay = READFIXED(save_p); ht->delaytimer = READFIXED(save_p); ht->crush = READUINT8(save_p); ht->texture = READINT32(save_p); ht->direction = READINT32(save_p); ht->tag = READINT16(save_p); - ht->olddirection = READINT32(save_p); ht->origspeed = READFIXED(save_p); ht->sourceline = READFIXED(save_p); if (ht->sector) diff --git a/src/p_spec.h b/src/p_spec.h index 2ae8320fc..4ad817ab2 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -287,7 +287,6 @@ typedef struct fixed_t bottomheight; ///< The lowest height to move to. fixed_t topheight; ///< The highest height to move to. fixed_t speed; ///< Ceiling speed. - fixed_t oldspeed; fixed_t delay; fixed_t delaytimer; UINT8 crush; ///< Whether to crush things or not. @@ -297,7 +296,6 @@ typedef struct // ID INT16 tag; ///< Tag of linedef executor to run when movement is done. - INT32 olddirection; fixed_t origspeed; ///< The original, "real" speed. INT32 sourceline; ///< Index of the source linedef } ceiling_t; From 588c56b22425e4ebc8a148771269617cdd60d921 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 26 Jun 2021 16:25:14 +0200 Subject: [PATCH 084/326] Floor/ceiling movers: Stop abusing the texture variable to store the sourceline --- src/p_ceilng.c | 16 +++++++--------- src/p_floor.c | 23 ++++++++++------------- src/p_saveg.c | 2 ++ src/p_spec.h | 1 + 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 83c342712..b64d496fb 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -46,8 +46,8 @@ void T_MoveCeiling(ceiling_t *ceiling) if (ceiling->type == bounceCeiling) { const fixed_t origspeed = FixedDiv(ceiling->origspeed, (ELEVATORSPEED/2)); - const fixed_t fs = abs(ceiling->sector->ceilingheight - lines[ceiling->texture].frontsector->ceilingheight); - const fixed_t bs = abs(ceiling->sector->ceilingheight - lines[ceiling->texture].backsector->ceilingheight); + const fixed_t fs = abs(ceiling->sector->ceilingheight - lines[ceiling->sourceline].frontsector->ceilingheight); + const fixed_t bs = abs(ceiling->sector->ceilingheight - lines[ceiling->sourceline].backsector->ceilingheight); if (fs < bs) ceiling->speed = FixedDiv(fs, 25*FRACUNIT) + FRACUNIT/4; else @@ -83,15 +83,15 @@ void T_MoveCeiling(ceiling_t *ceiling) { fixed_t dest = (ceiling->direction == 1) ? ceiling->topheight : ceiling->bottomheight; - if (dest == lines[ceiling->texture].frontsector->ceilingheight) + if (dest == lines[ceiling->sourceline].frontsector->ceilingheight) { - dest = lines[ceiling->texture].backsector->ceilingheight; - ceiling->speed = ceiling->origspeed = lines[ceiling->texture].args[3] << (FRACBITS - 2); // return trip, use args[3] + dest = lines[ceiling->sourceline].backsector->ceilingheight; + ceiling->speed = ceiling->origspeed = lines[ceiling->sourceline].args[3] << (FRACBITS - 2); // return trip, use args[3] } else { - dest = lines[ceiling->texture].frontsector->ceilingheight; - ceiling->speed = ceiling->origspeed = lines[ceiling->texture].args[2] << (FRACBITS - 2); // going frontways, use args[2] + dest = lines[ceiling->sourceline].frontsector->ceilingheight; + ceiling->speed = ceiling->origspeed = lines[ceiling->sourceline].args[2] << (FRACBITS - 2); // going frontways, use args[2] } if (dest < ceiling->sector->ceilingheight) // must move down @@ -330,8 +330,6 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) // Any delay? ceiling->delay = line->args[5]; ceiling->delaytimer = line->args[4]; // Initial delay - - ceiling->texture = (fixed_t)(line - lines); // hack: use texture to store sourceline number break; default: diff --git a/src/p_floor.c b/src/p_floor.c index 4ad78d86c..e388657cf 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -178,8 +178,8 @@ void T_MoveFloor(floormove_t *movefloor) if (movefloor->type == bounceFloor) { const fixed_t origspeed = FixedDiv(movefloor->origspeed,(ELEVATORSPEED/2)); - const fixed_t fs = abs(movefloor->sector->floorheight - lines[movefloor->texture].frontsector->floorheight); - const fixed_t bs = abs(movefloor->sector->floorheight - lines[movefloor->texture].backsector->floorheight); + const fixed_t fs = abs(movefloor->sector->floorheight - lines[movefloor->sourceline].frontsector->floorheight); + const fixed_t bs = abs(movefloor->sector->floorheight - lines[movefloor->sourceline].backsector->floorheight); if (fs < bs) movefloor->speed = FixedDiv(fs,25*FRACUNIT) + FRACUNIT/4; else @@ -203,15 +203,15 @@ void T_MoveFloor(floormove_t *movefloor) break; case bounceFloor: // Graue 03-12-2004 case bounceFloorCrush: // Graue 03-27-2004 - if (movefloor->floordestheight == lines[movefloor->texture].frontsector->floorheight) + if (movefloor->floordestheight == lines[movefloor->sourceline].frontsector->floorheight) { - movefloor->floordestheight = lines[movefloor->texture].backsector->floorheight; - movefloor->speed = movefloor->origspeed = lines[movefloor->texture].args[3] << (FRACBITS - 2); // return trip, use args[3] + movefloor->floordestheight = lines[movefloor->sourceline].backsector->floorheight; + movefloor->speed = movefloor->origspeed = lines[movefloor->sourceline].args[3] << (FRACBITS - 2); // return trip, use args[3] } else { - movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; - movefloor->speed = movefloor->origspeed = lines[movefloor->texture].args[2] << (FRACBITS - 2); // forward again, use args[2] + movefloor->floordestheight = lines[movefloor->sourceline].frontsector->floorheight; + movefloor->speed = movefloor->origspeed = lines[movefloor->sourceline].args[2] << (FRACBITS - 2); // forward again, use args[2] } movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1; movefloor->delaytimer = movefloor->delay; @@ -220,9 +220,9 @@ void T_MoveFloor(floormove_t *movefloor) case crushFloorOnce: if (movefloor->direction == 1) { - movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; + movefloor->floordestheight = lines[movefloor->sourceline].frontsector->floorheight; movefloor->direction = -1; - movefloor->speed = lines[movefloor->texture].args[3] << (FRACBITS - 2); + movefloor->speed = lines[movefloor->sourceline].args[3] << (FRACBITS - 2); movefloor->sector->soundorg.z = movefloor->sector->floorheight; S_StartSound(&movefloor->sector->soundorg, sfx_pstop); remove = false; @@ -1777,6 +1777,7 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) dofloor->type = floortype; dofloor->crush = false; // default: types that crush will change this dofloor->sector = sec; + dofloor->sourceline = (INT32)(line - lines); switch (floortype) { @@ -1856,8 +1857,6 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) // Any delay? dofloor->delay = line->args[5]; dofloor->delaytimer = line->args[4]; // Initial delay - - dofloor->texture = (fixed_t)(line - lines); // hack: store source line number break; case crushFloorOnce: @@ -1868,8 +1867,6 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) dofloor->direction = 1; // up else dofloor->direction = -1; // down - - dofloor->texture = (fixed_t)(line - lines); // hack: store source line number break; default: diff --git a/src/p_saveg.c b/src/p_saveg.c index 600561c8d..bf28b11a5 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2010,6 +2010,7 @@ static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, ht->delay); WRITEFIXED(save_p, ht->delaytimer); WRITEINT16(save_p, ht->tag); + WRITEFIXED(save_p, ht->sourceline); } static void SaveLightflashThinker(const thinker_t *th, const UINT8 type) @@ -3118,6 +3119,7 @@ static thinker_t* LoadFloormoveThinker(actionf_p1 thinker) ht->delay = READFIXED(save_p); ht->delaytimer = READFIXED(save_p); ht->tag = READINT16(save_p); + ht->sourceline = READFIXED(save_p); if (ht->sector) ht->sector->floordata = ht; return &ht->thinker; diff --git a/src/p_spec.h b/src/p_spec.h index 4ad817ab2..921af714e 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -355,6 +355,7 @@ typedef struct fixed_t delay; fixed_t delaytimer; INT16 tag; + INT32 sourceline; } floormove_t; typedef struct From 92982be76b7abbe9e3ca4f2c83fe0d234b971b38 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 27 Jun 2021 09:53:57 +0200 Subject: [PATCH 085/326] Adapt the remaining plane movement linedef types to UDMF --- src/p_setup.c | 15 +++++++++++++++ src/p_spec.c | 18 +++++------------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 4679a8dc7..9c1a2d68c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3085,6 +3085,10 @@ static void P_ConvertBinaryMap(void) case 51: //Instantly raise ceiling on level load lines[i].args[0] = tag; break; + case 52: //Continuously falling sector + lines[i].args[0] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); + break; case 53: //Continuous floor/ceiling mover case 54: //Continuous floor mover case 55: //Continuous ceiling mover @@ -3132,6 +3136,14 @@ static void P_ConvertBinaryMap(void) } lines[i].special = 61; break; + case 66: //Move floor by displacement + case 67: //Move ceiling by displacement + case 68: //Move floor and ceiling by displacement + lines[i].args[0] = tag; + lines[i].args[1] = lines[i].special - 66; + lines[i].args[2] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].special = 66; + break; case 76: //Make FOF bouncy lines[i].args[0] = tag; lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; @@ -3558,6 +3570,9 @@ static void P_ConvertBinaryMap(void) lines[i].args[4] = !!(lines[i].flags & ML_NOCLIMB); lines[i].special = 405; break; + case 411: //Stop plane movement + lines[i].args[0] = tag; + break; case 428: //Start platform movement lines[i].args[0] = tag; lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index e434d90c0..0bf158f29 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2297,7 +2297,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 411: // Stop floor/ceiling movement in tagged sector(s) - TAG_ITER_SECTORS(tag, secnum) + TAG_ITER_SECTORS(line->args[0], secnum) { if (sectors[secnum].floordata) { @@ -6322,7 +6322,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 52: // Continuously Falling sector - EV_DoContinuousFall(lines[i].frontsector, lines[i].backsector, P_AproxDistance(lines[i].dx, lines[i].dy), (lines[i].flags & ML_NOCLIMB)); + EV_DoContinuousFall(lines[i].frontsector, lines[i].backsector, lines[i].args[0] << FRACBITS, lines[i].args[1]); break; case 53: // Continuous plane movement (slowdown) @@ -6377,17 +6377,9 @@ void P_SpawnSpecials(boolean fromnetsave) } break; - case 66: // Displace floor by front sector - TAG_ITER_SECTORS(tag, s) - P_AddPlaneDisplaceThinker(pd_floor, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); - break; - case 67: // Displace ceiling by front sector - TAG_ITER_SECTORS(tag, s) - P_AddPlaneDisplaceThinker(pd_ceiling, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); - break; - case 68: // Displace both floor AND ceiling by front sector - TAG_ITER_SECTORS(tag, s) - P_AddPlaneDisplaceThinker(pd_both, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); + case 66: // Displace planes by front sector + TAG_ITER_SECTORS(lines[i].args[0], s) + P_AddPlaneDisplaceThinker(lines[i].args[1], abs(lines[i].args[2])<<8, sides[lines[i].sidenum[0]].sector-sectors, s, lines[i].args[2] < 0); break; case 70: // Add raise thinker to FOF From 4b0e3117406eb7422be306c0a24703499e465ab6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 27 Jun 2021 09:54:48 +0200 Subject: [PATCH 086/326] Fix typo --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 0bf158f29..723b71b9b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6318,7 +6318,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 51: // Instant raise for ceilings if (!udmf) - EV_DoCeiling(lines[i].args[1], &lines[i], instantRaise); + EV_DoCeiling(lines[i].args[0], &lines[i], instantRaise); break; case 52: // Continuously Falling sector From 13eb4cb35924eeedefa2e1b4360fffd6b944c129 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 27 Jun 2021 10:33:05 +0200 Subject: [PATCH 087/326] Add plane mover linedef types to UDB config --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 272 ++++++++++++++++++- extras/conf/udb/Includes/SRB222_misc.cfg | 7 + 2 files changed, 277 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 4c35e8723..4cf3159e2 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1570,6 +1570,92 @@ udmf { title = "Plane Movement"; + 52 + { + title = "Continuously Falling Sector"; + prefix = "(52)"; + arg0 + { + title = "Speed"; + } + arg1 + { + title = "Direction"; + type = 11; + enum + { + 0 = "Fall"; + 1 = "Rise"; + } + } + } + + 53 + { + title = "Continuous Plane Mover (Slowdown)"; + prefix = "(53)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Affected planes"; + type = 11; + enum = "floorceiling"; + } + arg2 + { + title = "Forward speed"; + } + arg3 + { + title = "Return speed"; + } + arg4 + { + title = "Starting delay"; + } + arg5 + { + title = "Delay before flip"; + } + } + + 56 + { + title = "Continuous Plane Mover (Constant)"; + prefix = "(56)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Affected planes"; + type = 11; + enum = "floorceiling"; + } + arg2 + { + title = "Forward speed"; + } + arg3 + { + title = "Return speed"; + } + arg4 + { + title = "Starting delay"; + } + arg5 + { + title = "Delay before flip"; + } + } + 60 { title = "Activate Moving Platform"; @@ -1592,15 +1678,62 @@ udmf title = "Delay before flip"; } arg4 + { + title = "Starting direction"; + type = 11; + enum = "downup"; + } + } + + 61 + { + title = "Ceiling Crusher"; + prefix = "(61)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 { title = "Starting direction"; type = 11; enum { - 0 = "Down"; - 1 = "Up"; + 0 = "Crush"; + 1 = "Retract"; } } + arg2 + { + title = "Crush speed"; + } + arg3 + { + title = "Retract speed"; + } + } + + 66 + { + title = "Move Planes by Displacement"; + prefix = "(66)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Affected planes"; + type = 11; + enum = "floorceiling"; + } + arg2 + { + title = "Translation factor"; + default = 256; + } } } @@ -2281,10 +2414,120 @@ udmf } } + linedefexecsector + { + title = "Linedef Executor (sector)"; + + 400 + { + title = "Set Tagged Sector's Heights/Textures"; + prefix = "(400)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Set heights?"; + type = 12; + enum + { + 1 = "Floor"; + 2 = "Ceiling"; + } + } + arg2 + { + title = "Set flats?"; + type = 12; + enum + { + 1 = "Floor"; + 2 = "Ceiling"; + } + } + } + } + linedefexecplane { title = "Linedef Executor (plane movement)"; + 403 + { + title = "Move Tagged Sector's Planes"; + prefix = "(403)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Affected planes"; + type = 11; + enum = "floorceiling"; + } + arg2 + { + title = "Speed"; + } + arg3 + { + title = "Linedef executor tag"; + type = 15; + } + arg4 + { + title = "Set flats?"; + type = 11; + enum = "noyes"; + } + } + + 405 + { + title = "Move Planes by Distance"; + prefix = "(405)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Affected planes"; + type = 11; + enum = "floorceiling"; + } + arg2 + { + title = "Distance"; + } + arg3 + { + title = "Speed"; + } + arg4 + { + title = "Instant?"; + type = 11; + enum = "noyes"; + } + } + + 411 + { + title = "Stop Plane Movement"; + prefix = "(411)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + } + 428 { title = "Start Platform Movement"; @@ -2317,6 +2560,31 @@ udmf } } } + + 429 + { + title = "Crush Planes Once"; + prefix = "(429)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Affected planes"; + type = 11; + enum = "floorceiling"; + } + arg2 + { + title = "Crush speed"; + } + arg3 + { + title = "Retract speed"; + } + } } linedefexecmisc diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 68629149e..1fa98a212 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -444,6 +444,13 @@ enums 4 = "Don't block players"; 8 = "Don't block non-players"; } + + floorceiling + { + 0 = "Floor"; + 1 = "Ceiling"; + 2 = "Both"; + } } //Default things filters From 099cea0a19c95cf94868f91258f1ff59521788f6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 27 Jun 2021 11:56:06 +0200 Subject: [PATCH 088/326] Implement "set flats" linedef type --- extras/conf/SRB2-22.cfg | 8 +++++++ extras/conf/udb/Includes/SRB222_linedefs.cfg | 22 ++++++++++++++++++++ src/p_setup.c | 14 +++++++++++++ src/p_spec.c | 12 +++++++++++ 4 files changed, 56 insertions(+) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index f457fe972..467856344 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -2009,6 +2009,14 @@ linedeftypes flags8text = "[3] Set delay by backside sector"; } + 408 + { + title = "Set Tagged Sector's Flats"; + prefix = "(408)"; + flags64text = "[6] Don't set floor flat"; + flags512text = "[9] Don't set ceiling flat"; + } + 409 { title = "Change Tagged Sector's Tag"; diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 4cf3159e2..0e110cfb6 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -765,6 +765,11 @@ doom title = "Set Tagged Sector's Light Level"; prefix = "(402)"; } + 408 + { + title = "Set Tagged Sector's Flats"; + prefix = "(408)"; + } 409 { title = "Change Tagged Sector's Tag"; @@ -2448,6 +2453,23 @@ udmf } } } + + 408 + { + title = "Set Tagged Sector's Flats"; + prefix = "(408)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Affected planes"; + type = 11; + enum = "floorceiling"; + } + } } linedefexecplane diff --git a/src/p_setup.c b/src/p_setup.c index 9c1a2d68c..56c3ed78b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3570,6 +3570,20 @@ static void P_ConvertBinaryMap(void) lines[i].args[4] = !!(lines[i].flags & ML_NOCLIMB); lines[i].special = 405; break; + case 408: //Set flats + lines[i].args[0] = tag; + if ((lines[i].flags & (ML_NOCLIMB|ML_EFFECT4)) == (ML_NOCLIMB|ML_EFFECT4)) + { + CONS_Alert(CONS_WARNING, M_GetText("Set flats linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), tag); + lines[i].special = 0; + } + else if (lines[i].flags & ML_NOCLIMB) + lines[i].args[1] = 1; + else if (lines[i].flags & ML_EFFECT4) + lines[i].args[1] = 0; + else + lines[i].args[1] = 2; + break; case 411: //Stop plane movement lines[i].args[0] = tag; break; diff --git a/src/p_spec.c b/src/p_spec.c index 723b71b9b..66071d9c6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2284,6 +2284,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) EV_DoCeiling(line->args[0], line, moveCeilingByDistance); break; + case 408: // Set flats + { + TAG_ITER_SECTORS(line->args[0], secnum) + { + if (line->args[1] != 1) + sectors[secnum].floorpic = line->frontsector->floorpic; + if (line->args[1] != 0) + sectors[secnum].ceilingpic = line->frontsector->ceilingpic; + } + break; + } + case 409: // Change tagged sectors' tag // (formerly "Change calling sectors' tag", but behavior was changed) { From 2da5b54e7383bb4017d310bd3d18f85cb1177b86 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 27 Jun 2021 12:21:26 +0200 Subject: [PATCH 089/326] Now that set flats linedef exists, simplify set heights linedef --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 18 ++++----------- src/p_ceilng.c | 24 +++++++------------- src/p_floor.c | 6 ++--- src/p_setup.c | 4 ++-- src/p_spec.c | 4 ++-- 5 files changed, 19 insertions(+), 37 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 0e110cfb6..abe50c1b5 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2434,23 +2434,15 @@ udmf } arg1 { - title = "Set heights?"; - type = 12; - enum - { - 1 = "Floor"; - 2 = "Ceiling"; - } + title = "Affected planes"; + type = 11; + enum = "floorceiling"; } arg2 { title = "Set flats?"; - type = 12; - enum - { - 1 = "Floor"; - 2 = "Ceiling"; - } + type = 11; + enum = "noyes"; } } diff --git a/src/p_ceilng.c b/src/p_ceilng.c index b64d496fb..ed385be33 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -273,27 +273,19 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) case instantMoveCeilingByFrontSector: ceiling->speed = INT32_MAX/2; - if (lines->args[1] & 2) - { - if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up - { - ceiling->direction = 1; - ceiling->topheight = line->frontsector->ceilingheight; - } - else // Move down - { - ceiling->direction = -1; - ceiling->bottomheight = line->frontsector->ceilingheight; - } - } - else + if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up { ceiling->direction = 1; - ceiling->topheight = sec->ceilingheight; + ceiling->topheight = line->frontsector->ceilingheight; + } + else // Move down + { + ceiling->direction = -1; + ceiling->bottomheight = line->frontsector->ceilingheight; } // If flag is set, change ceiling texture after moving - ceiling->texture = (line->args[2] & 2) ? line->frontsector->ceilingpic : -1; + ceiling->texture = line->args[2] ? line->frontsector->ceilingpic : -1; break; case moveCeilingByDistance: diff --git a/src/p_floor.c b/src/p_floor.c index e388657cf..eebb9366e 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1796,11 +1796,9 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) dofloor->floordestheight = P_FindLowestFloorSurrounding(sec); break; - // Linedef executor command, linetype 101. - // Front sector floor = destination height. case instantMoveFloorByFrontSector: dofloor->speed = INT32_MAX/2; // as above, "instant" is one tic - dofloor->floordestheight = (line->args[1] & 1) ? line->frontsector->floorheight : sec->floorheight; + dofloor->floordestheight = line->frontsector->floorheight; if (dofloor->floordestheight >= sec->floorheight) dofloor->direction = 1; // up @@ -1808,7 +1806,7 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) dofloor->direction = -1; // down // If flag is set, change floor texture after moving - dofloor->texture = (line->args[2] & 1) ? line->frontsector->floorpic : -1; + dofloor->texture = line->args[2] ? line->frontsector->floorpic : -1; break; case moveFloorByFrontSector: diff --git a/src/p_setup.c b/src/p_setup.c index 56c3ed78b..2b03fe173 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3548,8 +3548,8 @@ static void P_ConvertBinaryMap(void) case 400: //Set tagged sector's floor height/texture case 401: //Set tagged sector's ceiling height/texture lines[i].args[0] = tag; - lines[i].args[1] = lines[i].special - 399; - lines[i].args[2] = (lines[i].flags & ML_NOCLIMB) ? 0 : lines[i].special - 399; + lines[i].args[1] = lines[i].special - 400; + lines[i].args[2] = !!(lines[i].flags & ML_NOCLIMB); lines[i].special = 400; break; case 403: //Move tagged sector's floor diff --git a/src/p_spec.c b/src/p_spec.c index 66071d9c6..a3fdbe629 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2234,9 +2234,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) switch (line->special) { case 400: // Set tagged sector's heights/flats - if (line->args[1] & 1 || line->args[2] & 1) + if (line->args[1] != 1) EV_DoFloor(line->args[0], line, instantMoveFloorByFrontSector); - if (line->args[1] & 2 || line->args[2] & 2) + if (line->args[1] != 0) EV_DoCeiling(line->args[0], line, instantMoveCeilingByFrontSector); break; From ac5eb1518dc161619f405b1cae978b382e034da7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 27 Jun 2021 12:36:46 +0200 Subject: [PATCH 090/326] Add floor/ceiling/both enum --- src/p_setup.c | 14 +++++++------- src/p_spec.c | 28 ++++++++++++++-------------- src/p_spec.h | 7 +++++++ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 2b03fe173..46397dafb 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3093,7 +3093,7 @@ static void P_ConvertBinaryMap(void) case 54: //Continuous floor mover case 55: //Continuous ceiling mover lines[i].args[0] = tag; - lines[i].args[1] = (lines[i].special == 53) ? 2 : lines[i].special - 54; + lines[i].args[1] = (lines[i].special == 53) ? TMP_BOTH : lines[i].special - 54; lines[i].args[2] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; lines[i].args[3] = lines[i].args[2]; lines[i].args[4] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; @@ -3104,7 +3104,7 @@ static void P_ConvertBinaryMap(void) case 57: //Continuous two-speed floor mover case 58: //Continuous two-speed ceiling mover lines[i].args[0] = tag; - lines[i].args[1] = (lines[i].special == 56) ? 2 : lines[i].special - 57; + lines[i].args[1] = (lines[i].special == 56) ? TMP_BOTH : lines[i].special - 57; lines[i].args[2] = abs(lines[i].dx) >> FRACBITS; lines[i].args[3] = abs(lines[i].dy) >> FRACBITS; lines[i].args[4] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; @@ -3564,7 +3564,7 @@ static void P_ConvertBinaryMap(void) case 405: //Move floor according to front texture offsets case 407: //Move ceiling according to front texture offsets lines[i].args[0] = tag; - lines[i].args[1] = (lines[i].special == 405) ? 0 : 1; + lines[i].args[1] = (lines[i].special == 405) ? TMP_FLOOR : TMP_CEILING; lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; lines[i].args[3] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[4] = !!(lines[i].flags & ML_NOCLIMB); @@ -3578,11 +3578,11 @@ static void P_ConvertBinaryMap(void) lines[i].special = 0; } else if (lines[i].flags & ML_NOCLIMB) - lines[i].args[1] = 1; + lines[i].args[1] = TMP_CEILING; else if (lines[i].flags & ML_EFFECT4) - lines[i].args[1] = 0; + lines[i].args[1] = TMP_FLOOR; else - lines[i].args[1] = 2; + lines[i].args[1] = TMP_BOTH; break; case 411: //Stop plane movement lines[i].args[0] = tag; @@ -3598,7 +3598,7 @@ static void P_ConvertBinaryMap(void) case 430: //Crush floor once case 431: //Crush floor and ceiling once lines[i].args[0] = tag; - lines[i].args[1] = (lines[i].special == 429) ? 1 : ((lines[i].special == 430) ? 0 : 2); + lines[i].args[1] = (lines[i].special == 429) ? TMP_CEILING : ((lines[i].special == 430) ? TMP_FLOOR : TMP_BOTH); if (lines[i].special == 430 || lines[i].flags & ML_EFFECT4) { lines[i].args[2] = abs(lines[i].dx) >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index a3fdbe629..9987a7c6f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2234,9 +2234,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) switch (line->special) { case 400: // Set tagged sector's heights/flats - if (line->args[1] != 1) + if (line->args[1] != TMP_CEILING) EV_DoFloor(line->args[0], line, instantMoveFloorByFrontSector); - if (line->args[1] != 0) + if (line->args[1] != TMP_FLOOR) EV_DoCeiling(line->args[0], line, instantMoveCeilingByFrontSector); break; @@ -2271,16 +2271,16 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 403: // Move planes by front sector - if (line->args[1] != 1) + if (line->args[1] != TMP_CEILING) EV_DoFloor(line->args[0], line, moveFloorByFrontSector); - if (line->args[1] != 0) + if (line->args[1] != TMP_FLOOR) EV_DoCeiling(line->args[0], line, moveCeilingByFrontSector); break; case 405: // Move planes by distance - if (line->args[1] != 1) + if (line->args[1] != TMP_CEILING) EV_DoFloor(line->args[0], line, moveFloorByDistance); - if (line->args[1] != 0) + if (line->args[1] != TMP_FLOOR) EV_DoCeiling(line->args[0], line, moveCeilingByDistance); break; @@ -2288,9 +2288,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { TAG_ITER_SECTORS(line->args[0], secnum) { - if (line->args[1] != 1) + if (line->args[1] != TMP_CEILING) sectors[secnum].floorpic = line->frontsector->floorpic; - if (line->args[1] != 0) + if (line->args[1] != TMP_FLOOR) sectors[secnum].ceilingpic = line->frontsector->ceilingpic; } break; @@ -2883,9 +2883,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 429: // Crush planes once - if (line->args[1] == 0) + if (line->args[1] == TMP_FLOOR) EV_DoFloor(line->args[0], line, crushFloorOnce); - else if (line->args[1] == 1) + else if (line->args[1] == TMP_CEILING) EV_DoCrush(line->args[0], line, crushCeilOnce); else EV_DoCrush(line->args[0], line, crushBothOnce); @@ -6340,9 +6340,9 @@ void P_SpawnSpecials(boolean fromnetsave) case 53: // Continuous plane movement (slowdown) if (lines[i].backsector) { - if (lines[i].args[1] != 1) + if (lines[i].args[1] != TMP_CEILING) EV_DoFloor(lines[i].args[0], &lines[i], bounceFloor); - if (lines[i].args[1] != 0) + if (lines[i].args[1] != TMP_FLOOR) EV_DoCeiling(lines[i].args[0], &lines[i], bounceCeiling); } break; @@ -6350,9 +6350,9 @@ void P_SpawnSpecials(boolean fromnetsave) case 56: // Continuous plane movement (constant) if (lines[i].backsector) { - if (lines[i].args[1] != 1) + if (lines[i].args[1] != TMP_CEILING) EV_DoFloor(lines[i].args[0], &lines[i], bounceFloorCrush); - if (lines[i].args[1] != 0) + if (lines[i].args[1] != TMP_FLOOR) EV_DoCeiling(lines[i].args[0], &lines[i], bounceCeilingCrush); } break; diff --git a/src/p_spec.h b/src/p_spec.h index 921af714e..642f7fadf 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -102,6 +102,13 @@ typedef enum TMFL_SPLAT = 1<<1, } textmapfoflaserflags_t; +typedef enum +{ + TMP_FLOOR = 0, + TMP_CEILING = 1, + TMP_BOTH = 2, +} textmapplanes_t; + // GETSECSPECIAL (specialval, section) // // Pulls out the special # from a particular section. From 09bcc918c5a41786ce4407345e9e99ea1941959d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 27 Jun 2021 17:14:34 +0200 Subject: [PATCH 091/326] Fix alpha for rising and intangible FOFs --- src/p_spec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index a3c356194..6f66cb4a8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6664,7 +6664,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_CUTLEVEL; } - P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); P_AddRaiseThinker(lines[i].frontsector, lines[i].args[0], lines[i].args[4] << FRACBITS, ceilingtop, ceilingbottom, !!(lines[i].args[5] & TMFR_REVERSE), !!(lines[i].args[5] & TMFR_SPINDASH)); break; } @@ -6711,7 +6711,7 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[2] & TMFA_SPLAT) ffloorflags |= FF_SPLAT; - P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); break; case 223: // FOF (intangible, invisible) - for combining specials in a sector From b0a762a45e710b111c756c5fbf466309fa712e71 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 27 Jun 2021 17:49:00 +0200 Subject: [PATCH 092/326] Add missing null checks after P_AddFakeFloor calls --- src/p_spec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 6f66cb4a8..0b1b8e90f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6776,6 +6776,8 @@ void P_SpawnSpecials(boolean fromnetsave) TAG_ITER_SECTORS(lines[i].args[0], s) { ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers); + if (!fflr) + continue; fflr->busttype = busttype; fflr->specialflags = bustflags; fflr->busttag = lines[i].args[4]; @@ -6790,6 +6792,8 @@ void P_SpawnSpecials(boolean fromnetsave) TAG_ITER_SECTORS(lines[i].args[0], s) { ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, ffloorflags, secthinkers); + if (!fflr) + continue; fflr->sinkspeed = abs(lines[i].args[2]) << (FRACBITS - 1); fflr->friction = abs(lines[i].args[3]) << (FRACBITS - 6); } @@ -6807,6 +6811,8 @@ void P_SpawnSpecials(boolean fromnetsave) TAG_ITER_SECTORS(lines[i].args[0], s) { ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], lines[i].args[2], secthinkers); + if (!fflr) + continue; if (!udmf) // Ugly backwards compatibility stuff { if (lines[i].args[2] & FF_QUICKSAND) From 06e06a1cb652e0df572067b4c54d82ec2f4214f6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 27 Jun 2021 18:45:56 +0200 Subject: [PATCH 093/326] Replicate old hack in binary maps: Translucent FOFs set to full opacity cut cyan pixels --- src/p_setup.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- src/p_spec.c | 2 +- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index b0488dbbb..c88aa02f5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3104,17 +3104,21 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else lines[i].args[1] = 128; + + //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels + if (lines[i].args[1] == 256) + lines[i].args[2] |= TMFA_SPLAT; } else lines[i].args[1] = 255; //Appearance if (lines[i].special == 105) - lines[i].args[2] = TMFA_NOPLANES|TMFA_NOSIDES; + lines[i].args[2] |= TMFA_NOPLANES|TMFA_NOSIDES; else if (lines[i].special == 104) - lines[i].args[2] = TMFA_NOSIDES; + lines[i].args[2] |= TMFA_NOSIDES; else if (lines[i].special == 103) - lines[i].args[2] = TMFA_NOPLANES; + lines[i].args[2] |= TMFA_NOPLANES; if (lines[i].special != 100 && (lines[i].special != 104 || !(lines[i].flags & ML_NOCLIMB))) lines[i].args[2] |= TMFA_NOSHADE; if (lines[i].flags & ML_EFFECT6) @@ -3145,6 +3149,10 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else lines[i].args[1] = 128; + + //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels + if (lines[i].args[1] == 256) + lines[i].args[2] |= TMFW_SPLAT; } //No sides? @@ -3187,15 +3195,19 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else lines[i].args[1] = 128; + + //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels + if (lines[i].args[1] == 256) + lines[i].args[2] |= TMFA_SPLAT; } else lines[i].args[1] = 255; //Appearance if (lines[i].special == 142 || lines[i].special == 145) - lines[i].args[2] = TMFA_NOSIDES; + lines[i].args[2] |= TMFA_NOSIDES; else if (lines[i].special == 146) - lines[i].args[2] = TMFA_NOPLANES; + lines[i].args[2] |= TMFA_NOPLANES; if (lines[i].special != 146 && (lines[i].flags & ML_NOCLIMB)) lines[i].args[2] |= TMFA_NOSHADE; if (lines[i].flags & ML_EFFECT6) @@ -3256,6 +3268,10 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else lines[i].args[1] = 128; + + //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels + if (lines[i].args[1] == 256) + lines[i].args[3] |= TMFC_SPLAT; } else lines[i].args[1] = 255; @@ -3298,15 +3314,19 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else lines[i].args[1] = 128; + + //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels + if (lines[i].args[1] == 256) + lines[i].args[2] |= TMFA_SPLAT; } else lines[i].args[1] = 255; //Appearance if (lines[i].special == 193) - lines[i].args[2] = TMFA_NOPLANES|TMFA_NOSIDES; + lines[i].args[2] |= TMFA_NOPLANES|TMFA_NOSIDES; if (lines[i].special >= 194) - lines[i].args[2] = TMFA_INSIDES; + lines[i].args[2] |= TMFA_INSIDES; if (lines[i].special != 190 && (lines[i].special <= 193 || lines[i].flags & ML_NOCLIMB)) lines[i].args[2] |= TMFA_NOSHADE; if (lines[i].flags & ML_EFFECT6) @@ -3354,6 +3374,10 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else lines[i].args[1] = 128; + + //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels + if (lines[i].args[1] == 256) + lines[i].args[2] |= TMFA_SPLAT; } else lines[i].args[1] = 255; @@ -3411,6 +3435,10 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else lines[i].args[1] = 128; + + //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels + if (lines[i].args[1] == 256) + lines[i].args[3] |= TMFB_SPLAT; } else lines[i].args[1] = 255; @@ -3459,7 +3487,8 @@ static void P_ConvertBinaryMap(void) //Flags if (lines[i].flags & ML_EFFECT1) lines[i].args[2] = TMFL_NOBOSSES; - if (lines[i].flags & ML_EFFECT6) + //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels + if (lines[i].flags & ML_EFFECT6 || lines[i].args[1] == 256) lines[i].args[2] = TMFL_SPLAT; break; @@ -3478,6 +3507,10 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; else lines[i].args[1] = 128; + + //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels + if (lines[i].args[1] == 256) + lines[i].args[2] |= FF_SPLAT; } else lines[i].args[1] = 255; diff --git a/src/p_spec.c b/src/p_spec.c index 0b1b8e90f..ae144307e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5635,7 +5635,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I } fflr->alpha = max(0, min(0xff, alpha)); - if (fflr->alpha < 0xff) + if (fflr->alpha < 0xff || flags & FF_SPLAT) { fflr->flags |= FF_TRANSLUCENT; fflr->spawnflags = fflr->flags; From 977887f4566d0bb7d580cb23bc9a319c0c181262 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 30 Jun 2021 23:50:54 +0200 Subject: [PATCH 094/326] Adapt scroller linedefs to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 93 +++++++++++ extras/conf/udb/Includes/SRB222_misc.cfg | 21 +++ src/p_setup.c | 86 ++++++++++ src/p_spec.c | 166 ++++++------------- src/p_spec.h | 26 +++ 5 files changed, 279 insertions(+), 113 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index abe50c1b5..f67372e88 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2731,6 +2731,99 @@ udmf } } + scroll + { + title = "Wall and Plane Scrolling"; + + 500 + { + title = "Scroll Walls"; + prefix = "(500)"; + arg0 + { + title = "Side"; + type = 11; + enum = "frontbackboth"; + } + arg1 + { + title = "Horizontal speed"; + } + arg2 + { + title = "Vertical speed"; + } + } + + 502 + { + title = "Scroll Walls Remotely"; + prefix = "(502)"; + arg0 + { + title = "Linedef tag"; + type = 15; + } + arg1 + { + title = "Side"; + type = 11; + enum = "frontbackboth"; + } + arg2 + { + title = "Horizontal speed"; + } + arg3 + { + title = "Vertical speed"; + } + arg4 + { + title = "Type"; + type = 11; + enum = "scrolltype"; + } + } + + 510 + { + title = "Scroll Planes"; + prefix = "(510)"; + arg0 + { + title = "Sector tag"; + type = 13; + } + arg1 + { + title = "Affected planes"; + type = 11; + enum = "floorceiling"; + } + arg2 + { + title = "Scroll/Carry?"; + type = 11; + enum = "scrollcarry"; + } + arg3 + { + title = "Base speed"; + } + arg4 + { + title = "Type"; + type = 26; + enum = "scrolltype"; + flags + { + 4 = "Exclusive"; + } + } + } + } + light { 606 diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 1fa98a212..8a4bc29e2 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -437,6 +437,13 @@ enums 2 = "Back"; } + frontbackboth + { + 0 = "Front"; + 1 = "Back"; + 2 = "Front and back"; + } + tangibility { 1 = "Intangible from top"; @@ -451,6 +458,20 @@ enums 1 = "Ceiling"; 2 = "Both"; } + + scrollcarry + { + 0 = "Scroll and carry"; + 1 = "Scroll"; + 2 = "Carry"; + } + + scrolltype + { + 0 = "Regular"; + 1 = "Accelerative"; + 2 = "Displacement"; + } } //Default things filters diff --git a/src/p_setup.c b/src/p_setup.c index 46397dafb..9bc87af94 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3659,6 +3659,92 @@ static void P_ConvertBinaryMap(void) case 456: //Stop fading colormap lines[i].args[0] = Tag_FGet(&lines[i].tags); break; + case 500: //Scroll front wall left + case 501: //Scroll front wall right + lines[i].args[0] = 0; + lines[i].args[1] = (lines[i].special == 500) ? -1 : 1; + lines[i].args[2] = 0; + lines[i].special = 500; + break; + case 502: //Scroll tagged wall + case 503: //Scroll tagged wall (accelerative) + case 504: //Scroll tagged wall (displacement) + lines[i].args[0] = tag; + if (lines[i].flags & ML_EFFECT3) + { + if (lines[i].sidenum[1] == 0xffff) + { + CONS_Debug(DBG_GAMELOGIC, "Line special %d (line #%s) missing back side!\n", lines[i].special, sizeu1(i)); + lines[i].special = 0; + break; + } + lines[i].args[1] = 1; + } + else + lines[i].args[1] = 0; + if (lines[i].flags & ML_EFFECT2) + { + lines[i].args[2] = lines[i].dx >> (FRACBITS + SCROLL_SHIFT); + lines[i].args[3] = lines[i].dy >> (FRACBITS + SCROLL_SHIFT); + } + else + { + lines[i].args[2] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[3] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + } + lines[i].args[4] = lines[i].special - 502; + lines[i].special = 502; + break; + case 505: //Scroll front wall by front side offsets + case 506: //Scroll front wall by back side offsets + case 507: //Scroll back wall by front side offsets + case 508: //Scroll back wall by back side offsets + lines[i].args[0] = lines[i].special >= 507; + if (lines[i].special % 2 == 0) + { + if (lines[i].sidenum[1] == 0xffff) + { + CONS_Debug(DBG_GAMELOGIC, "Line special %d (line #%s) missing back side!\n", lines[i].special, sizeu1(i)); + lines[i].special = 0; + break; + } + lines[i].args[1] = sides[lines[i].sidenum[1]].rowoffset >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[1]].textureoffset >> FRACBITS; + } + else + { + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + } + lines[i].special = 500; + break; + case 510: //Scroll floor texture + case 511: //Scroll floor texture (accelerative) + case 512: //Scroll floor texture (displacement) + case 513: //Scroll ceiling texture + case 514: //Scroll ceiling texture (accelerative) + case 515: //Scroll ceiling texture (displacement) + case 520: //Carry objects on floor + case 521: //Carry objects on floor (accelerative) + case 522: //Carry objects on floor (displacement) + case 523: //Carry objects on ceiling + case 524: //Carry objects on ceiling (accelerative) + case 525: //Carry objects on ceiling (displacement) + case 530: //Scroll floor texture and carry objects + case 531: //Scroll floor texture and carry objects (accelerative) + case 532: //Scroll floor texture and carry objects (displacement) + case 533: //Scroll ceiling texture and carry objects + case 534: //Scroll ceiling texture and carry objects (accelerative) + case 535: //Scroll ceiling texture and carry objects (displacement) + lines[i].args[0] = tag; + lines[i].args[1] = ((lines[i].special % 10) < 3) ? TMP_FLOOR : TMP_CEILING; + lines[i].args[2] = ((lines[i].special - 510)/10 + 1) % 3; + lines[i].args[3] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + lines[i].args[4] = (lines[i].special % 10) % 3; + if (lines[i].args[2] != 1 && lines[i].flags & ML_NOCLIMB) + lines[i].args[4] |= 4; + lines[i].special = 510; + break; case 606: //Colormap lines[i].args[0] = Tag_FGet(&lines[i].tags); break; diff --git a/src/p_spec.c b/src/p_spec.c index 9987a7c6f..cf6dc5fdd 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -51,9 +51,6 @@ mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpoint mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs -// Amount (dx, dy) vector linedef is shifted right to get scroll amount -#define SCROLL_SHIFT 5 - /** Animated texture descriptor * This keeps track of an animated texture or an animated flat. * \sa P_UpdateSpecials, P_InitPicAnims, animdef_t @@ -7596,6 +7593,24 @@ static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT3 P_AddThinker(THINK_MAIN, &s->thinker); } +static void P_SpawnPlaneScroller(line_t *l, fixed_t dx, fixed_t dy, INT32 control, INT32 affectee, INT32 accel, INT32 exclusive) +{ + if (l->args[1] != TMP_CEILING) + { + if (l->args[2] != TMS_SCROLLONLY) + Add_Scroller(sc_carry, FixedMul(dx, CARRYFACTOR), FixedMul(dy, CARRYFACTOR), control, affectee, accel, exclusive); + if (l->args[2] != TMS_CARRYONLY) + Add_Scroller(sc_floor, -dx, dy, control, affectee, accel, exclusive); + } + if (l->args[1] != TMP_FLOOR) + { + if (l->args[2] != TMS_SCROLLONLY) + Add_Scroller(sc_carry_ceiling, FixedMul(dx, CARRYFACTOR), FixedMul(dy, CARRYFACTOR), control, affectee, accel, exclusive); + if (l->args[2] != TMS_CARRYONLY) + Add_Scroller(sc_ceiling, -dx, dy, control, affectee, accel, exclusive); + } +} + /** Initializes the scrollers. * * \todo Get rid of all the magic numbers. @@ -7605,140 +7620,65 @@ static void P_SpawnScrollers(void) { size_t i; line_t *l = lines; - mtag_t tag; for (i = 0; i < numlines; i++, l++) { - fixed_t dx = l->dx >> SCROLL_SHIFT; // direction and speed of scrolling - fixed_t dy = l->dy >> SCROLL_SHIFT; INT32 control = -1, accel = 0; // no control sector or acceleration - INT32 special = l->special; - tag = Tag_FGet(&l->tags); - - // These types are same as the ones they get set to except that the - // first side's sector's heights cause scrolling when they change, and - // this linedef controls the direction and speed of the scrolling. The - // most complicated linedef since donuts, but powerful :) - - if (special == 515 || special == 512 || special == 522 || special == 532 || special == 504) // displacement scrollers + if (l->special == 502 || l->special == 510) { - special -= 2; - control = (INT32)(sides[*l->sidenum].sector - sectors); - } - else if (special == 514 || special == 511 || special == 521 || special == 531 || special == 503) // accelerative scrollers - { - special--; - accel = 1; - control = (INT32)(sides[*l->sidenum].sector - sectors); - } - else if (special == 535 || special == 525) // displacement scrollers - { - special -= 2; - control = (INT32)(sides[*l->sidenum].sector - sectors); - } - else if (special == 534 || special == 524) // accelerative scrollers - { - accel = 1; - special--; - control = (INT32)(sides[*l->sidenum].sector - sectors); + if ((l->args[4] & TMST_TYPEMASK) != TMST_REGULAR) + control = (INT32)(sides[*l->sidenum].sector - sectors); + if ((l->args[4] & TMST_TYPEMASK) == TMST_ACCELERATIVE) + accel = 1; } - switch (special) + switch (l->special) { register INT32 s; - case 513: // scroll effect ceiling - case 533: // scroll and carry objects on ceiling - TAG_ITER_SECTORS(tag, s) - Add_Scroller(sc_ceiling, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); - if (special != 533) - break; - /* FALLTHRU */ + case 510: // plane scroller + { + fixed_t length = R_PointToDist2(l->v2->x, l->v2->y, l->v1->x, l->v1->y); + fixed_t speed = l->args[3] << FRACBITS; + fixed_t dx = FixedMul(FixedDiv(l->dx, length), speed) >> SCROLL_SHIFT; + fixed_t dy = FixedMul(FixedDiv(l->dy, length), speed) >> SCROLL_SHIFT; - case 523: // carry objects on ceiling - dx = FixedMul(dx, CARRYFACTOR); - dy = FixedMul(dy, CARRYFACTOR); - TAG_ITER_SECTORS(tag, s) - Add_Scroller(sc_carry_ceiling, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); - break; - - case 510: // scroll effect floor - case 530: // scroll and carry objects on floor - TAG_ITER_SECTORS(tag, s) - Add_Scroller(sc_floor, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); - if (special != 530) - break; - /* FALLTHRU */ - - case 520: // carry objects on floor - dx = FixedMul(dx, CARRYFACTOR); - dy = FixedMul(dy, CARRYFACTOR); - TAG_ITER_SECTORS(tag, s) - Add_Scroller(sc_carry, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); + if (l->args[0] == 0) + P_SpawnPlaneScroller(l, dx, dy, control, (INT32)(l->frontsector - sectors), accel, l->args[4] & TMST_EXCLUSIVE); + else + { + TAG_ITER_SECTORS(l->args[0], s) + P_SpawnPlaneScroller(l, dx, dy, control, s, accel, l->args[4] & TMST_EXCLUSIVE); + } break; + } // scroll wall according to linedef // (same direction and speed as scrolling floors) case 502: { - TAG_ITER_LINES(tag, s) + TAG_ITER_LINES(l->args[0], s) if (s != (INT32)i) { - if (l->flags & ML_EFFECT2) // use texture offsets instead - { - dx = sides[l->sidenum[0]].textureoffset; - dy = sides[l->sidenum[0]].rowoffset; - } - if (l->flags & ML_EFFECT3) - { - if (lines[s].sidenum[1] != 0xffff) - Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[1], accel, 0); - } - else - Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[0], accel, 0); + if (l->args[1] != TMSD_BACK) + Add_Scroller(sc_side, l->args[2] << FRACBITS, l->args[3] << FRACBITS, control, lines[s].sidenum[0], accel, 0); + if (l->args[1] != TMSD_FRONT && lines[s].sidenum[1] != 0xffff) + Add_Scroller(sc_side, l->args[2] << FRACBITS, l->args[3] << FRACBITS, control, lines[s].sidenum[1], accel, 0); } break; } - case 505: - s = lines[i].sidenum[0]; - Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, s, accel, 0); - break; - - case 506: - s = lines[i].sidenum[1]; - - if (s != 0xffff) - Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, lines[i].sidenum[0], accel, 0); - else - CONS_Debug(DBG_GAMELOGIC, "Line special 506 (line #%s) missing back side!\n", sizeu1(i)); - break; - - case 507: - s = lines[i].sidenum[0]; - - if (lines[i].sidenum[1] != 0xffff) - Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, lines[i].sidenum[1], accel, 0); - else - CONS_Debug(DBG_GAMELOGIC, "Line special 507 (line #%s) missing back side!\n", sizeu1(i)); - break; - - case 508: - s = lines[i].sidenum[1]; - - if (s != 0xffff) - Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, s, accel, 0); - else - CONS_Debug(DBG_GAMELOGIC, "Line special 508 (line #%s) missing back side!\n", sizeu1(i)); - break; - - case 500: // scroll first side - Add_Scroller(sc_side, FRACUNIT, 0, -1, lines[i].sidenum[0], accel, 0); - break; - - case 501: // jff 1/30/98 2-way scroll - Add_Scroller(sc_side, -FRACUNIT, 0, -1, lines[i].sidenum[0], accel, 0); + case 500: + if (l->args[0] != TMSD_BACK) + Add_Scroller(sc_side, -l->args[1] << FRACBITS, l->args[2] << FRACBITS, -1, l->sidenum[0], accel, 0); + if (l->args[0] != TMSD_FRONT) + { + if (l->sidenum[1] != 0xffff) + Add_Scroller(sc_side, -l->args[1] << FRACBITS, l->args[2] << FRACBITS, -1, l->sidenum[1], accel, 0); + else + CONS_Debug(DBG_GAMELOGIC, "Line special 500 (line #%s) missing back side!\n", sizeu1(i)); + } break; } } diff --git a/src/p_spec.h b/src/p_spec.h index 642f7fadf..aa9f85bc8 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -21,6 +21,9 @@ extern mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpo extern mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs extern mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs +// Amount (dx, dy) vector linedef is shifted right to get scroll amount +#define SCROLL_SHIFT 5 + //FOF flags typedef enum { @@ -109,6 +112,29 @@ typedef enum TMP_BOTH = 2, } textmapplanes_t; +typedef enum +{ + TMSD_FRONT = 0, + TMSD_BACK = 1, + TMSD_FRONTBACK = 2, +} textmapsides_t; + +typedef enum +{ + TMS_SCROLLCARRY = 0, + TMS_SCROLLONLY = 1, + TMS_CARRYONLY = 2, +} textmapscroll_t; + +typedef enum +{ + TMST_REGULAR = 0, + TMST_ACCELERATIVE = 1, + TMST_DISPLACEMENT = 2, + TMST_TYPEMASK = 3, + TMST_EXCLUSIVE = 4, +} textmapscrolltype_t; + // GETSECSPECIAL (specialval, section) // // Pulls out the special # from a particular section. From 052bfe130ce5f96ae29f12f2e7183800c863d638 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 1 Jul 2021 00:47:56 +0200 Subject: [PATCH 095/326] Make exclusive scrolling the default --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 2 +- src/p_setup.c | 4 ++-- src/p_spec.c | 4 ++-- src/p_spec.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index f67372e88..449691cdc 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2818,7 +2818,7 @@ udmf enum = "scrolltype"; flags { - 4 = "Exclusive"; + 4 = "Non-exclusive"; } } } diff --git a/src/p_setup.c b/src/p_setup.c index 9bc87af94..575998d20 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3741,8 +3741,8 @@ static void P_ConvertBinaryMap(void) lines[i].args[2] = ((lines[i].special - 510)/10 + 1) % 3; lines[i].args[3] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; lines[i].args[4] = (lines[i].special % 10) % 3; - if (lines[i].args[2] != 1 && lines[i].flags & ML_NOCLIMB) - lines[i].args[4] |= 4; + if (lines[i].args[2] != TMS_SCROLLONLY && !(lines[i].flags & ML_NOCLIMB)) + lines[i].args[4] |= TMST_NONEXCLUSIVE; lines[i].special = 510; break; case 606: //Colormap diff --git a/src/p_spec.c b/src/p_spec.c index cf6dc5fdd..32b935959 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7645,11 +7645,11 @@ static void P_SpawnScrollers(void) fixed_t dy = FixedMul(FixedDiv(l->dy, length), speed) >> SCROLL_SHIFT; if (l->args[0] == 0) - P_SpawnPlaneScroller(l, dx, dy, control, (INT32)(l->frontsector - sectors), accel, l->args[4] & TMST_EXCLUSIVE); + P_SpawnPlaneScroller(l, dx, dy, control, (INT32)(l->frontsector - sectors), accel, l->args[4] & TMST_NONEXCLUSIVE); else { TAG_ITER_SECTORS(l->args[0], s) - P_SpawnPlaneScroller(l, dx, dy, control, s, accel, l->args[4] & TMST_EXCLUSIVE); + P_SpawnPlaneScroller(l, dx, dy, control, s, accel, l->args[4] & TMST_NONEXCLUSIVE); } break; } diff --git a/src/p_spec.h b/src/p_spec.h index aa9f85bc8..c2b6953cf 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -132,7 +132,7 @@ typedef enum TMST_ACCELERATIVE = 1, TMST_DISPLACEMENT = 2, TMST_TYPEMASK = 3, - TMST_EXCLUSIVE = 4, + TMST_NONEXCLUSIVE = 4, } textmapscrolltype_t; // GETSECSPECIAL (specialval, section) From d0888c4ac5e4b9d58f48f3b8c209bd561ab76e16 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 1 Jul 2021 18:48:18 +0200 Subject: [PATCH 096/326] Split wind/current and point push/pull thinkers --- src/p_saveg.c | 38 +++++++++++++++++++++ src/p_spec.c | 92 +++++++++++++++++++++++++++++++-------------------- src/p_spec.h | 13 +++++++- src/p_tick.c | 8 ++++- 4 files changed, 114 insertions(+), 37 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index bf28b11a5..ea81e9853 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1483,6 +1483,7 @@ typedef enum tc_scroll, tc_friction, tc_pusher, + tc_pointpusher, tc_laserflash, tc_lightfade, tc_executor, @@ -2141,6 +2142,19 @@ static inline void SavePusherThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->slider); } +static inline void SavePointPusherThinker(const thinker_t* th, const UINT8 type) +{ + const pointpusher_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEINT32(save_p, ht->magnitude); + WRITEINT32(save_p, ht->radius); + WRITEINT32(save_p, ht->x); + WRITEINT32(save_p, ht->y); + WRITEINT32(save_p, ht->z); + WRITEINT32(save_p, ht->affectee); + WRITEINT32(save_p, ht->exclusive); +} + static void SaveLaserThinker(const thinker_t *th, const UINT8 type) { const laserthink_t *ht = (const void *)th; @@ -2460,6 +2474,11 @@ static void P_NetArchiveThinkers(void) SavePusherThinker(th, tc_pusher); continue; } + else if (th->function.acp1 == (actionf_p1)T_PointPusher) + { + SavePointPusherThinker(th, tc_pointpusher); + continue; + } else if (th->function.acp1 == (actionf_p1)T_BounceCheese) { SaveBounceCheeseThinker(th, tc_bouncecheese); @@ -3282,6 +3301,21 @@ static thinker_t* LoadPusherThinker(actionf_p1 thinker) return &ht->thinker; } +static thinker_t* LoadPointPusherThinker(actionf_p1 thinker) +{ + pointpusher_t *ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->magnitude = READINT32(save_p); + ht->radius = READINT32(save_p); + ht->x = READINT32(save_p); + ht->y = READINT32(save_p); + ht->z = READINT32(save_p); + ht->affectee = READINT32(save_p); + ht->exclusive = READINT32(save_p); + ht->source = P_GetPushThing(ht->affectee); + return &ht->thinker; +} + static inline thinker_t* LoadLaserThinker(actionf_p1 thinker) { laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); @@ -3744,6 +3778,10 @@ static void P_NetUnArchiveThinkers(void) th = LoadPusherThinker((actionf_p1)T_Pusher); break; + case tc_pointpusher: + th = LoadPointPusherThinker((actionf_p1)T_PointPusher); + break; + default: I_Error("P_UnarchiveSpecials: Unknown tclass %d in savegame", tclass); } diff --git a/src/p_spec.c b/src/p_spec.c index 32b935959..e05f1f066 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -98,6 +98,7 @@ typedef struct static void P_SpawnScrollers(void); static void P_SpawnFriction(void); static void P_SpawnPushers(void); +static void Add_PointPusher(INT32 magnitude, mobj_t *source, INT32 affectee, INT32 exclusive); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); @@ -5608,6 +5609,13 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I if (p->affectee == (INT32)sec2num) Add_Pusher(p->type, p->x_mag<y_mag<source, (INT32)(sec-sectors), p->affectee, p->exclusive, p->slider); } + else if (th->function.acp1 == (actionf_p1)T_PointPusher) + { + pointpusher_t *pp = (pointpusher_t *)th; + + if (pp->affectee == (INT32)sec2num) + Add_PointPusher(pp->magnitude, pp->source, pp->affectee, pp->exclusive); + } if(secthinkers) i++; else th = th->next; @@ -6169,6 +6177,8 @@ void P_SpawnSpecials(boolean fromnetsave) secthinkers[((friction_t *)th)->affectee].count++; else if (th->function.acp1 == (actionf_p1)T_Pusher) secthinkers[((pusher_t *)th)->affectee].count++; + else if (th->function.acp1 == (actionf_p1)T_PointPusher) + secthinkers[((pointpusher_t *)th)->affectee].count++; } // Allocate each list, and then zero the count so we can use it to track @@ -6189,6 +6199,8 @@ void P_SpawnSpecials(boolean fromnetsave) secnum = ((friction_t *)th)->affectee; else if (th->function.acp1 == (actionf_p1)T_Pusher) secnum = ((pusher_t *)th)->affectee; + else if (th->function.acp1 == (actionf_p1)T_PointPusher) + secnum = ((pointpusher_t *)th)->affectee; if (secnum != (size_t)-1) secthinkers[secnum].thinkers[secthinkers[secnum].count++] = th; @@ -8497,6 +8509,26 @@ static void P_SpawnFriction(void) #define PUSH_FACTOR 7 +static void Add_PointPusher(INT32 magnitude, mobj_t *source, INT32 affectee, INT32 exclusive) +{ + pointpusher_t *p = Z_Calloc(sizeof * p, PU_LEVSPEC, NULL); + + p->thinker.function.acp1 = (actionf_p1)T_PointPusher; + p->source = source; + p->magnitude = magnitude; + p->exclusive = exclusive; + + if (source) // point source exist? + { + p->radius = AngleFixed(source->angle); + p->x = p->source->x; + p->y = p->source->y; + p->z = p->source->z; + } + p->affectee = affectee; + P_AddThinker(THINK_MAIN, &p->thinker); +} + /** Adds a pusher. * * \param type Type of push/pull effect. @@ -8535,12 +8567,7 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * p->magnitude = P_AproxDistance(p->x_mag,p->y_mag); if (source) // point source exist? { - // where force goes to zero - if (type == p_push) - p->radius = AngleFixed(source->angle); - else - p->radius = (p->magnitude)<<(FRACBITS+1); - + p->radius = (p->magnitude)<<(FRACBITS+1); p->x = p->source->x; p->y = p->source->y; p->z = p->source->z; @@ -8549,10 +8576,9 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * P_AddThinker(THINK_MAIN, &p->thinker); } - // PIT_PushThing determines the angle and magnitude of the effect. // The object's x and y momentum values are changed. -static pusher_t *tmpusher; // pusher structure for blockmap searches +static pointpusher_t *tmpusher; // pointpusher structure for blockmap searches /** Applies a point pusher/puller to a thing. * @@ -8702,6 +8728,28 @@ static inline boolean PIT_PushThing(mobj_t *thing) return true; } +void T_PointPusher(pointpusher_t *p) +{ + INT32 xl, xh, yl, yh, bx, by; + + // Seek out all pushable things within the force radius of this + // point pusher. Crosses sectors, so use blockmap. + + tmpusher = p; // MT_PUSH/MT_PULL point source + tmbbox[BOXTOP] = p->y + p->radius; + tmbbox[BOXBOTTOM] = p->y - p->radius; + tmbbox[BOXRIGHT] = p->x + p->radius; + tmbbox[BOXLEFT] = p->x - p->radius; + + xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + P_BlockThingsIterator(bx, by, PIT_PushThing); +} + /** Applies a pusher to all affected objects. * * \param p Thinker for the pusher effect. @@ -8714,9 +8762,6 @@ void T_Pusher(pusher_t *p) mobj_t *thing; msecnode_t *node; INT32 xspeed = 0,yspeed = 0; - INT32 xl, xh, yl, yh, bx, by; - INT32 radius; - //INT32 ht = 0; boolean inFOF; boolean touching; boolean moved; @@ -8756,29 +8801,6 @@ void T_Pusher(pusher_t *p) // // In Phase II, you can apply these effects to Things other than players. - if (p->type == p_push) - { - - // Seek out all pushable things within the force radius of this - // point pusher. Crosses sectors, so use blockmap. - - tmpusher = p; // MT_PUSH/MT_PULL point source - radius = p->radius; // where force goes to zero - tmbbox[BOXTOP] = p->y + radius; - tmbbox[BOXBOTTOM] = p->y - radius; - tmbbox[BOXRIGHT] = p->x + radius; - tmbbox[BOXLEFT] = p->x - radius; - - xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - P_BlockThingsIterator(bx,by, PIT_PushThing); - return; - } - // constant pushers p_wind and p_current node = sec->touching_thinglist; // things touching this sector for (; node; node = node->m_thinglist_next) @@ -9022,7 +9044,7 @@ static void P_SpawnPushers(void) { thing = P_GetPushThing(s); if (thing) // No MT_P* means no effect - Add_Pusher(p_push, l->dx, l->dy, thing, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + Add_PointPusher(P_AproxDistance(l->dx >> FRACBITS, l->dy >> FRACBITS), thing, s, l->flags & ML_NOCLIMB); } break; case 545: // current up diff --git a/src/p_spec.h b/src/p_spec.h index c2b6953cf..10e7c9368 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -632,7 +632,6 @@ void T_Friction(friction_t *f); typedef enum { - p_push, ///< Point pusher or puller. p_wind, ///< Wind. p_current, ///< Current. p_upcurrent, ///< Upwards current. @@ -661,6 +660,17 @@ typedef struct INT32 slider; /// < Should the player go into an uncontrollable slide? } pusher_t; +typedef struct +{ + thinker_t thinker; ///< Thinker structure for push/pull effect. + mobj_t *source; ///< Point source. + INT32 magnitude; ///< Vector strength. + INT32 radius; ///< Effective radius. + INT32 x, y, z; ///< Point source. + INT32 affectee; ///< Number of affected sector. + INT32 exclusive; /// < Once this affect has been applied to a mobj, no other pushers may affect it. +} pointpusher_t; + // Model for disappearing/reappearing FOFs typedef struct { @@ -719,6 +729,7 @@ void T_FadeColormap(fadecolormap_t *d); // Prototype functions for pushers void T_Pusher(pusher_t *p); +void T_PointPusher(pointpusher_t *p); mobj_t *P_GetPushThing(UINT32 s); // Plane displacement diff --git a/src/p_tick.c b/src/p_tick.c index d7357eb82..1a8242db7 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -66,7 +66,8 @@ void Command_Numthinkers_f(void) "\t2: P_NullPrecipThinker\n" "\t3: T_Friction\n" "\t4: T_Pusher\n" - "\t5: P_RemoveThinkerDelayed\n"); + "\t5: T_PointPusher\n" + "\t6: P_RemoveThinkerDelayed\n"); return; } @@ -103,6 +104,11 @@ void Command_Numthinkers_f(void) CONS_Printf(M_GetText("Number of %s: "), "T_Pusher"); break; case 5: + start = end = THINK_MAIN; + action = (actionf_p1)T_PointPusher; + CONS_Printf(M_GetText("Number of %s: "), "T_PointPusher"); + break; + case 6: action = (actionf_p1)P_RemoveThinkerDelayed; CONS_Printf(M_GetText("Number of %s: "), "P_RemoveThinkerDelayed"); break; From 6f698b30650bc60fa7a17faee9c3df059447be22 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 1 Jul 2021 20:05:23 +0200 Subject: [PATCH 097/326] Refactor wind/current thinker --- src/p_saveg.c | 21 +++----- src/p_spec.c | 143 +++++++++++++++----------------------------------- src/p_spec.h | 21 +++----- 3 files changed, 55 insertions(+), 130 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index ea81e9853..567f75c4e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2128,13 +2128,9 @@ static inline void SavePusherThinker(const thinker_t *th, const UINT8 type) const pusher_t *ht = (const void *)th; WRITEUINT8(save_p, type); WRITEUINT8(save_p, ht->type); - WRITEINT32(save_p, ht->x_mag); - WRITEINT32(save_p, ht->y_mag); - WRITEINT32(save_p, ht->magnitude); - WRITEINT32(save_p, ht->radius); - WRITEINT32(save_p, ht->x); - WRITEINT32(save_p, ht->y); - WRITEINT32(save_p, ht->z); + WRITEFIXED(save_p, ht->x_mag); + WRITEFIXED(save_p, ht->y_mag); + WRITEFIXED(save_p, ht->z_mag); WRITEINT32(save_p, ht->affectee); WRITEUINT8(save_p, ht->roverpusher); WRITEINT32(save_p, ht->referrer); @@ -3285,19 +3281,14 @@ static thinker_t* LoadPusherThinker(actionf_p1 thinker) pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->type = READUINT8(save_p); - ht->x_mag = READINT32(save_p); - ht->y_mag = READINT32(save_p); - ht->magnitude = READINT32(save_p); - ht->radius = READINT32(save_p); - ht->x = READINT32(save_p); - ht->y = READINT32(save_p); - ht->z = READINT32(save_p); + ht->x_mag = READFIXED(save_p); + ht->y_mag = READFIXED(save_p); + ht->z_mag = READFIXED(save_p); ht->affectee = READINT32(save_p); ht->roverpusher = READUINT8(save_p); ht->referrer = READINT32(save_p); ht->exclusive = READINT32(save_p); ht->slider = READINT32(save_p); - ht->source = P_GetPushThing(ht->affectee); return &ht->thinker; } diff --git a/src/p_spec.c b/src/p_spec.c index e05f1f066..232e1d0e7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -99,7 +99,7 @@ static void P_SpawnScrollers(void); static void P_SpawnFriction(void); static void P_SpawnPushers(void); static void Add_PointPusher(INT32 magnitude, mobj_t *source, INT32 affectee, INT32 exclusive); -static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 +static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, fixed_t z_mag, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); #define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL, false); @@ -5499,6 +5499,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I thinker_t *th; friction_t *f; pusher_t *p; + pointpusher_t *pp; size_t sec2num; size_t i; @@ -5607,11 +5608,11 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I p = (pusher_t *)th; if (p->affectee == (INT32)sec2num) - Add_Pusher(p->type, p->x_mag<y_mag<source, (INT32)(sec-sectors), p->affectee, p->exclusive, p->slider); + Add_Pusher(p->type, p->x_mag, p->y_mag, p->z_mag, (INT32)(sec-sectors), p->affectee, p->exclusive, p->slider); } else if (th->function.acp1 == (actionf_p1)T_PointPusher) { - pointpusher_t *pp = (pointpusher_t *)th; + pp = (pointpusher_t *)th; if (pp->affectee == (INT32)sec2num) Add_PointPusher(pp->magnitude, pp->source, pp->affectee, pp->exclusive); @@ -8534,20 +8535,20 @@ static void Add_PointPusher(INT32 magnitude, mobj_t *source, INT32 affectee, INT * \param type Type of push/pull effect. * \param x_mag X magnitude. * \param y_mag Y magnitude. - * \param source For a point pusher/puller, the source object. + * \param z_mag Z magnitude. * \param affectee Target sector. * \param referrer What sector set it * \sa T_Pusher, P_GetPushThing, P_SpawnPushers */ -static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider) +static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, fixed_t z_mag, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider) { pusher_t *p = Z_Calloc(sizeof *p, PU_LEVSPEC, NULL); p->thinker.function.acp1 = (actionf_p1)T_Pusher; - p->source = source; p->type = type; - p->x_mag = x_mag>>FRACBITS; - p->y_mag = y_mag>>FRACBITS; + p->x_mag = x_mag; + p->y_mag = y_mag; + p->z_mag = z_mag; p->exclusive = exclusive; p->slider = slider; @@ -8559,19 +8560,6 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * else p->roverpusher = false; - // "The right triangle of the square of the length of the hypotenuse is equal to the sum of the squares of the lengths of the other two sides." - // "Bah! Stupid brains! Don't you know anything besides the Pythagorean Theorem?" - Earthworm Jim - if (type == p_downcurrent || type == p_upcurrent || type == p_upwind || type == p_downwind) - p->magnitude = P_AproxDistance(p->x_mag,p->y_mag)<<(FRACBITS-PUSH_FACTOR); - else - p->magnitude = P_AproxDistance(p->x_mag,p->y_mag); - if (source) // point source exist? - { - p->radius = (p->magnitude)<<(FRACBITS+1); - p->x = p->source->x; - p->y = p->source->y; - p->z = p->source->z; - } p->affectee = affectee; P_AddThinker(THINK_MAIN, &p->thinker); } @@ -8761,12 +8749,15 @@ void T_Pusher(pusher_t *p) sector_t *sec, *referrer = NULL; mobj_t *thing; msecnode_t *node; - INT32 xspeed = 0,yspeed = 0; + fixed_t x_mag, y_mag, z_mag; + fixed_t xspeed = 0, yspeed = 0, zspeed = 0; boolean inFOF; boolean touching; boolean moved; - xspeed = yspeed = 0; + x_mag = p->x_mag >> PUSH_FACTOR; + y_mag = p->y_mag >> PUSH_FACTOR; + z_mag = p->z_mag >> PUSH_FACTOR; sec = sectors + p->affectee; @@ -8875,84 +8866,36 @@ void T_Pusher(pusher_t *p) if (!touching && !inFOF) // Object is out of range of effect continue; - if (p->type == p_wind) + if (inFOF || (p->type == p_current && touching)) { - if (touching) // on ground - { - xspeed = (p->x_mag)>>1; // half force - yspeed = (p->y_mag)>>1; - moved = true; - } - else if (inFOF) - { - xspeed = (p->x_mag); // full force - yspeed = (p->y_mag); - moved = true; - } + xspeed = x_mag; // full force + yspeed = y_mag; + zspeed = z_mag; + moved = true; } - else if (p->type == p_upwind) + else if (p->type == p_wind && touching) { - if (touching) // on ground - { - thing->momz += (p->magnitude)>>1; - moved = true; - } - else if (inFOF) - { - thing->momz += p->magnitude; - moved = true; - } - } - else if (p->type == p_downwind) - { - if (touching) // on ground - { - thing->momz -= (p->magnitude)>>1; - moved = true; - } - else if (inFOF) - { - thing->momz -= p->magnitude; - moved = true; - } - } - else // p_current - { - if (!touching && !inFOF) // Not in water at all - xspeed = yspeed = 0; // no force - else // underwater / touching water - { - if (p->type == p_upcurrent) - thing->momz += p->magnitude; - else if (p->type == p_downcurrent) - thing->momz -= p->magnitude; - else - { - xspeed = p->x_mag; // full force - yspeed = p->y_mag; - } - moved = true; - } + xspeed = x_mag>>1; // half force + yspeed = y_mag>>1; + zspeed = z_mag>>1; + moved = true; } - if (p->type != p_downcurrent && p->type != p_upcurrent - && p->type != p_upwind && p->type != p_downwind) + thing->momx += xspeed; + thing->momy += yspeed; + thing->momz += xspeed; + if (thing->player) { - thing->momx += xspeed<<(FRACBITS-PUSH_FACTOR); - thing->momy += yspeed<<(FRACBITS-PUSH_FACTOR); - if (thing->player) - { - thing->player->cmomx += xspeed<<(FRACBITS-PUSH_FACTOR); - thing->player->cmomy += yspeed<<(FRACBITS-PUSH_FACTOR); - thing->player->cmomx = FixedMul(thing->player->cmomx, ORIG_FRICTION); - thing->player->cmomy = FixedMul(thing->player->cmomy, ORIG_FRICTION); - } - - // Tumbleweeds bounce a bit... - if (thing->type == MT_LITTLETUMBLEWEED || thing->type == MT_BIGTUMBLEWEED) - thing->momz += P_AproxDistance(xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)) >> 2; + thing->player->cmomx += xspeed; + thing->player->cmomy += yspeed; + thing->player->cmomx = FixedMul(thing->player->cmomx, ORIG_FRICTION); + thing->player->cmomy = FixedMul(thing->player->cmomy, ORIG_FRICTION); } + // Tumbleweeds bounce a bit... + if (thing->type == MT_LITTLETUMBLEWEED || thing->type == MT_BIGTUMBLEWEED) + thing->momz += P_AproxDistance(xspeed, yspeed) >> 2; + if (moved) { if (p->slider && thing->player) @@ -8964,7 +8907,7 @@ void T_Pusher(pusher_t *p) thing->player->pflags |= jumped; thing->player->pflags |= PF_SLIDING; - thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)); + thing->angle = R_PointToAngle2(0, 0, xspeed, yspeed); if (!demoplayback || P_ControlStyle(thing->player) == CS_LMAOGALOG) { @@ -9033,11 +8976,11 @@ static void P_SpawnPushers(void) { case 541: // wind TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_wind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + Add_Pusher(p_wind, l->dx, l->dy, 0, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 544: // current TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_current, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + Add_Pusher(p_current, l->dx, l->dy, 0, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 547: // push/pull TAG_ITER_SECTORS(tag, s) @@ -9049,19 +8992,19 @@ static void P_SpawnPushers(void) break; case 545: // current up TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_upcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + Add_Pusher(p_current, 0, 0, P_AproxDistance(l->dx, l->dy), s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 546: // current down TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_downcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + Add_Pusher(p_current, 0, 0, -P_AproxDistance(l->dx, l->dy), s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 542: // wind up TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_upwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + Add_Pusher(p_wind, 0, 0, P_AproxDistance(l->dx, l->dy), s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 543: // wind down TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_downwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + Add_Pusher(p_wind, 0, 0, -P_AproxDistance(l->dx, l->dy), s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; } } diff --git a/src/p_spec.h b/src/p_spec.h index 10e7c9368..98cb68161 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -634,27 +634,18 @@ typedef enum { p_wind, ///< Wind. p_current, ///< Current. - p_upcurrent, ///< Upwards current. - p_downcurrent, ///< Downwards current. - p_upwind, ///< Upwards wind. - p_downwind ///< Downwards wind. } pushertype_e; // Model for pushers for push/pull effects typedef struct { - thinker_t thinker; ///< Thinker structure for push/pull effect. - /** Types of push/pull effects. - */ - pushertype_e type; ///< Type of push/pull effect. - mobj_t *source; ///< Point source if point pusher/puller. - INT32 x_mag; ///< X strength. - INT32 y_mag; ///< Y strength. - INT32 magnitude; ///< Vector strength for point pusher/puller. - INT32 radius; ///< Effective radius for point pusher/puller. - INT32 x, y, z; ///< Point source if point pusher/puller. + thinker_t thinker; ///< Thinker structure for pusher effect. + pushertype_e type; ///< Type of pusher effect. + fixed_t x_mag; ///< X strength. + fixed_t y_mag; ///< Y strength. + fixed_t z_mag; ///< Z strength. INT32 affectee; ///< Number of affected sector. - UINT8 roverpusher; ///< flag for whether pusher originated from a FOF or not + UINT8 roverpusher; ///< flag for whether pusher originated from a FOF or not INT32 referrer; ///< If roverpusher == true, then this will contain the sector # of the control sector where the effect was applied. INT32 exclusive; /// < Once this affect has been applied to a mobj, no other pushers may affect it. INT32 slider; /// < Should the player go into an uncontrollable slide? From dcba011cf3adcb64972ba690b7d7b741e229a4d6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 1 Jul 2021 20:35:13 +0200 Subject: [PATCH 098/326] Adapt wind/current linedefs to UDMF --- src/p_setup.c | 26 ++++++++++++++++++++++++++ src/p_spec.c | 35 +++++++++++------------------------ src/p_spec.h | 6 ++++++ 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 575998d20..1dd172f1a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3745,6 +3745,32 @@ static void P_ConvertBinaryMap(void) lines[i].args[4] |= TMST_NONEXCLUSIVE; lines[i].special = 510; break; + case 541: //Wind + case 542: //Upwards wind + case 543: //Downwards wind + case 544: //Current + case 545: //Upwards current + case 546: //Downwards current + lines[i].args[0] = tag; + switch ((lines[i].special - 541) % 3) + { + case 0: + lines[i].args[1] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + break; + case 1: + lines[i].args[2] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + break; + case 2: + lines[i].args[2] = -R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + break; + } + lines[i].args[3] = (lines[i].special >= 544) ? p_current : p_wind; + if (lines[i].flags & ML_EFFECT4) + lines[i].args[4] |= TMPF_SLIDE; + if (!(lines[i].flags & ML_NOCLIMB)) + lines[i].args[4] |= TMPF_NONEXCLUSIVE; + lines[i].special = 541; + break; case 606: //Colormap lines[i].args[0] = Tag_FGet(&lines[i].tags); break; diff --git a/src/p_spec.c b/src/p_spec.c index 232e1d0e7..c200bb6dd 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -8883,7 +8883,7 @@ void T_Pusher(pusher_t *p) thing->momx += xspeed; thing->momy += yspeed; - thing->momz += xspeed; + thing->momz += zspeed; if (thing->player) { thing->player->cmomx += xspeed; @@ -8974,14 +8974,17 @@ static void P_SpawnPushers(void) tag = Tag_FGet(&l->tags); switch (l->special) { - case 541: // wind - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_wind, l->dx, l->dy, 0, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - break; - case 544: // current - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_current, l->dx, l->dy, 0, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + case 541: // wind/current + { + fixed_t length = R_PointToDist2(l->v2->x, l->v2->y, l->v1->x, l->v1->y); + fixed_t hspeed = l->args[1] << FRACBITS; + fixed_t dx = FixedMul(FixedDiv(l->dx, length), hspeed); + fixed_t dy = FixedMul(FixedDiv(l->dy, length), hspeed); + + TAG_ITER_SECTORS(l->args[0], s) + Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, s, -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE)); break; + } case 547: // push/pull TAG_ITER_SECTORS(tag, s) { @@ -8990,22 +8993,6 @@ static void P_SpawnPushers(void) Add_PointPusher(P_AproxDistance(l->dx >> FRACBITS, l->dy >> FRACBITS), thing, s, l->flags & ML_NOCLIMB); } break; - case 545: // current up - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_current, 0, 0, P_AproxDistance(l->dx, l->dy), s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - break; - case 546: // current down - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_current, 0, 0, -P_AproxDistance(l->dx, l->dy), s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - break; - case 542: // wind up - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_wind, 0, 0, P_AproxDistance(l->dx, l->dy), s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - break; - case 543: // wind down - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_wind, 0, 0, -P_AproxDistance(l->dx, l->dy), s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - break; } } } diff --git a/src/p_spec.h b/src/p_spec.h index 98cb68161..f08ee2f1f 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -135,6 +135,12 @@ typedef enum TMST_NONEXCLUSIVE = 4, } textmapscrolltype_t; +typedef enum +{ + TMPF_SLIDE = 1, + TMPF_NONEXCLUSIVE = 1<<1, +} textmappusherflags_t; + // GETSECSPECIAL (specialval, section) // // Pulls out the special # from a particular section. From 3542e2205d7a7e939485635975d22e6895419c73 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 1 Jul 2021 20:47:07 +0200 Subject: [PATCH 099/326] Add wind/current linedef to UDB config --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 39 ++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 449691cdc..e4841fd6e 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2822,6 +2822,45 @@ udmf } } } + + 541 + { + title = "Wind/Current"; + prefix = "(541)"; + arg0 + { + title = "Sector tag"; + type = 13; + } + arg1 + { + title = "Horizontal speed"; + } + arg2 + { + title = "Vertical speed"; + } + arg3 + { + title = "Type"; + type = 11; + enum + { + 0 = "Wind"; + 1 = "Current"; + } + } + arg4 + { + title = "Flags"; + type = 12; + flags + { + 1 = "Slide"; + 2 = "Non-exclusive"; + } + } + } } light From 9718674d3ba1a49d8f6a317c5c0acfafb24eff3c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 1 Jul 2021 20:59:46 +0200 Subject: [PATCH 100/326] Check for sector type in T_PointPusher --- src/p_spec.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index c200bb6dd..bf86fc7e2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -8719,6 +8719,13 @@ static inline boolean PIT_PushThing(mobj_t *thing) void T_PointPusher(pointpusher_t *p) { INT32 xl, xh, yl, yh, bx, by; + sector_t *sec = sectors + p->affectee; + + // Be sure the special sector type is still turned on. If so, proceed. + // Else, bail out; the sector type has been changed on us. + + if (GETSECSPECIAL(sec->special, 3) != 2) + return; // Seek out all pushable things within the force radius of this // point pusher. Crosses sectors, so use blockmap. From 64b67bcfe06231bc26275df176848fea1cd5b3e8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 1 Jul 2021 23:15:13 +0200 Subject: [PATCH 101/326] Wind/current linedef: Apply to front sector if tag = 0 --- src/p_spec.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index bf86fc7e2..a9262782f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -8988,8 +8988,13 @@ static void P_SpawnPushers(void) fixed_t dx = FixedMul(FixedDiv(l->dx, length), hspeed); fixed_t dy = FixedMul(FixedDiv(l->dy, length), hspeed); - TAG_ITER_SECTORS(l->args[0], s) - Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, s, -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE)); + if (l->args[0] == 0) + Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, (INT32)(l->frontsector - sectors), -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE)); + else + { + TAG_ITER_SECTORS(l->args[0], s) + Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, s, -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE)); + } break; } case 547: // push/pull From 6dfca597c526222aacaee9d2f7629ef3ea473554 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 1 Jul 2021 23:16:11 +0200 Subject: [PATCH 102/326] UDB config: Merge scroller and pusher sections --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index e4841fd6e..08a31297a 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2731,9 +2731,9 @@ udmf } } - scroll + scrollpush { - title = "Wall and Plane Scrolling"; + title = "Scrollers and Pushers"; 500 { From 805bafd9369a9af83ed2728c919d78a7c024846c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 2 Jul 2021 12:51:39 +0200 Subject: [PATCH 103/326] Adapt "change plane scroller direction" linedef type to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 15 +++++++++++++++ src/p_setup.c | 4 ++++ src/p_spec.c | 11 ++++++++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 08a31297a..25f53ca9b 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2462,6 +2462,21 @@ udmf enum = "floorceiling"; } } + + 435 + { + title = "Change Plane Scroller Direction"; + prefix = "(435)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Speed"; + } + } } linedefexecplane diff --git a/src/p_setup.c b/src/p_setup.c index 1dd172f1a..ca122fa62 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3611,6 +3611,10 @@ static void P_ConvertBinaryMap(void) } lines[i].special = 429; break; + case 435: //Change plane scroller direction + lines[i].args[0] = tag; + lines[i].args[1] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + break; case 443: //Call Lua function if (lines[i].text) { diff --git a/src/p_spec.c b/src/p_spec.c index a9262782f..59353e835 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2945,17 +2945,22 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) scroll_t *scroller; thinker_t *th; + fixed_t length = R_PointToDist2(line->v2->x, line->v2->y, line->v1->x, line->v1->y); + fixed_t speed = line->args[1] << FRACBITS; + fixed_t dx = FixedMul(FixedMul(FixedDiv(line->dx, length), speed) >> SCROLL_SHIFT, CARRYFACTOR); + fixed_t dy = FixedMul(FixedMul(FixedDiv(line->dy, length), speed) >> SCROLL_SHIFT, CARRYFACTOR); + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)T_Scroll) continue; scroller = (scroll_t *)th; - if (!Tag_Find(§ors[scroller->affectee].tags, tag)) + if (!Tag_Find(§ors[scroller->affectee].tags, line->args[0])) continue; - scroller->dx = FixedMul(line->dx>>SCROLL_SHIFT, CARRYFACTOR); - scroller->dy = FixedMul(line->dy>>SCROLL_SHIFT, CARRYFACTOR); + scroller->dx = dx; + scroller->dy = dy; } } break; From 3b1d64703db97046105fd9f220f6942dea93abcf Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 2 Jul 2021 17:18:55 +0200 Subject: [PATCH 104/326] Adapt polyobject door move linedef types to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 51 ++++++++++++++++++++ src/p_setup.c | 8 +++ src/p_spec.c | 22 +++------ 3 files changed, 66 insertions(+), 15 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 25f53ca9b..f97da48cc 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2746,6 +2746,57 @@ udmf } } + linedefexecpoly + { + title = "Linedef Executor (polyobject)"; + + 480 + { + title = "Door Slide"; + prefix = "(480)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Distance"; + } + arg3 + { + title = "Return delay"; + } + } + 481 + { + title = "Door Swing"; + prefix = "(481)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Angle distance"; + type = 8; + } + arg3 + { + title = "Return delay"; + } + } + } + scrollpush { title = "Scrollers and Pushers"; diff --git a/src/p_setup.c b/src/p_setup.c index ca122fa62..947ec8a1e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3663,6 +3663,14 @@ static void P_ConvertBinaryMap(void) case 456: //Stop fading colormap lines[i].args[0] = Tag_FGet(&lines[i].tags); break; + case 480: //Polyobject - door slide + case 481: //Polyobject - door move + lines[i].args[0] = tag; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + if (lines[i].sidenum[1] != 0xffff) + lines[i].args[3] = sides[lines[i].sidenum[1]].textureoffset >> FRACBITS; + break; case 500: //Scroll front wall left case 501: //Scroll front wall right lines[i].args[0] = 0; diff --git a/src/p_spec.c b/src/p_spec.c index 59353e835..e167d454e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -992,30 +992,22 @@ static boolean PolyDoor(line_t *line) { polydoordata_t pdd; - pdd.polyObjNum = Tag_FGet(&line->tags); // polyobject id + pdd.polyObjNum = line->args[0]; // polyobject id switch(line->special) { case 480: // Polyobj_DoorSlide pdd.doorType = POLY_DOOR_SLIDE; - pdd.speed = sides[line->sidenum[0]].textureoffset / 8; + pdd.speed = line->args[1] << (FRACBITS - 3); pdd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); // angle of motion - pdd.distance = sides[line->sidenum[0]].rowoffset; - - if (line->sidenum[1] != 0xffff) - pdd.delay = sides[line->sidenum[1]].textureoffset >> FRACBITS; // delay in tics - else - pdd.delay = 0; + pdd.distance = line->args[2] << FRACBITS; + pdd.delay = line->args[3]; // delay in tics break; case 481: // Polyobj_DoorSwing pdd.doorType = POLY_DOOR_SWING; - pdd.speed = sides[line->sidenum[0]].textureoffset >> FRACBITS; // angular speed - pdd.distance = sides[line->sidenum[0]].rowoffset >> FRACBITS; // angular distance - - if (line->sidenum[1] != 0xffff) - pdd.delay = sides[line->sidenum[1]].textureoffset >> FRACBITS; // delay in tics - else - pdd.delay = 0; + pdd.speed = line->args[1]; // angular speed + pdd.distance = line->args[2]; // angular distance + pdd.delay = line->args[3]; // delay in tics break; default: return 0; // ??? From 6e9afabd443197aaae2987c2a77a2d61780795b5 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 4 Jul 2021 12:54:48 +0200 Subject: [PATCH 105/326] Adapt polyobject move and rotate linedef types to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 60 +++++++++++++++++++- src/lua_polyobjlib.c | 7 ++- src/p_polyobj.c | 30 +++++----- src/p_polyobj.h | 21 +++++-- src/p_setup.c | 29 ++++++++++ src/p_spec.c | 41 +++++-------- 6 files changed, 139 insertions(+), 49 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index f97da48cc..b04b5e16a 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2772,6 +2772,7 @@ udmf title = "Return delay"; } } + 481 { title = "Door Swing"; @@ -2787,7 +2788,7 @@ udmf } arg2 { - title = "Angle distance"; + title = "Rotation"; type = 8; } arg3 @@ -2795,6 +2796,63 @@ udmf title = "Return delay"; } } + + 482 + { + title = "Move"; + prefix = "(482)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Distance"; + } + arg3 + { + title = "Override?"; + type = 11; + enum = "noyes"; + } + } + + 484 + { + title = "Rotate"; + prefix = "(484)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Rotation"; + type = 8; + } + arg3 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Don't turn others"; + 2 = "Turn players"; + 4 = "Continuous rotation"; + 8 = "Override"; + } + } + } } scrollpush diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index 5d76a912d..87dfad7f6 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -244,13 +244,14 @@ static int lib_polyobj_rotate(lua_State *L) { polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); angle_t delta = luaL_checkangle(L, 2); - UINT8 turnthings = (UINT8)luaL_optinteger(L, 3, 0); // don't turn anything by default? (could change this if not desired) - boolean checkmobjs = lua_opttrueboolean(L, 4); + boolean turnplayers = lua_opttrueboolean(L, 3); + boolean turnothers = lua_opttrueboolean(L, 4); + boolean checkmobjs = lua_opttrueboolean(L, 5); NOHUD INLEVEL if (!po) return LUA_ErrInvalid(L, "polyobj_t"); - lua_pushboolean(L, Polyobj_rotate(po, delta, turnthings, checkmobjs)); + lua_pushboolean(L, Polyobj_rotate(po, delta, turnplayers, turnothers, checkmobjs)); return 1; } diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 6431e4624..47327c949 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1089,7 +1089,7 @@ static void Polyobj_rotateLine(line_t *ld) } // Causes objects resting on top of the rotating polyobject to 'ride' with its movement. -static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, UINT8 turnthings) +static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, boolean turnplayers, boolean turnothers) { static INT32 pomovecount = 10000; INT32 x, y; @@ -1151,7 +1151,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, Polyobj_slideThing(mo, newxoff, newyoff); - if (turnthings == 2 || (turnthings == 1 && !mo->player)) { + if ((turnplayers && mo->player) || (turnothers && !mo->player)) { mo->angle += delta; if (mo->player) P_SetPlayerAngle(mo->player, (angle_t)(mo->player->angleturn << 16) + delta); @@ -1163,7 +1163,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, } // Rotates a polyobject around its start point. -boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs) +boolean Polyobj_rotate(polyobj_t *po, angle_t delta, boolean turnplayers, boolean turnothers, boolean checkmobjs) { size_t i; angle_t angle; @@ -1201,7 +1201,7 @@ boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean c for (i = 0; i < po->numLines; ++i) hitflags |= Polyobj_clipThings(po, po->lines[i]); - Polyobj_rotateThings(po, origin, delta, turnthings); + Polyobj_rotateThings(po, origin, delta, turnplayers, turnothers); } if (hitflags & 2) @@ -1409,7 +1409,7 @@ void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y) fixed_t dx, dy; // first, rotate to the saved angle - Polyobj_rotate(po, angle, false, false); + Polyobj_rotate(po, angle, false, false, false); // determine component distances to translate dx = x - po->spawnSpot.x; @@ -1452,7 +1452,7 @@ void T_PolyObjRotate(polyrotate_t *th) // rotate by 'speed' angle per frame // if distance == -1, this polyobject rotates perpetually - if (Polyobj_rotate(po, th->speed, th->turnobjs, true) && th->distance != -1) + if (Polyobj_rotate(po, th->speed, th->turnobjs & PTF_PLAYERS, th->turnobjs & PTF_OTHERS, true) && th->distance != -1) { INT32 avel = abs(th->speed); @@ -1854,7 +1854,7 @@ void T_PolyDoorSwing(polyswingdoor_t *th) // rotate by 'speed' angle per frame // if distance == -1, this polyobject rotates perpetually - if (Polyobj_rotate(po, th->speed, false, true) && th->distance != -1) + if (Polyobj_rotate(po, th->speed, false, false, true) && th->distance != -1) { INT32 avel = abs(th->speed); @@ -1985,7 +1985,7 @@ void T_PolyObjRotDisplace(polyrotdisplace_t *th) rotangle = FixedMul(th->rotscale, delta); - if (Polyobj_rotate(po, FixedAngle(rotangle), th->turnobjs, true)) + if (Polyobj_rotate(po, FixedAngle(rotangle), th->turnobjs & PTF_PLAYERS, th->turnobjs & PTF_OTHERS, true)) th->oldHeights = newheights; } @@ -2014,7 +2014,7 @@ boolean EV_DoPolyObjRotate(polyrotdata_t *prdata) return false; // check for override if this polyobj already has a thinker - if (po->thinker && !prdata->overRide) + if (po->thinker && !(prdata->flags & TMPR_OVERRIDE)) return false; // create a new thinker @@ -2029,10 +2029,10 @@ boolean EV_DoPolyObjRotate(polyrotdata_t *prdata) // use Hexen-style byte angles for speed and distance th->speed = Polyobj_AngSpeed(prdata->speed * prdata->direction); - if (prdata->distance == 360) // 360 means perpetual + if (prdata->flags & TMPR_CONTINUOUS) th->distance = -1; - else if (prdata->distance == 0) // 0 means 360 degrees - th->distance = 0xffffffff - 1; + else if (prdata->distance == 360) + th->distance = ANGLE_MAX - 1; else th->distance = FixedAngle(prdata->distance*FRACUNIT); @@ -2047,7 +2047,11 @@ boolean EV_DoPolyObjRotate(polyrotdata_t *prdata) oldpo = po; - th->turnobjs = prdata->turnobjs; + th->turnobjs = 0; + if (!(prdata->flags & TMPR_DONTROTATEOTHERS)) + th->turnobjs |= PTF_OTHERS; + if (prdata->flags & TMPR_ROTATEPLAYERS) + th->turnobjs |= PTF_PLAYERS; // apply action to mirroring polyobjects as well start = 0; diff --git a/src/p_polyobj.h b/src/p_polyobj.h index 7c814e0bf..9c8094028 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -137,7 +137,7 @@ typedef struct polyrotate_s INT32 polyObjNum; // numeric id of polyobject (avoid C pointers here) INT32 speed; // speed of movement per frame INT32 distance; // distance to move - UINT8 turnobjs; // turn objects? 0=no, 1=everything but players, 2=everything + UINT8 turnobjs; // turn objects? PTF_ flags } polyrotate_t; typedef struct polymove_s @@ -247,14 +247,27 @@ typedef struct polyfade_s // Line Activation Data Structures // +typedef enum +{ + TMPR_DONTROTATEOTHERS = 1, + TMPR_ROTATEPLAYERS = 1<<1, + TMPR_CONTINUOUS = 1<<2, + TMPR_OVERRIDE = 1<<3, +} textmappolyrotate_t; + +typedef enum +{ + PTF_PLAYERS = 1, // Turn players with movement + PTF_OTHERS = 1<<1, // Turn other mobjs with movement +} polyturnflags_e; + typedef struct polyrotdata_s { INT32 polyObjNum; // numeric id of polyobject to affect INT32 direction; // direction of rotation INT32 speed; // angular speed INT32 distance; // distance to move - UINT8 turnobjs; // rotate objects being carried? - UINT8 overRide; // if true, will override any action on the object + UINT8 flags; // TMPR_ flags } polyrotdata_t; typedef struct polymovedata_s @@ -337,7 +350,7 @@ typedef struct polyfadedata_s // boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs); -boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs); +boolean Polyobj_rotate(polyobj_t *po, angle_t delta, boolean turnplayers, boolean turnothers, boolean checkmobjs); polyobj_t *Polyobj_GetForNum(INT32 id); void Polyobj_InitLevel(void); void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y); diff --git a/src/p_setup.c b/src/p_setup.c index 947ec8a1e..7617e863f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3671,6 +3671,35 @@ static void P_ConvertBinaryMap(void) if (lines[i].sidenum[1] != 0xffff) lines[i].args[3] = sides[lines[i].sidenum[1]].textureoffset >> FRACBITS; break; + case 482: //Polyobject - move + case 483: //Polyobject - move, override + lines[i].args[0] = tag; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[3] = lines[i].special == 483; + lines[i].special = 482; + break; + case 484: //Polyobject - rotate right + case 485: //Polyobject - rotate right, override + case 486: //Polyobject - rotate left + case 487: //Polyobject - rotate left, override + lines[i].args[0] = tag; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + if (lines[i].args[2] == 360) + lines[i].args[3] |= TMPR_CONTINUOUS; + else if (lines[i].args[2] == 0) + lines[i].args[2] = 360; + if (lines[i].special < 486) + lines[i].args[2] *= -1; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[3] |= TMPR_DONTROTATEOTHERS; + else if (lines[i].flags & ML_EFFECT4) + lines[i].args[3] |= TMPR_ROTATEPLAYERS; + if (lines[i].special % 2 == 1) + lines[i].args[3] |= TMPR_OVERRIDE; + lines[i].special = 484; + break; case 500: //Scroll front wall left case 501: //Scroll front wall right lines[i].args[0] = 0; diff --git a/src/p_spec.c b/src/p_spec.c index e167d454e..6434a55d7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1016,17 +1016,17 @@ static boolean PolyDoor(line_t *line) return EV_DoPolyDoor(&pdd); } -// Parses arguments for parameterized polyobject move specials +// Parses arguments for parameterized polyobject move special static boolean PolyMove(line_t *line) { polymovedata_t pmd; - pmd.polyObjNum = Tag_FGet(&line->tags); - pmd.speed = sides[line->sidenum[0]].textureoffset / 8; + pmd.polyObjNum = line->args[0]; + pmd.speed = line->args[1] << (FRACBITS - 3); pmd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); - pmd.distance = sides[line->sidenum[0]].rowoffset; + pmd.distance = line->args[2] << FRACBITS; - pmd.overRide = (line->special == 483); // Polyobj_OR_Move + pmd.overRide = !!line->args[3]; // Polyobj_OR_Move return EV_DoPolyObjMove(&pmd); } @@ -1200,27 +1200,16 @@ static boolean PolyWaypoint(line_t *line) return EV_DoPolyObjWaypoint(&pwd); } -// Parses arguments for parameterized polyobject rotate specials +// Parses arguments for parameterized polyobject rotate special static boolean PolyRotate(line_t *line) { polyrotdata_t prd; - prd.polyObjNum = Tag_FGet(&line->tags); - prd.speed = sides[line->sidenum[0]].textureoffset >> FRACBITS; // angular speed - prd.distance = sides[line->sidenum[0]].rowoffset >> FRACBITS; // angular distance - - // Polyobj_(OR_)RotateRight have dir == -1 - prd.direction = (line->special == 484 || line->special == 485) ? -1 : 1; - - // Polyobj_OR types have override set to true - prd.overRide = (line->special == 485 || line->special == 487); - - if (line->flags & ML_NOCLIMB) - prd.turnobjs = 0; - else if (line->flags & ML_EFFECT4) - prd.turnobjs = 2; - else - prd.turnobjs = 1; + prd.polyObjNum = line->args[0]; + prd.speed = line->args[1]; // angular speed + prd.distance = abs(line->args[2]); // angular distance + prd.direction = (line->args[2] < 0) ? -1 : 1; + prd.flags = line->args[3]; return EV_DoPolyObjRotate(&prd); } @@ -1272,9 +1261,9 @@ static boolean PolyRotDisplace(line_t *line) if (line->flags & ML_NOCLIMB) pdd.turnobjs = 0; else if (line->flags & ML_EFFECT4) - pdd.turnobjs = 2; + pdd.turnobjs = PTF_PLAYERS|PTF_OTHERS; else - pdd.turnobjs = 1; + pdd.turnobjs = PTF_OTHERS; return EV_DoPolyObjRotDisplace(&pdd); } @@ -3906,13 +3895,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) PolyDoor(line); break; case 482: // Polyobj_Move - case 483: // Polyobj_OR_Move PolyMove(line); break; case 484: // Polyobj_RotateRight - case 485: // Polyobj_OR_RotateRight - case 486: // Polyobj_RotateLeft - case 487: // Polyobj_OR_RotateLeft PolyRotate(line); break; case 488: // Polyobj_Waypoint From 2cbda0e5ac4d84926499a18f1bc36f19a9c0083e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 4 Jul 2021 13:20:10 +0200 Subject: [PATCH 106/326] Adapt polyobject waypoint movement linedef to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 40 ++++++++++++++++++++ src/p_setup.c | 15 ++++++++ src/p_spec.c | 23 +++-------- 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index b04b5e16a..5d9f32743 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2853,6 +2853,46 @@ udmf } } } + + 488 + { + title = "Move by Waypoints"; + prefix = "(488)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Waypoint sequence"; + } + arg3 + { + title = "Return behavior"; + type = 11; + enum + { + 0 = "Don't return"; + 1 = "Return to first waypoint"; + 2 = "Repeat sequence in reverse"; + } + } + arg4 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move in reverse"; + 2 = "Loop movement"; + } + } + } } scrollpush diff --git a/src/p_setup.c b/src/p_setup.c index 7617e863f..6eef43a60 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3700,6 +3700,21 @@ static void P_ConvertBinaryMap(void) lines[i].args[3] |= TMPR_OVERRIDE; lines[i].special = 484; break; + case 488: //Polyobject - move by waypoints + lines[i].args[0] = tag; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + if (lines[i].flags & ML_EFFECT3) + lines[i].args[3] = PWR_WRAP; + else if (lines[i].flags & ML_EFFECT2) + lines[i].args[3] = PWR_COMEBACK; + else + lines[i].args[3] = PWR_STOP; + if (lines[i].flags & ML_EFFECT1) + lines[i].args[4] |= PWF_REVERSE; + if (lines[i].flags & ML_EFFECT4) + lines[i].args[4] |= PWF_LOOP; + break; case 500: //Scroll front wall left case 501: //Scroll front wall right lines[i].args[0] = 0; diff --git a/src/p_spec.c b/src/p_spec.c index 6434a55d7..306a11e4f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1178,24 +1178,11 @@ static boolean PolyWaypoint(line_t *line) { polywaypointdata_t pwd; - pwd.polyObjNum = Tag_FGet(&line->tags); - pwd.speed = sides[line->sidenum[0]].textureoffset / 8; - pwd.sequence = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Sequence # - - // Behavior after reaching the last waypoint? - if (line->flags & ML_EFFECT3) - pwd.returnbehavior = PWR_WRAP; // Wrap back to first waypoint - else if (line->flags & ML_EFFECT2) - pwd.returnbehavior = PWR_COMEBACK; // Go through sequence in reverse - else - pwd.returnbehavior = PWR_STOP; // Stop - - // Flags - pwd.flags = 0; - if (line->flags & ML_EFFECT1) - pwd.flags |= PWF_REVERSE; - if (line->flags & ML_EFFECT4) - pwd.flags |= PWF_LOOP; + pwd.polyObjNum = line->args[0]; + pwd.speed = line->args[1] << (FRACBITS - 3); + pwd.sequence = line->args[2]; + pwd.returnbehavior = line->args[3]; + pwd.flags = line->args[4]; return EV_DoPolyObjWaypoint(&pwd); } From 5c2ce62f00617767e43d43be9c4df3f08067d130 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 4 Jul 2021 13:45:41 +0200 Subject: [PATCH 107/326] Adapt polyobject visibility/tangibility linedefs to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 33 +++++++++++++ src/p_polyobj.h | 14 ++++++ src/p_setup.c | 8 +++ src/p_spec.c | 52 ++++++-------------- 4 files changed, 71 insertions(+), 36 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 5d9f32743..039507404 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2893,6 +2893,39 @@ udmf } } } + + 489 + { + title = "Set Visibility, Tangibility"; + prefix = "(489)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Visibility"; + type = 11; + enum + { + 0 = "No change"; + 1 = "Visible"; + 2 = "Invisible"; + } + } + arg2 + { + title = "Tangibility"; + type = 11; + enum + { + 0 = "No change"; + 1 = "Tangible"; + 2 = "Intangible"; + } + } + } } scrollpush diff --git a/src/p_polyobj.h b/src/p_polyobj.h index 9c8094028..b37ffa6ef 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -294,6 +294,20 @@ typedef struct polywaypointdata_s UINT8 flags; // PWF_ flags } polywaypointdata_t; +typedef enum +{ + TMPV_NOCHANGE = 1, + TMPV_VISIBLE = 1<<1, + TMPV_INVISIBLE = 1<<2, +} textmappolyvisibility_t; + +typedef enum +{ + TMPT_NOCHANGE = 1, + TMPT_TANGIBLE = 1<<1, + TMPT_INTANGIBLE = 1<<2, +} textmappolytangibility_t; + // polyobject door types typedef enum { diff --git a/src/p_setup.c b/src/p_setup.c index 6eef43a60..a6c650fc5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3715,6 +3715,14 @@ static void P_ConvertBinaryMap(void) if (lines[i].flags & ML_EFFECT4) lines[i].args[4] |= PWF_LOOP; break; + case 489: //Polyobject - turn invisible, intangible + case 490: //Polyobject - turn visible, tangible + lines[i].args[0] = tag; + lines[i].args[1] = 491 - lines[i].special; + if (!(lines[i].flags & ML_NOCLIMB)) + lines[i].args[2] = lines[i].args[1]; + lines[i].special = 489; + break; case 500: //Scroll front wall left case 501: //Scroll front wall right lines[i].args[0] = 0; diff --git a/src/p_spec.c b/src/p_spec.c index 306a11e4f..b5f67fedb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1031,16 +1031,14 @@ static boolean PolyMove(line_t *line) return EV_DoPolyObjMove(&pmd); } -// Makes a polyobject invisible and intangible -// If NOCLIMB is ticked, the polyobject will still be tangible, just not visible. -static void PolyInvisible(line_t *line) +static void PolySetVisibilityTangibility(line_t *line) { - INT32 polyObjNum = Tag_FGet(&line->tags); - polyobj_t *po; + INT32 polyObjNum = line->args[0]; + polyobj_t* po; if (!(po = Polyobj_GetForNum(polyObjNum))) { - CONS_Debug(DBG_POLYOBJ, "PolyInvisible: bad polyobj %d\n", polyObjNum); + CONS_Debug(DBG_POLYOBJ, "PolySetVisibilityTangibility: bad polyobj %d\n", polyObjNum); return; } @@ -1048,38 +1046,23 @@ static void PolyInvisible(line_t *line) if (po->isBad) return; - if (!(line->flags & ML_NOCLIMB)) - po->flags &= ~POF_SOLID; - - po->flags |= POF_NOSPECIALS; - po->flags &= ~POF_RENDERALL; -} - -// Makes a polyobject visible and tangible -// If NOCLIMB is ticked, the polyobject will not be tangible, just visible. -static void PolyVisible(line_t *line) -{ - INT32 polyObjNum = Tag_FGet(&line->tags); - polyobj_t *po; - - if (!(po = Polyobj_GetForNum(polyObjNum))) + if (line->args[1] == TMPV_VISIBLE) { - CONS_Debug(DBG_POLYOBJ, "PolyVisible: bad polyobj %d\n", polyObjNum); - return; + po->flags &= ~POF_NOSPECIALS; + po->flags |= (po->spawnflags & POF_RENDERALL); + } + else if (line->args[1] == TMPV_INVISIBLE) + { + po->flags |= POF_NOSPECIALS; + po->flags &= ~POF_RENDERALL; } - // don't allow line actions to affect bad polyobjects - if (po->isBad) - return; - - if (!(line->flags & ML_NOCLIMB)) + if (line->args[2] == TMPT_TANGIBLE) po->flags |= POF_SOLID; - - po->flags &= ~POF_NOSPECIALS; - po->flags |= (po->spawnflags & POF_RENDERALL); + else if (line->args[2] == TMPT_INTANGIBLE) + po->flags &= ~POF_SOLID; } - // Sets the translucency of a polyobject // Frontsector floor / 100 = translevel static void PolyTranslucency(line_t *line) @@ -3891,10 +3874,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) PolyWaypoint(line); break; case 489: - PolyInvisible(line); - break; - case 490: - PolyVisible(line); + PolySetVisibilityTangibility(line); break; case 491: PolyTranslucency(line); From 429c6588af520ea7a1164814972c0e17247d83b2 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 4 Jul 2021 14:10:11 +0200 Subject: [PATCH 108/326] Adapt polyobject waving flag linedef to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 19 +++++++++++++++++++ src/p_setup.c | 5 +++++ src/p_spec.c | 6 +++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 039507404..ff25fee2c 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1569,6 +1569,25 @@ udmf type = 15; } } + + 30 + { + title = "Waving Flag"; + prefix = "(30)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Distance"; + } + } } planemove diff --git a/src/p_setup.c b/src/p_setup.c index a6c650fc5..2b2efd0f8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3081,6 +3081,11 @@ static void P_ConvertBinaryMap(void) break; } + case 30: //Polyobject - waving flag + lines[i].args[0] = tag; + lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + break; case 50: //Instantly lower floor on level load case 51: //Instantly raise ceiling on level load lines[i].args[0] = tag; diff --git a/src/p_spec.c b/src/p_spec.c index b5f67fedb..b98b244b3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1189,10 +1189,10 @@ static boolean PolyFlag(line_t *line) { polyflagdata_t pfd; - pfd.polyObjNum = Tag_FGet(&line->tags); - pfd.speed = P_AproxDistance(line->dx, line->dy) >> FRACBITS; + pfd.polyObjNum = line->args[0]; + pfd.speed = line->args[1]; pfd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y) >> ANGLETOFINESHIFT; - pfd.momx = sides[line->sidenum[0]].textureoffset >> FRACBITS; + pfd.momx = line->args[2]; return EV_DoPolyObjFlag(&pfd); } From d2ad12c0343098ecc9bfcc16ab2e2ef18a9b5b70 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 4 Jul 2021 14:41:37 +0200 Subject: [PATCH 109/326] Adapt polyobject displacement linedefs to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 46 ++++++++++++++++++++ src/p_setup.c | 13 ++++++ src/p_spec.c | 22 ++++------ 3 files changed, 68 insertions(+), 13 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index ff25fee2c..63e363549 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1588,6 +1588,52 @@ udmf title = "Distance"; } } + + 31 + { + title = "Displacement by Front Sector"; + prefix = "(31)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Base speed"; + } + } + + 32 + { + title = "Angular Displacement by Front Sector"; + prefix = "(32)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Plane factor"; + default = 128; + } + arg2 + { + title = "Rotation factor"; + default = 90; + } + arg3 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Don't turn others"; + 2 = "Turn players"; + } + } + } } planemove diff --git a/src/p_setup.c b/src/p_setup.c index 2b2efd0f8..59d8ada8b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3086,6 +3086,19 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; lines[i].args[2] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; break; + case 31: //Polyobject - displacement by front sector + lines[i].args[0] = tag; + lines[i].args[1] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + break; + case 32: //Polyobject - angular displacement by front sector + lines[i].args[0] = tag; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset ? sides[lines[i].sidenum[0]].textureoffset >> FRACBITS : 128; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset ? sides[lines[i].sidenum[0]].rowoffset >> FRACBITS : 90; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[3] |= TMPR_DONTROTATEOTHERS; + else if (lines[i].flags & ML_EFFECT4) + lines[i].args[3] |= TMPR_ROTATEPLAYERS; + break; case 50: //Instantly lower floor on level load case 51: //Instantly raise ceiling on level load lines[i].args[0] = tag; diff --git a/src/p_spec.c b/src/p_spec.c index b98b244b3..721fe9d74 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1201,12 +1201,14 @@ static boolean PolyFlag(line_t *line) static boolean PolyDisplace(line_t *line) { polydisplacedata_t pdd; + fixed_t length = R_PointToDist2(line->v2->x, line->v2->y, line->v1->x, line->v1->y); + fixed_t speed = line->args[1] << FRACBITS; - pdd.polyObjNum = Tag_FGet(&line->tags); + pdd.polyObjNum = line->args[0]; pdd.controlSector = line->frontsector; - pdd.dx = line->dx>>8; - pdd.dy = line->dy>>8; + pdd.dx = FixedMul(FixedDiv(line->dx, length), speed) >> 8; + pdd.dy = FixedMul(FixedDiv(line->dy, length), speed) >> 8; return EV_DoPolyObjDisplace(&pdd); } @@ -1218,22 +1220,16 @@ static boolean PolyRotDisplace(line_t *line) polyrotdisplacedata_t pdd; fixed_t anginter, distinter; - pdd.polyObjNum = Tag_FGet(&line->tags); + pdd.polyObjNum = line->args[0]; pdd.controlSector = line->frontsector; // Rotate 'anginter' interval for each 'distinter' interval from the control sector. - // Use default values if not provided as fallback. - anginter = sides[line->sidenum[0]].rowoffset ? sides[line->sidenum[0]].rowoffset : 90*FRACUNIT; - distinter = sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : 128*FRACUNIT; + anginter = line->args[2] << FRACBITS; + distinter = line->args[1] << FRACBITS; pdd.rotscale = FixedDiv(anginter, distinter); // Same behavior as other rotators when carrying things. - if (line->flags & ML_NOCLIMB) - pdd.turnobjs = 0; - else if (line->flags & ML_EFFECT4) - pdd.turnobjs = PTF_PLAYERS|PTF_OTHERS; - else - pdd.turnobjs = PTF_OTHERS; + pdd.turnobjs = line->args[3]; return EV_DoPolyObjRotDisplace(&pdd); } From 6d007f388a6416af21c42fc8720f9b8ec380438e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 4 Jul 2021 15:37:42 +0200 Subject: [PATCH 110/326] Adapt set translucency linedef to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 21 + extras/conf/udb/Includes/SRB222_misc.cfg | 6 + src/p_setup.c | 9 + src/p_spec.c | 19 +- src/p_spec.c.orig | 9150 ++++++++++++++++++ 5 files changed, 9191 insertions(+), 14 deletions(-) create mode 100644 src/p_spec.c.orig diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 63e363549..f73d36044 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2991,6 +2991,27 @@ udmf } } } + + 491 + { + title = "Set Translucency"; + prefix = "(491)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Translucency level"; + } + arg2 + { + title = "Set/Add?"; + type = 11; + enum = "setadd"; + } + } } scrollpush diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 8a4bc29e2..8e8b1d71a 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -406,6 +406,12 @@ enums 1 = "Yes"; } + setadd + { + 0 = "Set"; + 1 = "Add"; + } + onoff { 0 = "On"; diff --git a/src/p_setup.c b/src/p_setup.c index 59d8ada8b..4bcb5c8e1 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3741,6 +3741,15 @@ static void P_ConvertBinaryMap(void) lines[i].args[2] = lines[i].args[1]; lines[i].special = 489; break; + case 491: //Polyobject - set translucency + lines[i].args[0] = tag; + // If Front X Offset is specified, use that. Else, use floorheight. + lines[i].args[1] = (sides[lines[i].sidenum[0]].textureoffset ? sides[lines[i].sidenum[0]].textureoffset : lines[i].frontsector->floorheight) >> FRACBITS; + // If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000. + if (!(lines[i].flags & ML_DONTPEGBOTTOM)) + lines[i].args[1] /= 100; + lines[i].args[2] = !!(lines[i].flags & ML_EFFECT3); + break; case 500: //Scroll front wall left case 501: //Scroll front wall right lines[i].args[0] = 0; diff --git a/src/p_spec.c b/src/p_spec.c index 721fe9d74..9862ffa2f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1064,16 +1064,14 @@ static void PolySetVisibilityTangibility(line_t *line) } // Sets the translucency of a polyobject -// Frontsector floor / 100 = translevel static void PolyTranslucency(line_t *line) { - INT32 polyObjNum = Tag_FGet(&line->tags); + INT32 polyObjNum = line->args[0]; polyobj_t *po; - INT32 value; if (!(po = Polyobj_GetForNum(polyObjNum))) { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: bad polyobj %d\n", polyObjNum); + CONS_Debug(DBG_POLYOBJ, "PolyTranslucency: bad polyobj %d\n", polyObjNum); return; } @@ -1081,17 +1079,10 @@ static void PolyTranslucency(line_t *line) if (po->isBad) return; - // If Front X Offset is specified, use that. Else, use floorheight. - value = (sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : line->frontsector->floorheight) >> FRACBITS; - - // If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000. - if (!(line->flags & ML_DONTPEGBOTTOM)) - value /= 100; - - if (line->flags & ML_EFFECT3) // relative calc - po->translucency += value; + if (lines->args[2]) // relative calc + po->translucency += line->args[1]; else - po->translucency = value; + po->translucency = line->args[1]; po->translucency = max(min(po->translucency, NUMTRANSMAPS), 0); } diff --git a/src/p_spec.c.orig b/src/p_spec.c.orig new file mode 100644 index 000000000..244f7166b --- /dev/null +++ b/src/p_spec.c.orig @@ -0,0 +1,9150 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2021 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file p_spec.c +/// \brief Implements special effects: +/// Texture animation, height or lighting changes +/// according to adjacent sectors, respective +/// utility functions, etc. +/// Line Tag handling. Line and Sector triggers. + +#include "dehacked.h" +#include "doomdef.h" +#include "g_game.h" +#include "p_local.h" +#include "p_setup.h" // levelflats for flat animation +#include "r_data.h" +#include "r_textures.h" +#include "m_random.h" +#include "p_mobj.h" +#include "i_system.h" +#include "s_sound.h" +#include "w_wad.h" +#include "z_zone.h" +#include "r_main.h" //Two extra includes. +#include "r_sky.h" +#include "p_polyobj.h" +#include "p_slopes.h" +#include "hu_stuff.h" +#include "v_video.h" // V_AUTOFADEOUT|V_ALLOWLOWERCASE +#include "m_misc.h" +#include "m_cond.h" //unlock triggers +#include "lua_hook.h" // LUA_HookLinedefExecute +#include "f_finale.h" // control text prompt +#include "r_skins.h" // skins + +#ifdef HW3SOUND +#include "hardware/hw3sound.h" +#endif + +// Not sure if this is necessary, but it was in w_wad.c, so I'm putting it here too -Shadow Hog +#include + +mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpoint +mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs +mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs + +// Amount (dx, dy) vector linedef is shifted right to get scroll amount +#define SCROLL_SHIFT 5 + +/** Animated texture descriptor + * This keeps track of an animated texture or an animated flat. + * \sa P_UpdateSpecials, P_InitPicAnims, animdef_t + */ +typedef struct +{ + SINT8 istexture; ///< ::true for a texture, ::false for a flat + INT32 picnum; ///< The end flat number + INT32 basepic; ///< The start flat number + INT32 numpics; ///< Number of frames in the animation + tic_t speed; ///< Number of tics for which each frame is shown +} anim_t; + +#if defined(_MSC_VER) +#pragma pack(1) +#endif + +/** Animated texture definition. + * Used for loading an ANIMDEFS lump from a wad. + * + * Animations are defined by the first and last frame (i.e., flat or texture). + * The animation sequence uses all flats between the start and end entry, in + * the order found in the wad. + * + * \sa anim_t + */ +typedef struct +{ + SINT8 istexture; ///< True for a texture, false for a flat. + char endname[9]; ///< Name of the last frame, null-terminated. + char startname[9]; ///< Name of the first frame, null-terminated. + INT32 speed ; ///< Number of tics for which each frame is shown. +} ATTRPACK animdef_t; + +#if defined(_MSC_VER) +#pragma pack() +#endif + +typedef struct +{ + UINT32 count; + thinker_t **thinkers; +} thinkerlist_t; + +static void P_SpawnScrollers(void); +static void P_SpawnFriction(void); +static void P_SpawnPushers(void); +static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 +static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); +static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); +#define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL, false); +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha); +static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, + INT16 destvalue, INT16 speed, boolean ticbased, boolean relative, + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha); +static void P_ResetColormapFader(sector_t *sector); +static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, + boolean ticbased, INT32 duration); +static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); +static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline); +//static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); +static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorflags, thinkerlist_t *secthinkers); +static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec); +static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer); +static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee, UINT8 reverse); + + +//SoM: 3/7/2000: New sturcture without limits. +static anim_t *lastanim; +static anim_t *anims = NULL; /// \todo free leak +static size_t maxanims; + +// Animating line specials + +// Init animated textures +// - now called at level loading P_SetupLevel() + +static animdef_t *animdefs = NULL; + +// Increase the size of animdefs to make room for a new animation definition +static void GrowAnimDefs(void) +{ + maxanims++; + animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); +} + +// A prototype; here instead of p_spec.h, so they're "private" +void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum); +void P_ParseAnimationDefintion(SINT8 istexture); + +/** Sets up texture and flat animations. + * + * Converts an ::animdef_t array loaded from a lump into + * ::anim_t format. + * + * Issues an error if any animation cycles are invalid. + * + * \sa P_FindAnimatedFlat, P_SetupLevelFlatAnims + * \author Steven McGranahan (original), Shadow Hog (had to rewrite it to handle multiple WADs), JTE (had to rewrite it to handle multiple WADs _correctly_) + */ +void P_InitPicAnims(void) +{ + // Init animation + INT32 w; // WAD + size_t i; + + I_Assert(animdefs == NULL); + + maxanims = 0; + + for (w = numwadfiles-1; w >= 0; w--) + { + UINT16 animdefsLumpNum; + + // Find ANIMDEFS lump in the WAD + animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0); + + while (animdefsLumpNum != INT16_MAX) + { + P_ParseANIMDEFSLump(w, animdefsLumpNum); + animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", (UINT16)w, animdefsLumpNum + 1); + } + } + + // Define the last one + animdefs[maxanims].istexture = -1; + strncpy(animdefs[maxanims].endname, "", 9); + strncpy(animdefs[maxanims].startname, "", 9); + animdefs[maxanims].speed = 0; + + if (anims) + free(anims); + + anims = (anim_t *)malloc(sizeof (*anims)*(maxanims + 1)); + if (!anims) + I_Error("Not enough free memory for ANIMDEFS data"); + + lastanim = anims; + for (i = 0; animdefs[i].istexture != -1; i++) + { + if (animdefs[i].istexture) + { + if (R_CheckTextureNumForName(animdefs[i].startname) == -1) + continue; + + lastanim->picnum = R_TextureNumForName(animdefs[i].endname); + lastanim->basepic = R_TextureNumForName(animdefs[i].startname); + } + else + { + if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR) + continue; + + lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname); + lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname); + } + + lastanim->istexture = animdefs[i].istexture; + lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; + + if (lastanim->numpics < 2) + { + free(anims); + I_Error("P_InitPicAnims: bad cycle from %s to %s", + animdefs[i].startname, animdefs[i].endname); + } + + lastanim->speed = LONG(animdefs[i].speed); + lastanim++; + } + lastanim->istexture = -1; + R_ClearTextureNumCache(false); + + // Clear animdefs now that we're done with it. + // We'll only be using anims from now on. + Z_Free(animdefs); + animdefs = NULL; +} + +void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum) +{ + char *animdefsLump; + size_t animdefsLumpLength; + char *animdefsText; + char *animdefsToken; + char *p; + + // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll + // need to make a space of memory where I can ensure that it will terminate + // correctly. Start by loading the relevant data from the WAD. + animdefsLump = (char *)W_CacheLumpNumPwad(wadNum,lumpnum,PU_STATIC); + // If that didn't exist, we have nothing to do here. + if (animdefsLump == NULL) return; + // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. + animdefsLumpLength = W_LumpLengthPwad(wadNum,lumpnum); + animdefsText = (char *)Z_Malloc((animdefsLumpLength+1)*sizeof(char),PU_STATIC,NULL); + // Now move the contents of the lump into this new location. + memmove(animdefsText,animdefsLump,animdefsLumpLength); + // Make damn well sure the last character in our new memory location is \0. + animdefsText[animdefsLumpLength] = '\0'; + // Finally, free up the memory from the first data load, because we really + // don't need it. + Z_Free(animdefsLump); + + // Now, let's start parsing this thing + p = animdefsText; + animdefsToken = M_GetToken(p); + while (animdefsToken != NULL) + { + if (stricmp(animdefsToken, "TEXTURE") == 0) + { + Z_Free(animdefsToken); + P_ParseAnimationDefintion(1); + } + else if (stricmp(animdefsToken, "FLAT") == 0) + { + Z_Free(animdefsToken); + P_ParseAnimationDefintion(0); + } + else if (stricmp(animdefsToken, "OSCILLATE") == 0) + { + // This probably came off the tail of an earlier definition. It's technically legal syntax, but we don't support it. + I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"OSCILLATE\" (the animation plays in reverse when it reaches the end) are not supported by SRB2"); + } + else + { + I_Error("Error parsing ANIMDEFS lump: Expected \"TEXTURE\" or \"FLAT\", got \"%s\"",animdefsToken); + } + // parse next line + while (*p != '\0' && *p != '\n') ++p; + if (*p == '\n') ++p; + animdefsToken = M_GetToken(p); + } + Z_Free(animdefsToken); + Z_Free((void *)animdefsText); +} + +void P_ParseAnimationDefintion(SINT8 istexture) +{ + char *animdefsToken; + size_t animdefsTokenLength; + char *endPos; + INT32 animSpeed; + size_t i; + + // Startname + animdefsToken = M_GetToken(NULL); + if (animdefsToken == NULL) + { + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where start texture/flat name should be"); + } + if (stricmp(animdefsToken, "OPTIONAL") == 0) + { + // This is meaningful to ZDoom - it tells the program NOT to bomb out + // if the textures can't be found - but it's useless in SRB2, so we'll + // just smile, nod, and carry on + Z_Free(animdefsToken); + animdefsToken = M_GetToken(NULL); + + if (animdefsToken == NULL) + { + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where start texture/flat name should be"); + } + else if (stricmp(animdefsToken, "RANGE") == 0) + { + // Oh. Um. Apparently "OPTIONAL" is a texture name. Naughty. + // I should probably handle this more gracefully, but right now + // I can't be bothered; especially since ZDoom doesn't handle this + // condition at all. + I_Error("Error parsing ANIMDEFS lump: \"OPTIONAL\" is a keyword; you cannot use it as the startname of an animation"); + } + } + animdefsTokenLength = strlen(animdefsToken); + if (animdefsTokenLength>8) + { + I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); + } + + // Search for existing animdef + for (i = 0; i < maxanims; i++) + if (animdefs[i].istexture == istexture // Check if it's the same type! + && stricmp(animdefsToken, animdefs[i].startname) == 0) + { + //CONS_Alert(CONS_NOTICE, "Duplicate animation: %s\n", animdefsToken); + + // If we weren't parsing in reverse order, we would `break` here and parse the new data into the existing slot we found. + // Instead, we're just going to skip parsing the rest of this line entirely. + Z_Free(animdefsToken); + return; + } + + // Not found + if (i == maxanims) + { + // Increase the size to make room for the new animation definition + GrowAnimDefs(); + strncpy(animdefs[i].startname, animdefsToken, 9); + } + + // animdefs[i].startname is now set to animdefsToken either way. + Z_Free(animdefsToken); + + // set texture type + animdefs[i].istexture = istexture; + + // "RANGE" + animdefsToken = M_GetToken(NULL); + if (animdefsToken == NULL) + { + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"RANGE\" after \"%s\"'s startname should be", animdefs[i].startname); + } + if (stricmp(animdefsToken, "ALLOWDECALS") == 0) + { + // Another ZDoom keyword, ho-hum. Skip it, move on to the next token. + Z_Free(animdefsToken); + animdefsToken = M_GetToken(NULL); + } + if (stricmp(animdefsToken, "PIC") == 0) + { + // This is technically legitimate ANIMDEFS syntax, but SRB2 doesn't support it. + I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"PIC\" (specific frames instead of a consecutive range) are not supported by SRB2"); + } + if (stricmp(animdefsToken, "RANGE") != 0) + { + I_Error("Error parsing ANIMDEFS lump: Expected \"RANGE\" after \"%s\"'s startname, got \"%s\"", animdefs[i].startname, animdefsToken); + } + Z_Free(animdefsToken); + + // Endname + animdefsToken = M_GetToken(NULL); + if (animdefsToken == NULL) + { + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s end texture/flat name should be", animdefs[i].startname); + } + animdefsTokenLength = strlen(animdefsToken); + if (animdefsTokenLength>8) + { + I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); + } + strncpy(animdefs[i].endname, animdefsToken, 9); + Z_Free(animdefsToken); + + // "TICS" + animdefsToken = M_GetToken(NULL); + if (animdefsToken == NULL) + { + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s \"TICS\" should be", animdefs[i].startname); + } + if (stricmp(animdefsToken, "RAND") == 0) + { + // This is technically legitimate ANIMDEFS syntax, but SRB2 doesn't support it. + I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"RAND\" (random duration per frame) are not supported by SRB2"); + } + if (stricmp(animdefsToken, "TICS") != 0) + { + I_Error("Error parsing ANIMDEFS lump: Expected \"TICS\" in animation definition for \"%s\", got \"%s\"", animdefs[i].startname, animdefsToken); + } + Z_Free(animdefsToken); + + // Speed + animdefsToken = M_GetToken(NULL); + if (animdefsToken == NULL) + { + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s animation speed should be", animdefs[i].startname); + } + endPos = NULL; +#ifndef AVOID_ERRNO + errno = 0; +#endif + animSpeed = strtol(animdefsToken,&endPos,10); + if (endPos == animdefsToken // Empty string + || *endPos != '\0' // Not end of string +#ifndef AVOID_ERRNO + || errno == ERANGE // Number out-of-range +#endif + || animSpeed < 0) // Number is not positive + { + I_Error("Error parsing ANIMDEFS lump: Expected a positive integer for \"%s\"'s animation speed, got \"%s\"", animdefs[i].startname, animdefsToken); + } + animdefs[i].speed = animSpeed; + Z_Free(animdefsToken); + +#ifdef WALLFLATS + // hehe... uhh..... + if (!istexture) + { + GrowAnimDefs(); + M_Memcpy(&animdefs[maxanims-1], &animdefs[i], sizeof(animdef_t)); + animdefs[maxanims-1].istexture = 1; + } +#endif +} + +/** Checks for flats in levelflats that are part of a flat animation sequence + * and sets them up for animation. + * + * \param animnum Index into ::anims to find flats for. + * \sa P_SetupLevelFlatAnims + */ +static inline void P_FindAnimatedFlat(INT32 animnum) +{ + size_t i; + lumpnum_t startflatnum, endflatnum; + levelflat_t *foundflats; + + foundflats = levelflats; + startflatnum = anims[animnum].basepic; + endflatnum = anims[animnum].picnum; + + // note: high word of lumpnum is the wad number + if ((startflatnum>>16) != (endflatnum>>16)) + I_Error("AnimatedFlat start %s not in same wad as end %s\n", + animdefs[animnum].startname, animdefs[animnum].endname); + + // + // now search through the levelflats if this anim flat sequence is used + // + for (i = 0; i < numlevelflats; i++, foundflats++) + { + // is that levelflat from the flat anim sequence ? + if ((anims[animnum].istexture) && (foundflats->type == LEVELFLAT_TEXTURE) + && ((UINT16)foundflats->u.texture.num >= startflatnum && (UINT16)foundflats->u.texture.num <= endflatnum)) + { + foundflats->u.texture.basenum = startflatnum; + foundflats->animseq = foundflats->u.texture.num - startflatnum; + foundflats->numpics = endflatnum - startflatnum + 1; + foundflats->speed = anims[animnum].speed; + + CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n", + atoi(sizeu1(i)), foundflats->name, foundflats->animseq, + foundflats->numpics,foundflats->speed); + } + else if ((!anims[animnum].istexture) && (foundflats->type == LEVELFLAT_FLAT) + && (foundflats->u.flat.lumpnum >= startflatnum && foundflats->u.flat.lumpnum <= endflatnum)) + { + foundflats->u.flat.baselumpnum = startflatnum; + foundflats->animseq = foundflats->u.flat.lumpnum - startflatnum; + foundflats->numpics = endflatnum - startflatnum + 1; + foundflats->speed = anims[animnum].speed; + + CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n", + atoi(sizeu1(i)), foundflats->name, foundflats->animseq, + foundflats->numpics,foundflats->speed); + } + } +} + +/** Sets up all flats used in a level. + * + * \sa P_InitPicAnims, P_FindAnimatedFlat + */ +void P_SetupLevelFlatAnims(void) +{ + INT32 i; + + // the original game flat anim sequences + for (i = 0; anims[i].istexture != -1; i++) + P_FindAnimatedFlat(i); +} + +// +// UTILITIES +// + +#if 0 +/** Gets a side from a sector line. + * + * \param currentSector Sector the line is in. + * \param line Index of the line within the sector. + * \param side 0 for front, 1 for back. + * \return Pointer to the side_t of the side you want. + * \sa getSector, twoSided, getNextSector + */ +static inline side_t *getSide(INT32 currentSector, INT32 line, INT32 side) +{ + return &sides[(sectors[currentSector].lines[line])->sidenum[side]]; +} + +/** Gets a sector from a sector line. + * + * \param currentSector Sector the line is in. + * \param line Index of the line within the sector. + * \param side 0 for front, 1 for back. + * \return Pointer to the ::sector_t of the sector on that side. + * \sa getSide, twoSided, getNextSector + */ +static inline sector_t *getSector(INT32 currentSector, INT32 line, INT32 side) +{ + return sides[(sectors[currentSector].lines[line])->sidenum[side]].sector; +} + +/** Determines whether a sector line is two-sided. + * Uses the Boom method, checking if the line's back side is set to -1, rather + * than looking for ::ML_TWOSIDED. + * + * \param sector The sector. + * \param line Line index within the sector. + * \return 1 if the sector is two-sided, 0 otherwise. + * \sa getSide, getSector, getNextSector + */ +static inline boolean twoSided(INT32 sector, INT32 line) +{ + return (sectors[sector].lines[line])->sidenum[1] != 0xffff; +} +#endif + +/** Finds sector next to current. + * + * \param line Pointer to the line to cross. + * \param sec Pointer to the current sector. + * \return Pointer to a ::sector_t of the adjacent sector, or NULL if the line + * is one-sided. + * \sa getSide, getSector, twoSided + * \author Steven McGranahan + */ +static sector_t *getNextSector(line_t *line, sector_t *sec) +{ + if (line->frontsector == sec) + { + if (line->backsector != sec) + return line->backsector; + else + return NULL; + } + return line->frontsector; +} + +/** Finds lowest floor in adjacent sectors. + * + * \param sec Sector to start in. + * \return Lowest floor height in an adjacent sector. + * \sa P_FindHighestFloorSurrounding, P_FindNextLowestFloor, + * P_FindLowestCeilingSurrounding + */ +fixed_t P_FindLowestFloorSurrounding(sector_t *sec) +{ + size_t i; + line_t *check; + sector_t *other; + fixed_t floorh; + + floorh = sec->floorheight; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->floorheight < floorh) + floorh = other->floorheight; + } + return floorh; +} + +/** Finds highest floor in adjacent sectors. + * + * \param sec Sector to start in. + * \return Highest floor height in an adjacent sector. + * \sa P_FindLowestFloorSurrounding, P_FindNextHighestFloor, + * P_FindHighestCeilingSurrounding + */ +fixed_t P_FindHighestFloorSurrounding(sector_t *sec) +{ + size_t i; + line_t *check; + sector_t *other; + fixed_t floorh = -500*FRACUNIT; + INT32 foundsector = 0; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + + if (!other) + continue; + + if (other->floorheight > floorh || !foundsector) + floorh = other->floorheight; + + if (!foundsector) + foundsector = 1; + } + return floorh; +} + +/** Finds next highest floor in adjacent sectors. + * + * \param sec Sector to start in. + * \param currentheight Height to start at. + * \return Next highest floor height in an adjacent sector, or currentheight + * if there are none higher. + * \sa P_FindHighestFloorSurrounding, P_FindNextLowestFloor, + * P_FindNextHighestCeiling + * \author Lee Killough + */ +fixed_t P_FindNextHighestFloor(sector_t *sec, fixed_t currentheight) +{ + sector_t *other; + size_t i; + fixed_t height; + + for (i = 0; i < sec->linecount; i++) + { + other = getNextSector(sec->lines[i],sec); + if (other && other->floorheight > currentheight) + { + height = other->floorheight; + while (++i < sec->linecount) + { + other = getNextSector(sec->lines[i], sec); + if (other && + other->floorheight < height && + other->floorheight > currentheight) + height = other->floorheight; + } + return height; + } + } + return currentheight; +} + +//////////////////////////////////////////////////// +// SoM: Start new Boom functions +//////////////////////////////////////////////////// + +/** Finds next lowest floor in adjacent sectors. + * + * \param sec Sector to start in. + * \param currentheight Height to start at. + * \return Next lowest floor height in an adjacent sector, or currentheight + * if there are none lower. + * \sa P_FindLowestFloorSurrounding, P_FindNextHighestFloor, + * P_FindNextLowestCeiling + * \author Lee Killough + */ +fixed_t P_FindNextLowestFloor(sector_t *sec, fixed_t currentheight) +{ + sector_t *other; + size_t i; + fixed_t height; + + for (i = 0; i < sec->linecount; i++) + { + other = getNextSector(sec->lines[i], sec); + if (other && other->floorheight < currentheight) + { + height = other->floorheight; + while (++i < sec->linecount) + { + other = getNextSector(sec->lines[i], sec); + if (other && other->floorheight > height + && other->floorheight < currentheight) + height = other->floorheight; + } + return height; + } + } + return currentheight; +} + +#if 0 +/** Finds next lowest ceiling in adjacent sectors. + * + * \param sec Sector to start in. + * \param currentheight Height to start at. + * \return Next lowest ceiling height in an adjacent sector, or currentheight + * if there are none lower. + * \sa P_FindLowestCeilingSurrounding, P_FindNextHighestCeiling, + * P_FindNextLowestFloor + * \author Lee Killough + */ +static fixed_t P_FindNextLowestCeiling(sector_t *sec, fixed_t currentheight) +{ + sector_t *other; + size_t i; + fixed_t height; + + for (i = 0; i < sec->linecount; i++) + { + other = getNextSector(sec->lines[i],sec); + if (other && other->ceilingheight < currentheight) + { + height = other->ceilingheight; + while (++i < sec->linecount) + { + other = getNextSector(sec->lines[i],sec); + if (other && other->ceilingheight > height + && other->ceilingheight < currentheight) + height = other->ceilingheight; + } + return height; + } + } + return currentheight; +} + +/** Finds next highest ceiling in adjacent sectors. + * + * \param sec Sector to start in. + * \param currentheight Height to start at. + * \return Next highest ceiling height in an adjacent sector, or currentheight + * if there are none higher. + * \sa P_FindHighestCeilingSurrounding, P_FindNextLowestCeiling, + * P_FindNextHighestFloor + * \author Lee Killough + */ +static fixed_t P_FindNextHighestCeiling(sector_t *sec, fixed_t currentheight) +{ + sector_t *other; + size_t i; + fixed_t height; + + for (i = 0; i < sec->linecount; i++) + { + other = getNextSector(sec->lines[i], sec); + if (other && other->ceilingheight > currentheight) + { + height = other->ceilingheight; + while (++i < sec->linecount) + { + other = getNextSector(sec->lines[i],sec); + if (other && other->ceilingheight < height + && other->ceilingheight > currentheight) + height = other->ceilingheight; + } + return height; + } + } + return currentheight; +} +#endif + +//////////////////////////// +// End New Boom functions +//////////////////////////// + +/** Finds lowest ceiling in adjacent sectors. + * + * \param sec Sector to start in. + * \return Lowest ceiling height in an adjacent sector. + * \sa P_FindHighestCeilingSurrounding, P_FindNextLowestCeiling, + * P_FindLowestFloorSurrounding + */ +fixed_t P_FindLowestCeilingSurrounding(sector_t *sec) +{ + size_t i; + line_t *check; + sector_t *other; + fixed_t height = 32000*FRACUNIT; //SoM: 3/7/2000: Remove ovf + INT32 foundsector = 0; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + + if (!other) + continue; + + if (other->ceilingheight < height || !foundsector) + height = other->ceilingheight; + + if (!foundsector) + foundsector = 1; + } + return height; +} + +/** Finds Highest ceiling in adjacent sectors. + * + * \param sec Sector to start in. + * \return Highest ceiling height in an adjacent sector. + * \sa P_FindLowestCeilingSurrounding, P_FindNextHighestCeiling, + * P_FindHighestFloorSurrounding + */ +fixed_t P_FindHighestCeilingSurrounding(sector_t *sec) +{ + size_t i; + line_t *check; + sector_t *other; + fixed_t height = 0; + INT32 foundsector = 0; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + + if (!other) + continue; + + if (other->ceilingheight > height || !foundsector) + height = other->ceilingheight; + + if (!foundsector) + foundsector = 1; + } + return height; +} + +#if 0 +//SoM: 3/7/2000: UTILS..... +// +// P_FindShortestTextureAround() +// +// Passed a sector number, returns the shortest lower texture on a +// linedef bounding the sector. +// +// +static fixed_t P_FindShortestTextureAround(INT32 secnum) +{ + fixed_t minsize = 32000<linecount; i++) + { + if (twoSided(secnum, i)) + { + side = getSide(secnum,i,0); + if (side->bottomtexture > 0) + if (textureheight[side->bottomtexture] < minsize) + minsize = textureheight[side->bottomtexture]; + side = getSide(secnum,i,1); + if (side->bottomtexture > 0) + if (textureheight[side->bottomtexture] < minsize) + minsize = textureheight[side->bottomtexture]; + } + } + return minsize; +} + +//SoM: 3/7/2000: Stuff.... (can you tell I'm getting tired? It's 12 : 30!) +// +// P_FindShortestUpperAround() +// +// Passed a sector number, returns the shortest upper texture on a +// linedef bounding the sector. +// +// +static fixed_t P_FindShortestUpperAround(INT32 secnum) +{ + fixed_t minsize = 32000<linecount; i++) + { + if (twoSided(secnum, i)) + { + side = getSide(secnum,i,0); + if (side->toptexture > 0) + if (textureheight[side->toptexture] < minsize) + minsize = textureheight[side->toptexture]; + side = getSide(secnum,i,1); + if (side->toptexture > 0) + if (textureheight[side->toptexture] < minsize) + minsize = textureheight[side->toptexture]; + } + } + return minsize; +} + +//SoM: 3/7/2000 +// +// P_FindModelFloorSector() +// +// Passed a floor height and a sector number, return a pointer to a +// a sector with that floor height across the lowest numbered two sided +// line surrounding the sector. +// +// Note: If no sector at that height bounds the sector passed, return NULL +// +// +static sector_t *P_FindModelFloorSector(fixed_t floordestheight, INT32 secnum) +{ + size_t i; + sector_t *sec = §ors[secnum]; + + for (i = 0; i < sec->linecount; i++) + { + if (twoSided(secnum, i)) + { + if (getSide(secnum,i,0)->sector-sectors == secnum) + sec = getSector(secnum,i,1); + else + sec = getSector(secnum,i,0); + + if (sec->floorheight == floordestheight) + return sec; + } + } + return NULL; +} + +// +// P_FindModelCeilingSector() +// +// Passed a ceiling height and a sector number, return a pointer to a +// a sector with that ceiling height across the lowest numbered two sided +// line surrounding the sector. +// +// Note: If no sector at that height bounds the sector passed, return NULL +// +static sector_t *P_FindModelCeilingSector(fixed_t ceildestheight, INT32 secnum) +{ + size_t i; + sector_t *sec = §ors[secnum]; + + for (i = 0; i < sec->linecount; i++) + { + if (twoSided(secnum, i)) + { + if (getSide(secnum, i, 0)->sector - sectors == secnum) + sec = getSector(secnum, i, 1); + else + sec = getSector(secnum, i, 0); + + if (sec->ceilingheight == ceildestheight) + return sec; + } + } + return NULL; +} +#endif + +// Parses arguments for parameterized polyobject door types +static boolean PolyDoor(line_t *line) +{ + polydoordata_t pdd; + + pdd.polyObjNum = Tag_FGet(&line->tags); // polyobject id + + switch(line->special) + { + case 480: // Polyobj_DoorSlide + pdd.doorType = POLY_DOOR_SLIDE; + pdd.speed = sides[line->sidenum[0]].textureoffset / 8; + pdd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); // angle of motion + pdd.distance = sides[line->sidenum[0]].rowoffset; + + if (line->sidenum[1] != 0xffff) + pdd.delay = sides[line->sidenum[1]].textureoffset >> FRACBITS; // delay in tics + else + pdd.delay = 0; + break; + case 481: // Polyobj_DoorSwing + pdd.doorType = POLY_DOOR_SWING; + pdd.speed = sides[line->sidenum[0]].textureoffset >> FRACBITS; // angular speed + pdd.distance = sides[line->sidenum[0]].rowoffset >> FRACBITS; // angular distance + + if (line->sidenum[1] != 0xffff) + pdd.delay = sides[line->sidenum[1]].textureoffset >> FRACBITS; // delay in tics + else + pdd.delay = 0; + break; + default: + return 0; // ??? + } + + return EV_DoPolyDoor(&pdd); +} + +// Parses arguments for parameterized polyobject move specials +static boolean PolyMove(line_t *line) +{ + polymovedata_t pmd; + + pmd.polyObjNum = Tag_FGet(&line->tags); + pmd.speed = sides[line->sidenum[0]].textureoffset / 8; + pmd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); + pmd.distance = sides[line->sidenum[0]].rowoffset; + + pmd.overRide = (line->special == 483); // Polyobj_OR_Move + + return EV_DoPolyObjMove(&pmd); +} + +// Makes a polyobject invisible and intangible +// If NOCLIMB is ticked, the polyobject will still be tangible, just not visible. +static void PolyInvisible(line_t *line) +{ + INT32 polyObjNum = Tag_FGet(&line->tags); + polyobj_t *po; + + if (!(po = Polyobj_GetForNum(polyObjNum))) + { + CONS_Debug(DBG_POLYOBJ, "PolyInvisible: bad polyobj %d\n", polyObjNum); + return; + } + + // don't allow line actions to affect bad polyobjects + if (po->isBad) + return; + + if (!(line->flags & ML_NOCLIMB)) + po->flags &= ~POF_SOLID; + + po->flags |= POF_NOSPECIALS; + po->flags &= ~POF_RENDERALL; +} + +// Makes a polyobject visible and tangible +// If NOCLIMB is ticked, the polyobject will not be tangible, just visible. +static void PolyVisible(line_t *line) +{ + INT32 polyObjNum = Tag_FGet(&line->tags); + polyobj_t *po; + + if (!(po = Polyobj_GetForNum(polyObjNum))) + { + CONS_Debug(DBG_POLYOBJ, "PolyVisible: bad polyobj %d\n", polyObjNum); + return; + } + + // don't allow line actions to affect bad polyobjects + if (po->isBad) + return; + + if (!(line->flags & ML_NOCLIMB)) + po->flags |= POF_SOLID; + + po->flags &= ~POF_NOSPECIALS; + po->flags |= (po->spawnflags & POF_RENDERALL); +} + + +// Sets the translucency of a polyobject +// Frontsector floor / 100 = translevel +static void PolyTranslucency(line_t *line) +{ + INT32 polyObjNum = Tag_FGet(&line->tags); + polyobj_t *po; + INT32 value; + + if (!(po = Polyobj_GetForNum(polyObjNum))) + { + CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: bad polyobj %d\n", polyObjNum); + return; + } + + // don't allow line actions to affect bad polyobjects + if (po->isBad) + return; + + // If Front X Offset is specified, use that. Else, use floorheight. + value = (sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : line->frontsector->floorheight) >> FRACBITS; + + // If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000. + if (!(line->flags & ML_DONTPEGBOTTOM)) + value /= 100; + + if (line->flags & ML_EFFECT3) // relative calc + po->translucency += value; + else + po->translucency = value; + + po->translucency = max(min(po->translucency, NUMTRANSMAPS), 0); +} + +// Makes a polyobject translucency fade and applies tangibility +static boolean PolyFade(line_t *line) +{ + INT32 polyObjNum = Tag_FGet(&line->tags); + polyobj_t *po; + polyfadedata_t pfd; + INT32 value; + + if (!(po = Polyobj_GetForNum(polyObjNum))) + { + CONS_Debug(DBG_POLYOBJ, "PolyFade: bad polyobj %d\n", polyObjNum); + return 0; + } + + // don't allow line actions to affect bad polyobjects + if (po->isBad) + return 0; + + // Prevent continuous execs from interfering on an existing fade + if (!(line->flags & ML_EFFECT5) + && po->thinker + && po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade) + { + CONS_Debug(DBG_POLYOBJ, "Line type 492 Executor: Fade PolyObject thinker already exists\n"); + return 0; + } + + pfd.polyObjNum = polyObjNum; + + // If Front X Offset is specified, use that. Else, use floorheight. + value = (sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : line->frontsector->floorheight) >> FRACBITS; + + // If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000. + if (!(line->flags & ML_DONTPEGBOTTOM)) + value /= 100; + + if (line->flags & ML_EFFECT3) // relative calc + pfd.destvalue = po->translucency + value; + else + pfd.destvalue = value; + + pfd.destvalue = max(min(pfd.destvalue, NUMTRANSMAPS), 0); + + // already equal, nothing to do + if (po->translucency == pfd.destvalue) + return 1; + + pfd.docollision = !(line->flags & ML_BOUNCY); // do not handle collision flags + pfd.doghostfade = (line->flags & ML_EFFECT1); // do ghost fade (no collision flags during fade) + pfd.ticbased = (line->flags & ML_EFFECT4); // Speed = Tic Duration + + // allow Back Y Offset to be consistent with other fade specials + pfd.speed = (line->sidenum[1] != 0xFFFF && !sides[line->sidenum[0]].rowoffset) ? + abs(sides[line->sidenum[1]].rowoffset>>FRACBITS) + : abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); + + + return EV_DoPolyObjFade(&pfd); +} + +// Parses arguments for parameterized polyobject waypoint movement +static boolean PolyWaypoint(line_t *line) +{ + polywaypointdata_t pwd; + + pwd.polyObjNum = Tag_FGet(&line->tags); + pwd.speed = sides[line->sidenum[0]].textureoffset / 8; + pwd.sequence = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Sequence # + + // Behavior after reaching the last waypoint? + if (line->flags & ML_EFFECT3) + pwd.returnbehavior = PWR_WRAP; // Wrap back to first waypoint + else if (line->flags & ML_EFFECT2) + pwd.returnbehavior = PWR_COMEBACK; // Go through sequence in reverse + else + pwd.returnbehavior = PWR_STOP; // Stop + + // Flags + pwd.flags = 0; + if (line->flags & ML_EFFECT1) + pwd.flags |= PWF_REVERSE; + if (line->flags & ML_EFFECT4) + pwd.flags |= PWF_LOOP; + + return EV_DoPolyObjWaypoint(&pwd); +} + +// Parses arguments for parameterized polyobject rotate specials +static boolean PolyRotate(line_t *line) +{ + polyrotdata_t prd; + + prd.polyObjNum = Tag_FGet(&line->tags); + prd.speed = sides[line->sidenum[0]].textureoffset >> FRACBITS; // angular speed + prd.distance = sides[line->sidenum[0]].rowoffset >> FRACBITS; // angular distance + + // Polyobj_(OR_)RotateRight have dir == -1 + prd.direction = (line->special == 484 || line->special == 485) ? -1 : 1; + + // Polyobj_OR types have override set to true + prd.overRide = (line->special == 485 || line->special == 487); + + if (line->flags & ML_NOCLIMB) + prd.turnobjs = 0; + else if (line->flags & ML_EFFECT4) + prd.turnobjs = 2; + else + prd.turnobjs = 1; + + return EV_DoPolyObjRotate(&prd); +} + +// Parses arguments for polyobject flag waving special +static boolean PolyFlag(line_t *line) +{ + polyflagdata_t pfd; + + pfd.polyObjNum = Tag_FGet(&line->tags); + pfd.speed = P_AproxDistance(line->dx, line->dy) >> FRACBITS; + pfd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y) >> ANGLETOFINESHIFT; + pfd.momx = sides[line->sidenum[0]].textureoffset >> FRACBITS; + + return EV_DoPolyObjFlag(&pfd); +} + +// Parses arguments for parameterized polyobject move-by-sector-heights specials +static boolean PolyDisplace(line_t *line) +{ + polydisplacedata_t pdd; + + pdd.polyObjNum = Tag_FGet(&line->tags); + + pdd.controlSector = line->frontsector; + pdd.dx = line->dx>>8; + pdd.dy = line->dy>>8; + + return EV_DoPolyObjDisplace(&pdd); +} + + +// Parses arguments for parameterized polyobject rotate-by-sector-heights specials +static boolean PolyRotDisplace(line_t *line) +{ + polyrotdisplacedata_t pdd; + fixed_t anginter, distinter; + + pdd.polyObjNum = Tag_FGet(&line->tags); + pdd.controlSector = line->frontsector; + + // Rotate 'anginter' interval for each 'distinter' interval from the control sector. + // Use default values if not provided as fallback. + anginter = sides[line->sidenum[0]].rowoffset ? sides[line->sidenum[0]].rowoffset : 90*FRACUNIT; + distinter = sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : 128*FRACUNIT; + pdd.rotscale = FixedDiv(anginter, distinter); + + // Same behavior as other rotators when carrying things. + if (line->flags & ML_NOCLIMB) + pdd.turnobjs = 0; + else if (line->flags & ML_EFFECT4) + pdd.turnobjs = 2; + else + pdd.turnobjs = 1; + + return EV_DoPolyObjRotDisplace(&pdd); +} + + +// +// P_RunNightserizeExecutors +// +void P_RunNightserizeExecutors(mobj_t *actor) +{ + size_t i; + + for (i = 0; i < numlines; i++) + { + if (lines[i].special == 323 || lines[i].special == 324) + P_RunTriggerLinedef(&lines[i], actor, NULL); + } +} + +// +// P_RunDeNightserizeExecutors +// +void P_RunDeNightserizeExecutors(mobj_t *actor) +{ + size_t i; + + for (i = 0; i < numlines; i++) + { + if (lines[i].special == 325 || lines[i].special == 326) + P_RunTriggerLinedef(&lines[i], actor, NULL); + } +} + +// +// P_RunNightsLapExecutors +// +void P_RunNightsLapExecutors(mobj_t *actor) +{ + size_t i; + + for (i = 0; i < numlines; i++) + { + if (lines[i].special == 327 || lines[i].special == 328) + P_RunTriggerLinedef(&lines[i], actor, NULL); + } +} + +// +// P_RunNightsCapsuleTouchExecutors +// +void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean enoughspheres) +{ + size_t i; + + for (i = 0; i < numlines; i++) + { + if ((lines[i].special == 329 || lines[i].special == 330) + && ((entering && (lines[i].flags & ML_TFERLINE)) + || (!entering && !(lines[i].flags & ML_TFERLINE))) + && ((lines[i].flags & ML_DONTPEGTOP) + || (enoughspheres && !(lines[i].flags & ML_BOUNCY)) + || (!enoughspheres && (lines[i].flags & ML_BOUNCY)))) + P_RunTriggerLinedef(&lines[i], actor, NULL); + } +} + +/** Finds minimum light from an adjacent sector. + * + * \param sector Sector to start in. + * \param max Maximum value to return. + * \return Minimum light value from an adjacent sector, or max if the minimum + * light value is greater than max. + */ +INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max) +{ + size_t i; + INT32 min = max; + line_t *line; + sector_t *check; + + for (i = 0; i < sector->linecount; i++) + { + line = sector->lines[i]; + check = getNextSector(line,sector); + + if (!check) + continue; + + if (check->lightlevel < min) + min = check->lightlevel; + } + return min; +} + +void T_ExecutorDelay(executor_t *e) +{ + if (--e->timer <= 0) + { + if (e->caller && P_MobjWasRemoved(e->caller)) // If the mobj died while we were delaying + P_SetTarget(&e->caller, NULL); // Call with no mobj! + P_ProcessLineSpecial(e->line, e->caller, e->sector); + P_SetTarget(&e->caller, NULL); // Let the mobj know it can be removed now. + P_RemoveThinker(&e->thinker); + } +} + +static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector) +{ + executor_t *e; + INT32 delay; + + if (udmf) + delay = line->executordelay; + else + { + if (!line->backsector) + I_Error("P_AddExecutorDelay: Line has no backsector!\n"); + + delay = (line->backsector->ceilingheight >> FRACBITS) + (line->backsector->floorheight >> FRACBITS); + } + + e = Z_Calloc(sizeof (*e), PU_LEVSPEC, NULL); + + e->thinker.function.acp1 = (actionf_p1)T_ExecutorDelay; + e->line = line; + e->sector = sector; + e->timer = delay; + P_SetTarget(&e->caller, mobj); // Use P_SetTarget to make sure the mobj doesn't get freed while we're delaying. + P_AddThinker(THINK_MAIN, &e->thinker); +} + +/** Used by P_RunTriggerLinedef to check a NiGHTS trigger linedef's conditions + * + * \param triggerline Trigger linedef to check conditions for; should NEVER be NULL. + * \param actor Object initiating the action; should not be NULL. + * \sa P_RunTriggerLinedef + */ +static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) +{ + INT16 specialtype = triggerline->special; + size_t i; + + UINT8 inputmare = max(0, min(255, sides[triggerline->sidenum[0]].textureoffset>>FRACBITS)); + UINT8 inputlap = max(0, min(255, sides[triggerline->sidenum[0]].rowoffset>>FRACBITS)); + + boolean ltemare = triggerline->flags & ML_NOCLIMB; + boolean gtemare = triggerline->flags & ML_BLOCKMONSTERS; + boolean ltelap = triggerline->flags & ML_EFFECT1; + boolean gtelap = triggerline->flags & ML_EFFECT2; + + boolean lapfrombonustime = triggerline->flags & ML_EFFECT3; + boolean perglobalinverse = triggerline->flags & ML_DONTPEGBOTTOM; + boolean perglobal = !(triggerline->flags & ML_EFFECT4) && !perglobalinverse; + + boolean donomares = triggerline->flags & ML_BOUNCY; // nightserize: run at end of level (no mares) + boolean fromnonights = triggerline->flags & ML_TFERLINE; // nightserize: from non-nights // denightserize: all players no nights + boolean fromnights = triggerline->flags & ML_DONTPEGTOP; // nightserize: from nights // denightserize: >0 players are nights + + UINT8 currentmare = UINT8_MAX; + UINT8 currentlap = UINT8_MAX; + + // Do early returns for Nightserize + if (specialtype >= 323 && specialtype <= 324) + { + // run only when no mares are found + if (donomares && P_FindLowestMare() != UINT8_MAX) + return false; + + // run only if there is a mare present + if (!donomares && P_FindLowestMare() == UINT8_MAX) + return false; + + // run only if player is nightserizing from non-nights + if (fromnonights) + { + if (!actor->player) + return false; + else if (actor->player->powers[pw_carry] == CR_NIGHTSMODE) + return false; + } + // run only if player is nightserizing from nights + else if (fromnights) + { + if (!actor->player) + return false; + else if (actor->player->powers[pw_carry] != CR_NIGHTSMODE) + return false; + } + } + + // Get current mare and lap (and check early return for DeNightserize) + if (perglobal || perglobalinverse + || (specialtype >= 325 && specialtype <= 326 && (fromnonights || fromnights))) + { + UINT8 playersarenights = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + UINT8 lap; + if (!playeringame[i] || players[i].spectator) + continue; + + // denightserize: run only if all players are not nights + if (specialtype >= 325 && specialtype <= 326 && fromnonights + && players[i].powers[pw_carry] == CR_NIGHTSMODE) + return false; + + // count number of nights players for denightserize return + if (specialtype >= 325 && specialtype <= 326 && fromnights + && players[i].powers[pw_carry] == CR_NIGHTSMODE) + playersarenights++; + + lap = lapfrombonustime ? players[i].marebonuslap : players[i].marelap; + + // get highest mare/lap of players + if (perglobal) + { + if (players[i].mare > currentmare || currentmare == UINT8_MAX) + { + currentmare = players[i].mare; + currentlap = UINT8_MAX; + } + if (players[i].mare == currentmare + && (lap > currentlap || currentlap == UINT8_MAX)) + currentlap = lap; + } + // get lowest mare/lap of players + else if (perglobalinverse) + { + if (players[i].mare < currentmare || currentmare == UINT8_MAX) + { + currentmare = players[i].mare; + currentlap = UINT8_MAX; + } + if (players[i].mare == currentmare + && (lap < currentlap || currentlap == UINT8_MAX)) + currentlap = lap; + } + } + + // denightserize: run only if >0 players are nights + if (specialtype >= 325 && specialtype <= 326 && fromnights + && playersarenights < 1) + return false; + } + // get current mare/lap from triggering player + else if (!perglobal && !perglobalinverse) + { + if (!actor->player) + return false; + currentmare = actor->player->mare; + currentlap = lapfrombonustime ? actor->player->marebonuslap : actor->player->marelap; + } + + if (lapfrombonustime && !currentlap) + return false; // special case: player->marebonuslap is 0 until passing through on bonus time. Don't trigger lines looking for inputlap 0. + + // Compare current mare/lap to input mare/lap based on rules + if (!(specialtype >= 323 && specialtype <= 324 && donomares) // don't return false if donomares and we got this far + && ((ltemare && currentmare > inputmare) + || (gtemare && currentmare < inputmare) + || (!ltemare && !gtemare && currentmare != inputmare) + || (ltelap && currentlap > inputlap) + || (gtelap && currentlap < inputlap) + || (!ltelap && !gtelap && currentlap != inputlap)) + ) + return false; + + return true; +} + +/** Used by P_LinedefExecute to check a trigger linedef's conditions + * The linedef executor specials in the trigger linedef's sector are run if all conditions are met. + * Return false cancels P_LinedefExecute, this happens if a condition is not met. + * + * \param triggerline Trigger linedef to check conditions for; should NEVER be NULL. + * \param actor Object initiating the action; should not be NULL. + * \param caller Sector in which the action was started. May be NULL. + * \sa P_ProcessLineSpecial, P_LinedefExecute + */ +boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller) +{ + sector_t *ctlsector; + fixed_t dist = P_AproxDistance(triggerline->dx, triggerline->dy)>>FRACBITS; + size_t i, linecnt, sectori; + INT16 specialtype = triggerline->special; + + ///////////////////////////////////////////////// + // Distance-checking/sector trigger conditions // + ///////////////////////////////////////////////// + + // Linetypes 303 and 304 require a specific + // number, or minimum or maximum, of rings. + if (specialtype == 303 || specialtype == 304) + { + fixed_t rings = 0; + + // With the passuse flag, count all player's + // rings. + if (triggerline->flags & ML_EFFECT4) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (!players[i].mo || ((maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings) <= 0) + continue; + + rings += (maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings; + } + } + else + { + if (!(actor && actor->player)) + return false; // no player to count rings from here, sorry + + rings = (maptol & TOL_NIGHTS) ? actor->player->spheres : actor->player->rings; + } + + if (triggerline->flags & ML_NOCLIMB) + { + if (rings > dist) + return false; + } + else if (triggerline->flags & ML_BLOCKMONSTERS) + { + if (rings < dist) + return false; + } + else + { + if (rings != dist) + return false; + } + } + else if (specialtype >= 314 && specialtype <= 315) + { + msecnode_t *node; + mobj_t *mo; + INT32 numpush = 0; + INT32 numneeded = dist; + + if (!caller) + return false; // we need a calling sector to find pushables in, silly! + + // Count the pushables in this sector + node = caller->touching_thinglist; // things touching this sector + while (node) + { + mo = node->m_thing; + if ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse)) + numpush++; + node = node->m_thinglist_next; + } + + if (triggerline->flags & ML_NOCLIMB) // Need at least or more + { + if (numpush < numneeded) + return false; + } + else if (triggerline->flags & ML_EFFECT4) // Need less than + { + if (numpush >= numneeded) + return false; + } + else // Need exact + { + if (numpush != numneeded) + return false; + } + } + else if (caller) + { + if (GETSECSPECIAL(caller->special, 2) == 6) + { + if (!(ALL7EMERALDS(emeralds))) + return false; + } + else if (GETSECSPECIAL(caller->special, 2) == 7) + { + UINT8 mare; + + if (!(maptol & TOL_NIGHTS)) + return false; + + mare = P_FindLowestMare(); + + if (triggerline->flags & ML_NOCLIMB) + { + if (!(mare <= dist)) + return false; + } + else if (triggerline->flags & ML_BLOCKMONSTERS) + { + if (!(mare >= dist)) + return false; + } + else + { + if (!(mare == dist)) + return false; + } + } + // If we were not triggered by a sector type especially for the purpose, + // a Linedef Executor linedef trigger is not handling sector triggers properly, return. + + else if ((!GETSECSPECIAL(caller->special, 2) || GETSECSPECIAL(caller->special, 2) > 7) && (specialtype > 322)) + { + CONS_Alert(CONS_WARNING, + M_GetText("Linedef executor trigger isn't handling sector triggers properly!\nspecialtype = %d, if you are not a dev, report this warning instance\nalong with the wad that caused it!\n"), + specialtype); + return false; + } + } + + ////////////////////////////////////// + // Miscellaneous trigger conditions // + ////////////////////////////////////// + + switch (specialtype) + { + case 305: // continuous + case 306: // each time + case 307: // once + if (!(actor && actor->player && actor->player->charability == dist/10)) + return false; + break; + case 309: // continuous + case 310: // each time + // Only red team members can activate this. + if (!(actor && actor->player && actor->player->ctfteam == 1)) + return false; + break; + case 311: // continuous + case 312: // each time + // Only blue team members can activate this. + if (!(actor && actor->player && actor->player->ctfteam == 2)) + return false; + break; + case 317: // continuous + case 318: // once + { // Unlockable triggers required + INT32 trigid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS); + + if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) + return false; + else if (trigid < 0 || trigid > 31) // limited by 32 bit variable + { + CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", triggerline->sidenum[0], trigid); + return false; + } + else if (!(unlocktriggers & (1 << trigid))) + return false; + } + break; + case 319: // continuous + case 320: // once + { // An unlockable itself must be unlocked! + INT32 unlockid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS); + + if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) + return false; + else if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count + { + CONS_Debug(DBG_GAMELOGIC, "Unlockable check (sidedef %hu): bad unlockable ID %d\n", triggerline->sidenum[0], unlockid); + return false; + } + else if (!(unlockables[unlockid-1].unlocked)) + return false; + } + break; + case 321: // continuous + case 322: // each time + // decrement calls left before triggering + if (triggerline->callcount > 0) + { + if (--triggerline->callcount > 0) + return false; + } + break; + case 323: // nightserize - each time + case 324: // nightserize - once + case 325: // denightserize - each time + case 326: // denightserize - once + case 327: // nights lap - each time + case 328: // nights lap - once + case 329: // nights egg capsule touch - each time + case 330: // nights egg capsule touch - once + if (!P_CheckNightsTriggerLine(triggerline, actor)) + return false; + break; + case 331: // continuous + case 332: // each time + case 333: // once + if (!(actor && actor->player && ((stricmp(triggerline->text, skins[actor->player->skin].name) == 0) ^ ((triggerline->flags & ML_NOCLIMB) == ML_NOCLIMB)))) + return false; + break; + case 334: // object dye - continuous + case 335: // object dye - each time + case 336: // object dye - once + { + INT32 triggercolor = (INT32)sides[triggerline->sidenum[0]].toptexture; + UINT16 color = (actor->player ? actor->player->powers[pw_dye] : actor->color); + boolean invert = (triggerline->flags & ML_NOCLIMB ? true : false); + + if (invert ^ (triggercolor != color)) + return false; + } + default: + break; + } + + ///////////////////////////////// + // Processing linedef specials // + ///////////////////////////////// + + ctlsector = triggerline->frontsector; + sectori = (size_t)(ctlsector - sectors); + linecnt = ctlsector->linecount; + + if (triggerline->flags & ML_EFFECT5) // disregard order for efficiency + { + for (i = 0; i < linecnt; i++) + if (ctlsector->lines[i]->special >= 400 + && ctlsector->lines[i]->special < 500) + { + if (ctlsector->lines[i]->executordelay) + P_AddExecutorDelay(ctlsector->lines[i], actor, caller); + else + P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); + } + } + else // walk around the sector in a defined order + { + boolean backwards = false; + size_t j, masterlineindex = (size_t)-1; + + for (i = 0; i < linecnt; i++) + if (ctlsector->lines[i] == triggerline) + { + masterlineindex = i; + break; + } + +#ifdef PARANOIA + if (masterlineindex == (size_t)-1) + { + const size_t li = (size_t)(ctlsector->lines[i] - lines); + I_Error("Line %s isn't linked into its front sector", sizeu1(li)); + } +#endif + + // i == masterlineindex + for (;;) + { + if (backwards) // v2 to v1 + { + for (j = 0; j < linecnt; j++) + { + if (i == j) + continue; + if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v2) + { + i = j; + break; + } + if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v1) + { + i = j; + backwards = false; + break; + } + } + if (j == linecnt) + { + const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes); + CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n", + sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v1->x, ctlsector->lines[i]->v1->y); + return false; // abort + } + } + else // v1 to v2 + { + for (j = 0; j < linecnt; j++) + { + if (i == j) + continue; + if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v1) + { + i = j; + break; + } + if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v2) + { + i = j; + backwards = true; + break; + } + } + if (j == linecnt) + { + const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes); + CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n", + sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v2->x, ctlsector->lines[i]->v2->y); + return false; // abort + } + } + + if (i == masterlineindex) + break; + + if (ctlsector->lines[i]->special >= 400 + && ctlsector->lines[i]->special < 500) + { + if (ctlsector->lines[i]->executordelay) + P_AddExecutorDelay(ctlsector->lines[i], actor, caller); + else + P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); + } + } + } + + // "Trigger on X calls" linedefs reset if noclimb is set + if ((specialtype == 321 || specialtype == 322) && triggerline->flags & ML_NOCLIMB) + triggerline->callcount = sides[triggerline->sidenum[0]].textureoffset>>FRACBITS; + else + // These special types work only once + if (specialtype == 302 // Once + || specialtype == 304 // Ring count - Once + || specialtype == 307 // Character ability - Once + || specialtype == 308 // Race only - Once + || specialtype == 313 // No More Enemies - Once + || specialtype == 315 // No of pushables - Once + || specialtype == 318 // Unlockable trigger - Once + || specialtype == 320 // Unlockable - Once + || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time + || specialtype == 324 // Nightserize - Once + || specialtype == 326 // DeNightserize - Once + || specialtype == 328 // Nights lap - Once + || specialtype == 330 // Nights Bonus Time - Once + || specialtype == 333 // Skin - Once + || specialtype == 336 // Dye - Once + || specialtype == 399) // Level Load + triggerline->special = 0; // Clear it out + + return true; +} + +/** Runs a linedef executor. + * Can be called by: + * - a player moving into a special sector or FOF. + * - a pushable object moving into a special sector or FOF. + * - a ceiling or floor movement from a previous linedef executor finishing. + * - any object in a state with the A_LinedefExecute() action. + * + * \param tag Tag of the linedef executor to run. + * \param actor Object initiating the action; should not be NULL. + * \param caller Sector in which the action was started. May be NULL. + * \sa P_ProcessLineSpecial, P_RunTriggerLinedef + * \author Graue + */ +void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) +{ + size_t masterline; + + CONS_Debug(DBG_GAMELOGIC, "P_LinedefExecute: Executing trigger linedefs of tag %d\n", tag); + + I_Assert(!actor || !P_MobjWasRemoved(actor)); // If actor is there, it must be valid. + + for (masterline = 0; masterline < numlines; masterline++) + { + if (Tag_FGet(&lines[masterline].tags) != tag) + continue; + + // "No More Enemies" and "Level Load" take care of themselves. + if (lines[masterline].special == 313 + || lines[masterline].special == 399 + // Each-time executors handle themselves, too + || lines[masterline].special == 301 // Each time + || lines[masterline].special == 306 // Character ability - Each time + || lines[masterline].special == 310 // CTF Red team - Each time + || lines[masterline].special == 312 // CTF Blue team - Each time + || lines[masterline].special == 322 // Trigger on X calls - Each Time + || lines[masterline].special == 332 // Skin - Each time + || lines[masterline].special == 335)// Dye - Each time + continue; + + if (lines[masterline].special < 300 + || lines[masterline].special > 399) + continue; + + if (!P_RunTriggerLinedef(&lines[masterline], actor, caller)) + return; // cancel P_LinedefExecute if function returns false + } +} + +// +// P_SwitchWeather +// +// Switches the weather! +// +void P_SwitchWeather(INT32 weathernum) +{ + boolean purge = false; + INT32 swap = 0; + + switch (weathernum) + { + case PRECIP_NONE: // None + if (curWeather == PRECIP_NONE) + return; // Nothing to do. + purge = true; + break; + case PRECIP_STORM: // Storm + case PRECIP_STORM_NOSTRIKES: // Storm w/ no lightning + case PRECIP_RAIN: // Rain + if (curWeather == PRECIP_SNOW || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN) + swap = PRECIP_RAIN; + break; + case PRECIP_SNOW: // Snow + if (curWeather == PRECIP_SNOW) + return; // Nothing to do. + if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN) + swap = PRECIP_SNOW; // Need to delete the other precips. + break; + case PRECIP_STORM_NORAIN: // Storm w/o rain + if (curWeather == PRECIP_SNOW + || curWeather == PRECIP_STORM + || curWeather == PRECIP_STORM_NOSTRIKES + || curWeather == PRECIP_RAIN + || curWeather == PRECIP_BLANK) + swap = PRECIP_STORM_NORAIN; + else if (curWeather == PRECIP_STORM_NORAIN) + return; + break; + case PRECIP_BLANK: + if (curWeather == PRECIP_SNOW + || curWeather == PRECIP_STORM + || curWeather == PRECIP_STORM_NOSTRIKES + || curWeather == PRECIP_RAIN) + swap = PRECIP_BLANK; + else if (curWeather == PRECIP_STORM_NORAIN) + swap = PRECIP_BLANK; + else if (curWeather == PRECIP_BLANK) + return; + break; + default: + CONS_Debug(DBG_GAMELOGIC, "P_SwitchWeather: Unknown weather type %d.\n", weathernum); + break; + } + + if (purge) + { + thinker_t *think; + precipmobj_t *precipmobj; + + for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next) + { + if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) + continue; // not a precipmobj thinker + + precipmobj = (precipmobj_t *)think; + + P_RemovePrecipMobj(precipmobj); + } + } + else if (swap && !((swap == PRECIP_BLANK && curWeather == PRECIP_STORM_NORAIN) || (swap == PRECIP_STORM_NORAIN && curWeather == PRECIP_BLANK))) // Rather than respawn all that crap, reuse it! + { + thinker_t *think; + precipmobj_t *precipmobj; + state_t *st; + + for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next) + { + if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) + continue; // not a precipmobj thinker + precipmobj = (precipmobj_t *)think; + + if (swap == PRECIP_RAIN) // Snow To Rain + { + precipmobj->flags = mobjinfo[MT_RAIN].flags; + st = &states[mobjinfo[MT_RAIN].spawnstate]; + precipmobj->state = st; + precipmobj->tics = st->tics; + precipmobj->sprite = st->sprite; + precipmobj->frame = st->frame; + precipmobj->momz = mobjinfo[MT_RAIN].speed; + + precipmobj->precipflags &= ~PCF_INVISIBLE; + + precipmobj->precipflags |= PCF_RAIN; + //think->function.acp1 = (actionf_p1)P_RainThinker; + } + else if (swap == PRECIP_SNOW) // Rain To Snow + { + INT32 z; + + precipmobj->flags = mobjinfo[MT_SNOWFLAKE].flags; + z = M_RandomByte(); + + if (z < 64) + z = 2; + else if (z < 144) + z = 1; + else + z = 0; + + st = &states[mobjinfo[MT_SNOWFLAKE].spawnstate+z]; + precipmobj->state = st; + precipmobj->tics = st->tics; + precipmobj->sprite = st->sprite; + precipmobj->frame = st->frame; + precipmobj->momz = mobjinfo[MT_SNOWFLAKE].speed; + + precipmobj->precipflags &= ~(PCF_INVISIBLE|PCF_RAIN); + + //think->function.acp1 = (actionf_p1)P_SnowThinker; + } + else if (swap == PRECIP_BLANK || swap == PRECIP_STORM_NORAIN) // Remove precip, but keep it around for reuse. + { + //think->function.acp1 = (actionf_p1)P_NullPrecipThinker; + + precipmobj->precipflags |= PCF_INVISIBLE; + } + } + } + + switch (weathernum) + { + case PRECIP_SNOW: // snow + curWeather = PRECIP_SNOW; + + if (!swap) + P_SpawnPrecipitation(); + + break; + case PRECIP_RAIN: // rain + { + boolean dontspawn = false; + + if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) + dontspawn = true; + + curWeather = PRECIP_RAIN; + + if (!dontspawn && !swap) + P_SpawnPrecipitation(); + + break; + } + case PRECIP_STORM: // storm + { + boolean dontspawn = false; + + if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) + dontspawn = true; + + curWeather = PRECIP_STORM; + + if (!dontspawn && !swap) + P_SpawnPrecipitation(); + + break; + } + case PRECIP_STORM_NOSTRIKES: // storm w/o lightning + { + boolean dontspawn = false; + + if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) + dontspawn = true; + + curWeather = PRECIP_STORM_NOSTRIKES; + + if (!dontspawn && !swap) + P_SpawnPrecipitation(); + + break; + } + case PRECIP_STORM_NORAIN: // storm w/o rain + curWeather = PRECIP_STORM_NORAIN; + + if (!swap) + P_SpawnPrecipitation(); + + break; + case PRECIP_BLANK: + curWeather = PRECIP_BLANK; + + if (!swap) + P_SpawnPrecipitation(); + + break; + default: + curWeather = PRECIP_NONE; + break; + } +} + +/** Gets an object. + * + * \param type Object type to look for. + * \param s Sector number to look in. + * \return Pointer to the first ::type found in the sector. + * \sa P_GetPushThing + */ +static mobj_t *P_GetObjectTypeInSectorNum(mobjtype_t type, size_t s) +{ + sector_t *sec = sectors + s; + mobj_t *thing = sec->thinglist; + + while (thing) + { + if (thing->type == type) + return thing; + thing = thing->snext; + } + return NULL; +} + +/** Processes the line special triggered by an object. + * + * \param line Line with the special command on it. + * \param mo mobj that triggered the line. Must be valid and non-NULL. + * \param callsec sector in which action was initiated; this can be NULL. + * Because of the A_LinedefExecute() action, even if non-NULL, + * this sector might not have the same tag as the linedef executor, + * and it might not have the linedef executor sector type. + * \todo Handle mo being NULL gracefully. T_MoveFloor() and T_MoveCeiling() + * don't have an object to pass. + * \todo Split up into multiple functions. + * \sa P_LinedefExecute + * \author Graue + */ +static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) +{ + INT32 secnum = -1; + mobj_t *bot = NULL; + mtag_t tag = Tag_FGet(&line->tags); + + I_Assert(!mo || !P_MobjWasRemoved(mo)); // If mo is there, mo must be valid! + + if (mo && mo->player && botingame) + bot = players[secondarydisplayplayer].mo; + + // note: only commands with linedef types >= 400 && < 500 can be used + switch (line->special) + { + case 400: // Set tagged sector's floor height/pic + EV_DoFloor(line, instantMoveFloorByFrontSector); + break; + + case 401: // Set tagged sector's ceiling height/pic + EV_DoCeiling(line, instantMoveCeilingByFrontSector); + break; + + case 402: // Set tagged sector's light level + { + INT16 newlightlevel; + INT32 newfloorlightsec, newceilinglightsec; + + newlightlevel = line->frontsector->lightlevel; + newfloorlightsec = line->frontsector->floorlightsec; + newceilinglightsec = line->frontsector->ceilinglightsec; + + // act on all sectors with the same tag as the triggering linedef + TAG_ITER_SECTORS(tag, secnum) + { + if (sectors[secnum].lightingdata) + { + // Stop the lighting madness going on in this sector! + P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); + sectors[secnum].lightingdata = NULL; + + // No, it's not an elevator_t, but any struct with a thinker_t named + // 'thinker' at the beginning will do here. (We don't know what it + // actually is: could be lightlevel_t, fireflicker_t, glow_t, etc.) + } + + sectors[secnum].lightlevel = newlightlevel; + sectors[secnum].floorlightsec = newfloorlightsec; + sectors[secnum].ceilinglightsec = newceilinglightsec; + } + } + break; + + case 403: // Move floor, linelen = speed, frontsector floor = dest height + EV_DoFloor(line, moveFloorByFrontSector); + break; + + case 404: // Move ceiling, linelen = speed, frontsector ceiling = dest height + EV_DoCeiling(line, moveCeilingByFrontSector); + break; + + case 405: // Move floor by front side texture offsets, offset x = speed, offset y = amount to raise/lower + EV_DoFloor(line, moveFloorByFrontTexture); + break; + + case 407: // Move ceiling by front side texture offsets, offset x = speed, offset y = amount to raise/lower + EV_DoCeiling(line, moveCeilingByFrontTexture); + break; + +/* case 405: // Lower floor by line, dx = speed, dy = amount to lower + EV_DoFloor(line, lowerFloorByLine); + break; + + case 406: // Raise floor by line, dx = speed, dy = amount to raise + EV_DoFloor(line, raiseFloorByLine); + break; + + case 407: // Lower ceiling by line, dx = speed, dy = amount to lower + EV_DoCeiling(line, lowerCeilingByLine); + break; + + case 408: // Raise ceiling by line, dx = speed, dy = amount to raise + EV_DoCeiling(line, raiseCeilingByLine); + break;*/ + + case 409: // Change tagged sectors' tag + // (formerly "Change calling sectors' tag", but behavior was changed) + { + TAG_ITER_SECTORS(tag, secnum) + Tag_SectorFSet(secnum,(INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS)); + break; + } + + case 410: // Change front sector's tag + Tag_SectorFSet((UINT32)(line->frontsector - sectors), (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS)); + break; + + case 411: // Stop floor/ceiling movement in tagged sector(s) + TAG_ITER_SECTORS(tag, secnum) + { + if (sectors[secnum].floordata) + { + if (sectors[secnum].floordata == sectors[secnum].ceilingdata) // elevator + { + P_RemoveThinker(&((elevator_t *)sectors[secnum].floordata)->thinker); + sectors[secnum].floordata = sectors[secnum].ceilingdata = NULL; + sectors[secnum].floorspeed = sectors[secnum].ceilspeed = 0; + } + else // floormove + { + P_RemoveThinker(&((floormove_t *)sectors[secnum].floordata)->thinker); + sectors[secnum].floordata = NULL; + sectors[secnum].floorspeed = 0; + } + } + + if (sectors[secnum].ceilingdata) // ceiling + { + P_RemoveThinker(&((ceiling_t *)sectors[secnum].ceilingdata)->thinker); + sectors[secnum].ceilingdata = NULL; + sectors[secnum].ceilspeed = 0; + } + } + break; + + case 412: // Teleport the player or thing + { + mobj_t *dest; + + if (!mo) // nothing to teleport + return; + + if (line->flags & ML_EFFECT3) // Relative silent teleport + { + fixed_t x, y, z; + + x = sides[line->sidenum[0]].textureoffset; + y = sides[line->sidenum[0]].rowoffset; + z = line->frontsector->ceilingheight; + + P_UnsetThingPosition(mo); + mo->x += x; + mo->y += y; + mo->z += z; + P_SetThingPosition(mo); + + if (mo->player) + { + if (bot) // This might put poor Tails in a wall if he's too far behind! D: But okay, whatever! >:3 + P_TeleportMove(bot, bot->x + x, bot->y + y, bot->z + z); + if (splitscreen && mo->player == &players[secondarydisplayplayer] && camera2.chase) + { + camera2.x += x; + camera2.y += y; + camera2.z += z; + camera2.subsector = R_PointInSubsector(camera2.x, camera2.y); + } + else if (camera.chase && mo->player == &players[displayplayer]) + { + camera.x += x; + camera.y += y; + camera.z += z; + camera.subsector = R_PointInSubsector(camera.x, camera.y); + } + } + } + else + { + if ((secnum = Tag_Iterate_Sectors(tag, 0)) < 0) + return; + + dest = P_GetObjectTypeInSectorNum(MT_TELEPORTMAN, secnum); + if (!dest) + return; + + if (bot) + P_Teleport(bot, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, (line->flags & ML_BLOCKMONSTERS) == 0, (line->flags & ML_EFFECT4) == ML_EFFECT4); + if (line->flags & ML_BLOCKMONSTERS) + P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, false, (line->flags & ML_EFFECT4) == ML_EFFECT4); + else + { + P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, true, (line->flags & ML_EFFECT4) == ML_EFFECT4); + // Play the 'bowrwoosh!' sound + S_StartSound(dest, sfx_mixup); + } + } + } + break; + + case 413: // Change music + // console player only unless NOCLIMB is set + if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player)) || titlemapinaction) + { + boolean musicsame = (!sides[line->sidenum[0]].text[0] || !strnicmp(sides[line->sidenum[0]].text, S_MusicName(), 7)); + UINT16 tracknum = (UINT16)max(sides[line->sidenum[0]].bottomtexture, 0); + INT32 position = (INT32)max(sides[line->sidenum[0]].midtexture, 0); + UINT32 prefadems = (UINT32)max(sides[line->sidenum[0]].textureoffset >> FRACBITS, 0); + UINT32 postfadems = (UINT32)max(sides[line->sidenum[0]].rowoffset >> FRACBITS, 0); + UINT8 fadetarget = (UINT8)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].textureoffset >> FRACBITS : 0, 0); + INT16 fadesource = (INT16)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].rowoffset >> FRACBITS : -1, -1); + + // Seek offset from current song position + if (line->flags & ML_EFFECT1) + { + // adjust for loop point if subtracting + if (position < 0 && S_GetMusicLength() && + S_GetMusicPosition() > S_GetMusicLoopPoint() && + S_GetMusicPosition() + position < S_GetMusicLoopPoint()) + position = max(S_GetMusicLength() - (S_GetMusicLoopPoint() - (S_GetMusicPosition() + position)), 0); + else + position = max(S_GetMusicPosition() + position, 0); + } + + // Fade current music to target volume (if music won't be changed) + if ((line->flags & ML_EFFECT2) && fadetarget && musicsame) + { + // 0 fadesource means fade from current volume. + // meaning that we can't specify volume 0 as the source volume -- this starts at 1. + if (!fadesource) + fadesource = -1; + + if (!postfadems) + S_SetInternalMusicVolume(fadetarget); + else + S_FadeMusicFromVolume(fadetarget, fadesource, postfadems); + + if (position) + S_SetMusicPosition(position); + } + // Change the music and apply position/fade operations + else + { + strncpy(mapmusname, sides[line->sidenum[0]].text, 7); + mapmusname[6] = 0; + + mapmusflags = tracknum & MUSIC_TRACKMASK; + if (!(line->flags & ML_BLOCKMONSTERS)) + mapmusflags |= MUSIC_RELOADRESET; + if (line->flags & ML_BOUNCY) + mapmusflags |= MUSIC_FORCERESET; + + mapmusposition = position; + + S_ChangeMusicEx(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4), position, + !(line->flags & ML_EFFECT2) ? prefadems : 0, + !(line->flags & ML_EFFECT2) ? postfadems : 0); + + if ((line->flags & ML_EFFECT2) && fadetarget) + { + if (!postfadems) + S_SetInternalMusicVolume(fadetarget); + else + S_FadeMusicFromVolume(fadetarget, fadesource, postfadems); + } + } + + // Except, you can use the ML_BLOCKMONSTERS flag to change this behavior. + // if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn. + } + break; + + case 414: // Play SFX + { + INT32 sfxnum; + + sfxnum = sides[line->sidenum[0]].toptexture; + + if (sfxnum == sfx_None) + return; // Do nothing! + if (sfxnum < sfx_None || sfxnum >= NUMSFX) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 414 Executor: sfx number %d is invalid!\n", sfxnum); + return; + } + + if (tag != 0) // Do special stuff only if a non-zero linedef tag is set + { + // Play sounds from tagged sectors' origins. + if (line->flags & ML_EFFECT5) // Repeat Midtexture + { + // Additionally play the sound from tagged sectors' soundorgs + sector_t *sec; + + TAG_ITER_SECTORS(tag, secnum) + { + sec = §ors[secnum]; + S_StartSound(&sec->soundorg, sfxnum); + } + } + + // Play the sound without origin for anyone, as long as they're inside tagged areas. + else + { + UINT8 i = 0; + mobj_t* camobj = players[displayplayer].mo; + ffloor_t *rover; + boolean foundit = false; + + for (i = 0; i < 2; camobj = players[secondarydisplayplayer].mo, i++) + { + if (!camobj) + continue; + + if (foundit || Tag_Find(&camobj->subsector->sector->tags, tag)) + { + foundit = true; + break; + } + + // Only trigger if mobj is touching the tag + for(rover = camobj->subsector->sector->ffloors; rover; rover = rover->next) + { + if (!Tag_Find(&rover->master->frontsector->tags, tag)) + continue; + + if (camobj->z > P_GetSpecialTopZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) + continue; + + if (camobj->z + camobj->height < P_GetSpecialBottomZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) + continue; + + foundit = true; + break; + } + } + + if (foundit) + S_StartSound(NULL, sfxnum); + } + } + else + { + if (line->flags & ML_NOCLIMB) + { + // play the sound from nowhere, but only if display player triggered it + if (mo && mo->player && (mo->player == &players[displayplayer] || mo->player == &players[secondarydisplayplayer])) + S_StartSound(NULL, sfxnum); + } + else if (line->flags & ML_EFFECT4) + { + // play the sound from nowhere + S_StartSound(NULL, sfxnum); + } + else if (line->flags & ML_BLOCKMONSTERS) + { + // play the sound from calling sector's soundorg + if (callsec) + S_StartSound(&callsec->soundorg, sfxnum); + else if (mo) + S_StartSound(&mo->subsector->sector->soundorg, sfxnum); + } + else if (mo) + { + // play the sound from mobj that triggered it + S_StartSound(mo, sfxnum); + } + } + } + break; + + case 415: // Run a script + if (cv_runscripts.value) + { + INT32 scrnum; + lumpnum_t lumpnum; + char newname[9]; + + strcpy(newname, G_BuildMapName(gamemap)); + newname[0] = 'S'; + newname[1] = 'C'; + newname[2] = 'R'; + + scrnum = sides[line->sidenum[0]].textureoffset>>FRACBITS; + if (scrnum < 0 || scrnum > 999) + { + scrnum = 0; + newname[5] = newname[6] = newname[7] = '0'; + } + else + { + newname[5] = (char)('0' + (char)((scrnum/100))); + newname[6] = (char)('0' + (char)((scrnum%100)/10)); + newname[7] = (char)('0' + (char)(scrnum%10)); + } + newname[8] = '\0'; + + lumpnum = W_CheckNumForName(newname); + + if (lumpnum == LUMPERROR || W_LumpLength(lumpnum) == 0) + { + CONS_Debug(DBG_SETUP, "SOC Error: script lump %s not found/not valid.\n", newname); + } + else + COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE)); + } + break; + + case 416: // Spawn adjustable fire flicker + TAG_ITER_SECTORS(tag, secnum) + { + if (line->flags & ML_NOCLIMB && line->backsector) + { + // Use front sector for min light level, back sector for max. + // This is tricky because P_SpawnAdjustableFireFlicker expects + // the maxsector (second argument) to also be the target + // sector, so we have to do some light level twiddling. + fireflicker_t *flick; + INT16 reallightlevel = sectors[secnum].lightlevel; + sectors[secnum].lightlevel = line->backsector->lightlevel; + + flick = P_SpawnAdjustableFireFlicker(line->frontsector, §ors[secnum], + P_AproxDistance(line->dx, line->dy)>>FRACBITS); + + // Make sure the starting light level is in range. + if (reallightlevel < flick->minlight) + reallightlevel = (INT16)flick->minlight; + else if (reallightlevel > flick->maxlight) + reallightlevel = (INT16)flick->maxlight; + + sectors[secnum].lightlevel = reallightlevel; + } + else + { + // Use front sector for min, target sector for max, + // the same way linetype 61 does it. + P_SpawnAdjustableFireFlicker(line->frontsector, §ors[secnum], + P_AproxDistance(line->dx, line->dy)>>FRACBITS); + } + } + break; + + case 417: // Spawn adjustable glowing light + TAG_ITER_SECTORS(tag, secnum) + { + if (line->flags & ML_NOCLIMB && line->backsector) + { + // Use front sector for min light level, back sector for max. + // This is tricky because P_SpawnAdjustableGlowingLight expects + // the maxsector (second argument) to also be the target + // sector, so we have to do some light level twiddling. + glow_t *glow; + INT16 reallightlevel = sectors[secnum].lightlevel; + sectors[secnum].lightlevel = line->backsector->lightlevel; + + glow = P_SpawnAdjustableGlowingLight(line->frontsector, §ors[secnum], + P_AproxDistance(line->dx, line->dy)>>FRACBITS); + + // Make sure the starting light level is in range. + if (reallightlevel < glow->minlight) + reallightlevel = (INT16)glow->minlight; + else if (reallightlevel > glow->maxlight) + reallightlevel = (INT16)glow->maxlight; + + sectors[secnum].lightlevel = reallightlevel; + } + else + { + // Use front sector for min, target sector for max, + // the same way linetype 602 does it. + P_SpawnAdjustableGlowingLight(line->frontsector, §ors[secnum], + P_AproxDistance(line->dx, line->dy)>>FRACBITS); + } + } + break; + + case 418: // Spawn adjustable strobe flash (unsynchronized) + TAG_ITER_SECTORS(tag, secnum) + { + if (line->flags & ML_NOCLIMB && line->backsector) + { + // Use front sector for min light level, back sector for max. + // This is tricky because P_SpawnAdjustableGlowingLight expects + // the maxsector (second argument) to also be the target + // sector, so we have to do some light level twiddling. + strobe_t *flash; + INT16 reallightlevel = sectors[secnum].lightlevel; + sectors[secnum].lightlevel = line->backsector->lightlevel; + + flash = P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], + abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, false); + + // Make sure the starting light level is in range. + if (reallightlevel < flash->minlight) + reallightlevel = (INT16)flash->minlight; + else if (reallightlevel > flash->maxlight) + reallightlevel = (INT16)flash->maxlight; + + sectors[secnum].lightlevel = reallightlevel; + } + else + { + // Use front sector for min, target sector for max, + // the same way linetype 602 does it. + P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], + abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, false); + } + } + break; + + case 419: // Spawn adjustable strobe flash (synchronized) + TAG_ITER_SECTORS(tag, secnum) + { + if (line->flags & ML_NOCLIMB && line->backsector) + { + // Use front sector for min light level, back sector for max. + // This is tricky because P_SpawnAdjustableGlowingLight expects + // the maxsector (second argument) to also be the target + // sector, so we have to do some light level twiddling. + strobe_t *flash; + INT16 reallightlevel = sectors[secnum].lightlevel; + sectors[secnum].lightlevel = line->backsector->lightlevel; + + flash = P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], + abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, true); + + // Make sure the starting light level is in range. + if (reallightlevel < flash->minlight) + reallightlevel = (INT16)flash->minlight; + else if (reallightlevel > flash->maxlight) + reallightlevel = (INT16)flash->maxlight; + + sectors[secnum].lightlevel = reallightlevel; + } + else + { + // Use front sector for min, target sector for max, + // the same way linetype 602 does it. + P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], + abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, true); + } + } + break; + + case 420: // Fade light levels in tagged sectors to new value + P_FadeLight(tag, + (line->flags & ML_DONTPEGBOTTOM) ? max(sides[line->sidenum[0]].textureoffset>>FRACBITS, 0) : line->frontsector->lightlevel, + // failsafe: if user specifies Back Y Offset and NOT Front Y Offset, use the Back Offset + // to be consistent with other light and fade specials + (line->flags & ML_DONTPEGBOTTOM) ? + ((line->sidenum[1] != 0xFFFF && !(sides[line->sidenum[0]].rowoffset>>FRACBITS)) ? + max(min(sides[line->sidenum[1]].rowoffset>>FRACBITS, 255), 0) + : max(min(sides[line->sidenum[0]].rowoffset>>FRACBITS, 255), 0)) + : abs(P_AproxDistance(line->dx, line->dy))>>FRACBITS, + (line->flags & ML_EFFECT4), + (line->flags & ML_EFFECT5)); + break; + + case 421: // Stop lighting effect in tagged sectors + TAG_ITER_SECTORS(tag, secnum) + if (sectors[secnum].lightingdata) + { + P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); + sectors[secnum].lightingdata = NULL; + } + break; + + case 422: // Cut away to another view + { + mobj_t *altview; + + if ((!mo || !mo->player) && !titlemapinaction) // only players have views, and title screens + return; + + if ((secnum = Tag_Iterate_Sectors(tag, 0)) < 0) + return; + + altview = P_GetObjectTypeInSectorNum(MT_ALTVIEWMAN, secnum); + if (!altview) + return; + + // If titlemap, set the camera ref for title's thinker + // This is not revoked until overwritten; awayviewtics is ignored + if (titlemapinaction) + titlemapcameraref = altview; + else + { + P_SetTarget(&mo->player->awayviewmobj, altview); + mo->player->awayviewtics = P_AproxDistance(line->dx, line->dy)>>FRACBITS; + } + + + if (line->flags & ML_NOCLIMB) // lets you specify a vertical angle + { + INT32 aim; + + aim = sides[line->sidenum[0]].textureoffset>>FRACBITS; + aim = (aim + 360) % 360; + aim *= (ANGLE_90>>8); + aim /= 90; + aim <<= 8; + if (titlemapinaction) + titlemapcameraref->cusval = (angle_t)aim; + else + mo->player->awayviewaiming = (angle_t)aim; + } + else + { + // straight ahead + if (!titlemapinaction) + mo->player->awayviewaiming = 0; + // don't do cusval cause that's annoying + } + } + break; + + case 423: // Change Sky + if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB)) + P_SetupLevelSky(sides[line->sidenum[0]].textureoffset>>FRACBITS, (line->flags & ML_NOCLIMB)); + break; + + case 424: // Change Weather + if (line->flags & ML_NOCLIMB) + { + globalweather = (UINT8)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + P_SwitchWeather(globalweather); + } + else if (mo && mo->player && P_IsLocalPlayer(mo->player)) + P_SwitchWeather(sides[line->sidenum[0]].textureoffset>>FRACBITS); + break; + + case 425: // Calls P_SetMobjState on calling mobj + if (mo && !mo->player) + P_SetMobjState(mo, sides[line->sidenum[0]].toptexture); //P_AproxDistance(line->dx, line->dy)>>FRACBITS); + break; + + case 426: // Moves the mobj to its sector's soundorg and on the floor, and stops it + if (!mo) + return; + + if (line->flags & ML_NOCLIMB) + { + P_UnsetThingPosition(mo); + mo->x = mo->subsector->sector->soundorg.x; + mo->y = mo->subsector->sector->soundorg.y; + mo->z = mo->floorz; + P_SetThingPosition(mo); + } + + mo->momx = mo->momy = mo->momz = 1; + mo->pmomz = 0; + + if (mo->player) + { + mo->player->rmomx = mo->player->rmomy = 1; + mo->player->cmomx = mo->player->cmomy = 0; + P_ResetPlayer(mo->player); + P_SetPlayerMobjState(mo, S_PLAY_STND); + + // Reset bot too. + if (bot) { + if (line->flags & ML_NOCLIMB) + P_TeleportMove(bot, mo->x, mo->y, mo->z); + bot->momx = bot->momy = bot->momz = 1; + bot->pmomz = 0; + bot->player->rmomx = bot->player->rmomy = 1; + bot->player->cmomx = bot->player->cmomy = 0; + P_ResetPlayer(bot->player); + P_SetPlayerMobjState(bot, S_PLAY_STND); + } + } + break; + + case 427: // Awards points if the mobj is a player + if (mo && mo->player) + P_AddPlayerScore(mo->player, sides[line->sidenum[0]].textureoffset>>FRACBITS); + break; + + case 428: // Start floating platform movement + EV_DoElevator(line, elevateContinuous, true); + break; + + case 429: // Crush Ceiling Down Once + EV_DoCrush(line, crushCeilOnce); + break; + + case 430: // Crush Floor Up Once + EV_DoFloor(line, crushFloorOnce); + break; + + case 431: // Crush Floor & Ceiling to middle Once + EV_DoCrush(line, crushBothOnce); + break; + + case 432: // Enable 2D Mode (Disable if noclimb) + if (mo && mo->player) + { + if (line->flags & ML_NOCLIMB) + mo->flags2 &= ~MF2_TWOD; + else + mo->flags2 |= MF2_TWOD; + + // Copy effect to bot if necessary + // (Teleport them to you so they don't break it.) + if (bot && (bot->flags2 & MF2_TWOD) != (mo->flags2 & MF2_TWOD)) { + bot->flags2 = (bot->flags2 & ~MF2_TWOD) | (mo->flags2 & MF2_TWOD); + P_TeleportMove(bot, mo->x, mo->y, mo->z); + } + } + break; + + case 433: // Flip gravity (Flop gravity if noclimb) Works on pushables, too! + if (line->flags & ML_NOCLIMB) + mo->flags2 &= ~MF2_OBJECTFLIP; + else + mo->flags2 |= MF2_OBJECTFLIP; + if (bot) + bot->flags2 = (bot->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); + break; + + case 434: // Custom Power + if (mo && mo->player) + { + mobj_t *dummy = P_SpawnMobj(mo->x, mo->y, mo->z, MT_NULL); + + var1 = sides[line->sidenum[0]].toptexture; //(line->dx>>FRACBITS)-1; + + if (line->sidenum[1] != 0xffff && line->flags & ML_BLOCKMONSTERS) // read power from back sidedef + var2 = sides[line->sidenum[1]].toptexture; + else if (line->flags & ML_NOCLIMB) // 'Infinite' + var2 = UINT16_MAX; + else + var2 = sides[line->sidenum[0]].textureoffset>>FRACBITS; + + P_SetTarget(&dummy->target, mo); + A_CustomPower(dummy); + + if (bot) { + P_SetTarget(&dummy->target, bot); + A_CustomPower(dummy); + } + P_RemoveMobj(dummy); + } + break; + + case 435: // Change scroller direction + { + scroll_t *scroller; + thinker_t *th; + + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + { + if (th->function.acp1 != (actionf_p1)T_Scroll) + continue; + + scroller = (scroll_t *)th; + if (!Tag_Find(§ors[scroller->affectee].tags, tag)) + continue; + + scroller->dx = FixedMul(line->dx>>SCROLL_SHIFT, CARRYFACTOR); + scroller->dy = FixedMul(line->dy>>SCROLL_SHIFT, CARRYFACTOR); + } + } + break; + + case 436: // Shatter block remotely + { + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to crumble + boolean foundrover = false; // for debug, "Can't find a FOF" message + + TAG_ITER_SECTORS(sectag, secnum) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 436 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (Tag_Find(&rover->master->frontsector->tags, foftag)) + { + foundrover = true; + + EV_CrumbleChain(sec, rover); + } + } + + if (!foundrover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 436 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + } + } + break; + + case 437: // Disable Player Controls + if (mo && mo->player) + { + UINT16 fractime = (UINT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + if (fractime < 1) + fractime = 1; //instantly wears off upon leaving + if (line->flags & ML_NOCLIMB) + fractime |= 1<<15; //more crazy &ing, as if music stuff wasn't enough + mo->player->powers[pw_nocontrol] = fractime; + if (bot) + bot->player->powers[pw_nocontrol] = fractime; + } + break; + + case 438: // Set player scale + if (mo) + { + mo->destscale = FixedDiv(P_AproxDistance(line->dx, line->dy), 100<destscale < FRACUNIT/100) + mo->destscale = FRACUNIT/100; + if (mo->player && bot) + bot->destscale = mo->destscale; + } + break; + + case 439: // Set texture + { + size_t linenum; + side_t *set = &sides[line->sidenum[0]], *this; + boolean always = !(line->flags & ML_NOCLIMB); // If noclimb: Only change mid texture if mid texture already exists on tagged lines, etc. + + for (linenum = 0; linenum < numlines; linenum++) + { + if (lines[linenum].special == 439) + continue; // Don't override other set texture lines! + + if (!Tag_Find(&lines[linenum].tags, tag)) + continue; // Find tagged lines + + // Front side + this = &sides[lines[linenum].sidenum[0]]; + if (always || this->toptexture) this->toptexture = set->toptexture; + if (always || this->midtexture) this->midtexture = set->midtexture; + if (always || this->bottomtexture) this->bottomtexture = set->bottomtexture; + + if (lines[linenum].sidenum[1] == 0xffff) + continue; // One-sided stops here. + + // Back side + this = &sides[lines[linenum].sidenum[1]]; + if (always || this->toptexture) this->toptexture = set->toptexture; + if (always || this->midtexture) this->midtexture = set->midtexture; + if (always || this->bottomtexture) this->bottomtexture = set->bottomtexture; + } + } + break; + + case 440: // Play race countdown and start Metal Sonic + if (!metalrecording && !metalplayback) + G_DoPlayMetal(); + break; + + case 441: // Trigger unlockable + if ((!modifiedgame || savemoddata) && !(netgame || multiplayer)) + { + INT32 trigid = (INT32)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + + if (trigid < 0 || trigid > 31) // limited by 32 bit variable + CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", line->sidenum[0], trigid); + else + { + unlocktriggers |= 1 << trigid; + + // Unlocked something? + if (M_UpdateUnlockablesAndExtraEmblems()) + { + S_StartSound(NULL, sfx_s3k68); + G_SaveGameData(); // only save if unlocked something + } + } + } + + // Execute one time only + line->special = 0; + break; + + case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors + { + const mobjtype_t type = (mobjtype_t)sides[line->sidenum[0]].toptexture; + statenum_t state = NUMSTATES; + sector_t *sec; + mobj_t *thing; + + if (line->sidenum[1] != 0xffff) + state = (statenum_t)sides[line->sidenum[1]].toptexture; + + TAG_ITER_SECTORS(tag, secnum) + { + boolean tryagain; + sec = sectors + secnum; + do { + tryagain = false; + for (thing = sec->thinglist; thing; thing = thing->snext) + if (thing->type == type) + { + if (state != NUMSTATES) + { + if (!P_SetMobjState(thing, state)) // set state to specific state + { // mobj was removed + tryagain = true; // snext is corrupt, we'll have to start over. + break; + } + } + else if (!P_SetMobjState(thing, thing->state->nextstate)) // set state to nextstate + { // mobj was removed + tryagain = true; // snext is corrupt, we'll have to start over. + break; + } + } + } while (tryagain); + } + break; + } + + case 443: // Calls a named Lua function + if (line->stringargs[0]) + LUA_HookLinedefExecute(line, mo, callsec); + else + CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in arg0str)\n", sizeu1(line-lines)); + break; + + case 444: // Earthquake camera + { + quake.intensity = sides[line->sidenum[0]].textureoffset; + quake.radius = sides[line->sidenum[0]].rowoffset; + quake.time = P_AproxDistance(line->dx, line->dy)>>FRACBITS; + + quake.epicenter = NULL; /// \todo + + // reasonable defaults. + if (!quake.intensity) + quake.intensity = 8<sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible (or not visible) in + ffloor_t *rover; // FOF to vanish/un-vanish + boolean foundrover = false; // for debug, "Can't find a FOF" message + ffloortype_e oldflags; // store FOF's old flags + + TAG_ITER_SECTORS(sectag, secnum) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 445 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (Tag_Find(&rover->master->frontsector->tags, foftag)) + { + foundrover = true; + + oldflags = rover->flags; + + // Abracadabra! + if (line->flags & ML_NOCLIMB) + rover->flags |= FF_EXISTS; + else + rover->flags &= ~FF_EXISTS; + + // if flags changed, reset sector's light list + if (rover->flags != oldflags) + { + sec->moved = true; + P_RecalcPrecipInSector(sec); + } + } + } + + if (!foundrover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 445 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + } + } + break; + + case 446: // Make block fall remotely (acts like FF_CRUMBLE) + { + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to make fall down + boolean foundrover = false; // for debug, "Can't find a FOF" message + player_t *player = NULL; // player that caused FOF to fall + boolean respawn = true; // should the fallen FOF respawn? + + if (mo) // NULL check + player = mo->player; + + if (line->flags & ML_NOCLIMB) // don't respawn! + respawn = false; + + TAG_ITER_SECTORS(sectag, secnum) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (Tag_Find(&rover->master->frontsector->tags, foftag)) + { + foundrover = true; + + if (line->flags & ML_BLOCKMONSTERS) // FOF flags determine respawn ability instead? + respawn = !(rover->flags & FF_NORETURN) ^ !!(line->flags & ML_NOCLIMB); // no climb inverts + + EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), player, rover->alpha, respawn); + } + } + + if (!foundrover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + } + } + break; + + case 447: // Change colormap of tagged sectors! + // Basically this special applies a colormap to the tagged sectors, just like 606 (the colormap linedef) + // Except it is activated by linedef executor, not level load + // This could even override existing colormaps I believe + // -- Monster Iestyn 14/06/18 + { + extracolormap_t *source; + if (!udmf) + source = sides[line->sidenum[0]].colormap_data; + else + { + if (!line->args[1]) + source = line->frontsector->extra_colormap; + else + { + INT32 sourcesec = Tag_Iterate_Sectors(line->args[1], 0); + if (sourcesec == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 447 Executor: Can't find sector with source colormap (tag %d)!\n", line->args[1]); + return; + } + source = sectors[sourcesec].extra_colormap; + } + } + TAG_ITER_SECTORS(line->args[0], secnum) + { + if (sectors[secnum].colormap_protected) + continue; + + P_ResetColormapFader(§ors[secnum]); + + if (line->args[2] & TMCF_RELATIVE) + { + extracolormap_t *target = (!udmf && (line->flags & ML_TFERLINE) && line->sidenum[1] != 0xFFFF) ? + sides[line->sidenum[1]].colormap_data : sectors[secnum].extra_colormap; // use back colormap instead of target sector + + extracolormap_t *exc = R_AddColormaps( + target, + source, + line->args[2] & TMCF_SUBLIGHTR, + line->args[2] & TMCF_SUBLIGHTG, + line->args[2] & TMCF_SUBLIGHTB, + line->args[2] & TMCF_SUBLIGHTA, + line->args[2] & TMCF_SUBFADER, + line->args[2] & TMCF_SUBFADEG, + line->args[2] & TMCF_SUBFADEB, + line->args[2] & TMCF_SUBFADEA, + line->args[2] & TMCF_SUBFADESTART, + line->args[2] & TMCF_SUBFADEEND, + line->args[2] & TMCF_IGNOREFLAGS, + false); + + if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + sectors[secnum].extra_colormap = exc; + } + else + Z_Free(exc); + } + else + sectors[secnum].extra_colormap = source; + } + break; + } + case 448: // Change skybox viewpoint/centerpoint + if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB)) + { + INT32 viewid = sides[line->sidenum[0]].textureoffset>>FRACBITS; + INT32 centerid = sides[line->sidenum[0]].rowoffset>>FRACBITS; + + if ((line->flags & (ML_EFFECT4|ML_BLOCKMONSTERS)) == ML_EFFECT4) // Solid Midtexture is on but Block Enemies is off? + { + CONS_Alert(CONS_WARNING, + M_GetText("Skybox switch linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), + tag); + } + else + { + // set viewpoint mobj + if (!(line->flags & ML_EFFECT4)) // Solid Midtexture turns off viewpoint setting + { + if (viewid >= 0 && viewid < 16) + skyboxmo[0] = skyboxviewpnts[viewid]; + else + skyboxmo[0] = NULL; + } + + // set centerpoint mobj + if (line->flags & ML_BLOCKMONSTERS) // Block Enemies turns ON centerpoint setting + { + if (centerid >= 0 && centerid < 16) + skyboxmo[1] = skyboxcenterpnts[centerid]; + else + skyboxmo[1] = NULL; + } + } + + CONS_Debug(DBG_GAMELOGIC, "Line type 448 Executor: viewid = %d, centerid = %d, viewpoint? = %s, centerpoint? = %s\n", + viewid, + centerid, + ((line->flags & ML_EFFECT4) ? "no" : "yes"), + ((line->flags & ML_BLOCKMONSTERS) ? "yes" : "no")); + } + break; + + case 449: // Enable bosses with parameter + { + INT32 bossid = sides[line->sidenum[0]].textureoffset>>FRACBITS; + if (bossid & ~15) // if any bits other than first 16 are set + { + CONS_Alert(CONS_WARNING, + M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"), + tag); + break; + } + if (line->flags & ML_NOCLIMB) + { + bossdisabled |= (1<sidenum[0]].textureoffset>>FRACBITS; + INT32 rvalue2 = sides[line->sidenum[0]].rowoffset>>FRACBITS; + INT32 result; + + if (rvalue1 <= rvalue2) + result = P_RandomRange(rvalue1, rvalue2); + else + result = P_RandomRange(rvalue2, rvalue1); + + P_LinedefExecute((INT16)result, mo, NULL); + break; + } + + case 452: // Set FOF alpha + { + INT16 destvalue = line->sidenum[1] != 0xffff ? + (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(P_AproxDistance(line->dx, line->dy)>>FRACBITS); + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to operate + boolean foundrover = false; // for debug, "Can't find a FOF" message + + TAG_ITER_SECTORS(sectag, secnum) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (Tag_Find(&rover->master->frontsector->tags, foftag)) + { + foundrover = true; + + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + // for relative alpha calc + if (!(line->flags & ML_NOCLIMB) && // do translucent + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + + P_RemoveFakeFloorFader(rover); + P_FadeFakeFloor(rover, + rover->alpha, + max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), + 0, // set alpha immediately + false, NULL, // tic-based logic + false, // do not handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // handle FF_TRANSLUCENT + false, // do not handle lighting + false, // do not handle colormap + false, // do not handle collision + false, // do not do ghost fade (no collision during fade) + true); // use exact alpha values (for opengl) + } + } + + if (!foundrover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + } + break; + } + + case 453: // Fade FOF + { + INT16 destvalue = line->sidenum[1] != 0xffff ? + (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(line->dx>>FRACBITS); + INT16 speed = line->sidenum[1] != 0xffff ? + (INT16)(abs(sides[line->sidenum[1]].rowoffset>>FRACBITS)) : (INT16)(abs(line->dy)>>FRACBITS); + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to operate + boolean foundrover = false; // for debug, "Can't find a FOF" message + size_t j = 0; // sec->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc + + TAG_ITER_SECTORS(sectag, secnum) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (Tag_Find(&rover->master->frontsector->tags, foftag)) + { + foundrover = true; + + // Prevent continuous execs from interfering on an existing fade + if (!(line->flags & ML_EFFECT5) + && rover->fadingdata) + //&& ((fade_t*)rover->fadingdata)->timer > (ticbased ? 2 : speed*2)) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Fade FOF thinker already exists, timer: %d\n", ((fade_t*)rover->fadingdata)->timer); + continue; + } + + if (speed > 0) + P_AddFakeFloorFader(rover, secnum, j, + destvalue, + speed, + (line->flags & ML_EFFECT4), // tic-based logic + (line->flags & ML_EFFECT3), // Relative destvalue + !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + !(line->flags & ML_EFFECT2), // do not handle lighting + !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) + !(line->flags & ML_BOUNCY), // do not handle collision + (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) + (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) + else + { + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + // for relative alpha calc + if (!(line->flags & ML_NOCLIMB) && // do translucent + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + + P_RemoveFakeFloorFader(rover); + P_FadeFakeFloor(rover, + rover->alpha, + max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), + 0, // set alpha immediately + false, NULL, // tic-based logic + !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + !(line->flags & ML_EFFECT2), // do not handle lighting + !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) + !(line->flags & ML_BOUNCY), // do not handle collision + (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) + (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) + } + } + j++; + } + + if (!foundrover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + } + break; + } + + case 454: // Stop fading FOF + { + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to operate + boolean foundrover = false; // for debug, "Can't find a FOF" message + + TAG_ITER_SECTORS(sectag, secnum) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (Tag_Find(&rover->master->frontsector->tags, foftag)) + { + foundrover = true; + + P_ResetFakeFloorFader(rover, NULL, + !(line->flags & ML_BLOCKMONSTERS)); // do not finalize collision flags + } + } + + if (!foundrover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + } + break; + } + + case 455: // Fade colormap + { + extracolormap_t *dest; + if (!udmf) + dest = sides[line->sidenum[0]].colormap_data; + else + { + if (!line->args[1]) + dest = line->frontsector->extra_colormap; + else + { + INT32 destsec = Tag_Iterate_Sectors(line->args[1], 0); + if (destsec == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Can't find sector with destination colormap (tag %d)!\n", line->args[1]); + return; + } + dest = sectors[destsec].extra_colormap; + } + } + + TAG_ITER_SECTORS(line->args[0], secnum) + { + extracolormap_t *source_exc, *dest_exc, *exc; + + if (sectors[secnum].colormap_protected) + continue; + + // Don't interrupt ongoing fade + if (!(line->args[3] & TMCF_OVERRIDE) + && sectors[secnum].fadecolormapdata) + //&& ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer > (ticbased ? 2 : speed*2)) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Fade color thinker already exists, timer: %d\n", ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer); + continue; + } + + if (!udmf && (line->flags & ML_TFERLINE)) // use back colormap instead of target sector + sectors[secnum].extra_colormap = (line->sidenum[1] != 0xFFFF) ? + sides[line->sidenum[1]].colormap_data : NULL; + + exc = sectors[secnum].extra_colormap; + + if (!(line->args[3] & TMCF_FROMBLACK) // Override fade from default rgba + && !R_CheckDefaultColormap(dest, true, false, false) + && R_CheckDefaultColormap(exc, true, false, false)) + { + exc = R_CopyColormap(exc, false); + exc->rgba = R_GetRgbaRGB(dest->rgba) + R_PutRgbaA(R_GetRgbaA(exc->rgba)); + //exc->fadergba = R_GetRgbaRGB(dest->rgba) + R_PutRgbaA(R_GetRgbaA(exc->fadergba)); + + if (!(source_exc = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + source_exc = exc; + } + else + Z_Free(exc); + + sectors[secnum].extra_colormap = source_exc; + } + else + source_exc = exc ? exc : R_GetDefaultColormap(); + + if (line->args[3] & TMCF_RELATIVE) + { + exc = R_AddColormaps( + source_exc, + dest, + line->args[3] & TMCF_SUBLIGHTR, + line->args[3] & TMCF_SUBLIGHTG, + line->args[3] & TMCF_SUBLIGHTB, + line->args[3] & TMCF_SUBLIGHTA, + line->args[3] & TMCF_SUBFADER, + line->args[3] & TMCF_SUBFADEG, + line->args[3] & TMCF_SUBFADEB, + line->args[3] & TMCF_SUBFADEA, + line->args[3] & TMCF_SUBFADESTART, + line->args[3] & TMCF_SUBFADEEND, + line->args[3] & TMCF_IGNOREFLAGS, + false); + } + else + exc = R_CopyColormap(dest, false); + + if (!(dest_exc = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + dest_exc = exc; + } + else + Z_Free(exc); + + Add_ColormapFader(§ors[secnum], source_exc, dest_exc, true, // tic-based timing + line->args[2]); + } + break; + } + case 456: // Stop fade colormap + TAG_ITER_SECTORS(line->args[0], secnum) + P_ResetColormapFader(§ors[secnum]); + break; + + case 457: // Track mobj angle to point + if (mo) + { + INT32 failureangle = FixedAngle((min(max(abs(sides[line->sidenum[0]].textureoffset>>FRACBITS), 0), 360))*FRACUNIT); + INT32 failuredelay = abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); + INT32 failureexectag = line->sidenum[1] != 0xffff ? + (INT32)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : 0; + boolean persist = (line->flags & ML_EFFECT2); + mobj_t *anchormo; + + if ((secnum = Tag_Iterate_Sectors(tag, 0)) < 0) + return; + + anchormo = P_GetObjectTypeInSectorNum(MT_ANGLEMAN, secnum); + if (!anchormo) + return; + + mo->eflags |= MFE_TRACERANGLE; + P_SetTarget(&mo->tracer, anchormo); + mo->lastlook = persist; // don't disable behavior after first failure + mo->extravalue1 = failureangle; // angle to exceed for failure state + mo->extravalue2 = failureexectag; // exec tag for failure state (angle is not within range) + mo->cusval = mo->cvmem = failuredelay; // cusval = tics to allow failure before line trigger; cvmem = decrement timer + } + break; + + case 458: // Stop tracking mobj angle to point + if (mo && (mo->eflags & MFE_TRACERANGLE)) + { + mo->eflags &= ~MFE_TRACERANGLE; + P_SetTarget(&mo->tracer, NULL); + mo->lastlook = mo->cvmem = mo->cusval = mo->extravalue1 = mo->extravalue2 = 0; + } + break; + + case 459: // Control Text Prompt + // console player only unless NOCLIMB is set + if (mo && mo->player && P_IsLocalPlayer(mo->player) && (!bot || bot != mo)) + { + INT32 promptnum = max(0, (sides[line->sidenum[0]].textureoffset>>FRACBITS)-1); + INT32 pagenum = max(0, (sides[line->sidenum[0]].rowoffset>>FRACBITS)-1); + INT32 postexectag = abs((line->sidenum[1] != 0xFFFF) ? sides[line->sidenum[1]].textureoffset>>FRACBITS : tag); + + boolean closetextprompt = (line->flags & ML_BLOCKMONSTERS); + //boolean allplayers = (line->flags & ML_NOCLIMB); + boolean runpostexec = (line->flags & ML_EFFECT1); + boolean blockcontrols = !(line->flags & ML_EFFECT2); + boolean freezerealtime = !(line->flags & ML_EFFECT3); + //boolean freezethinkers = (line->flags & ML_EFFECT4); + boolean callbynamedtag = (line->flags & ML_TFERLINE); + + if (closetextprompt) + F_EndTextPrompt(false, false); + else + { + if (callbynamedtag && sides[line->sidenum[0]].text && sides[line->sidenum[0]].text[0]) + F_GetPromptPageByNamedTag(sides[line->sidenum[0]].text, &promptnum, &pagenum); + F_StartTextPrompt(promptnum, pagenum, mo, runpostexec ? postexectag : 0, blockcontrols, freezerealtime); + } + } + break; + + case 460: // Award rings + { + INT16 rings = (sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT32 delay = (sides[line->sidenum[0]].rowoffset>>FRACBITS); + if (mo && mo->player) + { + if (delay <= 0 || !(leveltime % delay)) + P_GivePlayerRings(mo->player, rings); + } + } + break; + + case 461: // Spawns an object on the map based on texture offsets + { + const mobjtype_t type = (mobjtype_t)(sides[line->sidenum[0]].toptexture); + mobj_t *mobj; + + fixed_t x, y, z; + x = sides[line->sidenum[0]].textureoffset; + y = sides[line->sidenum[0]].rowoffset; + z = line->frontsector->floorheight; + + if (line->flags & ML_NOCLIMB) // If noclimb is set, spawn randomly within a range + { + if (line->sidenum[1] != 0xffff) // Make sure the linedef has a back side + { + x = P_RandomRange(sides[line->sidenum[0]].textureoffset>>FRACBITS, sides[line->sidenum[1]].textureoffset>>FRACBITS)<sidenum[0]].rowoffset>>FRACBITS, sides[line->sidenum[1]].rowoffset>>FRACBITS)<frontsector->floorheight>>FRACBITS, line->frontsector->ceilingheight>>FRACBITS)<special); + break; + } + } + + mobj = P_SpawnMobj(x, y, z, type); + if (mobj) + { + if (line->flags & ML_EFFECT1) + mobj->angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); + CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow. + } + else + CONS_Alert(CONS_ERROR,"Linedef Type %d - Spawn Object: Object did not spawn!\n", line->special); + } + break; + + case 462: // Stop clock (and end level in record attack) + if (G_PlatformGametype()) + { + stoppedclock = true; + CONS_Debug(DBG_GAMELOGIC, "Clock stopped!\n"); + if (modeattacking) + { + UINT8 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + P_DoPlayerExit(&players[i]); + } + } + } + break; + + case 463: // Dye object + { + INT32 color = sides[line->sidenum[0]].toptexture; + + if (mo) + { + if (color < 0 || color >= numskincolors) + return; + + var1 = 0; + var2 = color; + A_Dye(mo); + } + } + break; + + case 464: // Trigger Egg Capsule + { + thinker_t *th; + mobj_t *mo2; + + // Find the center of the Eggtrap and release all the pretty animals! + // The chimps are my friends.. heeheeheheehehee..... - LouisJM + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_EGGTRAP) + continue; + + if (!mo2->spawnpoint) + continue; + + if (mo2->spawnpoint->angle != tag) + continue; + + P_KillMobj(mo2, NULL, mo, 0); + } + + if (!(line->flags & ML_NOCLIMB)) + { + INT32 i; + + // Mark all players with the time to exit thingy! + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + P_DoPlayerExit(&players[i]); + } + } + } + break; + + case 465: // Set linedef executor delay + { + INT32 linenum; + + if (!udmf) + break; + + TAG_ITER_LINES(line->args[0], linenum) + { + if (line->args[2]) + lines[linenum].executordelay += line->args[1]; + else + lines[linenum].executordelay = line->args[1]; + } + } + break; + + case 466: // Set level failure state + { + if (line->flags & ML_NOCLIMB) + { + stagefailed = false; + CONS_Debug(DBG_GAMELOGIC, "Stage can be completed successfully!\n"); + } + else + { + stagefailed = true; + CONS_Debug(DBG_GAMELOGIC, "Stage will end in failure...\n"); + } + } + break; + + case 480: // Polyobj_DoorSlide + case 481: // Polyobj_DoorSwing + PolyDoor(line); + break; + case 482: // Polyobj_Move + case 483: // Polyobj_OR_Move + PolyMove(line); + break; + case 484: // Polyobj_RotateRight + case 485: // Polyobj_OR_RotateRight + case 486: // Polyobj_RotateLeft + case 487: // Polyobj_OR_RotateLeft + PolyRotate(line); + break; + case 488: // Polyobj_Waypoint + PolyWaypoint(line); + break; + case 489: + PolyInvisible(line); + break; + case 490: + PolyVisible(line); + break; + case 491: + PolyTranslucency(line); + break; + case 492: + PolyFade(line); + break; + + default: + break; + } +} + +// +// P_SetupSignExit +// +// Finds the exit sign in the current sector and +// sets its target to the player who passed the map. +// +void P_SetupSignExit(player_t *player) +{ + mobj_t *thing; + msecnode_t *node = player->mo->subsector->sector->touching_thinglist; // things touching this sector + thinker_t *think; + INT32 numfound = 0; + + for (; node; node = node->m_thinglist_next) + { + thing = node->m_thing; + if (thing->type != MT_SIGN) + continue; + + if (!numfound + && !(player->mo->target && player->mo->target->type == MT_SIGN) + && !((gametyperules & GTR_FRIENDLY) && (netgame || multiplayer) && cv_exitmove.value)) + P_SetTarget(&player->mo->target, thing); + + if (thing->state != &states[thing->info->spawnstate]) + continue; + + P_SetTarget(&thing->target, player->mo); + P_SetObjectMomZ(thing, 12*FRACUNIT, false); + P_SetMobjState(thing, S_SIGNSPIN1); + if (thing->info->seesound) + S_StartSound(thing, thing->info->seesound); + + ++numfound; + } + + if (numfound) + return; + + // didn't find any signposts in the exit sector. + // spin all signposts in the level then. + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) + { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + thing = (mobj_t *)think; + if (thing->type != MT_SIGN) + continue; + + if (!numfound + && !(player->mo->target && player->mo->target->type == MT_SIGN) + && !((gametyperules & GTR_FRIENDLY) && (netgame || multiplayer) && cv_exitmove.value)) + P_SetTarget(&player->mo->target, thing); + + if (thing->state != &states[thing->info->spawnstate]) + continue; + + P_SetTarget(&thing->target, player->mo); + P_SetObjectMomZ(thing, 12*FRACUNIT, false); + P_SetMobjState(thing, S_SIGNSPIN1); + if (thing->info->seesound) + S_StartSound(thing, thing->info->seesound); + + ++numfound; + } +} + +// +// P_IsFlagAtBase +// +// Checks to see if a flag is at its base. +// +boolean P_IsFlagAtBase(mobjtype_t flag) +{ + thinker_t *think; + mobj_t *mo; + INT32 specialnum = (flag == MT_REDFLAG) ? 3 : 4; + + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) + { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo = (mobj_t *)think; + + if (mo->type != flag) + continue; + + if (GETSECSPECIAL(mo->subsector->sector->special, 4) == specialnum) + return true; + else if (mo->subsector->sector->ffloors) // Check the 3D floors + { + ffloor_t *rover; + + for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + if (GETSECSPECIAL(rover->master->frontsector->special, 4) != specialnum) + continue; + + if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) + && mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector))) + continue; + + return true; + } + } + } + return false; +} + +// +// P_PlayerTouchingSectorSpecial +// +// Replaces the old player->specialsector. +// This allows a player to touch more than +// one sector at a time, if necessary. +// +// Returns a pointer to the first sector of +// the particular type that it finds. +// Returns NULL if it doesn't find it. +// +sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number) +{ + msecnode_t *node; + ffloor_t *rover; + + if (!player->mo) + return NULL; + + // Check default case first + if (GETSECSPECIAL(player->mo->subsector->sector->special, section) == number) + return player->mo->subsector->sector; + + // Hmm.. maybe there's a FOF that has it... + for (rover = player->mo->subsector->sector->ffloors; rover; rover = rover->next) + { + fixed_t topheight, bottomheight; + + if (GETSECSPECIAL(rover->master->frontsector->special, section) != number) + continue; + + if (!(rover->flags & FF_EXISTS)) + continue; + + topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); + bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); + + // Check the 3D floor's type... + if (rover->flags & FF_BLOCKPLAYER) + { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); + // Thing must be on top of the floor to be affected... + if (!(floorallowed || ceilingallowed)) + continue; + } + else + { + // Water and DEATH FOG!!! heh + if (player->mo->z > topheight || (player->mo->z + player->mo->height) < bottomheight) + continue; + } + + // This FOF has the special we're looking for! + return rover->master->frontsector; + } + + for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (GETSECSPECIAL(node->m_sector->special, section) == number) + { + // This sector has the special we're looking for, but + // are we allowed to touch it? + if (node->m_sector == player->mo->subsector->sector + || (node->m_sector->flags & SF_TRIGGERSPECIAL_TOUCH)) + return node->m_sector; + } + + // Hmm.. maybe there's a FOF that has it... + for (rover = node->m_sector->ffloors; rover; rover = rover->next) + { + fixed_t topheight, bottomheight; + + if (GETSECSPECIAL(rover->master->frontsector->special, section) != number) + continue; + + if (!(rover->flags & FF_EXISTS)) + continue; + + topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); + bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); + + // Check the 3D floor's type... + if (rover->flags & FF_BLOCKPLAYER) + { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); + // Thing must be on top of the floor to be affected... + if (!(floorallowed || ceilingallowed)) + continue; + } + else + { + // Water and DEATH FOG!!! heh + if (player->mo->z > topheight || (player->mo->z + player->mo->height) < bottomheight) + continue; + } + + // This FOF has the special we're looking for, but are we allowed to touch it? + if (node->m_sector == player->mo->subsector->sector + || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + return rover->master->frontsector; + } + } + + return NULL; +} + +// +// P_ThingIsOnThe3DFloor +// +// This checks whether the mobj is on/in the FOF we want it to be at +// Needed for the "All players" trigger sector specials only +// +static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *targetsec) +{ + ffloor_t *rover; + fixed_t top, bottom; + + if (!mo->player) // should NEVER happen + return false; + + if (!targetsec->ffloors) // also should NEVER happen + return false; + + for (rover = targetsec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector != sector) + continue; + + // we're assuming the FOF existed when the first player touched it + //if (!(rover->flags & FF_EXISTS)) + // return false; + + top = P_GetSpecialTopZ(mo, sector, targetsec); + bottom = P_GetSpecialBottomZ(mo, sector, targetsec); + + // Check the 3D floor's type... + if (rover->flags & FF_BLOCKPLAYER) + { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == top)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottom)); + // Thing must be on top of the floor to be affected... + if (!(floorallowed || ceilingallowed)) + continue; + } + else + { + // Water and intangible FOFs + if (mo->z > top || (mo->z + mo->height) < bottom) + return false; + } + + return true; + } + + return false; +} + +// +// P_MobjReadyToTrigger +// +// Is player standing on the sector's "ground"? +// +static boolean P_MobjReadyToTrigger(mobj_t *mo, sector_t *sec) +{ + boolean floorallowed = ((sec->flags & SF_FLIPSPECIAL_FLOOR) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == P_GetSpecialBottomZ(mo, sec, sec))); + boolean ceilingallowed = ((sec->flags & SF_FLIPSPECIAL_CEILING) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == P_GetSpecialTopZ(mo, sec, sec))); + // Thing must be on top of the floor to be affected... + return (floorallowed || ceilingallowed); +} + +/** Applies a sector special to a player. + * + * \param player Player in the sector. + * \param sector Sector with the special. + * \param roversector If !NULL, sector is actually an FOF; otherwise, sector + * is being physically contacted by the player. + * \todo Split up into multiple functions. + * \sa P_PlayerInSpecialSector, P_PlayerOnSpecial3DFloor + */ +void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector) +{ + INT32 i = 0; + INT32 section1, section2, section3, section4; + INT32 special; + mtag_t sectag = Tag_FGet(§or->tags); + + section1 = GETSECSPECIAL(sector->special, 1); + section2 = GETSECSPECIAL(sector->special, 2); + section3 = GETSECSPECIAL(sector->special, 3); + section4 = GETSECSPECIAL(sector->special, 4); + + // Ignore spectators + if (player->spectator) + return; + + // Ignore dead players. + // If this strange phenomenon could be potentially used in levels, + // TODO: modify this to accommodate for it. + if (player->playerstate != PST_LIVE) + return; + + // Conveyor stuff + if (section3 == 2 || section3 == 4) + player->onconveyor = section3; + + special = section1; + + // Process Section 1 + switch (special) + { + case 1: // Damage (Generic) + if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + P_DamageMobj(player->mo, NULL, NULL, 1, 0); + break; + case 2: // Damage (Water) + if ((roversector || P_MobjReadyToTrigger(player->mo, sector)) && (player->powers[pw_underwater] || player->powers[pw_carry] == CR_NIGHTSMODE)) + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_WATER); + break; + case 3: // Damage (Fire) + if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_FIRE); + break; + case 4: // Damage (Electrical) + if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_ELECTRIC); + break; + case 5: // Spikes + if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPIKE); + break; + case 6: // Death Pit (Camera Mod) + case 7: // Death Pit (No Camera Mod) + if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + { + if (player->quittime) + G_MovePlayerToSpawnOrStarpost(player - players); + else + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT); + } + break; + case 8: // Instant Kill + if (player->quittime) + G_MovePlayerToSpawnOrStarpost(player - players); + else + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); + break; + case 9: // Ring Drainer (Floor Touch) + case 10: // Ring Drainer (No Floor Touch) + if (leveltime % (TICRATE/2) == 0 && player->rings > 0) + { + player->rings--; + S_StartSound(player->mo, sfx_antiri); + } + break; + case 11: // Special Stage Damage + if (player->exiting || player->bot) // Don't do anything for bots or players who have just finished + break; + + if (!(player->powers[pw_shield] || player->spheres > 0)) // Don't do anything if no shield or spheres anyway + break; + + P_SpecialStageDamage(player, NULL, NULL); + break; + case 12: // Space Countdown + if (!(player->powers[pw_shield] & SH_PROTECTWATER) && !player->powers[pw_spacetime]) + player->powers[pw_spacetime] = spacetimetics + 1; + break; + case 13: // Ramp Sector (Increase step-up/down) + case 14: // Non-Ramp Sector (Don't step-down) + case 15: // Unused + break; + } + + special = section2; + + // Process Section 2 + switch (special) + { + case 1: // Trigger Linedef Exec (Pushable Objects) + break; + case 2: // Linedef executor requires all players present+doesn't require touching floor + case 3: // Linedef executor requires all players present + /// \todo check continues for proper splitscreen support? + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + if (!players[i].mo) + continue; + if (players[i].spectator) + continue; + if (players[i].bot) + continue; + if (G_CoopGametype() && players[i].lives <= 0) + continue; + if (roversector) + { + if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) + { + msecnode_t *node; + for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (P_ThingIsOnThe3DFloor(players[i].mo, sector, node->m_sector)) + break; + } + if (!node) + goto DoneSection2; + } + else if (players[i].mo->subsector && !P_ThingIsOnThe3DFloor(players[i].mo, sector, players[i].mo->subsector->sector)) // this function handles basically everything for us lmao + goto DoneSection2; + } + else + { + if (players[i].mo->subsector->sector == sector) + ; + else if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) + { + msecnode_t *node; + for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (node->m_sector == sector) + break; + } + if (!node) + goto DoneSection2; + } + else + goto DoneSection2; + + if (special == 3 && !P_MobjReadyToTrigger(players[i].mo, sector)) + goto DoneSection2; + } + } + /* FALLTHRU */ + case 4: // Linedef executor that doesn't require touching floor + case 5: // Linedef executor + case 6: // Linedef executor (7 Emeralds) + case 7: // Linedef executor (NiGHTS Mare) + if (!player->bot) + P_LinedefExecute(sectag, player->mo, sector); + break; + case 8: // Tells pushable things to check FOFs + break; + case 9: // Egg trap capsule + { + thinker_t *th; + mobj_t *mo2; + line_t junk; + + if (player->bot || sector->ceilingdata || sector->floordata) + return; + + // Find the center of the Eggtrap and release all the pretty animals! + // The chimps are my friends.. heeheeheheehehee..... - LouisJM + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; + if (mo2->type != MT_EGGTRAP) + continue; + P_KillMobj(mo2, NULL, player->mo, 0); + } + + // clear the special so you can't push the button twice. + sector->special = 0; + + // Initialize my junk + junk.tags.tags = NULL; + junk.tags.count = 0; + + // Move the button down + Tag_FSet(&junk.tags, LE_CAPSULE0); + EV_DoElevator(&junk, elevateDown, false); + + // Open the top FOF + Tag_FSet(&junk.tags, LE_CAPSULE1); + EV_DoFloor(&junk, raiseFloorToNearestFast); + // Open the bottom FOF + Tag_FSet(&junk.tags, LE_CAPSULE2); + EV_DoCeiling(&junk, lowerToLowestFast); + + // Mark all players with the time to exit thingy! + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + P_DoPlayerExit(&players[i]); + } + break; + } + case 10: // Special Stage Time/Rings + case 11: // Custom Gravity + break; + case 12: // Lua sector special + break; + } +DoneSection2: + + special = section3; + + // Process Section 3 + switch (special) + { + case 1: // Unused + case 2: // Wind/Current + case 3: // Unused + case 4: // Conveyor Belt + break; + + case 5: // Speed pad + if (player->powers[pw_flashing] != 0 && player->powers[pw_flashing] < TICRATE/2) + break; + + i = Tag_FindLineSpecial(4, sectag); + + if (i != -1) + { + angle_t lineangle; + fixed_t linespeed; + fixed_t sfxnum; + + lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); + linespeed = sides[lines[i].sidenum[0]].textureoffset; + + if (linespeed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Speed pad (tag %d) at zero speed.\n", sectag); + break; + } + + player->mo->angle = player->drawangle = lineangle; + + if (!demoplayback || P_ControlStyle(player) == CS_LMAOGALOG) + P_SetPlayerAngle(player, player->mo->angle); + + if (!(lines[i].flags & ML_EFFECT4)) + { + P_UnsetThingPosition(player->mo); + if (roversector) // make FOF speed pads work + { + player->mo->x = roversector->soundorg.x; + player->mo->y = roversector->soundorg.y; + } + else + { + player->mo->x = sector->soundorg.x; + player->mo->y = sector->soundorg.y; + } + P_SetThingPosition(player->mo); + } + + P_InstaThrust(player->mo, player->mo->angle, linespeed); + + if (lines[i].flags & ML_EFFECT5) // Roll! + { + if (!(player->pflags & PF_SPINNING)) + player->pflags |= PF_SPINNING; + + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + } + + player->powers[pw_flashing] = TICRATE/3; + + sfxnum = sides[lines[i].sidenum[0]].toptexture; + + if (!sfxnum) + sfxnum = sfx_spdpad; + + S_StartSound(player->mo, sfxnum); + } + break; + + case 6: // Unused + case 7: // Unused + case 8: // Unused + case 9: // Unused + case 10: // Unused + case 11: // Unused + case 12: // Unused + case 13: // Unused + case 14: // Unused + case 15: // Unused + break; + } + + special = section4; + + // Process Section 4 + switch (special) + { + case 1: // Starpost Activator + { + mobj_t *post = P_GetObjectTypeInSectorNum(MT_STARPOST, sector - sectors); + + if (!post) + break; + + P_TouchStarPost(post, player, false); + break; + } + + case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return + if (player->bot || !(gametyperules & GTR_ALLOWEXIT)) + break; + if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6) + { + player->nightstime = 6; // Just let P_Ticker take care of the rest. + return; + } + + // Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c) + { + INT32 lineindex; + + P_DoPlayerFinish(player); + + P_SetupSignExit(player); + // important: use sector->tag on next line instead of player->mo->subsector->tag + // this part is different from in P_PlayerThink, this is what was causing + // FOF custom exits not to work. + lineindex = Tag_FindLineSpecial(2, sectag); + + if (G_CoopGametype() && lineindex != -1) // Custom exit! + { + // Special goodies with the block monsters flag depending on emeralds collected + if ((lines[lineindex].flags & ML_BLOCKMONSTERS) && ALL7EMERALDS(emeralds)) + nextmapoverride = (INT16)(lines[lineindex].frontsector->ceilingheight>>FRACBITS); + else + nextmapoverride = (INT16)(lines[lineindex].frontsector->floorheight>>FRACBITS); + + if (lines[lineindex].flags & ML_NOCLIMB) + skipstats = 1; + } + } + break; + + case 3: // Red Team's Base + if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo)) + { + if (player->ctfteam == 1 && (player->gotflag & GF_BLUEFLAG)) + { + mobj_t *mo; + + // Make sure the red team still has their own + // flag at their base so they can score. + if (!P_IsFlagAtBase(MT_REDFLAG)) + break; + + HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE); + HU_SetCEchoDuration(5); + HU_DoCEcho(va(M_GetText("\205%s\200\\CAPTURED THE \204BLUE FLAG\200.\\\\\\\\"), player_names[player-players])); + + if (splitscreen || players[consoleplayer].ctfteam == 1) + S_StartSound(NULL, sfx_flgcap); + else if (players[consoleplayer].ctfteam == 2) + S_StartSound(NULL, sfx_lose); + + mo = P_SpawnMobj(player->mo->x,player->mo->y,player->mo->z,MT_BLUEFLAG); + player->gotflag &= ~GF_BLUEFLAG; + mo->flags &= ~MF_SPECIAL; + mo->fuse = TICRATE; + mo->spawnpoint = bflagpoint; + mo->flags2 |= MF2_JUSTATTACKED; + redscore += 1; + P_AddPlayerScore(player, 250); + } + } + break; + + case 4: // Blue Team's Base + if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo)) + { + if (player->ctfteam == 2 && (player->gotflag & GF_REDFLAG)) + { + mobj_t *mo; + + // Make sure the blue team still has their own + // flag at their base so they can score. + if (!P_IsFlagAtBase(MT_BLUEFLAG)) + break; + + HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE); + HU_SetCEchoDuration(5); + HU_DoCEcho(va(M_GetText("\204%s\200\\CAPTURED THE \205RED FLAG\200.\\\\\\\\"), player_names[player-players])); + + if (splitscreen || players[consoleplayer].ctfteam == 2) + S_StartSound(NULL, sfx_flgcap); + else if (players[consoleplayer].ctfteam == 1) + S_StartSound(NULL, sfx_lose); + + mo = P_SpawnMobj(player->mo->x,player->mo->y,player->mo->z,MT_REDFLAG); + player->gotflag &= ~GF_REDFLAG; + mo->flags &= ~MF_SPECIAL; + mo->fuse = TICRATE; + mo->spawnpoint = rflagpoint; + mo->flags2 |= MF2_JUSTATTACKED; + bluescore += 1; + P_AddPlayerScore(player, 250); + } + } + break; + + case 5: // Fan sector + player->mo->momz += mobjinfo[MT_FAN].mass/4; + + if (player->mo->momz > mobjinfo[MT_FAN].mass) + player->mo->momz = mobjinfo[MT_FAN].mass; + + P_ResetPlayer(player); + if (player->panim != PA_FALL) + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + break; + + case 6: // Super Sonic transformer + if (player->mo->health > 0 && !player->bot && (player->charflags & SF_SUPER) && !player->powers[pw_super] && ALL7EMERALDS(emeralds)) + P_DoSuperTransformation(player, true); + break; + + case 7: // Make player spin + if (!(player->pflags & PF_SPINNING)) + { + player->pflags |= PF_SPINNING; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartAttackSound(player->mo, sfx_spin); + + if (abs(player->rmomx) < FixedMul(5*FRACUNIT, player->mo->scale) + && abs(player->rmomy) < FixedMul(5*FRACUNIT, player->mo->scale)) + P_InstaThrust(player->mo, player->mo->angle, FixedMul(10*FRACUNIT, player->mo->scale)); + } + break; + + case 8: // Zoom Tube Start + { + INT32 sequence; + fixed_t speed; + INT32 lineindex; + mobj_t *waypoint = NULL; + angle_t an; + + if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) + break; + + if (player->powers[pw_ignorelatch] & (1<<15)) + break; + + // Find line #3 tagged to this sector + lineindex = Tag_FindLineSpecial(3, sectag); + + if (lineindex == -1) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #3.\n", sector->special); + break; + } + + // Grab speed and sequence values + speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; + sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; + + if (speed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); + break; + } + + waypoint = P_GetFirstWaypoint(sequence); + + if (!waypoint) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: FIRST WAYPOINT IN SEQUENCE %d NOT FOUND.\n", sequence); + break; + } + else + { + CONS_Debug(DBG_GAMELOGIC, "Waypoint %d found in sequence %d - speed = %d\n", waypoint->health, sequence, speed); + } + + an = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->x, waypoint->y) - player->mo->angle; + + if (an > ANGLE_90 && an < ANGLE_270 && !(lines[lineindex].flags & ML_EFFECT4)) + break; // behind back + + P_SetTarget(&player->mo->tracer, waypoint); + player->powers[pw_carry] = CR_ZOOMTUBE; + player->speed = speed; + player->pflags |= PF_SPINNING; + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); + player->climbing = 0; + + if (player->mo->state-states != S_PLAY_ROLL) + { + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_spin); + } + } + break; + + case 9: // Zoom Tube End + { + INT32 sequence; + fixed_t speed; + INT32 lineindex; + mobj_t *waypoint = NULL; + angle_t an; + + if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) + break; + + if (player->powers[pw_ignorelatch] & (1<<15)) + break; + + // Find line #3 tagged to this sector + lineindex = Tag_FindLineSpecial(3, sectag); + + if (lineindex == -1) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #3.\n", sector->special); + break; + } + + // Grab speed and sequence values + speed = -abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; // Negative means reverse + sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; + + if (speed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); + break; + } + + waypoint = P_GetLastWaypoint(sequence); + + if (!waypoint) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: LAST WAYPOINT IN SEQUENCE %d NOT FOUND.\n", sequence); + break; + } + else + { + CONS_Debug(DBG_GAMELOGIC, "Waypoint %d found in sequence %d - speed = %d\n", waypoint->health, sequence, speed); + } + + an = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->x, waypoint->y) - player->mo->angle; + + if (an > ANGLE_90 && an < ANGLE_270 && !(lines[lineindex].flags & ML_EFFECT4)) + break; // behind back + + P_SetTarget(&player->mo->tracer, waypoint); + player->powers[pw_carry] = CR_ZOOMTUBE; + player->speed = speed; + player->pflags |= PF_SPINNING; + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); + player->climbing = 0; + + if (player->mo->state-states != S_PLAY_ROLL) + { + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_spin); + } + } + break; + + case 10: // Finish Line + if (((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE) && !player->exiting) + { + if (player->starpostnum == numstarposts) // Must have touched all the starposts + { + player->laps++; + + if (player->powers[pw_carry] == CR_NIGHTSMODE) + player->drillmeter += 48*20; + + if (player->laps >= (UINT8)cv_numlaps.value) + CONS_Printf(M_GetText("%s has finished the race.\n"), player_names[player-players]); + else if (player->laps == (UINT8)cv_numlaps.value-1) + CONS_Printf(M_GetText("%s started the \205final lap\200!\n"), player_names[player-players]); + else + CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1); + + // Reset starposts (checkpoints) info + player->starpostscale = player->starpostangle = player->starposttime = player->starpostnum = 0; + player->starpostx = player->starposty = player->starpostz = 0; + P_ResetStarposts(); + + // Play the starpost sound for 'consistency' + S_StartSound(player->mo, sfx_strpst); + } + else if (player->starpostnum) + { + // blatant reuse of a variable that's normally unused in circuit + if (!player->tossdelay) + S_StartSound(player->mo, sfx_lose); + player->tossdelay = 3; + } + + if (player->laps >= (unsigned)cv_numlaps.value) + { + if (P_IsLocalPlayer(player)) + { + HU_SetCEchoFlags(0); + HU_SetCEchoDuration(5); + HU_DoCEcho("FINISHED!"); + } + + P_DoPlayerExit(player); + } + } + break; + + case 11: // Rope hang + { + INT32 sequence; + fixed_t speed; + INT32 lineindex; + mobj_t *waypointmid = NULL; + mobj_t *waypointhigh = NULL; + mobj_t *waypointlow = NULL; + mobj_t *closest = NULL; + vector3_t p, line[2], resulthigh, resultlow; + + if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG) + break; + + if (player->powers[pw_ignorelatch] & (1<<15)) + break; + + if (player->mo->momz > 0) + break; + + if (player->cmd.buttons & BT_SPIN) + break; + + if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate]) + break; + + if (player->exiting) + break; + + //initialize resulthigh and resultlow with 0 + memset(&resultlow, 0x00, sizeof(resultlow)); + memset(&resulthigh, 0x00, sizeof(resulthigh)); + + // Find line #11 tagged to this sector + lineindex = Tag_FindLineSpecial(11, sectag); + + if (lineindex == -1) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #11.\n", sector->special); + break; + } + + // Grab speed and sequence values + speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; + sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; + + if (speed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); + break; + } + + // Find the closest waypoint + // Find the preceding waypoint + // Find the proceeding waypoint + // Determine the closest spot on the line between the three waypoints + // Put player at that location. + + waypointmid = P_GetClosestWaypoint(sequence, player->mo); + + if (!waypointmid) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: WAYPOINT(S) IN SEQUENCE %d NOT FOUND.\n", sequence); + break; + } + + waypointlow = P_GetPreviousWaypoint(waypointmid, true); + waypointhigh = P_GetNextWaypoint(waypointmid, true); + + CONS_Debug(DBG_GAMELOGIC, "WaypointMid: %d; WaypointLow: %d; WaypointHigh: %d\n", + waypointmid->health, waypointlow ? waypointlow->health : -1, waypointhigh ? waypointhigh->health : -1); + + // Now we have three waypoints... the closest one we're near, and the one that comes before, and after. + // 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) + { + 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(&p, line, &resultlow); + } + + // Waypointmid and Waypointhigh: + if (waypointhigh) + { + 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(&p, line, &resulthigh); + } + + // 3D support now available. Disregard the previous notice here. -Red + + P_UnsetThingPosition(player->mo); + P_ResetPlayer(player); + player->mo->momx = player->mo->momy = player->mo->momz = 0; + + if (lines[lineindex].flags & ML_EFFECT1) // Don't wrap + { + mobj_t *highest = P_GetLastWaypoint(sequence); + highest->flags |= MF_SLIDEME; + } + + // Changing the conditions on these ifs to fix issues with snapping to the wrong spot -Red + if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == 0) + { + closest = waypointhigh; + player->mo->x = resulthigh.x; + player->mo->y = resulthigh.y; + player->mo->z = resulthigh.z - P_GetPlayerHeight(player); + } + else if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == numwaypoints[sequence] - 1) + { + closest = waypointmid; + player->mo->x = resultlow.x; + player->mo->y = resultlow.y; + player->mo->z = resultlow.z - P_GetPlayerHeight(player); + } + else + { + if (P_AproxDistance(P_AproxDistance(player->mo->x-resultlow.x, player->mo->y-resultlow.y), + player->mo->z-resultlow.z) < P_AproxDistance(P_AproxDistance(player->mo->x-resulthigh.x, + player->mo->y-resulthigh.y), player->mo->z-resulthigh.z)) + { + // Line between Mid and Low is closer + closest = waypointmid; + player->mo->x = resultlow.x; + player->mo->y = resultlow.y; + player->mo->z = resultlow.z - P_GetPlayerHeight(player); + } + else + { + // Line between Mid and High is closer + closest = waypointhigh; + player->mo->x = resulthigh.x; + player->mo->y = resulthigh.y; + player->mo->z = resulthigh.z - P_GetPlayerHeight(player); + } + } + + P_SetTarget(&player->mo->tracer, closest); + player->powers[pw_carry] = CR_ROPEHANG; + + // Option for static ropes. + if (lines[lineindex].flags & ML_NOCLIMB) + player->speed = 0; + else + player->speed = speed; + + S_StartSound(player->mo, sfx_s3k4a); + + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); + player->climbing = 0; + P_SetThingPosition(player->mo); + P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); + } + break; + case 12: // Camera noclip + case 13: // Unused + case 14: // Unused + case 15: // Unused + break; + } +} + +/** Checks if an object is standing on or is inside a special 3D floor. + * If so, the sector is returned. + * + * \param mo Object to check. + * \return Pointer to the sector with a special type, or NULL if no special 3D + * floors are being contacted. + * \sa P_PlayerOnSpecial3DFloor + */ +sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) +{ + sector_t *sector; + ffloor_t *rover; + fixed_t topheight, bottomheight; + + sector = mo->subsector->sector; + if (!sector->ffloors) + return NULL; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!rover->master->frontsector->special) + continue; + + if (!(rover->flags & FF_EXISTS)) + continue; + + topheight = P_GetSpecialTopZ(mo, sectors + rover->secnum, sector); + bottomheight = P_GetSpecialBottomZ(mo, sectors + rover->secnum, sector); + + // Check the 3D floor's type... + if (((rover->flags & FF_BLOCKPLAYER) && mo->player) + || ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) + { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == topheight)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottomheight)); + // Thing must be on top of the floor to be affected... + if (!(floorallowed || ceilingallowed)) + continue; + } + else + { + // Water and intangible FOFs + if (mo->z > topheight || (mo->z + mo->height) < bottomheight) + continue; + } + + return rover->master->frontsector; + } + + return NULL; +} + +#define TELEPORTED (player->mo->subsector->sector != originalsector) + +/** Checks if a player is standing on or is inside a 3D floor (e.g. water) and + * applies any specials. + * + * \param player Player to check. + * \sa P_ThingOnSpecial3DFloor, P_PlayerInSpecialSector + */ +static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) +{ + sector_t *originalsector = player->mo->subsector->sector; + ffloor_t *rover; + fixed_t topheight, bottomheight; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!rover->master->frontsector->special) + continue; + + if (!(rover->flags & FF_EXISTS)) + continue; + + topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, sector); + bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, sector); + + // Check the 3D floor's type... + if (rover->flags & FF_BLOCKPLAYER) + { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); + // Thing must be on top of the floor to be affected... + if (!(floorallowed || ceilingallowed)) + continue; + } + else + { + // Water and DEATH FOG!!! heh + if (player->mo->z > topheight || (player->mo->z + player->mo->height) < bottomheight) + continue; + } + + // This FOF has the special we're looking for, but are we allowed to touch it? + if (sector == player->mo->subsector->sector + || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + { + P_ProcessSpecialSector(player, rover->master->frontsector, sector); + if TELEPORTED return; + } + } + + // Allow sector specials to be applied to polyobjects! + if (player->mo->subsector->polyList) + { + polyobj_t *po = player->mo->subsector->polyList; + sector_t *polysec; + boolean touching = false; + boolean inside = false; + + while (po) + { + if (po->flags & POF_NOSPECIALS) + { + po = (polyobj_t *)(po->link.next); + continue; + } + + polysec = po->lines[0]->backsector; + + if ((polysec->flags & SF_TRIGGERSPECIAL_TOUCH)) + touching = P_MobjTouchingPolyobj(po, player->mo); + else + touching = false; + + inside = P_MobjInsidePolyobj(po, player->mo); + + if (!(inside || touching)) + { + po = (polyobj_t *)(po->link.next); + continue; + } + + // We're inside it! Yess... + if (!polysec->special) + { + po = (polyobj_t *)(po->link.next); + continue; + } + + if (!(po->flags & POF_TESTHEIGHT)) // Don't do height checking + ; + else if (po->flags & POF_SOLID) + { + boolean floorallowed = ((polysec->flags & SF_FLIPSPECIAL_FLOOR) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == polysec->ceilingheight)); + boolean ceilingallowed = ((polysec->flags & SF_FLIPSPECIAL_CEILING) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == polysec->floorheight)); + // Thing must be on top of the floor to be affected... + if (!(floorallowed || ceilingallowed)) + { + po = (polyobj_t *)(po->link.next); + continue; + } + } + else + { + // Water and DEATH FOG!!! heh + if (player->mo->z > polysec->ceilingheight || (player->mo->z + player->mo->height) < polysec->floorheight) + { + po = (polyobj_t *)(po->link.next); + continue; + } + } + + P_ProcessSpecialSector(player, polysec, sector); + if TELEPORTED return; + + po = (polyobj_t *)(po->link.next); + } + } +} + +#define VDOORSPEED (FRACUNIT*2) + +// +// P_RunSpecialSectorCheck +// +// Helper function to P_PlayerInSpecialSector +// +static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector) +{ + boolean nofloorneeded = false; + fixed_t f_affectpoint, c_affectpoint; + + if (!sector->special) // nothing special, exit + return; + + if (GETSECSPECIAL(sector->special, 2) == 9) // Egg trap capsule -- should only be for 3dFloors! + return; + + // The list of specials that activate without floor touch + // Check Section 1 + switch(GETSECSPECIAL(sector->special, 1)) + { + case 2: // Damage (water) + case 8: // Instant kill + case 10: // Ring drainer that doesn't require floor touch + case 12: // Space countdown + nofloorneeded = true; + break; + } + + // Check Section 2 + switch(GETSECSPECIAL(sector->special, 2)) + { + case 2: // Linedef executor (All players needed) + case 4: // Linedef executor + case 6: // Linedef executor (7 Emeralds) + case 7: // Linedef executor (NiGHTS Mare) + nofloorneeded = true; + break; + } + + // Check Section 3 +/* switch(GETSECSPECIAL(sector->special, 3)) + { + + }*/ + + // Check Section 4 + switch(GETSECSPECIAL(sector->special, 4)) + { + case 2: // Level Exit / GOAL Sector / Flag Return + if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap)) + { + // Special stage GOAL sector + // requires touching floor. + break; + } + /* FALLTHRU */ + + case 1: // Starpost activator + case 5: // Fan sector + case 6: // Super Sonic Transform + case 8: // Zoom Tube Start + case 9: // Zoom Tube End + case 10: // Finish line + nofloorneeded = true; + break; + } + + if (nofloorneeded) + { + P_ProcessSpecialSector(player, sector, NULL); + return; + } + + f_affectpoint = P_GetSpecialBottomZ(player->mo, sector, sector); + c_affectpoint = P_GetSpecialTopZ(player->mo, sector, sector); + + { + boolean floorallowed = ((sector->flags & SF_FLIPSPECIAL_FLOOR) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == f_affectpoint)); + boolean ceilingallowed = ((sector->flags & SF_FLIPSPECIAL_CEILING) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == c_affectpoint)); + // Thing must be on top of the floor to be affected... + if (!(floorallowed || ceilingallowed)) + return; + } + + P_ProcessSpecialSector(player, sector, NULL); +} + +/** Checks if the player is in a special sector or FOF and apply any specials. + * + * \param player Player to check. + * \sa P_PlayerOnSpecial3DFloor, P_ProcessSpecialSector + */ +void P_PlayerInSpecialSector(player_t *player) +{ + sector_t *originalsector; + sector_t *loopsector; + msecnode_t *node; + + if (!player->mo) + return; + + originalsector = player->mo->subsector->sector; + + P_PlayerOnSpecial3DFloor(player, originalsector); // Handle FOFs first. + if TELEPORTED return; + + P_RunSpecialSectorCheck(player, originalsector); + if TELEPORTED return; + + // Iterate through touching_sectorlist for SF_TRIGGERSPECIAL_TOUCH + for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + loopsector = node->m_sector; + + if (loopsector == originalsector) // Don't duplicate + continue; + + // Check 3D floors... + P_PlayerOnSpecial3DFloor(player, loopsector); + if TELEPORTED return; + + if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + continue; + + P_RunSpecialSectorCheck(player, loopsector); + if TELEPORTED return; + } +} + +#undef TELEPORTED + +/** Animate planes, scroll walls, etc. and keeps track of level timelimit and exits if time is up. + * + * \sa P_CheckTimeLimit, P_CheckPointLimit + */ +void P_UpdateSpecials(void) +{ + anim_t *anim; + INT32 i; + INT32 pic; + size_t j; + + levelflat_t *foundflats; // for flat animation + + // LEVEL TIMER + P_CheckTimeLimit(); + + // POINT LIMIT + P_CheckPointLimit(); + + // ANIMATE TEXTURES + for (anim = anims; anim < lastanim; anim++) + { + for (i = 0; i < anim->numpics; i++) + { + pic = anim->basepic + ((leveltime/anim->speed + i) % anim->numpics); + if (anim->istexture) + texturetranslation[anim->basepic+i] = pic; + } + } + + // ANIMATE FLATS + /// \todo do not check the non-animate flat.. link the animated ones? + /// \note its faster than the original anywaysince it animates only + /// flats used in the level, and there's usually very few of them + foundflats = levelflats; + for (j = 0; j < numlevelflats; j++, foundflats++) + { + if (foundflats->speed) // it is an animated flat + { + // update the levelflat texture number + if ((foundflats->type == LEVELFLAT_TEXTURE) && (foundflats->u.texture.basenum != -1)) + foundflats->u.texture.num = foundflats->u.texture.basenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); + // update the levelflat lump number + else if ((foundflats->type == LEVELFLAT_FLAT) && (foundflats->u.flat.baselumpnum != LUMPERROR)) + foundflats->u.flat.lumpnum = foundflats->u.flat.baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); + } + } +} + +// +// Floor over floors (FOFs), 3Dfloors, 3Dblocks, fake floors (ffloors), rovers, or whatever you want to call them +// + +/** Gets the ID number for a 3Dfloor in its target sector. + * + * \param fflr The 3Dfloor we want an ID for. + * \return ID of 3Dfloor in target sector. Note that the first FOF's ID is 0. UINT16_MAX is given if invalid. + * \sa P_GetFFloorByID + */ +UINT16 P_GetFFloorID(ffloor_t *fflr) +{ + ffloor_t *rover; + sector_t *sec; + UINT16 i = 0; + + if (!fflr) + return UINT16_MAX; + + sec = fflr->target; + + if (!sec->ffloors) + return UINT16_MAX; + for (rover = sec->ffloors; rover; rover = rover->next, i++) + if (rover == fflr) + return i; + return UINT16_MAX; +} + +/** Gets a 3Dfloor by control sector. + * + * \param sec Target sector. + * \param sec2 Control sector. + * \return Pointer to found 3Dfloor, or NULL. + * \sa P_GetFFloorByID + */ +static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2) +{ + ffloor_t *rover; + + if (!sec->ffloors) + return NULL; + for (rover = sec->ffloors; rover; rover = rover->next) + if (rover->secnum == (size_t)(sec2 - sectors)) + return rover; + return NULL; +} + +/** Gets a 3Dfloor by ID number. + * + * \param sec Target sector. + * \param id ID of 3Dfloor in target sector. Note that the first FOF's ID is 0. + * \return Pointer to found 3Dfloor, or NULL. + * \sa P_GetFFloorBySec, P_GetFFloorID + */ +ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id) +{ + ffloor_t *rover; + UINT16 i = 0; + + if (!sec->ffloors) + return NULL; + for (rover = sec->ffloors; rover; rover = rover->next) + if (i++ == id) + return rover; + return NULL; +} + +/** Adds a newly formed 3Dfloor structure to a sector's ffloors list. + * + * \param sec Target sector. + * \param fflr Newly formed 3Dfloor structure. + * \sa P_AddFakeFloor + */ +static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *fflr) +{ + ffloor_t *rover; + + if (!sec->ffloors) + { + sec->ffloors = fflr; + fflr->next = 0; + fflr->prev = 0; + return; + } + + for (rover = sec->ffloors; rover->next; rover = rover->next); + + rover->next = fflr; + fflr->prev = rover; + fflr->next = 0; +} + +/** Adds a 3Dfloor. + * + * \param sec Target sector. + * \param sec2 Control sector. + * \param master Control linedef. + * \param alpha Alpha value (0-255). + * \param flags Options affecting this 3Dfloor. + * \param secthinkers List of relevant thinkers sorted by sector. May be NULL. + * \return Pointer to the new 3Dfloor. + * \sa P_AddFFloor, P_AddFakeFloorsByLine, P_SpawnSpecials + */ +static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, INT32 alpha, ffloortype_e flags, thinkerlist_t *secthinkers) +{ + ffloor_t *fflr; + thinker_t *th; + friction_t *f; + pusher_t *p; + size_t sec2num; + size_t i; + + if (sec == sec2) + return NULL; //Don't need a fake floor on a control sector. + if ((fflr = (P_GetFFloorBySec(sec, sec2)))) + return fflr; // If this ffloor already exists, return it + + if (sec2->ceilingheight < sec2->floorheight) + { + fixed_t tempceiling = sec2->ceilingheight; + //flip the sector around and print an error instead of crashing 12.1.08 -Inuyasha + CONS_Alert(CONS_ERROR, M_GetText("A FOF tagged %d has a top height below its bottom.\n"), master->args[0]); + sec2->ceilingheight = sec2->floorheight; + sec2->floorheight = tempceiling; + } + + if (sec2->numattached == 0) + { + sec2->attached = Z_Malloc(sizeof (*sec2->attached) * sec2->maxattached, PU_STATIC, NULL); + sec2->attachedsolid = Z_Malloc(sizeof (*sec2->attachedsolid) * sec2->maxattached, PU_STATIC, NULL); + sec2->attached[0] = sec - sectors; + sec2->numattached = 1; + sec2->attachedsolid[0] = (flags & FF_SOLID); + } + else + { + for (i = 0; i < sec2->numattached; i++) + if (sec2->attached[i] == (size_t)(sec - sectors)) + return NULL; + + if (sec2->numattached >= sec2->maxattached) + { + sec2->maxattached *= 2; + sec2->attached = Z_Realloc(sec2->attached, sizeof (*sec2->attached) * sec2->maxattached, PU_STATIC, NULL); + sec2->attachedsolid = Z_Realloc(sec2->attachedsolid, sizeof (*sec2->attachedsolid) * sec2->maxattached, PU_STATIC, NULL); + } + sec2->attached[sec2->numattached] = sec - sectors; + sec2->attachedsolid[sec2->numattached] = (flags & FF_SOLID); + sec2->numattached++; + } + + // Add the floor + fflr = Z_Calloc(sizeof (*fflr), PU_LEVEL, NULL); + fflr->secnum = sec2 - sectors; + fflr->target = sec; + fflr->bottomheight = &sec2->floorheight; + fflr->bottompic = &sec2->floorpic; + fflr->bottomxoffs = &sec2->floor_xoffs; + fflr->bottomyoffs = &sec2->floor_yoffs; + fflr->bottomangle = &sec2->floorpic_angle; + + // Add the ceiling + fflr->topheight = &sec2->ceilingheight; + fflr->toppic = &sec2->ceilingpic; + fflr->toplightlevel = &sec2->lightlevel; + fflr->topxoffs = &sec2->ceiling_xoffs; + fflr->topyoffs = &sec2->ceiling_yoffs; + fflr->topangle = &sec2->ceilingpic_angle; + + // Add slopes + fflr->t_slope = &sec2->c_slope; + fflr->b_slope = &sec2->f_slope; + // mark the target sector as having slopes, if the FOF has any of its own + // (this fixes FOF slopes glitching initially at level load in software mode) + if (sec2->hasslope) + sec->hasslope = true; + + fflr->spawnflags = fflr->flags = flags; + fflr->master = master; + fflr->norender = INFTICS; + fflr->fadingdata = NULL; + + // Scan the thinkers to check for special conditions applying to this FOF. + // If we have thinkers sorted by sector, just check the relevant ones; + // otherwise, check them all. Apologies for the ugly loop... + + sec2num = sec2 - sectors; + + // Just initialise both of these to placate the compiler. + i = 0; + th = thlist[THINK_MAIN].next; + + for(;;) + { + if(secthinkers) + { + if(i < secthinkers[sec2num].count) + th = secthinkers[sec2num].thinkers[i]; + else break; + } + else if (th == &thlist[THINK_MAIN]) + break; + + // Should this FOF have friction? + if(th->function.acp1 == (actionf_p1)T_Friction) + { + f = (friction_t *)th; + + if (f->affectee == (INT32)sec2num) + Add_Friction(f->friction, f->movefactor, (INT32)(sec-sectors), f->affectee); + } + // Should this FOF have wind/current/pusher? + else if(th->function.acp1 == (actionf_p1)T_Pusher) + { + p = (pusher_t *)th; + + if (p->affectee == (INT32)sec2num) + Add_Pusher(p->type, p->x_mag<y_mag<source, (INT32)(sec-sectors), p->affectee, p->exclusive, p->slider); + } + + if(secthinkers) i++; + else th = th->next; + } + + fflr->alpha = max(0, min(0xff, alpha)); + if (fflr->alpha < 0xff) + { + fflr->flags |= FF_TRANSLUCENT; + fflr->spawnflags = fflr->flags; + } + fflr->spawnalpha = fflr->alpha; // save for netgames + + if (flags & FF_QUICKSAND) + CheckForQuicksand = true; + + if (flags & FF_BUSTUP) + CheckForBustableBlocks = true; + + if ((flags & FF_MARIO)) + { + if (!(flags & FF_GOOWATER)) // Don't change the textures of a brick block, just a question block + P_AddBlockThinker(sec2, master); + CheckForMarioBlocks = true; + } + + if ((flags & FF_CRUMBLE)) + sec2->crumblestate = CRUMBLE_WAIT; + + if ((flags & FF_FLOATBOB)) + { + P_AddFloatThinker(sec2, Tag_FGet(&master->tags), master); + CheckForFloatBob = true; + } + + P_AddFFloorToList(sec, fflr); + + return fflr; +} + +// +// SPECIAL SPAWNING +// + +/** Adds a float thinker. + * Float thinkers cause solid 3Dfloors to float on water. + * + * \param sec Control sector. + * \param actionsector Target sector. + * \sa P_SpawnSpecials, T_FloatSector + * \author SSNTails + */ +static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline) +{ + floatthink_t *floater; + + // create and initialize new thinker + floater = Z_Calloc(sizeof (*floater), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &floater->thinker); + + floater->thinker.function.acp1 = (actionf_p1)T_FloatSector; + + floater->sector = sec; + floater->tag = (INT16)tag; + floater->sourceline = sourceline; +} + +/** + * Adds a plane displacement thinker. + * Whenever the "control" sector moves, + * the "affectee" sector's floor or ceiling plane moves too! + * + * \param speed Rate of movement relative to control sector + * \param control Control sector. + * \param affectee Target sector. + * \param reverse Reverse direction? + * \sa P_SpawnSpecials, T_PlaneDisplace + * \author Monster Iestyn + */ +static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee, UINT8 reverse) +{ + planedisplace_t *displace; + + // create and initialize new displacement thinker + displace = Z_Calloc(sizeof (*displace), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &displace->thinker); + + displace->thinker.function.acp1 = (actionf_p1)T_PlaneDisplace; + displace->affectee = affectee; + displace->control = control; + displace->last_height = sectors[control].floorheight; + displace->speed = speed; + displace->type = type; + displace->reverse = reverse; +} + +/** Adds a Mario block thinker, which changes the block's texture between blank + * and ? depending on whether it has contents. + * Needed in case objects respawn inside. + * + * \param sec Control sector. + * \param actionsector Target sector. + * \param sourceline Control linedef. + * \sa P_SpawnSpecials, T_MarioBlockChecker + * \author SSNTails + */ +static void P_AddBlockThinker(sector_t *sec, line_t *sourceline) +{ + mariocheck_t *block; + + // create and initialize new elevator thinker + block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &block->thinker); + + block->thinker.function.acp1 = (actionf_p1)T_MarioBlockChecker; + block->sourceline = sourceline; + + block->sector = sec; +} + +/** Adds a raise thinker. + * A raise thinker checks to see if the + * player is standing on its 3D Floor, + * and if so, raises the platform towards + * it's destination. Otherwise, it lowers + * to the lowest nearby height if not + * there already. + * + * \param sec Control sector. + * \sa P_SpawnSpecials, T_RaiseSector + * \author SSNTails + */ +static void P_AddRaiseThinker(sector_t *sec, INT16 tag, fixed_t speed, fixed_t ceilingtop, fixed_t ceilingbottom, boolean lower, boolean spindash) +{ + raise_t *raise; + + raise = Z_Calloc(sizeof (*raise), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &raise->thinker); + + raise->thinker.function.acp1 = (actionf_p1)T_RaiseSector; + + raise->tag = tag; + raise->sector = sec; + + raise->ceilingtop = ceilingtop; + raise->ceilingbottom = ceilingbottom; + + raise->basespeed = speed >> 2; + + if (lower) + raise->flags |= RF_REVERSE; + if (spindash) + raise->flags |= RF_SPINDASH; +} + +static void P_AddAirbob(sector_t *sec, INT16 tag, fixed_t dist, boolean raise, boolean spindash, boolean dynamic) +{ + raise_t *airbob; + + airbob = Z_Calloc(sizeof (*airbob), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &airbob->thinker); + + airbob->thinker.function.acp1 = (actionf_p1)T_RaiseSector; + + airbob->tag = tag; + airbob->sector = sec; + + airbob->ceilingtop = sec->ceilingheight; + airbob->ceilingbottom = sec->ceilingheight - dist; + + airbob->basespeed = FRACUNIT; + + if (!raise) + airbob->flags |= RF_REVERSE; + if (spindash) + airbob->flags |= RF_SPINDASH; + if (dynamic) + airbob->flags |= RF_DYNAMIC; +} + +/** Adds a thwomp thinker. + * Even thwomps need to think! + * + * \param sec Control sector. + * \sa P_SpawnSpecials, T_ThwompSector + * \author SSNTails + */ +static inline void P_AddThwompThinker(sector_t *sec, line_t *sourceline, fixed_t crushspeed, fixed_t retractspeed, UINT16 sound) +{ + thwomp_t *thwomp; + + // You *probably* already have a thwomp in this sector. If you've combined it with something + // else that uses the floordata/ceilingdata, you must be weird. + if (sec->floordata || sec->ceilingdata) + return; + + // create and initialize new elevator thinker + thwomp = Z_Calloc(sizeof (*thwomp), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &thwomp->thinker); + + thwomp->thinker.function.acp1 = (actionf_p1)T_ThwompSector; + + // set up the fields according to the type of elevator action + thwomp->sourceline = sourceline; + thwomp->sector = sec; + thwomp->crushspeed = crushspeed; + thwomp->retractspeed = retractspeed; + thwomp->direction = 0; + thwomp->floorstartheight = sec->floorheight; + thwomp->ceilingstartheight = sec->ceilingheight; + thwomp->delay = 1; + thwomp->tag = Tag_FGet(&sourceline->tags); + thwomp->sound = sound; + + sec->floordata = thwomp; + sec->ceilingdata = thwomp; + // Start with 'resting' texture + sides[sourceline->sidenum[0]].midtexture = sides[sourceline->sidenum[0]].bottomtexture; +} + +/** Adds a thinker which checks if any MF_ENEMY objects with health are in the defined area. + * If not, a linedef executor is run once. + * + * \param sourceline Control linedef. + * \sa P_SpawnSpecials, T_NoEnemiesSector + * \author SSNTails + */ +static inline void P_AddNoEnemiesThinker(line_t *sourceline) +{ + noenemies_t *nobaddies; + + // create and initialize new thinker + nobaddies = Z_Calloc(sizeof (*nobaddies), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &nobaddies->thinker); + + nobaddies->thinker.function.acp1 = (actionf_p1)T_NoEnemiesSector; + + nobaddies->sourceline = sourceline; +} + +/** Adds a thinker for Each-Time linedef executors. A linedef executor is run + * only when a player enters the area and doesn't run again until they re-enter. + * + * \param sourceline Control linedef. + * \sa P_SpawnSpecials, T_EachTimeThinker + * \author SSNTails + */ +static void P_AddEachTimeThinker(line_t *sourceline) +{ + eachtime_t *eachtime; + + // create and initialize new thinker + eachtime = Z_Calloc(sizeof (*eachtime), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &eachtime->thinker); + + eachtime->thinker.function.acp1 = (actionf_p1)T_EachTimeThinker; + + eachtime->sourceline = sourceline; + eachtime->triggerOnExit = !!(sourceline->flags & ML_BOUNCY); +} + +/** Adds a camera scanner. + * + * \param sourcesec Control sector. + * \param actionsector Target sector. + * \param angle Angle of the source line. + * \sa P_SpawnSpecials, T_CameraScanner + * \author SSNTails + */ +static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsector, angle_t angle) +{ + elevator_t *elevator; // Why not? LOL + + CONS_Alert(CONS_WARNING, M_GetText("Detected a camera scanner effect (linedef type 5). This effect is deprecated and will be removed in the future!\n")); + + // create and initialize new elevator thinker + elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &elevator->thinker); + + elevator->thinker.function.acp1 = (actionf_p1)T_CameraScanner; + elevator->type = elevateBounce; + + // set up the fields according to the type of elevator action + elevator->sector = sourcesec; + elevator->actionsector = actionsector; + elevator->distance = FixedInt(AngleFixed(angle)); +} + +/** Flashes a laser block. + * + * \param flash Thinker structure for this laser. + * \sa P_AddLaserThinker + * \author SSNTails + */ +void T_LaserFlash(laserthink_t *flash) +{ + msecnode_t *node; + mobj_t *thing; + INT32 s; + ffloor_t *fflr; + sector_t *sector; + sector_t *sourcesec = flash->sourceline->frontsector; + fixed_t top, bottom; + + TAG_ITER_SECTORS(flash->tag, s) + { + sector = §ors[s]; + for (fflr = sector->ffloors; fflr; fflr = fflr->next) + { + if (fflr->master != flash->sourceline) + continue; + + if (!(fflr->flags & FF_EXISTS)) + break; + + if (leveltime & 2) + //fflr->flags |= FF_RENDERALL; + fflr->alpha = 0xB0; + else + //fflr->flags &= ~FF_RENDERALL; + fflr->alpha = 0x90; + + top = P_GetFFloorTopZAt (fflr, sector->soundorg.x, sector->soundorg.y); + bottom = P_GetFFloorBottomZAt(fflr, sector->soundorg.x, sector->soundorg.y); + sector->soundorg.z = (top + bottom)/2; + S_StartSound(§or->soundorg, sfx_laser); + + // Seek out objects to DESTROY! MUAHAHHAHAHAA!!!*cough* + for (node = sector->touching_thinglist; node && node->m_thing; node = node->m_thinglist_next) + { + thing = node->m_thing; + + if (flash->nobosses && thing->flags & MF_BOSS) + continue; // Don't hurt bosses + + // Don't endlessly kill egg guard shields (or anything else for that matter) + if (thing->health <= 0) + continue; + + top = P_GetSpecialTopZ(thing, sourcesec, sector); + bottom = P_GetSpecialBottomZ(thing, sourcesec, sector); + + if (thing->z >= top + || thing->z + thing->height <= bottom) + continue; + + if (thing->flags & MF_SHOOTABLE) + P_DamageMobj(thing, NULL, NULL, 1, 0); + else if (thing->type == MT_EGGSHIELD) + P_KillMobj(thing, NULL, NULL, 0); + } + + break; + } + } +} + +static inline void P_AddLaserThinker(INT16 tag, line_t *line, boolean nobosses) +{ + laserthink_t *flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); + + P_AddThinker(THINK_MAIN, &flash->thinker); + + flash->thinker.function.acp1 = (actionf_p1)T_LaserFlash; + flash->tag = tag; + flash->sourceline = line; + flash->nobosses = nobosses; +} + +// +// P_RunLevelLoadExecutors +// +// After loading/spawning all other specials +// and items, execute these. +// +static void P_RunLevelLoadExecutors(void) +{ + size_t i; + + for (i = 0; i < numlines; i++) + { + if (lines[i].special == 399) + P_RunTriggerLinedef(&lines[i], NULL, NULL); + } +} + +/** Before things are loaded, initialises certain stuff in case they're needed + * by P_SpawnSlopes or P_LoadThings. This was split off from + * P_SpawnSpecials, in case you couldn't tell. + * + * \sa P_SpawnSpecials + * \author Monster Iestyn + */ +void P_InitSpecials(void) +{ + // Set the default gravity. Custom gravity overrides this setting. + gravity = mapheaderinfo[gamemap-1]->gravity; + + // Defaults in case levels don't have them set. + sstimer = mapheaderinfo[gamemap-1]->sstimer*TICRATE + 6; + ssspheres = mapheaderinfo[gamemap-1]->ssspheres; + + CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false; + + // Set curWeather + switch (mapheaderinfo[gamemap-1]->weather) + { + case PRECIP_SNOW: // snow + case PRECIP_RAIN: // rain + case PRECIP_STORM: // storm + case PRECIP_STORM_NORAIN: // storm w/o rain + case PRECIP_STORM_NOSTRIKES: // storm w/o lightning + curWeather = mapheaderinfo[gamemap-1]->weather; + break; + default: // blank/none + curWeather = PRECIP_NONE; + break; + } + + // Set globalweather + globalweather = mapheaderinfo[gamemap-1]->weather; +} + +static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs) +{ + if (!(master->flags & ML_NETONLY)) // Modify floor flat alignment unless ML_NETONLY flag is set + { + sector->floorpic_angle = flatangle; + sector->floor_xoffs += xoffs; + sector->floor_yoffs += yoffs; + } + + if (!(master->flags & ML_NONET)) // Modify ceiling flat alignment unless ML_NONET flag is set + { + sector->ceilingpic_angle = flatangle; + sector->ceiling_xoffs += xoffs; + sector->ceiling_yoffs += yoffs; + } + +} + +static void P_MakeFOFBouncy(line_t *paramline, line_t *masterline) +{ + INT32 s; + TAG_ITER_DECLARECOUNTER(0); + + if (masterline->special < 100 || masterline->special >= 300) + return; + + TAG_ITER_SECTORS(0, masterline->args[0], s) + { + ffloor_t *rover; + + for (rover = sectors[s].ffloors; rover; rover = rover->next) + { + if (rover->master != masterline) + continue; + + rover->flags |= FF_BOUNCY; + rover->spawnflags |= FF_BOUNCY; + rover->bouncestrength = (paramline->args[1]<< FRACBITS)/100; + if (paramline->args[2]) + rover->specialflags |= FS_DAMPEN; + else + rover->specialflags &= ~FS_DAMPEN; + CheckForBouncySector = true; + break; + } + } + +} + +/** After the map has loaded, scans for specials that spawn 3Dfloors and + * thinkers. + * + * \todo Split up into multiple functions. + * \todo Get rid of all the magic numbers. + * \todo Potentially use 'fromnetsave' to stop any new thinkers from being created + * as they'll just be erased by UnArchiveThinkers. + * \sa P_SpawnPrecipitation, P_SpawnFriction, P_SpawnPushers, P_SpawnScrollers + */ +void P_SpawnSpecials(boolean fromnetsave) +{ + sector_t *sector; + size_t i; + INT32 j; + thinkerlist_t *secthinkers; + thinker_t *th; + TAG_ITER_DECLARECOUNTER(0); + // This used to be used, and *should* be used in the future, + // but currently isn't. + (void)fromnetsave; + + // yep, we do this here - "bossdisabled" is considered an apparatus of specials. + bossdisabled = 0; + stoppedclock = false; + + // Init special SECTORs. + sector = sectors; + for (i = 0; i < numsectors; i++, sector++) + { + if (!sector->special) + continue; + + // Process Section 1 + switch(GETSECSPECIAL(sector->special, 1)) + { + case 5: // Spikes + //Terrible hack to replace an even worse hack: + //Spike damage automatically sets SF_TRIGGERSPECIAL_TOUCH. + //Yes, this also affects other specials on the same sector. Sorry. + sector->flags |= SF_TRIGGERSPECIAL_TOUCH; + break; + } + + // Process Section 2 + switch(GETSECSPECIAL(sector->special, 2)) + { + case 10: // Time for special stage + sstimer = (sector->floorheight>>FRACBITS) * TICRATE + 6; // Time to finish + ssspheres = sector->ceilingheight>>FRACBITS; // Ring count for special stage + break; + + case 11: // Custom global gravity! + gravity = sector->floorheight/1000; + break; + } + + // Process Section 3 +/* switch(GETSECSPECIAL(player->specialsector, 3)) + { + + }*/ + + // Process Section 4 + switch(GETSECSPECIAL(sector->special, 4)) + { + case 10: // Circuit finish line + if ((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE) + circuitmap = true; + break; + } + } + + P_SpawnScrollers(); // Add generalized scrollers + P_SpawnFriction(); // Friction model using linedefs + P_SpawnPushers(); // Pusher model using linedefs + + // Look for thinkers that affect FOFs, and sort them by sector + + secthinkers = Z_Calloc(numsectors * sizeof(thinkerlist_t), PU_STATIC, NULL); + + // Firstly, find out how many there are in each sector + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)T_Friction) + secthinkers[((friction_t *)th)->affectee].count++; + else if (th->function.acp1 == (actionf_p1)T_Pusher) + secthinkers[((pusher_t *)th)->affectee].count++; + } + + // Allocate each list, and then zero the count so we can use it to track + // the end of the list as we add the thinkers + for (i = 0; i < numsectors; i++) + if(secthinkers[i].count > 0) + { + secthinkers[i].thinkers = Z_Malloc(secthinkers[i].count * sizeof(thinker_t *), PU_STATIC, NULL); + secthinkers[i].count = 0; + } + + // Finally, populate the lists. + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + { + size_t secnum = (size_t)-1; + + if (th->function.acp1 == (actionf_p1)T_Friction) + secnum = ((friction_t *)th)->affectee; + else if (th->function.acp1 == (actionf_p1)T_Pusher) + secnum = ((pusher_t *)th)->affectee; + + if (secnum != (size_t)-1) + secthinkers[secnum].thinkers[secthinkers[secnum].count++] = th; + } + + + // Init line EFFECTs + for (i = 0; i < numlines; i++) + { + mtag_t tag = Tag_FGet(&lines[i].tags); + + if (lines[i].special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment in netgames... + { + // set line specials to 0 here too, same reason as above + if (netgame || multiplayer) + { + if (lines[i].flags & ML_NONET) + { + lines[i].special = 0; + continue; + } + } + else if (lines[i].flags & ML_NETONLY) + { + lines[i].special = 0; + continue; + } + } + + switch (lines[i].special) + { + INT32 s; + INT32 l; + size_t sec; + ffloortype_e ffloorflags; + + case 1: // Definable gravity per sector + sec = sides[*lines[i].sidenum].sector - sectors; + TAG_ITER_SECTORS(tag, s) + { + sectors[s].gravity = §ors[sec].floorheight; // This allows it to change in realtime! + + if (lines[i].flags & ML_NOCLIMB) + sectors[s].verticalflip = true; + else + sectors[s].verticalflip = false; + + CheckForReverseGravity = sectors[s].verticalflip; + } + break; + + case 2: // Custom exit + break; + + case 3: // Zoom Tube Parameters + break; + + case 4: // Speed pad (combines with sector special Section3:5 or Section3:6) + break; + + case 5: // Change camera info + sec = sides[*lines[i].sidenum].sector - sectors; + TAG_ITER_SECTORS(tag, s) + P_AddCameraScanner(§ors[sec], §ors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)); + break; + + case 7: // Flat alignment - redone by toast + if ((lines[i].flags & (ML_NETONLY|ML_NONET)) != (ML_NETONLY|ML_NONET)) // If you can do something... + { + angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)); + fixed_t xoffs; + fixed_t yoffs; + + if (lines[i].flags & ML_EFFECT6) // Set offset through x and y texture offsets if ML_EFFECT6 flag is set + { + xoffs = sides[lines[i].sidenum[0]].textureoffset; + yoffs = sides[lines[i].sidenum[0]].rowoffset; + } + else // Otherwise, set calculated offsets such that line's v1 is the apparent origin + { + xoffs = -lines[i].v1->x; + yoffs = lines[i].v1->y; + } + + //If no tag is given, apply to front sector + if (tag == 0) + P_ApplyFlatAlignment(lines + i, lines[i].frontsector, flatangle, xoffs, yoffs); + else + { + TAG_ITER_SECTORS(tag, s) + P_ApplyFlatAlignment(lines + i, sectors + s, flatangle, xoffs, yoffs); + } + } + else // Otherwise, print a helpful warning. Can I do no less? + CONS_Alert(CONS_WARNING, + M_GetText("Flat alignment linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), + tag); + break; + + case 8: // Sector Parameters + TAG_ITER_SECTORS(tag, s) + { + if (lines[i].flags & ML_NOCLIMB) + { + sectors[s].flags &= ~SF_FLIPSPECIAL_FLOOR; + sectors[s].flags |= SF_FLIPSPECIAL_CEILING; + } + else if (lines[i].flags & ML_EFFECT4) + sectors[s].flags |= SF_FLIPSPECIAL_BOTH; + + if (lines[i].flags & ML_EFFECT3) + sectors[s].flags |= SF_TRIGGERSPECIAL_TOUCH; + if (lines[i].flags & ML_EFFECT2) + sectors[s].flags |= SF_TRIGGERSPECIAL_HEADBUMP; + + if (lines[i].flags & ML_EFFECT1) + sectors[s].flags |= SF_INVERTPRECIP; + + if (lines[i].frontsector && GETSECSPECIAL(lines[i].frontsector->special, 4) == 12) + sectors[s].camsec = sides[*lines[i].sidenum].sector-sectors; + } + break; + + case 9: // Chain Parameters + break; + + case 10: // Vertical culling plane for sprites and FOFs + TAG_ITER_SECTORS(tag, s) + sectors[s].cullheight = &lines[i]; // This allows it to change in realtime! + break; + + case 50: // Insta-Lower Sector + EV_DoFloor(&lines[i], instantLower); + break; + + case 51: // Instant raise for ceilings + EV_DoCeiling(&lines[i], instantRaise); + break; + + case 52: // Continuously Falling sector + EV_DoContinuousFall(lines[i].frontsector, lines[i].backsector, P_AproxDistance(lines[i].dx, lines[i].dy), (lines[i].flags & ML_NOCLIMB)); + break; + + case 53: // New super cool and awesome moving floor and ceiling type + case 54: // New super cool and awesome moving floor type + if (lines[i].backsector) + EV_DoFloor(&lines[i], bounceFloor); + if (lines[i].special == 54) + break; + /* FALLTHRU */ + + case 55: // New super cool and awesome moving ceiling type + if (lines[i].backsector) + EV_DoCeiling(&lines[i], bounceCeiling); + break; + + case 56: // New super cool and awesome moving floor and ceiling crush type + case 57: // New super cool and awesome moving floor crush type + if (lines[i].backsector) + EV_DoFloor(&lines[i], bounceFloorCrush); + + if (lines[i].special == 57) + break; //only move the floor + /* FALLTHRU */ + + case 58: // New super cool and awesome moving ceiling crush type + if (lines[i].backsector) + EV_DoCeiling(&lines[i], bounceCeilingCrush); + break; + + case 59: // Activate floating platform + EV_DoElevator(&lines[i], elevateContinuous, false); + break; + + case 60: // Floating platform with adjustable speed + EV_DoElevator(&lines[i], elevateContinuous, true); + break; + + case 61: // Crusher! + EV_DoCrush(&lines[i], crushAndRaise); + break; + + case 62: // Crusher (up and then down)! + EV_DoCrush(&lines[i], fastCrushAndRaise); + break; + + case 63: // support for drawn heights coming from different sector + sec = sides[*lines[i].sidenum].sector-sectors; + TAG_ITER_SECTORS(tag, s) + sectors[s].heightsec = (INT32)sec; + break; + + case 64: // Appearing/Disappearing FOF option + if (lines[i].flags & ML_BLOCKMONSTERS) { // Find FOFs by control sector tag + TAG_ITER_SECTORS(tag, s) + for (j = 0; (unsigned)j < sectors[s].linecount; j++) + if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) + Add_MasterDisappearer(abs(lines[i].dx>>FRACBITS), abs(lines[i].dy>>FRACBITS), abs(sides[lines[i].sidenum[0]].sector->floorheight>>FRACBITS), (INT32)(sectors[s].lines[j]-lines), (INT32)i); + } else // Find FOFs by effect sector tag + { + TAG_ITER_LINES(tag, s) + { + if ((size_t)s == i) + continue; + if (Tag_Find(&sides[lines[s].sidenum[0]].sector->tags, Tag_FGet(&sides[lines[i].sidenum[0]].sector->tags))) + Add_MasterDisappearer(abs(lines[i].dx>>FRACBITS), abs(lines[i].dy>>FRACBITS), abs(sides[lines[i].sidenum[0]].sector->floorheight>>FRACBITS), s, (INT32)i); + } + } + break; + + case 66: // Displace floor by front sector + TAG_ITER_SECTORS(tag, s) + P_AddPlaneDisplaceThinker(pd_floor, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); + break; + case 67: // Displace ceiling by front sector + TAG_ITER_SECTORS(tag, s) + P_AddPlaneDisplaceThinker(pd_ceiling, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); + break; + case 68: // Displace both floor AND ceiling by front sector + TAG_ITER_SECTORS(tag, s) + P_AddPlaneDisplaceThinker(pd_both, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); + break; + + case 70: // Add raise thinker to FOF + if (udmf) + { + fixed_t destheight = lines[i].args[2] << FRACBITS; + fixed_t startheight, topheight, bottomheight; + + TAG_ITER_LINES(0, lines[i].args[0], l) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + startheight = lines[l].frontsector->ceilingheight; + topheight = max(startheight, destheight); + bottomheight = min(startheight, destheight); + + P_AddRaiseThinker(lines[l].frontsector, lines[l].args[0], lines[i].args[1] << FRACBITS, topheight, bottomheight, (destheight < startheight), !!(lines[i].args[3])); + } + } + break; + + case 71: // Add air bob thinker to FOF + if (udmf) + { + TAG_ITER_LINES(0, lines[i].args[0], l) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + P_AddAirbob(lines[l].frontsector, lines[l].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); + } + } + break; + + case 72: // Add thwomp thinker to FOF + if (udmf) + { + UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; + + TAG_ITER_LINES(0, lines[i].args[0], l) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + P_AddThwompThinker(lines[l].frontsector, &lines[l], lines[i].args[1] << FRACBITS, lines[i].args[2] << FRACBITS, sound); + } + } + break; + + case 73: // Add laser thinker to FOF + if (udmf) + { + TAG_ITER_LINES(0, lines[i].args[0], l) + { + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + P_AddLaserThinker(lines[l].args[0], lines + l, !!(lines[i].args[1])); + } + } + break; + + case 100: // FOF (solid) + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; + + //Appearance settings + if (lines[i].args[2] & TMFA_NOPLANES) + ffloorflags &= ~FF_RENDERPLANES; + if (lines[i].args[2] & TMFA_NOSIDES) + ffloorflags &= ~FF_RENDERSIDES; + if (lines[i].args[2] & TMFA_INSIDES) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_BOTHPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_ALLSIDES; + } + if (lines[i].args[2] & TMFA_ONLYINSIDES) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_INVERTPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_INVERTSIDES; + } + if (lines[i].args[2] & TMFA_NOSHADE) + ffloorflags |= FF_NOSHADE; + if (lines[i].args[2] & TMFA_SPLAT) + ffloorflags |= FF_SPLAT; + + //Tangibility settings + if (lines[i].args[3] & TMFT_INTANGIBLETOP) + ffloorflags |= FF_REVERSEPLATFORM; + if (lines[i].args[3] & TMFT_INTANGIBLEBOTTOM) + ffloorflags |= FF_PLATFORM; + if (lines[i].args[3] & TMFT_DONTBLOCKPLAYER) + ffloorflags &= ~FF_BLOCKPLAYER; + if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) + ffloorflags &= ~FF_BLOCKOTHERS; + + //Cutting options + if (ffloorflags & FF_RENDERALL) + { + //If translucent or player can enter it, cut inner walls + if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) + ffloorflags |= FF_CUTEXTRA|FF_EXTRA; + else + ffloorflags |= FF_CUTLEVEL; + } + + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + break; + + case 120: // FOF (water) + ffloorflags = FF_EXISTS|FF_RENDERPLANES|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; + if (!(lines[i].args[2] & TMFW_NOSIDES)) + ffloorflags |= FF_RENDERSIDES|FF_ALLSIDES; + if (lines[i].args[2] & TMFW_DOUBLESHADOW) + ffloorflags |= FF_DOUBLESHADOW; + if (lines[i].args[2] & TMFW_COLORMAPONLY) + ffloorflags |= FF_COLORMAPONLY; + if (!(lines[i].args[2] & TMFW_NORIPPLE)) + ffloorflags |= FF_RIPPLE; + if (lines[i].args[2] & TMFW_GOOWATER) + ffloorflags |= FF_GOOWATER; + if (lines[i].args[2] & TMFW_SPLAT) + ffloorflags |= FF_SPLAT; + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + break; + + case 150: // FOF (Air bobbing) + P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL, secthinkers); + P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); + break; + + case 160: // FOF (Water bobbing) + P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB, secthinkers); + break; + + case 170: // FOF (Crumbling) + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE; + + //Tangibility settings + if (lines[i].args[2] & TMFT_INTANGIBLETOP) + ffloorflags |= FF_REVERSEPLATFORM; + if (lines[i].args[2] & TMFT_INTANGIBLEBOTTOM) + ffloorflags |= FF_PLATFORM; + if (lines[i].args[2] & TMFT_DONTBLOCKPLAYER) + ffloorflags &= ~FF_BLOCKPLAYER; + if (lines[i].args[2] & TMFT_DONTBLOCKOTHERS) + ffloorflags &= ~FF_BLOCKOTHERS; + + //Flags + if (lines[i].args[3] & TMFC_NOSHADE) + ffloorflags |= FF_NOSHADE; + if (lines[i].args[3] & TMFC_NORETURN) + ffloorflags |= FF_NORETURN; + if (lines[i].args[3] & TMFC_FLOATBOB) + ffloorflags |= FF_FLOATBOB; + if (lines[i].args[3] & TMFC_SPLAT) + ffloorflags |= FF_SPLAT; + + //If translucent or player can enter it, cut inner walls + if (lines[i].args[1] < 0xff || (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE)) + ffloorflags |= FF_CUTEXTRA|FF_EXTRA; + else + ffloorflags |= FF_CUTLEVEL; + + //If player can enter it, render insides + if (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_BOTHPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_ALLSIDES; + } + + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + if (lines[i].args[3] & TMFC_AIRBOB) + P_AddAirbob(lines[i].frontsector, lines[i].args[0], 16*FRACUNIT, false, false, false); + break; + + case 190: // FOF (Rising) + { + fixed_t ceilingtop = P_FindHighestCeilingSurrounding(lines[i].frontsector); + fixed_t ceilingbottom = P_FindLowestCeilingSurrounding(lines[i].frontsector); + + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; + + //Appearance settings + if (lines[i].args[2] & TMFA_NOPLANES) + ffloorflags &= ~FF_RENDERPLANES; + if (lines[i].args[2] & TMFA_NOSIDES) + ffloorflags &= ~FF_RENDERSIDES; + if (lines[i].args[2] & TMFA_INSIDES) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_BOTHPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_ALLSIDES; + } + if (lines[i].args[2] & TMFA_ONLYINSIDES) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_INVERTPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_INVERTSIDES; + } + if (lines[i].args[2] & TMFA_NOSHADE) + ffloorflags |= FF_NOSHADE; + if (lines[i].args[2] & TMFA_SPLAT) + ffloorflags |= FF_SPLAT; + + //Tangibility settings + if (lines[i].args[3] & TMFT_INTANGIBLETOP) + ffloorflags |= FF_REVERSEPLATFORM; + if (lines[i].args[3] & TMFT_INTANGIBLEBOTTOM) + ffloorflags |= FF_PLATFORM; + if (lines[i].args[3] & TMFT_DONTBLOCKPLAYER) + ffloorflags &= ~FF_BLOCKPLAYER; + if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) + ffloorflags &= ~FF_BLOCKOTHERS; + + //Cutting options + if (ffloorflags & FF_RENDERALL) + { + //If translucent or player can enter it, cut inner walls + if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) + ffloorflags |= FF_CUTEXTRA|FF_EXTRA; + else + ffloorflags |= FF_CUTLEVEL; + } + + P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); + P_AddRaiseThinker(lines[i].frontsector, lines[i].args[0], lines[i].args[4] << FRACBITS, ceilingtop, ceilingbottom, !!(lines[i].args[5] & TMFR_REVERSE), !!(lines[i].args[5] & TMFR_SPINDASH)); + break; + } + case 200: // Light block + ffloorflags = FF_EXISTS|FF_CUTSPRITES; + if (!lines[i].args[1]) + ffloorflags |= FF_DOUBLESHADOW; + P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); + break; + + case 202: // Fog + ffloorflags = FF_EXISTS|FF_RENDERALL|FF_FOG|FF_INVERTPLANES|FF_INVERTSIDES|FF_CUTEXTRA|FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES; + sec = sides[*lines[i].sidenum].sector - sectors; + // SoM: Because it's fog, check for an extra colormap and set the fog flag... + if (sectors[sec].extra_colormap) + sectors[sec].extra_colormap->flags = CMF_FOG; + P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); + break; + + case 220: //Intangible + ffloorflags = FF_EXISTS|FF_RENDERALL|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; + + //Appearance settings + if (lines[i].args[2] & TMFA_NOPLANES) + ffloorflags &= ~FF_RENDERPLANES; + if (lines[i].args[2] & TMFA_NOSIDES) + ffloorflags &= ~FF_RENDERSIDES; + if (!(lines[i].args[2] & TMFA_INSIDES)) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_BOTHPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_ALLSIDES; + } + if (lines[i].args[2] & TMFA_ONLYINSIDES) + { + if (ffloorflags & FF_RENDERPLANES) + ffloorflags |= FF_INVERTPLANES; + if (ffloorflags & FF_RENDERSIDES) + ffloorflags |= FF_INVERTSIDES; + } + if (lines[i].args[2] & TMFA_NOSHADE) + ffloorflags |= FF_NOSHADE; + if (lines[i].args[2] & TMFA_SPLAT) + ffloorflags |= FF_SPLAT; + + P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); + break; + + case 223: // FOF (intangible, invisible) - for combining specials in a sector + P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_NOSHADE, secthinkers); + break; + + case 250: // Mario Block + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO; + if (lines[i].args[1] & TMFM_BRICK) + ffloorflags |= FF_GOOWATER; + if (lines[i].args[1] & TMFM_INVISIBLE) + ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); + + P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); + break; + + case 251: // A THWOMP! + { + UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; + P_AddThwompThinker(lines[i].frontsector, &lines[i], lines[i].args[1] << FRACBITS, lines[i].args[2] << FRACBITS, sound); + P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); + break; + } + + case 254: // Bustable block + { + UINT8 busttype = BT_REGULAR; + ffloorspecialflags_e bustflags = 0; + + ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP; + + //Bustable type + switch (lines[i].args[2]) + { + case TMFB_TOUCH: + busttype = BT_TOUCH; + break; + case TMFB_SPIN: + busttype = BT_SPINBUST; + break; + case TMFB_REGULAR: + busttype = BT_REGULAR; + break; + case TMFB_STRONG: + busttype = BT_STRONG; + break; + } + + //Flags + if (lines[i].args[3] & TMFB_PUSHABLES) + bustflags |= FS_PUSHABLES; + if (lines[i].args[3] & TMFB_EXECUTOR) + bustflags |= FS_EXECUTOR; + if (lines[i].args[3] & TMFB_ONLYBOTTOM) + bustflags |= FS_ONLYBOTTOM; + if (lines[i].args[3] & TMFB_SPLAT) + ffloorflags |= FF_SPLAT; + + if (busttype != BT_TOUCH || bustflags & FS_ONLYBOTTOM) + ffloorflags |= FF_BLOCKPLAYER; + + TAG_ITER_SECTORS(0, lines[i].args[0], s) + { + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers); + fflr->busttype = busttype; + fflr->specialflags = bustflags; + fflr->busttag = lines[i].args[4]; + } + break; + } + case 257: // Quicksand + ffloorflags = FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES; + if (!(lines[i].args[1])) + ffloorflags |= FF_RIPPLE; + + TAG_ITER_SECTORS(0, lines[i].args[0], s) + { + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, ffloorflags, secthinkers); + fflr->sinkspeed = abs(lines[i].args[2]) << (FRACBITS - 1); + fflr->friction = abs(lines[i].args[3]) << (FRACBITS - 6); + } + break; + + case 258: // Laser block + ffloorflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT; + P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[2] & TMFL_NOBOSSES)); + if (lines[i].args[2] & TMFL_SPLAT) + ffloorflags |= FF_SPLAT; + P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + break; + + case 259: // Custom FOF + TAG_ITER_SECTORS(0, lines[i].args[0], s) + { + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], lines[i].args[2], secthinkers); + if (!udmf) // Ugly backwards compatibility stuff + { + if (lines[i].args[2] & FF_QUICKSAND) + { + fflr->sinkspeed = abs(lines[i].dx) >> 1; + fflr->friction = abs(lines[i].dy) >> 6; + } + if (lines[i].args[2] & FF_BUSTUP) + { + switch (lines[i].args[3] % TMFB_ONLYBOTTOM) + { + case TMFB_TOUCH: + fflr->busttype = BT_TOUCH; + break; + case TMFB_SPIN: + fflr->busttype = BT_SPINBUST; + break; + case TMFB_REGULAR: + fflr->busttype = BT_REGULAR; + break; + case TMFB_STRONG: + fflr->busttype = BT_STRONG; + break; + } + + if (lines[i].args[3] & TMFB_ONLYBOTTOM) + fflr->specialflags |= FS_ONLYBOTTOM; + if (lines[i].flags & ML_EFFECT4) + fflr->specialflags |= FS_PUSHABLES; + if (lines[i].flags & ML_EFFECT5) + { + fflr->specialflags |= FS_EXECUTOR; + fflr->busttag = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + } + } + } + } + break; + + case 260: // GZDoom-like 3D Floor. + { + UINT8 dtype = lines[i].args[1] & 3; + UINT8 dflags1 = lines[i].args[1] - dtype; + UINT8 dflags2 = lines[i].args[2]; + UINT8 dopacity = lines[i].args[3]; + boolean isfog = false; + + if (dtype == 0) + dtype = 1; + + ffloorflags = FF_EXISTS; + + if (dflags2 & 1) ffloorflags |= FF_NOSHADE; // Disable light effects (Means no shadowcast) + if (dflags2 & 2) ffloorflags |= FF_DOUBLESHADOW; // Restrict light inside (Means doubleshadow) + if (dflags2 & 4) isfog = true; // Fog effect (Explicitly render like a fog block) + + if (dflags1 & 4) ffloorflags |= FF_BOTHPLANES|FF_ALLSIDES; // Render-inside + if (dflags1 & 16) ffloorflags |= FF_INVERTSIDES|FF_INVERTPLANES; // Invert visibility rules + + // Fog block + if (isfog) + ffloorflags |= FF_RENDERALL|FF_CUTEXTRA|FF_CUTSPRITES|FF_BOTHPLANES|FF_EXTRA|FF_FOG|FF_INVERTPLANES|FF_ALLSIDES|FF_INVERTSIDES; + else + { + ffloorflags |= FF_RENDERALL; + + // Solid + if (dtype == 1) + ffloorflags |= FF_SOLID|FF_CUTLEVEL; + // Water + else if (dtype == 2) + ffloorflags |= FF_SWIMMABLE|FF_CUTEXTRA|FF_CUTSPRITES|FF_EXTRA|FF_RIPPLE; + // Intangible + else if (dtype == 3) + ffloorflags |= FF_CUTEXTRA|FF_CUTSPRITES|FF_EXTRA; + } + + // Non-opaque + if (dopacity < 255) + { + // Invisible + if (dopacity == 0) + { + // True invisible + if (ffloorflags & FF_NOSHADE) + ffloorflags &= ~(FF_RENDERALL|FF_CUTEXTRA|FF_CUTSPRITES|FF_EXTRA|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTLEVEL); + // Shadow block + else + { + ffloorflags |= FF_CUTSPRITES; + ffloorflags &= ~(FF_RENDERALL|FF_CUTEXTRA|FF_EXTRA|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTLEVEL); + } + } + else + { + ffloorflags |= FF_TRANSLUCENT|FF_CUTEXTRA|FF_EXTRA; + ffloorflags &= ~FF_CUTLEVEL; + } + } + + P_AddFakeFloorsByLine(i, dopacity, ffloorflags, secthinkers); + } + break; + + case 300: // Linedef executor (combines with sector special 974/975) and commands + case 302: + case 303: + case 304: + + // Charability linedef executors + case 305: + case 307: + break; + + case 308: // Race-only linedef executor. Triggers once. + if (!(gametyperules & GTR_RACE)) + lines[i].special = 0; + break; + + // Linedef executor triggers for CTF teams. + case 309: + case 311: + if (!(gametyperules & GTR_TEAMFLAGS)) + lines[i].special = 0; + break; + + // Each time executors + case 306: + case 301: + case 310: + case 312: + case 332: + case 335: + P_AddEachTimeThinker(&lines[i]); + break; + + // No More Enemies Linedef Exec + case 313: + P_AddNoEnemiesThinker(&lines[i]); + break; + + // Pushable linedef executors (count # of pushables) + case 314: + case 315: + break; + + // Unlock trigger executors + case 317: + case 318: + break; + case 319: + case 320: + break; + + // Trigger on X calls + case 321: + case 322: + if (lines[i].flags & ML_NOCLIMB && sides[lines[i].sidenum[0]].rowoffset > 0) // optional "starting" count + lines[i].callcount = sides[lines[i].sidenum[0]].rowoffset>>FRACBITS; + else + lines[i].callcount = sides[lines[i].sidenum[0]].textureoffset>>FRACBITS; + if (lines[i].special == 322) // Each time + P_AddEachTimeThinker(&lines[i]); + break; + + // NiGHTS trigger executors + case 323: + case 324: + case 325: + case 326: + case 327: + case 328: + case 329: + case 330: + break; + + // Skin trigger executors + case 331: + case 333: + break; + + // Object dye executors + case 334: + case 336: + break; + + case 399: // Linedef execute on map load + // This is handled in P_RunLevelLoadExecutors. + break; + + case 400: + case 401: + case 402: + case 403: + case 404: + case 405: + case 406: + case 407: + case 408: + case 409: + case 410: + case 411: + case 412: + case 413: + case 414: + case 415: + case 416: + case 417: + case 418: + case 419: + case 420: + case 421: + case 422: + case 423: + case 424: + case 425: + case 426: + case 427: + case 428: + case 429: + case 430: + case 431: + break; + + case 449: // Enable bosses with parameter + { + INT32 bossid = sides[*lines[i].sidenum].textureoffset>>FRACBITS; + if (bossid & ~15) // if any bits other than first 16 are set + { + CONS_Alert(CONS_WARNING, + M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"), + tag); + break; + } + if (!(lines[i].flags & ML_NOCLIMB)) + { + bossdisabled |= (1<>FRACBITS); + break; + + case 603: // Adjustable flickering light + sec = sides[*lines[i].sidenum].sector - sectors; + TAG_ITER_SECTORS(tag, s) + P_SpawnAdjustableFireFlicker(§ors[sec], §ors[s], + P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS); + break; + + case 604: // Adjustable Blinking Light (unsynchronized) + sec = sides[*lines[i].sidenum].sector - sectors; + TAG_ITER_SECTORS(tag, s) + P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], + abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, false); + break; + + case 605: // Adjustable Blinking Light (synchronized) + sec = sides[*lines[i].sidenum].sector - sectors; + TAG_ITER_SECTORS(tag, s) + P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], + abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, true); + break; + + case 606: // HACK! Copy colormaps. Just plain colormaps. + TAG_ITER_SECTORS(lines[i].args[0], s) + { + extracolormap_t *exc; + + if (sectors[s].colormap_protected) + continue; + + if (!udmf) + exc = sides[lines[i].sidenum[0]].colormap_data; + else + { + if (!lines[i].args[1]) + exc = lines[i].frontsector->extra_colormap; + else + { + INT32 sourcesec = Tag_Iterate_Sectors(lines[i].args[1], 0); + if (sourcesec == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 606: Can't find sector with source colormap (tag %d)!\n", lines[i].args[1]); + return; + } + exc = sectors[sourcesec].extra_colormap; + } + } + sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = exc; + } + break; + + default: + break; + } + } + + // And another round, this time with all FOFs already created + for (i = 0; i < numlines; i++) + { + switch (lines[i].special) + { + INT32 s; + INT32 l; + + case 74: // Make FOF bustable + { + UINT8 busttype = BT_REGULAR; + ffloorspecialflags_e bustflags = 0; + + if (!udmf) + break; + + switch (lines[i].args[1]) + { + case TMFB_TOUCH: + busttype = BT_TOUCH; + break; + case TMFB_SPIN: + busttype = BT_SPINBUST; + break; + case TMFB_REGULAR: + busttype = BT_REGULAR; + break; + case TMFB_STRONG: + busttype = BT_STRONG; + break; + } + + if (lines[i].args[2] & TMFB_PUSHABLES) + bustflags |= FS_PUSHABLES; + if (lines[i].args[2] & TMFB_EXECUTOR) + bustflags |= FS_EXECUTOR; + if (lines[i].args[2] & TMFB_ONLYBOTTOM) + bustflags |= FS_ONLYBOTTOM; + + TAG_ITER_LINES(0, lines[i].args[0], l) + { + TAG_ITER_DECLARECOUNTER(1); + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + TAG_ITER_SECTORS(1, lines[l].args[0], s) + { + ffloor_t *rover; + + for (rover = sectors[s].ffloors; rover; rover = rover->next) + { + if (rover->master != lines + l) + continue; + + rover->flags |= FF_BUSTUP; + rover->spawnflags |= FF_BUSTUP; + rover->busttype = busttype; + rover->specialflags &= ~FS_BUSTMASK; + rover->specialflags |= bustflags; + rover->busttag = lines[i].args[3]; + CheckForBustableBlocks = true; + break; + } + } + } + break; + } + + case 75: // Make FOF quicksand + { + if (!udmf) + break; + TAG_ITER_LINES(0, lines[i].args[0], l) + { + TAG_ITER_DECLARECOUNTER(1); + if (lines[l].special < 100 || lines[l].special >= 300) + continue; + + TAG_ITER_SECTORS(1, lines[l].args[0], s) + { + ffloor_t *rover; + + for (rover = sectors[s].ffloors; rover; rover = rover->next) + { + if (rover->master != lines + l) + continue; + + rover->flags |= FF_QUICKSAND; + rover->spawnflags |= FF_QUICKSAND; + rover->sinkspeed = abs(lines[i].args[1]) << (FRACBITS - 1); + rover->friction = abs(lines[i].args[2]) << (FRACBITS - 6); + CheckForQuicksand = true; + break; + } + } + } + break; + } + + case 76: // Make FOF bouncy + { + if (udmf) + { + TAG_ITER_LINES(0, lines[i].args[0], l) + P_MakeFOFBouncy(lines + i, lines + l); + } + else + { + TAG_ITER_SECTORS(0, lines[i].args[0], s) + for (j = 0; (unsigned)j < sectors[s].linecount; j++) + P_MakeFOFBouncy(lines + i, sectors[s].lines[j]); + } + break; + } + } + } + + + + + + // Allocate each list + for (i = 0; i < numsectors; i++) + if(secthinkers[i].thinkers) + Z_Free(secthinkers[i].thinkers); + + Z_Free(secthinkers); + + // haleyjd 02/20/06: spawn polyobjects + Polyobj_InitLevel(); + + for (i = 0; i < numlines; i++) + { + switch (lines[i].special) + { + case 30: // Polyobj_Flag + PolyFlag(&lines[i]); + break; + + case 31: // Polyobj_Displace + PolyDisplace(&lines[i]); + break; + + case 32: // Polyobj_RotDisplace + PolyRotDisplace(&lines[i]); + break; + } + } + + P_RunLevelLoadExecutors(); +} + +/** Adds 3Dfloors as appropriate based on a common control linedef. + * + * \param line Control linedef to use. + * \param alpha Alpha value (0-255). + * \param ffloorflags 3Dfloor flags to use. + * \param secthkiners Lists of thinkers sorted by sector. May be NULL. + * \sa P_SpawnSpecials, P_AddFakeFloor + * \author Graue + */ +static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorflags, thinkerlist_t *secthinkers) +{ + INT32 s; + mtag_t tag = lines[line].args[0]; + size_t sec = sides[*lines[line].sidenum].sector-sectors; + +<<<<<<< HEAD + TAG_ITER_SECTORS(0, tag, s) + P_AddFakeFloor(§ors[s], §ors[sec], lines+line, alpha, ffloorflags, secthinkers); +======= + line_t* li = lines + line; + TAG_ITER_SECTORS(tag, s) + P_AddFakeFloor(§ors[s], §ors[sec], li, ffloorflags, secthinkers); +>>>>>>> next +} + +/* + SoM: 3/8/2000: General scrolling functions. + T_Scroll, + Add_Scroller, + Add_WallScroller, + P_SpawnScrollers +*/ + +// helper function for T_Scroll +static void P_DoScrollMove(mobj_t *thing, fixed_t dx, fixed_t dy, INT32 exclusive) +{ + fixed_t fuckaj = 0; // Nov 05 14:12:08 <+MonsterIestyn> I've heard of explicitly defined variables but this is ridiculous + if (thing->player) + { + if (!(dx | dy)) + { + thing->player->cmomx = 0; + thing->player->cmomy = 0; + } + else + { + thing->player->cmomx += dx; + thing->player->cmomy += dy; + thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); + thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); + } + } + + if (thing->player && (thing->player->pflags & PF_SPINNING) && (thing->player->rmomx || thing->player->rmomy) && !(thing->player->pflags & PF_STARTDASH)) + fuckaj = FixedDiv(549*ORIG_FRICTION,500*FRACUNIT); + else if (thing->friction != ORIG_FRICTION) + fuckaj = thing->friction; + + if (fuckaj) { + // refactor thrust for new friction + dx = FixedDiv(dx, CARRYFACTOR); + dy = FixedDiv(dy, CARRYFACTOR); + + dx = FixedMul(dx, FRACUNIT-fuckaj); + dy = FixedMul(dy, FRACUNIT-fuckaj); + } + + thing->momx += dx; + thing->momy += dy; + + if (exclusive) + thing->eflags |= MFE_PUSHED; +} + +/** Processes an active scroller. + * This function, with the help of r_plane.c and r_bsp.c, supports generalized + * scrolling floors and walls, with optional mobj-carrying properties, e.g. + * conveyor belts, rivers, etc. A linedef with a special type affects all + * tagged sectors the same way, by creating scrolling and/or object-carrying + * properties. Multiple linedefs may be used on the same sector and are + * cumulative, although the special case of scrolling a floor and carrying + * things on it requires only one linedef. + * + * The linedef's direction determines the scrolling direction, and the + * linedef's length determines the scrolling speed. This was designed so an + * edge around a sector can be used to control the direction of the sector's + * scrolling, which is usually what is desired. + * + * \param s Thinker for the scroller to process. + * \todo Split up into multiple functions. + * \todo Use attached lists to make ::sc_carry_ceiling case faster and + * cleaner. + * \sa Add_Scroller, Add_WallScroller, P_SpawnScrollers + * \author Steven McGranahan + * \author Graue + */ +void T_Scroll(scroll_t *s) +{ + fixed_t dx = s->dx, dy = s->dy; + boolean is3dblock = false; + + if (s->control != -1) + { // compute scroll amounts based on a sector's height changes + fixed_t height = sectors[s->control].floorheight + + sectors[s->control].ceilingheight; + fixed_t delta = height - s->last_height; + s->last_height = height; + dx = FixedMul(dx, delta); + dy = FixedMul(dy, delta); + } + + if (s->accel) + { + s->vdx = dx += s->vdx; + s->vdy = dy += s->vdy; + } + +// if (!(dx | dy)) // no-op if both (x,y) offsets 0 +// return; + + switch (s->type) + { + side_t *side; + sector_t *sec; + fixed_t height; + msecnode_t *node; + mobj_t *thing; + line_t *line; + size_t i; + INT32 sect; + ffloor_t *rover; + + case sc_side: // scroll wall texture + side = sides + s->affectee; + side->textureoffset += dx; + side->rowoffset += dy; + break; + + case sc_floor: // scroll floor texture + sec = sectors + s->affectee; + sec->floor_xoffs += dx; + sec->floor_yoffs += dy; + break; + + case sc_ceiling: // scroll ceiling texture + sec = sectors + s->affectee; + sec->ceiling_xoffs += dx; + sec->ceiling_yoffs += dy; + break; + + case sc_carry: + sec = sectors + s->affectee; + height = sec->floorheight; + + // sec is the control sector, find the real sector(s) to use + for (i = 0; i < sec->linecount; i++) + { + line = sec->lines[i]; + + if (line->special < 100 || line->special >= 300) + is3dblock = false; + else + is3dblock = true; + + if (!is3dblock) + continue; + + TAG_ITER_SECTORS(Tag_FGet(&line->tags), sect) + { + sector_t *psec; + psec = sectors + sect; + + // Find the FOF corresponding to the control linedef + for (rover = psec->ffloors; rover; rover = rover->next) + { + if (rover->master == sec->lines[i]) + break; + } + + if (!rover) // This should be impossible, but don't complain if it is the case somehow + continue; + + if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there + continue; + + for (node = psec->touching_thinglist; node; node = node->m_thinglist_next) + { + thing = node->m_thing; + + if (thing->eflags & MFE_PUSHED) // Already pushed this tic by an exclusive pusher. + continue; + + height = P_GetSpecialBottomZ(thing, sec, psec); + + if (!(thing->flags & MF_NOCLIP)) // Thing must be clipped + if (!(thing->flags & MF_NOGRAVITY || thing->z+thing->height != height)) // Thing must a) be non-floating and have z+height == height + { + // Move objects only if on floor + // non-floating, and clipped. + P_DoScrollMove(thing, dx, dy, s->exclusive); + } + } // end of for loop through touching_thinglist + } // end of loop through sectors + } + + if (!is3dblock) + { + for (node = sec->touching_thinglist; node; node = node->m_thinglist_next) + { + thing = node->m_thing; + + if (thing->eflags & MFE_PUSHED) + continue; + + height = P_GetSpecialBottomZ(thing, sec, sec); + + if (!(thing->flags & MF_NOCLIP) && + (!(thing->flags & MF_NOGRAVITY || thing->z > height))) + { + // Move objects only if on floor or underwater, + // non-floating, and clipped. + P_DoScrollMove(thing, dx, dy, s->exclusive); + } + } + } + break; + + case sc_carry_ceiling: // carry on ceiling (FOF scrolling) + sec = sectors + s->affectee; + height = sec->ceilingheight; + + // sec is the control sector, find the real sector(s) to use + for (i = 0; i < sec->linecount; i++) + { + line = sec->lines[i]; + if (line->special < 100 || line->special >= 300) + is3dblock = false; + else + is3dblock = true; + + if (!is3dblock) + continue; + TAG_ITER_SECTORS(Tag_FGet(&line->tags), sect) + { + sector_t *psec; + psec = sectors + sect; + + // Find the FOF corresponding to the control linedef + for (rover = psec->ffloors; rover; rover = rover->next) + { + if (rover->master == sec->lines[i]) + break; + } + + if (!rover) // This should be impossible, but don't complain if it is the case somehow + continue; + + if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there + continue; + + for (node = psec->touching_thinglist; node; node = node->m_thinglist_next) + { + thing = node->m_thing; + + if (thing->eflags & MFE_PUSHED) + continue; + + height = P_GetSpecialTopZ(thing, sec, psec); + + if (!(thing->flags & MF_NOCLIP)) // Thing must be clipped + if (!(thing->flags & MF_NOGRAVITY || thing->z != height))// Thing must a) be non-floating and have z == height + { + // Move objects only if on floor or underwater, + // non-floating, and clipped. + P_DoScrollMove(thing, dx, dy, s->exclusive); + } + } // end of for loop through touching_thinglist + } // end of loop through sectors + } + + if (!is3dblock) + { + for (node = sec->touching_thinglist; node; node = node->m_thinglist_next) + { + thing = node->m_thing; + + if (thing->eflags & MFE_PUSHED) + continue; + + height = P_GetSpecialTopZ(thing, sec, sec); + + if (!(thing->flags & MF_NOCLIP) && + (!(thing->flags & MF_NOGRAVITY || thing->z+thing->height < height))) + { + // Move objects only if on floor or underwater, + // non-floating, and clipped. + P_DoScrollMove(thing, dx, dy, s->exclusive); + } + } + } + break; // end of sc_carry_ceiling + } // end of switch +} + +/** Adds a generalized scroller to the thinker list. + * + * \param type The enumerated type of scrolling. + * \param dx x speed of scrolling or its acceleration. + * \param dy y speed of scrolling or its acceleration. + * \param control Sector whose heights control this scroller's effect + * remotely, or -1 if there is no control sector. + * \param affectee Index of the affected object, sector or sidedef. + * \param accel Nonzero for an accelerative effect. + * \sa Add_WallScroller, P_SpawnScrollers, T_Scroll + */ +static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT32 affectee, INT32 accel, INT32 exclusive) +{ + scroll_t *s = Z_Calloc(sizeof *s, PU_LEVSPEC, NULL); + s->thinker.function.acp1 = (actionf_p1)T_Scroll; + s->type = type; + s->dx = dx; + s->dy = dy; + s->accel = accel; + s->exclusive = exclusive; + s->vdx = s->vdy = 0; + if ((s->control = control) != -1) + s->last_height = sectors[control].floorheight + sectors[control].ceilingheight; + s->affectee = affectee; + P_AddThinker(THINK_MAIN, &s->thinker); +} + +/** Initializes the scrollers. + * + * \todo Get rid of all the magic numbers. + * \sa P_SpawnSpecials, Add_Scroller, Add_WallScroller + */ +static void P_SpawnScrollers(void) +{ + size_t i; + line_t *l = lines; + mtag_t tag; + + for (i = 0; i < numlines; i++, l++) + { + fixed_t dx = l->dx >> SCROLL_SHIFT; // direction and speed of scrolling + fixed_t dy = l->dy >> SCROLL_SHIFT; + INT32 control = -1, accel = 0; // no control sector or acceleration + INT32 special = l->special; + + tag = Tag_FGet(&l->tags); + + // These types are same as the ones they get set to except that the + // first side's sector's heights cause scrolling when they change, and + // this linedef controls the direction and speed of the scrolling. The + // most complicated linedef since donuts, but powerful :) + + if (special == 515 || special == 512 || special == 522 || special == 532 || special == 504) // displacement scrollers + { + special -= 2; + control = (INT32)(sides[*l->sidenum].sector - sectors); + } + else if (special == 514 || special == 511 || special == 521 || special == 531 || special == 503) // accelerative scrollers + { + special--; + accel = 1; + control = (INT32)(sides[*l->sidenum].sector - sectors); + } + else if (special == 535 || special == 525) // displacement scrollers + { + special -= 2; + control = (INT32)(sides[*l->sidenum].sector - sectors); + } + else if (special == 534 || special == 524) // accelerative scrollers + { + accel = 1; + special--; + control = (INT32)(sides[*l->sidenum].sector - sectors); + } + + switch (special) + { + register INT32 s; + + case 513: // scroll effect ceiling + case 533: // scroll and carry objects on ceiling + TAG_ITER_SECTORS(tag, s) + Add_Scroller(sc_ceiling, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); + if (special != 533) + break; + /* FALLTHRU */ + + case 523: // carry objects on ceiling + dx = FixedMul(dx, CARRYFACTOR); + dy = FixedMul(dy, CARRYFACTOR); + TAG_ITER_SECTORS(tag, s) + Add_Scroller(sc_carry_ceiling, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); + break; + + case 510: // scroll effect floor + case 530: // scroll and carry objects on floor + TAG_ITER_SECTORS(tag, s) + Add_Scroller(sc_floor, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); + if (special != 530) + break; + /* FALLTHRU */ + + case 520: // carry objects on floor + dx = FixedMul(dx, CARRYFACTOR); + dy = FixedMul(dy, CARRYFACTOR); + TAG_ITER_SECTORS(tag, s) + Add_Scroller(sc_carry, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); + break; + + // scroll wall according to linedef + // (same direction and speed as scrolling floors) + case 502: + { + TAG_ITER_LINES(tag, s) + if (s != (INT32)i) + { + if (l->flags & ML_EFFECT2) // use texture offsets instead + { + dx = sides[l->sidenum[0]].textureoffset; + dy = sides[l->sidenum[0]].rowoffset; + } + if (l->flags & ML_EFFECT3) + { + if (lines[s].sidenum[1] != 0xffff) + Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[1], accel, 0); + } + else + Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[0], accel, 0); + } + break; + } + + case 505: + s = lines[i].sidenum[0]; + Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, s, accel, 0); + break; + + case 506: + s = lines[i].sidenum[1]; + + if (s != 0xffff) + Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, lines[i].sidenum[0], accel, 0); + else + CONS_Debug(DBG_GAMELOGIC, "Line special 506 (line #%s) missing back side!\n", sizeu1(i)); + break; + + case 507: + s = lines[i].sidenum[0]; + + if (lines[i].sidenum[1] != 0xffff) + Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, lines[i].sidenum[1], accel, 0); + else + CONS_Debug(DBG_GAMELOGIC, "Line special 507 (line #%s) missing back side!\n", sizeu1(i)); + break; + + case 508: + s = lines[i].sidenum[1]; + + if (s != 0xffff) + Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, s, accel, 0); + else + CONS_Debug(DBG_GAMELOGIC, "Line special 508 (line #%s) missing back side!\n", sizeu1(i)); + break; + + case 500: // scroll first side + Add_Scroller(sc_side, FRACUNIT, 0, -1, lines[i].sidenum[0], accel, 0); + break; + + case 501: // jff 1/30/98 2-way scroll + Add_Scroller(sc_side, -FRACUNIT, 0, -1, lines[i].sidenum[0], accel, 0); + break; + } + } +} + +/** Adds master appear/disappear thinker. + * + * \param appeartime tics to be existent + * \param disappeartime tics to be nonexistent + * \param sector pointer to control sector + */ +static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline) +{ + disappear_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); + + d->thinker.function.acp1 = (actionf_p1)T_Disappear; + d->appeartime = appeartime; + d->disappeartime = disappeartime; + d->offset = offset; + d->affectee = line; + d->sourceline = sourceline; + d->exists = true; + d->timer = 1; + + P_AddThinker(THINK_MAIN, &d->thinker); +} + +/** Makes a FOF appear/disappear + * + * \param d Disappear thinker. + * \sa Add_MasterDisappearer + */ +void T_Disappear(disappear_t *d) +{ + if (d->offset && !d->exists) + { + d->offset--; + return; + } + + if (--d->timer <= 0) + { + ffloor_t *rover; + register INT32 s; + mtag_t afftag = Tag_FGet(&lines[d->affectee].tags); + + TAG_ITER_SECTORS(afftag, s) + { + for (rover = sectors[s].ffloors; rover; rover = rover->next) + { + if (rover->master != &lines[d->affectee]) + continue; + + if (d->exists) + rover->flags &= ~FF_EXISTS; + else + { + rover->flags |= FF_EXISTS; + + if (!(lines[d->sourceline].flags & ML_NOCLIMB)) + { + sectors[s].soundorg.z = P_GetFFloorTopZAt(rover, sectors[s].soundorg.x, sectors[s].soundorg.y); + S_StartSound(§ors[s].soundorg, sfx_appear); + } + } + } + sectors[s].moved = true; + P_RecalcPrecipInSector(§ors[s]); + } + + if (d->exists) + { + d->timer = d->disappeartime; + d->exists = false; + } + else + { + d->timer = d->appeartime; + d->exists = true; + } + } +} + +/** Removes fadingdata from FOF control sector + * + * \param line line to search for target faders + * \param data pointer to set new fadingdata to. Can be NULL to erase. + */ +static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize) +{ + fade_t *fadingdata = (fade_t *)rover->fadingdata; + // find any existing thinkers and remove them, then replace with new data + if (fadingdata != data) + { + if (fadingdata) + { + if (finalize) + P_FadeFakeFloor(rover, + fadingdata->sourcevalue, + fadingdata->alpha >= fadingdata->destvalue ? + fadingdata->alpha - 1 : // trigger fade-out finish + fadingdata->alpha + 1, // trigger fade-in finish + 0, + fadingdata->ticbased, + &fadingdata->timer, + fadingdata->doexists, + fadingdata->dotranslucent, + fadingdata->dolighting, + fadingdata->docolormap, + fadingdata->docollision, + fadingdata->doghostfade, + fadingdata->exactalpha); + rover->alpha = fadingdata->alpha; + + if (fadingdata->dolighting) + P_RemoveLighting(§ors[rover->secnum]); + + if (fadingdata->docolormap) + P_ResetColormapFader(§ors[rover->secnum]); + + P_RemoveThinker(&fadingdata->thinker); + } + + rover->fadingdata = data; + } +} + +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha) +{ + boolean stillfading = false; + INT32 alpha; + fade_t *fadingdata = (fade_t *)rover->fadingdata; + (void)docolormap; // *shrug* maybe we can use this in the future. For now, let's be consistent with our other function params + + if (rover->master->special == 258) // Laser block + return false; + + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + if (dotranslucent && + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->flags & FF_FOG) && // do not include fog + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + + if (fadingdata) + alpha = fadingdata->alpha; + else + alpha = rover->alpha; + + // routines specific to fade in and fade out + if (!ticbased && alpha == destvalue) + return stillfading; + else if (alpha > destvalue) // fade out + { + // finish fading out + if (speed < 1 || (!ticbased && alpha - speed <= destvalue + speed) || + (ticbased && (--(*timer) <= 0 || alpha <= destvalue))) + { + alpha = destvalue; + + if (docollision) + { + if (rover->spawnflags & FF_SOLID) + rover->flags &= ~FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags &= ~FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags &= ~FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags &= ~FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags &= ~FF_MARIO; + } + } + else // continue fading out + { + if (!ticbased) + alpha -= speed; + else + { + INT16 delta = abs(destvalue - sourcevalue); + fixed_t factor = min(FixedDiv(speed - (*timer), speed), 1*FRACUNIT); + alpha = max(min(alpha, sourcevalue - (INT16)FixedMul(delta, factor)), destvalue); + } + stillfading = true; + } + } + else // fade in + { + // finish fading in + if (speed < 1 || (!ticbased && alpha + speed >= destvalue - speed) || + (ticbased && (--(*timer) <= 0 || alpha >= destvalue))) + { + alpha = destvalue; + + if (docollision) + { + if (rover->spawnflags & FF_SOLID) + rover->flags |= FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags |= FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags |= FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags |= FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags |= FF_MARIO; + } + } + else // continue fading in + { + if (!ticbased) + alpha += speed; + else + { + INT16 delta = abs(destvalue - sourcevalue); + fixed_t factor = min(FixedDiv(speed - (*timer), speed), 1*FRACUNIT); + alpha = min(max(alpha, sourcevalue + (INT16)FixedMul(delta, factor)), destvalue); + } + stillfading = true; + } + } + + // routines common to both fade in and fade out + if (!stillfading) + { + if (doexists && !(rover->spawnflags & FF_BUSTUP)) + { + if (alpha <= 1) + rover->flags &= ~FF_EXISTS; + else + rover->flags |= FF_EXISTS; + + // Re-render lighting at end of fade + if (dolighting && !(rover->spawnflags & FF_NOSHADE) && !(rover->flags & FF_EXISTS)) + rover->target->moved = true; + } + + if (dotranslucent && !(rover->flags & FF_FOG)) + { + if (alpha >= 256) + { + if (!(rover->flags & FF_CUTSOLIDS) && + (rover->spawnflags & FF_CUTSOLIDS)) + { + rover->flags |= FF_CUTSOLIDS; + rover->target->moved = true; + } + + rover->flags &= ~FF_TRANSLUCENT; + } + else + { + rover->flags |= FF_TRANSLUCENT; + + if ((rover->flags & FF_CUTSOLIDS) && + (rover->spawnflags & FF_CUTSOLIDS)) + { + rover->flags &= ~FF_CUTSOLIDS; + rover->target->moved = true; + } + } + + if ((rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES)) + { + if (rover->alpha > 1) + rover->flags |= FF_RENDERALL; + else + rover->flags &= ~FF_RENDERALL; + } + } + } + else + { + if (doexists && !(rover->spawnflags & FF_BUSTUP)) + { + // Re-render lighting if we haven't yet set FF_EXISTS (beginning of fade) + if (dolighting && !(rover->spawnflags & FF_NOSHADE) && !(rover->flags & FF_EXISTS)) + rover->target->moved = true; + + rover->flags |= FF_EXISTS; + } + + if (dotranslucent && !(rover->flags & FF_FOG)) + { + rover->flags |= FF_TRANSLUCENT; + + if ((rover->flags & FF_CUTSOLIDS) && + (rover->spawnflags & FF_CUTSOLIDS)) + { + rover->flags &= ~FF_CUTSOLIDS; + rover->target->moved = true; + } + + if ((rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES)) + rover->flags |= FF_RENDERALL; + } + + if (docollision) + { + if (doghostfade) // remove collision flags during fade + { + if (rover->spawnflags & FF_SOLID) + rover->flags &= ~FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags &= ~FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags &= ~FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags &= ~FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags &= ~FF_MARIO; + } + else // keep collision during fade + { + if (rover->spawnflags & FF_SOLID) + rover->flags |= FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags |= FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags |= FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags |= FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags |= FF_MARIO; + } + } + } + + if (!(rover->flags & FF_FOG)) // don't set FOG alpha + { + if (!stillfading || exactalpha) + rover->alpha = alpha; + else // clamp fadingdata->alpha to software's alpha levels + { + if (alpha < 12) + rover->alpha = destvalue < 12 ? destvalue : 1; // Don't even draw it + else if (alpha < 38) + rover->alpha = destvalue >= 12 && destvalue < 38 ? destvalue : 25; + else if (alpha < 64) + rover->alpha = destvalue >=38 && destvalue < 64 ? destvalue : 51; + else if (alpha < 89) + rover->alpha = destvalue >= 64 && destvalue < 89 ? destvalue : 76; + else if (alpha < 115) + rover->alpha = destvalue >= 89 && destvalue < 115 ? destvalue : 102; + else if (alpha < 140) + rover->alpha = destvalue >= 115 && destvalue < 140 ? destvalue : 128; + else if (alpha < 166) + rover->alpha = destvalue >= 140 && destvalue < 166 ? destvalue : 154; + else if (alpha < 192) + rover->alpha = destvalue >= 166 && destvalue < 192 ? destvalue : 179; + else if (alpha < 217) + rover->alpha = destvalue >= 192 && destvalue < 217 ? destvalue : 204; + else if (alpha < 243) + rover->alpha = destvalue >= 217 && destvalue < 243 ? destvalue : 230; + else // Opaque + rover->alpha = destvalue >= 243 ? destvalue : 256; + } + } + + if (fadingdata) + fadingdata->alpha = alpha; + + return stillfading; +} + +/** Adds fake floor fader thinker. + * + * \param destvalue transparency value to fade to + * \param speed speed to fade by + * \param ticbased tic-based logic, speed = duration + * \param relative Destvalue is relative to rover->alpha + * \param doexists handle FF_EXISTS + * \param dotranslucent handle FF_TRANSLUCENT + * \param dolighting fade FOF light + * \param docollision handle interactive flags + * \param doghostfade no interactive flags during fading + * \param exactalpha use exact alpha values (opengl) + */ +static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, + INT16 destvalue, INT16 speed, boolean ticbased, boolean relative, + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha) +{ + fade_t *d; + + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + if (dotranslucent && + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + + // already equal, nothing to do + if (rover->alpha == max(1, min(256, relative ? rover->alpha + destvalue : destvalue))) + return; + + d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); + + d->thinker.function.acp1 = (actionf_p1)T_Fade; + d->rover = rover; + d->sectornum = (UINT32)sectornum; + d->ffloornum = (UINT32)ffloornum; + + d->alpha = d->sourcevalue = rover->alpha; + d->destvalue = max(1, min(256, relative ? rover->alpha + destvalue : destvalue)); // rover->alpha is 1-256 + + if (ticbased) + { + d->ticbased = true; + d->timer = d->speed = abs(speed); // use d->speed as total duration + } + else + { + d->ticbased = false; + d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker + d->timer = -1; + } + + d->doexists = doexists; + d->dotranslucent = dotranslucent; + d->dolighting = dolighting; + d->docolormap = docolormap; + d->docollision = docollision; + d->doghostfade = doghostfade; + d->exactalpha = exactalpha; + + // find any existing thinkers and remove them, then replace with new data + P_ResetFakeFloorFader(rover, d, false); + + // Set a separate thinker for shadow fading + if (dolighting && !(rover->flags & FF_NOSHADE)) + { + UINT16 lightdelta = abs(sectors[rover->secnum].spawn_lightlevel - rover->target->lightlevel); + fixed_t alphapercent = min(FixedDiv(d->destvalue, rover->spawnalpha), 1*FRACUNIT); // don't make darker than spawn_lightlevel + fixed_t adjustedlightdelta = FixedMul(lightdelta, alphapercent); + + if (rover->target->lightlevel >= sectors[rover->secnum].spawn_lightlevel) // fading out, get lighter + d->destlightlevel = rover->target->lightlevel - adjustedlightdelta; + else // fading in, get darker + d->destlightlevel = rover->target->lightlevel + adjustedlightdelta; + + P_FadeLightBySector(§ors[rover->secnum], + d->destlightlevel, + ticbased ? d->timer : + FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT, + true); + } + else + d->destlightlevel = -1; + + // Set a separate thinker for colormap fading + if (docolormap && !(rover->flags & FF_NOSHADE) && sectors[rover->secnum].spawn_extra_colormap && !sectors[rover->secnum].colormap_protected) + { + extracolormap_t *dest_exc, + *source_exc = sectors[rover->secnum].extra_colormap ? sectors[rover->secnum].extra_colormap : R_GetDefaultColormap(); + + INT32 colordelta = R_GetRgbaA(sectors[rover->secnum].spawn_extra_colormap->rgba); // alpha is from 0 + fixed_t alphapercent = min(FixedDiv(d->destvalue, rover->spawnalpha), 1*FRACUNIT); // don't make darker than spawn_lightlevel + fixed_t adjustedcolordelta = FixedMul(colordelta, alphapercent); + INT32 coloralpha; + + coloralpha = adjustedcolordelta; + + dest_exc = R_CopyColormap(sectors[rover->secnum].spawn_extra_colormap, false); + dest_exc->rgba = R_GetRgbaRGB(dest_exc->rgba) + R_PutRgbaA(coloralpha); + + if (!(d->dest_exc = R_GetColormapFromList(dest_exc))) + { + dest_exc->colormap = R_CreateLightTable(dest_exc); + R_AddColormapToList(dest_exc); + d->dest_exc = dest_exc; + } + else + Z_Free(dest_exc); + + // If fading from 0, set source_exc rgb same to dest_exc + if (!R_CheckDefaultColormap(d->dest_exc, true, false, false) + && R_CheckDefaultColormap(source_exc, true, false, false)) + { + extracolormap_t *exc = R_CopyColormap(source_exc, false); + exc->rgba = R_GetRgbaRGB(d->dest_exc->rgba) + R_PutRgbaA(R_GetRgbaA(source_exc->rgba)); + exc->fadergba = R_GetRgbaRGB(d->dest_exc->rgba) + R_PutRgbaA(R_GetRgbaA(source_exc->fadergba)); + + if (!(source_exc = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + source_exc = exc; + } + else + Z_Free(exc); + } + + Add_ColormapFader(§ors[rover->secnum], source_exc, d->dest_exc, true, + ticbased ? d->timer : + FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT); + } + + P_AddThinker(THINK_MAIN, &d->thinker); +} + +/** Makes a FOF fade + * + * \param d Fade thinker. + * \sa P_AddFakeFloorFader + */ +void T_Fade(fade_t *d) +{ + if (d->rover && !P_FadeFakeFloor(d->rover, d->sourcevalue, d->destvalue, d->speed, d->ticbased, &d->timer, + d->doexists, d->dotranslucent, d->dolighting, d->docolormap, d->docollision, d->doghostfade, d->exactalpha)) + { + // Finalize lighting, copypasta from P_AddFakeFloorFader + if (d->dolighting && !(d->rover->flags & FF_NOSHADE) && d->destlightlevel > -1) + sectors[d->rover->secnum].lightlevel = d->destlightlevel; + + // Finalize colormap + if (d->docolormap && !(d->rover->flags & FF_NOSHADE) && sectors[d->rover->secnum].spawn_extra_colormap) + sectors[d->rover->secnum].extra_colormap = d->dest_exc; + + P_RemoveFakeFloorFader(d->rover); + } +} + +static void P_ResetColormapFader(sector_t *sector) +{ + if (sector->fadecolormapdata) + { + // The thinker is the first member in all the action structs, + // so just let the thinker get freed, and that will free the whole + // structure. + P_RemoveThinker(&((elevator_t *)sector->fadecolormapdata)->thinker); + sector->fadecolormapdata = NULL; + } +} + +static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, + boolean ticbased, INT32 duration) +{ + fadecolormap_t *d; + + P_ResetColormapFader(sector); + + // nothing to do, set immediately + if (!duration || R_CheckEqualColormaps(source_exc, dest_exc, true, true, true)) + { + sector->extra_colormap = dest_exc; + return; + } + + d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); + d->thinker.function.acp1 = (actionf_p1)T_FadeColormap; + d->sector = sector; + d->source_exc = source_exc; + d->dest_exc = dest_exc; + + if (ticbased) + { + d->ticbased = true; + d->duration = d->timer = duration; + } + else + { + d->ticbased = false; + d->timer = 256; + d->duration = duration; // use as speed + } + + sector->fadecolormapdata = d; + P_AddThinker(THINK_MAIN, &d->thinker); +} + +void T_FadeColormap(fadecolormap_t *d) +{ + if ((d->ticbased && --d->timer <= 0) + || (!d->ticbased && (d->timer -= d->duration) <= 0)) // d->duration used as speed decrement + { + d->sector->extra_colormap = d->dest_exc; + P_ResetColormapFader(d->sector); + } + else + { + extracolormap_t *exc; + INT32 duration = d->ticbased ? d->duration : 256; + fixed_t factor = min(FixedDiv(duration - d->timer, duration), 1*FRACUNIT); + INT16 cr, cg, cb, ca, fadestart, fadeend, flags; + INT32 rgba, fadergba; + + // NULL failsafes (or intentionally set to signify default) + if (!d->sector->extra_colormap) + d->sector->extra_colormap = R_GetDefaultColormap(); + + if (!d->source_exc) + d->source_exc = R_GetDefaultColormap(); + + if (!d->dest_exc) + d->dest_exc = R_GetDefaultColormap(); + + // For each var (rgba + fadergba + params = 11 vars), we apply + // percentage fading: currentval = sourceval + (delta * percent of duration elapsed) + // delta is negative when fading out (destval is lower) + // max/min are used to ensure progressive calcs don't go backwards and to cap values to dest. + +#define APPLYFADE(dest, src, cur) (\ +(dest-src < 0) ? \ + max(\ + min(cur,\ + src + (INT16)FixedMul(dest-src, factor)),\ + dest)\ +: (dest-src > 0) ? \ + min(\ + max(cur,\ + src + (INT16)FixedMul(dest-src, factor)),\ + dest)\ +: \ + dest\ +) + + cr = APPLYFADE(R_GetRgbaR(d->dest_exc->rgba), R_GetRgbaR(d->source_exc->rgba), R_GetRgbaR(d->sector->extra_colormap->rgba)); + cg = APPLYFADE(R_GetRgbaG(d->dest_exc->rgba), R_GetRgbaG(d->source_exc->rgba), R_GetRgbaG(d->sector->extra_colormap->rgba)); + cb = APPLYFADE(R_GetRgbaB(d->dest_exc->rgba), R_GetRgbaB(d->source_exc->rgba), R_GetRgbaB(d->sector->extra_colormap->rgba)); + ca = APPLYFADE(R_GetRgbaA(d->dest_exc->rgba), R_GetRgbaA(d->source_exc->rgba), R_GetRgbaA(d->sector->extra_colormap->rgba)); + + rgba = R_PutRgbaRGBA(cr, cg, cb, ca); + + cr = APPLYFADE(R_GetRgbaR(d->dest_exc->fadergba), R_GetRgbaR(d->source_exc->fadergba), R_GetRgbaR(d->sector->extra_colormap->fadergba)); + cg = APPLYFADE(R_GetRgbaG(d->dest_exc->fadergba), R_GetRgbaG(d->source_exc->fadergba), R_GetRgbaG(d->sector->extra_colormap->fadergba)); + cb = APPLYFADE(R_GetRgbaB(d->dest_exc->fadergba), R_GetRgbaB(d->source_exc->fadergba), R_GetRgbaB(d->sector->extra_colormap->fadergba)); + ca = APPLYFADE(R_GetRgbaA(d->dest_exc->fadergba), R_GetRgbaA(d->source_exc->fadergba), R_GetRgbaA(d->sector->extra_colormap->fadergba)); + + fadergba = R_PutRgbaRGBA(cr, cg, cb, ca); + + fadestart = APPLYFADE(d->dest_exc->fadestart, d->source_exc->fadestart, d->sector->extra_colormap->fadestart); + fadeend = APPLYFADE(d->dest_exc->fadeend, d->source_exc->fadeend, d->sector->extra_colormap->fadeend); + flags = abs(factor) > FRACUNIT/2 ? d->dest_exc->flags : d->source_exc->flags; // set new flags halfway through fade + +#undef APPLYFADE + + ////////////////// + // setup new colormap + ////////////////// + + if (!(d->sector->extra_colormap = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags))) + { + exc = R_CreateDefaultColormap(false); + exc->fadestart = fadestart; + exc->fadeend = fadeend; + exc->flags = flags; + exc->rgba = rgba; + exc->fadergba = fadergba; + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + d->sector->extra_colormap = exc; + } + } +} + +/* + SoM: 3/8/2000: Friction functions start. + Add_Friction, + T_Friction, + P_SpawnFriction +*/ + +/** Adds friction thinker. + * + * \param friction Friction value, 0xe800 is normal. + * \param affectee Target sector. + * \param roverfriction FOF or not + * \sa T_Friction, P_SpawnFriction + */ +static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer) +{ + friction_t *f = Z_Calloc(sizeof *f, PU_LEVSPEC, NULL); + + f->thinker.function.acp1 = (actionf_p1)T_Friction; + f->friction = friction; + f->movefactor = movefactor; + f->affectee = affectee; + + if (referrer != -1) + { + f->roverfriction = true; + f->referrer = referrer; + } + else + f->roverfriction = false; + + P_AddThinker(THINK_MAIN, &f->thinker); +} + +/** Applies friction to all things in a sector. + * + * \param f Friction thinker. + * \sa Add_Friction + */ +void T_Friction(friction_t *f) +{ + sector_t *sec, *referrer = NULL; + mobj_t *thing; + msecnode_t *node; + + sec = sectors + f->affectee; + + // Get FOF control sector + if (f->roverfriction) + referrer = sectors + f->referrer; + + // Assign the friction value to players on the floor, non-floating, + // and clipped. Normally the object's friction value is kept at + // ORIG_FRICTION and this thinker changes it for icy or muddy floors. + + // When the object is straddling sectors with the same + // floorheight that have different frictions, use the lowest + // friction value (muddy has precedence over icy). + + node = sec->touching_thinglist; // things touching this sector + while (node) + { + thing = node->m_thing; + // apparently, all I had to do was comment out part of the next line and + // friction works for all mobj's + // (or at least MF_PUSHABLEs, which is all I care about anyway) + if (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) && thing->z == thing->floorz) + { + if (f->roverfriction) + { + if (thing->floorz != P_GetSpecialTopZ(thing, referrer, sec)) + { + node = node->m_thinglist_next; + continue; + } + + if ((thing->friction == ORIG_FRICTION) // normal friction? + || (f->friction < thing->friction)) + { + thing->friction = f->friction; + if (thing->player) + thing->movefactor = f->movefactor; + } + } + else if (P_GetSpecialBottomZ(thing, sec, sec) == thing->floorz && (thing->friction == ORIG_FRICTION // normal friction? + || f->friction < thing->friction)) + { + thing->friction = f->friction; + if (thing->player) + thing->movefactor = f->movefactor; + } + } + node = node->m_thinglist_next; + } +} + +/** Spawns all friction effects. + * + * \sa P_SpawnSpecials, Add_Friction + */ +static void P_SpawnFriction(void) +{ + size_t i; + line_t *l = lines; + mtag_t tag; + register INT32 s; + fixed_t strength; // frontside texture offset controls magnitude + fixed_t friction; // friction value to be applied during movement + INT32 movefactor; // applied to each player move to simulate inertia + + for (i = 0; i < numlines; i++, l++) + if (l->special == 540) + { + tag = Tag_FGet(&l->tags); + strength = sides[l->sidenum[0]].textureoffset>>FRACBITS; + if (strength > 0) // sludge + strength = strength*2; // otherwise, the maximum sludginess value is +967... + + // The following might seem odd. At the time of movement, + // the move distance is multiplied by 'friction/0x10000', so a + // higher friction value actually means 'less friction'. + friction = ORIG_FRICTION - (0x1EB8*strength)/0x80; // ORIG_FRICTION is 0xE800 + + if (friction > FRACUNIT) + friction = FRACUNIT; + if (friction < 0) + friction = 0; + + movefactor = FixedDiv(ORIG_FRICTION, friction); + if (movefactor < FRACUNIT) + movefactor = 8*movefactor - 7*FRACUNIT; + else + movefactor = FRACUNIT; + + TAG_ITER_SECTORS(tag, s) + Add_Friction(friction, movefactor, s, -1); + } +} + +/* + SoM: 3/8/2000: Push/Pull/Wind/Current functions. + Add_Pusher, + PIT_PushThing, + T_Pusher, + P_GetPushThing, + P_SpawnPushers +*/ + +#define PUSH_FACTOR 7 + +/** Adds a pusher. + * + * \param type Type of push/pull effect. + * \param x_mag X magnitude. + * \param y_mag Y magnitude. + * \param source For a point pusher/puller, the source object. + * \param affectee Target sector. + * \param referrer What sector set it + * \sa T_Pusher, P_GetPushThing, P_SpawnPushers + */ +static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider) +{ + pusher_t *p = Z_Calloc(sizeof *p, PU_LEVSPEC, NULL); + + p->thinker.function.acp1 = (actionf_p1)T_Pusher; + p->source = source; + p->type = type; + p->x_mag = x_mag>>FRACBITS; + p->y_mag = y_mag>>FRACBITS; + p->exclusive = exclusive; + p->slider = slider; + + if (referrer != -1) + { + p->roverpusher = true; + p->referrer = referrer; + } + else + p->roverpusher = false; + + // "The right triangle of the square of the length of the hypotenuse is equal to the sum of the squares of the lengths of the other two sides." + // "Bah! Stupid brains! Don't you know anything besides the Pythagorean Theorem?" - Earthworm Jim + if (type == p_downcurrent || type == p_upcurrent || type == p_upwind || type == p_downwind) + p->magnitude = P_AproxDistance(p->x_mag,p->y_mag)<<(FRACBITS-PUSH_FACTOR); + else + p->magnitude = P_AproxDistance(p->x_mag,p->y_mag); + if (source) // point source exist? + { + // where force goes to zero + if (type == p_push) + p->radius = AngleFixed(source->angle); + else + p->radius = (p->magnitude)<<(FRACBITS+1); + + p->x = p->source->x; + p->y = p->source->y; + p->z = p->source->z; + } + p->affectee = affectee; + P_AddThinker(THINK_MAIN, &p->thinker); +} + + +// PIT_PushThing determines the angle and magnitude of the effect. +// The object's x and y momentum values are changed. +static pusher_t *tmpusher; // pusher structure for blockmap searches + +/** Applies a point pusher/puller to a thing. + * + * \param thing Thing to be pushed. + * \return True if the thing was pushed. + * \todo Make a more robust P_BlockThingsIterator() so the hidden parameter + * ::tmpusher won't need to be used. + * \sa T_Pusher + */ +static inline boolean PIT_PushThing(mobj_t *thing) +{ + if (thing->eflags & MFE_PUSHED) + return false; + + if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG) + return false; + + if (!tmpusher->source) + return false; + + // Allow this to affect pushable objects at some point? + if (thing->player && (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) || thing->player->powers[pw_carry] == CR_NIGHTSMODE)) + { + INT32 dist; + INT32 speed; + INT32 sx, sy, sz; + + sx = tmpusher->x; + sy = tmpusher->y; + sz = tmpusher->z; + + // don't fade wrt Z if health & 2 (mapthing has multi flag) + if (tmpusher->source->health & 2) + dist = P_AproxDistance(thing->x - sx,thing->y - sy); + else + { + // Make sure the Z is in range + if (thing->z < sz - tmpusher->radius || thing->z > sz + tmpusher->radius) + return false; + + dist = P_AproxDistance(P_AproxDistance(thing->x - sx, thing->y - sy), + thing->z - sz); + } + + speed = (tmpusher->magnitude - ((dist>>FRACBITS)>>1))<<(FRACBITS - PUSH_FACTOR - 1); + + // If speed <= 0, you're outside the effective radius. You also have + // to be able to see the push/pull source point. + + // Written with bits and pieces of P_HomingAttack + if ((speed > 0) && (P_CheckSight(thing, tmpusher->source))) + { + if (thing->player->powers[pw_carry] != CR_NIGHTSMODE) + { + // only push wrt Z if health & 1 (mapthing has ambush flag) + if (tmpusher->source->health & 1) + { + fixed_t tmpmomx, tmpmomy, tmpmomz; + + tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed); + tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed); + tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed); + if (tmpusher->source->type == MT_PUSH) // away! + { + tmpmomx *= -1; + tmpmomy *= -1; + tmpmomz *= -1; + } + + thing->momx += tmpmomx; + thing->momy += tmpmomy; + thing->momz += tmpmomz; + + if (thing->player) + { + thing->player->cmomx += tmpmomx; + thing->player->cmomy += tmpmomy; + thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); + thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); + } + } + else + { + angle_t pushangle; + + pushangle = R_PointToAngle2(thing->x, thing->y, sx, sy); + if (tmpusher->source->type == MT_PUSH) + pushangle += ANGLE_180; // away + pushangle >>= ANGLETOFINESHIFT; + thing->momx += FixedMul(speed, FINECOSINE(pushangle)); + thing->momy += FixedMul(speed, FINESINE(pushangle)); + + if (thing->player) + { + thing->player->cmomx += FixedMul(speed, FINECOSINE(pushangle)); + thing->player->cmomy += FixedMul(speed, FINESINE(pushangle)); + thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); + thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); + } + } + } + else + { + //NiGHTS-specific handling. + //By default, pushes and pulls only affect the Z-axis. + //By having the ambush flag, it affects the X-axis. + //By having the object special flag, it affects the Y-axis. + fixed_t tmpmomx, tmpmomy, tmpmomz; + + if (tmpusher->source->health & 1) + tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed); + else + tmpmomx = 0; + + if (tmpusher->source->health & 2) + tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed); + else + tmpmomy = 0; + + tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed); + + if (tmpusher->source->type == MT_PUSH) // away! + { + tmpmomx *= -1; + tmpmomy *= -1; + tmpmomz *= -1; + } + + thing->momx += tmpmomx; + thing->momy += tmpmomy; + thing->momz += tmpmomz; + + if (thing->player) + { + thing->player->cmomx += tmpmomx; + thing->player->cmomy += tmpmomy; + thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); + thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); + } + } + } + } + + if (tmpusher->exclusive) + thing->eflags |= MFE_PUSHED; + + return true; +} + +/** Applies a pusher to all affected objects. + * + * \param p Thinker for the pusher effect. + * \todo Split up into multiple functions. + * \sa Add_Pusher, PIT_PushThing + */ +void T_Pusher(pusher_t *p) +{ + sector_t *sec, *referrer = NULL; + mobj_t *thing; + msecnode_t *node; + INT32 xspeed = 0,yspeed = 0; + INT32 xl, xh, yl, yh, bx, by; + INT32 radius; + //INT32 ht = 0; + boolean inFOF; + boolean touching; + boolean moved; + + xspeed = yspeed = 0; + + sec = sectors + p->affectee; + + // Be sure the special sector type is still turned on. If so, proceed. + // Else, bail out; the sector type has been changed on us. + + if (p->roverpusher) + { + referrer = §ors[p->referrer]; + + if (GETSECSPECIAL(referrer->special, 3) != 2) + return; + } + else if (GETSECSPECIAL(sec->special, 3) != 2) + return; + + // For constant pushers (wind/current) there are 3 situations: + // + // 1) Affected Thing is above the floor. + // + // Apply the full force if wind, no force if current. + // + // 2) Affected Thing is on the ground. + // + // Apply half force if wind, full force if current. + // + // 3) Affected Thing is below the ground (underwater effect). + // + // Apply no force if wind, full force if current. + // + // Apply the effect to clipped players only for now. + // + // In Phase II, you can apply these effects to Things other than players. + + if (p->type == p_push) + { + + // Seek out all pushable things within the force radius of this + // point pusher. Crosses sectors, so use blockmap. + + tmpusher = p; // MT_PUSH/MT_PULL point source + radius = p->radius; // where force goes to zero + tmbbox[BOXTOP] = p->y + radius; + tmbbox[BOXBOTTOM] = p->y - radius; + tmbbox[BOXRIGHT] = p->x + radius; + tmbbox[BOXLEFT] = p->x - radius; + + xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + P_BlockThingsIterator(bx,by, PIT_PushThing); + return; + } + + // constant pushers p_wind and p_current + node = sec->touching_thinglist; // things touching this sector + for (; node; node = node->m_thinglist_next) + { + thing = node->m_thing; + if (thing->flags & (MF_NOGRAVITY | MF_NOCLIP) + && !(thing->type == MT_SMALLBUBBLE + || thing->type == MT_MEDIUMBUBBLE + || thing->type == MT_EXTRALARGEBUBBLE)) + continue; + + if (!((thing->flags & MF_PUSHABLE) || ((thing->info->flags & MF_PUSHABLE) && thing->fuse)) + && !(thing->type == MT_PLAYER + || thing->type == MT_SMALLBUBBLE + || thing->type == MT_MEDIUMBUBBLE + || thing->type == MT_EXTRALARGEBUBBLE + || thing->type == MT_LITTLETUMBLEWEED + || thing->type == MT_BIGTUMBLEWEED)) + continue; + + if (thing->eflags & MFE_PUSHED) + continue; + + if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG) + continue; + + if (thing->player && (thing->state == &states[thing->info->painstate]) && (thing->player->powers[pw_flashing] > (flashingtics/4)*3 && thing->player->powers[pw_flashing] <= flashingtics)) + continue; + + inFOF = touching = moved = false; + + // Find the area that the 'thing' is in + if (p->roverpusher) + { + fixed_t top, bottom; + + top = P_GetSpecialTopZ(thing, referrer, sec); + bottom = P_GetSpecialBottomZ(thing, referrer, sec); + + if (thing->eflags & MFE_VERTICALFLIP) + { + if (bottom > thing->z + thing->height + || top < (thing->z + (thing->height >> 1))) + continue; + + if (thing->z < bottom) + touching = true; + + if (thing->z + (thing->height >> 1) > bottom) + inFOF = true; + + } + else + { + if (top < thing->z || bottom > (thing->z + (thing->height >> 1))) + continue; + if (thing->z + thing->height > top) + touching = true; + + if (thing->z + (thing->height >> 1) < top) + inFOF = true; + } + } + else // Treat the entire sector as one big FOF + { + if (thing->z == P_GetSpecialBottomZ(thing, sec, sec)) + touching = true; + else if (p->type != p_current) + inFOF = true; + } + + if (!touching && !inFOF) // Object is out of range of effect + continue; + + if (p->type == p_wind) + { + if (touching) // on ground + { + xspeed = (p->x_mag)>>1; // half force + yspeed = (p->y_mag)>>1; + moved = true; + } + else if (inFOF) + { + xspeed = (p->x_mag); // full force + yspeed = (p->y_mag); + moved = true; + } + } + else if (p->type == p_upwind) + { + if (touching) // on ground + { + thing->momz += (p->magnitude)>>1; + moved = true; + } + else if (inFOF) + { + thing->momz += p->magnitude; + moved = true; + } + } + else if (p->type == p_downwind) + { + if (touching) // on ground + { + thing->momz -= (p->magnitude)>>1; + moved = true; + } + else if (inFOF) + { + thing->momz -= p->magnitude; + moved = true; + } + } + else // p_current + { + if (!touching && !inFOF) // Not in water at all + xspeed = yspeed = 0; // no force + else // underwater / touching water + { + if (p->type == p_upcurrent) + thing->momz += p->magnitude; + else if (p->type == p_downcurrent) + thing->momz -= p->magnitude; + else + { + xspeed = p->x_mag; // full force + yspeed = p->y_mag; + } + moved = true; + } + } + + if (p->type != p_downcurrent && p->type != p_upcurrent + && p->type != p_upwind && p->type != p_downwind) + { + thing->momx += xspeed<<(FRACBITS-PUSH_FACTOR); + thing->momy += yspeed<<(FRACBITS-PUSH_FACTOR); + if (thing->player) + { + thing->player->cmomx += xspeed<<(FRACBITS-PUSH_FACTOR); + thing->player->cmomy += yspeed<<(FRACBITS-PUSH_FACTOR); + thing->player->cmomx = FixedMul(thing->player->cmomx, ORIG_FRICTION); + thing->player->cmomy = FixedMul(thing->player->cmomy, ORIG_FRICTION); + } + + // Tumbleweeds bounce a bit... + if (thing->type == MT_LITTLETUMBLEWEED || thing->type == MT_BIGTUMBLEWEED) + thing->momz += P_AproxDistance(xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)) >> 2; + } + + if (moved) + { + if (p->slider && thing->player) + { + pflags_t jumped = (thing->player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE)); + P_ResetPlayer (thing->player); + + if (jumped) + thing->player->pflags |= jumped; + + thing->player->pflags |= PF_SLIDING; + thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)); + + if (!demoplayback || P_ControlStyle(thing->player) == CS_LMAOGALOG) + { + angle_t angle = thing->player->angleturn << 16; + if (thing->angle - angle > ANGLE_180) + P_SetPlayerAngle(thing->player, angle - (angle - thing->angle) / 8); + else + P_SetPlayerAngle(thing->player, angle + (thing->angle - angle) / 8); + //P_SetPlayerAngle(thing->player, thing->angle); + } + } + + if (p->exclusive) + thing->eflags |= MFE_PUSHED; + } + } +} + + +/** Gets a push/pull object. + * + * \param s Sector number to look in. + * \return Pointer to the first ::MT_PUSH or ::MT_PULL object found in the + * sector. + * \sa P_GetTeleportDestThing, P_GetStarpostThing, P_GetAltViewThing + */ +mobj_t *P_GetPushThing(UINT32 s) +{ + mobj_t *thing; + sector_t *sec; + + sec = sectors + s; + thing = sec->thinglist; + while (thing) + { + switch (thing->type) + { + case MT_PUSH: + case MT_PULL: + return thing; + default: + break; + } + thing = thing->snext; + } + return NULL; +} + +/** Spawns pushers. + * + * \todo Remove magic numbers. + * \sa P_SpawnSpecials, Add_Pusher + */ +static void P_SpawnPushers(void) +{ + size_t i; + line_t *l = lines; + mtag_t tag; + register INT32 s; + mobj_t *thing; + + for (i = 0; i < numlines; i++, l++) + { + tag = Tag_FGet(&l->tags); + switch (l->special) + { + case 541: // wind + TAG_ITER_SECTORS(tag, s) + Add_Pusher(p_wind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + break; + case 544: // current + TAG_ITER_SECTORS(tag, s) + Add_Pusher(p_current, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + break; + case 547: // push/pull + TAG_ITER_SECTORS(tag, s) + { + thing = P_GetPushThing(s); + if (thing) // No MT_P* means no effect + Add_Pusher(p_push, l->dx, l->dy, thing, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + } + break; + case 545: // current up + TAG_ITER_SECTORS(tag, s) + Add_Pusher(p_upcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + break; + case 546: // current down + TAG_ITER_SECTORS(tag, s) + Add_Pusher(p_downcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + break; + case 542: // wind up + TAG_ITER_SECTORS(tag, s) + Add_Pusher(p_upwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + break; + case 543: // wind down + TAG_ITER_SECTORS(tag, s) + Add_Pusher(p_downwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); + break; + } + } +} From 7e88db938d715a6f83d8681dd198a9185430ef26 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 4 Jul 2021 19:28:14 +0200 Subject: [PATCH 111/326] Adapt polyobject translucency fade linedef to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 40 +++++++++++++++++--- src/p_polyobj.h | 9 +++++ src/p_setup.c | 22 +++++++++++ src/p_spec.c | 30 +++++---------- 4 files changed, 74 insertions(+), 27 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index f73d36044..3751d781c 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2800,13 +2800,9 @@ udmf } arg2 { - title = "Set/add?"; + title = "Set/Add?"; type = 11; - enum - { - 0 = "Set"; - 1 = "Add"; - } + enum = "setadd"; } } } @@ -3012,6 +3008,38 @@ udmf enum = "setadd"; } } + + 492 + { + title = "Fade Translucency"; + prefix = "(492)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Translucency level"; + } + arg2 + { + title = "Fading speed"; + } + arg3 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Add to current translucency"; + 2 = "Interrupt ongoing fades"; + 4 = "Speed is duration"; + 8 = "Don't change collision"; + 16 = "No collision during fade"; + } + } + } } scrollpush diff --git a/src/p_polyobj.h b/src/p_polyobj.h index b37ffa6ef..411695775 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -349,6 +349,15 @@ typedef struct polyflagdata_s fixed_t momx; } polyflagdata_t; +typedef enum +{ + TMPF_RELATIVE = 1, + TMPF_OVERRIDE = 1<<1, + TMPF_TICBASED = 1<<2, + TMPF_IGNORECOLLISION = 1<<3, + TMPF_GHOSTFADE = 1<<4, +} textmappolyfade_t; + typedef struct polyfadedata_s { INT32 polyObjNum; diff --git a/src/p_setup.c b/src/p_setup.c index 4bcb5c8e1..11e5a385d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3750,6 +3750,28 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] /= 100; lines[i].args[2] = !!(lines[i].flags & ML_EFFECT3); break; + case 492: //Polyobject - fade translucency + lines[i].args[0] = tag; + // If Front X Offset is specified, use that. Else, use floorheight. + lines[i].args[1] = (sides[lines[i].sidenum[0]].textureoffset ? sides[lines[i].sidenum[0]].textureoffset : lines[i].frontsector->floorheight) >> FRACBITS; + // If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000. + if (!(lines[i].flags & ML_DONTPEGBOTTOM)) + lines[i].args[1] /= 100; + // allow Back Y Offset to be consistent with other fade specials + lines[i].args[2] = (lines[i].sidenum[1] != 0xffff && !sides[lines[i].sidenum[0]].rowoffset) ? + abs(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS) + : abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS); + if (lines[i].flags & ML_EFFECT3) + lines[i].args[3] |= TMPF_RELATIVE; + if (lines[i].flags & ML_EFFECT5) + lines[i].args[3] |= TMPF_OVERRIDE; + if (lines[i].flags & ML_EFFECT4) + lines[i].args[3] |= TMPF_TICBASED; + if (lines[i].flags & ML_BOUNCY) + lines[i].args[3] |= TMPF_IGNORECOLLISION; + if (lines[i].flags & ML_EFFECT1) + lines[i].args[3] |= TMPF_GHOSTFADE; + break; case 500: //Scroll front wall left case 501: //Scroll front wall right lines[i].args[0] = 0; diff --git a/src/p_spec.c b/src/p_spec.c index 9862ffa2f..0beac3c78 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1090,10 +1090,9 @@ static void PolyTranslucency(line_t *line) // Makes a polyobject translucency fade and applies tangibility static boolean PolyFade(line_t *line) { - INT32 polyObjNum = Tag_FGet(&line->tags); + INT32 polyObjNum = line->args[0]; polyobj_t *po; polyfadedata_t pfd; - INT32 value; if (!(po = Polyobj_GetForNum(polyObjNum))) { @@ -1106,7 +1105,7 @@ static boolean PolyFade(line_t *line) return 0; // Prevent continuous execs from interfering on an existing fade - if (!(line->flags & ML_EFFECT5) + if (!(line->args[3] & TMPF_OVERRIDE) && po->thinker && po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade) { @@ -1116,17 +1115,10 @@ static boolean PolyFade(line_t *line) pfd.polyObjNum = polyObjNum; - // If Front X Offset is specified, use that. Else, use floorheight. - value = (sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : line->frontsector->floorheight) >> FRACBITS; - - // If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000. - if (!(line->flags & ML_DONTPEGBOTTOM)) - value /= 100; - - if (line->flags & ML_EFFECT3) // relative calc - pfd.destvalue = po->translucency + value; + if (line->args[3] & TMPF_RELATIVE) // relative calc + pfd.destvalue = po->translucency + line->args[1]; else - pfd.destvalue = value; + pfd.destvalue = line->args[1]; pfd.destvalue = max(min(pfd.destvalue, NUMTRANSMAPS), 0); @@ -1134,15 +1126,11 @@ static boolean PolyFade(line_t *line) if (po->translucency == pfd.destvalue) return 1; - pfd.docollision = !(line->flags & ML_BOUNCY); // do not handle collision flags - pfd.doghostfade = (line->flags & ML_EFFECT1); // do ghost fade (no collision flags during fade) - pfd.ticbased = (line->flags & ML_EFFECT4); // Speed = Tic Duration - - // allow Back Y Offset to be consistent with other fade specials - pfd.speed = (line->sidenum[1] != 0xFFFF && !sides[line->sidenum[0]].rowoffset) ? - abs(sides[line->sidenum[1]].rowoffset>>FRACBITS) - : abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); + pfd.docollision = !(line->args[3] & TMPF_IGNORECOLLISION); // do not handle collision flags + pfd.doghostfade = (line->args[3] & TMPF_GHOSTFADE); // do ghost fade (no collision flags during fade) + pfd.ticbased = (line->args[3] & TMPF_TICBASED); // Speed = Tic Duration + pfd.speed = line->args[2]; return EV_DoPolyObjFade(&pfd); } From 9d3dc98939ab37abe416cea89a4577617fd491ee Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 17 Sep 2021 09:57:53 +0200 Subject: [PATCH 112/326] Fix "render insides" condition being inverted for intangible FOFs --- 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 c88aa02f5..17d71a8bf 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3385,7 +3385,7 @@ static void P_ConvertBinaryMap(void) //Appearance if (lines[i].special == 222) lines[i].args[2] |= TMFA_NOPLANES; - if (lines[i].special != 221) + if (lines[i].special == 221) lines[i].args[2] |= TMFA_INSIDES; if (lines[i].special != 220 && !(lines[i].flags & ML_NOCLIMB)) lines[i].args[2] |= TMFA_NOSHADE; From e15c160773daa65ac943ad447ce6eea4391152de Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 19 Sep 2021 08:58:21 +0200 Subject: [PATCH 113/326] Implement per-sector floor/ceiling lighting --- src/hardware/hw_main.c | 8 +++---- src/p_setup.c | 14 ++++++++++++ src/p_spec.c | 10 ++++++++ src/r_bsp.c | 28 +++++++++++++---------- src/r_defs.h | 6 ++++- src/r_segs.c | 52 +++++++++++++++++++++++------------------- 6 files changed, 77 insertions(+), 41 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e0851af85..f496de2ce 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3046,13 +3046,13 @@ static void HWR_Subsector(size_t num) } light = R_GetPlaneLight(gl_frontsector, locFloorHeight, false); - if (gl_frontsector->floorlightsec == -1) - floorlightlevel = *gl_frontsector->lightlist[light].lightlevel; + if (gl_frontsector->floorlightsec == -1 && !gl_frontsector->floorlightabsolute) + floorlightlevel = max(0, min(255, *gl_frontsector->lightlist[light].lightlevel + gl_frontsector->floorlightlevel)); floorcolormap = *gl_frontsector->lightlist[light].extra_colormap; light = R_GetPlaneLight(gl_frontsector, locCeilingHeight, false); - if (gl_frontsector->ceilinglightsec == -1) - ceilinglightlevel = *gl_frontsector->lightlist[light].lightlevel; + if (gl_frontsector->ceilinglightsec == -1 && !gl_frontsector->ceilinglightabsolute) + ceilinglightlevel = max(0, min(255, *gl_frontsector->lightlist[light].lightlevel + gl_frontsector->ceilinglightlevel)); ceilingcolormap = *gl_frontsector->lightlist[light].extra_colormap; } diff --git a/src/p_setup.c b/src/p_setup.c index e6f46e0c0..7225da985 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1043,6 +1043,9 @@ static void P_LoadSectors(UINT8 *data) ss->floorpic_angle = ss->ceilingpic_angle = 0; + ss->floorlightlevel = ss->ceilinglightlevel = 0; + ss->floorlightabsolute = ss->ceilinglightabsolute = false; + ss->colormap_protected = false; P_InitializeSector(ss); @@ -1529,6 +1532,14 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].ceilingpic = P_AddLevelFlat(val, foundflats); else if (fastcmp(param, "lightlevel")) sectors[i].lightlevel = atol(val); + else if (fastcmp(param, "lightfloor")) + sectors[i].floorlightlevel = atol(val); + else if (fastcmp(param, "lightfloorabsolute") && fastcmp("true", val)) + sectors[i].floorlightabsolute = true; + else if (fastcmp(param, "lightceiling")) + sectors[i].ceilinglightlevel = atol(val); + else if (fastcmp(param, "lightceilingabsolute") && fastcmp("true", val)) + sectors[i].ceilinglightabsolute = true; else if (fastcmp(param, "special")) sectors[i].special = atol(val); else if (fastcmp(param, "id")) @@ -1914,6 +1925,9 @@ static void P_LoadTextmap(void) sc->floorpic_angle = sc->ceilingpic_angle = 0; + sc->floorlightlevel = sc->ceilinglightlevel = 0; + sc->floorlightabsolute = sc->ceilinglightabsolute = false; + sc->colormap_protected = false; textmap_colormap.used = false; diff --git a/src/p_spec.c b/src/p_spec.c index be2141a67..f69b49568 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2126,9 +2126,15 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 402: // Set tagged sector's light level { INT16 newlightlevel; + INT16 newfloorlightlevel, newceilinglightlevel; + boolean newfloorlightabsolute, newceilinglightabsolute; INT32 newfloorlightsec, newceilinglightsec; newlightlevel = line->frontsector->lightlevel; + newfloorlightlevel = line->frontsector->floorlightlevel; + newfloorlightabsolute = line->frontsector->floorlightabsolute; + newceilinglightlevel = line->frontsector->ceilinglightlevel; + newceilinglightabsolute = line->frontsector->ceilinglightabsolute; newfloorlightsec = line->frontsector->floorlightsec; newceilinglightsec = line->frontsector->ceilinglightsec; @@ -2147,6 +2153,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } sectors[secnum].lightlevel = newlightlevel; + sectors[secnum].floorlightlevel = newfloorlightlevel; + sectors[secnum].floorlightabsolute = newfloorlightabsolute; + sectors[secnum].ceilinglightlevel = newceilinglightlevel; + sectors[secnum].ceilinglightabsolute = newceilinglightabsolute; sectors[secnum].floorlightsec = newfloorlightsec; sectors[secnum].ceilinglightsec = newceilinglightsec; } diff --git a/src/r_bsp.c b/src/r_bsp.c index 5acd4e70c..360c17be3 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -238,11 +238,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, { if (floorlightlevel) *floorlightlevel = sec->floorlightsec == -1 ? - sec->lightlevel : sectors[sec->floorlightsec].lightlevel; + (sec->floorlightabsolute ? sec->floorlightlevel : max(0, min(255, sec->lightlevel + sec->floorlightlevel))) : sectors[sec->floorlightsec].lightlevel; if (ceilinglightlevel) *ceilinglightlevel = sec->ceilinglightsec == -1 ? - sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel; + (sec->ceilinglightabsolute ? sec->ceilinglightlevel : max(0, min(255, sec->lightlevel + sec->ceilinglightlevel))) : sectors[sec->ceilinglightsec].lightlevel; // if (sec->midmap != -1) // mapnum = sec->midmap; @@ -301,11 +301,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->lightlevel = s->lightlevel; if (floorlightlevel) - *floorlightlevel = s->floorlightsec == -1 ? s->lightlevel + *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) : sectors[s->floorlightsec].lightlevel; if (ceilinglightlevel) - *ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel + *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) : sectors[s->ceilinglightsec].lightlevel; } else if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight @@ -339,12 +339,12 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->lightlevel = s->lightlevel; if (floorlightlevel) - *floorlightlevel = s->floorlightsec == -1 ? s->lightlevel : - sectors[s->floorlightsec].lightlevel; + *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) + : sectors[s->floorlightsec].lightlevel; if (ceilinglightlevel) - *ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel : - sectors[s->ceilinglightsec].lightlevel; + *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) + : sectors[s->ceilinglightsec].lightlevel; } sec = tempsec; } @@ -370,6 +370,10 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back) && back->ceiling_yoffs == front->ceiling_yoffs && back->ceilingpic_angle == front->ceilingpic_angle // Consider altered lighting. + && back->floorlightlevel == front->floorlightlevel + && back->floorlightabsolute == front->floorlightabsolute + && back->ceilinglightlevel == front->ceilinglightlevel + && back->ceilinglightabsolute == front->ceilinglightabsolute && back->floorlightsec == front->floorlightsec && back->ceilinglightsec == front->ceilinglightsec // Consider colormaps @@ -872,12 +876,12 @@ static void R_Subsector(size_t num) } light = R_GetPlaneLight(frontsector, floorcenterz, false); - if (frontsector->floorlightsec == -1) - floorlightlevel = *frontsector->lightlist[light].lightlevel; + if (frontsector->floorlightsec == -1 && !frontsector->floorlightabsolute) + floorlightlevel = max(0, min(255, *frontsector->lightlist[light].lightlevel + frontsector->floorlightlevel)); floorcolormap = *frontsector->lightlist[light].extra_colormap; light = R_GetPlaneLight(frontsector, ceilingcenterz, false); - if (frontsector->ceilinglightsec == -1) - ceilinglightlevel = *frontsector->lightlist[light].lightlevel; + if (frontsector->ceilinglightsec == -1 && !frontsector->ceilinglightabsolute) + ceilinglightlevel = max(0, min(255, *frontsector->lightlist[light].lightlevel + frontsector->ceilinglightlevel)); ceilingcolormap = *frontsector->lightlist[light].extra_colormap; } diff --git a/src/r_defs.h b/src/r_defs.h index cb21d5043..ab2b9fb2f 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -341,7 +341,11 @@ typedef struct sector_s INT32 heightsec; // other sector, or -1 if no other sector INT32 camsec; // used for camera clipping - INT32 floorlightsec, ceilinglightsec; + // floor and ceiling lighting + INT16 floorlightlevel, ceilinglightlevel; + boolean floorlightabsolute, ceilinglightabsolute; // absolute or relative to sector's light level? + INT32 floorlightsec, ceilinglightsec; // take floor/ceiling light level from another sector + INT32 crumblestate; // used for crumbling and bobbing // list of mobjs that are at least partially in the sector diff --git a/src/r_segs.c b/src/r_segs.c index a8c85ec33..68fb24195 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1908,18 +1908,20 @@ void R_StoreWallRange(INT32 start, INT32 stop) else if (worldlow != worldbottom || worldlowslope != worldbottomslope || backsector->f_slope != frontsector->f_slope - || backsector->floorpic != frontsector->floorpic - || backsector->lightlevel != frontsector->lightlevel - //SoM: 3/22/2000: Check floor x and y offsets. - || backsector->floor_xoffs != frontsector->floor_xoffs - || backsector->floor_yoffs != frontsector->floor_yoffs - || backsector->floorpic_angle != frontsector->floorpic_angle - //SoM: 3/22/2000: Prevents bleeding. - || (frontsector->heightsec != -1 && frontsector->floorpic != skyflatnum) - || backsector->floorlightsec != frontsector->floorlightsec - //SoM: 4/3/2000: Check for colormaps - || frontsector->extra_colormap != backsector->extra_colormap - || (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags))) + || backsector->floorpic != frontsector->floorpic + || backsector->lightlevel != frontsector->lightlevel + //SoM: 3/22/2000: Check floor x and y offsets. + || backsector->floor_xoffs != frontsector->floor_xoffs + || backsector->floor_yoffs != frontsector->floor_yoffs + || backsector->floorpic_angle != frontsector->floorpic_angle + //SoM: 3/22/2000: Prevents bleeding. + || (frontsector->heightsec != -1 && frontsector->floorpic != skyflatnum) + || backsector->floorlightlevel != frontsector->floorlightlevel + || backsector->floorlightabsolute != frontsector->floorlightabsolute + || backsector->floorlightsec != frontsector->floorlightsec + //SoM: 4/3/2000: Check for colormaps + || frontsector->extra_colormap != backsector->extra_colormap + || (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags))) { markfloor = true; } @@ -1939,18 +1941,20 @@ void R_StoreWallRange(INT32 start, INT32 stop) else if (worldhigh != worldtop || worldhighslope != worldtopslope || backsector->c_slope != frontsector->c_slope - || backsector->ceilingpic != frontsector->ceilingpic - || backsector->lightlevel != frontsector->lightlevel - //SoM: 3/22/2000: Check floor x and y offsets. - || backsector->ceiling_xoffs != frontsector->ceiling_xoffs - || backsector->ceiling_yoffs != frontsector->ceiling_yoffs - || backsector->ceilingpic_angle != frontsector->ceilingpic_angle - //SoM: 3/22/2000: Prevents bleeding. - || (frontsector->heightsec != -1 && frontsector->ceilingpic != skyflatnum) - || backsector->ceilinglightsec != frontsector->ceilinglightsec - //SoM: 4/3/2000: Check for colormaps - || frontsector->extra_colormap != backsector->extra_colormap - || (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags))) + || backsector->ceilingpic != frontsector->ceilingpic + || backsector->lightlevel != frontsector->lightlevel + //SoM: 3/22/2000: Check floor x and y offsets. + || backsector->ceiling_xoffs != frontsector->ceiling_xoffs + || backsector->ceiling_yoffs != frontsector->ceiling_yoffs + || backsector->ceilingpic_angle != frontsector->ceilingpic_angle + //SoM: 3/22/2000: Prevents bleeding. + || (frontsector->heightsec != -1 && frontsector->ceilingpic != skyflatnum) + || backsector->ceilinglightlevel != frontsector->ceilinglightlevel + || backsector->ceilinglightabsolute != frontsector->ceilinglightabsolute + || backsector->ceilinglightsec != frontsector->ceilinglightsec + //SoM: 4/3/2000: Check for colormaps + || frontsector->extra_colormap != backsector->extra_colormap + || (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags))) { markceiling = true; } From e43831bedb403ee21e2cefd6401db66c5e55316f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 19 Sep 2021 09:06:39 +0200 Subject: [PATCH 114/326] Expose floor/ceiling lighting to Lua --- src/lua_maplib.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 534ef9a07..52800535c 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -35,6 +35,10 @@ enum sector_e { sector_floorpic, sector_ceilingpic, sector_lightlevel, + sector_floorlightlevel, + sector_floorlightabsolute, + sector_ceilinglightlevel, + sector_ceilinglightabsolute, sector_special, sector_tag, sector_taglist, @@ -54,6 +58,10 @@ static const char *const sector_opt[] = { "floorpic", "ceilingpic", "lightlevel", + "floorlightlevel", + "floorlightabsolute", + "ceilinglightlevel", + "ceilinglightabsolute", "special", "tag", "taglist", @@ -591,6 +599,18 @@ static int sector_get(lua_State *L) case sector_lightlevel: lua_pushinteger(L, sector->lightlevel); return 1; + case sector_floorlightlevel: + lua_pushinteger(L, sector->floorlightlevel); + return 1; + case sector_floorlightabsolute: + lua_pushboolean(L, sector->floorlightabsolute); + return 1; + case sector_ceilinglightlevel: + lua_pushinteger(L, sector->ceilinglightlevel); + return 1; + case sector_ceilinglightabsolute: + lua_pushboolean(L, sector->ceilinglightabsolute); + return 1; case sector_special: lua_pushinteger(L, sector->special); return 1; @@ -695,6 +715,18 @@ static int sector_set(lua_State *L) case sector_lightlevel: sector->lightlevel = (INT16)luaL_checkinteger(L, 3); break; + case sector_floorlightlevel: + sector->floorlightlevel = (INT16)luaL_checkinteger(L, 3); + break; + case sector_floorlightabsolute: + sector->floorlightabsolute = luaL_checkboolean(L, 3); + break; + case sector_ceilinglightlevel: + sector->ceilinglightlevel = (INT16)luaL_checkinteger(L, 3); + break; + case sector_ceilinglightabsolute: + sector->ceilinglightabsolute = luaL_checkboolean(L, 3); + break; case sector_special: sector->special = (INT16)luaL_checkinteger(L, 3); break; From 68aa14f7d08f31414c91ea90f3397ed2261910d8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 19 Sep 2021 09:20:00 +0200 Subject: [PATCH 115/326] Netsync floor/ceiling lighting --- src/p_saveg.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 044f6bab0..ed849418a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -850,6 +850,8 @@ static void P_NetUnArchiveWaypoints(void) #define SD_TAGLIST 0x01 #define SD_COLORMAP 0x02 #define SD_CRUMBLESTATE 0x04 +#define SD_FLOORLIGHT 0x08 +#define SD_CEILLIGHT 0x10 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -1031,6 +1033,11 @@ static void ArchiveSectors(void) if (ss->crumblestate) diff3 |= SD_CRUMBLESTATE; + if (ss->floorlightlevel != spawnss->floorlightlevel || ss->floorlightabsolute != spawnss->floorlightabsolute) + diff3 |= SD_FLOORLIGHT; + if (ss->ceilinglightlevel != spawnss->ceilinglightlevel || ss->ceilinglightabsolute != spawnss->ceilinglightabsolute) + diff3 |= SD_CEILLIGHT; + if (ss->ffloors && CheckFFloorDiff(ss)) diff |= SD_FFLOORS; @@ -1084,6 +1091,16 @@ static void ArchiveSectors(void) // returns existing index if already added, or appends to net_colormaps and returns new index if (diff3 & SD_CRUMBLESTATE) WRITEINT32(save_p, ss->crumblestate); + if (diff3 & SD_FLOORLIGHT) + { + WRITEINT16(save_p, ss->floorlightlevel); + WRITEUINT8(save_p, ss->floorlightabsolute); + } + if (diff3 & SD_CEILLIGHT) + { + WRITEINT16(save_p, ss->ceilinglightlevel); + WRITEUINT8(save_p, ss->ceilinglightabsolute); + } if (diff & SD_FFLOORS) ArchiveFFloors(ss); } @@ -1175,6 +1192,16 @@ static void UnArchiveSectors(void) sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p)); if (diff3 & SD_CRUMBLESTATE) sectors[i].crumblestate = READINT32(save_p); + if (diff3 & SD_FLOORLIGHT) + { + sectors[i].floorlightlevel = READINT16(save_p); + sectors[i].floorlightabsolute = READUINT8(save_p); + } + if (diff3 & SD_CEILLIGHT) + { + sectors[i].ceilinglightlevel = READINT16(save_p); + sectors[i].ceilinglightabsolute = READUINT8(save_p); + } if (diff & SD_FFLOORS) UnArchiveFFloors(§ors[i]); From fe708db398e3f4de06987a8fc5225de42e520634 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 19 Sep 2021 14:23:04 +0200 Subject: [PATCH 116/326] Adapt setup of some lighting linedef executors to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 62 ++++++++++++++++++++ src/p_setup.c | 28 +++++++++ src/p_spec.c | 40 ++++++------- src/p_spec.h | 13 ++++ 4 files changed, 121 insertions(+), 22 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 3751d781c..76d65e663 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2511,6 +2511,28 @@ udmf } } + 402 + { + title = "Copy Light Level"; + prefix = "(402)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Don't copy main light level"; + 2 = "Don't copy floor light level"; + 4 = "Don't copy ceiling light level"; + } + } + } + 408 { title = "Set Tagged Sector's Flats"; @@ -2528,6 +2550,46 @@ udmf } } + 420 + { + title = "Fade Light Level"; + prefix = "(420)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Destination light level"; + } + arg2 + { + title = "Speed"; + } + arg3 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Speed is tic duration"; + 2 = "Override existing fade"; + } + } + } + + 421 + { + title = "Stop Lighting Effect"; + prefix = "(421)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + } + 435 { title = "Change Plane Scroller Direction"; diff --git a/src/p_setup.c b/src/p_setup.c index 7225da985..ffa81f3fb 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3657,6 +3657,10 @@ static void P_ConvertBinaryMap(void) lines[i].args[2] = !!(lines[i].flags & ML_NOCLIMB); lines[i].special = 400; break; + case 402: //Copy light level + lines[i].args[0] = tag; + lines[i].args[1] = 0; + break; case 403: //Move tagged sector's floor case 404: //Move tagged sector's ceiling lines[i].args[0] = tag; @@ -3692,6 +3696,30 @@ static void P_ConvertBinaryMap(void) case 411: //Stop plane movement lines[i].args[0] = tag; break; + case 420: //Fade light level + lines[i].args[0] = tag; + if (lines[i].flags & ML_DONTPEGBOTTOM) + { + lines[i].args[1] = max(sides[lines[i].sidenum[0]].textureoffset >> FRACBITS, 0); + // failsafe: if user specifies Back Y Offset and NOT Front Y Offset, use the Back Offset + // to be consistent with other light and fade specials + lines[i].args[2] = ((lines[i].sidenum[1] != 0xFFFF && !(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS)) ? + max(min(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS, 255), 0) + : max(min(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS, 255), 0)); + } + else + { + lines[i].args[1] = lines[i].frontsector->lightlevel; + lines[i].args[2] = abs(P_AproxDistance(lines[i].dx, lines[i].dy)) >> FRACBITS; + } + if (lines[i].flags & ML_EFFECT4) + lines[i].args[3] |= TMF_TICBASED; + if (lines[i].flags & ML_EFFECT5) + lines[i].args[3] |= TMF_FORCE; + break; + case 421: //Stop lighting effect + lines[i].args[0] = tag; + break; case 428: //Start platform movement lines[i].args[0] = tag; lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index f69b49568..d682b4242 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2123,7 +2123,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) EV_DoCeiling(line->args[0], line, instantMoveCeilingByFrontSector); break; - case 402: // Set tagged sector's light level + case 402: // Copy light level to tagged sectors { INT16 newlightlevel; INT16 newfloorlightlevel, newceilinglightlevel; @@ -2138,8 +2138,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) newfloorlightsec = line->frontsector->floorlightsec; newceilinglightsec = line->frontsector->ceilinglightsec; - // act on all sectors with the same tag as the triggering linedef - TAG_ITER_SECTORS(tag, secnum) + TAG_ITER_SECTORS(line->args[0], secnum) { if (sectors[secnum].lightingdata) { @@ -2152,13 +2151,20 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // actually is: could be lightlevel_t, fireflicker_t, glow_t, etc.) } - sectors[secnum].lightlevel = newlightlevel; - sectors[secnum].floorlightlevel = newfloorlightlevel; - sectors[secnum].floorlightabsolute = newfloorlightabsolute; - sectors[secnum].ceilinglightlevel = newceilinglightlevel; - sectors[secnum].ceilinglightabsolute = newceilinglightabsolute; - sectors[secnum].floorlightsec = newfloorlightsec; - sectors[secnum].ceilinglightsec = newceilinglightsec; + if (!(line->args[1] & TMLC_NOSECTOR)) + sectors[secnum].lightlevel = newlightlevel; + if (!(line->args[1] & TMLC_NOFLOOR)) + { + sectors[secnum].floorlightlevel = newfloorlightlevel; + sectors[secnum].floorlightabsolute = newfloorlightabsolute; + sectors[secnum].floorlightsec = newfloorlightsec; + } + if (!(line->args[1] & TMLC_NOCEILING)) + { + sectors[secnum].ceilinglightlevel = newceilinglightlevel; + sectors[secnum].ceilinglightabsolute = newceilinglightabsolute; + sectors[secnum].ceilinglightsec = newceilinglightsec; + } } } break; @@ -2638,21 +2644,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 420: // Fade light levels in tagged sectors to new value - P_FadeLight(tag, - (line->flags & ML_DONTPEGBOTTOM) ? max(sides[line->sidenum[0]].textureoffset>>FRACBITS, 0) : line->frontsector->lightlevel, - // failsafe: if user specifies Back Y Offset and NOT Front Y Offset, use the Back Offset - // to be consistent with other light and fade specials - (line->flags & ML_DONTPEGBOTTOM) ? - ((line->sidenum[1] != 0xFFFF && !(sides[line->sidenum[0]].rowoffset>>FRACBITS)) ? - max(min(sides[line->sidenum[1]].rowoffset>>FRACBITS, 255), 0) - : max(min(sides[line->sidenum[0]].rowoffset>>FRACBITS, 255), 0)) - : abs(P_AproxDistance(line->dx, line->dy))>>FRACBITS, - (line->flags & ML_EFFECT4), - (line->flags & ML_EFFECT5)); + P_FadeLight(line->args[0], line->args[1], line->args[2], line->args[3] & TMF_TICBASED, line->args[3] & TMF_FORCE); break; case 421: // Stop lighting effect in tagged sectors - TAG_ITER_SECTORS(tag, secnum) + TAG_ITER_SECTORS(line->args[0], secnum) if (sectors[secnum].lightingdata) { P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); diff --git a/src/p_spec.h b/src/p_spec.h index f08ee2f1f..19f8a847c 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -112,6 +112,19 @@ typedef enum TMP_BOTH = 2, } textmapplanes_t; +typedef enum +{ + TMLC_NOSECTOR = 1, + TMLC_NOFLOOR = 1<<1, + TMLC_NOCEILING = 1<<2, +} textmaplightcopyflags_t; + +typedef enum +{ + TMF_TICBASED = 1, + TMF_FORCE = 1<<1, +} textmapfadeflags_t; + typedef enum { TMSD_FRONT = 0, From 18c2cfcacec0a09e2bbdf73c4389daf87f00c4f8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 19 Sep 2021 15:52:54 +0200 Subject: [PATCH 117/326] Clean up arguments for the lighting effect functions --- src/p_lights.c | 76 ++++++++++++++++++-------------------------------- src/p_spec.c | 24 ++++++++-------- src/p_spec.h | 6 ++-- 3 files changed, 42 insertions(+), 64 deletions(-) diff --git a/src/p_lights.c b/src/p_lights.c index 1e41146da..4775597df 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -63,34 +63,27 @@ void T_FireFlicker(fireflicker_t *flick) /** Spawns an adjustable fire flicker effect in a sector. * - * \param minsector Sector whose light level is used as the darkest. - * \param maxsector Sector whose light level is used as the brightest, - * and also the target sector for the effect. + * \param sector Target sector for the effect. + * \param lighta One of the two light levels to move between. + * \param lightb The other light level. * \param length Four times the number of tics between flickers. * \sa T_FireFlicker */ -fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *minsector, sector_t *maxsector, INT32 length) +fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *sector, INT16 lighta, INT16 lightb, INT32 length) { fireflicker_t *flick; - P_RemoveLighting(maxsector); // out with the old, in with the new + P_RemoveLighting(sector); // out with the old, in with the new flick = Z_Calloc(sizeof (*flick), PU_LEVSPEC, NULL); P_AddThinker(THINK_MAIN, &flick->thinker); flick->thinker.function.acp1 = (actionf_p1)T_FireFlicker; - flick->sector = maxsector; - flick->maxlight = maxsector->lightlevel; - flick->minlight = minsector->lightlevel; - if (flick->minlight > flick->maxlight) - { - // You mixed them up, you dummy. - INT32 oops = flick->minlight; - flick->minlight = flick->maxlight; - flick->maxlight = oops; - } + flick->sector = sector; + flick->maxlight = max(lighta, lightb); + flick->minlight = min(lighta, lightb); flick->count = flick->resetcount = length/4; - maxsector->lightingdata = flick; + sector->lightingdata = flick; // input bounds checking and stuff if (!flick->resetcount) @@ -194,9 +187,9 @@ void T_StrobeFlash(strobe_t *flash) /** Spawns an adjustable strobe light effect in a sector. * - * \param minsector Sector whose light level is used as the darkest. - * \param maxsector Sector whose light level is used as the brightest, - * and also the target sector for the effect. + * \param sector Target sector for the effect. + * \param lighta One of the two light levels to move between. + * \param lightb The other light level. * \param darktime Time in tics for the light to be dark. * \param brighttime Time in tics for the light to be bright. * \param inSync If true, the effect will be kept in sync @@ -207,29 +200,21 @@ void T_StrobeFlash(strobe_t *flash) * the strobe flash is random. * \sa T_StrobeFlash */ -strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector, INT32 darktime, INT32 brighttime, boolean inSync) +strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *sector, INT16 lighta, INT16 lightb, INT32 darktime, INT32 brighttime, boolean inSync) { strobe_t *flash; - P_RemoveLighting(maxsector); // out with the old, in with the new + P_RemoveLighting(sector); // out with the old, in with the new flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); P_AddThinker(THINK_MAIN, &flash->thinker); - flash->sector = maxsector; + flash->sector = sector; flash->darktime = darktime; flash->brighttime = brighttime; flash->thinker.function.acp1 = (actionf_p1)T_StrobeFlash; - flash->maxlight = maxsector->lightlevel; - flash->minlight = minsector->lightlevel; - - if (flash->minlight > flash->maxlight) - { - // You mixed them up, you dummy. - INT32 oops = flash->minlight; - flash->minlight = flash->maxlight; - flash->maxlight = oops; - } + flash->maxlight = max(lighta, lightb); + flash->minlight = min(lighta, lightb); if (flash->minlight == flash->maxlight) flash->minlight = 0; @@ -239,7 +224,7 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector, else flash->count = 1; - maxsector->lightingdata = flash; + sector->lightingdata = flash; return flash; } @@ -276,31 +261,24 @@ void T_Glow(glow_t *g) /** Spawns an adjustable glowing light effect in a sector. * - * \param minsector Sector whose light level is used as the darkest. - * \param maxsector Sector whose light level is used as the brightest, - * and also the target sector for the effect. + * \param sector Target sector for the effect. + * \param lighta One of the two light levels to move between. + * \param lightb The other light level. * \param length The speed of the effect. * \sa T_Glow */ -glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, INT32 length) +glow_t *P_SpawnAdjustableGlowingLight(sector_t *sector, INT16 lighta, INT16 lightb, INT32 length) { glow_t *g; - P_RemoveLighting(maxsector); // out with the old, in with the new + P_RemoveLighting(sector); // out with the old, in with the new g = Z_Calloc(sizeof (*g), PU_LEVSPEC, NULL); P_AddThinker(THINK_MAIN, &g->thinker); - g->sector = maxsector; - g->minlight = minsector->lightlevel; - g->maxlight = maxsector->lightlevel; - if (g->minlight > g->maxlight) - { - // You mixed them up, you dummy. - INT32 oops = g->minlight; - g->minlight = g->maxlight; - g->maxlight = oops; - } + g->sector = sector; + g->minlight = min(lighta, lightb); + g->maxlight = max(lighta, lightb); g->thinker.function.acp1 = (actionf_p1)T_Glow; g->direction = 1; g->speed = length/4; @@ -317,7 +295,7 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, g->speed = (g->maxlight - g->minlight)/2; } - maxsector->lightingdata = g; + sector->lightingdata = g; return g; } diff --git a/src/p_spec.c b/src/p_spec.c index d682b4242..833a67290 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2520,7 +2520,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 reallightlevel = sectors[secnum].lightlevel; sectors[secnum].lightlevel = line->backsector->lightlevel; - flick = P_SpawnAdjustableFireFlicker(line->frontsector, §ors[secnum], + flick = P_SpawnAdjustableFireFlicker(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, P_AproxDistance(line->dx, line->dy)>>FRACBITS); // Make sure the starting light level is in range. @@ -2535,7 +2535,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { // Use front sector for min, target sector for max, // the same way linetype 61 does it. - P_SpawnAdjustableFireFlicker(line->frontsector, §ors[secnum], + P_SpawnAdjustableFireFlicker(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, P_AproxDistance(line->dx, line->dy)>>FRACBITS); } } @@ -2554,7 +2554,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 reallightlevel = sectors[secnum].lightlevel; sectors[secnum].lightlevel = line->backsector->lightlevel; - glow = P_SpawnAdjustableGlowingLight(line->frontsector, §ors[secnum], + glow = P_SpawnAdjustableGlowingLight(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, P_AproxDistance(line->dx, line->dy)>>FRACBITS); // Make sure the starting light level is in range. @@ -2569,7 +2569,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { // Use front sector for min, target sector for max, // the same way linetype 602 does it. - P_SpawnAdjustableGlowingLight(line->frontsector, §ors[secnum], + P_SpawnAdjustableGlowingLight(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, P_AproxDistance(line->dx, line->dy)>>FRACBITS); } } @@ -2588,7 +2588,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 reallightlevel = sectors[secnum].lightlevel; sectors[secnum].lightlevel = line->backsector->lightlevel; - flash = P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], + flash = P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, false); // Make sure the starting light level is in range. @@ -2603,7 +2603,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { // Use front sector for min, target sector for max, // the same way linetype 602 does it. - P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], + P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, false); } } @@ -2622,7 +2622,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 reallightlevel = sectors[secnum].lightlevel; sectors[secnum].lightlevel = line->backsector->lightlevel; - flash = P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], + flash = P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, true); // Make sure the starting light level is in range. @@ -2637,7 +2637,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { // Use front sector for min, target sector for max, // the same way linetype 602 does it. - P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], + P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, true); } } @@ -6960,28 +6960,28 @@ void P_SpawnSpecials(boolean fromnetsave) case 602: // Adjustable pulsating light sec = sides[*lines[i].sidenum].sector - sectors; TAG_ITER_SECTORS(tag, s) - P_SpawnAdjustableGlowingLight(§ors[sec], §ors[s], + P_SpawnAdjustableGlowingLight(§ors[s], sectors[sec].lightlevel, sectors[s].lightlevel, P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS); break; case 603: // Adjustable flickering light sec = sides[*lines[i].sidenum].sector - sectors; TAG_ITER_SECTORS(tag, s) - P_SpawnAdjustableFireFlicker(§ors[sec], §ors[s], + P_SpawnAdjustableFireFlicker(§ors[s], sectors[sec].lightlevel, sectors[s].lightlevel, P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS); break; case 604: // Adjustable Blinking Light (unsynchronized) sec = sides[*lines[i].sidenum].sector - sectors; TAG_ITER_SECTORS(tag, s) - P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], + P_SpawnAdjustableStrobeFlash(§ors[s], sectors[sec].lightlevel, sectors[s].lightlevel, abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, false); break; case 605: // Adjustable Blinking Light (synchronized) sec = sides[*lines[i].sidenum].sector - sectors; TAG_ITER_SECTORS(tag, s) - P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], + P_SpawnAdjustableStrobeFlash(§ors[s], sectors[sec].lightlevel, sectors[s].lightlevel, abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, true); break; diff --git a/src/p_spec.h b/src/p_spec.h index 19f8a847c..95005882b 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -284,15 +284,15 @@ typedef struct void P_RemoveLighting(sector_t *sector); void T_FireFlicker(fireflicker_t *flick); -fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *minsector, sector_t *maxsector, INT32 length); +fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *sector, INT16 lighta, INT16 lightb, INT32 length); void T_LightningFlash(lightflash_t *flash); void T_StrobeFlash(strobe_t *flash); void P_SpawnLightningFlash(sector_t *sector); -strobe_t * P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector, INT32 darktime, INT32 brighttime, boolean inSync); +strobe_t * P_SpawnAdjustableStrobeFlash(sector_t *sector, INT16 lighta, INT16 lightb, INT32 darktime, INT32 brighttime, boolean inSync); void T_Glow(glow_t *g); -glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, INT32 length); +glow_t *P_SpawnAdjustableGlowingLight(sector_t *sector, INT16 lighta, INT16 lightb, INT32 length); void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased); void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force); From 9180b86e9e1300bb64a35fd9c366fc47ff7ad4a3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 19 Sep 2021 16:12:06 +0200 Subject: [PATCH 118/326] No more unnecessary light level twiddling --- src/p_lights.c | 9 +++++++ src/p_spec.c | 68 +++----------------------------------------------- 2 files changed, 13 insertions(+), 64 deletions(-) diff --git a/src/p_lights.c b/src/p_lights.c index 4775597df..aae26ecc4 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -96,6 +96,9 @@ fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *sector, INT16 lighta, INT1 flick->maxlight++; } + // Make sure the starting light level is in range. + sector->lightlevel = max((INT16)flick->minlight, min((INT16)flick->maxlight, sector->lightlevel)); + return flick; } @@ -224,6 +227,9 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *sector, INT16 lighta, INT16 lig else flash->count = 1; + // Make sure the starting light level is in range. + sector->lightlevel = max((INT16)flash->minlight, min((INT16)flash->maxlight, sector->lightlevel)); + sector->lightingdata = flash; return flash; } @@ -295,6 +301,9 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *sector, INT16 lighta, INT16 ligh g->speed = (g->maxlight - g->minlight)/2; } + // Make sure the starting light level is in range. + sector->lightlevel = max((INT16)g->minlight, min((INT16)g->maxlight, sector->lightlevel)); + sector->lightingdata = g; return g; diff --git a/src/p_spec.c b/src/p_spec.c index 833a67290..17aa767eb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2513,23 +2513,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->flags & ML_NOCLIMB && line->backsector) { // Use front sector for min light level, back sector for max. - // This is tricky because P_SpawnAdjustableFireFlicker expects - // the maxsector (second argument) to also be the target - // sector, so we have to do some light level twiddling. - fireflicker_t *flick; - INT16 reallightlevel = sectors[secnum].lightlevel; - sectors[secnum].lightlevel = line->backsector->lightlevel; - - flick = P_SpawnAdjustableFireFlicker(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, + P_SpawnAdjustableFireFlicker(§ors[secnum], line->frontsector->lightlevel, line->backsector->lightlevel, P_AproxDistance(line->dx, line->dy)>>FRACBITS); - - // Make sure the starting light level is in range. - if (reallightlevel < flick->minlight) - reallightlevel = (INT16)flick->minlight; - else if (reallightlevel > flick->maxlight) - reallightlevel = (INT16)flick->maxlight; - - sectors[secnum].lightlevel = reallightlevel; } else { @@ -2547,23 +2532,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->flags & ML_NOCLIMB && line->backsector) { // Use front sector for min light level, back sector for max. - // This is tricky because P_SpawnAdjustableGlowingLight expects - // the maxsector (second argument) to also be the target - // sector, so we have to do some light level twiddling. - glow_t *glow; - INT16 reallightlevel = sectors[secnum].lightlevel; - sectors[secnum].lightlevel = line->backsector->lightlevel; - - glow = P_SpawnAdjustableGlowingLight(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, + P_SpawnAdjustableGlowingLight(§ors[secnum], line->frontsector->lightlevel, line->backsector->lightlevel, P_AproxDistance(line->dx, line->dy)>>FRACBITS); - - // Make sure the starting light level is in range. - if (reallightlevel < glow->minlight) - reallightlevel = (INT16)glow->minlight; - else if (reallightlevel > glow->maxlight) - reallightlevel = (INT16)glow->maxlight; - - sectors[secnum].lightlevel = reallightlevel; } else { @@ -2581,23 +2551,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->flags & ML_NOCLIMB && line->backsector) { // Use front sector for min light level, back sector for max. - // This is tricky because P_SpawnAdjustableGlowingLight expects - // the maxsector (second argument) to also be the target - // sector, so we have to do some light level twiddling. - strobe_t *flash; - INT16 reallightlevel = sectors[secnum].lightlevel; - sectors[secnum].lightlevel = line->backsector->lightlevel; - - flash = P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, + P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, line->backsector->lightlevel, abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, false); - - // Make sure the starting light level is in range. - if (reallightlevel < flash->minlight) - reallightlevel = (INT16)flash->minlight; - else if (reallightlevel > flash->maxlight) - reallightlevel = (INT16)flash->maxlight; - - sectors[secnum].lightlevel = reallightlevel; } else { @@ -2615,23 +2570,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->flags & ML_NOCLIMB && line->backsector) { // Use front sector for min light level, back sector for max. - // This is tricky because P_SpawnAdjustableGlowingLight expects - // the maxsector (second argument) to also be the target - // sector, so we have to do some light level twiddling. - strobe_t *flash; - INT16 reallightlevel = sectors[secnum].lightlevel; - sectors[secnum].lightlevel = line->backsector->lightlevel; - - flash = P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, + P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, line->backsector->lightlevel, abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, true); - - // Make sure the starting light level is in range. - if (reallightlevel < flash->minlight) - reallightlevel = (INT16)flash->minlight; - else if (reallightlevel > flash->maxlight) - reallightlevel = (INT16)flash->maxlight; - - sectors[secnum].lightlevel = reallightlevel; } else { From 44faed6285e166fe55aff2399c0c0f9f38e48f50 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 19 Sep 2021 16:25:27 +0200 Subject: [PATCH 119/326] Make light levels in thinkers INT16 --- src/p_lights.c | 24 ++++++++++++------------ src/p_saveg.c | 32 ++++++++++++++++---------------- src/p_spec.h | 16 ++++++++-------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/p_lights.c b/src/p_lights.c index aae26ecc4..e8da48e9a 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -54,9 +54,9 @@ void T_FireFlicker(fireflicker_t *flick) amount = (INT16)((UINT8)(P_RandomByte() & 3) * 16); if (flick->sector->lightlevel - amount < flick->minlight) - flick->sector->lightlevel = (INT16)flick->minlight; + flick->sector->lightlevel = flick->minlight; else - flick->sector->lightlevel = (INT16)((INT16)flick->maxlight - amount); + flick->sector->lightlevel = flick->maxlight - amount; flick->count = flick->resetcount; } @@ -97,7 +97,7 @@ fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *sector, INT16 lighta, INT1 } // Make sure the starting light level is in range. - sector->lightlevel = max((INT16)flick->minlight, min((INT16)flick->maxlight, sector->lightlevel)); + sector->lightlevel = max(flick->minlight, min(flick->maxlight, sector->lightlevel)); return flick; } @@ -178,12 +178,12 @@ void T_StrobeFlash(strobe_t *flash) if (flash->sector->lightlevel == flash->minlight) { - flash->sector->lightlevel = (INT16)flash->maxlight; + flash->sector->lightlevel = flash->maxlight; flash->count = flash->brighttime; } else { - flash->sector->lightlevel = (INT16)flash->minlight; + flash->sector->lightlevel = flash->minlight; flash->count = flash->darktime; } } @@ -228,7 +228,7 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *sector, INT16 lighta, INT16 lig flash->count = 1; // Make sure the starting light level is in range. - sector->lightlevel = max((INT16)flash->minlight, min((INT16)flash->maxlight, sector->lightlevel)); + sector->lightlevel = max(flash->minlight, min(flash->maxlight, sector->lightlevel)); sector->lightingdata = flash; return flash; @@ -245,20 +245,20 @@ void T_Glow(glow_t *g) { case -1: // DOWN - g->sector->lightlevel = (INT16)(g->sector->lightlevel - (INT16)g->speed); + g->sector->lightlevel -= g->speed; if (g->sector->lightlevel <= g->minlight) { - g->sector->lightlevel = (INT16)(g->sector->lightlevel + (INT16)g->speed); + g->sector->lightlevel += g->speed; g->direction = 1; } break; case 1: // UP - g->sector->lightlevel = (INT16)(g->sector->lightlevel + (INT16)g->speed); + g->sector->lightlevel += g->speed; if (g->sector->lightlevel >= g->maxlight) { - g->sector->lightlevel = (INT16)(g->sector->lightlevel - (INT16)g->speed); + g->sector->lightlevel -= g->speed; g->direction = -1; } break; @@ -287,7 +287,7 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *sector, INT16 lighta, INT16 ligh g->maxlight = max(lighta, lightb); g->thinker.function.acp1 = (actionf_p1)T_Glow; g->direction = 1; - g->speed = length/4; + g->speed = (INT16)(length/4); if (g->speed > (g->maxlight - g->minlight)/2) // don't make it ridiculous speed g->speed = (g->maxlight - g->minlight)/2; @@ -302,7 +302,7 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *sector, INT16 lighta, INT16 ligh } // Make sure the starting light level is in range. - sector->lightlevel = max((INT16)g->minlight, min((INT16)g->maxlight, sector->lightlevel)); + sector->lightlevel = max(g->minlight, min(g->maxlight, sector->lightlevel)); sector->lightingdata = g; diff --git a/src/p_saveg.c b/src/p_saveg.c index ed849418a..b17011837 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2083,8 +2083,8 @@ static void SaveStrobeThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, type); WRITEUINT32(save_p, SaveSector(ht->sector)); WRITEINT32(save_p, ht->count); - WRITEINT32(save_p, ht->minlight); - WRITEINT32(save_p, ht->maxlight); + WRITEINT16(save_p, ht->minlight); + WRITEINT16(save_p, ht->maxlight); WRITEINT32(save_p, ht->darktime); WRITEINT32(save_p, ht->brighttime); } @@ -2094,10 +2094,10 @@ static void SaveGlowThinker(const thinker_t *th, const UINT8 type) const glow_t *ht = (const void *)th; WRITEUINT8(save_p, type); WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->minlight); - WRITEINT32(save_p, ht->maxlight); - WRITEINT32(save_p, ht->direction); - WRITEINT32(save_p, ht->speed); + WRITEINT16(save_p, ht->minlight); + WRITEINT16(save_p, ht->maxlight); + WRITEINT16(save_p, ht->direction); + WRITEINT16(save_p, ht->speed); } static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type) @@ -2107,8 +2107,8 @@ static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, SaveSector(ht->sector)); WRITEINT32(save_p, ht->count); WRITEINT32(save_p, ht->resetcount); - WRITEINT32(save_p, ht->maxlight); - WRITEINT32(save_p, ht->minlight); + WRITEINT16(save_p, ht->maxlight); + WRITEINT16(save_p, ht->minlight); } static void SaveElevatorThinker(const thinker_t *th, const UINT8 type) @@ -3212,8 +3212,8 @@ static thinker_t* LoadStrobeThinker(actionf_p1 thinker) ht->thinker.function.acp1 = thinker; ht->sector = LoadSector(READUINT32(save_p)); ht->count = READINT32(save_p); - ht->minlight = READINT32(save_p); - ht->maxlight = READINT32(save_p); + ht->minlight = READINT16(save_p); + ht->maxlight = READINT16(save_p); ht->darktime = READINT32(save_p); ht->brighttime = READINT32(save_p); if (ht->sector) @@ -3226,10 +3226,10 @@ static thinker_t* LoadGlowThinker(actionf_p1 thinker) glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->sector = LoadSector(READUINT32(save_p)); - ht->minlight = READINT32(save_p); - ht->maxlight = READINT32(save_p); - ht->direction = READINT32(save_p); - ht->speed = READINT32(save_p); + ht->minlight = READINT16(save_p); + ht->maxlight = READINT16(save_p); + ht->direction = READINT16(save_p); + ht->speed = READINT16(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; @@ -3242,8 +3242,8 @@ static thinker_t* LoadFireflickerThinker(actionf_p1 thinker) ht->sector = LoadSector(READUINT32(save_p)); ht->count = READINT32(save_p); ht->resetcount = READINT32(save_p); - ht->maxlight = READINT32(save_p); - ht->minlight = READINT32(save_p); + ht->maxlight = READINT16(save_p); + ht->minlight = READINT16(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; diff --git a/src/p_spec.h b/src/p_spec.h index 95005882b..17e10d75b 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -216,8 +216,8 @@ typedef struct sector_t *sector; ///< The sector where action is taking place. INT32 count; INT32 resetcount; - INT32 maxlight; ///< The brightest light level to use. - INT32 minlight; ///< The darkest light level to use. + INT16 maxlight; ///< The brightest light level to use. + INT16 minlight; ///< The darkest light level to use. } fireflicker_t; typedef struct @@ -245,8 +245,8 @@ typedef struct thinker_t thinker; ///< The thinker in use for the effect. sector_t *sector; ///< The sector where the action is taking place. INT32 count; - INT32 minlight; ///< The minimum light level to use. - INT32 maxlight; ///< The maximum light level to use. + INT16 minlight; ///< The minimum light level to use. + INT16 maxlight; ///< The maximum light level to use. INT32 darktime; ///< How INT32 to use minlight. INT32 brighttime; ///< How INT32 to use maxlight. } strobe_t; @@ -255,10 +255,10 @@ typedef struct { thinker_t thinker; sector_t *sector; - INT32 minlight; - INT32 maxlight; - INT32 direction; - INT32 speed; + INT16 minlight; + INT16 maxlight; + INT16 direction; + INT16 speed; } glow_t; /** Thinker struct for fading lights. From 318c1b477d8ae9c7413c43b248a019c5ee233b33 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 19 Sep 2021 17:07:08 +0200 Subject: [PATCH 120/326] Adapt lighting effects to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 190 +++++++++++++++++++ src/p_setup.c | 30 +++ src/p_spec.c | 105 ++-------- src/p_spec.h | 6 + 4 files changed, 247 insertions(+), 84 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 76d65e663..2ec7691ab 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2550,6 +2550,101 @@ udmf } } + 416 + { + title = "Start Adjustable Flickering Light"; + prefix = "(416)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Brightness 1"; + } + arg3 + { + title = "Use target brightness?"; + type = 11; + enum = "noyes"; + } + arg4 + { + title = "Brightness 2"; + } + } + + 417 + { + title = "Start Adjustable Pulsating Light"; + prefix = "(417)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Brightness 1"; + } + arg3 + { + title = "Use target brightness?"; + type = 11; + enum = "noyes"; + } + arg4 + { + title = "Brightness 2"; + } + } + + 418 + { + title = "Start Adjustable Blinking Light"; + prefix = "(418)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Brightness 1 tics"; + } + arg2 + { + title = "Brightness 2 tics"; + } + arg3 + { + title = "Brightness 1"; + } + arg4 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Use target brightness"; + 2 = "Synchronized"; + } + } + arg5 + { + title = "Brightness 2"; + } + } + 420 { title = "Fade Light Level"; @@ -3238,6 +3333,101 @@ udmf light { + 602 + { + title = "Start Adjustable Pulsating Light"; + prefix = "(602)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Brightness 1"; + } + arg3 + { + title = "Use target brightness?"; + type = 11; + enum = "noyes"; + } + arg4 + { + title = "Brightness 2"; + } + } + + 603 + { + title = "Adjustable Flickering Light"; + prefix = "(603)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Brightness 1"; + } + arg3 + { + title = "Use target brightness?"; + type = 11; + enum = "noyes"; + } + arg4 + { + title = "Brightness 2"; + } + } + + 604 + { + title = "Start Adjustable Blinking Light"; + prefix = "(604)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Brightness 1 tics"; + } + arg2 + { + title = "Brightness 2 tics"; + } + arg3 + { + title = "Brightness 1"; + } + arg4 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Use target brightness"; + 2 = "Synchronized"; + } + } + arg5 + { + title = "Brightness 2"; + } + } + 606 { title = "Copy Colormap"; diff --git a/src/p_setup.c b/src/p_setup.c index ffa81f3fb..b87df4090 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3696,6 +3696,36 @@ static void P_ConvertBinaryMap(void) case 411: //Stop plane movement lines[i].args[0] = tag; break; + case 416: //Start adjustable flickering light + case 417: //Start adjustable pulsating light + case 602: //Adjustable pulsating light + case 603: //Adjustable flickering light + lines[i].args[0] = tag; + lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].args[2] = lines[i].frontsector->lightlevel; + if ((lines[i].flags & ML_NOCLIMB) && lines[i].backsector) + lines[i].args[4] = lines[i].backsector->lightlevel; + else + lines[i].args[3] = 1; + break; + case 418: //Start adjustable blinking light (unsynchronized) + case 419: //Start adjustable blinking light (synchronized) + case 604: //Adjustable blinking light (unsynchronized) + case 605: //Adjustable blinking light (synchronized) + lines[i].args[0] = tag; + lines[i].args[1] = abs(lines[i].dx) >> FRACBITS; + lines[i].args[2] = abs(lines[i].dy) >> FRACBITS; + lines[i].args[3] = lines[i].frontsector->lightlevel; + if ((lines[i].flags & ML_NOCLIMB) && lines[i].backsector) + lines[i].args[5] = lines[i].backsector->lightlevel; + else + lines[i].args[4] |= TMB_USETARGET; + if (lines[i].special % 2 == 1) + { + lines[i].args[4] |= TMB_SYNC; + lines[i].special--; + } + break; case 420: //Fade light level lines[i].args[0] = tag; if (lines[i].flags & ML_DONTPEGBOTTOM) diff --git a/src/p_spec.c b/src/p_spec.c index 17aa767eb..2737c4d24 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2508,79 +2508,22 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 416: // Spawn adjustable fire flicker - TAG_ITER_SECTORS(tag, secnum) - { - if (line->flags & ML_NOCLIMB && line->backsector) - { - // Use front sector for min light level, back sector for max. - P_SpawnAdjustableFireFlicker(§ors[secnum], line->frontsector->lightlevel, line->backsector->lightlevel, - P_AproxDistance(line->dx, line->dy)>>FRACBITS); - } - else - { - // Use front sector for min, target sector for max, - // the same way linetype 61 does it. - P_SpawnAdjustableFireFlicker(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, - P_AproxDistance(line->dx, line->dy)>>FRACBITS); - } - } + TAG_ITER_SECTORS(line->args[0], secnum) + P_SpawnAdjustableFireFlicker(§ors[secnum], line->args[2], + line->args[3] ? sectors[secnum].lightlevel : line->args[4], line->args[1]); break; case 417: // Spawn adjustable glowing light - TAG_ITER_SECTORS(tag, secnum) - { - if (line->flags & ML_NOCLIMB && line->backsector) - { - // Use front sector for min light level, back sector for max. - P_SpawnAdjustableGlowingLight(§ors[secnum], line->frontsector->lightlevel, line->backsector->lightlevel, - P_AproxDistance(line->dx, line->dy)>>FRACBITS); - } - else - { - // Use front sector for min, target sector for max, - // the same way linetype 602 does it. - P_SpawnAdjustableGlowingLight(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, - P_AproxDistance(line->dx, line->dy)>>FRACBITS); - } - } + TAG_ITER_SECTORS(line->args[0], secnum) + P_SpawnAdjustableGlowingLight(§ors[secnum], line->args[2], + line->args[3] ? sectors[secnum].lightlevel : line->args[4], line->args[1]); break; - case 418: // Spawn adjustable strobe flash (unsynchronized) - TAG_ITER_SECTORS(tag, secnum) - { - if (line->flags & ML_NOCLIMB && line->backsector) - { - // Use front sector for min light level, back sector for max. - P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, line->backsector->lightlevel, - abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, false); - } - else - { - // Use front sector for min, target sector for max, - // the same way linetype 602 does it. - P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, - abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, false); - } - } - break; - - case 419: // Spawn adjustable strobe flash (synchronized) - TAG_ITER_SECTORS(tag, secnum) - { - if (line->flags & ML_NOCLIMB && line->backsector) - { - // Use front sector for min light level, back sector for max. - P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, line->backsector->lightlevel, - abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, true); - } - else - { - // Use front sector for min, target sector for max, - // the same way linetype 602 does it. - P_SpawnAdjustableStrobeFlash(§ors[secnum], line->frontsector->lightlevel, sectors[secnum].lightlevel, - abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, true); - } - } + case 418: // Spawn adjustable strobe flash + TAG_ITER_SECTORS(line->args[0], secnum) + P_SpawnAdjustableStrobeFlash(§ors[secnum], line->args[3], + (line->args[4] & TMB_USETARGET) ? sectors[secnum].lightlevel : line->args[5], + line->args[1], line->args[2], line->args[4] & TMB_SYNC); break; case 420: // Fade light levels in tagged sectors to new value @@ -6899,30 +6842,24 @@ void P_SpawnSpecials(boolean fromnetsave) case 602: // Adjustable pulsating light sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(tag, s) - P_SpawnAdjustableGlowingLight(§ors[s], sectors[sec].lightlevel, sectors[s].lightlevel, - P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS); + TAG_ITER_SECTORS(lines[i].args[0], s) + P_SpawnAdjustableGlowingLight(§ors[s], lines[i].args[2], + lines[i].args[3] ? sectors[s].lightlevel : lines[i].args[4], lines[i].args[1]); break; case 603: // Adjustable flickering light sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(tag, s) - P_SpawnAdjustableFireFlicker(§ors[s], sectors[sec].lightlevel, sectors[s].lightlevel, - P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS); + TAG_ITER_SECTORS(lines[i].args[0], s) + P_SpawnAdjustableFireFlicker(§ors[s], lines[i].args[2], + lines[i].args[3] ? sectors[s].lightlevel : lines[i].args[4], lines[i].args[1]); break; - case 604: // Adjustable Blinking Light (unsynchronized) + case 604: // Adjustable Blinking Light sec = sides[*lines[i].sidenum].sector - sectors; TAG_ITER_SECTORS(tag, s) - P_SpawnAdjustableStrobeFlash(§ors[s], sectors[sec].lightlevel, sectors[s].lightlevel, - abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, false); - break; - - case 605: // Adjustable Blinking Light (synchronized) - sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(tag, s) - P_SpawnAdjustableStrobeFlash(§ors[s], sectors[sec].lightlevel, sectors[s].lightlevel, - abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, true); + P_SpawnAdjustableStrobeFlash(§ors[s], lines[i].args[3], + (lines[i].args[4] & TMB_USETARGET) ? sectors[s].lightlevel : lines[i].args[5], + lines[i].args[1], lines[i].args[2], lines[i].args[4] & TMB_SYNC); break; case 606: // HACK! Copy colormaps. Just plain colormaps. diff --git a/src/p_spec.h b/src/p_spec.h index 17e10d75b..d759b701b 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -125,6 +125,12 @@ typedef enum TMF_FORCE = 1<<1, } textmapfadeflags_t; +typedef enum +{ + TMB_USETARGET = 1, + TMB_SYNC = 1<<1, +} textmapblinkinglightflags_t; + typedef enum { TMSD_FRONT = 0, From 68712629092c96544576b14685c0ec792bb734a2 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 19 Sep 2021 23:12:30 +0200 Subject: [PATCH 121/326] Allow "fade light level" linedef executor to fade relative to current value --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 7 ++++--- src/lua_baselib.c | 3 ++- src/p_lights.c | 7 +++++-- src/p_setup.c | 2 +- src/p_spec.c | 2 +- src/p_spec.h | 7 ++++--- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 2ec7691ab..a75c98b4d 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2660,7 +2660,7 @@ udmf } arg2 { - title = "Speed"; + title = "Fading speed"; } arg3 { @@ -2668,8 +2668,9 @@ udmf type = 12; enum { - 1 = "Speed is tic duration"; - 2 = "Override existing fade"; + 1 = "Add to current translucency"; + 2 = "Interrupt ongoing fades"; + 4 = "Speed is duration"; } } } diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 350c1585f..7c1d61a9c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2342,9 +2342,10 @@ static int lib_pFadeLight(lua_State *L) INT32 speed = (INT32)luaL_checkinteger(L, 3); boolean ticbased = lua_optboolean(L, 4); boolean force = lua_optboolean(L, 5); + boolean relative = lua_optboolean(L, 6); NOHUD INLEVEL - P_FadeLight(tag, destvalue, speed, ticbased, force); + P_FadeLight(tag, destvalue, speed, ticbased, force, relative); return 0; } diff --git a/src/p_lights.c b/src/p_lights.c index e8da48e9a..58ab2e799 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -358,9 +358,10 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean } } -void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force) +void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force, boolean relative) { INT32 i; + INT32 realdestvalue; // search all sectors for ones with tag TAG_ITER_SECTORS(tag, i) @@ -373,7 +374,9 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, bool CONS_Debug(DBG_GAMELOGIC, "Line type 420 Executor: Fade light thinker already exists, timer: %d\n", ((lightlevel_t*)sectors[i].lightingdata)->timer); continue; } - P_FadeLightBySector(§ors[i], destvalue, speed, ticbased); + + realdestvalue = relative ? max(0, min(255, sectors[i].lightlevel + destvalue)) : destvalue; + P_FadeLightBySector(§ors[i], realdestvalue, speed, ticbased); } } diff --git a/src/p_setup.c b/src/p_setup.c index b87df4090..251e0fbb3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3745,7 +3745,7 @@ static void P_ConvertBinaryMap(void) if (lines[i].flags & ML_EFFECT4) lines[i].args[3] |= TMF_TICBASED; if (lines[i].flags & ML_EFFECT5) - lines[i].args[3] |= TMF_FORCE; + lines[i].args[3] |= TMF_OVERRIDE; break; case 421: //Stop lighting effect lines[i].args[0] = tag; diff --git a/src/p_spec.c b/src/p_spec.c index 2737c4d24..aeb657988 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2527,7 +2527,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 420: // Fade light levels in tagged sectors to new value - P_FadeLight(line->args[0], line->args[1], line->args[2], line->args[3] & TMF_TICBASED, line->args[3] & TMF_FORCE); + P_FadeLight(line->args[0], line->args[1], line->args[2], line->args[3] & TMF_TICBASED, line->args[3] & TMF_OVERRIDE, line->args[3] & TMF_RELATIVE); break; case 421: // Stop lighting effect in tagged sectors diff --git a/src/p_spec.h b/src/p_spec.h index d759b701b..ca0bf0cb3 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -121,8 +121,9 @@ typedef enum typedef enum { - TMF_TICBASED = 1, - TMF_FORCE = 1<<1, + TMF_RELATIVE = 1, + TMF_OVERRIDE = 1<<1, + TMF_TICBASED = 1<<2, } textmapfadeflags_t; typedef enum @@ -301,7 +302,7 @@ void T_Glow(glow_t *g); glow_t *P_SpawnAdjustableGlowingLight(sector_t *sector, INT16 lighta, INT16 lightb, INT32 length); void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased); -void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force); +void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force, boolean relative); void T_LightFade(lightlevel_t *ll); typedef enum From 1784c7b0ef232a0f2e9d376744ed4c3551a18d4a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Sep 2021 07:54:10 +0200 Subject: [PATCH 122/326] Add linedef executor for modifying (as opposed to copying) a sector's light level --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 41 +++++++++++++++++++- src/p_setup.c | 6 +++ src/p_spec.c | 39 +++++++++++++++++++ src/p_spec.h | 7 ++++ 4 files changed, 91 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index a75c98b4d..430645dec 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -762,7 +762,7 @@ doom } 402 { - title = "Set Tagged Sector's Light Level"; + title = "Copy Light Level to Tagged Sectors"; prefix = "(402)"; } 408 @@ -815,6 +815,11 @@ doom title = "Change Plane Scroller Direction"; prefix = "(435)"; } + 467 + { + title = "Set Tagged Sector's Light Level"; + prefix = "(467)"; + } } linedefexecplane @@ -2513,7 +2518,7 @@ udmf 402 { - title = "Copy Light Level"; + title = "Copy Light Level to Tagged Sectors"; prefix = "(402)"; arg0 { @@ -2700,6 +2705,38 @@ udmf title = "Speed"; } } + + 467 + { + title = "Set Tagged Sector's Light Level"; + prefix = "(467)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Light level"; + } + arg2 + { + title = "Affected area"; + type = 11; + enum + { + 0 = "Sector"; + 1 = "Floor"; + 2 = "Ceiling"; + } + } + arg3 + { + title = "Set/Add?"; + type = 11; + enum = "setadd"; + } + } } linedefexecplane diff --git a/src/p_setup.c b/src/p_setup.c index 251e0fbb3..c93a7ac2f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3826,6 +3826,12 @@ static void P_ConvertBinaryMap(void) case 456: //Stop fading colormap lines[i].args[0] = Tag_FGet(&lines[i].tags); break; + case 467: //Set light level + lines[i].args[0] = tag; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[2] = TML_SECTOR; + lines[i].args[3] = !!(lines[i].flags & ML_EFFECT3); + break; case 480: //Polyobject - door slide case 481: //Polyobject - door move lines[i].args[0] = tag; diff --git a/src/p_spec.c b/src/p_spec.c index aeb657988..c460c5a98 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3683,6 +3683,45 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; + case 467: // Set light level + TAG_ITER_SECTORS(line->args[0], secnum) + { + if (sectors[secnum].lightingdata) + { + // Stop any lighting effects going on in the sector + P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); + sectors[secnum].lightingdata = NULL; + + // No, it's not an elevator_t, but any struct with a thinker_t named + // 'thinker' at the beginning will do here. (We don't know what it + // actually is: could be lightlevel_t, fireflicker_t, glow_t, etc.) + } + + if (line->args[2] == TML_FLOOR) + { + if (line->args[3]) + sectors[secnum].floorlightlevel += line->args[1]; + else + sectors[secnum].floorlightlevel = line->args[1]; + } + else if (line->args[2] == TML_CEILING) + { + if (line->args[3]) + sectors[secnum].ceilinglightlevel += line->args[1]; + else + sectors[secnum].ceilinglightlevel = line->args[1]; + } + else + { + if (line->args[3]) + sectors[secnum].lightlevel += line->args[1]; + else + sectors[secnum].lightlevel = line->args[1]; + sectors[secnum].lightlevel = max(0, min(255, sectors[secnum].lightlevel)); + } + } + break; + case 480: // Polyobj_DoorSlide case 481: // Polyobj_DoorSwing PolyDoor(line); diff --git a/src/p_spec.h b/src/p_spec.h index ca0bf0cb3..adebf99d2 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -112,6 +112,13 @@ typedef enum TMP_BOTH = 2, } textmapplanes_t; +typedef enum +{ + TML_SECTOR = 0, + TML_FLOOR = 1, + TML_CEILING = 2, +} textmaplightareas_t; + typedef enum { TMLC_NOSECTOR = 1, From 609fb91e4bed9ccde4d12665b5e695a99a3f5219 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Sep 2021 08:18:59 +0200 Subject: [PATCH 123/326] Stop elevator abuse --- src/p_lights.c | 4 ++-- src/p_spec.c | 16 ++++------------ src/p_spec.h | 6 ++++++ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/p_lights.c b/src/p_lights.c index 58ab2e799..ba39bc72e 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -30,7 +30,7 @@ void P_RemoveLighting(sector_t *sector) // The thinker is the first member in all the lighting action structs, // so just let the thinker get freed, and that will free the whole // structure. - P_RemoveThinker(&((elevator_t *)sector->lightingdata)->thinker); + P_RemoveThinker(&((thinkerdata_t *)sector->lightingdata)->thinker); sector->lightingdata = NULL; } } @@ -144,7 +144,7 @@ void P_SpawnLightningFlash(sector_t *sector) minlight = ((lightflash_t *)sector->lightingdata)->minlight; } - P_RemoveThinker(&((elevator_t *)sector->lightingdata)->thinker); + P_RemoveThinker(&((thinkerdata_t *)sector->lightingdata)->thinker); } sector->lightingdata = NULL; diff --git a/src/p_spec.c b/src/p_spec.c index c460c5a98..250aa4eef 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2143,12 +2143,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (sectors[secnum].lightingdata) { // Stop the lighting madness going on in this sector! - P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); + P_RemoveThinker(&((thinkerdata_t *)sectors[secnum].lightingdata)->thinker); sectors[secnum].lightingdata = NULL; - - // No, it's not an elevator_t, but any struct with a thinker_t named - // 'thinker' at the beginning will do here. (We don't know what it - // actually is: could be lightlevel_t, fireflicker_t, glow_t, etc.) } if (!(line->args[1] & TMLC_NOSECTOR)) @@ -2534,7 +2530,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) TAG_ITER_SECTORS(line->args[0], secnum) if (sectors[secnum].lightingdata) { - P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); + P_RemoveThinker(&((thinkerdata_t *)sectors[secnum].lightingdata)->thinker); sectors[secnum].lightingdata = NULL; } break; @@ -3689,12 +3685,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (sectors[secnum].lightingdata) { // Stop any lighting effects going on in the sector - P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); + P_RemoveThinker(&((thinkerdata_t *)sectors[secnum].lightingdata)->thinker); sectors[secnum].lightingdata = NULL; - - // No, it's not an elevator_t, but any struct with a thinker_t named - // 'thinker' at the beginning will do here. (We don't know what it - // actually is: could be lightlevel_t, fireflicker_t, glow_t, etc.) } if (line->args[2] == TML_FLOOR) @@ -8040,7 +8032,7 @@ static void P_ResetColormapFader(sector_t *sector) // The thinker is the first member in all the action structs, // so just let the thinker get freed, and that will free the whole // structure. - P_RemoveThinker(&((elevator_t *)sector->fadecolormapdata)->thinker); + P_RemoveThinker(&((thinkerdata_t *)sector->fadecolormapdata)->thinker); sector->fadecolormapdata = NULL; } } diff --git a/src/p_spec.h b/src/p_spec.h index adebf99d2..c81839f22 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -219,6 +219,12 @@ void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean e UINT16 P_GetFFloorID(ffloor_t *fflr); ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id); +// Use this when you don't know the type of your thinker data struct but need to access its thinker. +typedef struct +{ + thinker_t thinker; +} thinkerdata_t; + // // P_LIGHTS // From 1b339a9e00f807b1f7271965850b315cb01cf550 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Sep 2021 08:36:55 +0200 Subject: [PATCH 124/326] Adapt linedef types 600-601 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 17 +++++++++++++++++ src/p_setup.c | 6 ++++++ src/p_spec.c | 17 ++++++++--------- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 430645dec..324660d59 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -3371,6 +3371,23 @@ udmf light { + 600 + { + title = "Copy Light Level to Tagged Sector's Planes"; + prefix = "(600)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Affected planes"; + type = 11; + enum = "floorceiling"; + } + } + 602 { title = "Start Adjustable Pulsating Light"; diff --git a/src/p_setup.c b/src/p_setup.c index c93a7ac2f..306847028 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4035,6 +4035,12 @@ static void P_ConvertBinaryMap(void) lines[i].args[4] |= TMPF_NONEXCLUSIVE; lines[i].special = 541; break; + case 600: //Floor lighting + case 601: //Ceiling lighting + lines[i].args[0] = tag; + lines[i].args[1] = (lines[i].special == 601) ? TMP_CEILING : TMP_FLOOR; + lines[i].special = 600; + break; case 606: //Colormap lines[i].args[0] = Tag_FGet(&lines[i].tags); break; diff --git a/src/p_spec.c b/src/p_spec.c index 250aa4eef..7ec7ca38c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6859,16 +6859,15 @@ void P_SpawnSpecials(boolean fromnetsave) // 546 is used for downwards current // 547 is used for push/pull - case 600: // floor lighting independently (e.g. lava) + case 600: // Copy light level to tagged sector's planes sec = sides[*lines[i].sidenum].sector-sectors; - TAG_ITER_SECTORS(tag, s) - sectors[s].floorlightsec = (INT32)sec; - break; - - case 601: // ceiling lighting independently - sec = sides[*lines[i].sidenum].sector-sectors; - TAG_ITER_SECTORS(tag, s) - sectors[s].ceilinglightsec = (INT32)sec; + TAG_ITER_SECTORS(lines[i].args[0], s) + { + if (lines[i].args[1] != TMP_CEILING) + sectors[s].floorlightsec = (INT32)sec; + if (lines[i].args[1] != TMP_FLOOR) + sectors[s].ceilinglightsec = (INT32)sec; + } break; case 602: // Adjustable pulsating light From d2eb4587c28886f82a7147925f13d87ea7226492 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Sep 2021 12:32:01 +0200 Subject: [PATCH 125/326] Adapt linedef type 415 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 11 ++++++++ src/p_setup.c | 25 +++++++++++++++++ src/p_spec.c | 29 ++------------------ 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 324660d59..60d5ecbda 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2880,6 +2880,17 @@ udmf { title = "Linedef Executor (misc.)"; + 415 + { + title = "Run Script"; + prefix = "(415)"; + stringarg0 + { + title = "Lump name"; + type = 2; + } + } + 443 { title = "Call Lua Function"; diff --git a/src/p_setup.c b/src/p_setup.c index 306847028..03f9554bb 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3696,6 +3696,31 @@ static void P_ConvertBinaryMap(void) case 411: //Stop plane movement lines[i].args[0] = tag; break; + case 415: //Run script + { + INT32 scrnum; + + lines[i].stringargs[0] = Z_Malloc(9, PU_LEVEL, NULL); + strcpy(lines[i].stringargs[0], G_BuildMapName(gamemap)); + lines[i].stringargs[0][0] = 'S'; + lines[i].stringargs[0][1] = 'C'; + lines[i].stringargs[0][2] = 'R'; + + scrnum = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + if (scrnum < 0 || scrnum > 999) + { + scrnum = 0; + lines[i].stringargs[0][5] = lines[i].stringargs[0][6] = lines[i].stringargs[0][7] = '0'; + } + else + { + lines[i].stringargs[0][5] = (char)('0' + (char)((scrnum / 100))); + lines[i].stringargs[0][6] = (char)('0' + (char)((scrnum % 100) / 10)); + lines[i].stringargs[0][7] = (char)('0' + (char)(scrnum % 10)); + } + lines[i].stringargs[0][8] = '\0'; + break; + } case 416: //Start adjustable flickering light case 417: //Start adjustable pulsating light case 602: //Adjustable pulsating light diff --git a/src/p_spec.c b/src/p_spec.c index 7ec7ca38c..0ff69f417 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2469,35 +2469,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 415: // Run a script if (cv_runscripts.value) { - INT32 scrnum; - lumpnum_t lumpnum; - char newname[9]; - - strcpy(newname, G_BuildMapName(gamemap)); - newname[0] = 'S'; - newname[1] = 'C'; - newname[2] = 'R'; - - scrnum = sides[line->sidenum[0]].textureoffset>>FRACBITS; - if (scrnum < 0 || scrnum > 999) - { - scrnum = 0; - newname[5] = newname[6] = newname[7] = '0'; - } - else - { - newname[5] = (char)('0' + (char)((scrnum/100))); - newname[6] = (char)('0' + (char)((scrnum%100)/10)); - newname[7] = (char)('0' + (char)(scrnum%10)); - } - newname[8] = '\0'; - - lumpnum = W_CheckNumForName(newname); + lumpnum_t lumpnum = W_CheckNumForName(line->stringargs[0]); if (lumpnum == LUMPERROR || W_LumpLength(lumpnum) == 0) - { - CONS_Debug(DBG_SETUP, "SOC Error: script lump %s not found/not valid.\n", newname); - } + CONS_Debug(DBG_SETUP, "Line type 415 Executor: script lump %s not found/not valid.\n", line->stringargs[0]); else COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE)); } From 4028d392b080b135e8afdbd59dd7ba4de446eea7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Sep 2021 12:42:31 +0200 Subject: [PATCH 126/326] Adapt linedef types 423 and 424 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 43 ++++++++++++++++++++ src/p_setup.c | 5 +++ src/p_spec.c | 10 ++--- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 60d5ecbda..f74210732 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2891,6 +2891,49 @@ udmf } } + 423 + { + title = "Change Sky"; + prefix = "(423)"; + arg0 + { + title = "Sky number"; + } + arg1 + { + title = "For all players?"; + type = 11; + enum = "noyes"; + } + } + + 424 + { + title = "Change Weather"; + prefix = "(424)"; + arg0 + { + title = "Weather"; + type = 11; + enum + { + 0 = "None"; + 1 = "Storm (thunder, lightning and rain)"; + 2 = "Snow"; + 3 = "Rain"; + 4 = "Preloaded"; + 5 = "Storm (no rain)"; + 6 = "Storm (no lightning)"; + } + } + arg1 + { + title = "For all players?"; + type = 11; + enum = "noyes"; + } + } + 443 { title = "Call Lua Function"; diff --git a/src/p_setup.c b/src/p_setup.c index 03f9554bb..370fdb2fa 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3775,6 +3775,11 @@ static void P_ConvertBinaryMap(void) case 421: //Stop lighting effect lines[i].args[0] = tag; break; + case 423: //Change sky + case 424: //Change weather + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); + break; case 428: //Start platform movement lines[i].args[0] = tag; lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index 0ff69f417..3cd046e10 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2560,18 +2560,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 423: // Change Sky - if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB)) - P_SetupLevelSky(sides[line->sidenum[0]].textureoffset>>FRACBITS, (line->flags & ML_NOCLIMB)); + if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || line->args[1]) + P_SetupLevelSky(line->args[0], line->args[1]); break; case 424: // Change Weather - if (line->flags & ML_NOCLIMB) + if (line->args[1]) { - globalweather = (UINT8)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + globalweather = (UINT8)(line->args[0]); P_SwitchWeather(globalweather); } else if (mo && mo->player && P_IsLocalPlayer(mo->player)) - P_SwitchWeather(sides[line->sidenum[0]].textureoffset>>FRACBITS); + P_SwitchWeather(line->args[0]); break; case 425: // Calls P_SetMobjState on calling mobj From 00b04f6d9e37e25c64f57122fe01d3145a7da0e3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Sep 2021 13:31:32 +0200 Subject: [PATCH 127/326] Adapt some player-related linedef executors to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 75 ++++++++++++++++++++ src/p_setup.c | 16 +++++ src/p_spec.c | 16 ++--- 3 files changed, 99 insertions(+), 8 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index f74210732..bc80549e4 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2876,6 +2876,81 @@ udmf } } + linedefexecplayer + { + title = "Linedef Executor (player/object)"; + + 426 + { + title = "Stop Object"; + prefix = "(426)"; + arg0 + { + title = "Move to center?"; + type = 11; + enum = "noyes"; + } + } + + 427 + { + title = "Award Score"; + prefix = "(427)"; + arg0 + { + title = "Score"; + } + } + + 432 + { + title = "Enable/Disable 2D Mode"; + prefix = "(432)"; + arg0 + { + title = "Mode"; + type = 11; + enum + { + 0 = "2D"; + 1 = "3D"; + } + } + } + + 433 + { + title = "Enable/Disable Gravity Flip"; + prefix = "(433)"; + arg0 + { + title = "Gravity"; + type = 11; + enum + { + 0 = "Reverse"; + 1 = "Normal"; + } + } + } + + 437 + { + title = "Disable Player Control"; + prefix = "(437)"; + arg0 + { + title = "Time"; + } + arg1 + { + title = "Allow jumping?"; + type = 11; + enum = "noyes"; + } + } + } + linedefexecmisc { title = "Linedef Executor (misc.)"; diff --git a/src/p_setup.c b/src/p_setup.c index 370fdb2fa..f5f3a22cc 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3780,6 +3780,12 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); break; + case 426: //Stop object + lines[i].args[0] = !!(lines[i].flags & ML_NOCLIMB); + break; + case 427: //Award score + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + break; case 428: //Start platform movement lines[i].args[0] = tag; lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; @@ -3804,10 +3810,20 @@ static void P_ConvertBinaryMap(void) } lines[i].special = 429; break; + case 432: //Enable/disable 2D mode + lines[i].args[0] = !!(lines[i].flags & ML_NOCLIMB); + break; + case 433: //Enable/disable gravity flip + lines[i].args[0] = !!(lines[i].flags & ML_NOCLIMB); + break; case 435: //Change plane scroller direction lines[i].args[0] = tag; lines[i].args[1] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; break; + case 437: //Disable player control + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); + break; case 443: //Call Lua function if (lines[i].text) { diff --git a/src/p_spec.c b/src/p_spec.c index 3cd046e10..e6dcf118a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2583,7 +2583,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!mo) return; - if (line->flags & ML_NOCLIMB) + if (line->args[0]) { P_UnsetThingPosition(mo); mo->x = mo->subsector->sector->soundorg.x; @@ -2618,7 +2618,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 427: // Awards points if the mobj is a player if (mo && mo->player) - P_AddPlayerScore(mo->player, sides[line->sidenum[0]].textureoffset>>FRACBITS); + P_AddPlayerScore(mo->player, line->args[0]); break; case 428: // Start floating platform movement @@ -2634,10 +2634,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) EV_DoCrush(line->args[0], line, crushBothOnce); break; - case 432: // Enable 2D Mode (Disable if noclimb) + case 432: // Enable/Disable 2D Mode if (mo && mo->player) { - if (line->flags & ML_NOCLIMB) + if (line->args[0]) mo->flags2 &= ~MF2_TWOD; else mo->flags2 |= MF2_TWOD; @@ -2651,8 +2651,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; - case 433: // Flip gravity (Flop gravity if noclimb) Works on pushables, too! - if (line->flags & ML_NOCLIMB) + case 433: // Flip/flop gravity. Works on pushables, too! + if (line->args[0]) mo->flags2 &= ~MF2_OBJECTFLIP; else mo->flags2 |= MF2_OBJECTFLIP; @@ -2750,10 +2750,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 437: // Disable Player Controls if (mo && mo->player) { - UINT16 fractime = (UINT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + UINT16 fractime = (UINT16)(line->args[0]); if (fractime < 1) fractime = 1; //instantly wears off upon leaving - if (line->flags & ML_NOCLIMB) + if (line->args[1]) fractime |= 1<<15; //more crazy &ing, as if music stuff wasn't enough mo->player->powers[pw_nocontrol] = fractime; if (bot) From 6010faf10ccc2e429520b09ece489daf84cde5e7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Sep 2021 13:37:04 +0200 Subject: [PATCH 128/326] Add linedef executors without parameters to UDMF config --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index bc80549e4..83e8165fd 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2949,6 +2949,12 @@ udmf enum = "noyes"; } } + + 462 + { + title = "Stop Timer/Exit Stage in Record Attack"; + prefix = "(462)"; + } } linedefexecmisc @@ -3009,6 +3015,12 @@ udmf } } + 440 + { + title = "Start Metal Sonic Race"; + prefix = "(440)"; + } + 443 { title = "Call Lua Function"; From 877ec96eeca105cecb07509e50322244048780dd Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Sep 2021 14:25:07 +0200 Subject: [PATCH 129/326] Adapt a whole bunch of linedef executors to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 137 +++++++++++++++++++ src/p_setup.c | 45 ++++++ src/p_spec.c | 73 +++++----- src/p_spec.h | 7 + 4 files changed, 221 insertions(+), 41 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 83e8165fd..9447a53ad 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -952,6 +952,11 @@ doom title = "Stop Timer/Exit Stage in Record Attack"; prefix = "(462)"; } + 466 + { + title = "Set Level Failure State"; + prefix = "(466)"; + } } linedefexecmisc @@ -2950,11 +2955,41 @@ udmf } } + 460 + { + title = "Award Rings"; + prefix = "(460)"; + arg0 + { + title = "Rings"; + } + arg1 + { + title = "Periodicity"; + } + } + 462 { title = "Stop Timer/Exit Stage in Record Attack"; prefix = "(462)"; } + + 466 + { + title = "Set Level Failure State"; + prefix = "(466)"; + arg0 + { + title = "State"; + type = 11; + enum + { + 0 = "Failure"; + 1 = "Success"; + } + } + } } linedefexecmisc @@ -3021,6 +3056,16 @@ udmf prefix = "(440)"; } + 441 + { + title = "Condition Set Trigger"; + prefix = "(441)"; + arg0 + { + title = "Trigger number"; + } + } + 443 { title = "Call Lua Function"; @@ -3032,6 +3077,20 @@ udmf } } + 444 + { + title = "Earthquake"; + prefix = "(444)"; + arg0 + { + title = "Duration"; + } + arg1 + { + title = "Intensity"; + } + } + 447 { title = "Change Tagged Sector's Colormap"; @@ -3068,6 +3127,84 @@ udmf } } + 448 + { + title = "Change Skybox"; + prefix = "(448)"; + arg0 + { + title = "Viewpoint ID"; + } + arg1 + { + title = "Centerpoint ID"; + } + arg2 + { + title = "Change?"; + type = 11; + enum + { + 0 = "Viewpoint"; + 1 = "Centerpoint"; + 2 = "Both"; + } + } + arg3 + { + title = "For all players?"; + type = 11; + enum = "noyes"; + } + } + + 449 + { + title = "Enable Bosses with Parameter"; + prefix = "(449)"; + arg0 + { + title = "Boss ID"; + } + arg1 + { + title = Effect"; + type = 11; + enum + { + 0 = "Enable"; + 1 = "Disable"; + } + } + } + + 450 + { + title = "Execute Linedef Executor (specific tag)"; + prefix = "(450)"; + arg0 + { + title = "Trigger linedef tag"; + type = 15; + } + } + + 451 + { + title = "Execute Linedef Executor (random tag in range)"; + prefix = "(451)"; + arg0 + { + title = "Start of tag range"; + type = 15; + } + arg1 + { + title = "End of tag range"; + type = 15; + } + } + 455 { title = "Fade Tagged Sector's Colormap"; diff --git a/src/p_setup.c b/src/p_setup.c index f5f3a22cc..782253cbd 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3824,6 +3824,9 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); break; + case 441: //Condition set trigger + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + break; case 443: //Call Lua function if (lines[i].text) { @@ -3833,6 +3836,11 @@ static void P_ConvertBinaryMap(void) else CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(i)); break; + case 444: //Earthquake + lines[i].args[0] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + break; case 447: //Change colormap lines[i].args[0] = Tag_FGet(&lines[i].tags); if (lines[i].flags & ML_EFFECT3) @@ -3844,6 +3852,36 @@ static void P_ConvertBinaryMap(void) if (lines[i].flags & ML_EFFECT2) lines[i].args[2] |= TMCF_SUBLIGHTB|TMCF_SUBFADEB; break; + case 448: //Change skybox + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + if ((lines[i].flags & (ML_EFFECT4|ML_BLOCKMONSTERS)) == ML_EFFECT4) // Solid Midtexture is on but Block Enemies is off? + { + CONS_Alert(CONS_WARNING, + M_GetText("Skybox switch linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), + tag); + lines[i].special = 0; + break; + } + else if ((lines[i].flags & (ML_EFFECT4|ML_BLOCKMONSTERS)) == (ML_EFFECT4|ML_BLOCKMONSTERS)) + lines[i].args[2] = TMS_CENTERPOINT; + else if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[2] = TMS_BOTH; + else + lines[i].args[2] = TMS_VIEWPOINT; + lines[i].args[3] = !!(lines[i].flags & ML_NOCLIMB); + break; + case 449: //Enable bosses with parameters + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); + break; + case 450: //Execute linedef executor (specific tag) + lines[i].args[0] = tag; + break; + case 451: //Execute linedef executor (random tag in range) + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + break; case 455: //Fade colormap { INT32 speed = (INT32)((((lines[i].flags & ML_DONTPEGBOTTOM) || !sides[lines[i].sidenum[0]].rowoffset) && lines[i].sidenum[1] != 0xFFFF) ? @@ -3872,6 +3910,13 @@ static void P_ConvertBinaryMap(void) case 456: //Stop fading colormap lines[i].args[0] = Tag_FGet(&lines[i].tags); break; + case 460: //Award rings + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + break; + case 466: //Set level failure state + lines[i].args[0] = !!(lines[i].flags & ML_NOCLIMB); + break; case 467: //Set light level lines[i].args[0] = tag; lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index e6dcf118a..a4d358361 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2812,7 +2812,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 441: // Trigger unlockable if ((!modifiedgame || savemoddata) && !(netgame || multiplayer)) { - INT32 trigid = (INT32)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT32 trigid = line->args[0]; if (trigid < 0 || trigid > 31) // limited by 32 bit variable CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", line->sidenum[0], trigid); @@ -2880,9 +2880,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 444: // Earthquake camera { - quake.intensity = sides[line->sidenum[0]].textureoffset; - quake.radius = sides[line->sidenum[0]].rowoffset; - quake.time = P_AproxDistance(line->dx, line->dy)>>FRACBITS; + quake.intensity = line->args[1] << FRACBITS; + quake.radius = line->args[2] << FRACBITS; + quake.time = line->args[0]; quake.epicenter = NULL; /// \todo @@ -3060,57 +3060,48 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; } case 448: // Change skybox viewpoint/centerpoint - if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB)) + if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || line->args[3]) { - INT32 viewid = sides[line->sidenum[0]].textureoffset>>FRACBITS; - INT32 centerid = sides[line->sidenum[0]].rowoffset>>FRACBITS; + INT32 viewid = line->args[0]; + INT32 centerid = line->args[1]; - if ((line->flags & (ML_EFFECT4|ML_BLOCKMONSTERS)) == ML_EFFECT4) // Solid Midtexture is on but Block Enemies is off? + // set viewpoint mobj + if (line->args[2] != TMS_CENTERPOINT) { - CONS_Alert(CONS_WARNING, - M_GetText("Skybox switch linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), - tag); + if (viewid >= 0 && viewid < 16) + skyboxmo[0] = skyboxviewpnts[viewid]; + else + skyboxmo[0] = NULL; } - else - { - // set viewpoint mobj - if (!(line->flags & ML_EFFECT4)) // Solid Midtexture turns off viewpoint setting - { - if (viewid >= 0 && viewid < 16) - skyboxmo[0] = skyboxviewpnts[viewid]; - else - skyboxmo[0] = NULL; - } - // set centerpoint mobj - if (line->flags & ML_BLOCKMONSTERS) // Block Enemies turns ON centerpoint setting - { - if (centerid >= 0 && centerid < 16) - skyboxmo[1] = skyboxcenterpnts[centerid]; - else - skyboxmo[1] = NULL; - } + // set centerpoint mobj + if (line->args[2] != TMS_VIEWPOINT) + { + if (centerid >= 0 && centerid < 16) + skyboxmo[1] = skyboxcenterpnts[centerid]; + else + skyboxmo[1] = NULL; } CONS_Debug(DBG_GAMELOGIC, "Line type 448 Executor: viewid = %d, centerid = %d, viewpoint? = %s, centerpoint? = %s\n", viewid, centerid, - ((line->flags & ML_EFFECT4) ? "no" : "yes"), - ((line->flags & ML_BLOCKMONSTERS) ? "yes" : "no")); + ((line->args[2] == TMS_CENTERPOINT) ? "no" : "yes"), + ((line->args[2] == TMS_VIEWPOINT) ? "no" : "yes")); } break; case 449: // Enable bosses with parameter { - INT32 bossid = sides[line->sidenum[0]].textureoffset>>FRACBITS; + INT32 bossid = line->args[0]; if (bossid & ~15) // if any bits other than first 16 are set { CONS_Alert(CONS_WARNING, - M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"), - tag); + M_GetText("Boss enable linedef has an invalid boss ID (%d).\nConsider changing it or removing it entirely.\n"), + bossid); break; } - if (line->flags & ML_NOCLIMB) + if (line->args[1]) { bossdisabled |= (1<args[0], mo, NULL); break; case 451: // Execute Random Linedef Executor { - INT32 rvalue1 = sides[line->sidenum[0]].textureoffset>>FRACBITS; - INT32 rvalue2 = sides[line->sidenum[0]].rowoffset>>FRACBITS; + INT32 rvalue1 = line->args[0]; + INT32 rvalue2 = line->args[1]; INT32 result; if (rvalue1 <= rvalue2) @@ -3500,8 +3491,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 460: // Award rings { - INT16 rings = (sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT32 delay = (sides[line->sidenum[0]].rowoffset>>FRACBITS); + INT16 rings = line->args[0]; + INT32 delay = line->args[1]; if (mo && mo->player) { if (delay <= 0 || !(leveltime % delay)) @@ -3641,7 +3632,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 466: // Set level failure state { - if (line->flags & ML_NOCLIMB) + if (line->args[1]) { stagefailed = false; CONS_Debug(DBG_GAMELOGIC, "Stage can be completed successfully!\n"); diff --git a/src/p_spec.h b/src/p_spec.h index c81839f22..caaf259db 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -139,6 +139,13 @@ typedef enum TMB_SYNC = 1<<1, } textmapblinkinglightflags_t; +typedef enum +{ + TMS_VIEWPOINT = 0, + TMS_CENTERPOINT = 1, + TMS_BOTH = 2, +} textmapskybox_t; + typedef enum { TMSD_FRONT = 0, From 3a73c6167ccbbe1c9286c99043552253d91d936a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Sep 2021 14:42:21 +0200 Subject: [PATCH 130/326] Adapt linedef type 439 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 23 ++++++++++++++++ src/p_setup.c | 5 ++++ src/p_spec.c | 29 +++++++++++--------- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 9447a53ad..27d8454dd 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -3050,6 +3050,29 @@ udmf } } + 439 + { + title = "Change Tagged Linedef's Textures"; + prefix = "(439)"; + arg0 + { + title = "Target linedef tag"; + type = 15; + } + arg1 + { + title = "Affected sides"; + type = 11; + enum = "frontbackboth"; + } + arg2 + { + title = "Change unset textures?"; + type = 11; + enum = "yesno"; + } + } + 440 { title = "Start Metal Sonic Race"; diff --git a/src/p_setup.c b/src/p_setup.c index 782253cbd..1476e1d43 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3824,6 +3824,11 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); break; + case 439: //Change tagged linedef's textures + lines[i].args[0] = tag; + lines[i].args[1] = TMSD_FRONTBACK; + lines[i].args[2] = !!(lines[i].flags & ML_NOCLIMB); + break; case 441: //Condition set trigger lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; break; diff --git a/src/p_spec.c b/src/p_spec.c index a4d358361..11a03056f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2776,30 +2776,33 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { size_t linenum; side_t *set = &sides[line->sidenum[0]], *this; - boolean always = !(line->flags & ML_NOCLIMB); // If noclimb: Only change mid texture if mid texture already exists on tagged lines, etc. + boolean always = !(line->args[2]); // If args[2] is set: Only change mid texture if mid texture already exists on tagged lines, etc. for (linenum = 0; linenum < numlines; linenum++) { if (lines[linenum].special == 439) continue; // Don't override other set texture lines! - if (!Tag_Find(&lines[linenum].tags, tag)) + if (!Tag_Find(&lines[linenum].tags, line->args[0])) continue; // Find tagged lines // Front side - this = &sides[lines[linenum].sidenum[0]]; - if (always || this->toptexture) this->toptexture = set->toptexture; - if (always || this->midtexture) this->midtexture = set->midtexture; - if (always || this->bottomtexture) this->bottomtexture = set->bottomtexture; - - if (lines[linenum].sidenum[1] == 0xffff) - continue; // One-sided stops here. + if (line->args[1] != TMSD_BACK) + { + this = &sides[lines[linenum].sidenum[0]]; + if (always || this->toptexture) this->toptexture = set->toptexture; + if (always || this->midtexture) this->midtexture = set->midtexture; + if (always || this->bottomtexture) this->bottomtexture = set->bottomtexture; + } // Back side - this = &sides[lines[linenum].sidenum[1]]; - if (always || this->toptexture) this->toptexture = set->toptexture; - if (always || this->midtexture) this->midtexture = set->midtexture; - if (always || this->bottomtexture) this->bottomtexture = set->bottomtexture; + if (line->args[1] != TMSD_FRONT && lines[linenum].sidenum[1] != 0xffff) + { + this = &sides[lines[linenum].sidenum[1]]; + if (always || this->toptexture) this->toptexture = set->toptexture; + if (always || this->midtexture) this->midtexture = set->midtexture; + if (always || this->bottomtexture) this->bottomtexture = set->bottomtexture; + } } } break; From 1bbf1b2887893405eea1bddb11dbf9a393a87111 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Sep 2021 14:50:18 +0200 Subject: [PATCH 131/326] Adapt linedef type 438 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 13 ++++++++++++- src/p_setup.c | 3 +++ src/p_spec.c | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 27d8454dd..e6e26b579 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2955,6 +2955,17 @@ udmf } } + 438 + { + title = "Change Object Size"; + prefix = "(438)"; + arg0 + { + title = "Size (%)"; + default = 100; + } + } + 460 { title = "Award Rings"; @@ -3191,7 +3202,7 @@ udmf } arg1 { - title = Effect"; + title = "Effect"; type = 11; enum { diff --git a/src/p_setup.c b/src/p_setup.c index 1476e1d43..0ea997eda 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3824,6 +3824,9 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); break; + case 438: //Change object size + lines[i].args[0] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + break; case 439: //Change tagged linedef's textures lines[i].args[0] = tag; lines[i].args[1] = TMSD_FRONTBACK; diff --git a/src/p_spec.c b/src/p_spec.c index 11a03056f..135670720 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2764,7 +2764,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 438: // Set player scale if (mo) { - mo->destscale = FixedDiv(P_AproxDistance(line->dx, line->dy), 100<destscale = FixedDiv(line->args[0]<destscale < FRACUNIT/100) mo->destscale = FRACUNIT/100; if (mo->player && bot) From 76c6b6f24f171a9f68a5a146d9741961edd531be Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Sep 2021 15:07:08 +0200 Subject: [PATCH 132/326] Forgot to adapt half of linedef type 449 --- src/p_spec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 135670720..efc5bc868 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6776,15 +6776,15 @@ void P_SpawnSpecials(boolean fromnetsave) case 449: // Enable bosses with parameter { - INT32 bossid = sides[*lines[i].sidenum].textureoffset>>FRACBITS; + INT32 bossid = lines[i].args[0]; if (bossid & ~15) // if any bits other than first 16 are set { CONS_Alert(CONS_WARNING, - M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"), - tag); + M_GetText("Boss enable linedef has an invalid boss ID (%d).\nConsider changing it or removing it entirely.\n"), + bossid); break; } - if (!(lines[i].flags & ML_NOCLIMB)) + if (!(lines[i].args[1])) { bossdisabled |= (1< Date: Tue, 21 Sep 2021 07:36:54 +0200 Subject: [PATCH 133/326] Adapt linedef types 425 and 442 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 42 ++++++++++++++++ src/p_setup.c | 30 +++++++++++- src/p_spec.c | 50 +++++++++++--------- 3 files changed, 97 insertions(+), 25 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index e6e26b579..ad7109769 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2885,6 +2885,17 @@ udmf { title = "Linedef Executor (player/object)"; + 425 + { + title = "Change Object State"; + prefix = "(425)"; + stringarg0 + { + title = "State"; + type = 2; + } + } + 426 { title = "Stop Object"; @@ -2966,6 +2977,37 @@ udmf } } + 442 + { + title = "Change Object Type State"; + prefix = "(442)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Change to"; + type = 11; + enum + { + 0 = "Specified state"; + 1 = "Next state"; + } + } + stringarg0 + { + title = "Object type"; + type = 2; + } + stringarg1 + { + title = "State"; + type = 2; + } + } + 460 { title = "Award Rings"; diff --git a/src/p_setup.c b/src/p_setup.c index 0ea997eda..c05fa5aae 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1292,9 +1292,7 @@ static void P_LoadSidedefs(UINT8 *data) case 334: // Trigger linedef executor: Object dye - Continuous case 335: // Trigger linedef executor: Object dye - Each time case 336: // Trigger linedef executor: Object dye - Once - case 425: // Calls P_SetMobjState on calling mobj case 434: // Custom Power - case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors case 461: // Spawns an object on the map based on texture offsets case 463: // Colorizes an object { @@ -1316,6 +1314,8 @@ static void P_LoadSidedefs(UINT8 *data) case 331: // Trigger linedef executor: Skin - Continuous case 332: // Trigger linedef executor: Skin - Each time case 333: // Trigger linedef executor: Skin - Once + case 425: // Calls P_SetMobjState on calling mobj + case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors case 443: // Calls a named Lua function case 459: // Control text prompt (named tag) { @@ -3780,6 +3780,13 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); break; + case 425: //Change object state + if (sides[lines[i].sidenum[0]].text) + { + lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); + } + break; case 426: //Stop object lines[i].args[0] = !!(lines[i].flags & ML_NOCLIMB); break; @@ -3835,6 +3842,25 @@ static void P_ConvertBinaryMap(void) case 441: //Condition set trigger lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; break; + case 442: //Change object type state + lines[i].args[0] = tag; + if (sides[lines[i].sidenum[0]].text) + { + lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); + } + if (lines[i].sidenum[1] == 0xffff) + lines[i].args[1] = 1; + else + { + lines[i].args[1] = 0; + if (sides[lines[i].sidenum[1]].text) + { + lines[i].stringargs[1] = Z_Malloc(strlen(sides[lines[i].sidenum[1]].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[1], sides[lines[i].sidenum[1]].text, strlen(sides[lines[i].sidenum[1]].text) + 1); + } + } + break; case 443: //Call Lua function if (lines[i].text) { diff --git a/src/p_spec.c b/src/p_spec.c index efc5bc868..14363bb1d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2576,7 +2576,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 425: // Calls P_SetMobjState on calling mobj if (mo && !mo->player) - P_SetMobjState(mo, sides[line->sidenum[0]].toptexture); //P_AproxDistance(line->dx, line->dy)>>FRACBITS); + { + statenum_t state = line->stringargs[0] ? get_number(line->stringargs[0]) : S_NULL; + if (state >= 0 && state < NUMSTATES) + P_SetMobjState(mo, state); + } break; case 426: // Moves the mobj to its sector's soundorg and on the floor, and stops it @@ -2838,37 +2842,37 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors { - const mobjtype_t type = (mobjtype_t)sides[line->sidenum[0]].toptexture; + const mobjtype_t type = line->stringargs[0] ? get_number(line->stringargs[0]) : MT_NULL; statenum_t state = NUMSTATES; - sector_t *sec; mobj_t *thing; - if (line->sidenum[1] != 0xffff) - state = (statenum_t)sides[line->sidenum[1]].toptexture; + if (type < 0 || type >= NUMMOBJTYPES) + break; - TAG_ITER_SECTORS(tag, secnum) + if (!line->args[1]) + { + state = line->stringargs[1] ? get_number(line->stringargs[1]) : S_NULL; + + if (state < 0 || state >= NUMSTATES) + break; + } + + TAG_ITER_SECTORS(line->args[0], secnum) { boolean tryagain; - sec = sectors + secnum; do { tryagain = false; - for (thing = sec->thinglist; thing; thing = thing->snext) - if (thing->type == type) - { - if (state != NUMSTATES) - { - if (!P_SetMobjState(thing, state)) // set state to specific state - { // mobj was removed - tryagain = true; // snext is corrupt, we'll have to start over. - break; - } - } - else if (!P_SetMobjState(thing, thing->state->nextstate)) // set state to nextstate - { // mobj was removed - tryagain = true; // snext is corrupt, we'll have to start over. - break; - } + for (thing = sectors[secnum].thinglist; thing; thing = thing->snext) + { + if (thing->type != type) + continue; + + if (!P_SetMobjState(thing, line->args[1] ? thing->state->nextstate : state)) + { // mobj was removed + tryagain = true; // snext is corrupt, we'll have to start over. + break; } + } } while (tryagain); } break; From 17bd20a15ec565e1aec078975970e02d460c984a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 07:44:55 +0200 Subject: [PATCH 134/326] Adapt linedef type 463 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 16 ++++++++++++++++ src/p_setup.c | 9 ++++++++- src/p_spec.c | 4 ++-- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index ad7109769..d00321707 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -952,6 +952,11 @@ doom title = "Stop Timer/Exit Stage in Record Attack"; prefix = "(462)"; } + 463 + { + title = "Dye Object"; + prefix = "(463)"; + } 466 { title = "Set Level Failure State"; @@ -3028,6 +3033,17 @@ udmf prefix = "(462)"; } + 463 + { + title = "Dye Object"; + prefix = "(463)"; + stringarg0 + { + title = "Skin color"; + type = 2; + } + } + 466 { title = "Set Level Failure State"; diff --git a/src/p_setup.c b/src/p_setup.c index c05fa5aae..92b425665 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1294,7 +1294,6 @@ static void P_LoadSidedefs(UINT8 *data) case 336: // Trigger linedef executor: Object dye - Once case 434: // Custom Power case 461: // Spawns an object on the map based on texture offsets - case 463: // Colorizes an object { char process[8*3+1]; memset(process,0,8*3+1); @@ -1318,6 +1317,7 @@ static void P_LoadSidedefs(UINT8 *data) case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors case 443: // Calls a named Lua function case 459: // Control text prompt (named tag) + case 463: // Colorizes an object { char process[8*3+1]; memset(process,0,8*3+1); @@ -3948,6 +3948,13 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; break; + case 463: //Dye object + if (sides[lines[i].sidenum[0]].text) + { + lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); + } + break; case 466: //Set level failure state lines[i].args[0] = !!(lines[i].flags & ML_NOCLIMB); break; diff --git a/src/p_spec.c b/src/p_spec.c index 14363bb1d..2527c57c3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3565,10 +3565,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 463: // Dye object { - INT32 color = sides[line->sidenum[0]].toptexture; - if (mo) { + INT32 color = line->stringargs[0] ? get_number(line->stringargs[0]) : SKINCOLOR_NONE; + if (color < 0 || color >= numskincolors) return; From ea1d442f31b2be3c6e6d091d2ac6bd47bf3efd87 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 08:34:55 +0200 Subject: [PATCH 135/326] Adapt linedef type 434 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 16 +++++++++++++ src/p_setup.c | 24 +++++++++++++++++++- src/p_spec.c | 10 +++----- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index d00321707..14f19b905 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2955,6 +2955,22 @@ udmf } } + 434 + { + title = "Award Power-Up"; + prefix = "(434)"; + stringarg0 + { + title = "Power"; + type = 2; + } + stringarg1 + { + title = "Duration/Amount"; + type = 2; + } + } + 437 { title = "Disable Player Control"; diff --git a/src/p_setup.c b/src/p_setup.c index 92b425665..0a0976cc8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1292,7 +1292,6 @@ static void P_LoadSidedefs(UINT8 *data) case 334: // Trigger linedef executor: Object dye - Continuous case 335: // Trigger linedef executor: Object dye - Each time case 336: // Trigger linedef executor: Object dye - Once - case 434: // Custom Power case 461: // Spawns an object on the map based on texture offsets { char process[8*3+1]; @@ -1314,6 +1313,7 @@ static void P_LoadSidedefs(UINT8 *data) case 332: // Trigger linedef executor: Skin - Each time case 333: // Trigger linedef executor: Skin - Once case 425: // Calls P_SetMobjState on calling mobj + case 434: // Custom Power case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors case 443: // Calls a named Lua function case 459: // Control text prompt (named tag) @@ -3823,6 +3823,28 @@ static void P_ConvertBinaryMap(void) case 433: //Enable/disable gravity flip lines[i].args[0] = !!(lines[i].flags & ML_NOCLIMB); break; + case 434: //Award power-up + if (sides[lines[i].sidenum[0]].text) + { + lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); + } + if (lines[i].sidenum[1] != 0xffff && lines[i].flags & ML_BLOCKMONSTERS) // read power from back sidedef + { + lines[i].stringargs[1] = Z_Malloc(strlen(sides[lines[i].sidenum[1]].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[1], sides[lines[i].sidenum[1]].text, strlen(sides[lines[i].sidenum[1]].text) + 1); + } + else if (lines[i].flags & ML_NOCLIMB) // 'Infinite' + { + lines[i].stringargs[1] = Z_Malloc(3, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[1], "-1", 3); + } + else + { + lines[i].stringargs[1] = Z_Malloc(7, PU_LEVEL, NULL); + snprintf(lines[i].stringargs[1], 7, "%d", sides[lines[i].sidenum[0]].textureoffset >> FRACBITS); + } + break; case 435: //Change plane scroller direction lines[i].args[0] = tag; lines[i].args[1] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index 2527c57c3..4f2a091d1 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2669,14 +2669,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { mobj_t *dummy = P_SpawnMobj(mo->x, mo->y, mo->z, MT_NULL); - var1 = sides[line->sidenum[0]].toptexture; //(line->dx>>FRACBITS)-1; - - if (line->sidenum[1] != 0xffff && line->flags & ML_BLOCKMONSTERS) // read power from back sidedef - var2 = sides[line->sidenum[1]].toptexture; - else if (line->flags & ML_NOCLIMB) // 'Infinite' + var1 = line->stringargs[0] ? get_number(line->stringargs[0]) : 0; + var2 = line->stringargs[1] ? get_number(line->stringargs[1]) : 0; + if (var2 == -1) // 'Infinite' var2 = UINT16_MAX; - else - var2 = sides[line->sidenum[0]].textureoffset>>FRACBITS; P_SetTarget(&dummy->target, mo); A_CustomPower(dummy); From 69e0c636a0236170e806ed3fd17d3cfd4d0bdcbd Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 09:05:40 +0200 Subject: [PATCH 136/326] Adapt linedef type 459 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 35 ++++++++++++++++++++ src/p_setup.c | 24 ++++++++++++++ src/p_spec.c | 26 +++++++-------- src/p_spec.h | 11 ++++++ 4 files changed, 83 insertions(+), 13 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 14f19b905..a33e54d68 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -3366,6 +3366,41 @@ udmf } } + 459 + { + title = "Control Text Prompt"; + prefix = "(459)"; + arg0 + { + title = "Prompt number"; + } + arg1 + { + title = "Page number"; + } + arg2 + { + title = "Flags"; + type = 11; + enum + { + 1 = "Close current text prompt"; + 2 = "Trigger linedef executor on close"; + 4 = "Find prompt by name"; + 8 = "Don't disable controls"; + } + } + arg3 + { + title = "Trigger linedef tag"; + type = 15; + } + stringarg0 + { + title = "Prompt name"; + } + } + 465 { title = "Set Linedef Executor Delay"; diff --git a/src/p_setup.c b/src/p_setup.c index 0a0976cc8..181c4eada 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3966,6 +3966,30 @@ static void P_ConvertBinaryMap(void) case 456: //Stop fading colormap lines[i].args[0] = Tag_FGet(&lines[i].tags); break; + case 459: //Control text prompt + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[2] |= TMP_CLOSE; + if (lines[i].flags & ML_EFFECT1) + lines[i].args[2] |= TMP_RUNPOSTEXEC; + if (lines[i].flags & ML_TFERLINE) + lines[i].args[2] |= TMP_CALLBYNAME; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[2] |= TMP_KEEPCONTROLS; + if (lines[i].flags & ML_EFFECT3) + lines[i].args[2] |= TMP_KEEPREALTIME; + /*if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] |= TMP_ALLPLAYERS; + if (lines[i].flags & ML_EFFECT4) + lines[i].args[2] |= ML_EFFECT4;*/ + lines[i].args[3] = (lines[i].sidenum[1] != 0xFFFF) ? sides[lines[i].sidenum[1]].textureoffset >> FRACBITS : tag; + if (sides[lines[i].sidenum[0]].text) + { + lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); + } + break; case 460: //Award rings lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index 4f2a091d1..8e469e8e9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3466,27 +3466,27 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 459: // Control Text Prompt - // console player only unless NOCLIMB is set + // console player only if (mo && mo->player && P_IsLocalPlayer(mo->player) && (!bot || bot != mo)) { - INT32 promptnum = max(0, (sides[line->sidenum[0]].textureoffset>>FRACBITS)-1); - INT32 pagenum = max(0, (sides[line->sidenum[0]].rowoffset>>FRACBITS)-1); - INT32 postexectag = abs((line->sidenum[1] != 0xFFFF) ? sides[line->sidenum[1]].textureoffset>>FRACBITS : tag); + INT32 promptnum = max(0, line->args[0] - 1); + INT32 pagenum = max(0, line->args[1] - 1); + INT32 postexectag = abs(line->args[3]); - boolean closetextprompt = (line->flags & ML_BLOCKMONSTERS); - //boolean allplayers = (line->flags & ML_NOCLIMB); - boolean runpostexec = (line->flags & ML_EFFECT1); - boolean blockcontrols = !(line->flags & ML_EFFECT2); - boolean freezerealtime = !(line->flags & ML_EFFECT3); - //boolean freezethinkers = (line->flags & ML_EFFECT4); - boolean callbynamedtag = (line->flags & ML_TFERLINE); + boolean closetextprompt = (line->args[2] & TMP_CLOSE); + //boolean allplayers = (line->args[2] & TMP_ALLPLAYERS); + boolean runpostexec = (line->args[2] & TMP_RUNPOSTEXEC); + boolean blockcontrols = !(line->args[2] & TMP_KEEPCONTROLS); + boolean freezerealtime = !(line->args[2] & TMP_KEEPREALTIME); + //boolean freezethinkers = (line->args[2] & TMP_FREEZETHINKERS); + boolean callbynamedtag = (line->args[2] & TMP_CALLBYNAME); if (closetextprompt) F_EndTextPrompt(false, false); else { - if (callbynamedtag && sides[line->sidenum[0]].text && sides[line->sidenum[0]].text[0]) - F_GetPromptPageByNamedTag(sides[line->sidenum[0]].text, &promptnum, &pagenum); + if (callbynamedtag && line->stringargs[0] && line->stringargs[0][0]) + F_GetPromptPageByNamedTag(line->stringargs[0], &promptnum, &pagenum); F_StartTextPrompt(promptnum, pagenum, mo, runpostexec ? postexectag : 0, blockcontrols, freezerealtime); } } diff --git a/src/p_spec.h b/src/p_spec.h index caaf259db..07f566e2a 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -146,6 +146,17 @@ typedef enum TMS_BOTH = 2, } textmapskybox_t; +typedef enum +{ + TMP_CLOSE = 1, + TMP_RUNPOSTEXEC = 1<<1, + TMP_CALLBYNAME = 1<<2, + TMP_KEEPCONTROLS = 1<<3, + TMP_KEEPREALTIME = 1<<4, + //TMP_ALLPLAYERS = 1<<5, + //TMP_FREEZETHINKERS = 1<<6, +} textmappromptflags_t; + typedef enum { TMSD_FRONT = 0, From 890934264b577b123f70cd8042442980fcaa79af Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 10:14:55 +0200 Subject: [PATCH 137/326] Adapt linedef type 414 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 39 ++++ src/p_setup.c | 59 +++++- src/p_spec.c | 196 ++++++++++--------- src/p_spec.h | 15 ++ 4 files changed, 212 insertions(+), 97 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index a33e54d68..10a2f768f 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -3081,6 +3081,45 @@ udmf { title = "Linedef Executor (misc.)"; + 414 + { + title = "Play Sound Effect"; + prefix = "(414)"; + arg0 + { + title = "Source"; + type = 11; + enum + { + 0 = "Triggering object"; + 1 = "Trigger sector"; + 2 = "Nowhere"; + 3 = "Tagged sectors"; + } + } + arg1 + { + title = "Listener"; + type = 11; + enum + { + 0 = "Triggering player"; + 1 = "Everyone"; + 2 = "Everyone touching tagged sectors"; + } + } + arg2 + { + title = "Target sector tag"; + type = 13; + } + stringarg0 + { + title = "Sound name"; + type = 2; + } + } + 415 { title = "Run Script"; diff --git a/src/p_setup.c b/src/p_setup.c index 181c4eada..f834cd3fa 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1273,7 +1273,6 @@ static void P_LoadSidedefs(UINT8 *data) } case 4: // Speed pad parameters - case 414: // Play SFX { sd->toptexture = sd->midtexture = sd->bottomtexture = 0; if (msd->toptexture[0] != '-' || msd->toptexture[1] != '\0') @@ -1286,6 +1285,20 @@ static void P_LoadSidedefs(UINT8 *data) break; } + case 414: // Play SFX + { + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; + if (msd->toptexture[0] != '-' || msd->toptexture[1] != '\0') + { + char process[8 + 1]; + M_Memcpy(process, msd->toptexture, 8); + process[8] = '\0'; + sd->text = Z_Malloc(strlen(process) + 1, PU_LEVEL, NULL); + M_Memcpy(sd->text, process, strlen(process) + 1); + } + break; + } + case 9: // Mace parameters case 14: // Bustable block parameters case 15: // Fan particle spawner parameters @@ -3696,6 +3709,50 @@ static void P_ConvertBinaryMap(void) case 411: //Stop plane movement lines[i].args[0] = tag; break; + case 414: //Play sound effect + lines[i].args[2] = tag; + if (tag != 0) + { + if (lines[i].flags & ML_EFFECT5) + { + lines[i].args[0] = TMSS_TAGGEDSECTOR; + lines[i].args[1] = TMSL_EVERYONE; + } + else + { + lines[i].args[0] = TMSS_NOWHERE; + lines[i].args[1] = TMSL_TAGGEDSECTOR; + } + } + else + { + if (lines[i].flags & ML_NOCLIMB) + { + lines[i].args[0] = TMSS_NOWHERE; + lines[i].args[1] = TMSL_TRIGGERER; + } + else if (lines[i].flags & ML_EFFECT4) + { + lines[i].args[0] = TMSS_NOWHERE; + lines[i].args[1] = TMSL_EVERYONE; + } + else if (lines[i].flags & ML_BLOCKMONSTERS) + { + lines[i].args[0] = TMSS_TRIGGERSECTOR; + lines[i].args[1] = TMSL_EVERYONE; + } + else + { + lines[i].args[0] = TMSS_TRIGGERMOBJ; + lines[i].args[1] = TMSL_EVERYONE; + } + } + if (sides[lines[i].sidenum[0]].text) + { + lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); + } + break; case 415: //Run script { INT32 scrnum; diff --git a/src/p_spec.c b/src/p_spec.c index 8e469e8e9..b828d97cd 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1906,6 +1906,105 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) } } +static void P_PlaySFX(INT32 sfxnum, mobj_t *mo, sector_t *callsec, INT16 tag, textmapsoundsource_t source, textmapsoundlistener_t listener) +{ + if (sfxnum == sfx_None) + return; // Do nothing! + + if (sfxnum < sfx_None || sfxnum >= NUMSFX) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 414 Executor: sfx number %d is invalid!\n", sfxnum); + return; + } + + // Check if you can hear the sound + switch (listener) + { + case TMSL_TRIGGERER: // only play sound if displayplayer + if (!mo) + return; + + if (!mo->player) + return; + + if (mo->player != &players[displayplayer] && mo->player != &players[secondarydisplayplayer]) + return; + + break; + case TMSL_TAGGEDSECTOR: // only play if touching tagged sectors + { + UINT8 i = 0; + mobj_t *camobj = players[displayplayer].mo; + ffloor_t *rover; + boolean foundit = false; + + for (i = 0; i < 2; camobj = players[secondarydisplayplayer].mo, i++) + { + if (!camobj) + continue; + + if (foundit || Tag_Find(&camobj->subsector->sector->tags, tag)) + { + foundit = true; + break; + } + + // Only trigger if mobj is touching the tag + for (rover = camobj->subsector->sector->ffloors; rover; rover = rover->next) + { + if (!Tag_Find(&rover->master->frontsector->tags, tag)) + continue; + + if (camobj->z > P_GetSpecialTopZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) + continue; + + if (camobj->z + camobj->height < P_GetSpecialBottomZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) + continue; + + foundit = true; + break; + } + } + + if (!foundit) + return; + + break; + } + case TMSL_EVERYONE: // no additional check + default: + break; + } + + // Play the sound from the specified source + switch (source) + { + case TMSS_TRIGGERMOBJ: // play the sound from mobj that triggered it + if (mo) + S_StartSound(mo, sfxnum); + break; + case TMSS_TRIGGERSECTOR: // play the sound from calling sector's soundorg + if (callsec) + S_StartSound(&callsec->soundorg, sfxnum); + else if (mo) + S_StartSound(&mo->subsector->sector->soundorg, sfxnum); + break; + case TMSS_NOWHERE: // play the sound from nowhere + S_StartSound(NULL, sfxnum); + break; + case TMSS_TAGGEDSECTOR: // play the sound from tagged sectors' soundorgs + { + INT32 secnum; + + TAG_ITER_SECTORS(tag, secnum) + S_StartSound(§ors[secnum].soundorg, sfxnum); + break; + } + default: + break; + } +} + static boolean is_rain_type (INT32 weathernum) { switch (weathernum) @@ -2368,102 +2467,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 414: // Play SFX - { - INT32 sfxnum; - - sfxnum = sides[line->sidenum[0]].toptexture; - - if (sfxnum == sfx_None) - return; // Do nothing! - if (sfxnum < sfx_None || sfxnum >= NUMSFX) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 414 Executor: sfx number %d is invalid!\n", sfxnum); - return; - } - - if (tag != 0) // Do special stuff only if a non-zero linedef tag is set - { - // Play sounds from tagged sectors' origins. - if (line->flags & ML_EFFECT5) // Repeat Midtexture - { - // Additionally play the sound from tagged sectors' soundorgs - sector_t *sec; - - TAG_ITER_SECTORS(tag, secnum) - { - sec = §ors[secnum]; - S_StartSound(&sec->soundorg, sfxnum); - } - } - - // Play the sound without origin for anyone, as long as they're inside tagged areas. - else - { - UINT8 i = 0; - mobj_t* camobj = players[displayplayer].mo; - ffloor_t *rover; - boolean foundit = false; - - for (i = 0; i < 2; camobj = players[secondarydisplayplayer].mo, i++) - { - if (!camobj) - continue; - - if (foundit || Tag_Find(&camobj->subsector->sector->tags, tag)) - { - foundit = true; - break; - } - - // Only trigger if mobj is touching the tag - for(rover = camobj->subsector->sector->ffloors; rover; rover = rover->next) - { - if (!Tag_Find(&rover->master->frontsector->tags, tag)) - continue; - - if (camobj->z > P_GetSpecialTopZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) - continue; - - if (camobj->z + camobj->height < P_GetSpecialBottomZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) - continue; - - foundit = true; - break; - } - } - - if (foundit) - S_StartSound(NULL, sfxnum); - } - } - else - { - if (line->flags & ML_NOCLIMB) - { - // play the sound from nowhere, but only if display player triggered it - if (mo && mo->player && (mo->player == &players[displayplayer] || mo->player == &players[secondarydisplayplayer])) - S_StartSound(NULL, sfxnum); - } - else if (line->flags & ML_EFFECT4) - { - // play the sound from nowhere - S_StartSound(NULL, sfxnum); - } - else if (line->flags & ML_BLOCKMONSTERS) - { - // play the sound from calling sector's soundorg - if (callsec) - S_StartSound(&callsec->soundorg, sfxnum); - else if (mo) - S_StartSound(&mo->subsector->sector->soundorg, sfxnum); - } - else if (mo) - { - // play the sound from mobj that triggered it - S_StartSound(mo, sfxnum); - } - } - } + P_PlaySFX(line->stringargs[0] ? get_number(line->stringargs[0]) : sfx_None, mo, callsec, line->args[2], line->args[0], line->args[1]); break; case 415: // Run a script diff --git a/src/p_spec.h b/src/p_spec.h index 07f566e2a..aeb557bf6 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -112,6 +112,21 @@ typedef enum TMP_BOTH = 2, } textmapplanes_t; +typedef enum +{ + TMSS_TRIGGERMOBJ = 0, + TMSS_TRIGGERSECTOR = 1, + TMSS_NOWHERE = 2, + TMSS_TAGGEDSECTOR = 3, +} textmapsoundsource_t; + +typedef enum +{ + TMSL_EVERYONE = 0, + TMSL_TRIGGERER = 1, + TMSL_TAGGEDSECTOR = 2, +} textmapsoundlistener_t; + typedef enum { TML_SECTOR = 0, From cabafeef1c5edb9a8ff863ae83fcff18bb0a611e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 10:35:01 +0200 Subject: [PATCH 138/326] Adapt linedef type 464 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 22 ++++++++++++++++++++ src/p_setup.c | 7 +++++++ src/p_spec.c | 4 ++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 10a2f768f..45e22b8d6 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -957,6 +957,11 @@ doom title = "Dye Object"; prefix = "(463)"; } + 464 + { + title = "Trigger Egg Capsule"; + prefix = "(464)"; + } 466 { title = "Set Level Failure State"; @@ -3060,6 +3065,23 @@ udmf } } + 464 + { + title = "Trigger Egg Capsule"; + prefix = "(464)"; + arg0 + { + title = "Egg Capsule tag"; + type = 14; + } + arg1 + { + title = "End level?"; + type = 11; + enum = "yesno"; + } + } + 466 { title = "Set Level Failure State"; diff --git a/src/p_setup.c b/src/p_setup.c index f834cd3fa..71575abaf 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4058,6 +4058,10 @@ static void P_ConvertBinaryMap(void) M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); } break; + case 464: //Trigger egg capsule + lines[i].args[0] = tag; + lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); + break; case 466: //Set level failure state lines[i].args[0] = !!(lines[i].flags & ML_NOCLIMB); break; @@ -4416,6 +4420,9 @@ static void P_ConvertBinaryMap(void) { switch (mapthings[i].type) { + case 291: + Tag_FSet(&mapthings[i].tags, mapthings[i].angle); + break; case 750: Tag_FSet(&mapthings[i].tags, mapthings[i].angle); break; diff --git a/src/p_spec.c b/src/p_spec.c index b828d97cd..256d6997e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3599,13 +3599,13 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!mo2->spawnpoint) continue; - if (mo2->spawnpoint->angle != tag) + if (!Tag_Find(&mo2->spawnpoint->tags, line->args[0])) continue; P_KillMobj(mo2, NULL, mo, 0); } - if (!(line->flags & ML_NOCLIMB)) + if (!(line->args[1])) { INT32 i; From d47069fbb6586eca742b49f984b116e87b4e5d09 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 11:30:34 +0200 Subject: [PATCH 139/326] Adapt linedef types 409 and 410 to UDMF --- extras/conf/SRB2-22.cfg | 4 ++ extras/conf/udb/Includes/SRB222_linedefs.cfg | 49 ++++++++++++++++++++ src/p_setup.c | 19 ++++++++ src/p_spec.c | 39 ++++++++++++++-- src/p_spec.h | 7 +++ src/taglist.c | 35 ++++++++++++++ src/taglist.h | 3 ++ 7 files changed, 153 insertions(+), 3 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 608fe508f..58f082201 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -2021,14 +2021,18 @@ linedeftypes { title = "Change Tagged Sector's Tag"; prefix = "(409)"; + flags2text = "[1] Remove tag"; flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Add tag"; } 410 { title = "Change Front Sector's Tag"; prefix = "(410)"; + flags2text = "[1] Remove tag"; flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Add tag"; } 416 diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 45e22b8d6..70c416f70 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2570,6 +2570,55 @@ udmf } } + 409 + { + title = "Change Tagged Sector's Tag"; + prefix = "(409)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Tag"; + type = 13; + } + arg2 + { + title = "Behavior"; + type = 11; + enum + { + 0 = "Add tag"; + 1 = "Remove tag"; + 2 = "Replace first tag"; + } + } + } + + 410 + { + title = "Change Front Sector's Tag"; + prefix = "(410)"; + arg0 + { + title = "Tag"; + type = 13; + } + arg1 + { + title = "Behavior"; + type = 11; + enum + { + 0 = "Add tag"; + 1 = "Remove tag"; + 2 = "Replace first tag"; + } + } + } + 416 { title = "Start Adjustable Flickering Light"; diff --git a/src/p_setup.c b/src/p_setup.c index 71575abaf..d64aff1bf 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3706,6 +3706,25 @@ static void P_ConvertBinaryMap(void) else lines[i].args[1] = TMP_BOTH; break; + case 409: //Change tagged sector's tag + lines[i].args[0] = tag; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] = TMT_ADD; + else if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[2] = TMT_REMOVE; + else + lines[i].args[2] = TMT_REPLACEFIRST; + break; + case 410: //Change front sector's tag + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[1] = TMT_ADD; + else if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[1] = TMT_REMOVE; + else + lines[i].args[1] = TMT_REPLACEFIRST; + break; case 411: //Stop plane movement lines[i].args[0] = tag; break; diff --git a/src/p_spec.c b/src/p_spec.c index 256d6997e..589b31145 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2293,14 +2293,47 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 409: // Change tagged sectors' tag // (formerly "Change calling sectors' tag", but behavior was changed) { - TAG_ITER_SECTORS(tag, secnum) - Tag_SectorFSet(secnum,(INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS)); + mtag_t newtag = line->args[1]; + + TAG_ITER_SECTORS(line->args[0], secnum) + { + switch (line->args[2]) + { + case TMT_ADD: + Tag_SectorAdd(secnum, newtag); + break; + case TMT_REMOVE: + Tag_SectorRemove(secnum, newtag); + break; + case TMT_REPLACEFIRST: + default: + Tag_SectorFSet(secnum, newtag); + break; + } + } break; } case 410: // Change front sector's tag - Tag_SectorFSet((UINT32)(line->frontsector - sectors), (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS)); + { + mtag_t newtag = line->args[1]; + secnum = (UINT32)(line->frontsector - sectors); + + switch (line->args[2]) + { + case TMT_ADD: + Tag_SectorAdd(secnum, newtag); + break; + case TMT_REMOVE: + Tag_SectorRemove(secnum, newtag); + break; + case TMT_REPLACEFIRST: + default: + Tag_SectorFSet(secnum, newtag); + break; + } break; + } case 411: // Stop floor/ceiling movement in tagged sector(s) TAG_ITER_SECTORS(line->args[0], secnum) diff --git a/src/p_spec.h b/src/p_spec.h index aeb557bf6..09a14d9a1 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -112,6 +112,13 @@ typedef enum TMP_BOTH = 2, } textmapplanes_t; +typedef enum +{ + TMT_ADD = 0, + TMT_REMOVE = 1, + TMT_REPLACEFIRST = 2, +} textmaptagoptions_t; + typedef enum { TMSS_TRIGGERMOBJ = 0, diff --git a/src/taglist.c b/src/taglist.c index ad1b9dc4b..f78f0c82b 100644 --- a/src/taglist.c +++ b/src/taglist.c @@ -37,6 +37,25 @@ void Tag_Add (taglist_t* list, const mtag_t tag) list->tags[list->count++] = tag; } +/// Removes a tag from a given element's taglist. +/// \warning This does not rebuild the global taggroups, which are used for iteration. +void Tag_Remove(taglist_t* list, const mtag_t tag) +{ + UINT16 i; + + for (i = 0; i < list->count; i++) + { + if (list->tags[i] != tag) + continue; + + for (; i+1 < list->count; i++) + list->tags[i] = list->tags[i+1]; + + list->tags = Z_Realloc(list->tags, (list->count - 1) * sizeof(mtag_t), PU_LEVEL, NULL); + return; + } +} + /// Sets the first tag entry in a taglist. /// Replicates the old way of accessing element->tag. void Tag_FSet (taglist_t* list, const mtag_t tag) @@ -376,6 +395,22 @@ INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start) // Ingame list manipulation. +/// Adds the tag to the given sector, and updates the global taggroups. +void Tag_SectorAdd (const size_t id, const mtag_t tag) +{ + sector_t* sec = §ors[id]; + Tag_Add(&sec->tags, tag); + Taggroup_Add(tags_sectors, tag, id); +} + +/// Removes the tag from the given sector, and updates the global taggroups. +void Tag_SectorRemove (const size_t id, const mtag_t tag) +{ + sector_t* sec = §ors[id]; + Tag_Remove(&sec->tags, tag); + Taggroup_Remove(tags_sectors, tag, id); +} + /// Changes the first tag for a given sector, and updates the global taggroups. void Tag_SectorFSet (const size_t id, const mtag_t tag) { diff --git a/src/taglist.h b/src/taglist.h index d045eb827..f15423d7a 100644 --- a/src/taglist.h +++ b/src/taglist.h @@ -28,12 +28,15 @@ typedef struct } taglist_t; void Tag_Add (taglist_t* list, const mtag_t tag); +void Tag_Remove (taglist_t* list, const mtag_t tag); void Tag_FSet (taglist_t* list, const mtag_t tag); mtag_t Tag_FGet (const taglist_t* list); boolean Tag_Find (const taglist_t* list, const mtag_t tag); boolean Tag_Share (const taglist_t* list1, const taglist_t* list2); boolean Tag_Compare (const taglist_t* list1, const taglist_t* list2); +void Tag_SectorAdd (const size_t id, const mtag_t tag); +void Tag_SectorRemove (const size_t id, const mtag_t tag); void Tag_SectorFSet (const size_t id, const mtag_t tag); /// Taggroup list. It is essentially just an element id list. From 2e120953ec2b06ffa376e009336228f1b106dd84 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 11:35:04 +0200 Subject: [PATCH 140/326] Fix typo in linedef type 400 conversion --- extras/conf/SRB2-22.cfg | 1 + src/p_setup.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 608fe508f..bcb823aa3 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -2000,6 +2000,7 @@ linedeftypes title = "Set Tagged Sector's Ceiling Height/Texture"; prefix = "(401)"; flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Keep floor flat"; } 402 diff --git a/src/p_setup.c b/src/p_setup.c index 27bfdc4c9..1e65a2dfd 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3622,7 +3622,7 @@ static void P_ConvertBinaryMap(void) case 401: //Set tagged sector's ceiling height/texture lines[i].args[0] = tag; lines[i].args[1] = lines[i].special - 400; - lines[i].args[2] = !!(lines[i].flags & ML_NOCLIMB); + lines[i].args[2] = !(lines[i].flags & ML_NOCLIMB); lines[i].special = 400; break; case 403: //Move tagged sector's floor From f1ad91ab34f750569b0d88099f8bc56e23c9d075 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 11:47:59 +0200 Subject: [PATCH 141/326] Add linedef type 467 to ZB config --- extras/conf/SRB2-22.cfg | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 608fe508f..dae5cc700 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -2004,7 +2004,7 @@ linedeftypes 402 { - title = "Set Tagged Sector's Light Level"; + title = "Copy Light Level to Tagged Sectors"; prefix = "(402)"; flags8text = "[3] Set delay by backside sector"; } @@ -2086,6 +2086,14 @@ linedeftypes prefix = "(435)"; flags8text = "[3] Set delay by backside sector"; } + + 467 + { + title = "Set Tagged Sector's Light Level"; + prefix = "(467)"; + flags8text = "[3] Set delay by backside sector"; + flags256text = "[8] Set relative to current"; + } } linedefexecplane From dbf6cd8b420170c6c557f7d00547e6834922c40e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 11:52:29 +0200 Subject: [PATCH 142/326] Add linedef type 76 to ZB config --- extras/conf/SRB2-22.cfg | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index f457fe972..b26dc6a28 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -771,6 +771,13 @@ linedeftypes flags2text = "[1] Use control sector tag"; flags64text = "[6] No sound effect"; } + + 76 + { + title = "Make FOF Bouncy"; + prefix = "(76)"; + flags16384text = "[14] Dampen"; + } } polyobject @@ -1273,7 +1280,7 @@ linedeftypes 160 { - title = "Floating, Bobbing"; + title = "Water Bobbing"; prefix = "(160)"; flags8text = "[3] Slope skew sides"; flags32text = "[5] Only block player"; From 19823fadbcf208a121a3d964e2bf825219c8f2e1 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 11:55:15 +0200 Subject: [PATCH 143/326] Mark bouncy FOF sector type as deprecated in ZB config --- extras/conf/SRB2-22.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index b26dc6a28..fd12b5c81 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -425,7 +425,7 @@ sectortypes 12 = "Space Countdown"; 13 = "Ramp Sector (double step-up/down)"; 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy FOF"; + 15 = "Bouncy FOF "; 16 = "Trigger Line Ex. (Pushable Objects)"; 32 = "Trigger Line Ex. (Anywhere, All Players)"; 48 = "Trigger Line Ex. (Floor Touch, All Players)"; @@ -475,7 +475,7 @@ gen_sectortypes 12 = "Space Countdown"; 13 = "Ramp Sector (double step-up/down)"; 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy FOF"; + 15 = "Bouncy FOF "; } second From 41d18bc591081690898b46dc44697e7aa67b8f80 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 12:55:22 +0200 Subject: [PATCH 144/326] Binary-to-UDMF conversion: Set up mapthing tags before global taglists are built --- src/p_setup.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index d64aff1bf..85e558b25 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3117,6 +3117,25 @@ static void P_AddBinaryMapTags(void) P_AddBinaryMapTagsFromLine(lines[i].backsector, &lines[i]); } } + + for (i = 0; i < nummapthings; i++) + { + switch (mapthings[i].type) + { + case 291: + case 750: + case 760: + case 761: + case 762: + Tag_FSet(&mapthings[i].tags, mapthings[i].angle); + break; + case 780: + Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo); + break; + default: + break; + } + } } //For maps in binary format, converts setup of specials to UDMF format. @@ -4439,23 +4458,11 @@ static void P_ConvertBinaryMap(void) { switch (mapthings[i].type) { - case 291: - Tag_FSet(&mapthings[i].tags, mapthings[i].angle); - break; - case 750: - Tag_FSet(&mapthings[i].tags, mapthings[i].angle); - break; - case 760: - case 761: - Tag_FSet(&mapthings[i].tags, mapthings[i].angle); - break; case 762: { INT32 check = -1; INT32 firstline = -1; - mtag_t tag = mapthings[i].angle; - - Tag_FSet(&mapthings[i].tags, tag); + mtag_t tag = Tag_FGet(&mapthings[i].tags); TAG_ITER_LINES(tag, check) { @@ -4472,9 +4479,6 @@ static void P_ConvertBinaryMap(void) mapthings[i].type = 761; break; } - case 780: - Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo); - break; default: break; } From 8b6140ddb232360dd48f90cd8f25a7d5fba6ee1c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 12:55:56 +0200 Subject: [PATCH 145/326] Linedef type 464: Use taglist search to find egg capsule center --- src/p_spec.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 589b31145..8a8997697 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3614,25 +3614,19 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 464: // Trigger Egg Capsule { - thinker_t *th; + INT32 mtnum; mobj_t *mo2; // Find the center of the Eggtrap and release all the pretty animals! // The chimps are my friends.. heeheeheheehehee..... - LouisJM - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + TAG_ITER_THINGS(line->args[0], mtnum) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + mo2 = mapthings[mtnum].mobj; + + if (!mo2) continue; - mo2 = (mobj_t *)th; - - if (mo2->type != MT_EGGTRAP) - continue; - - if (!mo2->spawnpoint) - continue; - - if (!Tag_Find(&mo2->spawnpoint->tags, line->args[0])) + if (mo2->thinker.function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; P_KillMobj(mo2, NULL, mo, 0); From be480eead042dacf5c814b9269cef19ec90d093c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 12:59:20 +0200 Subject: [PATCH 146/326] Linedef type 464: Re-add mobjtype check that I accidentally removed --- src/p_spec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 8a8997697..50b0a9125 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3626,6 +3626,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!mo2) continue; + if (mo2->type != MT_EGGTRAP) + continue; + if (mo2->thinker.function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; From d8b5cb6c909319230352c5204c0c9f2e008e2661 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 14:59:58 +0200 Subject: [PATCH 147/326] Adapt linedef type 422 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 15 ++++ src/p_setup.c | 5 ++ src/p_spec.c | 72 ++++++++++++-------- 3 files changed, 65 insertions(+), 27 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 70c416f70..ffda8082a 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -3202,6 +3202,21 @@ udmf } } + 422 + { + title = "Switch to Cut-Away View"; + prefix = "(422)"; + arg0 + { + title = "Viewpoint tag"; + type = 14; + } + arg1 + { + title = "Time"; + } + } + 423 { title = "Change Sky"; diff --git a/src/p_setup.c b/src/p_setup.c index 85e558b25..1e3581ce7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3870,6 +3870,11 @@ static void P_ConvertBinaryMap(void) case 421: //Stop lighting effect lines[i].args[0] = tag; break; + case 422: //Switch to cut-away view + lines[i].args[0] = tag; + lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].args[2] = (lines[i].flags & ML_NOCLIMB) ? sides[lines[i].sidenum[0]].textureoffset >> FRACBITS : 0; + break; case 423: //Change sky case 424: //Change weather lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index 50b0a9125..a00f2c094 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2187,6 +2187,39 @@ static mobj_t *P_GetObjectTypeInSectorNum(mobjtype_t type, size_t s) return NULL; } +static mobj_t* P_FindObjectTypeFromTag(mobjtype_t type, mtag_t tag) +{ + if (udmf) + { + INT32 mtnum; + mobj_t *mo; + + TAG_ITER_THINGS(tag, mtnum) + { + mo = mapthings[mtnum].mobj; + + if (!mo) + continue; + + if (mo->type != type) + continue; + + return mo; + } + + return NULL; + } + else + { + INT32 secnum; + + if ((secnum = Tag_Iterate_Sectors(tag, 0)) < 0) + return NULL; + + return P_GetObjectTypeInSectorNum(type, secnum); + } +} + /** Processes the line special triggered by an object. * * \param line Line with the special command on it. @@ -2550,15 +2583,13 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 422: // Cut away to another view { mobj_t *altview; + INT32 aim; if ((!mo || !mo->player) && !titlemapinaction) // only players have views, and title screens return; - if ((secnum = Tag_Iterate_Sectors(tag, 0)) < 0) - return; - - altview = P_GetObjectTypeInSectorNum(MT_ALTVIEWMAN, secnum); - if (!altview) + altview = P_FindObjectTypeFromTag(MT_ALTVIEWMAN, line->args[0]); + if (!altview || !altview->spawnpoint) return; // If titlemap, set the camera ref for title's thinker @@ -2568,31 +2599,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) else { P_SetTarget(&mo->player->awayviewmobj, altview); - mo->player->awayviewtics = P_AproxDistance(line->dx, line->dy)>>FRACBITS; + mo->player->awayviewtics = line->args[1]; } - - if (line->flags & ML_NOCLIMB) // lets you specify a vertical angle - { - INT32 aim; - - aim = sides[line->sidenum[0]].textureoffset>>FRACBITS; - aim = (aim + 360) % 360; - aim *= (ANGLE_90>>8); - aim /= 90; - aim <<= 8; - if (titlemapinaction) - titlemapcameraref->cusval = (angle_t)aim; - else - mo->player->awayviewaiming = (angle_t)aim; - } + aim = udmf ? altview->spawnpoint->pitch : line->args[2]; + aim = (aim + 360) % 360; + aim *= (ANGLE_90>>8); + aim /= 90; + aim <<= 8; + if (titlemapinaction) + titlemapcameraref->cusval = (angle_t)aim; else - { - // straight ahead - if (!titlemapinaction) - mo->player->awayviewaiming = 0; - // don't do cusval cause that's annoying - } + mo->player->awayviewaiming = (angle_t)aim; } break; From 132f3f21f1006de7855c3c75577266ec835369bd Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 15:10:50 +0200 Subject: [PATCH 148/326] Adapt linedef type 457 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 37 ++++++++++++++++++++ src/p_setup.c | 7 ++++ src/p_spec.c | 14 +++----- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index ffda8082a..cf81b56dd 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -3083,6 +3083,43 @@ udmf } } + 457 + { + title = "Track Object's Angle"; + prefix = "(457)"; + arg0 + { + title = "Anchor tag"; + type = 14; + } + arg1 + { + title = "Angle tolerance"; + type = 8; + } + arg2 + { + title = "Time tolerance"; + } + arg3 + { + title = "Trigger linedef tag"; + type = 15; + } + arg4 + { + title = "Track after failure?"; + type = 11; + enum = "noyes"; + } + } + + 458 + { + title = "Stop Tracking Object's Angle"; + prefix = "(458)"; + } + 460 { title = "Award Rings"; diff --git a/src/p_setup.c b/src/p_setup.c index 1e3581ce7..8e9d73e4b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4066,6 +4066,13 @@ static void P_ConvertBinaryMap(void) case 456: //Stop fading colormap lines[i].args[0] = Tag_FGet(&lines[i].tags); break; + case 457: //Track object's angle + lines[i].args[0] = tag; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[3] = (lines[i].sidenum[1] != 0xffff) ? sides[lines[i].sidenum[1]].rowoffset >> FRACBITS : 0; + lines[i].args[4] = !!(lines[i].flags & ML_EFFECT2); + break; case 459: //Control text prompt lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index a00f2c094..57f9237dc 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3488,17 +3488,13 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 457: // Track mobj angle to point if (mo) { - INT32 failureangle = FixedAngle((min(max(abs(sides[line->sidenum[0]].textureoffset>>FRACBITS), 0), 360))*FRACUNIT); - INT32 failuredelay = abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); - INT32 failureexectag = line->sidenum[1] != 0xffff ? - (INT32)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : 0; - boolean persist = (line->flags & ML_EFFECT2); + INT32 failureangle = FixedAngle((min(max(abs(line->args[1]), 0), 360))*FRACUNIT); + INT32 failuredelay = abs(line->args[2]); + INT32 failureexectag = line->args[3]; + boolean persist = !!(line->args[4]); mobj_t *anchormo; - if ((secnum = Tag_Iterate_Sectors(tag, 0)) < 0) - return; - - anchormo = P_GetObjectTypeInSectorNum(MT_ANGLEMAN, secnum); + anchormo = P_FindObjectTypeFromTag(MT_ANGLEMAN, line->args[0]); if (!anchormo) return; From 61e9adf30bb0f8142f7bab0b721ee2f955e62cf0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 15:31:53 +0200 Subject: [PATCH 149/326] Adapt linedef type 412 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 35 ++++++++++++++++++++ src/p_setup.c | 14 ++++++++ src/p_spec.c | 32 +++++++++--------- src/p_spec.h | 8 +++++ 4 files changed, 72 insertions(+), 17 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index cf81b56dd..a08c61463 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2944,6 +2944,41 @@ udmf { title = "Linedef Executor (player/object)"; + 412 + { + title = "Teleporter"; + prefix = "(412)"; + arg0 + { + title = "Destination tag"; + type = 14; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Silent"; + 2 = "Keep angle"; + 4 = "Keep momentum"; + 8 = "Relative silent"; + } + } + arg2 + { + title = "X offset"; + } + arg3 + { + title = "Y offset"; + } + arg4 + { + title = "Z offset"; + } + } + 425 { title = "Change Object State"; diff --git a/src/p_setup.c b/src/p_setup.c index 8e9d73e4b..879f2fb17 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3747,6 +3747,20 @@ static void P_ConvertBinaryMap(void) case 411: //Stop plane movement lines[i].args[0] = tag; break; + case 412: //Teleporter + lines[i].args[0] = tag; + if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[1] |= TMT_SILENT; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[1] |= TMT_KEEPANGLE; + if (lines[i].flags & ML_EFFECT4) + lines[i].args[1] |= TMT_KEEPMOMENTUM; + if (lines[i].flags & ML_EFFECT3) + lines[i].args[1] |= TMT_RELATIVE; + lines[i].args[2] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[3] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[4] = lines[i].frontsector->ceilingheight >> FRACBITS; + break; case 414: //Play sound effect lines[i].args[2] = tag; if (tag != 0) diff --git a/src/p_spec.c b/src/p_spec.c index 57f9237dc..bf6e05b7f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2238,7 +2238,6 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { INT32 secnum = -1; mobj_t *bot = NULL; - mtag_t tag = Tag_FGet(&line->tags); I_Assert(!mo || !P_MobjWasRemoved(mo)); // If mo is there, mo must be valid! @@ -2403,13 +2402,13 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!mo) // nothing to teleport return; - if (line->flags & ML_EFFECT3) // Relative silent teleport + if (line->args[1] & TMT_RELATIVE) // Relative silent teleport { fixed_t x, y, z; - x = sides[line->sidenum[0]].textureoffset; - y = sides[line->sidenum[0]].rowoffset; - z = line->frontsector->ceilingheight; + x = line->args[2] << FRACBITS; + y = line->args[3] << FRACBITS; + z = line->args[4] << FRACBITS; P_UnsetThingPosition(mo); mo->x += x; @@ -2439,23 +2438,22 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } else { - if ((secnum = Tag_Iterate_Sectors(tag, 0)) < 0) - return; + angle_t angle; + boolean silent, keepmomentum; - dest = P_GetObjectTypeInSectorNum(MT_TELEPORTMAN, secnum); + dest = P_FindObjectTypeFromTag(MT_TELEPORTMAN, line->args[0]); if (!dest) return; + angle = (line->args[1] & TMT_KEEPANGLE) ? mo->angle : dest->angle; + silent = !!(line->args[1] & TMT_SILENT); + keepmomentum = !!(line->args[1] & TMT_KEEPMOMENTUM); + if (bot) - P_Teleport(bot, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, (line->flags & ML_BLOCKMONSTERS) == 0, (line->flags & ML_EFFECT4) == ML_EFFECT4); - if (line->flags & ML_BLOCKMONSTERS) - P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, false, (line->flags & ML_EFFECT4) == ML_EFFECT4); - else - { - P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, true, (line->flags & ML_EFFECT4) == ML_EFFECT4); - // Play the 'bowrwoosh!' sound - S_StartSound(dest, sfx_mixup); - } + P_Teleport(bot, dest->x, dest->y, dest->z, angle, !silent, keepmomentum); + P_Teleport(mo, dest->x, dest->y, dest->z, angle, !silent, keepmomentum); + if (!silent) + S_StartSound(dest, sfx_mixup); // Play the 'bowrwoosh!' sound } } break; diff --git a/src/p_spec.h b/src/p_spec.h index 09a14d9a1..c5c1c6162 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -119,6 +119,14 @@ typedef enum TMT_REPLACEFIRST = 2, } textmaptagoptions_t; +typedef enum +{ + TMT_SILENT = 1, + TMT_KEEPANGLE = 1<<1, + TMT_KEEPMOMENTUM = 1<<2, + TMT_RELATIVE = 1<<3, +} textmapteleportflags_t; + typedef enum { TMSS_TRIGGERMOBJ = 0, From df7b22ac8ab37aa78dadb0ea13fde54c70a8603a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Sep 2021 15:34:47 +0200 Subject: [PATCH 150/326] Minor cleanup in P_ConvertBinaryMap --- 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 879f2fb17..155985a41 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4012,7 +4012,7 @@ static void P_ConvertBinaryMap(void) lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; break; case 447: //Change colormap - lines[i].args[0] = Tag_FGet(&lines[i].tags); + lines[i].args[0] = tag; if (lines[i].flags & ML_EFFECT3) lines[i].args[2] |= TMCF_RELATIVE; if (lines[i].flags & ML_EFFECT1) @@ -4058,7 +4058,7 @@ static void P_ConvertBinaryMap(void) abs(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS) : abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS)); - lines[i].args[0] = Tag_FGet(&lines[i].tags); + lines[i].args[0] = tag; if (lines[i].flags & ML_EFFECT4) lines[i].args[2] = speed; else @@ -4078,7 +4078,7 @@ static void P_ConvertBinaryMap(void) break; } case 456: //Stop fading colormap - lines[i].args[0] = Tag_FGet(&lines[i].tags); + lines[i].args[0] = tag; break; case 457: //Track object's angle lines[i].args[0] = tag; @@ -4345,7 +4345,7 @@ static void P_ConvertBinaryMap(void) lines[i].special = 600; break; case 606: //Colormap - lines[i].args[0] = Tag_FGet(&lines[i].tags); + lines[i].args[0] = tag; break; case 700: //Slope front sector floor case 701: //Slope front sector ceiling From 8ef8279764812a385fd1a4d18a69aa17f3ca71aa Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 22 Sep 2021 07:32:39 +0200 Subject: [PATCH 151/326] Adapt FOF-related linedef executors to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 164 +++++++++++++++++++ src/p_setup.c | 55 +++++++ src/p_spec.c | 109 ++++++------ src/p_spec.h | 26 +++ 4 files changed, 298 insertions(+), 56 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index a08c61463..9fbcc0a22 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -3332,6 +3332,22 @@ udmf } } + 436 + { + title = "Shatter FOF"; + prefix = "(436)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Control sector tag"; + type = 13; + } + } + 439 { title = "Change Tagged Linedef's Textures"; @@ -3396,6 +3412,60 @@ udmf } } + 445 + { + title = "Make FOF Disappear/Reappear"; + prefix = "(445)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Control sector tag"; + type = 13; + } + arg2 + { + title = "Effect"; + type = 11; + enum + { + 0 = "Disappear"; + 1 = "Reappear"; + } + } + } + + 446 + { + title = "Make FOF Crumble"; + prefix = "(446)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Control sector tag"; + type = 13; + } + arg2 + { + title = "Respawn?"; + type = 11; + enum + { + 0 = "Yes"; + 1 = "No"; + 2 = "Unless FF_NORETURN"; + 3 = "Only if FF_NORETURN"; + } + } + } + 447 { title = "Change Tagged Sector's Colormap"; @@ -3510,6 +3580,100 @@ udmf } } + 452 + { + title = "Set FOF Translucency"; + prefix = "(452)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Control sector tag"; + type = 13; + } + arg2 + { + title = "Alpha"; + } + arg3 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Add to current translucency"; + 2 = "Don't handle FF_TRANSLUCENT"; + } + } + } + + 453 + { + title = "Fade FOF"; + prefix = "(453)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Control sector tag"; + type = 13; + } + arg2 + { + title = "Alpha"; + } + arg3 + { + title = "Fading speed"; + } + arg4 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Add to current translucency"; + 2 = "Interrupt ongoing fades"; + 4 = "Speed is duration"; + 8 = "Don't change collision"; + 16 = "No collision during fade"; + 32 = "Don't handle FF_TRANSLUCENT"; + 64 = "Don't handle FF_EXISTS"; + 128 = "Don't fade lighting"; + 256 = "Don't fade colormap"; + 512 = "Use exact alpha in OpenGL"; + } + } + } + + 454 + { + title = "Stop Fading FOF"; + prefix = "(454)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Control sector tag"; + type = 13; + } + arg2 + { + title = "Finalize collision?"; + type = 11; + enum = "yesno"; + } + } + 455 { title = "Fade Tagged Sector's Colormap"; diff --git a/src/p_setup.c b/src/p_setup.c index 155985a41..0e393d267 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3963,6 +3963,10 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = tag; lines[i].args[1] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; break; + case 436: //Shatter FOF + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + break; case 437: //Disable player control lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); @@ -4011,6 +4015,19 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; break; + case 445: //Make FOF disappear/reappear + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[2] = !!(lines[i].flags & ML_NOCLIMB); + break; + case 446: //Make FOF crumble + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] |= TMFR_NORETURN; + if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[2] |= TMFR_CHECKFLAG; + break; case 447: //Change colormap lines[i].args[0] = tag; if (lines[i].flags & ML_EFFECT3) @@ -4052,6 +4069,44 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; break; + case 452: //Set FOF translucency + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[2] = lines[i].sidenum[1] != 0xffff ? (sides[lines[i].sidenum[1]].textureoffset >> FRACBITS) : (P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS); + if (lines[i].flags & ML_EFFECT3) + lines[i].args[3] |= TMST_RELATIVE; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[3] |= TMST_DONTDOTRANSLUCENT; + break; + case 453: //Fade FOF + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[2] = lines[i].sidenum[1] != 0xffff ? (sides[lines[i].sidenum[1]].textureoffset >> FRACBITS) : (lines[i].dx >> FRACBITS); + lines[i].args[3] = lines[i].sidenum[1] != 0xffff ? (sides[lines[i].sidenum[1]].rowoffset >> FRACBITS) : (abs(lines[i].dy) >> FRACBITS); + if (lines[i].flags & ML_EFFECT3) + lines[i].args[4] |= TMFT_RELATIVE; + if (lines[i].flags & ML_EFFECT5) + lines[i].args[4] |= TMFT_OVERRIDE; + if (lines[i].flags & ML_EFFECT4) + lines[i].args[4] |= TMFT_TICBASED; + if (lines[i].flags & ML_BOUNCY) + lines[i].args[4] |= TMFT_IGNORECOLLISION; + if (lines[i].flags & ML_EFFECT1) + lines[i].args[4] |= TMFT_GHOSTFADE; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[4] |= TMFT_DONTDOTRANSLUCENT; + if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[4] |= TMFT_DONTDOEXISTS; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[4] |= (TMFT_DONTDOLIGHTING|TMFT_DONTDOCOLORMAP); + if (lines[i].flags & ML_TFERLINE) + lines[i].args[4] |= TMFT_USEEXACTALPHA; + break; + case 454: //Stop fading FOF + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[2] = !!(lines[i].flags & ML_BLOCKMONSTERS); + break; case 455: //Fade colormap { INT32 speed = (INT32)((((lines[i].flags & ML_DONTPEGBOTTOM) || !sides[lines[i].sidenum[0]].rowoffset) && lines[i].sidenum[1] != 0xFFFF) ? diff --git a/src/p_spec.c b/src/p_spec.c index bf6e05b7f..812577ed5 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2765,8 +2765,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 436: // Shatter block remotely { - INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + INT16 sectag = (INT16)(line->args[0]); + INT16 foftag = (INT16)(line->args[1]); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to crumble boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -2950,10 +2950,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; } - case 445: // Force block disappear remotely (reappear if noclimb) + case 445: // Force block disappear remotely (reappear if args[2] is set) { - INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + INT16 sectag = (INT16)(line->args[0]); + INT16 foftag = (INT16)(line->args[1]); sector_t *sec; // Sector that the FOF is visible (or not visible) in ffloor_t *rover; // FOF to vanish/un-vanish boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -2978,7 +2978,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) oldflags = rover->flags; // Abracadabra! - if (line->flags & ML_NOCLIMB) + if (line->args[2]) rover->flags |= FF_EXISTS; else rover->flags &= ~FF_EXISTS; @@ -3003,8 +3003,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 446: // Make block fall remotely (acts like FF_CRUMBLE) { - INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + INT16 sectag = (INT16)(line->args[0]); + INT16 foftag = (INT16)(line->args[1]); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to make fall down boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -3014,7 +3014,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (mo) // NULL check player = mo->player; - if (line->flags & ML_NOCLIMB) // don't respawn! + if (line->args[2] & TMFR_NORETURN) // don't respawn! respawn = false; TAG_ITER_SECTORS(sectag, secnum) @@ -3033,8 +3033,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { foundrover = true; - if (line->flags & ML_BLOCKMONSTERS) // FOF flags determine respawn ability instead? - respawn = !(rover->flags & FF_NORETURN) ^ !!(line->flags & ML_NOCLIMB); // no climb inverts + if (line->args[2] & TMFR_CHECKFLAG) // FOF flags determine respawn ability instead? + respawn = !(rover->flags & FF_NORETURN) ^ !!(line->args[2] & TMFR_NORETURN); // TMFR_NORETURN inverts EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), player, rover->alpha, respawn); } @@ -3191,10 +3191,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 452: // Set FOF alpha { - INT16 destvalue = line->sidenum[1] != 0xffff ? - (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(P_AproxDistance(line->dx, line->dy)>>FRACBITS); - INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + INT16 destvalue = (INT16)(line->args[2]); + INT16 sectag = (INT16)(line->args[0]); + INT16 foftag = (INT16)(line->args[1]); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to operate boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -3218,7 +3217,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 // for relative alpha calc - if (!(line->flags & ML_NOCLIMB) && // do translucent + if (!(line->args[3] & TMST_DONTDOTRANSLUCENT) && // do translucent (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE !(rover->spawnflags & FF_RENDERSIDES) && !(rover->spawnflags & FF_RENDERPLANES) && @@ -3228,16 +3227,16 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, rover->alpha, - max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), - 0, // set alpha immediately - false, NULL, // tic-based logic - false, // do not handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // handle FF_TRANSLUCENT - false, // do not handle lighting - false, // do not handle colormap - false, // do not handle collision - false, // do not do ghost fade (no collision during fade) - true); // use exact alpha values (for opengl) + max(1, min(256, (line->args[3] & TMST_RELATIVE) ? rover->alpha + destvalue : destvalue)), + 0, // set alpha immediately + false, NULL, // tic-based logic + false, // do not handle FF_EXISTS + !(line->args[3] & TMST_DONTDOTRANSLUCENT), // handle FF_TRANSLUCENT + false, // do not handle lighting + false, // do not handle colormap + false, // do not handle collision + false, // do not do ghost fade (no collision during fade) + true); // use exact alpha values (for opengl) } } @@ -3252,12 +3251,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 453: // Fade FOF { - INT16 destvalue = line->sidenum[1] != 0xffff ? - (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(line->dx>>FRACBITS); - INT16 speed = line->sidenum[1] != 0xffff ? - (INT16)(abs(sides[line->sidenum[1]].rowoffset>>FRACBITS)) : (INT16)(abs(line->dy)>>FRACBITS); - INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + INT16 destvalue = (INT16)(line->args[2]); + INT16 speed = (INT16)(line->args[3]); + INT16 sectag = (INT16)(line->args[0]); + INT16 foftag = (INT16)(line->args[1]); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to operate boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -3280,7 +3277,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) foundrover = true; // Prevent continuous execs from interfering on an existing fade - if (!(line->flags & ML_EFFECT5) + if (!(line->args[4] & TMFT_OVERRIDE) && rover->fadingdata) //&& ((fade_t*)rover->fadingdata)->timer > (ticbased ? 2 : speed*2)) { @@ -3292,21 +3289,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_AddFakeFloorFader(rover, secnum, j, destvalue, speed, - (line->flags & ML_EFFECT4), // tic-based logic - (line->flags & ML_EFFECT3), // Relative destvalue - !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - !(line->flags & ML_EFFECT2), // do not handle lighting - !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) - !(line->flags & ML_BOUNCY), // do not handle collision - (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) - (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) + (line->args[4] & TMFT_TICBASED), // tic-based logic + (line->args[4] & TMFT_RELATIVE), // Relative destvalue + !(line->args[4] & TMFT_DONTDOEXISTS), // do not handle FF_EXISTS + !(line->args[4] & TMFT_DONTDOTRANSLUCENT), // do not handle FF_TRANSLUCENT + !(line->args[4] & TMFT_DONTDOLIGHTING), // do not handle lighting + !(line->args[4] & TMFT_DONTDOCOLORMAP), // do not handle colormap + !(line->args[4] & TMFT_IGNORECOLLISION), // do not handle collision + (line->args[4] & TMFT_GHOSTFADE), // do ghost fade (no collision during fade) + (line->args[4] & TMFT_USEEXACTALPHA)); // use exact alpha values (for opengl) else { // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 // for relative alpha calc - if (!(line->flags & ML_NOCLIMB) && // do translucent + if (!(line->args[4] & TMFT_DONTDOTRANSLUCENT) && // do translucent (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE !(rover->spawnflags & FF_RENDERSIDES) && !(rover->spawnflags & FF_RENDERPLANES) && @@ -3316,16 +3313,16 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, rover->alpha, - max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), - 0, // set alpha immediately - false, NULL, // tic-based logic - !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - !(line->flags & ML_EFFECT2), // do not handle lighting - !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) - !(line->flags & ML_BOUNCY), // do not handle collision - (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) - (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) + max(1, min(256, (line->args[4] & TMFT_RELATIVE) ? rover->alpha + destvalue : destvalue)), + 0, // set alpha immediately + false, NULL, // tic-based logic + !(line->args[4] & TMFT_DONTDOEXISTS), // do not handle FF_EXISTS + !(line->args[4] & TMFT_DONTDOTRANSLUCENT), // do not handle FF_TRANSLUCENT + !(line->args[4] & TMFT_DONTDOLIGHTING), // do not handle lighting + !(line->args[4] & TMFT_DONTDOCOLORMAP), // do not handle colormap + !(line->args[4] & TMFT_IGNORECOLLISION), // do not handle collision + (line->args[4] & TMFT_GHOSTFADE), // do ghost fade (no collision during fade) + (line->args[4] & TMFT_USEEXACTALPHA)); // use exact alpha values (for opengl) } } j++; @@ -3342,8 +3339,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 454: // Stop fading FOF { - INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + INT16 sectag = (INT16)(line->args[0]); + INT16 foftag = (INT16)(line->args[1]); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to operate boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -3365,7 +3362,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) foundrover = true; P_ResetFakeFloorFader(rover, NULL, - !(line->flags & ML_BLOCKMONSTERS)); // do not finalize collision flags + !(line->args[2])); // do not finalize collision flags } } diff --git a/src/p_spec.h b/src/p_spec.h index c5c1c6162..b8fbc3734 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -169,6 +169,32 @@ typedef enum TMB_SYNC = 1<<1, } textmapblinkinglightflags_t; +typedef enum +{ + TMFR_NORETURN = 1, + TMFR_CHECKFLAG = 1<<1, +} textmapfofrespawnflags_t; + +typedef enum +{ + TMST_RELATIVE = 1, + TMST_DONTDOTRANSLUCENT = 1<<1, +} textmapsettranslucencyflags_t; + +typedef enum +{ + TMFT_RELATIVE = 1, + TMFT_OVERRIDE = 1<<1, + TMFT_TICBASED = 1<<2, + TMFT_IGNORECOLLISION = 1<<3, + TMFT_GHOSTFADE = 1<<4, + TMFT_DONTDOTRANSLUCENT = 1<<5, + TMFT_DONTDOEXISTS = 1<<6, + TMFT_DONTDOLIGHTING = 1<<7, + TMFT_DONTDOCOLORMAP = 1<<8, + TMFT_USEEXACTALPHA = 1<<9, +} textmapfadetranslucencyflags_t; + typedef enum { TMS_VIEWPOINT = 0, From 03c1c592abc31e832e4b56a4b3384bc0d9b417a7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 22 Sep 2021 08:57:48 +0200 Subject: [PATCH 152/326] I surrender - we need more linedef args (also adapt the remaining linedef executors to UDMF) --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 96 ++++++++++++++++++++ extras/conf/udb/Includes/SRB222_misc.cfg | 10 ++ src/doomdata.h | 2 +- src/p_setup.c | 55 ++++++++++- src/p_spec.c | 71 +++++++-------- src/p_spec.h | 10 ++ src/r_defs.h | 2 +- 7 files changed, 206 insertions(+), 40 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 9fbcc0a22..88f40b8ac 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -3169,6 +3169,52 @@ udmf } } + 461 + { + title = "Spawn Object"; + prefix = "(461)"; + arg0 + { + title = "X position"; + } + arg1 + { + title = "Y position"; + } + arg2 + { + title = "Z position"; + } + arg3 + { + title = "Angle"; + type = 8; + } + arg4 + { + title = "Randomize position?"; + type = 11; + enum = "noyes"; + } + arg5 + { + title = "Max X position"; + } + arg6 + { + title = "Max Y position"; + } + arg7 + { + title = "Max Z position"; + } + stringarg0 + { + title = "Object type"; + type = 2; + } + } + 462 { title = "Stop Timer/Exit Stage in Record Attack"; @@ -3224,6 +3270,56 @@ udmf { title = "Linedef Executor (misc.)"; + 413 + { + title = "Change Music"; + prefix = "(413)"; + arg0 + { + title = "Flags"; + type = 12; + enum + { + 1 = "For all players"; + 2 = "Seek offset from current position"; + 4 = "Fade to custom volume"; + 8 = "Don't reload after death"; + 16 = "Force music reload"; + 32 = "Don't loop"; + } + } + arg1 + { + title = "Position"; + } + arg2 + { + title = "Fade out time"; + } + arg3 + { + title = "Fade in time"; + } + arg4 + { + title = "Fade destination volume"; + } + arg5 + { + title = "Fade start volume"; + default = -1; + } + arg6 + { + title = "Track number"; + } + stringarg0 + { + title = "Music name"; + type = 2; + } + } + 414 { title = "Play Sound Effect"; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 8e8b1d71a..1fd8f68b8 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -232,6 +232,16 @@ universalfields type = 0; default = 0; } + arg6 + { + type = 0; + default = 0; + } + arg7 + { + type = 0; + default = 0; + } stringarg0 { type = 2; diff --git a/src/doomdata.h b/src/doomdata.h index e317fec1b..7ba159a7c 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -196,7 +196,7 @@ typedef struct #pragma pack() #endif -#define NUMMAPTHINGARGS 6 +#define NUMMAPTHINGARGS 8 #define NUMMAPTHINGSTRINGARGS 2 // Thing definition, position, orientation and type, diff --git a/src/p_setup.c b/src/p_setup.c index 0e393d267..7b7396f74 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1305,7 +1305,6 @@ static void P_LoadSidedefs(UINT8 *data) case 334: // Trigger linedef executor: Object dye - Continuous case 335: // Trigger linedef executor: Object dye - Each time case 336: // Trigger linedef executor: Object dye - Once - case 461: // Spawns an object on the map based on texture offsets { char process[8*3+1]; memset(process,0,8*3+1); @@ -1330,6 +1329,7 @@ static void P_LoadSidedefs(UINT8 *data) case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors case 443: // Calls a named Lua function case 459: // Control text prompt (named tag) + case 461: // Spawns an object on the map based on texture offsets case 463: // Colorizes an object { char process[8*3+1]; @@ -3761,6 +3761,31 @@ static void P_ConvertBinaryMap(void) lines[i].args[3] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; lines[i].args[4] = lines[i].frontsector->ceilingheight >> FRACBITS; break; + case 413: //Change music + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[0] |= TMM_ALLPLAYERS; + if (lines[i].flags & ML_EFFECT1) + lines[i].args[0] |= TMM_OFFSET; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[0] |= TMM_FADE; + if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[0] |= TMM_NORELOAD; + if (lines[i].flags & ML_BOUNCY) + lines[i].args[0] |= TMM_FORCERESET; + if (lines[i].flags & ML_EFFECT4) + lines[i].args[0] |= TMM_NOLOOP; + lines[i].args[1] = sides[lines[i].sidenum[0]].midtexture; + lines[i].args[2] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[3] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[4] = (lines[i].sidenum[1] != 0xffff) ? sides[lines[i].sidenum[1]].textureoffset >> FRACBITS : 0; + lines[i].args[5] = (lines[i].sidenum[1] != 0xffff) ? sides[lines[i].sidenum[1]].rowoffset >> FRACBITS : -1; + lines[i].args[6] = sides[lines[i].sidenum[0]].bottomtexture; + if (sides[lines[i].sidenum[0]].text) + { + lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); + } + break; case 414: //Play sound effect lines[i].args[2] = tag; if (tag != 0) @@ -4170,6 +4195,34 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; break; + case 461: //Spawn object + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[2] = lines[i].frontsector->floorheight >> FRACBITS; + lines[i].args[3] = (lines[i].flags & ML_EFFECT1) ? AngleFixed(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)) >> FRACBITS : 0; + if (lines[i].flags & ML_NOCLIMB) + { + if (lines[i].sidenum[1] != 0xffff) // Make sure the linedef has a back side + { + lines[i].args[4] = 1; + lines[i].args[5] = sides[lines[i].sidenum[1]].textureoffset >> FRACBITS; + lines[i].args[6] = sides[lines[i].sidenum[1]].rowoffset >> FRACBITS; + lines[i].args[7] = lines[i].frontsector->ceilingheight >> FRACBITS; + } + else + { + CONS_Alert(CONS_WARNING, "Linedef Type %d - Spawn Object: Linedef is set for random range but has no back side.\n", lines[i].special); + lines[i].args[4] = 0; + } + } + else + lines[i].args[4] = 0; + if (sides[lines[i].sidenum[0]].text) + { + lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); + } + break; case 463: //Dye object if (sides[lines[i].sidenum[0]].text) { diff --git a/src/p_spec.c b/src/p_spec.c index 812577ed5..ef0703c50 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2459,19 +2459,19 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 413: // Change music - // console player only unless NOCLIMB is set - if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player)) || titlemapinaction) + // console player only unless TMM_ALLPLAYERS is set + if ((line->args[0] & TMM_ALLPLAYERS) || (mo && mo->player && P_IsLocalPlayer(mo->player)) || titlemapinaction) { - boolean musicsame = (!sides[line->sidenum[0]].text[0] || !strnicmp(sides[line->sidenum[0]].text, S_MusicName(), 7)); - UINT16 tracknum = (UINT16)max(sides[line->sidenum[0]].bottomtexture, 0); - INT32 position = (INT32)max(sides[line->sidenum[0]].midtexture, 0); - UINT32 prefadems = (UINT32)max(sides[line->sidenum[0]].textureoffset >> FRACBITS, 0); - UINT32 postfadems = (UINT32)max(sides[line->sidenum[0]].rowoffset >> FRACBITS, 0); - UINT8 fadetarget = (UINT8)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].textureoffset >> FRACBITS : 0, 0); - INT16 fadesource = (INT16)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].rowoffset >> FRACBITS : -1, -1); + boolean musicsame = (!line->stringargs[0] || !line->stringargs[0][0] || !strnicmp(line->stringargs[0], S_MusicName(), 7)); + UINT16 tracknum = (UINT16)max(line->args[6], 0); + INT32 position = (INT32)max(line->args[1], 0); + UINT32 prefadems = (UINT32)max(line->args[2], 0); + UINT32 postfadems = (UINT32)max(line->args[3], 0); + UINT8 fadetarget = (UINT8)max(line->args[4], 0); + INT16 fadesource = (INT16)max(line->args[5], -1); // Seek offset from current song position - if (line->flags & ML_EFFECT1) + if (line->args[0] & TMM_OFFSET) { // adjust for loop point if subtracting if (position < 0 && S_GetMusicLength() && @@ -2483,7 +2483,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } // Fade current music to target volume (if music won't be changed) - if ((line->flags & ML_EFFECT2) && fadetarget && musicsame) + if ((line->args[0] & TMM_FADE) && fadetarget && musicsame) { // 0 fadesource means fade from current volume. // meaning that we can't specify volume 0 as the source volume -- this starts at 1. @@ -2501,22 +2501,25 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // Change the music and apply position/fade operations else { - strncpy(mapmusname, sides[line->sidenum[0]].text, 7); + if (!line->stringargs[0]) + break; + + strncpy(mapmusname, line->stringargs[0], 7); mapmusname[6] = 0; mapmusflags = tracknum & MUSIC_TRACKMASK; - if (!(line->flags & ML_BLOCKMONSTERS)) + if (!(line->args[0] & TMM_NORELOAD)) mapmusflags |= MUSIC_RELOADRESET; - if (line->flags & ML_BOUNCY) + if (line->args[0] & TMM_FORCERESET) mapmusflags |= MUSIC_FORCERESET; mapmusposition = position; - S_ChangeMusicEx(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4), position, - !(line->flags & ML_EFFECT2) ? prefadems : 0, - !(line->flags & ML_EFFECT2) ? postfadems : 0); + S_ChangeMusicEx(mapmusname, mapmusflags, !(line->args[0] & TMM_NOLOOP), position, + !(line->args[0] & TMM_FADE) ? prefadems : 0, + !(line->args[0] & TMM_FADE) ? postfadems : 0); - if ((line->flags & ML_EFFECT2) && fadetarget) + if ((line->args[0] & TMM_FADE) && fadetarget) { if (!postfadems) S_SetInternalMusicVolume(fadetarget); @@ -2525,7 +2528,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } } - // Except, you can use the ML_BLOCKMONSTERS flag to change this behavior. + // Except, you can use the TMM_NORELOAD flag to change this behavior. // if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn. } break; @@ -3552,34 +3555,28 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 461: // Spawns an object on the map based on texture offsets { - const mobjtype_t type = (mobjtype_t)(sides[line->sidenum[0]].toptexture); + const mobjtype_t type = line->stringargs[0] ? get_number(line->stringargs[0]) : MT_NULL; mobj_t *mobj; fixed_t x, y, z; - x = sides[line->sidenum[0]].textureoffset; - y = sides[line->sidenum[0]].rowoffset; - z = line->frontsector->floorheight; - if (line->flags & ML_NOCLIMB) // If noclimb is set, spawn randomly within a range + if (line->args[4]) // If args[4] is set, spawn randomly within a range { - if (line->sidenum[1] != 0xffff) // Make sure the linedef has a back side - { - x = P_RandomRange(sides[line->sidenum[0]].textureoffset>>FRACBITS, sides[line->sidenum[1]].textureoffset>>FRACBITS)<sidenum[0]].rowoffset>>FRACBITS, sides[line->sidenum[1]].rowoffset>>FRACBITS)<frontsector->floorheight>>FRACBITS, line->frontsector->ceilingheight>>FRACBITS)<special); - break; - } + x = P_RandomRange(line->args[0], line->args[5])<args[1], line->args[6])<args[2], line->args[7])<args[0] << FRACBITS; + y = line->args[1] << FRACBITS; + z = line->args[2] << FRACBITS; } mobj = P_SpawnMobj(x, y, z, type); if (mobj) { - if (line->flags & ML_EFFECT1) - mobj->angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); + mobj->angle = FixedAngle(line->args[3] << FRACBITS); CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow. } else diff --git a/src/p_spec.h b/src/p_spec.h index b8fbc3734..74a2d438e 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -127,6 +127,16 @@ typedef enum TMT_RELATIVE = 1<<3, } textmapteleportflags_t; +typedef enum +{ + TMM_ALLPLAYERS = 1, + TMM_OFFSET = 1<<1, + TMM_FADE = 1<<2, + TMM_NORELOAD = 1<<3, + TMM_FORCERESET = 1<<4, + TMM_NOLOOP = 1<<5, +} textmapmusicflags_t; + typedef enum { TMSS_TRIGGERMOBJ = 0, diff --git a/src/r_defs.h b/src/r_defs.h index ab2b9fb2f..02937fd07 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -409,7 +409,7 @@ typedef enum #define HORIZONSPECIAL 41 -#define NUMLINEARGS 6 +#define NUMLINEARGS 8 #define NUMLINESTRINGARGS 2 typedef struct line_s From a61343bc8b9a39c45a7f3313e1115c1ffbe8e9ab Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 22 Sep 2021 10:38:08 +0200 Subject: [PATCH 153/326] P_LinedefExecute: Use global taglists to find trigger linedefs --- src/p_spec.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index ef0703c50..35e6f4b4c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1873,15 +1873,16 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller */ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) { - size_t masterline; + INT32 masterline; CONS_Debug(DBG_GAMELOGIC, "P_LinedefExecute: Executing trigger linedefs of tag %d\n", tag); I_Assert(!actor || !P_MobjWasRemoved(actor)); // If actor is there, it must be valid. - for (masterline = 0; masterline < numlines; masterline++) + TAG_ITER_LINES(tag, masterline) { - if (Tag_FGet(&lines[masterline].tags) != tag) + if (lines[masterline].special < 300 + || lines[masterline].special > 399) continue; // "No More Enemies" and "Level Load" take care of themselves. @@ -1897,10 +1898,6 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) || lines[masterline].special == 335)// Dye - Each time continue; - if (lines[masterline].special < 300 - || lines[masterline].special > 399) - continue; - if (!P_RunTriggerLinedef(&lines[masterline], actor, caller)) return; // cancel P_LinedefExecute if function returns false } From 280d23782c7c2e171b3eb2fdd7b2fef939a7b4b4 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 23 Sep 2021 10:21:53 +0200 Subject: [PATCH 154/326] Adapt linedef executor triggers that don't involve sector effects to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 260 +++++++++++++++++++ extras/conf/udb/Includes/SRB222_misc.cfg | 7 + src/p_setup.c | 73 ++++++ src/p_spec.c | 125 +++++---- src/p_spec.h | 47 ++++ 5 files changed, 456 insertions(+), 56 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 88f40b8ac..2f13b92e5 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2504,6 +2504,266 @@ udmf } } + linedeftrigger + { + title = "Linedef Executor Trigger"; + + 323 + { + title = "NiGHTSerize"; + prefix = "(323)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum + { + 0 = "Each time"; + 1 = "Once"; + } + } + arg1 + { + title = "Mare number"; + } + arg2 + { + title = "Lap number"; + } + arg3 + { + title = "Mare comparison"; + type = 11; + enum = "comparison"; + } + arg4 + { + title = "Lap comparison"; + type = 11; + enum = "comparison"; + } + arg5 + { + title = "Compared player"; + type = 11; + enum + { + 0 = "Fastest"; + 1 = "Slowest"; + 2 = "Triggerer"; + } + } + arg6 + { + title = "NiGHTS check"; + type = 11; + enum + { + 0 = "No check"; + 1 = "Trigger if player was not NiGHTS"; + 2 = "Trigger if player was already NiGHTS"; + } + } + arg7 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Only count bonus time laps"; + 2 = "Only trigger if final mare completed"; + } + } + } + 325 + { + title = "De-NiGHTSerize"; + prefix = "(325)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum + { + 0 = "Each time"; + 1 = "Once"; + } + } + arg1 + { + title = "Mare number"; + } + arg2 + { + title = "Lap number"; + } + arg3 + { + title = "Mare comparison"; + type = 11; + enum = "comparison"; + } + arg4 + { + title = "Lap comparison"; + type = 11; + enum = "comparison"; + } + arg5 + { + title = "Compared player"; + type = 11; + enum + { + 0 = "Fastest"; + 1 = "Slowest"; + 2 = "Triggerer"; + } + } + arg6 + { + title = "NiGHTS check"; + type = 11; + enum + { + 0 = "No check"; + 1 = "Trigger if nobody is now NiGHTS"; + 2 = "Trigger if somebody is still NiGHTS"; + } + } + arg7 + { + title = "Only bonus laps?"; + type = 11; + enum = "noyes"; + } + } + 327 + { + title = "NiGHTS Lap"; + prefix = "(327)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum + { + 0 = "Each time"; + 1 = "Once"; + } + } + arg1 + { + title = "Mare number"; + } + arg2 + { + title = "Lap number"; + } + arg3 + { + title = "Mare comparison"; + type = 11; + enum = "comparison"; + } + arg4 + { + title = "Lap comparison"; + type = 11; + enum = "comparison"; + } + arg5 + { + title = "Compared player"; + type = 11; + enum + { + 0 = "Fastest"; + 1 = "Slowest"; + 2 = "Triggerer"; + } + } + arg6 + { + title = "Only bonus laps?"; + type = 11; + enum = "noyes"; + } + } + 329 + { + title = "Ideya Capture Touch"; + prefix = "(329)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum + { + 0 = "Each time"; + 1 = "Once"; + } + } + arg1 + { + title = "Mare number"; + } + arg2 + { + title = "Lap number"; + } + arg3 + { + title = "Mare comparison"; + type = 11; + enum = "comparison"; + } + arg4 + { + title = "Lap comparison"; + type = 11; + enum = "comparison"; + } + arg5 + { + title = "Compared player"; + type = 11; + enum + { + 0 = "Fastest"; + 1 = "Slowest"; + 2 = "Triggerer"; + } + } + arg6 + { + title = "Spheres check"; + type = 11; + enum + { + 0 = "Trigger if enough spheres"; + 1 = "Trigger if not enough spheres"; + 2 = "Trigger regardless of spheres"; + } + } + arg7 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Only count bonus time laps"; + 2 = "Trigger upon entering Ideya Capture"; + } + } + } + 399 + { + title = "Level Load"; + prefix = "(399)"; + } + } + linedefexecsector { title = "Linedef Executor (sector)"; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 1fd8f68b8..ba1e9d16e 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -488,6 +488,13 @@ enums 1 = "Accelerative"; 2 = "Displacement"; } + + comparison + { + 0 = "Equal"; + 1 = "Less than or equal"; + 2 = "Greater than or equal"; + } } //Default things filters diff --git a/src/p_setup.c b/src/p_setup.c index 7b7396f74..0dbf15386 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3682,6 +3682,79 @@ static void P_ConvertBinaryMap(void) else lines[i].args[1] = 255; break; + case 323: //NiGHTSerize - Each time + case 324: //NiGHTSerize - Once + case 325: //DeNiGHTSerize - Each time + case 326: //DeNiGHTSerize - Once + case 327: //NiGHTS lap - Each time + case 328: //NiGHTS lap - Once + case 329: //Ideya capture touch - Each time + case 330: //Ideya capture touch - Once + lines[i].args[0] = (lines[i].special + 1) % 2; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[3] = TMC_LTE; + else if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[3] = TMC_GTE; + else + lines[i].args[3] = TMC_EQUAL; + if (lines[i].flags & ML_EFFECT1) + lines[i].args[4] = TMC_LTE; + else if (lines[i].flags & ML_EFFECT2) + lines[i].args[4] = TMC_GTE; + else + lines[i].args[4] = TMC_EQUAL; + if (lines[i].flags & ML_DONTPEGBOTTOM) + lines[i].args[5] = TMNP_SLOWEST; + else if (lines[i].flags & ML_EFFECT4) + lines[i].args[5] = TMNP_TRIGGERER; + else + lines[i].args[5] = TMNP_FASTEST; + if (lines[i].special % 2 == 0) + lines[i].special--; + if (lines[i].special == 323) + { + if (lines[i].flags & ML_TFERLINE) + lines[i].args[6] = TMN_FROMNONIGHTS; + else if (lines[i].flags & ML_DONTPEGTOP) + lines[i].args[6] = TMN_FROMNIGHTS; + else + lines[i].args[6] = TMN_ALWAYS; + + if (lines[i].flags & ML_EFFECT3) + lines[i].args[7] |= TMN_BONUSLAPS; + if (lines[i].flags & ML_BOUNCY) + lines[i].args[7] |= TMN_LEVELCOMPLETION; + } + else if (lines[i].special == 325) + { + if (lines[i].flags & ML_TFERLINE) + lines[i].args[6] = TMD_NOBODYNIGHTS; + else if (lines[i].flags & ML_DONTPEGTOP) + lines[i].args[6] = TMD_SOMEBODYNIGHTS; + else + lines[i].args[6] = TMD_ALWAYS; + + lines[i].args[7] = !!(lines[i].flags & ML_EFFECT3); + } + else if (lines[i].special == 327) + lines[i].args[6] = !!(lines[i].flags & ML_EFFECT3); + else + { + if (lines[i].flags & ML_DONTPEGTOP) + lines[i].args[6] = TMS_ALWAYS; + else if (lines[i].flags & ML_BOUNCY) + lines[i].args[6] = TMS_IFNOTENOUGH; + else + lines[i].args[6] = TMS_IFENOUGH; + + if (lines[i].flags & ML_EFFECT3) + lines[i].args[7] |= TMI_BONUSLAPS; + if (lines[i].flags & ML_TFERLINE) + lines[i].args[7] |= TMI_ENTER; + } + break; case 400: //Set tagged sector's floor height/texture case 401: //Set tagged sector's ceiling height/texture lines[i].args[0] = tag; diff --git a/src/p_spec.c b/src/p_spec.c index 35e6f4b4c..18318881d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1223,7 +1223,7 @@ void P_RunNightserizeExecutors(mobj_t *actor) for (i = 0; i < numlines; i++) { - if (lines[i].special == 323 || lines[i].special == 324) + if (lines[i].special == 323) P_RunTriggerLinedef(&lines[i], actor, NULL); } } @@ -1237,7 +1237,7 @@ void P_RunDeNightserizeExecutors(mobj_t *actor) for (i = 0; i < numlines; i++) { - if (lines[i].special == 325 || lines[i].special == 326) + if (lines[i].special == 325) P_RunTriggerLinedef(&lines[i], actor, NULL); } } @@ -1251,7 +1251,7 @@ void P_RunNightsLapExecutors(mobj_t *actor) for (i = 0; i < numlines; i++) { - if (lines[i].special == 327 || lines[i].special == 328) + if (lines[i].special == 327) P_RunTriggerLinedef(&lines[i], actor, NULL); } } @@ -1265,13 +1265,19 @@ void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean e for (i = 0; i < numlines; i++) { - if ((lines[i].special == 329 || lines[i].special == 330) - && ((entering && (lines[i].flags & ML_TFERLINE)) - || (!entering && !(lines[i].flags & ML_TFERLINE))) - && ((lines[i].flags & ML_DONTPEGTOP) - || (enoughspheres && !(lines[i].flags & ML_BOUNCY)) - || (!enoughspheres && (lines[i].flags & ML_BOUNCY)))) - P_RunTriggerLinedef(&lines[i], actor, NULL); + if (lines[i].special != 329) + continue; + + if (!!(lines[i].args[7] & TMI_ENTER) != entering) + continue; + + if (lines[i].args[6] == TMS_IFENOUGH && !enoughspheres) + continue; + + if (lines[i].args[6] == TMS_IFNOTENOUGH && enoughspheres) + continue; + + P_RunTriggerLinedef(&lines[i], actor, NULL); } } @@ -1351,27 +1357,42 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) INT16 specialtype = triggerline->special; size_t i; - UINT8 inputmare = max(0, min(255, sides[triggerline->sidenum[0]].textureoffset>>FRACBITS)); - UINT8 inputlap = max(0, min(255, sides[triggerline->sidenum[0]].rowoffset>>FRACBITS)); + UINT8 inputmare = max(0, min(255, triggerline->args[1])); + UINT8 inputlap = max(0, min(255, triggerline->args[2])); - boolean ltemare = triggerline->flags & ML_NOCLIMB; - boolean gtemare = triggerline->flags & ML_BLOCKMONSTERS; - boolean ltelap = triggerline->flags & ML_EFFECT1; - boolean gtelap = triggerline->flags & ML_EFFECT2; + textmapcomparison_t marecomp = triggerline->args[3]; + textmapcomparison_t lapcomp = triggerline->args[4]; + textmapnightsplayer_t checkplayer = triggerline->args[5]; - boolean lapfrombonustime = triggerline->flags & ML_EFFECT3; - boolean perglobalinverse = triggerline->flags & ML_DONTPEGBOTTOM; - boolean perglobal = !(triggerline->flags & ML_EFFECT4) && !perglobalinverse; + boolean lapfrombonustime; - boolean donomares = triggerline->flags & ML_BOUNCY; // nightserize: run at end of level (no mares) - boolean fromnonights = triggerline->flags & ML_TFERLINE; // nightserize: from non-nights // denightserize: all players no nights - boolean fromnights = triggerline->flags & ML_DONTPEGTOP; // nightserize: from nights // denightserize: >0 players are nights + boolean donomares = (specialtype == 323) && (triggerline->args[7] & TMN_LEVELCOMPLETION); // nightserize: run at end of level (no mares) UINT8 currentmare = UINT8_MAX; UINT8 currentlap = UINT8_MAX; + // Set lapfrombonustime + switch (specialtype) + { + case 323: + lapfrombonustime = !!(triggerline->args[7] & TMN_BONUSLAPS); + break; + case 325: + lapfrombonustime = !!(triggerline->args[7]); + break; + case 327: + lapfrombonustime = !!(triggerline->args[6]); + break; + case 329: + lapfrombonustime = !!(triggerline->args[7] & TMI_BONUSLAPS); + break; + default: + lapfrombonustime = false; + break; + } + // Do early returns for Nightserize - if (specialtype >= 323 && specialtype <= 324) + if (specialtype == 323) { // run only when no mares are found if (donomares && P_FindLowestMare() != UINT8_MAX) @@ -1382,7 +1403,7 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) return false; // run only if player is nightserizing from non-nights - if (fromnonights) + if (triggerline->args[6] == TMN_FROMNONIGHTS) { if (!actor->player) return false; @@ -1390,7 +1411,7 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) return false; } // run only if player is nightserizing from nights - else if (fromnights) + else if (triggerline->args[6] == TMN_FROMNIGHTS) { if (!actor->player) return false; @@ -1400,8 +1421,8 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) } // Get current mare and lap (and check early return for DeNightserize) - if (perglobal || perglobalinverse - || (specialtype >= 325 && specialtype <= 326 && (fromnonights || fromnights))) + if (checkplayer != TMNP_TRIGGERER + || (specialtype == 325 && triggerline->args[6] != TMD_ALWAYS)) { UINT8 playersarenights = 0; @@ -1412,19 +1433,19 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) continue; // denightserize: run only if all players are not nights - if (specialtype >= 325 && specialtype <= 326 && fromnonights + if (specialtype == 325 && triggerline->args[6] == TMD_NOBODYNIGHTS && players[i].powers[pw_carry] == CR_NIGHTSMODE) return false; // count number of nights players for denightserize return - if (specialtype >= 325 && specialtype <= 326 && fromnights + if (specialtype == 325 && triggerline->args[6] == TMD_SOMEBODYNIGHTS && players[i].powers[pw_carry] == CR_NIGHTSMODE) playersarenights++; lap = lapfrombonustime ? players[i].marebonuslap : players[i].marelap; // get highest mare/lap of players - if (perglobal) + if (checkplayer == TMNP_FASTEST) { if (players[i].mare > currentmare || currentmare == UINT8_MAX) { @@ -1436,7 +1457,7 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) currentlap = lap; } // get lowest mare/lap of players - else if (perglobalinverse) + else if (checkplayer == TMNP_SLOWEST) { if (players[i].mare < currentmare || currentmare == UINT8_MAX) { @@ -1450,12 +1471,12 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) } // denightserize: run only if >0 players are nights - if (specialtype >= 325 && specialtype <= 326 && fromnights + if (specialtype == 325 && triggerline->args[6] == TMD_SOMEBODYNIGHTS && playersarenights < 1) return false; } // get current mare/lap from triggering player - else if (!perglobal && !perglobalinverse) + else if (checkplayer == TMNP_TRIGGERER) { if (!actor->player) return false; @@ -1467,13 +1488,13 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) return false; // special case: player->marebonuslap is 0 until passing through on bonus time. Don't trigger lines looking for inputlap 0. // Compare current mare/lap to input mare/lap based on rules - if (!(specialtype >= 323 && specialtype <= 324 && donomares) // don't return false if donomares and we got this far - && ((ltemare && currentmare > inputmare) - || (gtemare && currentmare < inputmare) - || (!ltemare && !gtemare && currentmare != inputmare) - || (ltelap && currentlap > inputlap) - || (gtelap && currentlap < inputlap) - || (!ltelap && !gtelap && currentlap != inputlap)) + if (!donomares // don't return false if donomares and we got this far + && ((marecomp == TMC_LTE && currentmare > inputmare) + || (marecomp == TMC_GTE && currentmare < inputmare) + || (marecomp == TMC_EQUAL && currentmare != inputmare) + || (lapcomp == TMC_LTE && currentlap > inputlap) + || (lapcomp == TMC_GTE && currentlap < inputlap) + || (lapcomp == TMC_EQUAL && currentlap != inputlap)) ) return false; @@ -1690,14 +1711,10 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller return false; } break; - case 323: // nightserize - each time - case 324: // nightserize - once - case 325: // denightserize - each time - case 326: // denightserize - once - case 327: // nights lap - each time - case 328: // nights lap - once - case 329: // nights egg capsule touch - each time - case 330: // nights egg capsule touch - once + case 323: // nightserize + case 325: // denightserize + case 327: // nights lap + case 329: // nights egg capsule touch if (!P_CheckNightsTriggerLine(triggerline, actor)) return false; break; @@ -1846,10 +1863,10 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller || specialtype == 318 // Unlockable trigger - Once || specialtype == 320 // Unlockable - Once || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time - || specialtype == 324 // Nightserize - Once - || specialtype == 326 // DeNightserize - Once - || specialtype == 328 // Nights lap - Once - || specialtype == 330 // Nights Bonus Time - Once + || (specialtype == 323 && triggerline->args[0]) // Nightserize - Once + || (specialtype == 325 && triggerline->args[0]) // DeNightserize - Once + || (specialtype == 327 && triggerline->args[0]) // Nights lap - Once + || (specialtype == 329 && triggerline->args[0]) // Nights Bonus Time - Once || specialtype == 333 // Skin - Once || specialtype == 336 // Dye - Once || specialtype == 399) // Level Load @@ -6754,13 +6771,9 @@ void P_SpawnSpecials(boolean fromnetsave) // NiGHTS trigger executors case 323: - case 324: case 325: - case 326: case 327: - case 328: case 329: - case 330: break; // Skin trigger executors diff --git a/src/p_spec.h b/src/p_spec.h index 74a2d438e..0fdc216b9 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -105,6 +105,53 @@ typedef enum TMFL_SPLAT = 1<<1, } textmapfoflaserflags_t; +typedef enum +{ + TMC_EQUAL = 0, + TMC_LTE = 1, + TMC_GTE = 2, +} textmapcomparison_t; + +typedef enum +{ + TMNP_FASTEST = 0, + TMNP_SLOWEST = 1, + TMNP_TRIGGERER = 2, +} textmapnightsplayer_t; + +typedef enum +{ + TMN_ALWAYS = 0, + TMN_FROMNONIGHTS = 1, + TMN_FROMNIGHTS = 2, +} textmapnighterizeoptions_t; + +typedef enum +{ + TMN_BONUSLAPS = 1, + TMN_LEVELCOMPLETION = 1<<2, +} textmapnightserizeflags_t; + +typedef enum +{ + TMD_ALWAYS = 0, + TMD_NOBODYNIGHTS = 1, + TMD_SOMEBODYNIGHTS = 2, +} textmapdenighterizeoptions_t; + +typedef enum +{ + TMS_IFENOUGH = 0, + TMS_IFNOTENOUGH = 1, + TMS_ALWAYS = 2, +} textmapspherescheck_t; + +typedef enum +{ + TMI_BONUSLAPS = 1, + TMI_ENTER = 1<<2, +} textmapideyacaptureflags_t; + typedef enum { TMP_FLOOR = 0, From 5df1dd324d34156dbdf9f2d05933e51030ee46ab Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 23 Sep 2021 10:24:02 +0200 Subject: [PATCH 155/326] Fix oversight in T_MoveFloor --- src/p_floor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_floor.c b/src/p_floor.c index eebb9366e..2da410de5 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -231,6 +231,7 @@ void T_MoveFloor(floormove_t *movefloor) remove = true; break; default: + remove = true; break; } } From f26f41e03ac9b2d8ee033d627cc9218bdf5a3141 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 26 Sep 2021 06:48:26 +0200 Subject: [PATCH 156/326] Fix thinker functions that still use tag instead of args[0] for FOFs --- src/p_floor.c | 13 +++++-------- src/p_spec.c | 10 +++++----- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index 102ac67e0..6641c6904 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -634,7 +634,6 @@ void T_BounceCheese(bouncecheese_t *bouncer) sector_t *actionsector; boolean remove; INT32 i; - mtag_t tag = Tag_FGet(&bouncer->sourceline->tags); if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT || bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself! @@ -649,7 +648,7 @@ void T_BounceCheese(bouncecheese_t *bouncer) } // You can use multiple target sectors, but at your own risk!!! - TAG_ITER_SECTORS(tag, i) + TAG_ITER_SECTORS(bouncer->sourceline->args[0], i) { actionsector = §ors[i]; actionsector->moved = true; @@ -773,7 +772,7 @@ void T_StartCrumble(crumble_t *crumble) ffloor_t *rover; sector_t *sector; INT32 i; - mtag_t tag = Tag_FGet(&crumble->sourceline->tags); + mtag_t tag = crumble->sourceline->args[0]; // Once done, the no-return thinker just sits there, // constantly 'returning'... kind of an oxymoron, isn't it? @@ -1301,14 +1300,13 @@ void T_NoEnemiesSector(noenemies_t *nobaddies) for (i = 0; i < sec->linecount; i++) { INT32 targetsecnum = -1; - mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags); if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) continue; FOFsector = true; - TAG_ITER_SECTORS(tag2, targetsecnum) + TAG_ITER_SECTORS(sec->lines[i]->args[0], targetsecnum) { if (T_SectorHasEnemies(§ors[targetsecnum])) return; @@ -1421,14 +1419,13 @@ void T_EachTimeThinker(eachtime_t *eachtime) for (i = 0; i < sec->linecount; i++) { INT32 targetsecnum = -1; - mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags); if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) continue; FOFsector = true; - TAG_ITER_SECTORS(tag2, targetsecnum) + TAG_ITER_SECTORS(sec->lines[i]->args[0], targetsecnum) { targetsec = §ors[targetsecnum]; @@ -2418,7 +2415,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) block->direction = 1; block->floorstartheight = block->sector->floorheight; block->ceilingstartheight = block->sector->ceilingheight; - block->tag = (INT16)Tag_FGet(§or->tags); + block->tag = (INT16)rover->master->args[0]; if (itsamonitor) { diff --git a/src/p_spec.c b/src/p_spec.c index ae144307e..f1c3e10ad 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5660,7 +5660,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I if ((flags & FF_FLOATBOB)) { - P_AddFloatThinker(sec2, Tag_FGet(&master->tags), master); + P_AddFloatThinker(sec2, master->args[0], master); CheckForFloatBob = true; } @@ -5840,7 +5840,7 @@ static inline void P_AddThwompThinker(sector_t *sec, line_t *sourceline, fixed_t thwomp->floorstartheight = sec->floorheight; thwomp->ceilingstartheight = sec->ceilingheight; thwomp->delay = 1; - thwomp->tag = Tag_FGet(&sourceline->tags); + thwomp->tag = sourceline->args[0]; thwomp->sound = sound; sec->floordata = thwomp; @@ -7477,7 +7477,7 @@ void T_Scroll(scroll_t *s) if (!is3dblock) continue; - TAG_ITER_SECTORS(Tag_FGet(&line->tags), sect) + TAG_ITER_SECTORS(line->args[0], sect) { sector_t *psec; psec = sectors + sect; @@ -7552,7 +7552,7 @@ void T_Scroll(scroll_t *s) if (!is3dblock) continue; - TAG_ITER_SECTORS(Tag_FGet(&line->tags), sect) + TAG_ITER_SECTORS(line->args[0], sect) { sector_t *psec; psec = sectors + sect; @@ -7828,7 +7828,7 @@ void T_Disappear(disappear_t *d) { ffloor_t *rover; register INT32 s; - mtag_t afftag = Tag_FGet(&lines[d->affectee].tags); + mtag_t afftag = lines[d->affectee].args[0]; TAG_ITER_SECTORS(afftag, s) { From 5f7babb53fbbb40c837fd3be7687c7d8eed39b78 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 26 Sep 2021 20:42:01 +0200 Subject: [PATCH 157/326] Adapt linedef type 313 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 11 +++++++++++ src/p_floor.c | 2 +- src/p_setup.c | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 2f13b92e5..674d20443 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2508,6 +2508,17 @@ udmf { title = "Linedef Executor Trigger"; + 313 + { + title = "No More Enemies - Once"; + prefix = "(313)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + } + 323 { title = "NiGHTSerize"; diff --git a/src/p_floor.c b/src/p_floor.c index f421b550f..6a4ef554e 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1235,7 +1235,7 @@ void T_NoEnemiesSector(noenemies_t *nobaddies) sector_t *sec = NULL; INT32 secnum = -1; boolean FOFsector = false; - mtag_t tag = Tag_FGet(&nobaddies->sourceline->tags); + mtag_t tag = nobaddies->sourceline->args[0]; TAG_ITER_SECTORS(tag, secnum) { diff --git a/src/p_setup.c b/src/p_setup.c index 2ad6dcb06..ce0e27e38 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3715,6 +3715,9 @@ static void P_ConvertBinaryMap(void) else lines[i].args[1] = 255; break; + case 313: //No more enemies - once + lines[i].args[0] = tag; + break; case 323: //NiGHTSerize - Each time case 324: //NiGHTSerize - Once case 325: //DeNiGHTSerize - Each time From d44ef91f6f86ff504b58799c9147b64199011da3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 28 Nov 2021 19:34:42 +0100 Subject: [PATCH 158/326] Re-add FF_BUSTUP to INT_CONST --- src/deh_tables.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/deh_tables.c b/src/deh_tables.c index f2fd38059..f14eca6a9 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5226,6 +5226,7 @@ struct int_const_s const INT_CONST[] = { {"FF_CRUMBLE",FF_CRUMBLE}, ///< Falls 2 seconds after being stepped on, and randomly brings all touching crumbling 3dfloors down with it, providing their master sectors share the same tag (allows crumble platforms above or below, to also exist). {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. {"FF_MARIO",FF_MARIO}, ///< Acts like a question block when hit from underneath. Goodie spawned at top is determined by master sector. + {"FF_BUSTUP",FF_BUSTUP}, ///< You can spin through/punch this block and it will crumble! {"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand! {"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top. {"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity. From 6dc49042deb1f27217fd1d5107726732c2fd9bf8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 3 Dec 2021 18:48:16 +0100 Subject: [PATCH 159/326] Port katsy's bouncy FOF cleanup --- extras/conf/SRB2-22.cfg | 1 - extras/conf/udb/Includes/SRB222_linedefs.cfg | 6 --- src/deh_tables.c | 10 ++-- src/lua_maplib.c | 8 +-- src/p_mobj.c | 6 +-- src/p_setup.c | 2 - src/p_spec.c | 33 +++++------- src/p_user.c | 54 ++++---------------- src/r_defs.h | 14 ++--- 9 files changed, 39 insertions(+), 95 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index fd12b5c81..3f345da4f 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -776,7 +776,6 @@ linedeftypes { title = "Make FOF Bouncy"; prefix = "(76)"; - flags16384text = "[14] Dampen"; } } diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index d4f24e4ab..068fc2c8c 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1733,12 +1733,6 @@ udmf { title = "Bounce strength"; } - arg2 - { - title = "Dampen?"; - type = 11; - enum = "noyes"; - } } } diff --git a/src/deh_tables.c b/src/deh_tables.c index ff2639a74..438ff2090 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5230,12 +5230,10 @@ struct int_const_s const INT_CONST[] = { {"FF_BOUNCY",FF_BOUNCY}, ///< Bounces players {"FF_SPLAT",FF_SPLAT}, ///< Use splat flat renderer (treat cyan pixels as invisible) - // FOF special flags - {"FS_PUSHABLES",FS_PUSHABLES}, - {"FS_EXECUTOR",FS_EXECUTOR}, - {"FS_ONLYBOTTOM",FS_ONLYBOTTOM}, - {"FS_BUSTMASK",FS_BUSTMASK}, - {"FS_DAMPEN",FS_DAMPEN}, + // FOF bustable flags + {"FB_PUSHABLES",FB_PUSHABLES}, + {"FB_EXECUTOR",FB_EXECUTOR}, + {"FB_ONLYBOTTOM",FB_ONLYBOTTOM}, // Bustable FOF type {"BT_TOUCH",BT_TOUCH}, diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 534ef9a07..b54924cdf 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -196,7 +196,7 @@ enum ffloor_e { ffloor_next, ffloor_prev, ffloor_alpha, - ffloor_specialflags, + ffloor_bustflags, ffloor_busttype, ffloor_busttag, ffloor_sinkspeed, @@ -220,7 +220,7 @@ static const char *const ffloor_opt[] = { "next", "prev", "alpha", - "specialflags", + "bustflags", "busttype", "busttag", "sinkspeed", @@ -1819,8 +1819,8 @@ static int ffloor_get(lua_State *L) case ffloor_alpha: lua_pushinteger(L, ffloor->alpha); return 1; - case ffloor_specialflags: - lua_pushinteger(L, ffloor->specialflags); + case ffloor_bustflags: + lua_pushinteger(L, ffloor->bustflags); return 1; case ffloor_busttype: lua_pushinteger(L, ffloor->busttype); diff --git a/src/p_mobj.c b/src/p_mobj.c index 86c237f4a..268881811 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1688,7 +1688,7 @@ static void P_PushableCheckBustables(mobj_t *mo) if (!(rover->flags & FF_BUSTUP)) continue; - if (!(rover->specialflags & FS_PUSHABLES)) + if (!(rover->bustflags & FB_PUSHABLES)) continue; if (rover->master->frontsector->crumblestate != CRUMBLE_NONE) @@ -1698,7 +1698,7 @@ static void P_PushableCheckBustables(mobj_t *mo) bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); // Height checks - if (rover->specialflags & FS_ONLYBOTTOM) + if (rover->bustflags & FB_ONLYBOTTOM) { if (mo->z + mo->momz + mo->height < bottomheight) continue; @@ -1740,7 +1740,7 @@ static void P_PushableCheckBustables(mobj_t *mo) EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? - if (rover->specialflags & FS_EXECUTOR) + if (rover->bustflags & FB_EXECUTOR) P_LinedefExecute(rover->busttag, mo, node->m_sector); goto bustupdone; diff --git a/src/p_setup.c b/src/p_setup.c index 17d71a8bf..83a5fe26c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3084,8 +3084,6 @@ static void P_ConvertBinaryMap(void) case 76: //Make FOF bouncy lines[i].args[0] = tag; lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; - if (lines[i].flags & ML_BOUNCY) - lines[i].args[2] = 1; break; case 100: //FOF: solid, opaque, shadowcasting case 101: //FOF: solid, opaque, non-shadowcasting diff --git a/src/p_spec.c b/src/p_spec.c index f1c3e10ad..508c340b0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6089,10 +6089,6 @@ static void P_MakeFOFBouncy(line_t *paramline, line_t *masterline) rover->flags |= FF_BOUNCY; rover->spawnflags |= FF_BOUNCY; rover->bouncestrength = (paramline->args[1]<< FRACBITS)/100; - if (paramline->args[2]) - rover->specialflags |= FS_DAMPEN; - else - rover->specialflags &= ~FS_DAMPEN; CheckForBouncySector = true; break; } @@ -6739,7 +6735,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 254: // Bustable block { UINT8 busttype = BT_REGULAR; - ffloorspecialflags_e bustflags = 0; + ffloorbustflags_e bustflags = 0; ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP; @@ -6762,15 +6758,15 @@ void P_SpawnSpecials(boolean fromnetsave) //Flags if (lines[i].args[3] & TMFB_PUSHABLES) - bustflags |= FS_PUSHABLES; + bustflags |= FB_PUSHABLES; if (lines[i].args[3] & TMFB_EXECUTOR) - bustflags |= FS_EXECUTOR; + bustflags |= FB_EXECUTOR; if (lines[i].args[3] & TMFB_ONLYBOTTOM) - bustflags |= FS_ONLYBOTTOM; + bustflags |= FB_ONLYBOTTOM; if (lines[i].args[3] & TMFB_SPLAT) ffloorflags |= FF_SPLAT; - if (busttype != BT_TOUCH || bustflags & FS_ONLYBOTTOM) + if (busttype != BT_TOUCH || bustflags & FB_ONLYBOTTOM) ffloorflags |= FF_BLOCKPLAYER; TAG_ITER_SECTORS(lines[i].args[0], s) @@ -6778,8 +6774,8 @@ void P_SpawnSpecials(boolean fromnetsave) ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers); if (!fflr) continue; + fflr->bustflags = bustflags; fflr->busttype = busttype; - fflr->specialflags = bustflags; fflr->busttag = lines[i].args[4]; } break; @@ -6839,12 +6835,12 @@ void P_SpawnSpecials(boolean fromnetsave) } if (lines[i].args[3] & TMFB_ONLYBOTTOM) - fflr->specialflags |= FS_ONLYBOTTOM; + fflr->bustflags |= FB_ONLYBOTTOM; if (lines[i].flags & ML_EFFECT4) - fflr->specialflags |= FS_PUSHABLES; + fflr->bustflags |= FB_PUSHABLES; if (lines[i].flags & ML_EFFECT5) { - fflr->specialflags |= FS_EXECUTOR; + fflr->bustflags |= FB_EXECUTOR; fflr->busttag = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; } } @@ -7176,7 +7172,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 74: // Make FOF bustable { UINT8 busttype = BT_REGULAR; - ffloorspecialflags_e bustflags = 0; + ffloorbustflags_e bustflags = 0; if (!udmf) break; @@ -7198,11 +7194,11 @@ void P_SpawnSpecials(boolean fromnetsave) } if (lines[i].args[2] & TMFB_PUSHABLES) - bustflags |= FS_PUSHABLES; + bustflags |= FB_PUSHABLES; if (lines[i].args[2] & TMFB_EXECUTOR) - bustflags |= FS_EXECUTOR; + bustflags |= FB_EXECUTOR; if (lines[i].args[2] & TMFB_ONLYBOTTOM) - bustflags |= FS_ONLYBOTTOM; + bustflags |= FB_ONLYBOTTOM; TAG_ITER_LINES(lines[i].args[0], l) { @@ -7220,9 +7216,8 @@ void P_SpawnSpecials(boolean fromnetsave) rover->flags |= FF_BUSTUP; rover->spawnflags |= FF_BUSTUP; + rover->bustflags = bustflags; rover->busttype = busttype; - rover->specialflags &= ~FS_BUSTMASK; - rover->specialflags |= bustflags; rover->busttag = lines[i].args[3]; CheckForBustableBlocks = true; break; diff --git a/src/p_user.c b/src/p_user.c index 048f2f1f9..6466a5316 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2656,7 +2656,7 @@ static void P_CheckBustableBlocks(player_t *player) } // Height checks - if (rover->specialflags & FS_ONLYBOTTOM) + if (rover->bustflags & FB_ONLYBOTTOM) { if (player->mo->z + player->mo->momz + player->mo->height < bottomheight) continue; @@ -2710,7 +2710,7 @@ static void P_CheckBustableBlocks(player_t *player) EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? - if (rover->specialflags & FS_EXECUTOR) + if (rover->bustflags & FB_EXECUTOR) P_LinedefExecute(rover->busttag, player->mo, node->m_sector); goto bustupdone; @@ -2766,10 +2766,6 @@ static void P_CheckBouncySectors(player_t *player) { rover->flags |= FF_BOUNCY; rover->bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100; - if (rover->master->flags & ML_BOUNCY) - rover->specialflags |= FS_DAMPEN; - else - rover->specialflags &= ~FS_DAMPEN; } if (!(rover->flags & FF_BOUNCY)) @@ -2789,17 +2785,9 @@ static void P_CheckBouncySectors(player_t *player) { player->mo->momx = -FixedMul(player->mo->momx,rover->bouncestrength); player->mo->momy = -FixedMul(player->mo->momy,rover->bouncestrength); - - if (player->pflags & PF_SPINNING) - { - player->pflags &= ~PF_SPINNING; - player->pflags |= P_GetJumpFlags(player); - player->pflags |= PF_THOKKED; - } } else { - fixed_t newmom; pslope_t *slope = (abs(oldz - topheight) < abs(oldz + player->mo->height - bottomheight)) ? *rover->t_slope : *rover->b_slope; momentum.x = player->mo->momx; @@ -2809,53 +2797,29 @@ static void P_CheckBouncySectors(player_t *player) if (slope) P_ReverseQuantizeMomentumToSlope(&momentum, slope); - newmom = momentum.z = -FixedMul(momentum.z,rover->bouncestrength)/2; + momentum.z = -FixedMul(momentum.z,rover->bouncestrength)/2; - if (abs(newmom) < (rover->bouncestrength*2)) + if (abs(momentum.z) < (rover->bouncestrength*2)) goto bouncydone; - if (!(rover->specialflags & FS_DAMPEN)) - { - if (newmom > 0) - { - if (newmom < 8*FRACUNIT) - newmom = 8*FRACUNIT; - } - else if (newmom < 0) - { - if (newmom > -8*FRACUNIT) - newmom = -8*FRACUNIT; - } - } - - if (newmom > P_GetPlayerHeight(player)/2) - newmom = P_GetPlayerHeight(player)/2; - else if (newmom < -P_GetPlayerHeight(player)/2) - newmom = -P_GetPlayerHeight(player)/2; - - momentum.z = newmom*2; + if (momentum.z > FixedMul(24*FRACUNIT, player->mo->scale)) //half of the default player height + momentum.z = FixedMul(24*FRACUNIT, player->mo->scale); + else if (momentum.z < -FixedMul(24*FRACUNIT, player->mo->scale)) + momentum.z = -FixedMul(24*FRACUNIT, player->mo->scale); if (slope) P_QuantizeMomentumToSlope(&momentum, slope); player->mo->momx = momentum.x; player->mo->momy = momentum.y; - player->mo->momz = momentum.z/2; + player->mo->momz = momentum.z; if (player->pflags & PF_SPINNING) { - player->pflags &= ~PF_SPINNING; - player->pflags |= P_GetJumpFlags(player); player->pflags |= PF_THOKKED; } } - if ((player->pflags & PF_SPINNING) && player->speed < FixedMul(1<mo->scale) && player->mo->momz) - { - player->pflags &= ~PF_SPINNING; - player->pflags |= P_GetJumpFlags(player); - } - goto bouncydone; } } diff --git a/src/r_defs.h b/src/r_defs.h index cb21d5043..4cc7d2e96 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -154,12 +154,10 @@ typedef enum typedef enum { - FS_PUSHABLES = 0x1, // FF_BUSTABLE: Bustable by pushables - FS_EXECUTOR = 0x2, // FF_BUSTABLE: Trigger linedef executor - FS_ONLYBOTTOM = 0x4, // FF_BUSTABLE: Only bustable from below - FS_BUSTMASK = 0x7, - FS_DAMPEN = 0x8, // FF_BOUNCY: Dampen bounce -} ffloorspecialflags_e; + FB_PUSHABLES = 0x1, // Bustable by pushables + FB_EXECUTOR = 0x2, // Trigger linedef executor + FB_ONLYBOTTOM = 0x4, // Only bustable from below +} ffloorbustflags_e; typedef enum { @@ -201,10 +199,8 @@ typedef struct ffloor_s INT32 alpha; tic_t norender; // for culling - // Flags that are only relevant for special ffloor types - ffloorspecialflags_e specialflags; - // Only relevant for FF_BUSTUP + ffloorbustflags_e bustflags; UINT8 busttype; INT16 busttag; From 9ebc259ab3fd7cb7b98f6dc13c6c9f9b156579bb Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 6 Dec 2021 18:50:06 +0100 Subject: [PATCH 160/326] Split P_ProcessSpecialSector into multiple functions --- src/p_spec.c | 1156 ++++++++++++++++++++++++-------------------------- 1 file changed, 557 insertions(+), 599 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index c2caeb859..261f24aae 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4051,20 +4051,559 @@ static boolean P_MobjReadyToTrigger(mobj_t *mo, sector_t *sec) return (floorallowed || ceilingallowed); } +/// \todo check continues for proper splitscreen support? +static boolean P_DoAllPlayersTrigger(sector_t *sector, sector_t *roversector, boolean floortouch) +{ + INT32 i; + msecnode_t *node; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + if (!players[i].mo) + continue; + if (players[i].spectator) + continue; + if (players[i].bot) + continue; + if (G_CoopGametype() && players[i].lives <= 0) + continue; + if (roversector) + { + if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) + { + for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (P_ThingIsOnThe3DFloor(players[i].mo, sector, node->m_sector)) + break; + } + if (!node) + return false; + } + else if (players[i].mo->subsector && !P_ThingIsOnThe3DFloor(players[i].mo, sector, players[i].mo->subsector->sector)) // this function handles basically everything for us lmao + return false; + } + else + { + if (players[i].mo->subsector->sector != sector) + { + if (!(sector->flags & SF_TRIGGERSPECIAL_TOUCH)) + return false; + + for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (node->m_sector == sector) + break; + } + if (!node) + return false; + } + + if (floortouch && !P_MobjReadyToTrigger(players[i].mo, sector)) + return false; + } + } + + return true; +} + +static void P_ProcessEggCapsule(player_t *player, sector_t *sector) +{ + thinker_t *th; + mobj_t *mo2; + INT32 i; + + if (player->bot || sector->ceilingdata || sector->floordata) + return; + + // Find the center of the Eggtrap and release all the pretty animals! + // The chimps are my friends.. heeheeheheehehee..... - LouisJM + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; + if (mo2->type != MT_EGGTRAP) + continue; + P_KillMobj(mo2, NULL, player->mo, 0); + } + + // clear the special so you can't push the button twice. + sector->special = 0; + + // Move the button down + EV_DoElevator(LE_CAPSULE0, NULL, elevateDown); + + // Open the top FOF + EV_DoFloor(LE_CAPSULE1, NULL, raiseFloorToNearestFast); + // Open the bottom FOF + EV_DoCeiling(LE_CAPSULE2, NULL, lowerToLowestFast); + + // Mark all players with the time to exit thingy! + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + P_DoPlayerExit(&players[i]); + } +} + +static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *roversector, mtag_t sectag) +{ + INT32 lineindex; + angle_t lineangle; + fixed_t linespeed; + fixed_t sfxnum; + + if (player->powers[pw_flashing] != 0 && player->powers[pw_flashing] < TICRATE/2) + return; + + lineindex = Tag_FindLineSpecial(4, sectag); + + if (lineindex == -1) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #4.\n", sector->special); + return; + } + + lineangle = R_PointToAngle2(lines[lineindex].v1->x, lines[lineindex].v1->y, lines[lineindex].v2->x, lines[lineindex].v2->y); + linespeed = sides[lines[lineindex].sidenum[0]].textureoffset; + + if (linespeed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Speed pad (tag %d) at zero speed.\n", sectag); + return; + } + + player->mo->angle = player->drawangle = lineangle; + + if (!demoplayback || P_ControlStyle(player) == CS_LMAOGALOG) + P_SetPlayerAngle(player, player->mo->angle); + + if (!(lines[lineindex].flags & ML_EFFECT4)) + { + P_UnsetThingPosition(player->mo); + if (roversector) // make FOF speed pads work + { + player->mo->x = roversector->soundorg.x; + player->mo->y = roversector->soundorg.y; + } + else + { + player->mo->x = sector->soundorg.x; + player->mo->y = sector->soundorg.y; + } + P_SetThingPosition(player->mo); + } + + P_InstaThrust(player->mo, player->mo->angle, linespeed); + + if (lines[lineindex].flags & ML_EFFECT5) // Roll! + { + if (!(player->pflags & PF_SPINNING)) + player->pflags |= PF_SPINNING; + + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + } + + player->powers[pw_flashing] = TICRATE/3; + + sfxnum = sides[lines[lineindex].sidenum[0]].toptexture; + + if (!sfxnum) + sfxnum = sfx_spdpad; + + S_StartSound(player->mo, sfxnum); +} + +static void P_ProcessExitSector(player_t *player, mtag_t sectag) +{ + INT32 lineindex; + + if (!(gametyperules & GTR_ALLOWEXIT)) + return; + + if (player->bot) + return; + + if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6) + { + player->nightstime = 6; // Just let P_Ticker take care of the rest. + return; + } + + // Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c) + P_DoPlayerFinish(player); + + P_SetupSignExit(player); + + if (!G_CoopGametype()) + return; + + // Custom exit! + // important: use sectag on next line instead of player->mo->subsector->tag + // this part is different from in P_PlayerThink, this is what was causing + // FOF custom exits not to work. + lineindex = Tag_FindLineSpecial(2, sectag); + + if (lineindex == -1) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Exit sector missing line special #2.\n"); + return; + } + + // Special goodies with the block monsters flag depending on emeralds collected + if ((lines[lineindex].flags & ML_BLOCKMONSTERS) && ALL7EMERALDS(emeralds)) + nextmapoverride = (INT16)(lines[lineindex].frontsector->ceilingheight>>FRACBITS); + else + nextmapoverride = (INT16)(lines[lineindex].frontsector->floorheight>>FRACBITS); + + if (lines[lineindex].flags & ML_NOCLIMB) + skipstats = 1; +} + +static void P_ProcessTeamBase(player_t *player, boolean redteam) +{ + mobj_t *mo; + + if (!(gametyperules & GTR_TEAMFLAGS)) + return; + + if (!P_IsObjectOnGround(player->mo)) + return; + + if (player->ctfteam != (redteam ? 1 : 2)) + return; + + if (!(player->gotflag & (redteam ? GF_BLUEFLAG : GF_REDFLAG))) + return; + + // Make sure the team still has their own + // flag at their base so they can score. + if (!P_IsFlagAtBase(redteam ? MT_BLUEFLAG : MT_REDFLAG)) + return; + + HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE); + HU_SetCEchoDuration(5); + HU_DoCEcho(va(M_GetText("%s%s\200\\CAPTURED THE %s%s FLAG\200.\\\\\\\\"), redteam ? "\205" : "\204", player_names[player-players], redteam ? "\204" : "\205", redteam ? "BLUE" : "RED")); + + if (splitscreen || players[consoleplayer].ctfteam == (redteam ? 1 : 2)) + S_StartSound(NULL, sfx_flgcap); + else if (players[consoleplayer].ctfteam == (redteam ? 2 : 1)) + S_StartSound(NULL, sfx_lose); + + mo = P_SpawnMobj(player->mo->x,player->mo->y,player->mo->z, redteam ? MT_BLUEFLAG : MT_REDFLAG); + player->gotflag &= ~(redteam ? GF_BLUEFLAG : GF_REDFLAG); + mo->flags &= ~MF_SPECIAL; + mo->fuse = TICRATE; + mo->spawnpoint = redteam ? bflagpoint : rflagpoint; + mo->flags2 |= MF2_JUSTATTACKED; + if (redteam) + redscore += 1; + else + bluescore += 1; + P_AddPlayerScore(player, 250); +} + +static void P_ProcessZoomTube(player_t *player, sector_t *sector, mtag_t sectag, boolean end) +{ + INT32 sequence; + fixed_t speed; + INT32 lineindex; + mobj_t *waypoint = NULL; + angle_t an; + + if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) + return; + + if (player->powers[pw_ignorelatch] & (1<<15)) + return; + + // Find line #3 tagged to this sector + lineindex = Tag_FindLineSpecial(3, sectag); + + if (lineindex == -1) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #3.\n", sector->special); + return; + } + + // Grab speed and sequence values + speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; + if (end) + speed *= -1; + sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; + + if (speed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); + return; + } + + waypoint = end ? P_GetLastWaypoint(sequence) : P_GetFirstWaypoint(sequence); + + if (!waypoint) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: %s WAYPOINT IN SEQUENCE %d NOT FOUND.\n", end ? "LAST" : "FIRST", sequence); + return; + } + + CONS_Debug(DBG_GAMELOGIC, "Waypoint %d found in sequence %d - speed = %d\n", waypoint->health, sequence, speed); + + an = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->x, waypoint->y) - player->mo->angle; + + if (an > ANGLE_90 && an < ANGLE_270 && !(lines[lineindex].flags & ML_EFFECT4)) + return; // behind back + + P_SetTarget(&player->mo->tracer, waypoint); + player->powers[pw_carry] = CR_ZOOMTUBE; + player->speed = speed; + player->pflags |= PF_SPINNING; + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); + player->climbing = 0; + + if (player->mo->state-states != S_PLAY_ROLL) + { + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_spin); + } +} + +static void P_ProcessFinishLine(player_t *player) +{ + if ((gametyperules & (GTR_RACE|GTR_LIVES)) != GTR_RACE) + return; + + if (player->exiting) + return; + + if (player->starpostnum == numstarposts) // Must have touched all the starposts + { + player->laps++; + + if (player->powers[pw_carry] == CR_NIGHTSMODE) + player->drillmeter += 48*20; + + if (player->laps >= (UINT8)cv_numlaps.value) + CONS_Printf(M_GetText("%s has finished the race.\n"), player_names[player-players]); + else if (player->laps == (UINT8)cv_numlaps.value-1) + CONS_Printf(M_GetText("%s started the \205final lap\200!\n"), player_names[player-players]); + else + CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1); + + // Reset starposts (checkpoints) info + player->starpostscale = player->starpostangle = player->starposttime = player->starpostnum = 0; + player->starpostx = player->starposty = player->starpostz = 0; + P_ResetStarposts(); + + // Play the starpost sound for 'consistency' + S_StartSound(player->mo, sfx_strpst); + } + else if (player->starpostnum) + { + // blatant reuse of a variable that's normally unused in circuit + if (!player->tossdelay) + S_StartSound(player->mo, sfx_lose); + player->tossdelay = 3; + } + + if (player->laps >= (unsigned)cv_numlaps.value) + { + if (P_IsLocalPlayer(player)) + { + HU_SetCEchoFlags(0); + HU_SetCEchoDuration(5); + HU_DoCEcho("FINISHED!"); + } + + P_DoPlayerExit(player); + } +} + +static void P_ProcessRopeHang(player_t *player, sector_t *sector, mtag_t sectag) +{ + INT32 sequence; + fixed_t speed; + INT32 lineindex; + mobj_t *waypointmid = NULL; + mobj_t *waypointhigh = NULL; + mobj_t *waypointlow = NULL; + mobj_t *closest = NULL; + vector3_t p, line[2], resulthigh, resultlow; + + if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG) + return; + + if (player->powers[pw_ignorelatch] & (1<<15)) + return; + + if (player->mo->momz > 0) + return; + + if (player->cmd.buttons & BT_SPIN) + return; + + if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate]) + return; + + if (player->exiting) + return; + + //initialize resulthigh and resultlow with 0 + memset(&resultlow, 0x00, sizeof(resultlow)); + memset(&resulthigh, 0x00, sizeof(resulthigh)); + + // Find line #11 tagged to this sector + lineindex = Tag_FindLineSpecial(11, sectag); + + if (lineindex == -1) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #11.\n", sector->special); + return; + } + + // Grab speed and sequence values + speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; + sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; + + if (speed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); + return; + } + + // Find the closest waypoint + // Find the preceding waypoint + // Find the proceeding waypoint + // Determine the closest spot on the line between the three waypoints + // Put player at that location. + + waypointmid = P_GetClosestWaypoint(sequence, player->mo); + + if (!waypointmid) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: WAYPOINT(S) IN SEQUENCE %d NOT FOUND.\n", sequence); + return; + } + + waypointlow = P_GetPreviousWaypoint(waypointmid, true); + waypointhigh = P_GetNextWaypoint(waypointmid, true); + + CONS_Debug(DBG_GAMELOGIC, "WaypointMid: %d; WaypointLow: %d; WaypointHigh: %d\n", + waypointmid->health, waypointlow ? waypointlow->health : -1, waypointhigh ? waypointhigh->health : -1); + + // Now we have three waypoints... the closest one we're near, and the one that comes before, and after. + // 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) + { + 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(&p, line, &resultlow); + } + + // Waypointmid and Waypointhigh: + if (waypointhigh) + { + 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(&p, line, &resulthigh); + } + + // 3D support now available. Disregard the previous notice here. -Red + + P_UnsetThingPosition(player->mo); + P_ResetPlayer(player); + player->mo->momx = player->mo->momy = player->mo->momz = 0; + + if (lines[lineindex].flags & ML_EFFECT1) // Don't wrap + { + mobj_t *highest = P_GetLastWaypoint(sequence); + highest->flags |= MF_SLIDEME; + } + + // Changing the conditions on these ifs to fix issues with snapping to the wrong spot -Red + if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == 0) + { + closest = waypointhigh; + player->mo->x = resulthigh.x; + player->mo->y = resulthigh.y; + player->mo->z = resulthigh.z - P_GetPlayerHeight(player); + } + else if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == numwaypoints[sequence] - 1) + { + closest = waypointmid; + player->mo->x = resultlow.x; + player->mo->y = resultlow.y; + player->mo->z = resultlow.z - P_GetPlayerHeight(player); + } + else + { + if (P_AproxDistance(P_AproxDistance(player->mo->x-resultlow.x, player->mo->y-resultlow.y), + player->mo->z-resultlow.z) < P_AproxDistance(P_AproxDistance(player->mo->x-resulthigh.x, + player->mo->y-resulthigh.y), player->mo->z-resulthigh.z)) + { + // Line between Mid and Low is closer + closest = waypointmid; + player->mo->x = resultlow.x; + player->mo->y = resultlow.y; + player->mo->z = resultlow.z - P_GetPlayerHeight(player); + } + else + { + // Line between Mid and High is closer + closest = waypointhigh; + player->mo->x = resulthigh.x; + player->mo->y = resulthigh.y; + player->mo->z = resulthigh.z - P_GetPlayerHeight(player); + } + } + + P_SetTarget(&player->mo->tracer, closest); + player->powers[pw_carry] = CR_ROPEHANG; + + // Option for static ropes. + if (lines[lineindex].flags & ML_NOCLIMB) + player->speed = 0; + else + player->speed = speed; + + S_StartSound(player->mo, sfx_s3k4a); + + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); + player->climbing = 0; + P_SetThingPosition(player->mo); + P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); +} + /** Applies a sector special to a player. * * \param player Player in the sector. * \param sector Sector with the special. * \param roversector If !NULL, sector is actually an FOF; otherwise, sector * is being physically contacted by the player. - * \todo Split up into multiple functions. * \sa P_PlayerInSpecialSector, P_PlayerOnSpecial3DFloor */ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector) { - INT32 i = 0; INT32 section1, section2, section3, section4; - INT32 special; mtag_t sectag = Tag_FGet(§or->tags); section1 = GETSECSPECIAL(sector->special, 1); @@ -4086,10 +4625,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (section3 == 2 || section3 == 4) player->onconveyor = section3; - special = section1; - - // Process Section 1 - switch (special) + switch (section1) { case 1: // Damage (Generic) if (roversector || P_MobjReadyToTrigger(player->mo, sector)) @@ -4154,66 +4690,14 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers break; } - special = section2; - - // Process Section 2 - switch (special) + switch (section2) { case 1: // Trigger Linedef Exec (Pushable Objects) break; case 2: // Linedef executor requires all players present+doesn't require touching floor case 3: // Linedef executor requires all players present - /// \todo check continues for proper splitscreen support? - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - if (!players[i].mo) - continue; - if (players[i].spectator) - continue; - if (players[i].bot) - continue; - if (G_CoopGametype() && players[i].lives <= 0) - continue; - if (roversector) - { - if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) - { - msecnode_t *node; - for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (P_ThingIsOnThe3DFloor(players[i].mo, sector, node->m_sector)) - break; - } - if (!node) - goto DoneSection2; - } - else if (players[i].mo->subsector && !P_ThingIsOnThe3DFloor(players[i].mo, sector, players[i].mo->subsector->sector)) // this function handles basically everything for us lmao - goto DoneSection2; - } - else - { - if (players[i].mo->subsector->sector == sector) - ; - else if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) - { - msecnode_t *node; - for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (node->m_sector == sector) - break; - } - if (!node) - goto DoneSection2; - } - else - goto DoneSection2; - - if (special == 3 && !P_MobjReadyToTrigger(players[i].mo, sector)) - goto DoneSection2; - } - } + if (!P_DoAllPlayersTrigger(sector, roversector, section2 == 3)) + break; /* FALLTHRU */ case 4: // Linedef executor that doesn't require touching floor case 5: // Linedef executor @@ -4225,57 +4709,16 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers case 8: // Tells pushable things to check FOFs break; case 9: // Egg trap capsule - { - thinker_t *th; - mobj_t *mo2; - - if (player->bot || sector->ceilingdata || sector->floordata) - return; - - // Find the center of the Eggtrap and release all the pretty animals! - // The chimps are my friends.. heeheeheheehehee..... - LouisJM - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - mo2 = (mobj_t *)th; - if (mo2->type != MT_EGGTRAP) - continue; - P_KillMobj(mo2, NULL, player->mo, 0); - } - - // clear the special so you can't push the button twice. - sector->special = 0; - - // Move the button down - EV_DoElevator(LE_CAPSULE0, NULL, elevateDown); - - // Open the top FOF - EV_DoFloor(LE_CAPSULE1, NULL, raiseFloorToNearestFast); - // Open the bottom FOF - EV_DoCeiling(LE_CAPSULE2, NULL, lowerToLowestFast); - - // Mark all players with the time to exit thingy! - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - P_DoPlayerExit(&players[i]); - } + P_ProcessEggCapsule(player, sector); break; - } case 10: // Special Stage Time/Rings case 11: // Custom Gravity break; case 12: // Lua sector special break; } -DoneSection2: - special = section3; - - // Process Section 3 - switch (special) + switch (section3) { case 1: // Unused case 2: // Wind/Current @@ -4284,66 +4727,7 @@ DoneSection2: break; case 5: // Speed pad - if (player->powers[pw_flashing] != 0 && player->powers[pw_flashing] < TICRATE/2) - break; - - i = Tag_FindLineSpecial(4, sectag); - - if (i != -1) - { - angle_t lineangle; - fixed_t linespeed; - fixed_t sfxnum; - - lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); - linespeed = sides[lines[i].sidenum[0]].textureoffset; - - if (linespeed == 0) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Speed pad (tag %d) at zero speed.\n", sectag); - break; - } - - player->mo->angle = player->drawangle = lineangle; - - if (!demoplayback || P_ControlStyle(player) == CS_LMAOGALOG) - P_SetPlayerAngle(player, player->mo->angle); - - if (!(lines[i].flags & ML_EFFECT4)) - { - P_UnsetThingPosition(player->mo); - if (roversector) // make FOF speed pads work - { - player->mo->x = roversector->soundorg.x; - player->mo->y = roversector->soundorg.y; - } - else - { - player->mo->x = sector->soundorg.x; - player->mo->y = sector->soundorg.y; - } - P_SetThingPosition(player->mo); - } - - P_InstaThrust(player->mo, player->mo->angle, linespeed); - - if (lines[i].flags & ML_EFFECT5) // Roll! - { - if (!(player->pflags & PF_SPINNING)) - player->pflags |= PF_SPINNING; - - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - } - - player->powers[pw_flashing] = TICRATE/3; - - sfxnum = sides[lines[i].sidenum[0]].toptexture; - - if (!sfxnum) - sfxnum = sfx_spdpad; - - S_StartSound(player->mo, sfxnum); - } + P_ProcessSpeedPad(player, sector, roversector, sectag); break; case 6: // Unused @@ -4359,10 +4743,7 @@ DoneSection2: break; } - special = section4; - - // Process Section 4 - switch (special) + switch (section4) { case 1: // Starpost Activator { @@ -4376,104 +4757,15 @@ DoneSection2: } case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return - if (player->bot || !(gametyperules & GTR_ALLOWEXIT)) - break; - if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6) - { - player->nightstime = 6; // Just let P_Ticker take care of the rest. - return; - } - - // Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c) - { - INT32 lineindex; - - P_DoPlayerFinish(player); - - P_SetupSignExit(player); - // important: use sector->tag on next line instead of player->mo->subsector->tag - // this part is different from in P_PlayerThink, this is what was causing - // FOF custom exits not to work. - lineindex = Tag_FindLineSpecial(2, sectag); - - if (G_CoopGametype() && lineindex != -1) // Custom exit! - { - // Special goodies with the block monsters flag depending on emeralds collected - if ((lines[lineindex].flags & ML_BLOCKMONSTERS) && ALL7EMERALDS(emeralds)) - nextmapoverride = (INT16)(lines[lineindex].frontsector->ceilingheight>>FRACBITS); - else - nextmapoverride = (INT16)(lines[lineindex].frontsector->floorheight>>FRACBITS); - - if (lines[lineindex].flags & ML_NOCLIMB) - skipstats = 1; - } - } + P_ProcessExitSector(player, sectag); break; case 3: // Red Team's Base - if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo)) - { - if (player->ctfteam == 1 && (player->gotflag & GF_BLUEFLAG)) - { - mobj_t *mo; - - // Make sure the red team still has their own - // flag at their base so they can score. - if (!P_IsFlagAtBase(MT_REDFLAG)) - break; - - HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE); - HU_SetCEchoDuration(5); - HU_DoCEcho(va(M_GetText("\205%s\200\\CAPTURED THE \204BLUE FLAG\200.\\\\\\\\"), player_names[player-players])); - - if (splitscreen || players[consoleplayer].ctfteam == 1) - S_StartSound(NULL, sfx_flgcap); - else if (players[consoleplayer].ctfteam == 2) - S_StartSound(NULL, sfx_lose); - - mo = P_SpawnMobj(player->mo->x,player->mo->y,player->mo->z,MT_BLUEFLAG); - player->gotflag &= ~GF_BLUEFLAG; - mo->flags &= ~MF_SPECIAL; - mo->fuse = TICRATE; - mo->spawnpoint = bflagpoint; - mo->flags2 |= MF2_JUSTATTACKED; - redscore += 1; - P_AddPlayerScore(player, 250); - } - } + P_ProcessTeamBase(player, true); break; case 4: // Blue Team's Base - if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo)) - { - if (player->ctfteam == 2 && (player->gotflag & GF_REDFLAG)) - { - mobj_t *mo; - - // Make sure the blue team still has their own - // flag at their base so they can score. - if (!P_IsFlagAtBase(MT_BLUEFLAG)) - break; - - HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE); - HU_SetCEchoDuration(5); - HU_DoCEcho(va(M_GetText("\204%s\200\\CAPTURED THE \205RED FLAG\200.\\\\\\\\"), player_names[player-players])); - - if (splitscreen || players[consoleplayer].ctfteam == 2) - S_StartSound(NULL, sfx_flgcap); - else if (players[consoleplayer].ctfteam == 1) - S_StartSound(NULL, sfx_lose); - - mo = P_SpawnMobj(player->mo->x,player->mo->y,player->mo->z,MT_REDFLAG); - player->gotflag &= ~GF_REDFLAG; - mo->flags &= ~MF_SPECIAL; - mo->fuse = TICRATE; - mo->spawnpoint = rflagpoint; - mo->flags2 |= MF2_JUSTATTACKED; - bluescore += 1; - P_AddPlayerScore(player, 250); - } - } + P_ProcessTeamBase(player, false); break; case 5: // Fan sector @@ -4506,353 +4798,19 @@ DoneSection2: break; case 8: // Zoom Tube Start - { - INT32 sequence; - fixed_t speed; - INT32 lineindex; - mobj_t *waypoint = NULL; - angle_t an; - - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) - break; - - if (player->powers[pw_ignorelatch] & (1<<15)) - break; - - // Find line #3 tagged to this sector - lineindex = Tag_FindLineSpecial(3, sectag); - - if (lineindex == -1) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #3.\n", sector->special); - break; - } - - // Grab speed and sequence values - speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; - sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; - - if (speed == 0) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); - break; - } - - waypoint = P_GetFirstWaypoint(sequence); - - if (!waypoint) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: FIRST WAYPOINT IN SEQUENCE %d NOT FOUND.\n", sequence); - break; - } - else - { - CONS_Debug(DBG_GAMELOGIC, "Waypoint %d found in sequence %d - speed = %d\n", waypoint->health, sequence, speed); - } - - an = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->x, waypoint->y) - player->mo->angle; - - if (an > ANGLE_90 && an < ANGLE_270 && !(lines[lineindex].flags & ML_EFFECT4)) - break; // behind back - - P_SetTarget(&player->mo->tracer, waypoint); - player->powers[pw_carry] = CR_ZOOMTUBE; - player->speed = speed; - player->pflags |= PF_SPINNING; - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); - player->climbing = 0; - - if (player->mo->state-states != S_PLAY_ROLL) - { - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_spin); - } - } + P_ProcessZoomTube(player, sector, sectag, false); break; case 9: // Zoom Tube End - { - INT32 sequence; - fixed_t speed; - INT32 lineindex; - mobj_t *waypoint = NULL; - angle_t an; - - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) - break; - - if (player->powers[pw_ignorelatch] & (1<<15)) - break; - - // Find line #3 tagged to this sector - lineindex = Tag_FindLineSpecial(3, sectag); - - if (lineindex == -1) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #3.\n", sector->special); - break; - } - - // Grab speed and sequence values - speed = -abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; // Negative means reverse - sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; - - if (speed == 0) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); - break; - } - - waypoint = P_GetLastWaypoint(sequence); - - if (!waypoint) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: LAST WAYPOINT IN SEQUENCE %d NOT FOUND.\n", sequence); - break; - } - else - { - CONS_Debug(DBG_GAMELOGIC, "Waypoint %d found in sequence %d - speed = %d\n", waypoint->health, sequence, speed); - } - - an = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->x, waypoint->y) - player->mo->angle; - - if (an > ANGLE_90 && an < ANGLE_270 && !(lines[lineindex].flags & ML_EFFECT4)) - break; // behind back - - P_SetTarget(&player->mo->tracer, waypoint); - player->powers[pw_carry] = CR_ZOOMTUBE; - player->speed = speed; - player->pflags |= PF_SPINNING; - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); - player->climbing = 0; - - if (player->mo->state-states != S_PLAY_ROLL) - { - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_spin); - } - } + P_ProcessZoomTube(player, sector, sectag, true); break; case 10: // Finish Line - if (((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE) && !player->exiting) - { - if (player->starpostnum == numstarposts) // Must have touched all the starposts - { - player->laps++; - - if (player->powers[pw_carry] == CR_NIGHTSMODE) - player->drillmeter += 48*20; - - if (player->laps >= (UINT8)cv_numlaps.value) - CONS_Printf(M_GetText("%s has finished the race.\n"), player_names[player-players]); - else if (player->laps == (UINT8)cv_numlaps.value-1) - CONS_Printf(M_GetText("%s started the \205final lap\200!\n"), player_names[player-players]); - else - CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1); - - // Reset starposts (checkpoints) info - player->starpostscale = player->starpostangle = player->starposttime = player->starpostnum = 0; - player->starpostx = player->starposty = player->starpostz = 0; - P_ResetStarposts(); - - // Play the starpost sound for 'consistency' - S_StartSound(player->mo, sfx_strpst); - } - else if (player->starpostnum) - { - // blatant reuse of a variable that's normally unused in circuit - if (!player->tossdelay) - S_StartSound(player->mo, sfx_lose); - player->tossdelay = 3; - } - - if (player->laps >= (unsigned)cv_numlaps.value) - { - if (P_IsLocalPlayer(player)) - { - HU_SetCEchoFlags(0); - HU_SetCEchoDuration(5); - HU_DoCEcho("FINISHED!"); - } - - P_DoPlayerExit(player); - } - } + P_ProcessFinishLine(player); break; case 11: // Rope hang - { - INT32 sequence; - fixed_t speed; - INT32 lineindex; - mobj_t *waypointmid = NULL; - mobj_t *waypointhigh = NULL; - mobj_t *waypointlow = NULL; - mobj_t *closest = NULL; - vector3_t p, line[2], resulthigh, resultlow; - - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG) - break; - - if (player->powers[pw_ignorelatch] & (1<<15)) - break; - - if (player->mo->momz > 0) - break; - - if (player->cmd.buttons & BT_SPIN) - break; - - if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate]) - break; - - if (player->exiting) - break; - - //initialize resulthigh and resultlow with 0 - memset(&resultlow, 0x00, sizeof(resultlow)); - memset(&resulthigh, 0x00, sizeof(resulthigh)); - - // Find line #11 tagged to this sector - lineindex = Tag_FindLineSpecial(11, sectag); - - if (lineindex == -1) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #11.\n", sector->special); - break; - } - - // Grab speed and sequence values - speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; - sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; - - if (speed == 0) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); - break; - } - - // Find the closest waypoint - // Find the preceding waypoint - // Find the proceeding waypoint - // Determine the closest spot on the line between the three waypoints - // Put player at that location. - - waypointmid = P_GetClosestWaypoint(sequence, player->mo); - - if (!waypointmid) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: WAYPOINT(S) IN SEQUENCE %d NOT FOUND.\n", sequence); - break; - } - - waypointlow = P_GetPreviousWaypoint(waypointmid, true); - waypointhigh = P_GetNextWaypoint(waypointmid, true); - - CONS_Debug(DBG_GAMELOGIC, "WaypointMid: %d; WaypointLow: %d; WaypointHigh: %d\n", - waypointmid->health, waypointlow ? waypointlow->health : -1, waypointhigh ? waypointhigh->health : -1); - - // Now we have three waypoints... the closest one we're near, and the one that comes before, and after. - // 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) - { - 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(&p, line, &resultlow); - } - - // Waypointmid and Waypointhigh: - if (waypointhigh) - { - 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(&p, line, &resulthigh); - } - - // 3D support now available. Disregard the previous notice here. -Red - - P_UnsetThingPosition(player->mo); - P_ResetPlayer(player); - player->mo->momx = player->mo->momy = player->mo->momz = 0; - - if (lines[lineindex].flags & ML_EFFECT1) // Don't wrap - { - mobj_t *highest = P_GetLastWaypoint(sequence); - highest->flags |= MF_SLIDEME; - } - - // Changing the conditions on these ifs to fix issues with snapping to the wrong spot -Red - if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == 0) - { - closest = waypointhigh; - player->mo->x = resulthigh.x; - player->mo->y = resulthigh.y; - player->mo->z = resulthigh.z - P_GetPlayerHeight(player); - } - else if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == numwaypoints[sequence] - 1) - { - closest = waypointmid; - player->mo->x = resultlow.x; - player->mo->y = resultlow.y; - player->mo->z = resultlow.z - P_GetPlayerHeight(player); - } - else - { - if (P_AproxDistance(P_AproxDistance(player->mo->x-resultlow.x, player->mo->y-resultlow.y), - player->mo->z-resultlow.z) < P_AproxDistance(P_AproxDistance(player->mo->x-resulthigh.x, - player->mo->y-resulthigh.y), player->mo->z-resulthigh.z)) - { - // Line between Mid and Low is closer - closest = waypointmid; - player->mo->x = resultlow.x; - player->mo->y = resultlow.y; - player->mo->z = resultlow.z - P_GetPlayerHeight(player); - } - else - { - // Line between Mid and High is closer - closest = waypointhigh; - player->mo->x = resulthigh.x; - player->mo->y = resulthigh.y; - player->mo->z = resulthigh.z - P_GetPlayerHeight(player); - } - } - - P_SetTarget(&player->mo->tracer, closest); - player->powers[pw_carry] = CR_ROPEHANG; - - // Option for static ropes. - if (lines[lineindex].flags & ML_NOCLIMB) - player->speed = 0; - else - player->speed = speed; - - S_StartSound(player->mo, sfx_s3k4a); - - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); - player->climbing = 0; - P_SetThingPosition(player->mo); - P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); - } + P_ProcessRopeHang(player, sector, sectag); break; case 12: // Camera noclip case 13: // Unused From 222d05a42456bb6927fdc9c14fe864d279c237e5 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 6 Dec 2021 19:33:36 +0100 Subject: [PATCH 161/326] Refactor sector special plane touching code --- src/p_spec.c | 334 ++++++++++++++++----------------------------------- 1 file changed, 105 insertions(+), 229 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 261f24aae..02e48fab2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3879,6 +3879,53 @@ boolean P_IsFlagAtBase(mobjtype_t flag) return false; } +static boolean P_IsMobjTouchingPlane(mobj_t *mo, sector_t *sec, fixed_t floorz, fixed_t ceilingz) +{ + boolean floorallowed = ((sec->flags & SF_FLIPSPECIAL_FLOOR) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == floorz)); + boolean ceilingallowed = ((sec->flags & SF_FLIPSPECIAL_CEILING) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == ceilingz)); + return (floorallowed || ceilingallowed); +} + +static boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec) +{ + return P_IsMobjTouchingPlane(mo, sec, P_GetSpecialBottomZ(mo, sec, sec), P_GetSpecialTopZ(mo, sec, sec)); +} + +static boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *ffloor, sector_t *sec) +{ + fixed_t topheight = P_GetSpecialTopZ(mo, sectors + ffloor->secnum, sec); + fixed_t bottomheight = P_GetSpecialBottomZ(mo, sectors + ffloor->secnum, sec); + + if (((ffloor->flags & FF_BLOCKPLAYER) && mo->player) + || ((ffloor->flags & FF_BLOCKOTHERS) && !mo->player)) + { + // Solid 3D floor: Mobj must touch the top or bottom + return P_IsMobjTouchingPlane(mo, ffloor->master->frontsector, topheight, bottomheight); + } + else + { + // Water or intangible 3D floor: Mobj must be inside + return mo->z <= topheight && (mo->z + mo->height) >= bottomheight; + } +} + +static boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec) +{ + if (!(po->flags & POF_TESTHEIGHT)) // Don't do height checking + return true; + + if (po->flags & POF_SOLID) + { + // Solid polyobject: Player must touch the top or bottom + return P_IsMobjTouchingPlane(mo, polysec, polysec->ceilingheight, polysec->floorheight); + } + else + { + // Water or intangible polyobject: Player must be inside + return mo->z <= polysec->ceilingheight && (mo->z + mo->height) >= polysec->floorheight; + } +} + // // P_PlayerTouchingSectorSpecial // @@ -3905,32 +3952,14 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n // Hmm.. maybe there's a FOF that has it... for (rover = player->mo->subsector->sector->ffloors; rover; rover = rover->next) { - fixed_t topheight, bottomheight; - if (GETSECSPECIAL(rover->master->frontsector->special, section) != number) continue; if (!(rover->flags & FF_EXISTS)) continue; - topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); - bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); - - // Check the 3D floor's type... - if (rover->flags & FF_BLOCKPLAYER) - { - boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); - boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - continue; - } - else - { - // Water and DEATH FOG!!! heh - if (player->mo->z > topheight || (player->mo->z + player->mo->height) < bottomheight) - continue; - } + if (!P_IsMobjTouching3DFloor(player->mo, rover, player->mo->subsector->sector)) + continue; // This FOF has the special we're looking for! return rover->master->frontsector; @@ -3950,32 +3979,14 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n // Hmm.. maybe there's a FOF that has it... for (rover = node->m_sector->ffloors; rover; rover = rover->next) { - fixed_t topheight, bottomheight; - if (GETSECSPECIAL(rover->master->frontsector->special, section) != number) continue; if (!(rover->flags & FF_EXISTS)) continue; - topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); - bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); - - // Check the 3D floor's type... - if (rover->flags & FF_BLOCKPLAYER) - { - boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); - boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - continue; - } - else - { - // Water and DEATH FOG!!! heh - if (player->mo->z > topheight || (player->mo->z + player->mo->height) < bottomheight) - continue; - } + if (!P_IsMobjTouching3DFloor(player->mo, rover, node->m_sector)) + continue; // This FOF has the special we're looking for, but are we allowed to touch it? if (node->m_sector == player->mo->subsector->sector @@ -3996,14 +4007,10 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *targetsec) { ffloor_t *rover; - fixed_t top, bottom; if (!mo->player) // should NEVER happen return false; - if (!targetsec->ffloors) // also should NEVER happen - return false; - for (rover = targetsec->ffloors; rover; rover = rover->next) { if (rover->master->frontsector != sector) @@ -4013,44 +4020,12 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar //if (!(rover->flags & FF_EXISTS)) // return false; - top = P_GetSpecialTopZ(mo, sector, targetsec); - bottom = P_GetSpecialBottomZ(mo, sector, targetsec); - - // Check the 3D floor's type... - if (rover->flags & FF_BLOCKPLAYER) - { - boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == top)); - boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottom)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - continue; - } - else - { - // Water and intangible FOFs - if (mo->z > top || (mo->z + mo->height) < bottom) - return false; - } - - return true; + return P_IsMobjTouching3DFloor(mo, rover, targetsec); } return false; } -// -// P_MobjReadyToTrigger -// -// Is player standing on the sector's "ground"? -// -static boolean P_MobjReadyToTrigger(mobj_t *mo, sector_t *sec) -{ - boolean floorallowed = ((sec->flags & SF_FLIPSPECIAL_FLOOR) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == P_GetSpecialBottomZ(mo, sec, sec))); - boolean ceilingallowed = ((sec->flags & SF_FLIPSPECIAL_CEILING) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == P_GetSpecialTopZ(mo, sec, sec))); - // Thing must be on top of the floor to be affected... - return (floorallowed || ceilingallowed); -} - /// \todo check continues for proper splitscreen support? static boolean P_DoAllPlayersTrigger(sector_t *sector, sector_t *roversector, boolean floortouch) { @@ -4100,7 +4075,7 @@ static boolean P_DoAllPlayersTrigger(sector_t *sector, sector_t *roversector, bo return false; } - if (floortouch && !P_MobjReadyToTrigger(players[i].mo, sector)) + if (floortouch && !P_IsMobjTouchingSectorPlane(players[i].mo, sector)) return false; } } @@ -4628,28 +4603,28 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers switch (section1) { case 1: // Damage (Generic) - if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + if (roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) P_DamageMobj(player->mo, NULL, NULL, 1, 0); break; case 2: // Damage (Water) - if ((roversector || P_MobjReadyToTrigger(player->mo, sector)) && (player->powers[pw_underwater] || player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) && (player->powers[pw_underwater] || player->powers[pw_carry] == CR_NIGHTSMODE)) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_WATER); break; case 3: // Damage (Fire) - if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + if (roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_FIRE); break; case 4: // Damage (Electrical) - if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + if (roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_ELECTRIC); break; case 5: // Spikes - if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + if (roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPIKE); break; case 6: // Death Pit (Camera Mod) case 7: // Death Pit (No Camera Mod) - if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + if (roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) { if (player->quittime) G_MovePlayerToSpawnOrStarpost(player - players); @@ -4713,7 +4688,6 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers break; case 10: // Special Stage Time/Rings case 11: // Custom Gravity - break; case 12: // Lua sector special break; } @@ -4725,11 +4699,9 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers case 3: // Unused case 4: // Conveyor Belt break; - case 5: // Speed pad P_ProcessSpeedPad(player, sector, roversector, sectag); break; - case 6: // Unused case 7: // Unused case 8: // Unused @@ -4755,19 +4727,15 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_TouchStarPost(post, player, false); break; } - case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return P_ProcessExitSector(player, sectag); break; - case 3: // Red Team's Base P_ProcessTeamBase(player, true); break; - case 4: // Blue Team's Base P_ProcessTeamBase(player, false); break; - case 5: // Fan sector player->mo->momz += mobjinfo[MT_FAN].mass/4; @@ -4778,12 +4746,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (player->panim != PA_FALL) P_SetPlayerMobjState(player->mo, S_PLAY_FALL); break; - case 6: // Super Sonic transformer if (player->mo->health > 0 && !player->bot && (player->charflags & SF_SUPER) && !player->powers[pw_super] && ALL7EMERALDS(emeralds)) P_DoSuperTransformation(player, true); break; - case 7: // Make player spin if (!(player->pflags & PF_SPINNING)) { @@ -4796,19 +4762,15 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_InstaThrust(player->mo, player->mo->angle, FixedMul(10*FRACUNIT, player->mo->scale)); } break; - case 8: // Zoom Tube Start P_ProcessZoomTube(player, sector, sectag, false); break; - case 9: // Zoom Tube End P_ProcessZoomTube(player, sector, sectag, true); break; - case 10: // Finish Line P_ProcessFinishLine(player); break; - case 11: // Rope hang P_ProcessRopeHang(player, sector, sectag); break; @@ -4830,15 +4792,9 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers */ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) { - sector_t *sector; ffloor_t *rover; - fixed_t topheight, bottomheight; - sector = mo->subsector->sector; - if (!sector->ffloors) - return NULL; - - for (rover = sector->ffloors; rover; rover = rover->next) + for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) { if (!rover->master->frontsector->special) continue; @@ -4846,25 +4802,8 @@ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) if (!(rover->flags & FF_EXISTS)) continue; - topheight = P_GetSpecialTopZ(mo, sectors + rover->secnum, sector); - bottomheight = P_GetSpecialBottomZ(mo, sectors + rover->secnum, sector); - - // Check the 3D floor's type... - if (((rover->flags & FF_BLOCKPLAYER) && mo->player) - || ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) - { - boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == topheight)); - boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottomheight)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - continue; - } - else - { - // Water and intangible FOFs - if (mo->z > topheight || (mo->z + mo->height) < bottomheight) - continue; - } + if (!P_IsMobjTouching3DFloor(mo, rover, mo->subsector->sector)) + continue; return rover->master->frontsector; } @@ -4884,7 +4823,6 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) { sector_t *originalsector = player->mo->subsector->sector; ffloor_t *rover; - fixed_t topheight, bottomheight; for (rover = sector->ffloors; rover; rover = rover->next) { @@ -4894,24 +4832,8 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) if (!(rover->flags & FF_EXISTS)) continue; - topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, sector); - bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, sector); - - // Check the 3D floor's type... - if (rover->flags & FF_BLOCKPLAYER) - { - boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); - boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - continue; - } - else - { - // Water and DEATH FOG!!! heh - if (player->mo->z > topheight || (player->mo->z + player->mo->height) < bottomheight) - continue; - } + if (!P_IsMobjTouching3DFloor(player->mo, rover, sector)) + continue; // This FOF has the special we're looking for, but are we allowed to touch it? if (sector == player->mo->subsector->sector @@ -4921,77 +4843,40 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) if TELEPORTED return; } } - - // Allow sector specials to be applied to polyobjects! - if (player->mo->subsector->polyList) - { - polyobj_t *po = player->mo->subsector->polyList; - sector_t *polysec; - boolean touching = false; - boolean inside = false; - - while (po) - { - if (po->flags & POF_NOSPECIALS) - { - po = (polyobj_t *)(po->link.next); - continue; - } - - polysec = po->lines[0]->backsector; - - if ((polysec->flags & SF_TRIGGERSPECIAL_TOUCH)) - touching = P_MobjTouchingPolyobj(po, player->mo); - else - touching = false; - - inside = P_MobjInsidePolyobj(po, player->mo); - - if (!(inside || touching)) - { - po = (polyobj_t *)(po->link.next); - continue; - } - - // We're inside it! Yess... - if (!polysec->special) - { - po = (polyobj_t *)(po->link.next); - continue; - } - - if (!(po->flags & POF_TESTHEIGHT)) // Don't do height checking - ; - else if (po->flags & POF_SOLID) - { - boolean floorallowed = ((polysec->flags & SF_FLIPSPECIAL_FLOOR) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == polysec->ceilingheight)); - boolean ceilingallowed = ((polysec->flags & SF_FLIPSPECIAL_CEILING) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == polysec->floorheight)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - { - po = (polyobj_t *)(po->link.next); - continue; - } - } - else - { - // Water and DEATH FOG!!! heh - if (player->mo->z > polysec->ceilingheight || (player->mo->z + player->mo->height) < polysec->floorheight) - { - po = (polyobj_t *)(po->link.next); - continue; - } - } - - P_ProcessSpecialSector(player, polysec, sector); - if TELEPORTED return; - - po = (polyobj_t *)(po->link.next); - } - } } -#define VDOORSPEED (FRACUNIT*2) +static void P_PlayerOnSpecialPolyobj(player_t *player, sector_t *sector) +{ + sector_t *originalsector = player->mo->subsector->sector; + polyobj_t *po; + sector_t *polysec; + boolean touching = false; + boolean inside = false; + + //TODO: Check polyobjects in sector + for (po = player->mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) + { + if (po->flags & POF_NOSPECIALS) + continue; + + polysec = po->lines[0]->backsector; + + if (!polysec->special) + continue; + + touching = (polysec->flags & SF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); + inside = P_MobjInsidePolyobj(po, player->mo); + + if (!(inside || touching)) + continue; + + if (!P_IsMobjTouchingPolyobj(player->mo, po, polysec)) + continue; + + P_ProcessSpecialSector(player, polysec, sector); + if TELEPORTED return; + } +} // // P_RunSpecialSectorCheck @@ -5001,7 +4886,6 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector) { boolean nofloorneeded = false; - fixed_t f_affectpoint, c_affectpoint; if (!sector->special) // nothing special, exit return; @@ -5060,24 +4944,8 @@ static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector) break; } - if (nofloorneeded) - { + if (nofloorneeded || P_IsMobjTouchingSectorPlane(player->mo, sector)) P_ProcessSpecialSector(player, sector, NULL); - return; - } - - f_affectpoint = P_GetSpecialBottomZ(player->mo, sector, sector); - c_affectpoint = P_GetSpecialTopZ(player->mo, sector, sector); - - { - boolean floorallowed = ((sector->flags & SF_FLIPSPECIAL_FLOOR) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == f_affectpoint)); - boolean ceilingallowed = ((sector->flags & SF_FLIPSPECIAL_CEILING) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == c_affectpoint)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - return; - } - - P_ProcessSpecialSector(player, sector, NULL); } /** Checks if the player is in a special sector or FOF and apply any specials. @@ -5099,6 +4967,10 @@ void P_PlayerInSpecialSector(player_t *player) P_PlayerOnSpecial3DFloor(player, originalsector); // Handle FOFs first. if TELEPORTED return; + // Allow sector specials to be applied to polyobjects! + P_PlayerOnSpecialPolyobj(player, originalsector); + if TELEPORTED return; + P_RunSpecialSectorCheck(player, originalsector); if TELEPORTED return; @@ -5114,6 +4986,10 @@ void P_PlayerInSpecialSector(player_t *player) P_PlayerOnSpecial3DFloor(player, loopsector); if TELEPORTED return; + // Check polyobjects... + P_PlayerOnSpecialPolyobj(player, loopsector); + if TELEPORTED return; + if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) continue; From c9ed4841296912167f412a45fdd3815a84012bc5 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 7 Dec 2021 07:17:58 +0100 Subject: [PATCH 162/326] Rewrite each time thinker --- src/p_floor.c | 316 ++++++++++++++++++++++++-------------------------- src/p_local.h | 1 - src/p_saveg.c | 2 - src/p_spec.c | 6 +- src/p_spec.h | 5 +- src/p_user.c | 83 ------------- 6 files changed, 156 insertions(+), 257 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index 7fbc1ad4c..551469a29 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1272,216 +1272,198 @@ void T_NoEnemiesSector(noenemies_t *nobaddies) P_RemoveThinker(&nobaddies->thinker); } -// -// P_IsObjectOnRealGround -// -// Helper function for T_EachTimeThinker -// Like P_IsObjectOnGroundIn, except ONLY THE REAL GROUND IS CONSIDERED, NOT FOFS -// I'll consider whether to make this a more globally accessible function or whatever in future -// -- Monster Iestyn -// -static boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec) +static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line_t *sourceline) { - // Is the object in reverse gravity? - if (mo->eflags & MFE_VERTICALFLIP) + ffloor_t *rover; + + for (rover = sector->ffloors; rover; rover = rover->next) { - // Detect if the player is on the ceiling. - if (mo->z+mo->height >= P_GetSpecialTopZ(mo, sec, sec)) - return true; + if (GETSECSPECIAL(rover->master->frontsector->special, 2) < 2 || GETSECSPECIAL(rover->master->frontsector->special, 2) > 7) + continue; + + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!Tag_Find(&sourceline->tags, Tag_FGet(&rover->master->frontsector->tags))) + return false; + + if (!P_IsMobjTouching3DFloor(player->mo, rover, sector)) + continue; + + // This FOF has the special we're looking for, but are we allowed to touch it? + if (sector == player->mo->subsector->sector + || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + return rover->master->frontsector; } - // Nope! - else - { - // Detect if the player is on the floor. - if (mo->z <= P_GetSpecialBottomZ(mo, sec, sec)) - return true; - } - return false; + + return NULL; } -static boolean P_IsMobjTouchingSector(mobj_t *mo, sector_t *sec) +static sector_t *P_CheckPolyobjTriggers(player_t *player, line_t *sourceline) { - msecnode_t *node; + polyobj_t *po; + sector_t *polysec; + boolean touching = false; + boolean inside = false; - if (mo->subsector->sector == sec) - return true; + for (po = player->mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) //TODO + { + if (po->flags & POF_NOSPECIALS) + continue; - if (!(sec->flags & SF_TRIGGERSPECIAL_TOUCH)) + polysec = po->lines[0]->backsector; + + if (GETSECSPECIAL(polysec->special, 2) < 2 || GETSECSPECIAL(polysec->special, 2) > 7) + continue; + + if (!Tag_Find(&sourceline->tags, Tag_FGet(&polysec->tags))) + return false; + + touching = (polysec->flags & SF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); + inside = P_MobjInsidePolyobj(po, player->mo); + + if (!(inside || touching)) + continue; + + if (!P_IsMobjTouchingPolyobj(player->mo, po, polysec)) + continue; + + return polysec; + } + + return NULL; +} + +static boolean P_CheckSectorTriggers(player_t *player, sector_t *sector, line_t *sourceline) +{ + if (GETSECSPECIAL(sector->special, 2) < 2 || GETSECSPECIAL(sector->special, 2) > 7) return false; - for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + if (!Tag_Find(&sourceline->tags, Tag_FGet(§or->tags))) + return false; + + if (GETSECSPECIAL(sector->special, 2) != 3 && GETSECSPECIAL(sector->special, 2) != 5) + return true; // "Anywhere in sector" types + + return P_IsMobjTouchingSectorPlane(player->mo, sector); + +} + +static sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) +{ + sector_t *originalsector; + sector_t *loopsector; + msecnode_t *node; + sector_t *caller; + + if (!player->mo) + return NULL; + + originalsector = player->mo->subsector->sector; + + caller = P_Check3DFloorTriggers(player, originalsector, sourceline); // Handle FOFs first. + + if (caller) + return caller; + + // Allow sector specials to be applied to polyobjects! + caller = P_CheckPolyobjTriggers(player, sourceline); + + if (caller) + return caller; + + if (P_CheckSectorTriggers(player, originalsector, sourceline)) + return originalsector; + + // Iterate through touching_sectorlist for SF_TRIGGERSPECIAL_TOUCH + for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) { - if (node->m_sector == sec) - return true; + loopsector = node->m_sector; + + if (loopsector == originalsector) // Don't duplicate + continue; + + // Check 3D floors... + caller = P_Check3DFloorTriggers(player, loopsector, sourceline); // Handle FOFs first. + + if (caller) + return caller; + + //TODO: Check polyobjects in loopsector + + if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + continue; + + if (P_CheckSectorTriggers(player, loopsector, sourceline)) + return loopsector; } return false; } -// -// T_EachTimeThinker -// -// Runs a linedef exec whenever a player enters an area. -// Keeps track of players currently in the area and notices any changes. -// -// \sa P_AddEachTimeThinker -// +static boolean P_CheckAllTrigger(eachtime_t *eachtime) +{ + size_t i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (P_IsPlayerValid(i) && !eachtime->playersInArea[i]) + return false; + } + + return true; +} + void T_EachTimeThinker(eachtime_t *eachtime) { - size_t i, j; - sector_t *sec = NULL; - sector_t *targetsec = NULL; - INT32 secnum = -1; + size_t i; boolean oldPlayersInArea[MAXPLAYERS]; - boolean oldPlayersOnArea[MAXPLAYERS]; - boolean *oldPlayersArea; - boolean *playersArea; - boolean FOFsector = false; - boolean floortouch = false; - fixed_t bottomheight, topheight; - ffloor_t *rover; + sector_t *caller[MAXPLAYERS]; + boolean allPlayersChecked = false; + boolean allPlayersTrigger = false; mtag_t tag = Tag_FGet(&eachtime->sourceline->tags); for (i = 0; i < MAXPLAYERS; i++) { oldPlayersInArea[i] = eachtime->playersInArea[i]; - oldPlayersOnArea[i] = eachtime->playersOnArea[i]; - eachtime->playersInArea[i] = false; - eachtime->playersOnArea[i] = false; - } - - TAG_ITER_SECTORS(tag, secnum) - { - sec = §ors[secnum]; - - FOFsector = false; - - if (GETSECSPECIAL(sec->special, 2) == 3 || GETSECSPECIAL(sec->special, 2) == 5) - floortouch = true; - else if (GETSECSPECIAL(sec->special, 2) >= 1 && GETSECSPECIAL(sec->special, 2) <= 8) - floortouch = false; - else - continue; - - // Check the lines of this sector, to see if it is a FOF control sector. - for (i = 0; i < sec->linecount; i++) - { - INT32 targetsecnum = -1; - - if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) - continue; - - FOFsector = true; - - TAG_ITER_SECTORS(sec->lines[i]->args[0], targetsecnum) - { - targetsec = §ors[targetsecnum]; - - // Find the FOF corresponding to the control linedef - for (rover = targetsec->ffloors; rover; rover = rover->next) - { - if (rover->master == sec->lines[i]) - break; - } - - if (!rover) // This should be impossible, but don't complain if it is the case somehow - continue; - - if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there - continue; - - for (j = 0; j < MAXPLAYERS; j++) - { - if (!P_IsPlayerValid(j)) - continue; - - if (!P_IsMobjTouchingSector(players[j].mo, targetsec)) - continue; - - topheight = P_GetSpecialTopZ(players[j].mo, sec, targetsec); - bottomheight = P_GetSpecialBottomZ(players[j].mo, sec, targetsec); - - if (players[j].mo->z > topheight) - continue; - - if (players[j].mo->z + players[j].mo->height < bottomheight) - continue; - - if (floortouch && P_IsObjectOnGroundIn(players[j].mo, targetsec)) - eachtime->playersOnArea[j] = true; - else - eachtime->playersInArea[j] = true; - } - } - } - - if (!FOFsector) - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (!P_IsPlayerValid(i)) - continue; - - if (!P_IsMobjTouchingSector(players[i].mo, sec)) - continue; - - if (!(players[i].mo->subsector->sector == sec - || P_PlayerTouchingSectorSpecial(&players[i], 2, (GETSECSPECIAL(sec->special, 2))) == sec)) - continue; - - if (floortouch && P_IsObjectOnRealGround(players[i].mo, sec)) - eachtime->playersOnArea[i] = true; - else - eachtime->playersInArea[i] = true; - } - } - } - - // Check if a new player entered. - // If not, check if a player hit the floor. - // If either condition is true, execute. - if (floortouch) - { - playersArea = eachtime->playersOnArea; - oldPlayersArea = oldPlayersOnArea; - } - else - { - playersArea = eachtime->playersInArea; - oldPlayersArea = oldPlayersInArea; + caller[i] = P_IsPlayerValid(i) ? P_FindPlayerTrigger(&players[i], eachtime->sourceline) : NULL; + eachtime->playersInArea[i] = caller[i] != NULL; } // Easy check... nothing has changed - if (!memcmp(playersArea, oldPlayersArea, sizeof(boolean)*MAXPLAYERS)) + if (!memcmp(eachtime->playersInArea, oldPlayersInArea, sizeof(boolean)*MAXPLAYERS)) return; - // If sector has an "all players" trigger type, all players need to be in area - if (GETSECSPECIAL(sec->special, 2) == 2 || GETSECSPECIAL(sec->special, 2) == 3) - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (P_IsPlayerValid(i) && !playersArea[i]) - return; - } - } - // Trigger for every player who has entered (and exited, if triggerOnExit) for (i = 0; i < MAXPLAYERS; i++) { - if (playersArea[i] == oldPlayersArea[i]) + if (eachtime->playersInArea[i] == oldPlayersInArea[i]) continue; // If player has just left, check if still valid - if (!playersArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i))) + if (!eachtime->playersInArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i))) continue; + // If sector has an "all players" trigger type, all players need to be in area + if (caller[i] && (GETSECSPECIAL(caller[i]->special, 2) == 2 || GETSECSPECIAL(caller[i]->special, 2) == 3)) + { + if (!allPlayersChecked) + { + allPlayersChecked = true; + allPlayersTrigger = P_CheckAllTrigger(eachtime); + } + + if (!allPlayersTrigger) + continue; + } + CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", tag); // 03/08/14 -Monster Iestyn // No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever! // This should now run ONLY the stuff for eachtime->sourceline itself, instead of all trigger linedefs sharing the same tag. // Makes much more sense doing it this way, honestly. - P_RunTriggerLinedef(eachtime->sourceline, players[i].mo, sec); + P_RunTriggerLinedef(eachtime->sourceline, players[i].mo, caller[i]); if (!eachtime->sourceline->special) // this happens only for "Trigger on X calls" linedefs P_RemoveThinker(&eachtime->thinker); diff --git a/src/p_local.h b/src/p_local.h index 1fcd3050d..bbcd86b39 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -148,7 +148,6 @@ boolean P_PlayerShouldUseSpinHeight(player_t *player); boolean P_IsObjectInGoop(mobj_t *mo); boolean P_IsObjectOnGround(mobj_t *mo); -boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec); boolean P_InSpaceSector(mobj_t *mo); boolean P_InQuicksand(mobj_t *mo); boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff); diff --git a/src/p_saveg.c b/src/p_saveg.c index b17011837..bc9c31d64 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2012,7 +2012,6 @@ static void SaveEachTimeThinker(const thinker_t *th, const UINT8 type) for (i = 0; i < MAXPLAYERS; i++) { WRITECHAR(save_p, ht->playersInArea[i]); - WRITECHAR(save_p, ht->playersOnArea[i]); } WRITECHAR(save_p, ht->triggerOnExit); } @@ -3130,7 +3129,6 @@ static thinker_t* LoadEachTimeThinker(actionf_p1 thinker) for (i = 0; i < MAXPLAYERS; i++) { ht->playersInArea[i] = READCHAR(save_p); - ht->playersOnArea[i] = READCHAR(save_p); } ht->triggerOnExit = READCHAR(save_p); return &ht->thinker; diff --git a/src/p_spec.c b/src/p_spec.c index 02e48fab2..feab9f2b6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3886,12 +3886,12 @@ static boolean P_IsMobjTouchingPlane(mobj_t *mo, sector_t *sec, fixed_t floorz, return (floorallowed || ceilingallowed); } -static boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec) +boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec) { return P_IsMobjTouchingPlane(mo, sec, P_GetSpecialBottomZ(mo, sec, sec), P_GetSpecialTopZ(mo, sec, sec)); } -static boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *ffloor, sector_t *sec) +boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *ffloor, sector_t *sec) { fixed_t topheight = P_GetSpecialTopZ(mo, sectors + ffloor->secnum, sec); fixed_t bottomheight = P_GetSpecialBottomZ(mo, sectors + ffloor->secnum, sec); @@ -3909,7 +3909,7 @@ static boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *ffloor, sector_t *s } } -static boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec) +boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec) { if (!(po->flags & POF_TESTHEIGHT)) // Don't do height checking return true; diff --git a/src/p_spec.h b/src/p_spec.h index 0fdc216b9..5e79e9737 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -338,6 +338,10 @@ INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max); void P_SetupSignExit(player_t *player); boolean P_IsFlagAtBase(mobjtype_t flag); +boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec); +boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *ffloor, sector_t *sec); +boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec); + void P_SwitchWeather(INT32 weathernum); boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller); @@ -680,7 +684,6 @@ typedef struct thinker_t thinker; line_t *sourceline; // Source line of the thinker boolean playersInArea[MAXPLAYERS]; - boolean playersOnArea[MAXPLAYERS]; boolean triggerOnExit; } eachtime_t; diff --git a/src/p_user.c b/src/p_user.c index 9921ed078..4858c6ddd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1728,89 +1728,6 @@ boolean P_IsObjectOnGround(mobj_t *mo) return false; } -// -// P_IsObjectOnGroundIn -// -// Returns true if the player is -// on the ground in a specific sector. Takes reverse -// gravity and FOFs into account. -// -boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec) -{ - ffloor_t *rover; - - // Is the object in reverse gravity? - if (mo->eflags & MFE_VERTICALFLIP) - { - // Detect if the player is on the ceiling. - if (mo->z+mo->height >= P_GetSpecialTopZ(mo, sec, sec)) - return true; - // Otherwise, detect if the player is on the bottom of a FOF. - else - { - for (rover = sec->ffloors; rover; rover = rover->next) - { - // If the FOF doesn't exist, continue. - if (!(rover->flags & FF_EXISTS)) - continue; - - // If the FOF is configured to let the object through, continue. - if (!((rover->flags & FF_BLOCKPLAYER && mo->player) - || (rover->flags & FF_BLOCKOTHERS && !mo->player))) - continue; - - // If the the platform is intangible from below, continue. - if (rover->flags & FF_PLATFORM) - continue; - - // If the FOF is a water block, continue. (Unnecessary check?) - if (rover->flags & FF_SWIMMABLE) - continue; - - // Actually check if the player is on the suitable FOF. - if (mo->z+mo->height == P_GetSpecialBottomZ(mo, sectors + rover->secnum, sec)) - return true; - } - } - } - // Nope! - else - { - // Detect if the player is on the floor. - if (mo->z <= P_GetSpecialBottomZ(mo, sec, sec)) - return true; - // Otherwise, detect if the player is on the top of a FOF. - else - { - for (rover = sec->ffloors; rover; rover = rover->next) - { - // If the FOF doesn't exist, continue. - if (!(rover->flags & FF_EXISTS)) - continue; - - // If the FOF is configured to let the object through, continue. - if (!((rover->flags & FF_BLOCKPLAYER && mo->player) - || (rover->flags & FF_BLOCKOTHERS && !mo->player))) - continue; - - // If the the platform is intangible from above, continue. - if (rover->flags & FF_REVERSEPLATFORM) - continue; - - // If the FOF is a water block, continue. (Unnecessary check?) - if (rover->flags & FF_SWIMMABLE) - continue; - - // Actually check if the player is on the suitable FOF. - if (mo->z == P_GetSpecialTopZ(mo, sectors + rover->secnum, sec)) - return true; - } - } - } - - return false; -} - // // P_SetObjectMomZ // From 3cd56e456dc8dd52d185e0e5048feede9af34b18 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 7 Dec 2021 19:20:26 +0100 Subject: [PATCH 163/326] Rewrite pushable/mobj linedef executor trigger code --- src/p_mobj.c | 30 +------------- src/p_spec.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++----- src/p_spec.h | 2 + 3 files changed, 105 insertions(+), 37 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index fa1ed2443..2c6315271 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10048,15 +10048,7 @@ void P_MobjThinker(mobj_t *mobj) tmfloorthing = tmhitthing = NULL; // 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 = P_ThingOnSpecial3DFloor(mobj); - if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1) - { - mtag_t tag = Tag_FGet(&sec2->tags); - P_LinedefExecute(tag, mobj, sec2); - } - } + P_CheckMobjTrigger(mobj); if (mobj->scale != mobj->destscale) P_MobjScaleThink(mobj); // Slowly scale up/down to reach your destscale. @@ -10271,28 +10263,10 @@ boolean P_RailThinker(mobj_t *mobj) // Unquick, unoptimized function for pushables void P_PushableThinker(mobj_t *mobj) { - sector_t *sec; - I_Assert(mobj != NULL); I_Assert(!P_MobjWasRemoved(mobj)); - sec = mobj->subsector->sector; - - if (GETSECSPECIAL(sec->special, 2) == 1 && mobj->z == sec->floorheight) - { - mtag_t tag = Tag_FGet(&sec->tags); - P_LinedefExecute(tag, mobj, sec); - } - -// else if (GETSECSPECIAL(sec->special, 2) == 8) - { - sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj); - if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1) - { - mtag_t tag = Tag_FGet(&sec2->tags); - P_LinedefExecute(tag, mobj, sec2); - } - } + P_CheckPushableTrigger(mobj, mobj->subsector->sector); // it has to be pushable RIGHT NOW for this part to happen if (mobj->flags & MF_PUSHABLE && !(mobj->momx || mobj->momy)) diff --git a/src/p_spec.c b/src/p_spec.c index feab9f2b6..f4e0648f7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4811,7 +4811,7 @@ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) return NULL; } -#define TELEPORTED (player->mo->subsector->sector != originalsector) +#define TELEPORTED(mo) (mo->subsector->sector != originalsector) /** Checks if a player is standing on or is inside a 3D floor (e.g. water) and * applies any specials. @@ -4840,7 +4840,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) { P_ProcessSpecialSector(player, rover->master->frontsector, sector); - if TELEPORTED return; + if TELEPORTED(player->mo) return; } } } @@ -4874,7 +4874,7 @@ static void P_PlayerOnSpecialPolyobj(player_t *player, sector_t *sector) continue; P_ProcessSpecialSector(player, polysec, sector); - if TELEPORTED return; + if TELEPORTED(player->mo) return; } } @@ -4965,14 +4965,14 @@ void P_PlayerInSpecialSector(player_t *player) originalsector = player->mo->subsector->sector; P_PlayerOnSpecial3DFloor(player, originalsector); // Handle FOFs first. - if TELEPORTED return; + if TELEPORTED(player->mo) return; // Allow sector specials to be applied to polyobjects! P_PlayerOnSpecialPolyobj(player, originalsector); - if TELEPORTED return; + if TELEPORTED(player->mo) return; P_RunSpecialSectorCheck(player, originalsector); - if TELEPORTED return; + if TELEPORTED(player->mo) return; // Iterate through touching_sectorlist for SF_TRIGGERSPECIAL_TOUCH for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) @@ -4984,20 +4984,112 @@ void P_PlayerInSpecialSector(player_t *player) // Check 3D floors... P_PlayerOnSpecial3DFloor(player, loopsector); - if TELEPORTED return; + if TELEPORTED(player->mo) return; // Check polyobjects... P_PlayerOnSpecialPolyobj(player, loopsector); - if TELEPORTED return; + if TELEPORTED(player->mo) return; if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) continue; P_RunSpecialSectorCheck(player, loopsector); - if TELEPORTED return; + if TELEPORTED(player->mo) return; } } +static void P_CheckMobj3DFloorTrigger(mobj_t *mo) +{ + sector_t *originalsector = mo->subsector->sector; + ffloor_t *rover; + mtag_t tag; + + for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) + { + if (GETSECSPECIAL(rover->master->frontsector->special, 2) != 1) + continue; + + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!P_IsMobjTouching3DFloor(mo, rover, mo->subsector->sector)) + continue; + + tag = Tag_FGet(&rover->master->frontsector->tags); + P_LinedefExecute(tag, mo, rover->master->frontsector); + if TELEPORTED(mo) return; + } +} + +static void P_CheckMobjPolyobjTrigger(mobj_t *mo) +{ + sector_t *originalsector = mo->subsector->sector; + polyobj_t *po; + sector_t *polysec; + boolean touching = false; + boolean inside = false; + mtag_t tag; + + for (po = mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) + { + if (po->flags & POF_NOSPECIALS) + continue; + + polysec = po->lines[0]->backsector; + + if (!polysec->special) + continue; + + touching = (polysec->flags & SF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo); + inside = P_MobjInsidePolyobj(po, mo); + + if (!(inside || touching)) + continue; + + if (!P_IsMobjTouchingPolyobj(mo, po, polysec)) + continue; + + tag = Tag_FGet(&polysec->tags); + P_LinedefExecute(tag, mo, polysec); + if TELEPORTED(mo) return; + } +} + +void P_CheckPushableTrigger(mobj_t *mobj, sector_t *sec) +{ + sector_t *originalsector = mobj->subsector->sector; + + P_CheckMobj3DFloorTrigger(mobj); + if TELEPORTED(mobj) return; + + P_CheckMobjPolyobjTrigger(mobj); + if TELEPORTED(mobj) return; + + if (GETSECSPECIAL(sec->special, 2) == 1 && P_IsMobjTouchingSectorPlane(mobj, sec)) + { + mtag_t tag = Tag_FGet(&sec->tags); + P_LinedefExecute(tag, mobj, sec); + } +} + +void P_CheckMobjTrigger(mobj_t *mobj) +{ + sector_t *originalsector; + + if (!mobj->subsector) + return; + + originalsector = mobj->subsector->sector; + + if (GETSECSPECIAL(originalsector->special, 2) != 8) + return; + + P_CheckMobj3DFloorTrigger(mobj); + if TELEPORTED(mobj) return; + + P_CheckMobjPolyobjTrigger(mobj); +} + #undef TELEPORTED /** Animate planes, scroll walls, etc. and keeps track of level timelimit and exits if time is up. diff --git a/src/p_spec.h b/src/p_spec.h index 5e79e9737..50387fbd8 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -322,6 +322,8 @@ void P_SpawnSpecials(boolean fromnetsave); void P_UpdateSpecials(void); sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number); void P_PlayerInSpecialSector(player_t *player); +void P_CheckPushableTrigger(mobj_t *mobj, sector_t *sec); +void P_CheckMobjTrigger(mobj_t *mobj); void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector); fixed_t P_FindLowestFloorSurrounding(sector_t *sec); From c8cb09664714389ca82a886433027921472e6396 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 7 Dec 2021 21:39:45 +0100 Subject: [PATCH 164/326] "Floor touch" sector specials are no longer contaminated by "anywhere in sector" specials --- src/p_spec.c | 137 +++++++++++++++++---------------------------------- 1 file changed, 44 insertions(+), 93 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index f4e0648f7..bfaa97ba8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4192,7 +4192,7 @@ static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *rove S_StartSound(player->mo, sfxnum); } -static void P_ProcessExitSector(player_t *player, mtag_t sectag) +static void P_ProcessExitSector(player_t *player, boolean isTouching, mtag_t sectag) { INT32 lineindex; @@ -4202,9 +4202,10 @@ static void P_ProcessExitSector(player_t *player, mtag_t sectag) if (player->bot) return; - if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6) + if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap)) { - player->nightstime = 6; // Just let P_Ticker take care of the rest. + if (player->nightstime > 6 && isTouching) + player->nightstime = 6; // Just let P_Ticker take care of the rest. return; } @@ -4580,6 +4581,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers { INT32 section1, section2, section3, section4; mtag_t sectag = Tag_FGet(§or->tags); + boolean isTouching; + + if (!sector->special) + return; section1 = GETSECSPECIAL(sector->special, 1); section2 = GETSECSPECIAL(sector->special, 2); @@ -4600,37 +4605,38 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (section3 == 2 || section3 == 4) player->onconveyor = section3; + isTouching = roversector || P_IsMobjTouchingSectorPlane(player->mo, sector); + switch (section1) { case 1: // Damage (Generic) - if (roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) + if (isTouching) P_DamageMobj(player->mo, NULL, NULL, 1, 0); break; case 2: // Damage (Water) - if ((roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) && (player->powers[pw_underwater] || player->powers[pw_carry] == CR_NIGHTSMODE)) + if (isTouching && (player->powers[pw_underwater] || player->powers[pw_carry] == CR_NIGHTSMODE)) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_WATER); break; case 3: // Damage (Fire) - if (roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) + if (isTouching) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_FIRE); break; case 4: // Damage (Electrical) - if (roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) + if (isTouching) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_ELECTRIC); break; case 5: // Spikes - if (roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) + if (isTouching) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPIKE); break; case 6: // Death Pit (Camera Mod) case 7: // Death Pit (No Camera Mod) - if (roversector || P_IsMobjTouchingSectorPlane(player->mo, sector)) - { - if (player->quittime) - G_MovePlayerToSpawnOrStarpost(player - players); - else - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT); - } + if (!isTouching) + break; + if (player->quittime) + G_MovePlayerToSpawnOrStarpost(player - players); + else + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT); break; case 8: // Instant Kill if (player->quittime) @@ -4639,6 +4645,9 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); break; case 9: // Ring Drainer (Floor Touch) + if (!isTouching) + break; + /* FALLTHRU */ case 10: // Ring Drainer (No Floor Touch) if (leveltime % (TICRATE/2) == 0 && player->rings > 0) { @@ -4647,6 +4656,9 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers } break; case 11: // Special Stage Damage + if (!isTouching) + break; + if (player->exiting || player->bot) // Don't do anything for bots or players who have just finished break; @@ -4678,13 +4690,16 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers case 5: // Linedef executor case 6: // Linedef executor (7 Emeralds) case 7: // Linedef executor (NiGHTS Mare) + if ((section2 == 3 || section2 == 5) && !isTouching) + break; if (!player->bot) P_LinedefExecute(sectag, player->mo, sector); break; case 8: // Tells pushable things to check FOFs break; case 9: // Egg trap capsule - P_ProcessEggCapsule(player, sector); + if (roversector) + P_ProcessEggCapsule(player, sector); break; case 10: // Special Stage Time/Rings case 11: // Custom Gravity @@ -4700,7 +4715,8 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers case 4: // Conveyor Belt break; case 5: // Speed pad - P_ProcessSpeedPad(player, sector, roversector, sectag); + if (isTouching) + P_ProcessSpeedPad(player, sector, roversector, sectag); break; case 6: // Unused case 7: // Unused @@ -4728,13 +4744,15 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers break; } case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return - P_ProcessExitSector(player, sectag); + P_ProcessExitSector(player, isTouching, sectag); break; case 3: // Red Team's Base - P_ProcessTeamBase(player, true); + if (isTouching) + P_ProcessTeamBase(player, true); break; case 4: // Blue Team's Base - P_ProcessTeamBase(player, false); + if (isTouching) + P_ProcessTeamBase(player, false); break; case 5: // Fan sector player->mo->momz += mobjinfo[MT_FAN].mass/4; @@ -4751,6 +4769,8 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_DoSuperTransformation(player, true); break; case 7: // Make player spin + if (!isTouching) + break; if (!(player->pflags & PF_SPINNING)) { player->pflags |= PF_SPINNING; @@ -4772,7 +4792,8 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_ProcessFinishLine(player); break; case 11: // Rope hang - P_ProcessRopeHang(player, sector, sectag); + if (isTouching) + P_ProcessRopeHang(player, sector, sectag); break; case 12: // Camera noclip case 13: // Unused @@ -4878,76 +4899,6 @@ static void P_PlayerOnSpecialPolyobj(player_t *player, sector_t *sector) } } -// -// P_RunSpecialSectorCheck -// -// Helper function to P_PlayerInSpecialSector -// -static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector) -{ - boolean nofloorneeded = false; - - if (!sector->special) // nothing special, exit - return; - - if (GETSECSPECIAL(sector->special, 2) == 9) // Egg trap capsule -- should only be for 3dFloors! - return; - - // The list of specials that activate without floor touch - // Check Section 1 - switch(GETSECSPECIAL(sector->special, 1)) - { - case 2: // Damage (water) - case 8: // Instant kill - case 10: // Ring drainer that doesn't require floor touch - case 12: // Space countdown - nofloorneeded = true; - break; - } - - // Check Section 2 - switch(GETSECSPECIAL(sector->special, 2)) - { - case 2: // Linedef executor (All players needed) - case 4: // Linedef executor - case 6: // Linedef executor (7 Emeralds) - case 7: // Linedef executor (NiGHTS Mare) - nofloorneeded = true; - break; - } - - // Check Section 3 -/* switch(GETSECSPECIAL(sector->special, 3)) - { - - }*/ - - // Check Section 4 - switch(GETSECSPECIAL(sector->special, 4)) - { - case 2: // Level Exit / GOAL Sector / Flag Return - if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap)) - { - // Special stage GOAL sector - // requires touching floor. - break; - } - /* FALLTHRU */ - - case 1: // Starpost activator - case 5: // Fan sector - case 6: // Super Sonic Transform - case 8: // Zoom Tube Start - case 9: // Zoom Tube End - case 10: // Finish line - nofloorneeded = true; - break; - } - - if (nofloorneeded || P_IsMobjTouchingSectorPlane(player->mo, sector)) - P_ProcessSpecialSector(player, sector, NULL); -} - /** Checks if the player is in a special sector or FOF and apply any specials. * * \param player Player to check. @@ -4971,7 +4922,7 @@ void P_PlayerInSpecialSector(player_t *player) P_PlayerOnSpecialPolyobj(player, originalsector); if TELEPORTED(player->mo) return; - P_RunSpecialSectorCheck(player, originalsector); + P_ProcessSpecialSector(player, originalsector, NULL); if TELEPORTED(player->mo) return; // Iterate through touching_sectorlist for SF_TRIGGERSPECIAL_TOUCH @@ -4993,7 +4944,7 @@ void P_PlayerInSpecialSector(player_t *player) if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) continue; - P_RunSpecialSectorCheck(player, loopsector); + P_ProcessSpecialSector(player, loopsector, NULL); if TELEPORTED(player->mo) return; } } From 1a2b0d24ab845d67e27fc7bf75a4c569e01c660d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 8 Dec 2021 20:29:10 +0100 Subject: [PATCH 165/326] Make all players triggers work if players are in different sectors with the same tag --- src/p_floor.c | 129 ------------------------------------ src/p_spec.c | 177 +++++++++++++++++++++++++++++++++++--------------- src/p_spec.h | 1 + 3 files changed, 125 insertions(+), 182 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index 551469a29..fabc8de28 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1272,135 +1272,6 @@ void T_NoEnemiesSector(noenemies_t *nobaddies) P_RemoveThinker(&nobaddies->thinker); } -static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line_t *sourceline) -{ - ffloor_t *rover; - - for (rover = sector->ffloors; rover; rover = rover->next) - { - if (GETSECSPECIAL(rover->master->frontsector->special, 2) < 2 || GETSECSPECIAL(rover->master->frontsector->special, 2) > 7) - continue; - - if (!(rover->flags & FF_EXISTS)) - continue; - - if (!Tag_Find(&sourceline->tags, Tag_FGet(&rover->master->frontsector->tags))) - return false; - - if (!P_IsMobjTouching3DFloor(player->mo, rover, sector)) - continue; - - // This FOF has the special we're looking for, but are we allowed to touch it? - if (sector == player->mo->subsector->sector - || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) - return rover->master->frontsector; - } - - return NULL; -} - -static sector_t *P_CheckPolyobjTriggers(player_t *player, line_t *sourceline) -{ - polyobj_t *po; - sector_t *polysec; - boolean touching = false; - boolean inside = false; - - for (po = player->mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) //TODO - { - if (po->flags & POF_NOSPECIALS) - continue; - - polysec = po->lines[0]->backsector; - - if (GETSECSPECIAL(polysec->special, 2) < 2 || GETSECSPECIAL(polysec->special, 2) > 7) - continue; - - if (!Tag_Find(&sourceline->tags, Tag_FGet(&polysec->tags))) - return false; - - touching = (polysec->flags & SF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); - inside = P_MobjInsidePolyobj(po, player->mo); - - if (!(inside || touching)) - continue; - - if (!P_IsMobjTouchingPolyobj(player->mo, po, polysec)) - continue; - - return polysec; - } - - return NULL; -} - -static boolean P_CheckSectorTriggers(player_t *player, sector_t *sector, line_t *sourceline) -{ - if (GETSECSPECIAL(sector->special, 2) < 2 || GETSECSPECIAL(sector->special, 2) > 7) - return false; - - if (!Tag_Find(&sourceline->tags, Tag_FGet(§or->tags))) - return false; - - if (GETSECSPECIAL(sector->special, 2) != 3 && GETSECSPECIAL(sector->special, 2) != 5) - return true; // "Anywhere in sector" types - - return P_IsMobjTouchingSectorPlane(player->mo, sector); - -} - -static sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) -{ - sector_t *originalsector; - sector_t *loopsector; - msecnode_t *node; - sector_t *caller; - - if (!player->mo) - return NULL; - - originalsector = player->mo->subsector->sector; - - caller = P_Check3DFloorTriggers(player, originalsector, sourceline); // Handle FOFs first. - - if (caller) - return caller; - - // Allow sector specials to be applied to polyobjects! - caller = P_CheckPolyobjTriggers(player, sourceline); - - if (caller) - return caller; - - if (P_CheckSectorTriggers(player, originalsector, sourceline)) - return originalsector; - - // Iterate through touching_sectorlist for SF_TRIGGERSPECIAL_TOUCH - for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - loopsector = node->m_sector; - - if (loopsector == originalsector) // Don't duplicate - continue; - - // Check 3D floors... - caller = P_Check3DFloorTriggers(player, loopsector, sourceline); // Handle FOFs first. - - if (caller) - return caller; - - //TODO: Check polyobjects in loopsector - - if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) - continue; - - if (P_CheckSectorTriggers(player, loopsector, sourceline)) - return loopsector; - } - - return false; -} - static boolean P_CheckAllTrigger(eachtime_t *eachtime) { size_t i; diff --git a/src/p_spec.c b/src/p_spec.c index bfaa97ba8..49ba3adaf 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3998,39 +3998,142 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n return NULL; } -// -// P_ThingIsOnThe3DFloor -// -// This checks whether the mobj is on/in the FOF we want it to be at -// Needed for the "All players" trigger sector specials only -// -static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *targetsec) +static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line_t *sourceline) { ffloor_t *rover; - if (!mo->player) // should NEVER happen - return false; - - for (rover = targetsec->ffloors; rover; rover = rover->next) + for (rover = sector->ffloors; rover; rover = rover->next) { - if (rover->master->frontsector != sector) + if (GETSECSPECIAL(rover->master->frontsector->special, 2) < 2 || GETSECSPECIAL(rover->master->frontsector->special, 2) > 7) continue; - // we're assuming the FOF existed when the first player touched it - //if (!(rover->flags & FF_EXISTS)) - // return false; + if (!(rover->flags & FF_EXISTS)) + continue; - return P_IsMobjTouching3DFloor(mo, rover, targetsec); + if (!Tag_Find(&sourceline->tags, Tag_FGet(&rover->master->frontsector->tags))) + return false; + + if (!P_IsMobjTouching3DFloor(player->mo, rover, sector)) + continue; + + // This FOF has the special we're looking for, but are we allowed to touch it? + if (sector == player->mo->subsector->sector + || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + return rover->master->frontsector; + } + + return NULL; +} + +static sector_t *P_CheckPolyobjTriggers(player_t *player, line_t *sourceline) +{ + polyobj_t *po; + sector_t *polysec; + boolean touching = false; + boolean inside = false; + + for (po = player->mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) //TODO + { + if (po->flags & POF_NOSPECIALS) + continue; + + polysec = po->lines[0]->backsector; + + if (GETSECSPECIAL(polysec->special, 2) < 2 || GETSECSPECIAL(polysec->special, 2) > 7) + continue; + + if (!Tag_Find(&sourceline->tags, Tag_FGet(&polysec->tags))) + return false; + + touching = (polysec->flags & SF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); + inside = P_MobjInsidePolyobj(po, player->mo); + + if (!(inside || touching)) + continue; + + if (!P_IsMobjTouchingPolyobj(player->mo, po, polysec)) + continue; + + return polysec; + } + + return NULL; +} + +static boolean P_CheckSectorTriggers(player_t *player, sector_t *sector, line_t *sourceline) +{ + if (GETSECSPECIAL(sector->special, 2) < 2 || GETSECSPECIAL(sector->special, 2) > 7) + return false; + + if (!Tag_Find(&sourceline->tags, Tag_FGet(§or->tags))) + return false; + + if (GETSECSPECIAL(sector->special, 2) != 3 && GETSECSPECIAL(sector->special, 2) != 5) + return true; // "Anywhere in sector" types + + return P_IsMobjTouchingSectorPlane(player->mo, sector); + +} + +sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) +{ + sector_t *originalsector; + sector_t *loopsector; + msecnode_t *node; + sector_t *caller; + + if (!player->mo) + return NULL; + + originalsector = player->mo->subsector->sector; + + caller = P_Check3DFloorTriggers(player, originalsector, sourceline); // Handle FOFs first. + + if (caller) + return caller; + + // Allow sector specials to be applied to polyobjects! + caller = P_CheckPolyobjTriggers(player, sourceline); + + if (caller) + return caller; + + if (P_CheckSectorTriggers(player, originalsector, sourceline)) + return originalsector; + + // Iterate through touching_sectorlist for SF_TRIGGERSPECIAL_TOUCH + for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + loopsector = node->m_sector; + + if (loopsector == originalsector) // Don't duplicate + continue; + + // Check 3D floors... + caller = P_Check3DFloorTriggers(player, loopsector, sourceline); // Handle FOFs first. + + if (caller) + return caller; + + //TODO: Check polyobjects in loopsector + + if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + continue; + + if (P_CheckSectorTriggers(player, loopsector, sourceline)) + return loopsector; } return false; } /// \todo check continues for proper splitscreen support? -static boolean P_DoAllPlayersTrigger(sector_t *sector, sector_t *roversector, boolean floortouch) +static boolean P_DoAllPlayersTrigger(mtag_t sectag) { INT32 i; - msecnode_t *node; + line_t dummyline; + dummyline.tags.count = 1; + dummyline.tags.tags = §ag; for (i = 0; i < MAXPLAYERS; i++) { @@ -4044,40 +4147,8 @@ static boolean P_DoAllPlayersTrigger(sector_t *sector, sector_t *roversector, bo continue; if (G_CoopGametype() && players[i].lives <= 0) continue; - if (roversector) - { - if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) - { - for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (P_ThingIsOnThe3DFloor(players[i].mo, sector, node->m_sector)) - break; - } - if (!node) - return false; - } - else if (players[i].mo->subsector && !P_ThingIsOnThe3DFloor(players[i].mo, sector, players[i].mo->subsector->sector)) // this function handles basically everything for us lmao - return false; - } - else - { - if (players[i].mo->subsector->sector != sector) - { - if (!(sector->flags & SF_TRIGGERSPECIAL_TOUCH)) - return false; - - for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (node->m_sector == sector) - break; - } - if (!node) - return false; - } - - if (floortouch && !P_IsMobjTouchingSectorPlane(players[i].mo, sector)) - return false; - } + if (!P_FindPlayerTrigger(&players[i], &dummyline)) + return false; } return true; @@ -4683,7 +4754,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers break; case 2: // Linedef executor requires all players present+doesn't require touching floor case 3: // Linedef executor requires all players present - if (!P_DoAllPlayersTrigger(sector, roversector, section2 == 3)) + if (!P_DoAllPlayersTrigger(sectag)) break; /* FALLTHRU */ case 4: // Linedef executor that doesn't require touching floor diff --git a/src/p_spec.h b/src/p_spec.h index 50387fbd8..79cd4a6f4 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -324,6 +324,7 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n void P_PlayerInSpecialSector(player_t *player); void P_CheckPushableTrigger(mobj_t *mobj, sector_t *sec); void P_CheckMobjTrigger(mobj_t *mobj); +sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline); void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector); fixed_t P_FindLowestFloorSurrounding(sector_t *sec); From 060bc5fde06e9e7b7b039e23e0cc4d6f85646297 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 8 Dec 2021 21:07:26 +0100 Subject: [PATCH 166/326] Replace P_ThingOnSpecial3DFloor with the more versatile P_MobjTouchingSectorSpecial --- src/lua_baselib.c | 26 +++---- src/p_mobj.c | 6 +- src/p_spec.c | 177 ++++++++++++++++++++++++---------------------- src/p_spec.h | 3 +- 4 files changed, 110 insertions(+), 102 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index f51143556..d64f8abd2 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2202,6 +2202,19 @@ static int lib_pExplodeMissile(lua_State *L) return 0; } +static int lib_pMobjTouchingSectorSpecial(lua_State *L) +{ + mobj_t *mo = *((mobj_t**)luaL_checkudata(L, 1, META_MOBJ)); + INT32 section = (INT32)luaL_checkinteger(L, 2); + INT32 number = (INT32)luaL_checkinteger(L, 3); + //HUDSAFE + INLEVEL + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + LUA_PushUserdata(L, P_MobjTouchingSectorSpecial(mo, section, number), META_SECTOR); + return 1; +} + static int lib_pPlayerTouchingSectorSpecial(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -2353,17 +2366,6 @@ static int lib_pFadeLight(lua_State *L) return 0; } -static int lib_pThingOnSpecial3DFloor(lua_State *L) -{ - mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - NOHUD - INLEVEL - if (!mo) - return LUA_ErrInvalid(L, "mobj_t"); - LUA_PushUserdata(L, P_ThingOnSpecial3DFloor(mo), META_SECTOR); - return 1; -} - static int lib_pIsFlagAtBase(lua_State *L) { mobjtype_t flag = luaL_checkinteger(L, 1); @@ -4056,6 +4058,7 @@ static luaL_Reg lib[] = { {"P_SetMobjStateNF",lib_pSetMobjStateNF}, {"P_DoSuperTransformation",lib_pDoSuperTransformation}, {"P_ExplodeMissile",lib_pExplodeMissile}, + {"P_MobjTouchingSectorSpecial",lib_pMobjTouchingSectorSpecial}, {"P_PlayerTouchingSectorSpecial",lib_pPlayerTouchingSectorSpecial}, {"P_FindLowestFloorSurrounding",lib_pFindLowestFloorSurrounding}, {"P_FindHighestFloorSurrounding",lib_pFindHighestFloorSurrounding}, @@ -4068,7 +4071,6 @@ static luaL_Reg lib[] = { {"P_LinedefExecute",lib_pLinedefExecute}, {"P_SpawnLightningFlash",lib_pSpawnLightningFlash}, {"P_FadeLight",lib_pFadeLight}, - {"P_ThingOnSpecial3DFloor",lib_pThingOnSpecial3DFloor}, {"P_IsFlagAtBase",lib_pIsFlagAtBase}, {"P_SetupLevelSky",lib_pSetupLevelSky}, {"P_SetSkyboxMobj",lib_pSetSkyboxMobj}, diff --git a/src/p_mobj.c b/src/p_mobj.c index 2c6315271..d0af3112e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9611,13 +9611,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) 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)) + if (P_MobjTouchingSectorSpecial(mobj, 4, 2)) mobj->fuse = 1; // Return to base. 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 diff --git a/src/p_spec.c b/src/p_spec.c index 49ba3adaf..265cba2b5 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3926,6 +3926,99 @@ boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec) } } +static sector_t *P_MobjTouching3DFloorSpecial(mobj_t *mo, sector_t *sector, INT32 section, INT32 number) +{ + ffloor_t *rover; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (GETSECSPECIAL(rover->master->frontsector->special, section) != number) + continue; + + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!P_IsMobjTouching3DFloor(mo, rover, sector)) + continue; + + // This FOF has the special we're looking for, but are we allowed to touch it? + if (sector == mo->subsector->sector + || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + return rover->master->frontsector; + } + + return NULL; +} + +static sector_t *P_MobjTouchingPolyobjSpecial(mobj_t *mo, INT32 section, INT32 number) +{ + polyobj_t *po; + sector_t *polysec; + boolean touching = false; + boolean inside = false; + + for (po = mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) + { + if (po->flags & POF_NOSPECIALS) + continue; + + polysec = po->lines[0]->backsector; + + if (GETSECSPECIAL(polysec->special, section) != number) + continue; + + touching = (polysec->flags & SF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo); + inside = P_MobjInsidePolyobj(po, mo); + + if (!(inside || touching)) + continue; + + if (!P_IsMobjTouchingPolyobj(mo, po, polysec)) + continue; + + return polysec; + } + + return NULL; +} + +sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number) +{ + msecnode_t *node; + sector_t *result; + + result = P_MobjTouching3DFloorSpecial(mo, mo->subsector->sector, section, number); + if (result) + return result; + + result = P_MobjTouchingPolyobjSpecial(mo, section, number); + if (result) + return result; + + if (GETSECSPECIAL(mo->subsector->sector->special, section) == number) + return mo->subsector->sector; + + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (node->m_sector == mo->subsector->sector) // Don't duplicate + continue; + + result = P_MobjTouching3DFloorSpecial(mo, node->m_sector, section, number); + if (result) + return result; + + //TODO: Check polyobjects in node->m_sector + + if (!(node->m_sector->flags & SF_TRIGGERSPECIAL_TOUCH)) + continue; + + if (GETSECSPECIAL(mo->subsector->sector->special, section) == number) + return node->m_sector; + } + + return NULL; +} + // // P_PlayerTouchingSectorSpecial // @@ -3939,63 +4032,10 @@ boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec) // sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number) { - msecnode_t *node; - ffloor_t *rover; - if (!player->mo) return NULL; - // Check default case first - if (GETSECSPECIAL(player->mo->subsector->sector->special, section) == number) - return player->mo->subsector->sector; - - // Hmm.. maybe there's a FOF that has it... - for (rover = player->mo->subsector->sector->ffloors; rover; rover = rover->next) - { - if (GETSECSPECIAL(rover->master->frontsector->special, section) != number) - continue; - - if (!(rover->flags & FF_EXISTS)) - continue; - - if (!P_IsMobjTouching3DFloor(player->mo, rover, player->mo->subsector->sector)) - continue; - - // This FOF has the special we're looking for! - return rover->master->frontsector; - } - - for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (GETSECSPECIAL(node->m_sector->special, section) == number) - { - // This sector has the special we're looking for, but - // are we allowed to touch it? - if (node->m_sector == player->mo->subsector->sector - || (node->m_sector->flags & SF_TRIGGERSPECIAL_TOUCH)) - return node->m_sector; - } - - // Hmm.. maybe there's a FOF that has it... - for (rover = node->m_sector->ffloors; rover; rover = rover->next) - { - if (GETSECSPECIAL(rover->master->frontsector->special, section) != number) - continue; - - if (!(rover->flags & FF_EXISTS)) - continue; - - if (!P_IsMobjTouching3DFloor(player->mo, rover, node->m_sector)) - continue; - - // This FOF has the special we're looking for, but are we allowed to touch it? - if (node->m_sector == player->mo->subsector->sector - || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) - return rover->master->frontsector; - } - } - - return NULL; + return P_MobjTouchingSectorSpecial(player->mo, section, number); } static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line_t *sourceline) @@ -4874,35 +4914,6 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers } } -/** Checks if an object is standing on or is inside a special 3D floor. - * If so, the sector is returned. - * - * \param mo Object to check. - * \return Pointer to the sector with a special type, or NULL if no special 3D - * floors are being contacted. - * \sa P_PlayerOnSpecial3DFloor - */ -sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) -{ - ffloor_t *rover; - - for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) - { - if (!rover->master->frontsector->special) - continue; - - if (!(rover->flags & FF_EXISTS)) - continue; - - if (!P_IsMobjTouching3DFloor(mo, rover, mo->subsector->sector)) - continue; - - return rover->master->frontsector; - } - - return NULL; -} - #define TELEPORTED(mo) (mo->subsector->sector != originalsector) /** Checks if a player is standing on or is inside a 3D floor (e.g. water) and diff --git a/src/p_spec.h b/src/p_spec.h index 79cd4a6f4..2ff2cd64c 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -320,6 +320,7 @@ void P_SpawnSpecials(boolean fromnetsave); // every tic void P_UpdateSpecials(void); +sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number); sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number); void P_PlayerInSpecialSector(player_t *player); void P_CheckPushableTrigger(mobj_t *mobj, sector_t *sec); @@ -922,6 +923,4 @@ void T_PlaneDisplace(planedisplace_t *pd); void P_CalcHeight(player_t *player); -sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo); - #endif From 44434a64d1e92b82d02bab4bd354c49dceb782e0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 07:10:16 +0100 Subject: [PATCH 167/326] Refactor P_RunTriggerLinedef --- src/p_spec.c | 476 +++++++++++++++++++++++++-------------------------- 1 file changed, 233 insertions(+), 243 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 265cba2b5..ed2f9eb97 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1501,263 +1501,109 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) return true; } -/** Used by P_LinedefExecute to check a trigger linedef's conditions - * The linedef executor specials in the trigger linedef's sector are run if all conditions are met. - * Return false cancels P_LinedefExecute, this happens if a condition is not met. - * - * \param triggerline Trigger linedef to check conditions for; should NEVER be NULL. - * \param actor Object initiating the action; should not be NULL. - * \param caller Sector in which the action was started. May be NULL. - * \sa P_ProcessLineSpecial, P_LinedefExecute - */ -boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller) +static boolean P_CheckPlayerMare(line_t *triggerline, INT32 targetmare) { - sector_t *ctlsector; - fixed_t dist = P_AproxDistance(triggerline->dx, triggerline->dy)>>FRACBITS; - size_t i, linecnt, sectori; - INT16 specialtype = triggerline->special; + UINT8 mare; - ///////////////////////////////////////////////// - // Distance-checking/sector trigger conditions // - ///////////////////////////////////////////////// + if (!(maptol & TOL_NIGHTS)) + return false; - // Linetypes 303 and 304 require a specific - // number, or minimum or maximum, of rings. - if (specialtype == 303 || specialtype == 304) + mare = P_FindLowestMare(); + + if (triggerline->flags & ML_NOCLIMB) + return mare <= targetmare; + + if (triggerline->flags & ML_BLOCKMONSTERS) + return mare >= targetmare; + + return mare == targetmare; +} + +static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor, INT32 targetrings) +{ + INT32 rings = 0; + size_t i; + + // With the passuse flag, count all player's + // rings. + if (triggerline->flags & ML_EFFECT4) { - fixed_t rings = 0; - - // With the passuse flag, count all player's - // rings. - if (triggerline->flags & ML_EFFECT4) + for (i = 0; i < MAXPLAYERS; i++) { - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; + if (!playeringame[i] || players[i].spectator) + continue; - if (!players[i].mo || ((maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings) <= 0) - continue; + if (!players[i].mo || ((maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings) <= 0) + continue; - rings += (maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings; - } - } - else - { - if (!(actor && actor->player)) - return false; // no player to count rings from here, sorry - - rings = (maptol & TOL_NIGHTS) ? actor->player->spheres : actor->player->rings; - } - - if (triggerline->flags & ML_NOCLIMB) - { - if (rings > dist) - return false; - } - else if (triggerline->flags & ML_BLOCKMONSTERS) - { - if (rings < dist) - return false; - } - else - { - if (rings != dist) - return false; + rings += (maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings; } } - else if (specialtype >= 314 && specialtype <= 315) + else { - msecnode_t *node; - mobj_t *mo; - INT32 numpush = 0; - INT32 numneeded = dist; + if (!(actor && actor->player)) + return false; // no player to count rings from here, sorry - if (!caller) - return false; // we need a calling sector to find pushables in, silly! - - // Count the pushables in this sector - node = caller->touching_thinglist; // things touching this sector - while (node) - { - mo = node->m_thing; - if ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse)) - numpush++; - node = node->m_thinglist_next; - } - - if (triggerline->flags & ML_NOCLIMB) // Need at least or more - { - if (numpush < numneeded) - return false; - } - else if (triggerline->flags & ML_EFFECT4) // Need less than - { - if (numpush >= numneeded) - return false; - } - else // Need exact - { - if (numpush != numneeded) - return false; - } - } - else if (caller) - { - if (GETSECSPECIAL(caller->special, 2) == 6) - { - if (!(ALL7EMERALDS(emeralds))) - return false; - } - else if (GETSECSPECIAL(caller->special, 2) == 7) - { - UINT8 mare; - - if (!(maptol & TOL_NIGHTS)) - return false; - - mare = P_FindLowestMare(); - - if (triggerline->flags & ML_NOCLIMB) - { - if (!(mare <= dist)) - return false; - } - else if (triggerline->flags & ML_BLOCKMONSTERS) - { - if (!(mare >= dist)) - return false; - } - else - { - if (!(mare == dist)) - return false; - } - } - // If we were not triggered by a sector type especially for the purpose, - // a Linedef Executor linedef trigger is not handling sector triggers properly, return. - - else if ((!GETSECSPECIAL(caller->special, 2) || GETSECSPECIAL(caller->special, 2) > 7) && (specialtype > 322)) - { - CONS_Alert(CONS_WARNING, - M_GetText("Linedef executor trigger isn't handling sector triggers properly!\nspecialtype = %d, if you are not a dev, report this warning instance\nalong with the wad that caused it!\n"), - specialtype); - return false; - } + rings = (maptol & TOL_NIGHTS) ? actor->player->spheres : actor->player->rings; } - ////////////////////////////////////// - // Miscellaneous trigger conditions // - ////////////////////////////////////// + if (triggerline->flags & ML_NOCLIMB) + return rings <= targetrings; - switch (specialtype) + if (triggerline->flags & ML_BLOCKMONSTERS) + return rings >= targetrings; + + return rings == targetrings; +} + +static boolean P_CheckPushables(line_t *triggerline, sector_t *caller, INT32 targetpushables) +{ + msecnode_t *node; + mobj_t *mo; + INT32 numpushables = 0; + + if (!caller) + return false; // we need a calling sector to find pushables in, silly! + + // Count the pushables in this sector + for (node = caller->touching_thinglist; node; node = node->m_thinglist_next) { - case 305: // continuous - case 306: // each time - case 307: // once - if (!(actor && actor->player && actor->player->charability == dist/10)) - return false; - break; - case 309: // continuous - case 310: // each time - // Only red team members can activate this. - if (!(actor && actor->player && actor->player->ctfteam == 1)) - return false; - break; - case 311: // continuous - case 312: // each time - // Only blue team members can activate this. - if (!(actor && actor->player && actor->player->ctfteam == 2)) - return false; - break; - case 317: // continuous - case 318: // once - { // Unlockable triggers required - INT32 trigid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS); - - if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) - return false; - else if (trigid < 0 || trigid > 31) // limited by 32 bit variable - { - CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", triggerline->sidenum[0], trigid); - return false; - } - else if (!(unlocktriggers & (1 << trigid))) - return false; - } - break; - case 319: // continuous - case 320: // once - { // An unlockable itself must be unlocked! - INT32 unlockid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS); - - if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) - return false; - else if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count - { - CONS_Debug(DBG_GAMELOGIC, "Unlockable check (sidedef %hu): bad unlockable ID %d\n", triggerline->sidenum[0], unlockid); - return false; - } - else if (!(unlockables[unlockid-1].unlocked)) - return false; - } - break; - case 321: // continuous - case 322: // each time - // decrement calls left before triggering - if (triggerline->callcount > 0) - { - if (--triggerline->callcount > 0) - return false; - } - break; - case 323: // nightserize - case 325: // denightserize - case 327: // nights lap - case 329: // nights egg capsule touch - if (!P_CheckNightsTriggerLine(triggerline, actor)) - return false; - break; - case 331: // continuous - case 332: // each time - case 333: // once - if (!(actor && actor->player && ((stricmp(triggerline->text, skins[actor->player->skin].name) == 0) ^ ((triggerline->flags & ML_NOCLIMB) == ML_NOCLIMB)))) - return false; - break; - case 334: // object dye - continuous - case 335: // object dye - each time - case 336: // object dye - once - { - INT32 triggercolor = (INT32)sides[triggerline->sidenum[0]].toptexture; - UINT16 color = (actor->player ? actor->player->powers[pw_dye] : actor->color); - boolean invert = (triggerline->flags & ML_NOCLIMB ? true : false); - - if (invert ^ (triggercolor != color)) - return false; - } - default: - break; + mo = node->m_thing; + if ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse)) + numpushables++; } - ///////////////////////////////// - // Processing linedef specials // - ///////////////////////////////// + if (triggerline->flags & ML_NOCLIMB) + return numpushables >= targetpushables; - ctlsector = triggerline->frontsector; - sectori = (size_t)(ctlsector - sectors); - linecnt = ctlsector->linecount; + if (triggerline->flags & ML_EFFECT4) + return numpushables <= targetpushables; + + return numpushables == targetpushables; +} + +static void P_ActivateLinedefExecutor(line_t *line, mobj_t *actor, sector_t *caller) +{ + if (line->special < 400 || line->special >= 500) + return; + + if (line->executordelay) + P_AddExecutorDelay(line, actor, caller); + else + P_ProcessLineSpecial(line, actor, caller); +} + +static boolean P_ActivateLinedefExecutorsInSector(line_t *triggerline, mobj_t *actor, sector_t *caller) +{ + sector_t *ctlsector = triggerline->frontsector; + size_t sectori = (size_t)(ctlsector - sectors); + size_t linecnt = ctlsector->linecount; + size_t i; if (triggerline->flags & ML_EFFECT5) // disregard order for efficiency { for (i = 0; i < linecnt; i++) - if (ctlsector->lines[i]->special >= 400 - && ctlsector->lines[i]->special < 500) - { - if (ctlsector->lines[i]->executordelay) - P_AddExecutorDelay(ctlsector->lines[i], actor, caller); - else - P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); - } + P_ActivateLinedefExecutor(ctlsector->lines[i], actor, caller); } else // walk around the sector in a defined order { @@ -1838,17 +1684,161 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (i == masterlineindex) break; - if (ctlsector->lines[i]->special >= 400 - && ctlsector->lines[i]->special < 500) - { - if (ctlsector->lines[i]->executordelay) - P_AddExecutorDelay(ctlsector->lines[i], actor, caller); - else - P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); - } + P_ActivateLinedefExecutor(ctlsector->lines[i], actor, caller); } } + return true; +} + +/** Used by P_LinedefExecute to check a trigger linedef's conditions + * The linedef executor specials in the trigger linedef's sector are run if all conditions are met. + * Return false cancels P_LinedefExecute, this happens if a condition is not met. + * + * \param triggerline Trigger linedef to check conditions for; should NEVER be NULL. + * \param actor Object initiating the action; should not be NULL. + * \param caller Sector in which the action was started. May be NULL. + * \sa P_ProcessLineSpecial, P_LinedefExecute + */ +boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller) +{ + fixed_t dist = P_AproxDistance(triggerline->dx, triggerline->dy)>>FRACBITS; + INT16 specialtype = triggerline->special; + + //////////////////////// + // Trigger conditions // + //////////////////////// + + if (caller) + { + if (GETSECSPECIAL(caller->special, 2) == 6) + { + if (!(ALL7EMERALDS(emeralds))) + return false; + } + else if (GETSECSPECIAL(caller->special, 2) == 7) + { + if (!P_CheckPlayerMare(triggerline, dist)) + return false; + } + // If we were not triggered by a sector type especially for the purpose, + // a Linedef Executor linedef trigger is not handling sector triggers properly, return. + + else if ((!GETSECSPECIAL(caller->special, 2) || GETSECSPECIAL(caller->special, 2) > 7) && (specialtype > 322)) + { + CONS_Alert(CONS_WARNING, + M_GetText("Linedef executor trigger isn't handling sector triggers properly!\nspecialtype = %d, if you are not a dev, report this warning instance\nalong with the wad that caused it!\n"), + specialtype); + return false; + } + } + + switch (specialtype) + { + case 303: // continuous + case 304: // once + if (!P_CheckPlayerRings(triggerline, actor, dist)) + return false; + break; + case 305: // continuous + case 306: // each time + case 307: // once + if (!(actor && actor->player && actor->player->charability == dist/10)) + return false; + break; + case 309: // continuous + case 310: // each time + // Only red team members can activate this. + if (!(actor && actor->player && actor->player->ctfteam == 1)) + return false; + break; + case 311: // continuous + case 312: // each time + // Only blue team members can activate this. + if (!(actor && actor->player && actor->player->ctfteam == 2)) + return false; + break; + case 314: // continuous + case 315: // once + if (!P_CheckPushables(triggerline, caller, dist)) + return false; + break; + case 317: // continuous + case 318: // once + { // Unlockable triggers required + INT32 trigid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS); + + if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) + return false; + else if (trigid < 0 || trigid > 31) // limited by 32 bit variable + { + CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", triggerline->sidenum[0], trigid); + return false; + } + else if (!(unlocktriggers & (1 << trigid))) + return false; + } + break; + case 319: // continuous + case 320: // once + { // An unlockable itself must be unlocked! + INT32 unlockid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS); + + if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) + return false; + else if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count + { + CONS_Debug(DBG_GAMELOGIC, "Unlockable check (sidedef %hu): bad unlockable ID %d\n", triggerline->sidenum[0], unlockid); + return false; + } + else if (!(unlockables[unlockid-1].unlocked)) + return false; + } + break; + case 321: // continuous + case 322: // each time + // decrement calls left before triggering + if (triggerline->callcount > 0) + { + if (--triggerline->callcount > 0) + return false; + } + break; + case 323: // nightserize + case 325: // denightserize + case 327: // nights lap + case 329: // nights egg capsule touch + if (!P_CheckNightsTriggerLine(triggerline, actor)) + return false; + break; + case 331: // continuous + case 332: // each time + case 333: // once + if (!(actor && actor->player && ((stricmp(triggerline->text, skins[actor->player->skin].name) == 0) ^ ((triggerline->flags & ML_NOCLIMB) == ML_NOCLIMB)))) + return false; + break; + case 334: // object dye - continuous + case 335: // object dye - each time + case 336: // object dye - once + { + INT32 triggercolor = (INT32)sides[triggerline->sidenum[0]].toptexture; + UINT16 color = (actor->player ? actor->player->powers[pw_dye] : actor->color); + boolean invert = (triggerline->flags & ML_NOCLIMB ? true : false); + + if (invert ^ (triggercolor != color)) + return false; + } + default: + break; + } + + ///////////////////////////////// + // Processing linedef specials // + ///////////////////////////////// + + if (!P_ActivateLinedefExecutorsInSector(triggerline, actor, caller)) + return false; + // "Trigger on X calls" linedefs reset if noclimb is set if ((specialtype == 321 || specialtype == 322) && triggerline->flags & ML_NOCLIMB) triggerline->callcount = sides[triggerline->sidenum[0]].textureoffset>>FRACBITS; From f60873c19b2f2d26193c48d62fa03cba196f121a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 07:30:55 +0100 Subject: [PATCH 168/326] Adapt linedef types 300-302 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 12 +++++++++++ extras/conf/udb/Includes/SRB222_misc.cfg | 8 ++++++++ src/p_setup.c | 11 ++++++++++ src/p_spec.c | 21 +++++++++++--------- src/p_spec.h | 9 +++++++++ 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 776e9ba2d..489f7fc88 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2502,6 +2502,18 @@ udmf { title = "Linedef Executor Trigger"; + 300 + { + title = "Basic"; + prefix = "(300)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + } + 313 { title = "No More Enemies - Once"; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index ba1e9d16e..2f2992b0d 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -495,6 +495,14 @@ enums 1 = "Less than or equal"; 2 = "Greater than or equal"; } + + triggertype + { + 0 = "Continuous"; + 1 = "Once"; + 2 = "Each time on entry"; + 3 = "Each time on entry/exit"; + } } //Default things filters diff --git a/src/p_setup.c b/src/p_setup.c index ab0254c08..d70137676 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3713,6 +3713,17 @@ static void P_ConvertBinaryMap(void) else lines[i].args[1] = 255; break; + case 300: //Trigger linedef executor - Continuous + lines[i].args[0] = TMT_CONTINUOUS; + break; + case 301: //Trigger linedef executor - Each time + lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMT_EACHTIMEENTERANDEXIT : TMT_EACHTIMEENTER; + lines[i].special = 300; + break; + case 302: //Trigger linedef executor - Once + lines[i].args[0] = TMT_ONCE; + lines[i].special = 300; + break; case 313: //No more enemies - once lines[i].args[0] = tag; break; diff --git a/src/p_spec.c b/src/p_spec.c index ed2f9eb97..4db5ef218 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1844,7 +1844,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller triggerline->callcount = sides[triggerline->sidenum[0]].textureoffset>>FRACBITS; else // These special types work only once - if (specialtype == 302 // Once + if ((specialtype == 300 && triggerline->args[0] == TMT_ONCE) // Once || specialtype == 304 // Ring count - Once || specialtype == 307 // Character ability - Once || specialtype == 308 // Race only - Once @@ -1896,7 +1896,7 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) if (lines[masterline].special == 313 || lines[masterline].special == 399 // Each-time executors handle themselves, too - || lines[masterline].special == 301 // Each time + || (lines[masterline].special == 300 && lines[masterline].args[0] > TMT_EACHTIMEMASK) // Each time || lines[masterline].special == 306 // Character ability - Each time || lines[masterline].special == 310 // CTF Red team - Each time || lines[masterline].special == 312 // CTF Blue team - Each time @@ -5639,7 +5639,7 @@ static inline void P_AddNoEnemiesThinker(line_t *sourceline) * \sa P_SpawnSpecials, T_EachTimeThinker * \author SSNTails */ -static void P_AddEachTimeThinker(line_t *sourceline) +static void P_AddEachTimeThinker(line_t *sourceline, boolean triggerOnExit) { eachtime_t *eachtime; @@ -5650,7 +5650,7 @@ static void P_AddEachTimeThinker(line_t *sourceline) eachtime->thinker.function.acp1 = (actionf_p1)T_EachTimeThinker; eachtime->sourceline = sourceline; - eachtime->triggerOnExit = !!(sourceline->flags & ML_BOUNCY); + eachtime->triggerOnExit = triggerOnExit; } /** Adds a camera scanner. @@ -6659,8 +6659,12 @@ void P_SpawnSpecials(boolean fromnetsave) } break; - case 300: // Linedef executor (combines with sector special 974/975) and commands - case 302: + case 300: // Trigger linedef executor + if (lines[i].args[0] > TMT_EACHTIMEMASK) + P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); + break; + + // Count rings case 303: case 304: @@ -6683,12 +6687,11 @@ void P_SpawnSpecials(boolean fromnetsave) // Each time executors case 306: - case 301: case 310: case 312: case 332: case 335: - P_AddEachTimeThinker(&lines[i]); + P_AddEachTimeThinker(&lines[i], !!(lines[i].flags & ML_BOUNCY)); break; // No More Enemies Linedef Exec @@ -6717,7 +6720,7 @@ void P_SpawnSpecials(boolean fromnetsave) else lines[i].callcount = sides[lines[i].sidenum[0]].textureoffset>>FRACBITS; if (lines[i].special == 322) // Each time - P_AddEachTimeThinker(&lines[i]); + P_AddEachTimeThinker(&lines[i], !!(lines[i].flags & ML_BOUNCY)); break; // NiGHTS trigger executors diff --git a/src/p_spec.h b/src/p_spec.h index 2ff2cd64c..b7968432c 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -105,6 +105,15 @@ typedef enum TMFL_SPLAT = 1<<1, } textmapfoflaserflags_t; +typedef enum +{ + TMT_CONTINUOUS = 0, + TMT_ONCE = 1, + TMT_EACHTIMEMASK = TMT_ONCE, + TMT_EACHTIMEENTER = 2, + TMT_EACHTIMEENTERANDEXIT = 3, +} textmaptriggertype_t; + typedef enum { TMC_EQUAL = 0, From 92e724faca5c6e97d8bcfea5faed038f81641056 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 07:47:01 +0100 Subject: [PATCH 169/326] Adapt linedef types 303-304 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 28 ++++++++++++++ src/p_setup.c | 13 +++++++ src/p_spec.c | 39 ++++++++++---------- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 489f7fc88..8b8d1555b 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2514,6 +2514,34 @@ udmf } } + 303 + { + title = "Ring Count"; + prefix = "(303)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + arg1 + { + title = "Rings"; + } + arg2 + { + title = "Comparison"; + type = 11; + enum = "comparison"; + } + arg3 + { + title = "Count all players?"; + type = 11; + enum = "noyes"; + } + } + 313 { title = "No More Enemies - Once"; diff --git a/src/p_setup.c b/src/p_setup.c index d70137676..ef568b578 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3724,6 +3724,19 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = TMT_ONCE; lines[i].special = 300; break; + case 303: //Ring count - Continuous + case 304: //Ring count - Once + lines[i].args[0] = (lines[i].special == 304) ? TMT_ONCE : TMT_CONTINUOUS; + lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] = TMC_LTE; + else if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[2] = TMC_GTE; + else + lines[i].args[2] = TMC_EQUAL; + lines[i].args[3] = !!(lines[i].flags & ML_EFFECT4); + lines[i].special = 303; + break; case 313: //No more enemies - once lines[i].args[0] = tag; break; diff --git a/src/p_spec.c b/src/p_spec.c index 4db5ef218..631f61a4a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1519,14 +1519,14 @@ static boolean P_CheckPlayerMare(line_t *triggerline, INT32 targetmare) return mare == targetmare; } -static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor, INT32 targetrings) +static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor) { INT32 rings = 0; + INT32 targetrings = triggerline->args[1]; size_t i; - // With the passuse flag, count all player's - // rings. - if (triggerline->flags & ML_EFFECT4) + // Count all players' rings. + if (triggerline->args[3]) { for (i = 0; i < MAXPLAYERS; i++) { @@ -1547,13 +1547,16 @@ static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor, INT32 targ rings = (maptol & TOL_NIGHTS) ? actor->player->spheres : actor->player->rings; } - if (triggerline->flags & ML_NOCLIMB) - return rings <= targetrings; - - if (triggerline->flags & ML_BLOCKMONSTERS) - return rings >= targetrings; - - return rings == targetrings; + switch (triggerline->args[2]) + { + case TMC_EQUAL: + default: + return rings == targetrings; + case TMC_GTE: + return rings >= targetrings; + case TMC_LTE: + return rings <= targetrings; + } } static boolean P_CheckPushables(line_t *triggerline, sector_t *caller, INT32 targetpushables) @@ -1735,9 +1738,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller switch (specialtype) { - case 303: // continuous - case 304: // once - if (!P_CheckPlayerRings(triggerline, actor, dist)) + case 303: + if (!P_CheckPlayerRings(triggerline, actor)) return false; break; case 305: // continuous @@ -1844,8 +1846,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller triggerline->callcount = sides[triggerline->sidenum[0]].textureoffset>>FRACBITS; else // These special types work only once - if ((specialtype == 300 && triggerline->args[0] == TMT_ONCE) // Once - || specialtype == 304 // Ring count - Once + if ((specialtype == 300 && triggerline->args[0] == TMT_ONCE) // Basic + || (specialtype == 303 && triggerline->args[0] == TMT_ONCE) // Ring count || specialtype == 307 // Character ability - Once || specialtype == 308 // Race only - Once || specialtype == 313 // No More Enemies - Once @@ -6660,14 +6662,11 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 300: // Trigger linedef executor + case 303: // Count rings if (lines[i].args[0] > TMT_EACHTIMEMASK) P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); break; - // Count rings - case 303: - case 304: - // Charability linedef executors case 305: case 307: From f86dff8cf2c27b9111bef31681ef6c7eda0b713b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 07:56:15 +0100 Subject: [PATCH 170/326] Adapt linedef types 314-315 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 22 +++++++++++++ src/p_setup.c | 12 +++++++ src/p_spec.c | 33 ++++++++++---------- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 8b8d1555b..17b772f35 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2553,6 +2553,28 @@ udmf } } + 314 + { + title = "Number of Pushables"; + prefix = "(314)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + arg1 + { + title = "Pushables"; + } + arg2 + { + title = "Comparison"; + type = 11; + enum = "comparison"; + } + } + 323 { title = "NiGHTSerize"; diff --git a/src/p_setup.c b/src/p_setup.c index ef568b578..c2fee35b6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3740,6 +3740,18 @@ static void P_ConvertBinaryMap(void) case 313: //No more enemies - once lines[i].args[0] = tag; break; + case 314: //Number of pushables - Continuous + case 315: //Number of pushables - Once + lines[i].args[0] = (lines[i].special == 315) ? TMT_ONCE : TMT_CONTINUOUS; + lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] = TMC_GTE; + else if (lines[i].flags & ML_EFFECT4) + lines[i].args[2] = TMC_GTE; + else + lines[i].args[2] = TMC_EQUAL; + lines[i].special = 314; + break; case 323: //NiGHTSerize - Each time case 324: //NiGHTSerize - Once case 325: //DeNiGHTSerize - Each time diff --git a/src/p_spec.c b/src/p_spec.c index 631f61a4a..0e552f688 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1559,11 +1559,12 @@ static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor) } } -static boolean P_CheckPushables(line_t *triggerline, sector_t *caller, INT32 targetpushables) +static boolean P_CheckPushables(line_t *triggerline, sector_t *caller) { msecnode_t *node; mobj_t *mo; INT32 numpushables = 0; + INT32 targetpushables = triggerline->args[1]; if (!caller) return false; // we need a calling sector to find pushables in, silly! @@ -1576,13 +1577,16 @@ static boolean P_CheckPushables(line_t *triggerline, sector_t *caller, INT32 tar numpushables++; } - if (triggerline->flags & ML_NOCLIMB) - return numpushables >= targetpushables; - - if (triggerline->flags & ML_EFFECT4) - return numpushables <= targetpushables; - - return numpushables == targetpushables; + switch (triggerline->args[2]) + { + case TMC_EQUAL: + default: + return numpushables == targetpushables; + case TMC_GTE: + return numpushables >= targetpushables; + case TMC_LTE: + return numpushables <= targetpushables; + } } static void P_ActivateLinedefExecutor(line_t *line, mobj_t *actor, sector_t *caller) @@ -1760,9 +1764,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!(actor && actor->player && actor->player->ctfteam == 2)) return false; break; - case 314: // continuous - case 315: // once - if (!P_CheckPushables(triggerline, caller, dist)) + case 314: + if (!P_CheckPushables(triggerline, caller)) return false; break; case 317: // continuous @@ -1851,7 +1854,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller || specialtype == 307 // Character ability - Once || specialtype == 308 // Race only - Once || specialtype == 313 // No More Enemies - Once - || specialtype == 315 // No of pushables - Once + || (specialtype == 314 && triggerline->args[0] == TMT_ONCE) // No of pushables || specialtype == 318 // Unlockable trigger - Once || specialtype == 320 // Unlockable - Once || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time @@ -6663,6 +6666,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 300: // Trigger linedef executor case 303: // Count rings + case 314: // Pushable linedef executors (count # of pushables) if (lines[i].args[0] > TMT_EACHTIMEMASK) P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); break; @@ -6698,11 +6702,6 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddNoEnemiesThinker(&lines[i]); break; - // Pushable linedef executors (count # of pushables) - case 314: - case 315: - break; - // Unlock trigger executors case 317: case 318: From 9d87e97275dfffd42ec8420dba3032fdccafcc11 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 08:08:04 +0100 Subject: [PATCH 171/326] Adapt linedef types 317-320 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 32 ++++++++++++++++++++ src/p_setup.c | 12 ++++++++ src/p_spec.c | 24 +++++---------- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 17b772f35..f5eddf380 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2575,6 +2575,38 @@ udmf } } + 317 + { + title = "Condition Set Trigger"; + prefix = "(317)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + arg1 + { + title = "Trigger ID"; + } + } + + 319 + { + title = "Unlockable"; + prefix = "(319)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + arg1 + { + title = "Unlockable ID"; + } + } + 323 { title = "NiGHTSerize"; diff --git a/src/p_setup.c b/src/p_setup.c index c2fee35b6..add37c25b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3752,6 +3752,18 @@ static void P_ConvertBinaryMap(void) lines[i].args[2] = TMC_EQUAL; lines[i].special = 314; break; + case 317: //Condition set trigger - Continuous + case 318: //Condition set trigger - Once + lines[i].args[0] = (lines[i].special == 318) ? TMT_ONCE : TMT_CONTINUOUS; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].special = 317; + break; + case 319: //Unlockable trigger - Continuous + case 320: //Unlockable trigger - Once + lines[i].args[0] = (lines[i].special == 320) ? TMT_ONCE : TMT_CONTINUOUS; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].special = 319; + break; case 323: //NiGHTSerize - Each time case 324: //NiGHTSerize - Once case 325: //DeNiGHTSerize - Each time diff --git a/src/p_spec.c b/src/p_spec.c index 0e552f688..ca084750b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1768,10 +1768,9 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!P_CheckPushables(triggerline, caller)) return false; break; - case 317: // continuous - case 318: // once + case 317: { // Unlockable triggers required - INT32 trigid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS); + INT32 trigid = triggerline->args[1]; if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) return false; @@ -1784,10 +1783,9 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller return false; } break; - case 319: // continuous - case 320: // once + case 319: { // An unlockable itself must be unlocked! - INT32 unlockid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS); + INT32 unlockid = triggerline->args[1]; if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) return false; @@ -1855,8 +1853,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller || specialtype == 308 // Race only - Once || specialtype == 313 // No More Enemies - Once || (specialtype == 314 && triggerline->args[0] == TMT_ONCE) // No of pushables - || specialtype == 318 // Unlockable trigger - Once - || specialtype == 320 // Unlockable - Once + || (specialtype == 317 && triggerline->args[0] == TMT_ONCE) // Unlockable trigger + || (specialtype == 319 && triggerline->args[0] == TMT_ONCE) // Unlockable || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time || (specialtype == 323 && triggerline->args[0]) // Nightserize - Once || (specialtype == 325 && triggerline->args[0]) // DeNightserize - Once @@ -6667,6 +6665,8 @@ void P_SpawnSpecials(boolean fromnetsave) case 300: // Trigger linedef executor case 303: // Count rings case 314: // Pushable linedef executors (count # of pushables) + case 317: // Condition set trigger + case 319: // Unlockable trigger if (lines[i].args[0] > TMT_EACHTIMEMASK) P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); break; @@ -6702,14 +6702,6 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddNoEnemiesThinker(&lines[i]); break; - // Unlock trigger executors - case 317: - case 318: - break; - case 319: - case 320: - break; - // Trigger on X calls case 321: case 322: From 875ba7915ccbc0f85fad81f27c635e69f702d660 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 08:49:50 +0100 Subject: [PATCH 172/326] Adapt linedef types 309-312 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 18 ++++++++++++ extras/conf/udb/Includes/SRB222_misc.cfg | 6 ++++ src/p_setup.c | 11 +++++++ src/p_spec.c | 31 ++++++++------------ src/p_spec.h | 6 ++++ 5 files changed, 54 insertions(+), 18 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index f5eddf380..e74d4978e 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2542,6 +2542,24 @@ udmf } } + 309 + { + title = "CTF Team"; + prefix = "(309)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + arg1 + { + title = "Team"; + type = 11; + enum = "team"; + } + } + 313 { title = "No More Enemies - Once"; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 2f2992b0d..4b37d4628 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -503,6 +503,12 @@ enums 2 = "Each time on entry"; 3 = "Each time on entry/exit"; } + + team + { + 0 = "Red"; + 1 = "Blue"; + } } //Default things filters diff --git a/src/p_setup.c b/src/p_setup.c index add37c25b..4b567d324 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3737,6 +3737,17 @@ static void P_ConvertBinaryMap(void) lines[i].args[3] = !!(lines[i].flags & ML_EFFECT4); lines[i].special = 303; break; + case 309: //CTF red team - continuous + case 310: //CTF red team - each time + case 311: //CTF blue team - continuous + case 312: //CTF blue team - each time + if (lines[i].special % 2 == 1) + lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMT_EACHTIMEENTERANDEXIT : TMT_EACHTIMEENTER; + else + lines[i].args[0] = TMT_CONTINUOUS; + lines[i].args[1] = (lines[i].special > 310) ? TMT_BLUE : TMT_RED; + lines[i].special = 309; + break; case 313: //No more enemies - once lines[i].args[0] = tag; break; diff --git a/src/p_spec.c b/src/p_spec.c index ca084750b..f75cd5419 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1752,16 +1752,11 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!(actor && actor->player && actor->player->charability == dist/10)) return false; break; - case 309: // continuous - case 310: // each time - // Only red team members can activate this. - if (!(actor && actor->player && actor->player->ctfteam == 1)) + case 309: + // Only red/blue team members can activate this. + if (!(actor && actor->player)) return false; - break; - case 311: // continuous - case 312: // each time - // Only blue team members can activate this. - if (!(actor && actor->player && actor->player->ctfteam == 2)) + if (actor->player->ctfteam != ((triggerline->args[1] == TMT_RED) ? 1 : 2)) return false; break; case 314: @@ -1851,6 +1846,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller || (specialtype == 303 && triggerline->args[0] == TMT_ONCE) // Ring count || specialtype == 307 // Character ability - Once || specialtype == 308 // Race only - Once + || (specialtype == 309 && triggerline->args[0] == TMT_ONCE) // CTF team || specialtype == 313 // No More Enemies - Once || (specialtype == 314 && triggerline->args[0] == TMT_ONCE) // No of pushables || (specialtype == 317 && triggerline->args[0] == TMT_ONCE) // Unlockable trigger @@ -6662,6 +6658,14 @@ void P_SpawnSpecials(boolean fromnetsave) } break; + // Linedef executor triggers for CTF teams. + case 309: + if (!(gametyperules & GTR_TEAMFLAGS)) + { + lines[i].special = 0; + break; + } + /* FALLTHRU */ case 300: // Trigger linedef executor case 303: // Count rings case 314: // Pushable linedef executors (count # of pushables) @@ -6681,17 +6685,8 @@ void P_SpawnSpecials(boolean fromnetsave) lines[i].special = 0; break; - // Linedef executor triggers for CTF teams. - case 309: - case 311: - if (!(gametyperules & GTR_TEAMFLAGS)) - lines[i].special = 0; - break; - // Each time executors case 306: - case 310: - case 312: case 332: case 335: P_AddEachTimeThinker(&lines[i], !!(lines[i].flags & ML_BOUNCY)); diff --git a/src/p_spec.h b/src/p_spec.h index b7968432c..0ed5ad8d4 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -114,6 +114,12 @@ typedef enum TMT_EACHTIMEENTERANDEXIT = 3, } textmaptriggertype_t; +typedef enum +{ + TMT_RED = 0, + TMT_BLUE = 1, +} textmapteam_t; + typedef enum { TMC_EQUAL = 0, From 2638e1212c6ec60b60fbe17004e0d17fce261da4 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 16:10:39 +0100 Subject: [PATCH 173/326] Fix a typo --- 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 4b567d324..03f45eb02 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3741,7 +3741,7 @@ static void P_ConvertBinaryMap(void) case 310: //CTF red team - each time case 311: //CTF blue team - continuous case 312: //CTF blue team - each time - if (lines[i].special % 2 == 1) + if (lines[i].special % 2 == 0) lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMT_EACHTIMEENTERANDEXIT : TMT_EACHTIMEENTER; else lines[i].args[0] = TMT_CONTINUOUS; From 126cbdd189cf2385fed537108d548050d5424518 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 18:15:27 +0100 Subject: [PATCH 174/326] Adapt linedef types 321-322 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 26 ++++++++++++++++++++ extras/conf/udb/Includes/SRB222_misc.cfg | 7 ++++++ src/p_setup.c | 16 ++++++++++++ src/p_spec.c | 23 +++++++---------- src/p_spec.h | 8 ++++++ 5 files changed, 66 insertions(+), 14 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index e74d4978e..76bb2c5ba 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2625,6 +2625,32 @@ udmf } } + 321 + { + title = "Trigger After X Calls"; + prefix = "(321)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "xtriggertype"; + } + arg1 + { + title = "Calls"; + } + arg2 + { + title = "Can retrigger?"; + type = 11; + enum = "noyes"; + } + arg3 + { + title = "Starting calls"; + } + } + 323 { title = "NiGHTSerize"; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 4b37d4628..1e11ad255 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -504,6 +504,13 @@ enums 3 = "Each time on entry/exit"; } + xtriggertype + { + 0 = "Continuous"; + 1 = "Each time on entry"; + 2 = "Each time on entry/exit"; + } + team { 0 = "Red"; diff --git a/src/p_setup.c b/src/p_setup.c index 03f45eb02..a459e6401 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3775,6 +3775,22 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].special = 319; break; + case 321: //Trigger after X calls - Continuous + case 322: //Trigger after X calls - Each time + if (lines[i].special % 2 == 0) + lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMXT_EACHTIMEENTERANDEXIT : TMXT_EACHTIMEENTER; + else + lines[i].args[0] = TMXT_CONTINUOUS; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + if (lines[i].flags & ML_NOCLIMB) + { + lines[i].args[2] = 1; + lines[i].args[3] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + } + else + lines[i].args[2] = lines[i].args[3] = 0; + lines[i].special = 321; + break; case 323: //NiGHTSerize - Each time case 324: //NiGHTSerize - Once case 325: //DeNiGHTSerize - Each time diff --git a/src/p_spec.c b/src/p_spec.c index f75cd5419..5f3ce50d8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1793,8 +1793,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller return false; } break; - case 321: // continuous - case 322: // each time + case 321: // decrement calls left before triggering if (triggerline->callcount > 0) { @@ -1837,9 +1836,9 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!P_ActivateLinedefExecutorsInSector(triggerline, actor, caller)) return false; - // "Trigger on X calls" linedefs reset if noclimb is set - if ((specialtype == 321 || specialtype == 322) && triggerline->flags & ML_NOCLIMB) - triggerline->callcount = sides[triggerline->sidenum[0]].textureoffset>>FRACBITS; + // "Trigger on X calls" linedefs reset if args[2] is set + if (specialtype == 321 && triggerline->args[2]) + triggerline->callcount = triggerline->args[3]; else // These special types work only once if ((specialtype == 300 && triggerline->args[0] == TMT_ONCE) // Basic @@ -1851,7 +1850,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller || (specialtype == 314 && triggerline->args[0] == TMT_ONCE) // No of pushables || (specialtype == 317 && triggerline->args[0] == TMT_ONCE) // Unlockable trigger || (specialtype == 319 && triggerline->args[0] == TMT_ONCE) // Unlockable - || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time + || specialtype == 321 // Trigger on X calls || (specialtype == 323 && triggerline->args[0]) // Nightserize - Once || (specialtype == 325 && triggerline->args[0]) // DeNightserize - Once || (specialtype == 327 && triggerline->args[0]) // Nights lap - Once @@ -1899,7 +1898,7 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) || lines[masterline].special == 306 // Character ability - Each time || lines[masterline].special == 310 // CTF Red team - Each time || lines[masterline].special == 312 // CTF Blue team - Each time - || lines[masterline].special == 322 // Trigger on X calls - Each Time + || (lines[masterline].special == 321 && lines[masterline].args[0] > TMXT_EACHTIMEMASK) // Trigger after X calls - Each time || lines[masterline].special == 332 // Skin - Each time || lines[masterline].special == 335)// Dye - Each time continue; @@ -6699,13 +6698,9 @@ void P_SpawnSpecials(boolean fromnetsave) // Trigger on X calls case 321: - case 322: - if (lines[i].flags & ML_NOCLIMB && sides[lines[i].sidenum[0]].rowoffset > 0) // optional "starting" count - lines[i].callcount = sides[lines[i].sidenum[0]].rowoffset>>FRACBITS; - else - lines[i].callcount = sides[lines[i].sidenum[0]].textureoffset>>FRACBITS; - if (lines[i].special == 322) // Each time - P_AddEachTimeThinker(&lines[i], !!(lines[i].flags & ML_BOUNCY)); + lines[i].callcount = (lines[i].args[2] && lines[i].args[3] > 0) ? lines[i].args[3] : lines[i].args[1]; // optional "starting" count + if (lines[i].args[0] > TMXT_EACHTIMEMASK) // Each time + P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMXT_EACHTIMEENTERANDEXIT); break; // NiGHTS trigger executors diff --git a/src/p_spec.h b/src/p_spec.h index 0ed5ad8d4..a317467f8 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -114,6 +114,14 @@ typedef enum TMT_EACHTIMEENTERANDEXIT = 3, } textmaptriggertype_t; +typedef enum +{ + TMXT_CONTINUOUS = 0, + TMXT_EACHTIMEMASK = TMXT_CONTINUOUS, + TMXT_EACHTIMEENTER = 1, + TMXT_EACHTIMEENTERANDEXIT = 2, +} textmapxtriggertype_t; + typedef enum { TMT_RED = 0, From 670e32908e3a2ed2f7bf67ef53074cb70532bf28 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 18:56:50 +0100 Subject: [PATCH 175/326] Adapt linedef type 308 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 65 +++++++++++++++++ src/p_setup.c | 5 ++ src/p_spec.c | 76 ++++++++++++++------ src/p_spec.h | 9 +++ 4 files changed, 135 insertions(+), 20 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 76bb2c5ba..b4ef7f36a 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2542,6 +2542,71 @@ udmf } } + 308 + { + title = "Gametype"; + prefix = "(308)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + arg1 + { + title = "Rules"; + type = 12; + enum + { + 1 = "Campaign"; + 2 = "Ringslinger"; + 4 = "Spectators"; + 8 = "Lives"; + 16 = "Teams"; + 32 = "First person"; + 64 = "Match emeralds"; + 128 = "Team flags"; + 256 = "Coop"; + 512 = "Allow special stages"; + 1024 = "Spawn emerald tokens"; + 2048 = "Emerald hunt"; + 4096 = "Race"; + 8192 = "Tag"; + 16384 = "Point limit"; + 32768 = "Time limit"; + 65536 = "Overtime"; + 131072 = "Hurt messages"; + 262144 = "Friendly fire"; + 524288 = "Hide time countdown"; + 1048576 = "Frozen after hide time"; + 2097152 = "Blindfolded view"; + 4194304 = "Respawn delay"; + 8388608 = "Award pity shield"; + 16777216 = "Death score penalty"; + 33554432 = "No spectator spawn"; + 67108864 = "Use match starts"; + 134217728 = "Spawn invincibility"; + 268435456 = "Allow enemies"; + 536870912 = "Allow exit sectors"; + 1073741824 = "No title card"; + 2147483648 = "Allow cutscenes"; + } + } + arg2 + { + title = "Check if"; + type = 11; + enum + { + 0 = "Has all"; + 1 = "Has any"; + 2 = "Has exactly"; + 3 = "Doesn't have all"; + 4 = "Doesn't have any"; + } + } + } + 309 { title = "CTF Team"; diff --git a/src/p_setup.c b/src/p_setup.c index a459e6401..6b98ed738 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3737,6 +3737,11 @@ static void P_ConvertBinaryMap(void) lines[i].args[3] = !!(lines[i].flags & ML_EFFECT4); lines[i].special = 303; break; + case 308: //Race only - once + lines[i].args[0] = TMT_ONCE; + lines[i].args[1] = GTR_RACE; + lines[i].args[2] = TMG_HASANY; + break; case 309: //CTF red team - continuous case 310: //CTF red team - each time case 311: //CTF blue team - continuous diff --git a/src/p_spec.c b/src/p_spec.c index 5f3ce50d8..be0455fba 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1844,7 +1844,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if ((specialtype == 300 && triggerline->args[0] == TMT_ONCE) // Basic || (specialtype == 303 && triggerline->args[0] == TMT_ONCE) // Ring count || specialtype == 307 // Character ability - Once - || specialtype == 308 // Race only - Once + || (specialtype == 308 && triggerline->args[0] == TMT_ONCE) // Gametype || (specialtype == 309 && triggerline->args[0] == TMT_ONCE) // CTF team || specialtype == 313 // No More Enemies - Once || (specialtype == 314 && triggerline->args[0] == TMT_ONCE) // No of pushables @@ -1891,16 +1891,26 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) continue; // "No More Enemies" and "Level Load" take care of themselves. - if (lines[masterline].special == 313 - || lines[masterline].special == 399 - // Each-time executors handle themselves, too - || (lines[masterline].special == 300 && lines[masterline].args[0] > TMT_EACHTIMEMASK) // Each time - || lines[masterline].special == 306 // Character ability - Each time - || lines[masterline].special == 310 // CTF Red team - Each time - || lines[masterline].special == 312 // CTF Blue team - Each time - || (lines[masterline].special == 321 && lines[masterline].args[0] > TMXT_EACHTIMEMASK) // Trigger after X calls - Each time - || lines[masterline].special == 332 // Skin - Each time - || lines[masterline].special == 335)// Dye - Each time + if (lines[masterline].special == 313 || lines[masterline].special == 399) + continue; + + // Each-time executors handle themselves, too + if ((lines[masterline].special == 300 // Basic + || lines[masterline].special == 303 // Ring count + || lines[masterline].special == 308 // Gametype + || lines[masterline].special == 309 // CTF team + || lines[masterline].special == 314 // Number of pushables + || lines[masterline].special == 317 // Condition set trigger + || lines[masterline].special == 319) // Unlockable trigger + && lines[masterline].args[0] > TMT_EACHTIMEMASK) + continue; + + if (lines[masterline].special == 321 && lines[masterline].args[0] > TMXT_EACHTIMEMASK) // Trigger after X calls + continue; + + if (lines[masterline].special == 306 // Character ability + || lines[masterline].special == 332 // Skin + || lines[masterline].special == 335)// Dye continue; if (!P_RunTriggerLinedef(&lines[masterline], actor, caller)) @@ -5857,6 +5867,24 @@ static void P_MakeFOFBouncy(line_t *paramline, line_t *masterline) } +static boolean P_CheckGametypeRules(INT32 checktype, UINT32 target) +{ + switch (checktype) + { + case TMG_HASALL: + default: + return (gametyperules & target) == target; + case TMG_HASANY: + return !!(gametyperules & target); + case TMG_HASEXACTLY: + return gametyperules == target; + case TMG_DOESNTHAVEALL: + return (gametyperules & target) != target; + case TMG_DOESNTHAVEANY: + return !(gametyperules & target); + } +} + /** After the map has loaded, scans for specials that spawn 3Dfloors and * thinkers. * @@ -6657,14 +6685,6 @@ void P_SpawnSpecials(boolean fromnetsave) } break; - // Linedef executor triggers for CTF teams. - case 309: - if (!(gametyperules & GTR_TEAMFLAGS)) - { - lines[i].special = 0; - break; - } - /* FALLTHRU */ case 300: // Trigger linedef executor case 303: // Count rings case 314: // Pushable linedef executors (count # of pushables) @@ -6680,8 +6700,24 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 308: // Race-only linedef executor. Triggers once. - if (!(gametyperules & GTR_RACE)) + if (!P_CheckGametypeRules(lines[i].args[2], (UINT32)lines[i].args[1])) + { lines[i].special = 0; + break; + } + if (lines[i].args[0] > TMT_EACHTIMEMASK) + P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); + break; + + // Linedef executor triggers for CTF teams. + case 309: + if (!(gametyperules & GTR_TEAMFLAGS)) + { + lines[i].special = 0; + break; + } + if (lines[i].args[0] > TMT_EACHTIMEMASK) + P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); break; // Each time executors diff --git a/src/p_spec.h b/src/p_spec.h index a317467f8..c60bdda66 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -122,6 +122,15 @@ typedef enum TMXT_EACHTIMEENTERANDEXIT = 2, } textmapxtriggertype_t; +typedef enum +{ + TMG_HASALL = 0, + TMG_HASANY = 1, + TMG_HASEXACTLY = 2, + TMG_DOESNTHAVEALL = 3, + TMG_DOESNTHAVEANY = 4, +} textmapgametypecheck_t; + typedef enum { TMT_RED = 0, From a7f5bcfea7755c58989072999d846dc7d50cc7f3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 19:17:16 +0100 Subject: [PATCH 176/326] Adapt linedef type 305-307 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 36 ++++++++++++++++++++ src/p_setup.c | 24 +++++++++---- src/p_spec.c | 22 +++++------- 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index b4ef7f36a..065c9dc46 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2542,6 +2542,42 @@ udmf } } + 305 + { + title = "Character Ability"; + prefix = "(305)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + arg1 + { + title = "Ability"; + type = 11; + enum + { + 0 = "None"; + 1 = "Thok"; + 2 = "Fly"; + 3 = "Glide and climb"; + 4 = "Homing attack"; + 5 = "Swim"; + 6 = "Double jump"; + 7 = "Float"; + 8 = "Float with slow descent"; + 9 = "Telekinesis"; + 10 = "Fall switch"; + 11 = "Jump boost"; + 12 = "Air drill"; + 13 = "Jump-thok"; + 14 = "Pogo bounce"; + 15 = "Twin spin"; + } + } + } + 308 { title = "Gametype"; diff --git a/src/p_setup.c b/src/p_setup.c index 6b98ed738..e4080f256 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3714,14 +3714,14 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = 255; break; case 300: //Trigger linedef executor - Continuous - lines[i].args[0] = TMT_CONTINUOUS; - break; case 301: //Trigger linedef executor - Each time - lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMT_EACHTIMEENTERANDEXIT : TMT_EACHTIMEENTER; - lines[i].special = 300; - break; case 302: //Trigger linedef executor - Once - lines[i].args[0] = TMT_ONCE; + if (lines[i].special == 302) + lines[i].args[0] = TMT_ONCE; + else if (lines[i].special == 301) + lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMT_EACHTIMEENTERANDEXIT : TMT_EACHTIMEENTER; + else + lines[i].args[0] = TMT_CONTINUOUS; lines[i].special = 300; break; case 303: //Ring count - Continuous @@ -3737,6 +3737,18 @@ static void P_ConvertBinaryMap(void) lines[i].args[3] = !!(lines[i].flags & ML_EFFECT4); lines[i].special = 303; break; + case 305: //Character ability - Continuous + case 306: //Character ability - Each time + case 307: //Character ability - Once + if (lines[i].special == 307) + lines[i].args[0] = TMT_ONCE; + else if (lines[i].special == 306) + lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMT_EACHTIMEENTERANDEXIT : TMT_EACHTIMEENTER; + else + lines[i].args[0] = TMT_CONTINUOUS; + lines[i].args[1] = (P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS) / 10; + lines[i].special = 305; + break; case 308: //Race only - once lines[i].args[0] = TMT_ONCE; lines[i].args[1] = GTR_RACE; diff --git a/src/p_spec.c b/src/p_spec.c index be0455fba..013d72300 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1501,9 +1501,10 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) return true; } -static boolean P_CheckPlayerMare(line_t *triggerline, INT32 targetmare) +static boolean P_CheckPlayerMare(line_t *triggerline) { UINT8 mare; + INT32 targetmare = P_AproxDistance(triggerline->dx, triggerline->dy) >> FRACBITS; if (!(maptol & TOL_NIGHTS)) return false; @@ -1709,7 +1710,6 @@ static boolean P_ActivateLinedefExecutorsInSector(line_t *triggerline, mobj_t *a */ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller) { - fixed_t dist = P_AproxDistance(triggerline->dx, triggerline->dy)>>FRACBITS; INT16 specialtype = triggerline->special; //////////////////////// @@ -1725,7 +1725,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller } else if (GETSECSPECIAL(caller->special, 2) == 7) { - if (!P_CheckPlayerMare(triggerline, dist)) + if (!P_CheckPlayerMare(triggerline)) return false; } // If we were not triggered by a sector type especially for the purpose, @@ -1746,10 +1746,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!P_CheckPlayerRings(triggerline, actor)) return false; break; - case 305: // continuous - case 306: // each time - case 307: // once - if (!(actor && actor->player && actor->player->charability == dist/10)) + case 305: + if (!(actor && actor->player && actor->player->charability == triggerline->args[1])) return false; break; case 309: @@ -1843,7 +1841,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller // These special types work only once if ((specialtype == 300 && triggerline->args[0] == TMT_ONCE) // Basic || (specialtype == 303 && triggerline->args[0] == TMT_ONCE) // Ring count - || specialtype == 307 // Character ability - Once + || (specialtype == 305 && triggerline->args[0] == TMT_ONCE) // Character ability || (specialtype == 308 && triggerline->args[0] == TMT_ONCE) // Gametype || (specialtype == 309 && triggerline->args[0] == TMT_ONCE) // CTF team || specialtype == 313 // No More Enemies - Once @@ -1897,6 +1895,7 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) // Each-time executors handle themselves, too if ((lines[masterline].special == 300 // Basic || lines[masterline].special == 303 // Ring count + || lines[masterline].special == 305 // Character ability || lines[masterline].special == 308 // Gametype || lines[masterline].special == 309 // CTF team || lines[masterline].special == 314 // Number of pushables @@ -1908,8 +1907,7 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) if (lines[masterline].special == 321 && lines[masterline].args[0] > TMXT_EACHTIMEMASK) // Trigger after X calls continue; - if (lines[masterline].special == 306 // Character ability - || lines[masterline].special == 332 // Skin + if (lines[masterline].special == 332 // Skin || lines[masterline].special == 335)// Dye continue; @@ -6687,6 +6685,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 300: // Trigger linedef executor case 303: // Count rings + case 305: // Character ability case 314: // Pushable linedef executors (count # of pushables) case 317: // Condition set trigger case 319: // Unlockable trigger @@ -6694,9 +6693,6 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); break; - // Charability linedef executors - case 305: - case 307: break; case 308: // Race-only linedef executor. Triggers once. From adaf599e87c5f916e25fc90aa53c440498bb5e14 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 19:33:02 +0100 Subject: [PATCH 177/326] Adapt linedef types 331-333 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 24 ++++++++++++++++++ src/p_setup.c | 17 +++++++++++++ src/p_spec.c | 26 +++++++++----------- 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 065c9dc46..eef89d144 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -3001,6 +3001,30 @@ udmf } } } + + 331 + { + title = "Player Skin"; + prefix = "(331)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + arg1 + { + title = "Invert choice?"; + type = 11; + enum = "noyes"; + } + stringarg0 + { + title = "Skin name"; + type = 2; + } + } + 399 { title = "Level Load"; diff --git a/src/p_setup.c b/src/p_setup.c index e4080f256..abdc643c5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3881,6 +3881,23 @@ static void P_ConvertBinaryMap(void) lines[i].args[7] |= TMI_ENTER; } break; + case 331: // Player skin - continuous + case 332: // Player skin - each time + case 333: // Player skin - once + if (lines[i].special == 303) + lines[i].args[0] = TMT_ONCE; + else if (lines[i].special == 302) + lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMT_EACHTIMEENTERANDEXIT : TMT_EACHTIMEENTER; + else + lines[i].args[0] = TMT_CONTINUOUS; + lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); + if (lines[i].text) + { + lines[i].stringargs[0] = Z_Malloc(strlen(lines[i].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], lines[i].text, strlen(lines[i].text) + 1); + } + lines[i].special = 331; + break; case 400: //Set tagged sector's floor height/texture case 401: //Set tagged sector's ceiling height/texture lines[i].args[0] = tag; diff --git a/src/p_spec.c b/src/p_spec.c index 013d72300..94a4cc7da 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1806,10 +1806,12 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!P_CheckNightsTriggerLine(triggerline, actor)) return false; break; - case 331: // continuous - case 332: // each time - case 333: // once - if (!(actor && actor->player && ((stricmp(triggerline->text, skins[actor->player->skin].name) == 0) ^ ((triggerline->flags & ML_NOCLIMB) == ML_NOCLIMB)))) + case 331: + if (!(actor && actor->player)) + return false; + if (!triggerline->stringargs[0]) + return false; + if (!(stricmp(triggerline->stringargs[0], skins[actor->player->skin].name) == 0) ^ !!(triggerline->args[1])) return false; break; case 334: // object dye - continuous @@ -1853,7 +1855,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller || (specialtype == 325 && triggerline->args[0]) // DeNightserize - Once || (specialtype == 327 && triggerline->args[0]) // Nights lap - Once || (specialtype == 329 && triggerline->args[0]) // Nights Bonus Time - Once - || specialtype == 333 // Skin - Once + || (specialtype == 333 && triggerline->args[0] == TMT_ONCE) // Player skin || specialtype == 336 // Dye - Once || specialtype == 399) // Level Load triggerline->special = 0; // Clear it out @@ -1900,15 +1902,15 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) || lines[masterline].special == 309 // CTF team || lines[masterline].special == 314 // Number of pushables || lines[masterline].special == 317 // Condition set trigger - || lines[masterline].special == 319) // Unlockable trigger + || lines[masterline].special == 319 // Unlockable trigger + || lines[masterline].special == 331) // Player skin && lines[masterline].args[0] > TMT_EACHTIMEMASK) continue; if (lines[masterline].special == 321 && lines[masterline].args[0] > TMXT_EACHTIMEMASK) // Trigger after X calls continue; - if (lines[masterline].special == 332 // Skin - || lines[masterline].special == 335)// Dye + if (lines[masterline].special == 335) // Dye continue; if (!P_RunTriggerLinedef(&lines[masterline], actor, caller)) @@ -6689,6 +6691,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 314: // Pushable linedef executors (count # of pushables) case 317: // Condition set trigger case 319: // Unlockable trigger + case 331: // Player skin if (lines[i].args[0] > TMT_EACHTIMEMASK) P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); break; @@ -6717,8 +6720,6 @@ void P_SpawnSpecials(boolean fromnetsave) break; // Each time executors - case 306: - case 332: case 335: P_AddEachTimeThinker(&lines[i], !!(lines[i].flags & ML_BOUNCY)); break; @@ -6742,11 +6743,6 @@ void P_SpawnSpecials(boolean fromnetsave) case 329: break; - // Skin trigger executors - case 331: - case 333: - break; - // Object dye executors case 334: case 336: From c43d5c7183479fce9496e5d1d04f4cbaac617218 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 19:49:17 +0100 Subject: [PATCH 178/326] Adapt linedef types 334-336 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 38 ++++++++++++++++++++ src/p_setup.c | 23 ++++++++++-- src/p_spec.c | 30 +++++----------- 3 files changed, 66 insertions(+), 25 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index eef89d144..f5fb423f3 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -739,6 +739,21 @@ doom title = "Player Skin - Once"; prefix = "(333)"; } + 334 + { + title = "Object Dye - Continuous"; + prefix = "(334)"; + } + 335 + { + title = "Object Dye - Each Time"; + prefix = "(335)"; + } + 336 + { + title = "Object Dye - Once"; + prefix = "(336)"; + } 399 { title = "Level Load"; @@ -3025,6 +3040,29 @@ udmf } } + 334 + { + title = "Object Dye"; + prefix = "(334)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + arg1 + { + title = "Invert choice?"; + type = 11; + enum = "noyes"; + } + stringarg0 + { + title = "Color"; + type = 2; + } + } + 399 { title = "Level Load"; diff --git a/src/p_setup.c b/src/p_setup.c index abdc643c5..95e3c487b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1302,9 +1302,6 @@ static void P_LoadSidedefs(UINT8 *data) case 9: // Mace parameters case 14: // Bustable block parameters case 15: // Fan particle spawner parameters - case 334: // Trigger linedef executor: Object dye - Continuous - case 335: // Trigger linedef executor: Object dye - Each time - case 336: // Trigger linedef executor: Object dye - Once { char process[8*3+1]; memset(process,0,8*3+1); @@ -1324,6 +1321,9 @@ static void P_LoadSidedefs(UINT8 *data) case 331: // Trigger linedef executor: Skin - Continuous case 332: // Trigger linedef executor: Skin - Each time case 333: // Trigger linedef executor: Skin - Once + case 334: // Trigger linedef executor: Object dye - Continuous + case 335: // Trigger linedef executor: Object dye - Each time + case 336: // Trigger linedef executor: Object dye - Once case 425: // Calls P_SetMobjState on calling mobj case 434: // Custom Power case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors @@ -3898,6 +3898,23 @@ static void P_ConvertBinaryMap(void) } lines[i].special = 331; break; + case 334: // Object dye - continuous + case 335: // Object dye - each time + case 336: // Object dye - once + if (lines[i].special == 336) + lines[i].args[0] = TMT_ONCE; + else if (lines[i].special == 335) + lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMT_EACHTIMEENTERANDEXIT : TMT_EACHTIMEENTER; + else + lines[i].args[0] = TMT_CONTINUOUS; + lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); + if (sides[lines[i].sidenum[0]].text) + { + lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); + } + lines[i].special = 334; + break; case 400: //Set tagged sector's floor height/texture case 401: //Set tagged sector's ceiling height/texture lines[i].args[0] = tag; diff --git a/src/p_spec.c b/src/p_spec.c index 94a4cc7da..f5982e6f2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1814,15 +1814,12 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!(stricmp(triggerline->stringargs[0], skins[actor->player->skin].name) == 0) ^ !!(triggerline->args[1])) return false; break; - case 334: // object dye - continuous - case 335: // object dye - each time - case 336: // object dye - once + case 334: // object dye { - INT32 triggercolor = (INT32)sides[triggerline->sidenum[0]].toptexture; + INT32 triggercolor = triggerline->stringargs[0] ? get_number(triggerline->stringargs[0]) : SKINCOLOR_NONE; UINT16 color = (actor->player ? actor->player->powers[pw_dye] : actor->color); - boolean invert = (triggerline->flags & ML_NOCLIMB ? true : false); - if (invert ^ (triggercolor != color)) + if (!!(triggerline->args[1]) ^ (triggercolor != color)) return false; } default: @@ -1855,8 +1852,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller || (specialtype == 325 && triggerline->args[0]) // DeNightserize - Once || (specialtype == 327 && triggerline->args[0]) // Nights lap - Once || (specialtype == 329 && triggerline->args[0]) // Nights Bonus Time - Once - || (specialtype == 333 && triggerline->args[0] == TMT_ONCE) // Player skin - || specialtype == 336 // Dye - Once + || (specialtype == 331 && triggerline->args[0] == TMT_ONCE) // Player skin + || (specialtype == 334 && triggerline->args[0] == TMT_ONCE) // Object dye || specialtype == 399) // Level Load triggerline->special = 0; // Clear it out @@ -1903,16 +1900,14 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) || lines[masterline].special == 314 // Number of pushables || lines[masterline].special == 317 // Condition set trigger || lines[masterline].special == 319 // Unlockable trigger - || lines[masterline].special == 331) // Player skin + || lines[masterline].special == 331 // Player skin + || lines[masterline].special == 334) // Object dye && lines[masterline].args[0] > TMT_EACHTIMEMASK) continue; if (lines[masterline].special == 321 && lines[masterline].args[0] > TMXT_EACHTIMEMASK) // Trigger after X calls continue; - if (lines[masterline].special == 335) // Dye - continue; - if (!P_RunTriggerLinedef(&lines[masterline], actor, caller)) return; // cancel P_LinedefExecute if function returns false } @@ -6692,6 +6687,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 317: // Condition set trigger case 319: // Unlockable trigger case 331: // Player skin + case 334: // Object dye if (lines[i].args[0] > TMT_EACHTIMEMASK) P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); break; @@ -6719,11 +6715,6 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); break; - // Each time executors - case 335: - P_AddEachTimeThinker(&lines[i], !!(lines[i].flags & ML_BOUNCY)); - break; - // No More Enemies Linedef Exec case 313: P_AddNoEnemiesThinker(&lines[i]); @@ -6743,11 +6734,6 @@ void P_SpawnSpecials(boolean fromnetsave) case 329: break; - // Object dye executors - case 334: - case 336: - break; - case 399: // Linedef execute on map load // This is handled in P_RunLevelLoadExecutors. break; From 22420f92d2a8c63bf76059cada6c10d6d1a63715 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 20:02:03 +0100 Subject: [PATCH 179/326] Some trigger lineder cleanup --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 2 +- src/p_spec.c | 44 +++++++++++--------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index f5fb423f3..7635f03be 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2678,7 +2678,7 @@ udmf 313 { - title = "No More Enemies - Once"; + title = "No More Enemies"; prefix = "(313)"; arg0 { diff --git a/src/p_spec.c b/src/p_spec.c index f5982e6f2..340427b80 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1837,25 +1837,31 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (specialtype == 321 && triggerline->args[2]) triggerline->callcount = triggerline->args[3]; else - // These special types work only once - if ((specialtype == 300 && triggerline->args[0] == TMT_ONCE) // Basic - || (specialtype == 303 && triggerline->args[0] == TMT_ONCE) // Ring count - || (specialtype == 305 && triggerline->args[0] == TMT_ONCE) // Character ability - || (specialtype == 308 && triggerline->args[0] == TMT_ONCE) // Gametype - || (specialtype == 309 && triggerline->args[0] == TMT_ONCE) // CTF team - || specialtype == 313 // No More Enemies - Once - || (specialtype == 314 && triggerline->args[0] == TMT_ONCE) // No of pushables - || (specialtype == 317 && triggerline->args[0] == TMT_ONCE) // Unlockable trigger - || (specialtype == 319 && triggerline->args[0] == TMT_ONCE) // Unlockable - || specialtype == 321 // Trigger on X calls - || (specialtype == 323 && triggerline->args[0]) // Nightserize - Once - || (specialtype == 325 && triggerline->args[0]) // DeNightserize - Once - || (specialtype == 327 && triggerline->args[0]) // Nights lap - Once - || (specialtype == 329 && triggerline->args[0]) // Nights Bonus Time - Once - || (specialtype == 331 && triggerline->args[0] == TMT_ONCE) // Player skin - || (specialtype == 334 && triggerline->args[0] == TMT_ONCE) // Object dye - || specialtype == 399) // Level Load - triggerline->special = 0; // Clear it out + { + // These special types work only once + if (specialtype == 313 // No more enemies + || specialtype == 321 // Trigger on X calls + || specialtype == 399) // Level Load + triggerline->special = 0; + else if ((specialtype == 323 // Nightserize + || specialtype == 325 // DeNightserize + || specialtype == 327 // Nights lap + || specialtype == 329) // Nights bonus time + && triggerline->args[0]) + triggerline->special = 0; + else if ((specialtype == 300 // Basic + || specialtype == 303 // Ring count + || specialtype == 305 // Character ability + || specialtype == 308 // Gametype + || specialtype == 309 // CTF team + || specialtype == 314 // No of pushables + || specialtype == 317 // Unlockable trigger + || specialtype == 319 // Unlockable + || specialtype == 331 // Player skin + || specialtype == 334) // Object dye + && triggerline->args[0] == TMT_ONCE) + triggerline->special = 0; + } return true; } From 18e8ebf394c880153ff8b062e18dad27a10e2ea2 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 20:37:39 +0100 Subject: [PATCH 180/326] Add emerald check trigger linedef types and deprecate the emerald check sector type --- extras/conf/SRB2-22.cfg | 22 +++++++- extras/conf/udb/Includes/SRB222_linedefs.cfg | 57 +++++++++++++++++--- extras/conf/udb/Includes/SRB222_misc.cfg | 9 ++++ extras/conf/udb/Includes/SRB222_sectors.cfg | 4 +- src/p_setup.c | 15 +++++- src/p_spec.c | 41 +++++++++++--- src/p_spec.h | 12 ++--- 7 files changed, 134 insertions(+), 26 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 0d5b7ab92..7c53d99f6 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -431,7 +431,7 @@ sectortypes 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)"; + 96 = "Trigger Line Ex. (Emerald Check) "; 112 = "Trigger Line Ex. (NiGHTS Mare)"; 128 = "Check for Linedef Executor on FOFs"; 144 = "Egg Capsule"; @@ -486,7 +486,7 @@ gen_sectortypes 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)"; + 96 = "Trigger Line Ex. (Emerald Check) "; 112 = "Trigger Line Ex. (NiGHTS Mare)"; 128 = "Check for Linedef Executor on FOFs"; 144 = "Egg Capsule"; @@ -1982,6 +1982,24 @@ linedeftypes prefix = "(336)"; } + 337 + { + title = "Emerald Check - Continuous"; + prefix = "(337)"; + } + + 338 + { + title = "Emerald Check - Each Time"; + prefix = "(338)"; + } + + 339 + { + title = "Emerald Check - Once"; + prefix = "(339)"; + } + 399 { title = "Level Load"; diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 7635f03be..940d4b650 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -754,6 +754,21 @@ doom title = "Object Dye - Once"; prefix = "(336)"; } + 337 + { + title = "Emerald Check - Continuous"; + prefix = "(337)"; + } + 338 + { + title = "Emerald Check - Each Time"; + prefix = "(338)"; + } + 339 + { + title = "Emerald Check - Once"; + prefix = "(339)"; + } 399 { title = "Level Load"; @@ -2647,14 +2662,7 @@ udmf { title = "Check if"; type = 11; - enum - { - 0 = "Has all"; - 1 = "Has any"; - 2 = "Has exactly"; - 3 = "Doesn't have all"; - 4 = "Doesn't have any"; - } + enum = "flagcheck"; } } @@ -3063,6 +3071,39 @@ udmf } } + 337 + { + title = "Emerald Check"; + prefix = "(337)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + arg1 + { + title = "Emeralds"; + type = 12; + enum + { + 1 = "Emerald 1"; + 2 = "Emerald 2"; + 4 = "Emerald 3"; + 8 = "Emerald 4"; + 16 = "Emerald 5"; + 32 = "Emerald 6"; + 64 = "Emerald 7"; + } + } + arg2 + { + title = "Check if"; + type = 11; + enum = "flagcheck"; + } + } + 399 { title = "Level Load"; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 1e11ad255..f4a60581a 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -516,6 +516,15 @@ enums 0 = "Red"; 1 = "Blue"; } + + flagcheck + { + 0 = "Has all"; + 1 = "Has any"; + 2 = "Has exactly"; + 3 = "Doesn't have all"; + 4 = "Doesn't have any"; + } } //Default things filters diff --git a/extras/conf/udb/Includes/SRB222_sectors.cfg b/extras/conf/udb/Includes/SRB222_sectors.cfg index d0b7ba082..e02bfd7cc 100644 --- a/extras/conf/udb/Includes/SRB222_sectors.cfg +++ b/extras/conf/udb/Includes/SRB222_sectors.cfg @@ -21,7 +21,7 @@ sectortypes 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)"; + 96 = "Trigger Line Ex. (Emerald Check) "; 112 = "Trigger Line Ex. (NiGHTS Mare)"; 128 = "Check for Linedef Executor on FOFs"; 144 = "Egg Capsule"; @@ -74,7 +74,7 @@ gen_sectortypes 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)"; + 96 = "Trigger Line Ex. (Emerald Check) "; 112 = "Trigger Line Ex. (NiGHTS Mare)"; 128 = "Check for Linedef Executor on FOFs"; 144 = "Egg Capsule"; diff --git a/src/p_setup.c b/src/p_setup.c index 95e3c487b..6a1218f41 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3752,7 +3752,7 @@ static void P_ConvertBinaryMap(void) case 308: //Race only - once lines[i].args[0] = TMT_ONCE; lines[i].args[1] = GTR_RACE; - lines[i].args[2] = TMG_HASANY; + lines[i].args[2] = TMF_HASANY; break; case 309: //CTF red team - continuous case 310: //CTF red team - each time @@ -3915,6 +3915,19 @@ static void P_ConvertBinaryMap(void) } lines[i].special = 334; break; + case 337: //Emerald check - continuous + case 338: //Emerald check - each time + case 339: //Emerald check - once + if (lines[i].special == 339) + lines[i].args[0] = TMT_ONCE; + else if (lines[i].special == 338) + lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMT_EACHTIMEENTERANDEXIT : TMT_EACHTIMEENTER; + else + lines[i].args[0] = TMT_CONTINUOUS; + lines[i].args[1] = EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7; + lines[i].args[2] = TMF_HASALL; + lines[i].special = 337; + break; case 400: //Set tagged sector's floor height/texture case 401: //Set tagged sector's ceiling height/texture lines[i].args[0] = tag; diff --git a/src/p_spec.c b/src/p_spec.c index 340427b80..7c3f01333 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1590,6 +1590,24 @@ static boolean P_CheckPushables(line_t *triggerline, sector_t *caller) } } +static boolean P_CheckEmeralds(INT32 checktype, UINT16 target) +{ + switch (checktype) + { + case TMF_HASALL: + default: + return (emeralds & target) == target; + case TMF_HASANY: + return !!(emeralds & target); + case TMF_HASEXACTLY: + return emeralds == target; + case TMF_DOESNTHAVEALL: + return (emeralds & target) != target; + case TMF_DOESNTHAVEANY: + return !(emeralds & target); + } +} + static void P_ActivateLinedefExecutor(line_t *line, mobj_t *actor, sector_t *caller) { if (line->special < 400 || line->special >= 500) @@ -1720,6 +1738,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller { if (GETSECSPECIAL(caller->special, 2) == 6) { + CONS_Alert(CONS_WARNING, M_GetText("Deprecated emerald check sector type detected. Please use linedef types 337-339 instead.\n")); if (!(ALL7EMERALDS(emeralds))) return false; } @@ -1822,6 +1841,11 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!!(triggerline->args[1]) ^ (triggercolor != color)) return false; } + break; + case 337: // emerald check + if (!P_CheckEmeralds(triggerline->args[2], (UINT16)triggerline->args[1])) + return false; + break; default: break; } @@ -1858,7 +1882,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller || specialtype == 317 // Unlockable trigger || specialtype == 319 // Unlockable || specialtype == 331 // Player skin - || specialtype == 334) // Object dye + || specialtype == 334 // Object dye + || specialtype == 337) // Emerald check && triggerline->args[0] == TMT_ONCE) triggerline->special = 0; } @@ -1907,7 +1932,8 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) || lines[masterline].special == 317 // Condition set trigger || lines[masterline].special == 319 // Unlockable trigger || lines[masterline].special == 331 // Player skin - || lines[masterline].special == 334) // Object dye + || lines[masterline].special == 334 // Object dye + || lines[masterline].special == 337) // Emerald check && lines[masterline].args[0] > TMT_EACHTIMEMASK) continue; @@ -5872,16 +5898,16 @@ static boolean P_CheckGametypeRules(INT32 checktype, UINT32 target) { switch (checktype) { - case TMG_HASALL: + case TMF_HASALL: default: return (gametyperules & target) == target; - case TMG_HASANY: + case TMF_HASANY: return !!(gametyperules & target); - case TMG_HASEXACTLY: + case TMF_HASEXACTLY: return gametyperules == target; - case TMG_DOESNTHAVEALL: + case TMF_DOESNTHAVEALL: return (gametyperules & target) != target; - case TMG_DOESNTHAVEANY: + case TMF_DOESNTHAVEANY: return !(gametyperules & target); } } @@ -6694,6 +6720,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 319: // Unlockable trigger case 331: // Player skin case 334: // Object dye + case 337: // Emerald check if (lines[i].args[0] > TMT_EACHTIMEMASK) P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); break; diff --git a/src/p_spec.h b/src/p_spec.h index c60bdda66..ac42cd464 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -124,12 +124,12 @@ typedef enum typedef enum { - TMG_HASALL = 0, - TMG_HASANY = 1, - TMG_HASEXACTLY = 2, - TMG_DOESNTHAVEALL = 3, - TMG_DOESNTHAVEANY = 4, -} textmapgametypecheck_t; + TMF_HASALL = 0, + TMF_HASANY = 1, + TMF_HASEXACTLY = 2, + TMF_DOESNTHAVEALL = 3, + TMF_DOESNTHAVEANY = 4, +} textmapflagcheck_t; typedef enum { From dc4dd7581013c89cd0116e0cb88818c303f15d51 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 20:57:44 +0100 Subject: [PATCH 181/326] Add NiGHTS mare trigger linedef type and deprecate the NiGHTS mare sector type --- extras/conf/SRB2-22.cfg | 28 +++++++++++++-- extras/conf/udb/Includes/SRB222_linedefs.cfg | 37 ++++++++++++++++++++ src/p_setup.c | 20 ++++++++++- src/p_spec.c | 31 ++++++++++++++-- 4 files changed, 111 insertions(+), 5 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 7c53d99f6..9aeada89b 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -432,7 +432,7 @@ sectortypes 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)"; + 112 = "Trigger Line Ex. (NiGHTS Mare) "; 128 = "Check for Linedef Executor on FOFs"; 144 = "Egg Capsule"; 160 = "Special Stage Time/Spheres Parameters"; @@ -487,7 +487,7 @@ gen_sectortypes 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)"; + 112 = "Trigger Line Ex. (NiGHTS Mare) "; 128 = "Check for Linedef Executor on FOFs"; 144 = "Egg Capsule"; 160 = "Special Stage Time/Spheres Parameters"; @@ -2000,6 +2000,30 @@ linedeftypes prefix = "(339)"; } + 340 + { + title = "NiGHTS Mare - Continuous"; + flags2text = "[1] Mare greater or equal"; + flags64text = "[6] Mare less or equal"; + prefix = "(340)"; + } + + 341 + { + title = "NiGHTS Mare - Each Time"; + flags2text = "[1] Mare greater or equal"; + flags64text = "[6] Mare less or equal"; + prefix = "(341)"; + } + + 342 + { + title = "NiGHTS Mare - Once"; + flags2text = "[1] Mare greater or equal"; + flags64text = "[6] Mare less or equal"; + prefix = "(342)"; + } + 399 { title = "Level Load"; diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 940d4b650..d108821f7 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -769,6 +769,21 @@ doom title = "Emerald Check - Once"; prefix = "(339)"; } + 340 + { + title = "NiGHTS Mare - Continuous"; + prefix = "(340)"; + } + 341 + { + title = "NiGHTS Mare - Each Time"; + prefix = "(341)"; + } + 342 + { + title = "NiGHTS Mare - Once"; + prefix = "(342)"; + } 399 { title = "Level Load"; @@ -3104,6 +3119,28 @@ udmf } } + 340 + { + title = "NiGHTS Mare"; + prefix = "(340)"; + arg0 + { + title = "Trigger type"; + type = 11; + enum = "triggertype"; + } + arg1 + { + title = "Mare"; + } + arg2 + { + title = "Comparison"; + type = 11; + enum = "comparison"; + } + } + 399 { title = "Level Load"; diff --git a/src/p_setup.c b/src/p_setup.c index 6a1218f41..aa687bfa2 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3775,7 +3775,7 @@ static void P_ConvertBinaryMap(void) if (lines[i].flags & ML_NOCLIMB) lines[i].args[2] = TMC_GTE; else if (lines[i].flags & ML_EFFECT4) - lines[i].args[2] = TMC_GTE; + lines[i].args[2] = TMC_LTE; else lines[i].args[2] = TMC_EQUAL; lines[i].special = 314; @@ -3928,6 +3928,24 @@ static void P_ConvertBinaryMap(void) lines[i].args[2] = TMF_HASALL; lines[i].special = 337; break; + case 340: //NiGHTS mare - continuous + case 341: //NiGHTS mare - each time + case 342: //NiGHTS mare - once + if (lines[i].special == 342) + lines[i].args[0] = TMT_ONCE; + else if (lines[i].special == 341) + lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMT_EACHTIMEENTERANDEXIT : TMT_EACHTIMEENTER; + else + lines[i].args[0] = TMT_CONTINUOUS; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] = TMC_LTE; + else if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[2] = TMC_GTE; + else + lines[i].args[2] = TMC_EQUAL; + lines[i].special = 340; + break; case 400: //Set tagged sector's floor height/texture case 401: //Set tagged sector's ceiling height/texture lines[i].args[0] = tag; diff --git a/src/p_spec.c b/src/p_spec.c index 7c3f01333..58f28cddb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1501,7 +1501,7 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) return true; } -static boolean P_CheckPlayerMare(line_t *triggerline) +static boolean P_CheckPlayerMareOld(line_t *triggerline) { UINT8 mare; INT32 targetmare = P_AproxDistance(triggerline->dx, triggerline->dy) >> FRACBITS; @@ -1520,6 +1520,28 @@ static boolean P_CheckPlayerMare(line_t *triggerline) return mare == targetmare; } +static boolean P_CheckPlayerMare(line_t *triggerline) +{ + UINT8 mare; + INT32 targetmare = triggerline->args[1]; + + if (!(maptol & TOL_NIGHTS)) + return false; + + mare = P_FindLowestMare(); + + switch (triggerline->args[2]) + { + case TMC_EQUAL: + default: + return mare == targetmare; + case TMC_GTE: + return mare >= targetmare; + case TMC_LTE: + return mare <= targetmare; + } +} + static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor) { INT32 rings = 0; @@ -1744,7 +1766,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller } else if (GETSECSPECIAL(caller->special, 2) == 7) { - if (!P_CheckPlayerMare(triggerline)) + CONS_Alert(CONS_WARNING, M_GetText("Deprecated NiGHTS mare sector type detected. Please use linedef types 340-342 instead.\n")); + if (!P_CheckPlayerMareOld(triggerline)) return false; } // If we were not triggered by a sector type especially for the purpose, @@ -1846,6 +1869,10 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!P_CheckEmeralds(triggerline->args[2], (UINT16)triggerline->args[1])) return false; break; + case 340: // NiGHTS mare + if (!P_CheckPlayerMare(triggerline)) + return false; + break; default: break; } From cc38cd007114931727233d7496b7dcca37b3512d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 21:00:22 +0100 Subject: [PATCH 182/326] Remove outdated console warning that never happens anyway --- src/p_spec.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 58f28cddb..27bc3b435 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1770,16 +1770,6 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!P_CheckPlayerMareOld(triggerline)) return false; } - // If we were not triggered by a sector type especially for the purpose, - // a Linedef Executor linedef trigger is not handling sector triggers properly, return. - - else if ((!GETSECSPECIAL(caller->special, 2) || GETSECSPECIAL(caller->special, 2) > 7) && (specialtype > 322)) - { - CONS_Alert(CONS_WARNING, - M_GetText("Linedef executor trigger isn't handling sector triggers properly!\nspecialtype = %d, if you are not a dev, report this warning instance\nalong with the wad that caused it!\n"), - specialtype); - return false; - } } switch (specialtype) From a35a3b3edc2e9bacd09c4a6afc95aea5e1078ecc Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 21:15:11 +0100 Subject: [PATCH 183/326] Sector specials: Give up on trying to find polyobjects in touched sectors --- src/p_spec.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 27bc3b435..33109db6b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4049,8 +4049,6 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number) if (result) return result; - //TODO: Check polyobjects in node->m_sector - if (!(node->m_sector->flags & SF_TRIGGERSPECIAL_TOUCH)) continue; @@ -4197,8 +4195,6 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) if (caller) return caller; - //TODO: Check polyobjects in loopsector - if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) continue; @@ -4990,7 +4986,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) } } -static void P_PlayerOnSpecialPolyobj(player_t *player, sector_t *sector) +static void P_PlayerOnSpecialPolyobj(player_t *player) { sector_t *originalsector = player->mo->subsector->sector; polyobj_t *po; @@ -4998,7 +4994,6 @@ static void P_PlayerOnSpecialPolyobj(player_t *player, sector_t *sector) boolean touching = false; boolean inside = false; - //TODO: Check polyobjects in sector for (po = player->mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) { if (po->flags & POF_NOSPECIALS) @@ -5018,7 +5013,7 @@ static void P_PlayerOnSpecialPolyobj(player_t *player, sector_t *sector) if (!P_IsMobjTouchingPolyobj(player->mo, po, polysec)) continue; - P_ProcessSpecialSector(player, polysec, sector); + P_ProcessSpecialSector(player, polysec, originalsector); if TELEPORTED(player->mo) return; } } @@ -5043,7 +5038,7 @@ void P_PlayerInSpecialSector(player_t *player) if TELEPORTED(player->mo) return; // Allow sector specials to be applied to polyobjects! - P_PlayerOnSpecialPolyobj(player, originalsector); + P_PlayerOnSpecialPolyobj(player); if TELEPORTED(player->mo) return; P_ProcessSpecialSector(player, originalsector, NULL); @@ -5061,10 +5056,6 @@ void P_PlayerInSpecialSector(player_t *player) P_PlayerOnSpecial3DFloor(player, loopsector); if TELEPORTED(player->mo) return; - // Check polyobjects... - P_PlayerOnSpecialPolyobj(player, loopsector); - if TELEPORTED(player->mo) return; - if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) continue; From 21f8baea4a0f0a3538e6f0c4b38bf7fe63ccc407 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 21:36:46 +0100 Subject: [PATCH 184/326] Make trigger conditions for "all players" triggers consistent --- src/p_floor.c | 23 +++-------------------- src/p_spec.c | 32 +++++++++++++++++++++++--------- src/p_spec.h | 2 ++ 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index fabc8de28..c3a13d802 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1043,23 +1043,6 @@ void T_MarioBlockChecker(mariocheck_t *block) } } -static boolean P_IsPlayerValid(size_t playernum) -{ - if (!playeringame[playernum]) - return false; - - if (!players[playernum].mo) - return false; - - if (players[playernum].mo->health <= 0) - return false; - - if (players[playernum].spectator) - return false; - - return true; -} - // This is the Thwomp's 'brain'. It looks around for players nearby, and if // it finds any, **SMASH**!!! Muahahhaa.... void T_ThwompSector(thwomp_t *thwomp) @@ -1278,7 +1261,7 @@ static boolean P_CheckAllTrigger(eachtime_t *eachtime) for (i = 0; i < MAXPLAYERS; i++) { - if (P_IsPlayerValid(i) && !eachtime->playersInArea[i]) + if (P_CanPlayerTrigger(i) && !eachtime->playersInArea[i]) return false; } @@ -1297,7 +1280,7 @@ void T_EachTimeThinker(eachtime_t *eachtime) for (i = 0; i < MAXPLAYERS; i++) { oldPlayersInArea[i] = eachtime->playersInArea[i]; - caller[i] = P_IsPlayerValid(i) ? P_FindPlayerTrigger(&players[i], eachtime->sourceline) : NULL; + caller[i] = P_CanPlayerTrigger(i) ? P_FindPlayerTrigger(&players[i], eachtime->sourceline) : NULL; eachtime->playersInArea[i] = caller[i] != NULL; } @@ -1312,7 +1295,7 @@ void T_EachTimeThinker(eachtime_t *eachtime) continue; // If player has just left, check if still valid - if (!eachtime->playersInArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i))) + if (!eachtime->playersInArea[i] && (!eachtime->triggerOnExit || !P_CanPlayerTrigger(i))) continue; // If sector has an "all players" trigger type, all players need to be in area diff --git a/src/p_spec.c b/src/p_spec.c index 33109db6b..a1eb4183c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4205,6 +4205,28 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) return false; } +boolean P_IsPlayerValid(size_t playernum) +{ + if (!playeringame[playernum]) + return false; + + if (!players[playernum].mo) + return false; + + if (players[playernum].mo->health <= 0) + return false; + + if (players[playernum].spectator) + return false; + + return true; +} + +boolean P_CanPlayerTrigger(size_t playernum) +{ + return P_IsPlayerValid(playernum) && !players[playernum].bot; +} + /// \todo check continues for proper splitscreen support? static boolean P_DoAllPlayersTrigger(mtag_t sectag) { @@ -4215,15 +4237,7 @@ static boolean P_DoAllPlayersTrigger(mtag_t sectag) for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i]) - continue; - if (!players[i].mo) - continue; - if (players[i].spectator) - continue; - if (players[i].bot) - continue; - if (G_CoopGametype() && players[i].lives <= 0) + if (!P_CanPlayerTrigger(i)) continue; if (!P_FindPlayerTrigger(&players[i], &dummyline)) return false; diff --git a/src/p_spec.h b/src/p_spec.h index ac42cd464..054f2daf5 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -358,6 +358,8 @@ void P_PlayerInSpecialSector(player_t *player); void P_CheckPushableTrigger(mobj_t *mobj, sector_t *sec); void P_CheckMobjTrigger(mobj_t *mobj); sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline); +boolean P_IsPlayerValid(size_t playernum); +boolean P_CanPlayerTrigger(size_t playernum); void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector); fixed_t P_FindLowestFloorSurrounding(sector_t *sec); From 2c0fb5e80fa60d875031b9b2204b8eeff79084ab Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 9 Dec 2021 22:12:48 +0100 Subject: [PATCH 185/326] Delete accidentally added .orig file --- src/p_spec.c.orig | 9150 --------------------------------------------- 1 file changed, 9150 deletions(-) delete mode 100644 src/p_spec.c.orig diff --git a/src/p_spec.c.orig b/src/p_spec.c.orig deleted file mode 100644 index 244f7166b..000000000 --- a/src/p_spec.c.orig +++ /dev/null @@ -1,9150 +0,0 @@ -// SONIC ROBO BLAST 2 -//----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2021 by Sonic Team Junior. -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- -/// \file p_spec.c -/// \brief Implements special effects: -/// Texture animation, height or lighting changes -/// according to adjacent sectors, respective -/// utility functions, etc. -/// Line Tag handling. Line and Sector triggers. - -#include "dehacked.h" -#include "doomdef.h" -#include "g_game.h" -#include "p_local.h" -#include "p_setup.h" // levelflats for flat animation -#include "r_data.h" -#include "r_textures.h" -#include "m_random.h" -#include "p_mobj.h" -#include "i_system.h" -#include "s_sound.h" -#include "w_wad.h" -#include "z_zone.h" -#include "r_main.h" //Two extra includes. -#include "r_sky.h" -#include "p_polyobj.h" -#include "p_slopes.h" -#include "hu_stuff.h" -#include "v_video.h" // V_AUTOFADEOUT|V_ALLOWLOWERCASE -#include "m_misc.h" -#include "m_cond.h" //unlock triggers -#include "lua_hook.h" // LUA_HookLinedefExecute -#include "f_finale.h" // control text prompt -#include "r_skins.h" // skins - -#ifdef HW3SOUND -#include "hardware/hw3sound.h" -#endif - -// Not sure if this is necessary, but it was in w_wad.c, so I'm putting it here too -Shadow Hog -#include - -mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpoint -mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs -mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs - -// Amount (dx, dy) vector linedef is shifted right to get scroll amount -#define SCROLL_SHIFT 5 - -/** Animated texture descriptor - * This keeps track of an animated texture or an animated flat. - * \sa P_UpdateSpecials, P_InitPicAnims, animdef_t - */ -typedef struct -{ - SINT8 istexture; ///< ::true for a texture, ::false for a flat - INT32 picnum; ///< The end flat number - INT32 basepic; ///< The start flat number - INT32 numpics; ///< Number of frames in the animation - tic_t speed; ///< Number of tics for which each frame is shown -} anim_t; - -#if defined(_MSC_VER) -#pragma pack(1) -#endif - -/** Animated texture definition. - * Used for loading an ANIMDEFS lump from a wad. - * - * Animations are defined by the first and last frame (i.e., flat or texture). - * The animation sequence uses all flats between the start and end entry, in - * the order found in the wad. - * - * \sa anim_t - */ -typedef struct -{ - SINT8 istexture; ///< True for a texture, false for a flat. - char endname[9]; ///< Name of the last frame, null-terminated. - char startname[9]; ///< Name of the first frame, null-terminated. - INT32 speed ; ///< Number of tics for which each frame is shown. -} ATTRPACK animdef_t; - -#if defined(_MSC_VER) -#pragma pack() -#endif - -typedef struct -{ - UINT32 count; - thinker_t **thinkers; -} thinkerlist_t; - -static void P_SpawnScrollers(void); -static void P_SpawnFriction(void); -static void P_SpawnPushers(void); -static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 -static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); -static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); -#define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL, false); -static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, - boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, - boolean docollision, boolean doghostfade, boolean exactalpha); -static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, - INT16 destvalue, INT16 speed, boolean ticbased, boolean relative, - boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, - boolean docollision, boolean doghostfade, boolean exactalpha); -static void P_ResetColormapFader(sector_t *sector); -static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, - boolean ticbased, INT32 duration); -static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); -static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline); -//static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); -static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorflags, thinkerlist_t *secthinkers); -static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec); -static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer); -static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee, UINT8 reverse); - - -//SoM: 3/7/2000: New sturcture without limits. -static anim_t *lastanim; -static anim_t *anims = NULL; /// \todo free leak -static size_t maxanims; - -// Animating line specials - -// Init animated textures -// - now called at level loading P_SetupLevel() - -static animdef_t *animdefs = NULL; - -// Increase the size of animdefs to make room for a new animation definition -static void GrowAnimDefs(void) -{ - maxanims++; - animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); -} - -// A prototype; here instead of p_spec.h, so they're "private" -void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum); -void P_ParseAnimationDefintion(SINT8 istexture); - -/** Sets up texture and flat animations. - * - * Converts an ::animdef_t array loaded from a lump into - * ::anim_t format. - * - * Issues an error if any animation cycles are invalid. - * - * \sa P_FindAnimatedFlat, P_SetupLevelFlatAnims - * \author Steven McGranahan (original), Shadow Hog (had to rewrite it to handle multiple WADs), JTE (had to rewrite it to handle multiple WADs _correctly_) - */ -void P_InitPicAnims(void) -{ - // Init animation - INT32 w; // WAD - size_t i; - - I_Assert(animdefs == NULL); - - maxanims = 0; - - for (w = numwadfiles-1; w >= 0; w--) - { - UINT16 animdefsLumpNum; - - // Find ANIMDEFS lump in the WAD - animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0); - - while (animdefsLumpNum != INT16_MAX) - { - P_ParseANIMDEFSLump(w, animdefsLumpNum); - animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", (UINT16)w, animdefsLumpNum + 1); - } - } - - // Define the last one - animdefs[maxanims].istexture = -1; - strncpy(animdefs[maxanims].endname, "", 9); - strncpy(animdefs[maxanims].startname, "", 9); - animdefs[maxanims].speed = 0; - - if (anims) - free(anims); - - anims = (anim_t *)malloc(sizeof (*anims)*(maxanims + 1)); - if (!anims) - I_Error("Not enough free memory for ANIMDEFS data"); - - lastanim = anims; - for (i = 0; animdefs[i].istexture != -1; i++) - { - if (animdefs[i].istexture) - { - if (R_CheckTextureNumForName(animdefs[i].startname) == -1) - continue; - - lastanim->picnum = R_TextureNumForName(animdefs[i].endname); - lastanim->basepic = R_TextureNumForName(animdefs[i].startname); - } - else - { - if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR) - continue; - - lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname); - lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname); - } - - lastanim->istexture = animdefs[i].istexture; - lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; - - if (lastanim->numpics < 2) - { - free(anims); - I_Error("P_InitPicAnims: bad cycle from %s to %s", - animdefs[i].startname, animdefs[i].endname); - } - - lastanim->speed = LONG(animdefs[i].speed); - lastanim++; - } - lastanim->istexture = -1; - R_ClearTextureNumCache(false); - - // Clear animdefs now that we're done with it. - // We'll only be using anims from now on. - Z_Free(animdefs); - animdefs = NULL; -} - -void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum) -{ - char *animdefsLump; - size_t animdefsLumpLength; - char *animdefsText; - char *animdefsToken; - char *p; - - // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll - // need to make a space of memory where I can ensure that it will terminate - // correctly. Start by loading the relevant data from the WAD. - animdefsLump = (char *)W_CacheLumpNumPwad(wadNum,lumpnum,PU_STATIC); - // If that didn't exist, we have nothing to do here. - if (animdefsLump == NULL) return; - // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. - animdefsLumpLength = W_LumpLengthPwad(wadNum,lumpnum); - animdefsText = (char *)Z_Malloc((animdefsLumpLength+1)*sizeof(char),PU_STATIC,NULL); - // Now move the contents of the lump into this new location. - memmove(animdefsText,animdefsLump,animdefsLumpLength); - // Make damn well sure the last character in our new memory location is \0. - animdefsText[animdefsLumpLength] = '\0'; - // Finally, free up the memory from the first data load, because we really - // don't need it. - Z_Free(animdefsLump); - - // Now, let's start parsing this thing - p = animdefsText; - animdefsToken = M_GetToken(p); - while (animdefsToken != NULL) - { - if (stricmp(animdefsToken, "TEXTURE") == 0) - { - Z_Free(animdefsToken); - P_ParseAnimationDefintion(1); - } - else if (stricmp(animdefsToken, "FLAT") == 0) - { - Z_Free(animdefsToken); - P_ParseAnimationDefintion(0); - } - else if (stricmp(animdefsToken, "OSCILLATE") == 0) - { - // This probably came off the tail of an earlier definition. It's technically legal syntax, but we don't support it. - I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"OSCILLATE\" (the animation plays in reverse when it reaches the end) are not supported by SRB2"); - } - else - { - I_Error("Error parsing ANIMDEFS lump: Expected \"TEXTURE\" or \"FLAT\", got \"%s\"",animdefsToken); - } - // parse next line - while (*p != '\0' && *p != '\n') ++p; - if (*p == '\n') ++p; - animdefsToken = M_GetToken(p); - } - Z_Free(animdefsToken); - Z_Free((void *)animdefsText); -} - -void P_ParseAnimationDefintion(SINT8 istexture) -{ - char *animdefsToken; - size_t animdefsTokenLength; - char *endPos; - INT32 animSpeed; - size_t i; - - // Startname - animdefsToken = M_GetToken(NULL); - if (animdefsToken == NULL) - { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where start texture/flat name should be"); - } - if (stricmp(animdefsToken, "OPTIONAL") == 0) - { - // This is meaningful to ZDoom - it tells the program NOT to bomb out - // if the textures can't be found - but it's useless in SRB2, so we'll - // just smile, nod, and carry on - Z_Free(animdefsToken); - animdefsToken = M_GetToken(NULL); - - if (animdefsToken == NULL) - { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where start texture/flat name should be"); - } - else if (stricmp(animdefsToken, "RANGE") == 0) - { - // Oh. Um. Apparently "OPTIONAL" is a texture name. Naughty. - // I should probably handle this more gracefully, but right now - // I can't be bothered; especially since ZDoom doesn't handle this - // condition at all. - I_Error("Error parsing ANIMDEFS lump: \"OPTIONAL\" is a keyword; you cannot use it as the startname of an animation"); - } - } - animdefsTokenLength = strlen(animdefsToken); - if (animdefsTokenLength>8) - { - I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); - } - - // Search for existing animdef - for (i = 0; i < maxanims; i++) - if (animdefs[i].istexture == istexture // Check if it's the same type! - && stricmp(animdefsToken, animdefs[i].startname) == 0) - { - //CONS_Alert(CONS_NOTICE, "Duplicate animation: %s\n", animdefsToken); - - // If we weren't parsing in reverse order, we would `break` here and parse the new data into the existing slot we found. - // Instead, we're just going to skip parsing the rest of this line entirely. - Z_Free(animdefsToken); - return; - } - - // Not found - if (i == maxanims) - { - // Increase the size to make room for the new animation definition - GrowAnimDefs(); - strncpy(animdefs[i].startname, animdefsToken, 9); - } - - // animdefs[i].startname is now set to animdefsToken either way. - Z_Free(animdefsToken); - - // set texture type - animdefs[i].istexture = istexture; - - // "RANGE" - animdefsToken = M_GetToken(NULL); - if (animdefsToken == NULL) - { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"RANGE\" after \"%s\"'s startname should be", animdefs[i].startname); - } - if (stricmp(animdefsToken, "ALLOWDECALS") == 0) - { - // Another ZDoom keyword, ho-hum. Skip it, move on to the next token. - Z_Free(animdefsToken); - animdefsToken = M_GetToken(NULL); - } - if (stricmp(animdefsToken, "PIC") == 0) - { - // This is technically legitimate ANIMDEFS syntax, but SRB2 doesn't support it. - I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"PIC\" (specific frames instead of a consecutive range) are not supported by SRB2"); - } - if (stricmp(animdefsToken, "RANGE") != 0) - { - I_Error("Error parsing ANIMDEFS lump: Expected \"RANGE\" after \"%s\"'s startname, got \"%s\"", animdefs[i].startname, animdefsToken); - } - Z_Free(animdefsToken); - - // Endname - animdefsToken = M_GetToken(NULL); - if (animdefsToken == NULL) - { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s end texture/flat name should be", animdefs[i].startname); - } - animdefsTokenLength = strlen(animdefsToken); - if (animdefsTokenLength>8) - { - I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); - } - strncpy(animdefs[i].endname, animdefsToken, 9); - Z_Free(animdefsToken); - - // "TICS" - animdefsToken = M_GetToken(NULL); - if (animdefsToken == NULL) - { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s \"TICS\" should be", animdefs[i].startname); - } - if (stricmp(animdefsToken, "RAND") == 0) - { - // This is technically legitimate ANIMDEFS syntax, but SRB2 doesn't support it. - I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"RAND\" (random duration per frame) are not supported by SRB2"); - } - if (stricmp(animdefsToken, "TICS") != 0) - { - I_Error("Error parsing ANIMDEFS lump: Expected \"TICS\" in animation definition for \"%s\", got \"%s\"", animdefs[i].startname, animdefsToken); - } - Z_Free(animdefsToken); - - // Speed - animdefsToken = M_GetToken(NULL); - if (animdefsToken == NULL) - { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s animation speed should be", animdefs[i].startname); - } - endPos = NULL; -#ifndef AVOID_ERRNO - errno = 0; -#endif - animSpeed = strtol(animdefsToken,&endPos,10); - if (endPos == animdefsToken // Empty string - || *endPos != '\0' // Not end of string -#ifndef AVOID_ERRNO - || errno == ERANGE // Number out-of-range -#endif - || animSpeed < 0) // Number is not positive - { - I_Error("Error parsing ANIMDEFS lump: Expected a positive integer for \"%s\"'s animation speed, got \"%s\"", animdefs[i].startname, animdefsToken); - } - animdefs[i].speed = animSpeed; - Z_Free(animdefsToken); - -#ifdef WALLFLATS - // hehe... uhh..... - if (!istexture) - { - GrowAnimDefs(); - M_Memcpy(&animdefs[maxanims-1], &animdefs[i], sizeof(animdef_t)); - animdefs[maxanims-1].istexture = 1; - } -#endif -} - -/** Checks for flats in levelflats that are part of a flat animation sequence - * and sets them up for animation. - * - * \param animnum Index into ::anims to find flats for. - * \sa P_SetupLevelFlatAnims - */ -static inline void P_FindAnimatedFlat(INT32 animnum) -{ - size_t i; - lumpnum_t startflatnum, endflatnum; - levelflat_t *foundflats; - - foundflats = levelflats; - startflatnum = anims[animnum].basepic; - endflatnum = anims[animnum].picnum; - - // note: high word of lumpnum is the wad number - if ((startflatnum>>16) != (endflatnum>>16)) - I_Error("AnimatedFlat start %s not in same wad as end %s\n", - animdefs[animnum].startname, animdefs[animnum].endname); - - // - // now search through the levelflats if this anim flat sequence is used - // - for (i = 0; i < numlevelflats; i++, foundflats++) - { - // is that levelflat from the flat anim sequence ? - if ((anims[animnum].istexture) && (foundflats->type == LEVELFLAT_TEXTURE) - && ((UINT16)foundflats->u.texture.num >= startflatnum && (UINT16)foundflats->u.texture.num <= endflatnum)) - { - foundflats->u.texture.basenum = startflatnum; - foundflats->animseq = foundflats->u.texture.num - startflatnum; - foundflats->numpics = endflatnum - startflatnum + 1; - foundflats->speed = anims[animnum].speed; - - CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n", - atoi(sizeu1(i)), foundflats->name, foundflats->animseq, - foundflats->numpics,foundflats->speed); - } - else if ((!anims[animnum].istexture) && (foundflats->type == LEVELFLAT_FLAT) - && (foundflats->u.flat.lumpnum >= startflatnum && foundflats->u.flat.lumpnum <= endflatnum)) - { - foundflats->u.flat.baselumpnum = startflatnum; - foundflats->animseq = foundflats->u.flat.lumpnum - startflatnum; - foundflats->numpics = endflatnum - startflatnum + 1; - foundflats->speed = anims[animnum].speed; - - CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n", - atoi(sizeu1(i)), foundflats->name, foundflats->animseq, - foundflats->numpics,foundflats->speed); - } - } -} - -/** Sets up all flats used in a level. - * - * \sa P_InitPicAnims, P_FindAnimatedFlat - */ -void P_SetupLevelFlatAnims(void) -{ - INT32 i; - - // the original game flat anim sequences - for (i = 0; anims[i].istexture != -1; i++) - P_FindAnimatedFlat(i); -} - -// -// UTILITIES -// - -#if 0 -/** Gets a side from a sector line. - * - * \param currentSector Sector the line is in. - * \param line Index of the line within the sector. - * \param side 0 for front, 1 for back. - * \return Pointer to the side_t of the side you want. - * \sa getSector, twoSided, getNextSector - */ -static inline side_t *getSide(INT32 currentSector, INT32 line, INT32 side) -{ - return &sides[(sectors[currentSector].lines[line])->sidenum[side]]; -} - -/** Gets a sector from a sector line. - * - * \param currentSector Sector the line is in. - * \param line Index of the line within the sector. - * \param side 0 for front, 1 for back. - * \return Pointer to the ::sector_t of the sector on that side. - * \sa getSide, twoSided, getNextSector - */ -static inline sector_t *getSector(INT32 currentSector, INT32 line, INT32 side) -{ - return sides[(sectors[currentSector].lines[line])->sidenum[side]].sector; -} - -/** Determines whether a sector line is two-sided. - * Uses the Boom method, checking if the line's back side is set to -1, rather - * than looking for ::ML_TWOSIDED. - * - * \param sector The sector. - * \param line Line index within the sector. - * \return 1 if the sector is two-sided, 0 otherwise. - * \sa getSide, getSector, getNextSector - */ -static inline boolean twoSided(INT32 sector, INT32 line) -{ - return (sectors[sector].lines[line])->sidenum[1] != 0xffff; -} -#endif - -/** Finds sector next to current. - * - * \param line Pointer to the line to cross. - * \param sec Pointer to the current sector. - * \return Pointer to a ::sector_t of the adjacent sector, or NULL if the line - * is one-sided. - * \sa getSide, getSector, twoSided - * \author Steven McGranahan - */ -static sector_t *getNextSector(line_t *line, sector_t *sec) -{ - if (line->frontsector == sec) - { - if (line->backsector != sec) - return line->backsector; - else - return NULL; - } - return line->frontsector; -} - -/** Finds lowest floor in adjacent sectors. - * - * \param sec Sector to start in. - * \return Lowest floor height in an adjacent sector. - * \sa P_FindHighestFloorSurrounding, P_FindNextLowestFloor, - * P_FindLowestCeilingSurrounding - */ -fixed_t P_FindLowestFloorSurrounding(sector_t *sec) -{ - size_t i; - line_t *check; - sector_t *other; - fixed_t floorh; - - floorh = sec->floorheight; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check,sec); - - if (!other) - continue; - - if (other->floorheight < floorh) - floorh = other->floorheight; - } - return floorh; -} - -/** Finds highest floor in adjacent sectors. - * - * \param sec Sector to start in. - * \return Highest floor height in an adjacent sector. - * \sa P_FindLowestFloorSurrounding, P_FindNextHighestFloor, - * P_FindHighestCeilingSurrounding - */ -fixed_t P_FindHighestFloorSurrounding(sector_t *sec) -{ - size_t i; - line_t *check; - sector_t *other; - fixed_t floorh = -500*FRACUNIT; - INT32 foundsector = 0; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - - if (!other) - continue; - - if (other->floorheight > floorh || !foundsector) - floorh = other->floorheight; - - if (!foundsector) - foundsector = 1; - } - return floorh; -} - -/** Finds next highest floor in adjacent sectors. - * - * \param sec Sector to start in. - * \param currentheight Height to start at. - * \return Next highest floor height in an adjacent sector, or currentheight - * if there are none higher. - * \sa P_FindHighestFloorSurrounding, P_FindNextLowestFloor, - * P_FindNextHighestCeiling - * \author Lee Killough - */ -fixed_t P_FindNextHighestFloor(sector_t *sec, fixed_t currentheight) -{ - sector_t *other; - size_t i; - fixed_t height; - - for (i = 0; i < sec->linecount; i++) - { - other = getNextSector(sec->lines[i],sec); - if (other && other->floorheight > currentheight) - { - height = other->floorheight; - while (++i < sec->linecount) - { - other = getNextSector(sec->lines[i], sec); - if (other && - other->floorheight < height && - other->floorheight > currentheight) - height = other->floorheight; - } - return height; - } - } - return currentheight; -} - -//////////////////////////////////////////////////// -// SoM: Start new Boom functions -//////////////////////////////////////////////////// - -/** Finds next lowest floor in adjacent sectors. - * - * \param sec Sector to start in. - * \param currentheight Height to start at. - * \return Next lowest floor height in an adjacent sector, or currentheight - * if there are none lower. - * \sa P_FindLowestFloorSurrounding, P_FindNextHighestFloor, - * P_FindNextLowestCeiling - * \author Lee Killough - */ -fixed_t P_FindNextLowestFloor(sector_t *sec, fixed_t currentheight) -{ - sector_t *other; - size_t i; - fixed_t height; - - for (i = 0; i < sec->linecount; i++) - { - other = getNextSector(sec->lines[i], sec); - if (other && other->floorheight < currentheight) - { - height = other->floorheight; - while (++i < sec->linecount) - { - other = getNextSector(sec->lines[i], sec); - if (other && other->floorheight > height - && other->floorheight < currentheight) - height = other->floorheight; - } - return height; - } - } - return currentheight; -} - -#if 0 -/** Finds next lowest ceiling in adjacent sectors. - * - * \param sec Sector to start in. - * \param currentheight Height to start at. - * \return Next lowest ceiling height in an adjacent sector, or currentheight - * if there are none lower. - * \sa P_FindLowestCeilingSurrounding, P_FindNextHighestCeiling, - * P_FindNextLowestFloor - * \author Lee Killough - */ -static fixed_t P_FindNextLowestCeiling(sector_t *sec, fixed_t currentheight) -{ - sector_t *other; - size_t i; - fixed_t height; - - for (i = 0; i < sec->linecount; i++) - { - other = getNextSector(sec->lines[i],sec); - if (other && other->ceilingheight < currentheight) - { - height = other->ceilingheight; - while (++i < sec->linecount) - { - other = getNextSector(sec->lines[i],sec); - if (other && other->ceilingheight > height - && other->ceilingheight < currentheight) - height = other->ceilingheight; - } - return height; - } - } - return currentheight; -} - -/** Finds next highest ceiling in adjacent sectors. - * - * \param sec Sector to start in. - * \param currentheight Height to start at. - * \return Next highest ceiling height in an adjacent sector, or currentheight - * if there are none higher. - * \sa P_FindHighestCeilingSurrounding, P_FindNextLowestCeiling, - * P_FindNextHighestFloor - * \author Lee Killough - */ -static fixed_t P_FindNextHighestCeiling(sector_t *sec, fixed_t currentheight) -{ - sector_t *other; - size_t i; - fixed_t height; - - for (i = 0; i < sec->linecount; i++) - { - other = getNextSector(sec->lines[i], sec); - if (other && other->ceilingheight > currentheight) - { - height = other->ceilingheight; - while (++i < sec->linecount) - { - other = getNextSector(sec->lines[i],sec); - if (other && other->ceilingheight < height - && other->ceilingheight > currentheight) - height = other->ceilingheight; - } - return height; - } - } - return currentheight; -} -#endif - -//////////////////////////// -// End New Boom functions -//////////////////////////// - -/** Finds lowest ceiling in adjacent sectors. - * - * \param sec Sector to start in. - * \return Lowest ceiling height in an adjacent sector. - * \sa P_FindHighestCeilingSurrounding, P_FindNextLowestCeiling, - * P_FindLowestFloorSurrounding - */ -fixed_t P_FindLowestCeilingSurrounding(sector_t *sec) -{ - size_t i; - line_t *check; - sector_t *other; - fixed_t height = 32000*FRACUNIT; //SoM: 3/7/2000: Remove ovf - INT32 foundsector = 0; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - - if (!other) - continue; - - if (other->ceilingheight < height || !foundsector) - height = other->ceilingheight; - - if (!foundsector) - foundsector = 1; - } - return height; -} - -/** Finds Highest ceiling in adjacent sectors. - * - * \param sec Sector to start in. - * \return Highest ceiling height in an adjacent sector. - * \sa P_FindLowestCeilingSurrounding, P_FindNextHighestCeiling, - * P_FindHighestFloorSurrounding - */ -fixed_t P_FindHighestCeilingSurrounding(sector_t *sec) -{ - size_t i; - line_t *check; - sector_t *other; - fixed_t height = 0; - INT32 foundsector = 0; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - - if (!other) - continue; - - if (other->ceilingheight > height || !foundsector) - height = other->ceilingheight; - - if (!foundsector) - foundsector = 1; - } - return height; -} - -#if 0 -//SoM: 3/7/2000: UTILS..... -// -// P_FindShortestTextureAround() -// -// Passed a sector number, returns the shortest lower texture on a -// linedef bounding the sector. -// -// -static fixed_t P_FindShortestTextureAround(INT32 secnum) -{ - fixed_t minsize = 32000<linecount; i++) - { - if (twoSided(secnum, i)) - { - side = getSide(secnum,i,0); - if (side->bottomtexture > 0) - if (textureheight[side->bottomtexture] < minsize) - minsize = textureheight[side->bottomtexture]; - side = getSide(secnum,i,1); - if (side->bottomtexture > 0) - if (textureheight[side->bottomtexture] < minsize) - minsize = textureheight[side->bottomtexture]; - } - } - return minsize; -} - -//SoM: 3/7/2000: Stuff.... (can you tell I'm getting tired? It's 12 : 30!) -// -// P_FindShortestUpperAround() -// -// Passed a sector number, returns the shortest upper texture on a -// linedef bounding the sector. -// -// -static fixed_t P_FindShortestUpperAround(INT32 secnum) -{ - fixed_t minsize = 32000<linecount; i++) - { - if (twoSided(secnum, i)) - { - side = getSide(secnum,i,0); - if (side->toptexture > 0) - if (textureheight[side->toptexture] < minsize) - minsize = textureheight[side->toptexture]; - side = getSide(secnum,i,1); - if (side->toptexture > 0) - if (textureheight[side->toptexture] < minsize) - minsize = textureheight[side->toptexture]; - } - } - return minsize; -} - -//SoM: 3/7/2000 -// -// P_FindModelFloorSector() -// -// Passed a floor height and a sector number, return a pointer to a -// a sector with that floor height across the lowest numbered two sided -// line surrounding the sector. -// -// Note: If no sector at that height bounds the sector passed, return NULL -// -// -static sector_t *P_FindModelFloorSector(fixed_t floordestheight, INT32 secnum) -{ - size_t i; - sector_t *sec = §ors[secnum]; - - for (i = 0; i < sec->linecount; i++) - { - if (twoSided(secnum, i)) - { - if (getSide(secnum,i,0)->sector-sectors == secnum) - sec = getSector(secnum,i,1); - else - sec = getSector(secnum,i,0); - - if (sec->floorheight == floordestheight) - return sec; - } - } - return NULL; -} - -// -// P_FindModelCeilingSector() -// -// Passed a ceiling height and a sector number, return a pointer to a -// a sector with that ceiling height across the lowest numbered two sided -// line surrounding the sector. -// -// Note: If no sector at that height bounds the sector passed, return NULL -// -static sector_t *P_FindModelCeilingSector(fixed_t ceildestheight, INT32 secnum) -{ - size_t i; - sector_t *sec = §ors[secnum]; - - for (i = 0; i < sec->linecount; i++) - { - if (twoSided(secnum, i)) - { - if (getSide(secnum, i, 0)->sector - sectors == secnum) - sec = getSector(secnum, i, 1); - else - sec = getSector(secnum, i, 0); - - if (sec->ceilingheight == ceildestheight) - return sec; - } - } - return NULL; -} -#endif - -// Parses arguments for parameterized polyobject door types -static boolean PolyDoor(line_t *line) -{ - polydoordata_t pdd; - - pdd.polyObjNum = Tag_FGet(&line->tags); // polyobject id - - switch(line->special) - { - case 480: // Polyobj_DoorSlide - pdd.doorType = POLY_DOOR_SLIDE; - pdd.speed = sides[line->sidenum[0]].textureoffset / 8; - pdd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); // angle of motion - pdd.distance = sides[line->sidenum[0]].rowoffset; - - if (line->sidenum[1] != 0xffff) - pdd.delay = sides[line->sidenum[1]].textureoffset >> FRACBITS; // delay in tics - else - pdd.delay = 0; - break; - case 481: // Polyobj_DoorSwing - pdd.doorType = POLY_DOOR_SWING; - pdd.speed = sides[line->sidenum[0]].textureoffset >> FRACBITS; // angular speed - pdd.distance = sides[line->sidenum[0]].rowoffset >> FRACBITS; // angular distance - - if (line->sidenum[1] != 0xffff) - pdd.delay = sides[line->sidenum[1]].textureoffset >> FRACBITS; // delay in tics - else - pdd.delay = 0; - break; - default: - return 0; // ??? - } - - return EV_DoPolyDoor(&pdd); -} - -// Parses arguments for parameterized polyobject move specials -static boolean PolyMove(line_t *line) -{ - polymovedata_t pmd; - - pmd.polyObjNum = Tag_FGet(&line->tags); - pmd.speed = sides[line->sidenum[0]].textureoffset / 8; - pmd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); - pmd.distance = sides[line->sidenum[0]].rowoffset; - - pmd.overRide = (line->special == 483); // Polyobj_OR_Move - - return EV_DoPolyObjMove(&pmd); -} - -// Makes a polyobject invisible and intangible -// If NOCLIMB is ticked, the polyobject will still be tangible, just not visible. -static void PolyInvisible(line_t *line) -{ - INT32 polyObjNum = Tag_FGet(&line->tags); - polyobj_t *po; - - if (!(po = Polyobj_GetForNum(polyObjNum))) - { - CONS_Debug(DBG_POLYOBJ, "PolyInvisible: bad polyobj %d\n", polyObjNum); - return; - } - - // don't allow line actions to affect bad polyobjects - if (po->isBad) - return; - - if (!(line->flags & ML_NOCLIMB)) - po->flags &= ~POF_SOLID; - - po->flags |= POF_NOSPECIALS; - po->flags &= ~POF_RENDERALL; -} - -// Makes a polyobject visible and tangible -// If NOCLIMB is ticked, the polyobject will not be tangible, just visible. -static void PolyVisible(line_t *line) -{ - INT32 polyObjNum = Tag_FGet(&line->tags); - polyobj_t *po; - - if (!(po = Polyobj_GetForNum(polyObjNum))) - { - CONS_Debug(DBG_POLYOBJ, "PolyVisible: bad polyobj %d\n", polyObjNum); - return; - } - - // don't allow line actions to affect bad polyobjects - if (po->isBad) - return; - - if (!(line->flags & ML_NOCLIMB)) - po->flags |= POF_SOLID; - - po->flags &= ~POF_NOSPECIALS; - po->flags |= (po->spawnflags & POF_RENDERALL); -} - - -// Sets the translucency of a polyobject -// Frontsector floor / 100 = translevel -static void PolyTranslucency(line_t *line) -{ - INT32 polyObjNum = Tag_FGet(&line->tags); - polyobj_t *po; - INT32 value; - - if (!(po = Polyobj_GetForNum(polyObjNum))) - { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: bad polyobj %d\n", polyObjNum); - return; - } - - // don't allow line actions to affect bad polyobjects - if (po->isBad) - return; - - // If Front X Offset is specified, use that. Else, use floorheight. - value = (sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : line->frontsector->floorheight) >> FRACBITS; - - // If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000. - if (!(line->flags & ML_DONTPEGBOTTOM)) - value /= 100; - - if (line->flags & ML_EFFECT3) // relative calc - po->translucency += value; - else - po->translucency = value; - - po->translucency = max(min(po->translucency, NUMTRANSMAPS), 0); -} - -// Makes a polyobject translucency fade and applies tangibility -static boolean PolyFade(line_t *line) -{ - INT32 polyObjNum = Tag_FGet(&line->tags); - polyobj_t *po; - polyfadedata_t pfd; - INT32 value; - - if (!(po = Polyobj_GetForNum(polyObjNum))) - { - CONS_Debug(DBG_POLYOBJ, "PolyFade: bad polyobj %d\n", polyObjNum); - return 0; - } - - // don't allow line actions to affect bad polyobjects - if (po->isBad) - return 0; - - // Prevent continuous execs from interfering on an existing fade - if (!(line->flags & ML_EFFECT5) - && po->thinker - && po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade) - { - CONS_Debug(DBG_POLYOBJ, "Line type 492 Executor: Fade PolyObject thinker already exists\n"); - return 0; - } - - pfd.polyObjNum = polyObjNum; - - // If Front X Offset is specified, use that. Else, use floorheight. - value = (sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : line->frontsector->floorheight) >> FRACBITS; - - // If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000. - if (!(line->flags & ML_DONTPEGBOTTOM)) - value /= 100; - - if (line->flags & ML_EFFECT3) // relative calc - pfd.destvalue = po->translucency + value; - else - pfd.destvalue = value; - - pfd.destvalue = max(min(pfd.destvalue, NUMTRANSMAPS), 0); - - // already equal, nothing to do - if (po->translucency == pfd.destvalue) - return 1; - - pfd.docollision = !(line->flags & ML_BOUNCY); // do not handle collision flags - pfd.doghostfade = (line->flags & ML_EFFECT1); // do ghost fade (no collision flags during fade) - pfd.ticbased = (line->flags & ML_EFFECT4); // Speed = Tic Duration - - // allow Back Y Offset to be consistent with other fade specials - pfd.speed = (line->sidenum[1] != 0xFFFF && !sides[line->sidenum[0]].rowoffset) ? - abs(sides[line->sidenum[1]].rowoffset>>FRACBITS) - : abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); - - - return EV_DoPolyObjFade(&pfd); -} - -// Parses arguments for parameterized polyobject waypoint movement -static boolean PolyWaypoint(line_t *line) -{ - polywaypointdata_t pwd; - - pwd.polyObjNum = Tag_FGet(&line->tags); - pwd.speed = sides[line->sidenum[0]].textureoffset / 8; - pwd.sequence = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Sequence # - - // Behavior after reaching the last waypoint? - if (line->flags & ML_EFFECT3) - pwd.returnbehavior = PWR_WRAP; // Wrap back to first waypoint - else if (line->flags & ML_EFFECT2) - pwd.returnbehavior = PWR_COMEBACK; // Go through sequence in reverse - else - pwd.returnbehavior = PWR_STOP; // Stop - - // Flags - pwd.flags = 0; - if (line->flags & ML_EFFECT1) - pwd.flags |= PWF_REVERSE; - if (line->flags & ML_EFFECT4) - pwd.flags |= PWF_LOOP; - - return EV_DoPolyObjWaypoint(&pwd); -} - -// Parses arguments for parameterized polyobject rotate specials -static boolean PolyRotate(line_t *line) -{ - polyrotdata_t prd; - - prd.polyObjNum = Tag_FGet(&line->tags); - prd.speed = sides[line->sidenum[0]].textureoffset >> FRACBITS; // angular speed - prd.distance = sides[line->sidenum[0]].rowoffset >> FRACBITS; // angular distance - - // Polyobj_(OR_)RotateRight have dir == -1 - prd.direction = (line->special == 484 || line->special == 485) ? -1 : 1; - - // Polyobj_OR types have override set to true - prd.overRide = (line->special == 485 || line->special == 487); - - if (line->flags & ML_NOCLIMB) - prd.turnobjs = 0; - else if (line->flags & ML_EFFECT4) - prd.turnobjs = 2; - else - prd.turnobjs = 1; - - return EV_DoPolyObjRotate(&prd); -} - -// Parses arguments for polyobject flag waving special -static boolean PolyFlag(line_t *line) -{ - polyflagdata_t pfd; - - pfd.polyObjNum = Tag_FGet(&line->tags); - pfd.speed = P_AproxDistance(line->dx, line->dy) >> FRACBITS; - pfd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y) >> ANGLETOFINESHIFT; - pfd.momx = sides[line->sidenum[0]].textureoffset >> FRACBITS; - - return EV_DoPolyObjFlag(&pfd); -} - -// Parses arguments for parameterized polyobject move-by-sector-heights specials -static boolean PolyDisplace(line_t *line) -{ - polydisplacedata_t pdd; - - pdd.polyObjNum = Tag_FGet(&line->tags); - - pdd.controlSector = line->frontsector; - pdd.dx = line->dx>>8; - pdd.dy = line->dy>>8; - - return EV_DoPolyObjDisplace(&pdd); -} - - -// Parses arguments for parameterized polyobject rotate-by-sector-heights specials -static boolean PolyRotDisplace(line_t *line) -{ - polyrotdisplacedata_t pdd; - fixed_t anginter, distinter; - - pdd.polyObjNum = Tag_FGet(&line->tags); - pdd.controlSector = line->frontsector; - - // Rotate 'anginter' interval for each 'distinter' interval from the control sector. - // Use default values if not provided as fallback. - anginter = sides[line->sidenum[0]].rowoffset ? sides[line->sidenum[0]].rowoffset : 90*FRACUNIT; - distinter = sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : 128*FRACUNIT; - pdd.rotscale = FixedDiv(anginter, distinter); - - // Same behavior as other rotators when carrying things. - if (line->flags & ML_NOCLIMB) - pdd.turnobjs = 0; - else if (line->flags & ML_EFFECT4) - pdd.turnobjs = 2; - else - pdd.turnobjs = 1; - - return EV_DoPolyObjRotDisplace(&pdd); -} - - -// -// P_RunNightserizeExecutors -// -void P_RunNightserizeExecutors(mobj_t *actor) -{ - size_t i; - - for (i = 0; i < numlines; i++) - { - if (lines[i].special == 323 || lines[i].special == 324) - P_RunTriggerLinedef(&lines[i], actor, NULL); - } -} - -// -// P_RunDeNightserizeExecutors -// -void P_RunDeNightserizeExecutors(mobj_t *actor) -{ - size_t i; - - for (i = 0; i < numlines; i++) - { - if (lines[i].special == 325 || lines[i].special == 326) - P_RunTriggerLinedef(&lines[i], actor, NULL); - } -} - -// -// P_RunNightsLapExecutors -// -void P_RunNightsLapExecutors(mobj_t *actor) -{ - size_t i; - - for (i = 0; i < numlines; i++) - { - if (lines[i].special == 327 || lines[i].special == 328) - P_RunTriggerLinedef(&lines[i], actor, NULL); - } -} - -// -// P_RunNightsCapsuleTouchExecutors -// -void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean enoughspheres) -{ - size_t i; - - for (i = 0; i < numlines; i++) - { - if ((lines[i].special == 329 || lines[i].special == 330) - && ((entering && (lines[i].flags & ML_TFERLINE)) - || (!entering && !(lines[i].flags & ML_TFERLINE))) - && ((lines[i].flags & ML_DONTPEGTOP) - || (enoughspheres && !(lines[i].flags & ML_BOUNCY)) - || (!enoughspheres && (lines[i].flags & ML_BOUNCY)))) - P_RunTriggerLinedef(&lines[i], actor, NULL); - } -} - -/** Finds minimum light from an adjacent sector. - * - * \param sector Sector to start in. - * \param max Maximum value to return. - * \return Minimum light value from an adjacent sector, or max if the minimum - * light value is greater than max. - */ -INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max) -{ - size_t i; - INT32 min = max; - line_t *line; - sector_t *check; - - for (i = 0; i < sector->linecount; i++) - { - line = sector->lines[i]; - check = getNextSector(line,sector); - - if (!check) - continue; - - if (check->lightlevel < min) - min = check->lightlevel; - } - return min; -} - -void T_ExecutorDelay(executor_t *e) -{ - if (--e->timer <= 0) - { - if (e->caller && P_MobjWasRemoved(e->caller)) // If the mobj died while we were delaying - P_SetTarget(&e->caller, NULL); // Call with no mobj! - P_ProcessLineSpecial(e->line, e->caller, e->sector); - P_SetTarget(&e->caller, NULL); // Let the mobj know it can be removed now. - P_RemoveThinker(&e->thinker); - } -} - -static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector) -{ - executor_t *e; - INT32 delay; - - if (udmf) - delay = line->executordelay; - else - { - if (!line->backsector) - I_Error("P_AddExecutorDelay: Line has no backsector!\n"); - - delay = (line->backsector->ceilingheight >> FRACBITS) + (line->backsector->floorheight >> FRACBITS); - } - - e = Z_Calloc(sizeof (*e), PU_LEVSPEC, NULL); - - e->thinker.function.acp1 = (actionf_p1)T_ExecutorDelay; - e->line = line; - e->sector = sector; - e->timer = delay; - P_SetTarget(&e->caller, mobj); // Use P_SetTarget to make sure the mobj doesn't get freed while we're delaying. - P_AddThinker(THINK_MAIN, &e->thinker); -} - -/** Used by P_RunTriggerLinedef to check a NiGHTS trigger linedef's conditions - * - * \param triggerline Trigger linedef to check conditions for; should NEVER be NULL. - * \param actor Object initiating the action; should not be NULL. - * \sa P_RunTriggerLinedef - */ -static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) -{ - INT16 specialtype = triggerline->special; - size_t i; - - UINT8 inputmare = max(0, min(255, sides[triggerline->sidenum[0]].textureoffset>>FRACBITS)); - UINT8 inputlap = max(0, min(255, sides[triggerline->sidenum[0]].rowoffset>>FRACBITS)); - - boolean ltemare = triggerline->flags & ML_NOCLIMB; - boolean gtemare = triggerline->flags & ML_BLOCKMONSTERS; - boolean ltelap = triggerline->flags & ML_EFFECT1; - boolean gtelap = triggerline->flags & ML_EFFECT2; - - boolean lapfrombonustime = triggerline->flags & ML_EFFECT3; - boolean perglobalinverse = triggerline->flags & ML_DONTPEGBOTTOM; - boolean perglobal = !(triggerline->flags & ML_EFFECT4) && !perglobalinverse; - - boolean donomares = triggerline->flags & ML_BOUNCY; // nightserize: run at end of level (no mares) - boolean fromnonights = triggerline->flags & ML_TFERLINE; // nightserize: from non-nights // denightserize: all players no nights - boolean fromnights = triggerline->flags & ML_DONTPEGTOP; // nightserize: from nights // denightserize: >0 players are nights - - UINT8 currentmare = UINT8_MAX; - UINT8 currentlap = UINT8_MAX; - - // Do early returns for Nightserize - if (specialtype >= 323 && specialtype <= 324) - { - // run only when no mares are found - if (donomares && P_FindLowestMare() != UINT8_MAX) - return false; - - // run only if there is a mare present - if (!donomares && P_FindLowestMare() == UINT8_MAX) - return false; - - // run only if player is nightserizing from non-nights - if (fromnonights) - { - if (!actor->player) - return false; - else if (actor->player->powers[pw_carry] == CR_NIGHTSMODE) - return false; - } - // run only if player is nightserizing from nights - else if (fromnights) - { - if (!actor->player) - return false; - else if (actor->player->powers[pw_carry] != CR_NIGHTSMODE) - return false; - } - } - - // Get current mare and lap (and check early return for DeNightserize) - if (perglobal || perglobalinverse - || (specialtype >= 325 && specialtype <= 326 && (fromnonights || fromnights))) - { - UINT8 playersarenights = 0; - - for (i = 0; i < MAXPLAYERS; i++) - { - UINT8 lap; - if (!playeringame[i] || players[i].spectator) - continue; - - // denightserize: run only if all players are not nights - if (specialtype >= 325 && specialtype <= 326 && fromnonights - && players[i].powers[pw_carry] == CR_NIGHTSMODE) - return false; - - // count number of nights players for denightserize return - if (specialtype >= 325 && specialtype <= 326 && fromnights - && players[i].powers[pw_carry] == CR_NIGHTSMODE) - playersarenights++; - - lap = lapfrombonustime ? players[i].marebonuslap : players[i].marelap; - - // get highest mare/lap of players - if (perglobal) - { - if (players[i].mare > currentmare || currentmare == UINT8_MAX) - { - currentmare = players[i].mare; - currentlap = UINT8_MAX; - } - if (players[i].mare == currentmare - && (lap > currentlap || currentlap == UINT8_MAX)) - currentlap = lap; - } - // get lowest mare/lap of players - else if (perglobalinverse) - { - if (players[i].mare < currentmare || currentmare == UINT8_MAX) - { - currentmare = players[i].mare; - currentlap = UINT8_MAX; - } - if (players[i].mare == currentmare - && (lap < currentlap || currentlap == UINT8_MAX)) - currentlap = lap; - } - } - - // denightserize: run only if >0 players are nights - if (specialtype >= 325 && specialtype <= 326 && fromnights - && playersarenights < 1) - return false; - } - // get current mare/lap from triggering player - else if (!perglobal && !perglobalinverse) - { - if (!actor->player) - return false; - currentmare = actor->player->mare; - currentlap = lapfrombonustime ? actor->player->marebonuslap : actor->player->marelap; - } - - if (lapfrombonustime && !currentlap) - return false; // special case: player->marebonuslap is 0 until passing through on bonus time. Don't trigger lines looking for inputlap 0. - - // Compare current mare/lap to input mare/lap based on rules - if (!(specialtype >= 323 && specialtype <= 324 && donomares) // don't return false if donomares and we got this far - && ((ltemare && currentmare > inputmare) - || (gtemare && currentmare < inputmare) - || (!ltemare && !gtemare && currentmare != inputmare) - || (ltelap && currentlap > inputlap) - || (gtelap && currentlap < inputlap) - || (!ltelap && !gtelap && currentlap != inputlap)) - ) - return false; - - return true; -} - -/** Used by P_LinedefExecute to check a trigger linedef's conditions - * The linedef executor specials in the trigger linedef's sector are run if all conditions are met. - * Return false cancels P_LinedefExecute, this happens if a condition is not met. - * - * \param triggerline Trigger linedef to check conditions for; should NEVER be NULL. - * \param actor Object initiating the action; should not be NULL. - * \param caller Sector in which the action was started. May be NULL. - * \sa P_ProcessLineSpecial, P_LinedefExecute - */ -boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller) -{ - sector_t *ctlsector; - fixed_t dist = P_AproxDistance(triggerline->dx, triggerline->dy)>>FRACBITS; - size_t i, linecnt, sectori; - INT16 specialtype = triggerline->special; - - ///////////////////////////////////////////////// - // Distance-checking/sector trigger conditions // - ///////////////////////////////////////////////// - - // Linetypes 303 and 304 require a specific - // number, or minimum or maximum, of rings. - if (specialtype == 303 || specialtype == 304) - { - fixed_t rings = 0; - - // With the passuse flag, count all player's - // rings. - if (triggerline->flags & ML_EFFECT4) - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo || ((maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings) <= 0) - continue; - - rings += (maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings; - } - } - else - { - if (!(actor && actor->player)) - return false; // no player to count rings from here, sorry - - rings = (maptol & TOL_NIGHTS) ? actor->player->spheres : actor->player->rings; - } - - if (triggerline->flags & ML_NOCLIMB) - { - if (rings > dist) - return false; - } - else if (triggerline->flags & ML_BLOCKMONSTERS) - { - if (rings < dist) - return false; - } - else - { - if (rings != dist) - return false; - } - } - else if (specialtype >= 314 && specialtype <= 315) - { - msecnode_t *node; - mobj_t *mo; - INT32 numpush = 0; - INT32 numneeded = dist; - - if (!caller) - return false; // we need a calling sector to find pushables in, silly! - - // Count the pushables in this sector - node = caller->touching_thinglist; // things touching this sector - while (node) - { - mo = node->m_thing; - if ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse)) - numpush++; - node = node->m_thinglist_next; - } - - if (triggerline->flags & ML_NOCLIMB) // Need at least or more - { - if (numpush < numneeded) - return false; - } - else if (triggerline->flags & ML_EFFECT4) // Need less than - { - if (numpush >= numneeded) - return false; - } - else // Need exact - { - if (numpush != numneeded) - return false; - } - } - else if (caller) - { - if (GETSECSPECIAL(caller->special, 2) == 6) - { - if (!(ALL7EMERALDS(emeralds))) - return false; - } - else if (GETSECSPECIAL(caller->special, 2) == 7) - { - UINT8 mare; - - if (!(maptol & TOL_NIGHTS)) - return false; - - mare = P_FindLowestMare(); - - if (triggerline->flags & ML_NOCLIMB) - { - if (!(mare <= dist)) - return false; - } - else if (triggerline->flags & ML_BLOCKMONSTERS) - { - if (!(mare >= dist)) - return false; - } - else - { - if (!(mare == dist)) - return false; - } - } - // If we were not triggered by a sector type especially for the purpose, - // a Linedef Executor linedef trigger is not handling sector triggers properly, return. - - else if ((!GETSECSPECIAL(caller->special, 2) || GETSECSPECIAL(caller->special, 2) > 7) && (specialtype > 322)) - { - CONS_Alert(CONS_WARNING, - M_GetText("Linedef executor trigger isn't handling sector triggers properly!\nspecialtype = %d, if you are not a dev, report this warning instance\nalong with the wad that caused it!\n"), - specialtype); - return false; - } - } - - ////////////////////////////////////// - // Miscellaneous trigger conditions // - ////////////////////////////////////// - - switch (specialtype) - { - case 305: // continuous - case 306: // each time - case 307: // once - if (!(actor && actor->player && actor->player->charability == dist/10)) - return false; - break; - case 309: // continuous - case 310: // each time - // Only red team members can activate this. - if (!(actor && actor->player && actor->player->ctfteam == 1)) - return false; - break; - case 311: // continuous - case 312: // each time - // Only blue team members can activate this. - if (!(actor && actor->player && actor->player->ctfteam == 2)) - return false; - break; - case 317: // continuous - case 318: // once - { // Unlockable triggers required - INT32 trigid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS); - - if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) - return false; - else if (trigid < 0 || trigid > 31) // limited by 32 bit variable - { - CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", triggerline->sidenum[0], trigid); - return false; - } - else if (!(unlocktriggers & (1 << trigid))) - return false; - } - break; - case 319: // continuous - case 320: // once - { // An unlockable itself must be unlocked! - INT32 unlockid = (INT32)(sides[triggerline->sidenum[0]].textureoffset>>FRACBITS); - - if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) - return false; - else if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count - { - CONS_Debug(DBG_GAMELOGIC, "Unlockable check (sidedef %hu): bad unlockable ID %d\n", triggerline->sidenum[0], unlockid); - return false; - } - else if (!(unlockables[unlockid-1].unlocked)) - return false; - } - break; - case 321: // continuous - case 322: // each time - // decrement calls left before triggering - if (triggerline->callcount > 0) - { - if (--triggerline->callcount > 0) - return false; - } - break; - case 323: // nightserize - each time - case 324: // nightserize - once - case 325: // denightserize - each time - case 326: // denightserize - once - case 327: // nights lap - each time - case 328: // nights lap - once - case 329: // nights egg capsule touch - each time - case 330: // nights egg capsule touch - once - if (!P_CheckNightsTriggerLine(triggerline, actor)) - return false; - break; - case 331: // continuous - case 332: // each time - case 333: // once - if (!(actor && actor->player && ((stricmp(triggerline->text, skins[actor->player->skin].name) == 0) ^ ((triggerline->flags & ML_NOCLIMB) == ML_NOCLIMB)))) - return false; - break; - case 334: // object dye - continuous - case 335: // object dye - each time - case 336: // object dye - once - { - INT32 triggercolor = (INT32)sides[triggerline->sidenum[0]].toptexture; - UINT16 color = (actor->player ? actor->player->powers[pw_dye] : actor->color); - boolean invert = (triggerline->flags & ML_NOCLIMB ? true : false); - - if (invert ^ (triggercolor != color)) - return false; - } - default: - break; - } - - ///////////////////////////////// - // Processing linedef specials // - ///////////////////////////////// - - ctlsector = triggerline->frontsector; - sectori = (size_t)(ctlsector - sectors); - linecnt = ctlsector->linecount; - - if (triggerline->flags & ML_EFFECT5) // disregard order for efficiency - { - for (i = 0; i < linecnt; i++) - if (ctlsector->lines[i]->special >= 400 - && ctlsector->lines[i]->special < 500) - { - if (ctlsector->lines[i]->executordelay) - P_AddExecutorDelay(ctlsector->lines[i], actor, caller); - else - P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); - } - } - else // walk around the sector in a defined order - { - boolean backwards = false; - size_t j, masterlineindex = (size_t)-1; - - for (i = 0; i < linecnt; i++) - if (ctlsector->lines[i] == triggerline) - { - masterlineindex = i; - break; - } - -#ifdef PARANOIA - if (masterlineindex == (size_t)-1) - { - const size_t li = (size_t)(ctlsector->lines[i] - lines); - I_Error("Line %s isn't linked into its front sector", sizeu1(li)); - } -#endif - - // i == masterlineindex - for (;;) - { - if (backwards) // v2 to v1 - { - for (j = 0; j < linecnt; j++) - { - if (i == j) - continue; - if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v2) - { - i = j; - break; - } - if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v1) - { - i = j; - backwards = false; - break; - } - } - if (j == linecnt) - { - const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes); - CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n", - sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v1->x, ctlsector->lines[i]->v1->y); - return false; // abort - } - } - else // v1 to v2 - { - for (j = 0; j < linecnt; j++) - { - if (i == j) - continue; - if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v1) - { - i = j; - break; - } - if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v2) - { - i = j; - backwards = true; - break; - } - } - if (j == linecnt) - { - const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes); - CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n", - sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v2->x, ctlsector->lines[i]->v2->y); - return false; // abort - } - } - - if (i == masterlineindex) - break; - - if (ctlsector->lines[i]->special >= 400 - && ctlsector->lines[i]->special < 500) - { - if (ctlsector->lines[i]->executordelay) - P_AddExecutorDelay(ctlsector->lines[i], actor, caller); - else - P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); - } - } - } - - // "Trigger on X calls" linedefs reset if noclimb is set - if ((specialtype == 321 || specialtype == 322) && triggerline->flags & ML_NOCLIMB) - triggerline->callcount = sides[triggerline->sidenum[0]].textureoffset>>FRACBITS; - else - // These special types work only once - if (specialtype == 302 // Once - || specialtype == 304 // Ring count - Once - || specialtype == 307 // Character ability - Once - || specialtype == 308 // Race only - Once - || specialtype == 313 // No More Enemies - Once - || specialtype == 315 // No of pushables - Once - || specialtype == 318 // Unlockable trigger - Once - || specialtype == 320 // Unlockable - Once - || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time - || specialtype == 324 // Nightserize - Once - || specialtype == 326 // DeNightserize - Once - || specialtype == 328 // Nights lap - Once - || specialtype == 330 // Nights Bonus Time - Once - || specialtype == 333 // Skin - Once - || specialtype == 336 // Dye - Once - || specialtype == 399) // Level Load - triggerline->special = 0; // Clear it out - - return true; -} - -/** Runs a linedef executor. - * Can be called by: - * - a player moving into a special sector or FOF. - * - a pushable object moving into a special sector or FOF. - * - a ceiling or floor movement from a previous linedef executor finishing. - * - any object in a state with the A_LinedefExecute() action. - * - * \param tag Tag of the linedef executor to run. - * \param actor Object initiating the action; should not be NULL. - * \param caller Sector in which the action was started. May be NULL. - * \sa P_ProcessLineSpecial, P_RunTriggerLinedef - * \author Graue - */ -void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) -{ - size_t masterline; - - CONS_Debug(DBG_GAMELOGIC, "P_LinedefExecute: Executing trigger linedefs of tag %d\n", tag); - - I_Assert(!actor || !P_MobjWasRemoved(actor)); // If actor is there, it must be valid. - - for (masterline = 0; masterline < numlines; masterline++) - { - if (Tag_FGet(&lines[masterline].tags) != tag) - continue; - - // "No More Enemies" and "Level Load" take care of themselves. - if (lines[masterline].special == 313 - || lines[masterline].special == 399 - // Each-time executors handle themselves, too - || lines[masterline].special == 301 // Each time - || lines[masterline].special == 306 // Character ability - Each time - || lines[masterline].special == 310 // CTF Red team - Each time - || lines[masterline].special == 312 // CTF Blue team - Each time - || lines[masterline].special == 322 // Trigger on X calls - Each Time - || lines[masterline].special == 332 // Skin - Each time - || lines[masterline].special == 335)// Dye - Each time - continue; - - if (lines[masterline].special < 300 - || lines[masterline].special > 399) - continue; - - if (!P_RunTriggerLinedef(&lines[masterline], actor, caller)) - return; // cancel P_LinedefExecute if function returns false - } -} - -// -// P_SwitchWeather -// -// Switches the weather! -// -void P_SwitchWeather(INT32 weathernum) -{ - boolean purge = false; - INT32 swap = 0; - - switch (weathernum) - { - case PRECIP_NONE: // None - if (curWeather == PRECIP_NONE) - return; // Nothing to do. - purge = true; - break; - case PRECIP_STORM: // Storm - case PRECIP_STORM_NOSTRIKES: // Storm w/ no lightning - case PRECIP_RAIN: // Rain - if (curWeather == PRECIP_SNOW || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN) - swap = PRECIP_RAIN; - break; - case PRECIP_SNOW: // Snow - if (curWeather == PRECIP_SNOW) - return; // Nothing to do. - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN) - swap = PRECIP_SNOW; // Need to delete the other precips. - break; - case PRECIP_STORM_NORAIN: // Storm w/o rain - if (curWeather == PRECIP_SNOW - || curWeather == PRECIP_STORM - || curWeather == PRECIP_STORM_NOSTRIKES - || curWeather == PRECIP_RAIN - || curWeather == PRECIP_BLANK) - swap = PRECIP_STORM_NORAIN; - else if (curWeather == PRECIP_STORM_NORAIN) - return; - break; - case PRECIP_BLANK: - if (curWeather == PRECIP_SNOW - || curWeather == PRECIP_STORM - || curWeather == PRECIP_STORM_NOSTRIKES - || curWeather == PRECIP_RAIN) - swap = PRECIP_BLANK; - else if (curWeather == PRECIP_STORM_NORAIN) - swap = PRECIP_BLANK; - else if (curWeather == PRECIP_BLANK) - return; - break; - default: - CONS_Debug(DBG_GAMELOGIC, "P_SwitchWeather: Unknown weather type %d.\n", weathernum); - break; - } - - if (purge) - { - thinker_t *think; - precipmobj_t *precipmobj; - - for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next) - { - if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) - continue; // not a precipmobj thinker - - precipmobj = (precipmobj_t *)think; - - P_RemovePrecipMobj(precipmobj); - } - } - else if (swap && !((swap == PRECIP_BLANK && curWeather == PRECIP_STORM_NORAIN) || (swap == PRECIP_STORM_NORAIN && curWeather == PRECIP_BLANK))) // Rather than respawn all that crap, reuse it! - { - thinker_t *think; - precipmobj_t *precipmobj; - state_t *st; - - for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next) - { - if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) - continue; // not a precipmobj thinker - precipmobj = (precipmobj_t *)think; - - if (swap == PRECIP_RAIN) // Snow To Rain - { - precipmobj->flags = mobjinfo[MT_RAIN].flags; - st = &states[mobjinfo[MT_RAIN].spawnstate]; - precipmobj->state = st; - precipmobj->tics = st->tics; - precipmobj->sprite = st->sprite; - precipmobj->frame = st->frame; - precipmobj->momz = mobjinfo[MT_RAIN].speed; - - precipmobj->precipflags &= ~PCF_INVISIBLE; - - precipmobj->precipflags |= PCF_RAIN; - //think->function.acp1 = (actionf_p1)P_RainThinker; - } - else if (swap == PRECIP_SNOW) // Rain To Snow - { - INT32 z; - - precipmobj->flags = mobjinfo[MT_SNOWFLAKE].flags; - z = M_RandomByte(); - - if (z < 64) - z = 2; - else if (z < 144) - z = 1; - else - z = 0; - - st = &states[mobjinfo[MT_SNOWFLAKE].spawnstate+z]; - precipmobj->state = st; - precipmobj->tics = st->tics; - precipmobj->sprite = st->sprite; - precipmobj->frame = st->frame; - precipmobj->momz = mobjinfo[MT_SNOWFLAKE].speed; - - precipmobj->precipflags &= ~(PCF_INVISIBLE|PCF_RAIN); - - //think->function.acp1 = (actionf_p1)P_SnowThinker; - } - else if (swap == PRECIP_BLANK || swap == PRECIP_STORM_NORAIN) // Remove precip, but keep it around for reuse. - { - //think->function.acp1 = (actionf_p1)P_NullPrecipThinker; - - precipmobj->precipflags |= PCF_INVISIBLE; - } - } - } - - switch (weathernum) - { - case PRECIP_SNOW: // snow - curWeather = PRECIP_SNOW; - - if (!swap) - P_SpawnPrecipitation(); - - break; - case PRECIP_RAIN: // rain - { - boolean dontspawn = false; - - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) - dontspawn = true; - - curWeather = PRECIP_RAIN; - - if (!dontspawn && !swap) - P_SpawnPrecipitation(); - - break; - } - case PRECIP_STORM: // storm - { - boolean dontspawn = false; - - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) - dontspawn = true; - - curWeather = PRECIP_STORM; - - if (!dontspawn && !swap) - P_SpawnPrecipitation(); - - break; - } - case PRECIP_STORM_NOSTRIKES: // storm w/o lightning - { - boolean dontspawn = false; - - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) - dontspawn = true; - - curWeather = PRECIP_STORM_NOSTRIKES; - - if (!dontspawn && !swap) - P_SpawnPrecipitation(); - - break; - } - case PRECIP_STORM_NORAIN: // storm w/o rain - curWeather = PRECIP_STORM_NORAIN; - - if (!swap) - P_SpawnPrecipitation(); - - break; - case PRECIP_BLANK: - curWeather = PRECIP_BLANK; - - if (!swap) - P_SpawnPrecipitation(); - - break; - default: - curWeather = PRECIP_NONE; - break; - } -} - -/** Gets an object. - * - * \param type Object type to look for. - * \param s Sector number to look in. - * \return Pointer to the first ::type found in the sector. - * \sa P_GetPushThing - */ -static mobj_t *P_GetObjectTypeInSectorNum(mobjtype_t type, size_t s) -{ - sector_t *sec = sectors + s; - mobj_t *thing = sec->thinglist; - - while (thing) - { - if (thing->type == type) - return thing; - thing = thing->snext; - } - return NULL; -} - -/** Processes the line special triggered by an object. - * - * \param line Line with the special command on it. - * \param mo mobj that triggered the line. Must be valid and non-NULL. - * \param callsec sector in which action was initiated; this can be NULL. - * Because of the A_LinedefExecute() action, even if non-NULL, - * this sector might not have the same tag as the linedef executor, - * and it might not have the linedef executor sector type. - * \todo Handle mo being NULL gracefully. T_MoveFloor() and T_MoveCeiling() - * don't have an object to pass. - * \todo Split up into multiple functions. - * \sa P_LinedefExecute - * \author Graue - */ -static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) -{ - INT32 secnum = -1; - mobj_t *bot = NULL; - mtag_t tag = Tag_FGet(&line->tags); - - I_Assert(!mo || !P_MobjWasRemoved(mo)); // If mo is there, mo must be valid! - - if (mo && mo->player && botingame) - bot = players[secondarydisplayplayer].mo; - - // note: only commands with linedef types >= 400 && < 500 can be used - switch (line->special) - { - case 400: // Set tagged sector's floor height/pic - EV_DoFloor(line, instantMoveFloorByFrontSector); - break; - - case 401: // Set tagged sector's ceiling height/pic - EV_DoCeiling(line, instantMoveCeilingByFrontSector); - break; - - case 402: // Set tagged sector's light level - { - INT16 newlightlevel; - INT32 newfloorlightsec, newceilinglightsec; - - newlightlevel = line->frontsector->lightlevel; - newfloorlightsec = line->frontsector->floorlightsec; - newceilinglightsec = line->frontsector->ceilinglightsec; - - // act on all sectors with the same tag as the triggering linedef - TAG_ITER_SECTORS(tag, secnum) - { - if (sectors[secnum].lightingdata) - { - // Stop the lighting madness going on in this sector! - P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); - sectors[secnum].lightingdata = NULL; - - // No, it's not an elevator_t, but any struct with a thinker_t named - // 'thinker' at the beginning will do here. (We don't know what it - // actually is: could be lightlevel_t, fireflicker_t, glow_t, etc.) - } - - sectors[secnum].lightlevel = newlightlevel; - sectors[secnum].floorlightsec = newfloorlightsec; - sectors[secnum].ceilinglightsec = newceilinglightsec; - } - } - break; - - case 403: // Move floor, linelen = speed, frontsector floor = dest height - EV_DoFloor(line, moveFloorByFrontSector); - break; - - case 404: // Move ceiling, linelen = speed, frontsector ceiling = dest height - EV_DoCeiling(line, moveCeilingByFrontSector); - break; - - case 405: // Move floor by front side texture offsets, offset x = speed, offset y = amount to raise/lower - EV_DoFloor(line, moveFloorByFrontTexture); - break; - - case 407: // Move ceiling by front side texture offsets, offset x = speed, offset y = amount to raise/lower - EV_DoCeiling(line, moveCeilingByFrontTexture); - break; - -/* case 405: // Lower floor by line, dx = speed, dy = amount to lower - EV_DoFloor(line, lowerFloorByLine); - break; - - case 406: // Raise floor by line, dx = speed, dy = amount to raise - EV_DoFloor(line, raiseFloorByLine); - break; - - case 407: // Lower ceiling by line, dx = speed, dy = amount to lower - EV_DoCeiling(line, lowerCeilingByLine); - break; - - case 408: // Raise ceiling by line, dx = speed, dy = amount to raise - EV_DoCeiling(line, raiseCeilingByLine); - break;*/ - - case 409: // Change tagged sectors' tag - // (formerly "Change calling sectors' tag", but behavior was changed) - { - TAG_ITER_SECTORS(tag, secnum) - Tag_SectorFSet(secnum,(INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS)); - break; - } - - case 410: // Change front sector's tag - Tag_SectorFSet((UINT32)(line->frontsector - sectors), (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS)); - break; - - case 411: // Stop floor/ceiling movement in tagged sector(s) - TAG_ITER_SECTORS(tag, secnum) - { - if (sectors[secnum].floordata) - { - if (sectors[secnum].floordata == sectors[secnum].ceilingdata) // elevator - { - P_RemoveThinker(&((elevator_t *)sectors[secnum].floordata)->thinker); - sectors[secnum].floordata = sectors[secnum].ceilingdata = NULL; - sectors[secnum].floorspeed = sectors[secnum].ceilspeed = 0; - } - else // floormove - { - P_RemoveThinker(&((floormove_t *)sectors[secnum].floordata)->thinker); - sectors[secnum].floordata = NULL; - sectors[secnum].floorspeed = 0; - } - } - - if (sectors[secnum].ceilingdata) // ceiling - { - P_RemoveThinker(&((ceiling_t *)sectors[secnum].ceilingdata)->thinker); - sectors[secnum].ceilingdata = NULL; - sectors[secnum].ceilspeed = 0; - } - } - break; - - case 412: // Teleport the player or thing - { - mobj_t *dest; - - if (!mo) // nothing to teleport - return; - - if (line->flags & ML_EFFECT3) // Relative silent teleport - { - fixed_t x, y, z; - - x = sides[line->sidenum[0]].textureoffset; - y = sides[line->sidenum[0]].rowoffset; - z = line->frontsector->ceilingheight; - - P_UnsetThingPosition(mo); - mo->x += x; - mo->y += y; - mo->z += z; - P_SetThingPosition(mo); - - if (mo->player) - { - if (bot) // This might put poor Tails in a wall if he's too far behind! D: But okay, whatever! >:3 - P_TeleportMove(bot, bot->x + x, bot->y + y, bot->z + z); - if (splitscreen && mo->player == &players[secondarydisplayplayer] && camera2.chase) - { - camera2.x += x; - camera2.y += y; - camera2.z += z; - camera2.subsector = R_PointInSubsector(camera2.x, camera2.y); - } - else if (camera.chase && mo->player == &players[displayplayer]) - { - camera.x += x; - camera.y += y; - camera.z += z; - camera.subsector = R_PointInSubsector(camera.x, camera.y); - } - } - } - else - { - if ((secnum = Tag_Iterate_Sectors(tag, 0)) < 0) - return; - - dest = P_GetObjectTypeInSectorNum(MT_TELEPORTMAN, secnum); - if (!dest) - return; - - if (bot) - P_Teleport(bot, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, (line->flags & ML_BLOCKMONSTERS) == 0, (line->flags & ML_EFFECT4) == ML_EFFECT4); - if (line->flags & ML_BLOCKMONSTERS) - P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, false, (line->flags & ML_EFFECT4) == ML_EFFECT4); - else - { - P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, true, (line->flags & ML_EFFECT4) == ML_EFFECT4); - // Play the 'bowrwoosh!' sound - S_StartSound(dest, sfx_mixup); - } - } - } - break; - - case 413: // Change music - // console player only unless NOCLIMB is set - if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player)) || titlemapinaction) - { - boolean musicsame = (!sides[line->sidenum[0]].text[0] || !strnicmp(sides[line->sidenum[0]].text, S_MusicName(), 7)); - UINT16 tracknum = (UINT16)max(sides[line->sidenum[0]].bottomtexture, 0); - INT32 position = (INT32)max(sides[line->sidenum[0]].midtexture, 0); - UINT32 prefadems = (UINT32)max(sides[line->sidenum[0]].textureoffset >> FRACBITS, 0); - UINT32 postfadems = (UINT32)max(sides[line->sidenum[0]].rowoffset >> FRACBITS, 0); - UINT8 fadetarget = (UINT8)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].textureoffset >> FRACBITS : 0, 0); - INT16 fadesource = (INT16)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].rowoffset >> FRACBITS : -1, -1); - - // Seek offset from current song position - if (line->flags & ML_EFFECT1) - { - // adjust for loop point if subtracting - if (position < 0 && S_GetMusicLength() && - S_GetMusicPosition() > S_GetMusicLoopPoint() && - S_GetMusicPosition() + position < S_GetMusicLoopPoint()) - position = max(S_GetMusicLength() - (S_GetMusicLoopPoint() - (S_GetMusicPosition() + position)), 0); - else - position = max(S_GetMusicPosition() + position, 0); - } - - // Fade current music to target volume (if music won't be changed) - if ((line->flags & ML_EFFECT2) && fadetarget && musicsame) - { - // 0 fadesource means fade from current volume. - // meaning that we can't specify volume 0 as the source volume -- this starts at 1. - if (!fadesource) - fadesource = -1; - - if (!postfadems) - S_SetInternalMusicVolume(fadetarget); - else - S_FadeMusicFromVolume(fadetarget, fadesource, postfadems); - - if (position) - S_SetMusicPosition(position); - } - // Change the music and apply position/fade operations - else - { - strncpy(mapmusname, sides[line->sidenum[0]].text, 7); - mapmusname[6] = 0; - - mapmusflags = tracknum & MUSIC_TRACKMASK; - if (!(line->flags & ML_BLOCKMONSTERS)) - mapmusflags |= MUSIC_RELOADRESET; - if (line->flags & ML_BOUNCY) - mapmusflags |= MUSIC_FORCERESET; - - mapmusposition = position; - - S_ChangeMusicEx(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4), position, - !(line->flags & ML_EFFECT2) ? prefadems : 0, - !(line->flags & ML_EFFECT2) ? postfadems : 0); - - if ((line->flags & ML_EFFECT2) && fadetarget) - { - if (!postfadems) - S_SetInternalMusicVolume(fadetarget); - else - S_FadeMusicFromVolume(fadetarget, fadesource, postfadems); - } - } - - // Except, you can use the ML_BLOCKMONSTERS flag to change this behavior. - // if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn. - } - break; - - case 414: // Play SFX - { - INT32 sfxnum; - - sfxnum = sides[line->sidenum[0]].toptexture; - - if (sfxnum == sfx_None) - return; // Do nothing! - if (sfxnum < sfx_None || sfxnum >= NUMSFX) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 414 Executor: sfx number %d is invalid!\n", sfxnum); - return; - } - - if (tag != 0) // Do special stuff only if a non-zero linedef tag is set - { - // Play sounds from tagged sectors' origins. - if (line->flags & ML_EFFECT5) // Repeat Midtexture - { - // Additionally play the sound from tagged sectors' soundorgs - sector_t *sec; - - TAG_ITER_SECTORS(tag, secnum) - { - sec = §ors[secnum]; - S_StartSound(&sec->soundorg, sfxnum); - } - } - - // Play the sound without origin for anyone, as long as they're inside tagged areas. - else - { - UINT8 i = 0; - mobj_t* camobj = players[displayplayer].mo; - ffloor_t *rover; - boolean foundit = false; - - for (i = 0; i < 2; camobj = players[secondarydisplayplayer].mo, i++) - { - if (!camobj) - continue; - - if (foundit || Tag_Find(&camobj->subsector->sector->tags, tag)) - { - foundit = true; - break; - } - - // Only trigger if mobj is touching the tag - for(rover = camobj->subsector->sector->ffloors; rover; rover = rover->next) - { - if (!Tag_Find(&rover->master->frontsector->tags, tag)) - continue; - - if (camobj->z > P_GetSpecialTopZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) - continue; - - if (camobj->z + camobj->height < P_GetSpecialBottomZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) - continue; - - foundit = true; - break; - } - } - - if (foundit) - S_StartSound(NULL, sfxnum); - } - } - else - { - if (line->flags & ML_NOCLIMB) - { - // play the sound from nowhere, but only if display player triggered it - if (mo && mo->player && (mo->player == &players[displayplayer] || mo->player == &players[secondarydisplayplayer])) - S_StartSound(NULL, sfxnum); - } - else if (line->flags & ML_EFFECT4) - { - // play the sound from nowhere - S_StartSound(NULL, sfxnum); - } - else if (line->flags & ML_BLOCKMONSTERS) - { - // play the sound from calling sector's soundorg - if (callsec) - S_StartSound(&callsec->soundorg, sfxnum); - else if (mo) - S_StartSound(&mo->subsector->sector->soundorg, sfxnum); - } - else if (mo) - { - // play the sound from mobj that triggered it - S_StartSound(mo, sfxnum); - } - } - } - break; - - case 415: // Run a script - if (cv_runscripts.value) - { - INT32 scrnum; - lumpnum_t lumpnum; - char newname[9]; - - strcpy(newname, G_BuildMapName(gamemap)); - newname[0] = 'S'; - newname[1] = 'C'; - newname[2] = 'R'; - - scrnum = sides[line->sidenum[0]].textureoffset>>FRACBITS; - if (scrnum < 0 || scrnum > 999) - { - scrnum = 0; - newname[5] = newname[6] = newname[7] = '0'; - } - else - { - newname[5] = (char)('0' + (char)((scrnum/100))); - newname[6] = (char)('0' + (char)((scrnum%100)/10)); - newname[7] = (char)('0' + (char)(scrnum%10)); - } - newname[8] = '\0'; - - lumpnum = W_CheckNumForName(newname); - - if (lumpnum == LUMPERROR || W_LumpLength(lumpnum) == 0) - { - CONS_Debug(DBG_SETUP, "SOC Error: script lump %s not found/not valid.\n", newname); - } - else - COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE)); - } - break; - - case 416: // Spawn adjustable fire flicker - TAG_ITER_SECTORS(tag, secnum) - { - if (line->flags & ML_NOCLIMB && line->backsector) - { - // Use front sector for min light level, back sector for max. - // This is tricky because P_SpawnAdjustableFireFlicker expects - // the maxsector (second argument) to also be the target - // sector, so we have to do some light level twiddling. - fireflicker_t *flick; - INT16 reallightlevel = sectors[secnum].lightlevel; - sectors[secnum].lightlevel = line->backsector->lightlevel; - - flick = P_SpawnAdjustableFireFlicker(line->frontsector, §ors[secnum], - P_AproxDistance(line->dx, line->dy)>>FRACBITS); - - // Make sure the starting light level is in range. - if (reallightlevel < flick->minlight) - reallightlevel = (INT16)flick->minlight; - else if (reallightlevel > flick->maxlight) - reallightlevel = (INT16)flick->maxlight; - - sectors[secnum].lightlevel = reallightlevel; - } - else - { - // Use front sector for min, target sector for max, - // the same way linetype 61 does it. - P_SpawnAdjustableFireFlicker(line->frontsector, §ors[secnum], - P_AproxDistance(line->dx, line->dy)>>FRACBITS); - } - } - break; - - case 417: // Spawn adjustable glowing light - TAG_ITER_SECTORS(tag, secnum) - { - if (line->flags & ML_NOCLIMB && line->backsector) - { - // Use front sector for min light level, back sector for max. - // This is tricky because P_SpawnAdjustableGlowingLight expects - // the maxsector (second argument) to also be the target - // sector, so we have to do some light level twiddling. - glow_t *glow; - INT16 reallightlevel = sectors[secnum].lightlevel; - sectors[secnum].lightlevel = line->backsector->lightlevel; - - glow = P_SpawnAdjustableGlowingLight(line->frontsector, §ors[secnum], - P_AproxDistance(line->dx, line->dy)>>FRACBITS); - - // Make sure the starting light level is in range. - if (reallightlevel < glow->minlight) - reallightlevel = (INT16)glow->minlight; - else if (reallightlevel > glow->maxlight) - reallightlevel = (INT16)glow->maxlight; - - sectors[secnum].lightlevel = reallightlevel; - } - else - { - // Use front sector for min, target sector for max, - // the same way linetype 602 does it. - P_SpawnAdjustableGlowingLight(line->frontsector, §ors[secnum], - P_AproxDistance(line->dx, line->dy)>>FRACBITS); - } - } - break; - - case 418: // Spawn adjustable strobe flash (unsynchronized) - TAG_ITER_SECTORS(tag, secnum) - { - if (line->flags & ML_NOCLIMB && line->backsector) - { - // Use front sector for min light level, back sector for max. - // This is tricky because P_SpawnAdjustableGlowingLight expects - // the maxsector (second argument) to also be the target - // sector, so we have to do some light level twiddling. - strobe_t *flash; - INT16 reallightlevel = sectors[secnum].lightlevel; - sectors[secnum].lightlevel = line->backsector->lightlevel; - - flash = P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], - abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, false); - - // Make sure the starting light level is in range. - if (reallightlevel < flash->minlight) - reallightlevel = (INT16)flash->minlight; - else if (reallightlevel > flash->maxlight) - reallightlevel = (INT16)flash->maxlight; - - sectors[secnum].lightlevel = reallightlevel; - } - else - { - // Use front sector for min, target sector for max, - // the same way linetype 602 does it. - P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], - abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, false); - } - } - break; - - case 419: // Spawn adjustable strobe flash (synchronized) - TAG_ITER_SECTORS(tag, secnum) - { - if (line->flags & ML_NOCLIMB && line->backsector) - { - // Use front sector for min light level, back sector for max. - // This is tricky because P_SpawnAdjustableGlowingLight expects - // the maxsector (second argument) to also be the target - // sector, so we have to do some light level twiddling. - strobe_t *flash; - INT16 reallightlevel = sectors[secnum].lightlevel; - sectors[secnum].lightlevel = line->backsector->lightlevel; - - flash = P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], - abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, true); - - // Make sure the starting light level is in range. - if (reallightlevel < flash->minlight) - reallightlevel = (INT16)flash->minlight; - else if (reallightlevel > flash->maxlight) - reallightlevel = (INT16)flash->maxlight; - - sectors[secnum].lightlevel = reallightlevel; - } - else - { - // Use front sector for min, target sector for max, - // the same way linetype 602 does it. - P_SpawnAdjustableStrobeFlash(line->frontsector, §ors[secnum], - abs(line->dx)>>FRACBITS, abs(line->dy)>>FRACBITS, true); - } - } - break; - - case 420: // Fade light levels in tagged sectors to new value - P_FadeLight(tag, - (line->flags & ML_DONTPEGBOTTOM) ? max(sides[line->sidenum[0]].textureoffset>>FRACBITS, 0) : line->frontsector->lightlevel, - // failsafe: if user specifies Back Y Offset and NOT Front Y Offset, use the Back Offset - // to be consistent with other light and fade specials - (line->flags & ML_DONTPEGBOTTOM) ? - ((line->sidenum[1] != 0xFFFF && !(sides[line->sidenum[0]].rowoffset>>FRACBITS)) ? - max(min(sides[line->sidenum[1]].rowoffset>>FRACBITS, 255), 0) - : max(min(sides[line->sidenum[0]].rowoffset>>FRACBITS, 255), 0)) - : abs(P_AproxDistance(line->dx, line->dy))>>FRACBITS, - (line->flags & ML_EFFECT4), - (line->flags & ML_EFFECT5)); - break; - - case 421: // Stop lighting effect in tagged sectors - TAG_ITER_SECTORS(tag, secnum) - if (sectors[secnum].lightingdata) - { - P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); - sectors[secnum].lightingdata = NULL; - } - break; - - case 422: // Cut away to another view - { - mobj_t *altview; - - if ((!mo || !mo->player) && !titlemapinaction) // only players have views, and title screens - return; - - if ((secnum = Tag_Iterate_Sectors(tag, 0)) < 0) - return; - - altview = P_GetObjectTypeInSectorNum(MT_ALTVIEWMAN, secnum); - if (!altview) - return; - - // If titlemap, set the camera ref for title's thinker - // This is not revoked until overwritten; awayviewtics is ignored - if (titlemapinaction) - titlemapcameraref = altview; - else - { - P_SetTarget(&mo->player->awayviewmobj, altview); - mo->player->awayviewtics = P_AproxDistance(line->dx, line->dy)>>FRACBITS; - } - - - if (line->flags & ML_NOCLIMB) // lets you specify a vertical angle - { - INT32 aim; - - aim = sides[line->sidenum[0]].textureoffset>>FRACBITS; - aim = (aim + 360) % 360; - aim *= (ANGLE_90>>8); - aim /= 90; - aim <<= 8; - if (titlemapinaction) - titlemapcameraref->cusval = (angle_t)aim; - else - mo->player->awayviewaiming = (angle_t)aim; - } - else - { - // straight ahead - if (!titlemapinaction) - mo->player->awayviewaiming = 0; - // don't do cusval cause that's annoying - } - } - break; - - case 423: // Change Sky - if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB)) - P_SetupLevelSky(sides[line->sidenum[0]].textureoffset>>FRACBITS, (line->flags & ML_NOCLIMB)); - break; - - case 424: // Change Weather - if (line->flags & ML_NOCLIMB) - { - globalweather = (UINT8)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - P_SwitchWeather(globalweather); - } - else if (mo && mo->player && P_IsLocalPlayer(mo->player)) - P_SwitchWeather(sides[line->sidenum[0]].textureoffset>>FRACBITS); - break; - - case 425: // Calls P_SetMobjState on calling mobj - if (mo && !mo->player) - P_SetMobjState(mo, sides[line->sidenum[0]].toptexture); //P_AproxDistance(line->dx, line->dy)>>FRACBITS); - break; - - case 426: // Moves the mobj to its sector's soundorg and on the floor, and stops it - if (!mo) - return; - - if (line->flags & ML_NOCLIMB) - { - P_UnsetThingPosition(mo); - mo->x = mo->subsector->sector->soundorg.x; - mo->y = mo->subsector->sector->soundorg.y; - mo->z = mo->floorz; - P_SetThingPosition(mo); - } - - mo->momx = mo->momy = mo->momz = 1; - mo->pmomz = 0; - - if (mo->player) - { - mo->player->rmomx = mo->player->rmomy = 1; - mo->player->cmomx = mo->player->cmomy = 0; - P_ResetPlayer(mo->player); - P_SetPlayerMobjState(mo, S_PLAY_STND); - - // Reset bot too. - if (bot) { - if (line->flags & ML_NOCLIMB) - P_TeleportMove(bot, mo->x, mo->y, mo->z); - bot->momx = bot->momy = bot->momz = 1; - bot->pmomz = 0; - bot->player->rmomx = bot->player->rmomy = 1; - bot->player->cmomx = bot->player->cmomy = 0; - P_ResetPlayer(bot->player); - P_SetPlayerMobjState(bot, S_PLAY_STND); - } - } - break; - - case 427: // Awards points if the mobj is a player - if (mo && mo->player) - P_AddPlayerScore(mo->player, sides[line->sidenum[0]].textureoffset>>FRACBITS); - break; - - case 428: // Start floating platform movement - EV_DoElevator(line, elevateContinuous, true); - break; - - case 429: // Crush Ceiling Down Once - EV_DoCrush(line, crushCeilOnce); - break; - - case 430: // Crush Floor Up Once - EV_DoFloor(line, crushFloorOnce); - break; - - case 431: // Crush Floor & Ceiling to middle Once - EV_DoCrush(line, crushBothOnce); - break; - - case 432: // Enable 2D Mode (Disable if noclimb) - if (mo && mo->player) - { - if (line->flags & ML_NOCLIMB) - mo->flags2 &= ~MF2_TWOD; - else - mo->flags2 |= MF2_TWOD; - - // Copy effect to bot if necessary - // (Teleport them to you so they don't break it.) - if (bot && (bot->flags2 & MF2_TWOD) != (mo->flags2 & MF2_TWOD)) { - bot->flags2 = (bot->flags2 & ~MF2_TWOD) | (mo->flags2 & MF2_TWOD); - P_TeleportMove(bot, mo->x, mo->y, mo->z); - } - } - break; - - case 433: // Flip gravity (Flop gravity if noclimb) Works on pushables, too! - if (line->flags & ML_NOCLIMB) - mo->flags2 &= ~MF2_OBJECTFLIP; - else - mo->flags2 |= MF2_OBJECTFLIP; - if (bot) - bot->flags2 = (bot->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); - break; - - case 434: // Custom Power - if (mo && mo->player) - { - mobj_t *dummy = P_SpawnMobj(mo->x, mo->y, mo->z, MT_NULL); - - var1 = sides[line->sidenum[0]].toptexture; //(line->dx>>FRACBITS)-1; - - if (line->sidenum[1] != 0xffff && line->flags & ML_BLOCKMONSTERS) // read power from back sidedef - var2 = sides[line->sidenum[1]].toptexture; - else if (line->flags & ML_NOCLIMB) // 'Infinite' - var2 = UINT16_MAX; - else - var2 = sides[line->sidenum[0]].textureoffset>>FRACBITS; - - P_SetTarget(&dummy->target, mo); - A_CustomPower(dummy); - - if (bot) { - P_SetTarget(&dummy->target, bot); - A_CustomPower(dummy); - } - P_RemoveMobj(dummy); - } - break; - - case 435: // Change scroller direction - { - scroll_t *scroller; - thinker_t *th; - - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) - { - if (th->function.acp1 != (actionf_p1)T_Scroll) - continue; - - scroller = (scroll_t *)th; - if (!Tag_Find(§ors[scroller->affectee].tags, tag)) - continue; - - scroller->dx = FixedMul(line->dx>>SCROLL_SHIFT, CARRYFACTOR); - scroller->dy = FixedMul(line->dy>>SCROLL_SHIFT, CARRYFACTOR); - } - } - break; - - case 436: // Shatter block remotely - { - INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); - sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to crumble - boolean foundrover = false; // for debug, "Can't find a FOF" message - - TAG_ITER_SECTORS(sectag, secnum) - { - sec = sectors + secnum; - - if (!sec->ffloors) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 436 Executor: Target sector #%d has no FOFs.\n", secnum); - return; - } - - for (rover = sec->ffloors; rover; rover = rover->next) - { - if (Tag_Find(&rover->master->frontsector->tags, foftag)) - { - foundrover = true; - - EV_CrumbleChain(sec, rover); - } - } - - if (!foundrover) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 436 Executor: Can't find a FOF control sector with tag %d\n", foftag); - return; - } - } - } - break; - - case 437: // Disable Player Controls - if (mo && mo->player) - { - UINT16 fractime = (UINT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - if (fractime < 1) - fractime = 1; //instantly wears off upon leaving - if (line->flags & ML_NOCLIMB) - fractime |= 1<<15; //more crazy &ing, as if music stuff wasn't enough - mo->player->powers[pw_nocontrol] = fractime; - if (bot) - bot->player->powers[pw_nocontrol] = fractime; - } - break; - - case 438: // Set player scale - if (mo) - { - mo->destscale = FixedDiv(P_AproxDistance(line->dx, line->dy), 100<destscale < FRACUNIT/100) - mo->destscale = FRACUNIT/100; - if (mo->player && bot) - bot->destscale = mo->destscale; - } - break; - - case 439: // Set texture - { - size_t linenum; - side_t *set = &sides[line->sidenum[0]], *this; - boolean always = !(line->flags & ML_NOCLIMB); // If noclimb: Only change mid texture if mid texture already exists on tagged lines, etc. - - for (linenum = 0; linenum < numlines; linenum++) - { - if (lines[linenum].special == 439) - continue; // Don't override other set texture lines! - - if (!Tag_Find(&lines[linenum].tags, tag)) - continue; // Find tagged lines - - // Front side - this = &sides[lines[linenum].sidenum[0]]; - if (always || this->toptexture) this->toptexture = set->toptexture; - if (always || this->midtexture) this->midtexture = set->midtexture; - if (always || this->bottomtexture) this->bottomtexture = set->bottomtexture; - - if (lines[linenum].sidenum[1] == 0xffff) - continue; // One-sided stops here. - - // Back side - this = &sides[lines[linenum].sidenum[1]]; - if (always || this->toptexture) this->toptexture = set->toptexture; - if (always || this->midtexture) this->midtexture = set->midtexture; - if (always || this->bottomtexture) this->bottomtexture = set->bottomtexture; - } - } - break; - - case 440: // Play race countdown and start Metal Sonic - if (!metalrecording && !metalplayback) - G_DoPlayMetal(); - break; - - case 441: // Trigger unlockable - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer)) - { - INT32 trigid = (INT32)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - - if (trigid < 0 || trigid > 31) // limited by 32 bit variable - CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", line->sidenum[0], trigid); - else - { - unlocktriggers |= 1 << trigid; - - // Unlocked something? - if (M_UpdateUnlockablesAndExtraEmblems()) - { - S_StartSound(NULL, sfx_s3k68); - G_SaveGameData(); // only save if unlocked something - } - } - } - - // Execute one time only - line->special = 0; - break; - - case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors - { - const mobjtype_t type = (mobjtype_t)sides[line->sidenum[0]].toptexture; - statenum_t state = NUMSTATES; - sector_t *sec; - mobj_t *thing; - - if (line->sidenum[1] != 0xffff) - state = (statenum_t)sides[line->sidenum[1]].toptexture; - - TAG_ITER_SECTORS(tag, secnum) - { - boolean tryagain; - sec = sectors + secnum; - do { - tryagain = false; - for (thing = sec->thinglist; thing; thing = thing->snext) - if (thing->type == type) - { - if (state != NUMSTATES) - { - if (!P_SetMobjState(thing, state)) // set state to specific state - { // mobj was removed - tryagain = true; // snext is corrupt, we'll have to start over. - break; - } - } - else if (!P_SetMobjState(thing, thing->state->nextstate)) // set state to nextstate - { // mobj was removed - tryagain = true; // snext is corrupt, we'll have to start over. - break; - } - } - } while (tryagain); - } - break; - } - - case 443: // Calls a named Lua function - if (line->stringargs[0]) - LUA_HookLinedefExecute(line, mo, callsec); - else - CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in arg0str)\n", sizeu1(line-lines)); - break; - - case 444: // Earthquake camera - { - quake.intensity = sides[line->sidenum[0]].textureoffset; - quake.radius = sides[line->sidenum[0]].rowoffset; - quake.time = P_AproxDistance(line->dx, line->dy)>>FRACBITS; - - quake.epicenter = NULL; /// \todo - - // reasonable defaults. - if (!quake.intensity) - quake.intensity = 8<sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); - sector_t *sec; // Sector that the FOF is visible (or not visible) in - ffloor_t *rover; // FOF to vanish/un-vanish - boolean foundrover = false; // for debug, "Can't find a FOF" message - ffloortype_e oldflags; // store FOF's old flags - - TAG_ITER_SECTORS(sectag, secnum) - { - sec = sectors + secnum; - - if (!sec->ffloors) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 445 Executor: Target sector #%d has no FOFs.\n", secnum); - return; - } - - for (rover = sec->ffloors; rover; rover = rover->next) - { - if (Tag_Find(&rover->master->frontsector->tags, foftag)) - { - foundrover = true; - - oldflags = rover->flags; - - // Abracadabra! - if (line->flags & ML_NOCLIMB) - rover->flags |= FF_EXISTS; - else - rover->flags &= ~FF_EXISTS; - - // if flags changed, reset sector's light list - if (rover->flags != oldflags) - { - sec->moved = true; - P_RecalcPrecipInSector(sec); - } - } - } - - if (!foundrover) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 445 Executor: Can't find a FOF control sector with tag %d\n", foftag); - return; - } - } - } - break; - - case 446: // Make block fall remotely (acts like FF_CRUMBLE) - { - INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); - sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to make fall down - boolean foundrover = false; // for debug, "Can't find a FOF" message - player_t *player = NULL; // player that caused FOF to fall - boolean respawn = true; // should the fallen FOF respawn? - - if (mo) // NULL check - player = mo->player; - - if (line->flags & ML_NOCLIMB) // don't respawn! - respawn = false; - - TAG_ITER_SECTORS(sectag, secnum) - { - sec = sectors + secnum; - - if (!sec->ffloors) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Target sector #%d has no FOFs.\n", secnum); - return; - } - - for (rover = sec->ffloors; rover; rover = rover->next) - { - if (Tag_Find(&rover->master->frontsector->tags, foftag)) - { - foundrover = true; - - if (line->flags & ML_BLOCKMONSTERS) // FOF flags determine respawn ability instead? - respawn = !(rover->flags & FF_NORETURN) ^ !!(line->flags & ML_NOCLIMB); // no climb inverts - - EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), player, rover->alpha, respawn); - } - } - - if (!foundrover) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Can't find a FOF control sector with tag %d\n", foftag); - return; - } - } - } - break; - - case 447: // Change colormap of tagged sectors! - // Basically this special applies a colormap to the tagged sectors, just like 606 (the colormap linedef) - // Except it is activated by linedef executor, not level load - // This could even override existing colormaps I believe - // -- Monster Iestyn 14/06/18 - { - extracolormap_t *source; - if (!udmf) - source = sides[line->sidenum[0]].colormap_data; - else - { - if (!line->args[1]) - source = line->frontsector->extra_colormap; - else - { - INT32 sourcesec = Tag_Iterate_Sectors(line->args[1], 0); - if (sourcesec == -1) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 447 Executor: Can't find sector with source colormap (tag %d)!\n", line->args[1]); - return; - } - source = sectors[sourcesec].extra_colormap; - } - } - TAG_ITER_SECTORS(line->args[0], secnum) - { - if (sectors[secnum].colormap_protected) - continue; - - P_ResetColormapFader(§ors[secnum]); - - if (line->args[2] & TMCF_RELATIVE) - { - extracolormap_t *target = (!udmf && (line->flags & ML_TFERLINE) && line->sidenum[1] != 0xFFFF) ? - sides[line->sidenum[1]].colormap_data : sectors[secnum].extra_colormap; // use back colormap instead of target sector - - extracolormap_t *exc = R_AddColormaps( - target, - source, - line->args[2] & TMCF_SUBLIGHTR, - line->args[2] & TMCF_SUBLIGHTG, - line->args[2] & TMCF_SUBLIGHTB, - line->args[2] & TMCF_SUBLIGHTA, - line->args[2] & TMCF_SUBFADER, - line->args[2] & TMCF_SUBFADEG, - line->args[2] & TMCF_SUBFADEB, - line->args[2] & TMCF_SUBFADEA, - line->args[2] & TMCF_SUBFADESTART, - line->args[2] & TMCF_SUBFADEEND, - line->args[2] & TMCF_IGNOREFLAGS, - false); - - if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc))) - { - exc->colormap = R_CreateLightTable(exc); - R_AddColormapToList(exc); - sectors[secnum].extra_colormap = exc; - } - else - Z_Free(exc); - } - else - sectors[secnum].extra_colormap = source; - } - break; - } - case 448: // Change skybox viewpoint/centerpoint - if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB)) - { - INT32 viewid = sides[line->sidenum[0]].textureoffset>>FRACBITS; - INT32 centerid = sides[line->sidenum[0]].rowoffset>>FRACBITS; - - if ((line->flags & (ML_EFFECT4|ML_BLOCKMONSTERS)) == ML_EFFECT4) // Solid Midtexture is on but Block Enemies is off? - { - CONS_Alert(CONS_WARNING, - M_GetText("Skybox switch linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), - tag); - } - else - { - // set viewpoint mobj - if (!(line->flags & ML_EFFECT4)) // Solid Midtexture turns off viewpoint setting - { - if (viewid >= 0 && viewid < 16) - skyboxmo[0] = skyboxviewpnts[viewid]; - else - skyboxmo[0] = NULL; - } - - // set centerpoint mobj - if (line->flags & ML_BLOCKMONSTERS) // Block Enemies turns ON centerpoint setting - { - if (centerid >= 0 && centerid < 16) - skyboxmo[1] = skyboxcenterpnts[centerid]; - else - skyboxmo[1] = NULL; - } - } - - CONS_Debug(DBG_GAMELOGIC, "Line type 448 Executor: viewid = %d, centerid = %d, viewpoint? = %s, centerpoint? = %s\n", - viewid, - centerid, - ((line->flags & ML_EFFECT4) ? "no" : "yes"), - ((line->flags & ML_BLOCKMONSTERS) ? "yes" : "no")); - } - break; - - case 449: // Enable bosses with parameter - { - INT32 bossid = sides[line->sidenum[0]].textureoffset>>FRACBITS; - if (bossid & ~15) // if any bits other than first 16 are set - { - CONS_Alert(CONS_WARNING, - M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"), - tag); - break; - } - if (line->flags & ML_NOCLIMB) - { - bossdisabled |= (1<sidenum[0]].textureoffset>>FRACBITS; - INT32 rvalue2 = sides[line->sidenum[0]].rowoffset>>FRACBITS; - INT32 result; - - if (rvalue1 <= rvalue2) - result = P_RandomRange(rvalue1, rvalue2); - else - result = P_RandomRange(rvalue2, rvalue1); - - P_LinedefExecute((INT16)result, mo, NULL); - break; - } - - case 452: // Set FOF alpha - { - INT16 destvalue = line->sidenum[1] != 0xffff ? - (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(P_AproxDistance(line->dx, line->dy)>>FRACBITS); - INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); - sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to operate - boolean foundrover = false; // for debug, "Can't find a FOF" message - - TAG_ITER_SECTORS(sectag, secnum) - { - sec = sectors + secnum; - - if (!sec->ffloors) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Target sector #%d has no FOFs.\n", secnum); - return; - } - - for (rover = sec->ffloors; rover; rover = rover->next) - { - if (Tag_Find(&rover->master->frontsector->tags, foftag)) - { - foundrover = true; - - // If fading an invisible FOF whose render flags we did not yet set, - // initialize its alpha to 1 - // for relative alpha calc - if (!(line->flags & ML_NOCLIMB) && // do translucent - (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE - !(rover->spawnflags & FF_RENDERSIDES) && - !(rover->spawnflags & FF_RENDERPLANES) && - !(rover->flags & FF_RENDERALL)) - rover->alpha = 1; - - P_RemoveFakeFloorFader(rover); - P_FadeFakeFloor(rover, - rover->alpha, - max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), - 0, // set alpha immediately - false, NULL, // tic-based logic - false, // do not handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // handle FF_TRANSLUCENT - false, // do not handle lighting - false, // do not handle colormap - false, // do not handle collision - false, // do not do ghost fade (no collision during fade) - true); // use exact alpha values (for opengl) - } - } - - if (!foundrover) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag); - return; - } - } - break; - } - - case 453: // Fade FOF - { - INT16 destvalue = line->sidenum[1] != 0xffff ? - (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(line->dx>>FRACBITS); - INT16 speed = line->sidenum[1] != 0xffff ? - (INT16)(abs(sides[line->sidenum[1]].rowoffset>>FRACBITS)) : (INT16)(abs(line->dy)>>FRACBITS); - INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); - sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to operate - boolean foundrover = false; // for debug, "Can't find a FOF" message - size_t j = 0; // sec->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc - - TAG_ITER_SECTORS(sectag, secnum) - { - sec = sectors + secnum; - - if (!sec->ffloors) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Target sector #%d has no FOFs.\n", secnum); - return; - } - - for (rover = sec->ffloors; rover; rover = rover->next) - { - if (Tag_Find(&rover->master->frontsector->tags, foftag)) - { - foundrover = true; - - // Prevent continuous execs from interfering on an existing fade - if (!(line->flags & ML_EFFECT5) - && rover->fadingdata) - //&& ((fade_t*)rover->fadingdata)->timer > (ticbased ? 2 : speed*2)) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Fade FOF thinker already exists, timer: %d\n", ((fade_t*)rover->fadingdata)->timer); - continue; - } - - if (speed > 0) - P_AddFakeFloorFader(rover, secnum, j, - destvalue, - speed, - (line->flags & ML_EFFECT4), // tic-based logic - (line->flags & ML_EFFECT3), // Relative destvalue - !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - !(line->flags & ML_EFFECT2), // do not handle lighting - !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) - !(line->flags & ML_BOUNCY), // do not handle collision - (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) - (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) - else - { - // If fading an invisible FOF whose render flags we did not yet set, - // initialize its alpha to 1 - // for relative alpha calc - if (!(line->flags & ML_NOCLIMB) && // do translucent - (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE - !(rover->spawnflags & FF_RENDERSIDES) && - !(rover->spawnflags & FF_RENDERPLANES) && - !(rover->flags & FF_RENDERALL)) - rover->alpha = 1; - - P_RemoveFakeFloorFader(rover); - P_FadeFakeFloor(rover, - rover->alpha, - max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), - 0, // set alpha immediately - false, NULL, // tic-based logic - !(line->flags & ML_BLOCKMONSTERS), // do not handle FF_EXISTS - !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT - !(line->flags & ML_EFFECT2), // do not handle lighting - !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) - !(line->flags & ML_BOUNCY), // do not handle collision - (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) - (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) - } - } - j++; - } - - if (!foundrover) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag); - return; - } - } - break; - } - - case 454: // Stop fading FOF - { - INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); - sector_t *sec; // Sector that the FOF is visible in - ffloor_t *rover; // FOF that we are going to operate - boolean foundrover = false; // for debug, "Can't find a FOF" message - - TAG_ITER_SECTORS(sectag, secnum) - { - sec = sectors + secnum; - - if (!sec->ffloors) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Target sector #%d has no FOFs.\n", secnum); - return; - } - - for (rover = sec->ffloors; rover; rover = rover->next) - { - if (Tag_Find(&rover->master->frontsector->tags, foftag)) - { - foundrover = true; - - P_ResetFakeFloorFader(rover, NULL, - !(line->flags & ML_BLOCKMONSTERS)); // do not finalize collision flags - } - } - - if (!foundrover) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Can't find a FOF control sector with tag %d\n", foftag); - return; - } - } - break; - } - - case 455: // Fade colormap - { - extracolormap_t *dest; - if (!udmf) - dest = sides[line->sidenum[0]].colormap_data; - else - { - if (!line->args[1]) - dest = line->frontsector->extra_colormap; - else - { - INT32 destsec = Tag_Iterate_Sectors(line->args[1], 0); - if (destsec == -1) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Can't find sector with destination colormap (tag %d)!\n", line->args[1]); - return; - } - dest = sectors[destsec].extra_colormap; - } - } - - TAG_ITER_SECTORS(line->args[0], secnum) - { - extracolormap_t *source_exc, *dest_exc, *exc; - - if (sectors[secnum].colormap_protected) - continue; - - // Don't interrupt ongoing fade - if (!(line->args[3] & TMCF_OVERRIDE) - && sectors[secnum].fadecolormapdata) - //&& ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer > (ticbased ? 2 : speed*2)) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Fade color thinker already exists, timer: %d\n", ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer); - continue; - } - - if (!udmf && (line->flags & ML_TFERLINE)) // use back colormap instead of target sector - sectors[secnum].extra_colormap = (line->sidenum[1] != 0xFFFF) ? - sides[line->sidenum[1]].colormap_data : NULL; - - exc = sectors[secnum].extra_colormap; - - if (!(line->args[3] & TMCF_FROMBLACK) // Override fade from default rgba - && !R_CheckDefaultColormap(dest, true, false, false) - && R_CheckDefaultColormap(exc, true, false, false)) - { - exc = R_CopyColormap(exc, false); - exc->rgba = R_GetRgbaRGB(dest->rgba) + R_PutRgbaA(R_GetRgbaA(exc->rgba)); - //exc->fadergba = R_GetRgbaRGB(dest->rgba) + R_PutRgbaA(R_GetRgbaA(exc->fadergba)); - - if (!(source_exc = R_GetColormapFromList(exc))) - { - exc->colormap = R_CreateLightTable(exc); - R_AddColormapToList(exc); - source_exc = exc; - } - else - Z_Free(exc); - - sectors[secnum].extra_colormap = source_exc; - } - else - source_exc = exc ? exc : R_GetDefaultColormap(); - - if (line->args[3] & TMCF_RELATIVE) - { - exc = R_AddColormaps( - source_exc, - dest, - line->args[3] & TMCF_SUBLIGHTR, - line->args[3] & TMCF_SUBLIGHTG, - line->args[3] & TMCF_SUBLIGHTB, - line->args[3] & TMCF_SUBLIGHTA, - line->args[3] & TMCF_SUBFADER, - line->args[3] & TMCF_SUBFADEG, - line->args[3] & TMCF_SUBFADEB, - line->args[3] & TMCF_SUBFADEA, - line->args[3] & TMCF_SUBFADESTART, - line->args[3] & TMCF_SUBFADEEND, - line->args[3] & TMCF_IGNOREFLAGS, - false); - } - else - exc = R_CopyColormap(dest, false); - - if (!(dest_exc = R_GetColormapFromList(exc))) - { - exc->colormap = R_CreateLightTable(exc); - R_AddColormapToList(exc); - dest_exc = exc; - } - else - Z_Free(exc); - - Add_ColormapFader(§ors[secnum], source_exc, dest_exc, true, // tic-based timing - line->args[2]); - } - break; - } - case 456: // Stop fade colormap - TAG_ITER_SECTORS(line->args[0], secnum) - P_ResetColormapFader(§ors[secnum]); - break; - - case 457: // Track mobj angle to point - if (mo) - { - INT32 failureangle = FixedAngle((min(max(abs(sides[line->sidenum[0]].textureoffset>>FRACBITS), 0), 360))*FRACUNIT); - INT32 failuredelay = abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); - INT32 failureexectag = line->sidenum[1] != 0xffff ? - (INT32)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : 0; - boolean persist = (line->flags & ML_EFFECT2); - mobj_t *anchormo; - - if ((secnum = Tag_Iterate_Sectors(tag, 0)) < 0) - return; - - anchormo = P_GetObjectTypeInSectorNum(MT_ANGLEMAN, secnum); - if (!anchormo) - return; - - mo->eflags |= MFE_TRACERANGLE; - P_SetTarget(&mo->tracer, anchormo); - mo->lastlook = persist; // don't disable behavior after first failure - mo->extravalue1 = failureangle; // angle to exceed for failure state - mo->extravalue2 = failureexectag; // exec tag for failure state (angle is not within range) - mo->cusval = mo->cvmem = failuredelay; // cusval = tics to allow failure before line trigger; cvmem = decrement timer - } - break; - - case 458: // Stop tracking mobj angle to point - if (mo && (mo->eflags & MFE_TRACERANGLE)) - { - mo->eflags &= ~MFE_TRACERANGLE; - P_SetTarget(&mo->tracer, NULL); - mo->lastlook = mo->cvmem = mo->cusval = mo->extravalue1 = mo->extravalue2 = 0; - } - break; - - case 459: // Control Text Prompt - // console player only unless NOCLIMB is set - if (mo && mo->player && P_IsLocalPlayer(mo->player) && (!bot || bot != mo)) - { - INT32 promptnum = max(0, (sides[line->sidenum[0]].textureoffset>>FRACBITS)-1); - INT32 pagenum = max(0, (sides[line->sidenum[0]].rowoffset>>FRACBITS)-1); - INT32 postexectag = abs((line->sidenum[1] != 0xFFFF) ? sides[line->sidenum[1]].textureoffset>>FRACBITS : tag); - - boolean closetextprompt = (line->flags & ML_BLOCKMONSTERS); - //boolean allplayers = (line->flags & ML_NOCLIMB); - boolean runpostexec = (line->flags & ML_EFFECT1); - boolean blockcontrols = !(line->flags & ML_EFFECT2); - boolean freezerealtime = !(line->flags & ML_EFFECT3); - //boolean freezethinkers = (line->flags & ML_EFFECT4); - boolean callbynamedtag = (line->flags & ML_TFERLINE); - - if (closetextprompt) - F_EndTextPrompt(false, false); - else - { - if (callbynamedtag && sides[line->sidenum[0]].text && sides[line->sidenum[0]].text[0]) - F_GetPromptPageByNamedTag(sides[line->sidenum[0]].text, &promptnum, &pagenum); - F_StartTextPrompt(promptnum, pagenum, mo, runpostexec ? postexectag : 0, blockcontrols, freezerealtime); - } - } - break; - - case 460: // Award rings - { - INT16 rings = (sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT32 delay = (sides[line->sidenum[0]].rowoffset>>FRACBITS); - if (mo && mo->player) - { - if (delay <= 0 || !(leveltime % delay)) - P_GivePlayerRings(mo->player, rings); - } - } - break; - - case 461: // Spawns an object on the map based on texture offsets - { - const mobjtype_t type = (mobjtype_t)(sides[line->sidenum[0]].toptexture); - mobj_t *mobj; - - fixed_t x, y, z; - x = sides[line->sidenum[0]].textureoffset; - y = sides[line->sidenum[0]].rowoffset; - z = line->frontsector->floorheight; - - if (line->flags & ML_NOCLIMB) // If noclimb is set, spawn randomly within a range - { - if (line->sidenum[1] != 0xffff) // Make sure the linedef has a back side - { - x = P_RandomRange(sides[line->sidenum[0]].textureoffset>>FRACBITS, sides[line->sidenum[1]].textureoffset>>FRACBITS)<sidenum[0]].rowoffset>>FRACBITS, sides[line->sidenum[1]].rowoffset>>FRACBITS)<frontsector->floorheight>>FRACBITS, line->frontsector->ceilingheight>>FRACBITS)<special); - break; - } - } - - mobj = P_SpawnMobj(x, y, z, type); - if (mobj) - { - if (line->flags & ML_EFFECT1) - mobj->angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); - CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow. - } - else - CONS_Alert(CONS_ERROR,"Linedef Type %d - Spawn Object: Object did not spawn!\n", line->special); - } - break; - - case 462: // Stop clock (and end level in record attack) - if (G_PlatformGametype()) - { - stoppedclock = true; - CONS_Debug(DBG_GAMELOGIC, "Clock stopped!\n"); - if (modeattacking) - { - UINT8 i; - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - P_DoPlayerExit(&players[i]); - } - } - } - break; - - case 463: // Dye object - { - INT32 color = sides[line->sidenum[0]].toptexture; - - if (mo) - { - if (color < 0 || color >= numskincolors) - return; - - var1 = 0; - var2 = color; - A_Dye(mo); - } - } - break; - - case 464: // Trigger Egg Capsule - { - thinker_t *th; - mobj_t *mo2; - - // Find the center of the Eggtrap and release all the pretty animals! - // The chimps are my friends.. heeheeheheehehee..... - LouisJM - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_EGGTRAP) - continue; - - if (!mo2->spawnpoint) - continue; - - if (mo2->spawnpoint->angle != tag) - continue; - - P_KillMobj(mo2, NULL, mo, 0); - } - - if (!(line->flags & ML_NOCLIMB)) - { - INT32 i; - - // Mark all players with the time to exit thingy! - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - P_DoPlayerExit(&players[i]); - } - } - } - break; - - case 465: // Set linedef executor delay - { - INT32 linenum; - - if (!udmf) - break; - - TAG_ITER_LINES(line->args[0], linenum) - { - if (line->args[2]) - lines[linenum].executordelay += line->args[1]; - else - lines[linenum].executordelay = line->args[1]; - } - } - break; - - case 466: // Set level failure state - { - if (line->flags & ML_NOCLIMB) - { - stagefailed = false; - CONS_Debug(DBG_GAMELOGIC, "Stage can be completed successfully!\n"); - } - else - { - stagefailed = true; - CONS_Debug(DBG_GAMELOGIC, "Stage will end in failure...\n"); - } - } - break; - - case 480: // Polyobj_DoorSlide - case 481: // Polyobj_DoorSwing - PolyDoor(line); - break; - case 482: // Polyobj_Move - case 483: // Polyobj_OR_Move - PolyMove(line); - break; - case 484: // Polyobj_RotateRight - case 485: // Polyobj_OR_RotateRight - case 486: // Polyobj_RotateLeft - case 487: // Polyobj_OR_RotateLeft - PolyRotate(line); - break; - case 488: // Polyobj_Waypoint - PolyWaypoint(line); - break; - case 489: - PolyInvisible(line); - break; - case 490: - PolyVisible(line); - break; - case 491: - PolyTranslucency(line); - break; - case 492: - PolyFade(line); - break; - - default: - break; - } -} - -// -// P_SetupSignExit -// -// Finds the exit sign in the current sector and -// sets its target to the player who passed the map. -// -void P_SetupSignExit(player_t *player) -{ - mobj_t *thing; - msecnode_t *node = player->mo->subsector->sector->touching_thinglist; // things touching this sector - thinker_t *think; - INT32 numfound = 0; - - for (; node; node = node->m_thinglist_next) - { - thing = node->m_thing; - if (thing->type != MT_SIGN) - continue; - - if (!numfound - && !(player->mo->target && player->mo->target->type == MT_SIGN) - && !((gametyperules & GTR_FRIENDLY) && (netgame || multiplayer) && cv_exitmove.value)) - P_SetTarget(&player->mo->target, thing); - - if (thing->state != &states[thing->info->spawnstate]) - continue; - - P_SetTarget(&thing->target, player->mo); - P_SetObjectMomZ(thing, 12*FRACUNIT, false); - P_SetMobjState(thing, S_SIGNSPIN1); - if (thing->info->seesound) - S_StartSound(thing, thing->info->seesound); - - ++numfound; - } - - if (numfound) - return; - - // didn't find any signposts in the exit sector. - // spin all signposts in the level then. - for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) - { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - thing = (mobj_t *)think; - if (thing->type != MT_SIGN) - continue; - - if (!numfound - && !(player->mo->target && player->mo->target->type == MT_SIGN) - && !((gametyperules & GTR_FRIENDLY) && (netgame || multiplayer) && cv_exitmove.value)) - P_SetTarget(&player->mo->target, thing); - - if (thing->state != &states[thing->info->spawnstate]) - continue; - - P_SetTarget(&thing->target, player->mo); - P_SetObjectMomZ(thing, 12*FRACUNIT, false); - P_SetMobjState(thing, S_SIGNSPIN1); - if (thing->info->seesound) - S_StartSound(thing, thing->info->seesound); - - ++numfound; - } -} - -// -// P_IsFlagAtBase -// -// Checks to see if a flag is at its base. -// -boolean P_IsFlagAtBase(mobjtype_t flag) -{ - thinker_t *think; - mobj_t *mo; - INT32 specialnum = (flag == MT_REDFLAG) ? 3 : 4; - - for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) - { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo = (mobj_t *)think; - - if (mo->type != flag) - continue; - - if (GETSECSPECIAL(mo->subsector->sector->special, 4) == specialnum) - return true; - else if (mo->subsector->sector->ffloors) // Check the 3D floors - { - ffloor_t *rover; - - for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS)) - continue; - - if (GETSECSPECIAL(rover->master->frontsector->special, 4) != specialnum) - continue; - - if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) - && mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector))) - continue; - - return true; - } - } - } - return false; -} - -// -// P_PlayerTouchingSectorSpecial -// -// Replaces the old player->specialsector. -// This allows a player to touch more than -// one sector at a time, if necessary. -// -// Returns a pointer to the first sector of -// the particular type that it finds. -// Returns NULL if it doesn't find it. -// -sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number) -{ - msecnode_t *node; - ffloor_t *rover; - - if (!player->mo) - return NULL; - - // Check default case first - if (GETSECSPECIAL(player->mo->subsector->sector->special, section) == number) - return player->mo->subsector->sector; - - // Hmm.. maybe there's a FOF that has it... - for (rover = player->mo->subsector->sector->ffloors; rover; rover = rover->next) - { - fixed_t topheight, bottomheight; - - if (GETSECSPECIAL(rover->master->frontsector->special, section) != number) - continue; - - if (!(rover->flags & FF_EXISTS)) - continue; - - topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); - bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); - - // Check the 3D floor's type... - if (rover->flags & FF_BLOCKPLAYER) - { - boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); - boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - continue; - } - else - { - // Water and DEATH FOG!!! heh - if (player->mo->z > topheight || (player->mo->z + player->mo->height) < bottomheight) - continue; - } - - // This FOF has the special we're looking for! - return rover->master->frontsector; - } - - for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (GETSECSPECIAL(node->m_sector->special, section) == number) - { - // This sector has the special we're looking for, but - // are we allowed to touch it? - if (node->m_sector == player->mo->subsector->sector - || (node->m_sector->flags & SF_TRIGGERSPECIAL_TOUCH)) - return node->m_sector; - } - - // Hmm.. maybe there's a FOF that has it... - for (rover = node->m_sector->ffloors; rover; rover = rover->next) - { - fixed_t topheight, bottomheight; - - if (GETSECSPECIAL(rover->master->frontsector->special, section) != number) - continue; - - if (!(rover->flags & FF_EXISTS)) - continue; - - topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); - bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); - - // Check the 3D floor's type... - if (rover->flags & FF_BLOCKPLAYER) - { - boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); - boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - continue; - } - else - { - // Water and DEATH FOG!!! heh - if (player->mo->z > topheight || (player->mo->z + player->mo->height) < bottomheight) - continue; - } - - // This FOF has the special we're looking for, but are we allowed to touch it? - if (node->m_sector == player->mo->subsector->sector - || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) - return rover->master->frontsector; - } - } - - return NULL; -} - -// -// P_ThingIsOnThe3DFloor -// -// This checks whether the mobj is on/in the FOF we want it to be at -// Needed for the "All players" trigger sector specials only -// -static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *targetsec) -{ - ffloor_t *rover; - fixed_t top, bottom; - - if (!mo->player) // should NEVER happen - return false; - - if (!targetsec->ffloors) // also should NEVER happen - return false; - - for (rover = targetsec->ffloors; rover; rover = rover->next) - { - if (rover->master->frontsector != sector) - continue; - - // we're assuming the FOF existed when the first player touched it - //if (!(rover->flags & FF_EXISTS)) - // return false; - - top = P_GetSpecialTopZ(mo, sector, targetsec); - bottom = P_GetSpecialBottomZ(mo, sector, targetsec); - - // Check the 3D floor's type... - if (rover->flags & FF_BLOCKPLAYER) - { - boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == top)); - boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottom)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - continue; - } - else - { - // Water and intangible FOFs - if (mo->z > top || (mo->z + mo->height) < bottom) - return false; - } - - return true; - } - - return false; -} - -// -// P_MobjReadyToTrigger -// -// Is player standing on the sector's "ground"? -// -static boolean P_MobjReadyToTrigger(mobj_t *mo, sector_t *sec) -{ - boolean floorallowed = ((sec->flags & SF_FLIPSPECIAL_FLOOR) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == P_GetSpecialBottomZ(mo, sec, sec))); - boolean ceilingallowed = ((sec->flags & SF_FLIPSPECIAL_CEILING) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == P_GetSpecialTopZ(mo, sec, sec))); - // Thing must be on top of the floor to be affected... - return (floorallowed || ceilingallowed); -} - -/** Applies a sector special to a player. - * - * \param player Player in the sector. - * \param sector Sector with the special. - * \param roversector If !NULL, sector is actually an FOF; otherwise, sector - * is being physically contacted by the player. - * \todo Split up into multiple functions. - * \sa P_PlayerInSpecialSector, P_PlayerOnSpecial3DFloor - */ -void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector) -{ - INT32 i = 0; - INT32 section1, section2, section3, section4; - INT32 special; - mtag_t sectag = Tag_FGet(§or->tags); - - section1 = GETSECSPECIAL(sector->special, 1); - section2 = GETSECSPECIAL(sector->special, 2); - section3 = GETSECSPECIAL(sector->special, 3); - section4 = GETSECSPECIAL(sector->special, 4); - - // Ignore spectators - if (player->spectator) - return; - - // Ignore dead players. - // If this strange phenomenon could be potentially used in levels, - // TODO: modify this to accommodate for it. - if (player->playerstate != PST_LIVE) - return; - - // Conveyor stuff - if (section3 == 2 || section3 == 4) - player->onconveyor = section3; - - special = section1; - - // Process Section 1 - switch (special) - { - case 1: // Damage (Generic) - if (roversector || P_MobjReadyToTrigger(player->mo, sector)) - P_DamageMobj(player->mo, NULL, NULL, 1, 0); - break; - case 2: // Damage (Water) - if ((roversector || P_MobjReadyToTrigger(player->mo, sector)) && (player->powers[pw_underwater] || player->powers[pw_carry] == CR_NIGHTSMODE)) - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_WATER); - break; - case 3: // Damage (Fire) - if (roversector || P_MobjReadyToTrigger(player->mo, sector)) - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_FIRE); - break; - case 4: // Damage (Electrical) - if (roversector || P_MobjReadyToTrigger(player->mo, sector)) - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_ELECTRIC); - break; - case 5: // Spikes - if (roversector || P_MobjReadyToTrigger(player->mo, sector)) - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPIKE); - break; - case 6: // Death Pit (Camera Mod) - case 7: // Death Pit (No Camera Mod) - if (roversector || P_MobjReadyToTrigger(player->mo, sector)) - { - if (player->quittime) - G_MovePlayerToSpawnOrStarpost(player - players); - else - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT); - } - break; - case 8: // Instant Kill - if (player->quittime) - G_MovePlayerToSpawnOrStarpost(player - players); - else - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); - break; - case 9: // Ring Drainer (Floor Touch) - case 10: // Ring Drainer (No Floor Touch) - if (leveltime % (TICRATE/2) == 0 && player->rings > 0) - { - player->rings--; - S_StartSound(player->mo, sfx_antiri); - } - break; - case 11: // Special Stage Damage - if (player->exiting || player->bot) // Don't do anything for bots or players who have just finished - break; - - if (!(player->powers[pw_shield] || player->spheres > 0)) // Don't do anything if no shield or spheres anyway - break; - - P_SpecialStageDamage(player, NULL, NULL); - break; - case 12: // Space Countdown - if (!(player->powers[pw_shield] & SH_PROTECTWATER) && !player->powers[pw_spacetime]) - player->powers[pw_spacetime] = spacetimetics + 1; - break; - case 13: // Ramp Sector (Increase step-up/down) - case 14: // Non-Ramp Sector (Don't step-down) - case 15: // Unused - break; - } - - special = section2; - - // Process Section 2 - switch (special) - { - case 1: // Trigger Linedef Exec (Pushable Objects) - break; - case 2: // Linedef executor requires all players present+doesn't require touching floor - case 3: // Linedef executor requires all players present - /// \todo check continues for proper splitscreen support? - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - if (!players[i].mo) - continue; - if (players[i].spectator) - continue; - if (players[i].bot) - continue; - if (G_CoopGametype() && players[i].lives <= 0) - continue; - if (roversector) - { - if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) - { - msecnode_t *node; - for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (P_ThingIsOnThe3DFloor(players[i].mo, sector, node->m_sector)) - break; - } - if (!node) - goto DoneSection2; - } - else if (players[i].mo->subsector && !P_ThingIsOnThe3DFloor(players[i].mo, sector, players[i].mo->subsector->sector)) // this function handles basically everything for us lmao - goto DoneSection2; - } - else - { - if (players[i].mo->subsector->sector == sector) - ; - else if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) - { - msecnode_t *node; - for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (node->m_sector == sector) - break; - } - if (!node) - goto DoneSection2; - } - else - goto DoneSection2; - - if (special == 3 && !P_MobjReadyToTrigger(players[i].mo, sector)) - goto DoneSection2; - } - } - /* FALLTHRU */ - case 4: // Linedef executor that doesn't require touching floor - case 5: // Linedef executor - case 6: // Linedef executor (7 Emeralds) - case 7: // Linedef executor (NiGHTS Mare) - if (!player->bot) - P_LinedefExecute(sectag, player->mo, sector); - break; - case 8: // Tells pushable things to check FOFs - break; - case 9: // Egg trap capsule - { - thinker_t *th; - mobj_t *mo2; - line_t junk; - - if (player->bot || sector->ceilingdata || sector->floordata) - return; - - // Find the center of the Eggtrap and release all the pretty animals! - // The chimps are my friends.. heeheeheheehehee..... - LouisJM - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - mo2 = (mobj_t *)th; - if (mo2->type != MT_EGGTRAP) - continue; - P_KillMobj(mo2, NULL, player->mo, 0); - } - - // clear the special so you can't push the button twice. - sector->special = 0; - - // Initialize my junk - junk.tags.tags = NULL; - junk.tags.count = 0; - - // Move the button down - Tag_FSet(&junk.tags, LE_CAPSULE0); - EV_DoElevator(&junk, elevateDown, false); - - // Open the top FOF - Tag_FSet(&junk.tags, LE_CAPSULE1); - EV_DoFloor(&junk, raiseFloorToNearestFast); - // Open the bottom FOF - Tag_FSet(&junk.tags, LE_CAPSULE2); - EV_DoCeiling(&junk, lowerToLowestFast); - - // Mark all players with the time to exit thingy! - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - P_DoPlayerExit(&players[i]); - } - break; - } - case 10: // Special Stage Time/Rings - case 11: // Custom Gravity - break; - case 12: // Lua sector special - break; - } -DoneSection2: - - special = section3; - - // Process Section 3 - switch (special) - { - case 1: // Unused - case 2: // Wind/Current - case 3: // Unused - case 4: // Conveyor Belt - break; - - case 5: // Speed pad - if (player->powers[pw_flashing] != 0 && player->powers[pw_flashing] < TICRATE/2) - break; - - i = Tag_FindLineSpecial(4, sectag); - - if (i != -1) - { - angle_t lineangle; - fixed_t linespeed; - fixed_t sfxnum; - - lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); - linespeed = sides[lines[i].sidenum[0]].textureoffset; - - if (linespeed == 0) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Speed pad (tag %d) at zero speed.\n", sectag); - break; - } - - player->mo->angle = player->drawangle = lineangle; - - if (!demoplayback || P_ControlStyle(player) == CS_LMAOGALOG) - P_SetPlayerAngle(player, player->mo->angle); - - if (!(lines[i].flags & ML_EFFECT4)) - { - P_UnsetThingPosition(player->mo); - if (roversector) // make FOF speed pads work - { - player->mo->x = roversector->soundorg.x; - player->mo->y = roversector->soundorg.y; - } - else - { - player->mo->x = sector->soundorg.x; - player->mo->y = sector->soundorg.y; - } - P_SetThingPosition(player->mo); - } - - P_InstaThrust(player->mo, player->mo->angle, linespeed); - - if (lines[i].flags & ML_EFFECT5) // Roll! - { - if (!(player->pflags & PF_SPINNING)) - player->pflags |= PF_SPINNING; - - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - } - - player->powers[pw_flashing] = TICRATE/3; - - sfxnum = sides[lines[i].sidenum[0]].toptexture; - - if (!sfxnum) - sfxnum = sfx_spdpad; - - S_StartSound(player->mo, sfxnum); - } - break; - - case 6: // Unused - case 7: // Unused - case 8: // Unused - case 9: // Unused - case 10: // Unused - case 11: // Unused - case 12: // Unused - case 13: // Unused - case 14: // Unused - case 15: // Unused - break; - } - - special = section4; - - // Process Section 4 - switch (special) - { - case 1: // Starpost Activator - { - mobj_t *post = P_GetObjectTypeInSectorNum(MT_STARPOST, sector - sectors); - - if (!post) - break; - - P_TouchStarPost(post, player, false); - break; - } - - case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return - if (player->bot || !(gametyperules & GTR_ALLOWEXIT)) - break; - if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6) - { - player->nightstime = 6; // Just let P_Ticker take care of the rest. - return; - } - - // Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c) - { - INT32 lineindex; - - P_DoPlayerFinish(player); - - P_SetupSignExit(player); - // important: use sector->tag on next line instead of player->mo->subsector->tag - // this part is different from in P_PlayerThink, this is what was causing - // FOF custom exits not to work. - lineindex = Tag_FindLineSpecial(2, sectag); - - if (G_CoopGametype() && lineindex != -1) // Custom exit! - { - // Special goodies with the block monsters flag depending on emeralds collected - if ((lines[lineindex].flags & ML_BLOCKMONSTERS) && ALL7EMERALDS(emeralds)) - nextmapoverride = (INT16)(lines[lineindex].frontsector->ceilingheight>>FRACBITS); - else - nextmapoverride = (INT16)(lines[lineindex].frontsector->floorheight>>FRACBITS); - - if (lines[lineindex].flags & ML_NOCLIMB) - skipstats = 1; - } - } - break; - - case 3: // Red Team's Base - if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo)) - { - if (player->ctfteam == 1 && (player->gotflag & GF_BLUEFLAG)) - { - mobj_t *mo; - - // Make sure the red team still has their own - // flag at their base so they can score. - if (!P_IsFlagAtBase(MT_REDFLAG)) - break; - - HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE); - HU_SetCEchoDuration(5); - HU_DoCEcho(va(M_GetText("\205%s\200\\CAPTURED THE \204BLUE FLAG\200.\\\\\\\\"), player_names[player-players])); - - if (splitscreen || players[consoleplayer].ctfteam == 1) - S_StartSound(NULL, sfx_flgcap); - else if (players[consoleplayer].ctfteam == 2) - S_StartSound(NULL, sfx_lose); - - mo = P_SpawnMobj(player->mo->x,player->mo->y,player->mo->z,MT_BLUEFLAG); - player->gotflag &= ~GF_BLUEFLAG; - mo->flags &= ~MF_SPECIAL; - mo->fuse = TICRATE; - mo->spawnpoint = bflagpoint; - mo->flags2 |= MF2_JUSTATTACKED; - redscore += 1; - P_AddPlayerScore(player, 250); - } - } - break; - - case 4: // Blue Team's Base - if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo)) - { - if (player->ctfteam == 2 && (player->gotflag & GF_REDFLAG)) - { - mobj_t *mo; - - // Make sure the blue team still has their own - // flag at their base so they can score. - if (!P_IsFlagAtBase(MT_BLUEFLAG)) - break; - - HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE); - HU_SetCEchoDuration(5); - HU_DoCEcho(va(M_GetText("\204%s\200\\CAPTURED THE \205RED FLAG\200.\\\\\\\\"), player_names[player-players])); - - if (splitscreen || players[consoleplayer].ctfteam == 2) - S_StartSound(NULL, sfx_flgcap); - else if (players[consoleplayer].ctfteam == 1) - S_StartSound(NULL, sfx_lose); - - mo = P_SpawnMobj(player->mo->x,player->mo->y,player->mo->z,MT_REDFLAG); - player->gotflag &= ~GF_REDFLAG; - mo->flags &= ~MF_SPECIAL; - mo->fuse = TICRATE; - mo->spawnpoint = rflagpoint; - mo->flags2 |= MF2_JUSTATTACKED; - bluescore += 1; - P_AddPlayerScore(player, 250); - } - } - break; - - case 5: // Fan sector - player->mo->momz += mobjinfo[MT_FAN].mass/4; - - if (player->mo->momz > mobjinfo[MT_FAN].mass) - player->mo->momz = mobjinfo[MT_FAN].mass; - - P_ResetPlayer(player); - if (player->panim != PA_FALL) - P_SetPlayerMobjState(player->mo, S_PLAY_FALL); - break; - - case 6: // Super Sonic transformer - if (player->mo->health > 0 && !player->bot && (player->charflags & SF_SUPER) && !player->powers[pw_super] && ALL7EMERALDS(emeralds)) - P_DoSuperTransformation(player, true); - break; - - case 7: // Make player spin - if (!(player->pflags & PF_SPINNING)) - { - player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartAttackSound(player->mo, sfx_spin); - - if (abs(player->rmomx) < FixedMul(5*FRACUNIT, player->mo->scale) - && abs(player->rmomy) < FixedMul(5*FRACUNIT, player->mo->scale)) - P_InstaThrust(player->mo, player->mo->angle, FixedMul(10*FRACUNIT, player->mo->scale)); - } - break; - - case 8: // Zoom Tube Start - { - INT32 sequence; - fixed_t speed; - INT32 lineindex; - mobj_t *waypoint = NULL; - angle_t an; - - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) - break; - - if (player->powers[pw_ignorelatch] & (1<<15)) - break; - - // Find line #3 tagged to this sector - lineindex = Tag_FindLineSpecial(3, sectag); - - if (lineindex == -1) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #3.\n", sector->special); - break; - } - - // Grab speed and sequence values - speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; - sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; - - if (speed == 0) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); - break; - } - - waypoint = P_GetFirstWaypoint(sequence); - - if (!waypoint) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: FIRST WAYPOINT IN SEQUENCE %d NOT FOUND.\n", sequence); - break; - } - else - { - CONS_Debug(DBG_GAMELOGIC, "Waypoint %d found in sequence %d - speed = %d\n", waypoint->health, sequence, speed); - } - - an = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->x, waypoint->y) - player->mo->angle; - - if (an > ANGLE_90 && an < ANGLE_270 && !(lines[lineindex].flags & ML_EFFECT4)) - break; // behind back - - P_SetTarget(&player->mo->tracer, waypoint); - player->powers[pw_carry] = CR_ZOOMTUBE; - player->speed = speed; - player->pflags |= PF_SPINNING; - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); - player->climbing = 0; - - if (player->mo->state-states != S_PLAY_ROLL) - { - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_spin); - } - } - break; - - case 9: // Zoom Tube End - { - INT32 sequence; - fixed_t speed; - INT32 lineindex; - mobj_t *waypoint = NULL; - angle_t an; - - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) - break; - - if (player->powers[pw_ignorelatch] & (1<<15)) - break; - - // Find line #3 tagged to this sector - lineindex = Tag_FindLineSpecial(3, sectag); - - if (lineindex == -1) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #3.\n", sector->special); - break; - } - - // Grab speed and sequence values - speed = -abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; // Negative means reverse - sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; - - if (speed == 0) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); - break; - } - - waypoint = P_GetLastWaypoint(sequence); - - if (!waypoint) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: LAST WAYPOINT IN SEQUENCE %d NOT FOUND.\n", sequence); - break; - } - else - { - CONS_Debug(DBG_GAMELOGIC, "Waypoint %d found in sequence %d - speed = %d\n", waypoint->health, sequence, speed); - } - - an = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->x, waypoint->y) - player->mo->angle; - - if (an > ANGLE_90 && an < ANGLE_270 && !(lines[lineindex].flags & ML_EFFECT4)) - break; // behind back - - P_SetTarget(&player->mo->tracer, waypoint); - player->powers[pw_carry] = CR_ZOOMTUBE; - player->speed = speed; - player->pflags |= PF_SPINNING; - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); - player->climbing = 0; - - if (player->mo->state-states != S_PLAY_ROLL) - { - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_spin); - } - } - break; - - case 10: // Finish Line - if (((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE) && !player->exiting) - { - if (player->starpostnum == numstarposts) // Must have touched all the starposts - { - player->laps++; - - if (player->powers[pw_carry] == CR_NIGHTSMODE) - player->drillmeter += 48*20; - - if (player->laps >= (UINT8)cv_numlaps.value) - CONS_Printf(M_GetText("%s has finished the race.\n"), player_names[player-players]); - else if (player->laps == (UINT8)cv_numlaps.value-1) - CONS_Printf(M_GetText("%s started the \205final lap\200!\n"), player_names[player-players]); - else - CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1); - - // Reset starposts (checkpoints) info - player->starpostscale = player->starpostangle = player->starposttime = player->starpostnum = 0; - player->starpostx = player->starposty = player->starpostz = 0; - P_ResetStarposts(); - - // Play the starpost sound for 'consistency' - S_StartSound(player->mo, sfx_strpst); - } - else if (player->starpostnum) - { - // blatant reuse of a variable that's normally unused in circuit - if (!player->tossdelay) - S_StartSound(player->mo, sfx_lose); - player->tossdelay = 3; - } - - if (player->laps >= (unsigned)cv_numlaps.value) - { - if (P_IsLocalPlayer(player)) - { - HU_SetCEchoFlags(0); - HU_SetCEchoDuration(5); - HU_DoCEcho("FINISHED!"); - } - - P_DoPlayerExit(player); - } - } - break; - - case 11: // Rope hang - { - INT32 sequence; - fixed_t speed; - INT32 lineindex; - mobj_t *waypointmid = NULL; - mobj_t *waypointhigh = NULL; - mobj_t *waypointlow = NULL; - mobj_t *closest = NULL; - vector3_t p, line[2], resulthigh, resultlow; - - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG) - break; - - if (player->powers[pw_ignorelatch] & (1<<15)) - break; - - if (player->mo->momz > 0) - break; - - if (player->cmd.buttons & BT_SPIN) - break; - - if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate]) - break; - - if (player->exiting) - break; - - //initialize resulthigh and resultlow with 0 - memset(&resultlow, 0x00, sizeof(resultlow)); - memset(&resulthigh, 0x00, sizeof(resulthigh)); - - // Find line #11 tagged to this sector - lineindex = Tag_FindLineSpecial(11, sectag); - - if (lineindex == -1) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #11.\n", sector->special); - break; - } - - // Grab speed and sequence values - speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; - sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; - - if (speed == 0) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); - break; - } - - // Find the closest waypoint - // Find the preceding waypoint - // Find the proceeding waypoint - // Determine the closest spot on the line between the three waypoints - // Put player at that location. - - waypointmid = P_GetClosestWaypoint(sequence, player->mo); - - if (!waypointmid) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: WAYPOINT(S) IN SEQUENCE %d NOT FOUND.\n", sequence); - break; - } - - waypointlow = P_GetPreviousWaypoint(waypointmid, true); - waypointhigh = P_GetNextWaypoint(waypointmid, true); - - CONS_Debug(DBG_GAMELOGIC, "WaypointMid: %d; WaypointLow: %d; WaypointHigh: %d\n", - waypointmid->health, waypointlow ? waypointlow->health : -1, waypointhigh ? waypointhigh->health : -1); - - // Now we have three waypoints... the closest one we're near, and the one that comes before, and after. - // 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) - { - 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(&p, line, &resultlow); - } - - // Waypointmid and Waypointhigh: - if (waypointhigh) - { - 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(&p, line, &resulthigh); - } - - // 3D support now available. Disregard the previous notice here. -Red - - P_UnsetThingPosition(player->mo); - P_ResetPlayer(player); - player->mo->momx = player->mo->momy = player->mo->momz = 0; - - if (lines[lineindex].flags & ML_EFFECT1) // Don't wrap - { - mobj_t *highest = P_GetLastWaypoint(sequence); - highest->flags |= MF_SLIDEME; - } - - // Changing the conditions on these ifs to fix issues with snapping to the wrong spot -Red - if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == 0) - { - closest = waypointhigh; - player->mo->x = resulthigh.x; - player->mo->y = resulthigh.y; - player->mo->z = resulthigh.z - P_GetPlayerHeight(player); - } - else if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == numwaypoints[sequence] - 1) - { - closest = waypointmid; - player->mo->x = resultlow.x; - player->mo->y = resultlow.y; - player->mo->z = resultlow.z - P_GetPlayerHeight(player); - } - else - { - if (P_AproxDistance(P_AproxDistance(player->mo->x-resultlow.x, player->mo->y-resultlow.y), - player->mo->z-resultlow.z) < P_AproxDistance(P_AproxDistance(player->mo->x-resulthigh.x, - player->mo->y-resulthigh.y), player->mo->z-resulthigh.z)) - { - // Line between Mid and Low is closer - closest = waypointmid; - player->mo->x = resultlow.x; - player->mo->y = resultlow.y; - player->mo->z = resultlow.z - P_GetPlayerHeight(player); - } - else - { - // Line between Mid and High is closer - closest = waypointhigh; - player->mo->x = resulthigh.x; - player->mo->y = resulthigh.y; - player->mo->z = resulthigh.z - P_GetPlayerHeight(player); - } - } - - P_SetTarget(&player->mo->tracer, closest); - player->powers[pw_carry] = CR_ROPEHANG; - - // Option for static ropes. - if (lines[lineindex].flags & ML_NOCLIMB) - player->speed = 0; - else - player->speed = speed; - - S_StartSound(player->mo, sfx_s3k4a); - - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY); - player->climbing = 0; - P_SetThingPosition(player->mo); - P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); - } - break; - case 12: // Camera noclip - case 13: // Unused - case 14: // Unused - case 15: // Unused - break; - } -} - -/** Checks if an object is standing on or is inside a special 3D floor. - * If so, the sector is returned. - * - * \param mo Object to check. - * \return Pointer to the sector with a special type, or NULL if no special 3D - * floors are being contacted. - * \sa P_PlayerOnSpecial3DFloor - */ -sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) -{ - sector_t *sector; - ffloor_t *rover; - fixed_t topheight, bottomheight; - - sector = mo->subsector->sector; - if (!sector->ffloors) - return NULL; - - for (rover = sector->ffloors; rover; rover = rover->next) - { - if (!rover->master->frontsector->special) - continue; - - if (!(rover->flags & FF_EXISTS)) - continue; - - topheight = P_GetSpecialTopZ(mo, sectors + rover->secnum, sector); - bottomheight = P_GetSpecialBottomZ(mo, sectors + rover->secnum, sector); - - // Check the 3D floor's type... - if (((rover->flags & FF_BLOCKPLAYER) && mo->player) - || ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) - { - boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == topheight)); - boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottomheight)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - continue; - } - else - { - // Water and intangible FOFs - if (mo->z > topheight || (mo->z + mo->height) < bottomheight) - continue; - } - - return rover->master->frontsector; - } - - return NULL; -} - -#define TELEPORTED (player->mo->subsector->sector != originalsector) - -/** Checks if a player is standing on or is inside a 3D floor (e.g. water) and - * applies any specials. - * - * \param player Player to check. - * \sa P_ThingOnSpecial3DFloor, P_PlayerInSpecialSector - */ -static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) -{ - sector_t *originalsector = player->mo->subsector->sector; - ffloor_t *rover; - fixed_t topheight, bottomheight; - - for (rover = sector->ffloors; rover; rover = rover->next) - { - if (!rover->master->frontsector->special) - continue; - - if (!(rover->flags & FF_EXISTS)) - continue; - - topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, sector); - bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, sector); - - // Check the 3D floor's type... - if (rover->flags & FF_BLOCKPLAYER) - { - boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); - boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - continue; - } - else - { - // Water and DEATH FOG!!! heh - if (player->mo->z > topheight || (player->mo->z + player->mo->height) < bottomheight) - continue; - } - - // This FOF has the special we're looking for, but are we allowed to touch it? - if (sector == player->mo->subsector->sector - || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) - { - P_ProcessSpecialSector(player, rover->master->frontsector, sector); - if TELEPORTED return; - } - } - - // Allow sector specials to be applied to polyobjects! - if (player->mo->subsector->polyList) - { - polyobj_t *po = player->mo->subsector->polyList; - sector_t *polysec; - boolean touching = false; - boolean inside = false; - - while (po) - { - if (po->flags & POF_NOSPECIALS) - { - po = (polyobj_t *)(po->link.next); - continue; - } - - polysec = po->lines[0]->backsector; - - if ((polysec->flags & SF_TRIGGERSPECIAL_TOUCH)) - touching = P_MobjTouchingPolyobj(po, player->mo); - else - touching = false; - - inside = P_MobjInsidePolyobj(po, player->mo); - - if (!(inside || touching)) - { - po = (polyobj_t *)(po->link.next); - continue; - } - - // We're inside it! Yess... - if (!polysec->special) - { - po = (polyobj_t *)(po->link.next); - continue; - } - - if (!(po->flags & POF_TESTHEIGHT)) // Don't do height checking - ; - else if (po->flags & POF_SOLID) - { - boolean floorallowed = ((polysec->flags & SF_FLIPSPECIAL_FLOOR) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == polysec->ceilingheight)); - boolean ceilingallowed = ((polysec->flags & SF_FLIPSPECIAL_CEILING) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == polysec->floorheight)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - { - po = (polyobj_t *)(po->link.next); - continue; - } - } - else - { - // Water and DEATH FOG!!! heh - if (player->mo->z > polysec->ceilingheight || (player->mo->z + player->mo->height) < polysec->floorheight) - { - po = (polyobj_t *)(po->link.next); - continue; - } - } - - P_ProcessSpecialSector(player, polysec, sector); - if TELEPORTED return; - - po = (polyobj_t *)(po->link.next); - } - } -} - -#define VDOORSPEED (FRACUNIT*2) - -// -// P_RunSpecialSectorCheck -// -// Helper function to P_PlayerInSpecialSector -// -static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector) -{ - boolean nofloorneeded = false; - fixed_t f_affectpoint, c_affectpoint; - - if (!sector->special) // nothing special, exit - return; - - if (GETSECSPECIAL(sector->special, 2) == 9) // Egg trap capsule -- should only be for 3dFloors! - return; - - // The list of specials that activate without floor touch - // Check Section 1 - switch(GETSECSPECIAL(sector->special, 1)) - { - case 2: // Damage (water) - case 8: // Instant kill - case 10: // Ring drainer that doesn't require floor touch - case 12: // Space countdown - nofloorneeded = true; - break; - } - - // Check Section 2 - switch(GETSECSPECIAL(sector->special, 2)) - { - case 2: // Linedef executor (All players needed) - case 4: // Linedef executor - case 6: // Linedef executor (7 Emeralds) - case 7: // Linedef executor (NiGHTS Mare) - nofloorneeded = true; - break; - } - - // Check Section 3 -/* switch(GETSECSPECIAL(sector->special, 3)) - { - - }*/ - - // Check Section 4 - switch(GETSECSPECIAL(sector->special, 4)) - { - case 2: // Level Exit / GOAL Sector / Flag Return - if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap)) - { - // Special stage GOAL sector - // requires touching floor. - break; - } - /* FALLTHRU */ - - case 1: // Starpost activator - case 5: // Fan sector - case 6: // Super Sonic Transform - case 8: // Zoom Tube Start - case 9: // Zoom Tube End - case 10: // Finish line - nofloorneeded = true; - break; - } - - if (nofloorneeded) - { - P_ProcessSpecialSector(player, sector, NULL); - return; - } - - f_affectpoint = P_GetSpecialBottomZ(player->mo, sector, sector); - c_affectpoint = P_GetSpecialTopZ(player->mo, sector, sector); - - { - boolean floorallowed = ((sector->flags & SF_FLIPSPECIAL_FLOOR) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == f_affectpoint)); - boolean ceilingallowed = ((sector->flags & SF_FLIPSPECIAL_CEILING) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == c_affectpoint)); - // Thing must be on top of the floor to be affected... - if (!(floorallowed || ceilingallowed)) - return; - } - - P_ProcessSpecialSector(player, sector, NULL); -} - -/** Checks if the player is in a special sector or FOF and apply any specials. - * - * \param player Player to check. - * \sa P_PlayerOnSpecial3DFloor, P_ProcessSpecialSector - */ -void P_PlayerInSpecialSector(player_t *player) -{ - sector_t *originalsector; - sector_t *loopsector; - msecnode_t *node; - - if (!player->mo) - return; - - originalsector = player->mo->subsector->sector; - - P_PlayerOnSpecial3DFloor(player, originalsector); // Handle FOFs first. - if TELEPORTED return; - - P_RunSpecialSectorCheck(player, originalsector); - if TELEPORTED return; - - // Iterate through touching_sectorlist for SF_TRIGGERSPECIAL_TOUCH - for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - loopsector = node->m_sector; - - if (loopsector == originalsector) // Don't duplicate - continue; - - // Check 3D floors... - P_PlayerOnSpecial3DFloor(player, loopsector); - if TELEPORTED return; - - if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) - continue; - - P_RunSpecialSectorCheck(player, loopsector); - if TELEPORTED return; - } -} - -#undef TELEPORTED - -/** Animate planes, scroll walls, etc. and keeps track of level timelimit and exits if time is up. - * - * \sa P_CheckTimeLimit, P_CheckPointLimit - */ -void P_UpdateSpecials(void) -{ - anim_t *anim; - INT32 i; - INT32 pic; - size_t j; - - levelflat_t *foundflats; // for flat animation - - // LEVEL TIMER - P_CheckTimeLimit(); - - // POINT LIMIT - P_CheckPointLimit(); - - // ANIMATE TEXTURES - for (anim = anims; anim < lastanim; anim++) - { - for (i = 0; i < anim->numpics; i++) - { - pic = anim->basepic + ((leveltime/anim->speed + i) % anim->numpics); - if (anim->istexture) - texturetranslation[anim->basepic+i] = pic; - } - } - - // ANIMATE FLATS - /// \todo do not check the non-animate flat.. link the animated ones? - /// \note its faster than the original anywaysince it animates only - /// flats used in the level, and there's usually very few of them - foundflats = levelflats; - for (j = 0; j < numlevelflats; j++, foundflats++) - { - if (foundflats->speed) // it is an animated flat - { - // update the levelflat texture number - if ((foundflats->type == LEVELFLAT_TEXTURE) && (foundflats->u.texture.basenum != -1)) - foundflats->u.texture.num = foundflats->u.texture.basenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); - // update the levelflat lump number - else if ((foundflats->type == LEVELFLAT_FLAT) && (foundflats->u.flat.baselumpnum != LUMPERROR)) - foundflats->u.flat.lumpnum = foundflats->u.flat.baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); - } - } -} - -// -// Floor over floors (FOFs), 3Dfloors, 3Dblocks, fake floors (ffloors), rovers, or whatever you want to call them -// - -/** Gets the ID number for a 3Dfloor in its target sector. - * - * \param fflr The 3Dfloor we want an ID for. - * \return ID of 3Dfloor in target sector. Note that the first FOF's ID is 0. UINT16_MAX is given if invalid. - * \sa P_GetFFloorByID - */ -UINT16 P_GetFFloorID(ffloor_t *fflr) -{ - ffloor_t *rover; - sector_t *sec; - UINT16 i = 0; - - if (!fflr) - return UINT16_MAX; - - sec = fflr->target; - - if (!sec->ffloors) - return UINT16_MAX; - for (rover = sec->ffloors; rover; rover = rover->next, i++) - if (rover == fflr) - return i; - return UINT16_MAX; -} - -/** Gets a 3Dfloor by control sector. - * - * \param sec Target sector. - * \param sec2 Control sector. - * \return Pointer to found 3Dfloor, or NULL. - * \sa P_GetFFloorByID - */ -static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2) -{ - ffloor_t *rover; - - if (!sec->ffloors) - return NULL; - for (rover = sec->ffloors; rover; rover = rover->next) - if (rover->secnum == (size_t)(sec2 - sectors)) - return rover; - return NULL; -} - -/** Gets a 3Dfloor by ID number. - * - * \param sec Target sector. - * \param id ID of 3Dfloor in target sector. Note that the first FOF's ID is 0. - * \return Pointer to found 3Dfloor, or NULL. - * \sa P_GetFFloorBySec, P_GetFFloorID - */ -ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id) -{ - ffloor_t *rover; - UINT16 i = 0; - - if (!sec->ffloors) - return NULL; - for (rover = sec->ffloors; rover; rover = rover->next) - if (i++ == id) - return rover; - return NULL; -} - -/** Adds a newly formed 3Dfloor structure to a sector's ffloors list. - * - * \param sec Target sector. - * \param fflr Newly formed 3Dfloor structure. - * \sa P_AddFakeFloor - */ -static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *fflr) -{ - ffloor_t *rover; - - if (!sec->ffloors) - { - sec->ffloors = fflr; - fflr->next = 0; - fflr->prev = 0; - return; - } - - for (rover = sec->ffloors; rover->next; rover = rover->next); - - rover->next = fflr; - fflr->prev = rover; - fflr->next = 0; -} - -/** Adds a 3Dfloor. - * - * \param sec Target sector. - * \param sec2 Control sector. - * \param master Control linedef. - * \param alpha Alpha value (0-255). - * \param flags Options affecting this 3Dfloor. - * \param secthinkers List of relevant thinkers sorted by sector. May be NULL. - * \return Pointer to the new 3Dfloor. - * \sa P_AddFFloor, P_AddFakeFloorsByLine, P_SpawnSpecials - */ -static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, INT32 alpha, ffloortype_e flags, thinkerlist_t *secthinkers) -{ - ffloor_t *fflr; - thinker_t *th; - friction_t *f; - pusher_t *p; - size_t sec2num; - size_t i; - - if (sec == sec2) - return NULL; //Don't need a fake floor on a control sector. - if ((fflr = (P_GetFFloorBySec(sec, sec2)))) - return fflr; // If this ffloor already exists, return it - - if (sec2->ceilingheight < sec2->floorheight) - { - fixed_t tempceiling = sec2->ceilingheight; - //flip the sector around and print an error instead of crashing 12.1.08 -Inuyasha - CONS_Alert(CONS_ERROR, M_GetText("A FOF tagged %d has a top height below its bottom.\n"), master->args[0]); - sec2->ceilingheight = sec2->floorheight; - sec2->floorheight = tempceiling; - } - - if (sec2->numattached == 0) - { - sec2->attached = Z_Malloc(sizeof (*sec2->attached) * sec2->maxattached, PU_STATIC, NULL); - sec2->attachedsolid = Z_Malloc(sizeof (*sec2->attachedsolid) * sec2->maxattached, PU_STATIC, NULL); - sec2->attached[0] = sec - sectors; - sec2->numattached = 1; - sec2->attachedsolid[0] = (flags & FF_SOLID); - } - else - { - for (i = 0; i < sec2->numattached; i++) - if (sec2->attached[i] == (size_t)(sec - sectors)) - return NULL; - - if (sec2->numattached >= sec2->maxattached) - { - sec2->maxattached *= 2; - sec2->attached = Z_Realloc(sec2->attached, sizeof (*sec2->attached) * sec2->maxattached, PU_STATIC, NULL); - sec2->attachedsolid = Z_Realloc(sec2->attachedsolid, sizeof (*sec2->attachedsolid) * sec2->maxattached, PU_STATIC, NULL); - } - sec2->attached[sec2->numattached] = sec - sectors; - sec2->attachedsolid[sec2->numattached] = (flags & FF_SOLID); - sec2->numattached++; - } - - // Add the floor - fflr = Z_Calloc(sizeof (*fflr), PU_LEVEL, NULL); - fflr->secnum = sec2 - sectors; - fflr->target = sec; - fflr->bottomheight = &sec2->floorheight; - fflr->bottompic = &sec2->floorpic; - fflr->bottomxoffs = &sec2->floor_xoffs; - fflr->bottomyoffs = &sec2->floor_yoffs; - fflr->bottomangle = &sec2->floorpic_angle; - - // Add the ceiling - fflr->topheight = &sec2->ceilingheight; - fflr->toppic = &sec2->ceilingpic; - fflr->toplightlevel = &sec2->lightlevel; - fflr->topxoffs = &sec2->ceiling_xoffs; - fflr->topyoffs = &sec2->ceiling_yoffs; - fflr->topangle = &sec2->ceilingpic_angle; - - // Add slopes - fflr->t_slope = &sec2->c_slope; - fflr->b_slope = &sec2->f_slope; - // mark the target sector as having slopes, if the FOF has any of its own - // (this fixes FOF slopes glitching initially at level load in software mode) - if (sec2->hasslope) - sec->hasslope = true; - - fflr->spawnflags = fflr->flags = flags; - fflr->master = master; - fflr->norender = INFTICS; - fflr->fadingdata = NULL; - - // Scan the thinkers to check for special conditions applying to this FOF. - // If we have thinkers sorted by sector, just check the relevant ones; - // otherwise, check them all. Apologies for the ugly loop... - - sec2num = sec2 - sectors; - - // Just initialise both of these to placate the compiler. - i = 0; - th = thlist[THINK_MAIN].next; - - for(;;) - { - if(secthinkers) - { - if(i < secthinkers[sec2num].count) - th = secthinkers[sec2num].thinkers[i]; - else break; - } - else if (th == &thlist[THINK_MAIN]) - break; - - // Should this FOF have friction? - if(th->function.acp1 == (actionf_p1)T_Friction) - { - f = (friction_t *)th; - - if (f->affectee == (INT32)sec2num) - Add_Friction(f->friction, f->movefactor, (INT32)(sec-sectors), f->affectee); - } - // Should this FOF have wind/current/pusher? - else if(th->function.acp1 == (actionf_p1)T_Pusher) - { - p = (pusher_t *)th; - - if (p->affectee == (INT32)sec2num) - Add_Pusher(p->type, p->x_mag<y_mag<source, (INT32)(sec-sectors), p->affectee, p->exclusive, p->slider); - } - - if(secthinkers) i++; - else th = th->next; - } - - fflr->alpha = max(0, min(0xff, alpha)); - if (fflr->alpha < 0xff) - { - fflr->flags |= FF_TRANSLUCENT; - fflr->spawnflags = fflr->flags; - } - fflr->spawnalpha = fflr->alpha; // save for netgames - - if (flags & FF_QUICKSAND) - CheckForQuicksand = true; - - if (flags & FF_BUSTUP) - CheckForBustableBlocks = true; - - if ((flags & FF_MARIO)) - { - if (!(flags & FF_GOOWATER)) // Don't change the textures of a brick block, just a question block - P_AddBlockThinker(sec2, master); - CheckForMarioBlocks = true; - } - - if ((flags & FF_CRUMBLE)) - sec2->crumblestate = CRUMBLE_WAIT; - - if ((flags & FF_FLOATBOB)) - { - P_AddFloatThinker(sec2, Tag_FGet(&master->tags), master); - CheckForFloatBob = true; - } - - P_AddFFloorToList(sec, fflr); - - return fflr; -} - -// -// SPECIAL SPAWNING -// - -/** Adds a float thinker. - * Float thinkers cause solid 3Dfloors to float on water. - * - * \param sec Control sector. - * \param actionsector Target sector. - * \sa P_SpawnSpecials, T_FloatSector - * \author SSNTails - */ -static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline) -{ - floatthink_t *floater; - - // create and initialize new thinker - floater = Z_Calloc(sizeof (*floater), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &floater->thinker); - - floater->thinker.function.acp1 = (actionf_p1)T_FloatSector; - - floater->sector = sec; - floater->tag = (INT16)tag; - floater->sourceline = sourceline; -} - -/** - * Adds a plane displacement thinker. - * Whenever the "control" sector moves, - * the "affectee" sector's floor or ceiling plane moves too! - * - * \param speed Rate of movement relative to control sector - * \param control Control sector. - * \param affectee Target sector. - * \param reverse Reverse direction? - * \sa P_SpawnSpecials, T_PlaneDisplace - * \author Monster Iestyn - */ -static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee, UINT8 reverse) -{ - planedisplace_t *displace; - - // create and initialize new displacement thinker - displace = Z_Calloc(sizeof (*displace), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &displace->thinker); - - displace->thinker.function.acp1 = (actionf_p1)T_PlaneDisplace; - displace->affectee = affectee; - displace->control = control; - displace->last_height = sectors[control].floorheight; - displace->speed = speed; - displace->type = type; - displace->reverse = reverse; -} - -/** Adds a Mario block thinker, which changes the block's texture between blank - * and ? depending on whether it has contents. - * Needed in case objects respawn inside. - * - * \param sec Control sector. - * \param actionsector Target sector. - * \param sourceline Control linedef. - * \sa P_SpawnSpecials, T_MarioBlockChecker - * \author SSNTails - */ -static void P_AddBlockThinker(sector_t *sec, line_t *sourceline) -{ - mariocheck_t *block; - - // create and initialize new elevator thinker - block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &block->thinker); - - block->thinker.function.acp1 = (actionf_p1)T_MarioBlockChecker; - block->sourceline = sourceline; - - block->sector = sec; -} - -/** Adds a raise thinker. - * A raise thinker checks to see if the - * player is standing on its 3D Floor, - * and if so, raises the platform towards - * it's destination. Otherwise, it lowers - * to the lowest nearby height if not - * there already. - * - * \param sec Control sector. - * \sa P_SpawnSpecials, T_RaiseSector - * \author SSNTails - */ -static void P_AddRaiseThinker(sector_t *sec, INT16 tag, fixed_t speed, fixed_t ceilingtop, fixed_t ceilingbottom, boolean lower, boolean spindash) -{ - raise_t *raise; - - raise = Z_Calloc(sizeof (*raise), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &raise->thinker); - - raise->thinker.function.acp1 = (actionf_p1)T_RaiseSector; - - raise->tag = tag; - raise->sector = sec; - - raise->ceilingtop = ceilingtop; - raise->ceilingbottom = ceilingbottom; - - raise->basespeed = speed >> 2; - - if (lower) - raise->flags |= RF_REVERSE; - if (spindash) - raise->flags |= RF_SPINDASH; -} - -static void P_AddAirbob(sector_t *sec, INT16 tag, fixed_t dist, boolean raise, boolean spindash, boolean dynamic) -{ - raise_t *airbob; - - airbob = Z_Calloc(sizeof (*airbob), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &airbob->thinker); - - airbob->thinker.function.acp1 = (actionf_p1)T_RaiseSector; - - airbob->tag = tag; - airbob->sector = sec; - - airbob->ceilingtop = sec->ceilingheight; - airbob->ceilingbottom = sec->ceilingheight - dist; - - airbob->basespeed = FRACUNIT; - - if (!raise) - airbob->flags |= RF_REVERSE; - if (spindash) - airbob->flags |= RF_SPINDASH; - if (dynamic) - airbob->flags |= RF_DYNAMIC; -} - -/** Adds a thwomp thinker. - * Even thwomps need to think! - * - * \param sec Control sector. - * \sa P_SpawnSpecials, T_ThwompSector - * \author SSNTails - */ -static inline void P_AddThwompThinker(sector_t *sec, line_t *sourceline, fixed_t crushspeed, fixed_t retractspeed, UINT16 sound) -{ - thwomp_t *thwomp; - - // You *probably* already have a thwomp in this sector. If you've combined it with something - // else that uses the floordata/ceilingdata, you must be weird. - if (sec->floordata || sec->ceilingdata) - return; - - // create and initialize new elevator thinker - thwomp = Z_Calloc(sizeof (*thwomp), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &thwomp->thinker); - - thwomp->thinker.function.acp1 = (actionf_p1)T_ThwompSector; - - // set up the fields according to the type of elevator action - thwomp->sourceline = sourceline; - thwomp->sector = sec; - thwomp->crushspeed = crushspeed; - thwomp->retractspeed = retractspeed; - thwomp->direction = 0; - thwomp->floorstartheight = sec->floorheight; - thwomp->ceilingstartheight = sec->ceilingheight; - thwomp->delay = 1; - thwomp->tag = Tag_FGet(&sourceline->tags); - thwomp->sound = sound; - - sec->floordata = thwomp; - sec->ceilingdata = thwomp; - // Start with 'resting' texture - sides[sourceline->sidenum[0]].midtexture = sides[sourceline->sidenum[0]].bottomtexture; -} - -/** Adds a thinker which checks if any MF_ENEMY objects with health are in the defined area. - * If not, a linedef executor is run once. - * - * \param sourceline Control linedef. - * \sa P_SpawnSpecials, T_NoEnemiesSector - * \author SSNTails - */ -static inline void P_AddNoEnemiesThinker(line_t *sourceline) -{ - noenemies_t *nobaddies; - - // create and initialize new thinker - nobaddies = Z_Calloc(sizeof (*nobaddies), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &nobaddies->thinker); - - nobaddies->thinker.function.acp1 = (actionf_p1)T_NoEnemiesSector; - - nobaddies->sourceline = sourceline; -} - -/** Adds a thinker for Each-Time linedef executors. A linedef executor is run - * only when a player enters the area and doesn't run again until they re-enter. - * - * \param sourceline Control linedef. - * \sa P_SpawnSpecials, T_EachTimeThinker - * \author SSNTails - */ -static void P_AddEachTimeThinker(line_t *sourceline) -{ - eachtime_t *eachtime; - - // create and initialize new thinker - eachtime = Z_Calloc(sizeof (*eachtime), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &eachtime->thinker); - - eachtime->thinker.function.acp1 = (actionf_p1)T_EachTimeThinker; - - eachtime->sourceline = sourceline; - eachtime->triggerOnExit = !!(sourceline->flags & ML_BOUNCY); -} - -/** Adds a camera scanner. - * - * \param sourcesec Control sector. - * \param actionsector Target sector. - * \param angle Angle of the source line. - * \sa P_SpawnSpecials, T_CameraScanner - * \author SSNTails - */ -static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsector, angle_t angle) -{ - elevator_t *elevator; // Why not? LOL - - CONS_Alert(CONS_WARNING, M_GetText("Detected a camera scanner effect (linedef type 5). This effect is deprecated and will be removed in the future!\n")); - - // create and initialize new elevator thinker - elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); - P_AddThinker(THINK_MAIN, &elevator->thinker); - - elevator->thinker.function.acp1 = (actionf_p1)T_CameraScanner; - elevator->type = elevateBounce; - - // set up the fields according to the type of elevator action - elevator->sector = sourcesec; - elevator->actionsector = actionsector; - elevator->distance = FixedInt(AngleFixed(angle)); -} - -/** Flashes a laser block. - * - * \param flash Thinker structure for this laser. - * \sa P_AddLaserThinker - * \author SSNTails - */ -void T_LaserFlash(laserthink_t *flash) -{ - msecnode_t *node; - mobj_t *thing; - INT32 s; - ffloor_t *fflr; - sector_t *sector; - sector_t *sourcesec = flash->sourceline->frontsector; - fixed_t top, bottom; - - TAG_ITER_SECTORS(flash->tag, s) - { - sector = §ors[s]; - for (fflr = sector->ffloors; fflr; fflr = fflr->next) - { - if (fflr->master != flash->sourceline) - continue; - - if (!(fflr->flags & FF_EXISTS)) - break; - - if (leveltime & 2) - //fflr->flags |= FF_RENDERALL; - fflr->alpha = 0xB0; - else - //fflr->flags &= ~FF_RENDERALL; - fflr->alpha = 0x90; - - top = P_GetFFloorTopZAt (fflr, sector->soundorg.x, sector->soundorg.y); - bottom = P_GetFFloorBottomZAt(fflr, sector->soundorg.x, sector->soundorg.y); - sector->soundorg.z = (top + bottom)/2; - S_StartSound(§or->soundorg, sfx_laser); - - // Seek out objects to DESTROY! MUAHAHHAHAHAA!!!*cough* - for (node = sector->touching_thinglist; node && node->m_thing; node = node->m_thinglist_next) - { - thing = node->m_thing; - - if (flash->nobosses && thing->flags & MF_BOSS) - continue; // Don't hurt bosses - - // Don't endlessly kill egg guard shields (or anything else for that matter) - if (thing->health <= 0) - continue; - - top = P_GetSpecialTopZ(thing, sourcesec, sector); - bottom = P_GetSpecialBottomZ(thing, sourcesec, sector); - - if (thing->z >= top - || thing->z + thing->height <= bottom) - continue; - - if (thing->flags & MF_SHOOTABLE) - P_DamageMobj(thing, NULL, NULL, 1, 0); - else if (thing->type == MT_EGGSHIELD) - P_KillMobj(thing, NULL, NULL, 0); - } - - break; - } - } -} - -static inline void P_AddLaserThinker(INT16 tag, line_t *line, boolean nobosses) -{ - laserthink_t *flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); - - P_AddThinker(THINK_MAIN, &flash->thinker); - - flash->thinker.function.acp1 = (actionf_p1)T_LaserFlash; - flash->tag = tag; - flash->sourceline = line; - flash->nobosses = nobosses; -} - -// -// P_RunLevelLoadExecutors -// -// After loading/spawning all other specials -// and items, execute these. -// -static void P_RunLevelLoadExecutors(void) -{ - size_t i; - - for (i = 0; i < numlines; i++) - { - if (lines[i].special == 399) - P_RunTriggerLinedef(&lines[i], NULL, NULL); - } -} - -/** Before things are loaded, initialises certain stuff in case they're needed - * by P_SpawnSlopes or P_LoadThings. This was split off from - * P_SpawnSpecials, in case you couldn't tell. - * - * \sa P_SpawnSpecials - * \author Monster Iestyn - */ -void P_InitSpecials(void) -{ - // Set the default gravity. Custom gravity overrides this setting. - gravity = mapheaderinfo[gamemap-1]->gravity; - - // Defaults in case levels don't have them set. - sstimer = mapheaderinfo[gamemap-1]->sstimer*TICRATE + 6; - ssspheres = mapheaderinfo[gamemap-1]->ssspheres; - - CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false; - - // Set curWeather - switch (mapheaderinfo[gamemap-1]->weather) - { - case PRECIP_SNOW: // snow - case PRECIP_RAIN: // rain - case PRECIP_STORM: // storm - case PRECIP_STORM_NORAIN: // storm w/o rain - case PRECIP_STORM_NOSTRIKES: // storm w/o lightning - curWeather = mapheaderinfo[gamemap-1]->weather; - break; - default: // blank/none - curWeather = PRECIP_NONE; - break; - } - - // Set globalweather - globalweather = mapheaderinfo[gamemap-1]->weather; -} - -static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs) -{ - if (!(master->flags & ML_NETONLY)) // Modify floor flat alignment unless ML_NETONLY flag is set - { - sector->floorpic_angle = flatangle; - sector->floor_xoffs += xoffs; - sector->floor_yoffs += yoffs; - } - - if (!(master->flags & ML_NONET)) // Modify ceiling flat alignment unless ML_NONET flag is set - { - sector->ceilingpic_angle = flatangle; - sector->ceiling_xoffs += xoffs; - sector->ceiling_yoffs += yoffs; - } - -} - -static void P_MakeFOFBouncy(line_t *paramline, line_t *masterline) -{ - INT32 s; - TAG_ITER_DECLARECOUNTER(0); - - if (masterline->special < 100 || masterline->special >= 300) - return; - - TAG_ITER_SECTORS(0, masterline->args[0], s) - { - ffloor_t *rover; - - for (rover = sectors[s].ffloors; rover; rover = rover->next) - { - if (rover->master != masterline) - continue; - - rover->flags |= FF_BOUNCY; - rover->spawnflags |= FF_BOUNCY; - rover->bouncestrength = (paramline->args[1]<< FRACBITS)/100; - if (paramline->args[2]) - rover->specialflags |= FS_DAMPEN; - else - rover->specialflags &= ~FS_DAMPEN; - CheckForBouncySector = true; - break; - } - } - -} - -/** After the map has loaded, scans for specials that spawn 3Dfloors and - * thinkers. - * - * \todo Split up into multiple functions. - * \todo Get rid of all the magic numbers. - * \todo Potentially use 'fromnetsave' to stop any new thinkers from being created - * as they'll just be erased by UnArchiveThinkers. - * \sa P_SpawnPrecipitation, P_SpawnFriction, P_SpawnPushers, P_SpawnScrollers - */ -void P_SpawnSpecials(boolean fromnetsave) -{ - sector_t *sector; - size_t i; - INT32 j; - thinkerlist_t *secthinkers; - thinker_t *th; - TAG_ITER_DECLARECOUNTER(0); - // This used to be used, and *should* be used in the future, - // but currently isn't. - (void)fromnetsave; - - // yep, we do this here - "bossdisabled" is considered an apparatus of specials. - bossdisabled = 0; - stoppedclock = false; - - // Init special SECTORs. - sector = sectors; - for (i = 0; i < numsectors; i++, sector++) - { - if (!sector->special) - continue; - - // Process Section 1 - switch(GETSECSPECIAL(sector->special, 1)) - { - case 5: // Spikes - //Terrible hack to replace an even worse hack: - //Spike damage automatically sets SF_TRIGGERSPECIAL_TOUCH. - //Yes, this also affects other specials on the same sector. Sorry. - sector->flags |= SF_TRIGGERSPECIAL_TOUCH; - break; - } - - // Process Section 2 - switch(GETSECSPECIAL(sector->special, 2)) - { - case 10: // Time for special stage - sstimer = (sector->floorheight>>FRACBITS) * TICRATE + 6; // Time to finish - ssspheres = sector->ceilingheight>>FRACBITS; // Ring count for special stage - break; - - case 11: // Custom global gravity! - gravity = sector->floorheight/1000; - break; - } - - // Process Section 3 -/* switch(GETSECSPECIAL(player->specialsector, 3)) - { - - }*/ - - // Process Section 4 - switch(GETSECSPECIAL(sector->special, 4)) - { - case 10: // Circuit finish line - if ((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE) - circuitmap = true; - break; - } - } - - P_SpawnScrollers(); // Add generalized scrollers - P_SpawnFriction(); // Friction model using linedefs - P_SpawnPushers(); // Pusher model using linedefs - - // Look for thinkers that affect FOFs, and sort them by sector - - secthinkers = Z_Calloc(numsectors * sizeof(thinkerlist_t), PU_STATIC, NULL); - - // Firstly, find out how many there are in each sector - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)T_Friction) - secthinkers[((friction_t *)th)->affectee].count++; - else if (th->function.acp1 == (actionf_p1)T_Pusher) - secthinkers[((pusher_t *)th)->affectee].count++; - } - - // Allocate each list, and then zero the count so we can use it to track - // the end of the list as we add the thinkers - for (i = 0; i < numsectors; i++) - if(secthinkers[i].count > 0) - { - secthinkers[i].thinkers = Z_Malloc(secthinkers[i].count * sizeof(thinker_t *), PU_STATIC, NULL); - secthinkers[i].count = 0; - } - - // Finally, populate the lists. - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) - { - size_t secnum = (size_t)-1; - - if (th->function.acp1 == (actionf_p1)T_Friction) - secnum = ((friction_t *)th)->affectee; - else if (th->function.acp1 == (actionf_p1)T_Pusher) - secnum = ((pusher_t *)th)->affectee; - - if (secnum != (size_t)-1) - secthinkers[secnum].thinkers[secthinkers[secnum].count++] = th; - } - - - // Init line EFFECTs - for (i = 0; i < numlines; i++) - { - mtag_t tag = Tag_FGet(&lines[i].tags); - - if (lines[i].special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment in netgames... - { - // set line specials to 0 here too, same reason as above - if (netgame || multiplayer) - { - if (lines[i].flags & ML_NONET) - { - lines[i].special = 0; - continue; - } - } - else if (lines[i].flags & ML_NETONLY) - { - lines[i].special = 0; - continue; - } - } - - switch (lines[i].special) - { - INT32 s; - INT32 l; - size_t sec; - ffloortype_e ffloorflags; - - case 1: // Definable gravity per sector - sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(tag, s) - { - sectors[s].gravity = §ors[sec].floorheight; // This allows it to change in realtime! - - if (lines[i].flags & ML_NOCLIMB) - sectors[s].verticalflip = true; - else - sectors[s].verticalflip = false; - - CheckForReverseGravity = sectors[s].verticalflip; - } - break; - - case 2: // Custom exit - break; - - case 3: // Zoom Tube Parameters - break; - - case 4: // Speed pad (combines with sector special Section3:5 or Section3:6) - break; - - case 5: // Change camera info - sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(tag, s) - P_AddCameraScanner(§ors[sec], §ors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)); - break; - - case 7: // Flat alignment - redone by toast - if ((lines[i].flags & (ML_NETONLY|ML_NONET)) != (ML_NETONLY|ML_NONET)) // If you can do something... - { - angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)); - fixed_t xoffs; - fixed_t yoffs; - - if (lines[i].flags & ML_EFFECT6) // Set offset through x and y texture offsets if ML_EFFECT6 flag is set - { - xoffs = sides[lines[i].sidenum[0]].textureoffset; - yoffs = sides[lines[i].sidenum[0]].rowoffset; - } - else // Otherwise, set calculated offsets such that line's v1 is the apparent origin - { - xoffs = -lines[i].v1->x; - yoffs = lines[i].v1->y; - } - - //If no tag is given, apply to front sector - if (tag == 0) - P_ApplyFlatAlignment(lines + i, lines[i].frontsector, flatangle, xoffs, yoffs); - else - { - TAG_ITER_SECTORS(tag, s) - P_ApplyFlatAlignment(lines + i, sectors + s, flatangle, xoffs, yoffs); - } - } - else // Otherwise, print a helpful warning. Can I do no less? - CONS_Alert(CONS_WARNING, - M_GetText("Flat alignment linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), - tag); - break; - - case 8: // Sector Parameters - TAG_ITER_SECTORS(tag, s) - { - if (lines[i].flags & ML_NOCLIMB) - { - sectors[s].flags &= ~SF_FLIPSPECIAL_FLOOR; - sectors[s].flags |= SF_FLIPSPECIAL_CEILING; - } - else if (lines[i].flags & ML_EFFECT4) - sectors[s].flags |= SF_FLIPSPECIAL_BOTH; - - if (lines[i].flags & ML_EFFECT3) - sectors[s].flags |= SF_TRIGGERSPECIAL_TOUCH; - if (lines[i].flags & ML_EFFECT2) - sectors[s].flags |= SF_TRIGGERSPECIAL_HEADBUMP; - - if (lines[i].flags & ML_EFFECT1) - sectors[s].flags |= SF_INVERTPRECIP; - - if (lines[i].frontsector && GETSECSPECIAL(lines[i].frontsector->special, 4) == 12) - sectors[s].camsec = sides[*lines[i].sidenum].sector-sectors; - } - break; - - case 9: // Chain Parameters - break; - - case 10: // Vertical culling plane for sprites and FOFs - TAG_ITER_SECTORS(tag, s) - sectors[s].cullheight = &lines[i]; // This allows it to change in realtime! - break; - - case 50: // Insta-Lower Sector - EV_DoFloor(&lines[i], instantLower); - break; - - case 51: // Instant raise for ceilings - EV_DoCeiling(&lines[i], instantRaise); - break; - - case 52: // Continuously Falling sector - EV_DoContinuousFall(lines[i].frontsector, lines[i].backsector, P_AproxDistance(lines[i].dx, lines[i].dy), (lines[i].flags & ML_NOCLIMB)); - break; - - case 53: // New super cool and awesome moving floor and ceiling type - case 54: // New super cool and awesome moving floor type - if (lines[i].backsector) - EV_DoFloor(&lines[i], bounceFloor); - if (lines[i].special == 54) - break; - /* FALLTHRU */ - - case 55: // New super cool and awesome moving ceiling type - if (lines[i].backsector) - EV_DoCeiling(&lines[i], bounceCeiling); - break; - - case 56: // New super cool and awesome moving floor and ceiling crush type - case 57: // New super cool and awesome moving floor crush type - if (lines[i].backsector) - EV_DoFloor(&lines[i], bounceFloorCrush); - - if (lines[i].special == 57) - break; //only move the floor - /* FALLTHRU */ - - case 58: // New super cool and awesome moving ceiling crush type - if (lines[i].backsector) - EV_DoCeiling(&lines[i], bounceCeilingCrush); - break; - - case 59: // Activate floating platform - EV_DoElevator(&lines[i], elevateContinuous, false); - break; - - case 60: // Floating platform with adjustable speed - EV_DoElevator(&lines[i], elevateContinuous, true); - break; - - case 61: // Crusher! - EV_DoCrush(&lines[i], crushAndRaise); - break; - - case 62: // Crusher (up and then down)! - EV_DoCrush(&lines[i], fastCrushAndRaise); - break; - - case 63: // support for drawn heights coming from different sector - sec = sides[*lines[i].sidenum].sector-sectors; - TAG_ITER_SECTORS(tag, s) - sectors[s].heightsec = (INT32)sec; - break; - - case 64: // Appearing/Disappearing FOF option - if (lines[i].flags & ML_BLOCKMONSTERS) { // Find FOFs by control sector tag - TAG_ITER_SECTORS(tag, s) - for (j = 0; (unsigned)j < sectors[s].linecount; j++) - if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) - Add_MasterDisappearer(abs(lines[i].dx>>FRACBITS), abs(lines[i].dy>>FRACBITS), abs(sides[lines[i].sidenum[0]].sector->floorheight>>FRACBITS), (INT32)(sectors[s].lines[j]-lines), (INT32)i); - } else // Find FOFs by effect sector tag - { - TAG_ITER_LINES(tag, s) - { - if ((size_t)s == i) - continue; - if (Tag_Find(&sides[lines[s].sidenum[0]].sector->tags, Tag_FGet(&sides[lines[i].sidenum[0]].sector->tags))) - Add_MasterDisappearer(abs(lines[i].dx>>FRACBITS), abs(lines[i].dy>>FRACBITS), abs(sides[lines[i].sidenum[0]].sector->floorheight>>FRACBITS), s, (INT32)i); - } - } - break; - - case 66: // Displace floor by front sector - TAG_ITER_SECTORS(tag, s) - P_AddPlaneDisplaceThinker(pd_floor, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); - break; - case 67: // Displace ceiling by front sector - TAG_ITER_SECTORS(tag, s) - P_AddPlaneDisplaceThinker(pd_ceiling, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); - break; - case 68: // Displace both floor AND ceiling by front sector - TAG_ITER_SECTORS(tag, s) - P_AddPlaneDisplaceThinker(pd_both, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); - break; - - case 70: // Add raise thinker to FOF - if (udmf) - { - fixed_t destheight = lines[i].args[2] << FRACBITS; - fixed_t startheight, topheight, bottomheight; - - TAG_ITER_LINES(0, lines[i].args[0], l) - { - if (lines[l].special < 100 || lines[l].special >= 300) - continue; - - startheight = lines[l].frontsector->ceilingheight; - topheight = max(startheight, destheight); - bottomheight = min(startheight, destheight); - - P_AddRaiseThinker(lines[l].frontsector, lines[l].args[0], lines[i].args[1] << FRACBITS, topheight, bottomheight, (destheight < startheight), !!(lines[i].args[3])); - } - } - break; - - case 71: // Add air bob thinker to FOF - if (udmf) - { - TAG_ITER_LINES(0, lines[i].args[0], l) - { - if (lines[l].special < 100 || lines[l].special >= 300) - continue; - - P_AddAirbob(lines[l].frontsector, lines[l].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); - } - } - break; - - case 72: // Add thwomp thinker to FOF - if (udmf) - { - UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; - - TAG_ITER_LINES(0, lines[i].args[0], l) - { - if (lines[l].special < 100 || lines[l].special >= 300) - continue; - - P_AddThwompThinker(lines[l].frontsector, &lines[l], lines[i].args[1] << FRACBITS, lines[i].args[2] << FRACBITS, sound); - } - } - break; - - case 73: // Add laser thinker to FOF - if (udmf) - { - TAG_ITER_LINES(0, lines[i].args[0], l) - { - if (lines[l].special < 100 || lines[l].special >= 300) - continue; - - P_AddLaserThinker(lines[l].args[0], lines + l, !!(lines[i].args[1])); - } - } - break; - - case 100: // FOF (solid) - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; - - //Appearance settings - if (lines[i].args[2] & TMFA_NOPLANES) - ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[2] & TMFA_NOSIDES) - ffloorflags &= ~FF_RENDERSIDES; - if (lines[i].args[2] & TMFA_INSIDES) - { - if (ffloorflags & FF_RENDERPLANES) - ffloorflags |= FF_BOTHPLANES; - if (ffloorflags & FF_RENDERSIDES) - ffloorflags |= FF_ALLSIDES; - } - if (lines[i].args[2] & TMFA_ONLYINSIDES) - { - if (ffloorflags & FF_RENDERPLANES) - ffloorflags |= FF_INVERTPLANES; - if (ffloorflags & FF_RENDERSIDES) - ffloorflags |= FF_INVERTSIDES; - } - if (lines[i].args[2] & TMFA_NOSHADE) - ffloorflags |= FF_NOSHADE; - if (lines[i].args[2] & TMFA_SPLAT) - ffloorflags |= FF_SPLAT; - - //Tangibility settings - if (lines[i].args[3] & TMFT_INTANGIBLETOP) - ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[3] & TMFT_INTANGIBLEBOTTOM) - ffloorflags |= FF_PLATFORM; - if (lines[i].args[3] & TMFT_DONTBLOCKPLAYER) - ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) - ffloorflags &= ~FF_BLOCKOTHERS; - - //Cutting options - if (ffloorflags & FF_RENDERALL) - { - //If translucent or player can enter it, cut inner walls - if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) - ffloorflags |= FF_CUTEXTRA|FF_EXTRA; - else - ffloorflags |= FF_CUTLEVEL; - } - - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - break; - - case 120: // FOF (water) - ffloorflags = FF_EXISTS|FF_RENDERPLANES|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - if (!(lines[i].args[2] & TMFW_NOSIDES)) - ffloorflags |= FF_RENDERSIDES|FF_ALLSIDES; - if (lines[i].args[2] & TMFW_DOUBLESHADOW) - ffloorflags |= FF_DOUBLESHADOW; - if (lines[i].args[2] & TMFW_COLORMAPONLY) - ffloorflags |= FF_COLORMAPONLY; - if (!(lines[i].args[2] & TMFW_NORIPPLE)) - ffloorflags |= FF_RIPPLE; - if (lines[i].args[2] & TMFW_GOOWATER) - ffloorflags |= FF_GOOWATER; - if (lines[i].args[2] & TMFW_SPLAT) - ffloorflags |= FF_SPLAT; - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - break; - - case 150: // FOF (Air bobbing) - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL, secthinkers); - P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); - break; - - case 160: // FOF (Water bobbing) - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB, secthinkers); - break; - - case 170: // FOF (Crumbling) - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE; - - //Tangibility settings - if (lines[i].args[2] & TMFT_INTANGIBLETOP) - ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[2] & TMFT_INTANGIBLEBOTTOM) - ffloorflags |= FF_PLATFORM; - if (lines[i].args[2] & TMFT_DONTBLOCKPLAYER) - ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[2] & TMFT_DONTBLOCKOTHERS) - ffloorflags &= ~FF_BLOCKOTHERS; - - //Flags - if (lines[i].args[3] & TMFC_NOSHADE) - ffloorflags |= FF_NOSHADE; - if (lines[i].args[3] & TMFC_NORETURN) - ffloorflags |= FF_NORETURN; - if (lines[i].args[3] & TMFC_FLOATBOB) - ffloorflags |= FF_FLOATBOB; - if (lines[i].args[3] & TMFC_SPLAT) - ffloorflags |= FF_SPLAT; - - //If translucent or player can enter it, cut inner walls - if (lines[i].args[1] < 0xff || (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE)) - ffloorflags |= FF_CUTEXTRA|FF_EXTRA; - else - ffloorflags |= FF_CUTLEVEL; - - //If player can enter it, render insides - if (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE) - { - if (ffloorflags & FF_RENDERPLANES) - ffloorflags |= FF_BOTHPLANES; - if (ffloorflags & FF_RENDERSIDES) - ffloorflags |= FF_ALLSIDES; - } - - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - if (lines[i].args[3] & TMFC_AIRBOB) - P_AddAirbob(lines[i].frontsector, lines[i].args[0], 16*FRACUNIT, false, false, false); - break; - - case 190: // FOF (Rising) - { - fixed_t ceilingtop = P_FindHighestCeilingSurrounding(lines[i].frontsector); - fixed_t ceilingbottom = P_FindLowestCeilingSurrounding(lines[i].frontsector); - - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; - - //Appearance settings - if (lines[i].args[2] & TMFA_NOPLANES) - ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[2] & TMFA_NOSIDES) - ffloorflags &= ~FF_RENDERSIDES; - if (lines[i].args[2] & TMFA_INSIDES) - { - if (ffloorflags & FF_RENDERPLANES) - ffloorflags |= FF_BOTHPLANES; - if (ffloorflags & FF_RENDERSIDES) - ffloorflags |= FF_ALLSIDES; - } - if (lines[i].args[2] & TMFA_ONLYINSIDES) - { - if (ffloorflags & FF_RENDERPLANES) - ffloorflags |= FF_INVERTPLANES; - if (ffloorflags & FF_RENDERSIDES) - ffloorflags |= FF_INVERTSIDES; - } - if (lines[i].args[2] & TMFA_NOSHADE) - ffloorflags |= FF_NOSHADE; - if (lines[i].args[2] & TMFA_SPLAT) - ffloorflags |= FF_SPLAT; - - //Tangibility settings - if (lines[i].args[3] & TMFT_INTANGIBLETOP) - ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[3] & TMFT_INTANGIBLEBOTTOM) - ffloorflags |= FF_PLATFORM; - if (lines[i].args[3] & TMFT_DONTBLOCKPLAYER) - ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) - ffloorflags &= ~FF_BLOCKOTHERS; - - //Cutting options - if (ffloorflags & FF_RENDERALL) - { - //If translucent or player can enter it, cut inner walls - if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) - ffloorflags |= FF_CUTEXTRA|FF_EXTRA; - else - ffloorflags |= FF_CUTLEVEL; - } - - P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, lines[i].args[0], lines[i].args[4] << FRACBITS, ceilingtop, ceilingbottom, !!(lines[i].args[5] & TMFR_REVERSE), !!(lines[i].args[5] & TMFR_SPINDASH)); - break; - } - case 200: // Light block - ffloorflags = FF_EXISTS|FF_CUTSPRITES; - if (!lines[i].args[1]) - ffloorflags |= FF_DOUBLESHADOW; - P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); - break; - - case 202: // Fog - ffloorflags = FF_EXISTS|FF_RENDERALL|FF_FOG|FF_INVERTPLANES|FF_INVERTSIDES|FF_CUTEXTRA|FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES; - sec = sides[*lines[i].sidenum].sector - sectors; - // SoM: Because it's fog, check for an extra colormap and set the fog flag... - if (sectors[sec].extra_colormap) - sectors[sec].extra_colormap->flags = CMF_FOG; - P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); - break; - - case 220: //Intangible - ffloorflags = FF_EXISTS|FF_RENDERALL|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - - //Appearance settings - if (lines[i].args[2] & TMFA_NOPLANES) - ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[2] & TMFA_NOSIDES) - ffloorflags &= ~FF_RENDERSIDES; - if (!(lines[i].args[2] & TMFA_INSIDES)) - { - if (ffloorflags & FF_RENDERPLANES) - ffloorflags |= FF_BOTHPLANES; - if (ffloorflags & FF_RENDERSIDES) - ffloorflags |= FF_ALLSIDES; - } - if (lines[i].args[2] & TMFA_ONLYINSIDES) - { - if (ffloorflags & FF_RENDERPLANES) - ffloorflags |= FF_INVERTPLANES; - if (ffloorflags & FF_RENDERSIDES) - ffloorflags |= FF_INVERTSIDES; - } - if (lines[i].args[2] & TMFA_NOSHADE) - ffloorflags |= FF_NOSHADE; - if (lines[i].args[2] & TMFA_SPLAT) - ffloorflags |= FF_SPLAT; - - P_AddFakeFloorsByLine(i, (ffloorflags & FF_TRANSLUCENT) ? (lines[i].alpha * 0xff) >> FRACBITS : 0xff, ffloorflags, secthinkers); - break; - - case 223: // FOF (intangible, invisible) - for combining specials in a sector - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_NOSHADE, secthinkers); - break; - - case 250: // Mario Block - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO; - if (lines[i].args[1] & TMFM_BRICK) - ffloorflags |= FF_GOOWATER; - if (lines[i].args[1] & TMFM_INVISIBLE) - ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); - - P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); - break; - - case 251: // A THWOMP! - { - UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; - P_AddThwompThinker(lines[i].frontsector, &lines[i], lines[i].args[1] << FRACBITS, lines[i].args[2] << FRACBITS, sound); - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - break; - } - - case 254: // Bustable block - { - UINT8 busttype = BT_REGULAR; - ffloorspecialflags_e bustflags = 0; - - ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP; - - //Bustable type - switch (lines[i].args[2]) - { - case TMFB_TOUCH: - busttype = BT_TOUCH; - break; - case TMFB_SPIN: - busttype = BT_SPINBUST; - break; - case TMFB_REGULAR: - busttype = BT_REGULAR; - break; - case TMFB_STRONG: - busttype = BT_STRONG; - break; - } - - //Flags - if (lines[i].args[3] & TMFB_PUSHABLES) - bustflags |= FS_PUSHABLES; - if (lines[i].args[3] & TMFB_EXECUTOR) - bustflags |= FS_EXECUTOR; - if (lines[i].args[3] & TMFB_ONLYBOTTOM) - bustflags |= FS_ONLYBOTTOM; - if (lines[i].args[3] & TMFB_SPLAT) - ffloorflags |= FF_SPLAT; - - if (busttype != BT_TOUCH || bustflags & FS_ONLYBOTTOM) - ffloorflags |= FF_BLOCKPLAYER; - - TAG_ITER_SECTORS(0, lines[i].args[0], s) - { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers); - fflr->busttype = busttype; - fflr->specialflags = bustflags; - fflr->busttag = lines[i].args[4]; - } - break; - } - case 257: // Quicksand - ffloorflags = FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES; - if (!(lines[i].args[1])) - ffloorflags |= FF_RIPPLE; - - TAG_ITER_SECTORS(0, lines[i].args[0], s) - { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, ffloorflags, secthinkers); - fflr->sinkspeed = abs(lines[i].args[2]) << (FRACBITS - 1); - fflr->friction = abs(lines[i].args[3]) << (FRACBITS - 6); - } - break; - - case 258: // Laser block - ffloorflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT; - P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[2] & TMFL_NOBOSSES)); - if (lines[i].args[2] & TMFL_SPLAT) - ffloorflags |= FF_SPLAT; - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - break; - - case 259: // Custom FOF - TAG_ITER_SECTORS(0, lines[i].args[0], s) - { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], lines[i].args[2], secthinkers); - if (!udmf) // Ugly backwards compatibility stuff - { - if (lines[i].args[2] & FF_QUICKSAND) - { - fflr->sinkspeed = abs(lines[i].dx) >> 1; - fflr->friction = abs(lines[i].dy) >> 6; - } - if (lines[i].args[2] & FF_BUSTUP) - { - switch (lines[i].args[3] % TMFB_ONLYBOTTOM) - { - case TMFB_TOUCH: - fflr->busttype = BT_TOUCH; - break; - case TMFB_SPIN: - fflr->busttype = BT_SPINBUST; - break; - case TMFB_REGULAR: - fflr->busttype = BT_REGULAR; - break; - case TMFB_STRONG: - fflr->busttype = BT_STRONG; - break; - } - - if (lines[i].args[3] & TMFB_ONLYBOTTOM) - fflr->specialflags |= FS_ONLYBOTTOM; - if (lines[i].flags & ML_EFFECT4) - fflr->specialflags |= FS_PUSHABLES; - if (lines[i].flags & ML_EFFECT5) - { - fflr->specialflags |= FS_EXECUTOR; - fflr->busttag = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; - } - } - } - } - break; - - case 260: // GZDoom-like 3D Floor. - { - UINT8 dtype = lines[i].args[1] & 3; - UINT8 dflags1 = lines[i].args[1] - dtype; - UINT8 dflags2 = lines[i].args[2]; - UINT8 dopacity = lines[i].args[3]; - boolean isfog = false; - - if (dtype == 0) - dtype = 1; - - ffloorflags = FF_EXISTS; - - if (dflags2 & 1) ffloorflags |= FF_NOSHADE; // Disable light effects (Means no shadowcast) - if (dflags2 & 2) ffloorflags |= FF_DOUBLESHADOW; // Restrict light inside (Means doubleshadow) - if (dflags2 & 4) isfog = true; // Fog effect (Explicitly render like a fog block) - - if (dflags1 & 4) ffloorflags |= FF_BOTHPLANES|FF_ALLSIDES; // Render-inside - if (dflags1 & 16) ffloorflags |= FF_INVERTSIDES|FF_INVERTPLANES; // Invert visibility rules - - // Fog block - if (isfog) - ffloorflags |= FF_RENDERALL|FF_CUTEXTRA|FF_CUTSPRITES|FF_BOTHPLANES|FF_EXTRA|FF_FOG|FF_INVERTPLANES|FF_ALLSIDES|FF_INVERTSIDES; - else - { - ffloorflags |= FF_RENDERALL; - - // Solid - if (dtype == 1) - ffloorflags |= FF_SOLID|FF_CUTLEVEL; - // Water - else if (dtype == 2) - ffloorflags |= FF_SWIMMABLE|FF_CUTEXTRA|FF_CUTSPRITES|FF_EXTRA|FF_RIPPLE; - // Intangible - else if (dtype == 3) - ffloorflags |= FF_CUTEXTRA|FF_CUTSPRITES|FF_EXTRA; - } - - // Non-opaque - if (dopacity < 255) - { - // Invisible - if (dopacity == 0) - { - // True invisible - if (ffloorflags & FF_NOSHADE) - ffloorflags &= ~(FF_RENDERALL|FF_CUTEXTRA|FF_CUTSPRITES|FF_EXTRA|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTLEVEL); - // Shadow block - else - { - ffloorflags |= FF_CUTSPRITES; - ffloorflags &= ~(FF_RENDERALL|FF_CUTEXTRA|FF_EXTRA|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTLEVEL); - } - } - else - { - ffloorflags |= FF_TRANSLUCENT|FF_CUTEXTRA|FF_EXTRA; - ffloorflags &= ~FF_CUTLEVEL; - } - } - - P_AddFakeFloorsByLine(i, dopacity, ffloorflags, secthinkers); - } - break; - - case 300: // Linedef executor (combines with sector special 974/975) and commands - case 302: - case 303: - case 304: - - // Charability linedef executors - case 305: - case 307: - break; - - case 308: // Race-only linedef executor. Triggers once. - if (!(gametyperules & GTR_RACE)) - lines[i].special = 0; - break; - - // Linedef executor triggers for CTF teams. - case 309: - case 311: - if (!(gametyperules & GTR_TEAMFLAGS)) - lines[i].special = 0; - break; - - // Each time executors - case 306: - case 301: - case 310: - case 312: - case 332: - case 335: - P_AddEachTimeThinker(&lines[i]); - break; - - // No More Enemies Linedef Exec - case 313: - P_AddNoEnemiesThinker(&lines[i]); - break; - - // Pushable linedef executors (count # of pushables) - case 314: - case 315: - break; - - // Unlock trigger executors - case 317: - case 318: - break; - case 319: - case 320: - break; - - // Trigger on X calls - case 321: - case 322: - if (lines[i].flags & ML_NOCLIMB && sides[lines[i].sidenum[0]].rowoffset > 0) // optional "starting" count - lines[i].callcount = sides[lines[i].sidenum[0]].rowoffset>>FRACBITS; - else - lines[i].callcount = sides[lines[i].sidenum[0]].textureoffset>>FRACBITS; - if (lines[i].special == 322) // Each time - P_AddEachTimeThinker(&lines[i]); - break; - - // NiGHTS trigger executors - case 323: - case 324: - case 325: - case 326: - case 327: - case 328: - case 329: - case 330: - break; - - // Skin trigger executors - case 331: - case 333: - break; - - // Object dye executors - case 334: - case 336: - break; - - case 399: // Linedef execute on map load - // This is handled in P_RunLevelLoadExecutors. - break; - - case 400: - case 401: - case 402: - case 403: - case 404: - case 405: - case 406: - case 407: - case 408: - case 409: - case 410: - case 411: - case 412: - case 413: - case 414: - case 415: - case 416: - case 417: - case 418: - case 419: - case 420: - case 421: - case 422: - case 423: - case 424: - case 425: - case 426: - case 427: - case 428: - case 429: - case 430: - case 431: - break; - - case 449: // Enable bosses with parameter - { - INT32 bossid = sides[*lines[i].sidenum].textureoffset>>FRACBITS; - if (bossid & ~15) // if any bits other than first 16 are set - { - CONS_Alert(CONS_WARNING, - M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"), - tag); - break; - } - if (!(lines[i].flags & ML_NOCLIMB)) - { - bossdisabled |= (1<>FRACBITS); - break; - - case 603: // Adjustable flickering light - sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(tag, s) - P_SpawnAdjustableFireFlicker(§ors[sec], §ors[s], - P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS); - break; - - case 604: // Adjustable Blinking Light (unsynchronized) - sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(tag, s) - P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], - abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, false); - break; - - case 605: // Adjustable Blinking Light (synchronized) - sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(tag, s) - P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], - abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, true); - break; - - case 606: // HACK! Copy colormaps. Just plain colormaps. - TAG_ITER_SECTORS(lines[i].args[0], s) - { - extracolormap_t *exc; - - if (sectors[s].colormap_protected) - continue; - - if (!udmf) - exc = sides[lines[i].sidenum[0]].colormap_data; - else - { - if (!lines[i].args[1]) - exc = lines[i].frontsector->extra_colormap; - else - { - INT32 sourcesec = Tag_Iterate_Sectors(lines[i].args[1], 0); - if (sourcesec == -1) - { - CONS_Debug(DBG_GAMELOGIC, "Line type 606: Can't find sector with source colormap (tag %d)!\n", lines[i].args[1]); - return; - } - exc = sectors[sourcesec].extra_colormap; - } - } - sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = exc; - } - break; - - default: - break; - } - } - - // And another round, this time with all FOFs already created - for (i = 0; i < numlines; i++) - { - switch (lines[i].special) - { - INT32 s; - INT32 l; - - case 74: // Make FOF bustable - { - UINT8 busttype = BT_REGULAR; - ffloorspecialflags_e bustflags = 0; - - if (!udmf) - break; - - switch (lines[i].args[1]) - { - case TMFB_TOUCH: - busttype = BT_TOUCH; - break; - case TMFB_SPIN: - busttype = BT_SPINBUST; - break; - case TMFB_REGULAR: - busttype = BT_REGULAR; - break; - case TMFB_STRONG: - busttype = BT_STRONG; - break; - } - - if (lines[i].args[2] & TMFB_PUSHABLES) - bustflags |= FS_PUSHABLES; - if (lines[i].args[2] & TMFB_EXECUTOR) - bustflags |= FS_EXECUTOR; - if (lines[i].args[2] & TMFB_ONLYBOTTOM) - bustflags |= FS_ONLYBOTTOM; - - TAG_ITER_LINES(0, lines[i].args[0], l) - { - TAG_ITER_DECLARECOUNTER(1); - if (lines[l].special < 100 || lines[l].special >= 300) - continue; - - TAG_ITER_SECTORS(1, lines[l].args[0], s) - { - ffloor_t *rover; - - for (rover = sectors[s].ffloors; rover; rover = rover->next) - { - if (rover->master != lines + l) - continue; - - rover->flags |= FF_BUSTUP; - rover->spawnflags |= FF_BUSTUP; - rover->busttype = busttype; - rover->specialflags &= ~FS_BUSTMASK; - rover->specialflags |= bustflags; - rover->busttag = lines[i].args[3]; - CheckForBustableBlocks = true; - break; - } - } - } - break; - } - - case 75: // Make FOF quicksand - { - if (!udmf) - break; - TAG_ITER_LINES(0, lines[i].args[0], l) - { - TAG_ITER_DECLARECOUNTER(1); - if (lines[l].special < 100 || lines[l].special >= 300) - continue; - - TAG_ITER_SECTORS(1, lines[l].args[0], s) - { - ffloor_t *rover; - - for (rover = sectors[s].ffloors; rover; rover = rover->next) - { - if (rover->master != lines + l) - continue; - - rover->flags |= FF_QUICKSAND; - rover->spawnflags |= FF_QUICKSAND; - rover->sinkspeed = abs(lines[i].args[1]) << (FRACBITS - 1); - rover->friction = abs(lines[i].args[2]) << (FRACBITS - 6); - CheckForQuicksand = true; - break; - } - } - } - break; - } - - case 76: // Make FOF bouncy - { - if (udmf) - { - TAG_ITER_LINES(0, lines[i].args[0], l) - P_MakeFOFBouncy(lines + i, lines + l); - } - else - { - TAG_ITER_SECTORS(0, lines[i].args[0], s) - for (j = 0; (unsigned)j < sectors[s].linecount; j++) - P_MakeFOFBouncy(lines + i, sectors[s].lines[j]); - } - break; - } - } - } - - - - - - // Allocate each list - for (i = 0; i < numsectors; i++) - if(secthinkers[i].thinkers) - Z_Free(secthinkers[i].thinkers); - - Z_Free(secthinkers); - - // haleyjd 02/20/06: spawn polyobjects - Polyobj_InitLevel(); - - for (i = 0; i < numlines; i++) - { - switch (lines[i].special) - { - case 30: // Polyobj_Flag - PolyFlag(&lines[i]); - break; - - case 31: // Polyobj_Displace - PolyDisplace(&lines[i]); - break; - - case 32: // Polyobj_RotDisplace - PolyRotDisplace(&lines[i]); - break; - } - } - - P_RunLevelLoadExecutors(); -} - -/** Adds 3Dfloors as appropriate based on a common control linedef. - * - * \param line Control linedef to use. - * \param alpha Alpha value (0-255). - * \param ffloorflags 3Dfloor flags to use. - * \param secthkiners Lists of thinkers sorted by sector. May be NULL. - * \sa P_SpawnSpecials, P_AddFakeFloor - * \author Graue - */ -static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorflags, thinkerlist_t *secthinkers) -{ - INT32 s; - mtag_t tag = lines[line].args[0]; - size_t sec = sides[*lines[line].sidenum].sector-sectors; - -<<<<<<< HEAD - TAG_ITER_SECTORS(0, tag, s) - P_AddFakeFloor(§ors[s], §ors[sec], lines+line, alpha, ffloorflags, secthinkers); -======= - line_t* li = lines + line; - TAG_ITER_SECTORS(tag, s) - P_AddFakeFloor(§ors[s], §ors[sec], li, ffloorflags, secthinkers); ->>>>>>> next -} - -/* - SoM: 3/8/2000: General scrolling functions. - T_Scroll, - Add_Scroller, - Add_WallScroller, - P_SpawnScrollers -*/ - -// helper function for T_Scroll -static void P_DoScrollMove(mobj_t *thing, fixed_t dx, fixed_t dy, INT32 exclusive) -{ - fixed_t fuckaj = 0; // Nov 05 14:12:08 <+MonsterIestyn> I've heard of explicitly defined variables but this is ridiculous - if (thing->player) - { - if (!(dx | dy)) - { - thing->player->cmomx = 0; - thing->player->cmomy = 0; - } - else - { - thing->player->cmomx += dx; - thing->player->cmomy += dy; - thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); - thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); - } - } - - if (thing->player && (thing->player->pflags & PF_SPINNING) && (thing->player->rmomx || thing->player->rmomy) && !(thing->player->pflags & PF_STARTDASH)) - fuckaj = FixedDiv(549*ORIG_FRICTION,500*FRACUNIT); - else if (thing->friction != ORIG_FRICTION) - fuckaj = thing->friction; - - if (fuckaj) { - // refactor thrust for new friction - dx = FixedDiv(dx, CARRYFACTOR); - dy = FixedDiv(dy, CARRYFACTOR); - - dx = FixedMul(dx, FRACUNIT-fuckaj); - dy = FixedMul(dy, FRACUNIT-fuckaj); - } - - thing->momx += dx; - thing->momy += dy; - - if (exclusive) - thing->eflags |= MFE_PUSHED; -} - -/** Processes an active scroller. - * This function, with the help of r_plane.c and r_bsp.c, supports generalized - * scrolling floors and walls, with optional mobj-carrying properties, e.g. - * conveyor belts, rivers, etc. A linedef with a special type affects all - * tagged sectors the same way, by creating scrolling and/or object-carrying - * properties. Multiple linedefs may be used on the same sector and are - * cumulative, although the special case of scrolling a floor and carrying - * things on it requires only one linedef. - * - * The linedef's direction determines the scrolling direction, and the - * linedef's length determines the scrolling speed. This was designed so an - * edge around a sector can be used to control the direction of the sector's - * scrolling, which is usually what is desired. - * - * \param s Thinker for the scroller to process. - * \todo Split up into multiple functions. - * \todo Use attached lists to make ::sc_carry_ceiling case faster and - * cleaner. - * \sa Add_Scroller, Add_WallScroller, P_SpawnScrollers - * \author Steven McGranahan - * \author Graue - */ -void T_Scroll(scroll_t *s) -{ - fixed_t dx = s->dx, dy = s->dy; - boolean is3dblock = false; - - if (s->control != -1) - { // compute scroll amounts based on a sector's height changes - fixed_t height = sectors[s->control].floorheight + - sectors[s->control].ceilingheight; - fixed_t delta = height - s->last_height; - s->last_height = height; - dx = FixedMul(dx, delta); - dy = FixedMul(dy, delta); - } - - if (s->accel) - { - s->vdx = dx += s->vdx; - s->vdy = dy += s->vdy; - } - -// if (!(dx | dy)) // no-op if both (x,y) offsets 0 -// return; - - switch (s->type) - { - side_t *side; - sector_t *sec; - fixed_t height; - msecnode_t *node; - mobj_t *thing; - line_t *line; - size_t i; - INT32 sect; - ffloor_t *rover; - - case sc_side: // scroll wall texture - side = sides + s->affectee; - side->textureoffset += dx; - side->rowoffset += dy; - break; - - case sc_floor: // scroll floor texture - sec = sectors + s->affectee; - sec->floor_xoffs += dx; - sec->floor_yoffs += dy; - break; - - case sc_ceiling: // scroll ceiling texture - sec = sectors + s->affectee; - sec->ceiling_xoffs += dx; - sec->ceiling_yoffs += dy; - break; - - case sc_carry: - sec = sectors + s->affectee; - height = sec->floorheight; - - // sec is the control sector, find the real sector(s) to use - for (i = 0; i < sec->linecount; i++) - { - line = sec->lines[i]; - - if (line->special < 100 || line->special >= 300) - is3dblock = false; - else - is3dblock = true; - - if (!is3dblock) - continue; - - TAG_ITER_SECTORS(Tag_FGet(&line->tags), sect) - { - sector_t *psec; - psec = sectors + sect; - - // Find the FOF corresponding to the control linedef - for (rover = psec->ffloors; rover; rover = rover->next) - { - if (rover->master == sec->lines[i]) - break; - } - - if (!rover) // This should be impossible, but don't complain if it is the case somehow - continue; - - if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there - continue; - - for (node = psec->touching_thinglist; node; node = node->m_thinglist_next) - { - thing = node->m_thing; - - if (thing->eflags & MFE_PUSHED) // Already pushed this tic by an exclusive pusher. - continue; - - height = P_GetSpecialBottomZ(thing, sec, psec); - - if (!(thing->flags & MF_NOCLIP)) // Thing must be clipped - if (!(thing->flags & MF_NOGRAVITY || thing->z+thing->height != height)) // Thing must a) be non-floating and have z+height == height - { - // Move objects only if on floor - // non-floating, and clipped. - P_DoScrollMove(thing, dx, dy, s->exclusive); - } - } // end of for loop through touching_thinglist - } // end of loop through sectors - } - - if (!is3dblock) - { - for (node = sec->touching_thinglist; node; node = node->m_thinglist_next) - { - thing = node->m_thing; - - if (thing->eflags & MFE_PUSHED) - continue; - - height = P_GetSpecialBottomZ(thing, sec, sec); - - if (!(thing->flags & MF_NOCLIP) && - (!(thing->flags & MF_NOGRAVITY || thing->z > height))) - { - // Move objects only if on floor or underwater, - // non-floating, and clipped. - P_DoScrollMove(thing, dx, dy, s->exclusive); - } - } - } - break; - - case sc_carry_ceiling: // carry on ceiling (FOF scrolling) - sec = sectors + s->affectee; - height = sec->ceilingheight; - - // sec is the control sector, find the real sector(s) to use - for (i = 0; i < sec->linecount; i++) - { - line = sec->lines[i]; - if (line->special < 100 || line->special >= 300) - is3dblock = false; - else - is3dblock = true; - - if (!is3dblock) - continue; - TAG_ITER_SECTORS(Tag_FGet(&line->tags), sect) - { - sector_t *psec; - psec = sectors + sect; - - // Find the FOF corresponding to the control linedef - for (rover = psec->ffloors; rover; rover = rover->next) - { - if (rover->master == sec->lines[i]) - break; - } - - if (!rover) // This should be impossible, but don't complain if it is the case somehow - continue; - - if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there - continue; - - for (node = psec->touching_thinglist; node; node = node->m_thinglist_next) - { - thing = node->m_thing; - - if (thing->eflags & MFE_PUSHED) - continue; - - height = P_GetSpecialTopZ(thing, sec, psec); - - if (!(thing->flags & MF_NOCLIP)) // Thing must be clipped - if (!(thing->flags & MF_NOGRAVITY || thing->z != height))// Thing must a) be non-floating and have z == height - { - // Move objects only if on floor or underwater, - // non-floating, and clipped. - P_DoScrollMove(thing, dx, dy, s->exclusive); - } - } // end of for loop through touching_thinglist - } // end of loop through sectors - } - - if (!is3dblock) - { - for (node = sec->touching_thinglist; node; node = node->m_thinglist_next) - { - thing = node->m_thing; - - if (thing->eflags & MFE_PUSHED) - continue; - - height = P_GetSpecialTopZ(thing, sec, sec); - - if (!(thing->flags & MF_NOCLIP) && - (!(thing->flags & MF_NOGRAVITY || thing->z+thing->height < height))) - { - // Move objects only if on floor or underwater, - // non-floating, and clipped. - P_DoScrollMove(thing, dx, dy, s->exclusive); - } - } - } - break; // end of sc_carry_ceiling - } // end of switch -} - -/** Adds a generalized scroller to the thinker list. - * - * \param type The enumerated type of scrolling. - * \param dx x speed of scrolling or its acceleration. - * \param dy y speed of scrolling or its acceleration. - * \param control Sector whose heights control this scroller's effect - * remotely, or -1 if there is no control sector. - * \param affectee Index of the affected object, sector or sidedef. - * \param accel Nonzero for an accelerative effect. - * \sa Add_WallScroller, P_SpawnScrollers, T_Scroll - */ -static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT32 affectee, INT32 accel, INT32 exclusive) -{ - scroll_t *s = Z_Calloc(sizeof *s, PU_LEVSPEC, NULL); - s->thinker.function.acp1 = (actionf_p1)T_Scroll; - s->type = type; - s->dx = dx; - s->dy = dy; - s->accel = accel; - s->exclusive = exclusive; - s->vdx = s->vdy = 0; - if ((s->control = control) != -1) - s->last_height = sectors[control].floorheight + sectors[control].ceilingheight; - s->affectee = affectee; - P_AddThinker(THINK_MAIN, &s->thinker); -} - -/** Initializes the scrollers. - * - * \todo Get rid of all the magic numbers. - * \sa P_SpawnSpecials, Add_Scroller, Add_WallScroller - */ -static void P_SpawnScrollers(void) -{ - size_t i; - line_t *l = lines; - mtag_t tag; - - for (i = 0; i < numlines; i++, l++) - { - fixed_t dx = l->dx >> SCROLL_SHIFT; // direction and speed of scrolling - fixed_t dy = l->dy >> SCROLL_SHIFT; - INT32 control = -1, accel = 0; // no control sector or acceleration - INT32 special = l->special; - - tag = Tag_FGet(&l->tags); - - // These types are same as the ones they get set to except that the - // first side's sector's heights cause scrolling when they change, and - // this linedef controls the direction and speed of the scrolling. The - // most complicated linedef since donuts, but powerful :) - - if (special == 515 || special == 512 || special == 522 || special == 532 || special == 504) // displacement scrollers - { - special -= 2; - control = (INT32)(sides[*l->sidenum].sector - sectors); - } - else if (special == 514 || special == 511 || special == 521 || special == 531 || special == 503) // accelerative scrollers - { - special--; - accel = 1; - control = (INT32)(sides[*l->sidenum].sector - sectors); - } - else if (special == 535 || special == 525) // displacement scrollers - { - special -= 2; - control = (INT32)(sides[*l->sidenum].sector - sectors); - } - else if (special == 534 || special == 524) // accelerative scrollers - { - accel = 1; - special--; - control = (INT32)(sides[*l->sidenum].sector - sectors); - } - - switch (special) - { - register INT32 s; - - case 513: // scroll effect ceiling - case 533: // scroll and carry objects on ceiling - TAG_ITER_SECTORS(tag, s) - Add_Scroller(sc_ceiling, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); - if (special != 533) - break; - /* FALLTHRU */ - - case 523: // carry objects on ceiling - dx = FixedMul(dx, CARRYFACTOR); - dy = FixedMul(dy, CARRYFACTOR); - TAG_ITER_SECTORS(tag, s) - Add_Scroller(sc_carry_ceiling, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); - break; - - case 510: // scroll effect floor - case 530: // scroll and carry objects on floor - TAG_ITER_SECTORS(tag, s) - Add_Scroller(sc_floor, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); - if (special != 530) - break; - /* FALLTHRU */ - - case 520: // carry objects on floor - dx = FixedMul(dx, CARRYFACTOR); - dy = FixedMul(dy, CARRYFACTOR); - TAG_ITER_SECTORS(tag, s) - Add_Scroller(sc_carry, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); - break; - - // scroll wall according to linedef - // (same direction and speed as scrolling floors) - case 502: - { - TAG_ITER_LINES(tag, s) - if (s != (INT32)i) - { - if (l->flags & ML_EFFECT2) // use texture offsets instead - { - dx = sides[l->sidenum[0]].textureoffset; - dy = sides[l->sidenum[0]].rowoffset; - } - if (l->flags & ML_EFFECT3) - { - if (lines[s].sidenum[1] != 0xffff) - Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[1], accel, 0); - } - else - Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[0], accel, 0); - } - break; - } - - case 505: - s = lines[i].sidenum[0]; - Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, s, accel, 0); - break; - - case 506: - s = lines[i].sidenum[1]; - - if (s != 0xffff) - Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, lines[i].sidenum[0], accel, 0); - else - CONS_Debug(DBG_GAMELOGIC, "Line special 506 (line #%s) missing back side!\n", sizeu1(i)); - break; - - case 507: - s = lines[i].sidenum[0]; - - if (lines[i].sidenum[1] != 0xffff) - Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, lines[i].sidenum[1], accel, 0); - else - CONS_Debug(DBG_GAMELOGIC, "Line special 507 (line #%s) missing back side!\n", sizeu1(i)); - break; - - case 508: - s = lines[i].sidenum[1]; - - if (s != 0xffff) - Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, s, accel, 0); - else - CONS_Debug(DBG_GAMELOGIC, "Line special 508 (line #%s) missing back side!\n", sizeu1(i)); - break; - - case 500: // scroll first side - Add_Scroller(sc_side, FRACUNIT, 0, -1, lines[i].sidenum[0], accel, 0); - break; - - case 501: // jff 1/30/98 2-way scroll - Add_Scroller(sc_side, -FRACUNIT, 0, -1, lines[i].sidenum[0], accel, 0); - break; - } - } -} - -/** Adds master appear/disappear thinker. - * - * \param appeartime tics to be existent - * \param disappeartime tics to be nonexistent - * \param sector pointer to control sector - */ -static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline) -{ - disappear_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); - - d->thinker.function.acp1 = (actionf_p1)T_Disappear; - d->appeartime = appeartime; - d->disappeartime = disappeartime; - d->offset = offset; - d->affectee = line; - d->sourceline = sourceline; - d->exists = true; - d->timer = 1; - - P_AddThinker(THINK_MAIN, &d->thinker); -} - -/** Makes a FOF appear/disappear - * - * \param d Disappear thinker. - * \sa Add_MasterDisappearer - */ -void T_Disappear(disappear_t *d) -{ - if (d->offset && !d->exists) - { - d->offset--; - return; - } - - if (--d->timer <= 0) - { - ffloor_t *rover; - register INT32 s; - mtag_t afftag = Tag_FGet(&lines[d->affectee].tags); - - TAG_ITER_SECTORS(afftag, s) - { - for (rover = sectors[s].ffloors; rover; rover = rover->next) - { - if (rover->master != &lines[d->affectee]) - continue; - - if (d->exists) - rover->flags &= ~FF_EXISTS; - else - { - rover->flags |= FF_EXISTS; - - if (!(lines[d->sourceline].flags & ML_NOCLIMB)) - { - sectors[s].soundorg.z = P_GetFFloorTopZAt(rover, sectors[s].soundorg.x, sectors[s].soundorg.y); - S_StartSound(§ors[s].soundorg, sfx_appear); - } - } - } - sectors[s].moved = true; - P_RecalcPrecipInSector(§ors[s]); - } - - if (d->exists) - { - d->timer = d->disappeartime; - d->exists = false; - } - else - { - d->timer = d->appeartime; - d->exists = true; - } - } -} - -/** Removes fadingdata from FOF control sector - * - * \param line line to search for target faders - * \param data pointer to set new fadingdata to. Can be NULL to erase. - */ -static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize) -{ - fade_t *fadingdata = (fade_t *)rover->fadingdata; - // find any existing thinkers and remove them, then replace with new data - if (fadingdata != data) - { - if (fadingdata) - { - if (finalize) - P_FadeFakeFloor(rover, - fadingdata->sourcevalue, - fadingdata->alpha >= fadingdata->destvalue ? - fadingdata->alpha - 1 : // trigger fade-out finish - fadingdata->alpha + 1, // trigger fade-in finish - 0, - fadingdata->ticbased, - &fadingdata->timer, - fadingdata->doexists, - fadingdata->dotranslucent, - fadingdata->dolighting, - fadingdata->docolormap, - fadingdata->docollision, - fadingdata->doghostfade, - fadingdata->exactalpha); - rover->alpha = fadingdata->alpha; - - if (fadingdata->dolighting) - P_RemoveLighting(§ors[rover->secnum]); - - if (fadingdata->docolormap) - P_ResetColormapFader(§ors[rover->secnum]); - - P_RemoveThinker(&fadingdata->thinker); - } - - rover->fadingdata = data; - } -} - -static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, - boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, - boolean docollision, boolean doghostfade, boolean exactalpha) -{ - boolean stillfading = false; - INT32 alpha; - fade_t *fadingdata = (fade_t *)rover->fadingdata; - (void)docolormap; // *shrug* maybe we can use this in the future. For now, let's be consistent with our other function params - - if (rover->master->special == 258) // Laser block - return false; - - // If fading an invisible FOF whose render flags we did not yet set, - // initialize its alpha to 1 - if (dotranslucent && - (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE - !(rover->flags & FF_FOG) && // do not include fog - !(rover->spawnflags & FF_RENDERSIDES) && - !(rover->spawnflags & FF_RENDERPLANES) && - !(rover->flags & FF_RENDERALL)) - rover->alpha = 1; - - if (fadingdata) - alpha = fadingdata->alpha; - else - alpha = rover->alpha; - - // routines specific to fade in and fade out - if (!ticbased && alpha == destvalue) - return stillfading; - else if (alpha > destvalue) // fade out - { - // finish fading out - if (speed < 1 || (!ticbased && alpha - speed <= destvalue + speed) || - (ticbased && (--(*timer) <= 0 || alpha <= destvalue))) - { - alpha = destvalue; - - if (docollision) - { - if (rover->spawnflags & FF_SOLID) - rover->flags &= ~FF_SOLID; - if (rover->spawnflags & FF_SWIMMABLE) - rover->flags &= ~FF_SWIMMABLE; - if (rover->spawnflags & FF_QUICKSAND) - rover->flags &= ~FF_QUICKSAND; - if (rover->spawnflags & FF_BUSTUP) - rover->flags &= ~FF_BUSTUP; - if (rover->spawnflags & FF_MARIO) - rover->flags &= ~FF_MARIO; - } - } - else // continue fading out - { - if (!ticbased) - alpha -= speed; - else - { - INT16 delta = abs(destvalue - sourcevalue); - fixed_t factor = min(FixedDiv(speed - (*timer), speed), 1*FRACUNIT); - alpha = max(min(alpha, sourcevalue - (INT16)FixedMul(delta, factor)), destvalue); - } - stillfading = true; - } - } - else // fade in - { - // finish fading in - if (speed < 1 || (!ticbased && alpha + speed >= destvalue - speed) || - (ticbased && (--(*timer) <= 0 || alpha >= destvalue))) - { - alpha = destvalue; - - if (docollision) - { - if (rover->spawnflags & FF_SOLID) - rover->flags |= FF_SOLID; - if (rover->spawnflags & FF_SWIMMABLE) - rover->flags |= FF_SWIMMABLE; - if (rover->spawnflags & FF_QUICKSAND) - rover->flags |= FF_QUICKSAND; - if (rover->spawnflags & FF_BUSTUP) - rover->flags |= FF_BUSTUP; - if (rover->spawnflags & FF_MARIO) - rover->flags |= FF_MARIO; - } - } - else // continue fading in - { - if (!ticbased) - alpha += speed; - else - { - INT16 delta = abs(destvalue - sourcevalue); - fixed_t factor = min(FixedDiv(speed - (*timer), speed), 1*FRACUNIT); - alpha = min(max(alpha, sourcevalue + (INT16)FixedMul(delta, factor)), destvalue); - } - stillfading = true; - } - } - - // routines common to both fade in and fade out - if (!stillfading) - { - if (doexists && !(rover->spawnflags & FF_BUSTUP)) - { - if (alpha <= 1) - rover->flags &= ~FF_EXISTS; - else - rover->flags |= FF_EXISTS; - - // Re-render lighting at end of fade - if (dolighting && !(rover->spawnflags & FF_NOSHADE) && !(rover->flags & FF_EXISTS)) - rover->target->moved = true; - } - - if (dotranslucent && !(rover->flags & FF_FOG)) - { - if (alpha >= 256) - { - if (!(rover->flags & FF_CUTSOLIDS) && - (rover->spawnflags & FF_CUTSOLIDS)) - { - rover->flags |= FF_CUTSOLIDS; - rover->target->moved = true; - } - - rover->flags &= ~FF_TRANSLUCENT; - } - else - { - rover->flags |= FF_TRANSLUCENT; - - if ((rover->flags & FF_CUTSOLIDS) && - (rover->spawnflags & FF_CUTSOLIDS)) - { - rover->flags &= ~FF_CUTSOLIDS; - rover->target->moved = true; - } - } - - if ((rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE - !(rover->spawnflags & FF_RENDERSIDES) && - !(rover->spawnflags & FF_RENDERPLANES)) - { - if (rover->alpha > 1) - rover->flags |= FF_RENDERALL; - else - rover->flags &= ~FF_RENDERALL; - } - } - } - else - { - if (doexists && !(rover->spawnflags & FF_BUSTUP)) - { - // Re-render lighting if we haven't yet set FF_EXISTS (beginning of fade) - if (dolighting && !(rover->spawnflags & FF_NOSHADE) && !(rover->flags & FF_EXISTS)) - rover->target->moved = true; - - rover->flags |= FF_EXISTS; - } - - if (dotranslucent && !(rover->flags & FF_FOG)) - { - rover->flags |= FF_TRANSLUCENT; - - if ((rover->flags & FF_CUTSOLIDS) && - (rover->spawnflags & FF_CUTSOLIDS)) - { - rover->flags &= ~FF_CUTSOLIDS; - rover->target->moved = true; - } - - if ((rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE - !(rover->spawnflags & FF_RENDERSIDES) && - !(rover->spawnflags & FF_RENDERPLANES)) - rover->flags |= FF_RENDERALL; - } - - if (docollision) - { - if (doghostfade) // remove collision flags during fade - { - if (rover->spawnflags & FF_SOLID) - rover->flags &= ~FF_SOLID; - if (rover->spawnflags & FF_SWIMMABLE) - rover->flags &= ~FF_SWIMMABLE; - if (rover->spawnflags & FF_QUICKSAND) - rover->flags &= ~FF_QUICKSAND; - if (rover->spawnflags & FF_BUSTUP) - rover->flags &= ~FF_BUSTUP; - if (rover->spawnflags & FF_MARIO) - rover->flags &= ~FF_MARIO; - } - else // keep collision during fade - { - if (rover->spawnflags & FF_SOLID) - rover->flags |= FF_SOLID; - if (rover->spawnflags & FF_SWIMMABLE) - rover->flags |= FF_SWIMMABLE; - if (rover->spawnflags & FF_QUICKSAND) - rover->flags |= FF_QUICKSAND; - if (rover->spawnflags & FF_BUSTUP) - rover->flags |= FF_BUSTUP; - if (rover->spawnflags & FF_MARIO) - rover->flags |= FF_MARIO; - } - } - } - - if (!(rover->flags & FF_FOG)) // don't set FOG alpha - { - if (!stillfading || exactalpha) - rover->alpha = alpha; - else // clamp fadingdata->alpha to software's alpha levels - { - if (alpha < 12) - rover->alpha = destvalue < 12 ? destvalue : 1; // Don't even draw it - else if (alpha < 38) - rover->alpha = destvalue >= 12 && destvalue < 38 ? destvalue : 25; - else if (alpha < 64) - rover->alpha = destvalue >=38 && destvalue < 64 ? destvalue : 51; - else if (alpha < 89) - rover->alpha = destvalue >= 64 && destvalue < 89 ? destvalue : 76; - else if (alpha < 115) - rover->alpha = destvalue >= 89 && destvalue < 115 ? destvalue : 102; - else if (alpha < 140) - rover->alpha = destvalue >= 115 && destvalue < 140 ? destvalue : 128; - else if (alpha < 166) - rover->alpha = destvalue >= 140 && destvalue < 166 ? destvalue : 154; - else if (alpha < 192) - rover->alpha = destvalue >= 166 && destvalue < 192 ? destvalue : 179; - else if (alpha < 217) - rover->alpha = destvalue >= 192 && destvalue < 217 ? destvalue : 204; - else if (alpha < 243) - rover->alpha = destvalue >= 217 && destvalue < 243 ? destvalue : 230; - else // Opaque - rover->alpha = destvalue >= 243 ? destvalue : 256; - } - } - - if (fadingdata) - fadingdata->alpha = alpha; - - return stillfading; -} - -/** Adds fake floor fader thinker. - * - * \param destvalue transparency value to fade to - * \param speed speed to fade by - * \param ticbased tic-based logic, speed = duration - * \param relative Destvalue is relative to rover->alpha - * \param doexists handle FF_EXISTS - * \param dotranslucent handle FF_TRANSLUCENT - * \param dolighting fade FOF light - * \param docollision handle interactive flags - * \param doghostfade no interactive flags during fading - * \param exactalpha use exact alpha values (opengl) - */ -static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, - INT16 destvalue, INT16 speed, boolean ticbased, boolean relative, - boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, - boolean docollision, boolean doghostfade, boolean exactalpha) -{ - fade_t *d; - - // If fading an invisible FOF whose render flags we did not yet set, - // initialize its alpha to 1 - if (dotranslucent && - (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE - !(rover->spawnflags & FF_RENDERSIDES) && - !(rover->spawnflags & FF_RENDERPLANES) && - !(rover->flags & FF_RENDERALL)) - rover->alpha = 1; - - // already equal, nothing to do - if (rover->alpha == max(1, min(256, relative ? rover->alpha + destvalue : destvalue))) - return; - - d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); - - d->thinker.function.acp1 = (actionf_p1)T_Fade; - d->rover = rover; - d->sectornum = (UINT32)sectornum; - d->ffloornum = (UINT32)ffloornum; - - d->alpha = d->sourcevalue = rover->alpha; - d->destvalue = max(1, min(256, relative ? rover->alpha + destvalue : destvalue)); // rover->alpha is 1-256 - - if (ticbased) - { - d->ticbased = true; - d->timer = d->speed = abs(speed); // use d->speed as total duration - } - else - { - d->ticbased = false; - d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker - d->timer = -1; - } - - d->doexists = doexists; - d->dotranslucent = dotranslucent; - d->dolighting = dolighting; - d->docolormap = docolormap; - d->docollision = docollision; - d->doghostfade = doghostfade; - d->exactalpha = exactalpha; - - // find any existing thinkers and remove them, then replace with new data - P_ResetFakeFloorFader(rover, d, false); - - // Set a separate thinker for shadow fading - if (dolighting && !(rover->flags & FF_NOSHADE)) - { - UINT16 lightdelta = abs(sectors[rover->secnum].spawn_lightlevel - rover->target->lightlevel); - fixed_t alphapercent = min(FixedDiv(d->destvalue, rover->spawnalpha), 1*FRACUNIT); // don't make darker than spawn_lightlevel - fixed_t adjustedlightdelta = FixedMul(lightdelta, alphapercent); - - if (rover->target->lightlevel >= sectors[rover->secnum].spawn_lightlevel) // fading out, get lighter - d->destlightlevel = rover->target->lightlevel - adjustedlightdelta; - else // fading in, get darker - d->destlightlevel = rover->target->lightlevel + adjustedlightdelta; - - P_FadeLightBySector(§ors[rover->secnum], - d->destlightlevel, - ticbased ? d->timer : - FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT, - true); - } - else - d->destlightlevel = -1; - - // Set a separate thinker for colormap fading - if (docolormap && !(rover->flags & FF_NOSHADE) && sectors[rover->secnum].spawn_extra_colormap && !sectors[rover->secnum].colormap_protected) - { - extracolormap_t *dest_exc, - *source_exc = sectors[rover->secnum].extra_colormap ? sectors[rover->secnum].extra_colormap : R_GetDefaultColormap(); - - INT32 colordelta = R_GetRgbaA(sectors[rover->secnum].spawn_extra_colormap->rgba); // alpha is from 0 - fixed_t alphapercent = min(FixedDiv(d->destvalue, rover->spawnalpha), 1*FRACUNIT); // don't make darker than spawn_lightlevel - fixed_t adjustedcolordelta = FixedMul(colordelta, alphapercent); - INT32 coloralpha; - - coloralpha = adjustedcolordelta; - - dest_exc = R_CopyColormap(sectors[rover->secnum].spawn_extra_colormap, false); - dest_exc->rgba = R_GetRgbaRGB(dest_exc->rgba) + R_PutRgbaA(coloralpha); - - if (!(d->dest_exc = R_GetColormapFromList(dest_exc))) - { - dest_exc->colormap = R_CreateLightTable(dest_exc); - R_AddColormapToList(dest_exc); - d->dest_exc = dest_exc; - } - else - Z_Free(dest_exc); - - // If fading from 0, set source_exc rgb same to dest_exc - if (!R_CheckDefaultColormap(d->dest_exc, true, false, false) - && R_CheckDefaultColormap(source_exc, true, false, false)) - { - extracolormap_t *exc = R_CopyColormap(source_exc, false); - exc->rgba = R_GetRgbaRGB(d->dest_exc->rgba) + R_PutRgbaA(R_GetRgbaA(source_exc->rgba)); - exc->fadergba = R_GetRgbaRGB(d->dest_exc->rgba) + R_PutRgbaA(R_GetRgbaA(source_exc->fadergba)); - - if (!(source_exc = R_GetColormapFromList(exc))) - { - exc->colormap = R_CreateLightTable(exc); - R_AddColormapToList(exc); - source_exc = exc; - } - else - Z_Free(exc); - } - - Add_ColormapFader(§ors[rover->secnum], source_exc, d->dest_exc, true, - ticbased ? d->timer : - FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT); - } - - P_AddThinker(THINK_MAIN, &d->thinker); -} - -/** Makes a FOF fade - * - * \param d Fade thinker. - * \sa P_AddFakeFloorFader - */ -void T_Fade(fade_t *d) -{ - if (d->rover && !P_FadeFakeFloor(d->rover, d->sourcevalue, d->destvalue, d->speed, d->ticbased, &d->timer, - d->doexists, d->dotranslucent, d->dolighting, d->docolormap, d->docollision, d->doghostfade, d->exactalpha)) - { - // Finalize lighting, copypasta from P_AddFakeFloorFader - if (d->dolighting && !(d->rover->flags & FF_NOSHADE) && d->destlightlevel > -1) - sectors[d->rover->secnum].lightlevel = d->destlightlevel; - - // Finalize colormap - if (d->docolormap && !(d->rover->flags & FF_NOSHADE) && sectors[d->rover->secnum].spawn_extra_colormap) - sectors[d->rover->secnum].extra_colormap = d->dest_exc; - - P_RemoveFakeFloorFader(d->rover); - } -} - -static void P_ResetColormapFader(sector_t *sector) -{ - if (sector->fadecolormapdata) - { - // The thinker is the first member in all the action structs, - // so just let the thinker get freed, and that will free the whole - // structure. - P_RemoveThinker(&((elevator_t *)sector->fadecolormapdata)->thinker); - sector->fadecolormapdata = NULL; - } -} - -static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, - boolean ticbased, INT32 duration) -{ - fadecolormap_t *d; - - P_ResetColormapFader(sector); - - // nothing to do, set immediately - if (!duration || R_CheckEqualColormaps(source_exc, dest_exc, true, true, true)) - { - sector->extra_colormap = dest_exc; - return; - } - - d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); - d->thinker.function.acp1 = (actionf_p1)T_FadeColormap; - d->sector = sector; - d->source_exc = source_exc; - d->dest_exc = dest_exc; - - if (ticbased) - { - d->ticbased = true; - d->duration = d->timer = duration; - } - else - { - d->ticbased = false; - d->timer = 256; - d->duration = duration; // use as speed - } - - sector->fadecolormapdata = d; - P_AddThinker(THINK_MAIN, &d->thinker); -} - -void T_FadeColormap(fadecolormap_t *d) -{ - if ((d->ticbased && --d->timer <= 0) - || (!d->ticbased && (d->timer -= d->duration) <= 0)) // d->duration used as speed decrement - { - d->sector->extra_colormap = d->dest_exc; - P_ResetColormapFader(d->sector); - } - else - { - extracolormap_t *exc; - INT32 duration = d->ticbased ? d->duration : 256; - fixed_t factor = min(FixedDiv(duration - d->timer, duration), 1*FRACUNIT); - INT16 cr, cg, cb, ca, fadestart, fadeend, flags; - INT32 rgba, fadergba; - - // NULL failsafes (or intentionally set to signify default) - if (!d->sector->extra_colormap) - d->sector->extra_colormap = R_GetDefaultColormap(); - - if (!d->source_exc) - d->source_exc = R_GetDefaultColormap(); - - if (!d->dest_exc) - d->dest_exc = R_GetDefaultColormap(); - - // For each var (rgba + fadergba + params = 11 vars), we apply - // percentage fading: currentval = sourceval + (delta * percent of duration elapsed) - // delta is negative when fading out (destval is lower) - // max/min are used to ensure progressive calcs don't go backwards and to cap values to dest. - -#define APPLYFADE(dest, src, cur) (\ -(dest-src < 0) ? \ - max(\ - min(cur,\ - src + (INT16)FixedMul(dest-src, factor)),\ - dest)\ -: (dest-src > 0) ? \ - min(\ - max(cur,\ - src + (INT16)FixedMul(dest-src, factor)),\ - dest)\ -: \ - dest\ -) - - cr = APPLYFADE(R_GetRgbaR(d->dest_exc->rgba), R_GetRgbaR(d->source_exc->rgba), R_GetRgbaR(d->sector->extra_colormap->rgba)); - cg = APPLYFADE(R_GetRgbaG(d->dest_exc->rgba), R_GetRgbaG(d->source_exc->rgba), R_GetRgbaG(d->sector->extra_colormap->rgba)); - cb = APPLYFADE(R_GetRgbaB(d->dest_exc->rgba), R_GetRgbaB(d->source_exc->rgba), R_GetRgbaB(d->sector->extra_colormap->rgba)); - ca = APPLYFADE(R_GetRgbaA(d->dest_exc->rgba), R_GetRgbaA(d->source_exc->rgba), R_GetRgbaA(d->sector->extra_colormap->rgba)); - - rgba = R_PutRgbaRGBA(cr, cg, cb, ca); - - cr = APPLYFADE(R_GetRgbaR(d->dest_exc->fadergba), R_GetRgbaR(d->source_exc->fadergba), R_GetRgbaR(d->sector->extra_colormap->fadergba)); - cg = APPLYFADE(R_GetRgbaG(d->dest_exc->fadergba), R_GetRgbaG(d->source_exc->fadergba), R_GetRgbaG(d->sector->extra_colormap->fadergba)); - cb = APPLYFADE(R_GetRgbaB(d->dest_exc->fadergba), R_GetRgbaB(d->source_exc->fadergba), R_GetRgbaB(d->sector->extra_colormap->fadergba)); - ca = APPLYFADE(R_GetRgbaA(d->dest_exc->fadergba), R_GetRgbaA(d->source_exc->fadergba), R_GetRgbaA(d->sector->extra_colormap->fadergba)); - - fadergba = R_PutRgbaRGBA(cr, cg, cb, ca); - - fadestart = APPLYFADE(d->dest_exc->fadestart, d->source_exc->fadestart, d->sector->extra_colormap->fadestart); - fadeend = APPLYFADE(d->dest_exc->fadeend, d->source_exc->fadeend, d->sector->extra_colormap->fadeend); - flags = abs(factor) > FRACUNIT/2 ? d->dest_exc->flags : d->source_exc->flags; // set new flags halfway through fade - -#undef APPLYFADE - - ////////////////// - // setup new colormap - ////////////////// - - if (!(d->sector->extra_colormap = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags))) - { - exc = R_CreateDefaultColormap(false); - exc->fadestart = fadestart; - exc->fadeend = fadeend; - exc->flags = flags; - exc->rgba = rgba; - exc->fadergba = fadergba; - exc->colormap = R_CreateLightTable(exc); - R_AddColormapToList(exc); - d->sector->extra_colormap = exc; - } - } -} - -/* - SoM: 3/8/2000: Friction functions start. - Add_Friction, - T_Friction, - P_SpawnFriction -*/ - -/** Adds friction thinker. - * - * \param friction Friction value, 0xe800 is normal. - * \param affectee Target sector. - * \param roverfriction FOF or not - * \sa T_Friction, P_SpawnFriction - */ -static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer) -{ - friction_t *f = Z_Calloc(sizeof *f, PU_LEVSPEC, NULL); - - f->thinker.function.acp1 = (actionf_p1)T_Friction; - f->friction = friction; - f->movefactor = movefactor; - f->affectee = affectee; - - if (referrer != -1) - { - f->roverfriction = true; - f->referrer = referrer; - } - else - f->roverfriction = false; - - P_AddThinker(THINK_MAIN, &f->thinker); -} - -/** Applies friction to all things in a sector. - * - * \param f Friction thinker. - * \sa Add_Friction - */ -void T_Friction(friction_t *f) -{ - sector_t *sec, *referrer = NULL; - mobj_t *thing; - msecnode_t *node; - - sec = sectors + f->affectee; - - // Get FOF control sector - if (f->roverfriction) - referrer = sectors + f->referrer; - - // Assign the friction value to players on the floor, non-floating, - // and clipped. Normally the object's friction value is kept at - // ORIG_FRICTION and this thinker changes it for icy or muddy floors. - - // When the object is straddling sectors with the same - // floorheight that have different frictions, use the lowest - // friction value (muddy has precedence over icy). - - node = sec->touching_thinglist; // things touching this sector - while (node) - { - thing = node->m_thing; - // apparently, all I had to do was comment out part of the next line and - // friction works for all mobj's - // (or at least MF_PUSHABLEs, which is all I care about anyway) - if (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) && thing->z == thing->floorz) - { - if (f->roverfriction) - { - if (thing->floorz != P_GetSpecialTopZ(thing, referrer, sec)) - { - node = node->m_thinglist_next; - continue; - } - - if ((thing->friction == ORIG_FRICTION) // normal friction? - || (f->friction < thing->friction)) - { - thing->friction = f->friction; - if (thing->player) - thing->movefactor = f->movefactor; - } - } - else if (P_GetSpecialBottomZ(thing, sec, sec) == thing->floorz && (thing->friction == ORIG_FRICTION // normal friction? - || f->friction < thing->friction)) - { - thing->friction = f->friction; - if (thing->player) - thing->movefactor = f->movefactor; - } - } - node = node->m_thinglist_next; - } -} - -/** Spawns all friction effects. - * - * \sa P_SpawnSpecials, Add_Friction - */ -static void P_SpawnFriction(void) -{ - size_t i; - line_t *l = lines; - mtag_t tag; - register INT32 s; - fixed_t strength; // frontside texture offset controls magnitude - fixed_t friction; // friction value to be applied during movement - INT32 movefactor; // applied to each player move to simulate inertia - - for (i = 0; i < numlines; i++, l++) - if (l->special == 540) - { - tag = Tag_FGet(&l->tags); - strength = sides[l->sidenum[0]].textureoffset>>FRACBITS; - if (strength > 0) // sludge - strength = strength*2; // otherwise, the maximum sludginess value is +967... - - // The following might seem odd. At the time of movement, - // the move distance is multiplied by 'friction/0x10000', so a - // higher friction value actually means 'less friction'. - friction = ORIG_FRICTION - (0x1EB8*strength)/0x80; // ORIG_FRICTION is 0xE800 - - if (friction > FRACUNIT) - friction = FRACUNIT; - if (friction < 0) - friction = 0; - - movefactor = FixedDiv(ORIG_FRICTION, friction); - if (movefactor < FRACUNIT) - movefactor = 8*movefactor - 7*FRACUNIT; - else - movefactor = FRACUNIT; - - TAG_ITER_SECTORS(tag, s) - Add_Friction(friction, movefactor, s, -1); - } -} - -/* - SoM: 3/8/2000: Push/Pull/Wind/Current functions. - Add_Pusher, - PIT_PushThing, - T_Pusher, - P_GetPushThing, - P_SpawnPushers -*/ - -#define PUSH_FACTOR 7 - -/** Adds a pusher. - * - * \param type Type of push/pull effect. - * \param x_mag X magnitude. - * \param y_mag Y magnitude. - * \param source For a point pusher/puller, the source object. - * \param affectee Target sector. - * \param referrer What sector set it - * \sa T_Pusher, P_GetPushThing, P_SpawnPushers - */ -static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider) -{ - pusher_t *p = Z_Calloc(sizeof *p, PU_LEVSPEC, NULL); - - p->thinker.function.acp1 = (actionf_p1)T_Pusher; - p->source = source; - p->type = type; - p->x_mag = x_mag>>FRACBITS; - p->y_mag = y_mag>>FRACBITS; - p->exclusive = exclusive; - p->slider = slider; - - if (referrer != -1) - { - p->roverpusher = true; - p->referrer = referrer; - } - else - p->roverpusher = false; - - // "The right triangle of the square of the length of the hypotenuse is equal to the sum of the squares of the lengths of the other two sides." - // "Bah! Stupid brains! Don't you know anything besides the Pythagorean Theorem?" - Earthworm Jim - if (type == p_downcurrent || type == p_upcurrent || type == p_upwind || type == p_downwind) - p->magnitude = P_AproxDistance(p->x_mag,p->y_mag)<<(FRACBITS-PUSH_FACTOR); - else - p->magnitude = P_AproxDistance(p->x_mag,p->y_mag); - if (source) // point source exist? - { - // where force goes to zero - if (type == p_push) - p->radius = AngleFixed(source->angle); - else - p->radius = (p->magnitude)<<(FRACBITS+1); - - p->x = p->source->x; - p->y = p->source->y; - p->z = p->source->z; - } - p->affectee = affectee; - P_AddThinker(THINK_MAIN, &p->thinker); -} - - -// PIT_PushThing determines the angle and magnitude of the effect. -// The object's x and y momentum values are changed. -static pusher_t *tmpusher; // pusher structure for blockmap searches - -/** Applies a point pusher/puller to a thing. - * - * \param thing Thing to be pushed. - * \return True if the thing was pushed. - * \todo Make a more robust P_BlockThingsIterator() so the hidden parameter - * ::tmpusher won't need to be used. - * \sa T_Pusher - */ -static inline boolean PIT_PushThing(mobj_t *thing) -{ - if (thing->eflags & MFE_PUSHED) - return false; - - if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG) - return false; - - if (!tmpusher->source) - return false; - - // Allow this to affect pushable objects at some point? - if (thing->player && (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) || thing->player->powers[pw_carry] == CR_NIGHTSMODE)) - { - INT32 dist; - INT32 speed; - INT32 sx, sy, sz; - - sx = tmpusher->x; - sy = tmpusher->y; - sz = tmpusher->z; - - // don't fade wrt Z if health & 2 (mapthing has multi flag) - if (tmpusher->source->health & 2) - dist = P_AproxDistance(thing->x - sx,thing->y - sy); - else - { - // Make sure the Z is in range - if (thing->z < sz - tmpusher->radius || thing->z > sz + tmpusher->radius) - return false; - - dist = P_AproxDistance(P_AproxDistance(thing->x - sx, thing->y - sy), - thing->z - sz); - } - - speed = (tmpusher->magnitude - ((dist>>FRACBITS)>>1))<<(FRACBITS - PUSH_FACTOR - 1); - - // If speed <= 0, you're outside the effective radius. You also have - // to be able to see the push/pull source point. - - // Written with bits and pieces of P_HomingAttack - if ((speed > 0) && (P_CheckSight(thing, tmpusher->source))) - { - if (thing->player->powers[pw_carry] != CR_NIGHTSMODE) - { - // only push wrt Z if health & 1 (mapthing has ambush flag) - if (tmpusher->source->health & 1) - { - fixed_t tmpmomx, tmpmomy, tmpmomz; - - tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed); - tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed); - tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed); - if (tmpusher->source->type == MT_PUSH) // away! - { - tmpmomx *= -1; - tmpmomy *= -1; - tmpmomz *= -1; - } - - thing->momx += tmpmomx; - thing->momy += tmpmomy; - thing->momz += tmpmomz; - - if (thing->player) - { - thing->player->cmomx += tmpmomx; - thing->player->cmomy += tmpmomy; - thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); - thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); - } - } - else - { - angle_t pushangle; - - pushangle = R_PointToAngle2(thing->x, thing->y, sx, sy); - if (tmpusher->source->type == MT_PUSH) - pushangle += ANGLE_180; // away - pushangle >>= ANGLETOFINESHIFT; - thing->momx += FixedMul(speed, FINECOSINE(pushangle)); - thing->momy += FixedMul(speed, FINESINE(pushangle)); - - if (thing->player) - { - thing->player->cmomx += FixedMul(speed, FINECOSINE(pushangle)); - thing->player->cmomy += FixedMul(speed, FINESINE(pushangle)); - thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); - thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); - } - } - } - else - { - //NiGHTS-specific handling. - //By default, pushes and pulls only affect the Z-axis. - //By having the ambush flag, it affects the X-axis. - //By having the object special flag, it affects the Y-axis. - fixed_t tmpmomx, tmpmomy, tmpmomz; - - if (tmpusher->source->health & 1) - tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed); - else - tmpmomx = 0; - - if (tmpusher->source->health & 2) - tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed); - else - tmpmomy = 0; - - tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed); - - if (tmpusher->source->type == MT_PUSH) // away! - { - tmpmomx *= -1; - tmpmomy *= -1; - tmpmomz *= -1; - } - - thing->momx += tmpmomx; - thing->momy += tmpmomy; - thing->momz += tmpmomz; - - if (thing->player) - { - thing->player->cmomx += tmpmomx; - thing->player->cmomy += tmpmomy; - thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); - thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); - } - } - } - } - - if (tmpusher->exclusive) - thing->eflags |= MFE_PUSHED; - - return true; -} - -/** Applies a pusher to all affected objects. - * - * \param p Thinker for the pusher effect. - * \todo Split up into multiple functions. - * \sa Add_Pusher, PIT_PushThing - */ -void T_Pusher(pusher_t *p) -{ - sector_t *sec, *referrer = NULL; - mobj_t *thing; - msecnode_t *node; - INT32 xspeed = 0,yspeed = 0; - INT32 xl, xh, yl, yh, bx, by; - INT32 radius; - //INT32 ht = 0; - boolean inFOF; - boolean touching; - boolean moved; - - xspeed = yspeed = 0; - - sec = sectors + p->affectee; - - // Be sure the special sector type is still turned on. If so, proceed. - // Else, bail out; the sector type has been changed on us. - - if (p->roverpusher) - { - referrer = §ors[p->referrer]; - - if (GETSECSPECIAL(referrer->special, 3) != 2) - return; - } - else if (GETSECSPECIAL(sec->special, 3) != 2) - return; - - // For constant pushers (wind/current) there are 3 situations: - // - // 1) Affected Thing is above the floor. - // - // Apply the full force if wind, no force if current. - // - // 2) Affected Thing is on the ground. - // - // Apply half force if wind, full force if current. - // - // 3) Affected Thing is below the ground (underwater effect). - // - // Apply no force if wind, full force if current. - // - // Apply the effect to clipped players only for now. - // - // In Phase II, you can apply these effects to Things other than players. - - if (p->type == p_push) - { - - // Seek out all pushable things within the force radius of this - // point pusher. Crosses sectors, so use blockmap. - - tmpusher = p; // MT_PUSH/MT_PULL point source - radius = p->radius; // where force goes to zero - tmbbox[BOXTOP] = p->y + radius; - tmbbox[BOXBOTTOM] = p->y - radius; - tmbbox[BOXRIGHT] = p->x + radius; - tmbbox[BOXLEFT] = p->x - radius; - - xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - P_BlockThingsIterator(bx,by, PIT_PushThing); - return; - } - - // constant pushers p_wind and p_current - node = sec->touching_thinglist; // things touching this sector - for (; node; node = node->m_thinglist_next) - { - thing = node->m_thing; - if (thing->flags & (MF_NOGRAVITY | MF_NOCLIP) - && !(thing->type == MT_SMALLBUBBLE - || thing->type == MT_MEDIUMBUBBLE - || thing->type == MT_EXTRALARGEBUBBLE)) - continue; - - if (!((thing->flags & MF_PUSHABLE) || ((thing->info->flags & MF_PUSHABLE) && thing->fuse)) - && !(thing->type == MT_PLAYER - || thing->type == MT_SMALLBUBBLE - || thing->type == MT_MEDIUMBUBBLE - || thing->type == MT_EXTRALARGEBUBBLE - || thing->type == MT_LITTLETUMBLEWEED - || thing->type == MT_BIGTUMBLEWEED)) - continue; - - if (thing->eflags & MFE_PUSHED) - continue; - - if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG) - continue; - - if (thing->player && (thing->state == &states[thing->info->painstate]) && (thing->player->powers[pw_flashing] > (flashingtics/4)*3 && thing->player->powers[pw_flashing] <= flashingtics)) - continue; - - inFOF = touching = moved = false; - - // Find the area that the 'thing' is in - if (p->roverpusher) - { - fixed_t top, bottom; - - top = P_GetSpecialTopZ(thing, referrer, sec); - bottom = P_GetSpecialBottomZ(thing, referrer, sec); - - if (thing->eflags & MFE_VERTICALFLIP) - { - if (bottom > thing->z + thing->height - || top < (thing->z + (thing->height >> 1))) - continue; - - if (thing->z < bottom) - touching = true; - - if (thing->z + (thing->height >> 1) > bottom) - inFOF = true; - - } - else - { - if (top < thing->z || bottom > (thing->z + (thing->height >> 1))) - continue; - if (thing->z + thing->height > top) - touching = true; - - if (thing->z + (thing->height >> 1) < top) - inFOF = true; - } - } - else // Treat the entire sector as one big FOF - { - if (thing->z == P_GetSpecialBottomZ(thing, sec, sec)) - touching = true; - else if (p->type != p_current) - inFOF = true; - } - - if (!touching && !inFOF) // Object is out of range of effect - continue; - - if (p->type == p_wind) - { - if (touching) // on ground - { - xspeed = (p->x_mag)>>1; // half force - yspeed = (p->y_mag)>>1; - moved = true; - } - else if (inFOF) - { - xspeed = (p->x_mag); // full force - yspeed = (p->y_mag); - moved = true; - } - } - else if (p->type == p_upwind) - { - if (touching) // on ground - { - thing->momz += (p->magnitude)>>1; - moved = true; - } - else if (inFOF) - { - thing->momz += p->magnitude; - moved = true; - } - } - else if (p->type == p_downwind) - { - if (touching) // on ground - { - thing->momz -= (p->magnitude)>>1; - moved = true; - } - else if (inFOF) - { - thing->momz -= p->magnitude; - moved = true; - } - } - else // p_current - { - if (!touching && !inFOF) // Not in water at all - xspeed = yspeed = 0; // no force - else // underwater / touching water - { - if (p->type == p_upcurrent) - thing->momz += p->magnitude; - else if (p->type == p_downcurrent) - thing->momz -= p->magnitude; - else - { - xspeed = p->x_mag; // full force - yspeed = p->y_mag; - } - moved = true; - } - } - - if (p->type != p_downcurrent && p->type != p_upcurrent - && p->type != p_upwind && p->type != p_downwind) - { - thing->momx += xspeed<<(FRACBITS-PUSH_FACTOR); - thing->momy += yspeed<<(FRACBITS-PUSH_FACTOR); - if (thing->player) - { - thing->player->cmomx += xspeed<<(FRACBITS-PUSH_FACTOR); - thing->player->cmomy += yspeed<<(FRACBITS-PUSH_FACTOR); - thing->player->cmomx = FixedMul(thing->player->cmomx, ORIG_FRICTION); - thing->player->cmomy = FixedMul(thing->player->cmomy, ORIG_FRICTION); - } - - // Tumbleweeds bounce a bit... - if (thing->type == MT_LITTLETUMBLEWEED || thing->type == MT_BIGTUMBLEWEED) - thing->momz += P_AproxDistance(xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)) >> 2; - } - - if (moved) - { - if (p->slider && thing->player) - { - pflags_t jumped = (thing->player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE)); - P_ResetPlayer (thing->player); - - if (jumped) - thing->player->pflags |= jumped; - - thing->player->pflags |= PF_SLIDING; - thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)); - - if (!demoplayback || P_ControlStyle(thing->player) == CS_LMAOGALOG) - { - angle_t angle = thing->player->angleturn << 16; - if (thing->angle - angle > ANGLE_180) - P_SetPlayerAngle(thing->player, angle - (angle - thing->angle) / 8); - else - P_SetPlayerAngle(thing->player, angle + (thing->angle - angle) / 8); - //P_SetPlayerAngle(thing->player, thing->angle); - } - } - - if (p->exclusive) - thing->eflags |= MFE_PUSHED; - } - } -} - - -/** Gets a push/pull object. - * - * \param s Sector number to look in. - * \return Pointer to the first ::MT_PUSH or ::MT_PULL object found in the - * sector. - * \sa P_GetTeleportDestThing, P_GetStarpostThing, P_GetAltViewThing - */ -mobj_t *P_GetPushThing(UINT32 s) -{ - mobj_t *thing; - sector_t *sec; - - sec = sectors + s; - thing = sec->thinglist; - while (thing) - { - switch (thing->type) - { - case MT_PUSH: - case MT_PULL: - return thing; - default: - break; - } - thing = thing->snext; - } - return NULL; -} - -/** Spawns pushers. - * - * \todo Remove magic numbers. - * \sa P_SpawnSpecials, Add_Pusher - */ -static void P_SpawnPushers(void) -{ - size_t i; - line_t *l = lines; - mtag_t tag; - register INT32 s; - mobj_t *thing; - - for (i = 0; i < numlines; i++, l++) - { - tag = Tag_FGet(&l->tags); - switch (l->special) - { - case 541: // wind - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_wind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - break; - case 544: // current - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_current, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - break; - case 547: // push/pull - TAG_ITER_SECTORS(tag, s) - { - thing = P_GetPushThing(s); - if (thing) // No MT_P* means no effect - Add_Pusher(p_push, l->dx, l->dy, thing, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - } - break; - case 545: // current up - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_upcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - break; - case 546: // current down - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_downcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - break; - case 542: // wind up - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_upwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - break; - case 543: // wind down - TAG_ITER_SECTORS(tag, s) - Add_Pusher(p_downwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); - break; - } - } -} From f714966c8364db3871edd59e82ead563864c641b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 12 Dec 2021 08:27:27 +0100 Subject: [PATCH 186/326] Remove outdated linedef type check in HWR_ProcessSeg --- src/hardware/hw_main.c | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 9bade3d6f..d187b0897 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1434,34 +1434,10 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // set alpha for transparent walls // ooops ! this do not work at all because render order we should render it in backtofront order - switch (gl_linedef->special) - { - // Translucent - case 102: - case 121: - case 123: - case 124: - case 125: - case 141: - case 142: - case 144: - case 145: - case 174: - case 175: - case 192: - case 195: - case 221: - case 253: - case 256: - blendmode = PF_Translucent; - break; - default: - if (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT) - blendmode = HWR_TranstableToAlpha(R_GetLinedefTransTable(gl_linedef->alpha), &Surf); - else - blendmode = PF_Masked; - break; - } + if (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT) + blendmode = HWR_TranstableToAlpha(R_GetLinedefTransTable(gl_linedef->alpha), &Surf); + else + blendmode = PF_Masked; if (gl_curline->polyseg && gl_curline->polyseg->translucency > 0) { From 1b023732d034adb1c3f86d1cc8f0a594f9920051 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 13 Dec 2021 08:24:52 +0100 Subject: [PATCH 187/326] Adapt rock spawner to UDMF --- src/p_enemy.c | 43 +++++++++++++++---------------------------- src/p_mobj.c | 4 ---- src/p_setup.c | 26 ++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 1216bb095..c02ca38be 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -12,6 +12,7 @@ /// \brief Enemy thinking, AI /// Action Pointer Functions that are associated with states/frames +#include "dehacked.h" #include "doomdef.h" #include "g_game.h" #include "p_local.h" @@ -6182,48 +6183,34 @@ void A_RockSpawn(mobj_t *actor) { mobj_t *mo; mobjtype_t type; - INT32 i = Tag_FindLineSpecial(12, (INT16)actor->threshold); - line_t *line; fixed_t dist; - fixed_t randomoomph; if (LUA_CallAction(A_ROCKSPAWN, actor)) return; - if (i == -1) + if (!actor->spawnpoint) + return; + + type = actor->spawnpoint->stringargs[0] ? get_number(actor->spawnpoint->stringargs[0]) : MT_ROCKCRUMBLE1; + + if (type < MT_NULL || type >= NUMMOBJTYPES) { - CONS_Debug(DBG_GAMELOGIC, "A_RockSpawn: Unable to find parameter line 12 (tag %d)!\n", actor->threshold); + CONS_Debug(DBG_GAMELOGIC, "A_RockSpawn: Invalid mobj type %s!\n", actor->spawnpoint->stringargs[0]); return; } - line = &lines[i]; - - if (!(sides[line->sidenum[0]].textureoffset >> FRACBITS)) - { - CONS_Debug(DBG_GAMELOGIC, "A_RockSpawn: No X-offset detected! (tag %d)!\n", actor->threshold); - return; - } - - dist = P_AproxDistance(line->dx, line->dy)/16; - - if (dist < 1) - dist = 1; - - type = MT_ROCKCRUMBLE1 + (sides[line->sidenum[0]].rowoffset >> FRACBITS); - - if (line->flags & ML_NOCLIMB) - randomoomph = P_RandomByte() * (FRACUNIT/32); - else - randomoomph = 0; + dist = max(actor->spawnpoint->args[0] << (FRACBITS - 4), 1); + if (actor->spawnpoint->args[2]) + dist += actor->spawnpoint->args[2] ? P_RandomByte() * (FRACUNIT/32) : 0; // random oomph mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FALLINGROCK); P_SetMobjState(mo, mobjinfo[type].spawnstate); - mo->angle = R_PointToAngle2(line->v2->x, line->v2->y, line->v1->x, line->v1->y); + mo->angle = FixedAngle(actor->spawnpoint->angle << FRACBITS); - P_InstaThrust(mo, mo->angle, dist + randomoomph); - mo->momz = dist + randomoomph; + P_InstaThrust(mo, mo->angle, dist); + mo->momz = dist; - var1 = sides[line->sidenum[0]].textureoffset >> FRACBITS; + var1 = actor->spawnpoint->args[1]; A_SetTics(actor); } diff --git a/src/p_mobj.c b/src/p_mobj.c index d0af3112e..9ce4c70bf 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12722,10 +12722,6 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (!P_SetupParticleGen(mthing, mobj)) return false; break; - case MT_ROCKSPAWNER: - mobj->threshold = mthing->angle; - mobj->movecount = mthing->extrainfo; - break; case MT_POPUPTURRET: if (mthing->angle) mobj->threshold = mthing->angle; diff --git a/src/p_setup.c b/src/p_setup.c index aa687bfa2..fc8fff752 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4877,6 +4877,32 @@ static void P_ConvertBinaryMap(void) mapthings[i].type = 761; break; } + case 1202: //Rock spawner + { + mtag_t tag = (mtag_t)mapthings[i].angle; + INT32 j = Tag_FindLineSpecial(12, tag); + INT32 typeoffset; + + if (j == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Rock spawner: Unable to find parameter line 12 (tag %d)!\n", tag); + break; + } + mapthings[i].angle = AngleFixed(R_PointToAngle2(lines[j].v2->x, lines[j].v2->y, lines[j].v1->x, lines[j].v1->y)) >> FRACBITS; + mapthings[i].args[0] = P_AproxDistance(lines[j].dx, lines[j].dy) >> FRACBITS; + mapthings[i].args[1] = sides[lines[j].sidenum[0]].textureoffset >> FRACBITS; + mapthings[i].args[2] = !!(lines[j].flags & ML_NOCLIMB); + typeoffset = sides[lines[j].sidenum[0]].rowoffset >> FRACBITS; + if (typeoffset < 0 || typeoffset > 15) + { + CONS_Debug(DBG_GAMELOGIC, "Rock spawner: Invalid Y offset %d (tag %d)!\n", typeoffset, tag); + break; + } + + mapthings[i].stringargs[0] = Z_Malloc(17, PU_LEVEL, NULL); + sprintf(mapthings[i].stringargs[0], "MT_ROCKCRUMBLE%d", typeoffset + 1); + break; + } default: break; } From c1e22c4bb661ef8e43ecc4adb5427219903d963e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Dec 2021 06:43:06 +0100 Subject: [PATCH 188/326] Add two more linedef/thing args because the maces need them --- extras/conf/udb/Includes/SRB222_misc.cfg | 10 ++++++++++ src/doomdata.h | 2 +- src/r_defs.h | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index f4a60581a..f27e5408c 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -242,6 +242,16 @@ universalfields type = 0; default = 0; } + arg8 + { + type = 0; + default = 0; + } + arg9 + { + type = 0; + default = 0; + } stringarg0 { type = 2; diff --git a/src/doomdata.h b/src/doomdata.h index 7ba159a7c..630e18615 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -196,7 +196,7 @@ typedef struct #pragma pack() #endif -#define NUMMAPTHINGARGS 8 +#define NUMMAPTHINGARGS 10 #define NUMMAPTHINGSTRINGARGS 2 // Thing definition, position, orientation and type, diff --git a/src/r_defs.h b/src/r_defs.h index 8e17addf5..0609a48a8 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -405,7 +405,7 @@ typedef enum #define HORIZONSPECIAL 41 -#define NUMLINEARGS 8 +#define NUMLINEARGS 10 #define NUMLINESTRINGARGS 2 typedef struct line_s From ed9a562ec4b2c89466d0fc63f81becc2902b9aa3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Dec 2021 18:50:47 +0100 Subject: [PATCH 189/326] Adapt maces to UDMF --- src/p_mobj.c | 97 +++++++++++++++------------------------------------ src/p_setup.c | 61 ++++++++++++++++++++++++++++++++ src/p_spec.h | 12 +++++++ 3 files changed, 101 insertions(+), 69 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 9ce4c70bf..5b4feb3ca 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11,6 +11,7 @@ /// \file p_mobj.c /// \brief Moving object handling. Spawn functions +#include "dehacked.h" #include "doomdef.h" #include "g_game.h" #include "g_input.h" @@ -12039,59 +12040,20 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) 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 - line = Tag_FindLineSpecial(9, mthing->angle); - - 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; + mlength = abs(mthing->args[0]); + mnumspokes = mthing->args[1] + 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; + mwidth = max(0, mthing->args[2]); + mspeed = abs(mthing->args[3] << 4); + mphase = mthing->args[4] % 360; + mpinch = mthing->args[5] % 360; + mnumnospokes = mthing->args[6]; + mminlength = max(0, min(mlength - 1, mthing->args[7])); + mpitch = mthing->pitch % 360; + myaw = mthing->angle % 360; + mroll = mthing->roll % 360; CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n" "Length is %d (minus %d)\n" @@ -12122,26 +12084,23 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) switch (mobj->type) { case MT_SPRINGBALLPOINT: - macetype = ((mthing->options & MTF_AMBUSH) + macetype = ((mthing->args[8] & TMM_DOUBLESIZE) ? MT_REDSPRINGBALL : MT_YELLOWSPRINGBALL); chainlink = MT_SMALLMACECHAIN; break; case MT_FIREBARPOINT: - macetype = ((mthing->options & MTF_AMBUSH) + macetype = ((mthing->args[8] & TMM_DOUBLESIZE) ? 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; + macetype = mthing->stringargs[0] ? get_number(mthing->stringargs[0]) : MT_NULL; + chainlink = mthing->stringargs[1] ? get_number(mthing->stringargs[1]) : MT_NULL; break; case MT_CHAINPOINT: - if (mthing->options & MTF_AMBUSH) + if (mthing->args[8] & TMM_DOUBLESIZE) { macetype = MT_BIGGRABCHAIN; chainlink = MT_BIGMACECHAIN; @@ -12154,7 +12113,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) mchainlike = true; break; default: - if (mthing->options & MTF_AMBUSH) + if (mthing->args[8] & TMM_DOUBLESIZE) { macetype = MT_BIGMACE; chainlink = MT_BIGMACECHAIN; @@ -12181,11 +12140,11 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) firsttype = macetype; // Adjustable direction - if (lines[line].flags & ML_NOCLIMB) + if (mthing->args[8] & TMM_ALLOWYAWCONTROL) mobj->flags |= MF_SLIDEME; // Swinging - if (lines[line].flags & ML_EFFECT1) + if (mthing->args[8] & TMM_SWING) { mobj->flags2 |= MF2_STRONGBOX; mmin = ((mnumnospokes > 1) ? 1 : 0); @@ -12194,11 +12153,11 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) mmin = mnumspokes; // If over distance away, don't move UNLESS this flag is applied - if (lines[line].flags & ML_EFFECT5) + if (mthing->args[8] & TMM_ALWAYSTHINK) 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 + if ((mobj->type != MT_CHAINPOINT) && (((mthing->args[8] & TMM_MACELINKS) == TMM_MACELINKS) != (mobj->type == MT_FIREBARPOINT))) // exclusive or { linktype = macetype; radiusfactor = 2; // Double the radius. @@ -12210,7 +12169,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) mchainlike = (firsttype == chainlink); widthfactor = (mchainlike ? 1 : 2); - mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP | MF_NOCLIPHEIGHT)); + mflagsapply = (mthing->args[8] & TMM_CLIP) ? 0 : (MF_NOCLIP|MF_NOCLIPHEIGHT); mflags2apply = ((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0); meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0); @@ -12236,14 +12195,14 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) hprev = spawnee;\ } - mdosound = (mspeed && !(mthing->options & MTF_OBJECTSPECIAL)); - mdocenter = (macetype && (lines[line].flags & ML_EFFECT3)); + mdosound = (mspeed && !(mthing->args[8] & TMM_SILENT)); + mdocenter = (macetype && (mthing->args[8] & TMM_CENTERLINK)); // The actual spawning of spokes while (mnumspokes-- > 0) { // Offsets - if (lines[line].flags & ML_EFFECT1) // Swinging + if (mthing->args[8] & TMM_SWING) // Swinging mroll = (mroll - mspokeangle) & FINEMASK; else // Spinning mphase = (mphase - mspokeangle) & FINEMASK; @@ -12254,7 +12213,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) continue; linktype = chainlink; - firsttype = ((mthing->options & MTF_AMBUSH) ? MT_BIGGRABCHAIN : MT_SMALLGRABCHAIN); + firsttype = ((mthing->args[8] & TMM_DOUBLESIZE) ? MT_BIGGRABCHAIN : MT_SMALLGRABCHAIN); mmaxlength = 1 + (mlength - 1) * radiusfactor; radiusfactor = widthfactor = 1; } @@ -12263,7 +12222,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) if (mobj->type == MT_CHAINMACEPOINT) { // Make the links the same type as the end - repeated above - if (lines[line].flags & ML_EFFECT2) + if (mthing->args[8] & TMM_MACELINKS) { linktype = macetype; radiusfactor = 2; diff --git a/src/p_setup.c b/src/p_setup.c index fc8fff752..cfcf0047c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4877,6 +4877,67 @@ static void P_ConvertBinaryMap(void) mapthings[i].type = 761; break; } + case 1104: //Mace spawnpoint + case 1105: //Chain with maces spawnpoint + case 1106: //Chained spring spawnpoint + case 1107: //Chain spawnpoint + case 1109: //Firebar spawnpoint + case 1110: //Custom mace spawnpoint + { + mtag_t tag = (mtag_t)mapthings[i].angle; + INT32 j = Tag_FindLineSpecial(9, tag); + + if (j == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Chain/mace setup: Unable to find parameter line 9 (tag %d)!\n", tag); + break; + } + + mapthings[i].angle = lines[j].frontsector->ceilingheight >> FRACBITS; + mapthings[i].pitch = lines[j].frontsector->floorheight >> FRACBITS; + mapthings[i].args[0] = lines[j].dx >> FRACBITS; + mapthings[i].args[1] = mapthings[i].extrainfo; + mapthings[i].args[3] = lines[j].dy >> FRACBITS; + mapthings[i].args[4] = sides[lines[j].sidenum[0]].textureoffset >> FRACBITS; + mapthings[i].args[7] = -sides[lines[j].sidenum[0]].rowoffset >> FRACBITS; + if (lines[j].backsector) + { + mapthings[i].roll = lines[j].backsector->ceilingheight >> FRACBITS; + mapthings[i].args[2] = sides[lines[j].sidenum[1]].rowoffset >> FRACBITS; + mapthings[i].args[5] = lines[j].backsector->floorheight >> FRACBITS; + mapthings[i].args[6] = sides[lines[j].sidenum[1]].textureoffset >> FRACBITS; + } + if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[8] |= TMM_DOUBLESIZE; + if (mapthings[i].options & MTF_OBJECTSPECIAL) + mapthings[i].args[8] |= TMM_SILENT; + if (lines[j].flags & ML_NOCLIMB) + mapthings[i].args[8] |= TMM_ALLOWYAWCONTROL; + if (lines[j].flags & ML_EFFECT1) + mapthings[i].args[8] |= TMM_SWING; + if (lines[j].flags & ML_EFFECT2) + mapthings[i].args[8] |= TMM_MACELINKS; + if (lines[j].flags & ML_EFFECT3) + mapthings[i].args[8] |= TMM_CENTERLINK; + if (lines[j].flags & ML_EFFECT4) + mapthings[i].args[8] |= TMM_CLIP; + if (lines[j].flags & ML_EFFECT5) + mapthings[i].args[8] |= TMM_ALWAYSTHINK; + if (mapthings[i].type == 1110) + { + mobjtype_t mobjtype = (mobjtype_t)sides[lines[j].sidenum[0]].toptexture; + char buffer[12]; + sprintf(buffer, "%d", mobjtype); + mapthings[i].stringargs[0] = Z_Malloc(strlen(buffer) + 1, PU_LEVEL, NULL); + M_Memcpy(mapthings[i].stringargs[0], buffer, strlen(buffer) + 1); + + mobjtype = (lines[j].backsector) ? (mobjtype_t)sides[lines[j].sidenum[1]].toptexture : MT_NULL; + sprintf(buffer, "%d", mobjtype); + mapthings[i].stringargs[1] = Z_Malloc(strlen(buffer) + 1, PU_LEVEL, NULL); + M_Memcpy(mapthings[i].stringargs[1], buffer, strlen(buffer) + 1); + } + break; + } case 1202: //Rock spawner { mtag_t tag = (mtag_t)mapthings[i].angle; diff --git a/src/p_spec.h b/src/p_spec.h index 054f2daf5..94bd079b6 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -24,6 +24,18 @@ extern mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs // Amount (dx, dy) vector linedef is shifted right to get scroll amount #define SCROLL_SHIFT 5 +typedef enum +{ + TMM_DOUBLESIZE = 1, + TMM_SILENT = 1<<1, + TMM_ALLOWYAWCONTROL = 1<<2, + TMM_SWING = 1<<3, + TMM_MACELINKS = 1<<4, + TMM_CENTERLINK = 1<<5, + TMM_CLIP = 1<<6, + TMM_ALWAYSTHINK = 1<<7, +} textmapmaceflags_t; + //FOF flags typedef enum { From fa92ed2a8b6e2ffa598d5ffedfee966e4348ae8b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Dec 2021 19:08:59 +0100 Subject: [PATCH 190/326] Add a wrapper function for writing a constant into a string arg --- src/p_setup.c | 50 ++++++++++++++------------------------------------ 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index cfcf0047c..aecb4fe4d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3138,6 +3138,14 @@ static void P_AddBinaryMapTags(void) } } +static void P_WriteConstant(INT32 constant, char **target) +{ + char buffer[12]; + sprintf(buffer, "%d", constant); + *target = Z_Malloc(strlen(buffer) + 1, PU_LEVEL, NULL); + M_Memcpy(*target, buffer, strlen(buffer) + 1); +} + //For maps in binary format, converts setup of specials to UDMF format. static void P_ConvertBinaryMap(void) { @@ -3612,12 +3620,7 @@ static void P_ConvertBinaryMap(void) lines[i].args[2] = 16; } if (lines[i].flags & ML_EFFECT4) - { - char buffer[6]; - sprintf(buffer, "%d", sides[lines[i].sidenum[0]].textureoffset >> FRACBITS); - lines[i].stringargs[0] = Z_Malloc(strlen(buffer) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], buffer, strlen(buffer) + 1); - } + P_WriteConstant(sides[lines[i].sidenum[0]].textureoffset >> FRACBITS, &lines[i].stringargs[0]); break; case 252: //FOF: Shatter block case 253: //FOF: Shatter block, translucent @@ -4237,16 +4240,8 @@ static void P_ConvertBinaryMap(void) lines[i].stringargs[1] = Z_Malloc(strlen(sides[lines[i].sidenum[1]].text) + 1, PU_LEVEL, NULL); M_Memcpy(lines[i].stringargs[1], sides[lines[i].sidenum[1]].text, strlen(sides[lines[i].sidenum[1]].text) + 1); } - else if (lines[i].flags & ML_NOCLIMB) // 'Infinite' - { - lines[i].stringargs[1] = Z_Malloc(3, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[1], "-1", 3); - } else - { - lines[i].stringargs[1] = Z_Malloc(7, PU_LEVEL, NULL); - snprintf(lines[i].stringargs[1], 7, "%d", sides[lines[i].sidenum[0]].textureoffset >> FRACBITS); - } + P_WriteConstant((lines[i].flags & ML_NOCLIMB) ? -1 : (sides[lines[i].sidenum[0]].textureoffset >> FRACBITS), &lines[i].stringargs[1]); break; case 435: //Change plane scroller direction lines[i].args[0] = tag; @@ -4856,7 +4851,7 @@ static void P_ConvertBinaryMap(void) { switch (mapthings[i].type) { - case 762: + case 762: //PolyObject spawn point (crush) { INT32 check = -1; INT32 firstline = -1; @@ -4925,16 +4920,8 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[8] |= TMM_ALWAYSTHINK; if (mapthings[i].type == 1110) { - mobjtype_t mobjtype = (mobjtype_t)sides[lines[j].sidenum[0]].toptexture; - char buffer[12]; - sprintf(buffer, "%d", mobjtype); - mapthings[i].stringargs[0] = Z_Malloc(strlen(buffer) + 1, PU_LEVEL, NULL); - M_Memcpy(mapthings[i].stringargs[0], buffer, strlen(buffer) + 1); - - mobjtype = (lines[j].backsector) ? (mobjtype_t)sides[lines[j].sidenum[1]].toptexture : MT_NULL; - sprintf(buffer, "%d", mobjtype); - mapthings[i].stringargs[1] = Z_Malloc(strlen(buffer) + 1, PU_LEVEL, NULL); - M_Memcpy(mapthings[i].stringargs[1], buffer, strlen(buffer) + 1); + P_WriteConstant(sides[lines[j].sidenum[0]].toptexture, &mapthings[i].stringargs[0]); + P_WriteConstant(lines[j].backsector ? sides[lines[j].sidenum[1]].toptexture : MT_NULL, &mapthings[i].stringargs[1]); } break; } @@ -4942,7 +4929,6 @@ static void P_ConvertBinaryMap(void) { mtag_t tag = (mtag_t)mapthings[i].angle; INT32 j = Tag_FindLineSpecial(12, tag); - INT32 typeoffset; if (j == -1) { @@ -4953,15 +4939,7 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[0] = P_AproxDistance(lines[j].dx, lines[j].dy) >> FRACBITS; mapthings[i].args[1] = sides[lines[j].sidenum[0]].textureoffset >> FRACBITS; mapthings[i].args[2] = !!(lines[j].flags & ML_NOCLIMB); - typeoffset = sides[lines[j].sidenum[0]].rowoffset >> FRACBITS; - if (typeoffset < 0 || typeoffset > 15) - { - CONS_Debug(DBG_GAMELOGIC, "Rock spawner: Invalid Y offset %d (tag %d)!\n", typeoffset, tag); - break; - } - - mapthings[i].stringargs[0] = Z_Malloc(17, PU_LEVEL, NULL); - sprintf(mapthings[i].stringargs[0], "MT_ROCKCRUMBLE%d", typeoffset + 1); + P_WriteConstant(MT_ROCKCRUMBLE1 + (sides[lines[j].sidenum[0]].rowoffset >> FRACBITS), &mapthings[i].stringargs[0]); break; } default: From add371a1ce2fecb1a273aad00c849ab0b17c1e74 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Dec 2021 19:48:05 +0100 Subject: [PATCH 191/326] Add UDMF thing types to UDB config --- extras/conf/udb/Includes/SRB222_common.cfg | 12 + extras/conf/udb/Includes/SRB222_misc.cfg | 47 + extras/conf/udb/Includes/SRB222_things.cfg | 9384 +++++++++++++------- extras/conf/udb/SRB2_22Doom.cfg | 6 - extras/conf/udb/SRB2_22UDMF.cfg | 6 - 5 files changed, 6463 insertions(+), 2992 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg index d67835aeb..d5cf5a405 100644 --- a/extras/conf/udb/Includes/SRB222_common.cfg +++ b/extras/conf/udb/Includes/SRB222_common.cfg @@ -191,6 +191,12 @@ mapformat_doom // that make the same thing appear in the same modes thingflagsmask1 = 7; // 1 + 2 + 4 thingflagsmask2 = 0; + + // THING TYPES + thingtypes + { + include("SRB222_things.cfg", "doom"); + } } mapformat_udmf @@ -289,6 +295,12 @@ mapformat_udmf include("UDMF_misc.cfg", "thingflagscompare"); } + // THING TYPES + thingtypes + { + include("SRB222_things.cfg", "udmf"); + } + // LINEDEF TYPES linedeftypes { diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index f27e5408c..2111c198b 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -280,6 +280,41 @@ universalfields thing { + arg5 + { + type = 0; + default = 0; + } + arg6 + { + type = 0; + default = 0; + } + arg7 + { + type = 0; + default = 0; + } + arg8 + { + type = 0; + default = 0; + } + arg9 + { + type = 0; + default = 0; + } + stringarg0 + { + type = 2; + default = ""; + } + stringarg1 + { + type = 2; + default = ""; + } } } @@ -535,6 +570,18 @@ enums 3 = "Doesn't have all"; 4 = "Doesn't have any"; } + + maceflags + { + 1 = "Double size"; + 2 = "No sounds"; + 4 = "Player-turnable chain"; + 8 = "Swing instead of spin"; + 16 = "Make chain from end item"; + 32 = "Spawn link at origin"; + 64 = "Clip inside ground"; + 128 = "No distance check"; + } } //Default things filters diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 113c1a4c2..007196959 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3,3140 +3,6564 @@ // 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 +doom { - 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; - sprite = "PLAYA0"; - - 1 + editor { - 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"; + color = 15; // White + arrow = 1; + title = ""; + error = -1; width = 8; - height = 28; + height = 16; + sort = 1; + + 3328 = "3D Mode Start"; } - 103 + + starts { - title = "Buzz (Gold)"; - sprite = "BUZZA1"; - width = 28; - height = 40; - } - 104 - { - title = "Buzz (Red)"; - sprite = "RBUZA1"; - width = 28; - height = 40; - } - 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; - } - 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; - } - 138 - { - title = "Banpyura"; - sprite = "CR2BA0"; - width = 24; - height = 32; - } - 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"; + color = 1; // Blue + arrow = 1; + title = "Player Starts"; width = 16; height = 48; - } - 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; - } - 136 - { - title = "Pyre Fly"; - sprite = "PYREA0"; - width = 24; - height = 34; - } - 137 - { - title = "Dragonbomber"; - sprite = "DRABA1"; - width = 28; - height = 48; - } - 105 - { - title = "Jetty-Syn Bomber"; - sprite = "JETBB1"; - width = 20; - height = 50; - } - 106 - { - title = "Jetty-Syn Gunner"; - sprite = "JETGB1"; - width = 20; - height = 48; - } - 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; - } - 133 - { - title = "Hangster"; - sprite = "HBATC1"; - width = 24; - height = 24; - hangs = 1; - } - 127 - { - title = "Hive Elemental"; - sprite = "HIVEA0"; - width = 32; - height = 80; - } - 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; - } -} + sprite = "PLAYA0"; -bosses -{ - color = 8; // Dark_Gray - arrow = 1; - title = "Bosses"; + 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"; + } + } - 200 + enemies { - title = "Egg Mobile"; - sprite = "EGGMA1"; - width = 24; - height = 76; - } - 201 - { - title = "Egg Slimer"; - sprite = "EGGNA1"; - width = 24; - height = 76; - } - 202 - { - title = "Sea Egg"; - sprite = "EGGOA1"; - width = 32; - height = 116; - } - 203 - { - title = "Egg Colosseum"; - sprite = "EGGPA1"; - width = 24; - height = 76; - } - 204 - { - title = "Fang"; - sprite = "FANGA1"; - width = 24; - height = 60; - } - 206 - { - title = "Brak Eggman (Old)"; - sprite = "BRAKB1"; - width = 48; - height = 160; - } - 207 - { - title = "Metal Sonic (Race)"; - sprite = "METLI1"; - width = 16; - height = 48; - } - 208 - { - title = "Metal Sonic (Battle)"; - sprite = "METLC1"; - width = 16; - height = 48; - } - 209 - { - title = "Brak Eggman"; - sprite = "BRAK01"; - width = 48; - height = 160; - } - 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; - sprite = "internal:eggmanway"; - } - 293 - { - title = "Metal Sonic Gather Point"; - sprite = "internal:metal"; - width = 8; - height = 16; - } - 294 - { - title = "Fang Waypoint"; - sprite = "internal:eggmanway"; - width = 8; - height = 16; - } -} + color = 9; // Light_Blue + arrow = 1; + title = "Enemies"; -rings -{ - color = 14; // Yellow - title = "Rings and Weapon Panels"; - width = 24; - height = 24; - sprite = "RINGA0"; + 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; + } + 103 + { + title = "Buzz (Gold)"; + sprite = "BUZZA1"; + width = 28; + height = 40; + } + 104 + { + title = "Buzz (Red)"; + sprite = "RBUZA1"; + width = 28; + height = 40; + } + 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; + } + 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; + } + 138 + { + title = "Banpyura"; + sprite = "CR2BA0"; + width = 24; + height = 32; + } + 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; + } + 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; + } + 136 + { + title = "Pyre Fly"; + sprite = "PYREA0"; + width = 24; + height = 34; + } + 137 + { + title = "Dragonbomber"; + sprite = "DRABA1"; + width = 28; + height = 48; + } + 105 + { + title = "Jetty-Syn Bomber"; + sprite = "JETBB1"; + width = 20; + height = 50; + } + 106 + { + title = "Jetty-Syn Gunner"; + sprite = "JETGB1"; + width = 20; + height = 48; + } + 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; + } + 133 + { + title = "Hangster"; + sprite = "HBATC1"; + width = 24; + height = 24; + hangs = 1; + } + 127 + { + title = "Hive Elemental"; + sprite = "HIVEA0"; + width = 32; + height = 80; + } + 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; + } + } - 300 + bosses { - title = "Ring"; + color = 8; // Dark_Gray + arrow = 1; + title = "Bosses"; + + 200 + { + title = "Egg Mobile"; + sprite = "EGGMA1"; + width = 24; + height = 76; + } + 201 + { + title = "Egg Slimer"; + sprite = "EGGNA1"; + width = 24; + height = 76; + } + 202 + { + title = "Sea Egg"; + sprite = "EGGOA1"; + width = 32; + height = 116; + } + 203 + { + title = "Egg Colosseum"; + sprite = "EGGPA1"; + width = 24; + height = 76; + } + 204 + { + title = "Fang"; + sprite = "FANGA1"; + width = 24; + height = 60; + } + 206 + { + title = "Brak Eggman (Old)"; + sprite = "BRAKB1"; + width = 48; + height = 160; + } + 207 + { + title = "Metal Sonic (Race)"; + sprite = "METLI1"; + width = 16; + height = 48; + } + 208 + { + title = "Metal Sonic (Battle)"; + sprite = "METLC1"; + width = 16; + height = 48; + } + 209 + { + title = "Brak Eggman"; + sprite = "BRAK01"; + width = 48; + height = 160; + } + 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; + sprite = "internal:eggmanway"; + } + 293 + { + title = "Metal Sonic Gather Point"; + sprite = "internal:metal"; + width = 8; + height = 16; + } + 294 + { + title = "Fang Waypoint"; + sprite = "internal:eggmanway"; + width = 8; + height = 16; + } + } + + rings + { + color = 14; // Yellow + title = "Rings and Weapon Panels"; + width = 24; + height = 24; 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"; + 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"; + } + } - 310 + collectibles { - 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"; + color = 10; // Light_Green + title = "Other Collectibles"; width = 16; height = 32; - } - 313 - { - title = "Chaos Emerald 1 (Green)"; + sort = 1; 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"; - } - 322 - { - title = "Emblem"; - sprite = "EMBMA0"; - width = 16; - height = 30; - } -} -boxes -{ - color = 7; // Gray - blocking = 2; - title = "Monitors"; - width = 18; - height = 40; + 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; + } + 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"; + } + 322 + { + title = "Emblem"; + sprite = "EMBMA0"; + width = 16; + height = 30; + } + } - 400 + boxes { - 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"; - } - 410 - { - title = "Eggman"; - sprite = "TVEGA0"; - } - 411 - { - title = "Teleporter"; - sprite = "TVMXA0"; - } - 413 - { - title = "Gravity Boots"; - sprite = "TVGVA0"; - } - 414 - { - title = "CTF Team Ring Monitor (Red)"; - sprite = "TRRIA0"; - } - 415 - { - title = "CTF Team Ring Monitor (Blue)"; - sprite = "TBRIA0"; - } - 416 - { - title = "Recycler"; - sprite = "TVRCA0"; - } - 418 - { - title = "Score (1,000 Points)"; - sprite = "TV1KA0"; - } - 419 - { - title = "Score (10,000 Points)"; - sprite = "TVTKA0"; - } - 420 - { - title = "Flame Shield"; - sprite = "TVFLA0"; - } - 421 - { - title = "Water Shield"; - sprite = "TVBBA0"; - } - 422 - { - title = "Lightning Shield"; - sprite = "TVZPA0"; - } -} + color = 7; // Gray + blocking = 2; + title = "Monitors"; + width = 18; + height = 40; -boxes2 -{ - color = 18; // Gold - blocking = 2; - title = "Monitors (Respawning)"; - width = 20; - height = 44; + 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"; + } + 410 + { + title = "Eggman"; + sprite = "TVEGA0"; + } + 411 + { + title = "Teleporter"; + sprite = "TVMXA0"; + } + 413 + { + title = "Gravity Boots"; + sprite = "TVGVA0"; + } + 414 + { + title = "CTF Team Ring Monitor (Red)"; + sprite = "TRRIA0"; + } + 415 + { + title = "CTF Team Ring Monitor (Blue)"; + sprite = "TBRIA0"; + } + 416 + { + title = "Recycler"; + sprite = "TVRCA0"; + } + 418 + { + title = "Score (1,000 Points)"; + sprite = "TV1KA0"; + } + 419 + { + title = "Score (10,000 Points)"; + sprite = "TVTKA0"; + } + 420 + { + title = "Flame Shield"; + sprite = "TVFLA0"; + } + 421 + { + title = "Water Shield"; + sprite = "TVBBA0"; + } + 422 + { + title = "Lightning Shield"; + sprite = "TVZPA0"; + } + } - 431 + boxes2 { - 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"; - } -} + color = 18; // Gold + blocking = 2; + title = "Monitors (Respawning)"; + width = 20; + height = 44; -generic -{ - color = 11; // Light_Cyan - title = "Generic Items & Hazards"; + 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"; + } + } - 500 + generic { - title = "Air Bubble Patch"; - sprite = "BUBLE0"; - width = 8; + color = 11; // Light_Cyan + title = "Generic Items & Hazards"; + + 500 + { + title = "Air Bubble Patch"; + sprite = "BUBLE0"; + width = 8; + height = 16; + } + 501 + { + title = "Signpost"; + sprite = "SIGND0"; + width = 8; + height = 32; + } + 502 + { + arrow = 1; + title = "Star Post"; + sprite = "STPTA0M0"; + width = 64; + height = 128; + } + 520 + { + title = "Bomb Sphere"; + sprite = "SPHRD0"; + width = 16; + height = 24; + } + 521 + { + title = "Spikeball"; + sprite = "SPIKA0"; + width = 12; + height = 8; + } + 522 + { + title = "Wall Spike"; + sprite = "WSPKALAR"; + width = 16; + height = 14; + arrow = 1; + } + 523 + { + title = "Spike"; + sprite = "USPKA0"; + width = 8; + height = 32; + } + 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; - } - 501 - { - title = "Signpost"; - sprite = "SIGND0"; - width = 8; - height = 32; - } - 502 - { - arrow = 1; - title = "Star Post"; - sprite = "STPTA0M0"; - width = 64; - height = 128; - } - 520 - { - title = "Bomb Sphere"; - sprite = "SPHRD0"; - width = 16; - height = 24; - } - 521 - { - title = "Spikeball"; - sprite = "SPIKA0"; - width = 12; - height = 8; - } - 522 - { - title = "Wall Spike"; - sprite = "WSPKALAR"; - width = 16; - height = 14; - arrow = 1; - } - 523 - { - title = "Spike"; - sprite = "USPKA0"; - width = 8; - height = 32; - } - 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; - } - 541 - { - title = "Gas Jet"; - sprite = "STEMD0"; - width = 32; - } - 542 - { - title = "Bumper"; - sprite = "BUMPA0"; - width = 32; - height = 64; - } - 543 - { - title = "Balloon"; - sprite = "BLONA0"; - width = 32; - height = 64; - } - 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; - } - 556 - { - arrow = 1; - title = "Diagonal Red Spring"; sprite = "RSPRD2"; - width = 16; - } - 557 - { - arrow = 1; - title = "Diagonal Blue Spring"; - sprite = "BSPRD2"; - width = 16; - } - 558 - { - arrow = 1; - title = "Horizontal Yellow Spring"; - sprite = "SSWYD2D8"; - width = 16; - height = 32; - } - 559 - { - arrow = 1; - title = "Horizontal Red Spring"; - sprite = "SSWRD2D8"; - width = 16; - height = 32; - } - 560 - { - arrow = 1; - title = "Horizontal Blue Spring"; - sprite = "SSWBD2D8"; - 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"; - width = 28; - height = 2; - } - 545 - { - arrow = 1; - title = "Red Boost Panel"; - sprite = "BSTRA0"; - width = 28; - height = 2; - } -} -patterns -{ - color = 5; // Magenta - arrow = 1; - title = "Special Placement Patterns"; - width = 16; - height = 384; - sprite = "RINGA0"; + 540 + { + title = "Fan"; + sprite = "FANSA0D0"; + width = 16; + height = 8; + } + 541 + { + title = "Gas Jet"; + sprite = "STEMD0"; + width = 32; + } + 542 + { + title = "Bumper"; + sprite = "BUMPA0"; + width = 32; + height = 64; + } + 543 + { + title = "Balloon"; + sprite = "BLONA0"; + width = 32; + height = 64; + } + 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; + } + 556 + { + arrow = 1; + title = "Diagonal Red Spring"; + sprite = "RSPRD2"; + width = 16; + } + 557 + { + arrow = 1; + title = "Diagonal Blue Spring"; + sprite = "BSPRD2"; + width = 16; + } + 558 + { + arrow = 1; + title = "Horizontal Yellow Spring"; + sprite = "SSWYD2D8"; + width = 16; + height = 32; + } + 559 + { + arrow = 1; + title = "Horizontal Red Spring"; + sprite = "SSWRD2D8"; + width = 16; + height = 32; + } + 560 + { + arrow = 1; + title = "Horizontal Blue Spring"; + sprite = "SSWBD2D8"; + 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"; + width = 28; + height = 2; + } + 545 + { + arrow = 1; + title = "Red Boost Panel"; + sprite = "BSTRA0"; + width = 28; + height = 2; + } + } - 600 + patterns { - arrow = 0; - title = "5 Vertical Rings (Yellow Spring)"; + color = 5; // Magenta + arrow = 1; + title = "Special Placement Patterns"; + width = 16; + height = 384; 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; - } - 605 - { - title = "Circle of Rings (Big)"; - sprite = "RINGA0"; - width = 192; - } - 606 - { - title = "Circle of Blue Spheres"; - sprite = "SPHRA0"; - width = 96; - height = 192; - } - 607 - { - title = "Circle of Blue Spheres (Big)"; - sprite = "SPHRA0"; - width = 192; - } - 608 - { - title = "Circle of Rings and Spheres"; - sprite = "SPHRA0"; - width = 96; - height = 192; - } - 609 - { - title = "Circle of Rings and Spheres (Big)"; - sprite = "SPHRA0"; - width = 192; - } -} -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"; + 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; + } + 605 + { + title = "Circle of Rings (Big)"; + sprite = "RINGA0"; + width = 192; + } + 606 + { + title = "Circle of Blue Spheres"; + sprite = "SPHRA0"; + width = 96; + height = 192; + } + 607 + { + title = "Circle of Blue Spheres (Big)"; + sprite = "SPHRA0"; + width = 192; + } + 608 + { + title = "Circle of Rings and Spheres"; + sprite = "SPHRA0"; + width = 96; + height = 192; + } + 609 + { + title = "Circle of Rings and Spheres (Big)"; + sprite = "SPHRA0"; + width = 192; + } } - 701 + invisible { - title = "Water Ambience B (Large)"; - sprite = "internal:ambiance"; + 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"; + } + + 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"; + } + + 754 + { + title = "Push Point"; + sprite = "GWLGA0"; + } + 755 + { + title = "Pull Point"; + sprite = "GWLRA0"; + } + 756 + { + title = "Blast Linedef Executor"; + sprite = "TOADA0"; + width = 32; + height = 16; + } + 757 + { + title = "Fan Particle Generator"; + sprite = "PRTLA0"; + width = 8; + height = 16; + } + 758 + { + title = "Object Angle Anchor"; + sprite = "internal:view"; + } + 760 + { + title = "PolyObject Anchor"; + sprite = "internal:polyanchor"; + } + 761 + { + title = "PolyObject Spawn Point"; + sprite = "internal:polycenter"; + } + 762 + { + title = "PolyObject Spawn Point (Crush)"; + sprite = "internal:polycentercrush"; + } + 780 + { + title = "Skybox View Point"; + sprite = "internal:skyb"; + } } - 702 + greenflower { - title = "Water Ambience C (Medium)"; - sprite = "internal:ambiance"; + 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; + } } - 703 + technohill { - title = "Water Ambience D (Medium)"; - sprite = "internal:ambiance"; + 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; + } } - 704 + deepsea { - title = "Water Ambience E (Small)"; - sprite = "internal:ambiance"; + color = 10; // Green + title = "Deep Sea"; + + 1000 + { + arrow = 1; + blocking = 2; + title = "Gargoyle"; + sprite = "GARGA1"; + width = 16; + height = 40; + } + 1009 + { + arrow = 1; + blocking = 2; + title = "Gargoyle (Big)"; + sprite = "GARGB1"; + width = 32; + height = 80; + } + 1001 + { + title = "Seaweed"; + sprite = "SEWEA0"; + width = 24; + height = 56; + } + 1002 + { + title = "Dripping Water"; + sprite = "DRIPD0"; + width = 8; + height = 16; + hangs = 1; + } + 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; + } + 1008 + { + title = "Stalagmite (DSZ1)"; + sprite = "DSTGA0"; + width = 8; + height = 116; + } + 1010 + { + arrow = 1; + title = "Light Beam"; + sprite = "LIBEARAL"; + width = 16; + height = 16; + } + 1011 + { + title = "Stalagmite (DSZ2)"; + sprite = "DSTGA0"; + width = 8; + height = 116; + } + 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; + } } - 705 + castleeggman { - title = "Water Ambience F (Small)"; - sprite = "internal:ambiance"; + 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; + } + 1102 + { + arrow = 1; + blocking = 2; + title = "Eggman Statue"; + sprite = "ESTAA1"; + width = 32; + height = 240; + } + 1103 + { + title = "CEZ Flower"; + sprite = "FWR4A0"; + width = 16; + height = 40; + } + 1104 + { + title = "Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + } + 1105 + { + title = "Chain with Maces Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + } + 1106 + { + title = "Chained Spring Spawnpoint"; + sprite = "YSPBA0"; + width = 17; + height = 34; + } + 1107 + { + title = "Chain Spawnpoint"; + sprite = "BMCHA0"; + width = 17; + height = 34; + } + 1108 + { + arrow = 1; + title = "Hidden Chain Spawnpoint"; + sprite = "internal:chain3"; + width = 17; + height = 34; + } + 1109 + { + title = "Firebar Spawnpoint"; + sprite = "BFBRA0"; + width = 17; + height = 34; + } + 1110 + { + title = "Custom Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + } + 1111 + { + arrow = 1; + blocking = 2; + title = "Crawla Statue"; + sprite = "CSTAA1"; + width = 16; + height = 40; + } + 1112 + { + arrow = 1; + blocking = 2; + title = "Lance-a-Bot Statue"; + sprite = "CBBSA1"; + width = 32; + height = 72; + } + 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; + } + 1120 + { + title = "Candle Pricket"; + sprite = "CNDLB0"; + width = 8; + height = 176; + } + 1121 + { + title = "Flame Holder"; + sprite = "FLMHA0"; + width = 24; + height = 80; + } + 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; + } + 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; + } } - 706 + aridcanyon { - title = "Water Ambience G (Extra Large)"; - sprite = "internal:ambiance"; + color = 10; // Green + title = "Arid Canyon"; + + 1200 + { + title = "Tumbleweed (Big)"; + sprite = "BTBLA0"; + width = 24; + height = 48; + } + 1201 + { + title = "Tumbleweed (Small)"; + sprite = "STBLA0"; + width = 12; + height = 24; + } + 1202 + { + arrow = 1; + title = "Rock Spawner"; + sprite = "ROIAA0"; + width = 8; + height = 16; + } + 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; + } + 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; + } + 1230 + { + title = "Tiny Cactus"; + sprite = "CACTJ0"; + width = 13; + height = 28; + } + 1231 + { + title = "Small Cactus"; + sprite = "CACTK0"; + width = 15; + height = 60; + } } - 707 + redvolcano { - title = "Water Ambience H (Extra Large)"; - sprite = "internal:ambiance"; + color = 10; // Green + title = "Red Volcano"; + + 1300 + { + arrow = 1; + title = "Flame Jet (Horizontal)"; + sprite = "internal:flameh"; + width = 16; + height = 40; + } + 1301 + { + title = "Flame Jet (Vertical)"; + sprite = "internal:flamev"; + width = 16; + height = 40; + } + 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; + } + 1305 + { + title = "Rollout Rock"; + sprite = "PUMIA1A5"; + width = 30; + height = 60; + } + 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; + } } - 708 + botanicserenity { - 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"; - } - - 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"; - } - - 754 - { - title = "Push Point"; - sprite = "GWLGA0"; - } - 755 - { - title = "Pull Point"; - sprite = "GWLRA0"; - } - 756 - { - title = "Blast Linedef Executor"; - sprite = "TOADA0"; - width = 32; - height = 16; - } - 757 - { - title = "Fan Particle Generator"; - sprite = "PRTLA0"; - width = 8; - height = 16; - } - 758 - { - title = "Object Angle Anchor"; - sprite = "internal:view"; - } - 760 - { - title = "PolyObject Anchor"; - sprite = "internal:polyanchor"; - } - 761 - { - title = "PolyObject Spawn Point"; - sprite = "internal:polycenter"; - } - 762 - { - title = "PolyObject Spawn Point (Crush)"; - sprite = "internal:polycentercrush"; - } - 780 - { - title = "Skybox View Point"; - sprite = "internal:skyb"; - } -} - -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"; + color = 10; // Green + title = "Botanic Serenity"; 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; - } - 1009 - { - arrow = 1; - blocking = 2; - title = "Gargoyle (Big)"; - sprite = "GARGB1"; - width = 32; - height = 80; - } - 1001 - { - title = "Seaweed"; - sprite = "SEWEA0"; - width = 24; - height = 56; - } - 1002 - { - title = "Dripping Water"; - sprite = "DRIPD0"; - width = 8; - height = 16; - hangs = 1; - } - 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; - } - 1008 - { - title = "Stalagmite (DSZ1)"; - sprite = "DSTGA0"; - width = 8; - height = 116; - } - 1010 - { - arrow = 1; - title = "Light Beam"; - sprite = "LIBEARAL"; - width = 16; - height = 16; - } - 1011 - { - title = "Stalagmite (DSZ2)"; - sprite = "DSTGA0"; - width = 8; - height = 116; - } - 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; - } - 1102 - { - arrow = 1; - blocking = 2; - title = "Eggman Statue"; - sprite = "ESTAA1"; - width = 32; - height = 240; - } - 1103 - { - title = "CEZ Flower"; - sprite = "FWR4A0"; - width = 16; - height = 40; - } - 1104 - { - title = "Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1105 - { - title = "Chain with Maces Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1106 - { - title = "Chained Spring Spawnpoint"; - sprite = "YSPBA0"; - width = 17; - height = 34; - } - 1107 - { - title = "Chain Spawnpoint"; - sprite = "BMCHA0"; - width = 17; - height = 34; - } - 1108 - { - arrow = 1; - title = "Hidden Chain Spawnpoint"; - sprite = "internal:chain3"; - width = 17; - height = 34; - } - 1109 - { - title = "Firebar Spawnpoint"; - sprite = "BFBRA0"; - width = 17; - height = 34; - } - 1110 - { - title = "Custom Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1111 - { - arrow = 1; - blocking = 2; - title = "Crawla Statue"; - sprite = "CSTAA1"; - width = 16; - height = 40; - } - 1112 - { - arrow = 1; - blocking = 2; - title = "Lance-a-Bot Statue"; - sprite = "CBBSA1"; - width = 32; - height = 72; - } - 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; - } - 1120 - { - title = "Candle Pricket"; - sprite = "CNDLB0"; - width = 8; - height = 176; - } - 1121 - { - title = "Flame Holder"; - sprite = "FLMHA0"; - width = 24; - height = 80; - } - 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; - } - 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; - } - 1201 - { - title = "Tumbleweed (Small)"; - sprite = "STBLA0"; - width = 12; - height = 24; - } - 1202 - { - arrow = 1; - title = "Rock Spawner"; - sprite = "ROIAA0"; - width = 8; - height = 16; - } - 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; - } - 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; - } - 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; - } - 1301 - { - title = "Flame Jet (Vertical)"; - sprite = "internal:flamev"; - width = 16; - height = 40; - } - 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; - } - 1305 - { - title = "Rollout Rock"; - sprite = "PUMIA1A5"; - width = 30; - height = 60; - } - 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"; + 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"; + } } - 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"; + azuretemple + { + color = 10; // Green + title = "Azure Temple"; - 1500 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle"; - sprite = "BGARA1"; - width = 16; - height = 40; + 1500 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle"; + sprite = "BGARA1"; + width = 16; + height = 40; + } + 1501 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Up)"; + sprite = "BGARA1"; + width = 16; + height = 40; + } + 1502 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Down)"; + sprite = "BGARA1"; + width = 16; + height = 40; + } + 1503 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Long)"; + sprite = "BGARA1"; + width = 16; + height = 40; + } + 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; + } } - 1501 + + dreamhill { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Up)"; - sprite = "BGARA1"; - width = 16; - height = 40; + 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; + } } - 1502 + + nightstrk { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Down)"; - sprite = "BGARA1"; - width = 16; - height = 40; - } - 1503 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Long)"; - sprite = "BGARA1"; - width = 16; - height = 40; - } - 1504 - { - title = "ATZ Target"; - sprite = "RCRYB0"; - width = 24; - height = 32; - } - 1505 - { - title = "Green Flame"; - sprite = "CFLMA0E0"; + color = 13; // Pink + title = "NiGHTS Track"; width = 8; - height = 32; + height = 4096; + sprite = "UNKNA0"; + + 1700 + { + title = "Axis"; + sprite = "internal:axis1"; + circle = 1; + } + 1701 + { + title = "Axis Transfer"; + sprite = "internal:axis2"; + } + 1702 + { + title = "Axis Transfer Line"; + sprite = "internal:axis3"; + } + 1710 + { + title = "Ideya Capture"; + sprite = "CAPSA0"; + width = 72; + height = 144; + } } - 1506 + + nights { - arrow = 1; - blocking = 2; - title = "Blue Gargoyle"; - sprite = "BGARD1"; + color = 13; // Pink + title = "NiGHTS Items"; + width = 16; + height = 32; + + 1703 + { + title = "Ideya Drone"; + sprite = "NDRNA1"; + width = 16; + height = 56; + } + 1704 + { + arrow = 1; + title = "NiGHTS Bumper"; + sprite = "NBMPG3G7"; + width = 32; + height = 64; + } + 1705 + { + arrow = 1; + title = "Hoop (Generic)"; + sprite = "HOOPA0"; + width = 80; + height = 160; + } + 1706 + { + title = "Blue Sphere"; + sprite = "SPHRA0"; + width = 16; + height = 24; + } + 1707 + { + title = "Super Paraloop"; + sprite = "NPRUA0"; + } + 1708 + { + title = "Drill Refill"; + sprite = "NPRUB0"; + } + 1709 + { + title = "Nightopian Helper"; + sprite = "NPRUC0"; + } + 1711 + { + title = "Extra Time"; + sprite = "NPRUD0"; + } + 1712 + { + title = "Link Freeze"; + sprite = "NPRUE0"; + } + 1713 + { + arrow = 1; + title = "Hoop (Customizable)"; + sprite = "HOOPA0"; + width = 80; + height = 160; + } + 1714 + { + title = "Ideya Anchor Point"; + sprite = "internal:axis1"; + width = 8; + height = 16; + } + } + + mario + { + color = 6; // Brown + title = "Mario"; + + 1800 + { + title = "Coin"; + sprite = "COINA0"; + width = 16; + height = 24; + } + 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; + } + 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; + } + 1853 + { + blocking = 2; + title = "Snowman (With Hat)"; + sprite = "XMS3B0"; + width = 16; + height = 80; + } + 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; + } + } + + stalagmites + { + color = 10; // Green + title = "Stalagmites"; width = 16; height = 40; - } -} -dreamhill -{ - color = 10; // Green - title = "Dream Hill"; + 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; + } + } - 1600 + hauntedheights { - 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; - } -} + color = 10; // Green + title = "Haunted Heights"; -nightstrk -{ - color = 13; // Pink - title = "NiGHTS Track"; - width = 8; - height = 4096; - sprite = "UNKNA0"; + 2000 + { + title = "Smashing Spikeball"; + sprite = "FMCEA0"; + width = 18; + height = 28; + } + 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; + } + 2007 + { + title = "Jack-o'-lantern 2"; + sprite = "PUMKB0"; + width = 16; + height = 40; + } + 2008 + { + title = "Jack-o'-lantern 3"; + sprite = "PUMKC0"; + width = 16; + height = 40; + } + 2009 + { + title = "Purple Mushroom"; + sprite = "SHRMD0"; + width = 16; + height = 48; + } + 2010 + { + title = "HHZ Tree"; + sprite = "HHPLC0"; + width = 12; + height = 40; + } + } - 1700 + frozenhillside { - title = "Axis"; - sprite = "internal:axis1"; - circle = 1; - } - 1701 - { - title = "Axis Transfer"; - sprite = "internal:axis2"; - } - 1702 - { - title = "Axis Transfer Line"; - sprite = "internal:axis3"; - } - 1710 - { - title = "Ideya Capture"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } -} + color = 10; // Green + title = "Frozen Hillside"; -nights -{ - color = 13; // Pink - title = "NiGHTS Items"; - width = 16; - height = 32; + 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; + } + 2105 + { + title = "Mistletoe"; + sprite = "XMS6A0"; + width = 52; + height = 106; + } + } - 1703 + flickies { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - } - 1704 - { - arrow = 1; - title = "NiGHTS Bumper"; - sprite = "NBMPG3G7"; - width = 32; - height = 64; - } - 1705 - { - arrow = 1; - title = "Hoop (Generic)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1706 - { - title = "Blue Sphere"; - sprite = "SPHRA0"; - width = 16; - height = 24; - } - 1707 - { - title = "Super Paraloop"; - sprite = "NPRUA0"; - } - 1708 - { - title = "Drill Refill"; - sprite = "NPRUB0"; - } - 1709 - { - title = "Nightopian Helper"; - sprite = "NPRUC0"; - } - 1711 - { - title = "Extra Time"; - sprite = "NPRUD0"; - } - 1712 - { - title = "Link Freeze"; - sprite = "NPRUE0"; - } - 1713 - { - arrow = 1; - title = "Hoop (Customizable)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1714 - { - title = "Ideya Anchor Point"; - sprite = "internal:axis1"; + color = 10; // Green + title = "Flickies"; width = 8; - height = 16; - } -} - -mario -{ - color = 6; // Brown - title = "Mario"; - - 1800 - { - title = "Coin"; - sprite = "COINA0"; - width = 16; - height = 24; - } - 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; - } - 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; + + 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"; + } + 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"; + } } } -christmasdisco +udmf { - 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; - } - 1853 - { - blocking = 2; - title = "Snowman (With Hat)"; - sprite = "XMS3B0"; - width = 16; - height = 80; - } - 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 + editor { + color = 15; // White arrow = 1; - blocking = 2; - title = "Eggman Disco Statue"; - sprite = "ESTAB1"; - width = 20; - height = 96; - } -} + title = ""; + error = -1; + width = 8; + height = 16; + sort = 1; -stalagmites -{ - color = 10; // Green - title = "Stalagmites"; - width = 16; - height = 40; + 3328 = "3D Mode Start"; + } - 1900 + starts { - title = "Brown Stalagmite (Tall)"; - sprite = "STLGA0"; + color = 1; // Blue + arrow = 1; + title = "Player Starts"; width = 16; - height = 40; + height = 48; + 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"; + } } - 1901 + + enemies { - title = "Brown Stalagmite"; - sprite = "STLGB0"; - width = 16; - height = 40; + 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; + } + 103 + { + title = "Buzz (Gold)"; + sprite = "BUZZA1"; + width = 28; + height = 40; + } + 104 + { + title = "Buzz (Red)"; + sprite = "RBUZA1"; + width = 28; + height = 40; + } + 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; + } + 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; + } + 138 + { + title = "Banpyura"; + sprite = "CR2BA0"; + width = 24; + height = 32; + } + 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; + } + 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; + } + 136 + { + title = "Pyre Fly"; + sprite = "PYREA0"; + width = 24; + height = 34; + } + 137 + { + title = "Dragonbomber"; + sprite = "DRABA1"; + width = 28; + height = 48; + } + 105 + { + title = "Jetty-Syn Bomber"; + sprite = "JETBB1"; + width = 20; + height = 50; + } + 106 + { + title = "Jetty-Syn Gunner"; + sprite = "JETGB1"; + width = 20; + height = 48; + } + 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; + } + 133 + { + title = "Hangster"; + sprite = "HBATC1"; + width = 24; + height = 24; + hangs = 1; + } + 127 + { + title = "Hive Elemental"; + sprite = "HIVEA0"; + width = 32; + height = 80; + } + 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; + } } - 1902 + + bosses { - title = "Orange Stalagmite (Tall)"; - sprite = "STLGC0"; - width = 16; - height = 40; + color = 8; // Dark_Gray + arrow = 1; + title = "Bosses"; + + 200 + { + title = "Egg Mobile"; + sprite = "EGGMA1"; + width = 24; + height = 76; + } + 201 + { + title = "Egg Slimer"; + sprite = "EGGNA1"; + width = 24; + height = 76; + } + 202 + { + title = "Sea Egg"; + sprite = "EGGOA1"; + width = 32; + height = 116; + } + 203 + { + title = "Egg Colosseum"; + sprite = "EGGPA1"; + width = 24; + height = 76; + } + 204 + { + title = "Fang"; + sprite = "FANGA1"; + width = 24; + height = 60; + } + 206 + { + title = "Brak Eggman (Old)"; + sprite = "BRAKB1"; + width = 48; + height = 160; + } + 207 + { + title = "Metal Sonic (Race)"; + sprite = "METLI1"; + width = 16; + height = 48; + } + 208 + { + title = "Metal Sonic (Battle)"; + sprite = "METLC1"; + width = 16; + height = 48; + } + 209 + { + title = "Brak Eggman"; + sprite = "BRAK01"; + width = 48; + height = 160; + } + 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; + sprite = "internal:eggmanway"; + } + 293 + { + title = "Metal Sonic Gather Point"; + sprite = "internal:metal"; + width = 8; + height = 16; + } + 294 + { + title = "Fang Waypoint"; + sprite = "internal:eggmanway"; + width = 8; + height = 16; + } } - 1903 + + rings { - 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"; + color = 14; // Yellow + title = "Rings and Weapon Panels"; 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; - } -} + height = 24; + sprite = "RINGA0"; -hauntedheights -{ - color = 10; // Green - title = "Haunted Heights"; + 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"; + } + } - 2000 + collectibles { - title = "Smashing Spikeball"; - sprite = "FMCEA0"; + 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; + } + 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"; + } + 322 + { + title = "Emblem"; + sprite = "EMBMA0"; + width = 16; + height = 30; + } + } + + boxes + { + color = 7; // Gray + blocking = 2; + title = "Monitors"; width = 18; - height = 28; - } - 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; - } - 2007 - { - title = "Jack-o'-lantern 2"; - sprite = "PUMKB0"; - width = 16; - height = 40; - } - 2008 - { - title = "Jack-o'-lantern 3"; - sprite = "PUMKC0"; - width = 16; - height = 40; - } - 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"; + 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"; + } + 410 + { + title = "Eggman"; + sprite = "TVEGA0"; + } + 411 + { + title = "Teleporter"; + sprite = "TVMXA0"; + } + 413 + { + title = "Gravity Boots"; + sprite = "TVGVA0"; + } + 414 + { + title = "CTF Team Ring Monitor (Red)"; + sprite = "TRRIA0"; + } + 415 + { + title = "CTF Team Ring Monitor (Blue)"; + sprite = "TBRIA0"; + } + 416 + { + title = "Recycler"; + sprite = "TVRCA0"; + } + 418 + { + title = "Score (1,000 Points)"; + sprite = "TV1KA0"; + } + 419 + { + title = "Score (10,000 Points)"; + sprite = "TVTKA0"; + } + 420 + { + title = "Flame Shield"; + sprite = "TVFLA0"; + } + 421 + { + title = "Water Shield"; + sprite = "TVBBA0"; + } + 422 + { + title = "Lightning Shield"; + sprite = "TVZPA0"; + } + } - 2100 + boxes2 { - 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"; + color = 18; // Gold + blocking = 2; + title = "Monitors (Respawning)"; width = 20; - height = 200; + height = 44; + + 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"; + } } - 2103 + + generic { - title = "Crystal Tree (Pink)"; - sprite = "TRE3B0"; + color = 11; // Light_Cyan + title = "Generic Items & Hazards"; + + 500 + { + title = "Air Bubble Patch"; + sprite = "BUBLE0"; + width = 8; + height = 16; + } + 501 + { + title = "Signpost"; + sprite = "SIGND0"; + width = 8; + height = 32; + } + 502 + { + arrow = 1; + title = "Star Post"; + sprite = "STPTA0M0"; + width = 64; + height = 128; + } + 520 + { + title = "Bomb Sphere"; + sprite = "SPHRD0"; + width = 16; + height = 24; + } + 521 + { + title = "Spikeball"; + sprite = "SPIKA0"; + width = 12; + height = 8; + } + 522 + { + title = "Wall Spike"; + sprite = "WSPKALAR"; + width = 16; + height = 14; + arrow = 1; + } + 523 + { + title = "Spike"; + sprite = "USPKA0"; + width = 8; + height = 32; + } + 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 = 200; + height = 16; + sprite = "RSPRD2"; + + 540 + { + title = "Fan"; + sprite = "FANSA0D0"; + width = 16; + height = 8; + } + 541 + { + title = "Gas Jet"; + sprite = "STEMD0"; + width = 32; + } + 542 + { + title = "Bumper"; + sprite = "BUMPA0"; + width = 32; + height = 64; + } + 543 + { + title = "Balloon"; + sprite = "BLONA0"; + width = 32; + height = 64; + } + 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; + } + 556 + { + arrow = 1; + title = "Diagonal Red Spring"; + sprite = "RSPRD2"; + width = 16; + } + 557 + { + arrow = 1; + title = "Diagonal Blue Spring"; + sprite = "BSPRD2"; + width = 16; + } + 558 + { + arrow = 1; + title = "Horizontal Yellow Spring"; + sprite = "SSWYD2D8"; + width = 16; + height = 32; + } + 559 + { + arrow = 1; + title = "Horizontal Red Spring"; + sprite = "SSWRD2D8"; + width = 16; + height = 32; + } + 560 + { + arrow = 1; + title = "Horizontal Blue Spring"; + sprite = "SSWBD2D8"; + 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"; + width = 28; + height = 2; + } + 545 + { + arrow = 1; + title = "Red Boost Panel"; + sprite = "BSTRA0"; + width = 28; + height = 2; + } } - 2104 + + patterns { - title = "Amy Cameo"; - sprite = "ROSYA1"; + color = 5; // Magenta + arrow = 1; + title = "Special Placement Patterns"; width = 16; - height = 48; - } - 2105 - { - title = "Mistletoe"; - sprite = "XMS6A0"; - width = 52; - height = 106; - } -} + height = 384; + sprite = "RINGA0"; -flickies -{ - color = 10; // Green - title = "Flickies"; - width = 8; - height = 20; + 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; + } + 605 + { + title = "Circle of Rings (Big)"; + sprite = "RINGA0"; + width = 192; + } + 606 + { + title = "Circle of Blue Spheres"; + sprite = "SPHRA0"; + width = 96; + height = 192; + } + 607 + { + title = "Circle of Blue Spheres (Big)"; + sprite = "SPHRA0"; + width = 192; + } + 608 + { + title = "Circle of Rings and Spheres"; + sprite = "SPHRA0"; + width = 96; + height = 192; + } + 609 + { + title = "Circle of Rings and Spheres (Big)"; + sprite = "SPHRA0"; + width = 192; + } + } - 2200 + invisible { - title = "Bluebird"; - sprite = "FL01A1"; + 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"; + } + + 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"; + } + + 754 + { + title = "Push Point"; + sprite = "GWLGA0"; + } + 755 + { + title = "Pull Point"; + sprite = "GWLRA0"; + } + 756 + { + title = "Blast Linedef Executor"; + sprite = "TOADA0"; + width = 32; + height = 16; + } + 757 + { + title = "Fan Particle Generator"; + sprite = "PRTLA0"; + width = 8; + height = 16; + } + 758 + { + title = "Object Angle Anchor"; + sprite = "internal:view"; + } + 760 + { + title = "PolyObject Anchor"; + sprite = "internal:polyanchor"; + } + 761 + { + title = "PolyObject Spawn Point"; + sprite = "internal:polycenter"; + } + 762 + { + title = "PolyObject Spawn Point (Crush)"; + sprite = "internal:polycentercrush"; + } + 780 + { + title = "Skybox View Point"; + sprite = "internal:skyb"; + } } - 2201 + + greenflower { - title = "Rabbit"; - sprite = "FL02A1"; + 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; + } } - 2202 + + technohill { - title = "Chicken"; - sprite = "FL03A1"; + 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; + } } - 2203 + + deepsea { - title = "Seal"; - sprite = "FL04A1"; + color = 10; // Green + title = "Deep Sea"; + + 1000 + { + arrow = 1; + blocking = 2; + title = "Gargoyle"; + sprite = "GARGA1"; + width = 16; + height = 40; + } + 1009 + { + arrow = 1; + blocking = 2; + title = "Gargoyle (Big)"; + sprite = "GARGB1"; + width = 32; + height = 80; + } + 1001 + { + title = "Seaweed"; + sprite = "SEWEA0"; + width = 24; + height = 56; + } + 1002 + { + title = "Dripping Water"; + sprite = "DRIPD0"; + width = 8; + height = 16; + hangs = 1; + } + 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; + } + 1008 + { + title = "Stalagmite (DSZ1)"; + sprite = "DSTGA0"; + width = 8; + height = 116; + } + 1010 + { + arrow = 1; + title = "Light Beam"; + sprite = "LIBEARAL"; + width = 16; + height = 16; + } + 1011 + { + title = "Stalagmite (DSZ2)"; + sprite = "DSTGA0"; + width = 8; + height = 116; + } + 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; + } } - 2204 + + castleeggman { - title = "Pig"; - sprite = "FL05A1"; + 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; + } + 1102 + { + arrow = 1; + blocking = 2; + title = "Eggman Statue"; + sprite = "ESTAA1"; + width = 32; + height = 240; + } + 1103 + { + title = "CEZ Flower"; + sprite = "FWR4A0"; + width = 16; + height = 40; + } + 1104 + { + title = "Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of spokes"; + } + arg2 + { + title = "Width"; + } + arg3 + { + title = "Speed"; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum = "maceflags"; + } + } + 1105 + { + title = "Chain with Maces Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of spokes"; + } + arg2 + { + title = "Width"; + } + arg3 + { + title = "Speed"; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum = "maceflags"; + } + } + 1106 + { + title = "Chained Spring Spawnpoint"; + sprite = "YSPBA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of spokes"; + } + arg2 + { + title = "Width"; + } + arg3 + { + title = "Speed"; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum = "maceflags"; + } + } + 1107 + { + title = "Chain Spawnpoint"; + sprite = "BMCHA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of spokes"; + } + arg2 + { + title = "Width"; + } + arg3 + { + title = "Speed"; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum = "maceflags"; + + } + } + 1108 + { + arrow = 1; + title = "Hidden Chain Spawnpoint"; + sprite = "internal:chain3"; + width = 17; + height = 34; + } + 1109 + { + title = "Firebar Spawnpoint"; + sprite = "BFBRA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of spokes"; + } + arg2 + { + title = "Width"; + } + arg3 + { + title = "Speed"; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Double size"; + 2 = "No sounds"; + 4 = "Player-turnable chain"; + 8 = "Swing instead of spin"; + 16 = "Omit chain links"; + 32 = "Spawn link at origin"; + 64 = "Clip inside ground"; + 128 = "No distance check"; + } + } + } + 1110 + { + title = "Custom Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of spokes"; + } + arg2 + { + title = "Width"; + } + arg3 + { + title = "Speed"; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum = "maceflags"; + } + stringarg0 + { + title = "Mace object type"; + type = 2; + } + stringarg1 + { + title = "Link object type"; + type = 2; + } + } + 1111 + { + arrow = 1; + blocking = 2; + title = "Crawla Statue"; + sprite = "CSTAA1"; + width = 16; + height = 40; + } + 1112 + { + arrow = 1; + blocking = 2; + title = "Lance-a-Bot Statue"; + sprite = "CBBSA1"; + width = 32; + height = 72; + } + 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; + } + 1120 + { + title = "Candle Pricket"; + sprite = "CNDLB0"; + width = 8; + height = 176; + } + 1121 + { + title = "Flame Holder"; + sprite = "FLMHA0"; + width = 24; + height = 80; + } + 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; + } + 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; + } } - 2205 + + aridcanyon { - title = "Chipmunk"; - sprite = "FL06A1"; + color = 10; // Green + title = "Arid Canyon"; + + 1200 + { + title = "Tumbleweed (Big)"; + sprite = "BTBLA0"; + width = 24; + height = 48; + } + 1201 + { + title = "Tumbleweed (Small)"; + sprite = "STBLA0"; + width = 12; + height = 24; + } + 1202 + { + arrow = 1; + title = "Rock Spawner"; + sprite = "ROIAA0"; + width = 8; + height = 16; + arg0 + { + title = "Speed"; + } + arg1 + { + title = "Spawn interval"; + } + arg2 + { + title = "Randomize speed?"; + type = 11; + enum = "noyes"; + } + stringarg0 + { + title = "Object type"; + type = 2; + } + } + 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; + } + 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; + } + 1230 + { + title = "Tiny Cactus"; + sprite = "CACTJ0"; + width = 13; + height = 28; + } + 1231 + { + title = "Small Cactus"; + sprite = "CACTK0"; + width = 15; + height = 60; + } } - 2206 + + redvolcano { - title = "Penguin"; - sprite = "FL07A1"; + color = 10; // Green + title = "Red Volcano"; + + 1300 + { + arrow = 1; + title = "Flame Jet (Horizontal)"; + sprite = "internal:flameh"; + width = 16; + height = 40; + } + 1301 + { + title = "Flame Jet (Vertical)"; + sprite = "internal:flamev"; + width = 16; + height = 40; + } + 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; + } + 1305 + { + title = "Rollout Rock"; + sprite = "PUMIA1A5"; + width = 30; + height = 60; + } + 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; + } } - 2207 + + botanicserenity { - title = "Fish"; - sprite = "FL08A1"; + 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"; + } } - 2208 + + azuretemple { - title = "Ram"; - sprite = "FL09A1"; + color = 10; // Green + title = "Azure Temple"; + + 1500 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle"; + sprite = "BGARA1"; + width = 16; + height = 40; + } + 1501 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Up)"; + sprite = "BGARA1"; + width = 16; + height = 40; + } + 1502 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Down)"; + sprite = "BGARA1"; + width = 16; + height = 40; + } + 1503 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Long)"; + sprite = "BGARA1"; + width = 16; + height = 40; + } + 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; + } } - 2209 + + dreamhill { - title = "Puffin"; - sprite = "FL10A1"; + 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; + } } - 2210 + + nightstrk { - title = "Cow"; - sprite = "FL11A1"; + color = 13; // Pink + title = "NiGHTS Track"; + width = 8; + height = 4096; + sprite = "UNKNA0"; + + 1700 + { + title = "Axis"; + sprite = "internal:axis1"; + circle = 1; + } + 1701 + { + title = "Axis Transfer"; + sprite = "internal:axis2"; + } + 1702 + { + title = "Axis Transfer Line"; + sprite = "internal:axis3"; + } + 1710 + { + title = "Ideya Capture"; + sprite = "CAPSA0"; + width = 72; + height = 144; + } } - 2211 + + nights { - title = "Rat"; - sprite = "FL12A1"; + color = 13; // Pink + title = "NiGHTS Items"; + width = 16; + height = 32; + + 1703 + { + title = "Ideya Drone"; + sprite = "NDRNA1"; + width = 16; + height = 56; + } + 1704 + { + arrow = 1; + title = "NiGHTS Bumper"; + sprite = "NBMPG3G7"; + width = 32; + height = 64; + } + 1705 + { + arrow = 1; + title = "Hoop (Generic)"; + sprite = "HOOPA0"; + width = 80; + height = 160; + } + 1706 + { + title = "Blue Sphere"; + sprite = "SPHRA0"; + width = 16; + height = 24; + } + 1707 + { + title = "Super Paraloop"; + sprite = "NPRUA0"; + } + 1708 + { + title = "Drill Refill"; + sprite = "NPRUB0"; + } + 1709 + { + title = "Nightopian Helper"; + sprite = "NPRUC0"; + } + 1711 + { + title = "Extra Time"; + sprite = "NPRUD0"; + } + 1712 + { + title = "Link Freeze"; + sprite = "NPRUE0"; + } + 1713 + { + arrow = 1; + title = "Hoop (Customizable)"; + sprite = "HOOPA0"; + width = 80; + height = 160; + } + 1714 + { + title = "Ideya Anchor Point"; + sprite = "internal:axis1"; + width = 8; + height = 16; + } } - 2212 + + mario { - title = "Bear"; - sprite = "FL13A1"; + color = 6; // Brown + title = "Mario"; + + 1800 + { + title = "Coin"; + sprite = "COINA0"; + width = 16; + height = 24; + } + 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; + } + 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; + } } - 2213 + + christmasdisco { - title = "Dove"; - sprite = "FL14A1"; + 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; + } + 1853 + { + blocking = 2; + title = "Snowman (With Hat)"; + sprite = "XMS3B0"; + width = 16; + height = 80; + } + 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; + } } - 2214 + + stalagmites { - title = "Cat"; - sprite = "FL15A1"; + 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; + } } - 2215 + + hauntedheights { - title = "Canary"; - sprite = "FL16A1"; + color = 10; // Green + title = "Haunted Heights"; + + 2000 + { + title = "Smashing Spikeball"; + sprite = "FMCEA0"; + width = 18; + height = 28; + } + 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; + } + 2007 + { + title = "Jack-o'-lantern 2"; + sprite = "PUMKB0"; + width = 16; + height = 40; + } + 2008 + { + title = "Jack-o'-lantern 3"; + sprite = "PUMKC0"; + width = 16; + height = 40; + } + 2009 + { + title = "Purple Mushroom"; + sprite = "SHRMD0"; + width = 16; + height = 48; + } + 2010 + { + title = "HHZ Tree"; + sprite = "HHPLC0"; + width = 12; + height = 40; + } } - 2216 + + frozenhillside { - title = "Spider"; - sprite = "FS01A1"; + 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; + } + 2105 + { + title = "Mistletoe"; + sprite = "XMS6A0"; + width = 52; + height = 106; + } } - 2217 + + flickies { - title = "Bat"; - sprite = "FS02A0"; + color = 10; // Green + title = "Flickies"; + width = 8; + height = 20; + + 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"; + } + 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/udb/SRB2_22Doom.cfg b/extras/conf/udb/SRB2_22Doom.cfg index 891b9d507..9e733aa39 100644 --- a/extras/conf/udb/SRB2_22Doom.cfg +++ b/extras/conf/udb/SRB2_22Doom.cfg @@ -25,12 +25,6 @@ scriptlumpnames include("Includes\\SRB222_misc.cfg", "scriptlumpnames"); } -// THING TYPES -thingtypes -{ - include("Includes\\SRB222_things.cfg"); -} - //Default things filters thingsfilters { diff --git a/extras/conf/udb/SRB2_22UDMF.cfg b/extras/conf/udb/SRB2_22UDMF.cfg index 749cf499a..b6bd22478 100644 --- a/extras/conf/udb/SRB2_22UDMF.cfg +++ b/extras/conf/udb/SRB2_22UDMF.cfg @@ -25,12 +25,6 @@ scriptlumpnames include("Includes\\SRB222_misc.cfg", "scriptlumpnames"); } -// THING TYPES -thingtypes -{ - include("Includes\\SRB222_things.cfg"); -} - //Default things filters thingsfilters { From 2a2d70e7cf061446ac379a3e3d9d1f0732a4d64b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 14 Dec 2021 20:29:14 +0100 Subject: [PATCH 192/326] Refactor some onconveyor stuff --- src/p_user.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 4858c6ddd..011a23215 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -5574,6 +5574,22 @@ INT32 P_GetPlayerControlDirection(player_t *player) return 1; // Controls pointing in player's general direction } +static boolean P_ShouldResetConveyorMomentum(player_t *player) +{ + switch (player->onconveyor) + { + case 1: + return false; + case 2: // Wind/Current + return !(player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)); + case 3: + default: + return true; + case 4: // Actual conveyor belt + return !P_IsObjectOnGround(player->mo); + } +} + // Control scheme for 2d levels. static void P_2dMovement(player_t *player) { @@ -5608,16 +5624,7 @@ static void P_2dMovement(player_t *player) } } - // cmomx/cmomy stands for the conveyor belt speed. - if (player->onconveyor == 2) // Wind/Current - { - //if (player->mo->z > player->mo->watertop || player->mo->z + player->mo->height < player->mo->waterbottom) - if (!(player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) - player->cmomx = player->cmomy = 0; - } - else if (player->onconveyor == 4 && !P_IsObjectOnGround(player->mo)) // Actual conveyor belt - player->cmomx = player->cmomy = 0; - else if (player->onconveyor != 2 && player->onconveyor != 4 && player->onconveyor != 1) + if (P_ShouldResetConveyorMomentum(player)) player->cmomx = player->cmomy = 0; player->rmomx = player->mo->momx - player->cmomx; @@ -5800,16 +5807,7 @@ static void P_3dMovement(player_t *player) } movepushsideangle = movepushangle-ANGLE_90; - // cmomx/cmomy stands for the conveyor belt speed. - if (player->onconveyor == 2) // Wind/Current - { - //if (player->mo->z > player->mo->watertop || player->mo->z + player->mo->height < player->mo->waterbottom) - if (!(player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) - player->cmomx = player->cmomy = 0; - } - else if (player->onconveyor == 4 && !P_IsObjectOnGround(player->mo)) // Actual conveyor belt - player->cmomx = player->cmomy = 0; - else if (player->onconveyor != 2 && player->onconveyor != 4 && player->onconveyor != 1) + if (P_ShouldResetConveyorMomentum(player)) player->cmomx = player->cmomy = 0; player->rmomx = player->mo->momx - player->cmomx; From ebf692f1432307fd9e79897914fc2d0669586cb0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 16 Dec 2021 07:00:30 +0100 Subject: [PATCH 193/326] Adapt push/pull point to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 26 +- src/info.c | 28 -- src/info.h | 1 - src/p_mobj.c | 127 ++++++++- src/p_saveg.c | 38 --- src/p_setup.c | 57 ++++ src/p_spec.c | 287 +-------------------- src/p_spec.h | 23 +- src/p_tick.c | 8 +- 9 files changed, 216 insertions(+), 379 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 007196959..dd8e353eb 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4504,13 +4504,27 @@ udmf 754 { - title = "Push Point"; + title = "Push/Pull Point"; sprite = "GWLGA0"; - } - 755 - { - title = "Pull Point"; - sprite = "GWLRA0"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Strength"; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Fade using XY"; + 2 = "Push using XYZ"; + 4 = "Non-exclusive"; + } + } } 756 { diff --git a/src/info.c b/src/info.c index f56e5d78e..f44659bda 100644 --- a/src/info.c +++ b/src/info.c @@ -20713,34 +20713,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - // for use with wind and current effects - { // MT_PULL - 755, // doomednum - S_INVISIBLE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 8, // radius - 8, // height - 0, // display offset - 10, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - { // MT_GHOST -1, // doomednum S_THOK, // spawnstate diff --git a/src/info.h b/src/info.h index 031a08b43..28965f4b3 100644 --- a/src/info.h +++ b/src/info.h @@ -5046,7 +5046,6 @@ typedef enum mobj_type MT_CRUMBLEOBJ, // Sound generator for crumbling platform MT_TUBEWAYPOINT, MT_PUSH, - MT_PULL, MT_GHOST, MT_OVERLAY, MT_ANGLEMAN, diff --git a/src/p_mobj.c b/src/p_mobj.c index 5b4feb3ca..cf4e2ad6e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9234,6 +9234,118 @@ static void P_DragonbomberThink(mobj_t *mobj) #undef DRAGONTURNSPEED } +static mobj_t *pushmobj; + +#define PUSH_FACTOR 7 + +static inline boolean PIT_PushThing(mobj_t *thing) +{ + if (thing->eflags & MFE_PUSHED) + return false; + + if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG) + return false; + + if (!pushmobj) + return false; + + if (!pushmobj->spawnpoint) + return false; + + // Allow this to affect pushable objects at some point? + if (thing->player && !(thing->flags & (MF_NOGRAVITY|MF_NOCLIP))) + { + INT32 dist; + INT32 speed; + INT32 sx = pushmobj->x; + INT32 sy = pushmobj->y; + INT32 sz = pushmobj->z; + fixed_t radius = pushmobj->spawnpoint->args[0] << FRACBITS; + + if (pushmobj->spawnpoint->args[2] & TMPP_NOZFADE) + dist = P_AproxDistance(thing->x - sx, thing->y - sy); + else + { + // Make sure the Z is in range + if (thing->z < sz - radius || thing->z > sz + radius) + return false; + + dist = P_AproxDistance(P_AproxDistance(thing->x - sx, thing->y - sy), thing->z - sz); + } + + speed = (abs(pushmobj->spawnpoint->args[1]) - ((dist>>FRACBITS)>>1))<<(FRACBITS - PUSH_FACTOR - 1); + + // If speed <= 0, you're outside the effective radius. You also have + // to be able to see the push/pull source point. + + // Written with bits and pieces of P_HomingAttack + if ((speed > 0) && (P_CheckSight(thing, pushmobj))) + { + fixed_t tmpmomx, tmpmomy, tmpmomz; + + if (pushmobj->spawnpoint->args[2] & TMPP_PUSHZ) + { + tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed); + tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed); + tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed); + } + else + { + angle_t pushangle = R_PointToAngle2(thing->x, thing->y, sx, sy) >> ANGLETOFINESHIFT; + tmpmomx = FixedMul(speed, FINECOSINE(pushangle)); + tmpmomy = FixedMul(speed, FINESINE(pushangle)); + tmpmomz = 0; + } + + if (pushmobj->spawnpoint->args[1] > 0) // away! + { + tmpmomx *= -1; + tmpmomy *= -1; + tmpmomz *= -1; + } + + thing->momx += tmpmomx; + thing->momy += tmpmomy; + thing->momz += tmpmomz; + + if (thing->player) + { + thing->player->cmomx += tmpmomx; + thing->player->cmomy += tmpmomy; + thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); + thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); + } + } + } + + if (!(pushmobj->spawnpoint->args[2] & TMPP_NONEXCLUSIVE)) + thing->eflags |= MFE_PUSHED; + + return true; +} + +static void P_PointPushThink(mobj_t *mobj) +{ + INT32 xl, xh, yl, yh, bx, by; + fixed_t radius; + + if (!mobj->spawnpoint) + return; + + // Seek out all pushable things within the force radius of this + // point pusher. Crosses sectors, so use blockmap. + radius = mobj->spawnpoint->args[0] << FRACBITS; + + pushmobj = mobj; + xl = (unsigned)(mobj->x - radius - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (unsigned)(mobj->x + radius - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (unsigned)(mobj->y - radius - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (unsigned)(mobj->y + radius - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + P_BlockThingsIterator(bx, by, PIT_PushThing); +} + static boolean P_MobjRegularThink(mobj_t *mobj) { if ((mobj->flags & MF_ENEMY) && (mobj->state->nextstate == mobj->info->spawnstate && mobj->tics == 1)) @@ -9721,6 +9833,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) else mobj->rollangle = R_PointToAngle2(0, 0, mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1)); break; + case MT_PUSH: + P_PointPushThink(mobj); + break; case MT_SPINFIRE: if (mobj->flags & MF_NOGRAVITY) { @@ -12956,18 +13071,6 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean blueflag = mobj; bflagpoint = mobj->spawnpoint; break; - case MT_PUSH: - case MT_PULL: - mobj->health = 0; // Default behaviour: pushing uses XY, fading uses XYZ - - if (mthing->options & MTF_AMBUSH) - mobj->health |= 1; // If ambush is set, push using XYZ - if (mthing->options & MTF_OBJECTSPECIAL) - mobj->health |= 2; // If object special is set, fade using XY - - 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); diff --git a/src/p_saveg.c b/src/p_saveg.c index bc9c31d64..689fa4d95 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1537,7 +1537,6 @@ typedef enum tc_scroll, tc_friction, tc_pusher, - tc_pointpusher, tc_laserflash, tc_lightfade, tc_executor, @@ -2191,19 +2190,6 @@ static inline void SavePusherThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->slider); } -static inline void SavePointPusherThinker(const thinker_t* th, const UINT8 type) -{ - const pointpusher_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->magnitude); - WRITEINT32(save_p, ht->radius); - WRITEINT32(save_p, ht->x); - WRITEINT32(save_p, ht->y); - WRITEINT32(save_p, ht->z); - WRITEINT32(save_p, ht->affectee); - WRITEINT32(save_p, ht->exclusive); -} - static void SaveLaserThinker(const thinker_t *th, const UINT8 type) { const laserthink_t *ht = (const void *)th; @@ -2523,11 +2509,6 @@ static void P_NetArchiveThinkers(void) SavePusherThinker(th, tc_pusher); continue; } - else if (th->function.acp1 == (actionf_p1)T_PointPusher) - { - SavePointPusherThinker(th, tc_pointpusher); - continue; - } else if (th->function.acp1 == (actionf_p1)T_BounceCheese) { SaveBounceCheeseThinker(th, tc_bouncecheese); @@ -3344,21 +3325,6 @@ static thinker_t* LoadPusherThinker(actionf_p1 thinker) return &ht->thinker; } -static thinker_t* LoadPointPusherThinker(actionf_p1 thinker) -{ - pointpusher_t *ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->magnitude = READINT32(save_p); - ht->radius = READINT32(save_p); - ht->x = READINT32(save_p); - ht->y = READINT32(save_p); - ht->z = READINT32(save_p); - ht->affectee = READINT32(save_p); - ht->exclusive = READINT32(save_p); - ht->source = P_GetPushThing(ht->affectee); - return &ht->thinker; -} - static inline thinker_t* LoadLaserThinker(actionf_p1 thinker) { laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); @@ -3821,10 +3787,6 @@ static void P_NetUnArchiveThinkers(void) th = LoadPusherThinker((actionf_p1)T_Pusher); break; - case tc_pointpusher: - th = LoadPointPusherThinker((actionf_p1)T_PointPusher); - break; - default: I_Error("P_UnarchiveSpecials: Unknown tclass %d in savegame", tclass); } diff --git a/src/p_setup.c b/src/p_setup.c index aecb4fe4d..ce4c764e4 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3146,6 +3146,28 @@ static void P_WriteConstant(INT32 constant, char **target) M_Memcpy(*target, buffer, strlen(buffer) + 1); } +static line_t *P_FindPointPushLine(taglist_t *list) +{ + INT32 i, l; + + for (i = 0; i < list->count; i++) + { + mtag_t tag = list->tags[i]; + TAG_ITER_LINES(tag, l) + { + if (Tag_FGet(&lines[l].tags) != tag) + continue; + + if (lines[l].special != 547) + continue; + + return &lines[l]; + } + } + + return NULL; +} + //For maps in binary format, converts setup of specials to UDMF format. static void P_ConvertBinaryMap(void) { @@ -4851,6 +4873,41 @@ static void P_ConvertBinaryMap(void) { switch (mapthings[i].type) { + case 754: //Push point + case 755: //Pull point + { + subsector_t *ss = R_PointInSubsector(mapthings[i].x << FRACBITS, mapthings[i].y << FRACBITS); + sector_t *s; + line_t *line; + + if (!ss) + { + CONS_Debug(DBG_GAMELOGIC, "Push/pull point: Placed outside of map bounds!\n"); + break; + } + + s = ss->sector; + line = P_FindPointPushLine(&s->tags); + + if (!line) + { + CONS_Debug(DBG_GAMELOGIC, "Push/pull point: Unable to find line of type 547 tagged to sector %s!\n", sizeu1((size_t)(s - sectors))); + break; + } + + mapthings[i].args[0] = mapthings[i].angle; + mapthings[i].args[1] = P_AproxDistance(line->dx >> FRACBITS, line->dy >> FRACBITS); + if (mapthings[i].type == 755) + mapthings[i].args[1] *= -1; + if (mapthings[i].options & MTF_OBJECTSPECIAL) + mapthings[i].args[2] |= TMPP_NOZFADE; + if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[2] |= TMPP_PUSHZ; + if (!(line->flags & ML_NOCLIMB)) + mapthings[i].args[2] |= TMPP_NONEXCLUSIVE; + mapthings[i].type = 754; + break; + } case 762: //PolyObject spawn point (crush) { INT32 check = -1; diff --git a/src/p_spec.c b/src/p_spec.c index a1eb4183c..deb915eeb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -98,7 +98,6 @@ typedef struct static void P_SpawnScrollers(void); static void P_SpawnFriction(void); static void P_SpawnPushers(void); -static void Add_PointPusher(INT32 magnitude, mobj_t *source, INT32 affectee, INT32 exclusive); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, fixed_t z_mag, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); @@ -5331,7 +5330,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I thinker_t *th; friction_t *f; pusher_t *p; - pointpusher_t *pp; size_t sec2num; size_t i; @@ -5442,13 +5440,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I if (p->affectee == (INT32)sec2num) Add_Pusher(p->type, p->x_mag, p->y_mag, p->z_mag, (INT32)(sec-sectors), p->affectee, p->exclusive, p->slider); } - else if (th->function.acp1 == (actionf_p1)T_PointPusher) - { - pp = (pointpusher_t *)th; - - if (pp->affectee == (INT32)sec2num) - Add_PointPusher(pp->magnitude, pp->source, pp->affectee, pp->exclusive); - } if(secthinkers) i++; else th = th->next; @@ -6024,8 +6015,6 @@ void P_SpawnSpecials(boolean fromnetsave) secthinkers[((friction_t *)th)->affectee].count++; else if (th->function.acp1 == (actionf_p1)T_Pusher) secthinkers[((pusher_t *)th)->affectee].count++; - else if (th->function.acp1 == (actionf_p1)T_PointPusher) - secthinkers[((pointpusher_t *)th)->affectee].count++; } // Allocate each list, and then zero the count so we can use it to track @@ -6046,8 +6035,6 @@ void P_SpawnSpecials(boolean fromnetsave) secnum = ((friction_t *)th)->affectee; else if (th->function.acp1 == (actionf_p1)T_Pusher) secnum = ((pusher_t *)th)->affectee; - else if (th->function.acp1 == (actionf_p1)T_PointPusher) - secnum = ((pointpusher_t *)th)->affectee; if (secnum != (size_t)-1) secthinkers[secnum].thinkers[secthinkers[secnum].count++] = th; @@ -8328,26 +8315,6 @@ static void P_SpawnFriction(void) #define PUSH_FACTOR 7 -static void Add_PointPusher(INT32 magnitude, mobj_t *source, INT32 affectee, INT32 exclusive) -{ - pointpusher_t *p = Z_Calloc(sizeof * p, PU_LEVSPEC, NULL); - - p->thinker.function.acp1 = (actionf_p1)T_PointPusher; - p->source = source; - p->magnitude = magnitude; - p->exclusive = exclusive; - - if (source) // point source exist? - { - p->radius = AngleFixed(source->angle); - p->x = p->source->x; - p->y = p->source->y; - p->z = p->source->z; - } - p->affectee = affectee; - P_AddThinker(THINK_MAIN, &p->thinker); -} - /** Adds a pusher. * * \param type Type of push/pull effect. @@ -8382,187 +8349,6 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, fixed_t P_AddThinker(THINK_MAIN, &p->thinker); } -// PIT_PushThing determines the angle and magnitude of the effect. -// The object's x and y momentum values are changed. -static pointpusher_t *tmpusher; // pointpusher structure for blockmap searches - -/** Applies a point pusher/puller to a thing. - * - * \param thing Thing to be pushed. - * \return True if the thing was pushed. - * \todo Make a more robust P_BlockThingsIterator() so the hidden parameter - * ::tmpusher won't need to be used. - * \sa T_Pusher - */ -static inline boolean PIT_PushThing(mobj_t *thing) -{ - if (thing->eflags & MFE_PUSHED) - return false; - - if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG) - return false; - - if (!tmpusher->source) - return false; - - // Allow this to affect pushable objects at some point? - if (thing->player && (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) || thing->player->powers[pw_carry] == CR_NIGHTSMODE)) - { - INT32 dist; - INT32 speed; - INT32 sx, sy, sz; - - sx = tmpusher->x; - sy = tmpusher->y; - sz = tmpusher->z; - - // don't fade wrt Z if health & 2 (mapthing has multi flag) - if (tmpusher->source->health & 2) - dist = P_AproxDistance(thing->x - sx,thing->y - sy); - else - { - // Make sure the Z is in range - if (thing->z < sz - tmpusher->radius || thing->z > sz + tmpusher->radius) - return false; - - dist = P_AproxDistance(P_AproxDistance(thing->x - sx, thing->y - sy), - thing->z - sz); - } - - speed = (tmpusher->magnitude - ((dist>>FRACBITS)>>1))<<(FRACBITS - PUSH_FACTOR - 1); - - // If speed <= 0, you're outside the effective radius. You also have - // to be able to see the push/pull source point. - - // Written with bits and pieces of P_HomingAttack - if ((speed > 0) && (P_CheckSight(thing, tmpusher->source))) - { - if (thing->player->powers[pw_carry] != CR_NIGHTSMODE) - { - // only push wrt Z if health & 1 (mapthing has ambush flag) - if (tmpusher->source->health & 1) - { - fixed_t tmpmomx, tmpmomy, tmpmomz; - - tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed); - tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed); - tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed); - if (tmpusher->source->type == MT_PUSH) // away! - { - tmpmomx *= -1; - tmpmomy *= -1; - tmpmomz *= -1; - } - - thing->momx += tmpmomx; - thing->momy += tmpmomy; - thing->momz += tmpmomz; - - if (thing->player) - { - thing->player->cmomx += tmpmomx; - thing->player->cmomy += tmpmomy; - thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); - thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); - } - } - else - { - angle_t pushangle; - - pushangle = R_PointToAngle2(thing->x, thing->y, sx, sy); - if (tmpusher->source->type == MT_PUSH) - pushangle += ANGLE_180; // away - pushangle >>= ANGLETOFINESHIFT; - thing->momx += FixedMul(speed, FINECOSINE(pushangle)); - thing->momy += FixedMul(speed, FINESINE(pushangle)); - - if (thing->player) - { - thing->player->cmomx += FixedMul(speed, FINECOSINE(pushangle)); - thing->player->cmomy += FixedMul(speed, FINESINE(pushangle)); - thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); - thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); - } - } - } - else - { - //NiGHTS-specific handling. - //By default, pushes and pulls only affect the Z-axis. - //By having the ambush flag, it affects the X-axis. - //By having the object special flag, it affects the Y-axis. - fixed_t tmpmomx, tmpmomy, tmpmomz; - - if (tmpusher->source->health & 1) - tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed); - else - tmpmomx = 0; - - if (tmpusher->source->health & 2) - tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed); - else - tmpmomy = 0; - - tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed); - - if (tmpusher->source->type == MT_PUSH) // away! - { - tmpmomx *= -1; - tmpmomy *= -1; - tmpmomz *= -1; - } - - thing->momx += tmpmomx; - thing->momy += tmpmomy; - thing->momz += tmpmomz; - - if (thing->player) - { - thing->player->cmomx += tmpmomx; - thing->player->cmomy += tmpmomy; - thing->player->cmomx = FixedMul(thing->player->cmomx, 0xe800); - thing->player->cmomy = FixedMul(thing->player->cmomy, 0xe800); - } - } - } - } - - if (tmpusher->exclusive) - thing->eflags |= MFE_PUSHED; - - return true; -} - -void T_PointPusher(pointpusher_t *p) -{ - INT32 xl, xh, yl, yh, bx, by; - sector_t *sec = sectors + p->affectee; - - // Be sure the special sector type is still turned on. If so, proceed. - // Else, bail out; the sector type has been changed on us. - - if (GETSECSPECIAL(sec->special, 3) != 2) - return; - - // Seek out all pushable things within the force radius of this - // point pusher. Crosses sectors, so use blockmap. - - tmpusher = p; // MT_PUSH/MT_PULL point source - tmbbox[BOXTOP] = p->y + p->radius; - tmbbox[BOXBOTTOM] = p->y - p->radius; - tmbbox[BOXRIGHT] = p->x + p->radius; - tmbbox[BOXLEFT] = p->x - p->radius; - - xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - P_BlockThingsIterator(bx, by, PIT_PushThing); -} - /** Applies a pusher to all affected objects. * * \param p Thinker for the pusher effect. @@ -8751,78 +8537,33 @@ void T_Pusher(pusher_t *p) } } - -/** Gets a push/pull object. - * - * \param s Sector number to look in. - * \return Pointer to the first ::MT_PUSH or ::MT_PULL object found in the - * sector. - * \sa P_GetTeleportDestThing, P_GetStarpostThing, P_GetAltViewThing - */ -mobj_t *P_GetPushThing(UINT32 s) -{ - mobj_t *thing; - sector_t *sec; - - sec = sectors + s; - thing = sec->thinglist; - while (thing) - { - switch (thing->type) - { - case MT_PUSH: - case MT_PULL: - return thing; - default: - break; - } - thing = thing->snext; - } - return NULL; -} - /** Spawns pushers. * - * \todo Remove magic numbers. * \sa P_SpawnSpecials, Add_Pusher */ static void P_SpawnPushers(void) { size_t i; line_t *l = lines; - mtag_t tag; register INT32 s; - mobj_t *thing; + fixed_t length, hspeed, dx, dy; for (i = 0; i < numlines; i++, l++) { - tag = Tag_FGet(&l->tags); - switch (l->special) - { - case 541: // wind/current - { - fixed_t length = R_PointToDist2(l->v2->x, l->v2->y, l->v1->x, l->v1->y); - fixed_t hspeed = l->args[1] << FRACBITS; - fixed_t dx = FixedMul(FixedDiv(l->dx, length), hspeed); - fixed_t dy = FixedMul(FixedDiv(l->dy, length), hspeed); + if (l->special != 541) + continue; - if (l->args[0] == 0) - Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, (INT32)(l->frontsector - sectors), -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE)); - else - { - TAG_ITER_SECTORS(l->args[0], s) - Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, s, -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE)); - } - break; - } - case 547: // push/pull - TAG_ITER_SECTORS(tag, s) - { - thing = P_GetPushThing(s); - if (thing) // No MT_P* means no effect - Add_PointPusher(P_AproxDistance(l->dx >> FRACBITS, l->dy >> FRACBITS), thing, s, l->flags & ML_NOCLIMB); - } - break; + length = R_PointToDist2(l->v2->x, l->v2->y, l->v1->x, l->v1->y); + hspeed = l->args[1] << FRACBITS; + dx = FixedMul(FixedDiv(l->dx, length), hspeed); + dy = FixedMul(FixedDiv(l->dy, length), hspeed); + + if (l->args[0] == 0) + Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, (INT32)(l->frontsector - sectors), -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE)); + else + { + TAG_ITER_SECTORS(l->args[0], s) + Add_Pusher(l->args[3], dx, dy, l->args[2] << FRACBITS, s, -1, !(l->args[4] & TMPF_NONEXCLUSIVE), !!(l->args[4] & TMPF_SLIDE)); } } } diff --git a/src/p_spec.h b/src/p_spec.h index 94bd079b6..8e210b543 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -343,6 +343,14 @@ typedef enum TMPF_NONEXCLUSIVE = 1<<1, } textmappusherflags_t; + +typedef enum +{ + TMPP_NOZFADE = 1, + TMPP_PUSHZ = 1<<1, + TMPP_NONEXCLUSIVE = 1<<2, +} textmappointpushflags_t; + // GETSECSPECIAL (specialval, section) // // Pulls out the special # from a particular section. @@ -874,17 +882,6 @@ typedef struct INT32 slider; /// < Should the player go into an uncontrollable slide? } pusher_t; -typedef struct -{ - thinker_t thinker; ///< Thinker structure for push/pull effect. - mobj_t *source; ///< Point source. - INT32 magnitude; ///< Vector strength. - INT32 radius; ///< Effective radius. - INT32 x, y, z; ///< Point source. - INT32 affectee; ///< Number of affected sector. - INT32 exclusive; /// < Once this affect has been applied to a mobj, no other pushers may affect it. -} pointpusher_t; - // Model for disappearing/reappearing FOFs typedef struct { @@ -941,10 +938,8 @@ typedef struct void T_FadeColormap(fadecolormap_t *d); -// Prototype functions for pushers +// Prototype function for pushers void T_Pusher(pusher_t *p); -void T_PointPusher(pointpusher_t *p); -mobj_t *P_GetPushThing(UINT32 s); // Plane displacement typedef struct diff --git a/src/p_tick.c b/src/p_tick.c index d34272045..55a16fd81 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -66,8 +66,7 @@ void Command_Numthinkers_f(void) "\t2: P_NullPrecipThinker\n" "\t3: T_Friction\n" "\t4: T_Pusher\n" - "\t5: T_PointPusher\n" - "\t6: P_RemoveThinkerDelayed\n"); + "\t5: P_RemoveThinkerDelayed\n"); return; } @@ -104,11 +103,6 @@ void Command_Numthinkers_f(void) CONS_Printf(M_GetText("Number of %s: "), "T_Pusher"); break; case 5: - start = end = THINK_MAIN; - action = (actionf_p1)T_PointPusher; - CONS_Printf(M_GetText("Number of %s: "), "T_PointPusher"); - break; - case 6: action = (actionf_p1)P_RemoveThinkerDelayed; CONS_Printf(M_GetText("Number of %s: "), "P_RemoveThinkerDelayed"); break; From 1a1e5faf08eaa20f006b6c6a162da0890e52b253 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 18 Dec 2021 10:31:42 +0100 Subject: [PATCH 194/326] Adapt fan particle generator to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 11 ++++ extras/conf/udb/Includes/SRB222_things.cfg | 25 +++++++++ src/p_mobj.c | 58 ++++++++++++-------- src/p_setup.c | 18 ++++++ 4 files changed, 90 insertions(+), 22 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index d108821f7..c8b7ccf5f 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1591,6 +1591,17 @@ udmf } } + parameters + { + title = "Parameters"; + + 15 + { + title = "Fan Particle Generator Heights"; + prefix = "(15)"; + } + } + polyobject { title = "PolyObject"; diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index dd8e353eb..4d5bafb05 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4539,6 +4539,31 @@ udmf sprite = "PRTLA0"; width = 8; height = 16; + arg0 + { + title = "Particles"; + } + arg1 + { + title = "Radius"; + } + arg2 + { + title = "Rising speed"; + } + arg3 + { + title = "Rotation speed"; + type = 8; + } + arg4 + { + title = "Spawn interval"; + } + arg5 + { + title = "Rising distance"; + } } 758 { diff --git a/src/p_mobj.c b/src/p_mobj.c index cf4e2ad6e..a336a5a9e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7295,8 +7295,22 @@ static boolean P_ParticleGenSceneryThink(mobj_t *mobj) mobj->fuse = (tic_t)mobj->reactiontime; - bottomheight = lines[line].frontsector->floorheight; - topheight = lines[line].frontsector->ceilingheight - mobjinfo[(mobjtype_t)type].height; + if (line != -1) + { + bottomheight = lines[line].frontsector->floorheight; + topheight = lines[line].frontsector->ceilingheight - mobjinfo[(mobjtype_t)type].height; + } + else if (mobj->flags2 & MF2_OBJECTFLIP) + { + bottomheight = mobj->z - mobj->extravalue1; + topheight = mobj->z - mobjinfo[(mobjtype_t)type].height; + } + else + { + bottomheight = mobj->z; + topheight = mobj->z + mobj->extravalue1 - mobjinfo[(mobjtype_t)type].height; + } + if (mobj->waterbottom != bottomheight || mobj->watertop != topheight) { @@ -7305,7 +7319,8 @@ static boolean P_ParticleGenSceneryThink(mobj_t *mobj) else mobj->health = 0; - mobj->z = ((mobj->flags2 & MF2_OBJECTFLIP) ? topheight : bottomheight); + if (line != -1) + mobj->z = ((mobj->flags2 & MF2_OBJECTFLIP) ? topheight : bottomheight); } if (!mobj->health) @@ -12420,7 +12435,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj) { - fixed_t radius, speed; + fixed_t radius, speed, zdist; INT32 type, numdivisions, anglespeed, ticcount; angle_t angledivision; INT32 line; @@ -12429,41 +12444,34 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj) // Find the corresponding linedef special, using angle as tag line = Tag_FindLineSpecial(15, mthing->angle); - 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; - } + type = mthing->stringargs[0] ? get_number(mthing->stringargs[0]) : MT_PARTICLE; - 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 = mthing->args[4]; + if (ticcount < 1) ticcount = 3; - numdivisions = mthing->z; + numdivisions = mthing->args[0]; 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; + radius = mthing->args[1] << FRACBITS; + anglespeed = (mthing->args[3]) % 360; angledivision = 360/numdivisions; } else { - numdivisions = 1; // Simple trick to make A_ParticleSpawn simpler. + numdivisions = 1; // Simple trick to make P_ParticleGenSceneryThink simpler. radius = 0; anglespeed = 0; angledivision = 0; } - speed = abs(sides[lines[line].sidenum[0]].textureoffset); + speed = abs(mthing->args[2]) << FRACBITS; if (mthing->options & MTF_OBJECTFLIP) speed *= -1; + zdist = abs(mthing->args[5]) << FRACBITS; + CONS_Debug(DBG_GAMELOGIC, "Particle Generator (mapthing #%s):\n" "Radius is %d\n" "Speed is %d\n" @@ -12471,9 +12479,14 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj) "Numdivisions is %d\n" "Angledivision is %d\n" "Type is %d\n" - "Tic seperation is %d\n", + "Tic separation is %d\n", sizeu1(mthingi), radius, speed, anglespeed, numdivisions, angledivision, type, ticcount); + if (line == -1) + CONS_Debug(DBG_GAMELOGIC, "Spawn Z is %d\nZ dist is %d\n", mobj->z, zdist); + else + CONS_Debug(DBG_GAMELOGIC, "Heights are taken from control sector\n"); + mobj->angle = 0; mobj->movefactor = speed; mobj->lastlook = numdivisions; @@ -12482,6 +12495,7 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj) mobj->friction = radius; mobj->threshold = type; mobj->reactiontime = ticcount; + mobj->extravalue1 = zdist; mobj->cvmem = line; mobj->watertop = mobj->waterbottom = 0; return true; diff --git a/src/p_setup.c b/src/p_setup.c index ce4c764e4..1b1d9b85d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4908,6 +4908,24 @@ static void P_ConvertBinaryMap(void) mapthings[i].type = 754; break; } + case 757: //Fan particle generator + { + INT32 j = Tag_FindLineSpecial(15, mapthings[i].angle); + + if (j == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Particle generator (mapthing #%d) needs to be tagged to a #15 parameter line (trying to find tag %d).\n", i, mapthings[i].angle); + break; + } + mapthings[i].args[0] = mapthings[i].z; + mapthings[i].args[1] = R_PointToDist2(lines[j].v1->x, lines[j].v1->y, lines[j].v2->x, lines[j].v2->y) >> FRACBITS; + mapthings[i].args[2] = sides[lines[j].sidenum[0]].textureoffset >> FRACBITS; + mapthings[i].args[3] = sides[lines[j].sidenum[0]].rowoffset >> FRACBITS; + mapthings[i].args[4] = lines[j].backsector ? sides[lines[j].sidenum[1]].textureoffset >> FRACBITS : 0; + if (sides[lines[j].sidenum[0]].toptexture) + P_WriteConstant(sides[lines[j].sidenum[0]].toptexture, &mapthings[i].stringargs[0]); + break; + } case 762: //PolyObject spawn point (crush) { INT32 check = -1; From 482c24a1fb62824d5812852ef07a26f965ec939f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 18 Dec 2021 10:45:50 +0100 Subject: [PATCH 195/326] Adapt NiGHTS track items to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 46 ++++++++++++++++++++++ src/p_mobj.c | 20 +++++----- src/p_setup.c | 13 ++++++ 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 4d5bafb05..a0bc6f07f 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -6010,16 +6010,54 @@ udmf title = "Axis"; sprite = "internal:axis1"; circle = 1; + arg0 + { + title = "Mare"; + } + arg1 + { + title = "Order"; + } + arg2 + { + title = "Radius"; + } + arg3 + { + title = "Direction"; + type = 11; + enum + { + 0 = "Clockwise"; + 1 = "Counterclockwise"; + } + } } 1701 { title = "Axis Transfer"; sprite = "internal:axis2"; + arg0 + { + title = "Mare"; + } + arg1 + { + title = "Order"; + } } 1702 { title = "Axis Transfer Line"; sprite = "internal:axis3"; + arg0 + { + title = "Mare"; + } + arg1 + { + title = "Order"; + } } 1710 { @@ -6027,6 +6065,14 @@ udmf sprite = "CAPSA0"; width = 72; height = 144; + arg0 + { + title = "Mare"; + } + arg1 + { + title = "Required spheres"; + } } } diff --git a/src/p_mobj.c b/src/p_mobj.c index a336a5a9e..5defc9f2f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12823,11 +12823,10 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean P_SetMobjState(mobj, mobj->info->spawnstate + mobj->threshold); break; case MT_EGGCAPSULE: - if (mthing->angle <= 0) - mthing->angle = 20; // prevent 0 health - - mobj->health = mthing->angle; - mobj->threshold = min(mthing->extrainfo, 7); + mobj->threshold = min(mthing->args[0], 7); + mobj->health = mthing->args[1]; + if (mobj->health <= 0) + mobj->health = 20; // prevent 0 health break; case MT_TUBEWAYPOINT: { @@ -12940,20 +12939,19 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean return false; break; case MT_AXIS: - // Inverted if uppermost bit is set - if (mthing->angle & 16384) + // Inverted if args[3] is set + if (mthing->args[3]) mobj->flags2 |= MF2_AMBUSH; - if (mthing->angle > 0) - mobj->radius = (mthing->angle & 16383) << FRACBITS; + mobj->radius = abs(mthing->args[2]) << FRACBITS; // FALLTHRU case MT_AXISTRANSFER: case MT_AXISTRANSFERLINE: // Mare it belongs to - mobj->threshold = min(mthing->extrainfo, 7); + mobj->threshold = min(mthing->args[0], 7); // # in the mare - mobj->health = mthing->options; + mobj->health = mthing->args[1]; mobj->flags2 |= MF2_AXIS; break; diff --git a/src/p_setup.c b/src/p_setup.c index 1b1d9b85d..f1f37eb48 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5017,6 +5017,19 @@ static void P_ConvertBinaryMap(void) P_WriteConstant(MT_ROCKCRUMBLE1 + (sides[lines[j].sidenum[0]].rowoffset >> FRACBITS), &mapthings[i].stringargs[0]); break; } + case 1700: //Axis + mapthings[i].args[2] = mapthings[i].angle & 16383; + mapthings[i].args[3] = !!(mapthings[i].angle & 16384); + /* FALLTHRU */ + case 1701: //Axis transfer + case 1702: //Axis transfer line + mapthings[i].args[0] = mapthings[i].extrainfo; + mapthings[i].args[1] = mapthings[i].options; + break; + case 1710: //Ideya capture + mapthings[i].args[0] = mapthings[i].extrainfo; + mapthings[i].args[1] = mapthings[i].angle; + break; default: break; } From 59c6d59c00bb385789b1f7faebca4a3f787ea27f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 19 Dec 2021 10:16:03 +0100 Subject: [PATCH 196/326] Adapt NiGHTS things to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 18 +++++----- src/m_cheat.c | 4 +-- src/p_mobj.c | 41 +++++++--------------- src/p_saveg.c | 2 +- src/p_setup.c | 20 ++++++++++- 5 files changed, 44 insertions(+), 41 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index a0bc6f07f..cd9d360c8 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -6098,14 +6098,6 @@ udmf width = 32; height = 64; } - 1705 - { - arrow = 1; - title = "Hoop (Generic)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } 1706 { title = "Blue Sphere"; @@ -6141,10 +6133,14 @@ udmf 1713 { arrow = 1; - title = "Hoop (Customizable)"; + title = "Hoop"; sprite = "HOOPA0"; width = 80; height = 160; + arg0 + { + title = "Radius"; + } } 1714 { @@ -6152,6 +6148,10 @@ udmf sprite = "internal:axis1"; width = 8; height = 16; + arg0 + { + title = "Mare"; + } } } diff --git a/src/m_cheat.c b/src/m_cheat.c index ef896c991..52202f808 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1285,7 +1285,7 @@ void OP_NightsObjectplace(player_t *player) if (mt->type >= 600 && mt->type <= 609) // Placement patterns P_SpawnItemPattern(mt, false); - else if (mt->type == 1705 || mt->type == 1713) // NiGHTS Hoops + else if (mt->type == 1713) // NiGHTS Hoops P_SpawnHoop(mt); else P_SpawnMapThing(mt); @@ -1416,7 +1416,7 @@ void OP_ObjectplaceMovement(player_t *player) mt = OP_CreateNewMapThing(player, (UINT16)spawnthing, ceiling); if (mt->type >= 600 && mt->type <= 609) // Placement patterns P_SpawnItemPattern(mt, false); - else if (mt->type == 1705 || mt->type == 1713) // NiGHTS Hoops + else if (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 5defc9f2f..4d5784129 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11769,11 +11769,6 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt switch (mobjtype) { - // Bumpers never spawn flipped. - case MT_NIGHTSBUMPER: - flip = false; - break; - // Objects with a non-zero default height. case MT_CRAWLACOMMANDER: case MT_DETON: @@ -11883,7 +11878,7 @@ static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) } 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 + || mthing->type == 1713) // Hoops return true; // These are handled elsewhere. else if (mthing->type == mobjinfo[MT_EMERHUNT].doomednum) { @@ -12817,9 +12812,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->threshold = (TICRATE*2)-1; break; case MT_NIGHTSBUMPER: - // Lower 4 bits specify the angle of - // the bumper in 30 degree increments. - mobj->threshold = (mthing->options & 15) % 12; // It loops over, etc + // Pitch of the bumper is set in 30 degree increments. + mobj->threshold = ((mthing->pitch/30) + 3) % 12; P_SetMobjState(mobj, mobj->info->spawnstate + mobj->threshold); break; case MT_EGGCAPSULE: @@ -12838,7 +12832,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; } case MT_IDEYAANCHOR: - mobj->health = mthing->extrainfo; + mobj->health = mthing->args[0]; break; case MT_NIGHTSDRONE: if (!P_SetupNiGHTSDrone(mthing, mobj)) @@ -13258,13 +13252,18 @@ mobj_t *P_SpawnMapThing(mapthing_t *mthing) return P_SpawnMobjFromMapThing(mthing, x, y, z, i); } -static void P_SpawnHoopInternal(mapthing_t *mthing, INT32 hoopsize, fixed_t sizefactor) +void P_SpawnHoop(mapthing_t *mthing) { + if (metalrecording) + return; + mobj_t *mobj = NULL; mobj_t *nextmobj = NULL; mobj_t *hoopcenter; TMatrix *pitchmatrix, *yawmatrix; - fixed_t radius = hoopsize*sizefactor; + fixed_t radius = mthing->args[0] << FRACBITS; + fixed_t sizefactor = 4*FRACUNIT; + fixed_t hoopsize = radius/sizefactor; INT32 i; angle_t fa; TVector v, *res; @@ -13281,10 +13280,9 @@ static void P_SpawnHoopInternal(mapthing_t *mthing, INT32 hoopsize, fixed_t size hoopcenter->y = y; P_SetThingPosition(hoopcenter); - // Scale 0-255 to 0-359 =( - hoopcenter->movedir = ((mthing->angle & 255)*360)/256; // Pitch + hoopcenter->movedir = mthing->pitch; pitchmatrix = RotateXMatrix(FixedAngle(hoopcenter->movedir << FRACBITS)); - hoopcenter->movecount = (((UINT16)mthing->angle >> 8)*360)/256; // Yaw + hoopcenter->movecount = mthing->angle; yawmatrix = RotateZMatrix(FixedAngle(hoopcenter->movecount << FRACBITS)); // For the hoop when it flies away @@ -13364,19 +13362,6 @@ static void P_SpawnHoopInternal(mapthing_t *mthing, INT32 hoopsize, fixed_t size } while (hoopsize >= 8); } -void P_SpawnHoop(mapthing_t *mthing) -{ - if (metalrecording) - return; - - 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); -} - void P_SetBonusTime(mobj_t *mobj) { if (!mobj) diff --git a/src/p_saveg.c b/src/p_saveg.c index 689fa4d95..b505bdf88 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2736,7 +2736,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) { UINT16 spawnpointnum = READUINT16(save_p); - if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case + if (mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case { P_SpawnHoop(&mapthings[spawnpointnum]); return NULL; diff --git a/src/p_setup.c b/src/p_setup.c index f1f37eb48..aafe89ab3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -895,7 +895,7 @@ static void P_SpawnMapThings(boolean spawnemblems) if (mt->type >= 600 && mt->type <= 609) // item patterns P_SpawnItemPattern(mt, false); - else if (mt->type == 1705 || mt->type == 1713) // hoops + else if (mt->type == 1713) // hoops P_SpawnHoop(mt); else // Everything else P_SpawnMapThing(mt); @@ -5026,10 +5026,28 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[0] = mapthings[i].extrainfo; mapthings[i].args[1] = mapthings[i].options; break; + case 1704: //NiGHTS bumper + mapthings[i].pitch = 30 * (((mapthings[i].options & 15) + 9) % 12); + mapthings[i].options &= ~0xF; + break; + case 1705: //Hoop + case 1713: //Hoop (Customizable) + { + UINT16 oldangle = mapthings[i].angle; + mapthings[i].angle = ((oldangle >> 8)*360)/256; + mapthings[i].pitch = ((oldangle & 255)*360)/256; + mapthings[i].args[0] = (mapthings[i].type == 1705) ? 96 : (mapthings[i].options & 0xF)*16 + 32; + mapthings[i].options &= ~0xF; + mapthings[i].type = 1713; + break; + } case 1710: //Ideya capture mapthings[i].args[0] = mapthings[i].extrainfo; mapthings[i].args[1] = mapthings[i].angle; break; + case 1714: //Ideya anchor point + mapthings[i].args[0] = mapthings[i].extrainfo; + break; default: break; } From db1f2153277382861becb8bcda9014ea5842b874 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Dec 2021 21:14:39 +0100 Subject: [PATCH 197/326] Implement generic item rows and circles --- extras/conf/udb/Includes/SRB222_things.cfg | 40 ++++++++++++++++ src/m_cheat.c | 4 +- src/p_mobj.c | 56 ++++++++++++++++++++-- src/p_setup.c | 12 ++--- 4 files changed, 101 insertions(+), 11 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index cd9d360c8..86fe6b1a5 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4397,6 +4397,46 @@ udmf sprite = "SPHRA0"; width = 192; } + 610 + { + title = "Row of Items"; + sprite = "RINGA0"; + arg0 + { + title = "Number of items"; + } + arg1 + { + title = "Horizontal spacing"; + } + arg2 + { + title = "Vertical spacing"; + } + stringarg0 + { + title = "Object types"; + } + } + 611 + { + title = "Circle of Items"; + sprite = "RINGA0"; + width = 96; + height = 192; + arg0 + { + title = "Number of items"; + } + arg1 + { + title = "Radius"; + } + stringarg0 + { + title = "Object types"; + } + } } invisible diff --git a/src/m_cheat.c b/src/m_cheat.c index 52202f808..ddc1f6f29 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1283,7 +1283,7 @@ void OP_NightsObjectplace(player_t *player) mt = OP_CreateNewMapThing(player, (UINT16)cv_mapthingnum.value, false); mt->angle = angle; - if (mt->type >= 600 && mt->type <= 609) // Placement patterns + if (mt->type >= 600 && mt->type <= 611) // Placement patterns P_SpawnItemPattern(mt, false); else if (mt->type == 1713) // NiGHTS Hoops P_SpawnHoop(mt); @@ -1414,7 +1414,7 @@ void OP_ObjectplaceMovement(player_t *player) return; mt = OP_CreateNewMapThing(player, (UINT16)spawnthing, ceiling); - if (mt->type >= 600 && mt->type <= 609) // Placement patterns + if (mt->type >= 600 && mt->type <= 611) // Placement patterns P_SpawnItemPattern(mt, false); else if (mt->type == 1713) // NiGHTS Hoops P_SpawnHoop(mt); diff --git a/src/p_mobj.c b/src/p_mobj.c index 4d5784129..beed59e8f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11877,7 +11877,7 @@ static boolean P_SpawnNonMobjMapThing(mapthing_t *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 >= 600 && mthing->type <= 611) // Special placement patterns || mthing->type == 1713) // Hoops return true; // These are handled elsewhere. else if (mthing->type == mobjinfo[MT_EMERHUNT].doomednum) @@ -13373,7 +13373,7 @@ void P_SetBonusTime(mobj_t *mobj) 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) +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; mobj_t *mobj = NULL; @@ -13424,7 +13424,7 @@ static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t* itemtypes, UINT8 numi } } -static void P_SpawnSingularItemRow(mapthing_t* mthing, mobjtype_t itemtype, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle, boolean bonustime) +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); @@ -13488,6 +13488,35 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n } } +static void P_ParseItemTypes(char *itemstring, mobjtype_t *itemtypes, UINT8 *numitemtypes) +{ + char *tok; + + *numitemtypes = 0; + if (itemstring) + { + char *stringcopy = Z_Malloc(strlen(itemstring) + 1, PU_LEVEL, NULL); + M_Memcpy(stringcopy, itemstring, strlen(itemstring)); + stringcopy[strlen(itemstring)] = '\0'; + + tok = strtok(stringcopy, " "); + while (tok && *numitemtypes < 128) + { + itemtypes[*numitemtypes] = get_number(tok); + tok = strtok(NULL, " "); + (*numitemtypes)++; + } + + Z_Free(stringcopy); + } + else + { + //If no types are supplied, default to ring + itemtypes[0] = MT_RING; + *numitemtypes = 1; + } +} + void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) { switch (mthing->type) @@ -13525,6 +13554,27 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) P_SpawnItemCircle(mthing, itemtypes, 2, numitems, size, bonustime); return; } + case 610: // Generic item row + { + mobjtype_t itemtypes[128]; //If you want to have a row with more than 128 different object types, you're crazy. + UINT8 numitemtypes; + if (!udmf) + return; + P_ParseItemTypes(mthing->stringargs[0], itemtypes, &numitemtypes); + P_SpawnItemRow(mthing, itemtypes, numitemtypes, mthing->args[0], mthing->args[1] << FRACBITS, mthing->args[2] << FRACBITS, mthing->angle, bonustime); + return; + } + case 611: // Generic item circle + { + mobjtype_t itemtypes[128]; //If you want to have a circle with more than 128 different object types, you're crazy. + UINT8 numitemtypes; + if (!udmf) + return; + CONS_Printf("Itemstring: %s\n", mthing->stringargs[0]); + P_ParseItemTypes(mthing->stringargs[0], itemtypes, &numitemtypes); + P_SpawnItemCircle(mthing, itemtypes, numitemtypes, mthing->args[0], mthing->args[1] << FRACBITS, bonustime); + return; + } default: return; } diff --git a/src/p_setup.c b/src/p_setup.c index aafe89ab3..25250b449 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -734,7 +734,7 @@ void P_ReloadRings(void) mt->mobj = NULL; P_SetBonusTime(P_SpawnMapThing(mt)); } - else if (mt->type >= 600 && mt->type <= 609) // Item patterns + else if (mt->type >= 600 && mt->type <= 611) // Item patterns { mt->mobj = NULL; P_SpawnItemPattern(mt, true); @@ -893,7 +893,7 @@ static void P_SpawnMapThings(boolean spawnemblems) mt->mobj = NULL; - if (mt->type >= 600 && mt->type <= 609) // item patterns + if (mt->type >= 600 && mt->type <= 611) // item patterns P_SpawnItemPattern(mt, false); else if (mt->type == 1713) // hoops P_SpawnHoop(mt); @@ -1701,9 +1701,9 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val) P_SetLinedefV1(i, atol(val)); else if (fastcmp(param, "v2")) P_SetLinedefV2(i, atol(val)); - else if (strlen(param) == 7 && fastncmp(param, "arg", 3) && fastncmp(param + 4, "str", 3)) + else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9) { - size_t argnum = param[3] - '0'; + size_t argnum = atol(param + 9); if (argnum >= NUMLINESTRINGARGS) return; lines[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL); @@ -1800,9 +1800,9 @@ static void ParseTextmapThingParameter(UINT32 i, char *param, char *val) else if (fastcmp(param, "ambush") && fastcmp("true", val)) mapthings[i].options |= MTF_AMBUSH; - else if (strlen(param) == 7 && fastncmp(param, "arg", 3) && fastncmp(param + 4, "str", 3)) + else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9) { - size_t argnum = param[3] - '0'; + size_t argnum = atol(param + 9); if (argnum >= NUMMAPTHINGSTRINGARGS) return; mapthings[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL); From 72e2c24fdb714698f1a3c23f1c9035e5a387d3b4 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 20 Dec 2021 23:28:18 +0100 Subject: [PATCH 198/326] Adapt some reserved tags to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 15 +++++++++ src/info.c | 2 +- src/info.h | 2 ++ src/p_enemy.c | 36 +++++++++++++++++++++- src/p_inter.c | 3 +- src/p_setup.c | 9 ++++++ 6 files changed, 64 insertions(+), 3 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 86fe6b1a5..0efe006fb 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -258,6 +258,11 @@ doom sprite = "TRETA1"; width = 16; height = 32; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 111 { @@ -2704,6 +2709,11 @@ doom sprite = "KOOPA0"; width = 16; height = 48; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 1807 { @@ -2711,6 +2721,11 @@ doom sprite = "MAXEA0"; width = 8; height = 16; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 1808 { diff --git a/src/info.c b/src/info.c index f44659bda..d456d2afe 100644 --- a/src/info.c +++ b/src/info.c @@ -899,7 +899,7 @@ state_t states[NUMSTATES] = {SPR_TRET, FF_FULLBRIGHT|2, 7, {A_Pain}, 0, 0, S_TURRETSHOCK7}, // S_TURRETSHOCK6 {SPR_TRET, FF_FULLBRIGHT|3, 7, {NULL}, 0, 0, S_TURRETSHOCK8}, // S_TURRETSHOCK7 {SPR_TRET, FF_FULLBRIGHT|4, 7, {NULL}, 0, 0, S_TURRETSHOCK9}, // S_TURRETSHOCK8 - {SPR_TRET, FF_FULLBRIGHT|4, 7, {A_LinedefExecute}, LE_TURRET, 0, S_XPLD1}, // S_TURRETSHOCK9 + {SPR_TRET, FF_FULLBRIGHT|4, 7, {A_LinedefExecuteFromArg}, 0, 0, S_XPLD1}, // S_TURRETSHOCK9 {SPR_TURR, 0, 1, {A_Look}, 1, 0, S_TURRETPOPDOWN8}, // S_TURRETLOOK {SPR_TURR, 0, 0, {A_FaceTarget}, 0, 0, S_TURRETPOPUP1}, // S_TURRETSEE diff --git a/src/info.h b/src/info.h index 28965f4b3..d5fcc8504 100644 --- a/src/info.h +++ b/src/info.h @@ -150,6 +150,7 @@ enum actionnum A_BOSS3PATH, A_BOSS3SHOCKTHINK, A_LINEDEFEXECUTE, + A_LINEDEFEXECUTEFROMARG, A_PLAYSEESOUND, A_PLAYATTACKSOUND, A_PLAYACTIVESOUND, @@ -409,6 +410,7 @@ void A_Boss3TakeDamage(); void A_Boss3Path(); void A_Boss3ShockThink(); void A_LinedefExecute(); +void A_LinedefExecuteFromArg(); void A_PlaySeeSound(); void A_PlayAttackSound(); void A_PlayActiveSound(); diff --git a/src/p_enemy.c b/src/p_enemy.c index c02ca38be..a4607b497 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -173,6 +173,7 @@ void A_Boss3TakeDamage(mobj_t *actor); void A_Boss3Path(mobj_t *actor); void A_Boss3ShockThink(mobj_t *actor); void A_LinedefExecute(mobj_t *actor); +void A_LinedefExecuteFromArg(mobj_t *actor); void A_PlaySeeSound(mobj_t *actor); void A_PlayAttackSound(mobj_t *actor); void A_PlayActiveSound(mobj_t *actor); @@ -4049,7 +4050,8 @@ bossjustdie: } case MT_KOOPA: { - EV_DoCeiling(LE_KOOPA, NULL, raiseToHighest); + if (mo->spawnpoint) + EV_DoCeiling(mo->spawnpoint->args[0], NULL, raiseToHighest); return; } case MT_FANG: @@ -8307,6 +8309,38 @@ void A_LinedefExecute(mobj_t *actor) P_LinedefExecute((INT16)tagnum, actor, actor->subsector->sector); } +// Function: A_LinedefExecuteFromArg +// +// Description: Object's location is used to set the calling sector. The tag used is the spawnpoint mapthing's args[var1]. +// +// var1 = mapthing arg to take tag from +// var2 = unused +// +void A_LinedefExecuteFromArg(mobj_t *actor) +{ + INT32 tagnum; + INT32 locvar1 = var1; + + if (LUA_CallAction(A_LINEDEFEXECUTEFROMARG, actor)) + return; + + if (!actor->spawnpoint) + return; + + if (locvar1 < 0 || locvar1 > NUMMAPTHINGARGS) + { + CONS_Debug(DBG_GAMELOGIC, "A_LinedefExecuteFromArg: Invalid mapthing arg %d\n", locvar1); + return; + } + + tagnum = actor->spawnpoint->args[locvar1]; + + CONS_Debug(DBG_GAMELOGIC, "A_LinedefExecuteFromArg: Running mobjtype %d's sector with tag %d\n", actor->type, tagnum); + + // tag 32768 displayed in map editors is actually tag -32768, tag 32769 is -32767, 65535 is -1 etc. + P_LinedefExecute((INT16)tagnum, actor, actor->subsector->sector); +} + // Function: A_PlaySeeSound // // Description: Plays the object's seesound. diff --git a/src/p_inter.c b/src/p_inter.c index d84cb8ce5..62f6080bc 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1387,7 +1387,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->bot && player->bot != BOT_MPAI) return; - EV_DoElevator(LE_AXE, NULL, bridgeFall); + if (special->spawnpoint) + EV_DoElevator(special->spawnpoint->args[0], NULL, bridgeFall); // scan the remaining thinkers to find koopa for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) diff --git a/src/p_setup.c b/src/p_setup.c index 25250b449..46b47100c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4873,6 +4873,9 @@ static void P_ConvertBinaryMap(void) { switch (mapthings[i].type) { + case 110: //THZ Turret + mapthings[i].args[0] = LE_TURRET; + break; case 754: //Push point case 755: //Pull point { @@ -5048,6 +5051,12 @@ static void P_ConvertBinaryMap(void) case 1714: //Ideya anchor point mapthings[i].args[0] = mapthings[i].extrainfo; break; + case 1806: //King Bowser + mapthings[i].args[0] = LE_KOOPA; + break; + case 1807: //Axe + mapthings[i].args[0] = LE_AXE; + break; default: break; } From 3205b6d83a1b01b64eebaea2f6ce05c6594ef8e3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 08:01:51 +0100 Subject: [PATCH 199/326] Adapt player starts to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 210 +++++++++++++++++++++ src/p_mobj.c | 4 +- src/p_setup.c | 6 + 3 files changed, 218 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 0efe006fb..8ae317d89 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3187,176 +3187,386 @@ udmf { title = "Player 01 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 2 { title = "Player 02 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 3 { title = "Player 03 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 4 { title = "Player 04 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 5 { title = "Player 05 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 6 { title = "Player 06 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 7 { title = "Player 07 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 8 { title = "Player 08 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 9 { title = "Player 09 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 10 { title = "Player 10 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 11 { title = "Player 11 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 12 { title = "Player 12 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 13 { title = "Player 13 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 14 { title = "Player 14 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 15 { title = "Player 15 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 16 { title = "Player 16 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 17 { title = "Player 17 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 18 { title = "Player 18 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 19 { title = "Player 19 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 20 { title = "Player 20 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 21 { title = "Player 21 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 22 { title = "Player 22 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 23 { title = "Player 23 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 24 { title = "Player 24 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 25 { title = "Player 25 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 26 { title = "Player 26 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 27 { title = "Player 27 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 28 { title = "Player 28 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 29 { title = "Player 29 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 30 { title = "Player 30 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 31 { title = "Player 31 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 32 { title = "Player 32 Start"; sprite = "PLAYA0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 33 { title = "Match Start"; sprite = "NDRNA2A8"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 34 { title = "CTF Red Team Start"; sprite = "SIGNG0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } 35 { title = "CTF Blue Team Start"; sprite = "SIGNE0"; + arg0 + { + title = "Spawn on ceiling?"; + type = 11; + enum = "noyes"; + } } } diff --git a/src/p_mobj.c b/src/p_mobj.c index beed59e8f..c673f3971 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11643,9 +11643,9 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) { fixed_t offset = mthing->z << FRACBITS; - // Flagging a player's ambush will make them start on the ceiling + // Setting the spawnpoint's args[0] will make the player start on the ceiling // Objectflip inverts - if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP)) + if (!!(mthing->args[0]) ^ !!(mthing->options & MTF_OBJECTFLIP)) z = ceilingspawn - offset; else z = floor + offset; diff --git a/src/p_setup.c b/src/p_setup.c index 46b47100c..fc47c4573 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4871,6 +4871,12 @@ static void P_ConvertBinaryMap(void) for (i = 0; i < nummapthings; i++) { + if (mapthings[i].type >= 1 && mapthings[i].type <= 35) + { + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + continue; + } + switch (mapthings[i].type) { case 110: //THZ Turret From bfcbf5136be8689aed5e7b19e7a6aed6d19a7a90 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 17:26:55 +0100 Subject: [PATCH 200/326] Adapt SDURF and Puma to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 8 ++++++++ src/p_enemy.c | 12 ++++++++---- src/p_setup.c | 4 ++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 8ae317d89..cf6b8a875 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3596,6 +3596,10 @@ udmf sprite = "FISHA0"; width = 8; height = 28; + arg0 + { + title = "Jump strength"; + } } 103 { @@ -6468,6 +6472,10 @@ udmf sprite = "PUMAA0"; width = 8; height = 16; + arg0 + { + title = "Jump strength"; + } } 1806 { diff --git a/src/p_enemy.c b/src/p_enemy.c index a4607b497..64b21809f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4803,12 +4803,16 @@ void A_FishJump(mobj_t *actor) fixed_t jumpval; if (locvar1) - jumpval = var1; + jumpval = locvar1; else - jumpval = FixedMul(AngleFixed(actor->angle)/4, actor->scale); + { + if (actor->spawnpoint && actor->spawnpoint->args[0]) + jumpval = actor->spawnpoint->args[0]; + else + jumpval = 44; + } - if (!jumpval) jumpval = FixedMul(44*(FRACUNIT/4), actor->scale); - actor->momz = jumpval; + actor->momz = FixedMul(jumpval << (FRACBITS - 2), actor->scale); P_SetMobjStateNF(actor, actor->info->seestate); } diff --git a/src/p_setup.c b/src/p_setup.c index fc47c4573..ee29d6e10 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4879,6 +4879,10 @@ static void P_ConvertBinaryMap(void) switch (mapthings[i].type) { + case 102: //SDURF + case 1805: //Puma + mapthings[i].args[0] = mapthings[i].angle; + break; case 110: //THZ Turret mapthings[i].args[0] = LE_TURRET; break; From 7eee8b10a9995900f4d2f6a35487ac6fbec29fa9 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 17:31:29 +0100 Subject: [PATCH 201/326] Add A_LinedefExecuteFromArg to deh_tables.c --- src/deh_tables.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/deh_tables.c b/src/deh_tables.c index eda0258d6..f4074cf08 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -197,6 +197,7 @@ actionpointer_t actionpointers[] = {{A_Boss3Path}, "A_BOSS3PATH"}, {{A_Boss3ShockThink}, "A_BOSS3SHOCKTHINK"}, {{A_LinedefExecute}, "A_LINEDEFEXECUTE"}, + {{A_LinedefExecuteFromArg}, "A_LINEDEFEXECUTEFROMARG"}, {{A_PlaySeeSound}, "A_PLAYSEESOUND"}, {{A_PlayAttackSound}, "A_PLAYATTACKSOUND"}, {{A_PlayActiveSound}, "A_PLAYACTIVESOUND"}, From cbebdc219d013a54463b3e4ae074572757b1dd1c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 17:45:43 +0100 Subject: [PATCH 202/326] Adapt pop-up turret to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 4 ++++ src/p_mobj.c | 5 +---- src/p_setup.c | 3 +++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index cf6b8a875..303bfe396 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3635,6 +3635,10 @@ udmf sprite = "TURRI1"; width = 12; height = 64; + arg0 + { + title = "Firing delay"; + } } 122 { diff --git a/src/p_mobj.c b/src/p_mobj.c index c673f3971..a3e7f8f96 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12806,10 +12806,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean return false; break; case MT_POPUPTURRET: - if (mthing->angle) - mobj->threshold = mthing->angle; - else - mobj->threshold = (TICRATE*2)-1; + mobj->threshold = mthing->args[0] ? mthing->args[0] : (TICRATE*2)-1; break; case MT_NIGHTSBUMPER: // Pitch of the bumper is set in 30 degree increments. diff --git a/src/p_setup.c b/src/p_setup.c index ee29d6e10..e04de6e55 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4886,6 +4886,9 @@ static void P_ConvertBinaryMap(void) case 110: //THZ Turret mapthings[i].args[0] = LE_TURRET; break; + case 111: //Pop-up Turret + mapthings[i].args[0] = mapthings[i].angle; + break; case 754: //Push point case 755: //Pull point { From 4b58b45b5fb2c81f7541dea755f627e249169f5c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 17:58:37 +0100 Subject: [PATCH 203/326] Adapt emblem tags to UDMF --- src/p_mobj.c | 4 ++-- src/p_setup.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index a3e7f8f96..4810d3623 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12095,7 +12095,7 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) while (emblem) { - if ((emblem->type == ET_GLOBAL || emblem->type == ET_SKIN) && emblem->tag == mthing->angle) + if ((emblem->type == ET_GLOBAL || emblem->type == ET_SKIN) && emblem->tag == Tag_FGet(&mthing->tags)) break; emblem = M_GetLevelEmblems(-1); @@ -12103,7 +12103,7 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) if (!emblem) { - CONS_Debug(DBG_GAMELOGIC, "No map emblem for map %d with tag %d found!\n", gamemap, mthing->angle); + CONS_Debug(DBG_GAMELOGIC, "No map emblem for map %d with tag %d found!\n", gamemap, Tag_FGet(&mthing->tags)); return false; } diff --git a/src/p_setup.c b/src/p_setup.c index e04de6e55..ba3544d12 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3123,6 +3123,7 @@ static void P_AddBinaryMapTags(void) switch (mapthings[i].type) { case 291: + case 322: case 750: case 760: case 761: From 81bf0dceb21bd20de5896e205d8c7a4518ef433a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 18:12:38 +0100 Subject: [PATCH 204/326] Turn makesoftwarecorona into a function --- src/p_mobj.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 4810d3623..65c337cf2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12656,6 +12656,15 @@ static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong) return true; } +static mobj_t *P_MakeSoftwareCorona(mobj_t *mo, INT32 height) +{ + mobj_t *corona = P_SpawnMobjFromMobj(mo, 0, 0, height<sprite = SPR_FLAM; + corona->frame = (FF_FULLBRIGHT|FF_TRANS90|12); + corona->tics = -1; + return corona; +} + static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) { boolean override = LUA_HookMapThingSpawn(mobj, mthing); @@ -12731,16 +12740,10 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (mthing->angle > 0) mobj->color = ((mthing->angle - 1) % (numskincolors - 1)) + 1; break; -#define makesoftwarecorona(mo, h) \ - corona = P_SpawnMobjFromMobj(mo, 0, 0, h<sprite = SPR_FLAM;\ - corona->frame = (FF_FULLBRIGHT|FF_TRANS90|12);\ - corona->tics = -1 case MT_FLAME: if (mthing->options & MTF_EXTRA) { - mobj_t *corona; - makesoftwarecorona(mobj, 20); + mobj_t *corona = P_MakeSoftwareCorona(mobj, 20); P_SetScale(corona, (corona->destscale = mobj->scale*3)); P_SetTarget(&mobj->tracer, corona); } @@ -12753,8 +12756,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean flame->flags2 |= MF2_BOSSNOTRAP; if (mthing->options & MTF_EXTRA) { - mobj_t *corona; - makesoftwarecorona(flame, 20); + mobj_t *corona = P_MakeSoftwareCorona(flame, 20); P_SetScale(corona, (corona->destscale = flame->scale*3)); P_SetTarget(&flame->tracer, corona); } @@ -12763,12 +12765,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean case MT_CANDLE: case MT_CANDLEPRICKET: if (mthing->options & MTF_EXTRA) - { - mobj_t *corona; - makesoftwarecorona(mobj, ((mobj->type == MT_CANDLE) ? 42 : 176)); - } + P_MakeSoftwareCorona(mobj, ((mobj->type == MT_CANDLE) ? 42 : 176)); break; -#undef makesoftwarecorona case MT_JACKO1: case MT_JACKO2: case MT_JACKO3: From af30847a1f8b8d33892d1e11684702088104b2f6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 18:19:10 +0100 Subject: [PATCH 205/326] Adapt zoom tube waypoint to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 8 ++++++++ src/p_mobj.c | 4 ++-- src/p_setup.c | 4 ++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 303bfe396..03c2fc82d 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4773,6 +4773,14 @@ udmf { title = "Zoom Tube Waypoint"; sprite = "internal:zoom"; + arg0 + { + title = "Sequence"; + } + arg1 + { + title = "Order"; + } } 754 diff --git a/src/p_mobj.c b/src/p_mobj.c index 65c337cf2..7f12a190b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12819,8 +12819,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; case MT_TUBEWAYPOINT: { - UINT8 sequence = mthing->angle >> 8; - UINT8 id = mthing->angle & 255; + UINT8 sequence = mthing->args[0]; + UINT8 id = mthing->args[1]; mobj->health = id; mobj->threshold = sequence; P_AddWaypoint(sequence, id, mobj); diff --git a/src/p_setup.c b/src/p_setup.c index ba3544d12..bf12c88bc 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4890,6 +4890,10 @@ static void P_ConvertBinaryMap(void) case 111: //Pop-up Turret mapthings[i].args[0] = mapthings[i].angle; break; + case 753: //Zoom tube waypoint + mapthings[i].args[0] = mapthings[i].angle >> 8; + mapthings[i].args[1] = mapthings[i].angle & 255; + break; case 754: //Push point case 755: //Pull point { From 693fa7ba81ee97dc3207e90c03ecbbd0d431157b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 18:27:19 +0100 Subject: [PATCH 206/326] Adapt star posts to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 4 ++++ src/p_mobj.c | 10 +--------- src/p_setup.c | 11 +++++++++++ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 03c2fc82d..0fe11cf5e 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4370,6 +4370,10 @@ udmf sprite = "STPTA0M0"; width = 64; height = 128; + arg0 + { + title = "Order"; + } } 520 { diff --git a/src/p_mobj.c b/src/p_mobj.c index 7f12a190b..f6954baef 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12966,15 +12966,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj_t* mo2; boolean foundanother = false; - if (mthing->extrainfo) - // Allow thing Parameter to define star post num too! - // For starposts above param 15 (the 16th), add 360 to the angle like before and start parameter from 1 (NOT 0)! - // So the 16th starpost is angle=0 param=15, the 17th would be angle=360 param=1. - // This seems more intuitive for mappers to use until UDMF is ready, since most SP maps won't have over 16 consecutive star posts. - mobj->health = mthing->extrainfo + (mthing->angle/360)*15 + 1; - else - // Old behavior if Parameter is 0; add 360 to the angle for each consecutive star post. - mobj->health = (mthing->angle/360) + 1; + mobj->health = mthing->args[0] + 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) diff --git a/src/p_setup.c b/src/p_setup.c index bf12c88bc..1761a4be9 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4890,6 +4890,17 @@ static void P_ConvertBinaryMap(void) case 111: //Pop-up Turret mapthings[i].args[0] = mapthings[i].angle; break; + case 502: //Star post + if (mapthings[i].extrainfo) + // Allow thing Parameter to define star post num too! + // For starposts above param 15 (the 16th), add 360 to the angle like before and start parameter from 1 (NOT 0)! + // So the 16th starpost is angle=0 param=15, the 17th would be angle=360 param=1. + // This seems more intuitive for mappers to use, since most SP maps won't have over 16 consecutive star posts. + mapthings[i].args[0] = mapthings[i].extrainfo + (mapthings[i].angle/360) * 15; + else + // Old behavior if Parameter is 0; add 360 to the angle for each consecutive star post. + mapthings[i].args[0] = (mapthings[i].angle/360); + break; case 753: //Zoom tube waypoint mapthings[i].args[0] = mapthings[i].angle >> 8; mapthings[i].args[1] = mapthings[i].angle & 255; From 5918ecc2feb121e8cfdc2812b5a58da94f69df59 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 18:32:24 +0100 Subject: [PATCH 207/326] Refactor star post check --- src/p_mobj.c | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f6954baef..b676fd9c0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12665,6 +12665,28 @@ static mobj_t *P_MakeSoftwareCorona(mobj_t *mo, INT32 height) return corona; } +static boolean P_MapAlreadyHasStarPost(mobj_t *mobj) +{ + thinker_t *th; + mobj_t *mo2; + + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo2 = (mobj_t *)th; + + if (mo2 == mobj) + continue; + + if (mo2->type == MT_STARPOST && mo2->health == mobj->health) + return true; + } + + return false; +} + static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) { boolean override = LUA_HookMapThingSpawn(mobj, mthing); @@ -12961,35 +12983,10 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean } break; case MT_STARPOST: - { - thinker_t* th; - mobj_t* mo2; - boolean foundanother = false; - mobj->health = mthing->args[0] + 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) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t*)th; - - if (mo2 == mobj) - continue; - - if (mo2->type == MT_STARPOST && mo2->health == mobj->health) - { - foundanother = true; - break; - } - } - - if (!foundanother) + if (!P_MapAlreadyHasStarPost(mobj)) numstarposts++; break; - } case MT_SPIKE: // Pop up spikes! if (mthing->options & MTF_OBJECTSPECIAL) From 52c319167fe8d6138a6482e26a98db1bf789b002 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 21:08:40 +0100 Subject: [PATCH 208/326] (Mostly) adapt the Ideya Drone to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 24 + src/p_mobj.c | 519 +++++++++++---------- src/p_setup.c | 13 + src/p_spec.h | 8 + src/p_user.c | 8 +- 5 files changed, 309 insertions(+), 263 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 0fe11cf5e..7140267ba 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -6374,6 +6374,30 @@ udmf sprite = "NDRNA1"; width = 16; height = 56; + arg0 + { + title = "Time limit"; + } + arg1 + { + title = "Height"; + } + arg2 + { + title = "Radius"; + } + arg3 + { + title = "Alignment"; + type = 11; + enum + { + 0 = "Bottom with offset"; + 1 = "Bottom"; + 2 = "Middle"; + 3 = "Top"; + } + } } 1704 { diff --git a/src/p_mobj.c b/src/p_mobj.c index b676fd9c0..262c406dc 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8692,245 +8692,242 @@ static boolean P_EggRobo1Think(mobj_t *mobj) static void P_NiGHTSDroneThink(mobj_t *mobj) { + 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) { - // variable setup - mobj_t *goalpost = NULL; - mobj_t *sparkle = NULL; - mobj_t *droneman = NULL; + 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; + } - 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; + if (!goalpost || !sparkle || !droneman) + return; - fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff; + // 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 (mobj->target && mobj->target->type == MT_NIGHTSDRONE_GOAL) + 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) { - 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 { - 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); + 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 { - 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); + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; } - 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); + sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale); } else { - if (goalpost->x != mobj->x || goalpost->y != mobj->y) + if (topaligned) // Align droneman to top of hitbox { - P_TeleportMove(goalpost, mobj->x, mobj->y, goalpost->z); - P_TeleportMove(sparkle, mobj->x, mobj->y, sparkle->z); + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; } - - 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) + else if (middlealigned) // Align droneman to center of hitbox { - 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); + dronemanoffset = droneboxmandiff/2; + goaloffset = dronemangoaldiff/2 + dronemanoffset; } - } - // Invisible/bouncing mode. - else - { - INT32 i; - boolean bonustime = false; - fixed_t zcomp; - - // Bouncy bouncy! - if (!flip) + else if (bottomoffsetted) { - 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; + dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); + goaloffset = dronemangoaldiff + dronemanoffset; } 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; + dronemanoffset = droneboxmandiff; + goaloffset = dronemangoaldiff/2 + dronemanoffset; } - 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); + sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale); + } - // state switching logic + 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].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) + if (playeringame[i] && players[i].powers[pw_carry] != CR_NIGHTSMODE) { - bonustime = true; + bonustime = true; // variable reuse break; } if (bonustime) { - CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n"); + // 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; - 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; - } } } } @@ -12496,16 +12493,13 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj) return true; } -static boolean P_SetupNiGHTSDrone(mapthing_t* mthing, mobj_t* mobj) +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; + INT16 timelimit = mthing->args[0]; + fixed_t hitboxheight = mthing->args[1] << FRACBITS; + fixed_t hitboxradius = mthing->args[2] << FRACBITS; + INT32 dronemanalignment = mthing->args[3]; fixed_t oldheight = mobj->height; fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff; @@ -12528,25 +12522,25 @@ static boolean P_SetupNiGHTSDrone(mapthing_t* mthing, mobj_t* mobj) if (!flip) { - if (topaligned) // Align droneman to top of hitbox + switch (dronemanalignment) { - 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; + case TMDA_BOTTOMOFFSET: + default: + dronemanoffset = FixedMul(24*FRACUNIT, mobj->scale); + goaloffset = dronemangoaldiff + dronemanoffset; + break; + case TMDA_BOTTOM: + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + break; + case TMDA_MIDDLE: + dronemanoffset = droneboxmandiff/2; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + break; + case TMDA_TOP: + dronemanoffset = droneboxmandiff; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + break; } sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale); @@ -12556,25 +12550,25 @@ static boolean P_SetupNiGHTSDrone(mapthing_t* mthing, mobj_t* mobj) mobj->eflags |= MFE_VERTICALFLIP; mobj->flags2 |= MF2_OBJECTFLIP; - if (topaligned) // Align droneman to top of hitbox + switch (dronemanalignment) { - 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; + case TMDA_BOTTOMOFFSET: + default: + dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); + goaloffset = dronemangoaldiff + dronemanoffset; + break; + case TMDA_BOTTOM: + dronemanoffset = droneboxmandiff; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + break; + case TMDA_MIDDLE: + dronemanoffset = droneboxmandiff/2; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + break; + case TMDA_TOP: + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + break; } sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale); @@ -12582,9 +12576,9 @@ static boolean P_SetupNiGHTSDrone(mapthing_t* mthing, mobj_t* mobj) // 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); + 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); @@ -12600,12 +12594,21 @@ static boolean P_SetupNiGHTSDrone(mapthing_t* mthing, mobj_t* mobj) // 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; + switch (dronemanalignment) + { + case TMDA_BOTTOMOFFSET: + default: + mobj->flags |= MF_SLIDEME|MF_GRENADEBOUNCE; + break; + case TMDA_BOTTOM: + break; + case TMDA_MIDDLE: + mobj->flags |= MF_GRENADEBOUNCE; + break; + case TMDA_TOP: + mobj->flags |= MF_SLIDEME; + break; + } // Remember old Z position and flags for correction detection goalpost->movefactor = mobj->z; diff --git a/src/p_setup.c b/src/p_setup.c index 1761a4be9..12ccfff4d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5058,6 +5058,19 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[0] = mapthings[i].extrainfo; mapthings[i].args[1] = mapthings[i].options; break; + case 1703: //Ideya drone + mapthings[i].args[0] = mapthings[i].angle & 0xFFF; + mapthings[i].args[1] = mapthings[i].extrainfo*32; + mapthings[i].args[2] = ((mapthings[i].angle & 0xF000) >> 12)*32; + if ((mapthings[i].options & (MTF_OBJECTSPECIAL|MTF_EXTRA)) == (MTF_OBJECTSPECIAL|MTF_EXTRA)) + mapthings[i].args[3] = TMDA_BOTTOM; + else if ((mapthings[i].options & (MTF_OBJECTSPECIAL|MTF_EXTRA)) == MTF_OBJECTSPECIAL) + mapthings[i].args[3] = TMDA_TOP; + else if ((mapthings[i].options & (MTF_OBJECTSPECIAL|MTF_EXTRA)) == MTF_EXTRA) + mapthings[i].args[3] = TMDA_MIDDLE; + else + mapthings[i].args[3] = TMDA_BOTTOMOFFSET; + break; case 1704: //NiGHTS bumper mapthings[i].pitch = 30 * (((mapthings[i].options & 15) + 9) % 12); mapthings[i].options &= ~0xF; diff --git a/src/p_spec.h b/src/p_spec.h index 8e210b543..f9ad63957 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -36,6 +36,14 @@ typedef enum TMM_ALWAYSTHINK = 1<<7, } textmapmaceflags_t; +typedef enum +{ + TMDA_BOTTOMOFFSET = 1, + TMDA_BOTTOM = 1<<1, + TMDA_MIDDLE = 1<<2, + TMDA_TOP = 1<<3, +} textmapdronealignment_t; + //FOF flags typedef enum { diff --git a/src/p_user.c b/src/p_user.c index 011a23215..4f4a185ed 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -706,8 +706,7 @@ static void P_DeNightserizePlayer(player_t *player) // If you screwed up, kiss your score and ring bonus goodbye. // But only do this in special stage (and instakill!) In regular stages, wait til we hit the ground. - player->marescore = player->spheres =\ - player->rings = 0; + player->marescore = player->spheres = player->rings = 0; } // Check to see if the player should be killed. @@ -717,13 +716,12 @@ static void P_DeNightserizePlayer(player_t *player) continue; mo2 = (mobj_t *)th; - if (!(mo2->type == MT_NIGHTSDRONE)) + if (mo2->type != MT_NIGHTSDRONE) continue; if (mo2->flags2 & MF2_AMBUSH) { - player->marescore = player->spheres =\ - player->rings = 0; + player->marescore = player->spheres = player->rings = 0; P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); // Reset music to beginning if MIXNIGHTSCOUNTDOWN From a5ac10733af33a9012dbce763e51359f5fcc4624 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 21:51:37 +0100 Subject: [PATCH 209/326] Adapt Hive Elemental to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 4 ++++ src/p_mobj.c | 4 ++-- src/p_setup.c | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 7140267ba..c72603cc6 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3844,6 +3844,10 @@ udmf sprite = "HIVEA0"; width = 32; height = 80; + arg0 + { + title = "Number of bees"; + } } 128 { diff --git a/src/p_mobj.c b/src/p_mobj.c index 262c406dc..0652967d7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12859,8 +12859,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean return false; break; case MT_HIVEELEMENTAL: - if (mthing->extrainfo) - mobj->extravalue1 = mthing->extrainfo; + if (mthing->args[0]) + mobj->extravalue1 = mthing->args[0]; break; case MT_GLAREGOYLE: case MT_GLAREGOYLEUP: diff --git a/src/p_setup.c b/src/p_setup.c index 12ccfff4d..8d6b3e5de 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4890,6 +4890,9 @@ static void P_ConvertBinaryMap(void) case 111: //Pop-up Turret mapthings[i].args[0] = mapthings[i].angle; break; + case 127: //Hive Elemental + mapthings[i].args[0] = mapthings[i].extrainfo; + break; case 502: //Star post if (mapthings[i].extrainfo) // Allow thing Parameter to define star post num too! From 5eb2448a409e7337d30d7dd7cca3ef21145a48d6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 21:57:35 +0100 Subject: [PATCH 210/326] Adapt Pterabytes to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 5 +++++ src/p_enemy.c | 2 +- src/p_setup.c | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index c72603cc6..d5af8fb90 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3752,6 +3752,11 @@ udmf sprite = "PTERA2A8"; width = 16; height = 16; + arg0 + { + title = "Number of Pterabytes"; + default = 1; + } } 136 { diff --git a/src/p_enemy.c b/src/p_enemy.c index 64b21809f..079ae5e64 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -14270,7 +14270,7 @@ void A_SpawnPterabytes(mobj_t *actor) return; if (actor->spawnpoint) - amount = actor->spawnpoint->extrainfo + 1; + amount = min(1, actor->spawnpoint->args[0]); interval = FixedAngle(FRACUNIT*360/amount); diff --git a/src/p_setup.c b/src/p_setup.c index 8d6b3e5de..9ef539110 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4893,6 +4893,9 @@ static void P_ConvertBinaryMap(void) case 127: //Hive Elemental mapthings[i].args[0] = mapthings[i].extrainfo; break; + case 135: //Pterabyte Spawner + mapthings[i].args[0] = mapthings[i].extrainfo + 1; + break; case 502: //Star post if (mapthings[i].extrainfo) // Allow thing Parameter to define star post num too! From fe8c1d133112a55ab98c61b531779299f035f4c3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 21 Dec 2021 22:00:42 +0100 Subject: [PATCH 211/326] Adapt Pyre Fly to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 6 ++++++ src/p_mobj.c | 4 ++-- src/p_setup.c | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index d5af8fb90..e5bec6d3a 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3764,6 +3764,12 @@ udmf sprite = "PYREA0"; width = 24; height = 34; + arg0 + { + title = "Start on fire?"; + type = 11; + enum = "noyes"; + } } 137 { diff --git a/src/p_mobj.c b/src/p_mobj.c index 0652967d7..7c44ae8da 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12924,8 +12924,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean } break; case MT_PYREFLY: - //start on fire if Ambush flag is set, otherwise behave normally - if (mthing->options & MTF_AMBUSH) + //start on fire if args[0], otherwise behave normally + if (mthing->args[0]) { P_SetMobjState(mobj, mobj->info->meleestate); mobj->extravalue2 = 2; diff --git a/src/p_setup.c b/src/p_setup.c index 9ef539110..03a7cf564 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4896,6 +4896,9 @@ static void P_ConvertBinaryMap(void) case 135: //Pterabyte Spawner mapthings[i].args[0] = mapthings[i].extrainfo + 1; break; + case 136: //Pyre Fly + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + break; case 502: //Star post if (mapthings[i].extrainfo) // Allow thing Parameter to define star post num too! From baa99150d076cf4fb2781d95414a35dc00e27033 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 25 Dec 2021 09:58:00 +0100 Subject: [PATCH 212/326] Adapt Fang waypoint to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 6 ++++++ src/p_enemy.c | 25 ++++++++++------------ src/p_setup.c | 4 ++++ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index e5bec6d3a..5cc285118 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3989,6 +3989,12 @@ udmf sprite = "internal:eggmanway"; width = 8; height = 16; + arg0 + { + title = "Center waypoint?"; + type = 11; + enum = "noyes"; + } } } diff --git a/src/p_enemy.c b/src/p_enemy.c index 079ae5e64..bff7622b7 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -12693,7 +12693,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) { INT32 locvar1 = var1; boolean avoidcenter; - UINT32 i; + INT32 i; UINT8 extrainfo = (actor->spawnpoint ? actor->spawnpoint->extrainfo : 0); if (LUA_CallAction(A_BOSS5FINDWAYPOINT, actor)) @@ -12735,25 +12735,26 @@ void A_Boss5FindWaypoint(mobj_t *actor) } else if (locvar1 == 1) // always go to ambush-marked waypoint { + boolean found = false; + if (avoidcenter) goto nowaypoints; // if we can't go the center, why on earth are we doing this? - for (i = 0; i < nummapthings; i++) + TAG_ITER_THINGS(extrainfo, i) { if (!mapthings[i].mobj) continue; if (mapthings[i].mobj->type != MT_FANGWAYPOINT) continue; - if (mapthings[i].extrainfo != extrainfo) - continue; - if (!(mapthings[i].options & MTF_AMBUSH)) + if (!(mapthings[i].args[0])) continue; P_SetTarget(&actor->tracer, mapthings[i].mobj); + found = true; break; } - if (i == nummapthings) + if (!found) goto nowaypoints; } else // locvar1 == 0 @@ -12766,7 +12767,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) actor->z += hackoffset; // first, count how many waypoints we have - for (i = 0; i < nummapthings; i++) + TAG_ITER_THINGS(extrainfo, i) { if (!mapthings[i].mobj) continue; @@ -12774,9 +12775,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) continue; if (actor->tracer == mapthings[i].mobj) // this was your tracer last time continue; - if (mapthings[i].extrainfo != extrainfo) - continue; - if (mapthings[i].options & MTF_AMBUSH) + if (mapthings[i].args[0]) { if (avoidcenter) continue; @@ -12823,7 +12822,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) numfangwaypoints = 0; // now find them again and add them to the table! - for (i = 0; i < nummapthings; i++) + TAG_ITER_THINGS(extrainfo, i) { if (!mapthings[i].mobj) continue; @@ -12831,9 +12830,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) continue; if (actor->tracer == mapthings[i].mobj) // this was your tracer last time continue; - if (mapthings[i].extrainfo != extrainfo) - continue; - if (mapthings[i].options & MTF_AMBUSH) + if (mapthings[i].args[0]) { if (avoidcenter) continue; diff --git a/src/p_setup.c b/src/p_setup.c index 03a7cf564..e2603cc46 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3130,6 +3130,7 @@ static void P_AddBinaryMapTags(void) case 762: Tag_FSet(&mapthings[i].tags, mapthings[i].angle); break; + case 294: case 780: Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo); break; @@ -4899,6 +4900,9 @@ static void P_ConvertBinaryMap(void) case 136: //Pyre Fly mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; + case 294: + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + break; case 502: //Star post if (mapthings[i].extrainfo) // Allow thing Parameter to define star post num too! From 3661fd507941ab410363a0cb17e2f4f23e82eaf0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 26 Dec 2021 20:09:38 +0100 Subject: [PATCH 213/326] Adapt boss fly point to UDMF --- src/p_enemy.c | 83 +++++++++++++++++++-------------------------------- src/p_setup.c | 1 + 2 files changed, 31 insertions(+), 53 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index bff7622b7..26458f735 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3862,6 +3862,33 @@ void A_Explode(mobj_t *actor) P_RadiusAttack(actor, actor->target, actor->info->damage, locvar1, true); } +static mobj_t *P_FindBossFlyPoint(mobj_t *mo, INT32 tag) +{ + INT32 i; + mobj_t *closest = NULL; + + TAG_ITER_THINGS(tag, i) + { + mobj_t *mo2 = mapthings[i].mobj; + + if (!mo2) + continue; + + if (mo2->type != MT_BOSSFLYPOINT) + continue; + + // If this one's further than the last one, don't go for it. + if (closest && + P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) > + P_AproxDistance(P_AproxDistance(mo->x - closest->x, mo->y - closest->y), mo->z - closest->z)) + continue; + + closest = mo2; + } + + return closest; +} + // Function: A_BossDeath // // Description: Possibly trigger special effects when boss dies. @@ -4114,32 +4141,7 @@ bossjustdie: if (P_MobjWasRemoved(mo)) return; - P_SetTarget(&mo->target, NULL); - - // Flee! Flee! Find a point to escape to! If none, just shoot upward! - // scan the thinkers to find the runaway point - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_BOSSFLYPOINT) - continue; - - if (mo2->spawnpoint && mo2->spawnpoint->extrainfo != extrainfo) - continue; - - // If this one's further then the last one, don't go for it. - if (mo->target && - P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) > - P_AproxDistance(P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y), mo->z - mo->target->z)) - continue; - - // Otherwise... Do! - P_SetTarget(&mo->target, mo2); - } + P_SetTarget(&mo->target, P_FindBossFlyPoint(mo, extrainfo)); mo->flags |= MF_NOGRAVITY|MF_NOCLIP; mo->flags |= MF_NOCLIPHEIGHT; @@ -12701,35 +12703,10 @@ void A_Boss5FindWaypoint(mobj_t *actor) avoidcenter = !actor->tracer || (actor->health == actor->info->damage+1); - if (locvar1 == 2) // look for the boss waypoint + if (locvar1 == 2) // look for the boss flypoint { - thinker_t *th; - mobj_t *mo2; - P_SetTarget(&actor->tracer, NULL); - // Flee! Flee! Find a point to escape to! If none, just shoot upward! - // scan the thinkers to find the runaway point - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; + P_SetTarget(&actor->tracer, P_FindBossFlyPoint(actor, extrainfo)); - mo2 = (mobj_t *)th; - - if (mo2->type != MT_BOSSFLYPOINT) - continue; - - if (mo2->spawnpoint && mo2->spawnpoint->extrainfo != extrainfo) - continue; - - // If this one's further then the last one, don't go for it. - if (actor->tracer && - P_AproxDistance(P_AproxDistance(actor->x - mo2->x, actor->y - mo2->y), actor->z - mo2->z) > - P_AproxDistance(P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y), actor->z - actor->tracer->z)) - continue; - - // Otherwise... Do! - P_SetTarget(&actor->tracer, mo2); - } if (!actor->tracer) return; // no boss flypoints found } diff --git a/src/p_setup.c b/src/p_setup.c index e2603cc46..c6bcded53 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3130,6 +3130,7 @@ static void P_AddBinaryMapTags(void) case 762: Tag_FSet(&mapthings[i].tags, mapthings[i].angle); break; + case 290: case 294: case 780: Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo); From ea6fe56df6bc4189f53cae21d0e1030aadad00af Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 26 Dec 2021 20:31:02 +0100 Subject: [PATCH 214/326] Refactor A_BossDeath --- src/p_enemy.c | 398 ++++++++++++++++++++++++++------------------------ 1 file changed, 210 insertions(+), 188 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 26458f735..c90eb5336 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3889,57 +3889,33 @@ static mobj_t *P_FindBossFlyPoint(mobj_t *mo, INT32 tag) return closest; } -// Function: A_BossDeath -// -// Description: Possibly trigger special effects when boss dies. -// -// var1 = unused -// var2 = unused -// -void A_BossDeath(mobj_t *mo) +static void P_DoBossVictory(mobj_t *mo) { thinker_t *th; mobj_t *mo2; INT32 i; - if (LUA_CallAction(A_BOSSDEATH, mo)) - return; - - if (mo->spawnpoint && mo->spawnpoint->extrainfo) - P_LinedefExecute(LE_BOSSDEAD+(mo->spawnpoint->extrainfo*LE_PARAMWIDTH), mo, NULL); - else - P_LinedefExecute(LE_BOSSDEAD, mo, NULL); - mo->health = 0; - - // Boss is dead (but not necessarily fleeing...) - // Lua may use this to ignore bosses after they start fleeing - mo->flags2 |= MF2_BOSSDEAD; - - // make sure there is a player alive for victory - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && ((players[i].mo && players[i].mo->health) - || ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) - break; - - if (i == MAXPLAYERS) - return; // no one left alive, so do not end game - - // scan the remaining thinkers to see - // if all bosses are dead + // scan the remaining thinkers to see if all bosses are dead for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; - if (mo2 != mo && (mo2->flags & MF_BOSS) && mo2->health > 0) - goto bossjustdie; // other boss not dead - just go straight to dying! + + if (mo2 == mo) + continue; + + if ((mo2->flags & MF_BOSS) && mo2->health > 0) + return; } // victory! P_LinedefExecute(LE_ALLBOSSESDEAD, mo, NULL); + if (stoppedclock && modeattacking) // if you're just time attacking, skip making the capsule appear since you don't need to step on it anyways. - goto bossjustdie; + return; + if (mo->flags2 & MF2_BOSSNOTRAP) { for (i = 0; i < MAXPLAYERS; i++) @@ -3979,8 +3955,196 @@ void A_BossDeath(mobj_t *mo) mapheaderinfo[gamemap-1]->muspostbossfadein); } } +} + +static void P_SpawnBoss1Junk(mobj_t *mo) +{ + mobj_t *mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSEGLZ1); + + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSEGLZ2); +} + +static void P_SpawnBoss2Junk(mobj_t *mo) +{ + mobj_t *mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSTANK1); + + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSTANK2); + + mo2 = P_SpawnMobjFromMobj(mo, 0, 0, + mobjinfo[MT_EGGMOBILE2].height + (32<angle = mo->angle; + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + mo2->momz += mo->momz; + P_SetMobjState(mo2, S_BOSSSPIGOT); +} + +static void P_SpawnBoss3Junk(mobj_t *mo) +{ + mobj_t *mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK); + mo2->angle = mo->angle; + P_SetMobjState(mo2, S_BOSSSEBH1); +} + +static void P_DoCybrakdemonDeath(mobj_t *mo) +{ + mo->flags |= MF_NOCLIP; + mo->flags &= ~(MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT); + + S_StartSound(NULL, sfx_bedie2); + P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); + mo->z += P_MobjFlip(mo); + P_SetObjectMomZ(mo, 12*FRACUNIT, false); + S_StartSound(mo, sfx_bgxpld); + if (mo->spawnpoint && !(mo->spawnpoint->options & MTF_EXTRA)) + P_InstaThrust(mo, R_PointToAngle2(0, 0, mo->x, mo->y), 14*FRACUNIT); +} + +static void P_DoBoss5Death(mobj_t *mo) +{ + if (mo->flags2 & MF2_SLIDEPUSH) + { + P_RemoveMobj(mo); + return; + } + if (mo->tracer) + { + var1 = var2 = 0; + A_Boss5Jump(mo); + mo->momx = ((16 - 1)*mo->momx)/16; + mo->momy = ((16 - 1)*mo->momy)/16; + { + const fixed_t time = FixedHypot(mo->tracer->x - mo->x, mo->tracer->y - mo->y)/FixedHypot(mo->momx, mo->momy); + const fixed_t speed = 64*FRACUNIT; + mobj_t *pole = P_SpawnMobj( + mo->tracer->x - P_ReturnThrustX(mo->tracer, mo->tracer->angle, speed*time), + mo->tracer->y - P_ReturnThrustY(mo->tracer, mo->tracer->angle, speed*time), + mo->tracer->floorz + (256+1)*FRACUNIT, + MT_FSGNB); + P_SetTarget(&pole->tracer, P_SpawnMobj( + pole->x, pole->y, + pole->z - 256*FRACUNIT, + MT_FSGNB)); + P_SetTarget(&pole->tracer->tracer, P_SpawnMobj( + pole->x + P_ReturnThrustX(pole, mo->tracer->angle, FRACUNIT), + pole->y + P_ReturnThrustY(pole, mo->tracer->angle, FRACUNIT), + pole->z + 256*FRACUNIT, + MT_FSGNA)); + pole->tracer->flags |= MF_NOCLIPTHING; + P_SetScale(pole, (pole->destscale = 2*FRACUNIT)); + P_SetScale(pole->tracer, (pole->tracer->destscale = 2*FRACUNIT)); + pole->angle = pole->tracer->angle = mo->tracer->angle; + pole->tracer->tracer->angle = pole->angle - ANGLE_90; + pole->momx = P_ReturnThrustX(pole, pole->angle, speed); + pole->momy = P_ReturnThrustY(pole, pole->angle, speed); + pole->tracer->momx = pole->momx; + pole->tracer->momy = pole->momy; + pole->tracer->tracer->momx = pole->momx; + pole->tracer->tracer->momy = pole->momy; + } + } + else + { + P_SetObjectMomZ(mo, 10*FRACUNIT, false); + mo->flags |= MF_NOGRAVITY; + } + mo->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; +} + +static void P_DoBossDefaultDeath(mobj_t *mo) +{ + UINT8 extrainfo = (mo->spawnpoint ? mo->spawnpoint->extrainfo : 0); + + // Stop exploding and prepare to run. + P_SetMobjState(mo, mo->info->xdeathstate); + if (P_MobjWasRemoved(mo)) + return; + + P_SetTarget(&mo->target, P_FindBossFlyPoint(mo, extrainfo)); + + mo->flags |= MF_NOGRAVITY|MF_NOCLIP; + mo->flags |= MF_NOCLIPHEIGHT; + + mo->movedir = 0; + mo->extravalue1 = 35; + mo->flags2 |= MF2_BOSSFLEE; + mo->momz = P_MobjFlip(mo)*2*mo->scale; + + if (mo->target) + { + angle_t diff = R_PointToAngle2(mo->x, mo->y, mo->target->x, mo->target->y) - mo->angle; + if (diff) + { + if (diff > ANGLE_180) + diff = InvAngle(InvAngle(diff)/mo->extravalue1); + else + diff /= mo->extravalue1; + mo->movedir = diff; + } + } +} + +// Function: A_BossDeath +// +// Description: Possibly trigger special effects when boss dies. +// +// var1 = unused +// var2 = unused +// +void A_BossDeath(mobj_t *mo) +{ + INT32 i; + UINT8 extrainfo = (mo->spawnpoint ? mo->spawnpoint->extrainfo : 0); + + if (LUA_CallAction(A_BOSSDEATH, mo)) + return; + + P_LinedefExecute(LE_BOSSDEAD+(extrainfo*LE_PARAMWIDTH), mo, NULL); + mo->health = 0; + + // Boss is dead (but not necessarily fleeing...) + // Lua may use this to ignore bosses after they start fleeing + mo->flags2 |= MF2_BOSSDEAD; + + // make sure there is a player alive for victory + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && ((players[i].mo && players[i].mo->health) + || ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) + break; + + if (i == MAXPLAYERS) + return; // no one left alive, so do not end game + + P_DoBossVictory(mo); -bossjustdie: if (LUA_HookMobj(mo, MOBJ_HOOK(BossDeath))) return; else if (P_MobjWasRemoved(mo)) @@ -3992,61 +4156,13 @@ bossjustdie: default: break; case MT_EGGMOBILE: // twin laser pods - { - mo2 = P_SpawnMobjFromMobj(mo, - P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; - P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - P_SetMobjState(mo2, S_BOSSEGLZ1); - - mo2 = P_SpawnMobjFromMobj(mo, - P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; - P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - P_SetMobjState(mo2, S_BOSSEGLZ2); - } + P_SpawnBoss1Junk(mo); break; case MT_EGGMOBILE2: // twin tanks + spigot - { - mo2 = P_SpawnMobjFromMobj(mo, - P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; - P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - P_SetMobjState(mo2, S_BOSSTANK1); - - mo2 = P_SpawnMobjFromMobj(mo, - P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; - P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - P_SetMobjState(mo2, S_BOSSTANK2); - - mo2 = P_SpawnMobjFromMobj(mo, 0, 0, - mobjinfo[MT_EGGMOBILE2].height + (32<angle = mo->angle; - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - mo2->momz += mo->momz; - P_SetMobjState(mo2, S_BOSSSPIGOT); - } + P_SpawnBoss2Junk(mo); break; case MT_EGGMOBILE3: - { - mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK); - mo2->angle = mo->angle; - P_SetMobjState(mo2, S_BOSSSEBH1); - } + P_SpawnBoss3Junk(mo); break; } @@ -4054,118 +4170,24 @@ bossjustdie: switch (mo->type) { case MT_BLACKEGGMAN: - { mo->flags |= MF_NOCLIP; mo->flags &= ~MF_SPECIAL; S_StartSound(NULL, sfx_befall); break; - } case MT_CYBRAKDEMON: - { - mo->flags |= MF_NOCLIP; - mo->flags &= ~(MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT); - - S_StartSound(NULL, sfx_bedie2); - P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); - mo->z += P_MobjFlip(mo); - P_SetObjectMomZ(mo, 12*FRACUNIT, false); - S_StartSound(mo, sfx_bgxpld); - if (mo->spawnpoint && !(mo->spawnpoint->options & MTF_EXTRA)) - P_InstaThrust(mo, R_PointToAngle2(0, 0, mo->x, mo->y), 14*FRACUNIT); + P_DoCybrakdemonDeath(mo); break; - } case MT_KOOPA: - { if (mo->spawnpoint) EV_DoCeiling(mo->spawnpoint->args[0], NULL, raiseToHighest); - return; - } - case MT_FANG: - { - if (mo->flags2 & MF2_SLIDEPUSH) - { - P_RemoveMobj(mo); - return; - } - if (mo->tracer) - { - var1 = var2 = 0; - A_Boss5Jump(mo); - mo->momx = ((16 - 1)*mo->momx)/16; - mo->momy = ((16 - 1)*mo->momy)/16; - { - const fixed_t time = FixedHypot(mo->tracer->x - mo->x, mo->tracer->y - mo->y)/FixedHypot(mo->momx, mo->momy); - const fixed_t speed = 64*FRACUNIT; - mobj_t *pole = P_SpawnMobj( - mo->tracer->x - P_ReturnThrustX(mo->tracer, mo->tracer->angle, speed*time), - mo->tracer->y - P_ReturnThrustY(mo->tracer, mo->tracer->angle, speed*time), - mo->tracer->floorz + (256+1)*FRACUNIT, - MT_FSGNB); - P_SetTarget(&pole->tracer, P_SpawnMobj( - pole->x, pole->y, - pole->z - 256*FRACUNIT, - MT_FSGNB)); - P_SetTarget(&pole->tracer->tracer, P_SpawnMobj( - pole->x + P_ReturnThrustX(pole, mo->tracer->angle, FRACUNIT), - pole->y + P_ReturnThrustY(pole, mo->tracer->angle, FRACUNIT), - pole->z + 256*FRACUNIT, - MT_FSGNA)); - pole->tracer->flags |= MF_NOCLIPTHING; - P_SetScale(pole, (pole->destscale = 2*FRACUNIT)); - P_SetScale(pole->tracer, (pole->tracer->destscale = 2*FRACUNIT)); - pole->angle = pole->tracer->angle = mo->tracer->angle; - pole->tracer->tracer->angle = pole->angle - ANGLE_90; - pole->momx = P_ReturnThrustX(pole, pole->angle, speed); - pole->momy = P_ReturnThrustY(pole, pole->angle, speed); - pole->tracer->momx = pole->momx; - pole->tracer->momy = pole->momy; - pole->tracer->tracer->momx = pole->momx; - pole->tracer->tracer->momy = pole->momy; - } - } - else - { - P_SetObjectMomZ(mo, 10*FRACUNIT, false); - mo->flags |= MF_NOGRAVITY; - } - mo->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; - return; - } - default: //eggmobiles - { - UINT8 extrainfo = (mo->spawnpoint ? mo->spawnpoint->extrainfo : 0); - - // Stop exploding and prepare to run. - P_SetMobjState(mo, mo->info->xdeathstate); - if (P_MobjWasRemoved(mo)) - return; - - P_SetTarget(&mo->target, P_FindBossFlyPoint(mo, extrainfo)); - - mo->flags |= MF_NOGRAVITY|MF_NOCLIP; - mo->flags |= MF_NOCLIPHEIGHT; - - mo->movedir = 0; - mo->extravalue1 = 35; - mo->flags2 |= MF2_BOSSFLEE; - mo->momz = P_MobjFlip(mo)*2*mo->scale; - - if (mo->target) - { - angle_t diff = R_PointToAngle2(mo->x, mo->y, mo->target->x, mo->target->y) - mo->angle; - if (diff) - { - if (diff > ANGLE_180) - diff = InvAngle(InvAngle(diff)/mo->extravalue1); - else - diff /= mo->extravalue1; - mo->movedir = diff; - } - } - break; - } + case MT_FANG: + P_DoBoss5Death(mo); + break; + default: //eggmobiles + P_DoBossDefaultDeath(mo); + break; } } From 8535b595d641c33148839501c56c09e5ab7ee26d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 26 Dec 2021 21:11:24 +0100 Subject: [PATCH 215/326] Adapt some more player spawning stuff to UDMF --- src/g_demo.c | 2 +- src/m_cheat.c | 2 +- src/p_mobj.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index c97dbcf9e..01bc84a40 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -2212,7 +2212,7 @@ void G_AddGhost(char *defdemoname) 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)) + if (!!(mthing->args[0]) ^ !!(mthing->options & MTF_OBJECTFLIP)) { z = c - offset; if (z < f) diff --git a/src/m_cheat.c b/src/m_cheat.c index ddc1f6f29..b5c3b6563 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -539,7 +539,7 @@ 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)) + if (!!(mt->args[0]) ^ !!(mt->options & MTF_OBJECTFLIP)) intz = ss->sector->ceilingheight - p->mo->height - offset; else intz = ss->sector->floorheight + offset; diff --git a/src/p_mobj.c b/src/p_mobj.c index 7c44ae8da..e97719ddb 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11652,7 +11652,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) mobj->eflags |= MFE_VERTICALFLIP; mobj->flags2 |= MF2_OBJECTFLIP; } - if (mthing->options & MTF_AMBUSH) + if (mthing->args[0]) P_SetPlayerMobjState(mobj, S_PLAY_FALL); else if (metalrecording) P_SetPlayerMobjState(mobj, S_PLAY_WAIT); From 36217c646898fb72c38e2a10c6d18fdfa5897311 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 26 Dec 2021 21:33:20 +0100 Subject: [PATCH 216/326] Finish adapting slope vertices to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 6 ++++++ src/p_setup.c | 3 +++ src/p_slopes.c | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 5cc285118..1cb3b41ee 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4778,6 +4778,12 @@ udmf { title = "Slope Vertex"; sprite = "internal:vertexslope"; + arg0 + { + title = "Absolute height?"; + type = 11; + enum = "noyes"; + } } 751 diff --git a/src/p_setup.c b/src/p_setup.c index c6bcded53..cc5b32d73 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4915,6 +4915,9 @@ static void P_ConvertBinaryMap(void) // Old behavior if Parameter is 0; add 360 to the angle for each consecutive star post. mapthings[i].args[0] = (mapthings[i].angle/360); break; + case 750: //Slope vertex + mapthings[i].args[0] = mapthings[i].extrainfo; + break; case 753: //Zoom tube waypoint mapthings[i].args[0] = mapthings[i].angle >> 8; mapthings[i].args[1] = mapthings[i].angle & 255; diff --git a/src/p_slopes.c b/src/p_slopes.c index bfca153a6..c0cc3a98e 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -469,7 +469,7 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag vx[i].x = mt->x << FRACBITS; vx[i].y = mt->y << FRACBITS; vx[i].z = mt->z << FRACBITS; - if (!mt->extrainfo) + if (!mt->args[0]) vx[i].z += R_PointInSubsector(vx[i].x, vx[i].y)->sector->floorheight; } From c550de5dfa5e06370fd91ee03263c00cd1be23fc Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Dec 2021 07:32:57 +0100 Subject: [PATCH 217/326] Adapt spikes to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 36 ++++++++++++++++++++++ src/p_mobj.c | 33 ++++++++------------ src/p_setup.c | 22 +++++++++++++ src/p_spec.h | 6 ++++ 4 files changed, 76 insertions(+), 21 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 1cb3b41ee..5736cb7bf 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4417,6 +4417,24 @@ udmf width = 16; height = 14; arrow = 1; + arg0 + { + title = "Retraction interval"; + } + arg1 + { + title = "Start interval"; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Start retracted"; + 2 = "Intangible"; + } + } } 523 { @@ -4424,6 +4442,24 @@ udmf sprite = "USPKA0"; width = 8; height = 32; + arg0 + { + title = "Retraction interval"; + } + arg1 + { + title = "Start interval"; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Start retracted"; + 2 = "Intangible"; + } + } } 1130 { diff --git a/src/p_mobj.c b/src/p_mobj.c index e97719ddb..bb9bd22a7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10072,16 +10072,9 @@ static boolean P_FuseThink(mobj_t *mobj) 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); + mobj->fuse = mobj->spawnpoint ? mobj->spawnpoint->args[0] : mobj->info->speed; break; case MT_NIGHTSCORE: P_RemoveMobj(mobj); @@ -12992,15 +12985,13 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; case MT_SPIKE: // Pop up spikes! - if (mthing->options & MTF_OBJECTSPECIAL) + if (mthing->args[0]) { mobj->flags &= ~MF_SCENERY; - mobj->fuse = (16 - mthing->extrainfo)*(mthing->angle + mobj->info->speed)/16; - if (mthing->options & MTF_EXTRA) - P_SetMobjState(mobj, mobj->info->meleestate); + mobj->fuse = mthing->args[1]; } - // Use per-thing collision for spikes if the deaf flag isn't checked. - if (!(mthing->options & MTF_AMBUSH) && !metalrecording) + // Use per-thing collision for spikes unless the intangible flag is checked. + if (!(mthing->args[2] & TMSF_INTANGIBLE) && !metalrecording) { P_UnsetThingPosition(mobj); mobj->flags &= ~(MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT); @@ -13010,18 +13001,18 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; case MT_WALLSPIKE: // Pop up spikes! - if (mthing->options & MTF_OBJECTSPECIAL) + if (mthing->args[0]) { mobj->flags &= ~MF_SCENERY; - mobj->fuse = (16 - mthing->extrainfo)*((mthing->angle/360) + mobj->info->speed)/16; - if (mthing->options & MTF_EXTRA) - P_SetMobjState(mobj, mobj->info->meleestate); + mobj->fuse = mthing->args[1]; } - // Use per-thing collision for spikes if the deaf flag isn't checked. - if (!(mthing->options & MTF_AMBUSH) && !metalrecording) + if (mthing->args[2] & TMSF_RETRACTED) + P_SetMobjState(mobj, mobj->info->meleestate); + // Use per-thing collision for spikes unless the intangible flag is checked. + if (!(mthing->args[2] & TMSF_INTANGIBLE) && !metalrecording) { P_UnsetThingPosition(mobj); - mobj->flags &= ~(MF_NOBLOCKMAP | MF_NOCLIPHEIGHT); + mobj->flags &= ~(MF_NOBLOCKMAP|MF_NOCLIPHEIGHT); mobj->flags |= MF_SOLID; P_SetThingPosition(mobj); } diff --git a/src/p_setup.c b/src/p_setup.c index cc5b32d73..ac7d9e919 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4915,6 +4915,28 @@ static void P_ConvertBinaryMap(void) // Old behavior if Parameter is 0; add 360 to the angle for each consecutive star post. mapthings[i].args[0] = (mapthings[i].angle/360); break; + case 522: //Wall spike + if (mapthings[i].options & MTF_OBJECTSPECIAL) + { + mapthings[i].args[0] = mobjinfo[MT_WALLSPIKE].speed + mapthings[i].angle/360; + mapthings[i].args[1] = (16 - mapthings[i].extrainfo) * mapthings[i].args[0]/16; + if (mapthings[i].options & MTF_EXTRA) + mapthings[i].args[2] |= TMSF_RETRACTED; + } + if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[2] |= TMSF_INTANGIBLE; + break; + case 523: //Spike + if (mapthings[i].options & MTF_OBJECTSPECIAL) + { + mapthings[i].args[0] = mobjinfo[MT_SPIKE].speed + mapthings[i].angle; + mapthings[i].args[1] = (16 - mapthings[i].extrainfo) * mapthings[i].args[0]/16; + if (mapthings[i].options & MTF_EXTRA) + mapthings[i].args[2] |= TMSF_RETRACTED; + } + if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[2] |= TMSF_INTANGIBLE; + break; case 750: //Slope vertex mapthings[i].args[0] = mapthings[i].extrainfo; break; diff --git a/src/p_spec.h b/src/p_spec.h index f9ad63957..88dc6d9f8 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -44,6 +44,12 @@ typedef enum TMDA_TOP = 1<<3, } textmapdronealignment_t; +typedef enum +{ + TMSF_RETRACTED = 1, + TMSF_INTANGIBLE = 1<<1, +} textmapspikeflags_t; + //FOF flags typedef enum { From a14eacd63a855c19317786e129361156f5ab43d8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Dec 2021 08:55:59 +0100 Subject: [PATCH 218/326] Bowser isn't a boss, so don't call A_BossDeath just to do that one thing it needs to do --- src/p_enemy.c | 4 ---- src/p_mobj.c | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index c90eb5336..220f8cf16 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4178,10 +4178,6 @@ void A_BossDeath(mobj_t *mo) case MT_CYBRAKDEMON: P_DoCybrakdemonDeath(mo); break; - case MT_KOOPA: - if (mo->spawnpoint) - EV_DoCeiling(mo->spawnpoint->args[0], NULL, raiseToHighest); - break; case MT_FANG: P_DoBoss5Death(mo); break; diff --git a/src/p_mobj.c b/src/p_mobj.c index bb9bd22a7..7e8f4b397 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6939,7 +6939,6 @@ static void P_RemoveOverlay(mobj_t *thing) } } -void A_BossDeath(mobj_t *mo); // AI for the Koopa boss. static void P_KoopaThinker(mobj_t *koopa) { @@ -6947,7 +6946,8 @@ static void P_KoopaThinker(mobj_t *koopa) if (koopa->watertop > koopa->z + koopa->height + FixedMul(128*FRACUNIT, koopa->scale) && koopa->health > 0) { - A_BossDeath(koopa); + if (koopa->spawnpoint) + EV_DoCeiling(koopa->spawnpoint->args[0], NULL, raiseToHighest); P_RemoveMobj(koopa); return; } From 06bbee50bf7f31c2df2b44c6c6bd8315c550f3c1 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Dec 2021 15:07:37 +0100 Subject: [PATCH 219/326] Adapt boss IDs and trigger tags to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 167 +++++++++++++++++++++ src/info.c | 8 +- src/p_enemy.c | 29 ++-- src/p_mobj.c | 41 +++-- src/p_setup.c | 35 +++++ 5 files changed, 245 insertions(+), 35 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 5736cb7bf..31d6b794d 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3895,6 +3895,25 @@ udmf sprite = "EGGMA1"; width = 24; height = 76; + arg0 + { + title = "Boss ID"; + } + arg1 + { + title = "Death trigger tag"; + type = 15; + } + arg2 + { + title = "Victory trigger tag"; + type = 15; + } + arg3 + { + title = "Pinch trigger tag"; + type = 15; + } } 201 { @@ -3902,6 +3921,25 @@ udmf sprite = "EGGNA1"; width = 24; height = 76; + arg0 + { + title = "Boss ID"; + } + arg1 + { + title = "Death trigger tag"; + type = 15; + } + arg2 + { + title = "Victory trigger tag"; + type = 15; + } + arg3 + { + title = "Pinch trigger tag"; + type = 15; + } } 202 { @@ -3909,6 +3947,25 @@ udmf sprite = "EGGOA1"; width = 32; height = 116; + arg0 + { + title = "Boss ID"; + } + arg1 + { + title = "Death trigger tag"; + type = 15; + } + arg2 + { + title = "Victory trigger tag"; + type = 15; + } + arg3 + { + title = "Pinch trigger tag"; + type = 15; + } } 203 { @@ -3916,6 +3973,30 @@ udmf sprite = "EGGPA1"; width = 24; height = 76; + arg0 + { + title = "Boss ID"; + } + arg1 + { + title = "Death trigger tag"; + type = 15; + } + arg2 + { + title = "Victory trigger tag"; + type = 15; + } + arg3 + { + title = "Pinch trigger tag"; + type = 15; + } + arg4 + { + title = "Cage drop trigger tag"; + type = 15; + } } 204 { @@ -3923,6 +4004,25 @@ udmf sprite = "FANGA1"; width = 24; height = 60; + arg0 + { + title = "Boss ID"; + } + arg1 + { + title = "Death trigger tag"; + type = 15; + } + arg2 + { + title = "Victory trigger tag"; + type = 15; + } + arg3 + { + title = "Pinch trigger tag"; + type = 15; + } } 206 { @@ -3930,6 +4030,30 @@ udmf sprite = "BRAKB1"; width = 48; height = 160; + arg0 + { + title = "Boss ID"; + } + arg1 + { + title = "Death trigger tag"; + type = 15; + } + arg2 + { + title = "Victory trigger tag"; + type = 15; + } + arg3 + { + title = "Pinch trigger tag"; + type = 15; + } + arg4 + { + title = "Platform trigger tag"; + type = 15; + } } 207 { @@ -3944,6 +4068,25 @@ udmf sprite = "METLC1"; width = 16; height = 48; + arg0 + { + title = "Boss ID"; + } + arg1 + { + title = "Death trigger tag"; + type = 15; + } + arg2 + { + title = "Victory trigger tag"; + type = 15; + } + arg3 + { + title = "Pinch trigger tag"; + type = 15; + } } 209 { @@ -3951,6 +4094,30 @@ udmf sprite = "BRAK01"; width = 48; height = 160; + arg0 + { + title = "Boss ID"; + } + arg1 + { + title = "Death trigger tag"; + type = 15; + } + arg2 + { + title = "Victory trigger tag"; + type = 15; + } + arg3 + { + title = "Pinch trigger tag"; + type = 15; + } + arg4 + { + title = "Attack trigger tag"; + type = 15; + } } 290 { diff --git a/src/info.c b/src/info.c index d456d2afe..ddcf6709e 100644 --- a/src/info.c +++ b/src/info.c @@ -1452,7 +1452,7 @@ state_t states[NUMSTATES] = {SPR_FANG, 18, 16, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT1}, // S_FANG_PINCHLOBSHOT0 {SPR_FANG, 19, 2, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT2}, // S_FANG_PINCHLOBSHOT1 {SPR_FANG, 20, 30, {A_Boss5MakeItRain}, MT_FBOMB, -16, S_FANG_PINCHLOBSHOT3}, // S_FANG_PINCHLOBSHOT2 - {SPR_FANG, 20, 18, {A_LinedefExecute}, LE_BOSS4DROP, 0, S_FANG_PINCHLOBSHOT4}, // S_FANG_PINCHLOBSHOT3 + {SPR_FANG, 20, 18, {A_LinedefExecuteFromArg}, 3, 0, S_FANG_PINCHLOBSHOT4}, // S_FANG_PINCHLOBSHOT3 {SPR_FANG, 0, 0, {A_Boss5Calm}, 0, 0, S_FANG_PATHINGSTART1}, // S_FANG_PINCHLOBSHOT4 {SPR_FANG, 21, 0, {A_DoNPCPain}, 0, 0, S_FANG_DIE2}, // S_FANG_DIE1 @@ -1584,7 +1584,7 @@ state_t states[NUMSTATES] = {SPR_BRAK, 21, 3*TICRATE, {NULL}, 0, 0, S_BLACKEGG_DESTROYPLAT2}, // S_BLACKEGG_DESTROYPLAT1 {SPR_BRAK, 21, 1, {A_PlaySound}, sfx_s3k54, 0, S_BLACKEGG_DESTROYPLAT3}, // S_BLACKEGG_DESTROYPLAT2 - {SPR_BRAK, 21, 14, {A_LinedefExecute}, LE_BRAKPLATFORM, 0, S_BLACKEGG_STND}, // S_BLACKEGG_DESTROYPLAT3 + {SPR_BRAK, 21, 14, {A_LinedefExecuteFromArg}, 4, 0, S_BLACKEGG_STND}, // S_BLACKEGG_DESTROYPLAT3 {SPR_NULL, 0, 1, {A_CapeChase}, (160 - 20) << 16, 0, S_BLACKEGG_HELPER}, // S_BLACKEGG_HELPER @@ -1618,7 +1618,7 @@ state_t states[NUMSTATES] = {SPR_BRAK, 26 + FF_FULLBRIGHT, 2, {A_BrakFireShot}, MT_CYBRAKDEMON_FLAMESHOT, 128, S_CYBRAKDEMON_FLAME_ATTACK4}, // S_CYBRAKDEMON_FLAME_ATTACK3 // Fire {SPR_BRAK, 7, 1, {A_Repeat}, 30, S_CYBRAKDEMON_FLAME_ATTACK3, S_CYBRAKDEMON_FINISH_ATTACK1}, // S_CYBRAKDEMON_FLAME_ATTACK4 // Loop {SPR_BRAK, 0, 6, {A_RandomState}, S_CYBRAKDEMON_VILE_ATTACK1, S_CYBRAKDEMON_NAPALM_ATTACK1, S_CYBRAKDEMON_MISSILE_ATTACK1}, // S_CYBRAKDEMON_CHOOSE_ATTACK2 - {SPR_BRAK, 20, 0, {A_LinedefExecute}, LE_BRAKVILEATACK, 0, S_CYBRAKDEMON_VILE_ATTACK2}, // S_CYBRAKDEMON_VILE_ATTACK1 + {SPR_BRAK, 20, 0, {A_LinedefExecuteFromArg}, 4, 0, S_CYBRAKDEMON_VILE_ATTACK2}, // S_CYBRAKDEMON_VILE_ATTACK1 {SPR_BRAK, 20, 24, {A_VileTarget}, MT_CYBRAKDEMON_TARGET_RETICULE, 1, S_CYBRAKDEMON_VILE_ATTACK3}, // S_CYBRAKDEMON_VILE_ATTACK2 {SPR_BRAK, 19, 8, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_VILE_ATTACK4}, // S_CYBRAKDEMON_VILE_ATTACK3 {SPR_BRAK, 18, 8, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_VILE_ATTACK5}, // S_CYBRAKDEMON_VILE_ATTACK4 @@ -1631,7 +1631,7 @@ state_t states[NUMSTATES] = {SPR_BRAK, 0, 0, {A_SetReactionTime}, 0, 0, S_CYBRAKDEMON_WALK1}, // S_CYBRAKDEMON_FINISH_ATTACK2 // If just attacked, remove MF2_FRET w/out going back to spawnstate {SPR_BRAK, 18, 24, {A_Pain}, 0, 0, S_CYBRAKDEMON_PAIN2}, // S_CYBRAKDEMON_PAIN1 {SPR_BRAK, 18, 0, {A_CheckHealth}, 3, S_CYBRAKDEMON_PAIN3, S_CYBRAKDEMON_CHOOSE_ATTACK1}, // S_CYBRAKDEMON_PAIN2 - {SPR_BRAK, 18, 0, {A_LinedefExecute}, LE_PINCHPHASE, 0, S_CYBRAKDEMON_CHOOSE_ATTACK1}, // S_CYBRAKDEMON_PAIN3 + {SPR_BRAK, 18, 0, {A_LinedefExecuteFromArg}, 3, 0, S_CYBRAKDEMON_CHOOSE_ATTACK1}, // S_CYBRAKDEMON_PAIN3 {SPR_BRAK, 18, 1, {A_Repeat}, 1, S_CYBRAKDEMON_DIE1, S_CYBRAKDEMON_DIE2}, // S_CYBRAKDEMON_DIE1 {SPR_BRAK, 18, 2, {A_BossScream}, 2, 0, S_CYBRAKDEMON_DIE3}, // S_CYBRAKDEMON_DIE2 {SPR_BRAK, 18, 0, {A_Repeat}, 52, S_CYBRAKDEMON_DIE2, S_CYBRAKDEMON_DIE4}, // S_CYBRAKDEMON_DIE3 diff --git a/src/p_enemy.c b/src/p_enemy.c index 220f8cf16..5d7cacb36 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3911,7 +3911,8 @@ static void P_DoBossVictory(mobj_t *mo) } // victory! - P_LinedefExecute(LE_ALLBOSSESDEAD, mo, NULL); + if (mo->spawnpoint) + P_LinedefExecute(mo->spawnpoint->args[1], mo, NULL); if (stoppedclock && modeattacking) // if you're just time attacking, skip making the capsule appear since you don't need to step on it anyways. return; @@ -4081,14 +4082,14 @@ static void P_DoBoss5Death(mobj_t *mo) static void P_DoBossDefaultDeath(mobj_t *mo) { - UINT8 extrainfo = (mo->spawnpoint ? mo->spawnpoint->extrainfo : 0); + INT32 bossid = (mo->spawnpoint ? mo->spawnpoint->args[0] : 0); // Stop exploding and prepare to run. P_SetMobjState(mo, mo->info->xdeathstate); if (P_MobjWasRemoved(mo)) return; - P_SetTarget(&mo->target, P_FindBossFlyPoint(mo, extrainfo)); + P_SetTarget(&mo->target, P_FindBossFlyPoint(mo, bossid)); mo->flags |= MF_NOGRAVITY|MF_NOCLIP; mo->flags |= MF_NOCLIPHEIGHT; @@ -4122,12 +4123,12 @@ static void P_DoBossDefaultDeath(mobj_t *mo) void A_BossDeath(mobj_t *mo) { INT32 i; - UINT8 extrainfo = (mo->spawnpoint ? mo->spawnpoint->extrainfo : 0); if (LUA_CallAction(A_BOSSDEATH, mo)) return; - P_LinedefExecute(LE_BOSSDEAD+(extrainfo*LE_PARAMWIDTH), mo, NULL); + if (mo->spawnpoint) + P_LinedefExecute(mo->spawnpoint->args[1], mo, NULL); mo->health = 0; // Boss is dead (but not necessarily fleeing...) @@ -7070,10 +7071,8 @@ void A_Boss1Chase(mobj_t *actor) } else { - if (actor->spawnpoint && actor->spawnpoint->extrainfo) - P_LinedefExecute(LE_PINCHPHASE+(actor->spawnpoint->extrainfo*LE_PARAMWIDTH), actor, NULL); - else - P_LinedefExecute(LE_PINCHPHASE, actor, NULL); + if (actor->spawnpoint) + P_LinedefExecute(actor->spawnpoint->args[3], actor, NULL); P_SetMobjState(actor, actor->info->raisestate); } @@ -8324,8 +8323,6 @@ void A_LinedefExecute(mobj_t *actor) if (locvar2) tagnum += locvar2*(AngleFixed(actor->angle)>>FRACBITS); - else if (actor->spawnpoint && actor->spawnpoint->extrainfo) - tagnum += (actor->spawnpoint->extrainfo*LE_PARAMWIDTH); CONS_Debug(DBG_GAMELOGIC, "A_LinedefExecute: Running mobjtype %d's sector with tag %d\n", actor->type, tagnum); @@ -12714,7 +12711,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) INT32 locvar1 = var1; boolean avoidcenter; INT32 i; - UINT8 extrainfo = (actor->spawnpoint ? actor->spawnpoint->extrainfo : 0); + INT32 bossid = (actor->spawnpoint ? actor->spawnpoint->args[0] : 0); if (LUA_CallAction(A_BOSS5FINDWAYPOINT, actor)) return; @@ -12723,7 +12720,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) if (locvar1 == 2) // look for the boss flypoint { - P_SetTarget(&actor->tracer, P_FindBossFlyPoint(actor, extrainfo)); + P_SetTarget(&actor->tracer, P_FindBossFlyPoint(actor, bossid)); if (!actor->tracer) return; // no boss flypoints found @@ -12735,7 +12732,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) if (avoidcenter) goto nowaypoints; // if we can't go the center, why on earth are we doing this? - TAG_ITER_THINGS(extrainfo, i) + TAG_ITER_THINGS(bossid, i) { if (!mapthings[i].mobj) continue; @@ -12762,7 +12759,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) actor->z += hackoffset; // first, count how many waypoints we have - TAG_ITER_THINGS(extrainfo, i) + TAG_ITER_THINGS(bossid, i) { if (!mapthings[i].mobj) continue; @@ -12817,7 +12814,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) numfangwaypoints = 0; // now find them again and add them to the table! - TAG_ITER_THINGS(extrainfo, i) + TAG_ITER_THINGS(bossid, i) { if (!mapthings[i].mobj) continue; diff --git a/src/p_mobj.c b/src/p_mobj.c index 7e8f4b397..406519e22 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4347,7 +4347,8 @@ static void P_Boss2Thinker(mobj_t *mobj) { mobj->flags &= ~MF_NOGRAVITY; A_Boss2Pogo(mobj); - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); + if (mobj->spawnpoint) + P_LinedefExecute(mobj->spawnpoint->args[3], mobj, NULL); } } @@ -4476,7 +4477,8 @@ static void P_Boss3Thinker(mobj_t *mobj) dummy->cusval = mobj->cusval; CONS_Debug(DBG_GAMELOGIC, "Eggman path %d - Dummy selected paths %d and %d\n", way0, way1, way2); - P_LinedefExecute(LE_PINCHPHASE+(mobj->cusval*LE_PARAMWIDTH), mobj, NULL); + if (mobj->spawnpoint) + P_LinedefExecute(mobj->spawnpoint->args[3], mobj, NULL); } } else if (mobj->movecount) // Firing mode @@ -4642,12 +4644,14 @@ static void P_Boss3Thinker(mobj_t *mobj) // Move Boss4's sectors by delta. static boolean P_Boss4MoveCage(mobj_t *mobj, fixed_t delta) { - const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0); INT32 snum; sector_t *sector; boolean gotcage = false; - TAG_ITER_SECTORS(tag, snum) + if (!mobj->spawnpoint) + return false; + + TAG_ITER_SECTORS(mobj->spawnpoint->args[3], snum) { sector = §ors[snum]; sector->floorheight += delta; @@ -4726,13 +4730,15 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz) // Destroy cage FOFs. static void P_Boss4DestroyCage(mobj_t *mobj) { - const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0); INT32 snum; size_t a; sector_t *sector, *rsec; ffloor_t *rover; - TAG_ITER_SECTORS(tag, snum) + if (!mobj->spawnpoint) + return; + + TAG_ITER_SECTORS(mobj->spawnpoint->args[3], snum) { sector = §ors[snum]; @@ -5005,13 +5011,15 @@ static void P_Boss4Thinker(mobj_t *mobj) { // Proceed to pinch phase! P_Boss4DestroyCage(mobj); mobj->movedir = 3; - P_LinedefExecute(LE_PINCHPHASE + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); + if (mobj->spawnpoint) + P_LinedefExecute(mobj->spawnpoint->args[3], mobj, NULL); P_Boss4MoveSpikeballs(mobj, FixedAngle(mobj->movecount), 0); var1 = 3; A_BossJetFume(mobj); return; } - P_LinedefExecute(LE_BOSS4DROP - (mobj->info->spawnhealth-mobj->health) + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); + if (mobj->spawnpoint) + P_LinedefExecute(mobj->spawnpoint->args[4] - (mobj->info->spawnhealth-mobj->health), mobj, NULL); // 1 -> 1.5 second timer mobj->threshold = TICRATE+(TICRATE*(mobj->info->spawnhealth-mobj->health)/10); if (mobj->threshold < 1) @@ -5043,7 +5051,8 @@ static void P_Boss4Thinker(mobj_t *mobj) { // Proceed to pinch phase! P_Boss4DestroyCage(mobj); mobj->movedir = 3; - P_LinedefExecute(LE_PINCHPHASE + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); + if (mobj->spawnpoint) + P_LinedefExecute(mobj->spawnpoint->args[3], mobj, NULL); var1 = 3; A_BossJetFume(mobj); return; @@ -5183,7 +5192,8 @@ static void P_Boss7Thinker(mobj_t *mobj) // Begin platform destruction mobj->flags2 |= MF2_FRET; P_SetMobjState(mobj, mobj->info->raisestate); - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); + if (mobj->spawnpoint) + P_LinedefExecute(mobj->spawnpoint->args[3], mobj, NULL); } } else if (mobj->state == &states[S_BLACKEGG_HITFACE4] && mobj->tics == mobj->state->tics) @@ -5277,7 +5287,7 @@ static void P_Boss7Thinker(mobj_t *mobj) INT32 i; boolean foundgoop = false; INT32 closestNum; - UINT8 extrainfo = (mobj->spawnpoint ? mobj->spawnpoint->extrainfo : 0); + UINT8 bossid = (mobj->spawnpoint ? mobj->spawnpoint->args[0] : 0); // Looks for players in goop. If you find one, try to jump on him. for (i = 0; i < MAXPLAYERS; i++) @@ -5307,7 +5317,7 @@ static void P_Boss7Thinker(mobj_t *mobj) continue; if (!mo2->spawnpoint) continue; - if (mo2->spawnpoint->extrainfo != extrainfo) + if (mo2->spawnpoint->extrainfo != bossid) continue; if (mobj->health <= mobj->info->damage && !(mo2->spawnpoint->options & 7)) continue; // don't jump to center @@ -5364,7 +5374,7 @@ static void P_Boss7Thinker(mobj_t *mobj) continue; if ((mo2->spawnpoint->options & 7) != waypointNum) continue; - if (mo2->spawnpoint->extrainfo != extrainfo) + if (mo2->spawnpoint->extrainfo != bossid) continue; hitspot = mo2; @@ -6040,7 +6050,8 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->watertop = mobj->floorz + 16*FRACUNIT; else mobj->watertop = mobj->target->floorz + 16*FRACUNIT; - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); + if (mobj->spawnpoint) + P_LinedefExecute(mobj->spawnpoint->args[3], mobj, NULL); #if 0 whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct @@ -10147,7 +10158,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags & MF_NOTHINK) return; - if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && (bossdisabled & (1<spawnpoint->extrainfo))) + if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && (bossdisabled & (1<spawnpoint->args[0]))) return; // Remove dead target/tracer. diff --git a/src/p_setup.c b/src/p_setup.c index ac7d9e919..7fe66148f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3175,6 +3175,8 @@ static line_t *P_FindPointPushLine(taglist_t *list) static void P_ConvertBinaryMap(void) { size_t i; + mobjtype_t mobjtypeofthing[4096]; + mobjtype_t mobjtype; for (i = 0; i < numlines; i++) { @@ -4872,6 +4874,14 @@ static void P_ConvertBinaryMap(void) } } + for (i = 0; i < NUMMOBJTYPES; i++) + { + if (mobjinfo[i].doomednum < 0 || mobjinfo[i].doomednum >= 4096) + continue; + + mobjtypeofthing[mobjinfo[i].doomednum] = (mobjtype_t)i; + } + for (i = 0; i < nummapthings; i++) { if (mapthings[i].type >= 1 && mapthings[i].type <= 35) @@ -4880,6 +4890,19 @@ static void P_ConvertBinaryMap(void) continue; } + mobjtype = mobjtypeofthing[mapthings[i].type]; + if (mobjtype) + { + if (mobjinfo[mobjtype].flags & MF_BOSS) + { + INT32 paramoffset = mapthings[i].extrainfo*LE_PARAMWIDTH; + mapthings[i].args[0] = mapthings[i].extrainfo; + mapthings[i].args[1] = LE_BOSSDEAD + paramoffset; + mapthings[i].args[2] = LE_ALLBOSSESDEAD + paramoffset; + mapthings[i].args[3] = LE_PINCHPHASE + paramoffset; + } + } + switch (mapthings[i].type) { case 102: //SDURF @@ -4901,6 +4924,18 @@ static void P_ConvertBinaryMap(void) case 136: //Pyre Fly mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; + case 203: //Egg Colosseum + mapthings[i].args[4] = LE_BOSS4DROP + mapthings[i].extrainfo * LE_PARAMWIDTH; + break; + case 204: //Fang + mapthings[i].args[3] = LE_BOSS4DROP + mapthings[i].extrainfo*LE_PARAMWIDTH; + break; + case 206: //Brak Eggman (Old) + mapthings[i].args[4] = LE_BRAKPLATFORM + mapthings[i].extrainfo*LE_PARAMWIDTH; + break; + case 209: //Brak Eggman + mapthings[i].args[4] = LE_BRAKVILEATACK + mapthings[i].extrainfo*LE_PARAMWIDTH; + break; case 294: mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; From 8db84ffef9c6da8a845d8c07158a2adb40772651 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Dec 2021 15:37:21 +0100 Subject: [PATCH 220/326] Adapt boss waypoint to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 8 +++ src/p_enemy.c | 24 +++------ src/p_mobj.c | 62 +++++++++------------- src/p_setup.c | 5 ++ 4 files changed, 44 insertions(+), 55 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 31d6b794d..318981f18 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4142,6 +4142,14 @@ udmf width = 8; height = 16; sprite = "internal:eggmanway"; + arg0 + { + title = "Sea Egg sequence"; + } + arg1 + { + title = "Brak Eggman sequence"; + } } 293 { diff --git a/src/p_enemy.c b/src/p_enemy.c index 5d7cacb36..7e00ad91d 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8114,10 +8114,6 @@ void A_Boss3TakeDamage(mobj_t *actor) actor->movecount = var1; actor->movefactor = -512*FRACUNIT; - - /*if (actor->target && actor->target->spawnpoint) - actor->threshold = actor->target->spawnpoint->extrainfo;*/ - } // Function: A_Boss3Path @@ -8157,27 +8153,21 @@ void A_Boss3Path(mobj_t *actor) if (!(actor->flags2 & MF2_STRONGBOX)) { - thinker_t *th; mobj_t *mo2; + INT32 i; P_SetTarget(&actor->target, NULL); - // scan the thinkers - // to find a point that matches - // the number - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + // Find waypoint + TAG_ITER_THINGS(actor->cusval, i) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; + mo2 = mapthings[i].mobj; - mo2 = (mobj_t *)th; + if (!mo2) + continue; if (mo2->type != MT_BOSS3WAYPOINT) continue; - if (!mo2->spawnpoint) - continue; - if (mo2->spawnpoint->angle != actor->threshold) - continue; - if (mo2->spawnpoint->extrainfo != actor->cusval) + if (mapthings[i].args[0] != actor->threshold) continue; P_SetTarget(&actor->target, mo2); diff --git a/src/p_mobj.c b/src/p_mobj.c index 406519e22..b1b9db68a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4520,27 +4520,21 @@ static void P_Boss3Thinker(mobj_t *mobj) if (!(mobj->flags2 & MF2_STRONGBOX)) { - thinker_t *th; mobj_t *mo2; + INT32 i; P_SetTarget(&mobj->tracer, NULL); - // scan the thinkers - // to find a point that matches - // the number - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + // Find waypoint + TAG_ITER_THINGS(mobj->cusval, i) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; + mo2 = mapthings[i].mobj; - mo2 = (mobj_t *)th; + if (!mo2) + continue; if (mo2->type != MT_BOSS3WAYPOINT) continue; - if (!mo2->spawnpoint) - continue; - if (mo2->spawnpoint->angle != mobj->threshold) - continue; - if (mo2->spawnpoint->extrainfo != mobj->cusval) + if (mapthings[i].args[0] != mobj->threshold) continue; P_SetTarget(&mobj->tracer, mo2); @@ -5283,8 +5277,7 @@ static void P_Boss7Thinker(mobj_t *mobj) fixed_t vertical, horizontal; fixed_t airtime = 5*TICRATE; INT32 waypointNum = 0; - thinker_t *th; - INT32 i; + INT32 i, j; boolean foundgoop = false; INT32 closestNum; UINT8 bossid = (mobj->spawnpoint ? mobj->spawnpoint->args[0] : 0); @@ -5307,19 +5300,15 @@ static void P_Boss7Thinker(mobj_t *mobj) closestdist = INT32_MAX; // Just in case... // Find waypoint he is closest to - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + TAG_ITER_THINGS(bossid, j) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; + mo2 = mapthings[j].mobj; - mo2 = (mobj_t *)th; + if (!mo2) + continue; if (mo2->type != MT_BOSS3WAYPOINT) continue; - if (!mo2->spawnpoint) - continue; - if (mo2->spawnpoint->extrainfo != bossid) - continue; - if (mobj->health <= mobj->info->damage && !(mo2->spawnpoint->options & 7)) + if (mobj->health <= mobj->info->damage && !mapthings[j].args[1]) continue; // don't jump to center dist = P_AproxDistance(players[i].mo->x - mo2->x, players[i].mo->y - mo2->y); @@ -5327,7 +5316,7 @@ static void P_Boss7Thinker(mobj_t *mobj) if (!(closestNum == -1 || dist < closestdist)) continue; - closestNum = (mo2->spawnpoint->options & 7); + closestNum = mapthings[j].args[1]; closestdist = dist; foundgoop = true; } @@ -5347,7 +5336,7 @@ static void P_Boss7Thinker(mobj_t *mobj) } if (mobj->tracer && mobj->tracer->type == MT_BOSS3WAYPOINT - && mobj->tracer->spawnpoint && (mobj->tracer->spawnpoint->options & 7) == waypointNum) + && mobj->tracer->spawnpoint && mobj->tracer->spawnpoint->args[1] == waypointNum) { if (P_RandomChance(FRACUNIT/2)) waypointNum++; @@ -5360,28 +5349,25 @@ static void P_Boss7Thinker(mobj_t *mobj) waypointNum = ((waypointNum + 5) % 5); } - // scan the thinkers to find - // the waypoint to use - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + // Scan mapthings to find the waypoint to use + TAG_ITER_THINGS(bossid, i) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + mo2 = mapthings[i].mobj; + + if (!mo2) continue; - mo2 = (mobj_t *)th; if (mo2->type != MT_BOSS3WAYPOINT) continue; - if (!mo2->spawnpoint) - continue; - if ((mo2->spawnpoint->options & 7) != waypointNum) - continue; - if (mo2->spawnpoint->extrainfo != bossid) + + if (mapthings[i].args[1] != waypointNum) continue; hitspot = mo2; break; } - if (hitspot == NULL) + if (!hitspot) { CONS_Debug(DBG_GAMELOGIC, "BlackEggman unable to find waypoint #%d!\n", waypointNum); P_SetMobjState(mobj, mobj->info->spawnstate); @@ -12735,7 +12721,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean } break; case MT_EGGMOBILE3: - mobj->cusval = mthing->extrainfo; + mobj->cusval = mthing->args[0]; break; case MT_FAN: if (mthing->options & MTF_OBJECTSPECIAL) diff --git a/src/p_setup.c b/src/p_setup.c index 7fe66148f..c9237bef8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3131,6 +3131,7 @@ static void P_AddBinaryMapTags(void) Tag_FSet(&mapthings[i].tags, mapthings[i].angle); break; case 290: + case 292: case 294: case 780: Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo); @@ -4936,6 +4937,10 @@ static void P_ConvertBinaryMap(void) case 209: //Brak Eggman mapthings[i].args[4] = LE_BRAKVILEATACK + mapthings[i].extrainfo*LE_PARAMWIDTH; break; + case 292: //Boss waypoint + mapthings[i].args[0] = mapthings[i].angle; + mapthings[i].args[1] = mapthings[i].options & 7; + break; case 294: mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; From 3bab07d036874d613f9dad0841e9ebc99d08c042 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Dec 2021 17:36:16 +0100 Subject: [PATCH 221/326] Adapt flickies to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 39 ++++++++++++++++++ src/p_enemy.c | 48 +++++++++++----------- src/p_local.h | 2 +- src/p_setup.c | 25 ++++++++--- src/p_spec.h | 7 ++++ 5 files changed, 91 insertions(+), 30 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 318981f18..7032dcca5 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -7107,6 +7107,21 @@ udmf title = "Flickies"; width = 8; height = 20; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } 2200 { @@ -7147,6 +7162,30 @@ udmf { title = "Fish"; sprite = "FL08A1"; + arg2 + { + title = "Color"; + type = 11; + enum + { + 0 = "Random"; + 1 = "Red"; + 2 = "Cyan"; + 3 = "Blue"; + 4 = "Vapor"; + 5 = "Purple"; + 6 = "Bubblegum"; + 7 = "Neon"; + 8 = "Black"; + 9 = "Beige"; + 10 = "Lavender"; + 11 = "Ruby"; + 12 = "Salmon"; + 13 = "Sunset"; + 14 = "Orange"; + 15 = "Yellow"; + } + } } 2208 { diff --git a/src/p_enemy.c b/src/p_enemy.c index 7e00ad91d..27f169e20 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -11690,7 +11690,7 @@ void A_FlickySpawn(mobj_t *actor) } // Internal Flicky color setting -void P_InternalFlickySetColor(mobj_t *actor, UINT8 extrainfo) +void P_InternalFlickySetColor(mobj_t *actor, UINT8 color) { UINT8 flickycolors[] = { SKINCOLOR_RED, @@ -11710,11 +11710,11 @@ void P_InternalFlickySetColor(mobj_t *actor, UINT8 extrainfo) SKINCOLOR_YELLOW, }; - if (extrainfo == 0) + if (color == 0) // until we can customize flicky colors by level header, just stick to SRB2's defaults actor->color = flickycolors[P_RandomKey(2)]; //flickycolors[P_RandomKey(sizeof(flickycolors))]; else - actor->color = flickycolors[min(extrainfo-1, 14)]; // sizeof(flickycolors)-1 + actor->color = flickycolors[min(color-1, 14)]; // sizeof(flickycolors)-1 } // Function: A_FlickyCenter @@ -11724,17 +11724,17 @@ void P_InternalFlickySetColor(mobj_t *actor, UINT8 extrainfo) // var1: // Lower 16 bits = if 0, spawns random flicky based on level header. Else, spawns the designated thing type. // Bits 17-20 = Flicky color, up to 15. Applies to fish. -// Bit 21 = Flag MF_SLIDEME (see below) -// Bit 22 = Flag MF_GRENADEBOUNCE (see below) -// Bit 23 = Flag MF_NOCLIPTHING (see below) +// Bit 21 = Flag TMFF_AIMLESS (see below) +// Bit 22 = Flag TMFF_STATIONARY (see below) +// Bit 23 = Flag TMFF_HOP (see below) // // If actor is placed from a spawnpoint (map Thing), the Thing's properties take precedence. // -// var2 = maximum default distance away from spawn the flickies are allowed to travel. If angle != 0, then that's the radius. +// var2 = maximum default distance away from spawn the flickies are allowed to travel. If args[0] != 0, then that's the radius. // -// If MTF_EXTRA (MF_SLIDEME): is flagged, Flickies move aimlessly. Else, orbit around the target. -// If MTF_OBJECTSPECIAL (MF_GRENADEBOUNCE): Flickies stand in-place without gravity (unless they hop, then gravity is applied.) -// If MTF_AMBUSH (MF_NOCLIPTHING): is flagged, Flickies hop. +// If TMFF_AIMLESS (MF_SLIDEME): is flagged, Flickies move aimlessly. Else, orbit around the target. +// If TMFF_STATIONARY (MF_GRENADEBOUNCE): Flickies stand in-place without gravity (unless they hop, then gravity is applied.) +// If TMFF_HOP (MF_NOCLIPTHING): is flagged, Flickies hop. // void A_FlickyCenter(mobj_t *actor) { @@ -11756,14 +11756,15 @@ void A_FlickyCenter(mobj_t *actor) if (actor->spawnpoint) { actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING); - actor->flags |= ( - ((actor->spawnpoint->options & MTF_EXTRA) ? MF_SLIDEME : 0) - | ((actor->spawnpoint->options & MTF_OBJECTSPECIAL) ? MF_GRENADEBOUNCE : 0) - | ((actor->spawnpoint->options & MTF_AMBUSH) ? MF_NOCLIPTHING : 0) - ); - actor->extravalue1 = actor->spawnpoint->angle ? abs(actor->spawnpoint->angle) * FRACUNIT - : locvar2 ? abs(locvar2) : 384 * FRACUNIT; - actor->extravalue2 = actor->spawnpoint->extrainfo; + if (actor->spawnpoint->args[1] & TMFF_AIMLESS) + actor->flags |= MF_SLIDEME; + if (actor->spawnpoint->args[1] & TMFF_STATIONARY) + actor->flags |= MF_GRENADEBOUNCE; + if (actor->spawnpoint->args[1] & TMFF_HOP) + actor->flags |= MF_NOCLIPTHING; + actor->extravalue1 = actor->spawnpoint->args[0] ? abs(actor->spawnpoint->args[0])*FRACUNIT + : locvar2 ? abs(locvar2) : 384*FRACUNIT; + actor->extravalue2 = actor->spawnpoint->args[2]; actor->friction = actor->spawnpoint->x*FRACUNIT; actor->movefactor = actor->spawnpoint->y*FRACUNIT; actor->watertop = actor->spawnpoint->z*FRACUNIT; @@ -11771,11 +11772,12 @@ void A_FlickyCenter(mobj_t *actor) else { actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING); - actor->flags |= ( - ((flickyflags & 1) ? MF_SLIDEME : 0) - | ((flickyflags & 2) ? MF_GRENADEBOUNCE : 0) - | ((flickyflags & 4) ? MF_NOCLIPTHING : 0) - ); + if (flickyflags & TMFF_AIMLESS) + actor->flags |= MF_SLIDEME; + if (flickyflags & TMFF_STATIONARY) + actor->flags |= MF_GRENADEBOUNCE; + if (flickyflags & TMFF_HOP) + actor->flags |= MF_NOCLIPTHING; actor->extravalue1 = abs(locvar2); actor->extravalue2 = flickycolor; actor->friction = actor->x; diff --git a/src/p_local.h b/src/p_local.h index bbcd86b39..11a4856cf 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -370,7 +370,7 @@ void P_NewChaseDir(mobj_t *actor); boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed_t dist); mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers, SINT8 moveforward); -void P_InternalFlickySetColor(mobj_t *actor, UINT8 extrainfo); +void P_InternalFlickySetColor(mobj_t *actor, UINT8 color); #define P_IsFlickyCenter(type) (type > MT_FLICKY_01 && type < MT_SEED && (type - MT_FLICKY_01) % 2 ? 1 : 0) void P_InternalFlickyBubble(mobj_t *actor); void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez); diff --git a/src/p_setup.c b/src/p_setup.c index c9237bef8..5e9daa327 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4885,12 +4885,6 @@ static void P_ConvertBinaryMap(void) for (i = 0; i < nummapthings; i++) { - if (mapthings[i].type >= 1 && mapthings[i].type <= 35) - { - mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); - continue; - } - mobjtype = mobjtypeofthing[mapthings[i].type]; if (mobjtype) { @@ -4904,6 +4898,25 @@ static void P_ConvertBinaryMap(void) } } + if (mapthings[i].type >= 1 && mapthings[i].type <= 35) //Player starts + { + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + continue; + } + else if (mapthings[i].type >= 2200 && mapthings[i].type <= 2217) //Flickies + { + mapthings[i].args[0] = mapthings[i].angle; + if (mapthings[i].options & MTF_EXTRA) + mapthings[i].args[1] |= TMFF_AIMLESS; + if (mapthings[i].options & MTF_OBJECTSPECIAL) + mapthings[i].args[1] |= TMFF_STATIONARY; + if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[1] |= TMFF_HOP; + if (mapthings[i].type == 2207) + mapthings[i].args[2] = mapthings[i].extrainfo; + continue; + } + switch (mapthings[i].type) { case 102: //SDURF diff --git a/src/p_spec.h b/src/p_spec.h index 88dc6d9f8..53d7cd511 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -50,6 +50,13 @@ typedef enum TMSF_INTANGIBLE = 1<<1, } textmapspikeflags_t; +typedef enum +{ + TMFF_AIMLESS = 1, + TMFF_STATIONARY = 1<<1, + TMFF_HOP = 1<<2, +} textmapflickyflags_t; + //FOF flags typedef enum { From 720df51b6edd031050411d1c268b311703bcb4b8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Dec 2021 17:58:18 +0100 Subject: [PATCH 222/326] Adapt most flame jet settings to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 24 ++++++++++++++++++++++ src/p_mobj.c | 16 +++++---------- src/p_setup.c | 6 ++++++ 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 7032dcca5..b07a7f8a7 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -6110,6 +6110,18 @@ udmf sprite = "internal:flameh"; width = 16; height = 40; + arg0 + { + title = "On time"; + } + arg1 + { + title = "Off time"; + } + arg2 + { + title = "Strength"; + } } 1301 { @@ -6117,6 +6129,18 @@ udmf sprite = "internal:flamev"; width = 16; height = 40; + arg0 + { + title = "On time"; + } + arg1 + { + title = "Off time"; + } + arg2 + { + title = "Strength"; + } } 1302 { diff --git a/src/p_mobj.c b/src/p_mobj.c index b1b9db68a..7a9b50c3d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7226,8 +7226,7 @@ static void P_FlameJetSceneryThink(mobj_t *mobj) else flame->angle += FixedAngle(mobj->fuse<movedir; + strength = (mobj->movedir ? mobj->movedir : 80)<<(FRACBITS-2); P_InstaThrust(flame, flame->angle, strength); S_StartSound(flame, sfx_fire); @@ -7257,8 +7256,7 @@ static void P_VerticalFlameJetSceneryThink(mobj_t *mobj) flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); - strength = 20*FRACUNIT; - strength -= ((20*FRACUNIT)/16)*mobj->movedir; + strength = (mobj->movedir ? mobj->movedir : 80)<<(FRACBITS-2); // If deaf'd, the object spawns on the ceiling. if (mobj->flags2 & MF2_AMBUSH) @@ -12797,13 +12795,9 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; case MT_FLAMEJET: case MT_VERTICALFLAMEJET: - mobj->threshold = (mthing->angle >> 10) & 7; - mobj->movecount = (mthing->angle >> 13); - - mobj->threshold *= (TICRATE/2); - mobj->movecount *= (TICRATE/2); - - mobj->movedir = mthing->extrainfo; + mobj->movecount = mthing->args[0]; + mobj->threshold = mthing->args[1]; + mobj->movedir = mthing->args[2]; break; case MT_MACEPOINT: case MT_CHAINMACEPOINT: diff --git a/src/p_setup.c b/src/p_setup.c index 5e9daa327..dee0c86de 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5141,6 +5141,12 @@ static void P_ConvertBinaryMap(void) P_WriteConstant(MT_ROCKCRUMBLE1 + (sides[lines[j].sidenum[0]].rowoffset >> FRACBITS), &mapthings[i].stringargs[0]); break; } + case 1300: //Flame jet (horizontal) + case 1301: //Flame jet (vertical) + mapthings[i].args[0] = (mapthings[i].angle >> 13)*TICRATE/2; + mapthings[i].args[1] = ((mapthings[i].angle >> 10) & 7)*TICRATE/2; + mapthings[i].args[2] = 80 - 5*mapthings[i].extrainfo; + break; case 1700: //Axis mapthings[i].args[2] = mapthings[i].angle & 16383; mapthings[i].args[3] = !!(mapthings[i].angle & 16384); From fd3fa9a924c248853b0f679f7abb33d1f0525268 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Dec 2021 18:52:46 +0100 Subject: [PATCH 223/326] Adapt flame-related objects to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 46 ++++++++++++++++++++++ src/p_mobj.c | 10 ++--- src/p_setup.c | 16 ++++++++ src/p_spec.h | 6 +++ 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index b07a7f8a7..523c29c56 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -5409,6 +5409,12 @@ udmf sprite = "FLAMA0E0"; width = 8; height = 32; + arg0 + { + title = "Corona?"; + type = 11; + enum = "noyes"; + } } 1102 { @@ -5798,6 +5804,12 @@ udmf sprite = "CNDLA0"; width = 8; height = 48; + arg0 + { + title = "Corona?"; + type = 11; + enum = "noyes"; + } } 1120 { @@ -5805,6 +5817,12 @@ udmf sprite = "CNDLB0"; width = 8; height = 176; + arg0 + { + title = "Corona?"; + type = 11; + enum = "noyes"; + } } 1121 { @@ -5812,6 +5830,16 @@ udmf sprite = "FLMHA0"; width = 24; height = 80; + arg0 + { + title = "Flags"; + type = 12; + enum + { + 1 = "No flame"; + 2 = "Add corona"; + } + } } 1122 { @@ -7045,6 +7073,12 @@ udmf sprite = "PUMKA0"; width = 16; height = 40; + arg0 + { + title = "Flicker"; + type = 11; + enum = "yesno"; + } } 2007 { @@ -7052,6 +7086,12 @@ udmf sprite = "PUMKB0"; width = 16; height = 40; + arg0 + { + title = "Flicker"; + type = 11; + enum = "yesno"; + } } 2008 { @@ -7059,6 +7099,12 @@ udmf sprite = "PUMKC0"; width = 16; height = 40; + arg0 + { + title = "Flicker"; + type = 11; + enum = "yesno"; + } } 2009 { diff --git a/src/p_mobj.c b/src/p_mobj.c index 7a9b50c3d..7514b18bd 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12754,7 +12754,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->color = ((mthing->angle - 1) % (numskincolors - 1)) + 1; break; case MT_FLAME: - if (mthing->options & MTF_EXTRA) + if (mthing->args[0]) { mobj_t *corona = P_MakeSoftwareCorona(mobj, 20); P_SetScale(corona, (corona->destscale = mobj->scale*3)); @@ -12762,12 +12762,12 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean } break; case MT_FLAMEHOLDER: - if (!(mthing->options & MTF_OBJECTSPECIAL)) // Spawn the fire + if (!(mthing->args[0] & TMFH_NOFLAME)) // Spawn the fire { mobj_t *flame = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_FLAME); P_SetTarget(&flame->target, mobj); flame->flags2 |= MF2_BOSSNOTRAP; - if (mthing->options & MTF_EXTRA) + if (mthing->args[0] & TMFH_CORONA) { mobj_t *corona = P_MakeSoftwareCorona(flame, 20); P_SetScale(corona, (corona->destscale = flame->scale*3)); @@ -12777,13 +12777,13 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; case MT_CANDLE: case MT_CANDLEPRICKET: - if (mthing->options & MTF_EXTRA) + if (mthing->args[0]) P_MakeSoftwareCorona(mobj, ((mobj->type == MT_CANDLE) ? 42 : 176)); break; case MT_JACKO1: case MT_JACKO2: case MT_JACKO3: - if (!(mthing->options & MTF_EXTRA)) // take the torch out of the crafting recipe + if (!(mthing->args[0])) // take the torch out of the crafting recipe { mobj_t *overlay = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_OVERLAY); P_SetTarget(&overlay->target, mobj); diff --git a/src/p_setup.c b/src/p_setup.c index dee0c86de..1b05ab219 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5124,6 +5124,17 @@ static void P_ConvertBinaryMap(void) } break; } + case 1101: //Torch + case 1119: //Candle + case 1120: //Candle pricket + mapthings[i].args[0] = !!(mapthings[i].options & MTF_EXTRA); + break; + case 1121: //Flame holder + if (mapthings[i].options & MTF_OBJECTSPECIAL) + mapthings[i].args[0] |= TMFH_NOFLAME; + if (mapthings[i].options & MTF_EXTRA) + mapthings[i].args[0] |= TMFH_CORONA; + break; case 1202: //Rock spawner { mtag_t tag = (mtag_t)mapthings[i].angle; @@ -5197,6 +5208,11 @@ static void P_ConvertBinaryMap(void) case 1807: //Axe mapthings[i].args[0] = LE_AXE; break; + case 2006: //Jack-o'-lantern 1 + case 2007: //Jack-o'-lantern 2 + case 2008: //Jack-o'-lantern 3 + mapthings[i].args[0] = !!(mapthings[i].options & MTF_EXTRA); + break; default: break; } diff --git a/src/p_spec.h b/src/p_spec.h index 53d7cd511..3bd3b0d5c 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -57,6 +57,12 @@ typedef enum TMFF_HOP = 1<<2, } textmapflickyflags_t; +typedef enum +{ + TMFH_NOFLAME = 1, + TMFH_CORONA = 1<<1, +} textmapflameholderflags_t; + //FOF flags typedef enum { From 43a15387d296e71b7916929332093f6a227880ac Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 27 Dec 2021 21:28:42 +0100 Subject: [PATCH 224/326] Adapt diagonal springs to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 30 ++++++++++++++++++++++ src/p_mobj.c | 16 +++++++----- src/p_setup.c | 8 ++++++ src/p_spec.h | 6 +++++ 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 523c29c56..41a99d1d7 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4722,6 +4722,16 @@ udmf title = "Diagonal Yellow Spring"; sprite = "YSPRD2"; width = 16; + arg0 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Ignore gravity"; + 2 = "Rotate 22.5° CCW"; + } + } } 556 { @@ -4729,6 +4739,16 @@ udmf title = "Diagonal Red Spring"; sprite = "RSPRD2"; width = 16; + arg0 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Ignore gravity"; + 2 = "Rotate 22.5° CCW"; + } + } } 557 { @@ -4736,6 +4756,16 @@ udmf title = "Diagonal Blue Spring"; sprite = "BSPRD2"; width = 16; + arg0 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Ignore gravity"; + 2 = "Rotate 22.5° CCW"; + } + } } 558 { diff --git a/src/p_mobj.c b/src/p_mobj.c index 7514b18bd..018d853f6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13050,6 +13050,16 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (maptol & TOL_XMAS) P_SetMobjState(mobj, mobj->info->seestate); break; + case MT_YELLOWDIAG: + case MT_REDDIAG: + case MT_BLUEDIAG: + mobj->angle = FixedAngle(mthing->angle << FRACBITS); + if (mthing->args[0] & TMDS_NOGRAVITY) + mobj->flags |= MF_NOGRAVITY; + if (mthing->args[0] & TMDS_ROTATEEXTRA) + mobj->angle += ANGLE_22h; + *doangle = false; + break; default: break; } @@ -13065,9 +13075,6 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean 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 @@ -13095,9 +13102,6 @@ static void P_SetAmbush(mobj_t *mobj) 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 diff --git a/src/p_setup.c b/src/p_setup.c index 1b05ab219..783446298 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4990,6 +4990,14 @@ static void P_ConvertBinaryMap(void) if (mapthings[i].options & MTF_AMBUSH) mapthings[i].args[2] |= TMSF_INTANGIBLE; break; + case 555: //Diagonal yellow spring + case 556: //Diagonal red spring + case 557: //Diagonal blue spring + if (mapthings[i].options & MTF_OBJECTSPECIAL) + mapthings[i].args[0] |= TMDS_NOGRAVITY; + if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[0] |= TMDS_ROTATEEXTRA; + break; case 750: //Slope vertex mapthings[i].args[0] = mapthings[i].extrainfo; break; diff --git a/src/p_spec.h b/src/p_spec.h index 3bd3b0d5c..743c37744 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -63,6 +63,12 @@ typedef enum TMFH_CORONA = 1<<1, } textmapflameholderflags_t; +typedef enum +{ + TMDS_NOGRAVITY = 1, + TMDS_ROTATEEXTRA = 1<<1, +} textmapdiagonalspringflags_t; + //FOF flags typedef enum { From 90eb7c71a348351631d56ccb80fdc8934dac20f9 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 07:29:41 +0100 Subject: [PATCH 225/326] Adapt skybox view point to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 10 ++++++++++ src/p_mobj.c | 2 +- src/p_setup.c | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 41a99d1d7..f1ed572c1 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -5142,6 +5142,16 @@ udmf { title = "Skybox View Point"; sprite = "internal:skyb"; + arg0 + { + title = "Type"; + type = 11; + enum + { + 0 = "Viewpoint"; + 1 = "Centerpoint"; + } + } } } diff --git a/src/p_mobj.c b/src/p_mobj.c index 018d853f6..250935cc5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12705,7 +12705,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; } - if (mthing->options & MTF_OBJECTSPECIAL) + if (mthing->args[0]) skyboxcenterpnts[tag] = mobj; else skyboxviewpnts[tag] = mobj; diff --git a/src/p_setup.c b/src/p_setup.c index 783446298..1027b92e2 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5079,6 +5079,9 @@ static void P_ConvertBinaryMap(void) mapthings[i].type = 761; break; } + case 780: //Skybox + mapthings[i].args[0] = !!(mapthings[i].options & MTF_OBJECTSPECIAL); + break; case 1104: //Mace spawnpoint case 1105: //Chain with maces spawnpoint case 1106: //Chained spring spawnpoint From b1d087051112a6d1faaa6f9609c596cc0016bc17 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 07:40:38 +0100 Subject: [PATCH 226/326] (Mostly) adapt fan to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 10 ++++++++++ src/p_map.c | 2 +- src/p_mobj.c | 6 +++--- src/p_setup.c | 4 ++++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index f1ed572c1..4aa66b87d 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4680,6 +4680,16 @@ udmf sprite = "FANSA0D0"; width = 16; height = 8; + arg0 + { + title = "Lift height"; + } + arg1 + { + title = "Invisible?"; + type = 11; + enum = "noyes"; + } } 541 { diff --git a/src/p_map.c b/src/p_map.c index 836e75c4e..7caf5eca5 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -492,7 +492,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) switch (spring->type) { case MT_FAN: // fan - if (zdist > (spring->health << FRACBITS)) // max z distance determined by health (set by map thing angle) + if (zdist > (spring->health << FRACBITS)) // max z distance determined by health (set by map thing args[0]) break; if (flipval*object->momz >= FixedMul(speed, spring->scale)) // if object's already moving faster than your best, don't bother break; diff --git a/src/p_mobj.c b/src/p_mobj.c index 250935cc5..22a500715 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12722,7 +12722,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->cusval = mthing->args[0]; break; case MT_FAN: - if (mthing->options & MTF_OBJECTSPECIAL) + if (mthing->args[1]) { P_UnsetThingPosition(mobj); if (sector_list) @@ -12733,8 +12733,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->flags |= MF_NOSECTOR; // this flag basically turns it invisible P_SetThingPosition(mobj); } - if (mthing->angle) - mobj->health = mthing->angle; + if (mthing->args[0]) + mobj->health = mthing->args[0]; else mobj->health = FixedMul(mobj->subsector->sector->ceilingheight - mobj->subsector->sector->floorheight, 3*(FRACUNIT/4)) >> FRACBITS; break; diff --git a/src/p_setup.c b/src/p_setup.c index 1027b92e2..3a7b70b95 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4990,6 +4990,10 @@ static void P_ConvertBinaryMap(void) if (mapthings[i].options & MTF_AMBUSH) mapthings[i].args[2] |= TMSF_INTANGIBLE; break; + case 540: //Fan + mapthings[i].args[0] = mapthings[i].angle; + mapthings[i].args[1] = !!(mapthings[i].options & MTF_OBJECTSPECIAL); + break; case 555: //Diagonal yellow spring case 556: //Diagonal red spring case 557: //Diagonal blue spring From 8b69c621114325d2fbc3a60cabe0c92a2a87d711 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 08:19:56 +0100 Subject: [PATCH 227/326] Adapt more scenery items to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 36 ++++++++++++++++++++++ src/p_mobj.c | 12 ++++---- src/p_setup.c | 15 +++++++++ 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 4aa66b87d..250934fad 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -5351,6 +5351,10 @@ udmf width = 8; height = 16; hangs = 1; + arg0 + { + title = "Dripping delay"; + } } 1003 { @@ -5386,6 +5390,12 @@ udmf sprite = "KELPA0"; width = 16; height = 292; + arg0 + { + title = "Double size?"; + type = 11; + enum = "noyes"; + } } 1008 { @@ -5393,6 +5403,12 @@ udmf sprite = "DSTGA0"; width = 8; height = 116; + arg0 + { + title = "Double size?"; + type = 11; + enum = "noyes"; + } } 1010 { @@ -5408,6 +5424,12 @@ udmf sprite = "DSTGA0"; width = 8; height = 116; + arg0 + { + title = "Double size?"; + type = 11; + enum = "noyes"; + } } 1012 { @@ -6240,6 +6262,16 @@ udmf sprite = "LFALF0"; width = 30; height = 32; + arg0 + { + title = "Initial delay"; + } + arg1 + { + title = "Double size?"; + type = 11; + enum = "noyes"; + } } 1305 { @@ -7081,6 +7113,10 @@ udmf sprite = "FMCEA0"; width = 18; height = 28; + arg0 + { + title = "Initial delay"; + } } 2001 { diff --git a/src/p_mobj.c b/src/p_mobj.c index 22a500715..aaefa9fed 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12791,7 +12791,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean } break; case MT_WATERDRIP: - mobj->tics = 3*TICRATE + mthing->angle; + mobj->tics = 3*TICRATE + mthing->args[0]; break; case MT_FLAMEJET: case MT_VERTICALFLAMEJET: @@ -12856,7 +12856,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean case MT_DSZSTALAGMITE: case MT_DSZ2STALAGMITE: case MT_KELP: - if (mthing->options & MTF_OBJECTSPECIAL) { // make mobj twice as big as normal + if (mthing->args[0]) { // make mobj twice as big as normal P_SetScale(mobj, 2*mobj->scale); // not 2*FRACUNIT in case of something like the old ERZ3 mode mobj->destscale = mobj->scale; } @@ -12896,12 +12896,12 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean } break; case MT_SMASHINGSPIKEBALL: - if (mthing->angle > 0) - mobj->tics += mthing->angle; + if (mthing->args[0] > 0) + mobj->tics += mthing->args[0]; break; case MT_LAVAFALL: - mobj->fuse = 30 + mthing->angle; - if (mthing->options & MTF_AMBUSH) + mobj->fuse = 30 + mthing->args[0]; + if (mthing->args[1]) { P_SetScale(mobj, 2*mobj->scale); mobj->destscale = mobj->scale; diff --git a/src/p_setup.c b/src/p_setup.c index 3a7b70b95..b25b3aa14 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5086,6 +5086,14 @@ static void P_ConvertBinaryMap(void) case 780: //Skybox mapthings[i].args[0] = !!(mapthings[i].options & MTF_OBJECTSPECIAL); break; + case 1002: //Dripping water + mapthings[i].args[0] = mapthings[i].angle; + break; + case 1007: //Kelp + case 1008: //Stalagmite (DSZ1) + case 1011: //Stalagmite (DSZ2) + mapthings[i].args[0] = !!(mapthings[i].options & MTF_OBJECTSPECIAL); + break; case 1104: //Mace spawnpoint case 1105: //Chain with maces spawnpoint case 1106: //Chained spring spawnpoint @@ -5173,6 +5181,10 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[1] = ((mapthings[i].angle >> 10) & 7)*TICRATE/2; mapthings[i].args[2] = 80 - 5*mapthings[i].extrainfo; break; + case 1304: //Lavafall + mapthings[i].args[0] = mapthings[i].angle; + mapthings[i].args[1] = !!(mapthings[i].options & MTF_AMBUSH); + break; case 1700: //Axis mapthings[i].args[2] = mapthings[i].angle & 16383; mapthings[i].args[3] = !!(mapthings[i].angle & 16384); @@ -5223,6 +5235,9 @@ static void P_ConvertBinaryMap(void) case 1807: //Axe mapthings[i].args[0] = LE_AXE; break; + case 2000: //Smashing spikeball + mapthings[i].args[0] = mapthings[i].angle; + break; case 2006: //Jack-o'-lantern 1 case 2007: //Jack-o'-lantern 2 case 2008: //Jack-o'-lantern 3 From e140bd82528db6ee89bd30ca14df62a4f29f2bf7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 08:26:04 +0100 Subject: [PATCH 228/326] Adapt balloon colors to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 4 ++++ src/p_mobj.c | 4 ++-- src/p_setup.c | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 250934fad..4453edace 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4710,6 +4710,10 @@ udmf sprite = "BLONA0"; width = 32; height = 64; + stringarg0 + { + title = "Color"; + } } 550 { diff --git a/src/p_mobj.c b/src/p_mobj.c index aaefa9fed..bf413572f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12750,8 +12750,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean } break; case MT_BALLOON: - if (mthing->angle > 0) - mobj->color = ((mthing->angle - 1) % (numskincolors - 1)) + 1; + if (mthing->stringargs[0]) + mobj->color = get_number(mthing->stringargs[0]); break; case MT_FLAME: if (mthing->args[0]) diff --git a/src/p_setup.c b/src/p_setup.c index b25b3aa14..dfabc0e9f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4994,6 +4994,10 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[0] = mapthings[i].angle; mapthings[i].args[1] = !!(mapthings[i].options & MTF_OBJECTSPECIAL); break; + case 543: //Balloon + if (mapthings[i].angle > 0) + P_WriteConstant(((mapthings[i].angle - 1) % (numskincolors - 1)) + 1, &mapthings[i].stringargs[0]); + break; case 555: //Diagonal yellow spring case 556: //Diagonal red spring case 557: //Diagonal blue spring From 52482716190980add0f6416a2c1b8cf8899d98d9 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 08:33:57 +0100 Subject: [PATCH 229/326] Adapt blast linedef executor to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 5 +++++ src/p_inter.c | 2 +- src/p_setup.c | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 4453edace..d2c13154d 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -5099,6 +5099,11 @@ udmf sprite = "TOADA0"; width = 32; height = 16; + arg0 + { + title = "Linedef tag"; + type = 15; + } } 757 { diff --git a/src/p_inter.c b/src/p_inter.c index 62f6080bc..9a3562fc8 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2771,7 +2771,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget case MT_BLASTEXECUTOR: if (target->spawnpoint) - P_LinedefExecute(target->spawnpoint->angle, (source ? source : inflictor), target->subsector->sector); + P_LinedefExecute(target->spawnpoint->args[0], (source ? source : inflictor), target->subsector->sector); break; case MT_SPINBOBERT: diff --git a/src/p_setup.c b/src/p_setup.c index dfabc0e9f..54f887d60 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5048,6 +5048,9 @@ static void P_ConvertBinaryMap(void) mapthings[i].type = 754; break; } + case 756: //Blast linedef executor + mapthings[i].args[0] = mapthings[i].angle; + break; case 757: //Fan particle generator { INT32 j = Tag_FindLineSpecial(15, mapthings[i].angle); From 1cff7a161aff241841133c53131a123b99b97dbe Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 09:58:45 +0100 Subject: [PATCH 230/326] Adapt ambient sound effects to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 70 +---- src/info.c | 285 +-------------------- src/info.h | 12 +- src/m_cheat.c | 2 +- src/p_mobj.c | 13 +- src/p_mobj.h | 2 +- src/p_setup.c | 27 ++ 7 files changed, 53 insertions(+), 358 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index d2c13154d..58c4fe53d 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4965,68 +4965,16 @@ udmf 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"; + title = "Ambient Sound Effect"; sprite = "internal:ambiance"; + arg0 + { + title = "Repeat speed"; + } + stringarg0 + { + title = "Sound"; + } } 750 diff --git a/src/info.c b/src/info.c index ddcf6709e..51f9ea8e6 100644 --- a/src/info.c +++ b/src/info.c @@ -18056,13 +18056,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - // ambient water 1a (large) - { // MT_AWATERA + // ambient sound effect + { // MT_AMBIENT 700, // doomednum S_INVISIBLE, // spawnstate - 35, // spawnhealth + 1000, // spawnhealth S_NULL, // seestate - sfx_amwtr1, // seesound + sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate @@ -18084,283 +18084,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - // ambient water 1b (large) - { // MT_AWATERB - 701, // doomednum - S_INVISIBLE, // spawnstate - 35, // spawnhealth - S_NULL, // seestate - sfx_amwtr2, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY|MF_AMBIENT, // flags - S_NULL // raisestate - }, - - // ambient water 2a (medium) - { // MT_AWATERC - 702, // doomednum - S_INVISIBLE, // spawnstate - 35, // spawnhealth - S_NULL, // seestate - sfx_amwtr3, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY|MF_AMBIENT, // flags - S_NULL // raisestate - }, - - // ambient water 2b (medium) - { // MT_AWATERD - 703, // doomednum - S_INVISIBLE, // spawnstate - 35, // spawnhealth - S_NULL, // seestate - sfx_amwtr4, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY|MF_AMBIENT, // flags - S_NULL // raisestate - }, - - // ambient water 3a (small) - { // MT_AWATERE - 704, // doomednum - S_INVISIBLE, // spawnstate - 35, // spawnhealth - S_NULL, // seestate - sfx_amwtr5, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY|MF_AMBIENT, // flags - S_NULL // raisestate - }, - - // ambient water 3b (small) - { // MT_AWATERF - 705, // doomednum - S_INVISIBLE, // spawnstate - 35, // spawnhealth - S_NULL, // seestate - sfx_amwtr6, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY|MF_AMBIENT, // flags - S_NULL // raisestate - }, - - // ambient water 4a (extra large) - { // MT_AWATERG - 706, // doomednum - S_INVISIBLE, // spawnstate - 35, // spawnhealth - S_NULL, // seestate - sfx_amwtr7, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY|MF_AMBIENT, // flags - S_NULL // raisestate - }, - - // ambient water 4b (extra large) - { // MT_AWATERH - 707, // doomednum - S_INVISIBLE, // spawnstate - 35, // spawnhealth - S_NULL, // seestate - sfx_amwtr8, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY|MF_AMBIENT, // flags - S_NULL // raisestate - }, - - { // MT_RANDOMAMBIENT - 708, // doomednum - S_INVISIBLE, // spawnstate - 512, // spawnhealth: repeat speed - S_NULL, // seestate - sfx_ambint, // seesound - 0, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 255, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 1000, // mass - 0, // damage - sfx_None, // activesound - MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_AMBIENT, // flags - S_NULL // raisestate - }, - - { // MT_RANDOMAMBIENT2 - 709, // doomednum - S_INVISIBLE, // spawnstate - 220, // spawnhealth: repeat speed - S_NULL, // seestate - sfx_ambin2, // seesound - 0, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 255, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 1000, // mass - 0, // damage - sfx_None, // activesound - MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_AMBIENT, // flags - S_NULL // raisestate - }, - - { // MT_MACHINEAMBIENCE - 710, // doomednum - S_INVISIBLE, // spawnstate - 24, // spawnhealth: repeat speed - S_NULL, // seestate - sfx_ambmac, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 200, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 1*FRACUNIT, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 100, // mass - 20, // damage - sfx_None, // activesound - MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_AMBIENT, // flags - S_NULL // raisestate - }, - { // MT_CORK -1, // doomednum S_CORK, // spawnstate diff --git a/src/info.h b/src/info.h index d5fcc8504..7b33f92ba 100644 --- a/src/info.h +++ b/src/info.h @@ -4934,17 +4934,7 @@ typedef enum mobj_type MT_FINISHFLAG, // Finish flag // Ambient Sounds - MT_AWATERA, // Ambient Water Sound 1 - MT_AWATERB, // Ambient Water Sound 2 - MT_AWATERC, // Ambient Water Sound 3 - MT_AWATERD, // Ambient Water Sound 4 - MT_AWATERE, // Ambient Water Sound 5 - MT_AWATERF, // Ambient Water Sound 6 - MT_AWATERG, // Ambient Water Sound 7 - MT_AWATERH, // Ambient Water Sound 8 - MT_RANDOMAMBIENT, - MT_RANDOMAMBIENT2, - MT_MACHINEAMBIENCE, + MT_AMBIENT, MT_CORK, MT_LHRT, diff --git a/src/m_cheat.c b/src/m_cheat.c index b5c3b6563..2f90b54ee 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1004,7 +1004,7 @@ static void OP_CycleThings(INT32 amt) } while (mobjinfo[op_currentthing].doomednum == -1 || op_currentthing == MT_NIGHTSDRONE - || mobjinfo[op_currentthing].flags & (MF_AMBIENT|MF_NOSECTOR) + || mobjinfo[op_currentthing].flags & MF_NOSECTOR || (states[mobjinfo[op_currentthing].spawnstate].sprite == SPR_NULL && states[mobjinfo[op_currentthing].seestate].sprite == SPR_NULL) ); diff --git a/src/p_mobj.c b/src/p_mobj.c index bf413572f..55f7a729a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10230,10 +10230,12 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags2 & MF2_FIRING) P_FiringThink(mobj); - if (mobj->flags & MF_AMBIENT) + if (mobj->type == MT_AMBIENT) { - if (!(leveltime % mobj->health) && mobj->info->seesound) - S_StartSound(mobj, mobj->info->seesound); + if (leveltime % mobj->health) + return; + if (mobj->threshold) + S_StartSound(mobj, mobj->threshold); return; } @@ -13060,6 +13062,11 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->angle += ANGLE_22h; *doangle = false; break; + case MT_AMBIENT: + if (mthing->stringargs[0]) + mobj->threshold = get_number(mthing->stringargs[0]); + mobj->health = mthing->args[0] ? mthing->args[0] : TICRATE; + break; default: break; } diff --git a/src/p_mobj.h b/src/p_mobj.h index 2d096385b..23028f995 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -118,7 +118,7 @@ typedef enum // Don't apply gravity (every tic); object will float, keeping current height // or changing it actively. MF_NOGRAVITY = 1<<9, - // This object is an ambient sound. + // This object is an ambient sound. Obsolete, but keep this around for backwards compatibility. MF_AMBIENT = 1<<10, // Slide this object when it hits a wall. MF_SLIDEME = 1<<11, diff --git a/src/p_setup.c b/src/p_setup.c index 54f887d60..37893f4c8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5006,6 +5006,33 @@ static void P_ConvertBinaryMap(void) if (mapthings[i].options & MTF_AMBUSH) mapthings[i].args[0] |= TMDS_ROTATEEXTRA; break; + case 700: //Water ambience A + case 701: //Water ambience A + case 702: //Water ambience A + case 703: //Water ambience A + case 704: //Water ambience A + case 705: //Water ambience A + case 706: //Water ambience A + case 707: //Water ambience A + mapthings[i].args[0] = 35; + P_WriteConstant(sfx_amwtr1 + mapthings[i].type - 700, &mapthings[i].stringargs[0]); + mapthings[i].type = 700; + break; + case 708: //Disco ambience + mapthings[i].args[0] = 512; + P_WriteConstant(sfx_ambint, &mapthings[i].stringargs[0]); + mapthings[i].type = 700; + break; + case 709: //Volcano ambience + mapthings[i].args[0] = 220; + P_WriteConstant(sfx_ambin2, &mapthings[i].stringargs[0]); + mapthings[i].type = 700; + break; + case 710: //Machine ambience + mapthings[i].args[0] = 24; + P_WriteConstant(sfx_ambmac, &mapthings[i].stringargs[0]); + mapthings[i].type = 700; + break; case 750: //Slope vertex mapthings[i].args[0] = mapthings[i].extrainfo; break; From 5d1284bc81dbe31efc8b21c750ffa5d4296dd803 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 11:42:53 +0100 Subject: [PATCH 231/326] Fix unitialized array in P_ConvertBinaryMap --- 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 37893f4c8..492c0aabc 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3176,7 +3176,7 @@ static line_t *P_FindPointPushLine(taglist_t *list) static void P_ConvertBinaryMap(void) { size_t i; - mobjtype_t mobjtypeofthing[4096]; + mobjtype_t mobjtypeofthing[4096] = {0}; mobjtype_t mobjtype; for (i = 0; i < numlines; i++) From b4a206c063d2ac43c7e3aa7732f7db6ede56ac3a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 13:14:48 +0100 Subject: [PATCH 232/326] Adapt remaining enemies to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 125 ++++++++++++++++++++- src/p_enemy.c | 21 +++- src/p_mobj.c | 53 ++++++++- src/p_setup.c | 37 +++++- src/p_spec.h | 13 +++ 5 files changed, 235 insertions(+), 14 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 58c4fe53d..102805b1b 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3607,6 +3607,12 @@ udmf sprite = "BUZZA1"; width = 28; height = 40; + arg0 + { + title = "Can move?"; + type = 11; + enum = "yesno"; + } } 104 { @@ -3614,6 +3620,12 @@ udmf sprite = "RBUZA1"; width = 28; height = 40; + arg0 + { + title = "Can move?"; + type = 11; + enum = "yesno"; + } } 108 { @@ -3674,6 +3686,16 @@ udmf sprite = "CRABA0"; width = 24; height = 32; + arg0 + { + title = "Spawn direction"; + type = 11; + enum + { + 0 = "Right"; + 1 = "Left"; + } + } } 138 { @@ -3681,6 +3703,16 @@ udmf sprite = "CR2BA0"; width = 24; height = 32; + arg0 + { + title = "Spawn direction"; + type = 11; + enum + { + 0 = "Right"; + 1 = "Left"; + } + } } 117 { @@ -3688,6 +3720,12 @@ udmf sprite = "ARCHA1"; width = 24; height = 32; + arg0 + { + title = "Can jump?"; + type = 11; + enum = "yesno"; + } } 118 { @@ -3709,6 +3747,23 @@ udmf sprite = "ESHIA1"; width = 16; height = 48; + arg0 + { + title = "Turn direction"; + type = 11; + enum + { + 0 = "Back"; + 1 = "Right"; + 2 = "Left"; + } + } + arg1 + { + title = "Double speed?"; + type = 11; + enum = "noyes"; + } } 115 { @@ -3784,6 +3839,12 @@ udmf sprite = "JETBB1"; width = 20; height = 50; + arg0 + { + title = "Can move?"; + type = 11; + enum = "yesno"; + } } 106 { @@ -3791,6 +3852,12 @@ udmf sprite = "JETGB1"; width = 20; height = 48; + arg0 + { + title = "Can move?"; + type = 11; + enum = "yesno"; + } } 112 { @@ -3840,6 +3907,12 @@ udmf sprite = "CACOA0"; width = 32; height = 32; + arg0 + { + title = "Can move?"; + type = 11; + enum = "yesno"; + } } 133 { @@ -3866,6 +3939,12 @@ udmf sprite = "BUMBA1"; width = 16; height = 32; + arg0 + { + title = "Can move?"; + type = 11; + enum = "yesno"; + } } 124 { @@ -4551,6 +4630,12 @@ udmf sprite = "BUBLE0"; width = 8; height = 16; + arg0 + { + title = "Distance check?"; + type = 11; + enum = "yesno"; + } } 501 { @@ -4686,9 +4771,13 @@ udmf } arg1 { - title = "Invisible?"; - type = 11; - enum = "noyes"; + title = "Flags"; + type = 12; + enum + { + 1 = "Invisible"; + 2 = "No distance check"; + } } } 541 @@ -4710,6 +4799,12 @@ udmf sprite = "BLONA0"; width = 32; height = 64; + arg0 + { + title = "Respawn?"; + type = 11; + enum = "noyes"; + } stringarg0 { title = "Color"; @@ -5942,6 +6037,12 @@ udmf sprite = "BTBLA0"; width = 24; height = 48; + arg0 + { + title = "Move perpetually?"; + type = 11; + enum = "noyes"; + } } 1201 { @@ -5949,6 +6050,12 @@ udmf sprite = "STBLA0"; width = 12; height = 24; + arg0 + { + title = "Move perpetually?"; + type = 11; + enum = "noyes"; + } } 1202 { @@ -6608,6 +6715,12 @@ udmf sprite = "NTPNALAR"; width = 16; height = 32; + arg0 + { + title = "Can move?"; + type = 11; + enum = "yesno"; + } } } @@ -6727,6 +6840,12 @@ udmf 3 = "Top"; } } + arg4 + { + title = "Die upon time up?"; + type = 11; + enum = "noyes"; + } } 1704 { diff --git a/src/p_enemy.c b/src/p_enemy.c index 27f169e20..e077b3926 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -7909,12 +7909,21 @@ void A_GuardChase(mobj_t *actor) false) && speed > 0) // can't be the same check as previous so that P_TryMove gets to happen. { - if (actor->spawnpoint && ((actor->spawnpoint->options & (MTF_EXTRA|MTF_OBJECTSPECIAL)) == MTF_OBJECTSPECIAL)) - actor->angle += ANGLE_90; - else if (actor->spawnpoint && ((actor->spawnpoint->options & (MTF_EXTRA|MTF_OBJECTSPECIAL)) == MTF_EXTRA)) - actor->angle -= ANGLE_90; - else - actor->angle += ANGLE_180; + INT32 direction = actor->spawnpoint ? actor->spawnpoint->args[0] : TMGD_BACK; + + switch (direction) + { + case TMGD_BACK: + default: + actor->angle += ANGLE_180; + break; + case TMGD_RIGHT: + actor->angle -= ANGLE_90; + break; + case TMGD_LEFT: + actor->angle += ANGLE_90; + break; + } } if (actor->extravalue1 < actor->info->speed) diff --git a/src/p_mobj.c b/src/p_mobj.c index 55f7a729a..aa27c4015 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2681,7 +2681,7 @@ boolean P_ZMovement(mobj_t *mo) { if (mo->flags2 & MF2_AMBUSH) { - // If deafed, give the tumbleweed another random kick if it runs out of steam. + // Give the tumbleweed another random kick if it runs out of steam. mom.z += P_MobjFlip(mo)*FixedMul(6*FRACUNIT, mo->scale); if (P_RandomChance(FRACUNIT/2)) @@ -12504,6 +12504,9 @@ static boolean P_SetupNiGHTSDrone(mapthing_t *mthing, mobj_t *mobj) else mobj->height = mobjinfo[MT_NIGHTSDRONE].height; + if (mthing->args[4]) + mobj->flags2 |= MF2_AMBUSH; //Kill player upon time up + droneboxmandiff = max(mobj->height - mobjinfo[MT_NIGHTSDRONE_MAN].height, 0); dronemangoaldiff = max(mobjinfo[MT_NIGHTSDRONE_MAN].height - mobjinfo[MT_NIGHTSDRONE_GOAL].height, 0); @@ -12723,8 +12726,12 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean case MT_EGGMOBILE3: mobj->cusval = mthing->args[0]; break; + case MT_BUBBLES: + if (mthing->args[0]) + mobj->flags2 |= MF2_AMBUSH; + break; case MT_FAN: - if (mthing->args[1]) + if (mthing->args[1] & TMF_INVISIBLE) { P_UnsetThingPosition(mobj); if (sector_list) @@ -12735,6 +12742,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->flags |= MF_NOSECTOR; // this flag basically turns it invisible P_SetThingPosition(mobj); } + if (mthing->args[1] & TMF_NODISTANCECHECK) + mobj->flags2 |= MF2_AMBUSH; if (mthing->args[0]) mobj->health = mthing->args[0]; else @@ -12754,6 +12763,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean case MT_BALLOON: if (mthing->stringargs[0]) mobj->color = get_number(mthing->stringargs[0]); + if (mthing->args[0]) + mobj->flags2 |= MF2_AMBUSH; break; case MT_FLAME: if (mthing->args[0]) @@ -13032,12 +13043,13 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; case MT_BIGTUMBLEWEED: case MT_LITTLETUMBLEWEED: - if (mthing->options & MTF_AMBUSH) + if (mthing->args[0]) { 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; + mobj->flags2 |= MF2_AMBUSH; } break; case MT_REDFLAG: @@ -13067,6 +13079,23 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->threshold = get_number(mthing->stringargs[0]); mobj->health = mthing->args[0] ? mthing->args[0] : TICRATE; break; + case MT_GOLDBUZZ: + case MT_REDBUZZ: + case MT_JETTBOMBER: + case MT_JETTGUNNER: + case MT_ROBOHOOD: + case MT_CRUSHSTACEAN: + case MT_BANPYURA: + case MT_BUMBLEBORE: + case MT_CACOLANTERN: + case MT_PIAN: + if (mthing->args[0]) + mobj->flags2 |= MF2_AMBUSH; + break; + case MT_EGGGUARD: + if (mthing->args[1]) + mobj->flags2 |= MF2_AMBUSH; + break; default: break; } @@ -13099,10 +13128,28 @@ static void P_SetAmbush(mobj_t *mobj) mobj->flags2 |= MF2_AMBUSH; } + //TODO: Make this obsolete else if (mobj->type != MT_AXIS && mobj->type != MT_AXISTRANSFER && mobj->type != MT_AXISTRANSFERLINE && mobj->type != MT_NIGHTSBUMPER && + mobj->type != MT_NIGHTSDRONE && + mobj->type != MT_BALLOON && + mobj->type != MT_BIGTUMBLEWEED && + mobj->type != MT_LITTLETUMBLEWEED && + mobj->type != MT_BUBBLES && + mobj->type != MT_FAN && + mobj->type != MT_ROBOHOOD && + mobj->type != MT_CRUSHSTACEAN && + mobj->type != MT_BANPYURA && + mobj->type != MT_GOLDBUZZ && + mobj->type != MT_REDBUZZ && + mobj->type != MT_JETTBOMBER && + mobj->type != MT_JETTGUNNER && + mobj->type != MT_BUMBLEBORE && + mobj->type != MT_CACOLANTERN && + mobj->type != MT_PIAN && + mobj->type != MT_EGGGUARD && mobj->type != MT_STARPOST) mobj->flags2 |= MF2_AMBUSH; } diff --git a/src/p_setup.c b/src/p_setup.c index 492c0aabc..8333c21f3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4929,6 +4929,27 @@ static void P_ConvertBinaryMap(void) case 111: //Pop-up Turret mapthings[i].args[0] = mapthings[i].angle; break; + case 103: //Buzz (Gold) + case 104: //Buzz (Red) + case 105: //Jetty-syn Bomber + case 106: //Jetty-syn Gunner + case 117: //Robo-Hood + case 126: //Crushstacean + case 128: //Bumblebore + case 132: //Cacolantern + case 138: //Banpyura + case 1602: //Pian + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + break; + case 119: //Egg Guard + if ((mapthings[i].options & (MTF_EXTRA|MTF_OBJECTSPECIAL)) == MTF_OBJECTSPECIAL) + mapthings[i].args[0] = TMGD_LEFT; + else if ((mapthings[i].options & (MTF_EXTRA|MTF_OBJECTSPECIAL)) == MTF_EXTRA) + mapthings[i].args[0] = TMGD_RIGHT; + else + mapthings[i].args[0] = TMGD_BACK; + mapthings[i].args[1] = !!(mapthings[i].options & MTF_AMBUSH); + break; case 127: //Hive Elemental mapthings[i].args[0] = mapthings[i].extrainfo; break; @@ -4954,7 +4975,10 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[0] = mapthings[i].angle; mapthings[i].args[1] = mapthings[i].options & 7; break; - case 294: + case 294: //Fang waypoint + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + break; + case 500: //Air bubble patch mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; case 502: //Star post @@ -4992,11 +5016,15 @@ static void P_ConvertBinaryMap(void) break; case 540: //Fan mapthings[i].args[0] = mapthings[i].angle; - mapthings[i].args[1] = !!(mapthings[i].options & MTF_OBJECTSPECIAL); + if (mapthings[i].options & MTF_OBJECTSPECIAL) + mapthings[i].args[1] |= TMF_INVISIBLE; + if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[1] |= TMF_NODISTANCECHECK; break; case 543: //Balloon if (mapthings[i].angle > 0) P_WriteConstant(((mapthings[i].angle - 1) % (numskincolors - 1)) + 1, &mapthings[i].stringargs[0]); + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; case 555: //Diagonal yellow spring case 556: //Diagonal red spring @@ -5192,6 +5220,10 @@ static void P_ConvertBinaryMap(void) if (mapthings[i].options & MTF_EXTRA) mapthings[i].args[0] |= TMFH_CORONA; break; + case 1200: //Tumbleweed (Big) + case 1201: //Tumbleweed (Small) + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + break; case 1202: //Rock spawner { mtag_t tag = (mtag_t)mapthings[i].angle; @@ -5240,6 +5272,7 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[3] = TMDA_MIDDLE; else mapthings[i].args[3] = TMDA_BOTTOMOFFSET; + mapthings[i].args[4] = !!(mapthings[i].options & MTF_AMBUSH); break; case 1704: //NiGHTS bumper mapthings[i].pitch = 30 * (((mapthings[i].options & 15) + 9) % 12); diff --git a/src/p_spec.h b/src/p_spec.h index 743c37744..697a140ea 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -69,6 +69,19 @@ typedef enum TMDS_ROTATEEXTRA = 1<<1, } textmapdiagonalspringflags_t; +typedef enum +{ + TMF_INVISIBLE = 1, + TMF_NODISTANCECHECK = 1<<1, +} textmapfanflags_t; + +typedef enum +{ + TMGD_BACK = 0, + TMGD_RIGHT = 1, + TMGD_LEFT = 2, +} textmapguarddirection_t; + //FOF flags typedef enum { From 42f823600c1c874731e3b4805ccdb84b8db468d8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 14:01:45 +0100 Subject: [PATCH 233/326] Adapt NiGHTS items to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 50 ++++++++++++++++++++++ src/p_mobj.c | 23 +++++----- src/p_setup.c | 7 +++ src/p_spec.h | 6 +++ 4 files changed, 75 insertions(+), 11 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 102805b1b..d0dc85cc5 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -6866,26 +6866,76 @@ udmf { title = "Super Paraloop"; sprite = "NPRUA0"; + arg0 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Bonus time only"; + 2 = "Spawn immediately"; + } + } } 1708 { title = "Drill Refill"; sprite = "NPRUB0"; + arg0 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Bonus time only"; + 2 = "Spawn immediately"; + } + } } 1709 { title = "Nightopian Helper"; sprite = "NPRUC0"; + arg0 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Bonus time only"; + 2 = "Spawn immediately"; + } + } } 1711 { title = "Extra Time"; sprite = "NPRUD0"; + arg0 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Bonus time only"; + 2 = "Spawn immediately"; + } + } } 1712 { title = "Link Freeze"; sprite = "NPRUE0"; + arg0 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Bonus time only"; + 2 = "Spawn immediately"; + } + } } 1713 { diff --git a/src/p_mobj.c b/src/p_mobj.c index aa27c4015..c1d0fb7ac 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13105,19 +13105,24 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (mthing->options & MTF_OBJECTSPECIAL) // No egg trap for this boss mobj->flags2 |= MF2_BOSSNOTRAP; } + if (mobj->flags & MF_NIGHTSITEM) + { + // Requires you to be in bonus time to activate + if (mthing->args[0] & TMNI_BONUSONLY) + mobj->flags2 |= MF2_STRONGBOX; + // Spawn already displayed + if (mthing->args[0] & TMNI_REVEAL) + { + mobj->flags |= MF_SPECIAL; + mobj->flags &= ~MF_NIGHTSITEM; + } + } return true; } static void P_SetAmbush(mobj_t *mobj) { - 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; @@ -13163,10 +13168,6 @@ static void P_SetObjectSpecial(mobj_t *mobj) 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) { diff --git a/src/p_setup.c b/src/p_setup.c index 8333c21f3..5431b0124 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4896,6 +4896,13 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[2] = LE_ALLBOSSESDEAD + paramoffset; mapthings[i].args[3] = LE_PINCHPHASE + paramoffset; } + if (mobjinfo[mobjtype].flags & MF_NIGHTSITEM) + { + if (mapthings[i].options & MTF_OBJECTSPECIAL) + mapthings[i].args[0] |= TMNI_BONUSONLY; + if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[0] |= TMNI_REVEAL; + } } if (mapthings[i].type >= 1 && mapthings[i].type <= 35) //Player starts diff --git a/src/p_spec.h b/src/p_spec.h index 697a140ea..61ad5d6e4 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -82,6 +82,12 @@ typedef enum TMGD_LEFT = 2, } textmapguarddirection_t; +typedef enum +{ + TMNI_BONUSONLY = 1, + TMNI_REVEAL = 1<<1, +} textmapnightsitem_t; + //FOF flags typedef enum { From 53931727bddb9a51b0eed348ba23eb1722fd36f3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 14:28:36 +0100 Subject: [PATCH 234/326] Adapt pushables to UDMF --- extras/conf/udb/Includes/SRB222_misc.cfg | 8 ++ extras/conf/udb/Includes/SRB222_things.cfg | 96 ++++++++++++++++++++++ src/p_mobj.c | 44 +++++----- src/p_setup.c | 11 +++ src/p_spec.h | 8 ++ 5 files changed, 146 insertions(+), 21 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 2111c198b..dbcd22629 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -582,6 +582,14 @@ enums 64 = "Clip inside ground"; 128 = "No distance check"; } + + pushablebehavior + { + 0 = "Normal"; + 1 = "Slide"; + 2 = "Immovable"; + 3 = "Classic"; + } } //Default things filters diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index d0dc85cc5..649ddd647 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3740,6 +3740,12 @@ udmf sprite = "CBBSA1"; width = 32; height = 72; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 119 { @@ -5379,6 +5385,12 @@ udmf sprite = "GARGA1"; width = 16; height = 40; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1009 { @@ -5388,6 +5400,12 @@ udmf sprite = "GARGB1"; width = 32; height = 80; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1001 { @@ -5548,6 +5566,12 @@ udmf sprite = "ESTAA1"; width = 32; height = 240; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1103 { @@ -5875,6 +5899,12 @@ udmf sprite = "CSTAA1"; width = 16; height = 40; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1112 { @@ -5884,6 +5914,12 @@ udmf sprite = "CBBSA1"; width = 32; height = 72; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1114 { @@ -5986,6 +6022,12 @@ udmf sprite = "CBLLA0"; width = 20; height = 40; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1125 { @@ -6182,6 +6224,12 @@ udmf sprite = "BARRA1"; width = 24; height = 63; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1217 { @@ -6637,6 +6685,12 @@ udmf sprite = "BGARA1"; width = 16; height = 40; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1501 { @@ -6646,6 +6700,12 @@ udmf sprite = "BGARA1"; width = 16; height = 40; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1502 { @@ -6655,6 +6715,12 @@ udmf sprite = "BGARA1"; width = 16; height = 40; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1503 { @@ -6664,6 +6730,12 @@ udmf sprite = "BGARA1"; width = 16; height = 40; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1504 { @@ -6687,6 +6759,12 @@ udmf sprite = "BGARD1"; width = 16; height = 40; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } } @@ -7078,6 +7156,12 @@ udmf sprite = "XMS3A0"; width = 16; height = 64; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1853 { @@ -7086,6 +7170,12 @@ udmf sprite = "XMS3B0"; width = 16; height = 80; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } 1854 { @@ -7146,6 +7236,12 @@ udmf sprite = "ESTAB1"; width = 20; height = 96; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } } } diff --git a/src/p_mobj.c b/src/p_mobj.c index c1d0fb7ac..4fe3e02ac 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13117,15 +13117,31 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->flags &= ~MF_NIGHTSITEM; } } + if (mobj->flags & MF_PUSHABLE) + { + switch (mthing->args[0]) + { + case TMP_NORMAL: + default: + break; + case TMP_SLIDE: + mobj->flags2 |= MF2_SLIDEPUSH; + mobj->flags |= MF_BOUNCE; + break; + case TMP_IMMOVABLE: + mobj->flags &= ~MF_PUSHABLE; + break; + case TMP_CLASSIC: + mobj->flags2 |= MF2_CLASSICPUSH; + break; + } + } return true; } static void P_SetAmbush(mobj_t *mobj) { - if (mobj->flags & MF_PUSHABLE) - mobj->flags &= ~MF_PUSHABLE; - if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) { // flag for strong/weak random boxes @@ -13167,13 +13183,6 @@ static void P_SetObjectSpecial(mobj_t *mobj) // any monitor with nonzero speed is allowed to respawn like this 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; - } } static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, mobjtype_t i) @@ -13202,18 +13211,11 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, if (i == MT_NIGHTSBUMPER) return mobj; - if ((mthing->options & MTF_AMBUSH) - && (mthing->options & MTF_OBJECTSPECIAL) - && (mobj->flags & MF_PUSHABLE)) - mobj->flags2 |= MF2_CLASSICPUSH; - else - { - if (mthing->options & MTF_AMBUSH) - P_SetAmbush(mobj); + if (mthing->options & MTF_AMBUSH) + P_SetAmbush(mobj); - if (mthing->options & MTF_OBJECTSPECIAL) - P_SetObjectSpecial(mobj); - } + if (mthing->options & MTF_OBJECTSPECIAL) + P_SetObjectSpecial(mobj); // Generic reverse gravity for individual objects flag. if (mthing->options & MTF_OBJECTFLIP) diff --git a/src/p_setup.c b/src/p_setup.c index 5431b0124..de6eb1c93 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4903,6 +4903,17 @@ static void P_ConvertBinaryMap(void) if (mapthings[i].options & MTF_AMBUSH) mapthings[i].args[0] |= TMNI_REVEAL; } + if (mobjinfo[mobjtype].flags & MF_PUSHABLE) + { + if ((mapthings[i].options & (MTF_OBJECTSPECIAL|MTF_AMBUSH)) == (MTF_OBJECTSPECIAL|MTF_AMBUSH)) + mapthings[i].args[0] = TMP_CLASSIC; + else if (mapthings[i].options & MTF_OBJECTSPECIAL) + mapthings[i].args[0] = TMP_SLIDE; + else if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[0] = TMP_IMMOVABLE; + else + mapthings[i].args[0] = TMP_NORMAL; + } } if (mapthings[i].type >= 1 && mapthings[i].type <= 35) //Player starts diff --git a/src/p_spec.h b/src/p_spec.h index 61ad5d6e4..220376903 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -88,6 +88,14 @@ typedef enum TMNI_REVEAL = 1<<1, } textmapnightsitem_t; +typedef enum +{ + TMP_NORMAL = 0, + TMP_SLIDE = 1, + TMP_IMMOVABLE = 2, + TMP_CLASSIC = 3, +} textmappushabletype_t; + //FOF flags typedef enum { From 79c3197de2c40bb8f91582cebceda46f736ec6f2 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 16:38:52 +0100 Subject: [PATCH 235/326] Adapt various thing types for UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 135 +++++++++++++++++++++ src/p_inter.c | 2 +- src/p_mobj.c | 45 +++++-- src/p_setup.c | 57 +++++++++ src/p_spec.h | 7 ++ 5 files changed, 236 insertions(+), 10 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 649ddd647..02d90eacf 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4265,6 +4265,12 @@ udmf width = 24; height = 24; sprite = "RINGA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } 300 { @@ -4380,6 +4386,12 @@ udmf sprite = "TOKEA0"; width = 16; height = 32; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 313 { @@ -4420,11 +4432,23 @@ udmf { title = "Emerald Hunt Location"; sprite = "SHRDA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 321 { title = "Match Chaos Emerald Spawn"; sprite = "CEMGA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 322 { @@ -4432,6 +4456,12 @@ udmf sprite = "EMBMA0"; width = 16; height = 30; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } } @@ -4661,6 +4691,12 @@ udmf { title = "Order"; } + arg1 + { + title = "Respawn at center?"; + type = 11; + enum = "noyes"; + } } 520 { @@ -4668,6 +4704,12 @@ udmf sprite = "SPHRD0"; width = 16; height = 24; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 521 { @@ -4675,6 +4717,12 @@ udmf sprite = "SPIKA0"; width = 12; height = 8; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 522 { @@ -4791,6 +4839,12 @@ udmf title = "Gas Jet"; sprite = "STEMD0"; width = 32; + arg0 + { + title = "Play sound?"; + type = 11; + enum = "noyes"; + } } 542 { @@ -4889,6 +4943,12 @@ udmf sprite = "SSWYD2D8"; width = 16; height = 32; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 559 { @@ -4897,6 +4957,12 @@ udmf sprite = "SSWRD2D8"; width = 16; height = 32; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 560 { @@ -4905,6 +4971,12 @@ udmf sprite = "SSWBD2D8"; width = 16; height = 32; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 1134 { @@ -4927,6 +4999,12 @@ udmf sprite = "BSTYA0"; width = 28; height = 2; + arg0 + { + title = "Force spin?"; + type = 11; + enum = "noyes"; + } } 545 { @@ -4935,6 +5013,12 @@ udmf sprite = "BSTRA0"; width = 28; height = 2; + arg0 + { + title = "Force spin?"; + type = 11; + enum = "noyes"; + } } } @@ -5572,6 +5656,12 @@ udmf type = 11; enum = "pushablebehavior"; } + arg1 + { + title = "Solid gold?"; + type = 11; + enum = "noyes"; + } } 1103 { @@ -6049,6 +6139,17 @@ udmf sprite = "EGR1A1"; width = 20; height = 72; + arg0 + { + title = "Movement"; + type = 11; + enum + { + 0 = "None"; + 1 = "Right"; + 2 = "Left"; + } + } } 1128 { @@ -6265,6 +6366,12 @@ udmf sprite = "SALDARAL"; width = 96; height = 160; + arg0 + { + title = "Allow non-minecart players?"; + type = 11; + enum = "noyes"; + } } 1222 { @@ -6293,6 +6400,16 @@ udmf sprite = "internal:zoom"; width = 8; height = 16; + arg0 + { + title = "Type"; + type = 11; + enum + { + 0 = "Disable"; + 1 = "Enable"; + } + } } 1230 { @@ -6391,6 +6508,12 @@ udmf sprite = "PUMIA1A5"; width = 30; height = 60; + arg0 + { + title = "Buoyant?"; + type = 11; + enum = "yesno"; + } } 1306 { @@ -6939,6 +7062,12 @@ udmf sprite = "SPHRA0"; width = 16; height = 24; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 1707 { @@ -7051,6 +7180,12 @@ udmf sprite = "COINA0"; width = 16; height = 24; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 1801 { diff --git a/src/p_inter.c b/src/p_inter.c index 9a3562fc8..028ac0ef3 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1437,7 +1437,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Misc touchables // // *************** // case MT_STARPOST: - P_TouchStarPost(special, player, special->spawnpoint && (special->spawnpoint->options & MTF_OBJECTSPECIAL)); + P_TouchStarPost(special, player, special->spawnpoint && special->spawnpoint->args[1]); return; case MT_FAKEMOBILE: diff --git a/src/p_mobj.c b/src/p_mobj.c index 4fe3e02ac..fa3bba57a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8590,9 +8590,9 @@ static boolean P_EggRobo1Think(mobj_t *mobj) { fixed_t basex = mobj->cusval, basey = mobj->cvmem; - if (mobj->spawnpoint && mobj->spawnpoint->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)) + if (mobj->spawnpoint && mobj->spawnpoint->args[0] != TMED_NONE) { - angle_t sideang = mobj->movedir + ((mobj->spawnpoint->options & MTF_AMBUSH) ? ANGLE_90 : -ANGLE_90); + angle_t sideang = mobj->movedir + ((mobj->spawnpoint->args[0] == TMED_LEFT) ? 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); @@ -11775,14 +11775,14 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt dz = 288*FRACUNIT; break; - // Horizontal springs, may float additional units with MTF_AMBUSH. + // Horizontal springs, float additional units unless args[0] is set. case MT_YELLOWHORIZ: case MT_REDHORIZ: case MT_BLUEHORIZ: - offset += mthing->options & MTF_AMBUSH ? 16*FRACUNIT : 0; + offset += mthing->args[0] ? 0 : 16*FRACUNIT; break; - // Ring-like items, may float additional units with MTF_AMBUSH. + // Ring-like items, float additional units unless args[0] is set. case MT_SPIKEBALL: case MT_EMERHUNT: case MT_EMERALDSPAWN: @@ -11796,13 +11796,13 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt case MT_BOMBSPHERE: case MT_NIGHTSCHIP: case MT_NIGHTSSTAR: - offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; + offset += mthing->args[0] ? 0 : 24*FRACUNIT; break; // Remaining objects. default: if (P_WeaponOrPanel(mobjtype)) - offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; + offset += mthing->args[0] ? 0 : 24*FRACUNIT; } if (!(dz + offset)) // Snap to the surfaces when there's no offset set. @@ -12717,7 +12717,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; } case MT_EGGSTATUE: - if (mthing->options & MTF_EXTRA) + if (mthing->args[1]) { mobj->color = SKINCOLOR_GOLD; mobj->colorized = true; @@ -13096,6 +13096,22 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (mthing->args[1]) mobj->flags2 |= MF2_AMBUSH; break; + case MT_STEAM: + if (mthing->args[0]) + mobj->flags2 |= MF2_AMBUSH; + break; + case MT_SALOONDOORCENTER: + if (mthing->args[0]) + mobj->flags2 |= MF2_AMBUSH; + break; + case MT_MINECARTSWITCHPOINT: + if (mthing->args[0]) + mobj->flags2 |= MF2_AMBUSH; + break; + case MT_ROLLOUTSPAWN: + if (mthing->args[0]) + mobj->flags2 |= MF2_AMBUSH; + break; default: break; } @@ -13136,6 +13152,12 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; } } + if (mobj->flags & MF_SPRING && mobj->info->painchance == 3) + { + if (mthing->args[0]) + mobj->flags2 |= MF2_AMBUSH; + } + return true; } @@ -13171,7 +13193,12 @@ static void P_SetAmbush(mobj_t *mobj) mobj->type != MT_CACOLANTERN && mobj->type != MT_PIAN && mobj->type != MT_EGGGUARD && - mobj->type != MT_STARPOST) + mobj->type != MT_STEAM && + mobj->type != MT_SALOONDOORCENTER && + mobj->type != MT_MINECARTSWITCHPOINT && + mobj->type != MT_ROLLOUTSPAWN && + mobj->type != MT_STARPOST && + !(mobj->flags & MF_SPRING && mobj->info->painchance == 3)) mobj->flags2 |= MF2_AMBUSH; } diff --git a/src/p_setup.c b/src/p_setup.c index de6eb1c93..c267167fe 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4914,6 +4914,8 @@ static void P_ConvertBinaryMap(void) else mapthings[i].args[0] = TMP_NORMAL; } + if (mobjinfo[mobjtype].flags & MF_SPRING && mobjinfo[mobjtype].painchance == 3) + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); } if (mapthings[i].type >= 1 && mapthings[i].type <= 35) //Player starts @@ -4996,6 +4998,32 @@ static void P_ConvertBinaryMap(void) case 294: //Fang waypoint mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; + case 300: //Ring + case 301: //Bounce ring + case 302: //Rail ring + case 303: //Infinity ring + case 304: //Automatic ring + case 305: //Explosion ring + case 306: //Scatter ring + case 307: //Grenade ring + case 308: //Red team ring + case 309: //Blue team ring + case 312: //Emerald token + case 320: //Emerald hunt location + case 321: //Match chaos emerald spawn + case 322: //Emblem + case 330: //Bounce ring panel + case 331: //Rail ring panel + case 332: //Automatic ring panel + case 333: //Explosion ring panel + case 334: //Scatter ring panel + case 335: //Grenade ring panel + case 520: //Bomb sphere + case 521: //Spikeball + case 1706: //Blue sphere + case 1800: //Coin + mapthings[i].args[0] = !(mapthings[i].options & MTF_AMBUSH); + break; case 500: //Air bubble patch mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; @@ -5009,6 +5037,7 @@ static void P_ConvertBinaryMap(void) else // Old behavior if Parameter is 0; add 360 to the angle for each consecutive star post. mapthings[i].args[0] = (mapthings[i].angle/360); + mapthings[i].args[1] = !!(mapthings[i].options & MTF_OBJECTSPECIAL); break; case 522: //Wall spike if (mapthings[i].options & MTF_OBJECTSPECIAL) @@ -5039,6 +5068,9 @@ static void P_ConvertBinaryMap(void) if (mapthings[i].options & MTF_AMBUSH) mapthings[i].args[1] |= TMF_NODISTANCECHECK; break; + case 541: //Gas jet + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + break; case 543: //Balloon if (mapthings[i].angle > 0) P_WriteConstant(((mapthings[i].angle - 1) % (numskincolors - 1)) + 1, &mapthings[i].stringargs[0]); @@ -5052,6 +5084,11 @@ static void P_ConvertBinaryMap(void) if (mapthings[i].options & MTF_AMBUSH) mapthings[i].args[0] |= TMDS_ROTATEEXTRA; break; + case 558: //Horizontal yellow spring + case 559: //Horizontal red spring + case 560: //Horizontal blue spring + mapthings[i].args[0] = !(mapthings[i].options & MTF_AMBUSH); + break; case 700: //Water ambience A case 701: //Water ambience A case 702: //Water ambience A @@ -5174,6 +5211,9 @@ static void P_ConvertBinaryMap(void) case 1011: //Stalagmite (DSZ2) mapthings[i].args[0] = !!(mapthings[i].options & MTF_OBJECTSPECIAL); break; + case 1102: //Eggman Statue + mapthings[i].args[1] = !!(mapthings[i].options & MTF_EXTRA); + break; case 1104: //Mace spawnpoint case 1105: //Chain with maces spawnpoint case 1106: //Chained spring spawnpoint @@ -5238,6 +5278,14 @@ static void P_ConvertBinaryMap(void) if (mapthings[i].options & MTF_EXTRA) mapthings[i].args[0] |= TMFH_CORONA; break; + case 1127: //Spectator EggRobo + if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[0] = TMED_LEFT; + else if (mapthings[i].options & MTF_OBJECTSPECIAL) + mapthings[i].args[0] = TMED_RIGHT; + else + mapthings[i].args[0] = TMED_NONE; + break; case 1200: //Tumbleweed (Big) case 1201: //Tumbleweed (Small) mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); @@ -5259,6 +5307,12 @@ static void P_ConvertBinaryMap(void) P_WriteConstant(MT_ROCKCRUMBLE1 + (sides[lines[j].sidenum[0]].rowoffset >> FRACBITS), &mapthings[i].stringargs[0]); break; } + case 1221: //Minecart saloon door + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + break; + case 1229: //Minecart switch point + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + break; case 1300: //Flame jet (horizontal) case 1301: //Flame jet (vertical) mapthings[i].args[0] = (mapthings[i].angle >> 13)*TICRATE/2; @@ -5269,6 +5323,9 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[0] = mapthings[i].angle; mapthings[i].args[1] = !!(mapthings[i].options & MTF_AMBUSH); break; + case 1305: //Rollout Rock + mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + break; case 1700: //Axis mapthings[i].args[2] = mapthings[i].angle & 16383; mapthings[i].args[3] = !!(mapthings[i].angle & 16384); diff --git a/src/p_spec.h b/src/p_spec.h index 220376903..0fc7c6ee1 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -96,6 +96,13 @@ typedef enum TMP_CLASSIC = 3, } textmappushabletype_t; +typedef enum +{ + TMED_NONE = 0, + TMED_RIGHT = 1, + TMED_LEFT = 2, +} textmapeggrobodirection_t; + //FOF flags typedef enum { From e71a952d709bdca005234b4d91aaa81c5bf27980 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 17:54:26 +0100 Subject: [PATCH 236/326] Adapt monitors to UDMF --- extras/conf/udb/Includes/SRB222_misc.cfg | 7 ++ extras/conf/udb/Includes/SRB222_things.cfg | 110 +++++++++++++++++++++ src/p_enemy.c | 8 +- src/p_mobj.c | 56 ++++------- src/p_setup.c | 20 +++- src/p_spec.h | 7 ++ 6 files changed, 166 insertions(+), 42 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index dbcd22629..3547266cb 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -590,6 +590,13 @@ enums 2 = "Immovable"; 3 = "Classic"; } + + monitorrespawn + { + 0 = "Same item"; + 1 = "Random (Weak)"; + 2 = "Random (Strong)"; + } } //Default things filters diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 02d90eacf..ab1ce5ad5 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4472,56 +4472,131 @@ udmf title = "Monitors"; width = 18; height = 40; + arg0 + { + title = "Death trigger tag"; + type = 15; + } 400 { title = "Super Ring (10 Rings)"; sprite = "TVRIA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 401 { title = "Pity Shield"; sprite = "TVPIA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 402 { title = "Attraction Shield"; sprite = "TVATA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 403 { title = "Force Shield"; sprite = "TVFOA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 404 { title = "Armageddon Shield"; sprite = "TVARA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 405 { title = "Whirlwind Shield"; sprite = "TVWWA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 406 { title = "Elemental Shield"; sprite = "TVELA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 407 { title = "Super Sneakers"; sprite = "TVSSA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 408 { title = "Invincibility"; sprite = "TVIVA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 409 { title = "Extra Life"; sprite = "TV1UA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } + arg2 + { + title = "Points"; + type = 11; + enum + { + 0 = "1,000"; + 1 = "10,000"; + } + } } 410 { @@ -4532,6 +4607,12 @@ udmf { title = "Teleporter"; sprite = "TVMXA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 413 { @@ -4552,6 +4633,12 @@ udmf { title = "Recycler"; sprite = "TVRCA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 418 { @@ -4567,16 +4654,34 @@ udmf { title = "Flame Shield"; sprite = "TVFLA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 421 { title = "Water Shield"; sprite = "TVBBA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } 422 { title = "Lightning Shield"; sprite = "TVZPA0"; + arg1 + { + title = "Respawn behavior"; + type = 11; + enum = "monitorrespawn"; + } } } @@ -4587,6 +4692,11 @@ udmf title = "Monitors (Respawning)"; width = 20; height = 44; + arg0 + { + title = "Death trigger tag"; + type = 15; + } 431 { diff --git a/src/p_enemy.c b/src/p_enemy.c index e077b3926..bbbb9495f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3717,8 +3717,8 @@ void A_MonitorPop(mobj_t *actor) // Run a linedef executor immediately upon popping // You may want to delay your effects by 18 tics to sync with the reward giving - if (actor->spawnpoint && actor->lastlook) - P_LinedefExecute(actor->lastlook, actor->target, NULL); + if (actor->spawnpoint && actor->spawnpoint->args[0]) + P_LinedefExecute(actor->spawnpoint->args[0], actor->target, NULL); } // Function: A_GoldMonitorPop @@ -3803,8 +3803,8 @@ void A_GoldMonitorPop(mobj_t *actor) // Run a linedef executor immediately upon popping // You may want to delay your effects by 18 tics to sync with the reward giving - if (actor->spawnpoint && actor->lastlook) - P_LinedefExecute(actor->lastlook, actor->target, NULL); + if (actor->spawnpoint && actor->spawnpoint->args[0]) + P_LinedefExecute(actor->spawnpoint->args[0], actor->target, NULL); } // Function: A_GoldMonitorRestore diff --git a/src/p_mobj.c b/src/p_mobj.c index fa3bba57a..09c518fe7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12033,7 +12033,7 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) case 2: // Unchanging if (i == MT_MYSTERY_BOX) return MT_NULL; // don't spawn - mthing->options &= ~(MTF_AMBUSH|MTF_OBJECTSPECIAL); // no random respawning! + mthing->args[1] = TMMR_SAME; // no random respawning! return i; case 3: // Don't spawn return MT_NULL; @@ -12063,8 +12063,7 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) if (modeattacking && i == MT_1UP_BOX) // 1UPs -->> Score TVs { - // Either or, doesn't matter which. - if (mthing->options & (MTF_AMBUSH | MTF_OBJECTSPECIAL)) + if (mthing->args[2]) return MT_SCORE10K_BOX; // 10,000 else return MT_SCORE1K_BOX; // 1,000 @@ -13157,22 +13156,27 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (mthing->args[0]) mobj->flags2 |= MF2_AMBUSH; } - + if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) + { + switch (mthing->args[1]) + { + case TMMR_SAME: + default: + break; + case TMMR_WEAK: + mobj->flags2 |= MF2_AMBUSH; + break; + case TMMR_STRONG: + mobj->flags2 |= MF2_STRONGBOX; + } + } return true; } static void P_SetAmbush(mobj_t *mobj) { - 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; - } - - //TODO: Make this obsolete - else if (mobj->type != MT_AXIS && + if (mobj->type != MT_AXIS && mobj->type != MT_AXISTRANSFER && mobj->type != MT_AXISTRANSFERLINE && mobj->type != MT_NIGHTSBUMPER && @@ -13198,20 +13202,11 @@ static void P_SetAmbush(mobj_t *mobj) mobj->type != MT_MINECARTSWITCHPOINT && mobj->type != MT_ROLLOUTSPAWN && mobj->type != MT_STARPOST && - !(mobj->flags & MF_SPRING && mobj->info->painchance == 3)) + !((mobj->flags & MF_SPRING) && mobj->info->painchance == 3) && + !((mobj->flags & MF_MONITOR) && mobj->info->speed != 0)) mobj->flags2 |= MF2_AMBUSH; } -static void P_SetObjectSpecial(mobj_t *mobj) -{ - 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; - } -} - static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, mobjtype_t i) { mobj_t *mobj = NULL; @@ -13241,9 +13236,6 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, if (mthing->options & MTF_AMBUSH) P_SetAmbush(mobj); - if (mthing->options & MTF_OBJECTSPECIAL) - P_SetObjectSpecial(mobj); - // Generic reverse gravity for individual objects flag. if (mthing->options & MTF_OBJECTFLIP) { @@ -13251,16 +13243,6 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, mobj->flags2 |= MF2_OBJECTFLIP; } - // Extra functionality - if (mthing->options & MTF_EXTRA) - { - if (mobj->flags & MF_MONITOR && (mthing->angle & 16384)) - { - // Store line exec tag to run upon popping - mobj->lastlook = (mthing->angle & 16383); - } - } - // Final set of not being able to draw nightsitems. if (mobj->flags & MF_NIGHTSITEM) mobj->flags2 |= MF2_DONTDRAW; diff --git a/src/p_setup.c b/src/p_setup.c index c267167fe..0f9234767 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4914,8 +4914,23 @@ static void P_ConvertBinaryMap(void) else mapthings[i].args[0] = TMP_NORMAL; } - if (mobjinfo[mobjtype].flags & MF_SPRING && mobjinfo[mobjtype].painchance == 3) + if ((mobjinfo[mobjtype].flags & MF_SPRING) && mobjinfo[mobjtype].painchance == 3) mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); + if (mobjinfo[mobjtype].flags & MF_MONITOR) + { + if ((mapthings[i].options & MTF_EXTRA) && mapthings[i].angle & 16384) + mapthings[i].args[0] = mapthings[i].angle & 16383; + + if (mobjinfo[mobjtype].speed != 0) + { + if (mapthings[i].options & MTF_OBJECTSPECIAL) + mapthings[i].args[1] = TMMR_STRONG; + else if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[1] = TMMR_WEAK; + else + mapthings[i].args[1] = TMMR_SAME; + } + } } if (mapthings[i].type >= 1 && mapthings[i].type <= 35) //Player starts @@ -5024,6 +5039,9 @@ static void P_ConvertBinaryMap(void) case 1800: //Coin mapthings[i].args[0] = !(mapthings[i].options & MTF_AMBUSH); break; + case 409: //Extra life monitor + mapthings[i].args[2] = !(mapthings[i].options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)); + break; case 500: //Air bubble patch mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; diff --git a/src/p_spec.h b/src/p_spec.h index 0fc7c6ee1..994db8cf4 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -103,6 +103,13 @@ typedef enum TMED_LEFT = 2, } textmapeggrobodirection_t; +typedef enum +{ + TMMR_SAME = 0, + TMMR_WEAK = 1, + TMMR_STRONG = 2, +} textmapmonitorrespawn_t; + //FOF flags typedef enum { From a091b7d16d54c1a970d2fdcc05b70ec8dc645151 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 22:52:24 +0100 Subject: [PATCH 237/326] Adapt bosses to UDMF and remove now-unused mapthing flags --- extras/conf/udb/Includes/SRB222_misc.cfg | 3 - extras/conf/udb/Includes/SRB222_things.cfg | 162 +++++++++++++++++---- src/info.c | 8 +- src/p_enemy.c | 10 +- src/p_mobj.c | 90 +++++------- src/p_setup.c | 40 +++-- src/p_spec.h | 12 ++ 7 files changed, 221 insertions(+), 104 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 3547266cb..57c7c88a3 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -87,10 +87,7 @@ thingflags // THING FLAGS thingflags_udmf { - extra = "Extra"; flip = "Flip"; - special = "Special"; - ambush = "Ambush"; } diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index ab1ce5ad5..328cf7673 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3985,16 +3985,22 @@ udmf title = "Boss ID"; } arg1 + { + title = "End level on death?"; + type = 11; + enum = "noyes"; + } + arg2 { title = "Death trigger tag"; type = 15; } - arg2 + arg3 { title = "Victory trigger tag"; type = 15; } - arg3 + arg4 { title = "Pinch trigger tag"; type = 15; @@ -4012,19 +4018,31 @@ udmf } arg1 { - title = "Death trigger tag"; - type = 15; + title = "End level on death?"; + type = 11; + enum = "noyes"; } arg2 { - title = "Victory trigger tag"; + title = "Death trigger tag"; type = 15; } arg3 + { + title = "Victory trigger tag"; + type = 15; + } + arg4 { title = "Pinch trigger tag"; type = 15; } + arg5 + { + title = "Speed up when hit?"; + type = 11; + enum = "noyes"; + } } 202 { @@ -4037,16 +4055,22 @@ udmf title = "Boss ID"; } arg1 + { + title = "End level on death?"; + type = 11; + enum = "noyes"; + } + arg2 { title = "Death trigger tag"; type = 15; } - arg2 + arg3 { title = "Victory trigger tag"; type = 15; } - arg3 + arg4 { title = "Pinch trigger tag"; type = 15; @@ -4064,20 +4088,26 @@ udmf } arg1 { - title = "Death trigger tag"; - type = 15; + title = "End level on death?"; + type = 11; + enum = "noyes"; } arg2 { - title = "Victory trigger tag"; + title = "Death trigger tag"; type = 15; } arg3 { - title = "Pinch trigger tag"; + title = "Victory trigger tag"; type = 15; } arg4 + { + title = "Pinch trigger tag"; + type = 15; + } + arg5 { title = "Cage drop trigger tag"; type = 15; @@ -4095,19 +4125,35 @@ udmf } arg1 { - title = "Death trigger tag"; - type = 15; + title = "End level on death?"; + type = 11; + enum = "noyes"; } arg2 { - title = "Victory trigger tag"; + title = "Death trigger tag"; type = 15; } arg3 + { + title = "Victory trigger tag"; + type = 15; + } + arg4 { title = "Pinch trigger tag"; type = 15; } + arg5 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Grayscale"; + 2 = "Skip intro"; + } + } } 206 { @@ -4121,20 +4167,26 @@ udmf } arg1 { - title = "Death trigger tag"; - type = 15; + title = "End level on death?"; + type = 11; + enum = "noyes"; } arg2 { - title = "Victory trigger tag"; + title = "Death trigger tag"; type = 15; } arg3 { - title = "Pinch trigger tag"; + title = "Victory trigger tag"; type = 15; } arg4 + { + title = "Pinch trigger tag"; + type = 15; + } + arg5 { title = "Platform trigger tag"; type = 15; @@ -4146,6 +4198,12 @@ udmf sprite = "METLI1"; width = 16; height = 48; + arg0 + { + title = "Grayscale?"; + type = 11; + enum = "noyes"; + } } 208 { @@ -4159,19 +4217,31 @@ udmf } arg1 { - title = "Death trigger tag"; - type = 15; + title = "End level on death?"; + type = 11; + enum = "noyes"; } arg2 { - title = "Victory trigger tag"; + title = "Death trigger tag"; type = 15; } arg3 + { + title = "Victory trigger tag"; + type = 15; + } + arg4 { title = "Pinch trigger tag"; type = 15; } + arg5 + { + title = "Grayscale?"; + type = 11; + enum = "noyes"; + } } 209 { @@ -4185,24 +4255,40 @@ udmf } arg1 { - title = "Death trigger tag"; - type = 15; + title = "End level on death?"; + type = 11; + enum = "noyes"; } arg2 { - title = "Victory trigger tag"; + title = "Death trigger tag"; type = 15; } arg3 { - title = "Pinch trigger tag"; + title = "Victory trigger tag"; type = 15; } arg4 + { + title = "Pinch trigger tag"; + type = 15; + } + arg5 { title = "Attack trigger tag"; type = 15; } + arg6 + { + title = "Flags"; + type = 12; + enum + { + 1 = "No origin-fling death"; + 2 = "Electric barrier"; + } + } } 290 { @@ -6561,6 +6647,16 @@ udmf { title = "Strength"; } + arg3 + { + title = "Waving direction"; + type = 11; + enum + { + 0 = "Horizontal"; + 1 = "Vertical"; + } + } } 1301 { @@ -6580,6 +6676,16 @@ udmf { title = "Strength"; } + arg3 + { + title = "Shooting direction"; + type = 11; + enum + { + 0 = "Upwards"; + 1 = "Downwards"; + } + } } 1302 { @@ -7714,6 +7820,12 @@ udmf sprite = "ROSYA1"; width = 16; height = 48; + arg0 + { + title = "Grayscale?"; + type = 11; + enum = "noyes"; + } } 2105 { diff --git a/src/info.c b/src/info.c index 51f9ea8e6..c9443700c 100644 --- a/src/info.c +++ b/src/info.c @@ -1452,7 +1452,7 @@ state_t states[NUMSTATES] = {SPR_FANG, 18, 16, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT1}, // S_FANG_PINCHLOBSHOT0 {SPR_FANG, 19, 2, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT2}, // S_FANG_PINCHLOBSHOT1 {SPR_FANG, 20, 30, {A_Boss5MakeItRain}, MT_FBOMB, -16, S_FANG_PINCHLOBSHOT3}, // S_FANG_PINCHLOBSHOT2 - {SPR_FANG, 20, 18, {A_LinedefExecuteFromArg}, 3, 0, S_FANG_PINCHLOBSHOT4}, // S_FANG_PINCHLOBSHOT3 + {SPR_FANG, 20, 18, {A_LinedefExecuteFromArg}, 4, 0, S_FANG_PINCHLOBSHOT4}, // S_FANG_PINCHLOBSHOT3 {SPR_FANG, 0, 0, {A_Boss5Calm}, 0, 0, S_FANG_PATHINGSTART1}, // S_FANG_PINCHLOBSHOT4 {SPR_FANG, 21, 0, {A_DoNPCPain}, 0, 0, S_FANG_DIE2}, // S_FANG_DIE1 @@ -1584,7 +1584,7 @@ state_t states[NUMSTATES] = {SPR_BRAK, 21, 3*TICRATE, {NULL}, 0, 0, S_BLACKEGG_DESTROYPLAT2}, // S_BLACKEGG_DESTROYPLAT1 {SPR_BRAK, 21, 1, {A_PlaySound}, sfx_s3k54, 0, S_BLACKEGG_DESTROYPLAT3}, // S_BLACKEGG_DESTROYPLAT2 - {SPR_BRAK, 21, 14, {A_LinedefExecuteFromArg}, 4, 0, S_BLACKEGG_STND}, // S_BLACKEGG_DESTROYPLAT3 + {SPR_BRAK, 21, 14, {A_LinedefExecuteFromArg}, 5, 0, S_BLACKEGG_STND}, // S_BLACKEGG_DESTROYPLAT3 {SPR_NULL, 0, 1, {A_CapeChase}, (160 - 20) << 16, 0, S_BLACKEGG_HELPER}, // S_BLACKEGG_HELPER @@ -1618,7 +1618,7 @@ state_t states[NUMSTATES] = {SPR_BRAK, 26 + FF_FULLBRIGHT, 2, {A_BrakFireShot}, MT_CYBRAKDEMON_FLAMESHOT, 128, S_CYBRAKDEMON_FLAME_ATTACK4}, // S_CYBRAKDEMON_FLAME_ATTACK3 // Fire {SPR_BRAK, 7, 1, {A_Repeat}, 30, S_CYBRAKDEMON_FLAME_ATTACK3, S_CYBRAKDEMON_FINISH_ATTACK1}, // S_CYBRAKDEMON_FLAME_ATTACK4 // Loop {SPR_BRAK, 0, 6, {A_RandomState}, S_CYBRAKDEMON_VILE_ATTACK1, S_CYBRAKDEMON_NAPALM_ATTACK1, S_CYBRAKDEMON_MISSILE_ATTACK1}, // S_CYBRAKDEMON_CHOOSE_ATTACK2 - {SPR_BRAK, 20, 0, {A_LinedefExecuteFromArg}, 4, 0, S_CYBRAKDEMON_VILE_ATTACK2}, // S_CYBRAKDEMON_VILE_ATTACK1 + {SPR_BRAK, 20, 0, {A_LinedefExecuteFromArg}, 5, 0, S_CYBRAKDEMON_VILE_ATTACK2}, // S_CYBRAKDEMON_VILE_ATTACK1 {SPR_BRAK, 20, 24, {A_VileTarget}, MT_CYBRAKDEMON_TARGET_RETICULE, 1, S_CYBRAKDEMON_VILE_ATTACK3}, // S_CYBRAKDEMON_VILE_ATTACK2 {SPR_BRAK, 19, 8, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_VILE_ATTACK4}, // S_CYBRAKDEMON_VILE_ATTACK3 {SPR_BRAK, 18, 8, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_VILE_ATTACK5}, // S_CYBRAKDEMON_VILE_ATTACK4 @@ -1631,7 +1631,7 @@ state_t states[NUMSTATES] = {SPR_BRAK, 0, 0, {A_SetReactionTime}, 0, 0, S_CYBRAKDEMON_WALK1}, // S_CYBRAKDEMON_FINISH_ATTACK2 // If just attacked, remove MF2_FRET w/out going back to spawnstate {SPR_BRAK, 18, 24, {A_Pain}, 0, 0, S_CYBRAKDEMON_PAIN2}, // S_CYBRAKDEMON_PAIN1 {SPR_BRAK, 18, 0, {A_CheckHealth}, 3, S_CYBRAKDEMON_PAIN3, S_CYBRAKDEMON_CHOOSE_ATTACK1}, // S_CYBRAKDEMON_PAIN2 - {SPR_BRAK, 18, 0, {A_LinedefExecuteFromArg}, 3, 0, S_CYBRAKDEMON_CHOOSE_ATTACK1}, // S_CYBRAKDEMON_PAIN3 + {SPR_BRAK, 18, 0, {A_LinedefExecuteFromArg}, 4, 0, S_CYBRAKDEMON_CHOOSE_ATTACK1}, // S_CYBRAKDEMON_PAIN3 {SPR_BRAK, 18, 1, {A_Repeat}, 1, S_CYBRAKDEMON_DIE1, S_CYBRAKDEMON_DIE2}, // S_CYBRAKDEMON_DIE1 {SPR_BRAK, 18, 2, {A_BossScream}, 2, 0, S_CYBRAKDEMON_DIE3}, // S_CYBRAKDEMON_DIE2 {SPR_BRAK, 18, 0, {A_Repeat}, 52, S_CYBRAKDEMON_DIE2, S_CYBRAKDEMON_DIE4}, // S_CYBRAKDEMON_DIE3 diff --git a/src/p_enemy.c b/src/p_enemy.c index bbbb9495f..f7e8e6565 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3912,7 +3912,7 @@ static void P_DoBossVictory(mobj_t *mo) // victory! if (mo->spawnpoint) - P_LinedefExecute(mo->spawnpoint->args[1], mo, NULL); + P_LinedefExecute(mo->spawnpoint->args[3], mo, NULL); if (stoppedclock && modeattacking) // if you're just time attacking, skip making the capsule appear since you don't need to step on it anyways. return; @@ -4025,7 +4025,7 @@ static void P_DoCybrakdemonDeath(mobj_t *mo) mo->z += P_MobjFlip(mo); P_SetObjectMomZ(mo, 12*FRACUNIT, false); S_StartSound(mo, sfx_bgxpld); - if (mo->spawnpoint && !(mo->spawnpoint->options & MTF_EXTRA)) + if (mo->spawnpoint && !(mo->spawnpoint->args[6] & TMB_NODEATHFLING)) P_InstaThrust(mo, R_PointToAngle2(0, 0, mo->x, mo->y), 14*FRACUNIT); } @@ -4128,7 +4128,7 @@ void A_BossDeath(mobj_t *mo) return; if (mo->spawnpoint) - P_LinedefExecute(mo->spawnpoint->args[1], mo, NULL); + P_LinedefExecute(mo->spawnpoint->args[2], mo, NULL); mo->health = 0; // Boss is dead (but not necessarily fleeing...) @@ -7072,7 +7072,7 @@ void A_Boss1Chase(mobj_t *actor) else { if (actor->spawnpoint) - P_LinedefExecute(actor->spawnpoint->args[3], actor, NULL); + P_LinedefExecute(actor->spawnpoint->args[4], actor, NULL); P_SetMobjState(actor, actor->info->raisestate); } @@ -7196,7 +7196,7 @@ void A_Boss2Chase(mobj_t *actor) } else { - // Only speed up if you have the 'Deaf' flag. + // Only speed up if you have the ambush flag. if (actor->flags2 & MF2_AMBUSH) speedvar = actor->health; else diff --git a/src/p_mobj.c b/src/p_mobj.c index 09c518fe7..3de85fa2b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4348,7 +4348,7 @@ static void P_Boss2Thinker(mobj_t *mobj) mobj->flags &= ~MF_NOGRAVITY; A_Boss2Pogo(mobj); if (mobj->spawnpoint) - P_LinedefExecute(mobj->spawnpoint->args[3], mobj, NULL); + P_LinedefExecute(mobj->spawnpoint->args[4], mobj, NULL); } } @@ -4645,7 +4645,7 @@ static boolean P_Boss4MoveCage(mobj_t *mobj, fixed_t delta) if (!mobj->spawnpoint) return false; - TAG_ITER_SECTORS(mobj->spawnpoint->args[3], snum) + TAG_ITER_SECTORS(mobj->spawnpoint->args[4], snum) { sector = §ors[snum]; sector->floorheight += delta; @@ -4732,7 +4732,7 @@ static void P_Boss4DestroyCage(mobj_t *mobj) if (!mobj->spawnpoint) return; - TAG_ITER_SECTORS(mobj->spawnpoint->args[3], snum) + TAG_ITER_SECTORS(mobj->spawnpoint->args[4], snum) { sector = §ors[snum]; @@ -5006,14 +5006,14 @@ static void P_Boss4Thinker(mobj_t *mobj) P_Boss4DestroyCage(mobj); mobj->movedir = 3; if (mobj->spawnpoint) - P_LinedefExecute(mobj->spawnpoint->args[3], mobj, NULL); + P_LinedefExecute(mobj->spawnpoint->args[4], mobj, NULL); P_Boss4MoveSpikeballs(mobj, FixedAngle(mobj->movecount), 0); var1 = 3; A_BossJetFume(mobj); return; } if (mobj->spawnpoint) - P_LinedefExecute(mobj->spawnpoint->args[4] - (mobj->info->spawnhealth-mobj->health), mobj, NULL); + P_LinedefExecute(mobj->spawnpoint->args[5] - (mobj->info->spawnhealth-mobj->health), mobj, NULL); // 1 -> 1.5 second timer mobj->threshold = TICRATE+(TICRATE*(mobj->info->spawnhealth-mobj->health)/10); if (mobj->threshold < 1) @@ -5046,7 +5046,7 @@ static void P_Boss4Thinker(mobj_t *mobj) P_Boss4DestroyCage(mobj); mobj->movedir = 3; if (mobj->spawnpoint) - P_LinedefExecute(mobj->spawnpoint->args[3], mobj, NULL); + P_LinedefExecute(mobj->spawnpoint->args[4], mobj, NULL); var1 = 3; A_BossJetFume(mobj); return; @@ -5187,7 +5187,7 @@ static void P_Boss7Thinker(mobj_t *mobj) mobj->flags2 |= MF2_FRET; P_SetMobjState(mobj, mobj->info->raisestate); if (mobj->spawnpoint) - P_LinedefExecute(mobj->spawnpoint->args[3], mobj, NULL); + P_LinedefExecute(mobj->spawnpoint->args[4], mobj, NULL); } } else if (mobj->state == &states[S_BLACKEGG_HITFACE4] && mobj->tics == mobj->state->tics) @@ -6037,7 +6037,7 @@ static void P_Boss9Thinker(mobj_t *mobj) else mobj->watertop = mobj->target->floorz + 16*FRACUNIT; if (mobj->spawnpoint) - P_LinedefExecute(mobj->spawnpoint->args[3], mobj, NULL); + P_LinedefExecute(mobj->spawnpoint->args[4], mobj, NULL); #if 0 whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct @@ -11909,7 +11909,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) runemeraldmanager = true; break; case MT_ROSY: - if (!(G_CoopGametype() || (mthing->options & MTF_EXTRA))) + if (!(G_CoopGametype() || mthing->args[0])) return false; // she doesn't hang out here if (!(netgame || multiplayer) && players[consoleplayer].skin == 3) @@ -12722,6 +12722,10 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->colorized = true; } break; + case MT_EGGMOBILE2: + if (mthing->args[5]) + mobj->flags2 |= MF2_AMBUSH; + break; case MT_EGGMOBILE3: mobj->cusval = mthing->args[0]; break; @@ -12748,11 +12752,27 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean else mobj->health = FixedMul(mobj->subsector->sector->ceilingheight - mobj->subsector->sector->floorheight, 3*(FRACUNIT/4)) >> FRACBITS; break; - case MT_METALSONIC_RACE: - case MT_METALSONIC_BATTLE: case MT_FANG: + if (mthing->args[5] & TMF_GRAYSCALE) + { + mobj->color = SKINCOLOR_SILVER; + mobj->colorized = true; + mobj->flags2 |= MF2_SLIDEPUSH; + } + if (mthing->args[5] & TMF_SKIPINTRO) + mobj->flags2 |= MF2_AMBUSH; + break; + case MT_METALSONIC_BATTLE: + if (mthing->args[5]) + { + mobj->color = SKINCOLOR_SILVER; + mobj->colorized = true; + mobj->flags2 |= MF2_SLIDEPUSH; + } + break; + case MT_METALSONIC_RACE: case MT_ROSY: - if (mthing->options & MTF_EXTRA) + if (mthing->args[0]) { mobj->color = SKINCOLOR_SILVER; mobj->colorized = true; @@ -12810,6 +12830,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->movecount = mthing->args[0]; mobj->threshold = mthing->args[1]; mobj->movedir = mthing->args[2]; + if (mthing->args[3]) + mobj->flags2 |= MF2_AMBUSH; break; case MT_MACEPOINT: case MT_CHAINMACEPOINT: @@ -12971,7 +12993,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->health = 1 << (tokenbits - 1); break; case MT_CYBRAKDEMON: - if (mthing->options & MTF_AMBUSH) + if (mthing->args[6] & TMB_BARRIER) { mobj_t* elecmobj; elecmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_CYBRAKDEMON_ELECTRIC_BARRIER); @@ -13117,7 +13139,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (mobj->flags & MF_BOSS) { - if (mthing->options & MTF_OBJECTSPECIAL) // No egg trap for this boss + if (mthing->args[1]) // No egg trap for this boss mobj->flags2 |= MF2_BOSSNOTRAP; } if (mobj->flags & MF_NIGHTSITEM) @@ -13174,39 +13196,6 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean return true; } -static void P_SetAmbush(mobj_t *mobj) -{ - if (mobj->type != MT_AXIS && - mobj->type != MT_AXISTRANSFER && - mobj->type != MT_AXISTRANSFERLINE && - mobj->type != MT_NIGHTSBUMPER && - mobj->type != MT_NIGHTSDRONE && - mobj->type != MT_BALLOON && - mobj->type != MT_BIGTUMBLEWEED && - mobj->type != MT_LITTLETUMBLEWEED && - mobj->type != MT_BUBBLES && - mobj->type != MT_FAN && - mobj->type != MT_ROBOHOOD && - mobj->type != MT_CRUSHSTACEAN && - mobj->type != MT_BANPYURA && - mobj->type != MT_GOLDBUZZ && - mobj->type != MT_REDBUZZ && - mobj->type != MT_JETTBOMBER && - mobj->type != MT_JETTGUNNER && - mobj->type != MT_BUMBLEBORE && - mobj->type != MT_CACOLANTERN && - mobj->type != MT_PIAN && - mobj->type != MT_EGGGUARD && - mobj->type != MT_STEAM && - mobj->type != MT_SALOONDOORCENTER && - mobj->type != MT_MINECARTSWITCHPOINT && - mobj->type != MT_ROLLOUTSPAWN && - mobj->type != MT_STARPOST && - !((mobj->flags & MF_SPRING) && mobj->info->painchance == 3) && - !((mobj->flags & MF_MONITOR) && mobj->info->speed != 0)) - mobj->flags2 |= MF2_AMBUSH; -} - static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, mobjtype_t i) { mobj_t *mobj = NULL; @@ -13229,13 +13218,6 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, mthing->mobj = mobj; - // ignore MTF_ flags and return early - if (i == MT_NIGHTSBUMPER) - return mobj; - - if (mthing->options & MTF_AMBUSH) - P_SetAmbush(mobj); - // Generic reverse gravity for individual objects flag. if (mthing->options & MTF_OBJECTFLIP) { diff --git a/src/p_setup.c b/src/p_setup.c index 0f9234767..1a063bc2c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1791,14 +1791,8 @@ static void ParseTextmapThingParameter(UINT32 i, char *param, char *val) else if (fastcmp(param, "scale") || fastcmp(param, "scalex") || fastcmp(param, "scaley")) mapthings[i].scale = FLOAT_TO_FIXED(atof(val)); // Flags - else if (fastcmp(param, "extra") && fastcmp("true", val)) - mapthings[i].options |= MTF_EXTRA; else if (fastcmp(param, "flip") && fastcmp("true", val)) mapthings[i].options |= MTF_OBJECTFLIP; - else if (fastcmp(param, "objectspecial") && fastcmp("true", val)) - mapthings[i].options |= MTF_OBJECTSPECIAL; - else if (fastcmp(param, "ambush") && fastcmp("true", val)) - mapthings[i].options |= MTF_AMBUSH; else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9) { @@ -4892,9 +4886,10 @@ static void P_ConvertBinaryMap(void) { INT32 paramoffset = mapthings[i].extrainfo*LE_PARAMWIDTH; mapthings[i].args[0] = mapthings[i].extrainfo; - mapthings[i].args[1] = LE_BOSSDEAD + paramoffset; - mapthings[i].args[2] = LE_ALLBOSSESDEAD + paramoffset; - mapthings[i].args[3] = LE_PINCHPHASE + paramoffset; + mapthings[i].args[1] = !!(mapthings[i].options & MTF_OBJECTSPECIAL); + mapthings[i].args[2] = LE_BOSSDEAD + paramoffset; + mapthings[i].args[3] = LE_ALLBOSSESDEAD + paramoffset; + mapthings[i].args[4] = LE_PINCHPHASE + paramoffset; } if (mobjinfo[mobjtype].flags & MF_NIGHTSITEM) { @@ -4994,17 +4989,35 @@ static void P_ConvertBinaryMap(void) case 136: //Pyre Fly mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; + case 202: //Egg Slimer + mapthings[i].args[5] = !!(mapthings[i].options & MTF_AMBUSH); + break; case 203: //Egg Colosseum - mapthings[i].args[4] = LE_BOSS4DROP + mapthings[i].extrainfo * LE_PARAMWIDTH; + mapthings[i].args[5] = LE_BOSS4DROP + mapthings[i].extrainfo * LE_PARAMWIDTH; break; case 204: //Fang - mapthings[i].args[3] = LE_BOSS4DROP + mapthings[i].extrainfo*LE_PARAMWIDTH; + mapthings[i].args[4] = LE_BOSS4DROP + mapthings[i].extrainfo*LE_PARAMWIDTH; + if (mapthings[i].options & MTF_EXTRA) + mapthings[i].args[5] |= TMF_GRAYSCALE; + if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[5] |= TMF_SKIPINTRO; break; case 206: //Brak Eggman (Old) - mapthings[i].args[4] = LE_BRAKPLATFORM + mapthings[i].extrainfo*LE_PARAMWIDTH; + mapthings[i].args[5] = LE_BRAKPLATFORM + mapthings[i].extrainfo*LE_PARAMWIDTH; + break; + case 207: //Metal Sonic (Race) + case 2104: //Amy Cameo + mapthings[i].args[0] = !!(mapthings[i].options & MTF_EXTRA); + break; + case 208: //Metal Sonic (Battle) + mapthings[i].args[5] = !!(mapthings[i].options & MTF_EXTRA); break; case 209: //Brak Eggman - mapthings[i].args[4] = LE_BRAKVILEATACK + mapthings[i].extrainfo*LE_PARAMWIDTH; + mapthings[i].args[5] = LE_BRAKVILEATACK + mapthings[i].extrainfo*LE_PARAMWIDTH; + if (mapthings[i].options & MTF_EXTRA) + mapthings[i].args[6] |= TMB_NODEATHFLING; + if (mapthings[i].options & MTF_AMBUSH) + mapthings[i].args[6] |= TMB_BARRIER; break; case 292: //Boss waypoint mapthings[i].args[0] = mapthings[i].angle; @@ -5336,6 +5349,7 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[0] = (mapthings[i].angle >> 13)*TICRATE/2; mapthings[i].args[1] = ((mapthings[i].angle >> 10) & 7)*TICRATE/2; mapthings[i].args[2] = 80 - 5*mapthings[i].extrainfo; + mapthings[i].args[3] = !!(mapthings[i].options & MTF_AMBUSH); break; case 1304: //Lavafall mapthings[i].args[0] = mapthings[i].angle; diff --git a/src/p_spec.h b/src/p_spec.h index 994db8cf4..f77af5a0d 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -110,6 +110,18 @@ typedef enum TMMR_STRONG = 2, } textmapmonitorrespawn_t; +typedef enum +{ + TMF_GRAYSCALE = 1, + TMF_SKIPINTRO = 1<<1, +} textmapfangflags_t; + +typedef enum +{ + TMB_NODEATHFLING = 1, + TMB_BARRIER = 1<<1, +} textmapbrakflags_t; + //FOF flags typedef enum { From 2a868ca60d68f0c2385851ec597bbb00e9b4bcdf Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 23:06:48 +0100 Subject: [PATCH 238/326] Adapt Glaregoyles to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 16 ++++++++++++++++ src/p_mobj.c | 3 +-- src/p_setup.c | 7 +++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 328cf7673..9d557060e 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -7030,6 +7030,10 @@ udmf type = 11; enum = "pushablebehavior"; } + arg1 + { + title = "Starting delay"; + } } 1501 { @@ -7045,6 +7049,10 @@ udmf type = 11; enum = "pushablebehavior"; } + arg1 + { + title = "Starting delay"; + } } 1502 { @@ -7060,6 +7068,10 @@ udmf type = 11; enum = "pushablebehavior"; } + arg1 + { + title = "Starting delay"; + } } 1503 { @@ -7075,6 +7087,10 @@ udmf type = 11; enum = "pushablebehavior"; } + arg1 + { + title = "Starting delay"; + } } 1504 { diff --git a/src/p_mobj.c b/src/p_mobj.c index 3de85fa2b..5a8645708 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12884,8 +12884,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean case MT_GLAREGOYLEUP: case MT_GLAREGOYLEDOWN: case MT_GLAREGOYLELONG: - if (mthing->angle >= 360) - mobj->tics += 7*(mthing->angle/360) + 1; // starting delay + mobj->tics += mthing->args[1]; // starting delay break; case MT_DSZSTALAGMITE: case MT_DSZ2STALAGMITE: diff --git a/src/p_setup.c b/src/p_setup.c index 1a063bc2c..e0c805a4b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5358,6 +5358,13 @@ static void P_ConvertBinaryMap(void) case 1305: //Rollout Rock mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; + case 1500: //Glaregoyle + case 1501: //Glaregoyle (Up) + case 1502: //Glaregoyle (Down) + case 1503: //Glaregoyle (Long) + if (mapthings[i].angle >= 360) + mapthings[i].args[1] = 7*(mapthings[i].angle/360) + 1; + break; case 1700: //Axis mapthings[i].args[2] = mapthings[i].angle & 16383; mapthings[i].args[3] = !!(mapthings[i].angle & 16384); From e76d33267827114f2a004f2f28880ceab07ccc19 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 28 Dec 2021 23:51:08 +0100 Subject: [PATCH 239/326] Disable the old hacky way of doing egg capsules in UDMF maps --- src/doomdef.h | 2 +- src/p_enemy.c | 13 ++++++++----- src/p_spec.c | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 7e7e35599..41ec9ef33 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -401,7 +401,7 @@ extern skincolor_t skincolors[MAXSKINCOLORS]; #define PUSHACCEL (2*FRACUNIT) // Acceleration for MF2_SLIDEPUSH items. -// Special linedef executor tag numbers! +// Special linedef executor tag numbers! Binary map format only (UDMF has other ways of doing these things). enum { LE_PINCHPHASE = -2, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!) LE_ALLBOSSESDEAD = -3, // All bosses in the map are dead (Egg capsule raise) diff --git a/src/p_enemy.c b/src/p_enemy.c index f7e8e6565..5c92bdc06 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3928,11 +3928,14 @@ static void P_DoBossVictory(mobj_t *mo) } else { - // Bring the egg trap up to the surface - // Incredibly shitty code ahead - EV_DoElevator(LE_CAPSULE0, NULL, elevateHighest); - EV_DoElevator(LE_CAPSULE1, NULL, elevateUp); - EV_DoElevator(LE_CAPSULE2, NULL, elevateHighest); + if (!udmf) + { + // Bring the egg trap up to the surface + // Incredibly shitty code ahead + EV_DoElevator(LE_CAPSULE0, NULL, elevateHighest); + EV_DoElevator(LE_CAPSULE1, NULL, elevateUp); + EV_DoElevator(LE_CAPSULE2, NULL, elevateHighest); + } if (mapheaderinfo[gamemap-1]->muspostbossname[0] && S_MusicExists(mapheaderinfo[gamemap-1]->muspostbossname, !midi_disabled, !digital_disabled)) diff --git a/src/p_spec.c b/src/p_spec.c index deb915eeb..4afc4946d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4860,7 +4860,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers case 8: // Tells pushable things to check FOFs break; case 9: // Egg trap capsule - if (roversector) + if (!udmf && roversector) P_ProcessEggCapsule(player, sector); break; case 10: // Special Stage Time/Rings From cbf32c6615e3dbb60b71a48897b5083c2bf2859e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 08:12:28 +0100 Subject: [PATCH 240/326] Adapt some miscellaneous linedef types to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 51 +++++++++++++++ src/hardware/hw_main.c | 2 +- src/p_setup.c | 37 +++++++++++ src/p_spec.c | 68 +++++++------------- src/p_spec.h | 1 + src/r_main.c | 4 +- 6 files changed, 117 insertions(+), 46 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index c8b7ccf5f..b82ab30c9 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1589,6 +1589,57 @@ udmf title = "None"; prefix = "(0)"; } + + 7 + { + title = "Sector Flat Alignment"; + prefix = "(7)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Affected planes"; + type = 11; + enum = "floorceiling"; + default = 2; + } + } + + 10 + { + title = "Culling Plane"; + prefix = "(10)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Culling behavior"; + type = 11; + enum + { + 0 = "Always"; + 1 = "Only while in sector"; + } + } + } + + 40 + { + title = "Visual Portal Between Tagged Linedefs"; + prefix = "(40)"; + } + + 41 + { + title = "Horizon Effect"; + prefix = "(41)"; + } } parameters diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 83a8595d1..4b97e8779 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3576,7 +3576,7 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v return false; cullplane = FIXED_TO_FLOAT(cullheight->frontsector->floorheight); - if (cullheight->flags & ML_NOCLIMB) // Group culling + if (cullheight->args[1]) // Group culling { if (!viewcullheight) return false; diff --git a/src/p_setup.c b/src/p_setup.c index e0c805a4b..4564ec75e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3179,6 +3179,43 @@ static void P_ConvertBinaryMap(void) switch (lines[i].special) { + case 7: //Sector flat alignment + lines[i].args[0] = tag; + if ((lines[i].flags & (ML_NETONLY|ML_NONET)) == (ML_NETONLY|ML_NONET)) + { + CONS_Alert(CONS_WARNING, M_GetText("Flat alignment linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), tag); + lines[i].special = 0; + } + else if (lines[i].flags & ML_NETONLY) + lines[i].args[1] = TMP_CEILING; + else if (lines[i].flags & ML_NONET) + lines[i].args[1] = TMP_FLOOR; + else + lines[i].args[1] = TMP_BOTH; + lines[i].flags &= ~(ML_NETONLY|ML_NONET); + + if (lines[i].flags & ML_EFFECT6) // Set offset through x and y texture offsets + { + angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)); + fixed_t xoffs = sides[lines[i].sidenum[0]].textureoffset; + fixed_t yoffs = sides[lines[i].sidenum[0]].rowoffset; + + //If no tag is given, apply to front sector + if (lines[i].args[0] == 0) + P_ApplyFlatAlignment(lines[i].frontsector, flatangle, xoffs, yoffs, lines[i].args[1] != TMP_CEILING, lines[i].args[1] != TMP_FLOOR); + else + { + INT32 s; + TAG_ITER_SECTORS(lines[i].args[0], s) + P_ApplyFlatAlignment(sectors + s, flatangle, xoffs, yoffs, lines[i].args[1] != TMP_CEILING, lines[i].args[1] != TMP_FLOOR); + } + lines[i].special = 0; + } + break; + case 10: //Culling plane + lines[i].args[0] = tag; + lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); + break; case 20: //PolyObject first line { INT32 check = -1; diff --git a/src/p_spec.c b/src/p_spec.c index 4afc4946d..ca08ad875 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5863,16 +5863,16 @@ void P_InitSpecials(void) globalweather = mapheaderinfo[gamemap-1]->weather; } -static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs) +void P_ApplyFlatAlignment(sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs, boolean floor, boolean ceiling) { - if (!(master->flags & ML_NETONLY)) // Modify floor flat alignment unless ML_NETONLY flag is set + if (floor) { sector->floorpic_angle = flatangle; sector->floor_xoffs += xoffs; sector->floor_yoffs += yoffs; } - if (!(master->flags & ML_NONET)) // Modify ceiling flat alignment unless ML_NONET flag is set + if (ceiling) { sector->ceilingpic_angle = flatangle; sector->ceiling_xoffs += xoffs; @@ -6046,23 +6046,20 @@ void P_SpawnSpecials(boolean fromnetsave) { mtag_t tag = Tag_FGet(&lines[i].tags); - if (lines[i].special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment in netgames... + // set line specials to 0 here too, same reason as above + if (netgame || multiplayer) { - // set line specials to 0 here too, same reason as above - if (netgame || multiplayer) - { - if (lines[i].flags & ML_NONET) - { - lines[i].special = 0; - continue; - } - } - else if (lines[i].flags & ML_NETONLY) + if (lines[i].flags & ML_NONET) { lines[i].special = 0; continue; } } + else if (lines[i].flags & ML_NETONLY) + { + lines[i].special = 0; + continue; + } switch (lines[i].special) { @@ -6102,37 +6099,22 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 7: // Flat alignment - redone by toast - if ((lines[i].flags & (ML_NETONLY|ML_NONET)) != (ML_NETONLY|ML_NONET)) // If you can do something... + { + // Set calculated offsets such that line's v1 is the apparent origin + angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)); + fixed_t xoffs = -lines[i].v1->x; + fixed_t yoffs = lines[i].v1->y; + + //If no tag is given, apply to front sector + if (lines[i].args[0] == 0) + P_ApplyFlatAlignment(lines[i].frontsector, flatangle, xoffs, yoffs, lines[i].args[1] != TMP_CEILING, lines[i].args[1] != TMP_FLOOR); + else { - angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)); - fixed_t xoffs; - fixed_t yoffs; - - if (lines[i].flags & ML_EFFECT6) // Set offset through x and y texture offsets if ML_EFFECT6 flag is set - { - xoffs = sides[lines[i].sidenum[0]].textureoffset; - yoffs = sides[lines[i].sidenum[0]].rowoffset; - } - else // Otherwise, set calculated offsets such that line's v1 is the apparent origin - { - xoffs = -lines[i].v1->x; - yoffs = lines[i].v1->y; - } - - //If no tag is given, apply to front sector - if (tag == 0) - P_ApplyFlatAlignment(lines + i, lines[i].frontsector, flatangle, xoffs, yoffs); - else - { - TAG_ITER_SECTORS(tag, s) - P_ApplyFlatAlignment(lines + i, sectors + s, flatangle, xoffs, yoffs); - } + TAG_ITER_SECTORS(lines[i].args[0], s) + P_ApplyFlatAlignment(sectors + s, flatangle, xoffs, yoffs, lines[i].args[1] != TMP_CEILING, lines[i].args[1] != TMP_FLOOR); } - else // Otherwise, print a helpful warning. Can I do no less? - CONS_Alert(CONS_WARNING, - M_GetText("Flat alignment linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), - tag); break; + } case 8: // Sector Parameters TAG_ITER_SECTORS(tag, s) @@ -6162,7 +6144,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 10: // Vertical culling plane for sprites and FOFs - TAG_ITER_SECTORS(tag, s) + TAG_ITER_SECTORS(lines[i].args[0], s) sectors[s].cullheight = &lines[i]; // This allows it to change in realtime! break; diff --git a/src/p_spec.h b/src/p_spec.h index f77af5a0d..6b98ca0e3 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -454,6 +454,7 @@ void P_SetupLevelFlatAnims(void); // at map load void P_InitSpecials(void); +void P_ApplyFlatAlignment(sector_t* sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs, boolean floor, boolean ceiling); void P_SpawnSpecials(boolean fromnetsave); // every tic diff --git a/src/r_main.c b/src/r_main.c index 8729b5dcb..b1d27fdff 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -445,7 +445,7 @@ fixed_t R_ScaleFromGlobalAngle(angle_t visangle) // R_DoCulling // Checks viewz and top/bottom heights of an item against culling planes // Returns true if the item is to be culled, i.e it shouldn't be drawn! -// if ML_NOCLIMB is set, the camera view is required to be in the same area for culling to occur +// if args[1] is set, the camera view is required to be in the same area for culling to occur boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph) { fixed_t cullplane; @@ -454,7 +454,7 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe return false; cullplane = cullheight->frontsector->floorheight; - if (cullheight->flags & ML_NOCLIMB) // Group culling + if (cullheight->args[1]) // Group culling { if (!viewcullheight) return false; From 1aa9ba1447a970638c99be8e62767f993c1fdf4e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 08:31:47 +0100 Subject: [PATCH 241/326] Delete removed mobj types from deh_tables.c --- src/deh_tables.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index f4074cf08..f73f10151 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4113,17 +4113,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_FINISHFLAG", // Finish flag // Ambient Sounds - "MT_AWATERA", // Ambient Water Sound 1 - "MT_AWATERB", // Ambient Water Sound 2 - "MT_AWATERC", // Ambient Water Sound 3 - "MT_AWATERD", // Ambient Water Sound 4 - "MT_AWATERE", // Ambient Water Sound 5 - "MT_AWATERF", // Ambient Water Sound 6 - "MT_AWATERG", // Ambient Water Sound 7 - "MT_AWATERH", // Ambient Water Sound 8 - "MT_RANDOMAMBIENT", - "MT_RANDOMAMBIENT2", - "MT_MACHINEAMBIENCE", + "MT_AMBIENT", "MT_CORK", "MT_LHRT", @@ -4227,7 +4217,6 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_CRUMBLEOBJ", // Sound generator for crumbling platform "MT_TUBEWAYPOINT", "MT_PUSH", - "MT_PULL", "MT_GHOST", "MT_OVERLAY", "MT_ANGLEMAN", From c76d0e33268b059295d5ce3bee1df0dc8077a187 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 10:42:20 +0100 Subject: [PATCH 242/326] Implement linedef executor for changing linedef args --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 25 ++++++++++++++++++++ src/p_spec.c | 23 ++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index b82ab30c9..b36ca21f9 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -4584,6 +4584,31 @@ udmf enum = "setadd"; } } + + 468 + { + title = "Change Linedef Argument"; + prefix = "(468)"; + arg0 + { + title = "Linedef tag"; + type = 15; + } + arg1 + { + title = "Argument"; + } + arg2 + { + title = "Value"; + } + arg3 + { + title = "Set/Add?"; + type = 11; + enum = "setadd"; + } + } } linedefexecpoly diff --git a/src/p_spec.c b/src/p_spec.c index ca08ad875..5b2532f93 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3778,6 +3778,29 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; + case 468: // Change linedef executor argument + { + INT32 linenum; + + if (!udmf) + break; + + if (line->args[1] < 0 || line->args[1] >= NUMLINEARGS) + { + CONS_Debug(DBG_GAMELOGIC, "Linedef type 468: Invalid linedef arg %d\n", line->args[1]); + break; + } + + TAG_ITER_LINES(line->args[0], linenum) + { + if (line->args[3]) + lines[linenum].args[line->args[1]] += line->args[2]; + else + lines[linenum].args[line->args[1]] = line->args[2]; + } + } + break; + case 480: // Polyobj_DoorSlide case 481: // Polyobj_DoorSwing PolyDoor(line); From 234e8f5f8f1ab0e256b8071f5bda0881aac464c9 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 10:55:39 +0100 Subject: [PATCH 243/326] Disable camera scanner effect in UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 2 +- src/p_spec.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index b36ca21f9..5abb11ae9 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -16,7 +16,7 @@ doom } 5 { - title = "Camera Scanner"; + title = "Camera Scanner "; prefix = "(5)"; } 7 diff --git a/src/p_spec.c b/src/p_spec.c index 5b2532f93..0dd38b7bc 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6116,6 +6116,9 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 5: // Change camera info + if (udmf) + break; + sec = sides[*lines[i].sidenum].sector - sectors; TAG_ITER_SECTORS(tag, s) P_AddCameraScanner(§ors[sec], §ors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)); From 3bac97ee65009f27e3b970e724c854c0e9e4446c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 10:59:26 +0100 Subject: [PATCH 244/326] Clean up P_SpawnSpecials a bit --- src/p_spec.c | 95 ---------------------------------------------------- 1 file changed, 95 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 4afc4946d..5108b4d73 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6086,15 +6086,6 @@ void P_SpawnSpecials(boolean fromnetsave) } break; - case 2: // Custom exit - break; - - case 3: // Zoom Tube Parameters - break; - - case 4: // Speed pad (combines with sector special Section3:5 or Section3:6) - break; - case 5: // Change camera info sec = sides[*lines[i].sidenum].sector - sectors; TAG_ITER_SECTORS(tag, s) @@ -6158,9 +6149,6 @@ void P_SpawnSpecials(boolean fromnetsave) } break; - case 9: // Chain Parameters - break; - case 10: // Vertical culling plane for sprites and FOFs TAG_ITER_SECTORS(tag, s) sectors[s].cullheight = &lines[i]; // This allows it to change in realtime! @@ -6734,8 +6722,6 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT); break; - break; - case 308: // Race-only linedef executor. Triggers once. if (!P_CheckGametypeRules(lines[i].args[2], (UINT32)lines[i].args[1])) { @@ -6769,51 +6755,6 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMXT_EACHTIMEENTERANDEXIT); break; - // NiGHTS trigger executors - case 323: - case 325: - case 327: - case 329: - break; - - case 399: // Linedef execute on map load - // This is handled in P_RunLevelLoadExecutors. - break; - - case 400: - case 401: - case 402: - case 403: - case 404: - case 405: - case 406: - case 407: - case 408: - case 409: - case 410: - case 411: - case 412: - case 413: - case 414: - case 415: - case 416: - case 417: - case 418: - case 419: - case 420: - case 421: - case 422: - case 423: - case 424: - case 425: - case 426: - case 427: - case 428: - case 429: - case 430: - case 431: - break; - case 449: // Enable bosses with parameter { INT32 bossid = lines[i].args[0]; @@ -6832,42 +6773,6 @@ void P_SpawnSpecials(boolean fromnetsave) break; } - // 500 is used for a scroller - // 501 is used for a scroller - // 502 is used for a scroller - // 503 is used for a scroller - // 504 is used for a scroller - // 505 is used for a scroller - // 506 is used for a scroller - // 507 is used for a scroller - // 508 is used for a scroller - // 510 is used for a scroller - // 511 is used for a scroller - // 512 is used for a scroller - // 513 is used for a scroller - // 514 is used for a scroller - // 515 is used for a scroller - // 520 is used for a scroller - // 521 is used for a scroller - // 522 is used for a scroller - // 523 is used for a scroller - // 524 is used for a scroller - // 525 is used for a scroller - // 530 is used for a scroller - // 531 is used for a scroller - // 532 is used for a scroller - // 533 is used for a scroller - // 534 is used for a scroller - // 535 is used for a scroller - // 540 is used for friction - // 541 is used for wind - // 542 is used for upwards wind - // 543 is used for downwards wind - // 544 is used for current - // 545 is used for upwards current - // 546 is used for downwards current - // 547 is used for push/pull - case 600: // Copy light level to tagged sector's planes sec = sides[*lines[i].sidenum].sector-sectors; TAG_ITER_SECTORS(lines[i].args[0], s) From 49c1645b5fef84c56cfe161a4a207292a9974642 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 11:03:00 +0100 Subject: [PATCH 245/326] Adapt linedef type 63 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 11 +++++++++++ src/p_setup.c | 3 +++ src/p_spec.c | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 5abb11ae9..c2bcfa3b3 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1640,6 +1640,17 @@ udmf title = "Horizon Effect"; prefix = "(41)"; } + + 63 + { + title = "Fake Floor/Ceiling Planes"; + prefix = "(63)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + } } parameters diff --git a/src/p_setup.c b/src/p_setup.c index 4564ec75e..9fe4446a6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3340,6 +3340,9 @@ static void P_ConvertBinaryMap(void) } lines[i].special = 61; break; + case 63: //Fake floor/ceiling planes + lines[i].args[0] = tag; + break; case 66: //Move floor by displacement case 67: //Move ceiling by displacement case 68: //Move floor and ceiling by displacement diff --git a/src/p_spec.c b/src/p_spec.c index 22ca43bbb..82f18b402 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6206,7 +6206,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 63: // support for drawn heights coming from different sector sec = sides[*lines[i].sidenum].sector-sectors; - TAG_ITER_SECTORS(tag, s) + TAG_ITER_SECTORS(lines[i].args[0], s) sectors[s].heightsec = (INT32)sec; break; From 1e1ea22e5124d7c91d4b5390e04f79a7aab113bf Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 13:53:38 +0100 Subject: [PATCH 246/326] Separate thinker structs for dynamic line and vertex slopes --- src/p_saveg.c | 32 ++++++++++++++++++++++++-------- src/p_slopes.c | 44 +++++++++++++++++++++----------------------- src/p_slopes.h | 20 ++++++++++---------- 3 files changed, 55 insertions(+), 41 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 4d958f924..ffca42cd3 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2281,16 +2281,23 @@ static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, ht->type); } -static inline void SaveDynamicSlopeThinker(const thinker_t *th, const UINT8 type) +static inline void SaveDynamicLineSlopeThinker(const thinker_t *th, const UINT8 type) { - const dynplanethink_t* ht = (const void*)th; + const dynlineplanethink_t* ht = (const void*)th; WRITEUINT8(save_p, type); WRITEUINT8(save_p, ht->type); WRITEUINT32(save_p, SaveSlope(ht->slope)); WRITEUINT32(save_p, SaveLine(ht->sourceline)); WRITEFIXED(save_p, ht->extent); +} +static inline void SaveDynamicVertexSlopeThinker(const thinker_t *th, const UINT8 type) +{ + const dynvertexplanethink_t* ht = (const void*)th; + + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveSlope(ht->slope)); WRITEMEM(save_p, ht->tags, sizeof(ht->tags)); WRITEMEM(save_p, ht->vex, sizeof(ht->vex)); } @@ -2617,12 +2624,12 @@ static void P_NetArchiveThinkers(void) } else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine) { - SaveDynamicSlopeThinker(th, tc_dynslopeline); + SaveDynamicLineSlopeThinker(th, tc_dynslopeline); continue; } else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert) { - SaveDynamicSlopeThinker(th, tc_dynslopevert); + SaveDynamicVertexSlopeThinker(th, tc_dynslopevert); continue; } #ifdef PARANOIA @@ -3447,15 +3454,24 @@ static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker) return &ht->thinker; } -static inline thinker_t* LoadDynamicSlopeThinker(actionf_p1 thinker) +static inline thinker_t* LoadDynamicLineSlopeThinker(actionf_p1 thinker) { - dynplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); + dynlineplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->type = READUINT8(save_p); ht->slope = LoadSlope(READUINT32(save_p)); ht->sourceline = LoadLine(READUINT32(save_p)); ht->extent = READFIXED(save_p); + return &ht->thinker; +} + +static inline thinker_t* LoadDynamicVertexSlopeThinker(actionf_p1 thinker) +{ + dynvertexplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + + ht->slope = LoadSlope(READUINT32(save_p)); READMEM(save_p, ht->tags, sizeof(ht->tags)); READMEM(save_p, ht->vex, sizeof(ht->vex)); return &ht->thinker; @@ -3770,11 +3786,11 @@ static void P_NetUnArchiveThinkers(void) break; case tc_dynslopeline: - th = LoadDynamicSlopeThinker((actionf_p1)T_DynamicSlopeLine); + th = LoadDynamicLineSlopeThinker((actionf_p1)T_DynamicSlopeLine); break; case tc_dynslopevert: - th = LoadDynamicSlopeThinker((actionf_p1)T_DynamicSlopeVert); + th = LoadDynamicVertexSlopeThinker((actionf_p1)T_DynamicSlopeVert); break; case tc_scroll: diff --git a/src/p_slopes.c b/src/p_slopes.c index c0cc3a98e..415642abf 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -121,7 +121,7 @@ static void ReconfigureViaConstants (pslope_t *slope, const fixed_t a, const fix } /// Recalculate dynamic slopes. -void T_DynamicSlopeLine (dynplanethink_t* th) +void T_DynamicSlopeLine (dynlineplanethink_t* th) { pslope_t* slope = th->slope; line_t* srcline = th->sourceline; @@ -161,7 +161,7 @@ void T_DynamicSlopeLine (dynplanethink_t* th) } /// Mapthing-defined -void T_DynamicSlopeVert (dynplanethink_t* th) +void T_DynamicSlopeVert (dynvertexplanethink_t* th) { pslope_t* slope = th->slope; @@ -180,28 +180,26 @@ void T_DynamicSlopeVert (dynplanethink_t* th) ReconfigureViaVertexes(slope, th->vex[0], th->vex[1], th->vex[2]); } -static inline void P_AddDynSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent, const INT16 tags[3], const vector3_t vx[3]) +static inline void P_AddDynLineSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent) { - dynplanethink_t* th = Z_Calloc(sizeof (*th), PU_LEVSPEC, NULL); - switch (type) - { - case DP_VERTEX: - th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeVert; - memcpy(th->tags, tags, sizeof(th->tags)); - memcpy(th->vex, vx, sizeof(th->vex)); - break; - default: - th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeLine; - th->sourceline = sourceline; - th->extent = extent; - } - + dynlineplanethink_t* th = Z_Calloc(sizeof (*th), PU_LEVSPEC, NULL); + th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeLine; th->slope = slope; th->type = type; - + th->sourceline = sourceline; + th->extent = extent; P_AddThinker(THINK_DYNSLOPE, &th->thinker); } +static inline void P_AddDynVertexSlopeThinker (pslope_t* slope, const INT16 tags[3], const vector3_t vx[3]) +{ + dynvertexplanethink_t* th = Z_Calloc(sizeof (*th), PU_LEVSPEC, NULL); + th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeVert; + th->slope = slope; + memcpy(th->tags, tags, sizeof(th->tags)); + memcpy(th->vex, vx, sizeof(th->vex)); + P_AddThinker(THINK_DYNSLOPE, &th->thinker); +} /// Create a new slope and add it to the slope list. static inline pslope_t* Slope_Add (const UINT8 flags) @@ -358,7 +356,7 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) P_CalculateSlopeNormal(fslope); if (spawnthinker && (flags & SL_DYNAMIC)) - P_AddDynSlopeThinker(fslope, DP_FRONTFLOOR, line, extent, NULL, NULL); + P_AddDynLineSlopeThinker(fslope, DP_FRONTFLOOR, line, extent); } if(frontceil) { @@ -375,7 +373,7 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) P_CalculateSlopeNormal(cslope); if (spawnthinker && (flags & SL_DYNAMIC)) - P_AddDynSlopeThinker(cslope, DP_FRONTCEIL, line, extent, NULL, NULL); + P_AddDynLineSlopeThinker(cslope, DP_FRONTCEIL, line, extent); } } if(backfloor || backceil) @@ -415,7 +413,7 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) P_CalculateSlopeNormal(fslope); if (spawnthinker && (flags & SL_DYNAMIC)) - P_AddDynSlopeThinker(fslope, DP_BACKFLOOR, line, extent, NULL, NULL); + P_AddDynLineSlopeThinker(fslope, DP_BACKFLOOR, line, extent); } if(backceil) { @@ -432,7 +430,7 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) P_CalculateSlopeNormal(cslope); if (spawnthinker && (flags & SL_DYNAMIC)) - P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL); + P_AddDynLineSlopeThinker(cslope, DP_BACKCEIL, line, extent); } } } @@ -476,7 +474,7 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag ReconfigureViaVertexes(ret, vx[0], vx[1], vx[2]); if (spawnthinker && (flags & SL_DYNAMIC)) - P_AddDynSlopeThinker(ret, DP_VERTEX, NULL, 0, tags, vx); + P_AddDynVertexSlopeThinker(ret, tags, vx); return ret; } diff --git a/src/p_slopes.h b/src/p_slopes.h index 43cd3edb0..45588d463 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -95,26 +95,26 @@ typedef enum { DP_FRONTCEIL, DP_BACKFLOOR, DP_BACKCEIL, - DP_VERTEX } dynplanetype_t; /// Permit slopes to be dynamically altered through a thinker. typedef struct { thinker_t thinker; - - pslope_t* slope; + pslope_t *slope; dynplanetype_t type; - - // Used by line slopes. - line_t* sourceline; + line_t *sourceline; fixed_t extent; +} dynlineplanethink_t; - // Used by mapthing vertex slopes. +typedef struct +{ + thinker_t thinker; + pslope_t *slope; INT16 tags[3]; vector3_t vex[3]; -} dynplanethink_t; +} dynvertexplanethink_t; -void T_DynamicSlopeLine (dynplanethink_t* th); -void T_DynamicSlopeVert (dynplanethink_t* th); +void T_DynamicSlopeLine (dynlineplanethink_t* th); +void T_DynamicSlopeVert (dynvertexplanethink_t* th); #endif // #ifndef P_SLOPES_H__ From 228efa5ffc77a8fcefc0bdb28fe9d0a1aec0e72a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 15:29:59 +0100 Subject: [PATCH 247/326] Add "relative" setting to linedef type 799 and adapt it to UDMF --- extras/conf/SRB2-22.cfg | 1 + extras/conf/udb/Includes/SRB222_linedefs.cfg | 16 +++++++++ src/p_saveg.c | 16 +++++++-- src/p_setup.c | 4 ++- src/p_slopes.c | 35 +++++++++++++------- src/p_slopes.h | 5 ++- 6 files changed, 60 insertions(+), 17 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 9aeada89b..ec568e865 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -3253,6 +3253,7 @@ linedeftypes { title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; prefix = "(799)"; + flags64text = "[6] Use relative heights"; } } diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index c2bcfa3b3..169709de4 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -5233,5 +5233,21 @@ udmf } } } + + 799 + { + title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; + prefix = "(799)"; + arg0 + { + title = "Apply height"; + type = 11; + enum + { + 0 = "Absolute"; + 1 = "Relative"; + } + } + } } } diff --git a/src/p_saveg.c b/src/p_saveg.c index ffca42cd3..5e204f9bc 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2294,12 +2294,17 @@ static inline void SaveDynamicLineSlopeThinker(const thinker_t *th, const UINT8 static inline void SaveDynamicVertexSlopeThinker(const thinker_t *th, const UINT8 type) { + size_t i; const dynvertexplanethink_t* ht = (const void*)th; WRITEUINT8(save_p, type); WRITEUINT32(save_p, SaveSlope(ht->slope)); - WRITEMEM(save_p, ht->tags, sizeof(ht->tags)); - WRITEMEM(save_p, ht->vex, sizeof(ht->vex)); + for (i = 0; i < 3; i++) + WRITEUINT32(save_p, SaveSector(ht->secs[i])); + WRITEMEM(save_p, ht->vex, sizeof(ht->vex)); + WRITEMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights)); + WRITEMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights)); + WRITEUINT8(save_p, ht->relative); } static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type) @@ -3468,12 +3473,17 @@ static inline thinker_t* LoadDynamicLineSlopeThinker(actionf_p1 thinker) static inline thinker_t* LoadDynamicVertexSlopeThinker(actionf_p1 thinker) { + size_t i; dynvertexplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->slope = LoadSlope(READUINT32(save_p)); - READMEM(save_p, ht->tags, sizeof(ht->tags)); + for (i = 0; i < 3; i++) + ht->secs[i] = LoadSector(READUINT32(save_p)); READMEM(save_p, ht->vex, sizeof(ht->vex)); + READMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights)); + READMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights)); + ht->relative = READUINT8(save_p); return &ht->thinker; } diff --git a/src/p_setup.c b/src/p_setup.c index 9fe4446a6..2f815a228 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4885,7 +4885,9 @@ static void P_ConvertBinaryMap(void) lines[i].args[4] |= TMSC_BACKTOFRONTCEILING; lines[i].special = 720; break; - + case 799: //Set dynamic slope vertex to front sector height + lines[i].args[0] = !!(lines[i].flags & ML_NOCLIMB); + break; case 900: //Translucent wall (10%) case 901: //Translucent wall (20%) case 902: //Translucent wall (30%) diff --git a/src/p_slopes.c b/src/p_slopes.c index 415642abf..b9154b890 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -163,21 +163,17 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th) /// Mapthing-defined void T_DynamicSlopeVert (dynvertexplanethink_t* th) { - pslope_t* slope = th->slope; - size_t i; - INT32 l; - for (i = 0; i < 3; i++) { - l = Tag_FindLineSpecial(799, th->tags[i]); - if (l != -1) { - th->vex[i].z = lines[l].frontsector->floorheight; - } + for (i = 0; i < 3; i++) + { + if (th->relative & (1 << i)) + th->vex[i].z = th->origvecheights[i] + (th->secs[i]->floorheight - th->origsecheights[i]); else - th->vex[i].z = 0; + th->vex[i].z = th->secs[i]->floorheight; } - ReconfigureViaVertexes(slope, th->vex[0], th->vex[1], th->vex[2]); + ReconfigureViaVertexes(th->slope, th->vex[0], th->vex[1], th->vex[2]); } static inline void P_AddDynLineSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent) @@ -194,10 +190,25 @@ static inline void P_AddDynLineSlopeThinker (pslope_t* slope, dynplanetype_t typ static inline void P_AddDynVertexSlopeThinker (pslope_t* slope, const INT16 tags[3], const vector3_t vx[3]) { dynvertexplanethink_t* th = Z_Calloc(sizeof (*th), PU_LEVSPEC, NULL); + size_t i; + INT32 l; th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeVert; th->slope = slope; - memcpy(th->tags, tags, sizeof(th->tags)); - memcpy(th->vex, vx, sizeof(th->vex)); + + for (i = 0; i < 3; i++) { + l = Tag_FindLineSpecial(799, tags[i]); + if (l == -1) + { + Z_Free(th); + return; + } + th->secs[i] = lines[l].frontsector; + th->vex[i] = vx[i]; + th->origsecheights[i] = lines[l].frontsector->floorheight; + th->origvecheights[i] = vx[i].z; + if (lines[l].args[0]) + th->relative |= 1<thinker); } diff --git a/src/p_slopes.h b/src/p_slopes.h index 45588d463..0b3e0b517 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -111,8 +111,11 @@ typedef struct { thinker_t thinker; pslope_t *slope; - INT16 tags[3]; + sector_t *secs[3]; vector3_t vex[3]; + fixed_t origsecheights[3]; + fixed_t origvecheights[3]; + UINT8 relative; } dynvertexplanethink_t; void T_DynamicSlopeLine (dynlineplanethink_t* th); From 338f1357a61786e42de31849d7f7fc8ce45e84cb Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 15:53:20 +0100 Subject: [PATCH 248/326] Particle generator: Use args[6] instead of angle for tagging --- extras/conf/udb/Includes/SRB222_things.cfg | 5 +++++ src/p_mobj.c | 4 ++-- src/p_setup.c | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 9d557060e..0cb0287c5 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -5465,6 +5465,11 @@ udmf { title = "Rising distance"; } + arg6 + { + title = "Heights control linedef"; + type = 15; + } } 758 { diff --git a/src/p_mobj.c b/src/p_mobj.c index 7b6f14fa4..46510200e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12430,8 +12430,8 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj) INT32 line; const size_t mthingi = (size_t)(mthing - mapthings); - // Find the corresponding linedef special, using angle as tag - line = Tag_FindLineSpecial(15, mthing->angle); + // Find the corresponding linedef special, using args[6] as tag + line = mthing->args[6] ? Tag_FindLineSpecial(15, mthing->args[6]) : -1; type = mthing->stringargs[0] ? get_number(mthing->stringargs[0]) : MT_PARTICLE; diff --git a/src/p_setup.c b/src/p_setup.c index e0c805a4b..77d009194 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5206,6 +5206,7 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[2] = sides[lines[j].sidenum[0]].textureoffset >> FRACBITS; mapthings[i].args[3] = sides[lines[j].sidenum[0]].rowoffset >> FRACBITS; mapthings[i].args[4] = lines[j].backsector ? sides[lines[j].sidenum[1]].textureoffset >> FRACBITS : 0; + mapthings[i].args[6] = mapthings[i].angle; if (sides[lines[j].sidenum[0]].toptexture) P_WriteConstant(sides[lines[j].sidenum[0]].toptexture, &mapthings[i].stringargs[0]); break; From 0b3180cdfa4bddc6a87343e22049ed897a56f324 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 21:03:47 +0100 Subject: [PATCH 249/326] Adapt linedef type 64 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 34 +++++++++++++++++++ src/p_setup.c | 8 +++++ src/p_spec.c | 35 +++++++++++++------- 3 files changed, 65 insertions(+), 12 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 169709de4..684ed5ac8 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1662,6 +1662,40 @@ udmf title = "Fan Particle Generator Heights"; prefix = "(15)"; } + + 64 + { + title = "Continuously Appearing/Disappearing FOF"; + prefix = "(64)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Control sector tag"; + type = 13; + } + arg2 + { + title = "On time"; + } + arg3 + { + title = "Off time"; + } + arg4 + { + title = "Initial delay"; + } + arg5 + { + title = "Play sound?"; + type = 11; + enum = "yesno"; + } + } } polyobject diff --git a/src/p_setup.c b/src/p_setup.c index c6cfdfe1d..c8da584e8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3343,6 +3343,14 @@ static void P_ConvertBinaryMap(void) case 63: //Fake floor/ceiling planes lines[i].args[0] = tag; break; + case 64: //Appearing/disappearing FOF + lines[i].args[0] = (lines[i].flags & ML_BLOCKMONSTERS) ? 0 : tag; + lines[i].args[1] = (lines[i].flags & ML_BLOCKMONSTERS) ? tag : Tag_FGet(&lines[i].frontsector->tags); + lines[i].args[2] = lines[i].dx >> FRACBITS; + lines[i].args[3] = lines[i].dy >> FRACBITS; + lines[i].args[4] = lines[i].frontsector->floorheight >> FRACBITS; + lines[i].args[5] = !!(lines[i].flags & ML_NOCLIMB); + break; case 66: //Move floor by displacement case 67: //Move ceiling by displacement case 68: //Move floor and ceiling by displacement diff --git a/src/p_spec.c b/src/p_spec.c index 82f18b402..f202cede2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2989,7 +2989,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->stringargs[0]) LUA_HookLinedefExecute(line, mo, callsec); else - CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in arg0str)\n", sizeu1(line-lines)); + CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in stringarg0)\n", sizeu1(line-lines)); break; case 444: // Earthquake camera @@ -6211,19 +6211,30 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 64: // Appearing/Disappearing FOF option - if (lines[i].flags & ML_BLOCKMONSTERS) { // Find FOFs by control sector tag - TAG_ITER_SECTORS(tag, s) - for (j = 0; (unsigned)j < sectors[s].linecount; j++) - if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) - Add_MasterDisappearer(abs(lines[i].dx>>FRACBITS), abs(lines[i].dy>>FRACBITS), abs(sides[lines[i].sidenum[0]].sector->floorheight>>FRACBITS), (INT32)(sectors[s].lines[j]-lines), (INT32)i); - } else // Find FOFs by effect sector tag + if (lines[i].args[0] == 0) // Find FOFs by control sector tag { - TAG_ITER_LINES(tag, s) + TAG_ITER_SECTORS(lines[i].args[1], s) { - if ((size_t)s == i) + for (j = 0; (unsigned)j < sectors[s].linecount; j++) + { + if (sectors[s].lines[j]->special < 100 || sectors[s].lines[j]->special >= 300) + continue; + + Add_MasterDisappearer(abs(lines[i].args[2]), abs(lines[i].args[3]), abs(lines[i].args[4]), (INT32)(sectors[s].lines[j] - lines), (INT32)i); + } + } + } + else // Find FOFs by effect sector tag + { + TAG_ITER_LINES(lines[i].args[0], s) + { + if (lines[s].special < 100 || lines[s].special >= 300) continue; - if (Tag_Find(&sides[lines[s].sidenum[0]].sector->tags, Tag_FGet(&sides[lines[i].sidenum[0]].sector->tags))) - Add_MasterDisappearer(abs(lines[i].dx>>FRACBITS), abs(lines[i].dy>>FRACBITS), abs(sides[lines[i].sidenum[0]].sector->floorheight>>FRACBITS), s, (INT32)i); + + if (lines[i].args[1] != 0 && !Tag_Find(&lines[s].frontsector->tags, lines[i].args[1])) + continue; + + Add_MasterDisappearer(abs(lines[i].args[2]), abs(lines[i].args[3]), abs(lines[i].args[4]), s, (INT32)i); } } break; @@ -7469,7 +7480,7 @@ void T_Disappear(disappear_t *d) { rover->flags |= FF_EXISTS; - if (!(lines[d->sourceline].flags & ML_NOCLIMB)) + if (!(lines[d->sourceline].args[5])) { sectors[s].soundorg.z = P_GetFFloorTopZAt(rover, sectors[s].soundorg.x, sectors[s].soundorg.y); S_StartSound(§ors[s].soundorg, sfx_appear); From 208f852c4b931c9a6970eb1f62357ae61e2a216c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 21:04:55 +0100 Subject: [PATCH 250/326] Remove bridge thinker linedef type from UDB config --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 5 ----- 1 file changed, 5 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 684ed5ac8..0de8bb152 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -125,11 +125,6 @@ doom title = "Continuously Appearing/Disappearing FOF"; prefix = "(64)"; } - 65 - { - title = "Bridge Thinker "; - prefix = "(65)"; - } 76 { title = "Make FOF Bouncy"; From 69797377c4bededbae4358d11c1157d52a390b8d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 23:03:37 +0100 Subject: [PATCH 251/326] Adapt some parameter linedef types to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 98 ++++++++++++++++++++ src/p_setup.c | 27 ++++++ src/p_spec.c | 72 +++++++------- src/p_spec.h | 12 +++ src/p_user.c | 4 +- 5 files changed, 180 insertions(+), 33 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 0de8bb152..097ac02eb 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1652,12 +1652,110 @@ udmf { title = "Parameters"; + 2 + { + title = "Custom Exit"; + prefix = "(2)"; + arg0 + { + title = "Next map"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Skip score tally"; + 2 = "Check emeralds"; + } + } + arg2 + { + title = "Next map (all emeralds)"; + } + } + + 3 + { + title = "Zoom Tube Parameters"; + prefix = "(3)"; + arg0 + { + title = "Speed"; + } + arg1 + { + title = "Sequence"; + } + arg2 + { + title = "Check player direction?"; + type = 11; + enum = "yesno"; + } + } + + 4 + { + title = "Speed Pad Parameters"; + prefix = "(4)"; + arg0 + { + title = "Speed"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "No teleport to center"; + 2 = "Force spinning frames"; + } + } + stringarg0 + { + title = "Sound"; + } + } + + 11 + { + title = "Rope Hang Parameters"; + prefix = "(11)"; + arg0 + { + title = "Speed"; + } + arg1 + { + title = "Sequence"; + } + arg2 + { + title = "Loop?"; + type = 11; + enum = "yesno"; + } + } + 15 { title = "Fan Particle Generator Heights"; prefix = "(15)"; } + 16 + { + title = "Minecart Parameters"; + prefix = "(16)"; + arg0 + { + title = "Order"; + } + } + 64 { title = "Continuously Appearing/Disappearing FOF"; diff --git a/src/p_setup.c b/src/p_setup.c index c8da584e8..08ff08f98 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3179,6 +3179,25 @@ static void P_ConvertBinaryMap(void) switch (lines[i].special) { + case 2: //Custom exit + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[1] |= TMEF_SKIPTALLY; + if (lines[i].flags & ML_BLOCKMONSTERS) + lines[i].args[1] |= TMEF_EMERALDCHECK; + break; + case 3: //Zoom tube parameters + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[2] = !!(lines[i].flags & ML_EFFECT4); + break; + case 4: //Speed pad parameters + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + if (lines[i].flags & ML_EFFECT4) + lines[i].args[1] |= TMSP_NOTELEPORT; + if (lines[i].flags & ML_EFFECT5) + lines[i].args[1] |= TMSP_FORCESPIN; + P_WriteConstant(sides[lines[i].sidenum[0]].toptexture ? sides[lines[i].sidenum[0]].toptexture : sfx_spdpad, &lines[i].stringargs[0]); + break; case 7: //Sector flat alignment lines[i].args[0] = tag; if ((lines[i].flags & (ML_NETONLY|ML_NONET)) == (ML_NETONLY|ML_NONET)) @@ -3216,6 +3235,14 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = tag; lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); break; + case 11: //Rope hang parameters + lines[i].args[0] = (lines[i].flags & ML_NOCLIMB) ? 0 : sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[2] = !!(lines[i].flags & ML_EFFECT1); + break; + case 16: //Minecart parameters + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + break; case 20: //PolyObject first line { INT32 check = -1; diff --git a/src/p_spec.c b/src/p_spec.c index f202cede2..ab2f67d74 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4311,15 +4311,36 @@ static void P_ProcessEggCapsule(player_t *player, sector_t *sector) static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *roversector, mtag_t sectag) { - INT32 lineindex; + INT32 lineindex = -1; angle_t lineangle; fixed_t linespeed; fixed_t sfxnum; + size_t i; if (player->powers[pw_flashing] != 0 && player->powers[pw_flashing] < TICRATE/2) return; - lineindex = Tag_FindLineSpecial(4, sectag); + // Try for lines facing the sector itself, with tag 0. + for (i = 0; i < sector->linecount; i++) + { + line_t *li = sector->lines[i]; + + if (li->frontsector != sector) + continue; + + if (li->special != 4) + continue; + + if (!Tag_Find(&li->tags, 0)) + continue; + + lineindex = li - lines; + break; + } + + // Nothing found? Look via tag. + if (lineindex == -1) + lineindex = Tag_FindLineSpecial(4, sectag); if (lineindex == -1) { @@ -4328,7 +4349,7 @@ static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *rove } lineangle = R_PointToAngle2(lines[lineindex].v1->x, lines[lineindex].v1->y, lines[lineindex].v2->x, lines[lineindex].v2->y); - linespeed = sides[lines[lineindex].sidenum[0]].textureoffset; + linespeed = lines[lineindex].args[0] << FRACBITS; if (linespeed == 0) { @@ -4341,7 +4362,7 @@ static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *rove if (!demoplayback || P_ControlStyle(player) == CS_LMAOGALOG) P_SetPlayerAngle(player, player->mo->angle); - if (!(lines[lineindex].flags & ML_EFFECT4)) + if (!(lines[lineindex].args[1] & TMSP_NOTELEPORT)) { P_UnsetThingPosition(player->mo); if (roversector) // make FOF speed pads work @@ -4359,7 +4380,7 @@ static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *rove P_InstaThrust(player->mo, player->mo->angle, linespeed); - if (lines[lineindex].flags & ML_EFFECT5) // Roll! + if (lines[lineindex].args[1] & TMSP_FORCESPIN) // Roll! { if (!(player->pflags & PF_SPINNING)) player->pflags |= PF_SPINNING; @@ -4369,7 +4390,7 @@ static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *rove player->powers[pw_flashing] = TICRATE/3; - sfxnum = sides[lines[lineindex].sidenum[0]].toptexture; + sfxnum = lines[lineindex].stringargs[0] ? get_number(lines[lineindex].stringargs[0]) : sfx_spdpad; if (!sfxnum) sfxnum = sfx_spdpad; @@ -4414,13 +4435,13 @@ static void P_ProcessExitSector(player_t *player, boolean isTouching, mtag_t sec return; } - // Special goodies with the block monsters flag depending on emeralds collected - if ((lines[lineindex].flags & ML_BLOCKMONSTERS) && ALL7EMERALDS(emeralds)) - nextmapoverride = (INT16)(lines[lineindex].frontsector->ceilingheight>>FRACBITS); + // Special goodies depending on emeralds collected + if ((lines[lineindex].args[1] & TMEF_EMERALDCHECK) && ALL7EMERALDS(emeralds)) + nextmapoverride = (INT16)(udmf ? lines[lineindex].args[2] : lines[lineindex].frontsector->ceilingheight>>FRACBITS); else - nextmapoverride = (INT16)(lines[lineindex].frontsector->floorheight>>FRACBITS); + nextmapoverride = (INT16)(udmf ? lines[lineindex].args[0] : lines[lineindex].frontsector->floorheight>>FRACBITS); - if (lines[lineindex].flags & ML_NOCLIMB) + if (lines[lineindex].args[1] & TMEF_SKIPTALLY) skipstats = 1; } @@ -4491,10 +4512,10 @@ static void P_ProcessZoomTube(player_t *player, sector_t *sector, mtag_t sectag, } // Grab speed and sequence values - speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; + speed = abs(lines[lineindex].args[0])<<(FRACBITS-3); if (end) speed *= -1; - sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; + sequence = abs(lines[lineindex].args[1]); if (speed == 0) { @@ -4514,7 +4535,7 @@ static void P_ProcessZoomTube(player_t *player, sector_t *sector, mtag_t sectag, an = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->x, waypoint->y) - player->mo->angle; - if (an > ANGLE_90 && an < ANGLE_270 && !(lines[lineindex].flags & ML_EFFECT4)) + if (an > ANGLE_90 && an < ANGLE_270 && !(lines[lineindex].args[2])) return; // behind back P_SetTarget(&player->mo->tracer, waypoint); @@ -4625,14 +4646,8 @@ static void P_ProcessRopeHang(player_t *player, sector_t *sector, mtag_t sectag) } // Grab speed and sequence values - speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; - sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; - - if (speed == 0) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); - return; - } + speed = abs(lines[lineindex].args[0]) << (FRACBITS - 3); + sequence = abs(lines[lineindex].args[1]); // Find the closest waypoint // Find the preceding waypoint @@ -4694,21 +4709,21 @@ static void P_ProcessRopeHang(player_t *player, sector_t *sector, mtag_t sectag) P_ResetPlayer(player); player->mo->momx = player->mo->momy = player->mo->momz = 0; - if (lines[lineindex].flags & ML_EFFECT1) // Don't wrap + if (lines[lineindex].args[2]) // Don't wrap { mobj_t *highest = P_GetLastWaypoint(sequence); highest->flags |= MF_SLIDEME; } // Changing the conditions on these ifs to fix issues with snapping to the wrong spot -Red - if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == 0) + if ((lines[lineindex].args[2]) && waypointmid->health == 0) { closest = waypointhigh; player->mo->x = resulthigh.x; player->mo->y = resulthigh.y; player->mo->z = resulthigh.z - P_GetPlayerHeight(player); } - else if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == numwaypoints[sequence] - 1) + else if ((lines[lineindex].args[2]) && waypointmid->health == numwaypoints[sequence] - 1) { closest = waypointmid; player->mo->x = resultlow.x; @@ -4739,12 +4754,7 @@ static void P_ProcessRopeHang(player_t *player, sector_t *sector, mtag_t sectag) P_SetTarget(&player->mo->tracer, closest); player->powers[pw_carry] = CR_ROPEHANG; - - // Option for static ropes. - if (lines[lineindex].flags & ML_NOCLIMB) - player->speed = 0; - else - player->speed = speed; + player->speed = speed; S_StartSound(player->mo, sfx_s3k4a); diff --git a/src/p_spec.h b/src/p_spec.h index 6b98ca0e3..6b1db7faf 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -122,6 +122,18 @@ typedef enum TMB_BARRIER = 1<<1, } textmapbrakflags_t; +typedef enum +{ + TMEF_SKIPTALLY = 1, + TMEF_EMERALDCHECK = 1<<1, +} textmapexitflags_t; + +typedef enum +{ + TMSP_NOTELEPORT = 1, + TMSP_FORCESPIN = 1<<1, +} textmapspeedpadflags_t; + //FOF flags typedef enum { diff --git a/src/p_user.c b/src/p_user.c index 5be3370ae..60000afa0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10768,7 +10768,7 @@ static mobj_t *P_LookForRails(mobj_t* mobj, fixed_t c, fixed_t s, angle_t target fixed_t nx, ny; angle_t nang, dummy, angdiff; mobj_t *mark; - mobj_t *snax = P_GetAxis(sides[lines[lline].sidenum[0]].textureoffset >> FRACBITS); + mobj_t *snax = P_GetAxis(lines[lline].args[0]); if (!snax) return NULL; P_GetAxisPosition(x, y, snax, &nx, &ny, &nang, &dummy); @@ -10870,7 +10870,7 @@ static void P_MinecartThink(player_t *player) // Update axis if the cart is standing on a rail. if (sec && lnum != -1) { - mobj_t *axis = P_GetAxis(sides[lines[lnum].sidenum[0]].textureoffset >> FRACBITS); + mobj_t *axis = P_GetAxis(lines[lnum].args[0]); fixed_t newx, newy; angle_t targetangle, grind; angle_t prevangle, angdiff; From 9af28321a53e74f21dadaeff1cd6efae91dcf43b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 23:12:46 +0100 Subject: [PATCH 252/326] Fix unadapted flag for linedef type 426 --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 7084b8740..b5523698f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2664,7 +2664,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // Reset bot too. if (bot) { - if (line->flags & ML_NOCLIMB) + if (line->args[0]) P_TeleportMove(bot, mo->x, mo->y, mo->z); bot->momx = bot->momy = bot->momz = 1; bot->pmomz = 0; From 73ba288e5d8bf410b08216a3bb2ab8fec4cf3cb3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 29 Dec 2021 23:45:43 +0100 Subject: [PATCH 253/326] P_ProcessLinedefsAfterSidedefs: Skip text copying in UDMF --- src/p_setup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 08ff08f98..16019e5c0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2048,6 +2048,9 @@ static void P_ProcessLinedefsAfterSidedefs(void) 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; + if (udmf) + continue; + switch (ld->special) { // Compile linedef 'text' from both sidedefs 'text' for appropriate specials. @@ -2068,8 +2071,6 @@ static void P_ProcessLinedefsAfterSidedefs(void) break; case 447: // Change colormap case 455: // Fade colormap - if (udmf) - break; if (ld->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets) { extracolormap_t *exc = R_CopyColormap(sides[ld->sidenum[0]].colormap_data, false); From 696d4945a7a31825f13334acc401d78fbeafd43a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 07:54:16 +0100 Subject: [PATCH 254/326] Adapt linedef type 14 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 27 +++++++++++++++++++ src/p_floor.c | 28 +++++++++----------- src/p_setup.c | 6 +++++ 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 097ac02eb..7c2411dc8 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1717,6 +1717,7 @@ udmf stringarg0 { title = "Sound"; + type = 2; } } @@ -1740,6 +1741,31 @@ udmf } } + 14 + { + title = "Bustable Block Parameters"; + prefix = "(14)"; + arg0 + { + title = "Debris spacing"; + } + arg1 + { + title = "Debris lifetime"; + } + arg2 + { + title = "Launch from center?"; + type = 11; + enum = "noyes"; + } + stringarg0 + { + title = "Debris object type"; + type = 2; + } + } + 15 { title = "Fan Particle Generator Heights"; @@ -4699,6 +4725,7 @@ udmf stringarg0 { title = "Prompt name"; + type = 2; } } diff --git a/src/p_floor.c b/src/p_floor.c index c3a13d802..85a1f54a8 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -11,6 +11,7 @@ /// \file p_floor.c /// \brief Floor animation, elevators +#include "dehacked.h" #include "doomdef.h" #include "doomstat.h" #include "m_random.h" @@ -1812,7 +1813,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) fixed_t leftx, rightx, topy, bottomy, topz, bottomz, widthfactor, heightfactor, a, b, c, spacing; mobjtype_t type; tic_t lifetime; - INT16 flags; + boolean fromcenter; sector_t *controlsec = rover->master->frontsector; mtag_t tag = Tag_FGet(&controlsec->tags); @@ -1842,25 +1843,20 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) spacing = (32<>FRACBITS != -1) - lifetime = (sides[lines[tagline].sidenum[0]].rowoffset>>FRACBITS); - else - lifetime = 0; - } - flags = lines[tagline].flags; + if (lines[tagline].stringargs[0]) + type = get_number(lines[tagline].stringargs[0]); + if (lines[tagline].args[0]) + spacing = lines[tagline].args[0] << FRACBITS; + if (lines[tagline].args[1]) + lifetime = (lines[tagline].args[1] != -1) ? lines[tagline].args[1] : 0; + fromcenter = !!lines[tagline].args[2]; } } @@ -1895,7 +1891,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) topz = *rover->topheight-(spacing>>1); bottomz = *rover->bottomheight; - if (flags & ML_EFFECT1) + if (fromcenter) { widthfactor = (rightx + topy - leftx - bottomy)>>3; heightfactor = (topz - *rover->bottomheight)>>2; @@ -1918,7 +1914,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) spawned = P_SpawnMobj(a, b, c, type); spawned->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones - if (flags & ML_EFFECT1) + if (fromcenter) { P_InstaThrust(spawned, R_PointToAngle2(sec->soundorg.x, sec->soundorg.y, a, b), FixedDiv(P_AproxDistance(a - sec->soundorg.x, b - sec->soundorg.y), widthfactor)); P_SetObjectMomZ(spawned, FixedDiv((c - bottomz), heightfactor), false); diff --git a/src/p_setup.c b/src/p_setup.c index 16019e5c0..850fee4f1 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3241,6 +3241,12 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; lines[i].args[2] = !!(lines[i].flags & ML_EFFECT1); break; + case 14: //Bustable block parameters + lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; + lines[i].args[2] = !!(lines[i].flags & ML_EFFECT1); + P_WriteConstant(sides[lines[i].sidenum[0]].toptexture, &lines[i].stringargs[0]); + break; case 16: //Minecart parameters lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; break; From 34229030f289c311eb02d66a96d00b7a3757d861 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 08:10:20 +0100 Subject: [PATCH 255/326] Make implementation of slope copying with linedef type 700 not hacky --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 1 + src/p_setup.c | 6 +- src/p_slopes.c | 62 ++++++++++++-------- src/p_slopes.h | 3 +- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 7c2411dc8..7e316c1ce 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -5303,6 +5303,7 @@ udmf { 1 = "No physics"; 2 = "Dynamic"; + 4 = "Copy to other side"; } } } diff --git a/src/p_setup.c b/src/p_setup.c index 850fee4f1..2e3fb1967 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4839,12 +4839,8 @@ static void P_ConvertBinaryMap(void) lines[i].args[2] |= TMSL_NOPHYSICS; if (lines[i].flags & ML_NONET) lines[i].args[2] |= TMSL_DYNAMIC; - if (lines[i].flags & ML_TFERLINE) - { - lines[i].args[4] |= backfloor ? TMSC_BACKTOFRONTFLOOR : (frontfloor ? TMSC_FRONTTOBACKFLOOR : 0); - lines[i].args[4] |= backceil ? TMSC_BACKTOFRONTCEILING : (frontceil ? TMSC_FRONTTOBACKCEILING : 0); - } + lines[i].args[2] |= TMSL_COPY; lines[i].special = 700; break; diff --git a/src/p_slopes.c b/src/p_slopes.c index b9154b890..d67c68edf 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -277,6 +277,27 @@ static fixed_t GetExtent(sector_t *sector, line_t *line) return fardist; } +static boolean P_CopySlope(pslope_t** toslope, pslope_t* fromslope) +{ + if (*toslope || !fromslope) + return true; + + *toslope = fromslope; + return true; +} + +static void P_UpdateHasSlope(sector_t *sec) +{ + size_t i; + + sec->hasslope = true; + + // if this is an FOF control sector, make sure any target sectors also are marked as having slopes + if (sec->numattached) + for (i = 0; i < sec->numattached; i++) + sectors[sec->attached[i]].hasslope = true; +} + /// Creates one or more slopes based on the given line type and front/back sectors. static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) { @@ -444,6 +465,23 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) P_AddDynLineSlopeThinker(cslope, DP_BACKCEIL, line, extent); } } + + if (line->args[2] & TMSL_COPY) + { + if (frontfloor) + P_CopySlope(&line->backsector->f_slope, line->frontsector->f_slope); + if (backfloor) + P_CopySlope(&line->frontsector->f_slope, line->backsector->f_slope); + if (frontceil) + P_CopySlope(&line->backsector->c_slope, line->frontsector->c_slope); + if (backceil) + P_CopySlope(&line->frontsector->c_slope, line->backsector->c_slope); + + if (backfloor || backceil) + P_UpdateHasSlope(line->frontsector); + if (frontfloor || frontceil) + P_UpdateHasSlope(line->backsector); + } } /// Creates a new slope from three mapthings with the specified IDs @@ -600,27 +638,6 @@ static boolean P_SetSlopeFromTag(sector_t *sec, INT32 tag, boolean ceiling) return false; } -static boolean P_CopySlope(pslope_t **toslope, pslope_t *fromslope) -{ - if (*toslope || !fromslope) - return true; - - *toslope = fromslope; - return true; -} - -static void P_UpdateHasSlope(sector_t *sec) -{ - size_t i; - - sec->hasslope = true; - - // if this is an FOF control sector, make sure any target sectors also are marked as having slopes - if (sec->numattached) - for (i = 0; i < sec->numattached; i++) - sectors[sec->attached[i]].hasslope = true; -} - // // P_CopySectorSlope // @@ -710,9 +727,6 @@ void P_SpawnSlopes(const boolean fromsave) { for (i = 0; i < numlines; i++) switch (lines[i].special) { - case 700: - if (lines[i].flags & ML_TFERLINE) P_CopySectorSlope(&lines[i]); - break; case 720: P_CopySectorSlope(&lines[i]); default: diff --git a/src/p_slopes.h b/src/p_slopes.h index 0b3e0b517..ae1966011 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -44,7 +44,8 @@ typedef enum typedef enum { TMSL_NOPHYSICS = 1, - TMSL_DYNAMIC = 2, + TMSL_DYNAMIC = 1<<1, + TMSL_COPY = 1<<2, } textmapslopeflags_t; void P_LinkSlopeThinkers (void); From ff4b68424f6836f7d7dc06f5284bba6632ebd2d3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 08:32:59 +0100 Subject: [PATCH 256/326] Fix missing section title in UDB config --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 7e316c1ce..da54414da 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -5145,6 +5145,8 @@ udmf light { + title = "Lighting"; + 600 { title = "Copy Light Level to Tagged Sector's Planes"; From 2fd6eafbcf0f226d7edda5a47b6e8b6c49eb5839 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 14:16:00 +0100 Subject: [PATCH 257/326] Expose sector flags to Lua and UDMF --- extras/conf/udb/Includes/SRB222_misc.cfg | 5 +++ src/deh_lua.c | 15 +++++++++ src/deh_tables.c | 8 +++++ src/deh_tables.h | 1 + src/lua_maplib.c | 10 +++++- src/p_map.c | 2 +- src/p_mobj.c | 8 ++--- src/p_polyobj.c | 2 +- src/p_setup.c | 15 ++++++++- src/p_spec.c | 40 ++++++++++++------------ src/r_defs.h | 12 +++---- 11 files changed, 84 insertions(+), 34 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 57c7c88a3..6d64aea81 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -74,6 +74,11 @@ sectorflags colormapfog = "Fog Planes in Colormap"; colormapfadesprites = "Fade Fullbright in Colormap"; colormapprotected = "Protected Colormap"; + flipspecial_nofloor = "No Trigger on Floor Touch"; + flipspecial_ceiling = "Trigger on Ceiling Touch"; + triggerspecial_touch = "Trigger on Edge Touch"; + triggerspecial_headbump = "Trigger on Headbump"; + invertprecip = "Invert Precipitation"; } thingflags diff --git a/src/deh_lua.c b/src/deh_lua.c index a2ffca95b..ae062695c 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -338,6 +338,21 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word); return 0; } + else if (fastncmp("MSF_", word, 3)) { + p = word + 4; + for (i = 0; i < 4; i++) + if (MSF_LIST[i] && fastcmp(p, MSF_LIST[i])) { + lua_pushinteger(L, ((lua_Integer)1 << i)); + return 1; + } + if (fastcmp(p, "FLIPSPECIAL_BOTH")) + { + lua_pushinteger(L, (lua_Integer)MSF_FLIPSPECIAL_BOTH); + return 1; + } + if (mathlib) return luaL_error(L, "sector flag '%s' could not be found.\n", word); + return 0; + } else if (fastncmp("S_",word,2)) { p = word+2; for (i = 0; i < NUMSTATEFREESLOTS; i++) { diff --git a/src/deh_tables.c b/src/deh_tables.c index f73f10151..73cf7068e 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4471,6 +4471,14 @@ const char *const ML_LIST[16] = { "TFERLINE" }; +// Sector flags +const char *const MSF_LIST[4] = { + "FLIPSPECIAL_FLOOR", + "FLIPSPECIAL_CEILING", + "TRIGGERSPECIAL_TOUCH", + "TRIGGERSPECIAL_HEADBUMP", +}; + const char *COLOR_ENUMS[] = { "NONE", // SKINCOLOR_NONE, diff --git a/src/deh_tables.h b/src/deh_tables.h index 1f265cc99..77260d507 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -65,6 +65,7 @@ extern const char *const MAPTHINGFLAG_LIST[4]; extern const char *const PLAYERFLAG_LIST[]; extern const char *const GAMETYPERULE_LIST[]; extern const char *const ML_LIST[16]; // Linedef flags +extern const char* const MSF_LIST[4]; // Sector flags extern const char *COLOR_ENUMS[]; extern const char *const POWERS_LIST[]; extern const char *const HUDITEMS_LIST[]; diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0ee87d2d2..9f267d071 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -48,7 +48,8 @@ enum sector_e { sector_lines, sector_ffloors, sector_fslope, - sector_cslope + sector_cslope, + sector_flags, }; static const char *const sector_opt[] = { @@ -72,6 +73,7 @@ static const char *const sector_opt[] = { "ffloors", "f_slope", "c_slope", + "flags", NULL}; enum subsector_e { @@ -649,6 +651,9 @@ static int sector_get(lua_State *L) case sector_cslope: // c_slope LUA_PushUserdata(L, sector->c_slope, META_SLOPE); return 1; + case sector_flags: // flags + lua_pushinteger(L, sector->flags); + return 1; } return 0; } @@ -735,6 +740,9 @@ static int sector_set(lua_State *L) break; case sector_taglist: return LUA_ErrSetDirectly(L, "sector_t", "taglist"); + case sector_flags: + sector->flags = luaL_checkinteger(L, 3); + break; } return 0; } diff --git a/src/p_map.c b/src/p_map.c index 5d90399d5..6b69df9cb 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3455,7 +3455,7 @@ static boolean PTR_SlideTraverse(intercept_t *in) // see if it is closer than best so far if (li->polyobj && slidemo->player) { - if ((li->polyobj->lines[0]->backsector->flags & SF_TRIGGERSPECIAL_TOUCH) && !(li->polyobj->flags & POF_NOSPECIALS)) + if ((li->polyobj->lines[0]->backsector->flags & MSF_TRIGGERSPECIAL_TOUCH) && !(li->polyobj->flags & POF_NOSPECIALS)) P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector); } diff --git a/src/p_mobj.c b/src/p_mobj.c index 46510200e..47a70233b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2324,9 +2324,9 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) return false; if (((mo->z <= mo->subsector->sector->floorheight - && ((mo->subsector->sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_FLOOR)) + && ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_FLOOR)) || (mo->z + mo->height >= mo->subsector->sector->ceilingheight - && ((mo->subsector->sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_CEILING))) + && ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_CEILING))) && (GETSECSPECIAL(mo->subsector->sector->special, 1) == 6 || GETSECSPECIAL(mo->subsector->sector->special, 1) == 7)) return true; @@ -11219,7 +11219,7 @@ void P_SpawnPrecipitation(void) if (curWeather == PRECIP_SNOW) { // Not in a sector with visible sky -- exception for NiGHTS. - if ((!(maptol & TOL_NIGHTS) && (precipsector->sector->ceilingpic != skyflatnum)) == !(precipsector->sector->flags & SF_INVERTPRECIP)) + if ((!(maptol & TOL_NIGHTS) && (precipsector->sector->ceilingpic != skyflatnum)) == !(precipsector->sector->flags & MSF_INVERTPRECIP)) continue; rainmo = P_SpawnSnowMobj(x, y, height, MT_SNOWFLAKE); @@ -11232,7 +11232,7 @@ void P_SpawnPrecipitation(void) else // everything else. { // Not in a sector with visible sky. - if ((precipsector->sector->ceilingpic != skyflatnum) == !(precipsector->sector->flags & SF_INVERTPRECIP)) + if ((precipsector->sector->ceilingpic != skyflatnum) == !(precipsector->sector->flags & MSF_INVERTPRECIP)) continue; rainmo = P_SpawnRainMobj(x, y, height, MT_RAIN); diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 47327c949..bcad36f80 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -963,7 +963,7 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line) else Polyobj_pushThing(po, line, mo); - if (mo->player && (po->lines[0]->backsector->flags & SF_TRIGGERSPECIAL_TOUCH) && !(po->flags & POF_NOSPECIALS)) + if (mo->player && (po->lines[0]->backsector->flags & MSF_TRIGGERSPECIAL_TOUCH) && !(po->flags & POF_NOSPECIALS)) P_ProcessSpecialSector(mo->player, mo->subsector->sector, po->lines[0]->backsector); hitflags |= 1; diff --git a/src/p_setup.c b/src/p_setup.c index 2e3fb1967..b83d950f2 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1001,7 +1001,6 @@ static void P_InitializeSector(sector_t *ss) ss->gravity = NULL; ss->verticalflip = false; - ss->flags = SF_FLIPSPECIAL_FLOOR; ss->cullheight = NULL; @@ -1048,6 +1047,8 @@ static void P_LoadSectors(UINT8 *data) ss->colormap_protected = false; + ss->flags = MSF_FLIPSPECIAL_FLOOR; + P_InitializeSector(ss); } } @@ -1661,6 +1662,16 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) } else if (fastcmp(param, "colormapprotected") && fastcmp("true", val)) sectors[i].colormap_protected = true; + else if (fastcmp(param, "flipspecial_nofloor") && fastcmp("true", val)) + sectors[i].flags &= ~MSF_FLIPSPECIAL_FLOOR; + else if (fastcmp(param, "flipspecial_ceiling") && fastcmp("true", val)) + sectors[i].flags |= MSF_FLIPSPECIAL_CEILING; + else if (fastcmp(param, "triggerspecial_touch") && fastcmp("true", val)) + sectors[i].flags |= MSF_TRIGGERSPECIAL_TOUCH; + else if (fastcmp(param, "triggerspecial_headbump") && fastcmp("true", val)) + sectors[i].flags |= MSF_TRIGGERSPECIAL_HEADBUMP; + else if (fastcmp(param, "invertprecip") && fastcmp("true", val)) + sectors[i].flags |= MSF_INVERTPRECIP; } static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val) @@ -1937,6 +1948,8 @@ static void P_LoadTextmap(void) sc->colormap_protected = false; + sc->flags = MSF_FLIPSPECIAL_FLOOR; + textmap_colormap.used = false; textmap_colormap.lightcolor = 0; textmap_colormap.lightalpha = 25; diff --git a/src/p_spec.c b/src/p_spec.c index ab2f67d74..37b077535 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3945,8 +3945,8 @@ boolean P_IsFlagAtBase(mobjtype_t flag) static boolean P_IsMobjTouchingPlane(mobj_t *mo, sector_t *sec, fixed_t floorz, fixed_t ceilingz) { - boolean floorallowed = ((sec->flags & SF_FLIPSPECIAL_FLOOR) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == floorz)); - boolean ceilingallowed = ((sec->flags & SF_FLIPSPECIAL_CEILING) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == ceilingz)); + boolean floorallowed = ((sec->flags & MSF_FLIPSPECIAL_FLOOR) && ((sec->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == floorz)); + boolean ceilingallowed = ((sec->flags & MSF_FLIPSPECIAL_CEILING) && ((sec->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == ceilingz)); return (floorallowed || ceilingallowed); } @@ -4007,7 +4007,7 @@ static sector_t *P_MobjTouching3DFloorSpecial(mobj_t *mo, sector_t *sector, INT3 // This FOF has the special we're looking for, but are we allowed to touch it? if (sector == mo->subsector->sector - || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + || (rover->master->frontsector->flags & MSF_TRIGGERSPECIAL_TOUCH)) return rover->master->frontsector; } @@ -4031,7 +4031,7 @@ static sector_t *P_MobjTouchingPolyobjSpecial(mobj_t *mo, INT32 section, INT32 n if (GETSECSPECIAL(polysec->special, section) != number) continue; - touching = (polysec->flags & SF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo); + touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo); inside = P_MobjInsidePolyobj(po, mo); if (!(inside || touching)) @@ -4071,7 +4071,7 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number) if (result) return result; - if (!(node->m_sector->flags & SF_TRIGGERSPECIAL_TOUCH)) + if (!(node->m_sector->flags & MSF_TRIGGERSPECIAL_TOUCH)) continue; if (GETSECSPECIAL(mo->subsector->sector->special, section) == number) @@ -4120,7 +4120,7 @@ static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line // This FOF has the special we're looking for, but are we allowed to touch it? if (sector == player->mo->subsector->sector - || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + || (rover->master->frontsector->flags & MSF_TRIGGERSPECIAL_TOUCH)) return rover->master->frontsector; } @@ -4147,7 +4147,7 @@ static sector_t *P_CheckPolyobjTriggers(player_t *player, line_t *sourceline) if (!Tag_Find(&sourceline->tags, Tag_FGet(&polysec->tags))) return false; - touching = (polysec->flags & SF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); + touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); inside = P_MobjInsidePolyobj(po, player->mo); if (!(inside || touching)) @@ -4217,7 +4217,7 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) if (caller) return caller; - if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + if (!(loopsector->flags & MSF_TRIGGERSPECIAL_TOUCH)) continue; if (P_CheckSectorTriggers(player, loopsector, sourceline)) @@ -5024,7 +5024,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) // This FOF has the special we're looking for, but are we allowed to touch it? if (sector == player->mo->subsector->sector - || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + || (rover->master->frontsector->flags & MSF_TRIGGERSPECIAL_TOUCH)) { P_ProcessSpecialSector(player, rover->master->frontsector, sector); if TELEPORTED(player->mo) return; @@ -5050,7 +5050,7 @@ static void P_PlayerOnSpecialPolyobj(player_t *player) if (!polysec->special) continue; - touching = (polysec->flags & SF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); + touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); inside = P_MobjInsidePolyobj(po, player->mo); if (!(inside || touching)) @@ -5102,7 +5102,7 @@ void P_PlayerInSpecialSector(player_t *player) P_PlayerOnSpecial3DFloor(player, loopsector); if TELEPORTED(player->mo) return; - if (!(loopsector->flags & SF_TRIGGERSPECIAL_TOUCH)) + if (!(loopsector->flags & MSF_TRIGGERSPECIAL_TOUCH)) continue; P_ProcessSpecialSector(player, loopsector, NULL); @@ -5152,7 +5152,7 @@ static void P_CheckMobjPolyobjTrigger(mobj_t *mo) if (!polysec->special) continue; - touching = (polysec->flags & SF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo); + touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo); inside = P_MobjInsidePolyobj(po, mo); if (!(inside || touching)) @@ -5994,9 +5994,9 @@ void P_SpawnSpecials(boolean fromnetsave) { case 5: // Spikes //Terrible hack to replace an even worse hack: - //Spike damage automatically sets SF_TRIGGERSPECIAL_TOUCH. + //Spike damage automatically sets MSF_TRIGGERSPECIAL_TOUCH. //Yes, this also affects other specials on the same sector. Sorry. - sector->flags |= SF_TRIGGERSPECIAL_TOUCH; + sector->flags |= MSF_TRIGGERSPECIAL_TOUCH; break; case 15: // Bouncy FOF CONS_Alert(CONS_WARNING, M_GetText("Deprecated bouncy FOF sector type detected. Please use linedef type 76 instead.\n")); @@ -6148,19 +6148,19 @@ void P_SpawnSpecials(boolean fromnetsave) { if (lines[i].flags & ML_NOCLIMB) { - sectors[s].flags &= ~SF_FLIPSPECIAL_FLOOR; - sectors[s].flags |= SF_FLIPSPECIAL_CEILING; + sectors[s].flags &= ~MSF_FLIPSPECIAL_FLOOR; + sectors[s].flags |= MSF_FLIPSPECIAL_CEILING; } else if (lines[i].flags & ML_EFFECT4) - sectors[s].flags |= SF_FLIPSPECIAL_BOTH; + sectors[s].flags |= MSF_FLIPSPECIAL_BOTH; if (lines[i].flags & ML_EFFECT3) - sectors[s].flags |= SF_TRIGGERSPECIAL_TOUCH; + sectors[s].flags |= MSF_TRIGGERSPECIAL_TOUCH; if (lines[i].flags & ML_EFFECT2) - sectors[s].flags |= SF_TRIGGERSPECIAL_HEADBUMP; + sectors[s].flags |= MSF_TRIGGERSPECIAL_HEADBUMP; if (lines[i].flags & ML_EFFECT1) - sectors[s].flags |= SF_INVERTPRECIP; + sectors[s].flags |= MSF_INVERTPRECIP; if (lines[i].frontsector && GETSECSPECIAL(lines[i].frontsector->special, 4) == 12) sectors[s].camsec = sides[*lines[i].sidenum].sector-sectors; diff --git a/src/r_defs.h b/src/r_defs.h index 0609a48a8..c10428431 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -276,14 +276,14 @@ typedef struct pslope_s typedef enum { // flipspecial - planes with effect - SF_FLIPSPECIAL_FLOOR = 1, - SF_FLIPSPECIAL_CEILING = 1<<1, - SF_FLIPSPECIAL_BOTH = (SF_FLIPSPECIAL_FLOOR|SF_FLIPSPECIAL_CEILING), + MSF_FLIPSPECIAL_FLOOR = 1, + MSF_FLIPSPECIAL_CEILING = 1<<1, + MSF_FLIPSPECIAL_BOTH = (MSF_FLIPSPECIAL_FLOOR|MSF_FLIPSPECIAL_CEILING), // triggerspecial - conditions under which plane touch causes effect - SF_TRIGGERSPECIAL_TOUCH = 1<<2, - SF_TRIGGERSPECIAL_HEADBUMP = 1<<3, + MSF_TRIGGERSPECIAL_TOUCH = 1<<2, + MSF_TRIGGERSPECIAL_HEADBUMP = 1<<3, // invertprecip - inverts presence of precipitation - SF_INVERTPRECIP = 1<<4, + MSF_INVERTPRECIP = 1<<4, } sectorflags_t; From 2a1f96aa3cecae4c41d5c6cee918a6c69e5213dc Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 14:26:51 +0100 Subject: [PATCH 258/326] Adapt linedef type 8 to UDMF --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 6 +++++ src/p_setup.c | 28 ++++++++++++++++++++ src/p_spec.c | 26 +++--------------- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index da54414da..e8ec7de2b 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1721,6 +1721,12 @@ udmf } } + 8 + { + title = "Set Camera Collision Planes"; + prefix = "(8)"; + } + 11 { title = "Rope Hang Parameters"; diff --git a/src/p_setup.c b/src/p_setup.c index b83d950f2..987f4f6f5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3245,6 +3245,34 @@ static void P_ConvertBinaryMap(void) lines[i].special = 0; } break; + case 8: //Special sector properties + { + INT32 s; + + TAG_ITER_SECTORS(tag, s) + { + if (lines[i].flags & ML_NOCLIMB) + { + sectors[s].flags &= ~MSF_FLIPSPECIAL_FLOOR; + sectors[s].flags |= MSF_FLIPSPECIAL_CEILING; + } + else if (lines[i].flags & ML_EFFECT4) + sectors[s].flags |= MSF_FLIPSPECIAL_BOTH; + + if (lines[i].flags & ML_EFFECT3) + sectors[s].flags |= MSF_TRIGGERSPECIAL_TOUCH; + if (lines[i].flags & ML_EFFECT2) + sectors[s].flags |= MSF_TRIGGERSPECIAL_HEADBUMP; + + if (lines[i].flags & ML_EFFECT1) + sectors[s].flags |= MSF_INVERTPRECIP; + } + + if (GETSECSPECIAL(lines[i].frontsector->special, 4) != 12) + lines[i].special = 0; + + break; + } case 10: //Culling plane lines[i].args[0] = tag; lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); diff --git a/src/p_spec.c b/src/p_spec.c index 37b077535..ef48fbf62 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6143,28 +6143,10 @@ void P_SpawnSpecials(boolean fromnetsave) break; } - case 8: // Sector Parameters - TAG_ITER_SECTORS(tag, s) - { - if (lines[i].flags & ML_NOCLIMB) - { - sectors[s].flags &= ~MSF_FLIPSPECIAL_FLOOR; - sectors[s].flags |= MSF_FLIPSPECIAL_CEILING; - } - else if (lines[i].flags & ML_EFFECT4) - sectors[s].flags |= MSF_FLIPSPECIAL_BOTH; - - if (lines[i].flags & ML_EFFECT3) - sectors[s].flags |= MSF_TRIGGERSPECIAL_TOUCH; - if (lines[i].flags & ML_EFFECT2) - sectors[s].flags |= MSF_TRIGGERSPECIAL_HEADBUMP; - - if (lines[i].flags & ML_EFFECT1) - sectors[s].flags |= MSF_INVERTPRECIP; - - if (lines[i].frontsector && GETSECSPECIAL(lines[i].frontsector->special, 4) == 12) - sectors[s].camsec = sides[*lines[i].sidenum].sector-sectors; - } + case 8: // Set camera collision planes + if (lines[i].frontsector) + TAG_ITER_SECTORS(tag, s) + sectors[s].camsec = lines[i].frontsector-sectors; break; case 10: // Vertical culling plane for sprites and FOFs From b74d06b4e7de16833cad70bd054e7b3095d37559 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 14:33:24 +0100 Subject: [PATCH 259/326] Netsync sector flags --- src/p_saveg.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 5e204f9bc..0f5679940 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -852,6 +852,7 @@ static void P_NetUnArchiveWaypoints(void) #define SD_CRUMBLESTATE 0x04 #define SD_FLOORLIGHT 0x08 #define SD_CEILLIGHT 0x10 +#define SD_FLAG 0x20 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -1037,6 +1038,8 @@ static void ArchiveSectors(void) diff3 |= SD_FLOORLIGHT; if (ss->ceilinglightlevel != spawnss->ceilinglightlevel || ss->ceilinglightabsolute != spawnss->ceilinglightabsolute) diff3 |= SD_CEILLIGHT; + if (ss->flags != spawnss->flags) + diff3 |= SD_FLAG; if (ss->ffloors && CheckFFloorDiff(ss)) diff |= SD_FFLOORS; @@ -1101,6 +1104,8 @@ static void ArchiveSectors(void) WRITEINT16(save_p, ss->ceilinglightlevel); WRITEUINT8(save_p, ss->ceilinglightabsolute); } + if (diff3 & SD_FLAG) + WRITEUINT32(save_p, ss->flags); if (diff & SD_FFLOORS) ArchiveFFloors(ss); } @@ -1202,6 +1207,9 @@ static void UnArchiveSectors(void) sectors[i].ceilinglightlevel = READINT16(save_p); sectors[i].ceilinglightabsolute = READUINT8(save_p); } + if (diff3 & SD_FLAG) + sectors[i].flags = READUINT32(save_p); + if (diff & SD_FFLOORS) UnArchiveFFloors(§ors[i]); From f30b97ba933c4407e40e4990e855efbdd3523895 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 14:48:40 +0100 Subject: [PATCH 260/326] Adapt heat wave effect to UDMF --- extras/conf/udb/Includes/SRB222_misc.cfg | 1 + src/deh_lua.c | 2 +- src/deh_tables.c | 3 +- src/deh_tables.h | 2 +- src/p_mobj.c | 10 ++--- src/p_setup.c | 11 +++++ src/p_user.c | 56 +++++++++--------------- src/r_defs.h | 1 + 8 files changed, 40 insertions(+), 46 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 6d64aea81..52cd22322 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -79,6 +79,7 @@ sectorflags triggerspecial_touch = "Trigger on Edge Touch"; triggerspecial_headbump = "Trigger on Headbump"; invertprecip = "Invert Precipitation"; + heatwave = "Heat Wave"; } thingflags diff --git a/src/deh_lua.c b/src/deh_lua.c index ae062695c..28030052a 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -340,7 +340,7 @@ static inline int lib_getenum(lua_State *L) } else if (fastncmp("MSF_", word, 3)) { p = word + 4; - for (i = 0; i < 4; i++) + for (i = 0; i < 5; i++) if (MSF_LIST[i] && fastcmp(p, MSF_LIST[i])) { lua_pushinteger(L, ((lua_Integer)1 << i)); return 1; diff --git a/src/deh_tables.c b/src/deh_tables.c index 73cf7068e..b6a9e0225 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4472,11 +4472,12 @@ const char *const ML_LIST[16] = { }; // Sector flags -const char *const MSF_LIST[4] = { +const char *const MSF_LIST[5] = { "FLIPSPECIAL_FLOOR", "FLIPSPECIAL_CEILING", "TRIGGERSPECIAL_TOUCH", "TRIGGERSPECIAL_HEADBUMP", + "HEATWAVE", }; const char *COLOR_ENUMS[] = { diff --git a/src/deh_tables.h b/src/deh_tables.h index 77260d507..982c6ff4a 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -65,7 +65,7 @@ extern const char *const MAPTHINGFLAG_LIST[4]; extern const char *const PLAYERFLAG_LIST[]; extern const char *const GAMETYPERULE_LIST[]; extern const char *const ML_LIST[16]; // Linedef flags -extern const char* const MSF_LIST[4]; // Sector flags +extern const char* const MSF_LIST[5]; // Sector flags extern const char *COLOR_ENUMS[]; extern const char *const POWERS_LIST[]; extern const char *const HUDITEMS_LIST[]; diff --git a/src/p_mobj.c b/src/p_mobj.c index 47a70233b..428274679 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3551,19 +3551,16 @@ static boolean P_CameraCheckHeat(camera_t *thiscam) { sector_t *sector; fixed_t halfheight = thiscam->z + (thiscam->height >> 1); - size_t i; // see if we are in water sector = thiscam->subsector->sector; - for (i = 0; i < sector->tags.count; i++) - if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1) - return true; + if (sector->flags & MSF_HEATWAVE) + return true; if (sector->ffloors) { ffloor_t *rover; - size_t j; for (rover = sector->ffloors; rover; rover = rover->next) { @@ -3575,8 +3572,7 @@ static boolean P_CameraCheckHeat(camera_t *thiscam) if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y)) continue; - for (j = 0; j < rover->master->frontsector->tags.count; j++) - if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1) + if (rover->master->frontsector->flags & MSF_HEATWAVE) return true; } } diff --git a/src/p_setup.c b/src/p_setup.c index 987f4f6f5..ec35ad824 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1672,6 +1672,8 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].flags |= MSF_TRIGGERSPECIAL_HEADBUMP; else if (fastcmp(param, "invertprecip") && fastcmp("true", val)) sectors[i].flags |= MSF_INVERTPRECIP; + else if (fastcmp(param, "heatwave") && fastcmp("true", val)) + sectors[i].flags |= MSF_HEATWAVE; } static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val) @@ -3282,6 +3284,15 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; lines[i].args[2] = !!(lines[i].flags & ML_EFFECT1); break; + case 13: //Heat wave effect + { + INT32 s; + + TAG_ITER_SECTORS(tag, s) + sectors[s].flags |= MSF_HEATWAVE; + + break; + } case 14: //Bustable block parameters lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; diff --git a/src/p_user.c b/src/p_user.c index 60000afa0..8adb6ef9b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10466,7 +10466,6 @@ static void P_CalcPostImg(player_t *player) postimg_t *type; INT32 *param; fixed_t pviewheight; - size_t i; if (player->mo->eflags & MFE_VERTICALFLIP) pviewheight = player->mo->z + player->mo->height - player->viewheight; @@ -10491,45 +10490,30 @@ static void P_CalcPostImg(player_t *player) } // see if we are in heat (no, not THAT kind of heat...) - for (i = 0; i < sector->tags.count; i++) + if (sector->flags & MSF_HEATWAVE) + *type = postimg_heat; + else if (sector->ffloors) { - if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1) - { - *type = postimg_heat; - break; - } - else if (sector->ffloors) - { - ffloor_t *rover; - fixed_t topheight; - fixed_t bottomheight; - boolean gotres = false; + ffloor_t *rover; + fixed_t topheight; + fixed_t bottomheight; - for (rover = sector->ffloors; rover; rover = rover->next) + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y); + bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y); + + if (pviewheight >= topheight || pviewheight <= bottomheight) + continue; + + if (rover->master->frontsector->flags & MSF_HEATWAVE) { - size_t j; - - if (!(rover->flags & FF_EXISTS)) - continue; - - topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y); - bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y); - - if (pviewheight >= topheight || pviewheight <= bottomheight) - continue; - - for (j = 0; j < rover->master->frontsector->tags.count; j++) - { - if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1) - { - *type = postimg_heat; - gotres = true; - break; - } - } - } - if (gotres) + *type = postimg_heat; break; + } } } diff --git a/src/r_defs.h b/src/r_defs.h index c10428431..16c4ad64f 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -284,6 +284,7 @@ typedef enum MSF_TRIGGERSPECIAL_HEADBUMP = 1<<3, // invertprecip - inverts presence of precipitation MSF_INVERTPRECIP = 1<<4, + MSF_HEATWAVE = 1<<5, // heat wave effect } sectorflags_t; From e3d41e0bda760400521d8b847b27fd5c826e9839 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 15:32:28 +0100 Subject: [PATCH 261/326] Adapt linedef type 540 to UDMF --- extras/conf/udb/Includes/SRB222_misc.cfg | 6 +++ src/lua_maplib.c | 6 +++ src/p_setup.c | 9 ++++ src/p_spec.c | 54 ++++++++++++------------ src/r_defs.h | 2 + 5 files changed, 50 insertions(+), 27 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 52cd22322..4139fa967 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -226,6 +226,12 @@ universalfields type = 3; default = false; } + + friction + { + type = 0; + default = 0; + } } linedef diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 9f267d071..a74c6fc97 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -50,6 +50,7 @@ enum sector_e { sector_fslope, sector_cslope, sector_flags, + sector_friction, }; static const char *const sector_opt[] = { @@ -74,6 +75,7 @@ static const char *const sector_opt[] = { "f_slope", "c_slope", "flags", + "friction", NULL}; enum subsector_e { @@ -654,6 +656,9 @@ static int sector_get(lua_State *L) case sector_flags: // flags lua_pushinteger(L, sector->flags); return 1; + case sector_friction: // friction + lua_pushinteger(L, sector->friction); + return 1; } return 0; } @@ -681,6 +686,7 @@ static int sector_set(lua_State *L) case sector_ffloors: // ffloors case sector_fslope: // f_slope case sector_cslope: // c_slope + case sector_friction: // friction default: return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]); case sector_floorheight: { // floorheight diff --git a/src/p_setup.c b/src/p_setup.c index ec35ad824..85d4ee5dc 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1674,6 +1674,8 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].flags |= MSF_INVERTPRECIP; else if (fastcmp(param, "heatwave") && fastcmp("true", val)) sectors[i].flags |= MSF_HEATWAVE; + else if (fastcmp(param, "friction")) + sectors[i].friction = atol(val); } static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val) @@ -4835,6 +4837,13 @@ static void P_ConvertBinaryMap(void) lines[i].args[4] |= TMST_NONEXCLUSIVE; lines[i].special = 510; break; + case 540: //Floor friction + { + INT32 s; + TAG_ITER_SECTORS(tag, s) + sectors[s].friction = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + break; + } case 541: //Wind case 542: //Upwards wind case 543: //Downwards wind diff --git a/src/p_spec.c b/src/p_spec.c index ef48fbf62..69b76aee7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -8184,40 +8184,40 @@ void T_Friction(friction_t *f) static void P_SpawnFriction(void) { size_t i; - line_t *l = lines; - mtag_t tag; - register INT32 s; - fixed_t strength; // frontside texture offset controls magnitude + sector_t *s = sectors; + + fixed_t strength; // friction value of sector fixed_t friction; // friction value to be applied during movement INT32 movefactor; // applied to each player move to simulate inertia - for (i = 0; i < numlines; i++, l++) - if (l->special == 540) - { - tag = Tag_FGet(&l->tags); - strength = sides[l->sidenum[0]].textureoffset>>FRACBITS; - if (strength > 0) // sludge - strength = strength*2; // otherwise, the maximum sludginess value is +967... + for (i = 0; i < numsectors; i++, s++) + { + if (!s->friction) + continue; - // The following might seem odd. At the time of movement, - // the move distance is multiplied by 'friction/0x10000', so a - // higher friction value actually means 'less friction'. - friction = ORIG_FRICTION - (0x1EB8*strength)/0x80; // ORIG_FRICTION is 0xE800 + strength = s->friction; + if (strength > 0) // sludge + strength = strength*2; // otherwise, the maximum sludginess value is +967... - if (friction > FRACUNIT) - friction = FRACUNIT; - if (friction < 0) - friction = 0; + // The following might seem odd. At the time of movement, + // the move distance is multiplied by 'friction/0x10000', so a + // higher friction value actually means 'less friction'. + friction = ORIG_FRICTION - (0x1EB8*strength)/0x80; // ORIG_FRICTION is 0xE800 - movefactor = FixedDiv(ORIG_FRICTION, friction); - if (movefactor < FRACUNIT) - movefactor = 8*movefactor - 7*FRACUNIT; - else - movefactor = FRACUNIT; + if (friction > FRACUNIT) + friction = FRACUNIT; + if (friction < 0) + friction = 0; - TAG_ITER_SECTORS(tag, s) - Add_Friction(friction, movefactor, s, -1); - } + movefactor = FixedDiv(ORIG_FRICTION, friction); + if (movefactor < FRACUNIT) + movefactor = 8*movefactor - 7*FRACUNIT; + else + movefactor = FRACUNIT; + + Add_Friction(friction, movefactor, (INT32)(s-sectors), -1); + + } } /* diff --git a/src/r_defs.h b/src/r_defs.h index 16c4ad64f..105494bd7 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -371,6 +371,8 @@ typedef struct sector_s boolean verticalflip; // If gravity < 0, then allow flipped physics sectorflags_t flags; + INT32 friction; + // Sprite culling feature struct line_s *cullheight; From 86e2fefcacec985ff8f5c20ea8428f96f61d4518 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 18:19:42 +0100 Subject: [PATCH 262/326] Add sector gravity field for UDMF --- src/lua_maplib.c | 8 ++++++++ src/p_enemy.c | 15 +++------------ src/p_mobj.c | 14 ++++++-------- src/p_saveg.c | 8 +++++++- src/p_setup.c | 8 +++++++- src/p_spec.c | 10 +++++++++- src/p_spec.h | 1 + src/r_defs.h | 4 ++-- 8 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index a74c6fc97..0a147acbb 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -51,6 +51,7 @@ enum sector_e { sector_cslope, sector_flags, sector_friction, + sector_gravity, }; static const char *const sector_opt[] = { @@ -76,6 +77,7 @@ static const char *const sector_opt[] = { "c_slope", "flags", "friction", + "gravity", NULL}; enum subsector_e { @@ -659,6 +661,9 @@ static int sector_get(lua_State *L) case sector_friction: // friction lua_pushinteger(L, sector->friction); return 1; + case sector_gravity: // gravity + lua_pushfixed(L, sector->gravity); + return 1; } return 0; } @@ -749,6 +754,9 @@ static int sector_set(lua_State *L) case sector_flags: sector->flags = luaL_checkinteger(L, 3); break; + case sector_gravity: + sector->gravity = luaL_checkfixed(L, 3); + break; } return 0; } diff --git a/src/p_enemy.c b/src/p_enemy.c index 5c92bdc06..9cf5687e7 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -11461,10 +11461,7 @@ void A_BrakLobShot(mobj_t *actor) return; // Don't even bother if we've got nothing to aim at. // Look up actor's current gravity situation - if (actor->subsector->sector->gravity) - g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000))); - else - g = gravity; + g = FixedMul(gravity, P_GetSectorGravityFactor(actor->subsector->sector)); // Look up distance between actor and its target x = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); @@ -11576,10 +11573,7 @@ void A_NapalmScatter(mobj_t *actor) airtime = 16<subsector->sector->gravity) - g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000))); - else - g = gravity; + g = FixedMul(gravity, P_GetSectorGravityFactor(actor->subsector->sector)); // vy = (g*(airtime-1))/2 vy = FixedMul(g,(airtime-(1<>1; @@ -12289,10 +12283,7 @@ void A_Boss5Jump(mobj_t *actor) return; // Don't even bother if we've got nothing to aim at. // Look up actor's current gravity situation - if (actor->subsector->sector->gravity) - g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000))); - else - g = gravity; + g = FixedMul(gravity, P_GetSectorGravityFactor(actor->subsector->sector)); // Look up distance between actor and its tracer x = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); diff --git a/src/p_mobj.c b/src/p_mobj.c index 428274679..aea7964be 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1446,6 +1446,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) if (mo->subsector->sector->ffloors) // Check for 3D floor gravity too. { ffloor_t *rover; + fixed_t gravfactor; for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) { @@ -1455,11 +1456,12 @@ fixed_t P_GetMobjGravity(mobj_t *mo) if ((rover->flags & (FF_SWIMMABLE|FF_GOOWATER)) == (FF_SWIMMABLE|FF_GOOWATER)) goopgravity = true; - if (!(rover->master->frontsector->gravity)) + gravfactor = P_GetSectorGravityFactor(mo->subsector->sector); + + if (gravfactor == FRACUNIT) continue; - gravityadd = -FixedMul(gravity, - (FixedDiv(*rover->master->frontsector->gravity>>FRACBITS, 1000))); + gravityadd = -FixedMul(gravity, gravfactor); if (rover->master->frontsector->verticalflip && gravityadd > 0) mo->eflags |= MFE_VERTICALFLIP; @@ -1471,11 +1473,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) if (no3dfloorgrav) { - if (mo->subsector->sector->gravity) - gravityadd = -FixedMul(gravity, - (FixedDiv(*mo->subsector->sector->gravity>>FRACBITS, 1000))); - else - gravityadd = -gravity; + gravityadd = -FixedMul(gravity, P_GetSectorGravityFactor(mo->subsector->sector)); if (mo->subsector->sector->verticalflip && gravityadd > 0) mo->eflags |= MFE_VERTICALFLIP; diff --git a/src/p_saveg.c b/src/p_saveg.c index 0f5679940..66df83603 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -853,6 +853,7 @@ static void P_NetUnArchiveWaypoints(void) #define SD_FLOORLIGHT 0x08 #define SD_CEILLIGHT 0x10 #define SD_FLAG 0x20 +#define SD_GRAVITY 0x40 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -1040,6 +1041,8 @@ static void ArchiveSectors(void) diff3 |= SD_CEILLIGHT; if (ss->flags != spawnss->flags) diff3 |= SD_FLAG; + if (ss->gravity != spawnss->gravity) + diff3 |= SD_GRAVITY; if (ss->ffloors && CheckFFloorDiff(ss)) diff |= SD_FFLOORS; @@ -1106,6 +1109,8 @@ static void ArchiveSectors(void) } if (diff3 & SD_FLAG) WRITEUINT32(save_p, ss->flags); + if (diff3 & SD_GRAVITY) + WRITEFIXED(save_p, ss->gravity); if (diff & SD_FFLOORS) ArchiveFFloors(ss); } @@ -1209,7 +1214,8 @@ static void UnArchiveSectors(void) } if (diff3 & SD_FLAG) sectors[i].flags = READUINT32(save_p); - + if (diff3 & SD_GRAVITY) + sectors[i].gravity = READFIXED(save_p); if (diff & SD_FFLOORS) UnArchiveFFloors(§ors[i]); diff --git a/src/p_setup.c b/src/p_setup.c index 85d4ee5dc..2bcde2b92 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -999,7 +999,7 @@ static void P_InitializeSector(sector_t *ss) ss->extra_colormap = NULL; - ss->gravity = NULL; + ss->gravityptr = NULL; ss->verticalflip = false; ss->cullheight = NULL; @@ -1047,6 +1047,8 @@ static void P_LoadSectors(UINT8 *data) ss->colormap_protected = false; + ss->gravity = FRACUNIT; + ss->flags = MSF_FLIPSPECIAL_FLOOR; P_InitializeSector(ss); @@ -1676,6 +1678,8 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].flags |= MSF_HEATWAVE; else if (fastcmp(param, "friction")) sectors[i].friction = atol(val); + else if (fastcmp(param, "gravity")) + sectors[i].gravity = FLOAT_TO_FIXED(atof(val)); } static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val) @@ -1952,6 +1956,8 @@ static void P_LoadTextmap(void) sc->colormap_protected = false; + sc->gravity = FRACUNIT; + sc->flags = MSF_FLIPSPECIAL_FLOOR; textmap_colormap.used = false; diff --git a/src/p_spec.c b/src/p_spec.c index 69b76aee7..846ce9376 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5958,6 +5958,14 @@ static boolean P_CheckGametypeRules(INT32 checktype, UINT32 target) } } +fixed_t P_GetSectorGravityFactor(sector_t *sec) +{ + if (sec->gravityptr) + return FixedDiv(*sec->gravityptr >> FRACBITS, 1000); + else + return sec->gravity; +} + /** After the map has loaded, scans for specials that spawn 3Dfloors and * thinkers. * @@ -6105,7 +6113,7 @@ void P_SpawnSpecials(boolean fromnetsave) sec = sides[*lines[i].sidenum].sector - sectors; TAG_ITER_SECTORS(tag, s) { - sectors[s].gravity = §ors[sec].floorheight; // This allows it to change in realtime! + sectors[s].gravityptr = §ors[sec].floorheight; // This allows it to change in realtime! if (lines[i].flags & ML_NOCLIMB) sectors[s].verticalflip = true; diff --git a/src/p_spec.h b/src/p_spec.h index 6b1db7faf..82f858a05 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -467,6 +467,7 @@ void P_SetupLevelFlatAnims(void); // at map load void P_InitSpecials(void); void P_ApplyFlatAlignment(sector_t* sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs, boolean floor, boolean ceiling); +fixed_t P_GetSectorGravityFactor(sector_t *sec); void P_SpawnSpecials(boolean fromnetsave); // every tic diff --git a/src/r_defs.h b/src/r_defs.h index 105494bd7..0fd13b707 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -366,8 +366,8 @@ typedef struct sector_s extracolormap_t *extra_colormap; boolean colormap_protected; - // This points to the master's floorheight, so it can be changed in realtime! - fixed_t *gravity; // per-sector gravity + fixed_t gravity; // per-sector gravity factor + fixed_t *gravityptr; // For binary format: Read gravity from floor height of master sector boolean verticalflip; // If gravity < 0, then allow flipped physics sectorflags_t flags; From b3863c57be9bcf6edaa3ff8821965b6b3e77aca9 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 18:50:02 +0100 Subject: [PATCH 263/326] Replace verticalflip in sector_t with a sector flag that's accessible via Lua and UDMF --- extras/conf/udb/Includes/SRB222_misc.cfg | 1 + src/deh_lua.c | 2 +- src/deh_tables.c | 3 ++- src/deh_tables.h | 2 +- src/lua_maplib.c | 1 + src/p_mobj.c | 4 ++-- src/p_saveg.c | 3 +++ src/p_setup.c | 3 ++- src/p_spec.c | 8 +++++--- src/r_defs.h | 4 ++-- 10 files changed, 20 insertions(+), 11 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 4139fa967..36518be9f 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -79,6 +79,7 @@ sectorflags triggerspecial_touch = "Trigger on Edge Touch"; triggerspecial_headbump = "Trigger on Headbump"; invertprecip = "Invert Precipitation"; + gravityflip = "Flip Objects in Reverse Gravity"; heatwave = "Heat Wave"; } diff --git a/src/deh_lua.c b/src/deh_lua.c index 28030052a..e360febaf 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -340,7 +340,7 @@ static inline int lib_getenum(lua_State *L) } else if (fastncmp("MSF_", word, 3)) { p = word + 4; - for (i = 0; i < 5; i++) + for (i = 0; i < 6; i++) if (MSF_LIST[i] && fastcmp(p, MSF_LIST[i])) { lua_pushinteger(L, ((lua_Integer)1 << i)); return 1; diff --git a/src/deh_tables.c b/src/deh_tables.c index b6a9e0225..095aae0f2 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4472,11 +4472,12 @@ const char *const ML_LIST[16] = { }; // Sector flags -const char *const MSF_LIST[5] = { +const char *const MSF_LIST[6] = { "FLIPSPECIAL_FLOOR", "FLIPSPECIAL_CEILING", "TRIGGERSPECIAL_TOUCH", "TRIGGERSPECIAL_HEADBUMP", + "GRAVITYFLIP", "HEATWAVE", }; diff --git a/src/deh_tables.h b/src/deh_tables.h index 982c6ff4a..2e514a5b1 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -65,7 +65,7 @@ extern const char *const MAPTHINGFLAG_LIST[4]; extern const char *const PLAYERFLAG_LIST[]; extern const char *const GAMETYPERULE_LIST[]; extern const char *const ML_LIST[16]; // Linedef flags -extern const char* const MSF_LIST[5]; // Sector flags +extern const char* const MSF_LIST[6]; // Sector flags extern const char *COLOR_ENUMS[]; extern const char *const POWERS_LIST[]; extern const char *const HUDITEMS_LIST[]; diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0a147acbb..74f45535f 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -753,6 +753,7 @@ static int sector_set(lua_State *L) return LUA_ErrSetDirectly(L, "sector_t", "taglist"); case sector_flags: sector->flags = luaL_checkinteger(L, 3); + CheckForReverseGravity |= (sector->flags & MSF_GRAVITYFLIP); break; case sector_gravity: sector->gravity = luaL_checkfixed(L, 3); diff --git a/src/p_mobj.c b/src/p_mobj.c index aea7964be..bdfee2616 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1463,7 +1463,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) gravityadd = -FixedMul(gravity, gravfactor); - if (rover->master->frontsector->verticalflip && gravityadd > 0) + if ((rover->master->frontsector->flags & MSF_GRAVITYFLIP) && gravityadd > 0) mo->eflags |= MFE_VERTICALFLIP; no3dfloorgrav = false; @@ -1475,7 +1475,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) { gravityadd = -FixedMul(gravity, P_GetSectorGravityFactor(mo->subsector->sector)); - if (mo->subsector->sector->verticalflip && gravityadd > 0) + if ((mo->subsector->sector->flags & MSF_GRAVITYFLIP) && gravityadd > 0) mo->eflags |= MFE_VERTICALFLIP; } diff --git a/src/p_saveg.c b/src/p_saveg.c index 66df83603..d7a9750b7 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1213,7 +1213,10 @@ static void UnArchiveSectors(void) sectors[i].ceilinglightabsolute = READUINT8(save_p); } if (diff3 & SD_FLAG) + { sectors[i].flags = READUINT32(save_p); + CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP); + } if (diff3 & SD_GRAVITY) sectors[i].gravity = READFIXED(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index 2bcde2b92..70c6276d0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1000,7 +1000,6 @@ static void P_InitializeSector(sector_t *ss) ss->extra_colormap = NULL; ss->gravityptr = NULL; - ss->verticalflip = false; ss->cullheight = NULL; @@ -1674,6 +1673,8 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].flags |= MSF_TRIGGERSPECIAL_HEADBUMP; else if (fastcmp(param, "invertprecip") && fastcmp("true", val)) sectors[i].flags |= MSF_INVERTPRECIP; + else if (fastcmp(param, "gravityflip") && fastcmp("true", val)) + sectors[i].flags |= MSF_GRAVITYFLIP; else if (fastcmp(param, "heatwave") && fastcmp("true", val)) sectors[i].flags |= MSF_HEATWAVE; else if (fastcmp(param, "friction")) diff --git a/src/p_spec.c b/src/p_spec.c index 846ce9376..604921445 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5994,6 +5994,8 @@ void P_SpawnSpecials(boolean fromnetsave) sector = sectors; for (i = 0; i < numsectors; i++, sector++) { + CheckForReverseGravity |= (sector->flags & MSF_GRAVITYFLIP); + if (!sector->special) continue; @@ -6116,11 +6118,11 @@ void P_SpawnSpecials(boolean fromnetsave) sectors[s].gravityptr = §ors[sec].floorheight; // This allows it to change in realtime! if (lines[i].flags & ML_NOCLIMB) - sectors[s].verticalflip = true; + sectors[s].flags |= MSF_GRAVITYFLIP; else - sectors[s].verticalflip = false; + sectors[s].flags &= ~MSF_GRAVITYFLIP; - CheckForReverseGravity = sectors[s].verticalflip; + CheckForReverseGravity |= (sectors[s].flags & MSF_GRAVITYFLIP); } break; diff --git a/src/r_defs.h b/src/r_defs.h index 0fd13b707..c565473dd 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -284,7 +284,8 @@ typedef enum MSF_TRIGGERSPECIAL_HEADBUMP = 1<<3, // invertprecip - inverts presence of precipitation MSF_INVERTPRECIP = 1<<4, - MSF_HEATWAVE = 1<<5, // heat wave effect + MSF_GRAVITYFLIP = 1<<5, + MSF_HEATWAVE = 1<<6, } sectorflags_t; @@ -368,7 +369,6 @@ typedef struct sector_s fixed_t gravity; // per-sector gravity factor fixed_t *gravityptr; // For binary format: Read gravity from floor height of master sector - boolean verticalflip; // If gravity < 0, then allow flipped physics sectorflags_t flags; INT32 friction; From 7b830fbddf7c6d4b3e7815e9b28914d5c815664c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 19:28:01 +0100 Subject: [PATCH 264/326] Add "change sector's gravity" linedef executor in UDMF to replace linedef type 1 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 37 ++++++++++++++++++++ src/p_spec.c | 30 ++++++++++++++++ src/p_spec.h | 7 ++++ 3 files changed, 74 insertions(+) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index e8ec7de2b..e2e1d187a 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -3677,6 +3677,43 @@ udmf enum = "setadd"; } } + + 469 + { + title = "Change Tagged Sector's Gravity"; + prefix = "(469)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Set/Multiply?"; + type = 11; + enum + { + 0 = "Set"; + 1 = "Multiply"; + } + } + arg2 + { + title = "Flip flag"; + type = 11; + enum + { + 0 = "Don't change"; + 1 = "Set"; + 2 = "Remove"; + } + } + stringarg0 + { + title = "Gravity value"; + type = 2; + } + } } linedefexecplane diff --git a/src/p_spec.c b/src/p_spec.c index 604921445..2e6094ef2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3801,6 +3801,33 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; + case 469: // Change sector gravity + { + fixed_t gravityvalue; + + if (!udmf) + break; + + if (!line->stringargs[0]) + break; + + gravityvalue = FloatToFixed(atof(line->stringargs[0])); + + TAG_ITER_SECTORS(line->args[0], secnum) + { + if (line->args[1]) + sectors[secnum].gravity = FixedMul(sectors[secnum].gravity, gravityvalue); + else + sectors[secnum].gravity = gravityvalue; + + if (line->args[2] == TMF_ADD) + sectors[secnum].flags |= MSF_GRAVITYFLIP; + else if (line->args[2] == TMF_REMOVE) + sectors[secnum].flags &= ~MSF_GRAVITYFLIP; + } + } + break; + case 480: // Polyobj_DoorSlide case 481: // Polyobj_DoorSwing PolyDoor(line); @@ -6112,6 +6139,9 @@ void P_SpawnSpecials(boolean fromnetsave) ffloortype_e ffloorflags; case 1: // Definable gravity per sector + if (udmf) + break; + sec = sides[*lines[i].sidenum].sector - sectors; TAG_ITER_SECTORS(tag, s) { diff --git a/src/p_spec.h b/src/p_spec.h index 82f858a05..c1f25b3d6 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -412,6 +412,13 @@ typedef enum //TMP_FREEZETHINKERS = 1<<6, } textmappromptflags_t; +typedef enum +{ + TMF_NOCHANGE = 0, + TMF_ADD = 1, + TMF_REMOVE = 2, +} textmapsetflagflags_t; + typedef enum { TMSD_FRONT = 0, From 570a6ab395ee0cc2de69e3d1a6e1abb5da6de3a8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 20:37:57 +0100 Subject: [PATCH 265/326] Turn "intangible to camera" sector special into a sector flag --- extras/conf/udb/Includes/SRB222_misc.cfg | 1 + src/deh_lua.c | 2 +- src/deh_tables.c | 3 ++- src/deh_tables.h | 2 +- src/p_map.c | 6 +++--- src/p_maputl.c | 4 ++-- src/p_setup.c | 14 ++++++++++++++ src/p_spec.c | 2 +- src/p_user.c | 6 +++--- src/r_defs.h | 1 + 10 files changed, 29 insertions(+), 12 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 36518be9f..709514df8 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -81,6 +81,7 @@ sectorflags invertprecip = "Invert Precipitation"; gravityflip = "Flip Objects in Reverse Gravity"; heatwave = "Heat Wave"; + noclipcamera = "Intangible to the Camera"; } thingflags diff --git a/src/deh_lua.c b/src/deh_lua.c index e360febaf..10f5eb46d 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -340,7 +340,7 @@ static inline int lib_getenum(lua_State *L) } else if (fastncmp("MSF_", word, 3)) { p = word + 4; - for (i = 0; i < 6; i++) + for (i = 0; i < 7; i++) if (MSF_LIST[i] && fastcmp(p, MSF_LIST[i])) { lua_pushinteger(L, ((lua_Integer)1 << i)); return 1; diff --git a/src/deh_tables.c b/src/deh_tables.c index 095aae0f2..276bfce18 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4472,13 +4472,14 @@ const char *const ML_LIST[16] = { }; // Sector flags -const char *const MSF_LIST[6] = { +const char *const MSF_LIST[7] = { "FLIPSPECIAL_FLOOR", "FLIPSPECIAL_CEILING", "TRIGGERSPECIAL_TOUCH", "TRIGGERSPECIAL_HEADBUMP", "GRAVITYFLIP", "HEATWAVE", + "NOCLIPCAMERA", }; const char *COLOR_ENUMS[] = { diff --git a/src/deh_tables.h b/src/deh_tables.h index 2e514a5b1..8cabb2063 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -65,7 +65,7 @@ extern const char *const MAPTHINGFLAG_LIST[4]; extern const char *const PLAYERFLAG_LIST[]; extern const char *const GAMETYPERULE_LIST[]; extern const char *const ML_LIST[16]; // Linedef flags -extern const char* const MSF_LIST[6]; // Sector flags +extern const char* const MSF_LIST[7]; // Sector flags extern const char *COLOR_ENUMS[]; extern const char *const POWERS_LIST[]; extern const char *const HUDITEMS_LIST[]; diff --git a/src/p_map.c b/src/p_map.c index 6b69df9cb..8b236c7c3 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2319,7 +2319,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) mapcampointer = thiscam; - if (GETSECSPECIAL(newsubsec->sector->special, 4) == 12) + if (newsubsec->sector->flags & MSF_NOCLIPCAMERA) { // Camera noclip on entire sector. tmfloorz = tmdropoffz = thiscam->z; tmceilingz = tmdrpoffceilz = thiscam->z + thiscam->height; @@ -2359,7 +2359,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) for (rover = newsubsec->sector->ffloors; rover; rover = rover->next) { fixed_t topheight, bottomheight; - if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERALL) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12) + if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERALL) || (rover->master->frontsector->flags & MSF_NOCLIPCAMERA)) continue; topheight = P_CameraGetFOFTopZ(thiscam, newsubsec->sector, rover, x, y, NULL); @@ -2431,7 +2431,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) // We're inside it! Yess... polysec = po->lines[0]->backsector; - if (GETSECSPECIAL(polysec->special, 4) == 12) + if (polysec->flags & MSF_NOCLIPCAMERA) { // Camera noclip polyobj. plink = (polymaplink_t *)(plink->link.next); continue; diff --git a/src/p_maputl.c b/src/p_maputl.c index efcebe736..ee22578ef 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -374,7 +374,7 @@ void P_CameraLineOpening(line_t *linedef) for (rover = front->ffloors; rover; rover = rover->next) { fixed_t topheight, bottomheight; - if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12) + if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || (rover->master->frontsector->flags & MSF_NOCLIPCAMERA)) continue; topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, tmx, tmy, linedef); @@ -398,7 +398,7 @@ void P_CameraLineOpening(line_t *linedef) for (rover = back->ffloors; rover; rover = rover->next) { fixed_t topheight, bottomheight; - if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12) + if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || (rover->master->frontsector->flags & MSF_NOCLIPCAMERA)) continue; topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tmx, tmy, linedef); diff --git a/src/p_setup.c b/src/p_setup.c index 70c6276d0..0f398c5bc 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1677,6 +1677,8 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].flags |= MSF_GRAVITYFLIP; else if (fastcmp(param, "heatwave") && fastcmp("true", val)) sectors[i].flags |= MSF_HEATWAVE; + else if (fastcmp(param, "noclipcamera") && fastcmp("true", val)) + sectors[i].flags |= MSF_NOCLIPCAMERA; else if (fastcmp(param, "friction")) sectors[i].friction = atol(val); else if (fastcmp(param, "gravity")) @@ -5017,6 +5019,18 @@ static void P_ConvertBinaryMap(void) } } + for (i = 0; i < numsectors; i++) + { + switch(GETSECSPECIAL(sectors[i].special, 4)) + { + case 12: //Intangible to the camera + sectors[i].flags |= MSF_NOCLIPCAMERA; + break; + default: + break; + } + } + for (i = 0; i < NUMMOBJTYPES; i++) { if (mobjinfo[i].doomednum < 0 || mobjinfo[i].doomednum >= 4096) diff --git a/src/p_spec.c b/src/p_spec.c index 2e6094ef2..9fe9ad8ef 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5017,7 +5017,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (isTouching) P_ProcessRopeHang(player, sector, sectag); break; - case 12: // Camera noclip + case 12: // Unused case 13: // Unused case 14: // Unused case 15: // Unused diff --git a/src/p_user.c b/src/p_user.c index 8adb6ef9b..d94b7556f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10057,7 +10057,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall for (rover = newsubsec->sector->ffloors; rover; rover = rover->next) { fixed_t topheight, bottomheight; - if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERALL) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12) + if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERALL) || (rover->master->frontsector->flags & MSF_NOCLIPCAMERA)) continue; topheight = P_CameraGetFOFTopZ(thiscam, newsubsec->sector, rover, midx, midy, NULL); @@ -10121,7 +10121,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // We're inside it! Yess... polysec = po->lines[0]->backsector; - if (GETSECSPECIAL(polysec->special, 4) == 12) + if (polysec->flags & MSF_NOCLIPCAMERA) { // Camera noclip polyobj. plink = (polymaplink_t *)(plink->link.next); continue; @@ -10183,7 +10183,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall for (rover = newsubsec->sector->ffloors; rover; rover = rover->next) { fixed_t topheight, bottomheight; - if ((rover->flags & FF_BLOCKOTHERS) && (rover->flags & FF_RENDERALL) && (rover->flags & FF_EXISTS) && GETSECSPECIAL(rover->master->frontsector->special, 4) != 12) + if ((rover->flags & FF_BLOCKOTHERS) && (rover->flags & FF_RENDERALL) && (rover->flags & FF_EXISTS) && !(rover->master->frontsector->flags & MSF_NOCLIPCAMERA)) { topheight = P_CameraGetFOFTopZ(thiscam, newsubsec->sector, rover, midx, midy, NULL); bottomheight = P_CameraGetFOFBottomZ(thiscam, newsubsec->sector, rover, midx, midy, NULL); diff --git a/src/r_defs.h b/src/r_defs.h index c565473dd..833958ab1 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -286,6 +286,7 @@ typedef enum MSF_INVERTPRECIP = 1<<4, MSF_GRAVITYFLIP = 1<<5, MSF_HEATWAVE = 1<<6, + MSF_NOCLIPCAMERA = 1<<7, } sectorflags_t; From e1393954c7268dad64543aa249e20f8d33f0d16e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 30 Dec 2021 21:27:09 +0100 Subject: [PATCH 266/326] Make deprecated sector types inaccessible in UDMF --- extras/conf/SRB2-22.cfg | 8 ++++---- extras/conf/udb/Includes/SRB222_sectors.cfg | 12 ++++++------ src/p_spec.c | 16 ++++++++++------ src/p_user.c | 2 +- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index ec568e865..81d8ed193 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -435,8 +435,8 @@ sectortypes 112 = "Trigger Line Ex. (NiGHTS Mare) "; 128 = "Check for Linedef Executor on FOFs"; 144 = "Egg Capsule"; - 160 = "Special Stage Time/Spheres Parameters"; - 176 = "Custom Global Gravity"; + 160 = "Special Stage Time/Spheres Parameters "; + 176 = "Custom Global Gravity "; 512 = "Wind/Current"; 1024 = "Conveyor Belt"; 1280 = "Speed Pad"; @@ -490,8 +490,8 @@ gen_sectortypes 112 = "Trigger Line Ex. (NiGHTS Mare) "; 128 = "Check for Linedef Executor on FOFs"; 144 = "Egg Capsule"; - 160 = "Special Stage Time/Spheres Parameters"; - 176 = "Custom Global Gravity"; + 160 = "Special Stage Time/Spheres Parameters "; + 176 = "Custom Global Gravity "; } third diff --git a/extras/conf/udb/Includes/SRB222_sectors.cfg b/extras/conf/udb/Includes/SRB222_sectors.cfg index e02bfd7cc..412aed155 100644 --- a/extras/conf/udb/Includes/SRB222_sectors.cfg +++ b/extras/conf/udb/Includes/SRB222_sectors.cfg @@ -22,11 +22,11 @@ sectortypes 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)"; + 112 = "Trigger Line Ex. (NiGHTS Mare) "; 128 = "Check for Linedef Executor on FOFs"; 144 = "Egg Capsule"; - 160 = "Special Stage Time/Spheres Parameters"; - 176 = "Custom Global Gravity"; + 160 = "Special Stage Time/Spheres Parameters "; + 176 = "Custom Global Gravity "; 512 = "Wind/Current"; 1024 = "Conveyor Belt"; 1280 = "Speed Pad"; @@ -75,11 +75,11 @@ gen_sectortypes 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)"; + 112 = "Trigger Line Ex. (NiGHTS Mare) "; 128 = "Check for Linedef Executor on FOFs"; 144 = "Egg Capsule"; - 160 = "Special Stage Time/Spheres Parameters"; - 176 = "Custom Global Gravity"; + 160 = "Special Stage Time/Spheres Parameters "; + 176 = "Custom Global Gravity "; } third diff --git a/src/p_spec.c b/src/p_spec.c index 9fe9ad8ef..388440d75 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4871,6 +4871,8 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers break; /* FALLTHRU */ case 10: // Ring Drainer (No Floor Touch) + if (udmf) + break; if (leveltime % (TICRATE/2) == 0 && player->rings > 0) { player->rings--; @@ -6036,6 +6038,8 @@ void P_SpawnSpecials(boolean fromnetsave) sector->flags |= MSF_TRIGGERSPECIAL_TOUCH; break; case 15: // Bouncy FOF + if (udmf) + break; CONS_Alert(CONS_WARNING, M_GetText("Deprecated bouncy FOF sector type detected. Please use linedef type 76 instead.\n")); CheckForBouncySector = true; break; @@ -6045,21 +6049,21 @@ void P_SpawnSpecials(boolean fromnetsave) switch(GETSECSPECIAL(sector->special, 2)) { case 10: // Time for special stage + if (udmf) + break; + CONS_Alert(CONS_WARNING, M_GetText("Deprecated sector type for special stage requirements detected. Please use the SpecialStageTime and SpecialStageSpheres level header options instead.\n")); sstimer = (sector->floorheight>>FRACBITS) * TICRATE + 6; // Time to finish ssspheres = sector->ceilingheight>>FRACBITS; // Ring count for special stage break; case 11: // Custom global gravity! + if (udmf) + break; + CONS_Alert(CONS_WARNING, M_GetText("Deprecated sector type for global gravity detected. Please use the Gravity level header option instead.\n")); gravity = sector->floorheight/1000; break; } - // Process Section 3 -/* switch(GETSECSPECIAL(player->specialsector, 3)) - { - - }*/ - // Process Section 4 switch(GETSECSPECIAL(sector->special, 4)) { diff --git a/src/p_user.c b/src/p_user.c index d94b7556f..45c64500f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2677,7 +2677,7 @@ static void P_CheckBouncySectors(player_t *player) continue; // FOFs should not be bouncy if they don't even "exist" // Handle deprecated bouncy FOF sector type - if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 15) + if (!udmf && GETSECSPECIAL(rover->master->frontsector->special, 1) == 15) { rover->flags |= FF_BOUNCY; rover->bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100; From feaa4f1273b42418718bb4f43a724f17536f66e4 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 00:03:24 +0100 Subject: [PATCH 267/326] Replace most sector specials with sector special flags --- extras/conf/udb/Includes/SRB222_misc.cfg | 19 ++ src/deh_lua.c | 10 + src/deh_tables.c | 22 ++ src/deh_tables.h | 1 + src/lua_baselib.c | 26 ++ src/lua_maplib.c | 8 + src/p_inter.c | 3 +- src/p_map.c | 20 +- src/p_mobj.c | 2 +- src/p_saveg.c | 9 +- src/p_setup.c | 102 +++++++ src/p_spec.c | 363 +++++++++++++---------- src/p_spec.h | 2 + src/p_user.c | 7 +- src/r_defs.h | 23 ++ 15 files changed, 446 insertions(+), 171 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 709514df8..d6210e9f1 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -82,6 +82,25 @@ sectorflags gravityflip = "Flip Objects in Reverse Gravity"; heatwave = "Heat Wave"; noclipcamera = "Intangible to the Camera"; + outerspace = "Space Countdown"; + doublestepup = "Ramp Sector (double step-up/down)"; + nostepdown = "Non-Ramp Sector (No step-down)"; + windcurrent = "Wind/Current"; + conveyor = "Conveyor Belt"; + speedpad = "Speed Pad"; + starpostactivator = "Star Post Activator"; + exit = "Exit"; + specialstagepit = "Special Stage Pit"; + returnflag = "Return Flag"; + redteambase = "Red Team Base"; + blueteambase = "Blue Team Base"; + fan = "Fan Sector"; + supertransform = "Super Sonic Transform"; + forcespin = "Force Spin"; + zoomtubestart = "Zoom Tube Start"; + zoomtubeend = "Zoom Tube End"; + finishline = "Circuit Finish Line"; + ropehang = "Rope Hang"; } thingflags diff --git a/src/deh_lua.c b/src/deh_lua.c index 10f5eb46d..56d2ec1e9 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -353,6 +353,16 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "sector flag '%s' could not be found.\n", word); return 0; } + else if (fastncmp("SSF_", word, 3)) { + p = word + 4; + for (i = 0; i < 19; i++) + if (SSF_LIST[i] && fastcmp(p, SSF_LIST[i])) { + lua_pushinteger(L, ((lua_Integer)1 << i)); + return 1; + } + if (mathlib) return luaL_error(L, "sector special flag '%s' could not be found.\n", word); + return 0; + } else if (fastncmp("S_",word,2)) { p = word+2; for (i = 0; i < NUMSTATEFREESLOTS; i++) { diff --git a/src/deh_tables.c b/src/deh_tables.c index 276bfce18..26fa74c90 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4482,6 +4482,28 @@ const char *const MSF_LIST[7] = { "NOCLIPCAMERA", }; +// Sector special flags +const char* const SSF_LIST[19] = { + "OUTERSPACE", + "DOUBLESTEPUP", + "WINDCURRENT", + "CONVEYOR", + "SPEEDPAD", + "STARPOSTACTIVATOR", + "EXIT", + "SPECIALSTAGEPIT", + "RETURNFLAG", + "REDTEAMBASE", + "BLUETEAMBASE", + "FAN", + "SUPERTRANSFORM", + "FORCESPIN", + "ZOOMTUBESTART", + "ZOOMTUBEEND", + "FINISHLINE", + "ROPEHANG", +}; + const char *COLOR_ENUMS[] = { "NONE", // SKINCOLOR_NONE, diff --git a/src/deh_tables.h b/src/deh_tables.h index 8cabb2063..35f58c882 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -66,6 +66,7 @@ extern const char *const PLAYERFLAG_LIST[]; extern const char *const GAMETYPERULE_LIST[]; extern const char *const ML_LIST[16]; // Linedef flags extern const char* const MSF_LIST[7]; // Sector flags +extern const char* const SSF_LIST[19]; // Sector special flags extern const char *COLOR_ENUMS[]; extern const char *const POWERS_LIST[]; extern const char *const HUDITEMS_LIST[]; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index d64f8abd2..27af76ed8 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2215,6 +2215,18 @@ static int lib_pMobjTouchingSectorSpecial(lua_State *L) return 1; } +static int lib_pMobjTouchingSectorSpecialFlag(lua_State *L) +{ + mobj_t *mo = *((mobj_t**)luaL_checkudata(L, 1, META_MOBJ)); + sectorspecialflags_t flag = (INT32)luaL_checkinteger(L, 2); + //HUDSAFE + INLEVEL + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + LUA_PushUserdata(L, P_MobjTouchingSectorSpecialFlag(mo, flag), META_SECTOR); + return 1; +} + static int lib_pPlayerTouchingSectorSpecial(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -2228,6 +2240,18 @@ static int lib_pPlayerTouchingSectorSpecial(lua_State *L) return 1; } +static int lib_pPlayerTouchingSectorSpecialFlag(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + sectorspecialflags_t flag = (INT32)luaL_checkinteger(L, 2); + //HUDSAFE + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + LUA_PushUserdata(L, P_PlayerTouchingSectorSpecialFlag(player, flag), META_SECTOR); + return 1; +} + static int lib_pFindLowestFloorSurrounding(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); @@ -4059,7 +4083,9 @@ static luaL_Reg lib[] = { {"P_DoSuperTransformation",lib_pDoSuperTransformation}, {"P_ExplodeMissile",lib_pExplodeMissile}, {"P_MobjTouchingSectorSpecial",lib_pMobjTouchingSectorSpecial}, + {"P_MobjTouchingSectorSpecialFlag",lib_pMobjTouchingSectorSpecialFlag}, {"P_PlayerTouchingSectorSpecial",lib_pPlayerTouchingSectorSpecial}, + {"P_PlayerTouchingSectorSpecialFlag",lib_pPlayerTouchingSectorSpecialFlag}, {"P_FindLowestFloorSurrounding",lib_pFindLowestFloorSurrounding}, {"P_FindHighestFloorSurrounding",lib_pFindHighestFloorSurrounding}, {"P_FindNextHighestFloor",lib_pFindNextHighestFloor}, diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 74f45535f..8ab8c7e83 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -50,6 +50,7 @@ enum sector_e { sector_fslope, sector_cslope, sector_flags, + sector_specialflags, sector_friction, sector_gravity, }; @@ -76,6 +77,7 @@ static const char *const sector_opt[] = { "f_slope", "c_slope", "flags", + "specialflags", "friction", "gravity", NULL}; @@ -658,6 +660,9 @@ static int sector_get(lua_State *L) case sector_flags: // flags lua_pushinteger(L, sector->flags); return 1; + case sector_specialflags: // specialflags + lua_pushinteger(L, sector->specialflags); + return 1; case sector_friction: // friction lua_pushinteger(L, sector->friction); return 1; @@ -755,6 +760,9 @@ static int sector_set(lua_State *L) sector->flags = luaL_checkinteger(L, 3); CheckForReverseGravity |= (sector->flags & MSF_GRAVITYFLIP); break; + case sector_specialflags: + sector->specialflags = luaL_checkinteger(L, 3); + break; case sector_gravity: sector->gravity = luaL_checkfixed(L, 3); break; diff --git a/src/p_inter.c b/src/p_inter.c index 028ac0ef3..caf247f96 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -763,6 +763,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // return; { UINT8 flagteam = (special->type == MT_REDFLAG) ? 1 : 2; + sectorspecialflags_t specialflag = (special->type == MT_REDFLAG) ? SSF_REDTEAMBASE : SSF_BLUETEAMBASE; const char *flagtext; char flagcolor; char plname[MAXPLAYERNAME+4]; @@ -792,7 +793,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->fuse = 1; special->flags2 |= MF2_JUSTATTACKED; - if (!P_PlayerTouchingSectorSpecial(player, 4, 2 + flagteam)) + if (!P_PlayerTouchingSectorSpecialFlag(player, specialflag)) { CONS_Printf(M_GetText("%s returned the %c%s%c to base.\n"), plname, flagcolor, flagtext, 0x80); diff --git a/src/p_map.c b/src/p_map.c index 8b236c7c3..beae1a8ea 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2699,14 +2699,14 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->player) { - // If using type Section1:13, double the maxstep. - if (P_PlayerTouchingSectorSpecial(thing->player, 1, 13) - || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13) + // If using SSF_DOUBLESTEPUP, double the maxstep. + if (P_PlayerTouchingSectorSpecialFlag(thing->player, SSF_DOUBLESTEPUP) + || (R_PointInSubsector(x, y)->sector->specialflags & SSF_DOUBLESTEPUP)) maxstep <<= 1; - // If using type Section1:14, no maxstep. - if (P_PlayerTouchingSectorSpecial(thing->player, 1, 14) - || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14) + // If using SSF_NOSTEPDOWN, no maxstep. + if (P_PlayerTouchingSectorSpecialFlag(thing->player, SSF_NOSTEPDOWN) + || (R_PointInSubsector(x, y)->sector->specialflags & SSF_NOSTEPDOWN)) maxstep = 0; // Don't 'step up' while springing, @@ -2717,12 +2717,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) } else if (thing->flags & MF_PUSHABLE) { - // If using type Section1:13, double the maxstep. - if (GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13) + // If using SSF_DOUBLESTEPUP, double the maxstep. + if (R_PointInSubsector(x, y)->sector->specialflags & SSF_DOUBLESTEPUP) maxstep <<= 1; - // If using type Section1:14, no maxstep. - if (GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14) + // If using SSF_NOSTEPDOWN, no maxstep. + if (R_PointInSubsector(x, y)->sector->specialflags & SSF_NOSTEPDOWN) maxstep = 0; } diff --git a/src/p_mobj.c b/src/p_mobj.c index bdfee2616..4b31307ef 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9738,7 +9738,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) break; case MT_BLUEFLAG: case MT_REDFLAG: - if (P_MobjTouchingSectorSpecial(mobj, 4, 2)) + if (P_MobjTouchingSectorSpecialFlag(mobj, SSF_RETURNFLAG)) mobj->fuse = 1; // Return to base. break; case MT_SPINDUST: // Spindash dust diff --git a/src/p_saveg.c b/src/p_saveg.c index d7a9750b7..1923fa576 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -853,7 +853,8 @@ static void P_NetUnArchiveWaypoints(void) #define SD_FLOORLIGHT 0x08 #define SD_CEILLIGHT 0x10 #define SD_FLAG 0x20 -#define SD_GRAVITY 0x40 +#define SD_SPECIALFLAG 0x40 +#define SD_GRAVITY 0x80 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -1041,6 +1042,8 @@ static void ArchiveSectors(void) diff3 |= SD_CEILLIGHT; if (ss->flags != spawnss->flags) diff3 |= SD_FLAG; + if (ss->specialflags != spawnss->specialflags) + diff3 |= SD_SPECIALFLAG; if (ss->gravity != spawnss->gravity) diff3 |= SD_GRAVITY; @@ -1109,6 +1112,8 @@ static void ArchiveSectors(void) } if (diff3 & SD_FLAG) WRITEUINT32(save_p, ss->flags); + if (diff3 & SD_SPECIALFLAG) + WRITEUINT32(save_p, ss->specialflags); if (diff3 & SD_GRAVITY) WRITEFIXED(save_p, ss->gravity); if (diff & SD_FFLOORS) @@ -1217,6 +1222,8 @@ static void UnArchiveSectors(void) sectors[i].flags = READUINT32(save_p); CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP); } + if (diff3 & SD_SPECIALFLAG) + sectors[i].specialflags = READUINT32(save_p); if (diff3 & SD_GRAVITY) sectors[i].gravity = READFIXED(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index 0f398c5bc..17fd5bb63 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1679,6 +1679,44 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].flags |= MSF_HEATWAVE; else if (fastcmp(param, "noclipcamera") && fastcmp("true", val)) sectors[i].flags |= MSF_NOCLIPCAMERA; + else if (fastcmp(param, "outerspace") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_OUTERSPACE; + else if (fastcmp(param, "doublestepup") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_DOUBLESTEPUP; + else if (fastcmp(param, "nostepdown") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_NOSTEPDOWN; + else if (fastcmp(param, "windcurrent") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_WINDCURRENT; + else if (fastcmp(param, "conveyor") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_CONVEYOR; + else if (fastcmp(param, "speedpad") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_SPEEDPAD; + else if (fastcmp(param, "starpostactivator") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_STARPOSTACTIVATOR; + else if (fastcmp(param, "exit") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_EXIT; + else if (fastcmp(param, "specialstagepit") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_SPECIALSTAGEPIT; + else if (fastcmp(param, "returnflag") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_RETURNFLAG; + else if (fastcmp(param, "redteambase") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_REDTEAMBASE; + else if (fastcmp(param, "blueteambase") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_BLUETEAMBASE; + else if (fastcmp(param, "fan") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_FAN; + else if (fastcmp(param, "supertransform") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_SUPERTRANSFORM; + else if (fastcmp(param, "forcespin") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_FORCESPIN; + else if (fastcmp(param, "zoomtubestart") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_ZOOMTUBESTART; + else if (fastcmp(param, "zoomtubeend") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_ZOOMTUBEEND; + else if (fastcmp(param, "finishline") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_FINISHLINE; + else if (fastcmp(param, "ropehang") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_ROPEHANG; else if (fastcmp(param, "friction")) sectors[i].friction = atol(val); else if (fastcmp(param, "gravity")) @@ -5021,8 +5059,72 @@ static void P_ConvertBinaryMap(void) for (i = 0; i < numsectors; i++) { + + switch(GETSECSPECIAL(sectors[i].special, 1)) + { + case 12: //Space countdown + sectors[i].specialflags |= SSF_OUTERSPACE; + break; + case 13: //Ramp sector + sectors[i].specialflags |= SSF_DOUBLESTEPUP; + break; + case 14: //Non-ramp sector + sectors[i].specialflags |= SSF_NOSTEPDOWN; + break; + default: + break; + } + + switch(GETSECSPECIAL(sectors[i].special, 3)) + { + case 2: //Wind/Current + sectors[i].specialflags |= SSF_WINDCURRENT; + break; + case 4: //Conveyor belt + sectors[i].specialflags |= SSF_CONVEYOR; + break; + case 5: //Speed pad + sectors[i].specialflags |= SSF_SPEEDPAD; + break; + default: + break; + } + switch(GETSECSPECIAL(sectors[i].special, 4)) { + case 1: //Star post activator + sectors[i].specialflags |= SSF_STARPOSTACTIVATOR; + break; + case 2: //Exit/Special Stage pit/Return flag + sectors[i].specialflags |= SSF_EXIT|SSF_SPECIALSTAGEPIT|SSF_RETURNFLAG; + break; + case 3: //Red team base + sectors[i].specialflags |= SSF_REDTEAMBASE; + break; + case 4: //Blue team base + sectors[i].specialflags |= SSF_BLUETEAMBASE; + break; + case 5: //Fan sector + sectors[i].specialflags |= SSF_FAN; + break; + case 6: //Super Sonic transform + sectors[i].specialflags |= SSF_SUPERTRANSFORM; + break; + case 7: //Force spin + sectors[i].specialflags |= SSF_FORCESPIN; + break; + case 8: //Zoom tube start + sectors[i].specialflags |= SSF_ZOOMTUBESTART; + break; + case 9: //Zoom tube end + sectors[i].specialflags |= SSF_ZOOMTUBEEND; + break; + case 10: //Circuit finish line + sectors[i].specialflags |= SSF_FINISHLINE; + break; + case 11: //Rope hang + sectors[i].specialflags |= SSF_ROPEHANG; + break; case 12: //Intangible to the camera sectors[i].flags |= MSF_NOCLIPCAMERA; break; diff --git a/src/p_spec.c b/src/p_spec.c index 388440d75..2e4821972 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3933,7 +3933,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) { thinker_t *think; mobj_t *mo; - INT32 specialnum = (flag == MT_REDFLAG) ? 3 : 4; + sectorspecialflags_t specialflag = (flag == MT_REDFLAG) ? SSF_REDTEAMBASE : SSF_BLUETEAMBASE; for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { @@ -3945,7 +3945,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) if (mo->type != flag) continue; - if (GETSECSPECIAL(mo->subsector->sector->special, 4) == specialnum) + if (mo->subsector->sector->specialflags & specialflag) return true; else if (mo->subsector->sector->ffloors) // Check the 3D floors { @@ -3956,7 +3956,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) if (!(rover->flags & FF_EXISTS)) continue; - if (GETSECSPECIAL(rover->master->frontsector->special, 4) != specialnum) + if (!(rover->master->frontsector->specialflags & specialflag)) continue; if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) @@ -4041,6 +4041,30 @@ static sector_t *P_MobjTouching3DFloorSpecial(mobj_t *mo, sector_t *sector, INT3 return NULL; } +static sector_t *P_MobjTouching3DFloorSpecialFlag(mobj_t *mo, sector_t *sector, sectorspecialflags_t flag) +{ + ffloor_t *rover; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->master->frontsector->specialflags & flag)) + continue; + + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!P_IsMobjTouching3DFloor(mo, rover, sector)) + continue; + + // This FOF has the special we're looking for, but are we allowed to touch it? + if (sector == mo->subsector->sector + || (rover->master->frontsector->flags & MSF_TRIGGERSPECIAL_TOUCH)) + return rover->master->frontsector; + } + + return NULL; +} + static sector_t *P_MobjTouchingPolyobjSpecial(mobj_t *mo, INT32 section, INT32 number) { polyobj_t *po; @@ -4073,6 +4097,38 @@ static sector_t *P_MobjTouchingPolyobjSpecial(mobj_t *mo, INT32 section, INT32 n return NULL; } +static sector_t *P_MobjTouchingPolyobjSpecialFlag(mobj_t *mo, sectorspecialflags_t flag) +{ + polyobj_t *po; + sector_t *polysec; + boolean touching = false; + boolean inside = false; + + for (po = mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) + { + if (po->flags & POF_NOSPECIALS) + continue; + + polysec = po->lines[0]->backsector; + + if (!(polysec->specialflags & flag)) + continue; + + touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo); + inside = P_MobjInsidePolyobj(po, mo); + + if (!(inside || touching)) + continue; + + if (!P_IsMobjTouchingPolyobj(mo, po, polysec)) + continue; + + return polysec; + } + + return NULL; +} + sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number) { msecnode_t *node; @@ -4101,7 +4157,42 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number) if (!(node->m_sector->flags & MSF_TRIGGERSPECIAL_TOUCH)) continue; - if (GETSECSPECIAL(mo->subsector->sector->special, section) == number) + if (GETSECSPECIAL(node->m_sector->special, section) == number) + return node->m_sector; + } + + return NULL; +} + +sector_t *P_MobjTouchingSectorSpecialFlag(mobj_t *mo, sectorspecialflags_t flag) +{ + msecnode_t *node; + sector_t *result; + + result = P_MobjTouching3DFloorSpecialFlag(mo, mo->subsector->sector, flag); + if (result) + return result; + + result = P_MobjTouchingPolyobjSpecialFlag(mo, flag); + if (result) + return result; + + if (mo->subsector->sector->specialflags & flag) + return mo->subsector->sector; + + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (node->m_sector == mo->subsector->sector) // Don't duplicate + continue; + + result = P_MobjTouching3DFloorSpecialFlag(mo, node->m_sector, flag); + if (result) + return result; + + if (!(node->m_sector->flags & MSF_TRIGGERSPECIAL_TOUCH)) + continue; + + if (node->m_sector->specialflags & flag) return node->m_sector; } @@ -4127,6 +4218,14 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n return P_MobjTouchingSectorSpecial(player->mo, section, number); } +sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags_t flag) +{ + if (!player->mo) + return NULL; + + return P_MobjTouchingSectorSpecialFlag(player->mo, flag); +} + static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line_t *sourceline) { ffloor_t *rover; @@ -4371,7 +4470,7 @@ static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *rove if (lineindex == -1) { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #4.\n", sector->special); + CONS_Debug(DBG_GAMELOGIC, "ERROR: Speed pad missing line special #4.\n"); return; } @@ -4425,7 +4524,27 @@ static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *rove S_StartSound(player->mo, sfxnum); } -static void P_ProcessExitSector(player_t *player, boolean isTouching, mtag_t sectag) +static void P_ProcessSpecialStagePit(player_t* player) +{ + if (!(gametyperules & GTR_ALLOWEXIT)) + return; + + if (player->bot) + return; + + if (!G_IsSpecialStage(gamemap)) + return; + + if (maptol & TOL_NIGHTS) + return; + + if (player->nightstime <= 6) + return; + + player->nightstime = 6; // Just let P_Ticker take care of the rest. +} + +static void P_ProcessExitSector(player_t *player, mtag_t sectag) { INT32 lineindex; @@ -4435,13 +4554,6 @@ static void P_ProcessExitSector(player_t *player, boolean isTouching, mtag_t sec if (player->bot) return; - if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap)) - { - if (player->nightstime > 6 && isTouching) - player->nightstime = 6; // Just let P_Ticker take care of the rest. - return; - } - // Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c) P_DoPlayerFinish(player); @@ -4515,7 +4627,7 @@ static void P_ProcessTeamBase(player_t *player, boolean redteam) P_AddPlayerScore(player, 250); } -static void P_ProcessZoomTube(player_t *player, sector_t *sector, mtag_t sectag, boolean end) +static void P_ProcessZoomTube(player_t *player, mtag_t sectag, boolean end) { INT32 sequence; fixed_t speed; @@ -4534,7 +4646,7 @@ static void P_ProcessZoomTube(player_t *player, sector_t *sector, mtag_t sectag, if (lineindex == -1) { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #3.\n", sector->special); + CONS_Debug(DBG_GAMELOGIC, "ERROR: Zoom tube missing line special #3.\n"); return; } @@ -4630,7 +4742,7 @@ static void P_ProcessFinishLine(player_t *player) } } -static void P_ProcessRopeHang(player_t *player, sector_t *sector, mtag_t sectag) +static void P_ProcessRopeHang(player_t *player, mtag_t sectag) { INT32 sequence; fixed_t speed; @@ -4668,7 +4780,7 @@ static void P_ProcessRopeHang(player_t *player, sector_t *sector, mtag_t sectag) if (lineindex == -1) { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #11.\n", sector->special); + CONS_Debug(DBG_GAMELOGIC, "ERROR: Rope hang missing line special #11.\n"); return; } @@ -4801,18 +4913,13 @@ static void P_ProcessRopeHang(player_t *player, sector_t *sector, mtag_t sectag) */ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector) { - INT32 section1, section2, section3, section4; + INT32 section1, section2; mtag_t sectag = Tag_FGet(§or->tags); boolean isTouching; - if (!sector->special) + if (!sector->special && sector->specialflags == 0) return; - section1 = GETSECSPECIAL(sector->special, 1); - section2 = GETSECSPECIAL(sector->special, 2); - section3 = GETSECSPECIAL(sector->special, 3); - section4 = GETSECSPECIAL(sector->special, 4); - // Ignore spectators if (player->spectator) return; @@ -4823,12 +4930,74 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (player->playerstate != PST_LIVE) return; - // Conveyor stuff - if (section3 == 2 || section3 == 4) - player->onconveyor = section3; - isTouching = roversector || P_IsMobjTouchingSectorPlane(player->mo, sector); + if (sector->specialflags & SSF_OUTERSPACE) + { + if (!(player->powers[pw_shield] & SH_PROTECTWATER) && !player->powers[pw_spacetime]) + player->powers[pw_spacetime] = spacetimetics + 1; + } + if (sector->specialflags & SSF_WINDCURRENT) + player->onconveyor = 2; + if (sector->specialflags & SSF_CONVEYOR) + player->onconveyor = 4; + if ((sector->specialflags & SSF_SPEEDPAD) && isTouching) + P_ProcessSpeedPad(player, sector, roversector, sectag); + if (sector->specialflags & SSF_STARPOSTACTIVATOR) + { + mobj_t *post = P_GetObjectTypeInSectorNum(MT_STARPOST, sector - sectors); + if (post) + P_TouchStarPost(post, player, false); + } + if (sector->specialflags & SSF_EXIT) + P_ProcessExitSector(player, sectag); + if ((sector->specialflags & SSF_SPECIALSTAGEPIT) && isTouching) + P_ProcessSpecialStagePit(player); + if ((sector->specialflags & SSF_REDTEAMBASE) && isTouching) + P_ProcessTeamBase(player, true); + if ((sector->specialflags & SSF_BLUETEAMBASE) && isTouching) + P_ProcessTeamBase(player, false); + if (sector->specialflags & SSF_FAN) + { + player->mo->momz += mobjinfo[MT_FAN].mass/4; + + if (player->mo->momz > mobjinfo[MT_FAN].mass) + player->mo->momz = mobjinfo[MT_FAN].mass; + + P_ResetPlayer(player); + if (player->panim != PA_FALL) + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + } + if (sector->specialflags & SSF_SUPERTRANSFORM) + { + if (player->mo->health > 0 && !player->bot && (player->charflags & SF_SUPER) && !player->powers[pw_super] && ALL7EMERALDS(emeralds)) + P_DoSuperTransformation(player, true); + } + if ((sector->specialflags & SSF_FORCESPIN) && isTouching) + { + if (!(player->pflags & PF_SPINNING)) + { + player->pflags |= PF_SPINNING; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartAttackSound(player->mo, sfx_spin); + + if (abs(player->rmomx) < FixedMul(5*FRACUNIT, player->mo->scale) + && abs(player->rmomy) < FixedMul(5*FRACUNIT, player->mo->scale)) + P_InstaThrust(player->mo, player->mo->angle, FixedMul(10*FRACUNIT, player->mo->scale)); + } + } + if (sector->specialflags & SSF_ZOOMTUBESTART) + P_ProcessZoomTube(player, sectag, false); + if (sector->specialflags & SSF_ZOOMTUBEEND) + P_ProcessZoomTube(player, sectag, true); + if (sector->specialflags & SSF_FINISHLINE) + P_ProcessFinishLine(player); + if ((sector->specialflags & SSF_ROPEHANG) && isTouching) + P_ProcessRopeHang(player, sectag); + + section1 = GETSECSPECIAL(sector->special, 1); + section2 = GETSECSPECIAL(sector->special, 2); + switch (section1) { case 1: // Damage (Generic) @@ -4891,20 +5060,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_SpecialStageDamage(player, NULL, NULL); break; - case 12: // Space Countdown - if (!(player->powers[pw_shield] & SH_PROTECTWATER) && !player->powers[pw_spacetime]) - player->powers[pw_spacetime] = spacetimetics + 1; - break; - case 13: // Ramp Sector (Increase step-up/down) - case 14: // Non-Ramp Sector (Don't step-down) - case 15: // Bouncy FOF (deprecated) - break; } switch (section2) { - case 1: // Trigger Linedef Exec (Pushable Objects) - break; case 2: // Linedef executor requires all players present+doesn't require touching floor case 3: // Linedef executor requires all players present if (!P_DoAllPlayersTrigger(sectag)) @@ -4919,111 +5078,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (!player->bot) P_LinedefExecute(sectag, player->mo, sector); break; - case 8: // Tells pushable things to check FOFs - break; case 9: // Egg trap capsule if (!udmf && roversector) P_ProcessEggCapsule(player, sector); break; - case 10: // Special Stage Time/Rings - case 11: // Custom Gravity - case 12: // Lua sector special - break; - } - - switch (section3) - { - case 1: // Unused - case 2: // Wind/Current - case 3: // Unused - case 4: // Conveyor Belt - break; - case 5: // Speed pad - if (isTouching) - P_ProcessSpeedPad(player, sector, roversector, sectag); - break; - case 6: // Unused - case 7: // Unused - case 8: // Unused - case 9: // Unused - case 10: // Unused - case 11: // Unused - case 12: // Unused - case 13: // Unused - case 14: // Unused - case 15: // Unused - break; - } - - switch (section4) - { - case 1: // Starpost Activator - { - mobj_t *post = P_GetObjectTypeInSectorNum(MT_STARPOST, sector - sectors); - - if (!post) - break; - - P_TouchStarPost(post, player, false); - break; - } - case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return - P_ProcessExitSector(player, isTouching, sectag); - break; - case 3: // Red Team's Base - if (isTouching) - P_ProcessTeamBase(player, true); - break; - case 4: // Blue Team's Base - if (isTouching) - P_ProcessTeamBase(player, false); - break; - case 5: // Fan sector - player->mo->momz += mobjinfo[MT_FAN].mass/4; - - if (player->mo->momz > mobjinfo[MT_FAN].mass) - player->mo->momz = mobjinfo[MT_FAN].mass; - - P_ResetPlayer(player); - if (player->panim != PA_FALL) - P_SetPlayerMobjState(player->mo, S_PLAY_FALL); - break; - case 6: // Super Sonic transformer - if (player->mo->health > 0 && !player->bot && (player->charflags & SF_SUPER) && !player->powers[pw_super] && ALL7EMERALDS(emeralds)) - P_DoSuperTransformation(player, true); - break; - case 7: // Make player spin - if (!isTouching) - break; - if (!(player->pflags & PF_SPINNING)) - { - player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartAttackSound(player->mo, sfx_spin); - - if (abs(player->rmomx) < FixedMul(5*FRACUNIT, player->mo->scale) - && abs(player->rmomy) < FixedMul(5*FRACUNIT, player->mo->scale)) - P_InstaThrust(player->mo, player->mo->angle, FixedMul(10*FRACUNIT, player->mo->scale)); - } - break; - case 8: // Zoom Tube Start - P_ProcessZoomTube(player, sector, sectag, false); - break; - case 9: // Zoom Tube End - P_ProcessZoomTube(player, sector, sectag, true); - break; - case 10: // Finish Line - P_ProcessFinishLine(player); - break; - case 11: // Rope hang - if (isTouching) - P_ProcessRopeHang(player, sector, sectag); - break; - case 12: // Unused - case 13: // Unused - case 14: // Unused - case 15: // Unused - break; } } @@ -5042,7 +5100,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) for (rover = sector->ffloors; rover; rover = rover->next) { - if (!rover->master->frontsector->special) + if (!rover->master->frontsector->special && rover->master->frontsector->specialflags == 0) continue; if (!(rover->flags & FF_EXISTS)) @@ -5076,7 +5134,7 @@ static void P_PlayerOnSpecialPolyobj(player_t *player) polysec = po->lines[0]->backsector; - if (!polysec->special) + if (!polysec->special && polysec->specialflags == 0) continue; touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); @@ -6025,6 +6083,12 @@ void P_SpawnSpecials(boolean fromnetsave) { CheckForReverseGravity |= (sector->flags & MSF_GRAVITYFLIP); + if (sector->specialflags & SSF_FINISHLINE) + { + if ((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE) + circuitmap = true; + } + if (!sector->special) continue; @@ -6063,15 +6127,6 @@ void P_SpawnSpecials(boolean fromnetsave) gravity = sector->floorheight/1000; break; } - - // Process Section 4 - switch(GETSECSPECIAL(sector->special, 4)) - { - case 10: // Circuit finish line - if ((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE) - circuitmap = true; - break; - } } P_SpawnScrollers(); // Add generalized scrollers @@ -8332,17 +8387,17 @@ void T_Pusher(pusher_t *p) sec = sectors + p->affectee; - // Be sure the special sector type is still turned on. If so, proceed. - // Else, bail out; the sector type has been changed on us. + // Be sure the sector special flag is still turned on. If so, proceed. + // Else, bail out; the flag has been changed on us. if (p->roverpusher) { referrer = §ors[p->referrer]; - if (GETSECSPECIAL(referrer->special, 3) != 2) + if (!(referrer->specialflags & SSF_WINDCURRENT)) return; } - else if (GETSECSPECIAL(sec->special, 3) != 2) + else if (!(sec->specialflags & SSF_WINDCURRENT)) return; // For constant pushers (wind/current) there are 3 situations: diff --git a/src/p_spec.h b/src/p_spec.h index c1f25b3d6..19d3bd103 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -480,7 +480,9 @@ void P_SpawnSpecials(boolean fromnetsave); // every tic void P_UpdateSpecials(void); sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number); +sector_t *P_MobjTouchingSectorSpecialFlag(mobj_t *mo, sectorspecialflags_t flag); sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number); +sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags_t flag); void P_PlayerInSpecialSector(player_t *player); void P_CheckPushableTrigger(mobj_t *mobj, sector_t *sec); void P_CheckMobjTrigger(mobj_t *mobj); diff --git a/src/p_user.c b/src/p_user.c index 45c64500f..1006e21ed 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2166,13 +2166,12 @@ void P_DoPlayerExit(player_t *player) P_RestoreMusic(player); } -#define SPACESPECIAL 12 boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space { sector_t *sector = mo->subsector->sector; fixed_t topheight, bottomheight; - if (GETSECSPECIAL(sector->special, 1) == SPACESPECIAL) + if (sector->specialflags & SSF_OUTERSPACE) return true; if (sector->ffloors) @@ -2184,7 +2183,7 @@ boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space if (!(rover->flags & FF_EXISTS)) continue; - if (GETSECSPECIAL(rover->master->frontsector->special, 1) != SPACESPECIAL) + if (!(rover->master->frontsector->specialflags & SSF_OUTERSPACE)) continue; topheight = P_GetFFloorTopZAt (rover, mo->x, mo->y); bottomheight = P_GetFFloorBottomZAt(rover, mo->x, mo->y); @@ -4678,7 +4677,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (onground && player->pflags & PF_SPINNING && !(player->pflags & PF_STARTDASH) && player->speed < 5*player->mo->scale && canstand) { - if (GETSECSPECIAL(player->mo->subsector->sector->special, 4) == 7 || (player->mo->ceilingz - player->mo->floorz < P_GetPlayerHeight(player))) + if ((player->mo->subsector->sector->specialflags & SSF_FORCESPIN) || (player->mo->ceilingz - player->mo->floorz < P_GetPlayerHeight(player))) P_InstaThrust(player->mo, player->mo->angle, 10*player->mo->scale); else { diff --git a/src/r_defs.h b/src/r_defs.h index 833958ab1..2b1cbfa58 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -289,6 +289,28 @@ typedef enum MSF_NOCLIPCAMERA = 1<<7, } sectorflags_t; +typedef enum +{ + SSF_OUTERSPACE = 1, + SSF_DOUBLESTEPUP = 1<<1, + SSF_NOSTEPDOWN = 1<<2, + SSF_WINDCURRENT = 1<<3, + SSF_CONVEYOR = 1<<4, + SSF_SPEEDPAD = 1<<5, + SSF_STARPOSTACTIVATOR = 1<<6, + SSF_EXIT = 1<<7, + SSF_SPECIALSTAGEPIT = 1<<8, + SSF_RETURNFLAG = 1<<9, + SSF_REDTEAMBASE = 1<<10, + SSF_BLUETEAMBASE = 1<<11, + SSF_FAN = 1<<12, + SSF_SUPERTRANSFORM = 1<<13, + SSF_FORCESPIN = 1<<14, + SSF_ZOOMTUBESTART = 1<<15, + SSF_ZOOMTUBEEND = 1<<16, + SSF_FINISHLINE = 1<<17, + SSF_ROPEHANG = 1<<18, +} sectorspecialflags_t; typedef enum { @@ -371,6 +393,7 @@ typedef struct sector_s fixed_t gravity; // per-sector gravity factor fixed_t *gravityptr; // For binary format: Read gravity from floor height of master sector sectorflags_t flags; + sectorspecialflags_t specialflags; INT32 friction; From 417809f78e3b32e2d109bdb9a4582dcf2ee084fe Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 00:05:47 +0100 Subject: [PATCH 268/326] Fix typo in P_MobjTouchingSectorSpecial --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index a1eb4183c..13facd78e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4052,7 +4052,7 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number) if (!(node->m_sector->flags & SF_TRIGGERSPECIAL_TOUCH)) continue; - if (GETSECSPECIAL(mo->subsector->sector->special, section) == number) + if (GETSECSPECIAL(node->m_sector->special, section) == number) return node->m_sector; } From b3be8d1f44bb09bff9d3a36235511393b2ab4f47 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 08:53:00 +0100 Subject: [PATCH 269/326] Implement sector damagetype field --- extras/conf/udb/Includes/SRB222_common.cfg | 3 ++ src/deh_lua.c | 26 +++++++--- src/deh_tables.c | 32 +++++++++--- src/deh_tables.h | 7 +-- src/lua_maplib.c | 8 +++ src/p_map.c | 2 +- src/p_mobj.c | 14 ++--- src/p_saveg.c | 33 +++++++++--- src/p_setup.c | 53 ++++++++++++++++++- src/p_spec.c | 60 ++++++++++++---------- src/p_user.c | 4 +- src/r_defs.h | 15 ++++++ 12 files changed, 194 insertions(+), 63 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg index d5cf5a405..d15fbcdcb 100644 --- a/extras/conf/udb/Includes/SRB222_common.cfg +++ b/extras/conf/udb/Includes/SRB222_common.cfg @@ -258,6 +258,9 @@ mapformat_udmf include("SRB222_sectors.cfg", "gen_sectortypes"); } + damagetypes = "Generic Water Fire Electric Spike DeathPitTilt DeathPitNoTilt Instakill SpecialStage"; + + // LINEDEF FLAGS linedefflags { diff --git a/src/deh_lua.c b/src/deh_lua.c index 56d2ec1e9..e313c5888 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -330,18 +330,18 @@ static inline int lib_getenum(lua_State *L) } else if (fastncmp("ML_", word, 3)) { p = word+3; - for (i = 0; i < 16; i++) - if (ML_LIST[i] && fastcmp(p, ML_LIST[i])) { + for (i = 0; ML_LIST[i]; i++) + if (fastcmp(p, ML_LIST[i])) { lua_pushinteger(L, ((lua_Integer)1<specialflags); return 1; + case sector_damagetype: // damagetype + lua_pushinteger(L, (UINT8)sector->damagetype); + return 1; case sector_friction: // friction lua_pushinteger(L, sector->friction); return 1; @@ -763,6 +768,9 @@ static int sector_set(lua_State *L) case sector_specialflags: sector->specialflags = luaL_checkinteger(L, 3); break; + case sector_damagetype: + sector->damagetype = (UINT8)luaL_checkinteger(L, 3); + break; case sector_gravity: sector->gravity = luaL_checkfixed(L, 3); break; diff --git a/src/p_map.c b/src/p_map.c index beae1a8ea..c3271c10e 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3594,7 +3594,7 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec) if (!(rover->flags & FF_SWIMMABLE)) continue; - if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 3) + if (rover->master->frontsector->damagetype != SD_FIRE) continue; if (rover->master->flags & ML_BLOCKMONSTERS) diff --git a/src/p_mobj.c b/src/p_mobj.c index 4b31307ef..004575a79 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2325,8 +2325,8 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) && ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_FLOOR)) || (mo->z + mo->height >= mo->subsector->sector->ceilingheight && ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_CEILING))) - && (GETSECSPECIAL(mo->subsector->sector->special, 1) == 6 - || GETSECSPECIAL(mo->subsector->sector->special, 1) == 7)) + && (mo->subsector->sector->damagetype == SD_DEATHPITTILT + || mo->subsector->sector->damagetype == SD_DEATHPITNOTILT)) return true; return false; @@ -2334,7 +2334,7 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) boolean P_CheckSolidLava(ffloor_t *rover) { - if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 + if (rover->flags & FF_SWIMMABLE && rover->master->frontsector->damagetype == SD_FIRE && !(rover->master->flags & ML_BLOCKMONSTERS)) return true; @@ -3305,7 +3305,7 @@ void P_MobjCheckWater(mobj_t *mobj) if (mobj->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) { - if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 3) + if (rover->master->frontsector->damagetype == SD_FIRE) mobj->eflags |= MFE_TOUCHLAVA; if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY)) @@ -4097,7 +4097,7 @@ static void P_KillRingsInLava(mobj_t *mo) if (!(rover->flags & FF_EXISTS)) continue; // fof must be real if (!(rover->flags & FF_SWIMMABLE // fof must be water - && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3)) // fof must be lava water + && rover->master->frontsector->damagetype == SD_FIRE)) // fof must be lava water continue; // find heights of FOF @@ -10985,8 +10985,8 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype if (mobj->floorz != starting_floorz) mobj->precipflags |= PCF_FOF; - else if (GETSECSPECIAL(mobj->subsector->sector->special, 1) == 7 - || GETSECSPECIAL(mobj->subsector->sector->special, 1) == 6 + else if (mobj->subsector->sector->damagetype == SD_DEATHPITNOTILT + || mobj->subsector->sector->damagetype == SD_DEATHPITTILT || mobj->subsector->sector->floorpic == skyflatnum) mobj->precipflags |= PCF_PIT; diff --git a/src/p_saveg.c b/src/p_saveg.c index 1923fa576..1baa34582 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -854,7 +854,11 @@ static void P_NetUnArchiveWaypoints(void) #define SD_CEILLIGHT 0x10 #define SD_FLAG 0x20 #define SD_SPECIALFLAG 0x40 -#define SD_GRAVITY 0x80 +#define SD_DIFF4 0x80 + +//diff4 flags +#define SD_DAMAGETYPE 0x01 +#define SD_GRAVITY 0x02 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -993,11 +997,11 @@ static void ArchiveSectors(void) size_t i, j; const sector_t *ss = sectors; const sector_t *spawnss = spawnsectors; - UINT8 diff, diff2, diff3; + UINT8 diff, diff2, diff3, diff4; for (i = 0; i < numsectors; i++, ss++, spawnss++) { - diff = diff2 = diff3 = 0; + diff = diff2 = diff3 = diff4 = 0; if (ss->floorheight != spawnss->floorheight) diff |= SD_FLOORHT; if (ss->ceilingheight != spawnss->ceilingheight) @@ -1044,12 +1048,17 @@ static void ArchiveSectors(void) diff3 |= SD_FLAG; if (ss->specialflags != spawnss->specialflags) diff3 |= SD_SPECIALFLAG; + if (ss->damagetype != spawnss->damagetype) + diff4 |= SD_DAMAGETYPE; if (ss->gravity != spawnss->gravity) - diff3 |= SD_GRAVITY; + diff4 |= SD_GRAVITY; if (ss->ffloors && CheckFFloorDiff(ss)) diff |= SD_FFLOORS; + if (diff4) + diff3 |= SD_DIFF4; + if (diff3) diff2 |= SD_DIFF3; @@ -1064,6 +1073,8 @@ static void ArchiveSectors(void) WRITEUINT8(save_p, diff2); if (diff2 & SD_DIFF3) WRITEUINT8(save_p, diff3); + if (diff3 & SD_DIFF4) + WRITEUINT8(save_p, diff4); if (diff & SD_FLOORHT) WRITEFIXED(save_p, ss->floorheight); if (diff & SD_CEILHT) @@ -1114,7 +1125,9 @@ static void ArchiveSectors(void) WRITEUINT32(save_p, ss->flags); if (diff3 & SD_SPECIALFLAG) WRITEUINT32(save_p, ss->specialflags); - if (diff3 & SD_GRAVITY) + if (diff4 & SD_DAMAGETYPE) + WRITEUINT8(save_p, ss->damagetype); + if (diff4 & SD_GRAVITY) WRITEFIXED(save_p, ss->gravity); if (diff & SD_FFLOORS) ArchiveFFloors(ss); @@ -1127,7 +1140,7 @@ static void ArchiveSectors(void) static void UnArchiveSectors(void) { UINT16 i, j; - UINT8 diff, diff2, diff3; + UINT8 diff, diff2, diff3, diff4; for (;;) { i = READUINT16(save_p); @@ -1147,6 +1160,10 @@ static void UnArchiveSectors(void) diff3 = READUINT8(save_p); else diff3 = 0; + if (diff3 & SD_DIFF4) + diff4 = READUINT8(save_p); + else + diff4 = 0; if (diff & SD_FLOORHT) sectors[i].floorheight = READFIXED(save_p); @@ -1224,7 +1241,9 @@ static void UnArchiveSectors(void) } if (diff3 & SD_SPECIALFLAG) sectors[i].specialflags = READUINT32(save_p); - if (diff3 & SD_GRAVITY) + if (diff4 & SD_DAMAGETYPE) + sectors[i].damagetype = READUINT8(save_p); + if (diff4 & SD_GRAVITY) sectors[i].gravity = READFIXED(save_p); if (diff & SD_FFLOORS) diff --git a/src/p_setup.c b/src/p_setup.c index 17fd5bb63..4efbc4e4b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1049,6 +1049,8 @@ static void P_LoadSectors(UINT8 *data) ss->gravity = FRACUNIT; ss->flags = MSF_FLIPSPECIAL_FLOOR; + ss->specialflags = 0; + ss->damagetype = SD_NONE; P_InitializeSector(ss); } @@ -1721,6 +1723,27 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].friction = atol(val); else if (fastcmp(param, "gravity")) sectors[i].gravity = FLOAT_TO_FIXED(atof(val)); + else if (fastcmp(param, "damagetype")) + { + if (fastcmp(val, "Generic")) + sectors[i].damagetype = SD_GENERIC; + if (fastcmp(val, "Water")) + sectors[i].damagetype = SD_WATER; + if (fastcmp(val, "Fire")) + sectors[i].damagetype = SD_FIRE; + if (fastcmp(val, "Electric")) + sectors[i].damagetype = SD_ELECTRIC; + if (fastcmp(val, "Spike")) + sectors[i].damagetype = SD_SPIKE; + if (fastcmp(val, "DeathPitTilt")) + sectors[i].damagetype = SD_DEATHPITTILT; + if (fastcmp(val, "DeathPitNoTilt")) + sectors[i].damagetype = SD_DEATHPITNOTILT; + if (fastcmp(val, "Instakill")) + sectors[i].damagetype = SD_INSTAKILL; + if (fastcmp(val, "SpecialStage")) + sectors[i].damagetype = SD_SPECIALSTAGE; + } } static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val) @@ -2000,6 +2023,8 @@ static void P_LoadTextmap(void) sc->gravity = FRACUNIT; sc->flags = MSF_FLIPSPECIAL_FLOOR; + sc->specialflags = 0; + sc->damagetype = SD_NONE; textmap_colormap.used = false; textmap_colormap.lightcolor = 0; @@ -5059,9 +5084,35 @@ static void P_ConvertBinaryMap(void) for (i = 0; i < numsectors; i++) { - switch(GETSECSPECIAL(sectors[i].special, 1)) { + case 1: //Damage + sectors[i].damagetype = SD_GENERIC; + break; + case 2: //Damage (Water) + sectors[i].damagetype = SD_WATER; + break; + case 3: //Damage (Fire) + sectors[i].damagetype = SD_FIRE; + break; + case 4: //Damage (Electric) + sectors[i].damagetype = SD_ELECTRIC; + break; + case 5: //Spikes + sectors[i].damagetype = SD_SPIKE; + break; + case 6: //Death pit (camera tilt) + sectors[i].damagetype = SD_DEATHPITTILT; + break; + case 7: //Death pit (no camera tilt) + sectors[i].damagetype = SD_DEATHPITNOTILT; + break; + case 8: //Instakill + sectors[i].damagetype = SD_INSTAKILL; + break; + case 11: //Special stage damage + sectors[i].damagetype = SD_SPECIALSTAGE; + break; case 12: //Space countdown sectors[i].specialflags |= SSF_OUTERSPACE; break; diff --git a/src/p_spec.c b/src/p_spec.c index 2e4821972..95c3a5118 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4917,7 +4917,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers mtag_t sectag = Tag_FGet(§or->tags); boolean isTouching; - if (!sector->special && sector->specialflags == 0) + if (!sector->special && sector->specialflags == 0 && sector->damagetype == SD_NONE) return; // Ignore spectators @@ -4995,33 +4995,30 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if ((sector->specialflags & SSF_ROPEHANG) && isTouching) P_ProcessRopeHang(player, sectag); - section1 = GETSECSPECIAL(sector->special, 1); - section2 = GETSECSPECIAL(sector->special, 2); - - switch (section1) + switch (sector->damagetype) { - case 1: // Damage (Generic) + case SD_GENERIC: if (isTouching) P_DamageMobj(player->mo, NULL, NULL, 1, 0); break; - case 2: // Damage (Water) + case SD_WATER: if (isTouching && (player->powers[pw_underwater] || player->powers[pw_carry] == CR_NIGHTSMODE)) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_WATER); break; - case 3: // Damage (Fire) + case SD_FIRE: if (isTouching) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_FIRE); break; - case 4: // Damage (Electrical) + case SD_ELECTRIC: if (isTouching) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_ELECTRIC); break; - case 5: // Spikes + case SD_SPIKE: if (isTouching) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPIKE); break; - case 6: // Death Pit (Camera Mod) - case 7: // Death Pit (No Camera Mod) + case SD_DEATHPITTILT: + case SD_DEATHPITNOTILT: if (!isTouching) break; if (player->quittime) @@ -5029,12 +5026,33 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers else P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT); break; - case 8: // Instant Kill + case SD_INSTAKILL: if (player->quittime) G_MovePlayerToSpawnOrStarpost(player - players); else P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); break; + case SD_SPECIALSTAGE: + if (!isTouching) + break; + + if (player->exiting || player->bot) // Don't do anything for bots or players who have just finished + break; + + if (!(player->powers[pw_shield] || player->spheres > 0)) // Don't do anything if no shield or spheres anyway + break; + + P_SpecialStageDamage(player, NULL, NULL); + break; + default: + break; + } + + section1 = GETSECSPECIAL(sector->special, 1); + section2 = GETSECSPECIAL(sector->special, 2); + + switch (section1) + { case 9: // Ring Drainer (Floor Touch) if (!isTouching) break; @@ -5048,18 +5066,6 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers S_StartSound(player->mo, sfx_antiri); } break; - case 11: // Special Stage Damage - if (!isTouching) - break; - - if (player->exiting || player->bot) // Don't do anything for bots or players who have just finished - break; - - if (!(player->powers[pw_shield] || player->spheres > 0)) // Don't do anything if no shield or spheres anyway - break; - - P_SpecialStageDamage(player, NULL, NULL); - break; } switch (section2) @@ -5100,7 +5106,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) for (rover = sector->ffloors; rover; rover = rover->next) { - if (!rover->master->frontsector->special && rover->master->frontsector->specialflags == 0) + if (!rover->master->frontsector->special && rover->master->frontsector->specialflags == 0 && rover->master->frontsector->damagetype == SD_NONE) continue; if (!(rover->flags & FF_EXISTS)) @@ -5134,7 +5140,7 @@ static void P_PlayerOnSpecialPolyobj(player_t *player) polysec = po->lines[0]->backsector; - if (!polysec->special && polysec->specialflags == 0) + if (!polysec->special && polysec->specialflags == 0 && polysec->damagetype == SD_NONE) continue; touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); diff --git a/src/p_user.c b/src/p_user.c index 1006e21ed..7360d2ef9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10258,7 +10258,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall thiscam->momx = FixedMul(x - thiscam->x, camspeed); thiscam->momy = FixedMul(y - thiscam->y, camspeed); - if (GETSECSPECIAL(thiscam->subsector->sector->special, 1) == 6 + if (thiscam->subsector->sector->damagetype == SD_DEATHPITTILT && thiscam->z < thiscam->subsector->sector->floorheight + 256*FRACUNIT && FixedMul(z - thiscam->z, camspeed) < 0) { @@ -12230,7 +12230,7 @@ static boolean P_MobjAboveLava(mobj_t *mobj) for (rover = sector->ffloors; rover; rover = rover->next) { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || GETSECSPECIAL(rover->master->frontsector->special, 1) != 3) + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->master->frontsector->damagetype != SD_FIRE) continue; if (mobj->eflags & MFE_VERTICALFLIP) diff --git a/src/r_defs.h b/src/r_defs.h index 2b1cbfa58..4180af800 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -312,6 +312,20 @@ typedef enum SSF_ROPEHANG = 1<<18, } sectorspecialflags_t; +typedef enum +{ + SD_NONE = 0, + SD_GENERIC = 1, + SD_WATER = 2, + SD_FIRE = 3, + SD_ELECTRIC = 4, + SD_SPIKE = 5, + SD_DEATHPITTILT = 6, + SD_DEATHPITNOTILT = 7, + SD_INSTAKILL = 8, + SD_SPECIALSTAGE = 9, +} sectordamage_t; + typedef enum { CRUMBLE_NONE, // No crumble thinker @@ -394,6 +408,7 @@ typedef struct sector_s fixed_t *gravityptr; // For binary format: Read gravity from floor height of master sector sectorflags_t flags; sectorspecialflags_t specialflags; + UINT8 damagetype; INT32 friction; From 208395214a4e75852f5dcc53baafc4d64fdc81b0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 11:39:34 +0100 Subject: [PATCH 270/326] Implement sector fields for linedef executor triggering --- extras/conf/udb/Includes/SRB222_misc.cfg | 20 ++ src/deh_lua.c | 10 + src/deh_tables.c | 10 + src/deh_tables.h | 1 + src/lua_maplib.c | 16 ++ src/p_floor.c | 5 +- src/p_mobj.c | 6 +- src/p_saveg.c | 16 +- src/p_setup.c | 58 ++++++ src/p_spec.c | 240 ++++++++++++++--------- src/p_spec.h | 3 +- src/r_defs.h | 25 ++- 12 files changed, 299 insertions(+), 111 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index d6210e9f1..537214b58 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -78,6 +78,8 @@ sectorflags flipspecial_ceiling = "Trigger on Ceiling Touch"; triggerspecial_touch = "Trigger on Edge Touch"; triggerspecial_headbump = "Trigger on Headbump"; + triggerline_plane = "Linedef Trigger Requires Plane Touch"; + triggerline_mobj = "Non-Pushables Can Trigger Linedef"; invertprecip = "Invert Precipitation"; gravityflip = "Flip Objects in Reverse Gravity"; heatwave = "Heat Wave"; @@ -253,6 +255,24 @@ universalfields type = 0; default = 0; } + + triggertag + { + type = 15; + default = 0; + } + + triggerer + { + type = 0; + default = 0; + enum + { + 0 = "Player"; + 1 = "All players"; + 2 = "Object"; + } + } } linedef diff --git a/src/deh_lua.c b/src/deh_lua.c index e313c5888..9472c1e7b 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -373,6 +373,16 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "sector damagetype '%s' could not be found.\n", word); return 0; } + else if (fastncmp("TO_", word, 3)) { + p = word + 3; + for (i = 0; TO_LIST[i]; i++) + if (fastcmp(p, TO_LIST[i])) { + lua_pushinteger(L, i); + return 1; + } + if (mathlib) return luaL_error(L, "sector triggerer '%s' could not be found.\n", word); + return 0; + } else if (fastncmp("S_",word,2)) { p = word+2; for (i = 0; i < NUMSTATEFREESLOTS; i++) { diff --git a/src/deh_tables.c b/src/deh_tables.c index 1409fae58..bc3368e06 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4478,6 +4478,8 @@ const char *const MSF_LIST[] = { "FLIPSPECIAL_CEILING", "TRIGGERSPECIAL_TOUCH", "TRIGGERSPECIAL_HEADBUMP", + "TRIGGERLINE_PLANE", + "TRIGGERLINE_MOBJ", "GRAVITYFLIP", "HEATWAVE", "NOCLIPCAMERA", @@ -4522,6 +4524,14 @@ const char *const SD_LIST[] = { NULL }; +// Sector triggerer +const char *const TO_LIST[] = { + "PLAYER", + "ALLPLAYERS", + "MOBJ", + NULL +}; + const char *COLOR_ENUMS[] = { "NONE", // SKINCOLOR_NONE, diff --git a/src/deh_tables.h b/src/deh_tables.h index 3fbc6357b..dccf98252 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -68,6 +68,7 @@ extern const char *const ML_LIST[]; // Linedef flags extern const char *const MSF_LIST[]; // Sector flags extern const char *const SSF_LIST[]; // Sector special flags extern const char *const SD_LIST[]; // Sector damagetype +extern const char *const TO_LIST[]; // Sector triggerer extern const char *COLOR_ENUMS[]; extern const char *const POWERS_LIST[]; extern const char *const HUDITEMS_LIST[]; diff --git a/src/lua_maplib.c b/src/lua_maplib.c index b18f4a44f..4bbd826ef 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -52,6 +52,8 @@ enum sector_e { sector_flags, sector_specialflags, sector_damagetype, + sector_triggertag, + sector_triggerer, sector_friction, sector_gravity, }; @@ -80,6 +82,8 @@ static const char *const sector_opt[] = { "flags", "specialflags", "damagetype", + "triggertag", + "triggerer", "friction", "gravity", NULL}; @@ -668,6 +672,12 @@ static int sector_get(lua_State *L) case sector_damagetype: // damagetype lua_pushinteger(L, (UINT8)sector->damagetype); return 1; + case sector_triggertag: // triggertag + lua_pushinteger(L, (INT16)sector->triggertag); + return 1; + case sector_triggerer: // triggerer + lua_pushinteger(L, (UINT8)sector->triggerer); + return 1; case sector_friction: // friction lua_pushinteger(L, sector->friction); return 1; @@ -771,6 +781,12 @@ static int sector_set(lua_State *L) case sector_damagetype: sector->damagetype = (UINT8)luaL_checkinteger(L, 3); break; + case sector_triggertag: + sector->triggertag = (INT16)luaL_checkinteger(L, 3); + break; + case sector_triggerer: + sector->triggerer = (UINT8)luaL_checkinteger(L, 3); + break; case sector_gravity: sector->gravity = luaL_checkfixed(L, 3); break; diff --git a/src/p_floor.c b/src/p_floor.c index 85a1f54a8..5f71a1fbe 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1276,7 +1276,6 @@ void T_EachTimeThinker(eachtime_t *eachtime) sector_t *caller[MAXPLAYERS]; boolean allPlayersChecked = false; boolean allPlayersTrigger = false; - mtag_t tag = Tag_FGet(&eachtime->sourceline->tags); for (i = 0; i < MAXPLAYERS; i++) { @@ -1300,7 +1299,7 @@ void T_EachTimeThinker(eachtime_t *eachtime) continue; // If sector has an "all players" trigger type, all players need to be in area - if (caller[i] && (GETSECSPECIAL(caller[i]->special, 2) == 2 || GETSECSPECIAL(caller[i]->special, 2) == 3)) + if (caller[i] && caller[i]->triggerer == TO_ALLPLAYERS) { if (!allPlayersChecked) { @@ -1312,7 +1311,7 @@ void T_EachTimeThinker(eachtime_t *eachtime) continue; } - CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", tag); + CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", Tag_FGet(&eachtime->sourceline->tags)); // 03/08/14 -Monster Iestyn // No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever! diff --git a/src/p_mobj.c b/src/p_mobj.c index 004575a79..57ff8d4f1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10161,8 +10161,8 @@ void P_MobjThinker(mobj_t *mobj) tmfloorthing = tmhitthing = NULL; - // Sector special (2,8) allows ANY mobj to trigger a linedef exec - P_CheckMobjTrigger(mobj); + // Sector flag MSF_TRIGGERLINE_MOBJ allows ANY mobj to trigger a linedef exec + P_CheckMobjTrigger(mobj, false); if (mobj->scale != mobj->destscale) P_MobjScaleThink(mobj); // Slowly scale up/down to reach your destscale. @@ -10382,7 +10382,7 @@ void P_PushableThinker(mobj_t *mobj) I_Assert(mobj != NULL); I_Assert(!P_MobjWasRemoved(mobj)); - P_CheckPushableTrigger(mobj, mobj->subsector->sector); + P_CheckMobjTrigger(mobj, true); // it has to be pushable RIGHT NOW for this part to happen if (mobj->flags & MF_PUSHABLE && !(mobj->momx || mobj->momy)) diff --git a/src/p_saveg.c b/src/p_saveg.c index 1baa34582..50608ad7a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -858,7 +858,9 @@ static void P_NetUnArchiveWaypoints(void) //diff4 flags #define SD_DAMAGETYPE 0x01 -#define SD_GRAVITY 0x02 +#define SD_TRIGGERTAG 0x02 +#define SD_TRIGGERER 0x04 +#define SD_GRAVITY 0x08 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -1050,6 +1052,10 @@ static void ArchiveSectors(void) diff3 |= SD_SPECIALFLAG; if (ss->damagetype != spawnss->damagetype) diff4 |= SD_DAMAGETYPE; + if (ss->triggertag != spawnss->triggertag) + diff4 |= SD_TRIGGERTAG; + if (ss->triggerer != spawnss->triggerer) + diff4 |= SD_TRIGGERER; if (ss->gravity != spawnss->gravity) diff4 |= SD_GRAVITY; @@ -1127,6 +1133,10 @@ static void ArchiveSectors(void) WRITEUINT32(save_p, ss->specialflags); if (diff4 & SD_DAMAGETYPE) WRITEUINT8(save_p, ss->damagetype); + if (diff4 & SD_TRIGGERTAG) + WRITEINT16(save_p, ss->triggertag); + if (diff4 & SD_TRIGGERER) + WRITEUINT8(save_p, ss->triggerer); if (diff4 & SD_GRAVITY) WRITEFIXED(save_p, ss->gravity); if (diff & SD_FFLOORS) @@ -1243,6 +1253,10 @@ static void UnArchiveSectors(void) sectors[i].specialflags = READUINT32(save_p); if (diff4 & SD_DAMAGETYPE) sectors[i].damagetype = READUINT8(save_p); + if (diff4 & SD_TRIGGERTAG) + sectors[i].triggertag = READINT16(save_p); + if (diff4 & SD_TRIGGERER) + sectors[i].triggerer = READUINT8(save_p); if (diff4 & SD_GRAVITY) sectors[i].gravity = READFIXED(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index 4efbc4e4b..f64bd842c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1051,6 +1051,8 @@ static void P_LoadSectors(UINT8 *data) ss->flags = MSF_FLIPSPECIAL_FLOOR; ss->specialflags = 0; ss->damagetype = SD_NONE; + ss->triggertag = 0; + ss->triggerer = TO_PLAYER; P_InitializeSector(ss); } @@ -1673,6 +1675,10 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].flags |= MSF_TRIGGERSPECIAL_TOUCH; else if (fastcmp(param, "triggerspecial_headbump") && fastcmp("true", val)) sectors[i].flags |= MSF_TRIGGERSPECIAL_HEADBUMP; + else if (fastcmp(param, "triggerline_plane") && fastcmp("true", val)) + sectors[i].flags |= MSF_TRIGGERLINE_PLANE; + else if (fastcmp(param, "triggerline_mobj") && fastcmp("true", val)) + sectors[i].flags |= MSF_TRIGGERLINE_MOBJ; else if (fastcmp(param, "invertprecip") && fastcmp("true", val)) sectors[i].flags |= MSF_INVERTPRECIP; else if (fastcmp(param, "gravityflip") && fastcmp("true", val)) @@ -1744,6 +1750,10 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) if (fastcmp(val, "SpecialStage")) sectors[i].damagetype = SD_SPECIALSTAGE; } + else if (fastcmp(param, "triggertag")) + sectors[i].triggertag = atol(val); + else if (fastcmp(param, "triggerer")) + sectors[i].triggerer = atol(val); } static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val) @@ -2025,6 +2035,8 @@ static void P_LoadTextmap(void) sc->flags = MSF_FLIPSPECIAL_FLOOR; sc->specialflags = 0; sc->damagetype = SD_NONE; + sc->triggertag = 0; + sc->triggerer = TO_PLAYER; textmap_colormap.used = false; textmap_colormap.lightcolor = 0; @@ -5084,6 +5096,8 @@ static void P_ConvertBinaryMap(void) for (i = 0; i < numsectors; i++) { + mtag_t tag = Tag_FGet(§ors[i].tags); + switch(GETSECSPECIAL(sectors[i].special, 1)) { case 1: //Damage @@ -5126,6 +5140,50 @@ static void P_ConvertBinaryMap(void) break; } + switch(GETSECSPECIAL(sectors[i].special, 2)) + { + case 1: //Trigger linedef executor (pushable objects) + sectors[i].triggertag = tag; + sectors[i].flags |= MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_MOBJ; + break; + case 2: //Trigger linedef executor (Anywhere in sector, all players) + sectors[i].triggertag = tag; + sectors[i].flags &= ~MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_ALLPLAYERS; + break; + case 3: //Trigger linedef executor (Floor touch, all players) + sectors[i].triggertag = tag; + sectors[i].flags |= MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_ALLPLAYERS; + break; + case 4: //Trigger linedef executor (Anywhere in sector) + sectors[i].triggertag = tag; + sectors[i].flags &= ~MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_PLAYER; + break; + case 5: //Trigger linedef executor (Floor touch) + sectors[i].triggertag = tag; + sectors[i].flags |= MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_PLAYER; + break; + case 6: //Trigger linedef executor (Emerald check) + sectors[i].triggertag = tag; + sectors[i].flags &= ~MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_PLAYEREMERALDS; + break; + case 7: //Trigger linedef executor (NiGHTS mare) + sectors[i].triggertag = tag; + sectors[i].flags &= ~MSF_TRIGGERLINE_PLANE; + sectors[i].triggerer = TO_PLAYERNIGHTS; + break; + case 8: //Check for linedef executor on FOFs + sectors[i].flags |= MSF_TRIGGERLINE_MOBJ; + break; + default: + break; + } + switch(GETSECSPECIAL(sectors[i].special, 3)) { case 2: //Wind/Current diff --git a/src/p_spec.c b/src/p_spec.c index 95c3a5118..973c6ee3c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1755,15 +1755,15 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller // Trigger conditions // //////////////////////// - if (caller) + if (caller && !udmf) { - if (GETSECSPECIAL(caller->special, 2) == 6) + if (caller->triggerer == TO_PLAYEREMERALDS) { CONS_Alert(CONS_WARNING, M_GetText("Deprecated emerald check sector type detected. Please use linedef types 337-339 instead.\n")); if (!(ALL7EMERALDS(emeralds))) return false; } - else if (GETSECSPECIAL(caller->special, 2) == 7) + else if (caller->triggerer == TO_PLAYERNIGHTS) { CONS_Alert(CONS_WARNING, M_GetText("Deprecated NiGHTS mare sector type detected. Please use linedef types 340-342 instead.\n")); if (!P_CheckPlayerMareOld(triggerline)) @@ -4226,20 +4226,23 @@ sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags return P_MobjTouchingSectorSpecialFlag(player->mo, flag); } -static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line_t *sourceline) +static sector_t *P_CheckPlayer3DFloorTrigger(player_t *player, sector_t *sector, line_t *sourceline) { ffloor_t *rover; for (rover = sector->ffloors; rover; rover = rover->next) { - if (GETSECSPECIAL(rover->master->frontsector->special, 2) < 2 || GETSECSPECIAL(rover->master->frontsector->special, 2) > 7) + if (!rover->master->frontsector->triggertag) + continue; + + if (rover->master->frontsector->triggerer == TO_MOBJ) continue; if (!(rover->flags & FF_EXISTS)) continue; - if (!Tag_Find(&sourceline->tags, Tag_FGet(&rover->master->frontsector->tags))) - return false; + if (!Tag_Find(&sourceline->tags, rover->master->frontsector->triggertag)) + continue; if (!P_IsMobjTouching3DFloor(player->mo, rover, sector)) continue; @@ -4253,25 +4256,28 @@ static sector_t *P_Check3DFloorTriggers(player_t *player, sector_t *sector, line return NULL; } -static sector_t *P_CheckPolyobjTriggers(player_t *player, line_t *sourceline) +static sector_t *P_CheckPlayerPolyobjTrigger(player_t *player, line_t *sourceline) { polyobj_t *po; sector_t *polysec; boolean touching = false; boolean inside = false; - for (po = player->mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) //TODO + for (po = player->mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) { if (po->flags & POF_NOSPECIALS) continue; polysec = po->lines[0]->backsector; - if (GETSECSPECIAL(polysec->special, 2) < 2 || GETSECSPECIAL(polysec->special, 2) > 7) + if (!polysec->triggertag) continue; - if (!Tag_Find(&sourceline->tags, Tag_FGet(&polysec->tags))) - return false; + if (polysec->triggerer == TO_MOBJ) + continue; + + if (!Tag_Find(&sourceline->tags, polysec->triggertag)) + continue; touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); inside = P_MobjInsidePolyobj(po, player->mo); @@ -4288,16 +4294,19 @@ static sector_t *P_CheckPolyobjTriggers(player_t *player, line_t *sourceline) return NULL; } -static boolean P_CheckSectorTriggers(player_t *player, sector_t *sector, line_t *sourceline) +static boolean P_CheckPlayerSectorTrigger(player_t *player, sector_t *sector, line_t *sourceline) { - if (GETSECSPECIAL(sector->special, 2) < 2 || GETSECSPECIAL(sector->special, 2) > 7) + if (!sector->triggertag) return false; - if (!Tag_Find(&sourceline->tags, Tag_FGet(§or->tags))) + if (sector->triggerer == TO_MOBJ) return false; - if (GETSECSPECIAL(sector->special, 2) != 3 && GETSECSPECIAL(sector->special, 2) != 5) - return true; // "Anywhere in sector" types + if (!Tag_Find(&sourceline->tags, sector->triggertag)) + return false; + + if (!(sector->flags & MSF_TRIGGERLINE_PLANE)) + return true; // Don't require plane touch return P_IsMobjTouchingSectorPlane(player->mo, sector); @@ -4315,18 +4324,18 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) originalsector = player->mo->subsector->sector; - caller = P_Check3DFloorTriggers(player, originalsector, sourceline); // Handle FOFs first. + caller = P_CheckPlayer3DFloorTrigger(player, originalsector, sourceline); // Handle FOFs first. if (caller) return caller; // Allow sector specials to be applied to polyobjects! - caller = P_CheckPolyobjTriggers(player, sourceline); + caller = P_CheckPlayerPolyobjTrigger(player, sourceline); if (caller) return caller; - if (P_CheckSectorTriggers(player, originalsector, sourceline)) + if (P_CheckPlayerSectorTrigger(player, originalsector, sourceline)) return originalsector; // Iterate through touching_sectorlist for SF_TRIGGERSPECIAL_TOUCH @@ -4338,7 +4347,7 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) continue; // Check 3D floors... - caller = P_Check3DFloorTriggers(player, loopsector, sourceline); // Handle FOFs first. + caller = P_CheckPlayer3DFloorTrigger(player, loopsector, sourceline); // Handle FOFs first. if (caller) return caller; @@ -4346,7 +4355,7 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) if (!(loopsector->flags & MSF_TRIGGERSPECIAL_TOUCH)) continue; - if (P_CheckSectorTriggers(player, loopsector, sourceline)) + if (P_CheckPlayerSectorTrigger(player, loopsector, sourceline)) return loopsector; } @@ -4376,12 +4385,12 @@ boolean P_CanPlayerTrigger(size_t playernum) } /// \todo check continues for proper splitscreen support? -static boolean P_DoAllPlayersTrigger(mtag_t sectag) +static boolean P_DoAllPlayersTrigger(mtag_t triggertag) { INT32 i; line_t dummyline; dummyline.tags.count = 1; - dummyline.tags.tags = §ag; + dummyline.tags.tags = &triggertag; for (i = 0; i < MAXPLAYERS; i++) { @@ -4903,34 +4912,26 @@ static void P_ProcessRopeHang(player_t *player, mtag_t sectag) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); } -/** Applies a sector special to a player. - * - * \param player Player in the sector. - * \param sector Sector with the special. - * \param roversector If !NULL, sector is actually an FOF; otherwise, sector - * is being physically contacted by the player. - * \sa P_PlayerInSpecialSector, P_PlayerOnSpecial3DFloor - */ -void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector) +static boolean P_SectorHasSpecial(sector_t *sec) +{ + if (sec->specialflags) + return true; + + if (sec->damagetype != SD_NONE) + return true; + + if (sec->triggertag) + return true; + + if (sec->special) + return true; + + return false; +} + +static void P_EvaluateSpecialFlags(player_t *player, sector_t *sector, sector_t *roversector, boolean isTouching) { - INT32 section1, section2; mtag_t sectag = Tag_FGet(§or->tags); - boolean isTouching; - - if (!sector->special && sector->specialflags == 0 && sector->damagetype == SD_NONE) - return; - - // Ignore spectators - if (player->spectator) - return; - - // Ignore dead players. - // If this strange phenomenon could be potentially used in levels, - // TODO: modify this to accommodate for it. - if (player->playerstate != PST_LIVE) - return; - - isTouching = roversector || P_IsMobjTouchingSectorPlane(player->mo, sector); if (sector->specialflags & SSF_OUTERSPACE) { @@ -4994,7 +4995,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_ProcessFinishLine(player); if ((sector->specialflags & SSF_ROPEHANG) && isTouching) P_ProcessRopeHang(player, sectag); +} +static void P_EvaluateDamageType(player_t *player, sector_t *sector, boolean isTouching) +{ switch (sector->damagetype) { case SD_GENERIC: @@ -5047,19 +5051,36 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers default: break; } +} - section1 = GETSECSPECIAL(sector->special, 1); - section2 = GETSECSPECIAL(sector->special, 2); +static void P_EvaluateLinedefExecutorTrigger(player_t *player, sector_t *sector, boolean isTouching) +{ + if (player->bot) + return; - switch (section1) + if (!sector->triggertag) + return; + + if (sector->triggerer == TO_MOBJ) + return; + else if (sector->triggerer == TO_ALLPLAYERS && !P_DoAllPlayersTrigger(sector->triggertag)) + return; + + if ((sector->flags & MSF_TRIGGERLINE_PLANE) && !isTouching) + return; + + P_LinedefExecute(sector->triggertag, player->mo, sector); +} + +static void P_EvaluateOldSectorSpecial(player_t *player, sector_t *sector, sector_t *roversector, boolean isTouching) +{ + switch (GETSECSPECIAL(sector->special, 1)) { case 9: // Ring Drainer (Floor Touch) if (!isTouching) break; /* FALLTHRU */ case 10: // Ring Drainer (No Floor Touch) - if (udmf) - break; if (leveltime % (TICRATE/2) == 0 && player->rings > 0) { player->rings--; @@ -5068,29 +5089,50 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers break; } - switch (section2) + switch (GETSECSPECIAL(sector->special, 2)) { - case 2: // Linedef executor requires all players present+doesn't require touching floor - case 3: // Linedef executor requires all players present - if (!P_DoAllPlayersTrigger(sectag)) - break; - /* FALLTHRU */ - case 4: // Linedef executor that doesn't require touching floor - case 5: // Linedef executor - case 6: // Linedef executor (7 Emeralds) - case 7: // Linedef executor (NiGHTS Mare) - if ((section2 == 3 || section2 == 5) && !isTouching) - break; - if (!player->bot) - P_LinedefExecute(sectag, player->mo, sector); - break; case 9: // Egg trap capsule - if (!udmf && roversector) + if (roversector) P_ProcessEggCapsule(player, sector); break; } } +/** Applies a sector special to a player. + * + * \param player Player in the sector. + * \param sector Sector with the special. + * \param roversector If !NULL, sector is actually an FOF; otherwise, sector + * is being physically contacted by the player. + * \sa P_PlayerInSpecialSector, P_PlayerOnSpecial3DFloor + */ +void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector) +{ + boolean isTouching; + + if (!P_SectorHasSpecial(sector)) + return; + + // Ignore spectators + if (player->spectator) + return; + + // Ignore dead players. + // If this strange phenomenon could be potentially used in levels, + // TODO: modify this to accommodate for it. + if (player->playerstate != PST_LIVE) + return; + + isTouching = roversector || P_IsMobjTouchingSectorPlane(player->mo, sector); + + P_EvaluateSpecialFlags(player, sector, roversector, isTouching); + P_EvaluateDamageType(player, sector, isTouching); + P_EvaluateLinedefExecutorTrigger(player, sector, isTouching); + + if (!udmf) + P_EvaluateOldSectorSpecial(player, sector, roversector, isTouching); +} + #define TELEPORTED(mo) (mo->subsector->sector != originalsector) /** Checks if a player is standing on or is inside a 3D floor (e.g. water) and @@ -5106,7 +5148,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) for (rover = sector->ffloors; rover; rover = rover->next) { - if (!rover->master->frontsector->special && rover->master->frontsector->specialflags == 0 && rover->master->frontsector->damagetype == SD_NONE) + if (!P_SectorHasSpecial(rover->master->frontsector)) continue; if (!(rover->flags & FF_EXISTS)) @@ -5140,7 +5182,7 @@ static void P_PlayerOnSpecialPolyobj(player_t *player) polysec = po->lines[0]->backsector; - if (!polysec->special && polysec->specialflags == 0 && polysec->damagetype == SD_NONE) + if (!P_SectorHasSpecial(polysec)) continue; touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo); @@ -5203,25 +5245,26 @@ void P_PlayerInSpecialSector(player_t *player) } } -static void P_CheckMobj3DFloorTrigger(mobj_t *mo) +static void P_CheckMobj3DFloorTrigger(mobj_t *mo, sector_t *sec) { sector_t *originalsector = mo->subsector->sector; ffloor_t *rover; - mtag_t tag; - for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) + for (rover = sec->ffloors; rover; rover = rover->next) { - if (GETSECSPECIAL(rover->master->frontsector->special, 2) != 1) + if (!rover->master->frontsector->triggertag) + continue; + + if (rover->master->frontsector->triggerer != TO_MOBJ) continue; if (!(rover->flags & FF_EXISTS)) continue; - if (!P_IsMobjTouching3DFloor(mo, rover, mo->subsector->sector)) + if (!P_IsMobjTouching3DFloor(mo, rover, sec)) continue; - tag = Tag_FGet(&rover->master->frontsector->tags); - P_LinedefExecute(tag, mo, rover->master->frontsector); + P_LinedefExecute(rover->master->frontsector->triggertag, mo, rover->master->frontsector); if TELEPORTED(mo) return; } } @@ -5233,7 +5276,6 @@ static void P_CheckMobjPolyobjTrigger(mobj_t *mo) sector_t *polysec; boolean touching = false; boolean inside = false; - mtag_t tag; for (po = mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next)) { @@ -5242,7 +5284,10 @@ static void P_CheckMobjPolyobjTrigger(mobj_t *mo) polysec = po->lines[0]->backsector; - if (!polysec->special) + if (!polysec->triggertag) + continue; + + if (polysec->triggerer != TO_MOBJ) continue; touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo); @@ -5254,30 +5299,26 @@ static void P_CheckMobjPolyobjTrigger(mobj_t *mo) if (!P_IsMobjTouchingPolyobj(mo, po, polysec)) continue; - tag = Tag_FGet(&polysec->tags); - P_LinedefExecute(tag, mo, polysec); + P_LinedefExecute(polysec->triggertag, mo, polysec); if TELEPORTED(mo) return; } } -void P_CheckPushableTrigger(mobj_t *mobj, sector_t *sec) +static void P_CheckMobjSectorTrigger(mobj_t *mo, sector_t *sec) { - sector_t *originalsector = mobj->subsector->sector; + if (!sec->triggertag) + return; - P_CheckMobj3DFloorTrigger(mobj); - if TELEPORTED(mobj) return; + if (sec->triggerer != TO_MOBJ) + return; - P_CheckMobjPolyobjTrigger(mobj); - if TELEPORTED(mobj) return; + if ((sec->flags & MSF_TRIGGERLINE_PLANE) && !P_IsMobjTouchingSectorPlane(mo, sec)) + return; - if (GETSECSPECIAL(sec->special, 2) == 1 && P_IsMobjTouchingSectorPlane(mobj, sec)) - { - mtag_t tag = Tag_FGet(&sec->tags); - P_LinedefExecute(tag, mobj, sec); - } + P_LinedefExecute(sec->triggertag, mo, sec); } -void P_CheckMobjTrigger(mobj_t *mobj) +void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable) { sector_t *originalsector; @@ -5286,13 +5327,16 @@ void P_CheckMobjTrigger(mobj_t *mobj) originalsector = mobj->subsector->sector; - if (GETSECSPECIAL(originalsector->special, 2) != 8) + if (!pushable && !(originalsector->flags & MSF_TRIGGERLINE_MOBJ)) return; - P_CheckMobj3DFloorTrigger(mobj); + P_CheckMobj3DFloorTrigger(mobj, originalsector); if TELEPORTED(mobj) return; P_CheckMobjPolyobjTrigger(mobj); + if TELEPORTED(mobj) return; + + P_CheckMobjSectorTrigger(mobj, originalsector); } #undef TELEPORTED diff --git a/src/p_spec.h b/src/p_spec.h index 19d3bd103..d02b5989f 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -484,8 +484,7 @@ sector_t *P_MobjTouchingSectorSpecialFlag(mobj_t *mo, sectorspecialflags_t flag) sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number); sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags_t flag); void P_PlayerInSpecialSector(player_t *player); -void P_CheckPushableTrigger(mobj_t *mobj, sector_t *sec); -void P_CheckMobjTrigger(mobj_t *mobj); +void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable); sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline); boolean P_IsPlayerValid(size_t playernum); boolean P_CanPlayerTrigger(size_t playernum); diff --git a/src/r_defs.h b/src/r_defs.h index 4180af800..cd632aeca 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -282,11 +282,14 @@ typedef enum // triggerspecial - conditions under which plane touch causes effect MSF_TRIGGERSPECIAL_TOUCH = 1<<2, MSF_TRIGGERSPECIAL_HEADBUMP = 1<<3, + // triggerline - conditions for linedef executor triggering + MSF_TRIGGERLINE_PLANE = 1<<4, // require plane touch + MSF_TRIGGERLINE_MOBJ = 1<<5, // allow non-pushable mobjs to trigger // invertprecip - inverts presence of precipitation - MSF_INVERTPRECIP = 1<<4, - MSF_GRAVITYFLIP = 1<<5, - MSF_HEATWAVE = 1<<6, - MSF_NOCLIPCAMERA = 1<<7, + MSF_INVERTPRECIP = 1<<6, + MSF_GRAVITYFLIP = 1<<7, + MSF_HEATWAVE = 1<<8, + MSF_NOCLIPCAMERA = 1<<9, } sectorflags_t; typedef enum @@ -326,6 +329,15 @@ typedef enum SD_SPECIALSTAGE = 9, } sectordamage_t; +typedef enum +{ + TO_PLAYER = 0, + TO_ALLPLAYERS = 1, + TO_MOBJ = 2, + TO_PLAYEREMERALDS = 3, // only for binary backwards compatibility: check player emeralds + TO_PLAYERNIGHTS = 4, // only for binary backwards compatibility: check NiGHTS mare +} triggerobject_t; + typedef enum { CRUMBLE_NONE, // No crumble thinker @@ -406,10 +418,15 @@ typedef struct sector_s fixed_t gravity; // per-sector gravity factor fixed_t *gravityptr; // For binary format: Read gravity from floor height of master sector + sectorflags_t flags; sectorspecialflags_t specialflags; UINT8 damagetype; + // Linedef executor triggering + mtag_t triggertag; // tag to call upon triggering + UINT8 triggerer; // who can trigger? + INT32 friction; // Sprite culling feature From e011962156e56c08374392a7e806cfcd9d718dfc Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 11:44:05 +0100 Subject: [PATCH 271/326] Make the sector special field inaccessible in UDMF --- extras/conf/udb/Includes/SRB222_common.cfg | 13 ------------- src/p_setup.c | 2 -- 2 files changed, 15 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg index d15fbcdcb..b06b7bad7 100644 --- a/extras/conf/udb/Includes/SRB222_common.cfg +++ b/extras/conf/udb/Includes/SRB222_common.cfg @@ -246,21 +246,8 @@ mapformat_udmf include("SRB222_misc.cfg", "sectorbrightness"); } - // SECTOR TYPES - sectortypes - { - include("SRB222_sectors.cfg", "sectortypes"); - } - - // GENERALISED SECTOR TYPES - gen_sectortypes - { - include("SRB222_sectors.cfg", "gen_sectortypes"); - } - damagetypes = "Generic Water Fire Electric Spike DeathPitTilt DeathPitNoTilt Instakill SpecialStage"; - // LINEDEF FLAGS linedefflags { diff --git a/src/p_setup.c b/src/p_setup.c index f64bd842c..6fac64568 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1559,8 +1559,6 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].ceilinglightlevel = atol(val); else if (fastcmp(param, "lightceilingabsolute") && fastcmp("true", val)) sectors[i].ceilinglightabsolute = true; - else if (fastcmp(param, "special")) - sectors[i].special = atol(val); else if (fastcmp(param, "id")) Tag_FSet(§ors[i].tags, atol(val)); else if (fastcmp(param, "moreids")) From 2b4d32b37274d7caf4bcc3235205bf582757436f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 12:15:01 +0100 Subject: [PATCH 272/326] Turn solid lava into a damagetype --- extras/conf/udb/Includes/SRB222_common.cfg | 2 +- src/deh_tables.c | 1 + src/p_map.c | 5 +---- src/p_mobj.c | 16 ++++++-------- src/p_setup.c | 25 +++++++++++++++++++++- src/p_spec.c | 1 + src/p_user.c | 5 ++++- src/r_defs.h | 13 +++++------ 8 files changed, 46 insertions(+), 22 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg index b06b7bad7..0b35ec17c 100644 --- a/extras/conf/udb/Includes/SRB222_common.cfg +++ b/extras/conf/udb/Includes/SRB222_common.cfg @@ -246,7 +246,7 @@ mapformat_udmf include("SRB222_misc.cfg", "sectorbrightness"); } - damagetypes = "Generic Water Fire Electric Spike DeathPitTilt DeathPitNoTilt Instakill SpecialStage"; + damagetypes = "Generic Water Fire Lava Electric Spike DeathPitTilt DeathPitNoTilt Instakill SpecialStage"; // LINEDEF FLAGS linedefflags diff --git a/src/deh_tables.c b/src/deh_tables.c index bc3368e06..52718cc8b 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4515,6 +4515,7 @@ const char *const SD_LIST[] = { "GENERIC", "WATER", "FIRE", + "LAVA", "ELECTRIC", "SPIKE", "DEATHPITTILT", diff --git a/src/p_map.c b/src/p_map.c index c3271c10e..72775e5e6 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3594,10 +3594,7 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec) if (!(rover->flags & FF_SWIMMABLE)) continue; - if (rover->master->frontsector->damagetype != SD_FIRE) - continue; - - if (rover->master->flags & ML_BLOCKMONSTERS) + if (rover->master->frontsector->damagetype != SD_LAVA) continue; topheight = P_GetFFloorTopZAt(rover, mo->x, mo->y); diff --git a/src/p_mobj.c b/src/p_mobj.c index 57ff8d4f1..753d298a4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2334,11 +2334,7 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) boolean P_CheckSolidLava(ffloor_t *rover) { - if (rover->flags & FF_SWIMMABLE && rover->master->frontsector->damagetype == SD_FIRE - && !(rover->master->flags & ML_BLOCKMONSTERS)) - return true; - - return false; + return (rover->flags & FF_SWIMMABLE) && (rover->master->frontsector->damagetype == SD_LAVA); } // @@ -3305,7 +3301,7 @@ void P_MobjCheckWater(mobj_t *mobj) if (mobj->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) { - if (rover->master->frontsector->damagetype == SD_FIRE) + if (rover->master->frontsector->damagetype == SD_FIRE || rover->master->frontsector->damagetype == SD_LAVA) mobj->eflags |= MFE_TOUCHLAVA; if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY)) @@ -4096,9 +4092,11 @@ static void P_KillRingsInLava(mobj_t *mo) { if (!(rover->flags & FF_EXISTS)) continue; // fof must be real - if (!(rover->flags & FF_SWIMMABLE // fof must be water - && rover->master->frontsector->damagetype == SD_FIRE)) // fof must be lava water - continue; + if (!(rover->flags & FF_SWIMMABLE)) + continue; // fof must be water + + if (rover->master->frontsector->damagetype != SD_FIRE && rover->master->frontsector->damagetype != SD_LAVA) + continue; // fof must have fire or lava damage // find heights of FOF topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); diff --git a/src/p_setup.c b/src/p_setup.c index 6fac64568..b7afe6fb4 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1735,6 +1735,8 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].damagetype = SD_WATER; if (fastcmp(val, "Fire")) sectors[i].damagetype = SD_FIRE; + if (fastcmp(val, "Lava")) + sectors[i].damagetype = SD_LAVA; if (fastcmp(val, "Electric")) sectors[i].damagetype = SD_ELECTRIC; if (fastcmp(val, "Spike")) @@ -5105,8 +5107,29 @@ static void P_ConvertBinaryMap(void) sectors[i].damagetype = SD_WATER; break; case 3: //Damage (Fire) - sectors[i].damagetype = SD_FIRE; + { + size_t j; + boolean isLava = false; + + for (j = 0; j < sectors[i].linecount; j++) + { + line_t *line = sectors[i].lines[j]; + + if (line->frontsector != §ors[i]) + continue; + + if (line->flags & ML_BLOCKMONSTERS) + continue; + + if (line->special == 120 || (line->special == 259 && (line->args[2] & FF_SWIMMABLE))) + { + isLava = true; + break; + } + } + sectors[i].damagetype = isLava ? SD_LAVA : SD_FIRE; break; + } case 4: //Damage (Electric) sectors[i].damagetype = SD_ELECTRIC; break; diff --git a/src/p_spec.c b/src/p_spec.c index 973c6ee3c..e6b1e4ec5 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5010,6 +5010,7 @@ static void P_EvaluateDamageType(player_t *player, sector_t *sector, boolean isT P_DamageMobj(player->mo, NULL, NULL, 1, DMG_WATER); break; case SD_FIRE: + case SD_LAVA: if (isTouching) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_FIRE); break; diff --git a/src/p_user.c b/src/p_user.c index 7360d2ef9..254bcc65e 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -12230,7 +12230,10 @@ static boolean P_MobjAboveLava(mobj_t *mobj) for (rover = sector->ffloors; rover; rover = rover->next) { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->master->frontsector->damagetype != SD_FIRE) + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE)) + continue; + + if (rover->master->frontsector->damagetype != SD_FIRE && rover->master->frontsector->damagetype != SD_LAVA) continue; if (mobj->eflags & MFE_VERTICALFLIP) diff --git a/src/r_defs.h b/src/r_defs.h index cd632aeca..c56abdbfd 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -321,12 +321,13 @@ typedef enum SD_GENERIC = 1, SD_WATER = 2, SD_FIRE = 3, - SD_ELECTRIC = 4, - SD_SPIKE = 5, - SD_DEATHPITTILT = 6, - SD_DEATHPITNOTILT = 7, - SD_INSTAKILL = 8, - SD_SPECIALSTAGE = 9, + SD_LAVA = 4, + SD_ELECTRIC = 5, + SD_SPIKE = 6, + SD_DEATHPITTILT = 7, + SD_DEATHPITNOTILT = 8, + SD_INSTAKILL = 9, + SD_SPECIALSTAGE = 10, } sectordamage_t; typedef enum From eef7763d68c4ee59b117d09465a14149e60ead3b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 13:58:41 +0100 Subject: [PATCH 273/326] Set SSF_WINDCURRENT and SSF_CONVEYOR automatically if there's a pusher/conveyor --- extras/conf/SRB2-22.cfg | 4 ---- extras/conf/udb/Includes/SRB222_misc.cfg | 2 -- extras/conf/udb/Includes/SRB222_sectors.cfg | 4 ---- src/p_setup.c | 10 ---------- src/p_spec.c | 22 +++++++++------------ 5 files changed, 9 insertions(+), 33 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 81d8ed193..1b36a47fa 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -437,8 +437,6 @@ sectortypes 144 = "Egg Capsule"; 160 = "Special Stage Time/Spheres 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"; @@ -497,8 +495,6 @@ gen_sectortypes third { 0 = "Normal"; - 512 = "Wind/Current"; - 1024 = "Conveyor Belt"; 1280 = "Speed Pad"; } diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 537214b58..bc284a3f9 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -87,8 +87,6 @@ sectorflags outerspace = "Space Countdown"; doublestepup = "Ramp Sector (double step-up/down)"; nostepdown = "Non-Ramp Sector (No step-down)"; - windcurrent = "Wind/Current"; - conveyor = "Conveyor Belt"; speedpad = "Speed Pad"; starpostactivator = "Star Post Activator"; exit = "Exit"; diff --git a/extras/conf/udb/Includes/SRB222_sectors.cfg b/extras/conf/udb/Includes/SRB222_sectors.cfg index 412aed155..f9df297e7 100644 --- a/extras/conf/udb/Includes/SRB222_sectors.cfg +++ b/extras/conf/udb/Includes/SRB222_sectors.cfg @@ -27,8 +27,6 @@ sectortypes 144 = "Egg Capsule"; 160 = "Special Stage Time/Spheres 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"; @@ -85,8 +83,6 @@ gen_sectortypes third { 0 = "Normal"; - 512 = "Wind/Current"; - 1024 = "Conveyor Belt"; 1280 = "Speed Pad"; } diff --git a/src/p_setup.c b/src/p_setup.c index b7afe6fb4..4383b77e1 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1691,10 +1691,6 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].specialflags |= SSF_DOUBLESTEPUP; else if (fastcmp(param, "nostepdown") && fastcmp("true", val)) sectors[i].specialflags |= SSF_NOSTEPDOWN; - else if (fastcmp(param, "windcurrent") && fastcmp("true", val)) - sectors[i].specialflags |= SSF_WINDCURRENT; - else if (fastcmp(param, "conveyor") && fastcmp("true", val)) - sectors[i].specialflags |= SSF_CONVEYOR; else if (fastcmp(param, "speedpad") && fastcmp("true", val)) sectors[i].specialflags |= SSF_SPEEDPAD; else if (fastcmp(param, "starpostactivator") && fastcmp("true", val)) @@ -5207,12 +5203,6 @@ static void P_ConvertBinaryMap(void) switch(GETSECSPECIAL(sectors[i].special, 3)) { - case 2: //Wind/Current - sectors[i].specialflags |= SSF_WINDCURRENT; - break; - case 4: //Conveyor belt - sectors[i].specialflags |= SSF_CONVEYOR; - break; case 5: //Speed pad sectors[i].specialflags |= SSF_SPEEDPAD; break; diff --git a/src/p_spec.c b/src/p_spec.c index e6b1e4ec5..f97e40cc4 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7471,9 +7471,12 @@ static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT3 s->accel = accel; s->exclusive = exclusive; s->vdx = s->vdy = 0; - if ((s->control = control) != -1) + s->control = control; + if (s->control != -1) s->last_height = sectors[control].floorheight + sectors[control].ceilingheight; s->affectee = affectee; + if (type == sc_carry || type == sc_carry_ceiling) + sectors[affectee].specialflags |= SSF_CONVEYOR; P_AddThinker(THINK_MAIN, &s->thinker); } @@ -8407,9 +8410,13 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, fixed_t { p->roverpusher = true; p->referrer = referrer; + sectors[referrer].specialflags |= SSF_WINDCURRENT; } else + { p->roverpusher = false; + sectors[affectee].specialflags |= SSF_WINDCURRENT; + } p->affectee = affectee; P_AddThinker(THINK_MAIN, &p->thinker); @@ -8437,19 +8444,8 @@ void T_Pusher(pusher_t *p) z_mag = p->z_mag >> PUSH_FACTOR; sec = sectors + p->affectee; - - // Be sure the sector special flag is still turned on. If so, proceed. - // Else, bail out; the flag has been changed on us. - if (p->roverpusher) - { - referrer = §ors[p->referrer]; - - if (!(referrer->specialflags & SSF_WINDCURRENT)) - return; - } - else if (!(sec->specialflags & SSF_WINDCURRENT)) - return; + referrer = sectors + p->referrer; // For constant pushers (wind/current) there are 3 situations: // From 9b780f417e6664da349f80f21c105a4b6364beb5 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 14:06:06 +0100 Subject: [PATCH 274/326] Fix a conversion oversight with linedef type 8 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 5 +++++ src/p_setup.c | 1 + src/p_spec.c | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index e2e1d187a..62f7ec12e 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1725,6 +1725,11 @@ udmf { title = "Set Camera Collision Planes"; prefix = "(8)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } } 11 diff --git a/src/p_setup.c b/src/p_setup.c index 4383b77e1..5d8bc9cc0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3333,6 +3333,7 @@ static void P_ConvertBinaryMap(void) { INT32 s; + lines[i].args[0] = tag; TAG_ITER_SECTORS(tag, s) { if (lines[i].flags & ML_NOCLIMB) diff --git a/src/p_spec.c b/src/p_spec.c index f97e40cc4..4785b8866 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6295,7 +6295,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 8: // Set camera collision planes if (lines[i].frontsector) - TAG_ITER_SECTORS(tag, s) + TAG_ITER_SECTORS(lines[i].args[0], s) sectors[s].camsec = lines[i].frontsector-sectors; break; From ee728126df0e3a5b9575ef654e27b08332840a1c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 14:09:22 +0100 Subject: [PATCH 275/326] Fix oversight with linedef type 604 --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 27c35e9f0..b87f254d2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6888,7 +6888,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 604: // Adjustable Blinking Light sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(tag, s) + TAG_ITER_SECTORS(lines[i].args[0], s) P_SpawnAdjustableStrobeFlash(§ors[s], lines[i].args[3], (lines[i].args[4] & TMB_USETARGET) ? sectors[s].lightlevel : lines[i].args[5], lines[i].args[1], lines[i].args[2], lines[i].args[4] & TMB_SYNC); From e4d7b3df6cbc74e3c2c8a8866d4c0d0d81682e09 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 14:17:17 +0100 Subject: [PATCH 276/326] Minor cleanup in P_SpawnSpecials --- src/p_spec.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index c18b5bd93..73a095fde 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6224,8 +6224,6 @@ void P_SpawnSpecials(boolean fromnetsave) // Init line EFFECTs for (i = 0; i < numlines; i++) { - mtag_t tag = Tag_FGet(&lines[i].tags); - // set line specials to 0 here too, same reason as above if (netgame || multiplayer) { @@ -6253,7 +6251,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(tag, s) + TAG_ITER_SECTORS(Tag_FGet(&lines[i].tags), s) { sectors[s].gravityptr = §ors[sec].floorheight; // This allows it to change in realtime! @@ -6271,7 +6269,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(tag, s) + TAG_ITER_SECTORS(Tag_FGet(&lines[i].tags), s) P_AddCameraScanner(§ors[sec], §ors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)); break; From 8e4cbf8b76f662578425ea92d63602f74e17de84 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 31 Dec 2021 15:33:47 +0100 Subject: [PATCH 277/326] Disable ML_EFFECT5 on linedef executor triggers for UDMF maps (what a pointless feature) --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 408b43478..c548a32ca 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1648,7 +1648,7 @@ static boolean P_ActivateLinedefExecutorsInSector(line_t *triggerline, mobj_t *a size_t linecnt = ctlsector->linecount; size_t i; - if (triggerline->flags & ML_EFFECT5) // disregard order for efficiency + if (!udmf && triggerline->flags & ML_EFFECT5) // disregard order for efficiency { for (i = 0; i < linecnt; i++) P_ActivateLinedefExecutor(ctlsector->lines[i], actor, caller); From afde568856948b9e07f2f52d569abca1aaeb1983 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 4 Jan 2022 19:33:17 +0100 Subject: [PATCH 278/326] Add blendmode support to FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 62 ++++- extras/conf/udb/Includes/SRB222_misc.cfg | 9 + src/p_setup.c | 201 +++++++-------- src/p_spec.c | 250 ++++++++++--------- src/p_spec.h | 10 +- 5 files changed, 302 insertions(+), 230 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 15e7685c3..d40f2a373 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2453,6 +2453,12 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Appearance"; type = 12; @@ -2466,7 +2472,7 @@ udmf 32 = "Cut cyan flat pixels"; } } - arg3 + arg4 { title = "Tangibility"; type = 12; @@ -2489,6 +2495,12 @@ udmf default = 128; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Flags"; type = 12; @@ -2556,12 +2568,18 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Tangibility"; type = 12; enum = "tangibility"; } - arg3 + arg4 { title = "Flags"; type = 12; @@ -2591,6 +2609,12 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Appearance"; type = 12; @@ -2604,17 +2628,17 @@ udmf 32 = "Cut cyan flat pixels"; } } - arg3 + arg4 { title = "Tangibility"; type = 12; enum = "tangibility"; } - arg4 + arg5 { title = "Speed"; } - arg5 + arg6 { title = "Flags"; type = 12; @@ -2669,6 +2693,12 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Appearance"; type = 12; @@ -2755,6 +2785,12 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Bustable type"; type = 11; @@ -2766,7 +2802,7 @@ udmf 3 = "Strong"; } } - arg3 + arg4 { title = "Flags"; type = 12; @@ -2778,7 +2814,7 @@ udmf 8 = "Cut cyan flat pixels"; } } - arg4 + arg5 { title = "Linedef executor tag"; type = 15; @@ -2825,6 +2861,12 @@ udmf default = 128; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Flags"; type = 12; @@ -2851,6 +2893,12 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Flags"; type = 12; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index c46fff822..e392014c8 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -649,6 +649,15 @@ enums 1 = "Random (Weak)"; 2 = "Random (Strong)"; } + + blendmodes + { + 0 = "Translucent"; + 1 = "Add"; + 2 = "Subtract"; + 3 = "Reverse subtract"; + 4 = "Modulate"; + } } //Default things filters diff --git a/src/p_setup.c b/src/p_setup.c index dbbd99859..15e7c6d09 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3282,6 +3282,24 @@ static line_t *P_FindPointPushLine(taglist_t *list) return NULL; } +static void P_SetBinaryFOFAlpha(line_t *line) +{ + if (sides[line->sidenum[0]].toptexture > 0) + { + line->args[1] = sides[line->sidenum[0]].toptexture; + if (sides[line->sidenum[0]].toptexture >= 1001) + { + line->args[2] = (sides[line->sidenum[0]].toptexture/1000); + line->args[1] %= 1000; + } + } + else + { + line->args[1] = 128; + line->args[2] = TMB_TRANSLUCENT; + } +} + //For maps in binary format, converts setup of specials to UDMF format. static void P_ConvertBinaryMap(void) { @@ -3562,36 +3580,33 @@ static void P_ConvertBinaryMap(void) if (lines[i].special == 102) { if (lines[i].flags & ML_NOCLIMB) - lines[i].args[2] |= TMFA_INSIDES; - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + lines[i].args[3] |= TMFA_INSIDES; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; } else lines[i].args[1] = 255; //Appearance if (lines[i].special == 105) - lines[i].args[2] |= TMFA_NOPLANES|TMFA_NOSIDES; + lines[i].args[3] |= TMFA_NOPLANES|TMFA_NOSIDES; else if (lines[i].special == 104) - lines[i].args[2] |= TMFA_NOSIDES; + lines[i].args[3] |= TMFA_NOSIDES; else if (lines[i].special == 103) - lines[i].args[2] |= TMFA_NOPLANES; + lines[i].args[3] |= TMFA_NOPLANES; if (lines[i].special != 100 && (lines[i].special != 104 || !(lines[i].flags & ML_NOCLIMB))) - lines[i].args[2] |= TMFA_NOSHADE; + lines[i].args[3] |= TMFA_NOSHADE; if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; //Tangibility if (lines[i].flags & ML_EFFECT1) - lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; + lines[i].args[4] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; + lines[i].args[4] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 100; break; @@ -3608,35 +3623,32 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = 255; else { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= TMFW_SPLAT; + lines[i].args[3] |= TMFW_SPLAT; } //No sides? if (lines[i].special == 122 || lines[i].special == 123 || lines[i].special == 125) - lines[i].args[2] |= TMFW_NOSIDES; + lines[i].args[3] |= TMFW_NOSIDES; //Flags if (lines[i].flags & ML_NOCLIMB) - lines[i].args[2] |= TMFW_DOUBLESHADOW; + lines[i].args[3] |= TMFW_DOUBLESHADOW; if (lines[i].flags & ML_EFFECT4) - lines[i].args[2] |= TMFW_COLORMAPONLY; + lines[i].args[3] |= TMFW_COLORMAPONLY; if (!(lines[i].flags & ML_EFFECT5)) - lines[i].args[2] |= TMFW_NORIPPLE; + lines[i].args[3] |= TMFW_NORIPPLE; //Goo? if (lines[i].special >= 124) - lines[i].args[2] |= TMFW_GOOWATER; + lines[i].args[3] |= TMFW_GOOWATER; //Splat rendering? if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= TMFW_SPLAT; + lines[i].args[3] |= TMFW_SPLAT; lines[i].special = 120; break; @@ -3653,41 +3665,38 @@ static void P_ConvertBinaryMap(void) if (lines[i].special == 141 || lines[i].special == 142 || lines[i].special == 144 || lines[i].special == 145) { if (lines[i].flags & ML_NOCLIMB) - lines[i].args[2] |= TMFA_INSIDES; - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + lines[i].args[3] |= TMFA_INSIDES; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; } else lines[i].args[1] = 255; //Appearance if (lines[i].special == 142 || lines[i].special == 145) - lines[i].args[2] |= TMFA_NOSIDES; + lines[i].args[3] |= TMFA_NOSIDES; else if (lines[i].special == 146) - lines[i].args[2] |= TMFA_NOPLANES; + lines[i].args[3] |= TMFA_NOPLANES; if (lines[i].special != 146 && (lines[i].flags & ML_NOCLIMB)) - lines[i].args[2] |= TMFA_NOSHADE; + lines[i].args[3] |= TMFA_NOSHADE; if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; //Tangibility if (lines[i].special <= 142) - lines[i].args[3] |= TMFT_INTANGIBLEBOTTOM; + lines[i].args[4] |= TMFT_INTANGIBLEBOTTOM; else if (lines[i].special <= 145) - lines[i].args[3] |= TMFT_INTANGIBLETOP; + lines[i].args[4] |= TMFT_INTANGIBLETOP; else - lines[i].args[3] |= TMFT_INTANGIBLEBOTTOM|TMFT_INTANGIBLETOP; + lines[i].args[4] |= TMFT_INTANGIBLEBOTTOM|TMFT_INTANGIBLETOP; if (lines[i].flags & ML_EFFECT1) - lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; + lines[i].args[4] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; + lines[i].args[4] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 100; break; @@ -3727,38 +3736,35 @@ static void P_ConvertBinaryMap(void) //Alpha if (lines[i].special >= 174 && lines[i].special <= 175) { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[3] |= TMFC_SPLAT; + lines[i].args[4] |= TMFC_SPLAT; } else lines[i].args[1] = 255; if (lines[i].special >= 172 && lines[i].special <= 175) { - lines[i].args[2] |= TMFT_INTANGIBLEBOTTOM; + lines[i].args[3] |= TMFT_INTANGIBLEBOTTOM; if (lines[i].flags & ML_NOCLIMB) - lines[i].args[3] |= TMFC_NOSHADE; + lines[i].args[4] |= TMFC_NOSHADE; } if (lines[i].special % 2 == 1) - lines[i].args[3] |= TMFC_NORETURN; + lines[i].args[4] |= TMFC_NORETURN; if (lines[i].special == 176 || lines[i].special == 177 || lines[i].special == 180) - lines[i].args[3] |= TMFC_AIRBOB; + lines[i].args[4] |= TMFC_AIRBOB; if (lines[i].special >= 176 && lines[i].special <= 179) - lines[i].args[3] |= TMFC_FLOATBOB; + lines[i].args[4] |= TMFC_FLOATBOB; if (lines[i].flags & ML_EFFECT6) - lines[i].args[3] |= TMFC_SPLAT; + lines[i].args[4] |= TMFC_SPLAT; if (lines[i].flags & ML_EFFECT1) - lines[i].args[2] |= TMFT_DONTBLOCKOTHERS; + lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[2] |= TMFT_DONTBLOCKPLAYER; + lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 170; break; @@ -3773,44 +3779,41 @@ static void P_ConvertBinaryMap(void) //Translucency if (lines[i].special == 192 || lines[i].special == 195) { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; } else lines[i].args[1] = 255; //Appearance if (lines[i].special == 193) - lines[i].args[2] |= TMFA_NOPLANES|TMFA_NOSIDES; + lines[i].args[3] |= TMFA_NOPLANES|TMFA_NOSIDES; if (lines[i].special >= 194) - lines[i].args[2] |= TMFA_INSIDES; + lines[i].args[3] |= TMFA_INSIDES; if (lines[i].special != 190 && (lines[i].special <= 193 || lines[i].flags & ML_NOCLIMB)) - lines[i].args[2] |= TMFA_NOSHADE; + lines[i].args[3] |= TMFA_NOSHADE; if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; //Tangibility if (lines[i].flags & ML_EFFECT1) - lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; + lines[i].args[4] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; + lines[i].args[4] |= TMFT_DONTBLOCKPLAYER; if (lines[i].special >= 194) - lines[i].args[3] |= TMFT_INTANGIBLEBOTTOM; + lines[i].args[4] |= TMFT_INTANGIBLEBOTTOM; //Speed - lines[i].args[4] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].args[5] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; //Flags if (lines[i].flags & ML_BLOCKMONSTERS) - lines[i].args[5] |= TMFR_REVERSE; + lines[i].args[6] |= TMFR_REVERSE; if (lines[i].flags & ML_BLOCKMONSTERS) - lines[i].args[5] |= TMFR_SPINDASH; + lines[i].args[6] |= TMFR_SPINDASH; lines[i].special = 190; break; @@ -3833,27 +3836,24 @@ static void P_ConvertBinaryMap(void) //Alpha if (lines[i].special == 221) { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; } else lines[i].args[1] = 255; //Appearance if (lines[i].special == 222) - lines[i].args[2] |= TMFA_NOPLANES; + lines[i].args[3] |= TMFA_NOPLANES; if (lines[i].special == 221) - lines[i].args[2] |= TMFA_INSIDES; + lines[i].args[3] |= TMFA_INSIDES; if (lines[i].special != 220 && !(lines[i].flags & ML_NOCLIMB)) - lines[i].args[2] |= TMFA_NOSHADE; + lines[i].args[3] |= TMFA_NOSHADE; if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; lines[i].special = 220; break; @@ -3889,40 +3889,37 @@ static void P_ConvertBinaryMap(void) //Alpha if (lines[i].special == 253 || lines[i].special == 256) { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[3] |= TMFB_SPLAT; + lines[i].args[4] |= TMFB_SPLAT; } else lines[i].args[1] = 255; //Bustable type if (lines[i].special <= 253) - lines[i].args[2] = TMFB_TOUCH; + lines[i].args[3] = TMFB_TOUCH; else if (lines[i].special >= 255) - lines[i].args[2] = TMFB_SPIN; + lines[i].args[3] = TMFB_SPIN; else if (lines[i].flags & ML_NOCLIMB) - lines[i].args[2] = TMFB_STRONG; + lines[i].args[3] = TMFB_STRONG; else - lines[i].args[2] = TMFB_REGULAR; + lines[i].args[3] = TMFB_REGULAR; //Flags if (lines[i].flags & ML_EFFECT4) - lines[i].args[3] |= TMFB_PUSHABLES; + lines[i].args[4] |= TMFB_PUSHABLES; if (lines[i].flags & ML_EFFECT5) { - lines[i].args[3] |= TMFB_EXECUTOR; - lines[i].args[4] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].args[4] |= TMFB_EXECUTOR; + lines[i].args[5] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; } if (lines[i].special == 252 && lines[i].flags & ML_NOCLIMB) - lines[i].args[3] |= TMFB_ONLYBOTTOM; + lines[i].args[4] |= TMFB_ONLYBOTTOM; if (lines[i].flags & ML_EFFECT6) - lines[i].args[3] |= TMFB_SPLAT; + lines[i].args[4] |= TMFB_SPLAT; lines[i].special = 254; break; @@ -3937,17 +3934,14 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = tag; //Alpha - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Flags if (lines[i].flags & ML_EFFECT1) - lines[i].args[2] = TMFL_NOBOSSES; + lines[i].args[3] |= TMFL_NOBOSSES; //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].flags & ML_EFFECT6 || lines[i].args[1] == 256) - lines[i].args[2] = TMFL_SPLAT; + lines[i].args[3] |= TMFL_SPLAT; break; case 259: //Custom FOF @@ -3955,20 +3949,17 @@ static void P_ConvertBinaryMap(void) I_Error("Custom FOF (tag %d) found without a linedef back side!", tag); lines[i].args[0] = tag; - lines[i].args[2] = sides[lines[i].sidenum[1]].toptexture; + lines[i].args[3] = sides[lines[i].sidenum[1]].toptexture; if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= FF_SPLAT; - lines[i].args[3] = sides[lines[i].sidenum[1]].midtexture; - if (lines[i].args[2] & FF_TRANSLUCENT) + lines[i].args[3] |= FF_SPLAT; + lines[i].args[4] = sides[lines[i].sidenum[1]].midtexture; + if (lines[i].args[3] & FF_TRANSLUCENT) { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= FF_SPLAT; + lines[i].args[3] |= FF_SPLAT; } else lines[i].args[1] = 255; diff --git a/src/p_spec.c b/src/p_spec.c index 1220edf8f..9358d6766 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -115,7 +115,7 @@ static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, ext static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); -static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorflags, thinkerlist_t *secthinkers); +static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, UINT8 blendmode, ffloortype_e ffloorflags, thinkerlist_t *secthinkers); static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec); static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer); static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee, UINT8 reverse); @@ -5490,12 +5490,13 @@ static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *fflr) * \param sec2 Control sector. * \param master Control linedef. * \param alpha Alpha value (0-255). + * \param blendmode Blending mode. * \param flags Options affecting this 3Dfloor. * \param secthinkers List of relevant thinkers sorted by sector. May be NULL. * \return Pointer to the new 3Dfloor. * \sa P_AddFFloor, P_AddFakeFloorsByLine, P_SpawnSpecials */ -static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, INT32 alpha, ffloortype_e flags, thinkerlist_t *secthinkers) +static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, INT32 alpha, UINT8 blendmode, ffloortype_e flags, thinkerlist_t *secthinkers) { ffloor_t *fflr; thinker_t *th; @@ -5621,15 +5622,29 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I { fflr->flags |= FF_TRANSLUCENT; fflr->spawnflags = fflr->flags; - - if (sides[master->sidenum[0]].toptexture >= 1001) - { - fflr->blend = (sides[master->sidenum[0]].toptexture/1000)+1; // becomes an AST - fflr->alpha %= 1000; - } } fflr->spawnalpha = fflr->alpha; // save for netgames + switch (blendmode) + { + case TMB_TRANSLUCENT: + default: + fflr->blend = AST_TRANSLUCENT; + break; + case TMB_ADD: + fflr->blend = AST_ADD; + break; + case TMB_SUBTRACT: + fflr->blend = AST_SUBTRACT; + break; + case TMB_REVERSESUBTRACT: + fflr->blend = AST_REVERSESUBTRACT; + break; + case TMB_MODULATE: + fflr->blend = AST_MODULATE; + break; + } + if (flags & FF_QUICKSAND) CheckForQuicksand = true; @@ -6455,29 +6470,81 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; //Appearance settings - if (lines[i].args[2] & TMFA_NOPLANES) + if (lines[i].args[3] & TMFA_NOPLANES) ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[2] & TMFA_NOSIDES) + if (lines[i].args[3] & TMFA_NOSIDES) ffloorflags &= ~FF_RENDERSIDES; - if (lines[i].args[2] & TMFA_INSIDES) + if (lines[i].args[3] & TMFA_INSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_ALLSIDES; } - if (lines[i].args[2] & TMFA_ONLYINSIDES) + if (lines[i].args[3] & TMFA_ONLYINSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_INVERTPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_INVERTSIDES; } - if (lines[i].args[2] & TMFA_NOSHADE) + if (lines[i].args[3] & TMFA_NOSHADE) ffloorflags |= FF_NOSHADE; - if (lines[i].args[2] & TMFA_SPLAT) + if (lines[i].args[3] & TMFA_SPLAT) ffloorflags |= FF_SPLAT; + //Tangibility settings + if (lines[i].args[4] & TMFT_INTANGIBLETOP) + ffloorflags |= FF_REVERSEPLATFORM; + if (lines[i].args[4] & TMFT_INTANGIBLEBOTTOM) + ffloorflags |= FF_PLATFORM; + if (lines[i].args[4] & TMFT_DONTBLOCKPLAYER) + ffloorflags &= ~FF_BLOCKPLAYER; + if (lines[i].args[4] & TMFT_DONTBLOCKOTHERS) + ffloorflags &= ~FF_BLOCKOTHERS; + + //Cutting options + if (ffloorflags & FF_RENDERALL) + { + //If translucent or player can enter it, cut inner walls + if ((lines[i].args[1] < 255) || (lines[i].args[4] & TMFT_VISIBLEFROMINSIDE)) + ffloorflags |= FF_CUTEXTRA|FF_EXTRA; + else + ffloorflags |= FF_CUTLEVEL; + } + + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); + break; + + case 120: // FOF (water) + ffloorflags = FF_EXISTS|FF_RENDERPLANES|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; + if (!(lines[i].args[3] & TMFW_NOSIDES)) + ffloorflags |= FF_RENDERSIDES|FF_ALLSIDES; + if (lines[i].args[3] & TMFW_DOUBLESHADOW) + ffloorflags |= FF_DOUBLESHADOW; + if (lines[i].args[3] & TMFW_COLORMAPONLY) + ffloorflags |= FF_COLORMAPONLY; + if (!(lines[i].args[3] & TMFW_NORIPPLE)) + ffloorflags |= FF_RIPPLE; + if (lines[i].args[3] & TMFW_GOOWATER) + ffloorflags |= FF_GOOWATER; + if (lines[i].args[3] & TMFW_SPLAT) + ffloorflags |= FF_SPLAT; + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); + break; + + case 150: // FOF (Air bobbing) + P_AddFakeFloorsByLine(i, 0xff, AST_COPY, FF_EXISTS|FF_SOLID|FF_RENDERALL, secthinkers); + P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); + break; + + case 160: // FOF (Water bobbing) + P_AddFakeFloorsByLine(i, 0xff, AST_COPY, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB, secthinkers); + break; + + case 170: // FOF (Crumbling) + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE; + //Tangibility settings if (lines[i].args[3] & TMFT_INTANGIBLETOP) ffloorflags |= FF_REVERSEPLATFORM; @@ -6488,76 +6555,24 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) ffloorflags &= ~FF_BLOCKOTHERS; - //Cutting options - if (ffloorflags & FF_RENDERALL) - { - //If translucent or player can enter it, cut inner walls - if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) - ffloorflags |= FF_CUTEXTRA|FF_EXTRA; - else - ffloorflags |= FF_CUTLEVEL; - } - - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - break; - - case 120: // FOF (water) - ffloorflags = FF_EXISTS|FF_RENDERPLANES|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - if (!(lines[i].args[2] & TMFW_NOSIDES)) - ffloorflags |= FF_RENDERSIDES|FF_ALLSIDES; - if (lines[i].args[2] & TMFW_DOUBLESHADOW) - ffloorflags |= FF_DOUBLESHADOW; - if (lines[i].args[2] & TMFW_COLORMAPONLY) - ffloorflags |= FF_COLORMAPONLY; - if (!(lines[i].args[2] & TMFW_NORIPPLE)) - ffloorflags |= FF_RIPPLE; - if (lines[i].args[2] & TMFW_GOOWATER) - ffloorflags |= FF_GOOWATER; - if (lines[i].args[2] & TMFW_SPLAT) - ffloorflags |= FF_SPLAT; - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - break; - - case 150: // FOF (Air bobbing) - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL, secthinkers); - P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); - break; - - case 160: // FOF (Water bobbing) - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB, secthinkers); - break; - - case 170: // FOF (Crumbling) - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE; - - //Tangibility settings - if (lines[i].args[2] & TMFT_INTANGIBLETOP) - ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[2] & TMFT_INTANGIBLEBOTTOM) - ffloorflags |= FF_PLATFORM; - if (lines[i].args[2] & TMFT_DONTBLOCKPLAYER) - ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[2] & TMFT_DONTBLOCKOTHERS) - ffloorflags &= ~FF_BLOCKOTHERS; - //Flags - if (lines[i].args[3] & TMFC_NOSHADE) + if (lines[i].args[4] & TMFC_NOSHADE) ffloorflags |= FF_NOSHADE; - if (lines[i].args[3] & TMFC_NORETURN) + if (lines[i].args[4] & TMFC_NORETURN) ffloorflags |= FF_NORETURN; - if (lines[i].args[3] & TMFC_FLOATBOB) + if (lines[i].args[4] & TMFC_FLOATBOB) ffloorflags |= FF_FLOATBOB; - if (lines[i].args[3] & TMFC_SPLAT) + if (lines[i].args[4] & TMFC_SPLAT) ffloorflags |= FF_SPLAT; //If translucent or player can enter it, cut inner walls - if (lines[i].args[1] < 0xff || (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE)) + if (lines[i].args[1] < 0xff || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) ffloorflags |= FF_CUTEXTRA|FF_EXTRA; else ffloorflags |= FF_CUTLEVEL; //If player can enter it, render insides - if (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE) + if (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; @@ -6565,8 +6580,8 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_ALLSIDES; } - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - if (lines[i].args[3] & TMFC_AIRBOB) + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); + if (lines[i].args[4] & TMFC_AIRBOB) P_AddAirbob(lines[i].frontsector, lines[i].args[0], 16*FRACUNIT, false, false, false); break; @@ -6578,50 +6593,50 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; //Appearance settings - if (lines[i].args[2] & TMFA_NOPLANES) + if (lines[i].args[3] & TMFA_NOPLANES) ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[2] & TMFA_NOSIDES) + if (lines[i].args[3] & TMFA_NOSIDES) ffloorflags &= ~FF_RENDERSIDES; - if (lines[i].args[2] & TMFA_INSIDES) + if (lines[i].args[3] & TMFA_INSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_ALLSIDES; } - if (lines[i].args[2] & TMFA_ONLYINSIDES) + if (lines[i].args[3] & TMFA_ONLYINSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_INVERTPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_INVERTSIDES; } - if (lines[i].args[2] & TMFA_NOSHADE) + if (lines[i].args[3] & TMFA_NOSHADE) ffloorflags |= FF_NOSHADE; - if (lines[i].args[2] & TMFA_SPLAT) + if (lines[i].args[3] & TMFA_SPLAT) ffloorflags |= FF_SPLAT; //Tangibility settings - if (lines[i].args[3] & TMFT_INTANGIBLETOP) + if (lines[i].args[4] & TMFT_INTANGIBLETOP) ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[3] & TMFT_INTANGIBLEBOTTOM) + if (lines[i].args[4] & TMFT_INTANGIBLEBOTTOM) ffloorflags |= FF_PLATFORM; - if (lines[i].args[3] & TMFT_DONTBLOCKPLAYER) + if (lines[i].args[4] & TMFT_DONTBLOCKPLAYER) ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) + if (lines[i].args[4] & TMFT_DONTBLOCKOTHERS) ffloorflags &= ~FF_BLOCKOTHERS; //Cutting options if (ffloorflags & FF_RENDERALL) { //If translucent or player can enter it, cut inner walls - if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) + if ((lines[i].args[1] < 255) || (lines[i].args[4] & TMFT_VISIBLEFROMINSIDE)) ffloorflags |= FF_CUTEXTRA|FF_EXTRA; else ffloorflags |= FF_CUTLEVEL; } - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); P_AddRaiseThinker(lines[i].frontsector, lines[i].args[0], lines[i].args[4] << FRACBITS, ceilingtop, ceilingbottom, !!(lines[i].args[5] & TMFR_REVERSE), !!(lines[i].args[5] & TMFR_SPINDASH)); break; } @@ -6629,7 +6644,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_CUTSPRITES; if (!lines[i].args[1]) ffloorflags |= FF_DOUBLESHADOW; - P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, AST_COPY, ffloorflags, secthinkers); break; case 202: // Fog @@ -6638,41 +6653,41 @@ void P_SpawnSpecials(boolean fromnetsave) // SoM: Because it's fog, check for an extra colormap and set the fog flag... if (sectors[sec].extra_colormap) sectors[sec].extra_colormap->flags = CMF_FOG; - P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, AST_COPY, ffloorflags, secthinkers); break; case 220: //Intangible ffloorflags = FF_EXISTS|FF_RENDERALL|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; //Appearance settings - if (lines[i].args[2] & TMFA_NOPLANES) + if (lines[i].args[3] & TMFA_NOPLANES) ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[2] & TMFA_NOSIDES) + if (lines[i].args[3] & TMFA_NOSIDES) ffloorflags &= ~FF_RENDERSIDES; - if (!(lines[i].args[2] & TMFA_INSIDES)) + if (!(lines[i].args[3] & TMFA_INSIDES)) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_ALLSIDES; } - if (lines[i].args[2] & TMFA_ONLYINSIDES) + if (lines[i].args[3] & TMFA_ONLYINSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_INVERTPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_INVERTSIDES; } - if (lines[i].args[2] & TMFA_NOSHADE) + if (lines[i].args[3] & TMFA_NOSHADE) ffloorflags |= FF_NOSHADE; - if (lines[i].args[2] & TMFA_SPLAT) + if (lines[i].args[3] & TMFA_SPLAT) ffloorflags |= FF_SPLAT; - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); break; case 223: // FOF (intangible, invisible) - for combining specials in a sector - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_NOSHADE, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, AST_COPY, FF_EXISTS|FF_NOSHADE, secthinkers); break; case 250: // Mario Block @@ -6682,14 +6697,14 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[1] & TMFM_INVISIBLE) ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); - P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, AST_COPY, ffloorflags, secthinkers); break; case 251: // A THWOMP! { UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; P_AddThwompThinker(lines[i].frontsector, &lines[i], lines[i].args[1] << (FRACBITS - 3), lines[i].args[2] << (FRACBITS - 3), sound); - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, AST_COPY, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); break; } @@ -6701,7 +6716,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP; //Bustable type - switch (lines[i].args[2]) + switch (lines[i].args[3]) { case TMFB_TOUCH: busttype = BT_TOUCH; @@ -6718,13 +6733,13 @@ void P_SpawnSpecials(boolean fromnetsave) } //Flags - if (lines[i].args[3] & TMFB_PUSHABLES) + if (lines[i].args[4] & TMFB_PUSHABLES) bustflags |= FB_PUSHABLES; - if (lines[i].args[3] & TMFB_EXECUTOR) + if (lines[i].args[4] & TMFB_EXECUTOR) bustflags |= FB_EXECUTOR; - if (lines[i].args[3] & TMFB_ONLYBOTTOM) + if (lines[i].args[4] & TMFB_ONLYBOTTOM) bustflags |= FB_ONLYBOTTOM; - if (lines[i].args[3] & TMFB_SPLAT) + if (lines[i].args[4] & TMFB_SPLAT) ffloorflags |= FF_SPLAT; if (busttype != BT_TOUCH || bustflags & FB_ONLYBOTTOM) @@ -6732,12 +6747,12 @@ void P_SpawnSpecials(boolean fromnetsave) TAG_ITER_SECTORS(lines[i].args[0], s) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); if (!fflr) continue; fflr->bustflags = bustflags; fflr->busttype = busttype; - fflr->busttag = lines[i].args[4]; + fflr->busttag = lines[i].args[5]; } break; } @@ -6748,7 +6763,7 @@ void P_SpawnSpecials(boolean fromnetsave) TAG_ITER_SECTORS(lines[i].args[0], s) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, ffloorflags, secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, AST_COPY, ffloorflags, secthinkers); if (!fflr) continue; fflr->sinkspeed = abs(lines[i].args[2]) << (FRACBITS - 1); @@ -6758,28 +6773,28 @@ void P_SpawnSpecials(boolean fromnetsave) case 258: // Laser block ffloorflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT; - P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[2] & TMFL_NOBOSSES)); - if (lines[i].args[2] & TMFL_SPLAT) + P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[3] & TMFL_NOBOSSES)); + if (lines[i].args[3] & TMFL_SPLAT) ffloorflags |= FF_SPLAT; - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); break; case 259: // Custom FOF TAG_ITER_SECTORS(lines[i].args[0], s) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], lines[i].args[2], secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], lines[i].args[2], lines[i].args[3], secthinkers); if (!fflr) continue; if (!udmf) // Ugly backwards compatibility stuff { - if (lines[i].args[2] & FF_QUICKSAND) + if (lines[i].args[3] & FF_QUICKSAND) { fflr->sinkspeed = abs(lines[i].dx) >> 1; fflr->friction = abs(lines[i].dy) >> 6; } - if (lines[i].args[2] & FF_BUSTUP) + if (lines[i].args[3] & FF_BUSTUP) { - switch (lines[i].args[3] % TMFB_ONLYBOTTOM) + switch (lines[i].args[4] % TMFB_ONLYBOTTOM) { case TMFB_TOUCH: fflr->busttype = BT_TOUCH; @@ -6795,7 +6810,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; } - if (lines[i].args[3] & TMFB_ONLYBOTTOM) + if (lines[i].args[4] & TMFB_ONLYBOTTOM) fflr->bustflags |= FB_ONLYBOTTOM; if (lines[i].flags & ML_EFFECT4) fflr->bustflags |= FB_PUSHABLES; @@ -6870,7 +6885,7 @@ void P_SpawnSpecials(boolean fromnetsave) } } - P_AddFakeFloorsByLine(i, dopacity, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, dopacity, AST_TRANSLUCENT, ffloorflags, secthinkers); } break; @@ -7159,12 +7174,13 @@ void P_SpawnSpecials(boolean fromnetsave) * * \param line Control linedef to use. * \param alpha Alpha value (0-255). + * \param blendmode Blending mode. * \param ffloorflags 3Dfloor flags to use. * \param secthkiners Lists of thinkers sorted by sector. May be NULL. * \sa P_SpawnSpecials, P_AddFakeFloor * \author Graue */ -static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorflags, thinkerlist_t *secthinkers) +static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, UINT8 blendmode, ffloortype_e ffloorflags, thinkerlist_t *secthinkers) { INT32 s; mtag_t tag = lines[line].args[0]; @@ -7172,7 +7188,7 @@ static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorf line_t* li = lines + line; TAG_ITER_SECTORS(tag, s) - P_AddFakeFloor(§ors[s], §ors[sec], li, alpha, ffloorflags, secthinkers); + P_AddFakeFloor(§ors[s], §ors[sec], li, alpha, blendmode, ffloorflags, secthinkers); } /* diff --git a/src/p_spec.h b/src/p_spec.h index d02b5989f..40d7197fb 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -448,7 +448,6 @@ typedef enum TMPF_NONEXCLUSIVE = 1<<1, } textmappusherflags_t; - typedef enum { TMPP_NOZFADE = 1, @@ -456,6 +455,15 @@ typedef enum TMPP_NONEXCLUSIVE = 1<<2, } textmappointpushflags_t; +typedef enum +{ + TMB_TRANSLUCENT = 0, + TMB_ADD = 1, + TMB_SUBTRACT = 2, + TMB_REVERSESUBTRACT = 3, + TMB_MODULATE = 4, +} textmapblendmodes_t; + // GETSECSPECIAL (specialval, section) // // Pulls out the special # from a particular section. From 7609f300bad0ed2b8cbfaa8dd63818b0d86dcc3e Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 4 Jan 2022 19:45:36 +0100 Subject: [PATCH 279/326] Fix typo in laser FOF conversion --- 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 fd8b19f1c..057ccb45e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3557,10 +3557,10 @@ static void P_ConvertBinaryMap(void) //Flags if (lines[i].flags & ML_EFFECT1) - lines[i].args[2] = TMFL_NOBOSSES; + lines[i].args[2] |= TMFL_NOBOSSES; //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].flags & ML_EFFECT6 || lines[i].args[1] == 256) - lines[i].args[2] = TMFL_SPLAT; + lines[i].args[2] |= TMFL_SPLAT; break; case 259: //Custom FOF From e0ed58f577f1bd0662244cf1dc2e192a66232abd Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 4 Jan 2022 19:49:28 +0100 Subject: [PATCH 280/326] Fix UDB config typo --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 4169548cf..c99ed4bab 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -3384,7 +3384,7 @@ udmf 602 { - title = "Start Adjustable Pulsating Light"; + title = "Adjustable Pulsating Light"; prefix = "(602)"; arg0 { @@ -3442,7 +3442,7 @@ udmf 604 { - title = "Start Adjustable Blinking Light"; + title = "Adjustable Blinking Light"; prefix = "(604)"; arg0 { From 6cc7cc3276b8e256c7cf1ec836071fbbb9b6db9d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 4 Jan 2022 19:50:34 +0100 Subject: [PATCH 281/326] Fix UDB config typo --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index cf51d9a9a..8c0b208a7 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -2731,7 +2731,7 @@ udmf type = 12; enum { - 1 = "Add to current translucency"; + 1 = "Add to current light level"; 2 = "Interrupt ongoing fades"; 4 = "Speed is duration"; } From 46ad1e4a5cf279891387eb2bc3d2ad442446ca45 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 4 Jan 2022 19:54:43 +0100 Subject: [PATCH 282/326] UDB config: Move thing type args from Doom section to UDMF section --- extras/conf/udb/Includes/SRB222_things.cfg | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 0cb0287c5..28347c5e9 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -258,11 +258,6 @@ doom sprite = "TRETA1"; width = 16; height = 32; - arg0 - { - title = "Death trigger tag"; - type = 15; - } } 111 { @@ -2709,11 +2704,6 @@ doom sprite = "KOOPA0"; width = 16; height = 48; - arg0 - { - title = "Death trigger tag"; - type = 15; - } } 1807 { @@ -2721,11 +2711,6 @@ doom sprite = "MAXEA0"; width = 8; height = 16; - arg0 - { - title = "Death trigger tag"; - type = 15; - } } 1808 { @@ -3640,6 +3625,11 @@ udmf sprite = "TRETA1"; width = 16; height = 32; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 111 { @@ -7471,6 +7461,11 @@ udmf sprite = "KOOPA0"; width = 16; height = 48; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 1807 { @@ -7478,6 +7473,11 @@ udmf sprite = "MAXEA0"; width = 8; height = 16; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 1808 { From 9d67420e5caa4224894ce6932157fc484057815f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 4 Jan 2022 19:57:14 +0100 Subject: [PATCH 283/326] Egg Slimer: Fix typo in binary-to-UDMF conversion and invert speed-up flag --- extras/conf/udb/Includes/SRB222_things.cfg | 2 +- src/p_mobj.c | 2 +- src/p_setup.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 28347c5e9..dea20c9c6 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -4031,7 +4031,7 @@ udmf { title = "Speed up when hit?"; type = 11; - enum = "noyes"; + enum = "yesno"; } } 202 diff --git a/src/p_mobj.c b/src/p_mobj.c index 46510200e..f70c11218 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12731,7 +12731,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean } break; case MT_EGGMOBILE2: - if (mthing->args[5]) + if (!mthing->args[5]) mobj->flags2 |= MF2_AMBUSH; break; case MT_EGGMOBILE3: diff --git a/src/p_setup.c b/src/p_setup.c index 77d009194..16faee251 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4989,8 +4989,8 @@ static void P_ConvertBinaryMap(void) case 136: //Pyre Fly mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; - case 202: //Egg Slimer - mapthings[i].args[5] = !!(mapthings[i].options & MTF_AMBUSH); + case 201: //Egg Slimer + mapthings[i].args[5] = !(mapthings[i].options & MTF_AMBUSH); break; case 203: //Egg Colosseum mapthings[i].args[5] = LE_BOSS4DROP + mapthings[i].extrainfo * LE_PARAMWIDTH; From 88fae019a2fece3af15f68b250f8e30253fbe954 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 4 Jan 2022 19:59:51 +0100 Subject: [PATCH 284/326] Fix typos in binary-to-UDMF conversion --- src/p_setup.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 16faee251..bed7291f3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5121,13 +5121,13 @@ static void P_ConvertBinaryMap(void) mapthings[i].args[0] = !(mapthings[i].options & MTF_AMBUSH); break; case 700: //Water ambience A - case 701: //Water ambience A - case 702: //Water ambience A - case 703: //Water ambience A - case 704: //Water ambience A - case 705: //Water ambience A - case 706: //Water ambience A - case 707: //Water ambience A + case 701: //Water ambience B + case 702: //Water ambience C + case 703: //Water ambience D + case 704: //Water ambience E + case 705: //Water ambience F + case 706: //Water ambience G + case 707: //Water ambience H mapthings[i].args[0] = 35; P_WriteConstant(sfx_amwtr1 + mapthings[i].type - 700, &mapthings[i].stringargs[0]); mapthings[i].type = 700; From 70a28bad9456e3085b6714d059259faefab7a6e4 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 4 Jan 2022 20:02:58 +0100 Subject: [PATCH 285/326] Gas jet: Fix typo in UDB config --- extras/conf/udb/Includes/SRB222_things.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index dea20c9c6..2ddf6c80a 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -5029,7 +5029,7 @@ udmf { title = "Play sound?"; type = 11; - enum = "noyes"; + enum = "yesno"; } } 542 From 8291d433cb65efc3cc7aa892978806b8f29a0c00 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 4 Jan 2022 20:05:21 +0100 Subject: [PATCH 286/326] Chained spring: Correct flag description in UDB config --- extras/conf/udb/Includes/SRB222_things.cfg | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 2ddf6c80a..c5a881c5c 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -5999,7 +5999,17 @@ udmf { title = "Flags"; type = 12; - enum = "maceflags"; + enum + { + 1 = "Red spring"; + 2 = "No sounds"; + 4 = "Player-turnable chain"; + 8 = "Swing instead of spin"; + 16 = "Make chain from end item"; + 32 = "Spawn link at origin"; + 64 = "Clip inside ground"; + 128 = "No distance check"; + } } } 1107 From 577ae68d6d3475258d95962cf7edc01800e05ec2 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 4 Jan 2022 21:25:34 +0100 Subject: [PATCH 287/326] Make sector friction a floating-point field --- extras/conf/udb/Includes/SRB222_misc.cfg | 4 ++-- src/lua_maplib.c | 2 +- src/p_setup.c | 20 ++++++++++++++++++-- src/p_spec.c | 12 ++---------- src/r_defs.h | 2 +- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index bc284a3f9..e8da74e99 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -250,8 +250,8 @@ universalfields friction { - type = 0; - default = 0; + type = 1; + default = 0.90625; } triggertag diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 4bbd826ef..41ed0bbdc 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -679,7 +679,7 @@ static int sector_get(lua_State *L) lua_pushinteger(L, (UINT8)sector->triggerer); return 1; case sector_friction: // friction - lua_pushinteger(L, sector->friction); + lua_pushfixed(L, sector->friction); return 1; case sector_gravity: // gravity lua_pushfixed(L, sector->gravity); diff --git a/src/p_setup.c b/src/p_setup.c index 5d8bc9cc0..2e6b89ce1 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1054,6 +1054,8 @@ static void P_LoadSectors(UINT8 *data) ss->triggertag = 0; ss->triggerer = TO_PLAYER; + ss->friction = ORIG_FRICTION; + P_InitializeSector(ss); } } @@ -1720,7 +1722,7 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) else if (fastcmp(param, "ropehang") && fastcmp("true", val)) sectors[i].specialflags |= SSF_ROPEHANG; else if (fastcmp(param, "friction")) - sectors[i].friction = atol(val); + sectors[i].friction = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "gravity")) sectors[i].gravity = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "damagetype")) @@ -2034,6 +2036,8 @@ static void P_LoadTextmap(void) sc->triggertag = 0; sc->triggerer = TO_PLAYER; + sc->friction = ORIG_FRICTION; + textmap_colormap.used = false; textmap_colormap.lightcolor = 0; textmap_colormap.lightalpha = 25; @@ -4921,8 +4925,20 @@ static void P_ConvertBinaryMap(void) case 540: //Floor friction { INT32 s; + fixed_t strength; // friction value of sector + fixed_t friction; // friction value to be applied during movement + + strength = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + if (strength > 0) // sludge + strength = strength*2; // otherwise, the maximum sludginess value is +967... + + // The following might seem odd. At the time of movement, + // the move distance is multiplied by 'friction/0x10000', so a + // higher friction value actually means 'less friction'. + friction = ORIG_FRICTION - (0x1EB8*strength)/0x80; // ORIG_FRICTION is 0xE800 + TAG_ITER_SECTORS(tag, s) - sectors[s].friction = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + sectors[s].friction = friction; break; } case 541: //Wind diff --git a/src/p_spec.c b/src/p_spec.c index 73a095fde..4d6b83414 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -8337,23 +8337,15 @@ static void P_SpawnFriction(void) size_t i; sector_t *s = sectors; - fixed_t strength; // friction value of sector fixed_t friction; // friction value to be applied during movement INT32 movefactor; // applied to each player move to simulate inertia for (i = 0; i < numsectors; i++, s++) { - if (!s->friction) + if (s->friction == ORIG_FRICTION) continue; - strength = s->friction; - if (strength > 0) // sludge - strength = strength*2; // otherwise, the maximum sludginess value is +967... - - // The following might seem odd. At the time of movement, - // the move distance is multiplied by 'friction/0x10000', so a - // higher friction value actually means 'less friction'. - friction = ORIG_FRICTION - (0x1EB8*strength)/0x80; // ORIG_FRICTION is 0xE800 + friction = s->friction; if (friction > FRACUNIT) friction = FRACUNIT; diff --git a/src/r_defs.h b/src/r_defs.h index c56abdbfd..ce3ffaad9 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -428,7 +428,7 @@ typedef struct sector_s mtag_t triggertag; // tag to call upon triggering UINT8 triggerer; // who can trigger? - INT32 friction; + fixed_t friction; // Sprite culling feature struct line_s *cullheight; From a8e32cfe12914864677b3bef202df5de24c58db6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 5 Jan 2022 00:26:10 +0100 Subject: [PATCH 288/326] Fix incorrect turnaround behavior for bounceFloor and bounceCeiling --- src/p_ceilng.c | 7 +++++-- src/p_floor.c | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index ed385be33..aa31e4301 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -86,14 +86,17 @@ void T_MoveCeiling(ceiling_t *ceiling) if (dest == lines[ceiling->sourceline].frontsector->ceilingheight) { dest = lines[ceiling->sourceline].backsector->ceilingheight; - ceiling->speed = ceiling->origspeed = lines[ceiling->sourceline].args[3] << (FRACBITS - 2); // return trip, use args[3] + ceiling->origspeed = lines[ceiling->sourceline].args[3] << (FRACBITS - 2); // return trip, use args[3] } else { dest = lines[ceiling->sourceline].frontsector->ceilingheight; - ceiling->speed = ceiling->origspeed = lines[ceiling->sourceline].args[2] << (FRACBITS - 2); // going frontways, use args[2] + ceiling->origspeed = lines[ceiling->sourceline].args[2] << (FRACBITS - 2); // going frontways, use args[2] } + if (ceiling->type == bounceCeilingCrush) + ceiling->speed = ceiling->origspeed; + if (dest < ceiling->sector->ceilingheight) // must move down { ceiling->direction = -1; diff --git a/src/p_floor.c b/src/p_floor.c index 7f1a7c2e0..1d7cc3f5b 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -206,13 +206,15 @@ void T_MoveFloor(floormove_t *movefloor) if (movefloor->floordestheight == lines[movefloor->sourceline].frontsector->floorheight) { movefloor->floordestheight = lines[movefloor->sourceline].backsector->floorheight; - movefloor->speed = movefloor->origspeed = lines[movefloor->sourceline].args[3] << (FRACBITS - 2); // return trip, use args[3] + movefloor->origspeed = lines[movefloor->sourceline].args[3] << (FRACBITS - 2); // return trip, use args[3] } else { movefloor->floordestheight = lines[movefloor->sourceline].frontsector->floorheight; - movefloor->speed = movefloor->origspeed = lines[movefloor->sourceline].args[2] << (FRACBITS - 2); // forward again, use args[2] + movefloor->origspeed = lines[movefloor->sourceline].args[2] << (FRACBITS - 2); // forward again, use args[2] } + if (movefloor->type == bounceFloorCrush) + movefloor->speed = movefloor->origspeed; movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1; movefloor->delaytimer = movefloor->delay; remove = false; From d25bc75a92769edc7e6e0e724d9d34c0580535cf Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 5 Jan 2022 09:22:13 +0100 Subject: [PATCH 289/326] Remove redundant UDMF check in P_LoadSidedefs --- src/p_setup.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 399f66c58..b89b38f5b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1233,11 +1233,8 @@ static void P_LoadSidedefs(UINT8 *data) case 455: // Fade colormaps! mazmazz 9/12/2018 (:flag_us:) // SoM: R_CreateColormap will only create a colormap in software mode... // Perhaps we should just call it instead of doing the calculations here. - if (!udmf) - { - sd->colormap_data = R_CreateColormapFromLinedef(msd->toptexture, msd->midtexture, msd->bottomtexture); - sd->toptexture = sd->midtexture = sd->bottomtexture = 0; - } + sd->colormap_data = R_CreateColormapFromLinedef(msd->toptexture, msd->midtexture, msd->bottomtexture); + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; break; case 413: // Change music From 06b7d7ceb80dc1664224e5334816ce80c75fd6ec Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 5 Jan 2022 18:05:47 +0100 Subject: [PATCH 290/326] Make only ML_EFFECT3 affect midtexture pegging in UDMF --- src/hardware/hw_main.c | 10 +++++----- src/p_maputl.c | 2 +- src/p_setup.c | 8 ++++++++ src/r_segs.c | 12 ++++++------ 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 291cabe9a..dece1deda 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1330,7 +1330,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (gl_linedef->flags & ML_EFFECT2) { - if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) + if (gl_linedef->flags & ML_EFFECT3) { polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset; polytop = polybottom + textureheight[gl_midtexture]*repeats; @@ -1341,7 +1341,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom polybottom = polytop - textureheight[gl_midtexture]*repeats; } } - else if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) + else if (gl_linedef->flags & ML_EFFECT3) { polybottom = popenbottom + gl_sidedef->rowoffset; polytop = polybottom + textureheight[gl_midtexture]*repeats; @@ -1371,7 +1371,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { // PEGGING - if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) + if (gl_linedef->flags & ML_EFFECT3) texturevpeg = textureheight[gl_sidedef->midtexture]*repeats - h + polybottom; else texturevpeg = polytop - h; @@ -1396,7 +1396,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (gl_linedef->flags & ML_EFFECT2) midtextureslant = 0; - else if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) + else if (gl_linedef->flags & ML_EFFECT3) midtextureslant = worldlow < worldbottom ? worldbottomslope-worldbottom : worldlowslope-worldlow; @@ -1421,7 +1421,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { // PEGGING - if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) + if (gl_linedef->flags & ML_EFFECT3) texturevpeg = textureheight[gl_sidedef->midtexture]*repeats - h + polybottom; else texturevpeg = polytop - h; diff --git a/src/p_maputl.c b/src/p_maputl.c index ee22578ef..0e10d1411 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -524,7 +524,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat texbottom = openbottom + side->rowoffset; textop = opentop + side->rowoffset; - } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { + } else if (linedef->flags & ML_EFFECT3) { texbottom = openbottom + side->rowoffset; textop = texbottom + texheight*(side->repeatcnt+1); } else { diff --git a/src/p_setup.c b/src/p_setup.c index b89b38f5b..f92fd46a9 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5852,6 +5852,14 @@ static void P_ConvertBinaryMap(void) break; } } + + for (i = 0; i < numlines; i++) + { + if (!!(lines[i].flags & ML_DONTPEGBOTTOM) ^ !!(lines[i].flags & ML_EFFECT3)) + lines[i].flags |= ML_EFFECT3; + else + lines[i].flags &= ~ML_EFFECT3; + } } /** Compute MD5 message digest for bytes read from memory source diff --git a/src/r_segs.c b/src/r_segs.c index 48d071b29..28968563e 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -345,7 +345,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { dc_texturemid = ds->maskedtextureheight[dc_x]; - if (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3)) + if (curline->linedef->flags & ML_EFFECT3) dc_texturemid += (textureheight[texnum])*times + textureheight[texnum]; else dc_texturemid -= (textureheight[texnum])*times; @@ -1455,9 +1455,9 @@ static void R_RenderSegLoop (void) maskedtexturecol[rw_x] = (INT16)texturecolumn; if (maskedtextureheight != NULL) { - maskedtextureheight[rw_x] = (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3) ? + maskedtextureheight[rw_x] = (curline->linedef->flags & ML_EFFECT3) ? max(rw_midtexturemid, rw_midtextureback) : - min(rw_midtexturemid, rw_midtextureback)); + min(rw_midtexturemid, rw_midtextureback); } } @@ -2247,7 +2247,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (curline->polyseg) { // use REAL front and back floors please, so midtexture rendering isn't mucked up rw_midtextureslide = rw_midtexturebackslide = 0; - if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) + if (linedef->flags & ML_EFFECT3) rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz; else rw_midtexturemid = rw_midtextureback = min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz; @@ -2258,13 +2258,13 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (linedef->flags & ML_EFFECT2) { // Ignore slopes when texturing rw_midtextureslide = rw_midtexturebackslide = 0; - if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) + if (linedef->flags & ML_EFFECT3) rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz; else rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz; } - else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) + else if (linedef->flags & ML_EFFECT3) { rw_midtexturemid = worldbottom; rw_midtextureslide = floorfrontslide; From 55559a5f9841f6314307e9741760298949859bb7 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 5 Jan 2022 18:15:04 +0100 Subject: [PATCH 291/326] Split P_ConvertBinaryMap into multiple functions --- src/p_setup.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index f92fd46a9..18b12fee3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3304,12 +3304,9 @@ static void P_SetBinaryFOFAlpha(line_t *line) } } -//For maps in binary format, converts setup of specials to UDMF format. -static void P_ConvertBinaryMap(void) +static void P_ConvertBinaryLinedefTypes(void) { size_t i; - mobjtype_t mobjtypeofthing[4096] = {0}; - mobjtype_t mobjtype; for (i = 0; i < numlines; i++) { @@ -5128,6 +5125,11 @@ static void P_ConvertBinaryMap(void) lines[i].executordelay = 1; } } +} + +static void P_ConvertBinarySectorTypes(void) +{ + size_t i; for (i = 0; i < numsectors; i++) { @@ -5291,6 +5293,13 @@ static void P_ConvertBinaryMap(void) break; } } +} + +static void P_ConvertBinaryThingTypes(void) +{ + size_t i; + mobjtype_t mobjtypeofthing[4096] = {0}; + mobjtype_t mobjtype; for (i = 0; i < NUMMOBJTYPES; i++) { @@ -5852,6 +5861,11 @@ static void P_ConvertBinaryMap(void) break; } } +} + +static void P_ConvertBinaryLinedefFlags(void) +{ + size_t i; for (i = 0; i < numlines; i++) { @@ -5862,6 +5876,15 @@ static void P_ConvertBinaryMap(void) } } +//For maps in binary format, converts setup of specials to UDMF format. +static void P_ConvertBinaryMap(void) +{ + P_ConvertBinaryLinedefTypes(); + P_ConvertBinarySectorTypes(); + P_ConvertBinaryThingTypes(); + P_ConvertBinaryLinedefFlags(); +} + /** Compute MD5 message digest for bytes read from memory source * * The resulting message digest number will be written into the 16 bytes From 5f97047b9673f908af370520a9a36f14a14cc9ee Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 5 Jan 2022 18:40:02 +0100 Subject: [PATCH 292/326] Rename linedef flags --- src/deh_lua.c | 26 ++++++ src/deh_tables.c | 10 +-- src/doomdata.h | 10 +-- src/p_maputl.c | 10 +-- src/p_setup.c | 212 +++++++++++++++++++++++------------------------ 5 files changed, 147 insertions(+), 121 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index 9472c1e7b..bead7a325 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -335,6 +335,32 @@ static inline int lib_getenum(lua_State *L) lua_pushinteger(L, ((lua_Integer)1<z + mobj->height; // Check for collision with front side's midtexture if Effect 4 is set - if (linedef->flags & ML_EFFECT4 + if (linedef->flags & ML_MIDSOLID && !linedef->polyobj // don't do anything for polyobjects! ...for now ) { side_t *side = &sides[linedef->sidenum[0]]; @@ -508,10 +508,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) // don't remove this code unless solid midtextures // on non-solid polyobjects should NEVER happen in the future if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { - if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat + if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat texbottom = back->floorheight + side->rowoffset; textop = back->ceilingheight + side->rowoffset; - } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { + } else if (linedef->flags & ML_MIDTEX) { texbottom = back->floorheight + side->rowoffset; textop = texbottom + texheight*(side->repeatcnt+1); } else { @@ -521,10 +521,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) } else #endif { - if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat + if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat texbottom = openbottom + side->rowoffset; textop = opentop + side->rowoffset; - } else if (linedef->flags & ML_EFFECT3) { + } else if (linedef->flags & ML_MIDPEG) { texbottom = openbottom + side->rowoffset; textop = texbottom + texheight*(side->repeatcnt+1); } else { diff --git a/src/p_setup.c b/src/p_setup.c index 18b12fee3..fdd2f82d7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1210,7 +1210,7 @@ static void P_LoadSidedefs(UINT8 *data) isfrontside = sd->line->sidenum[0] == i; // Repeat count for midtexture - if (((sd->line->flags & (ML_TWOSIDED|ML_EFFECT5)) == (ML_TWOSIDED|ML_EFFECT5)) + if (((sd->line->flags & (ML_TWOSIDED|ML_WRAPMIDTEX)) == (ML_TWOSIDED|ML_WRAPMIDTEX)) && !(sd->special >= 300 && sd->special < 500)) // exempt linedef exec specials { sd->repeatcnt = (INT16)(((UINT16)textureoffset) >> 12); @@ -1841,17 +1841,17 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val) else if (fastcmp(param, "dontpegbottom") && fastcmp("true", val)) lines[i].flags |= ML_DONTPEGBOTTOM; else if (fastcmp(param, "skewtd") && fastcmp("true", val)) - lines[i].flags |= ML_EFFECT1; + lines[i].flags |= ML_SKEWTD; else if (fastcmp(param, "noclimb") && fastcmp("true", val)) lines[i].flags |= ML_NOCLIMB; else if (fastcmp(param, "noskew") && fastcmp("true", val)) - lines[i].flags |= ML_EFFECT2; + lines[i].flags |= ML_NOSKEW; else if (fastcmp(param, "midpeg") && fastcmp("true", val)) - lines[i].flags |= ML_EFFECT3; + lines[i].flags |= ML_MIDPEG; else if (fastcmp(param, "midsolid") && fastcmp("true", val)) - lines[i].flags |= ML_EFFECT4; + lines[i].flags |= ML_MIDSOLID; else if (fastcmp(param, "wrapmidtex") && fastcmp("true", val)) - lines[i].flags |= ML_EFFECT5; + lines[i].flags |= ML_WRAPMIDTEX; else if (fastcmp(param, "effect6") && fastcmp("true", val)) lines[i].flags |= ML_EFFECT6; else if (fastcmp(param, "nonet") && fastcmp("true", val)) @@ -3217,7 +3217,7 @@ static void P_AddBinaryMapTags(void) boolean matches_target_tag = target_tag && Tag_Find(§ors[j].tags, target_tag); size_t k; for (k = 0; k < 4; k++) { - if (lines[i].flags & ML_EFFECT5) { + if (lines[i].flags & ML_WRAPMIDTEX) { if (matches_target_tag || (offset_tags[k] && Tag_Find(§ors[j].tags, offset_tags[k]))) { Tag_Add(§ors[j].tags, tag); break; @@ -3323,13 +3323,13 @@ static void P_ConvertBinaryLinedefTypes(void) case 3: //Zoom tube parameters lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; - lines[i].args[2] = !!(lines[i].flags & ML_EFFECT4); + lines[i].args[2] = !!(lines[i].flags & ML_MIDSOLID); break; case 4: //Speed pad parameters lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) lines[i].args[1] |= TMSP_NOTELEPORT; - if (lines[i].flags & ML_EFFECT5) + if (lines[i].flags & ML_WRAPMIDTEX) lines[i].args[1] |= TMSP_FORCESPIN; P_WriteConstant(sides[lines[i].sidenum[0]].toptexture ? sides[lines[i].sidenum[0]].toptexture : sfx_spdpad, &lines[i].stringargs[0]); break; @@ -3378,15 +3378,15 @@ static void P_ConvertBinaryLinedefTypes(void) sectors[s].flags &= ~MSF_FLIPSPECIAL_FLOOR; sectors[s].flags |= MSF_FLIPSPECIAL_CEILING; } - else if (lines[i].flags & ML_EFFECT4) + else if (lines[i].flags & ML_MIDSOLID) sectors[s].flags |= MSF_FLIPSPECIAL_BOTH; - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) sectors[s].flags |= MSF_TRIGGERSPECIAL_TOUCH; - if (lines[i].flags & ML_EFFECT2) + if (lines[i].flags & ML_NOSKEW) sectors[s].flags |= MSF_TRIGGERSPECIAL_HEADBUMP; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) sectors[s].flags |= MSF_INVERTPRECIP; } @@ -3402,7 +3402,7 @@ static void P_ConvertBinaryLinedefTypes(void) case 11: //Rope hang parameters lines[i].args[0] = (lines[i].flags & ML_NOCLIMB) ? 0 : sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; - lines[i].args[2] = !!(lines[i].flags & ML_EFFECT1); + lines[i].args[2] = !!(lines[i].flags & ML_SKEWTD); break; case 13: //Heat wave effect { @@ -3416,7 +3416,7 @@ static void P_ConvertBinaryLinedefTypes(void) case 14: //Bustable block parameters lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; - lines[i].args[2] = !!(lines[i].flags & ML_EFFECT1); + lines[i].args[2] = !!(lines[i].flags & ML_SKEWTD); P_WriteConstant(sides[lines[i].sidenum[0]].toptexture, &lines[i].stringargs[0]); break; case 16: //Minecart parameters @@ -3456,15 +3456,15 @@ static void P_ConvertBinaryLinedefTypes(void) : ((lines[paramline].frontsector->floorheight >> FRACBITS) / 100); //Flags - if (lines[paramline].flags & ML_EFFECT1) + if (lines[paramline].flags & ML_SKEWTD) lines[i].args[3] |= TMPF_NOINSIDES; - if (lines[paramline].flags & ML_EFFECT2) + if (lines[paramline].flags & ML_NOSKEW) lines[i].args[3] |= TMPF_INTANGIBLE; - if (lines[paramline].flags & ML_EFFECT3) + if (lines[paramline].flags & ML_MIDPEG) lines[i].args[3] |= TMPF_PUSHABLESTOP; - if (lines[paramline].flags & ML_EFFECT4) + if (lines[paramline].flags & ML_MIDSOLID) lines[i].args[3] &= ~TMPF_INVISIBLEPLANES; - /*if (lines[paramline].flags & ML_EFFECT5) + /*if (lines[paramline].flags & ML_WRAPMIDTEX) lines[i].args[3] |= TMPF_DONTCLIPPLANES;*/ if (lines[paramline].flags & ML_EFFECT6) lines[i].args[3] |= TMPF_SPLAT; @@ -3488,7 +3488,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset ? sides[lines[i].sidenum[0]].rowoffset >> FRACBITS : 90; if (lines[i].flags & ML_NOCLIMB) lines[i].args[3] |= TMPR_DONTROTATEOTHERS; - else if (lines[i].flags & ML_EFFECT4) + else if (lines[i].flags & ML_MIDSOLID) lines[i].args[3] |= TMPR_ROTATEPLAYERS; break; case 50: //Instantly lower floor on level load @@ -3534,7 +3534,7 @@ static void P_ConvertBinaryLinedefTypes(void) case 62: //Crusher (Floor to ceiling) lines[i].args[0] = tag; lines[i].args[1] = lines[i].special - 61; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) { lines[i].args[2] = abs(lines[i].dx) >> FRACBITS; lines[i].args[3] = lines[i].args[2]; @@ -3604,9 +3604,9 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[3] |= TMFA_SPLAT; //Tangibility - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[4] |= TMFT_DONTBLOCKOTHERS; - if (lines[i].flags & ML_EFFECT2) + if (lines[i].flags & ML_NOSKEW) lines[i].args[4] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 100; @@ -3638,9 +3638,9 @@ static void P_ConvertBinaryLinedefTypes(void) //Flags if (lines[i].flags & ML_NOCLIMB) lines[i].args[3] |= TMFW_DOUBLESHADOW; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) lines[i].args[3] |= TMFW_COLORMAPONLY; - if (!(lines[i].flags & ML_EFFECT5)) + if (!(lines[i].flags & ML_WRAPMIDTEX)) lines[i].args[3] |= TMFW_NORIPPLE; //Goo? @@ -3694,9 +3694,9 @@ static void P_ConvertBinaryLinedefTypes(void) else lines[i].args[4] |= TMFT_INTANGIBLEBOTTOM|TMFT_INTANGIBLETOP; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[4] |= TMFT_DONTBLOCKOTHERS; - if (lines[i].flags & ML_EFFECT2) + if (lines[i].flags & ML_NOSKEW) lines[i].args[4] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 100; @@ -3762,9 +3762,9 @@ static void P_ConvertBinaryLinedefTypes(void) if (lines[i].flags & ML_EFFECT6) lines[i].args[4] |= TMFC_SPLAT; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; - if (lines[i].flags & ML_EFFECT2) + if (lines[i].flags & ML_NOSKEW) lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 170; @@ -3800,9 +3800,9 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[3] |= TMFA_SPLAT; //Tangibility - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[4] |= TMFT_DONTBLOCKOTHERS; - if (lines[i].flags & ML_EFFECT2) + if (lines[i].flags & ML_NOSKEW) lines[i].args[4] |= TMFT_DONTBLOCKPLAYER; if (lines[i].special >= 194) lines[i].args[4] |= TMFT_INTANGIBLEBOTTOM; @@ -3862,12 +3862,12 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[0] = tag; if (lines[i].flags & ML_NOCLIMB) lines[i].args[1] |= TMFM_BRICK; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[1] |= TMFM_INVISIBLE; break; case 251: //FOF: Thwomp block lines[i].args[0] = tag; - if (lines[i].flags & ML_EFFECT5) //Custom speeds + if (lines[i].flags & ML_WRAPMIDTEX) //Custom speeds { lines[i].args[1] = lines[i].dy >> FRACBITS; lines[i].args[2] = lines[i].dx >> FRACBITS; @@ -3877,7 +3877,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[1] = 80; lines[i].args[2] = 16; } - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) P_WriteConstant(sides[lines[i].sidenum[0]].textureoffset >> FRACBITS, &lines[i].stringargs[0]); break; case 252: //FOF: Shatter block @@ -3910,9 +3910,9 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[3] = TMFB_REGULAR; //Flags - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) lines[i].args[4] |= TMFB_PUSHABLES; - if (lines[i].flags & ML_EFFECT5) + if (lines[i].flags & ML_WRAPMIDTEX) { lines[i].args[4] |= TMFB_EXECUTOR; lines[i].args[5] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; @@ -3926,7 +3926,7 @@ static void P_ConvertBinaryLinedefTypes(void) break; case 257: //FOF: Quicksand lines[i].args[0] = tag; - if (!(lines[i].flags & ML_EFFECT5)) + if (!(lines[i].flags & ML_WRAPMIDTEX)) lines[i].args[1] = 1; //No ripple effect lines[i].args[2] = lines[i].dx >> FRACBITS; //Sinking speed lines[i].args[3] = lines[i].dy >> FRACBITS; //Friction @@ -3938,7 +3938,7 @@ static void P_ConvertBinaryLinedefTypes(void) P_SetBinaryFOFAlpha(&lines[i]); //Flags - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[3] |= TMFL_NOBOSSES; //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].flags & ML_EFFECT6 || lines[i].args[1] == 256) @@ -3986,7 +3986,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[2] = TMC_GTE; else lines[i].args[2] = TMC_EQUAL; - lines[i].args[3] = !!(lines[i].flags & ML_EFFECT4); + lines[i].args[3] = !!(lines[i].flags & ML_MIDSOLID); lines[i].special = 303; break; case 305: //Character ability - Continuous @@ -4026,7 +4026,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; if (lines[i].flags & ML_NOCLIMB) lines[i].args[2] = TMC_GTE; - else if (lines[i].flags & ML_EFFECT4) + else if (lines[i].flags & ML_MIDSOLID) lines[i].args[2] = TMC_LTE; else lines[i].args[2] = TMC_EQUAL; @@ -4077,15 +4077,15 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[3] = TMC_GTE; else lines[i].args[3] = TMC_EQUAL; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[4] = TMC_LTE; - else if (lines[i].flags & ML_EFFECT2) + else if (lines[i].flags & ML_NOSKEW) lines[i].args[4] = TMC_GTE; else lines[i].args[4] = TMC_EQUAL; if (lines[i].flags & ML_DONTPEGBOTTOM) lines[i].args[5] = TMNP_SLOWEST; - else if (lines[i].flags & ML_EFFECT4) + else if (lines[i].flags & ML_MIDSOLID) lines[i].args[5] = TMNP_TRIGGERER; else lines[i].args[5] = TMNP_FASTEST; @@ -4100,7 +4100,7 @@ static void P_ConvertBinaryLinedefTypes(void) else lines[i].args[6] = TMN_ALWAYS; - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) lines[i].args[7] |= TMN_BONUSLAPS; if (lines[i].flags & ML_BOUNCY) lines[i].args[7] |= TMN_LEVELCOMPLETION; @@ -4114,10 +4114,10 @@ static void P_ConvertBinaryLinedefTypes(void) else lines[i].args[6] = TMD_ALWAYS; - lines[i].args[7] = !!(lines[i].flags & ML_EFFECT3); + lines[i].args[7] = !!(lines[i].flags & ML_MIDPEG); } else if (lines[i].special == 327) - lines[i].args[6] = !!(lines[i].flags & ML_EFFECT3); + lines[i].args[6] = !!(lines[i].flags & ML_MIDPEG); else { if (lines[i].flags & ML_DONTPEGTOP) @@ -4127,7 +4127,7 @@ static void P_ConvertBinaryLinedefTypes(void) else lines[i].args[6] = TMS_IFENOUGH; - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) lines[i].args[7] |= TMI_BONUSLAPS; if (lines[i].flags & ML_TFERLINE) lines[i].args[7] |= TMI_ENTER; @@ -4229,14 +4229,14 @@ static void P_ConvertBinaryLinedefTypes(void) break; case 408: //Set flats lines[i].args[0] = tag; - if ((lines[i].flags & (ML_NOCLIMB|ML_EFFECT4)) == (ML_NOCLIMB|ML_EFFECT4)) + if ((lines[i].flags & (ML_NOCLIMB|ML_MIDSOLID)) == (ML_NOCLIMB|ML_MIDSOLID)) { CONS_Alert(CONS_WARNING, M_GetText("Set flats linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), tag); lines[i].special = 0; } else if (lines[i].flags & ML_NOCLIMB) lines[i].args[1] = TMP_CEILING; - else if (lines[i].flags & ML_EFFECT4) + else if (lines[i].flags & ML_MIDSOLID) lines[i].args[1] = TMP_FLOOR; else lines[i].args[1] = TMP_BOTH; @@ -4269,9 +4269,9 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[1] |= TMT_SILENT; if (lines[i].flags & ML_NOCLIMB) lines[i].args[1] |= TMT_KEEPANGLE; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) lines[i].args[1] |= TMT_KEEPMOMENTUM; - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) lines[i].args[1] |= TMT_RELATIVE; lines[i].args[2] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[3] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; @@ -4280,15 +4280,15 @@ static void P_ConvertBinaryLinedefTypes(void) case 413: //Change music if (lines[i].flags & ML_NOCLIMB) lines[i].args[0] |= TMM_ALLPLAYERS; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[0] |= TMM_OFFSET; - if (lines[i].flags & ML_EFFECT2) + if (lines[i].flags & ML_NOSKEW) lines[i].args[0] |= TMM_FADE; if (lines[i].flags & ML_BLOCKMONSTERS) lines[i].args[0] |= TMM_NORELOAD; if (lines[i].flags & ML_BOUNCY) lines[i].args[0] |= TMM_FORCERESET; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) lines[i].args[0] |= TMM_NOLOOP; lines[i].args[1] = sides[lines[i].sidenum[0]].midtexture; lines[i].args[2] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; @@ -4306,7 +4306,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[2] = tag; if (tag != 0) { - if (lines[i].flags & ML_EFFECT5) + if (lines[i].flags & ML_WRAPMIDTEX) { lines[i].args[0] = TMSS_TAGGEDSECTOR; lines[i].args[1] = TMSL_EVERYONE; @@ -4324,7 +4324,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[0] = TMSS_NOWHERE; lines[i].args[1] = TMSL_TRIGGERER; } - else if (lines[i].flags & ML_EFFECT4) + else if (lines[i].flags & ML_MIDSOLID) { lines[i].args[0] = TMSS_NOWHERE; lines[i].args[1] = TMSL_EVERYONE; @@ -4417,9 +4417,9 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[1] = lines[i].frontsector->lightlevel; lines[i].args[2] = abs(P_AproxDistance(lines[i].dx, lines[i].dy)) >> FRACBITS; } - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) lines[i].args[3] |= TMF_TICBASED; - if (lines[i].flags & ML_EFFECT5) + if (lines[i].flags & ML_WRAPMIDTEX) lines[i].args[3] |= TMF_OVERRIDE; break; case 421: //Stop lighting effect @@ -4460,7 +4460,7 @@ static void P_ConvertBinaryLinedefTypes(void) case 431: //Crush floor and ceiling once lines[i].args[0] = tag; lines[i].args[1] = (lines[i].special == 429) ? TMP_CEILING : ((lines[i].special == 430) ? TMP_FLOOR : TMP_BOTH); - if (lines[i].special == 430 || lines[i].flags & ML_EFFECT4) + if (lines[i].special == 430 || lines[i].flags & ML_MIDSOLID) { lines[i].args[2] = abs(lines[i].dx) >> FRACBITS; lines[i].args[3] = lines[i].args[2]; @@ -4563,19 +4563,19 @@ static void P_ConvertBinaryLinedefTypes(void) break; case 447: //Change colormap lines[i].args[0] = tag; - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) lines[i].args[2] |= TMCF_RELATIVE; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[2] |= TMCF_SUBLIGHTR|TMCF_SUBFADER; if (lines[i].flags & ML_NOCLIMB) lines[i].args[2] |= TMCF_SUBLIGHTG|TMCF_SUBFADEG; - if (lines[i].flags & ML_EFFECT2) + if (lines[i].flags & ML_NOSKEW) lines[i].args[2] |= TMCF_SUBLIGHTB|TMCF_SUBFADEB; break; case 448: //Change skybox lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; - if ((lines[i].flags & (ML_EFFECT4|ML_BLOCKMONSTERS)) == ML_EFFECT4) // Solid Midtexture is on but Block Enemies is off? + if ((lines[i].flags & (ML_MIDSOLID|ML_BLOCKMONSTERS)) == ML_MIDSOLID) // Solid Midtexture is on but Block Enemies is off? { CONS_Alert(CONS_WARNING, M_GetText("Skybox switch linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), @@ -4583,7 +4583,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].special = 0; break; } - else if ((lines[i].flags & (ML_EFFECT4|ML_BLOCKMONSTERS)) == (ML_EFFECT4|ML_BLOCKMONSTERS)) + else if ((lines[i].flags & (ML_MIDSOLID|ML_BLOCKMONSTERS)) == (ML_MIDSOLID|ML_BLOCKMONSTERS)) lines[i].args[2] = TMS_CENTERPOINT; else if (lines[i].flags & ML_BLOCKMONSTERS) lines[i].args[2] = TMS_BOTH; @@ -4606,7 +4606,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; lines[i].args[2] = lines[i].sidenum[1] != 0xffff ? (sides[lines[i].sidenum[1]].textureoffset >> FRACBITS) : (P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS); - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) lines[i].args[3] |= TMST_RELATIVE; if (lines[i].flags & ML_NOCLIMB) lines[i].args[3] |= TMST_DONTDOTRANSLUCENT; @@ -4616,21 +4616,21 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; lines[i].args[2] = lines[i].sidenum[1] != 0xffff ? (sides[lines[i].sidenum[1]].textureoffset >> FRACBITS) : (lines[i].dx >> FRACBITS); lines[i].args[3] = lines[i].sidenum[1] != 0xffff ? (sides[lines[i].sidenum[1]].rowoffset >> FRACBITS) : (abs(lines[i].dy) >> FRACBITS); - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) lines[i].args[4] |= TMFT_RELATIVE; - if (lines[i].flags & ML_EFFECT5) + if (lines[i].flags & ML_WRAPMIDTEX) lines[i].args[4] |= TMFT_OVERRIDE; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) lines[i].args[4] |= TMFT_TICBASED; if (lines[i].flags & ML_BOUNCY) lines[i].args[4] |= TMFT_IGNORECOLLISION; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[4] |= TMFT_GHOSTFADE; if (lines[i].flags & ML_NOCLIMB) lines[i].args[4] |= TMFT_DONTDOTRANSLUCENT; if (lines[i].flags & ML_BLOCKMONSTERS) lines[i].args[4] |= TMFT_DONTDOEXISTS; - if (lines[i].flags & ML_EFFECT2) + if (lines[i].flags & ML_NOSKEW) lines[i].args[4] |= (TMFT_DONTDOLIGHTING|TMFT_DONTDOCOLORMAP); if (lines[i].flags & ML_TFERLINE) lines[i].args[4] |= TMFT_USEEXACTALPHA; @@ -4647,21 +4647,21 @@ static void P_ConvertBinaryLinedefTypes(void) : abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS)); lines[i].args[0] = tag; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) lines[i].args[2] = speed; else lines[i].args[2] = (256 + speed - 1)/speed; - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) lines[i].args[3] |= TMCF_RELATIVE; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[3] |= TMCF_SUBLIGHTR|TMCF_SUBFADER; if (lines[i].flags & ML_NOCLIMB) lines[i].args[3] |= TMCF_SUBLIGHTG|TMCF_SUBFADEG; - if (lines[i].flags & ML_EFFECT2) + if (lines[i].flags & ML_NOSKEW) lines[i].args[3] |= TMCF_SUBLIGHTB|TMCF_SUBFADEB; if (lines[i].flags & ML_BOUNCY) lines[i].args[3] |= TMCF_FROMBLACK; - if (lines[i].flags & ML_EFFECT5) + if (lines[i].flags & ML_WRAPMIDTEX) lines[i].args[3] |= TMCF_OVERRIDE; break; } @@ -4673,25 +4673,25 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; lines[i].args[3] = (lines[i].sidenum[1] != 0xffff) ? sides[lines[i].sidenum[1]].rowoffset >> FRACBITS : 0; - lines[i].args[4] = !!(lines[i].flags & ML_EFFECT2); + lines[i].args[4] = !!(lines[i].flags & ML_NOSKEW); break; case 459: //Control text prompt lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; if (lines[i].flags & ML_BLOCKMONSTERS) lines[i].args[2] |= TMP_CLOSE; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[2] |= TMP_RUNPOSTEXEC; if (lines[i].flags & ML_TFERLINE) lines[i].args[2] |= TMP_CALLBYNAME; - if (lines[i].flags & ML_EFFECT2) + if (lines[i].flags & ML_NOSKEW) lines[i].args[2] |= TMP_KEEPCONTROLS; - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) lines[i].args[2] |= TMP_KEEPREALTIME; /*if (lines[i].flags & ML_NOCLIMB) lines[i].args[2] |= TMP_ALLPLAYERS; - if (lines[i].flags & ML_EFFECT4) - lines[i].args[2] |= ML_EFFECT4;*/ + if (lines[i].flags & ML_MIDSOLID) + lines[i].args[2] |= TMP_FREEZETHINKERS;*/ lines[i].args[3] = (lines[i].sidenum[1] != 0xFFFF) ? sides[lines[i].sidenum[1]].textureoffset >> FRACBITS : tag; if (sides[lines[i].sidenum[0]].text) { @@ -4707,7 +4707,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; lines[i].args[2] = lines[i].frontsector->floorheight >> FRACBITS; - lines[i].args[3] = (lines[i].flags & ML_EFFECT1) ? AngleFixed(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)) >> FRACBITS : 0; + lines[i].args[3] = (lines[i].flags & ML_SKEWTD) ? AngleFixed(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)) >> FRACBITS : 0; if (lines[i].flags & ML_NOCLIMB) { if (lines[i].sidenum[1] != 0xffff) // Make sure the linedef has a back side @@ -4749,7 +4749,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[0] = tag; lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[2] = TML_SECTOR; - lines[i].args[3] = !!(lines[i].flags & ML_EFFECT3); + lines[i].args[3] = !!(lines[i].flags & ML_MIDPEG); break; case 480: //Polyobject - door slide case 481: //Polyobject - door move @@ -4782,7 +4782,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[2] *= -1; if (lines[i].flags & ML_NOCLIMB) lines[i].args[3] |= TMPR_DONTROTATEOTHERS; - else if (lines[i].flags & ML_EFFECT4) + else if (lines[i].flags & ML_MIDSOLID) lines[i].args[3] |= TMPR_ROTATEPLAYERS; if (lines[i].special % 2 == 1) lines[i].args[3] |= TMPR_OVERRIDE; @@ -4792,15 +4792,15 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[0] = tag; lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) lines[i].args[3] = PWR_WRAP; - else if (lines[i].flags & ML_EFFECT2) + else if (lines[i].flags & ML_NOSKEW) lines[i].args[3] = PWR_COMEBACK; else lines[i].args[3] = PWR_STOP; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[4] |= PWF_REVERSE; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) lines[i].args[4] |= PWF_LOOP; break; case 489: //Polyobject - turn invisible, intangible @@ -4818,7 +4818,7 @@ static void P_ConvertBinaryLinedefTypes(void) // If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000. if (!(lines[i].flags & ML_DONTPEGBOTTOM)) lines[i].args[1] /= 100; - lines[i].args[2] = !!(lines[i].flags & ML_EFFECT3); + lines[i].args[2] = !!(lines[i].flags & ML_MIDPEG); break; case 492: //Polyobject - fade translucency lines[i].args[0] = tag; @@ -4831,15 +4831,15 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[2] = (lines[i].sidenum[1] != 0xffff && !sides[lines[i].sidenum[0]].rowoffset) ? abs(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS) : abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS); - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) lines[i].args[3] |= TMPF_RELATIVE; - if (lines[i].flags & ML_EFFECT5) + if (lines[i].flags & ML_WRAPMIDTEX) lines[i].args[3] |= TMPF_OVERRIDE; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) lines[i].args[3] |= TMPF_TICBASED; if (lines[i].flags & ML_BOUNCY) lines[i].args[3] |= TMPF_IGNORECOLLISION; - if (lines[i].flags & ML_EFFECT1) + if (lines[i].flags & ML_SKEWTD) lines[i].args[3] |= TMPF_GHOSTFADE; break; case 500: //Scroll front wall left @@ -4853,7 +4853,7 @@ static void P_ConvertBinaryLinedefTypes(void) case 503: //Scroll tagged wall (accelerative) case 504: //Scroll tagged wall (displacement) lines[i].args[0] = tag; - if (lines[i].flags & ML_EFFECT3) + if (lines[i].flags & ML_MIDPEG) { if (lines[i].sidenum[1] == 0xffff) { @@ -4865,7 +4865,7 @@ static void P_ConvertBinaryLinedefTypes(void) } else lines[i].args[1] = 0; - if (lines[i].flags & ML_EFFECT2) + if (lines[i].flags & ML_NOSKEW) { lines[i].args[2] = lines[i].dx >> (FRACBITS + SCROLL_SHIFT); lines[i].args[3] = lines[i].dy >> (FRACBITS + SCROLL_SHIFT); @@ -4955,7 +4955,7 @@ static void P_ConvertBinaryLinedefTypes(void) break; } lines[i].args[3] = (lines[i].special >= 544) ? p_current : p_wind; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) lines[i].args[4] |= TMPF_SLIDE; if (!(lines[i].flags & ML_NOCLIMB)) lines[i].args[4] |= TMPF_NONEXCLUSIVE; @@ -5714,15 +5714,15 @@ static void P_ConvertBinaryThingTypes(void) mapthings[i].args[8] |= TMM_SILENT; if (lines[j].flags & ML_NOCLIMB) mapthings[i].args[8] |= TMM_ALLOWYAWCONTROL; - if (lines[j].flags & ML_EFFECT1) + if (lines[j].flags & ML_SKEWTD) mapthings[i].args[8] |= TMM_SWING; - if (lines[j].flags & ML_EFFECT2) + if (lines[j].flags & ML_NOSKEW) mapthings[i].args[8] |= TMM_MACELINKS; - if (lines[j].flags & ML_EFFECT3) + if (lines[j].flags & ML_MIDPEG) mapthings[i].args[8] |= TMM_CENTERLINK; - if (lines[j].flags & ML_EFFECT4) + if (lines[j].flags & ML_MIDSOLID) mapthings[i].args[8] |= TMM_CLIP; - if (lines[j].flags & ML_EFFECT5) + if (lines[j].flags & ML_WRAPMIDTEX) mapthings[i].args[8] |= TMM_ALWAYSTHINK; if (mapthings[i].type == 1110) { @@ -5869,10 +5869,10 @@ static void P_ConvertBinaryLinedefFlags(void) for (i = 0; i < numlines; i++) { - if (!!(lines[i].flags & ML_DONTPEGBOTTOM) ^ !!(lines[i].flags & ML_EFFECT3)) - lines[i].flags |= ML_EFFECT3; + if (!!(lines[i].flags & ML_DONTPEGBOTTOM) ^ !!(lines[i].flags & ML_MIDPEG)) + lines[i].flags |= ML_MIDPEG; else - lines[i].flags &= ~ML_EFFECT3; + lines[i].flags &= ~ML_MIDPEG; } } From 2bef8da42f964def4c40bacb7a7f5a144b73c82f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 5 Jan 2022 18:42:53 +0100 Subject: [PATCH 293/326] Remove access to unused effect6 flag in UDMF --- extras/conf/udb/Includes/SRB222_misc.cfg | 1 - src/p_setup.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index e392014c8..544516f7d 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -58,7 +58,6 @@ linedefflags_udmf wrapmidtex = "Repeat Midtexture"; netonly = "Netgame Only"; nonet = "No Netgame"; - effect6 = "Effect 6"; bouncy = "Bouncy Wall"; transfer = "Transfer Line"; } diff --git a/src/p_setup.c b/src/p_setup.c index fdd2f82d7..7f1e00730 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1852,8 +1852,8 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val) lines[i].flags |= ML_MIDSOLID; else if (fastcmp(param, "wrapmidtex") && fastcmp("true", val)) lines[i].flags |= ML_WRAPMIDTEX; - else if (fastcmp(param, "effect6") && fastcmp("true", val)) - lines[i].flags |= ML_EFFECT6; + /*else if (fastcmp(param, "effect6") && fastcmp("true", val)) + lines[i].flags |= ML_EFFECT6;*/ else if (fastcmp(param, "nonet") && fastcmp("true", val)) lines[i].flags |= ML_NONET; else if (fastcmp(param, "netonly") && fastcmp("true", val)) From fcb69b9c2f10e9d0c3af6208a00381f36a122c4d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 5 Jan 2022 19:43:40 +0100 Subject: [PATCH 294/326] Rename more linedef flags --- src/hardware/hw_main.c | 28 ++++++++++++++-------------- src/p_ceilng.c | 2 +- src/p_spec.c | 6 +++--- src/r_segs.c | 20 ++++++++++---------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index dece1deda..bafe8ce7a 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1146,7 +1146,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // PEGGING if (gl_linedef->flags & ML_DONTPEGTOP) texturevpegtop = 0; - else if (gl_linedef->flags & ML_EFFECT1) + else if (gl_linedef->flags & ML_SKEWTD) texturevpegtop = worldhigh + textureheight[gl_sidedef->toptexture] - worldtop; else texturevpegtop = gl_backsector->ceilingheight + textureheight[gl_sidedef->toptexture] - gl_frontsector->ceilingheight; @@ -1162,7 +1162,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; // Adjust t value for sloped walls - if (!(gl_linedef->flags & ML_EFFECT1)) + if (!(gl_linedef->flags & ML_SKEWTD)) { // Unskewed wallVerts[3].t -= (worldtop - gl_frontsector->ceilingheight) * grTex->scaleY; @@ -1212,7 +1212,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // PEGGING if (!(gl_linedef->flags & ML_DONTPEGBOTTOM)) texturevpegbottom = 0; - else if (gl_linedef->flags & ML_EFFECT1) + else if (gl_linedef->flags & ML_SKEWTD) texturevpegbottom = worldbottom - worldlow; else texturevpegbottom = gl_frontsector->floorheight - gl_backsector->floorheight; @@ -1228,7 +1228,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; // Adjust t value for sloped walls - if (!(gl_linedef->flags & ML_EFFECT1)) + if (!(gl_linedef->flags & ML_SKEWTD)) { // Unskewed wallVerts[0].t -= (worldbottom - gl_frontsector->floorheight) * grTex->scaleY; @@ -1286,7 +1286,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (gl_sidedef->repeatcnt) repeats = 1 + gl_sidedef->repeatcnt; - else if (gl_linedef->flags & ML_EFFECT5) + else if (gl_linedef->flags & ML_WRAPMIDTEX) { fixed_t high, low; @@ -1328,9 +1328,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom popenbottom = max(worldbottom, worldlow); } - if (gl_linedef->flags & ML_EFFECT2) + if (gl_linedef->flags & ML_NOSKEW) { - if (gl_linedef->flags & ML_EFFECT3) + if (gl_linedef->flags & ML_MIDPEG) { polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset; polytop = polybottom + textureheight[gl_midtexture]*repeats; @@ -1341,7 +1341,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom polybottom = polytop - textureheight[gl_midtexture]*repeats; } } - else if (gl_linedef->flags & ML_EFFECT3) + else if (gl_linedef->flags & ML_MIDPEG) { polybottom = popenbottom + gl_sidedef->rowoffset; polytop = polybottom + textureheight[gl_midtexture]*repeats; @@ -1371,7 +1371,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { // PEGGING - if (gl_linedef->flags & ML_EFFECT3) + if (gl_linedef->flags & ML_MIDPEG) texturevpeg = textureheight[gl_sidedef->midtexture]*repeats - h + polybottom; else texturevpeg = polytop - h; @@ -1394,9 +1394,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { fixed_t midtextureslant; - if (gl_linedef->flags & ML_EFFECT2) + if (gl_linedef->flags & ML_NOSKEW) midtextureslant = 0; - else if (gl_linedef->flags & ML_EFFECT3) + else if (gl_linedef->flags & ML_MIDPEG) midtextureslant = worldlow < worldbottom ? worldbottomslope-worldbottom : worldlowslope-worldlow; @@ -1421,7 +1421,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { // PEGGING - if (gl_linedef->flags & ML_EFFECT3) + if (gl_linedef->flags & ML_MIDPEG) texturevpeg = textureheight[gl_sidedef->midtexture]*repeats - h + polybottom; else texturevpeg = polytop - h; @@ -1538,7 +1538,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { fixed_t texturevpeg; // PEGGING - if ((gl_linedef->flags & (ML_DONTPEGBOTTOM|ML_EFFECT2)) == (ML_DONTPEGBOTTOM|ML_EFFECT2)) + if ((gl_linedef->flags & (ML_DONTPEGBOTTOM|ML_NOSKEW)) == (ML_DONTPEGBOTTOM|ML_NOSKEW)) texturevpeg = gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight + gl_sidedef->rowoffset; else if (gl_linedef->flags & ML_DONTPEGBOTTOM) texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset; @@ -1554,7 +1554,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; // Texture correction for slopes - if (gl_linedef->flags & ML_EFFECT2) { + if (gl_linedef->flags & ML_NOSKEW) { wallVerts[3].t += (gl_frontsector->ceilingheight - worldtop) * grTex->scaleY; wallVerts[2].t += (gl_frontsector->ceilingheight - worldtopslope) * grTex->scaleY; wallVerts[0].t += (gl_frontsector->floorheight - worldbottom) * grTex->scaleY; diff --git a/src/p_ceilng.c b/src/p_ceilng.c index ed385be33..11d08724f 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -375,7 +375,7 @@ INT32 EV_DoCrush(mtag_t tag, line_t *line, ceiling_e type) ceiling->topheight = P_FindHighestCeilingSurrounding(sec); ceiling->direction = 1; // Retain stupid behavior for backwards compatibility - if (!udmf && !(line->flags & ML_EFFECT4)) + if (!udmf && !(line->flags & ML_MIDSOLID)) ceiling->speed /= 2; else ceiling->speed = line->args[3] << (FRACBITS - 2); diff --git a/src/p_spec.c b/src/p_spec.c index 9358d6766..53c7f9cc8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1647,7 +1647,7 @@ static boolean P_ActivateLinedefExecutorsInSector(line_t *triggerline, mobj_t *a size_t linecnt = ctlsector->linecount; size_t i; - if (triggerline->flags & ML_EFFECT5) // disregard order for efficiency + if (triggerline->flags & ML_WRAPMIDTEX) // disregard order for efficiency { for (i = 0; i < linecnt; i++) P_ActivateLinedefExecutor(ctlsector->lines[i], actor, caller); @@ -6812,9 +6812,9 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[4] & TMFB_ONLYBOTTOM) fflr->bustflags |= FB_ONLYBOTTOM; - if (lines[i].flags & ML_EFFECT4) + if (lines[i].flags & ML_MIDSOLID) fflr->bustflags |= FB_PUSHABLES; - if (lines[i].flags & ML_EFFECT5) + if (lines[i].flags & ML_WRAPMIDTEX) { fflr->bustflags |= FB_EXECUTOR; fflr->busttag = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; diff --git a/src/r_segs.c b/src/r_segs.c index 28968563e..f1a0d9596 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -301,7 +301,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (ds->curline->sidedef->repeatcnt) repeats = 1 + ds->curline->sidedef->repeatcnt; - else if (ldef->flags & ML_EFFECT5) + else if (ldef->flags & ML_WRAPMIDTEX) { fixed_t high, low; @@ -345,7 +345,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { dc_texturemid = ds->maskedtextureheight[dc_x]; - if (curline->linedef->flags & ML_EFFECT3) + if (curline->linedef->flags & ML_MIDPEG) dc_texturemid += (textureheight[texnum])*times + textureheight[texnum]; else dc_texturemid -= (textureheight[texnum])*times; @@ -1455,7 +1455,7 @@ static void R_RenderSegLoop (void) maskedtexturecol[rw_x] = (INT16)texturecolumn; if (maskedtextureheight != NULL) { - maskedtextureheight[rw_x] = (curline->linedef->flags & ML_EFFECT3) ? + maskedtextureheight[rw_x] = (curline->linedef->flags & ML_MIDPEG) ? max(rw_midtexturemid, rw_midtextureback) : min(rw_midtexturemid, rw_midtextureback); } @@ -1766,7 +1766,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) texheight = textureheight[midtexture]; // a single sided line is terminal, so it must mark ends markfloor = markceiling = true; - if (linedef->flags & ML_EFFECT2) { + if (linedef->flags & ML_NOSKEW) { if (linedef->flags & ML_DONTPEGBOTTOM) rw_midtexturemid = frontsector->floorheight + texheight - viewz; else @@ -1991,7 +1991,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) toptexture = R_GetTextureNum(sidedef->toptexture); texheight = textureheight[toptexture]; } - if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked + if (!(linedef->flags & ML_SKEWTD)) { // Ignore slopes for lower/upper textures unless flag is checked if (linedef->flags & ML_DONTPEGTOP) rw_toptexturemid = frontsector->ceilingheight - viewz; else @@ -2016,7 +2016,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) // bottom texture bottomtexture = R_GetTextureNum(sidedef->bottomtexture); - if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked + if (!(linedef->flags & ML_SKEWTD)) { // Ignore slopes for lower/upper textures unless flag is checked if (linedef->flags & ML_DONTPEGBOTTOM) rw_bottomtexturemid = frontsector->floorheight - viewz; else @@ -2247,7 +2247,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (curline->polyseg) { // use REAL front and back floors please, so midtexture rendering isn't mucked up rw_midtextureslide = rw_midtexturebackslide = 0; - if (linedef->flags & ML_EFFECT3) + if (linedef->flags & ML_MIDPEG) rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz; else rw_midtexturemid = rw_midtextureback = min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz; @@ -2255,16 +2255,16 @@ void R_StoreWallRange(INT32 start, INT32 stop) else { // Set midtexture starting height - if (linedef->flags & ML_EFFECT2) + if (linedef->flags & ML_NOSKEW) { // Ignore slopes when texturing rw_midtextureslide = rw_midtexturebackslide = 0; - if (linedef->flags & ML_EFFECT3) + if (linedef->flags & ML_MIDPEG) rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz; else rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz; } - else if (linedef->flags & ML_EFFECT3) + else if (linedef->flags & ML_MIDPEG) { rw_midtexturemid = worldbottom; rw_midtextureslide = floorfrontslide; From e406a52446fa3a3fb774e3e2a75c289e1c33fa27 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 5 Jan 2022 22:33:14 +0100 Subject: [PATCH 295/326] Remove weird special behavior for two-sided upper textures in software --- src/r_segs.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/r_segs.c b/src/r_segs.c index f1a0d9596..34ac23e60 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1975,22 +1975,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) { fixed_t texheight; // top texture - if ((linedef->flags & (ML_DONTPEGTOP) && (linedef->flags & ML_DONTPEGBOTTOM)) - && linedef->sidenum[1] != 0xffff) - { - // Special case... use offsets from 2nd side but only if it has a texture. - side_t *def = &sides[linedef->sidenum[1]]; - toptexture = R_GetTextureNum(def->toptexture); + toptexture = R_GetTextureNum(sidedef->toptexture); + texheight = textureheight[toptexture]; - if (!toptexture) //Second side has no texture, use the first side's instead. - toptexture = R_GetTextureNum(sidedef->toptexture); - texheight = textureheight[toptexture]; - } - else - { - toptexture = R_GetTextureNum(sidedef->toptexture); - texheight = textureheight[toptexture]; - } if (!(linedef->flags & ML_SKEWTD)) { // Ignore slopes for lower/upper textures unless flag is checked if (linedef->flags & ML_DONTPEGTOP) rw_toptexturemid = frontsector->ceilingheight - viewz; From 659410dde1b9159004e4d4bfc60aaab5121847a8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 5 Jan 2022 23:47:05 +0100 Subject: [PATCH 296/326] Use Slope Skew flag instead of Upper Unpegged for FOF skewing --- src/hardware/hw_main.c | 4 ++-- src/p_setup.c | 22 ++++++++++++++++++++++ src/r_segs.c | 4 ++-- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index bafe8ce7a..37b044e45 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1703,13 +1703,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { texturevpeg = sides[newline->sidenum[0]].rowoffset; attachtobottom = !!(newline->flags & ML_DONTPEGBOTTOM); - slopeskew = !!(newline->flags & ML_DONTPEGTOP); + slopeskew = !!(newline->flags & ML_SKEWTD); } else { texturevpeg = sides[rover->master->sidenum[0]].rowoffset; attachtobottom = !!(gl_linedef->flags & ML_DONTPEGBOTTOM); - slopeskew = !!(rover->master->flags & ML_DONTPEGTOP); + slopeskew = !!(rover->master->flags & ML_SKEWTD); } grTex = HWR_GetTexture(texnum); diff --git a/src/p_setup.c b/src/p_setup.c index 7f1e00730..717d2ddce 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5873,6 +5873,28 @@ static void P_ConvertBinaryLinedefFlags(void) lines[i].flags |= ML_MIDPEG; else lines[i].flags &= ~ML_MIDPEG; + + if (lines[i].special >= 100 && lines[i].special < 300) + { + if (lines[i].flags & ML_DONTPEGTOP) + lines[i].flags |= ML_SKEWTD; + else + lines[i].flags = ~ML_SKEWTD; + + if ((lines[i].flags & ML_TFERLINE) && lines[i].frontsector) + { + size_t j; + + for (j = 0; j < lines[i].frontsector->linecount; j++) + { + if (lines[i].frontsector->lines[j]->flags & ML_DONTPEGTOP) + lines[i].frontsector->lines[j]->flags |= ML_SKEWTD; + else + lines[i].frontsector->lines[j]->flags = ~ML_SKEWTD; + } + } + } + } } diff --git a/src/r_segs.c b/src/r_segs.c index 34ac23e60..78b7a50de 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -765,10 +765,10 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) skewslope = *pfloor->t_slope; // skew using top slope by default if (newline) { - if (newline->flags & ML_DONTPEGTOP) + if (newline->flags & ML_SKEWTD) slopeskew = true; } - else if (pfloor->master->flags & ML_DONTPEGTOP) + else if (pfloor->master->flags & ML_SKEWTD) slopeskew = true; if (slopeskew) From 1de5b777101febf6bcd09326d5278cfc9c16cd4a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 5 Jan 2022 23:47:05 +0100 Subject: [PATCH 297/326] Fix typo --- 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 717d2ddce..e3b71baef 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5879,7 +5879,7 @@ static void P_ConvertBinaryLinedefFlags(void) if (lines[i].flags & ML_DONTPEGTOP) lines[i].flags |= ML_SKEWTD; else - lines[i].flags = ~ML_SKEWTD; + lines[i].flags &= ~ML_SKEWTD; if ((lines[i].flags & ML_TFERLINE) && lines[i].frontsector) { @@ -5890,7 +5890,7 @@ static void P_ConvertBinaryLinedefFlags(void) if (lines[i].frontsector->lines[j]->flags & ML_DONTPEGTOP) lines[i].frontsector->lines[j]->flags |= ML_SKEWTD; else - lines[i].frontsector->lines[j]->flags = ~ML_SKEWTD; + lines[i].frontsector->lines[j]->flags &= ~ML_SKEWTD; } } } From 8b5f6cca37b6179e363f14175ab52e19d627ac79 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 7 Jan 2022 12:45:40 +0100 Subject: [PATCH 298/326] Add command line parameter for saving the current map in TEXTMAP format --- src/p_setup.c | 410 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 409 insertions(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index e3b71baef..817bd8fec 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1983,6 +1983,406 @@ static INT32 P_ColorToRGBA(INT32 color, UINT8 alpha) return R_PutRgbaRGBA(r, g, b, alpha); } +static INT32 P_RGBAToColor(INT32 rgba) +{ + UINT8 r = R_GetRgbaR(rgba); + UINT8 g = R_GetRgbaG(rgba); + UINT8 b = R_GetRgbaB(rgba); + return (r << 16) | (g << 8) | b; +} + +static void P_WriteTextmap(void) +{ + size_t i, j; + FILE *f; + char *filepath = va(pandf, srb2home, "TEXTMAP"); + mtag_t firsttag; + + f = fopen(filepath, "w"); + if (!f) + { + CONS_Alert(CONS_ERROR, M_GetText("Couldn't save map file %s\n"), filepath); + return; + } + + fprintf(f, "namespace = \"srb2\";\n"); + for (i = 0; i < nummapthings; i++) + { + fprintf(f, "thing // %d\n", i); + fprintf(f, "{\n"); + firsttag = Tag_FGet(&mapthings[i].tags); + if (firsttag != 0) + fprintf(f, "id = %d;\n", firsttag); + if (mapthings[i].tags.count > 1) + { + fprintf(f, "moreids = \""); + for (j = 1; j < mapthings[i].tags.count; j++) + { + if (j > 1) + fprintf(f, " "); + fprintf(f, " %d", mapthings[i].tags.tags[j]); + } + fprintf(f, "\";\n"); + } + fprintf(f, "x = %d;\n", mapthings[i].x); + fprintf(f, "y = %d;\n", mapthings[i].y); + if (mapthings[i].z != 0) + fprintf(f, "height = %d;\n", mapthings[i].z); + if (mapthings[i].angle != 0) + fprintf(f, "angle = %d;\n", mapthings[i].angle); + if (mapthings[i].pitch != 0) + fprintf(f, "pitch = %d;\n", mapthings[i].pitch); + if (mapthings[i].roll != 0) + fprintf(f, "roll = %d;\n", mapthings[i].roll); + if (mapthings[i].type != 0) + fprintf(f, "type = %d;\n", mapthings[i].type); + if (mapthings[i].scale != FRACUNIT) + fprintf(f, "scale = %f;\n", FIXED_TO_FLOAT(mapthings[i].scale)); + if (mapthings[i].options & MTF_OBJECTFLIP) + fprintf(f, "flip = true;\n"); + for (j = 0; j < NUMMAPTHINGARGS; j++) + if (mapthings[i].args[j] != 0) + fprintf(f, "arg%d = %d;\n", j, mapthings[i].args[j]); + for (j = 0; j < NUMMAPTHINGSTRINGARGS; j++) + if (mapthings[i].stringargs[j]) + fprintf(f, "stringarg%d = \"%s\";\n", j, mapthings[i].stringargs[j]); + fprintf(f, "}\n"); + fprintf(f, "\n"); + } + + for (i = 0; i < numvertexes; i++) + { + fprintf(f, "vertex // %d\n", i); + fprintf(f, "{\n"); + fprintf(f, "x = %f;\n", FIXED_TO_FLOAT(vertexes[i].x)); + fprintf(f, "y = %f;\n", FIXED_TO_FLOAT(vertexes[i].y)); + if (vertexes[i].floorzset) + fprintf(f, "zfloor = %f;\n", FIXED_TO_FLOAT(vertexes[i].floorz)); + if (vertexes[i].ceilingzset) + fprintf(f, "zceiling = %f;\n", FIXED_TO_FLOAT(vertexes[i].ceilingz)); + fprintf(f, "}\n"); + fprintf(f, "\n"); + } + + for (i = 0; i < numlines; i++) + { + fprintf(f, "linedef // %d\n", i); + fprintf(f, "{\n"); + firsttag = Tag_FGet(&lines[i].tags); + if (firsttag != 0) + fprintf(f, "id = %d;\n", firsttag); + if (lines[i].tags.count > 1) + { + fprintf(f, "moreids = \""); + for (j = 1; j < lines[i].tags.count; j++) + { + if (j > 1) + fprintf(f, " "); + fprintf(f, " %d", lines[i].tags.tags[j]); + } + fprintf(f, "\";\n"); + } + if (lines[i].special != 0) + fprintf(f, "special = %d;\n", lines[i].special); + fprintf(f, "v1 = %d;\n", lines[i].v1 - vertexes); + fprintf(f, "v2 = %d;\n", lines[i].v2 - vertexes); + for (j = 0; j < NUMLINEARGS; j++) + if (lines[i].args[j] != 0) + fprintf(f, "arg%d = %d;\n", j, lines[i].args[j]); + for (j = 0; j < NUMLINESTRINGARGS; j++) + if (lines[i].stringargs[j]) + fprintf(f, "stringarg%d = \"%s\";\n", j, lines[i].stringargs[j]); + fprintf(f, "sidefront = %d;\n", lines[i].sidenum[0]); + if (lines[i].sidenum[1] != 0xffff) + fprintf(f, "sideback = %d;\n", lines[i].sidenum[1]); + if (lines[i].alpha != FRACUNIT) + fprintf(f, "alpha = %f;\n", FIXED_TO_FLOAT(lines[i].alpha)); + if (lines[i].blendmode != AST_COPY) + { + switch (lines[i].blendmode) + { + case AST_ADD: + fprintf(f, "renderstyle = \"add\";\n"); + break; + case AST_SUBTRACT: + fprintf(f, "renderstyle = \"subtract\";\n"); + break; + case AST_REVERSESUBTRACT: + fprintf(f, "renderstyle = \"reversesubtract\";\n"); + break; + case AST_MODULATE: + fprintf(f, "renderstyle = \"modulate\";\n"); + break; + case AST_FOG: + fprintf(f, "renderstyle = \"fog\";\n"); + break; + default: + break; + } + } + if (lines[i].executordelay != 0) + fprintf(f, "executordelay = %d;\n", lines[i].executordelay); + if (lines[i].flags & ML_IMPASSIBLE) + fprintf(f, "blocking = true;\n"); + if (lines[i].flags & ML_BLOCKMONSTERS) + fprintf(f, "blockmonsters = true;\n"); + if (lines[i].flags & ML_TWOSIDED) + fprintf(f, "twosided = true;\n"); + if (lines[i].flags & ML_DONTPEGTOP) + fprintf(f, "dontpegtop = true;\n"); + if (lines[i].flags & ML_DONTPEGBOTTOM) + fprintf(f, "dontpegbottom = true;\n"); + if (lines[i].flags & ML_SKEWTD) + fprintf(f, "skewtd = true;\n"); + if (lines[i].flags & ML_NOCLIMB) + fprintf(f, "noclimb = true;\n"); + if (lines[i].flags & ML_NOSKEW) + fprintf(f, "noskew = true;\n"); + if (lines[i].flags & ML_MIDPEG) + fprintf(f, "midpeg = true;\n"); + if (lines[i].flags & ML_MIDSOLID) + fprintf(f, "midsolid = true;\n"); + if (lines[i].flags & ML_WRAPMIDTEX) + fprintf(f, "wrapmidtex = true;\n"); + if (lines[i].flags & ML_NONET) + fprintf(f, "nonet = true;\n"); + if (lines[i].flags & ML_NETONLY) + fprintf(f, "netonly = true;\n"); + if (lines[i].flags & ML_BOUNCY) + fprintf(f, "bouncy = true;\n"); + if (lines[i].flags & ML_TFERLINE) + fprintf(f, "transfer = true;\n"); + fprintf(f, "}\n"); + fprintf(f, "\n"); + } + + for (i = 0; i < numsides; i++) + { + fprintf(f, "sidedef // %d\n", i); + fprintf(f, "{\n"); + if (sides[i].textureoffset != 0) + fprintf(f, "offsetx = %d;\n", sides[i].textureoffset >> FRACBITS); + if (sides[i].rowoffset != 0) + fprintf(f, "offsety = %d;\n", sides[i].rowoffset >> FRACBITS); + if (sides[i].toptexture != 0) + fprintf(f, "texturetop = \"%.*s\";\n", 8, textures[sides[i].toptexture]->name); + if (sides[i].bottomtexture != 0) + fprintf(f, "texturebottom = \"%.*s\";\n", 8, textures[sides[i].bottomtexture]->name); + if (sides[i].midtexture != 0) + fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[sides[i].midtexture]->name); + fprintf(f, "sector = %d;\n", sides[i].sector - sectors); + if (sides[i].repeatcnt != 0) + fprintf(f, "repeatcnt = %d;\n", sides[i].repeatcnt); + fprintf(f, "}\n"); + fprintf(f, "\n"); + } + + for (i = 0; i < numsectors; i++) + { + fprintf(f, "sector // %d\n", i); + fprintf(f, "{\n"); + if (sectors[i].floorheight != 0) + fprintf(f, "heightfloor = %d;\n", sectors[i].floorheight >> FRACBITS); + if (sectors[i].ceilingheight != 0) + fprintf(f, "heightceiling = %d;\n", sectors[i].ceilingheight >> FRACBITS); + if (sectors[i].floorpic != -1) + fprintf(f, "texturefloor = \"%s\";\n", levelflats[sectors[i].floorpic].name); + if (sectors[i].ceilingpic != -1) + fprintf(f, "textureceiling = \"%s\";\n", levelflats[sectors[i].ceilingpic].name); + if (sectors[i].lightlevel != 255) + fprintf(f, "lightlevel = %d;\n", sectors[i].lightlevel); + if (sectors[i].floorlightlevel != 0) + fprintf(f, "lightfloor = %d;\n", sectors[i].floorlightlevel); + if (sectors[i].floorlightabsolute) + fprintf(f, "lightfloorabsolute = true;\n"); + if (sectors[i].ceilinglightlevel != 0) + fprintf(f, "lightceiling = %d;\n", sectors[i].ceilinglightlevel); + if (sectors[i].ceilinglightabsolute) + fprintf(f, "lightceilingabsolute = true;\n"); + firsttag = Tag_FGet(§ors[i].tags); + if (firsttag != 0) + fprintf(f, "id = %d;\n", firsttag); + if (sectors[i].tags.count > 1) + { + fprintf(f, "moreids = \""); + for (j = 1; j < sectors[i].tags.count; j++) + { + if (j > 1) + fprintf(f, " "); + fprintf(f, "%d", sectors[i].tags.tags[j]); + } + fprintf(f, "\";\n"); + } + //TODO: Un-fix offsets + if (sectors[i].floor_xoffs != 0) + fprintf(f, "xpanningfloor = %f;\n", FIXED_TO_FLOAT(sectors[i].floor_xoffs)); + if (sectors[i].floor_yoffs != 0) + fprintf(f, "ypanningfloor = %f;\n", FIXED_TO_FLOAT(sectors[i].floor_yoffs)); + if (sectors[i].ceiling_xoffs != 0) + fprintf(f, "xpanningceiling = %f;\n", FIXED_TO_FLOAT(sectors[i].ceiling_xoffs)); + if (sectors[i].ceiling_yoffs != 0) + fprintf(f, "ypanningceiling = %f;\n", FIXED_TO_FLOAT(sectors[i].ceiling_yoffs)); + if (sectors[i].floorpic_angle != 0) + fprintf(f, "rotationfloor = %f;\n", FIXED_TO_FLOAT(AngleFixed(sectors[i].floorpic_angle))); + if (sectors[i].ceilingpic_angle != 0) + fprintf(f, "rotationceiling = %f;\n", FIXED_TO_FLOAT(AngleFixed(sectors[i].ceilingpic_angle))); + //TODO: Only if slope was defined via equations + /*if (sectors[i].f_slope) + { + fixed_t a = sectors[i].f_slope->normal.x; + fixed_t b = sectors[i].f_slope->normal.y; + fixed_t c = sectors[i].f_slope->normal.z; + fixed_t d = -FV3_Dot(§ors[i].f_slope->normal, §ors[i].f_slope->o); + fprintf(f, "floorplane_a = %f;\n", FIXED_TO_FLOAT(a)); + fprintf(f, "floorplane_b = %f;\n", FIXED_TO_FLOAT(b)); + fprintf(f, "floorplane_c = %f;\n", FIXED_TO_FLOAT(c)); + fprintf(f, "floorplane_d = %f;\n", FIXED_TO_FLOAT(d)); + } + if (sectors[i].c_slope) + { + fixed_t a = sectors[i].c_slope->normal.x; + fixed_t b = sectors[i].c_slope->normal.y; + fixed_t c = sectors[i].c_slope->normal.z; + fixed_t d = -FV3_Dot(§ors[i].c_slope->normal, §ors[i].c_slope->o); + fprintf(f, "ceilingplane_a = %f;\n", FIXED_TO_FLOAT(a)); + fprintf(f, "ceilingplane_b = %f;\n", FIXED_TO_FLOAT(b)); + fprintf(f, "ceilingplane_c = %f;\n", FIXED_TO_FLOAT(c)); + fprintf(f, "ceilingplane_d = %f;\n", FIXED_TO_FLOAT(d)); + }*/ + if (sectors[i].extra_colormap) + { + INT32 lightcolor = P_RGBAToColor(sectors[i].extra_colormap->rgba); + UINT8 lightalpha = R_GetRgbaA(sectors[i].extra_colormap->rgba); + INT32 fadecolor = P_RGBAToColor(sectors[i].extra_colormap->fadergba); + UINT8 fadealpha = R_GetRgbaA(sectors[i].extra_colormap->fadergba); + + if (lightcolor != 0) + fprintf(f, "lightcolor = %d;\n", lightcolor); + if (lightalpha != 25) + fprintf(f, "lightalpha = %d;\n", lightalpha); + if (fadecolor != 0) + fprintf(f, "fadecolor = %d;\n", fadecolor); + if (fadealpha != 25) + fprintf(f, "fadealpha = %d;\n", fadealpha); + if (sectors[i].extra_colormap->fadestart != 0) + fprintf(f, "fadestart = %d;\n", sectors[i].extra_colormap->fadestart); + if (sectors[i].extra_colormap->fadeend != 31) + fprintf(f, "fadeend = %d;\n", sectors[i].extra_colormap->fadeend); + if (sectors[i].extra_colormap->flags & CMF_FOG) + fprintf(f, "colormapfog = true;\n"); + if (sectors[i].extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES) + fprintf(f, "colormapfadesprites = true;\n"); + } + if (sectors[i].colormap_protected) + fprintf(f, "colormapprotected = true;\n"); + if (!(sectors[i].flags & MSF_FLIPSPECIAL_FLOOR)) + fprintf(f, "flipspecial_nofloor = true;\n"); + if (sectors[i].flags & MSF_FLIPSPECIAL_CEILING) + fprintf(f, "flipspecial_ceiling = true;\n"); + if (sectors[i].flags & MSF_TRIGGERSPECIAL_TOUCH) + fprintf(f, "triggerspecial_touch = true;\n"); + if (sectors[i].flags & MSF_TRIGGERSPECIAL_HEADBUMP) + fprintf(f, "triggerspecial_headbump = true;\n"); + if (sectors[i].flags & MSF_TRIGGERLINE_PLANE) + fprintf(f, "triggerline_plane = true;\n"); + if (sectors[i].flags & MSF_TRIGGERLINE_MOBJ) + fprintf(f, "triggerline_mobj = true;\n"); + if (sectors[i].flags & MSF_INVERTPRECIP) + fprintf(f, "invertprecip = true;\n"); + if (sectors[i].flags & MSF_GRAVITYFLIP) + fprintf(f, "gravityflip = true;\n"); + if (sectors[i].flags & MSF_HEATWAVE) + fprintf(f, "heatwave = true;\n"); + if (sectors[i].flags & MSF_NOCLIPCAMERA) + fprintf(f, "noclipcamera = true;\n"); + if (sectors[i].specialflags & SSF_OUTERSPACE) + fprintf(f, "outerspace = true;\n"); + if (sectors[i].specialflags & SSF_DOUBLESTEPUP) + fprintf(f, "doublestepup = true;\n"); + if (sectors[i].specialflags & SSF_NOSTEPDOWN) + fprintf(f, "nostepdown = true;\n"); + if (sectors[i].specialflags & SSF_SPEEDPAD) + fprintf(f, "speedpad = true;\n"); + if (sectors[i].specialflags & SSF_STARPOSTACTIVATOR) + fprintf(f, "starpostactivator = true;\n"); + if (sectors[i].specialflags & SSF_EXIT) + fprintf(f, "exit = true;\n"); + if (sectors[i].specialflags & SSF_SPECIALSTAGEPIT) + fprintf(f, "specialstagepit = true;\n"); + if (sectors[i].specialflags & SSF_RETURNFLAG) + fprintf(f, "returnflag = true;\n"); + if (sectors[i].specialflags & SSF_REDTEAMBASE) + fprintf(f, "redteambase = true;\n"); + if (sectors[i].specialflags & SSF_BLUETEAMBASE) + fprintf(f, "blueteambase = true;\n"); + if (sectors[i].specialflags & SSF_FAN) + fprintf(f, "fan = true;\n"); + if (sectors[i].specialflags & SSF_SUPERTRANSFORM) + fprintf(f, "supertransform = true;\n"); + if (sectors[i].specialflags & SSF_FORCESPIN) + fprintf(f, "forcespin = true;\n"); + if (sectors[i].specialflags & SSF_ZOOMTUBESTART) + fprintf(f, "zoomtubestart = true;\n"); + if (sectors[i].specialflags & SSF_ZOOMTUBEEND) + fprintf(f, "zoomtubeend = true;\n"); + if (sectors[i].specialflags & SSF_FINISHLINE) + fprintf(f, "finishline = true;\n"); + if (sectors[i].specialflags & SSF_ROPEHANG) + fprintf(f, "ropehang = true;\n"); + //TODO: Float + if (sectors[i].friction != 0) + fprintf(f, "friction = %d;\n", sectors[i].friction); + if (sectors[i].gravity != FRACUNIT) + fprintf(f, "gravity = %f;\n", FIXED_TO_FLOAT(sectors[i].gravity)); + if (sectors[i].damagetype != SD_NONE) + { + switch (sectors[i].damagetype) + { + case SD_GENERIC: + fprintf(f, "damagetype = \"Generic\";\n"); + break; + case SD_WATER: + fprintf(f, "damagetype = \"Water\";\n"); + break; + case SD_FIRE: + fprintf(f, "damagetype = \"Fire\";\n"); + break; + case SD_LAVA: + fprintf(f, "damagetype = \"Lava\";\n"); + break; + case SD_ELECTRIC: + fprintf(f, "damagetype = \"Electric\";\n"); + break; + case SD_SPIKE: + fprintf(f, "damagetype = \"Spike\";\n"); + break; + case SD_DEATHPITTILT: + fprintf(f, "damagetype = \"DeathPitTilt\";\n"); + break; + case SD_DEATHPITNOTILT: + fprintf(f, "damagetype = \"DeathPitNoTilt\";\n"); + break; + case SD_INSTAKILL: + fprintf(f, "damagetype = \"Instakill\";\n"); + break; + case SD_SPECIALSTAGE: + fprintf(f, "damagetype = \"SpecialStage\";\n"); + break; + default: + break; + } + } + if (sectors[i].triggertag != 0) + fprintf(f, "triggertag = %d;\n", sectors[i].triggertag); + if (sectors[i].triggerer != 0) + fprintf(f, "triggerer = %d;\n", sectors[i].triggerer); + fprintf(f, "}\n"); + fprintf(f, "\n"); + } + + fclose(f); +} + /** Loads the textmap data, after obtaining the elements count and allocating their respective space. */ static void P_LoadTextmap(void) @@ -2587,11 +2987,17 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype linenum = (nodetype == NT_XGL3) ? READUINT32((*data)) : READUINT16((*data)); if (linenum != 0xFFFF && linenum >= numlines) - I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid linedef %d!\n", sizeu1(k), m, linenum); + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid linedef %d!\n", sizeu1(k), i, linenum); segs[k].glseg = (linenum == 0xFFFF); segs[k].linedef = (linenum == 0xFFFF) ? NULL : &lines[linenum]; segs[k].side = READUINT8((*data)); } + while (segs[subsectors[i].firstline].glseg) + { + subsectors[i].firstline++; + if (subsectors[i].firstline == k) + I_Error("P_LoadExtendedSubsectorsAndSegs: Subsector %d does not have any valid segs!", i); + } break; case NT_XNOD: @@ -5905,6 +6311,8 @@ static void P_ConvertBinaryMap(void) P_ConvertBinarySectorTypes(); P_ConvertBinaryThingTypes(); P_ConvertBinaryLinedefFlags(); + if (M_CheckParm("-writetextmap")) + P_WriteTextmap(); } /** Compute MD5 message digest for bytes read from memory source From 95ce2aca9800f480b53a61370f90242576178e2c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 7 Jan 2022 12:48:06 +0100 Subject: [PATCH 299/326] P_WriteTextmap: Update friction to float --- src/p_setup.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index e39675a55..e577dc340 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2331,9 +2331,8 @@ static void P_WriteTextmap(void) fprintf(f, "finishline = true;\n"); if (sectors[i].specialflags & SSF_ROPEHANG) fprintf(f, "ropehang = true;\n"); - //TODO: Float - if (sectors[i].friction != 0) - fprintf(f, "friction = %d;\n", sectors[i].friction); + if (sectors[i].friction != ORIG_FRICTION) + fprintf(f, "friction = %f;\n", FIXED_TO_FLOAT(sectors[i].friction)); if (sectors[i].gravity != FRACUNIT) fprintf(f, "gravity = %f;\n", FIXED_TO_FLOAT(sectors[i].gravity)); if (sectors[i].damagetype != SD_NONE) From 56b00fac54ec34c7bd653f5c4a666dd6870983dd Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 7 Jan 2022 13:39:25 +0100 Subject: [PATCH 300/326] P_WriteTextmap: Rearrange properties and remove some defaults --- src/p_setup.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index e577dc340..bfaaeab77 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2030,8 +2030,7 @@ static void P_WriteTextmap(void) fprintf(f, "y = %d;\n", mapthings[i].y); if (mapthings[i].z != 0) fprintf(f, "height = %d;\n", mapthings[i].z); - if (mapthings[i].angle != 0) - fprintf(f, "angle = %d;\n", mapthings[i].angle); + fprintf(f, "angle = %d;\n", mapthings[i].angle); if (mapthings[i].pitch != 0) fprintf(f, "pitch = %d;\n", mapthings[i].pitch); if (mapthings[i].roll != 0) @@ -2070,6 +2069,11 @@ static void P_WriteTextmap(void) { fprintf(f, "linedef // %d\n", i); fprintf(f, "{\n"); + fprintf(f, "v1 = %d;\n", lines[i].v1 - vertexes); + fprintf(f, "v2 = %d;\n", lines[i].v2 - vertexes); + fprintf(f, "sidefront = %d;\n", lines[i].sidenum[0]); + if (lines[i].sidenum[1] != 0xffff) + fprintf(f, "sideback = %d;\n", lines[i].sidenum[1]); firsttag = Tag_FGet(&lines[i].tags); if (firsttag != 0) fprintf(f, "id = %d;\n", firsttag); @@ -2086,17 +2090,12 @@ static void P_WriteTextmap(void) } if (lines[i].special != 0) fprintf(f, "special = %d;\n", lines[i].special); - fprintf(f, "v1 = %d;\n", lines[i].v1 - vertexes); - fprintf(f, "v2 = %d;\n", lines[i].v2 - vertexes); for (j = 0; j < NUMLINEARGS; j++) if (lines[i].args[j] != 0) fprintf(f, "arg%d = %d;\n", j, lines[i].args[j]); for (j = 0; j < NUMLINESTRINGARGS; j++) if (lines[i].stringargs[j]) fprintf(f, "stringarg%d = \"%s\";\n", j, lines[i].stringargs[j]); - fprintf(f, "sidefront = %d;\n", lines[i].sidenum[0]); - if (lines[i].sidenum[1] != 0xffff) - fprintf(f, "sideback = %d;\n", lines[i].sidenum[1]); if (lines[i].alpha != FRACUNIT) fprintf(f, "alpha = %f;\n", FIXED_TO_FLOAT(lines[i].alpha)); if (lines[i].blendmode != AST_COPY) @@ -2162,6 +2161,7 @@ static void P_WriteTextmap(void) { fprintf(f, "sidedef // %d\n", i); fprintf(f, "{\n"); + fprintf(f, "sector = %d;\n", sides[i].sector - sectors); if (sides[i].textureoffset != 0) fprintf(f, "offsetx = %d;\n", sides[i].textureoffset >> FRACBITS); if (sides[i].rowoffset != 0) @@ -2172,7 +2172,6 @@ static void P_WriteTextmap(void) fprintf(f, "texturebottom = \"%.*s\";\n", 8, textures[sides[i].bottomtexture]->name); if (sides[i].midtexture != 0) fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[sides[i].midtexture]->name); - fprintf(f, "sector = %d;\n", sides[i].sector - sectors); if (sides[i].repeatcnt != 0) fprintf(f, "repeatcnt = %d;\n", sides[i].repeatcnt); fprintf(f, "}\n"); @@ -2183,16 +2182,13 @@ static void P_WriteTextmap(void) { fprintf(f, "sector // %d\n", i); fprintf(f, "{\n"); - if (sectors[i].floorheight != 0) - fprintf(f, "heightfloor = %d;\n", sectors[i].floorheight >> FRACBITS); - if (sectors[i].ceilingheight != 0) - fprintf(f, "heightceiling = %d;\n", sectors[i].ceilingheight >> FRACBITS); + fprintf(f, "heightfloor = %d;\n", sectors[i].floorheight >> FRACBITS); + fprintf(f, "heightceiling = %d;\n", sectors[i].ceilingheight >> FRACBITS); if (sectors[i].floorpic != -1) fprintf(f, "texturefloor = \"%s\";\n", levelflats[sectors[i].floorpic].name); if (sectors[i].ceilingpic != -1) fprintf(f, "textureceiling = \"%s\";\n", levelflats[sectors[i].ceilingpic].name); - if (sectors[i].lightlevel != 255) - fprintf(f, "lightlevel = %d;\n", sectors[i].lightlevel); + fprintf(f, "lightlevel = %d;\n", sectors[i].lightlevel); if (sectors[i].floorlightlevel != 0) fprintf(f, "lightfloor = %d;\n", sectors[i].floorlightlevel); if (sectors[i].floorlightabsolute) From b05bcc46577f585ff72575e6d1bcff89f069d767 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 7 Jan 2022 15:44:56 +0100 Subject: [PATCH 301/326] P_WriteTextmap: Correct flat offsets --- src/p_setup.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 2ae303855..c6561a8a8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1977,6 +1977,29 @@ static void TextmapFixFlatOffsets(sector_t *sec) } } +static void TextmapUnfixFlatOffsets(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; + sec->floor_xoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + sec->floor_yoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % 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; + sec->ceiling_xoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + sec->ceiling_yoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + } +} + static INT32 P_ColorToRGBA(INT32 color, UINT8 alpha) { UINT8 r = (color >> 16) & 0xFF; @@ -2211,15 +2234,16 @@ static void P_WriteTextmap(void) } fprintf(f, "\";\n"); } - //TODO: Un-fix offsets - if (sectors[i].floor_xoffs != 0) - fprintf(f, "xpanningfloor = %f;\n", FIXED_TO_FLOAT(sectors[i].floor_xoffs)); - if (sectors[i].floor_yoffs != 0) - fprintf(f, "ypanningfloor = %f;\n", FIXED_TO_FLOAT(sectors[i].floor_yoffs)); - if (sectors[i].ceiling_xoffs != 0) - fprintf(f, "xpanningceiling = %f;\n", FIXED_TO_FLOAT(sectors[i].ceiling_xoffs)); - if (sectors[i].ceiling_yoffs != 0) - fprintf(f, "ypanningceiling = %f;\n", FIXED_TO_FLOAT(sectors[i].ceiling_yoffs)); + sector_t tempsec = sectors[i]; + TextmapUnfixFlatOffsets(&tempsec); + if (tempsec.floor_xoffs != 0) + fprintf(f, "xpanningfloor = %f;\n", FIXED_TO_FLOAT(tempsec.floor_xoffs)); + if (tempsec.floor_yoffs != 0) + fprintf(f, "ypanningfloor = %f;\n", FIXED_TO_FLOAT(tempsec.floor_yoffs)); + if (tempsec.ceiling_xoffs != 0) + fprintf(f, "xpanningceiling = %f;\n", FIXED_TO_FLOAT(tempsec.ceiling_xoffs)); + if (tempsec.ceiling_yoffs != 0) + fprintf(f, "ypanningceiling = %f;\n", FIXED_TO_FLOAT(tempsec.ceiling_yoffs)); if (sectors[i].floorpic_angle != 0) fprintf(f, "rotationfloor = %f;\n", FIXED_TO_FLOAT(AngleFixed(sectors[i].floorpic_angle))); if (sectors[i].ceilingpic_angle != 0) From 1269fe6c0e1d9fa22062b8aa079b5c877385e65c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 8 Jan 2022 13:17:15 +0100 Subject: [PATCH 302/326] Implement faster textmap parser --- src/doomdef.h | 7 ++- src/m_misc.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++--- src/p_setup.c | 71 ++++++++++----------- 3 files changed, 194 insertions(+), 50 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 41ec9ef33..1b86cc954 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -483,8 +483,11 @@ 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); +void M_TokenizerOpen(const char *inputString); +void M_TokenizerClose(void); +const char *M_TokenizerRead(UINT32 i); +UINT32 M_TokenizerGetEndPos(void); +void M_TokenizerSetEndPos(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 59783d5d3..d49307c7f 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1970,18 +1970,168 @@ void M_UnGetToken(void) endPos = oldendPos; } -/** Returns the current token's position. - */ -UINT32 M_GetTokenPos(void) +#define NUMTOKENS 2 +static const char *tokenizerInput = NULL; +static UINT32 tokenCapacity[NUMTOKENS] = {0}; +static char *tokenizerToken[NUMTOKENS] = {NULL}; +static UINT32 tokenizerStartPos = 0; +static UINT32 tokenizerEndPos = 0; +static UINT32 tokenizerInputLength = 0; +static UINT8 tokenizerInComment = 0; // 0 = not in comment, 1 = // Single-line, 2 = /* Multi-line */ + +void M_TokenizerOpen(const char *inputString) { - return endPos; + size_t i; + + tokenizerInput = inputString; + for (i = 0; i < NUMTOKENS; i++) + { + tokenCapacity[i] = 1024; + tokenizerToken[i] = (char*)Z_Malloc(tokenCapacity[i] * sizeof(char), PU_STATIC, NULL); + } + tokenizerInputLength = strlen(tokenizerInput); } -/** Sets the current token's position. - */ -void M_SetTokenPos(UINT32 newPos) +void M_TokenizerClose(void) { - endPos = newPos; + size_t i; + + tokenizerInput = NULL; + for (i = 0; i < NUMTOKENS; i++) + Z_Free(tokenizerToken[i]); + tokenizerStartPos = 0; + tokenizerEndPos = 0; + tokenizerInComment = 0; +} + +static void M_DetectComment(UINT32 *pos) +{ + if (tokenizerInComment) + return; + + if (*pos >= tokenizerInputLength - 1) + return; + + if (tokenizerInput[*pos] != '/') + return; + + //Single-line comment start + if (tokenizerInput[*pos + 1] == '/') + tokenizerInComment = 1; + //Multi-line comment start + else if (tokenizerInput[*pos + 1] == '*') + tokenizerInComment = 2; +} + +static void M_ReadTokenString(UINT32 i) +{ + UINT32 tokenLength = tokenizerEndPos - tokenizerStartPos; + if (tokenLength + 1 > tokenCapacity[i]) + { + tokenCapacity[i] = tokenLength + 1; + // Assign the memory. Don't forget an extra byte for the end of the string! + tokenizerToken[i] = (char *)Z_Malloc(tokenCapacity[i] * sizeof(char), PU_STATIC, NULL); + } + // Copy the string. + M_Memcpy(tokenizerToken[i], tokenizerInput + tokenizerStartPos, (size_t)tokenLength); + // Make the final character NUL. + tokenizerToken[i][tokenLength] = '\0'; +} + +const char *M_TokenizerRead(UINT32 i) +{ + if (!tokenizerInput) + return NULL; + + tokenizerStartPos = tokenizerEndPos; + + // Try to detect comments now, in case we're pointing right at one + M_DetectComment(&tokenizerStartPos); + + // Find the first non-whitespace char, or else the end of the string trying + while ((tokenizerInput[tokenizerStartPos] == ' ' + || tokenizerInput[tokenizerStartPos] == '\t' + || tokenizerInput[tokenizerStartPos] == '\r' + || tokenizerInput[tokenizerStartPos] == '\n' + || tokenizerInput[tokenizerStartPos] == '\0' + || tokenizerInput[tokenizerStartPos] == '=' || tokenizerInput[tokenizerStartPos] == ';' // UDMF TEXTMAP. + || tokenizerInComment != 0) + && tokenizerStartPos < tokenizerInputLength) + { + // Try to detect comment endings now + if (tokenizerInComment == 1 && tokenizerInput[tokenizerStartPos] == '\n') + tokenizerInComment = 0; // End of line for a single-line comment + else if (tokenizerInComment == 2 + && tokenizerStartPos < tokenizerInputLength - 1 + && tokenizerInput[tokenizerStartPos] == '*' + && tokenizerInput[tokenizerStartPos+1] == '/') + { + // End of multi-line comment + tokenizerInComment = 0; + tokenizerStartPos++; // Make damn well sure we're out of the comment ending at the end of it all + } + + tokenizerStartPos++; + M_DetectComment(&tokenizerStartPos); + } + + // If the end of the string is reached, no token is to be read + if (tokenizerStartPos == tokenizerInputLength) { + tokenizerEndPos = tokenizerInputLength; + return NULL; + } + // Else, if it's one of these three symbols, capture only this one character + else if (tokenizerInput[tokenizerStartPos] == ',' + || tokenizerInput[tokenizerStartPos] == '{' + || tokenizerInput[tokenizerStartPos] == '}') + { + tokenizerEndPos = tokenizerStartPos + 1; + tokenizerToken[i][0] = tokenizerInput[tokenizerStartPos]; + tokenizerToken[i][1] = '\0'; + return tokenizerToken[i]; + } + // Return entire string within quotes, except without the quotes. + else if (tokenizerInput[tokenizerStartPos] == '"') + { + tokenizerEndPos = ++tokenizerStartPos; + while (tokenizerInput[tokenizerEndPos] != '"' && tokenizerEndPos < tokenizerInputLength) + tokenizerEndPos++; + + M_ReadTokenString(i); + tokenizerEndPos++; + return tokenizerToken[i]; + } + + // 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. + tokenizerEndPos = tokenizerStartPos + 1; + while ((tokenizerInput[tokenizerEndPos] != ' ' + && tokenizerInput[tokenizerEndPos] != '\t' + && tokenizerInput[tokenizerEndPos] != '\r' + && tokenizerInput[tokenizerEndPos] != '\n' + && tokenizerInput[tokenizerEndPos] != ',' + && tokenizerInput[tokenizerEndPos] != '{' + && tokenizerInput[tokenizerEndPos] != '}' + && tokenizerInput[tokenizerEndPos] != '=' && tokenizerInput[tokenizerEndPos] != ';' // UDMF TEXTMAP. + && tokenizerInComment == 0) + && tokenizerEndPos < tokenizerInputLength) + { + tokenizerEndPos++; + // Try to detect comment starts now; if it's in a comment, we don't want it in this token + M_DetectComment(&tokenizerEndPos); + } + + M_ReadTokenString(i); + return tokenizerToken[i]; +} + +UINT32 M_TokenizerGetEndPos(void) +{ + return tokenizerEndPos; +} + +void M_TokenizerSetEndPos(UINT32 newPos) +{ + tokenizerEndPos = newPos; } /** Count bits in a number. diff --git a/src/p_setup.c b/src/p_setup.c index c6561a8a8..74f761f24 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1428,9 +1428,9 @@ UINT32 vertexesPos[UINT16_MAX]; UINT32 sectorsPos[UINT16_MAX]; // Determine total amount of map data in TEXTMAP. -static boolean TextmapCount(UINT8 *data, size_t size) +static boolean TextmapCount(size_t size) { - char *tkn = M_GetToken((char *)data); + const char *tkn = M_TokenizerRead(0); UINT8 brackets = 0; nummapthings = 0; @@ -1442,20 +1442,16 @@ static boolean TextmapCount(UINT8 *data, size_t size) // Look for namespace at the beginning. if (!fastcmp(tkn, "namespace")) { - Z_Free(tkn); CONS_Alert(CONS_ERROR, "No namespace at beginning of lump!\n"); return false; } - Z_Free(tkn); // Check if namespace is valid. - tkn = M_GetToken(NULL); + tkn = M_TokenizerRead(0); if (!fastcmp(tkn, "srb2")) CONS_Alert(CONS_WARNING, "Invalid namespace '%s', only 'srb2' is supported.\n", tkn); - Z_Free(tkn); - tkn = M_GetToken(NULL); - while (tkn && M_GetTokenPos() < size) + while ((tkn = M_TokenizerRead(0)) && M_TokenizerGetEndPos() < size) { // Avoid anything inside bracketed stuff, only look for external keywords. if (brackets) @@ -1467,24 +1463,19 @@ static boolean TextmapCount(UINT8 *data, size_t size) brackets++; // Check for valid fields. else if (fastcmp(tkn, "thing")) - mapthingsPos[nummapthings++] = M_GetTokenPos(); + mapthingsPos[nummapthings++] = M_TokenizerGetEndPos(); else if (fastcmp(tkn, "linedef")) - linesPos[numlines++] = M_GetTokenPos(); + linesPos[numlines++] = M_TokenizerGetEndPos(); else if (fastcmp(tkn, "sidedef")) - sidesPos[numsides++] = M_GetTokenPos(); + sidesPos[numsides++] = M_TokenizerGetEndPos(); else if (fastcmp(tkn, "vertex")) - vertexesPos[numvertexes++] = M_GetTokenPos(); + vertexesPos[numvertexes++] = M_TokenizerGetEndPos(); else if (fastcmp(tkn, "sector")) - sectorsPos[numsectors++] = M_GetTokenPos(); + sectorsPos[numsectors++] = M_TokenizerGetEndPos(); else CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn); - - Z_Free(tkn); - tkn = M_GetToken(NULL); } - Z_Free(tkn); - if (brackets) { CONS_Alert(CONS_ERROR, "Unclosed brackets detected in textmap lump.\n"); @@ -1494,7 +1485,7 @@ static boolean TextmapCount(UINT8 *data, size_t size) return true; } -static void ParseTextmapVertexParameter(UINT32 i, char *param, char *val) +static void ParseTextmapVertexParameter(UINT32 i, const char *param, const char *val) { if (fastcmp(param, "x")) vertexes[i].x = FLOAT_TO_FIXED(atof(val)); @@ -1541,7 +1532,7 @@ typedef struct textmap_plane_s { textmap_plane_t textmap_planefloor = {0, 0, 0, 0, 0}; textmap_plane_t textmap_planeceiling = {0, 0, 0, 0, 0}; -static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) +static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char *val) { if (fastcmp(param, "heightfloor")) sectors[i].floorheight = atol(val) << FRACBITS; @@ -1565,7 +1556,7 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) Tag_FSet(§ors[i].tags, atol(val)); else if (fastcmp(param, "moreids")) { - char* id = val; + const char* id = val; while (id) { Tag_Add(§ors[i].tags, atol(id)); @@ -1754,7 +1745,7 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) sectors[i].triggerer = atol(val); } -static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val) +static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char *val) { if (fastcmp(param, "offsetx")) sides[i].textureoffset = atol(val)<data, textmap->size)) + M_TokenizerOpen((char *)textmap->data); + if (!TextmapCount(textmap->size)) + { + M_TokenizerClose(); return false; + } } else { @@ -2704,7 +2692,10 @@ static boolean P_LoadMapData(const virtres_t *virt) // Load map data. if (udmf) + { P_LoadTextmap(); + M_TokenizerClose(); + } else { P_LoadVertices(virtvertexes->data); From 90cd009b23cbe8261c352e34bf4c363ddb65ec71 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 8 Jan 2022 16:58:55 +0100 Subject: [PATCH 303/326] Remove writethings because it no longer works properly with the binary-to-UDMF conversion --- src/d_netcmd.c | 2 +- src/m_cheat.c | 4 ++-- src/m_cheat.h | 2 +- src/p_setup.c | 4 ++-- src/p_setup.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index fe7e7678f..b0f776183 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -880,7 +880,7 @@ void D_RegisterClientCommands(void) // ingame object placing COM_AddCommand("objectplace", Command_ObjectPlace_f); - COM_AddCommand("writethings", Command_Writethings_f); + //COM_AddCommand("writethings", Command_Writethings_f); CV_RegisterVar(&cv_speed); CV_RegisterVar(&cv_opflags); CV_RegisterVar(&cv_ophoopflags); diff --git a/src/m_cheat.c b/src/m_cheat.c index 2f90b54ee..2b72905d5 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1428,14 +1428,14 @@ void OP_ObjectplaceMovement(player_t *player) // // Objectplace related commands. // -void Command_Writethings_f(void) +/*void Command_Writethings_f(void) { REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; REQUIRE_OBJECTPLACE; P_WriteThings(); -} +}*/ void Command_ObjectPlace_f(void) { diff --git a/src/m_cheat.h b/src/m_cheat.h index ee4ba5f55..5caeae59b 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -26,7 +26,7 @@ void cht_Init(void); // ObjectPlace // void Command_ObjectPlace_f(void); -void Command_Writethings_f(void); +//void Command_Writethings_f(void); extern consvar_t cv_opflags, cv_ophoopflags, cv_mapthingnum, cv_speed; //extern consvar_t cv_snapto, cv_grid; diff --git a/src/p_setup.c b/src/p_setup.c index 74f761f24..4ba794781 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -907,7 +907,7 @@ static void P_SpawnMapThings(boolean spawnemblems) } // Experimental groovy write function! -void P_WriteThings(void) +/*void P_WriteThings(void) { size_t i, length; mapthing_t *mt; @@ -942,7 +942,7 @@ void P_WriteThings(void) savebuf_p = NULL; CONS_Printf(M_GetText("newthings%d.lmp saved.\n"), gamemap); -} +}*/ // // MAP LOADING FUNCTIONS diff --git a/src/p_setup.h b/src/p_setup.h index c3c680fdd..0a7c2bd43 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -107,7 +107,7 @@ boolean P_AddFolder(const char *folderpath); boolean P_RunSOC(const char *socfilename); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num); -void P_WriteThings(void); +//void P_WriteThings(void); size_t P_PrecacheLevelFlats(void); void P_AllocMapHeader(INT16 i); From 8615e86a0b6c8ecbf3e74b1a67cd190aeb7e057b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 9 Jan 2022 09:27:39 +0100 Subject: [PATCH 304/326] P_WriteTextmap: Don't try to write invalid textures --- 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 4ba794781..32d3e93a4 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2173,11 +2173,11 @@ static void P_WriteTextmap(void) fprintf(f, "offsetx = %d;\n", sides[i].textureoffset >> FRACBITS); if (sides[i].rowoffset != 0) fprintf(f, "offsety = %d;\n", sides[i].rowoffset >> FRACBITS); - if (sides[i].toptexture != 0) + if (sides[i].toptexture > 0 && sides[i].toptexture < numtextures) fprintf(f, "texturetop = \"%.*s\";\n", 8, textures[sides[i].toptexture]->name); - if (sides[i].bottomtexture != 0) + if (sides[i].bottomtexture > 0 && sides[i].bottomtexture < numtextures) fprintf(f, "texturebottom = \"%.*s\";\n", 8, textures[sides[i].bottomtexture]->name); - if (sides[i].midtexture != 0) + if (sides[i].midtexture > 0 && sides[i].midtexture < numtextures) fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[sides[i].midtexture]->name); if (sides[i].repeatcnt != 0) fprintf(f, "repeatcnt = %d;\n", sides[i].repeatcnt); From a46619684ff5d2c7fd9d19cbeabea4a47e7da582 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 9 Jan 2022 09:30:15 +0100 Subject: [PATCH 305/326] Disable NiGHTS objectplace, which serves no purpose anymore without writethings --- src/m_cheat.c | 4 ++-- src/m_cheat.h | 2 +- src/p_user.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/m_cheat.c b/src/m_cheat.c index 2b72905d5..8c8e48447 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1137,7 +1137,7 @@ void OP_ResetObjectplace(void) // // Main meat of objectplace: handling functions // -void OP_NightsObjectplace(player_t *player) +/*void OP_NightsObjectplace(player_t *player) { ticcmd_t *cmd = &player->cmd; mapthing_t *mt; @@ -1290,7 +1290,7 @@ void OP_NightsObjectplace(player_t *player) else P_SpawnMapThing(mt); } -} +}*/ // // OP_ObjectplaceMovement diff --git a/src/m_cheat.h b/src/m_cheat.h index 5caeae59b..2707332d3 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -38,7 +38,7 @@ extern UINT32 op_displayflags; boolean OP_FreezeObjectplace(void); void OP_ResetObjectplace(void); -void OP_NightsObjectplace(player_t *player); +//void OP_NightsObjectplace(player_t *player); void OP_ObjectplaceMovement(player_t *player); // diff --git a/src/p_user.c b/src/p_user.c index a24848d51..658b97634 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7520,8 +7520,8 @@ static void P_NiGHTSMovement(player_t *player) } } - if (objectplacing) - OP_NightsObjectplace(player); + //if (objectplacing) + // OP_NightsObjectplace(player); } // May be used in future for CTF From c1f03e77201d3c07f7c8d121866a6501bb19f1c0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 9 Jan 2022 10:22:25 +0100 Subject: [PATCH 306/326] P_WriteTextmap: Convert colormaps --- src/p_setup.c | 323 ++++++++++++++++++++++++++++---------------------- 1 file changed, 181 insertions(+), 142 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 32d3e93a4..51ea552a8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2006,6 +2006,11 @@ static void P_WriteTextmap(void) FILE *f; char *filepath = va(pandf, srb2home, "TEXTMAP"); mtag_t firsttag; + mapthing_t *wmapthings; + vertex_t *wvertexes; + sector_t *wsectors; + line_t *wlines; + side_t *wsides; f = fopen(filepath, "w"); if (!f) @@ -2014,6 +2019,34 @@ static void P_WriteTextmap(void) return; } + wmapthings = Z_Calloc(nummapthings * sizeof(*mapthings), PU_LEVEL, NULL); + wvertexes = Z_Calloc(numvertexes * sizeof(*vertexes), PU_LEVEL, NULL); + wsectors = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL); + wlines = Z_Calloc(numlines * sizeof(*lines), PU_LEVEL, NULL); + wsides = Z_Calloc(numsides * sizeof(*sides), PU_LEVEL, NULL); + + memcpy(wmapthings, mapthings, nummapthings * sizeof(*mapthings)); + memcpy(wvertexes, vertexes, numvertexes * sizeof(*vertexes)); + memcpy(wsectors, sectors, numsectors * sizeof(*sectors)); + memcpy(wlines, lines, numlines * sizeof(*lines)); + memcpy(wsides, sides, numsides * sizeof(*sides)); + + for (i = 0; i < numlines; i++) + { + INT32 s; + + if (wlines[i].special != 606) + continue; + + TAG_ITER_SECTORS(wlines[i].args[0], s) + { + if (wsectors[s].colormap_protected) + continue; + + wsectors[s].extra_colormap = wsides[wlines[i].sidenum[0]].colormap_data; + } + } + fprintf(f, "namespace = \"srb2\";\n"); for (i = 0; i < nummapthings; i++) { @@ -2033,24 +2066,24 @@ static void P_WriteTextmap(void) } fprintf(f, "\";\n"); } - fprintf(f, "x = %d;\n", mapthings[i].x); - fprintf(f, "y = %d;\n", mapthings[i].y); - if (mapthings[i].z != 0) - fprintf(f, "height = %d;\n", mapthings[i].z); - fprintf(f, "angle = %d;\n", mapthings[i].angle); - if (mapthings[i].pitch != 0) - fprintf(f, "pitch = %d;\n", mapthings[i].pitch); - if (mapthings[i].roll != 0) - fprintf(f, "roll = %d;\n", mapthings[i].roll); - if (mapthings[i].type != 0) - fprintf(f, "type = %d;\n", mapthings[i].type); - if (mapthings[i].scale != FRACUNIT) - fprintf(f, "scale = %f;\n", FIXED_TO_FLOAT(mapthings[i].scale)); - if (mapthings[i].options & MTF_OBJECTFLIP) + fprintf(f, "x = %d;\n", wmapthings[i].x); + fprintf(f, "y = %d;\n", wmapthings[i].y); + if (wmapthings[i].z != 0) + fprintf(f, "height = %d;\n", wmapthings[i].z); + fprintf(f, "angle = %d;\n", wmapthings[i].angle); + if (wmapthings[i].pitch != 0) + fprintf(f, "pitch = %d;\n", wmapthings[i].pitch); + if (wmapthings[i].roll != 0) + fprintf(f, "roll = %d;\n", wmapthings[i].roll); + if (wmapthings[i].type != 0) + fprintf(f, "type = %d;\n", wmapthings[i].type); + if (wmapthings[i].scale != FRACUNIT) + fprintf(f, "scale = %f;\n", FIXED_TO_FLOAT(wmapthings[i].scale)); + if (wmapthings[i].options & MTF_OBJECTFLIP) fprintf(f, "flip = true;\n"); for (j = 0; j < NUMMAPTHINGARGS; j++) - if (mapthings[i].args[j] != 0) - fprintf(f, "arg%d = %d;\n", j, mapthings[i].args[j]); + if (wmapthings[i].args[j] != 0) + fprintf(f, "arg%d = %d;\n", j, wmapthings[i].args[j]); for (j = 0; j < NUMMAPTHINGSTRINGARGS; j++) if (mapthings[i].stringargs[j]) fprintf(f, "stringarg%d = \"%s\";\n", j, mapthings[i].stringargs[j]); @@ -2062,12 +2095,12 @@ static void P_WriteTextmap(void) { fprintf(f, "vertex // %d\n", i); fprintf(f, "{\n"); - fprintf(f, "x = %f;\n", FIXED_TO_FLOAT(vertexes[i].x)); - fprintf(f, "y = %f;\n", FIXED_TO_FLOAT(vertexes[i].y)); - if (vertexes[i].floorzset) - fprintf(f, "zfloor = %f;\n", FIXED_TO_FLOAT(vertexes[i].floorz)); - if (vertexes[i].ceilingzset) - fprintf(f, "zceiling = %f;\n", FIXED_TO_FLOAT(vertexes[i].ceilingz)); + fprintf(f, "x = %f;\n", FIXED_TO_FLOAT(wvertexes[i].x)); + fprintf(f, "y = %f;\n", FIXED_TO_FLOAT(wvertexes[i].y)); + if (wvertexes[i].floorzset) + fprintf(f, "zfloor = %f;\n", FIXED_TO_FLOAT(wvertexes[i].floorz)); + if (wvertexes[i].ceilingzset) + fprintf(f, "zceiling = %f;\n", FIXED_TO_FLOAT(wvertexes[i].ceilingz)); fprintf(f, "}\n"); fprintf(f, "\n"); } @@ -2076,11 +2109,11 @@ static void P_WriteTextmap(void) { fprintf(f, "linedef // %d\n", i); fprintf(f, "{\n"); - fprintf(f, "v1 = %d;\n", lines[i].v1 - vertexes); - fprintf(f, "v2 = %d;\n", lines[i].v2 - vertexes); - fprintf(f, "sidefront = %d;\n", lines[i].sidenum[0]); - if (lines[i].sidenum[1] != 0xffff) - fprintf(f, "sideback = %d;\n", lines[i].sidenum[1]); + fprintf(f, "v1 = %d;\n", wlines[i].v1 - vertexes); + fprintf(f, "v2 = %d;\n", wlines[i].v2 - vertexes); + fprintf(f, "sidefront = %d;\n", wlines[i].sidenum[0]); + if (wlines[i].sidenum[1] != 0xffff) + fprintf(f, "sideback = %d;\n", wlines[i].sidenum[1]); firsttag = Tag_FGet(&lines[i].tags); if (firsttag != 0) fprintf(f, "id = %d;\n", firsttag); @@ -2095,19 +2128,19 @@ static void P_WriteTextmap(void) } fprintf(f, "\";\n"); } - if (lines[i].special != 0) - fprintf(f, "special = %d;\n", lines[i].special); + if (wlines[i].special != 0) + fprintf(f, "special = %d;\n", wlines[i].special); for (j = 0; j < NUMLINEARGS; j++) - if (lines[i].args[j] != 0) - fprintf(f, "arg%d = %d;\n", j, lines[i].args[j]); + if (wlines[i].args[j] != 0) + fprintf(f, "arg%d = %d;\n", j, wlines[i].args[j]); for (j = 0; j < NUMLINESTRINGARGS; j++) if (lines[i].stringargs[j]) fprintf(f, "stringarg%d = \"%s\";\n", j, lines[i].stringargs[j]); - if (lines[i].alpha != FRACUNIT) - fprintf(f, "alpha = %f;\n", FIXED_TO_FLOAT(lines[i].alpha)); - if (lines[i].blendmode != AST_COPY) + if (wlines[i].alpha != FRACUNIT) + fprintf(f, "alpha = %f;\n", FIXED_TO_FLOAT(wlines[i].alpha)); + if (wlines[i].blendmode != AST_COPY) { - switch (lines[i].blendmode) + switch (wlines[i].blendmode) { case AST_ADD: fprintf(f, "renderstyle = \"add\";\n"); @@ -2128,37 +2161,37 @@ static void P_WriteTextmap(void) break; } } - if (lines[i].executordelay != 0) - fprintf(f, "executordelay = %d;\n", lines[i].executordelay); - if (lines[i].flags & ML_IMPASSIBLE) + if (wlines[i].executordelay != 0) + fprintf(f, "executordelay = %d;\n", wlines[i].executordelay); + if (wlines[i].flags & ML_IMPASSIBLE) fprintf(f, "blocking = true;\n"); - if (lines[i].flags & ML_BLOCKMONSTERS) + if (wlines[i].flags & ML_BLOCKMONSTERS) fprintf(f, "blockmonsters = true;\n"); - if (lines[i].flags & ML_TWOSIDED) + if (wlines[i].flags & ML_TWOSIDED) fprintf(f, "twosided = true;\n"); - if (lines[i].flags & ML_DONTPEGTOP) + if (wlines[i].flags & ML_DONTPEGTOP) fprintf(f, "dontpegtop = true;\n"); - if (lines[i].flags & ML_DONTPEGBOTTOM) + if (wlines[i].flags & ML_DONTPEGBOTTOM) fprintf(f, "dontpegbottom = true;\n"); - if (lines[i].flags & ML_SKEWTD) + if (wlines[i].flags & ML_SKEWTD) fprintf(f, "skewtd = true;\n"); - if (lines[i].flags & ML_NOCLIMB) + if (wlines[i].flags & ML_NOCLIMB) fprintf(f, "noclimb = true;\n"); - if (lines[i].flags & ML_NOSKEW) + if (wlines[i].flags & ML_NOSKEW) fprintf(f, "noskew = true;\n"); - if (lines[i].flags & ML_MIDPEG) + if (wlines[i].flags & ML_MIDPEG) fprintf(f, "midpeg = true;\n"); - if (lines[i].flags & ML_MIDSOLID) + if (wlines[i].flags & ML_MIDSOLID) fprintf(f, "midsolid = true;\n"); - if (lines[i].flags & ML_WRAPMIDTEX) + if (wlines[i].flags & ML_WRAPMIDTEX) fprintf(f, "wrapmidtex = true;\n"); - if (lines[i].flags & ML_NONET) + if (wlines[i].flags & ML_NONET) fprintf(f, "nonet = true;\n"); - if (lines[i].flags & ML_NETONLY) + if (wlines[i].flags & ML_NETONLY) fprintf(f, "netonly = true;\n"); - if (lines[i].flags & ML_BOUNCY) + if (wlines[i].flags & ML_BOUNCY) fprintf(f, "bouncy = true;\n"); - if (lines[i].flags & ML_TFERLINE) + if (wlines[i].flags & ML_TFERLINE) fprintf(f, "transfer = true;\n"); fprintf(f, "}\n"); fprintf(f, "\n"); @@ -2168,19 +2201,19 @@ static void P_WriteTextmap(void) { fprintf(f, "sidedef // %d\n", i); fprintf(f, "{\n"); - fprintf(f, "sector = %d;\n", sides[i].sector - sectors); - if (sides[i].textureoffset != 0) - fprintf(f, "offsetx = %d;\n", sides[i].textureoffset >> FRACBITS); - if (sides[i].rowoffset != 0) - fprintf(f, "offsety = %d;\n", sides[i].rowoffset >> FRACBITS); - if (sides[i].toptexture > 0 && sides[i].toptexture < numtextures) - fprintf(f, "texturetop = \"%.*s\";\n", 8, textures[sides[i].toptexture]->name); - if (sides[i].bottomtexture > 0 && sides[i].bottomtexture < numtextures) - fprintf(f, "texturebottom = \"%.*s\";\n", 8, textures[sides[i].bottomtexture]->name); - if (sides[i].midtexture > 0 && sides[i].midtexture < numtextures) - fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[sides[i].midtexture]->name); - if (sides[i].repeatcnt != 0) - fprintf(f, "repeatcnt = %d;\n", sides[i].repeatcnt); + fprintf(f, "sector = %d;\n", wsides[i].sector - sectors); + if (wsides[i].textureoffset != 0) + fprintf(f, "offsetx = %d;\n", wsides[i].textureoffset >> FRACBITS); + if (wsides[i].rowoffset != 0) + fprintf(f, "offsety = %d;\n", wsides[i].rowoffset >> FRACBITS); + if (wsides[i].toptexture > 0 && wsides[i].toptexture < numtextures) + fprintf(f, "texturetop = \"%.*s\";\n", 8, textures[wsides[i].toptexture]->name); + if (wsides[i].bottomtexture > 0 && wsides[i].bottomtexture < numtextures) + fprintf(f, "texturebottom = \"%.*s\";\n", 8, textures[wsides[i].bottomtexture]->name); + if (wsides[i].midtexture > 0 && wsides[i].midtexture < numtextures) + fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[wsides[i].midtexture]->name); + if (wsides[i].repeatcnt != 0) + fprintf(f, "repeatcnt = %d;\n", wsides[i].repeatcnt); fprintf(f, "}\n"); fprintf(f, "\n"); } @@ -2189,20 +2222,20 @@ static void P_WriteTextmap(void) { fprintf(f, "sector // %d\n", i); fprintf(f, "{\n"); - fprintf(f, "heightfloor = %d;\n", sectors[i].floorheight >> FRACBITS); - fprintf(f, "heightceiling = %d;\n", sectors[i].ceilingheight >> FRACBITS); - if (sectors[i].floorpic != -1) - fprintf(f, "texturefloor = \"%s\";\n", levelflats[sectors[i].floorpic].name); - if (sectors[i].ceilingpic != -1) - fprintf(f, "textureceiling = \"%s\";\n", levelflats[sectors[i].ceilingpic].name); - fprintf(f, "lightlevel = %d;\n", sectors[i].lightlevel); - if (sectors[i].floorlightlevel != 0) - fprintf(f, "lightfloor = %d;\n", sectors[i].floorlightlevel); - if (sectors[i].floorlightabsolute) + fprintf(f, "heightfloor = %d;\n", wsectors[i].floorheight >> FRACBITS); + fprintf(f, "heightceiling = %d;\n", wsectors[i].ceilingheight >> FRACBITS); + if (wsectors[i].floorpic != -1) + fprintf(f, "texturefloor = \"%s\";\n", levelflats[wsectors[i].floorpic].name); + if (wsectors[i].ceilingpic != -1) + fprintf(f, "textureceiling = \"%s\";\n", levelflats[wsectors[i].ceilingpic].name); + fprintf(f, "lightlevel = %d;\n", wsectors[i].lightlevel); + if (wsectors[i].floorlightlevel != 0) + fprintf(f, "lightfloor = %d;\n", wsectors[i].floorlightlevel); + if (wsectors[i].floorlightabsolute) fprintf(f, "lightfloorabsolute = true;\n"); - if (sectors[i].ceilinglightlevel != 0) - fprintf(f, "lightceiling = %d;\n", sectors[i].ceilinglightlevel); - if (sectors[i].ceilinglightabsolute) + if (wsectors[i].ceilinglightlevel != 0) + fprintf(f, "lightceiling = %d;\n", wsectors[i].ceilinglightlevel); + if (wsectors[i].ceilinglightabsolute) fprintf(f, "lightceilingabsolute = true;\n"); firsttag = Tag_FGet(§ors[i].tags); if (firsttag != 0) @@ -2218,7 +2251,7 @@ static void P_WriteTextmap(void) } fprintf(f, "\";\n"); } - sector_t tempsec = sectors[i]; + sector_t tempsec = wsectors[i]; TextmapUnfixFlatOffsets(&tempsec); if (tempsec.floor_xoffs != 0) fprintf(f, "xpanningfloor = %f;\n", FIXED_TO_FLOAT(tempsec.floor_xoffs)); @@ -2228,39 +2261,39 @@ static void P_WriteTextmap(void) fprintf(f, "xpanningceiling = %f;\n", FIXED_TO_FLOAT(tempsec.ceiling_xoffs)); if (tempsec.ceiling_yoffs != 0) fprintf(f, "ypanningceiling = %f;\n", FIXED_TO_FLOAT(tempsec.ceiling_yoffs)); - if (sectors[i].floorpic_angle != 0) - fprintf(f, "rotationfloor = %f;\n", FIXED_TO_FLOAT(AngleFixed(sectors[i].floorpic_angle))); - if (sectors[i].ceilingpic_angle != 0) - fprintf(f, "rotationceiling = %f;\n", FIXED_TO_FLOAT(AngleFixed(sectors[i].ceilingpic_angle))); + if (wsectors[i].floorpic_angle != 0) + fprintf(f, "rotationfloor = %f;\n", FIXED_TO_FLOAT(AngleFixed(wsectors[i].floorpic_angle))); + if (wsectors[i].ceilingpic_angle != 0) + fprintf(f, "rotationceiling = %f;\n", FIXED_TO_FLOAT(AngleFixed(wsectors[i].ceilingpic_angle))); //TODO: Only if slope was defined via equations - /*if (sectors[i].f_slope) + /*if (wsectors[i].f_slope) { - fixed_t a = sectors[i].f_slope->normal.x; - fixed_t b = sectors[i].f_slope->normal.y; - fixed_t c = sectors[i].f_slope->normal.z; - fixed_t d = -FV3_Dot(§ors[i].f_slope->normal, §ors[i].f_slope->o); + fixed_t a = wsectors[i].f_slope->normal.x; + fixed_t b = wsectors[i].f_slope->normal.y; + fixed_t c = wsectors[i].f_slope->normal.z; + fixed_t d = -FV3_Dot(&wsectors[i].f_slope->normal, &wsectors[i].f_slope->o); fprintf(f, "floorplane_a = %f;\n", FIXED_TO_FLOAT(a)); fprintf(f, "floorplane_b = %f;\n", FIXED_TO_FLOAT(b)); fprintf(f, "floorplane_c = %f;\n", FIXED_TO_FLOAT(c)); fprintf(f, "floorplane_d = %f;\n", FIXED_TO_FLOAT(d)); } - if (sectors[i].c_slope) + if (wsectors[i].c_slope) { - fixed_t a = sectors[i].c_slope->normal.x; - fixed_t b = sectors[i].c_slope->normal.y; - fixed_t c = sectors[i].c_slope->normal.z; - fixed_t d = -FV3_Dot(§ors[i].c_slope->normal, §ors[i].c_slope->o); + fixed_t a = wsectors[i].c_slope->normal.x; + fixed_t b = wsectors[i].c_slope->normal.y; + fixed_t c = wsectors[i].c_slope->normal.z; + fixed_t d = -FV3_Dot(&wsectors[i].c_slope->normal, &wsectors[i].c_slope->o); fprintf(f, "ceilingplane_a = %f;\n", FIXED_TO_FLOAT(a)); fprintf(f, "ceilingplane_b = %f;\n", FIXED_TO_FLOAT(b)); fprintf(f, "ceilingplane_c = %f;\n", FIXED_TO_FLOAT(c)); fprintf(f, "ceilingplane_d = %f;\n", FIXED_TO_FLOAT(d)); }*/ - if (sectors[i].extra_colormap) + if (wsectors[i].extra_colormap) { - INT32 lightcolor = P_RGBAToColor(sectors[i].extra_colormap->rgba); - UINT8 lightalpha = R_GetRgbaA(sectors[i].extra_colormap->rgba); - INT32 fadecolor = P_RGBAToColor(sectors[i].extra_colormap->fadergba); - UINT8 fadealpha = R_GetRgbaA(sectors[i].extra_colormap->fadergba); + INT32 lightcolor = P_RGBAToColor(wsectors[i].extra_colormap->rgba); + UINT8 lightalpha = R_GetRgbaA(wsectors[i].extra_colormap->rgba); + INT32 fadecolor = P_RGBAToColor(wsectors[i].extra_colormap->fadergba); + UINT8 fadealpha = R_GetRgbaA(wsectors[i].extra_colormap->fadergba); if (lightcolor != 0) fprintf(f, "lightcolor = %d;\n", lightcolor); @@ -2270,78 +2303,78 @@ static void P_WriteTextmap(void) fprintf(f, "fadecolor = %d;\n", fadecolor); if (fadealpha != 25) fprintf(f, "fadealpha = %d;\n", fadealpha); - if (sectors[i].extra_colormap->fadestart != 0) - fprintf(f, "fadestart = %d;\n", sectors[i].extra_colormap->fadestart); - if (sectors[i].extra_colormap->fadeend != 31) - fprintf(f, "fadeend = %d;\n", sectors[i].extra_colormap->fadeend); - if (sectors[i].extra_colormap->flags & CMF_FOG) + if (wsectors[i].extra_colormap->fadestart != 0) + fprintf(f, "fadestart = %d;\n", wsectors[i].extra_colormap->fadestart); + if (wsectors[i].extra_colormap->fadeend != 31) + fprintf(f, "fadeend = %d;\n", wsectors[i].extra_colormap->fadeend); + if (wsectors[i].extra_colormap->flags & CMF_FOG) fprintf(f, "colormapfog = true;\n"); - if (sectors[i].extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES) + if (wsectors[i].extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES) fprintf(f, "colormapfadesprites = true;\n"); } - if (sectors[i].colormap_protected) + if (wsectors[i].colormap_protected) fprintf(f, "colormapprotected = true;\n"); - if (!(sectors[i].flags & MSF_FLIPSPECIAL_FLOOR)) + if (!(wsectors[i].flags & MSF_FLIPSPECIAL_FLOOR)) fprintf(f, "flipspecial_nofloor = true;\n"); - if (sectors[i].flags & MSF_FLIPSPECIAL_CEILING) + if (wsectors[i].flags & MSF_FLIPSPECIAL_CEILING) fprintf(f, "flipspecial_ceiling = true;\n"); - if (sectors[i].flags & MSF_TRIGGERSPECIAL_TOUCH) + if (wsectors[i].flags & MSF_TRIGGERSPECIAL_TOUCH) fprintf(f, "triggerspecial_touch = true;\n"); - if (sectors[i].flags & MSF_TRIGGERSPECIAL_HEADBUMP) + if (wsectors[i].flags & MSF_TRIGGERSPECIAL_HEADBUMP) fprintf(f, "triggerspecial_headbump = true;\n"); - if (sectors[i].flags & MSF_TRIGGERLINE_PLANE) + if (wsectors[i].flags & MSF_TRIGGERLINE_PLANE) fprintf(f, "triggerline_plane = true;\n"); - if (sectors[i].flags & MSF_TRIGGERLINE_MOBJ) + if (wsectors[i].flags & MSF_TRIGGERLINE_MOBJ) fprintf(f, "triggerline_mobj = true;\n"); - if (sectors[i].flags & MSF_INVERTPRECIP) + if (wsectors[i].flags & MSF_INVERTPRECIP) fprintf(f, "invertprecip = true;\n"); - if (sectors[i].flags & MSF_GRAVITYFLIP) + if (wsectors[i].flags & MSF_GRAVITYFLIP) fprintf(f, "gravityflip = true;\n"); - if (sectors[i].flags & MSF_HEATWAVE) + if (wsectors[i].flags & MSF_HEATWAVE) fprintf(f, "heatwave = true;\n"); - if (sectors[i].flags & MSF_NOCLIPCAMERA) + if (wsectors[i].flags & MSF_NOCLIPCAMERA) fprintf(f, "noclipcamera = true;\n"); - if (sectors[i].specialflags & SSF_OUTERSPACE) + if (wsectors[i].specialflags & SSF_OUTERSPACE) fprintf(f, "outerspace = true;\n"); - if (sectors[i].specialflags & SSF_DOUBLESTEPUP) + if (wsectors[i].specialflags & SSF_DOUBLESTEPUP) fprintf(f, "doublestepup = true;\n"); - if (sectors[i].specialflags & SSF_NOSTEPDOWN) + if (wsectors[i].specialflags & SSF_NOSTEPDOWN) fprintf(f, "nostepdown = true;\n"); - if (sectors[i].specialflags & SSF_SPEEDPAD) + if (wsectors[i].specialflags & SSF_SPEEDPAD) fprintf(f, "speedpad = true;\n"); - if (sectors[i].specialflags & SSF_STARPOSTACTIVATOR) + if (wsectors[i].specialflags & SSF_STARPOSTACTIVATOR) fprintf(f, "starpostactivator = true;\n"); - if (sectors[i].specialflags & SSF_EXIT) + if (wsectors[i].specialflags & SSF_EXIT) fprintf(f, "exit = true;\n"); - if (sectors[i].specialflags & SSF_SPECIALSTAGEPIT) + if (wsectors[i].specialflags & SSF_SPECIALSTAGEPIT) fprintf(f, "specialstagepit = true;\n"); - if (sectors[i].specialflags & SSF_RETURNFLAG) + if (wsectors[i].specialflags & SSF_RETURNFLAG) fprintf(f, "returnflag = true;\n"); - if (sectors[i].specialflags & SSF_REDTEAMBASE) + if (wsectors[i].specialflags & SSF_REDTEAMBASE) fprintf(f, "redteambase = true;\n"); - if (sectors[i].specialflags & SSF_BLUETEAMBASE) + if (wsectors[i].specialflags & SSF_BLUETEAMBASE) fprintf(f, "blueteambase = true;\n"); - if (sectors[i].specialflags & SSF_FAN) + if (wsectors[i].specialflags & SSF_FAN) fprintf(f, "fan = true;\n"); - if (sectors[i].specialflags & SSF_SUPERTRANSFORM) + if (wsectors[i].specialflags & SSF_SUPERTRANSFORM) fprintf(f, "supertransform = true;\n"); - if (sectors[i].specialflags & SSF_FORCESPIN) + if (wsectors[i].specialflags & SSF_FORCESPIN) fprintf(f, "forcespin = true;\n"); - if (sectors[i].specialflags & SSF_ZOOMTUBESTART) + if (wsectors[i].specialflags & SSF_ZOOMTUBESTART) fprintf(f, "zoomtubestart = true;\n"); - if (sectors[i].specialflags & SSF_ZOOMTUBEEND) + if (wsectors[i].specialflags & SSF_ZOOMTUBEEND) fprintf(f, "zoomtubeend = true;\n"); - if (sectors[i].specialflags & SSF_FINISHLINE) + if (wsectors[i].specialflags & SSF_FINISHLINE) fprintf(f, "finishline = true;\n"); - if (sectors[i].specialflags & SSF_ROPEHANG) + if (wsectors[i].specialflags & SSF_ROPEHANG) fprintf(f, "ropehang = true;\n"); - if (sectors[i].friction != ORIG_FRICTION) - fprintf(f, "friction = %f;\n", FIXED_TO_FLOAT(sectors[i].friction)); - if (sectors[i].gravity != FRACUNIT) - fprintf(f, "gravity = %f;\n", FIXED_TO_FLOAT(sectors[i].gravity)); - if (sectors[i].damagetype != SD_NONE) + if (wsectors[i].friction != ORIG_FRICTION) + fprintf(f, "friction = %f;\n", FIXED_TO_FLOAT(wsectors[i].friction)); + if (wsectors[i].gravity != FRACUNIT) + fprintf(f, "gravity = %f;\n", FIXED_TO_FLOAT(wsectors[i].gravity)); + if (wsectors[i].damagetype != SD_NONE) { - switch (sectors[i].damagetype) + switch (wsectors[i].damagetype) { case SD_GENERIC: fprintf(f, "damagetype = \"Generic\";\n"); @@ -2377,15 +2410,21 @@ static void P_WriteTextmap(void) break; } } - if (sectors[i].triggertag != 0) - fprintf(f, "triggertag = %d;\n", sectors[i].triggertag); - if (sectors[i].triggerer != 0) - fprintf(f, "triggerer = %d;\n", sectors[i].triggerer); + if (wsectors[i].triggertag != 0) + fprintf(f, "triggertag = %d;\n", wsectors[i].triggertag); + if (wsectors[i].triggerer != 0) + fprintf(f, "triggerer = %d;\n", wsectors[i].triggerer); fprintf(f, "}\n"); fprintf(f, "\n"); } fclose(f); + + Z_Free(wmapthings); + Z_Free(wvertexes); + Z_Free(wsectors); + Z_Free(wlines); + Z_Free(wsides); } /** Loads the textmap data, after obtaining the elements count and allocating their respective space. From 5f6014223dd5fc30aaeeb3f7394e910c5ab0293a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 9 Jan 2022 10:38:05 +0100 Subject: [PATCH 307/326] Don't convert global colormaps --- src/p_setup.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 51ea552a8..247741f0f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2035,15 +2035,25 @@ static void P_WriteTextmap(void) { INT32 s; - if (wlines[i].special != 606) - continue; - - TAG_ITER_SECTORS(wlines[i].args[0], s) + switch (wlines[i].special) { - if (wsectors[s].colormap_protected) - continue; + case 606: + if (wlines[i].args[0] == MTAG_GLOBAL) + { + CONS_Printf("Linedef %d applies a global colormap which cannot be converted automatically. Please convert it manually.\n", i); + break; + } - wsectors[s].extra_colormap = wsides[wlines[i].sidenum[0]].colormap_data; + TAG_ITER_SECTORS(wlines[i].args[0], s) + { + if (wsectors[s].colormap_protected) + continue; + + wsectors[s].extra_colormap = wsides[wlines[i].sidenum[0]].colormap_data; + } + break; + default: + break; } } From 1fbfc9bea9b01425b97517e1937a5cce15ac10b3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 9 Jan 2022 11:44:53 +0100 Subject: [PATCH 308/326] P_WriteTextmap: Convert custom gravity and custom exit --- src/p_setup.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 247741f0f..0b0345a51 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2037,10 +2037,27 @@ static void P_WriteTextmap(void) switch (wlines[i].special) { + case 1: + TAG_ITER_SECTORS(Tag_FGet(&lines[i].tags), s) + { + CONS_Alert(CONS_WARNING, M_GetText("Linedef %d applies custom gravity to sector %d. Changes to this gravity at runtime will not be reflected in the converted map. Use linedef type 469 for this.\n"), i, s); + wsectors[s].gravity = FixedDiv(lines[i].frontsector->floorheight >> FRACBITS, 1000); + } + break; + case 2: + CONS_Alert(CONS_WARNING, M_GetText("Custom exit linedef %d detected. Changes to the next map at runtime will not be reflected in the converted map. Use linedef type 465 for this.\n"), i); + wlines[i].args[0] = lines[i].frontsector->floorheight >> FRACBITS; + wlines[i].args[2] = lines[i].frontsector->ceilingheight >> FRACBITS; + break; + case 5: + case 50: + case 51: + CONS_Alert(CONS_WARNING, M_GetText("Linedef %d has type %d, which has been removed in UDMF.\n"), i, wlines[i].special); + break; case 606: if (wlines[i].args[0] == MTAG_GLOBAL) { - CONS_Printf("Linedef %d applies a global colormap which cannot be converted automatically. Please convert it manually.\n", i); + CONS_Alert(CONS_WARNING, M_GetText("Linedef %d applies a global colormap which cannot be converted automatically. Please convert it manually.\n"), i); break; } From 7276c6bef5c80e0f6b9254331d13944f5e8b7744 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 9 Jan 2022 12:37:46 +0100 Subject: [PATCH 309/326] P_WriteTextmap: Correctly write linedef executor delays --- 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 0b0345a51..7171ada81 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2045,7 +2045,7 @@ static void P_WriteTextmap(void) } break; case 2: - CONS_Alert(CONS_WARNING, M_GetText("Custom exit linedef %d detected. Changes to the next map at runtime will not be reflected in the converted map. Use linedef type 465 for this.\n"), i); + CONS_Alert(CONS_WARNING, M_GetText("Custom exit linedef %d detected. Changes to the next map at runtime will not be reflected in the converted map. Use linedef type 468 for this.\n"), i); wlines[i].args[0] = lines[i].frontsector->floorheight >> FRACBITS; wlines[i].args[2] = lines[i].frontsector->ceilingheight >> FRACBITS; break; @@ -2188,8 +2188,11 @@ static void P_WriteTextmap(void) break; } } - if (wlines[i].executordelay != 0) - fprintf(f, "executordelay = %d;\n", wlines[i].executordelay); + if (wlines[i].executordelay != 0 && wlines[i].backsector) + { + CONS_Alert(CONS_WARNING, M_GetText("Linedef %d has an executor delay. Changes to the delay at runtime will not be reflected in the converted map. Use linedef type 465 for this.\n"), i); + fprintf(f, "executordelay = %d;\n", (wlines[i].backsector->ceilingheight >> FRACBITS) + (wlines[i].backsector->floorheight >> FRACBITS)); + } if (wlines[i].flags & ML_IMPASSIBLE) fprintf(f, "blocking = true;\n"); if (wlines[i].flags & ML_BLOCKMONSTERS) From b3ca6845c17fc2656991fd20ee0943530be1fdba Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 9 Jan 2022 12:38:49 +0100 Subject: [PATCH 310/326] P_WriteTextmap: Don't bother with equation slopes because binary maps can't have them anyway --- src/p_setup.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 7171ada81..06f101fce 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2295,29 +2295,6 @@ static void P_WriteTextmap(void) fprintf(f, "rotationfloor = %f;\n", FIXED_TO_FLOAT(AngleFixed(wsectors[i].floorpic_angle))); if (wsectors[i].ceilingpic_angle != 0) fprintf(f, "rotationceiling = %f;\n", FIXED_TO_FLOAT(AngleFixed(wsectors[i].ceilingpic_angle))); - //TODO: Only if slope was defined via equations - /*if (wsectors[i].f_slope) - { - fixed_t a = wsectors[i].f_slope->normal.x; - fixed_t b = wsectors[i].f_slope->normal.y; - fixed_t c = wsectors[i].f_slope->normal.z; - fixed_t d = -FV3_Dot(&wsectors[i].f_slope->normal, &wsectors[i].f_slope->o); - fprintf(f, "floorplane_a = %f;\n", FIXED_TO_FLOAT(a)); - fprintf(f, "floorplane_b = %f;\n", FIXED_TO_FLOAT(b)); - fprintf(f, "floorplane_c = %f;\n", FIXED_TO_FLOAT(c)); - fprintf(f, "floorplane_d = %f;\n", FIXED_TO_FLOAT(d)); - } - if (wsectors[i].c_slope) - { - fixed_t a = wsectors[i].c_slope->normal.x; - fixed_t b = wsectors[i].c_slope->normal.y; - fixed_t c = wsectors[i].c_slope->normal.z; - fixed_t d = -FV3_Dot(&wsectors[i].c_slope->normal, &wsectors[i].c_slope->o); - fprintf(f, "ceilingplane_a = %f;\n", FIXED_TO_FLOAT(a)); - fprintf(f, "ceilingplane_b = %f;\n", FIXED_TO_FLOAT(b)); - fprintf(f, "ceilingplane_c = %f;\n", FIXED_TO_FLOAT(c)); - fprintf(f, "ceilingplane_d = %f;\n", FIXED_TO_FLOAT(d)); - }*/ if (wsectors[i].extra_colormap) { INT32 lightcolor = P_RGBAToColor(wsectors[i].extra_colormap->rgba); From ce29d05be8eca83d8409527af2bb1f91c687ef6b Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 9 Jan 2022 12:53:12 +0100 Subject: [PATCH 311/326] Fix typo in wall scroller conversion --- 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 1ecd24471..01daa55f1 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3816,13 +3816,13 @@ static void P_ConvertBinaryMap(void) lines[i].special = 0; break; } - lines[i].args[1] = sides[lines[i].sidenum[1]].rowoffset >> FRACBITS; - lines[i].args[2] = sides[lines[i].sidenum[1]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[1]].textureoffset >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[1]].rowoffset >> FRACBITS; } else { - lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; - lines[i].args[2] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; } lines[i].special = 500; break; From 576ded653776e3c08b67f64cb7351dc0b2ebb2bc Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 10 Jan 2022 20:59:57 +0100 Subject: [PATCH 312/326] Fix incorrectly applied FOF blendmodes --- src/p_spec.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 470595937..ce6bd6c0b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5629,7 +5629,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I { case TMB_TRANSLUCENT: default: - fflr->blend = AST_TRANSLUCENT; + fflr->blend = AST_COPY; break; case TMB_ADD: fflr->blend = AST_ADD; @@ -6534,12 +6534,12 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 150: // FOF (Air bobbing) - P_AddFakeFloorsByLine(i, 0xff, AST_COPY, FF_EXISTS|FF_SOLID|FF_RENDERALL, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, FF_EXISTS|FF_SOLID|FF_RENDERALL, secthinkers); P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); break; case 160: // FOF (Water bobbing) - P_AddFakeFloorsByLine(i, 0xff, AST_COPY, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB, secthinkers); break; case 170: // FOF (Crumbling) @@ -6644,7 +6644,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_CUTSPRITES; if (!lines[i].args[1]) ffloorflags |= FF_DOUBLESHADOW; - P_AddFakeFloorsByLine(i, 0xff, AST_COPY, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, ffloorflags, secthinkers); break; case 202: // Fog @@ -6653,7 +6653,7 @@ void P_SpawnSpecials(boolean fromnetsave) // SoM: Because it's fog, check for an extra colormap and set the fog flag... if (sectors[sec].extra_colormap) sectors[sec].extra_colormap->flags = CMF_FOG; - P_AddFakeFloorsByLine(i, 0xff, AST_COPY, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, ffloorflags, secthinkers); break; case 220: //Intangible @@ -6687,7 +6687,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 223: // FOF (intangible, invisible) - for combining specials in a sector - P_AddFakeFloorsByLine(i, 0xff, AST_COPY, FF_EXISTS|FF_NOSHADE, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, FF_EXISTS|FF_NOSHADE, secthinkers); break; case 250: // Mario Block @@ -6697,14 +6697,14 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[1] & TMFM_INVISIBLE) ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); - P_AddFakeFloorsByLine(i, 0xff, AST_COPY, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, ffloorflags, secthinkers); break; case 251: // A THWOMP! { UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; P_AddThwompThinker(lines[i].frontsector, &lines[i], lines[i].args[1] << (FRACBITS - 3), lines[i].args[2] << (FRACBITS - 3), sound); - P_AddFakeFloorsByLine(i, 0xff, AST_COPY, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); break; } @@ -6763,7 +6763,7 @@ void P_SpawnSpecials(boolean fromnetsave) TAG_ITER_SECTORS(lines[i].args[0], s) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, AST_COPY, ffloorflags, secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, TMB_TRANSLUCENT, ffloorflags, secthinkers); if (!fflr) continue; fflr->sinkspeed = abs(lines[i].args[2]) << (FRACBITS - 1); @@ -6885,7 +6885,7 @@ void P_SpawnSpecials(boolean fromnetsave) } } - P_AddFakeFloorsByLine(i, dopacity, AST_TRANSLUCENT, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, dopacity, TMB_TRANSLUCENT, ffloorflags, secthinkers); } break; From 3b4fad16dbb42aed5b873ff14600417a0852b284 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 10 Jan 2022 21:23:55 +0100 Subject: [PATCH 313/326] P_WriteTextmap: Convert global colormaps --- src/p_setup.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 41384bc97..4f6c98ab0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2057,16 +2057,18 @@ static void P_WriteTextmap(void) case 606: if (wlines[i].args[0] == MTAG_GLOBAL) { - CONS_Alert(CONS_WARNING, M_GetText("Linedef %d applies a global colormap which cannot be converted automatically. Please convert it manually.\n"), i); - break; + sector_t *sec = wlines[i].frontsector - sectors + wsectors; + sec->extra_colormap = wsides[wlines[i].sidenum[0]].colormap_data; } - - TAG_ITER_SECTORS(wlines[i].args[0], s) + else { - if (wsectors[s].colormap_protected) - continue; + TAG_ITER_SECTORS(wlines[i].args[0], s) + { + if (wsectors[s].colormap_protected) + continue; - wsectors[s].extra_colormap = wsides[wlines[i].sidenum[0]].colormap_data; + wsectors[s].extra_colormap = wsides[wlines[i].sidenum[0]].colormap_data; + } } break; default: From 0b9876d61bdea36414a332034c3ed2b8ffc6be9f Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 10 Jan 2022 22:10:19 +0100 Subject: [PATCH 314/326] P_WriteTextmap: Clear out colormap linedef special after copying the colormap --- src/p_setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_setup.c b/src/p_setup.c index 4f6c98ab0..683ba5498 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2069,6 +2069,7 @@ static void P_WriteTextmap(void) wsectors[s].extra_colormap = wsides[wlines[i].sidenum[0]].colormap_data; } + lines[i].special = 0; } break; default: From 666833e64b4e32d72e841bc00aeeb40e1054bb24 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 11 Jan 2022 20:24:07 +0100 Subject: [PATCH 315/326] P_WriteTextmap: Add warnings for deprecated sector specials and reserved tags --- src/p_setup.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index 683ba5498..f69789a6a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2077,6 +2077,41 @@ static void P_WriteTextmap(void) } } + for (i = 0; i < numsectors; i++) + { + if (Tag_Find(§ors[i].tags, LE_CAPSULE0)) + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which has been removed in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE0); + if (Tag_Find(§ors[i].tags, LE_CAPSULE1)) + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which has been removed in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE1); + if (Tag_Find(§ors[i].tags, LE_CAPSULE2)) + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which has been removed in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE2); + + switch (GETSECSPECIAL(wsectors[i].special, 1)) + { + case 9: + case 10: + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has ring drainer effect, which has been removed in UDMF. Use linedef type 462 instead.\n"), i); + break; + default: + break; + } + + switch (GETSECSPECIAL(wsectors[i].special, 2)) + { + case 6: + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has emerald check trigger type, which has been removed in UDMF. Please use linedef types 337-339 instead.\n"), i); + break; + case 7: + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has NiGHTS mare trigger type, which has been removed in UDMF. Please use linedef types 340-342 instead.\n"), i); + break; + case 9: + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has Egg Capsule type, which has been removed in UDMF. Please use linedef type 464 instead.\n"), i); + break; + default: + break; + } + } + fprintf(f, "namespace = \"srb2\";\n"); for (i = 0; i < nummapthings; i++) { From 25fe26badcf1063fc7d50e11b4afaa2dcb0e1657 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 12 Jan 2022 21:36:19 +0100 Subject: [PATCH 316/326] P_WriteTextmap: Add more warnings for unconvertable stuff --- src/p_setup.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index f69789a6a..92cf7dc1f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2052,7 +2052,23 @@ static void P_WriteTextmap(void) case 5: case 50: case 51: - CONS_Alert(CONS_WARNING, M_GetText("Linedef %d has type %d, which has been removed in UDMF.\n"), i, wlines[i].special); + CONS_Alert(CONS_WARNING, M_GetText("Linedef %d has type %d, which is not supported in UDMF.\n"), i, wlines[i].special); + break; + case 259: + if (wlines[i].args[3] & FF_QUICKSAND) + CONS_Alert(CONS_WARNING, M_GetText("Quicksand properties of custom FOF on linedef %d cannot be converted. Use linedef type 75 instead.\n"), i); + if (wlines[i].args[3] & FF_BUSTUP) + CONS_Alert(CONS_WARNING, M_GetText("Bustable properties of custom FOF on linedef %d cannot be converted. Use linedef type 74 instead.\n"), i); + break; + case 447: + CONS_Alert(CONS_WARNING, M_GetText("Linedef %d has change colormap action, which cannot be converted automatically. Tag arg0 to a sector with the desired colormap.\n"), i); + if (wlines[i].flags & ML_TFERLINE) + CONS_Alert(CONS_WARNING, M_GetText("Linedef %d mixes front and back colormaps, which is not supported in UDMF. Copy one colormap to the target sector first, then mix in the second one.\n"), i); + break; + case 455: + CONS_Alert(CONS_WARNING, M_GetText("Linedef %d has fade colormap action, which cannot be converted automatically. Tag arg0 to a sector with the desired colormap.\n"), i); + if (wlines[i].flags & ML_TFERLINE) + CONS_Alert(CONS_WARNING, M_GetText("Linedef %d specifies starting colormap for the fade, which is not supported in UDMF. Change the colormap with linedef type 447 instead.\n"), i); break; case 606: if (wlines[i].args[0] == MTAG_GLOBAL) @@ -2075,22 +2091,25 @@ static void P_WriteTextmap(void) default: break; } + + if (wlines[i].special >= 300 && wlines[i].special < 400 && wlines[i].flags & ML_WRAPMIDTEX) + CONS_Alert(CONS_WARNING, M_GetText("Linedef executor trigger linedef %d has disregard order flag, which is not supported in UDMF.\n"), i); } for (i = 0; i < numsectors; i++) { if (Tag_Find(§ors[i].tags, LE_CAPSULE0)) - CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which has been removed in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE0); + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which is not supported in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE0); if (Tag_Find(§ors[i].tags, LE_CAPSULE1)) - CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which has been removed in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE1); + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which is not supported in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE1); if (Tag_Find(§ors[i].tags, LE_CAPSULE2)) - CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which has been removed in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE2); + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which is not supported in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE2); switch (GETSECSPECIAL(wsectors[i].special, 1)) { case 9: case 10: - CONS_Alert(CONS_WARNING, M_GetText("Sector %d has ring drainer effect, which has been removed in UDMF. Use linedef type 462 instead.\n"), i); + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has ring drainer effect, which is not supported in UDMF. Use linedef type 462 instead.\n"), i); break; default: break; @@ -2099,13 +2118,13 @@ static void P_WriteTextmap(void) switch (GETSECSPECIAL(wsectors[i].special, 2)) { case 6: - CONS_Alert(CONS_WARNING, M_GetText("Sector %d has emerald check trigger type, which has been removed in UDMF. Please use linedef types 337-339 instead.\n"), i); + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has emerald check trigger type, which is not supported in UDMF. Use linedef types 337-339 instead.\n"), i); break; case 7: - CONS_Alert(CONS_WARNING, M_GetText("Sector %d has NiGHTS mare trigger type, which has been removed in UDMF. Please use linedef types 340-342 instead.\n"), i); + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has NiGHTS mare trigger type, which is not supported in UDMF. Use linedef types 340-342 instead.\n"), i); break; case 9: - CONS_Alert(CONS_WARNING, M_GetText("Sector %d has Egg Capsule type, which has been removed in UDMF. Please use linedef type 464 instead.\n"), i); + CONS_Alert(CONS_WARNING, M_GetText("Sector %d has Egg Capsule type, which is not supported in UDMF. Use linedef type 464 instead.\n"), i); break; default: break; From 1dcee17fa4d74ea069ad45ad51c9c89727595671 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 13 Jan 2022 18:54:18 +0100 Subject: [PATCH 317/326] P_WriteTextmap: Convert linedef type 76 --- src/p_setup.c | 62 ++++++++++++++++++++++++++++++++++++++++----------- src/taglist.c | 13 +++++++++++ src/taglist.h | 2 ++ 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 92cf7dc1f..9fceacb07 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2011,6 +2011,7 @@ static void P_WriteTextmap(void) sector_t *wsectors; line_t *wlines; side_t *wsides; + mtag_t freetag; f = fopen(filepath, "w"); if (!f) @@ -2031,6 +2032,16 @@ static void P_WriteTextmap(void) memcpy(wlines, lines, numlines * sizeof(*lines)); memcpy(wsides, sides, numsides * sizeof(*sides)); + for (i = 0; i < numsectors; i++) + if (sectors[i].tags.count) + wsectors[i].tags.tags = memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t)); + + for (i = 0; i < numlines; i++) + if (lines[i].tags.count) + wlines[i].tags.tags = memcpy(Z_Malloc(lines[i].tags.count * sizeof(mtag_t), PU_LEVEL, NULL), lines[i].tags.tags, lines[i].tags.count * sizeof(mtag_t)); + + freetag = Tag_NextUnused(0); + for (i = 0; i < numlines; i++) { INT32 s; @@ -2038,7 +2049,7 @@ static void P_WriteTextmap(void) switch (wlines[i].special) { case 1: - TAG_ITER_SECTORS(Tag_FGet(&lines[i].tags), s) + TAG_ITER_SECTORS(Tag_FGet(&wlines[i].tags), s) { CONS_Alert(CONS_WARNING, M_GetText("Linedef %d applies custom gravity to sector %d. Changes to this gravity at runtime will not be reflected in the converted map. Use linedef type 469 for this.\n"), i, s); wsectors[s].gravity = FixedDiv(lines[i].frontsector->floorheight >> FRACBITS, 1000); @@ -2054,6 +2065,23 @@ static void P_WriteTextmap(void) case 51: CONS_Alert(CONS_WARNING, M_GetText("Linedef %d has type %d, which is not supported in UDMF.\n"), i, wlines[i].special); break; + case 76: + if (freetag == (mtag_t)MAXTAGS) + { + CONS_Alert(CONS_WARNING, M_GetText("No unused tag found. Linedef %d with type 76 cannot be converted.\n"), i); + break; + } + TAG_ITER_SECTORS(wlines[i].args[0], s) + for (j = 0; (unsigned)j < wsectors[s].linecount; j++) + { + line_t *line = wsectors[s].lines[j] - lines + wlines; + if (line->special < 100 || line->special >= 300) + continue; + Tag_Add(&line->tags, freetag); + } + wlines[i].args[0] = freetag; + freetag = Tag_NextUnused(freetag); + break; case 259: if (wlines[i].args[3] & FF_QUICKSAND) CONS_Alert(CONS_WARNING, M_GetText("Quicksand properties of custom FOF on linedef %d cannot be converted. Use linedef type 75 instead.\n"), i); @@ -2085,7 +2113,7 @@ static void P_WriteTextmap(void) wsectors[s].extra_colormap = wsides[wlines[i].sidenum[0]].colormap_data; } - lines[i].special = 0; + wlines[i].special = 0; } break; default: @@ -2098,11 +2126,11 @@ static void P_WriteTextmap(void) for (i = 0; i < numsectors; i++) { - if (Tag_Find(§ors[i].tags, LE_CAPSULE0)) + if (Tag_Find(&wsectors[i].tags, LE_CAPSULE0)) CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which is not supported in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE0); - if (Tag_Find(§ors[i].tags, LE_CAPSULE1)) + if (Tag_Find(&wsectors[i].tags, LE_CAPSULE1)) CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which is not supported in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE1); - if (Tag_Find(§ors[i].tags, LE_CAPSULE2)) + if (Tag_Find(&wsectors[i].tags, LE_CAPSULE2)) CONS_Alert(CONS_WARNING, M_GetText("Sector %d has reserved tag %d, which is not supported in UDMF. Use arg3 of the boss mapthing instead.\n"), i, LE_CAPSULE2); switch (GETSECSPECIAL(wsectors[i].special, 1)) @@ -2198,17 +2226,17 @@ static void P_WriteTextmap(void) fprintf(f, "sidefront = %d;\n", wlines[i].sidenum[0]); if (wlines[i].sidenum[1] != 0xffff) fprintf(f, "sideback = %d;\n", wlines[i].sidenum[1]); - firsttag = Tag_FGet(&lines[i].tags); + firsttag = Tag_FGet(&wlines[i].tags); if (firsttag != 0) fprintf(f, "id = %d;\n", firsttag); - if (lines[i].tags.count > 1) + if (wlines[i].tags.count > 1) { fprintf(f, "moreids = \""); - for (j = 1; j < lines[i].tags.count; j++) + for (j = 1; j < wlines[i].tags.count; j++) { if (j > 1) fprintf(f, " "); - fprintf(f, " %d", lines[i].tags.tags[j]); + fprintf(f, " %d", wlines[i].tags.tags[j]); } fprintf(f, "\";\n"); } @@ -2324,17 +2352,17 @@ static void P_WriteTextmap(void) fprintf(f, "lightceiling = %d;\n", wsectors[i].ceilinglightlevel); if (wsectors[i].ceilinglightabsolute) fprintf(f, "lightceilingabsolute = true;\n"); - firsttag = Tag_FGet(§ors[i].tags); + firsttag = Tag_FGet(&wsectors[i].tags); if (firsttag != 0) fprintf(f, "id = %d;\n", firsttag); - if (sectors[i].tags.count > 1) + if (wsectors[i].tags.count > 1) { fprintf(f, "moreids = \""); - for (j = 1; j < sectors[i].tags.count; j++) + for (j = 1; j < wsectors[i].tags.count; j++) { if (j > 1) fprintf(f, " "); - fprintf(f, "%d", sectors[i].tags.tags[j]); + fprintf(f, "%d", wsectors[i].tags.tags[j]); } fprintf(f, "\";\n"); } @@ -2484,6 +2512,14 @@ static void P_WriteTextmap(void) fclose(f); + for (i = 0; i < numsectors; i++) + if (wsectors[i].tags.count) + Z_Free(wsectors[i].tags.tags); + + for (i = 0; i < numlines; i++) + if (wlines[i].tags.count) + Z_Free(wlines[i].tags.tags); + Z_Free(wmapthings); Z_Free(wvertexes); Z_Free(wsectors); diff --git a/src/taglist.c b/src/taglist.c index a67c7f1c2..82ba25500 100644 --- a/src/taglist.c +++ b/src/taglist.c @@ -455,3 +455,16 @@ void Tag_SectorFSet (const size_t id, const mtag_t tag) Taggroup_Add(tags_sectors, tag, id); Tag_FSet(&sec->tags, tag); } + +mtag_t Tag_NextUnused(mtag_t start) +{ + while ((UINT16)start < MAXTAGS) + { + if (!in_bit_array(tags_available, (UINT16)start)) + return start; + + start++; + } + + return MAXTAGS; +} diff --git a/src/taglist.h b/src/taglist.h index 39f71ad43..7d58ec689 100644 --- a/src/taglist.h +++ b/src/taglist.h @@ -49,6 +49,8 @@ typedef struct extern bitarray_t tags_available[]; +extern mtag_t Tag_NextUnused(mtag_t start); + extern size_t num_tags; extern taggroup_t* tags_sectors[]; From 2d4aabe48ef1092324d6705f554fbb9bf97988a6 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 13 Jan 2022 18:57:41 +0100 Subject: [PATCH 318/326] P_WriteTextmap: Remove superfluous whitespaces in moreids --- 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 9fceacb07..cbe26f176 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2174,7 +2174,7 @@ static void P_WriteTextmap(void) { if (j > 1) fprintf(f, " "); - fprintf(f, " %d", mapthings[i].tags.tags[j]); + fprintf(f, "%d", mapthings[i].tags.tags[j]); } fprintf(f, "\";\n"); } @@ -2236,7 +2236,7 @@ static void P_WriteTextmap(void) { if (j > 1) fprintf(f, " "); - fprintf(f, " %d", wlines[i].tags.tags[j]); + fprintf(f, "%d", wlines[i].tags.tags[j]); } fprintf(f, "\";\n"); } From b8524fc74128d9f834a9efaa3011d52788cc8417 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 13 Jan 2022 21:59:00 +0100 Subject: [PATCH 319/326] P_WriteTextmap: Convert linedef executors that rely on mapthings --- src/p_setup.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index cbe26f176..c1e557cc9 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2000,6 +2000,13 @@ static INT32 P_RGBAToColor(INT32 rgba) return (r << 16) | (g << 8) | b; } +typedef struct +{ + mapthing_t *teleport; + mapthing_t *altview; + mapthing_t *angleanchor; +} sectorspecialthings_t; + static void P_WriteTextmap(void) { size_t i, j; @@ -2012,6 +2019,7 @@ static void P_WriteTextmap(void) line_t *wlines; side_t *wsides; mtag_t freetag; + sectorspecialthings_t *specialthings; f = fopen(filepath, "w"); if (!f) @@ -2025,6 +2033,7 @@ static void P_WriteTextmap(void) wsectors = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL); wlines = Z_Calloc(numlines * sizeof(*lines), PU_LEVEL, NULL); wsides = Z_Calloc(numsides * sizeof(*sides), PU_LEVEL, NULL); + specialthings = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL); memcpy(wmapthings, mapthings, nummapthings * sizeof(*mapthings)); memcpy(wvertexes, vertexes, numvertexes * sizeof(*vertexes)); @@ -2032,6 +2041,10 @@ static void P_WriteTextmap(void) memcpy(wlines, lines, numlines * sizeof(*lines)); memcpy(wsides, sides, numsides * sizeof(*sides)); + for (i = 0; i < nummapthings; i++) + if (mapthings[i].tags.count) + wmapthings[i].tags.tags = memcpy(Z_Malloc(mapthings[i].tags.count * sizeof(mtag_t), PU_LEVEL, NULL), mapthings[i].tags.tags, mapthings[i].tags.count * sizeof(mtag_t)); + for (i = 0; i < numsectors; i++) if (sectors[i].tags.count) wsectors[i].tags.tags = memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t)); @@ -2042,6 +2055,40 @@ static void P_WriteTextmap(void) freetag = Tag_NextUnused(0); + for (i = 0; i < nummapthings; i++) + { + subsector_t *ss; + INT32 s; + + if (wmapthings[i].type != 751 && wmapthings[i].type != 752 && wmapthings[i].type != 758) + continue; + + ss = R_PointInSubsector(wmapthings[i].x << FRACBITS, wmapthings[i].y << FRACBITS); + + if (!ss) + continue; + + s = ss->sector - sectors; + + switch (wmapthings[i].type) + { + case 751: + if (!specialthings[s].teleport) + specialthings[s].teleport = &wmapthings[i]; + break; + case 752: + if (!specialthings[s].altview) + specialthings[s].altview = &wmapthings[i]; + break; + case 758: + if (!specialthings[s].angleanchor) + specialthings[s].angleanchor = &wmapthings[i]; + break; + default: + break; + } + } + for (i = 0; i < numlines; i++) { INT32 s; @@ -2088,6 +2135,35 @@ static void P_WriteTextmap(void) if (wlines[i].args[3] & FF_BUSTUP) CONS_Alert(CONS_WARNING, M_GetText("Bustable properties of custom FOF on linedef %d cannot be converted. Use linedef type 74 instead.\n"), i); break; + case 412: + if ((s = Tag_Iterate_Sectors(wlines[i].args[0], 0)) < 0) + break; + if (!specialthings[s].teleport) + break; + if (freetag == (mtag_t)MAXTAGS) + { + CONS_Alert(CONS_WARNING, M_GetText("No unused tag found. Linedef %d with type 412 cannot be converted.\n"), i); + break; + } + Tag_Add(&specialthings[s].teleport->tags, freetag); + wlines[i].args[0] = freetag; + freetag = Tag_NextUnused(freetag); + break; + case 422: + if ((s = Tag_Iterate_Sectors(wlines[i].args[0], 0)) < 0) + break; + if (!specialthings[s].altview) + break; + if (freetag == (mtag_t)MAXTAGS) + { + CONS_Alert(CONS_WARNING, M_GetText("No unused tag found. Linedef %d with type 422 cannot be converted.\n"), i); + break; + } + Tag_Add(&specialthings[s].altview->tags, freetag); + wlines[i].args[0] = freetag; + specialthings[s].altview->pitch = wlines[i].args[2]; + freetag = Tag_NextUnused(freetag); + break; case 447: CONS_Alert(CONS_WARNING, M_GetText("Linedef %d has change colormap action, which cannot be converted automatically. Tag arg0 to a sector with the desired colormap.\n"), i); if (wlines[i].flags & ML_TFERLINE) @@ -2098,6 +2174,20 @@ static void P_WriteTextmap(void) if (wlines[i].flags & ML_TFERLINE) CONS_Alert(CONS_WARNING, M_GetText("Linedef %d specifies starting colormap for the fade, which is not supported in UDMF. Change the colormap with linedef type 447 instead.\n"), i); break; + case 457: + if ((s = Tag_Iterate_Sectors(wlines[i].args[0], 0)) < 0) + break; + if (!specialthings[s].angleanchor) + break; + if (freetag == (mtag_t)MAXTAGS) + { + CONS_Alert(CONS_WARNING, M_GetText("No unused tag found. Linedef %d with type 457 cannot be converted.\n"), i); + break; + } + Tag_Add(&specialthings[s].angleanchor->tags, freetag); + wlines[i].args[0] = freetag; + freetag = Tag_NextUnused(freetag); + break; case 606: if (wlines[i].args[0] == MTAG_GLOBAL) { @@ -2164,17 +2254,17 @@ static void P_WriteTextmap(void) { fprintf(f, "thing // %d\n", i); fprintf(f, "{\n"); - firsttag = Tag_FGet(&mapthings[i].tags); + firsttag = Tag_FGet(&wmapthings[i].tags); if (firsttag != 0) fprintf(f, "id = %d;\n", firsttag); - if (mapthings[i].tags.count > 1) + if (wmapthings[i].tags.count > 1) { fprintf(f, "moreids = \""); - for (j = 1; j < mapthings[i].tags.count; j++) + for (j = 1; j < wmapthings[i].tags.count; j++) { if (j > 1) fprintf(f, " "); - fprintf(f, "%d", mapthings[i].tags.tags[j]); + fprintf(f, "%d", wmapthings[i].tags.tags[j]); } fprintf(f, "\";\n"); } @@ -2512,6 +2602,10 @@ static void P_WriteTextmap(void) fclose(f); + for (i = 0; i < nummapthings; i++) + if (wmapthings[i].tags.count) + Z_Free(wmapthings[i].tags.tags); + for (i = 0; i < numsectors; i++) if (wsectors[i].tags.count) Z_Free(wsectors[i].tags.tags); @@ -2525,6 +2619,7 @@ static void P_WriteTextmap(void) Z_Free(wsectors); Z_Free(wlines); Z_Free(wsides); + Z_Free(specialthings); } /** Loads the textmap data, after obtaining the elements count and allocating their respective space. From 1fdfb6ba6e84a5b8943282aede4d0cb0ff813451 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 13 Jan 2022 22:14:41 +0100 Subject: [PATCH 320/326] P_WriteTextmap: Add warning for linedef type 61 --- src/p_setup.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index c1e557cc9..7f4c63cad 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2112,6 +2112,13 @@ static void P_WriteTextmap(void) case 51: CONS_Alert(CONS_WARNING, M_GetText("Linedef %d has type %d, which is not supported in UDMF.\n"), i, wlines[i].special); break; + case 61: + if (wlines[i].flags & ML_MIDSOLID) + continue; + if (!wlines[i].args[1]) + continue; + CONS_Alert(CONS_WARNING, M_GetText("Linedef %d with crusher type 61 rises twice as fast on spawn. This behavior is not supported in UDMF.\n"), i); + break; case 76: if (freetag == (mtag_t)MAXTAGS) { From 7c0687bc33970319667bebc1d38eed2aceb995dc Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 13 Jan 2022 23:02:38 +0100 Subject: [PATCH 321/326] P_WriteTextmap: Copy colormap only to first tagged sector and do the rest via the linedef --- src/p_setup.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 7f4c63cad..55268fa54 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2209,8 +2209,16 @@ static void P_WriteTextmap(void) continue; wsectors[s].extra_colormap = wsides[wlines[i].sidenum[0]].colormap_data; + if (freetag == (mtag_t)MAXTAGS) + { + CONS_Alert(CONS_WARNING, M_GetText("No unused tag found. Linedef %d with type 606 cannot be converted.\n"), i); + break; + } + Tag_Add(&wsectors[s].tags, freetag); + wlines[i].args[1] = freetag; + freetag = Tag_NextUnused(freetag); + break; } - wlines[i].special = 0; } break; default: From 37bb9d9c1157c255946ebe1e015534994303a8fd Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 13 Jan 2022 23:11:10 +0100 Subject: [PATCH 322/326] Fix oversight with rising FOFs --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index ce6bd6c0b..b6ae43025 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6637,7 +6637,7 @@ void P_SpawnSpecials(boolean fromnetsave) } P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, lines[i].args[0], lines[i].args[4] << FRACBITS, ceilingtop, ceilingbottom, !!(lines[i].args[5] & TMFR_REVERSE), !!(lines[i].args[5] & TMFR_SPINDASH)); + P_AddRaiseThinker(lines[i].frontsector, lines[i].args[0], lines[i].args[5] << FRACBITS, ceilingtop, ceilingbottom, !!(lines[i].args[6] & TMFR_REVERSE), !!(lines[i].args[6] & TMFR_SPINDASH)); break; } case 200: // Light block From 323cfaace966168473fdfe17859bb3249440576c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 14 Jan 2022 19:40:45 +0100 Subject: [PATCH 323/326] Add blendmode support to FOFs --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 62 ++++- extras/conf/udb/Includes/SRB222_misc.cfg | 64 +++++ src/doomdata.h | 2 +- src/p_setup.c | 201 +++++++-------- src/p_spec.c | 252 ++++++++++--------- src/p_spec.h | 9 + src/r_defs.h | 2 +- 7 files changed, 360 insertions(+), 232 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index be0f3f0f3..e431de70c 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1910,6 +1910,12 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Appearance"; type = 12; @@ -1923,7 +1929,7 @@ udmf 32 = "Cut cyan flat pixels"; } } - arg3 + arg4 { title = "Tangibility"; type = 12; @@ -1946,6 +1952,12 @@ udmf default = 128; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Flags"; type = 12; @@ -2013,12 +2025,18 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Tangibility"; type = 12; enum = "tangibility"; } - arg3 + arg4 { title = "Flags"; type = 12; @@ -2048,6 +2066,12 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Appearance"; type = 12; @@ -2061,17 +2085,17 @@ udmf 32 = "Cut cyan flat pixels"; } } - arg3 + arg4 { title = "Tangibility"; type = 12; enum = "tangibility"; } - arg4 + arg5 { title = "Speed"; } - arg5 + arg6 { title = "Flags"; type = 12; @@ -2126,6 +2150,12 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Appearance"; type = 12; @@ -2212,6 +2242,12 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Bustable type"; type = 11; @@ -2223,7 +2259,7 @@ udmf 3 = "Strong"; } } - arg3 + arg4 { title = "Flags"; type = 12; @@ -2235,7 +2271,7 @@ udmf 8 = "Cut cyan flat pixels"; } } - arg4 + arg5 { title = "Linedef executor tag"; type = 15; @@ -2282,6 +2318,12 @@ udmf default = 128; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Flags"; type = 12; @@ -2308,6 +2350,12 @@ udmf default = 255; } arg2 + { + title = "Blending mode"; + type = 11; + enum = "blendmodes"; + } + arg3 { title = "Flags"; type = 12; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 50c83e456..7fecf65f7 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -236,6 +236,26 @@ universalfields type = 0; default = 0; } + arg6 + { + type = 0; + default = 0; + } + arg7 + { + type = 0; + default = 0; + } + arg8 + { + type = 0; + default = 0; + } + arg9 + { + type = 0; + default = 0; + } stringarg0 { type = 2; @@ -264,6 +284,41 @@ universalfields thing { + arg5 + { + type = 0; + default = 0; + } + arg6 + { + type = 0; + default = 0; + } + arg7 + { + type = 0; + default = 0; + } + arg8 + { + type = 0; + default = 0; + } + arg9 + { + type = 0; + default = 0; + } + stringarg0 + { + type = 2; + default = ""; + } + stringarg1 + { + type = 2; + default = ""; + } } } @@ -448,6 +503,15 @@ enums 4 = "Don't block players"; 8 = "Don't block non-players"; } + + blendmodes + { + 0 = "Translucent"; + 1 = "Add"; + 2 = "Subtract"; + 3 = "Reverse subtract"; + 4 = "Modulate"; + } } //Default things filters diff --git a/src/doomdata.h b/src/doomdata.h index e317fec1b..630e18615 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -196,7 +196,7 @@ typedef struct #pragma pack() #endif -#define NUMMAPTHINGARGS 6 +#define NUMMAPTHINGARGS 10 #define NUMMAPTHINGSTRINGARGS 2 // Thing definition, position, orientation and type, diff --git a/src/p_setup.c b/src/p_setup.c index 694f15ef7..10bc1dfd3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3117,6 +3117,24 @@ static void P_AddBinaryMapTags(void) } } +static void P_SetBinaryFOFAlpha(line_t *line) +{ + if (sides[line->sidenum[0]].toptexture > 0) + { + line->args[1] = sides[line->sidenum[0]].toptexture; + if (sides[line->sidenum[0]].toptexture >= 1001) + { + line->args[2] = (sides[line->sidenum[0]].toptexture/1000); + line->args[1] %= 1000; + } + } + else + { + line->args[1] = 128; + line->args[2] = TMB_TRANSLUCENT; + } +} + //For maps in binary format, converts setup of specials to UDMF format. static void P_ConvertBinaryMap(void) { @@ -3195,36 +3213,33 @@ static void P_ConvertBinaryMap(void) if (lines[i].special == 102) { if (lines[i].flags & ML_NOCLIMB) - lines[i].args[2] |= TMFA_INSIDES; - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + lines[i].args[3] |= TMFA_INSIDES; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; } else lines[i].args[1] = 255; //Appearance if (lines[i].special == 105) - lines[i].args[2] |= TMFA_NOPLANES|TMFA_NOSIDES; + lines[i].args[3] |= TMFA_NOPLANES|TMFA_NOSIDES; else if (lines[i].special == 104) - lines[i].args[2] |= TMFA_NOSIDES; + lines[i].args[3] |= TMFA_NOSIDES; else if (lines[i].special == 103) - lines[i].args[2] |= TMFA_NOPLANES; + lines[i].args[3] |= TMFA_NOPLANES; if (lines[i].special != 100 && (lines[i].special != 104 || !(lines[i].flags & ML_NOCLIMB))) - lines[i].args[2] |= TMFA_NOSHADE; + lines[i].args[3] |= TMFA_NOSHADE; if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; //Tangibility if (lines[i].flags & ML_EFFECT1) - lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; + lines[i].args[4] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; + lines[i].args[4] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 100; break; @@ -3241,35 +3256,32 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = 255; else { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= TMFW_SPLAT; + lines[i].args[3] |= TMFW_SPLAT; } //No sides? if (lines[i].special == 122 || lines[i].special == 123 || lines[i].special == 125) - lines[i].args[2] |= TMFW_NOSIDES; + lines[i].args[3] |= TMFW_NOSIDES; //Flags if (lines[i].flags & ML_NOCLIMB) - lines[i].args[2] |= TMFW_DOUBLESHADOW; + lines[i].args[3] |= TMFW_DOUBLESHADOW; if (lines[i].flags & ML_EFFECT4) - lines[i].args[2] |= TMFW_COLORMAPONLY; + lines[i].args[3] |= TMFW_COLORMAPONLY; if (!(lines[i].flags & ML_EFFECT5)) - lines[i].args[2] |= TMFW_NORIPPLE; + lines[i].args[3] |= TMFW_NORIPPLE; //Goo? if (lines[i].special >= 124) - lines[i].args[2] |= TMFW_GOOWATER; + lines[i].args[3] |= TMFW_GOOWATER; //Splat rendering? if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= TMFW_SPLAT; + lines[i].args[3] |= TMFW_SPLAT; lines[i].special = 120; break; @@ -3286,41 +3298,38 @@ static void P_ConvertBinaryMap(void) if (lines[i].special == 141 || lines[i].special == 142 || lines[i].special == 144 || lines[i].special == 145) { if (lines[i].flags & ML_NOCLIMB) - lines[i].args[2] |= TMFA_INSIDES; - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + lines[i].args[3] |= TMFA_INSIDES; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; } else lines[i].args[1] = 255; //Appearance if (lines[i].special == 142 || lines[i].special == 145) - lines[i].args[2] |= TMFA_NOSIDES; + lines[i].args[3] |= TMFA_NOSIDES; else if (lines[i].special == 146) - lines[i].args[2] |= TMFA_NOPLANES; + lines[i].args[3] |= TMFA_NOPLANES; if (lines[i].special != 146 && (lines[i].flags & ML_NOCLIMB)) - lines[i].args[2] |= TMFA_NOSHADE; + lines[i].args[3] |= TMFA_NOSHADE; if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; //Tangibility if (lines[i].special <= 142) - lines[i].args[3] |= TMFT_INTANGIBLEBOTTOM; + lines[i].args[4] |= TMFT_INTANGIBLEBOTTOM; else if (lines[i].special <= 145) - lines[i].args[3] |= TMFT_INTANGIBLETOP; + lines[i].args[4] |= TMFT_INTANGIBLETOP; else - lines[i].args[3] |= TMFT_INTANGIBLEBOTTOM|TMFT_INTANGIBLETOP; + lines[i].args[4] |= TMFT_INTANGIBLEBOTTOM|TMFT_INTANGIBLETOP; if (lines[i].flags & ML_EFFECT1) - lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; + lines[i].args[4] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; + lines[i].args[4] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 100; break; @@ -3360,38 +3369,35 @@ static void P_ConvertBinaryMap(void) //Alpha if (lines[i].special >= 174 && lines[i].special <= 175) { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[3] |= TMFC_SPLAT; + lines[i].args[4] |= TMFC_SPLAT; } else lines[i].args[1] = 255; if (lines[i].special >= 172 && lines[i].special <= 175) { - lines[i].args[2] |= TMFT_INTANGIBLEBOTTOM; + lines[i].args[3] |= TMFT_INTANGIBLEBOTTOM; if (lines[i].flags & ML_NOCLIMB) - lines[i].args[3] |= TMFC_NOSHADE; + lines[i].args[4] |= TMFC_NOSHADE; } if (lines[i].special % 2 == 1) - lines[i].args[3] |= TMFC_NORETURN; + lines[i].args[4] |= TMFC_NORETURN; if (lines[i].special == 176 || lines[i].special == 177 || lines[i].special == 180) - lines[i].args[3] |= TMFC_AIRBOB; + lines[i].args[4] |= TMFC_AIRBOB; if (lines[i].special >= 176 && lines[i].special <= 179) - lines[i].args[3] |= TMFC_FLOATBOB; + lines[i].args[4] |= TMFC_FLOATBOB; if (lines[i].flags & ML_EFFECT6) - lines[i].args[3] |= TMFC_SPLAT; + lines[i].args[4] |= TMFC_SPLAT; if (lines[i].flags & ML_EFFECT1) - lines[i].args[2] |= TMFT_DONTBLOCKOTHERS; + lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[2] |= TMFT_DONTBLOCKPLAYER; + lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; lines[i].special = 170; break; @@ -3406,44 +3412,41 @@ static void P_ConvertBinaryMap(void) //Translucency if (lines[i].special == 192 || lines[i].special == 195) { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; } else lines[i].args[1] = 255; //Appearance if (lines[i].special == 193) - lines[i].args[2] |= TMFA_NOPLANES|TMFA_NOSIDES; + lines[i].args[3] |= TMFA_NOPLANES|TMFA_NOSIDES; if (lines[i].special >= 194) - lines[i].args[2] |= TMFA_INSIDES; + lines[i].args[3] |= TMFA_INSIDES; if (lines[i].special != 190 && (lines[i].special <= 193 || lines[i].flags & ML_NOCLIMB)) - lines[i].args[2] |= TMFA_NOSHADE; + lines[i].args[3] |= TMFA_NOSHADE; if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; //Tangibility if (lines[i].flags & ML_EFFECT1) - lines[i].args[3] |= TMFT_DONTBLOCKOTHERS; + lines[i].args[4] |= TMFT_DONTBLOCKOTHERS; if (lines[i].flags & ML_EFFECT2) - lines[i].args[3] |= TMFT_DONTBLOCKPLAYER; + lines[i].args[4] |= TMFT_DONTBLOCKPLAYER; if (lines[i].special >= 194) - lines[i].args[3] |= TMFT_INTANGIBLEBOTTOM; + lines[i].args[4] |= TMFT_INTANGIBLEBOTTOM; //Speed - lines[i].args[4] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].args[5] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; //Flags if (lines[i].flags & ML_BLOCKMONSTERS) - lines[i].args[5] |= TMFR_REVERSE; + lines[i].args[6] |= TMFR_REVERSE; if (lines[i].flags & ML_BLOCKMONSTERS) - lines[i].args[5] |= TMFR_SPINDASH; + lines[i].args[6] |= TMFR_SPINDASH; lines[i].special = 190; break; @@ -3466,27 +3469,24 @@ static void P_ConvertBinaryMap(void) //Alpha if (lines[i].special == 221) { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; } else lines[i].args[1] = 255; //Appearance if (lines[i].special == 222) - lines[i].args[2] |= TMFA_NOPLANES; + lines[i].args[3] |= TMFA_NOPLANES; if (lines[i].special == 221) - lines[i].args[2] |= TMFA_INSIDES; + lines[i].args[3] |= TMFA_INSIDES; if (lines[i].special != 220 && !(lines[i].flags & ML_NOCLIMB)) - lines[i].args[2] |= TMFA_NOSHADE; + lines[i].args[3] |= TMFA_NOSHADE; if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= TMFA_SPLAT; + lines[i].args[3] |= TMFA_SPLAT; lines[i].special = 220; break; @@ -3527,40 +3527,37 @@ static void P_ConvertBinaryMap(void) //Alpha if (lines[i].special == 253 || lines[i].special == 256) { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[3] |= TMFB_SPLAT; + lines[i].args[4] |= TMFB_SPLAT; } else lines[i].args[1] = 255; //Bustable type if (lines[i].special <= 253) - lines[i].args[2] = TMFB_TOUCH; + lines[i].args[3] = TMFB_TOUCH; else if (lines[i].special >= 255) - lines[i].args[2] = TMFB_SPIN; + lines[i].args[3] = TMFB_SPIN; else if (lines[i].flags & ML_NOCLIMB) - lines[i].args[2] = TMFB_STRONG; + lines[i].args[3] = TMFB_STRONG; else - lines[i].args[2] = TMFB_REGULAR; + lines[i].args[3] = TMFB_REGULAR; //Flags if (lines[i].flags & ML_EFFECT4) - lines[i].args[3] |= TMFB_PUSHABLES; + lines[i].args[4] |= TMFB_PUSHABLES; if (lines[i].flags & ML_EFFECT5) { - lines[i].args[3] |= TMFB_EXECUTOR; - lines[i].args[4] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; + lines[i].args[4] |= TMFB_EXECUTOR; + lines[i].args[5] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; } if (lines[i].special == 252 && lines[i].flags & ML_NOCLIMB) - lines[i].args[3] |= TMFB_ONLYBOTTOM; + lines[i].args[4] |= TMFB_ONLYBOTTOM; if (lines[i].flags & ML_EFFECT6) - lines[i].args[3] |= TMFB_SPLAT; + lines[i].args[4] |= TMFB_SPLAT; lines[i].special = 254; break; @@ -3575,17 +3572,14 @@ static void P_ConvertBinaryMap(void) lines[i].args[0] = tag; //Alpha - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Flags if (lines[i].flags & ML_EFFECT1) - lines[i].args[2] |= TMFL_NOBOSSES; + lines[i].args[3] |= TMFL_NOBOSSES; //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].flags & ML_EFFECT6 || lines[i].args[1] == 256) - lines[i].args[2] |= TMFL_SPLAT; + lines[i].args[3] |= TMFL_SPLAT; break; case 259: //Custom FOF @@ -3593,20 +3587,17 @@ static void P_ConvertBinaryMap(void) I_Error("Custom FOF (tag %d) found without a linedef back side!", tag); lines[i].args[0] = tag; - lines[i].args[2] = sides[lines[i].sidenum[1]].toptexture; + lines[i].args[3] = sides[lines[i].sidenum[1]].toptexture; if (lines[i].flags & ML_EFFECT6) - lines[i].args[2] |= FF_SPLAT; - lines[i].args[3] = sides[lines[i].sidenum[1]].midtexture; - if (lines[i].args[2] & FF_TRANSLUCENT) + lines[i].args[3] |= FF_SPLAT; + lines[i].args[4] = sides[lines[i].sidenum[1]].midtexture; + if (lines[i].args[3] & FF_TRANSLUCENT) { - if (sides[lines[i].sidenum[0]].toptexture > 0) - lines[i].args[1] = sides[lines[i].sidenum[0]].toptexture; - else - lines[i].args[1] = 128; + P_SetBinaryFOFAlpha(&lines[i]); //Replicate old hack: Translucent FOFs set to full opacity cut cyan pixels if (lines[i].args[1] == 256) - lines[i].args[2] |= FF_SPLAT; + lines[i].args[3] |= FF_SPLAT; } else lines[i].args[1] = 255; diff --git a/src/p_spec.c b/src/p_spec.c index 56fe98154..2b3e5a000 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -118,7 +118,7 @@ static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, ext static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); -static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorflags, thinkerlist_t *secthinkers); +static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, UINT8 blendmode, ffloortype_e ffloorflags, thinkerlist_t *secthinkers); static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec); static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer); static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee, UINT8 reverse); @@ -5467,12 +5467,13 @@ static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *fflr) * \param sec2 Control sector. * \param master Control linedef. * \param alpha Alpha value (0-255). + * \param blendmode Blending mode. * \param flags Options affecting this 3Dfloor. * \param secthinkers List of relevant thinkers sorted by sector. May be NULL. * \return Pointer to the new 3Dfloor. * \sa P_AddFFloor, P_AddFakeFloorsByLine, P_SpawnSpecials */ -static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, INT32 alpha, ffloortype_e flags, thinkerlist_t *secthinkers) +static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, INT32 alpha, UINT8 blendmode, ffloortype_e flags, thinkerlist_t *secthinkers) { ffloor_t *fflr; thinker_t *th; @@ -5598,15 +5599,29 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I { fflr->flags |= FF_TRANSLUCENT; fflr->spawnflags = fflr->flags; - - if (sides[master->sidenum[0]].toptexture >= 1001) - { - fflr->blend = (sides[master->sidenum[0]].toptexture / 1000) + 1; // becomes an AST - fflr->alpha %= 1000; - } } fflr->spawnalpha = fflr->alpha; // save for netgames + switch (blendmode) + { + case TMB_TRANSLUCENT: + default: + fflr->blend = AST_COPY; + break; + case TMB_ADD: + fflr->blend = AST_ADD; + break; + case TMB_SUBTRACT: + fflr->blend = AST_SUBTRACT; + break; + case TMB_REVERSESUBTRACT: + fflr->blend = AST_REVERSESUBTRACT; + break; + case TMB_MODULATE: + fflr->blend = AST_MODULATE; + break; + } + if (flags & FF_QUICKSAND) CheckForQuicksand = true; @@ -6459,29 +6474,81 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; //Appearance settings - if (lines[i].args[2] & TMFA_NOPLANES) + if (lines[i].args[3] & TMFA_NOPLANES) ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[2] & TMFA_NOSIDES) + if (lines[i].args[3] & TMFA_NOSIDES) ffloorflags &= ~FF_RENDERSIDES; - if (lines[i].args[2] & TMFA_INSIDES) + if (lines[i].args[3] & TMFA_INSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_ALLSIDES; } - if (lines[i].args[2] & TMFA_ONLYINSIDES) + if (lines[i].args[3] & TMFA_ONLYINSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_INVERTPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_INVERTSIDES; } - if (lines[i].args[2] & TMFA_NOSHADE) + if (lines[i].args[3] & TMFA_NOSHADE) ffloorflags |= FF_NOSHADE; - if (lines[i].args[2] & TMFA_SPLAT) + if (lines[i].args[3] & TMFA_SPLAT) ffloorflags |= FF_SPLAT; + //Tangibility settings + if (lines[i].args[4] & TMFT_INTANGIBLETOP) + ffloorflags |= FF_REVERSEPLATFORM; + if (lines[i].args[4] & TMFT_INTANGIBLEBOTTOM) + ffloorflags |= FF_PLATFORM; + if (lines[i].args[4] & TMFT_DONTBLOCKPLAYER) + ffloorflags &= ~FF_BLOCKPLAYER; + if (lines[i].args[4] & TMFT_DONTBLOCKOTHERS) + ffloorflags &= ~FF_BLOCKOTHERS; + + //Cutting options + if (ffloorflags & FF_RENDERALL) + { + //If translucent or player can enter it, cut inner walls + if ((lines[i].args[1] < 255) || (lines[i].args[4] & TMFT_VISIBLEFROMINSIDE)) + ffloorflags |= FF_CUTEXTRA|FF_EXTRA; + else + ffloorflags |= FF_CUTLEVEL; + } + + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); + break; + + case 120: // FOF (water) + ffloorflags = FF_EXISTS|FF_RENDERPLANES|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; + if (!(lines[i].args[3] & TMFW_NOSIDES)) + ffloorflags |= FF_RENDERSIDES|FF_ALLSIDES; + if (lines[i].args[3] & TMFW_DOUBLESHADOW) + ffloorflags |= FF_DOUBLESHADOW; + if (lines[i].args[3] & TMFW_COLORMAPONLY) + ffloorflags |= FF_COLORMAPONLY; + if (!(lines[i].args[3] & TMFW_NORIPPLE)) + ffloorflags |= FF_RIPPLE; + if (lines[i].args[3] & TMFW_GOOWATER) + ffloorflags |= FF_GOOWATER; + if (lines[i].args[3] & TMFW_SPLAT) + ffloorflags |= FF_SPLAT; + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); + break; + + case 150: // FOF (Air bobbing) + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, FF_EXISTS|FF_SOLID|FF_RENDERALL, secthinkers); + P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); + break; + + case 160: // FOF (Water bobbing) + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB, secthinkers); + break; + + case 170: // FOF (Crumbling) + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE; + //Tangibility settings if (lines[i].args[3] & TMFT_INTANGIBLETOP) ffloorflags |= FF_REVERSEPLATFORM; @@ -6492,76 +6559,24 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) ffloorflags &= ~FF_BLOCKOTHERS; - //Cutting options - if (ffloorflags & FF_RENDERALL) - { - //If translucent or player can enter it, cut inner walls - if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) - ffloorflags |= FF_CUTEXTRA|FF_EXTRA; - else - ffloorflags |= FF_CUTLEVEL; - } - - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - break; - - case 120: // FOF (water) - ffloorflags = FF_EXISTS|FF_RENDERPLANES|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; - if (!(lines[i].args[2] & TMFW_NOSIDES)) - ffloorflags |= FF_RENDERSIDES|FF_ALLSIDES; - if (lines[i].args[2] & TMFW_DOUBLESHADOW) - ffloorflags |= FF_DOUBLESHADOW; - if (lines[i].args[2] & TMFW_COLORMAPONLY) - ffloorflags |= FF_COLORMAPONLY; - if (!(lines[i].args[2] & TMFW_NORIPPLE)) - ffloorflags |= FF_RIPPLE; - if (lines[i].args[2] & TMFW_GOOWATER) - ffloorflags |= FF_GOOWATER; - if (lines[i].args[2] & TMFW_SPLAT) - ffloorflags |= FF_SPLAT; - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - break; - - case 150: // FOF (Air bobbing) - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL, secthinkers); - P_AddAirbob(lines[i].frontsector, lines[i].args[0], lines[i].args[1] << FRACBITS, !!(lines[i].args[2] & TMFB_REVERSE), !!(lines[i].args[2] & TMFB_SPINDASH), !!(lines[i].args[2] & TMFB_DYNAMIC)); - break; - - case 160: // FOF (Water bobbing) - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB, secthinkers); - break; - - case 170: // FOF (Crumbling) - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE; - - //Tangibility settings - if (lines[i].args[2] & TMFT_INTANGIBLETOP) - ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[2] & TMFT_INTANGIBLEBOTTOM) - ffloorflags |= FF_PLATFORM; - if (lines[i].args[2] & TMFT_DONTBLOCKPLAYER) - ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[2] & TMFT_DONTBLOCKOTHERS) - ffloorflags &= ~FF_BLOCKOTHERS; - //Flags - if (lines[i].args[3] & TMFC_NOSHADE) + if (lines[i].args[4] & TMFC_NOSHADE) ffloorflags |= FF_NOSHADE; - if (lines[i].args[3] & TMFC_NORETURN) + if (lines[i].args[4] & TMFC_NORETURN) ffloorflags |= FF_NORETURN; - if (lines[i].args[3] & TMFC_FLOATBOB) + if (lines[i].args[4] & TMFC_FLOATBOB) ffloorflags |= FF_FLOATBOB; - if (lines[i].args[3] & TMFC_SPLAT) + if (lines[i].args[4] & TMFC_SPLAT) ffloorflags |= FF_SPLAT; //If translucent or player can enter it, cut inner walls - if (lines[i].args[1] < 0xff || (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE)) + if (lines[i].args[1] < 0xff || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) ffloorflags |= FF_CUTEXTRA|FF_EXTRA; else ffloorflags |= FF_CUTLEVEL; //If player can enter it, render insides - if (lines[i].args[2] & TMFT_VISIBLEFROMINSIDE) + if (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; @@ -6569,8 +6584,8 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags |= FF_ALLSIDES; } - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - if (lines[i].args[3] & TMFC_AIRBOB) + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); + if (lines[i].args[4] & TMFC_AIRBOB) P_AddAirbob(lines[i].frontsector, lines[i].args[0], 16*FRACUNIT, false, false, false); break; @@ -6582,58 +6597,58 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL; //Appearance settings - if (lines[i].args[2] & TMFA_NOPLANES) + if (lines[i].args[3] & TMFA_NOPLANES) ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[2] & TMFA_NOSIDES) + if (lines[i].args[3] & TMFA_NOSIDES) ffloorflags &= ~FF_RENDERSIDES; - if (lines[i].args[2] & TMFA_INSIDES) + if (lines[i].args[3] & TMFA_INSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_ALLSIDES; } - if (lines[i].args[2] & TMFA_ONLYINSIDES) + if (lines[i].args[3] & TMFA_ONLYINSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_INVERTPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_INVERTSIDES; } - if (lines[i].args[2] & TMFA_NOSHADE) + if (lines[i].args[3] & TMFA_NOSHADE) ffloorflags |= FF_NOSHADE; - if (lines[i].args[2] & TMFA_SPLAT) + if (lines[i].args[3] & TMFA_SPLAT) ffloorflags |= FF_SPLAT; //Tangibility settings - if (lines[i].args[3] & TMFT_INTANGIBLETOP) + if (lines[i].args[4] & TMFT_INTANGIBLETOP) ffloorflags |= FF_REVERSEPLATFORM; - if (lines[i].args[3] & TMFT_INTANGIBLEBOTTOM) + if (lines[i].args[4] & TMFT_INTANGIBLEBOTTOM) ffloorflags |= FF_PLATFORM; - if (lines[i].args[3] & TMFT_DONTBLOCKPLAYER) + if (lines[i].args[4] & TMFT_DONTBLOCKPLAYER) ffloorflags &= ~FF_BLOCKPLAYER; - if (lines[i].args[3] & TMFT_DONTBLOCKOTHERS) + if (lines[i].args[4] & TMFT_DONTBLOCKOTHERS) ffloorflags &= ~FF_BLOCKOTHERS; //Cutting options if (ffloorflags & FF_RENDERALL) { //If translucent or player can enter it, cut inner walls - if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)) + if ((lines[i].args[1] < 255) || (lines[i].args[4] & TMFT_VISIBLEFROMINSIDE)) ffloorflags |= FF_CUTEXTRA|FF_EXTRA; else ffloorflags |= FF_CUTLEVEL; } - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, lines[i].args[0], lines[i].args[4] << FRACBITS, ceilingtop, ceilingbottom, !!(lines[i].args[5] & TMFR_REVERSE), !!(lines[i].args[5] & TMFR_SPINDASH)); + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); + P_AddRaiseThinker(lines[i].frontsector, lines[i].args[0], lines[i].args[5] << FRACBITS, ceilingtop, ceilingbottom, !!(lines[i].args[6] & TMFR_REVERSE), !!(lines[i].args[6] & TMFR_SPINDASH)); break; } case 200: // Light block ffloorflags = FF_EXISTS|FF_CUTSPRITES; if (!lines[i].args[1]) ffloorflags |= FF_DOUBLESHADOW; - P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, ffloorflags, secthinkers); break; case 202: // Fog @@ -6642,41 +6657,41 @@ void P_SpawnSpecials(boolean fromnetsave) // SoM: Because it's fog, check for an extra colormap and set the fog flag... if (sectors[sec].extra_colormap) sectors[sec].extra_colormap->flags = CMF_FOG; - P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, ffloorflags, secthinkers); break; case 220: //Intangible ffloorflags = FF_EXISTS|FF_RENDERALL|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES; //Appearance settings - if (lines[i].args[2] & TMFA_NOPLANES) + if (lines[i].args[3] & TMFA_NOPLANES) ffloorflags &= ~FF_RENDERPLANES; - if (lines[i].args[2] & TMFA_NOSIDES) + if (lines[i].args[3] & TMFA_NOSIDES) ffloorflags &= ~FF_RENDERSIDES; - if (!(lines[i].args[2] & TMFA_INSIDES)) + if (!(lines[i].args[3] & TMFA_INSIDES)) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_BOTHPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_ALLSIDES; } - if (lines[i].args[2] & TMFA_ONLYINSIDES) + if (lines[i].args[3] & TMFA_ONLYINSIDES) { if (ffloorflags & FF_RENDERPLANES) ffloorflags |= FF_INVERTPLANES; if (ffloorflags & FF_RENDERSIDES) ffloorflags |= FF_INVERTSIDES; } - if (lines[i].args[2] & TMFA_NOSHADE) + if (lines[i].args[3] & TMFA_NOSHADE) ffloorflags |= FF_NOSHADE; - if (lines[i].args[2] & TMFA_SPLAT) + if (lines[i].args[3] & TMFA_SPLAT) ffloorflags |= FF_SPLAT; - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); break; case 223: // FOF (intangible, invisible) - for combining specials in a sector - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_NOSHADE, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, FF_EXISTS|FF_NOSHADE, secthinkers); break; case 250: // Mario Block @@ -6686,14 +6701,14 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[1] & TMFM_INVISIBLE) ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); - P_AddFakeFloorsByLine(i, 0xff, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, ffloorflags, secthinkers); break; case 251: // A THWOMP! { UINT16 sound = (lines[i].stringargs[0]) ? get_number(lines[i].stringargs[0]) : sfx_thwomp; P_AddThwompThinker(lines[i].frontsector, &lines[i], lines[i].args[1] << (FRACBITS - 3), lines[i].args[2] << (FRACBITS - 3), sound); - P_AddFakeFloorsByLine(i, 0xff, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); + P_AddFakeFloorsByLine(i, 0xff, TMB_TRANSLUCENT, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); break; } @@ -6705,7 +6720,7 @@ void P_SpawnSpecials(boolean fromnetsave) ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP; //Bustable type - switch (lines[i].args[2]) + switch (lines[i].args[3]) { case TMFB_TOUCH: busttype = BT_TOUCH; @@ -6722,13 +6737,13 @@ void P_SpawnSpecials(boolean fromnetsave) } //Flags - if (lines[i].args[3] & TMFB_PUSHABLES) + if (lines[i].args[4] & TMFB_PUSHABLES) bustflags |= FB_PUSHABLES; - if (lines[i].args[3] & TMFB_EXECUTOR) + if (lines[i].args[4] & TMFB_EXECUTOR) bustflags |= FB_EXECUTOR; - if (lines[i].args[3] & TMFB_ONLYBOTTOM) + if (lines[i].args[4] & TMFB_ONLYBOTTOM) bustflags |= FB_ONLYBOTTOM; - if (lines[i].args[3] & TMFB_SPLAT) + if (lines[i].args[4] & TMFB_SPLAT) ffloorflags |= FF_SPLAT; if (busttype != BT_TOUCH || bustflags & FB_ONLYBOTTOM) @@ -6736,12 +6751,12 @@ void P_SpawnSpecials(boolean fromnetsave) TAG_ITER_SECTORS(lines[i].args[0], s) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); if (!fflr) continue; fflr->bustflags = bustflags; fflr->busttype = busttype; - fflr->busttag = lines[i].args[4]; + fflr->busttag = lines[i].args[5]; } break; } @@ -6752,7 +6767,7 @@ void P_SpawnSpecials(boolean fromnetsave) TAG_ITER_SECTORS(lines[i].args[0], s) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, ffloorflags, secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, 0xff, TMB_TRANSLUCENT, ffloorflags, secthinkers); if (!fflr) continue; fflr->sinkspeed = abs(lines[i].args[2]) << (FRACBITS - 1); @@ -6762,28 +6777,28 @@ void P_SpawnSpecials(boolean fromnetsave) case 258: // Laser block ffloorflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT; - P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[2] & TMFL_NOBOSSES)); - if (lines[i].args[2] & TMFL_SPLAT) + P_AddLaserThinker(lines[i].args[0], lines + i, !!(lines[i].args[3] & TMFL_NOBOSSES)); + if (lines[i].args[3] & TMFL_SPLAT) ffloorflags |= FF_SPLAT; - P_AddFakeFloorsByLine(i, lines[i].args[1], ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); break; case 259: // Custom FOF TAG_ITER_SECTORS(lines[i].args[0], s) { - ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], lines[i].args[2], secthinkers); + ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], lines[i].args[2], lines[i].args[3], secthinkers); if (!fflr) continue; if (!udmf) // Ugly backwards compatibility stuff { - if (lines[i].args[2] & FF_QUICKSAND) + if (lines[i].args[3] & FF_QUICKSAND) { fflr->sinkspeed = abs(lines[i].dx) >> 1; fflr->friction = abs(lines[i].dy) >> 6; } - if (lines[i].args[2] & FF_BUSTUP) + if (lines[i].args[3] & FF_BUSTUP) { - switch (lines[i].args[3] % TMFB_ONLYBOTTOM) + switch (lines[i].args[4] % TMFB_ONLYBOTTOM) { case TMFB_TOUCH: fflr->busttype = BT_TOUCH; @@ -6799,7 +6814,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; } - if (lines[i].args[3] & TMFB_ONLYBOTTOM) + if (lines[i].args[4] & TMFB_ONLYBOTTOM) fflr->bustflags |= FB_ONLYBOTTOM; if (lines[i].flags & ML_EFFECT4) fflr->bustflags |= FB_PUSHABLES; @@ -6874,7 +6889,7 @@ void P_SpawnSpecials(boolean fromnetsave) } } - P_AddFakeFloorsByLine(i, dopacity, ffloorflags, secthinkers); + P_AddFakeFloorsByLine(i, dopacity, TMB_TRANSLUCENT, ffloorflags, secthinkers); } break; @@ -7280,12 +7295,13 @@ void P_SpawnSpecials(boolean fromnetsave) * * \param line Control linedef to use. * \param alpha Alpha value (0-255). + * \param blendmode Blending mode. * \param ffloorflags 3Dfloor flags to use. * \param secthkiners Lists of thinkers sorted by sector. May be NULL. * \sa P_SpawnSpecials, P_AddFakeFloor * \author Graue */ -static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorflags, thinkerlist_t *secthinkers) +static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, UINT8 blendmode, ffloortype_e ffloorflags, thinkerlist_t *secthinkers) { INT32 s; mtag_t tag = lines[line].args[0]; @@ -7293,7 +7309,7 @@ static void P_AddFakeFloorsByLine(size_t line, INT32 alpha, ffloortype_e ffloorf line_t* li = lines + line; TAG_ITER_SECTORS(tag, s) - P_AddFakeFloor(§ors[s], §ors[sec], li, alpha, ffloorflags, secthinkers); + P_AddFakeFloor(§ors[s], §ors[sec], li, alpha, blendmode, ffloorflags, secthinkers); } /* diff --git a/src/p_spec.h b/src/p_spec.h index 536b6c313..a3dbb9322 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -102,6 +102,15 @@ typedef enum TMFL_SPLAT = 1<<1, } textmapfoflaserflags_t; +typedef enum +{ + TMB_TRANSLUCENT = 0, + TMB_ADD = 1, + TMB_SUBTRACT = 2, + TMB_REVERSESUBTRACT = 3, + TMB_MODULATE = 4, +} textmapblendmodes_t; + // GETSECSPECIAL (specialval, section) // // Pulls out the special # from a particular section. diff --git a/src/r_defs.h b/src/r_defs.h index 43caa3d79..8bb0b4b9f 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -402,7 +402,7 @@ typedef enum #define HORIZONSPECIAL 41 -#define NUMLINEARGS 6 +#define NUMLINEARGS 10 #define NUMLINESTRINGARGS 2 typedef struct line_s From 9815d40c2034be1630f129ebfdd5ce282dbb2e2a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 20 Apr 2022 20:06:08 +0200 Subject: [PATCH 324/326] Adapt tutorial plant to UDMF --- extras/conf/udb/Includes/SRB222_things.cfg | 32 ++++++++++++++++++++++ src/p_mobj.c | 6 ++-- src/p_setup.c | 3 ++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index c5a881c5c..53d70647b 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3044,6 +3044,20 @@ doom } } + tutorial + { + color = 10; // Green + title = "Tutorial"; + + 799 + { + title = "Tutorial Plant"; + sprite = "TUPFH0"; + width = 40; + height = 144; + } + } + flickies { color = 10; // Green @@ -7867,6 +7881,24 @@ udmf } } + tutorial + { + color = 10; // Green + title = "Tutorial"; + + 799 + { + title = "Tutorial Plant"; + sprite = "TUPFH0"; + width = 40; + height = 144; + arg0 + { + title = "Start frame"; + } + } + } + flickies { color = 10; // Green diff --git a/src/p_mobj.c b/src/p_mobj.c index ea53395ed..9056f5a3f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12922,15 +12922,15 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean { segment = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_TUTORIALLEAF); segment->angle = mobj->angle + FixedAngle(i*60*FRACUNIT); - P_SetMobjState(segment, S_TUTORIALLEAF1 + mthing->extrainfo); + P_SetMobjState(segment, S_TUTORIALLEAF1 + mthing->args[0]); } for (i = 0; i < 3; i++) { segment = P_SpawnMobjFromMobj(mobj, 0, 0, 112*FRACUNIT, MT_TUTORIALFLOWER); segment->angle = mobj->angle + FixedAngle(i*120*FRACUNIT); - P_SetMobjState(segment, S_TUTORIALFLOWER1 + mthing->extrainfo); + P_SetMobjState(segment, S_TUTORIALFLOWER1 + mthing->args[0]); } - P_SetMobjState(P_SpawnMobjFromMobj(mobj, 0, 0, 112*FRACUNIT, MT_TUTORIALFLOWERF), S_TUTORIALFLOWERF1 + mthing->extrainfo); + P_SetMobjState(P_SpawnMobjFromMobj(mobj, 0, 0, 112*FRACUNIT, MT_TUTORIALFLOWERF), S_TUTORIALFLOWERF1 + mthing->args[0]); } break; case MT_CEZPOLE1: diff --git a/src/p_setup.c b/src/p_setup.c index 45c5cc3b3..89e7175bc 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5262,6 +5262,9 @@ static void P_ConvertBinaryMap(void) case 780: //Skybox mapthings[i].args[0] = !!(mapthings[i].options & MTF_OBJECTSPECIAL); break; + case 799: //Tutorial plant + mapthings[i].args[0] = mapthings[i].extrainfo; + break; case 1002: //Dripping water mapthings[i].args[0] = mapthings[i].angle; break; From 465327288c7be322bb71014693dac1d3e05754f5 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 20 Apr 2022 20:55:13 +0200 Subject: [PATCH 325/326] Fix int type error --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 1ce965da9..d2f032c43 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2780,7 +2780,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (mo && mo->player) { powertype_t power = line->stringargs[0] ? get_number(line->stringargs[0]) : 0; - UINT16 value = line->stringargs[1] ? get_number(line->stringargs[1]) : 0; + INT32 value = line->stringargs[1] ? get_number(line->stringargs[1]) : 0; if (value == -1) // 'Infinite' value = UINT16_MAX; From d400a7186a2169411029fbc070874f6e6f841a82 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 20 Apr 2022 20:57:16 +0200 Subject: [PATCH 326/326] Fix int type error --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index d38ab2d4f..e645e0c16 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2724,7 +2724,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (mo && mo->player) { powertype_t power = line->stringargs[0] ? get_number(line->stringargs[0]) : 0; - UINT16 value = line->stringargs[1] ? get_number(line->stringargs[1]) : 0; + INT32 value = line->stringargs[1] ? get_number(line->stringargs[1]) : 0; if (value == -1) // 'Infinite' value = UINT16_MAX;