Merge public next into uncappedrevengeance

This is to capture the UDMF merges and make the later code review
easier.
This commit is contained in:
Eidolon 2022-05-03 14:45:14 -05:00
commit 805941a98f
51 changed files with 21619 additions and 9768 deletions

View file

@ -425,20 +425,18 @@ sectortypes
12 = "Space Countdown"; 12 = "Space Countdown";
13 = "Ramp Sector (double step-up/down)"; 13 = "Ramp Sector (double step-up/down)";
14 = "Non-Ramp Sector (no step-down)"; 14 = "Non-Ramp Sector (no step-down)";
15 = "Bouncy FOF"; 15 = "Bouncy FOF <deprecated>";
16 = "Trigger Line Ex. (Pushable Objects)"; 16 = "Trigger Line Ex. (Pushable Objects)";
32 = "Trigger Line Ex. (Anywhere, All Players)"; 32 = "Trigger Line Ex. (Anywhere, All Players)";
48 = "Trigger Line Ex. (Floor Touch, All Players)"; 48 = "Trigger Line Ex. (Floor Touch, All Players)";
64 = "Trigger Line Ex. (Anywhere in Sector)"; 64 = "Trigger Line Ex. (Anywhere in Sector)";
80 = "Trigger Line Ex. (Floor Touch)"; 80 = "Trigger Line Ex. (Floor Touch)";
96 = "Trigger Line Ex. (Emerald Check)"; 96 = "Trigger Line Ex. (Emerald Check) <deprecated>";
112 = "Trigger Line Ex. (NiGHTS Mare)"; 112 = "Trigger Line Ex. (NiGHTS Mare) <deprecated>";
128 = "Check for Linedef Executor on FOFs"; 128 = "Check for Linedef Executor on FOFs";
144 = "Egg Capsule"; 144 = "Egg Capsule";
160 = "Special Stage Time/Spheres Parameters"; 160 = "Special Stage Time/Spheres Parameters <deprecated>";
176 = "Custom Global Gravity"; 176 = "Custom Global Gravity <deprecated>";
512 = "Wind/Current";
1024 = "Conveyor Belt";
1280 = "Speed Pad"; 1280 = "Speed Pad";
4096 = "Star Post Activator"; 4096 = "Star Post Activator";
8192 = "Exit/Special Stage Pit/Return Flag"; 8192 = "Exit/Special Stage Pit/Return Flag";
@ -475,7 +473,7 @@ gen_sectortypes
12 = "Space Countdown"; 12 = "Space Countdown";
13 = "Ramp Sector (double step-up/down)"; 13 = "Ramp Sector (double step-up/down)";
14 = "Non-Ramp Sector (no step-down)"; 14 = "Non-Ramp Sector (no step-down)";
15 = "Bouncy FOF"; 15 = "Bouncy FOF <deprecated>";
} }
second second
@ -486,19 +484,17 @@ gen_sectortypes
48 = "Trigger Line Ex. (Floor Touch, All Players)"; 48 = "Trigger Line Ex. (Floor Touch, All Players)";
64 = "Trigger Line Ex. (Anywhere in Sector)"; 64 = "Trigger Line Ex. (Anywhere in Sector)";
80 = "Trigger Line Ex. (Floor Touch)"; 80 = "Trigger Line Ex. (Floor Touch)";
96 = "Trigger Line Ex. (Emerald Check)"; 96 = "Trigger Line Ex. (Emerald Check) <deprecated>";
112 = "Trigger Line Ex. (NiGHTS Mare)"; 112 = "Trigger Line Ex. (NiGHTS Mare) <deprecated>";
128 = "Check for Linedef Executor on FOFs"; 128 = "Check for Linedef Executor on FOFs";
144 = "Egg Capsule"; 144 = "Egg Capsule";
160 = "Special Stage Time/Spheres Parameters"; 160 = "Special Stage Time/Spheres Parameters <deprecated>";
176 = "Custom Global Gravity"; 176 = "Custom Global Gravity <deprecated>";
} }
third third
{ {
0 = "Normal"; 0 = "Normal";
512 = "Wind/Current";
1024 = "Conveyor Belt";
1280 = "Speed Pad"; 1280 = "Speed Pad";
} }
@ -771,6 +767,12 @@ linedeftypes
flags2text = "[1] Use control sector tag"; flags2text = "[1] Use control sector tag";
flags64text = "[6] No sound effect"; flags64text = "[6] No sound effect";
} }
76
{
title = "Make FOF Bouncy";
prefix = "(76)";
}
} }
polyobject polyobject
@ -1279,7 +1281,7 @@ linedeftypes
160 160
{ {
title = "Floating, Bobbing"; title = "Water Bobbing";
prefix = "(160)"; prefix = "(160)";
flags8text = "[3] Slope skew sides"; flags8text = "[3] Slope skew sides";
flags32text = "[5] Only block player"; flags32text = "[5] Only block player";
@ -2018,6 +2020,48 @@ linedeftypes
flags1024text = "[10] Use faster, unordered execution"; flags1024text = "[10] Use faster, unordered execution";
} }
337
{
title = "Emerald Check - Continuous";
prefix = "(337)";
}
338
{
title = "Emerald Check - Each Time";
prefix = "(338)";
}
339
{
title = "Emerald Check - Once";
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 399
{ {
title = "Level Load"; title = "Level Load";
@ -2048,23 +2092,35 @@ linedeftypes
402 402
{ {
title = "Set Tagged Sector's Light Level"; title = "Copy Light Level to Tagged Sectors";
prefix = "(402)"; prefix = "(402)";
flags8text = "[3] Set delay by backside sector"; 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 409
{ {
title = "Change Tagged Sector's Tag"; title = "Change Tagged Sector's Tag";
prefix = "(409)"; prefix = "(409)";
flags2text = "[1] Remove tag";
flags8text = "[3] Set delay by backside sector"; flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Add tag";
} }
410 410
{ {
title = "Change Front Sector's Tag"; title = "Change Front Sector's Tag";
prefix = "(410)"; prefix = "(410)";
flags2text = "[1] Remove tag";
flags8text = "[3] Set delay by backside sector"; flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Add tag";
} }
416 416
@ -2122,6 +2178,14 @@ linedeftypes
prefix = "(435)"; prefix = "(435)";
flags8text = "[3] Set delay by backside sector"; 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 linedefexecplane
@ -3228,6 +3292,7 @@ linedeftypes
{ {
title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; title = "Set Tagged Dynamic Slope Vertex to Front Sector Height";
prefix = "(799)"; prefix = "(799)";
flags64text = "[6] Use relative heights";
} }
} }

View file

@ -191,6 +191,12 @@ mapformat_doom
// that make the same thing appear in the same modes // that make the same thing appear in the same modes
thingflagsmask1 = 7; // 1 + 2 + 4 thingflagsmask1 = 7; // 1 + 2 + 4
thingflagsmask2 = 0; thingflagsmask2 = 0;
// THING TYPES
thingtypes
{
include("SRB222_things.cfg", "doom");
}
} }
mapformat_udmf mapformat_udmf
@ -240,17 +246,7 @@ mapformat_udmf
include("SRB222_misc.cfg", "sectorbrightness"); include("SRB222_misc.cfg", "sectorbrightness");
} }
// SECTOR TYPES damagetypes = "Generic Water Fire Lava Electric Spike DeathPitTilt DeathPitNoTilt Instakill SpecialStage";
sectortypes
{
include("SRB222_sectors.cfg", "sectortypes");
}
// GENERALISED SECTOR TYPES
gen_sectortypes
{
include("SRB222_sectors.cfg", "gen_sectortypes");
}
// LINEDEF FLAGS // LINEDEF FLAGS
linedefflags linedefflags
@ -289,6 +285,12 @@ mapformat_udmf
include("UDMF_misc.cfg", "thingflagscompare"); include("UDMF_misc.cfg", "thingflagscompare");
} }
// THING TYPES
thingtypes
{
include("SRB222_things.cfg", "udmf");
}
// LINEDEF TYPES // LINEDEF TYPES
linedeftypes linedeftypes
{ {

File diff suppressed because it is too large Load diff

View file

@ -58,7 +58,6 @@ linedefflags_udmf
wrapmidtex = "Repeat Midtexture"; wrapmidtex = "Repeat Midtexture";
netonly = "Netgame Only"; netonly = "Netgame Only";
nonet = "No Netgame"; nonet = "No Netgame";
effect6 = "Effect 6";
bouncy = "Bouncy Wall"; bouncy = "Bouncy Wall";
transfer = "Transfer Line"; transfer = "Transfer Line";
} }
@ -78,6 +77,33 @@ sectorflags
colormapfog = "Fog Planes in Colormap"; colormapfog = "Fog Planes in Colormap";
colormapfadesprites = "Fade Fullbright in Colormap"; colormapfadesprites = "Fade Fullbright in Colormap";
colormapprotected = "Protected 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";
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";
noclipcamera = "Intangible to the Camera";
outerspace = "Space Countdown";
doublestepup = "Ramp Sector (double step-up/down)";
nostepdown = "Non-Ramp Sector (No step-down)";
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 thingflags
@ -91,10 +117,7 @@ thingflags
// THING FLAGS // THING FLAGS
thingflags_udmf thingflags_udmf
{ {
extra = "Extra";
flip = "Flip"; flip = "Flip";
special = "Special";
ambush = "Ambush";
} }
@ -227,6 +250,30 @@ universalfields
type = 3; type = 3;
default = false; default = false;
} }
friction
{
type = 1;
default = 0.90625;
}
triggertag
{
type = 15;
default = 0;
}
triggerer
{
type = 0;
default = 0;
enum
{
0 = "Player";
1 = "All players";
2 = "Object";
}
}
} }
linedef linedef
@ -236,6 +283,26 @@ universalfields
type = 0; type = 0;
default = 0; default = 0;
} }
arg6
{
type = 0;
default = 0;
}
arg7
{
type = 0;
default = 0;
}
arg8
{
type = 0;
default = 0;
}
arg9
{
type = 0;
default = 0;
}
stringarg0 stringarg0
{ {
type = 2; type = 2;
@ -264,6 +331,41 @@ universalfields
thing 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 = "";
}
} }
} }
@ -410,6 +512,12 @@ enums
1 = "Yes"; 1 = "Yes";
} }
setadd
{
0 = "Set";
1 = "Add";
}
onoff onoff
{ {
0 = "On"; 0 = "On";
@ -441,6 +549,13 @@ enums
2 = "Back"; 2 = "Back";
} }
frontbackboth
{
0 = "Front";
1 = "Back";
2 = "Front and back";
}
tangibility tangibility
{ {
1 = "Intangible from top"; 1 = "Intangible from top";
@ -448,6 +563,100 @@ enums
4 = "Don't block players"; 4 = "Don't block players";
8 = "Don't block non-players"; 8 = "Don't block non-players";
} }
floorceiling
{
0 = "Floor";
1 = "Ceiling";
2 = "Both";
}
scrollcarry
{
0 = "Scroll and carry";
1 = "Scroll";
2 = "Carry";
}
scrolltype
{
0 = "Regular";
1 = "Accelerative";
2 = "Displacement";
}
comparison
{
0 = "Equal";
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";
}
xtriggertype
{
0 = "Continuous";
1 = "Each time on entry";
2 = "Each time on entry/exit";
}
team
{
0 = "Red";
1 = "Blue";
}
flagcheck
{
0 = "Has all";
1 = "Has any";
2 = "Has exactly";
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";
}
pushablebehavior
{
0 = "Normal";
1 = "Slide";
2 = "Immovable";
3 = "Classic";
}
monitorrespawn
{
0 = "Same item";
1 = "Random (Weak)";
2 = "Random (Strong)";
}
blendmodes
{
0 = "Translucent";
1 = "Add";
2 = "Subtract";
3 = "Reverse subtract";
4 = "Modulate";
}
} }
//Default things filters //Default things filters
@ -626,4 +835,4 @@ flats
start = "F_START"; start = "F_START";
end = "FF_END"; end = "FF_END";
} }
} }

View file

@ -15,20 +15,18 @@ sectortypes
12 = "Space Countdown"; 12 = "Space Countdown";
13 = "Ramp Sector (double step-up/down)"; 13 = "Ramp Sector (double step-up/down)";
14 = "Non-Ramp Sector (no step-down)"; 14 = "Non-Ramp Sector (no step-down)";
15 = "Bouncy FOF"; 15 = "Bouncy FOF <deprecated>";
16 = "Trigger Line Ex. (Pushable Objects)"; 16 = "Trigger Line Ex. (Pushable Objects)";
32 = "Trigger Line Ex. (Anywhere, All Players)"; 32 = "Trigger Line Ex. (Anywhere, All Players)";
48 = "Trigger Line Ex. (Floor Touch, All Players)"; 48 = "Trigger Line Ex. (Floor Touch, All Players)";
64 = "Trigger Line Ex. (Anywhere in Sector)"; 64 = "Trigger Line Ex. (Anywhere in Sector)";
80 = "Trigger Line Ex. (Floor Touch)"; 80 = "Trigger Line Ex. (Floor Touch)";
96 = "Trigger Line Ex. (Emerald Check)"; 96 = "Trigger Line Ex. (Emerald Check) <deprecated>";
112 = "Trigger Line Ex. (NiGHTS Mare)"; 112 = "Trigger Line Ex. (NiGHTS Mare) <deprecated>";
128 = "Check for Linedef Executor on FOFs"; 128 = "Check for Linedef Executor on FOFs";
144 = "Egg Capsule"; 144 = "Egg Capsule";
160 = "Special Stage Time/Spheres Parameters"; 160 = "Special Stage Time/Spheres Parameters <deprecated>";
176 = "Custom Global Gravity"; 176 = "Custom Global Gravity <deprecated>";
512 = "Wind/Current";
1024 = "Conveyor Belt";
1280 = "Speed Pad"; 1280 = "Speed Pad";
4096 = "Star Post Activator"; 4096 = "Star Post Activator";
8192 = "Exit/Special Stage Pit/Return Flag"; 8192 = "Exit/Special Stage Pit/Return Flag";
@ -63,7 +61,7 @@ gen_sectortypes
12 = "Space Countdown"; 12 = "Space Countdown";
13 = "Ramp Sector (double step-up/down)"; 13 = "Ramp Sector (double step-up/down)";
14 = "Non-Ramp Sector (no step-down)"; 14 = "Non-Ramp Sector (no step-down)";
15 = "Bouncy FOF"; 15 = "Bouncy FOF <deprecated>";
} }
second second
@ -74,19 +72,17 @@ gen_sectortypes
48 = "Trigger Line Ex. (Floor Touch, All Players)"; 48 = "Trigger Line Ex. (Floor Touch, All Players)";
64 = "Trigger Line Ex. (Anywhere in Sector)"; 64 = "Trigger Line Ex. (Anywhere in Sector)";
80 = "Trigger Line Ex. (Floor Touch)"; 80 = "Trigger Line Ex. (Floor Touch)";
96 = "Trigger Line Ex. (Emerald Check)"; 96 = "Trigger Line Ex. (Emerald Check) <deprecated>";
112 = "Trigger Line Ex. (NiGHTS Mare)"; 112 = "Trigger Line Ex. (NiGHTS Mare) <deprecated>";
128 = "Check for Linedef Executor on FOFs"; 128 = "Check for Linedef Executor on FOFs";
144 = "Egg Capsule"; 144 = "Egg Capsule";
160 = "Special Stage Time/Spheres Parameters"; 160 = "Special Stage Time/Spheres Parameters <deprecated>";
176 = "Custom Global Gravity"; 176 = "Custom Global Gravity <deprecated>";
} }
third third
{ {
0 = "Normal"; 0 = "Normal";
512 = "Wind/Current";
1024 = "Conveyor Belt";
1280 = "Speed Pad"; 1280 = "Speed Pad";
} }

File diff suppressed because it is too large Load diff

View file

@ -25,12 +25,6 @@ scriptlumpnames
include("Includes\\SRB222_misc.cfg", "scriptlumpnames"); include("Includes\\SRB222_misc.cfg", "scriptlumpnames");
} }
// THING TYPES
thingtypes
{
include("Includes\\SRB222_things.cfg");
}
//Default things filters //Default things filters
thingsfilters thingsfilters
{ {

View file

@ -25,12 +25,6 @@ scriptlumpnames
include("Includes\\SRB222_misc.cfg", "scriptlumpnames"); include("Includes\\SRB222_misc.cfg", "scriptlumpnames");
} }
// THING TYPES
thingtypes
{
include("Includes\\SRB222_things.cfg");
}
//Default things filters //Default things filters
thingsfilters thingsfilters
{ {

View file

@ -881,7 +881,7 @@ void D_RegisterClientCommands(void)
// ingame object placing // ingame object placing
COM_AddCommand("objectplace", Command_ObjectPlace_f); 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_speed);
CV_RegisterVar(&cv_opflags); CV_RegisterVar(&cv_opflags);
CV_RegisterVar(&cv_ophoopflags); CV_RegisterVar(&cv_ophoopflags);

View file

@ -330,14 +330,85 @@ static inline int lib_getenum(lua_State *L)
} }
else if (fastncmp("ML_", word, 3)) { else if (fastncmp("ML_", word, 3)) {
p = word+3; p = word+3;
for (i = 0; i < 16; i++) for (i = 0; ML_LIST[i]; i++)
if (ML_LIST[i] && fastcmp(p, ML_LIST[i])) { if (fastcmp(p, ML_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i)); lua_pushinteger(L, ((lua_Integer)1<<i));
return 1; return 1;
} }
// Aliases
if (fastcmp(p, "EFFECT1"))
{
lua_pushinteger(L, (lua_Integer)ML_SKEWTD);
return 1;
}
if (fastcmp(p, "EFFECT2"))
{
lua_pushinteger(L, (lua_Integer)ML_NOSKEW);
return 1;
}
if (fastcmp(p, "EFFECT3"))
{
lua_pushinteger(L, (lua_Integer)ML_MIDPEG);
return 1;
}
if (fastcmp(p, "EFFECT4"))
{
lua_pushinteger(L, (lua_Integer)ML_MIDSOLID);
return 1;
}
if (fastcmp(p, "EFFECT5"))
{
lua_pushinteger(L, (lua_Integer)ML_WRAPMIDTEX);
return 1;
}
if (mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word); if (mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word);
return 0; return 0;
} }
else if (fastncmp("MSF_", word, 4)) {
p = word + 4;
for (i = 0; MSF_LIST[i]; i++)
if (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("SSF_", word, 4)) {
p = word + 4;
for (i = 0; SSF_LIST[i]; i++)
if (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("SD_", word, 3)) {
p = word + 3;
for (i = 0; SD_LIST[i]; i++)
if (fastcmp(p, SD_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
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)) { else if (fastncmp("S_",word,2)) {
p = word+2; p = word+2;
for (i = 0; i < NUMSTATEFREESLOTS; i++) { for (i = 0; i < NUMSTATEFREESLOTS; i++) {

View file

@ -199,6 +199,7 @@ actionpointer_t actionpointers[] =
{{A_Boss3Path}, "A_BOSS3PATH"}, {{A_Boss3Path}, "A_BOSS3PATH"},
{{A_Boss3ShockThink}, "A_BOSS3SHOCKTHINK"}, {{A_Boss3ShockThink}, "A_BOSS3SHOCKTHINK"},
{{A_LinedefExecute}, "A_LINEDEFEXECUTE"}, {{A_LinedefExecute}, "A_LINEDEFEXECUTE"},
{{A_LinedefExecuteFromArg}, "A_LINEDEFEXECUTEFROMARG"},
{{A_PlaySeeSound}, "A_PLAYSEESOUND"}, {{A_PlaySeeSound}, "A_PLAYSEESOUND"},
{{A_PlayAttackSound}, "A_PLAYATTACKSOUND"}, {{A_PlayAttackSound}, "A_PLAYATTACKSOUND"},
{{A_PlayActiveSound}, "A_PLAYACTIVESOUND"}, {{A_PlayActiveSound}, "A_PLAYACTIVESOUND"},
@ -4171,17 +4172,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_FINISHFLAG", // Finish flag "MT_FINISHFLAG", // Finish flag
// Ambient Sounds // Ambient Sounds
"MT_AWATERA", // Ambient Water Sound 1 "MT_AMBIENT",
"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_CORK", "MT_CORK",
"MT_LHRT", "MT_LHRT",
@ -4285,7 +4276,6 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_CRUMBLEOBJ", // Sound generator for crumbling platform "MT_CRUMBLEOBJ", // Sound generator for crumbling platform
"MT_TUBEWAYPOINT", "MT_TUBEWAYPOINT",
"MT_PUSH", "MT_PUSH",
"MT_PULL",
"MT_GHOST", "MT_GHOST",
"MT_OVERLAY", "MT_OVERLAY",
"MT_ANGLEMAN", "MT_ANGLEMAN",
@ -4522,23 +4512,85 @@ const char *const GAMETYPERULE_LIST[] = {
}; };
// Linedef flags // Linedef flags
const char *const ML_LIST[16] = { const char *const ML_LIST[] = {
"IMPASSIBLE", "IMPASSIBLE",
"BLOCKMONSTERS", "BLOCKMONSTERS",
"TWOSIDED", "TWOSIDED",
"DONTPEGTOP", "DONTPEGTOP",
"DONTPEGBOTTOM", "DONTPEGBOTTOM",
"EFFECT1", "SKEWTD",
"NOCLIMB", "NOCLIMB",
"EFFECT2", "NOSKEW",
"EFFECT3", "MIDPEG",
"EFFECT4", "MIDSOLID",
"EFFECT5", "WRAPMIDTEX",
"NOSONIC", "NETONLY",
"NOTAILS", "NONET",
"NOKNUX", "EFFECT6",
"BOUNCY", "BOUNCY",
"TFERLINE" "TFERLINE",
NULL
};
// Sector flags
const char *const MSF_LIST[] = {
"FLIPSPECIAL_FLOOR",
"FLIPSPECIAL_CEILING",
"TRIGGERSPECIAL_TOUCH",
"TRIGGERSPECIAL_HEADBUMP",
"TRIGGERLINE_PLANE",
"TRIGGERLINE_MOBJ",
"GRAVITYFLIP",
"HEATWAVE",
"NOCLIPCAMERA",
NULL
};
// Sector special flags
const char *const SSF_LIST[] = {
"OUTERSPACE",
"DOUBLESTEPUP",
"WINDCURRENT",
"CONVEYOR",
"SPEEDPAD",
"STARPOSTACTIVATOR",
"EXIT",
"SPECIALSTAGEPIT",
"RETURNFLAG",
"REDTEAMBASE",
"BLUETEAMBASE",
"FAN",
"SUPERTRANSFORM",
"FORCESPIN",
"ZOOMTUBESTART",
"ZOOMTUBEEND",
"FINISHLINE",
"ROPEHANG",
NULL
};
// Sector damagetypes
const char *const SD_LIST[] = {
"NONE",
"GENERIC",
"WATER",
"FIRE",
"LAVA",
"ELECTRIC",
"SPIKE",
"DEATHPITTILT",
"DEATHPITNOTILT",
"INSTAKILL",
"SPECIALSTAGE",
NULL
};
// Sector triggerer
const char *const TO_LIST[] = {
"PLAYER",
"ALLPLAYERS",
"MOBJ",
NULL
}; };
const char *COLOR_ENUMS[] = { const char *COLOR_ENUMS[] = {
@ -5298,7 +5350,7 @@ struct int_const_s const INT_CONST[] = {
{"FF_FLOATBOB",FF_FLOATBOB}, ///< Floats on water and bobs if you step on it. {"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_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_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_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_BUSTUP",FF_BUSTUP}, ///< You can spin through/punch this block and it will crumble!
{"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand! {"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand!
@ -5306,12 +5358,21 @@ struct int_const_s const INT_CONST[] = {
{"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity. {"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_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_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_RIPPLE",FF_RIPPLE}, ///< Ripple the flats
{"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel
{"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. {"FF_BOUNCY",FF_BOUNCY}, ///< Bounces players
{"FF_SPLAT",FF_SPLAT}, ///< Use splat flat renderer (treat cyan pixels as invisible)
// FOF bustable flags
{"FB_PUSHABLES",FB_PUSHABLES},
{"FB_EXECUTOR",FB_EXECUTOR},
{"FB_ONLYBOTTOM",FB_ONLYBOTTOM},
// Bustable FOF type
{"BT_TOUCH",BT_TOUCH},
{"BT_SPINBUST",BT_SPINBUST},
{"BT_REGULAR",BT_REGULAR},
{"BT_STRONG",BT_STRONG},
// PolyObject flags // PolyObject flags
{"POF_CLIPLINES",POF_CLIPLINES}, ///< Test against lines for collision {"POF_CLIPLINES",POF_CLIPLINES}, ///< Test against lines for collision

View file

@ -64,7 +64,11 @@ extern const char *const MOBJEFLAG_LIST[];
extern const char *const MAPTHINGFLAG_LIST[4]; extern const char *const MAPTHINGFLAG_LIST[4];
extern const char *const PLAYERFLAG_LIST[]; extern const char *const PLAYERFLAG_LIST[];
extern const char *const GAMETYPERULE_LIST[]; extern const char *const GAMETYPERULE_LIST[];
extern const char *const ML_LIST[16]; // Linedef flags 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 *COLOR_ENUMS[];
extern const char *const POWERS_LIST[]; extern const char *const POWERS_LIST[];
extern const char *const HUDITEMS_LIST[]; extern const char *const HUDITEMS_LIST[];

View file

@ -123,15 +123,15 @@ typedef struct
// lower texture unpegged // lower texture unpegged
#define ML_DONTPEGBOTTOM 16 #define ML_DONTPEGBOTTOM 16
#define ML_EFFECT1 32 #define ML_SKEWTD 32
// Don't let Knuckles climb on this line // Don't let Knuckles climb on this line
#define ML_NOCLIMB 64 #define ML_NOCLIMB 64
#define ML_EFFECT2 128 #define ML_NOSKEW 128
#define ML_EFFECT3 256 #define ML_MIDPEG 256
#define ML_EFFECT4 512 #define ML_MIDSOLID 512
#define ML_EFFECT5 1024 #define ML_WRAPMIDTEX 1024
#define ML_NETONLY 2048 // Apply effect only in netgames #define ML_NETONLY 2048 // Apply effect only in netgames
#define ML_NONET 4096 // Apply effect only in single player games #define ML_NONET 4096 // Apply effect only in single player games
@ -196,7 +196,7 @@ typedef struct
#pragma pack() #pragma pack()
#endif #endif
#define NUMMAPTHINGARGS 6 #define NUMMAPTHINGARGS 10
#define NUMMAPTHINGSTRINGARGS 2 #define NUMMAPTHINGSTRINGARGS 2
// Thing definition, position, orientation and type, // Thing definition, position, orientation and type,

View file

@ -401,7 +401,7 @@ extern skincolor_t skincolors[MAXSKINCOLORS];
#define PUSHACCEL (2*FRACUNIT) // Acceleration for MF2_SLIDEPUSH items. #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 { enum {
LE_PINCHPHASE = -2, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!) 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) LE_ALLBOSSESDEAD = -3, // All bosses in the map are dead (Egg capsule raise)
@ -483,8 +483,11 @@ extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL;
char *va(const char *format, ...) FUNCPRINTF; char *va(const char *format, ...) FUNCPRINTF;
char *M_GetToken(const char *inputString); char *M_GetToken(const char *inputString);
void M_UnGetToken(void); void M_UnGetToken(void);
UINT32 M_GetTokenPos(void); void M_TokenizerOpen(const char *inputString);
void M_SetTokenPos(UINT32 newPos); 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 *sizeu1(size_t num);
char *sizeu2(size_t num); char *sizeu2(size_t num);
char *sizeu3(size_t num); char *sizeu3(size_t num);

View file

@ -2222,7 +2222,7 @@ void G_AddGhost(char *defdemoname)
gh->mo->angle = FixedAngle(mthing->angle << FRACBITS); gh->mo->angle = FixedAngle(mthing->angle << FRACBITS);
f = gh->mo->floorz; f = gh->mo->floorz;
c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height; 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; z = c - offset;
if (z < f) if (z < f)

View file

@ -1148,7 +1148,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// PEGGING // PEGGING
if (gl_linedef->flags & ML_DONTPEGTOP) if (gl_linedef->flags & ML_DONTPEGTOP)
texturevpegtop = 0; texturevpegtop = 0;
else if (gl_linedef->flags & ML_EFFECT1) else if (gl_linedef->flags & ML_SKEWTD)
texturevpegtop = worldhigh + textureheight[gl_sidedef->toptexture] - worldtop; texturevpegtop = worldhigh + textureheight[gl_sidedef->toptexture] - worldtop;
else else
texturevpegtop = gl_backsector->ceilingheight + textureheight[gl_sidedef->toptexture] - gl_frontsector->ceilingheight; texturevpegtop = gl_backsector->ceilingheight + textureheight[gl_sidedef->toptexture] - gl_frontsector->ceilingheight;
@ -1164,7 +1164,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
// Adjust t value for sloped walls // Adjust t value for sloped walls
if (!(gl_linedef->flags & ML_EFFECT1)) if (!(gl_linedef->flags & ML_SKEWTD))
{ {
// Unskewed // Unskewed
wallVerts[3].t -= (worldtop - gl_frontsector->ceilingheight) * grTex->scaleY; wallVerts[3].t -= (worldtop - gl_frontsector->ceilingheight) * grTex->scaleY;
@ -1214,7 +1214,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// PEGGING // PEGGING
if (!(gl_linedef->flags & ML_DONTPEGBOTTOM)) if (!(gl_linedef->flags & ML_DONTPEGBOTTOM))
texturevpegbottom = 0; texturevpegbottom = 0;
else if (gl_linedef->flags & ML_EFFECT1) else if (gl_linedef->flags & ML_SKEWTD)
texturevpegbottom = worldbottom - worldlow; texturevpegbottom = worldbottom - worldlow;
else else
texturevpegbottom = gl_frontsector->floorheight - gl_backsector->floorheight; texturevpegbottom = gl_frontsector->floorheight - gl_backsector->floorheight;
@ -1230,7 +1230,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
// Adjust t value for sloped walls // Adjust t value for sloped walls
if (!(gl_linedef->flags & ML_EFFECT1)) if (!(gl_linedef->flags & ML_SKEWTD))
{ {
// Unskewed // Unskewed
wallVerts[0].t -= (worldbottom - gl_frontsector->floorheight) * grTex->scaleY; wallVerts[0].t -= (worldbottom - gl_frontsector->floorheight) * grTex->scaleY;
@ -1288,7 +1288,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if (gl_sidedef->repeatcnt) if (gl_sidedef->repeatcnt)
repeats = 1 + 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; fixed_t high, low;
@ -1330,9 +1330,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
popenbottom = max(worldbottom, worldlow); popenbottom = max(worldbottom, worldlow);
} }
if (gl_linedef->flags & ML_EFFECT2) if (gl_linedef->flags & ML_NOSKEW)
{ {
if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) if (gl_linedef->flags & ML_MIDPEG)
{ {
polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset; polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset;
polytop = polybottom + textureheight[gl_midtexture]*repeats; polytop = polybottom + textureheight[gl_midtexture]*repeats;
@ -1343,7 +1343,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
polybottom = polytop - textureheight[gl_midtexture]*repeats; polybottom = polytop - textureheight[gl_midtexture]*repeats;
} }
} }
else if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) else if (gl_linedef->flags & ML_MIDPEG)
{ {
polybottom = popenbottom + gl_sidedef->rowoffset; polybottom = popenbottom + gl_sidedef->rowoffset;
polytop = polybottom + textureheight[gl_midtexture]*repeats; polytop = polybottom + textureheight[gl_midtexture]*repeats;
@ -1373,7 +1373,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
{ {
// PEGGING // PEGGING
if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) if (gl_linedef->flags & ML_MIDPEG)
texturevpeg = textureheight[gl_sidedef->midtexture]*repeats - h + polybottom; texturevpeg = textureheight[gl_sidedef->midtexture]*repeats - h + polybottom;
else else
texturevpeg = polytop - h; texturevpeg = polytop - h;
@ -1396,9 +1396,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
{ {
fixed_t midtextureslant; fixed_t midtextureslant;
if (gl_linedef->flags & ML_EFFECT2) if (gl_linedef->flags & ML_NOSKEW)
midtextureslant = 0; midtextureslant = 0;
else if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) else if (gl_linedef->flags & ML_MIDPEG)
midtextureslant = worldlow < worldbottom midtextureslant = worldlow < worldbottom
? worldbottomslope-worldbottom ? worldbottomslope-worldbottom
: worldlowslope-worldlow; : worldlowslope-worldlow;
@ -1423,7 +1423,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
{ {
// PEGGING // PEGGING
if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) if (gl_linedef->flags & ML_MIDPEG)
texturevpeg = textureheight[gl_sidedef->midtexture]*repeats - h + polybottom; texturevpeg = textureheight[gl_sidedef->midtexture]*repeats - h + polybottom;
else else
texturevpeg = polytop - h; texturevpeg = polytop - h;
@ -1437,44 +1437,17 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// set alpha for transparent walls // set alpha for transparent walls
// ooops ! this do not work at all because render order we should render it in backtofront order // ooops ! this do not work at all because render order we should render it in backtofront order
switch (gl_linedef->special) if (gl_linedef->blendmode && gl_linedef->blendmode != AST_FOG)
{ {
// Translucent if (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT)
case 102: blendmode = HWR_SurfaceBlend(gl_linedef->blendmode, R_GetLinedefTransTable(gl_linedef->alpha), &Surf);
case 121: else
case 123: blendmode = HWR_GetBlendModeFlag(gl_linedef->blendmode);
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:
if (gl_linedef->blendmode && gl_linedef->blendmode != AST_FOG)
blendmode = HWR_SurfaceBlend(gl_linedef->blendmode, R_GetLinedefTransTable(gl_linedef->alpha), &Surf);
else
blendmode = PF_Translucent;
break;
default:
if (gl_linedef->blendmode && gl_linedef->blendmode != AST_FOG)
{
if (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT)
blendmode = HWR_SurfaceBlend(gl_linedef->blendmode, R_GetLinedefTransTable(gl_linedef->alpha), &Surf);
else
blendmode = HWR_GetBlendModeFlag(gl_linedef->blendmode);
}
else if (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT)
blendmode = HWR_TranstableToAlpha(R_GetLinedefTransTable(gl_linedef->alpha), &Surf);
else
blendmode = PF_Masked;
break;
} }
else 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) if (gl_curline->polyseg && gl_curline->polyseg->translucency > 0)
{ {
@ -1540,7 +1513,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
{ {
fixed_t texturevpeg; fixed_t texturevpeg;
// PEGGING // 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; texturevpeg = gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight + gl_sidedef->rowoffset;
else if (gl_linedef->flags & ML_DONTPEGBOTTOM) else if (gl_linedef->flags & ML_DONTPEGBOTTOM)
texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset; texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset;
@ -1556,7 +1529,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
// Texture correction for slopes // 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[3].t += (gl_frontsector->ceilingheight - worldtop) * grTex->scaleY;
wallVerts[2].t += (gl_frontsector->ceilingheight - worldtopslope) * grTex->scaleY; wallVerts[2].t += (gl_frontsector->ceilingheight - worldtopslope) * grTex->scaleY;
wallVerts[0].t += (gl_frontsector->floorheight - worldbottom) * grTex->scaleY; wallVerts[0].t += (gl_frontsector->floorheight - worldbottom) * grTex->scaleY;
@ -1705,13 +1678,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
{ {
texturevpeg = sides[newline->sidenum[0]].rowoffset; texturevpeg = sides[newline->sidenum[0]].rowoffset;
attachtobottom = !!(newline->flags & ML_DONTPEGBOTTOM); attachtobottom = !!(newline->flags & ML_DONTPEGBOTTOM);
slopeskew = !!(newline->flags & ML_DONTPEGTOP); slopeskew = !!(newline->flags & ML_SKEWTD);
} }
else else
{ {
texturevpeg = sides[rover->master->sidenum[0]].rowoffset; texturevpeg = sides[rover->master->sidenum[0]].rowoffset;
attachtobottom = !!(gl_linedef->flags & ML_DONTPEGBOTTOM); attachtobottom = !!(gl_linedef->flags & ML_DONTPEGBOTTOM);
slopeskew = !!(rover->master->flags & ML_DONTPEGTOP); slopeskew = !!(rover->master->flags & ML_SKEWTD);
} }
grTex = HWR_GetTexture(texnum); grTex = HWR_GetTexture(texnum);
@ -3080,13 +3053,13 @@ static void HWR_Subsector(size_t num)
} }
light = R_GetPlaneLight(gl_frontsector, locFloorHeight, false); light = R_GetPlaneLight(gl_frontsector, locFloorHeight, false);
if (gl_frontsector->floorlightsec == -1) if (gl_frontsector->floorlightsec == -1 && !gl_frontsector->floorlightabsolute)
floorlightlevel = *gl_frontsector->lightlist[light].lightlevel; floorlightlevel = max(0, min(255, *gl_frontsector->lightlist[light].lightlevel + gl_frontsector->floorlightlevel));
floorcolormap = *gl_frontsector->lightlist[light].extra_colormap; floorcolormap = *gl_frontsector->lightlist[light].extra_colormap;
light = R_GetPlaneLight(gl_frontsector, locCeilingHeight, false); light = R_GetPlaneLight(gl_frontsector, locCeilingHeight, false);
if (gl_frontsector->ceilinglightsec == -1) if (gl_frontsector->ceilinglightsec == -1 && !gl_frontsector->ceilinglightabsolute)
ceilinglightlevel = *gl_frontsector->lightlist[light].lightlevel; ceilinglightlevel = max(0, min(255, *gl_frontsector->lightlist[light].lightlevel + gl_frontsector->ceilinglightlevel));
ceilingcolormap = *gl_frontsector->lightlist[light].extra_colormap; ceilingcolormap = *gl_frontsector->lightlist[light].extra_colormap;
} }
@ -3611,7 +3584,7 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v
return false; return false;
cullplane = FIXED_TO_FLOAT(cullheight->frontsector->floorheight); cullplane = FIXED_TO_FLOAT(cullheight->frontsector->floorheight);
if (cullheight->flags & ML_NOCLIMB) // Group culling if (cullheight->args[1]) // Group culling
{ {
if (!viewcullheight) if (!viewcullheight)
return false; return false;

View file

@ -903,7 +903,7 @@ state_t states[NUMSTATES] =
{SPR_TRET, FF_FULLBRIGHT|2, 7, {A_Pain}, 0, 0, S_TURRETSHOCK7}, // S_TURRETSHOCK6 {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|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, {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, 1, {A_Look}, 1, 0, S_TURRETPOPDOWN8}, // S_TURRETLOOK
{SPR_TURR, 0, 0, {A_FaceTarget}, 0, 0, S_TURRETPOPUP1}, // S_TURRETSEE {SPR_TURR, 0, 0, {A_FaceTarget}, 0, 0, S_TURRETPOPUP1}, // S_TURRETSEE
@ -1456,7 +1456,7 @@ state_t states[NUMSTATES] =
{SPR_FANG, 18, 16, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT1}, // S_FANG_PINCHLOBSHOT0 {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, 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, 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}, 4, 0, S_FANG_PINCHLOBSHOT4}, // S_FANG_PINCHLOBSHOT3
{SPR_FANG, 0, 0, {A_Boss5Calm}, 0, 0, S_FANG_PATHINGSTART1}, // S_FANG_PINCHLOBSHOT4 {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 {SPR_FANG, 21, 0, {A_DoNPCPain}, 0, 0, S_FANG_DIE2}, // S_FANG_DIE1
@ -1588,7 +1588,7 @@ state_t states[NUMSTATES] =
{SPR_BRAK, 21, 3*TICRATE, {NULL}, 0, 0, S_BLACKEGG_DESTROYPLAT2}, // S_BLACKEGG_DESTROYPLAT1 {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, 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}, 5, 0, S_BLACKEGG_STND}, // S_BLACKEGG_DESTROYPLAT3
{SPR_NULL, 0, 1, {A_CapeChase}, (160 - 20) << 16, 0, S_BLACKEGG_HELPER}, // S_BLACKEGG_HELPER {SPR_NULL, 0, 1, {A_CapeChase}, (160 - 20) << 16, 0, S_BLACKEGG_HELPER}, // S_BLACKEGG_HELPER
@ -1622,7 +1622,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, 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, 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, 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}, 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, 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, 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 {SPR_BRAK, 18, 8, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_VILE_ATTACK5}, // S_CYBRAKDEMON_VILE_ATTACK4
@ -1635,7 +1635,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, 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, 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_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}, 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, 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, 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 {SPR_BRAK, 18, 0, {A_Repeat}, 52, S_CYBRAKDEMON_DIE2, S_CYBRAKDEMON_DIE4}, // S_CYBRAKDEMON_DIE3
@ -18217,13 +18217,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
// ambient water 1a (large) // ambient sound effect
{ // MT_AWATERA { // MT_AMBIENT
700, // doomednum 700, // doomednum
S_INVISIBLE, // spawnstate S_INVISIBLE, // spawnstate
35, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_amwtr1, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
S_NULL, // painstate S_NULL, // painstate
@ -18245,283 +18245,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate 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 { // MT_CORK
-1, // doomednum -1, // doomednum
S_CORK, // spawnstate S_CORK, // spawnstate
@ -20874,34 +20597,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate 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 { // MT_GHOST
-1, // doomednum -1, // doomednum
S_THOK, // spawnstate S_THOK, // spawnstate

View file

@ -152,6 +152,7 @@ enum actionnum
A_BOSS3PATH, A_BOSS3PATH,
A_BOSS3SHOCKTHINK, A_BOSS3SHOCKTHINK,
A_LINEDEFEXECUTE, A_LINEDEFEXECUTE,
A_LINEDEFEXECUTEFROMARG,
A_PLAYSEESOUND, A_PLAYSEESOUND,
A_PLAYATTACKSOUND, A_PLAYATTACKSOUND,
A_PLAYACTIVESOUND, A_PLAYACTIVESOUND,
@ -415,6 +416,7 @@ void A_Boss3TakeDamage();
void A_Boss3Path(); void A_Boss3Path();
void A_Boss3ShockThink(); void A_Boss3ShockThink();
void A_LinedefExecute(); void A_LinedefExecute();
void A_LinedefExecuteFromArg();
void A_PlaySeeSound(); void A_PlaySeeSound();
void A_PlayAttackSound(); void A_PlayAttackSound();
void A_PlayActiveSound(); void A_PlayActiveSound();
@ -4999,17 +5001,7 @@ typedef enum mobj_type
MT_FINISHFLAG, // Finish flag MT_FINISHFLAG, // Finish flag
// Ambient Sounds // Ambient Sounds
MT_AWATERA, // Ambient Water Sound 1 MT_AMBIENT,
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_CORK, MT_CORK,
MT_LHRT, MT_LHRT,
@ -5113,7 +5105,6 @@ typedef enum mobj_type
MT_CRUMBLEOBJ, // Sound generator for crumbling platform MT_CRUMBLEOBJ, // Sound generator for crumbling platform
MT_TUBEWAYPOINT, MT_TUBEWAYPOINT,
MT_PUSH, MT_PUSH,
MT_PULL,
MT_GHOST, MT_GHOST,
MT_OVERLAY, MT_OVERLAY,
MT_ANGLEMAN, MT_ANGLEMAN,

View file

@ -2237,6 +2237,31 @@ static int lib_pExplodeMissile(lua_State *L)
return 0; 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_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) static int lib_pPlayerTouchingSectorSpecial(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -2250,6 +2275,18 @@ static int lib_pPlayerTouchingSectorSpecial(lua_State *L)
return 1; 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) static int lib_pFindLowestFloorSurrounding(lua_State *L)
{ {
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
@ -2381,23 +2418,13 @@ static int lib_pFadeLight(lua_State *L)
INT32 speed = (INT32)luaL_checkinteger(L, 3); INT32 speed = (INT32)luaL_checkinteger(L, 3);
boolean ticbased = lua_optboolean(L, 4); boolean ticbased = lua_optboolean(L, 4);
boolean force = lua_optboolean(L, 5); boolean force = lua_optboolean(L, 5);
boolean relative = lua_optboolean(L, 6);
NOHUD NOHUD
INLEVEL INLEVEL
P_FadeLight(tag, destvalue, speed, ticbased, force); P_FadeLight(tag, destvalue, speed, ticbased, force, relative);
return 0; 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) static int lib_pIsFlagAtBase(lua_State *L)
{ {
mobjtype_t flag = luaL_checkinteger(L, 1); mobjtype_t flag = luaL_checkinteger(L, 1);
@ -4092,7 +4119,10 @@ static luaL_Reg lib[] = {
{"P_SetMobjStateNF",lib_pSetMobjStateNF}, {"P_SetMobjStateNF",lib_pSetMobjStateNF},
{"P_DoSuperTransformation",lib_pDoSuperTransformation}, {"P_DoSuperTransformation",lib_pDoSuperTransformation},
{"P_ExplodeMissile",lib_pExplodeMissile}, {"P_ExplodeMissile",lib_pExplodeMissile},
{"P_MobjTouchingSectorSpecial",lib_pMobjTouchingSectorSpecial},
{"P_MobjTouchingSectorSpecialFlag",lib_pMobjTouchingSectorSpecialFlag},
{"P_PlayerTouchingSectorSpecial",lib_pPlayerTouchingSectorSpecial}, {"P_PlayerTouchingSectorSpecial",lib_pPlayerTouchingSectorSpecial},
{"P_PlayerTouchingSectorSpecialFlag",lib_pPlayerTouchingSectorSpecialFlag},
{"P_FindLowestFloorSurrounding",lib_pFindLowestFloorSurrounding}, {"P_FindLowestFloorSurrounding",lib_pFindLowestFloorSurrounding},
{"P_FindHighestFloorSurrounding",lib_pFindHighestFloorSurrounding}, {"P_FindHighestFloorSurrounding",lib_pFindHighestFloorSurrounding},
{"P_FindNextHighestFloor",lib_pFindNextHighestFloor}, {"P_FindNextHighestFloor",lib_pFindNextHighestFloor},
@ -4104,7 +4134,6 @@ static luaL_Reg lib[] = {
{"P_LinedefExecute",lib_pLinedefExecute}, {"P_LinedefExecute",lib_pLinedefExecute},
{"P_SpawnLightningFlash",lib_pSpawnLightningFlash}, {"P_SpawnLightningFlash",lib_pSpawnLightningFlash},
{"P_FadeLight",lib_pFadeLight}, {"P_FadeLight",lib_pFadeLight},
{"P_ThingOnSpecial3DFloor",lib_pThingOnSpecial3DFloor},
{"P_IsFlagAtBase",lib_pIsFlagAtBase}, {"P_IsFlagAtBase",lib_pIsFlagAtBase},
{"P_SetupLevelSky",lib_pSetupLevelSky}, {"P_SetupLevelSky",lib_pSetupLevelSky},
{"P_SetSkyboxMobj",lib_pSetSkyboxMobj}, {"P_SetSkyboxMobj",lib_pSetSkyboxMobj},

View file

@ -35,6 +35,10 @@ enum sector_e {
sector_floorpic, sector_floorpic,
sector_ceilingpic, sector_ceilingpic,
sector_lightlevel, sector_lightlevel,
sector_floorlightlevel,
sector_floorlightabsolute,
sector_ceilinglightlevel,
sector_ceilinglightabsolute,
sector_special, sector_special,
sector_tag, sector_tag,
sector_taglist, sector_taglist,
@ -44,7 +48,14 @@ enum sector_e {
sector_lines, sector_lines,
sector_ffloors, sector_ffloors,
sector_fslope, sector_fslope,
sector_cslope sector_cslope,
sector_flags,
sector_specialflags,
sector_damagetype,
sector_triggertag,
sector_triggerer,
sector_friction,
sector_gravity,
}; };
static const char *const sector_opt[] = { static const char *const sector_opt[] = {
@ -54,6 +65,10 @@ static const char *const sector_opt[] = {
"floorpic", "floorpic",
"ceilingpic", "ceilingpic",
"lightlevel", "lightlevel",
"floorlightlevel",
"floorlightabsolute",
"ceilinglightlevel",
"ceilinglightabsolute",
"special", "special",
"tag", "tag",
"taglist", "taglist",
@ -64,6 +79,13 @@ static const char *const sector_opt[] = {
"ffloors", "ffloors",
"f_slope", "f_slope",
"c_slope", "c_slope",
"flags",
"specialflags",
"damagetype",
"triggertag",
"triggerer",
"friction",
"gravity",
NULL}; NULL};
enum subsector_e { enum subsector_e {
@ -199,6 +221,12 @@ enum ffloor_e {
ffloor_prev, ffloor_prev,
ffloor_alpha, ffloor_alpha,
ffloor_blend, ffloor_blend,
ffloor_bustflags,
ffloor_busttype,
ffloor_busttag,
ffloor_sinkspeed,
ffloor_friction,
ffloor_bouncestrength,
}; };
static const char *const ffloor_opt[] = { static const char *const ffloor_opt[] = {
@ -218,6 +246,12 @@ static const char *const ffloor_opt[] = {
"prev", "prev",
"alpha", "alpha",
"blend", "blend",
"bustflags",
"busttype",
"busttag",
"sinkspeed",
"friction",
"bouncestrength",
NULL}; NULL};
#ifdef HAVE_LUA_SEGS #ifdef HAVE_LUA_SEGS
@ -583,6 +617,18 @@ static int sector_get(lua_State *L)
case sector_lightlevel: case sector_lightlevel:
lua_pushinteger(L, sector->lightlevel); lua_pushinteger(L, sector->lightlevel);
return 1; 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: case sector_special:
lua_pushinteger(L, sector->special); lua_pushinteger(L, sector->special);
return 1; return 1;
@ -621,6 +667,27 @@ static int sector_get(lua_State *L)
case sector_cslope: // c_slope case sector_cslope: // c_slope
LUA_PushUserdata(L, sector->c_slope, META_SLOPE); LUA_PushUserdata(L, sector->c_slope, META_SLOPE);
return 1; return 1;
case sector_flags: // flags
lua_pushinteger(L, sector->flags);
return 1;
case sector_specialflags: // specialflags
lua_pushinteger(L, sector->specialflags);
return 1;
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_pushfixed(L, sector->friction);
return 1;
case sector_gravity: // gravity
lua_pushfixed(L, sector->gravity);
return 1;
} }
return 0; return 0;
} }
@ -648,6 +715,7 @@ static int sector_set(lua_State *L)
case sector_ffloors: // ffloors case sector_ffloors: // ffloors
case sector_fslope: // f_slope case sector_fslope: // f_slope
case sector_cslope: // c_slope case sector_cslope: // c_slope
case sector_friction: // friction
default: default:
return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]); return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]);
case sector_floorheight: { // floorheight case sector_floorheight: { // floorheight
@ -687,6 +755,18 @@ static int sector_set(lua_State *L)
case sector_lightlevel: case sector_lightlevel:
sector->lightlevel = (INT16)luaL_checkinteger(L, 3); sector->lightlevel = (INT16)luaL_checkinteger(L, 3);
break; 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: case sector_special:
sector->special = (INT16)luaL_checkinteger(L, 3); sector->special = (INT16)luaL_checkinteger(L, 3);
break; break;
@ -695,6 +775,25 @@ static int sector_set(lua_State *L)
break; break;
case sector_taglist: case sector_taglist:
return LUA_ErrSetDirectly(L, "sector_t", "taglist"); return LUA_ErrSetDirectly(L, "sector_t", "taglist");
case sector_flags:
sector->flags = luaL_checkinteger(L, 3);
CheckForReverseGravity |= (sector->flags & MSF_GRAVITYFLIP);
break;
case sector_specialflags:
sector->specialflags = luaL_checkinteger(L, 3);
break;
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;
} }
return 0; return 0;
} }
@ -1817,6 +1916,24 @@ static int ffloor_get(lua_State *L)
case ffloor_blend: case ffloor_blend:
lua_pushinteger(L, ffloor->blend); lua_pushinteger(L, ffloor->blend);
return 1; return 1;
case ffloor_bustflags:
lua_pushinteger(L, ffloor->bustflags);
return 1;
case ffloor_busttype:
lua_pushinteger(L, ffloor->busttype);
return 1;
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;
case ffloor_bouncestrength:
lua_pushfixed(L, ffloor->bouncestrength);
return 1;
} }
return 0; return 0;
} }

View file

@ -244,13 +244,14 @@ static int lib_polyobj_rotate(lua_State *L)
{ {
polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
angle_t delta = luaL_checkangle(L, 2); 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 turnplayers = lua_opttrueboolean(L, 3);
boolean checkmobjs = lua_opttrueboolean(L, 4); boolean turnothers = lua_opttrueboolean(L, 4);
boolean checkmobjs = lua_opttrueboolean(L, 5);
NOHUD NOHUD
INLEVEL INLEVEL
if (!po) if (!po)
return LUA_ErrInvalid(L, "polyobj_t"); 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; return 1;
} }

View file

@ -539,7 +539,7 @@ void Command_Teleport_f(void)
// Flagging a player's ambush will make them start on the ceiling // Flagging a player's ambush will make them start on the ceiling
// Objectflip inverts // 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; intz = ss->sector->ceilingheight - p->mo->height - offset;
else else
intz = ss->sector->floorheight + offset; intz = ss->sector->floorheight + offset;
@ -1004,7 +1004,7 @@ static void OP_CycleThings(INT32 amt)
} while } while
(mobjinfo[op_currentthing].doomednum == -1 (mobjinfo[op_currentthing].doomednum == -1
|| op_currentthing == MT_NIGHTSDRONE || 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].spawnstate].sprite == SPR_NULL
&& states[mobjinfo[op_currentthing].seestate].sprite == SPR_NULL) && states[mobjinfo[op_currentthing].seestate].sprite == SPR_NULL)
); );
@ -1137,7 +1137,7 @@ void OP_ResetObjectplace(void)
// //
// Main meat of objectplace: handling functions // Main meat of objectplace: handling functions
// //
void OP_NightsObjectplace(player_t *player) /*void OP_NightsObjectplace(player_t *player)
{ {
ticcmd_t *cmd = &player->cmd; ticcmd_t *cmd = &player->cmd;
mapthing_t *mt; mapthing_t *mt;
@ -1283,14 +1283,14 @@ void OP_NightsObjectplace(player_t *player)
mt = OP_CreateNewMapThing(player, (UINT16)cv_mapthingnum.value, false); mt = OP_CreateNewMapThing(player, (UINT16)cv_mapthingnum.value, false);
mt->angle = angle; 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); P_SpawnItemPattern(mt, false);
else if (mt->type == 1705 || mt->type == 1713) // NiGHTS Hoops else if (mt->type == 1713) // NiGHTS Hoops
P_SpawnHoop(mt); P_SpawnHoop(mt);
else else
P_SpawnMapThing(mt); P_SpawnMapThing(mt);
} }
} }*/
// //
// OP_ObjectplaceMovement // OP_ObjectplaceMovement
@ -1414,9 +1414,9 @@ void OP_ObjectplaceMovement(player_t *player)
return; return;
mt = OP_CreateNewMapThing(player, (UINT16)spawnthing, ceiling); 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); P_SpawnItemPattern(mt, false);
else if (mt->type == 1705 || mt->type == 1713) // NiGHTS Hoops else if (mt->type == 1713) // NiGHTS Hoops
P_SpawnHoop(mt); P_SpawnHoop(mt);
else else
P_SpawnMapThing(mt); P_SpawnMapThing(mt);
@ -1428,14 +1428,14 @@ void OP_ObjectplaceMovement(player_t *player)
// //
// Objectplace related commands. // Objectplace related commands.
// //
void Command_Writethings_f(void) /*void Command_Writethings_f(void)
{ {
REQUIRE_INLEVEL; REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER; REQUIRE_SINGLEPLAYER;
REQUIRE_OBJECTPLACE; REQUIRE_OBJECTPLACE;
P_WriteThings(); P_WriteThings();
} }*/
void Command_ObjectPlace_f(void) void Command_ObjectPlace_f(void)
{ {

View file

@ -26,7 +26,7 @@ void cht_Init(void);
// ObjectPlace // ObjectPlace
// //
void Command_ObjectPlace_f(void); 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_opflags, cv_ophoopflags, cv_mapthingnum, cv_speed;
//extern consvar_t cv_snapto, cv_grid; //extern consvar_t cv_snapto, cv_grid;
@ -38,7 +38,7 @@ extern UINT32 op_displayflags;
boolean OP_FreezeObjectplace(void); boolean OP_FreezeObjectplace(void);
void OP_ResetObjectplace(void); void OP_ResetObjectplace(void);
void OP_NightsObjectplace(player_t *player); //void OP_NightsObjectplace(player_t *player);
void OP_ObjectplaceMovement(player_t *player); void OP_ObjectplaceMovement(player_t *player);
// //

View file

@ -1971,18 +1971,168 @@ void M_UnGetToken(void)
endPos = oldendPos; endPos = oldendPos;
} }
/** Returns the current token's position. #define NUMTOKENS 2
*/ static const char *tokenizerInput = NULL;
UINT32 M_GetTokenPos(void) 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_TokenizerClose(void)
*/
void M_SetTokenPos(UINT32 newPos)
{ {
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. /** Count bits in a number.

View file

@ -35,7 +35,6 @@ INT32 ceilmovesound = sfx_None;
void T_MoveCeiling(ceiling_t *ceiling) void T_MoveCeiling(ceiling_t *ceiling)
{ {
result_e res; result_e res;
boolean dontupdate = false;
if (ceiling->delaytimer) if (ceiling->delaytimer)
{ {
@ -43,259 +42,81 @@ void T_MoveCeiling(ceiling_t *ceiling)
return; 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 const fixed_t origspeed = FixedDiv(ceiling->origspeed, (ELEVATORSPEED/2));
break; const fixed_t fs = abs(ceiling->sector->ceilingheight - lines[ceiling->sourceline].frontsector->ceilingheight);
case 1: // UP const fixed_t bs = abs(ceiling->sector->ceilingheight - lines[ceiling->sourceline].backsector->ceilingheight);
res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight, false, true, ceiling->direction); if (fs < bs)
ceiling->speed = FixedDiv(fs, 25*FRACUNIT) + FRACUNIT/4;
if (ceiling->type == bounceCeiling) else
{ ceiling->speed = FixedDiv(bs, 25*FRACUNIT) + FRACUNIT/4;
const fixed_t origspeed = FixedDiv(ceiling->origspeed,(ELEVATORSPEED/2)); ceiling->speed = FixedMul(ceiling->speed, origspeed);
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)
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 raiseCeilingByLine:
case moveCeilingByFrontTexture:
ceiling->sector->ceilingdata = NULL;
ceiling->sector->ceilspeed = 0;
P_RemoveThinker(&ceiling->thinker);
dontupdate = true;
break;
case fastCrushAndRaise:
case crushAndRaise:
ceiling->direction = -1;
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)
{
// 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)
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 lowerAndCrush:
case lowerToLowest:
case raiseToLowest:
// case lowerCeilingByLine:
case moveCeilingByFrontTexture:
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;
}
}
else if (res == crushed)
{
switch (ceiling->type)
{
case crushAndRaise:
case lowerAndCrush:
ceiling->speed = FixedDiv(CEILSPEED,8*FRACUNIT);
break;
default:
break;
}
}
break;
} }
if (!dontupdate)
ceiling->sector->ceilspeed = ceiling->speed*ceiling->direction; if (res == pastdest)
else {
ceiling->sector->ceilspeed = 0; 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->tag) // chained linedef executing
P_LinedefExecute(ceiling->tag, 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:
case bounceCeilingCrush:
{
fixed_t dest = (ceiling->direction == 1) ? ceiling->topheight : ceiling->bottomheight;
if (dest == lines[ceiling->sourceline].frontsector->ceilingheight)
{
dest = lines[ceiling->sourceline].backsector->ceilingheight;
ceiling->origspeed = lines[ceiling->sourceline].args[3] << (FRACBITS - 2); // return trip, use args[3]
}
else
{
dest = lines[ceiling->sourceline].frontsector->ceilingheight;
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;
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. /** Moves a ceiling crusher.
@ -323,11 +144,7 @@ void T_CrushCeiling(ceiling_t *ceiling)
if (res == pastdest) if (res == pastdest)
{ {
ceiling->direction = -1; ceiling->direction = -1;
ceiling->speed = lines[ceiling->sourceline].args[2] << (FRACBITS - 2);
if (lines[ceiling->sourceline].flags & ML_EFFECT4)
ceiling->speed = ceiling->oldspeed;
else
ceiling->speed = ceiling->oldspeed*2;
if (ceiling->type == crushCeilOnce if (ceiling->type == crushCeilOnce
|| ceiling->type == crushBothOnce) || ceiling->type == crushBothOnce)
@ -368,12 +185,8 @@ void T_CrushCeiling(ceiling_t *ceiling)
ceiling->sector->soundorg.z = ceiling->sector->floorheight; ceiling->sector->soundorg.z = ceiling->sector->floorheight;
S_StartSound(mp,sfx_pstop); 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->direction = 1;
ceiling->speed = lines[ceiling->sourceline].args[3] << (FRACBITS - 2);
} }
break; break;
} }
@ -386,18 +199,18 @@ void T_CrushCeiling(ceiling_t *ceiling)
/** Starts a ceiling mover. /** Starts a ceiling mover.
* *
* \param tag Tag.
* \param line The source line. * \param line The source line.
* \param type The type of ceiling movement. * \param type The type of ceiling movement.
* \return 1 if at least one ceiling mover was started, 0 otherwise. * \return 1 if at least one ceiling mover was started, 0 otherwise.
* \sa EV_DoCrush, EV_DoFloor, EV_DoElevator, T_MoveCeiling * \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 rtn = 0, firstone = 1;
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
ceiling_t *ceiling; ceiling_t *ceiling;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_SECTORS(tag, secnum) TAG_ITER_SECTORS(tag, secnum)
{ {
@ -418,44 +231,12 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
switch (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;
/* FALLTHRU */
case lowerAndCrush:
ceiling->bottomheight = sec->floorheight;
ceiling->bottomheight += 4*FRACUNIT;
ceiling->direction = -1;
ceiling->speed = line->dx;
break;
case raiseToHighest: case raiseToHighest:
ceiling->topheight = P_FindHighestCeilingSurrounding(sec); ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
ceiling->direction = 1; ceiling->direction = 1;
ceiling->speed = CEILSPEED; ceiling->speed = CEILSPEED;
break; 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: case lowerToLowestFast:
ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec); ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec);
ceiling->direction = -1; ceiling->direction = -1;
@ -470,8 +251,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
// Linedef executor excellence // Linedef executor excellence
case moveCeilingByFrontSector: case moveCeilingByFrontSector:
ceiling->speed = P_AproxDistance(line->dx, line->dy); ceiling->speed = line->args[2] << (FRACBITS - 3);
ceiling->speed = FixedDiv(ceiling->speed,8*FRACUNIT);
if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up
{ {
ceiling->direction = 1; ceiling->direction = 1;
@ -484,21 +264,13 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
} }
// chained linedef executing ability // chained linedef executing ability
if (line->flags & ML_BLOCKMONSTERS) // only set it on ONE of the moving sectors (the smallest numbered)
{ // only set it if there isn't also a floor mover
// only set it on ONE of the moving sectors (the smallest numbered) if (line->args[3] && line->args[1] == 1)
// and front side x offset must be positive ceiling->tag = firstone ? (INT16)line->args[3] : 0;
if (firstone && sides[line->sidenum[0]].textureoffset > 0)
ceiling->texture = (sides[line->sidenum[0]].textureoffset>>FRACBITS) - 32769;
else
ceiling->texture = -1;
}
// flat changing ability // flat changing ability
else if (line->flags & ML_NOCLIMB) ceiling->texture = line->args[4] ? line->frontsector->ceilingpic : -1;
ceiling->texture = line->frontsector->ceilingpic;
else
ceiling->texture = -1;
break; break;
// More linedef executor junk // More linedef executor junk
@ -515,67 +287,30 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
ceiling->direction = -1; ceiling->direction = -1;
ceiling->bottomheight = line->frontsector->ceilingheight; ceiling->bottomheight = line->frontsector->ceilingheight;
} }
if (line->flags & ML_NOCLIMB)
ceiling->texture = -1; // If flag is set, change ceiling texture after moving
else ceiling->texture = line->args[2] ? line->frontsector->ceilingpic : -1;
ceiling->texture = line->frontsector->ceilingpic;
break; break;
case moveCeilingByFrontTexture: case moveCeilingByDistance:
if (line->flags & ML_NOCLIMB) if (line->args[4])
ceiling->speed = INT32_MAX/2; // as above, "instant" is one tic ceiling->speed = INT32_MAX/2; // as above, "instant" is one tic
else 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) if (line->args[2] > 0)
{ {
ceiling->direction = 1; // up 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 { else {
ceiling->direction = -1; // down 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; 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: 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: case bounceCeilingCrush:
ceiling->speed = abs(line->dx); // same speed as elevateContinuous ceiling->speed = line->args[2] << (FRACBITS - 2); // same speed as elevateContinuous
ceiling->speed = FixedDiv(ceiling->speed,4*FRACUNIT);
ceiling->origspeed = ceiling->speed; ceiling->origspeed = ceiling->speed;
if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up if (line->frontsector->ceilingheight >= sec->ceilingheight) // Move up
{ {
@ -589,10 +324,8 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
} }
// Any delay? // Any delay?
ceiling->delay = sides[line->sidenum[0]].textureoffset >> FRACBITS; ceiling->delay = line->args[5];
ceiling->delaytimer = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Initial delay ceiling->delaytimer = line->args[4]; // Initial delay
ceiling->texture = (fixed_t)(line - lines); // hack: use texture to store sourceline number
break; break;
default: default:
@ -600,7 +333,6 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
} }
ceiling->tag = tag;
ceiling->type = type; ceiling->type = type;
firstone = 0; firstone = 0;
@ -612,19 +344,19 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
/** Starts a ceiling crusher. /** Starts a ceiling crusher.
* *
* \param tag Tag.
* \param line The source line. * \param line The source line.
* \param type The type of ceiling, either ::crushAndRaise or * \param type The type of ceiling, either ::crushAndRaise or
* ::fastCrushAndRaise. * ::fastCrushAndRaise.
* \return 1 if at least one crusher was started, 0 otherwise. * \return 1 if at least one crusher was started, 0 otherwise.
* \sa EV_DoCeiling, EV_DoFloor, EV_DoElevator, T_CrushCeiling * \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 rtn = 0;
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
ceiling_t *ceiling; ceiling_t *ceiling;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_SECTORS(tag, secnum) TAG_ITER_SECTORS(tag, secnum)
{ {
@ -642,46 +374,33 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
ceiling->sector = sec; ceiling->sector = sec;
ceiling->crush = true; ceiling->crush = true;
ceiling->sourceline = (INT32)(line-lines); ceiling->sourceline = (INT32)(line-lines);
ceiling->speed = ceiling->origspeed = line->args[2] << (FRACBITS - 2);
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);
switch(type) switch(type)
{ {
case fastCrushAndRaise: // Up and then down case raiseAndCrush: // Up and then down
ceiling->topheight = P_FindHighestCeilingSurrounding(sec); ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
ceiling->direction = 1; ceiling->direction = 1;
ceiling->speed = ceiling->oldspeed; // Retain stupid behavior for backwards compatibility
if (!udmf && !(line->flags & ML_MIDSOLID))
ceiling->speed /= 2;
else
ceiling->speed = line->args[3] << (FRACBITS - 2);
ceiling->bottomheight = sec->floorheight + FRACUNIT; ceiling->bottomheight = sec->floorheight + FRACUNIT;
break; break;
case crushBothOnce: case crushBothOnce:
ceiling->topheight = sec->ceilingheight; ceiling->topheight = sec->ceilingheight;
ceiling->bottomheight = sec->floorheight + (sec->ceilingheight-sec->floorheight)/2; ceiling->bottomheight = sec->floorheight + (sec->ceilingheight-sec->floorheight)/2;
ceiling->direction = -1; ceiling->direction = -1;
if (line->flags & ML_EFFECT4)
ceiling->speed = ceiling->oldspeed;
else
ceiling->speed = ceiling->oldspeed*2;
break; break;
case crushCeilOnce: case crushCeilOnce:
default: // Down and then up. default: // Down and then up.
ceiling->topheight = sec->ceilingheight; ceiling->topheight = sec->ceilingheight;
ceiling->direction = -1; ceiling->direction = -1;
if (line->flags & ML_EFFECT4)
ceiling->speed = ceiling->oldspeed;
else
ceiling->speed = ceiling->oldspeed*2;
ceiling->bottomheight = sec->floorheight + FRACUNIT; ceiling->bottomheight = sec->floorheight + FRACUNIT;
break; break;
} }
ceiling->tag = tag;
ceiling->type = type; ceiling->type = type;
// interpolation // interpolation

File diff suppressed because it is too large Load diff

View file

@ -11,6 +11,7 @@
/// \file p_floor.c /// \file p_floor.c
/// \brief Floor animation, elevators /// \brief Floor animation, elevators
#include "dehacked.h"
#include "doomdef.h" #include "doomdef.h"
#include "doomstat.h" #include "doomstat.h"
#include "m_random.h" #include "m_random.h"
@ -163,7 +164,7 @@ result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crus
void T_MoveFloor(floormove_t *movefloor) void T_MoveFloor(floormove_t *movefloor)
{ {
result_e res = 0; result_e res = 0;
boolean dontupdate = false; boolean remove = false;
if (movefloor->delaytimer) if (movefloor->delaytimer)
{ {
@ -179,8 +180,8 @@ void T_MoveFloor(floormove_t *movefloor)
if (movefloor->type == bounceFloor) if (movefloor->type == bounceFloor)
{ {
const fixed_t origspeed = FixedDiv(movefloor->origspeed,(ELEVATORSPEED/2)); 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 fs = abs(movefloor->sector->floorheight - lines[movefloor->sourceline].frontsector->floorheight);
const fixed_t bs = abs(movefloor->sector->floorheight - lines[movefloor->texture].backsector->floorheight); const fixed_t bs = abs(movefloor->sector->floorheight - lines[movefloor->sourceline].backsector->floorheight);
if (fs < bs) if (fs < bs)
movefloor->speed = FixedDiv(fs,25*FRACUNIT) + FRACUNIT/4; movefloor->speed = FixedDiv(fs,25*FRACUNIT) + FRACUNIT/4;
else else
@ -191,113 +192,62 @@ void T_MoveFloor(floormove_t *movefloor)
if (res == pastdest) if (res == pastdest)
{ {
if (movefloor->direction == 1) switch (movefloor->type)
{ {
switch (movefloor->type) case moveFloorByFrontSector:
{ if (movefloor->tag) // chained linedef executing
case moveFloorByFrontSector: P_LinedefExecute(movefloor->tag, NULL, NULL);
if (movefloor->texture < -1) // chained linedef executing /* FALLTHRU */
P_LinedefExecute((INT16)(movefloor->texture + INT16_MAX + 2), NULL, NULL); case instantMoveFloorByFrontSector:
/* FALLTHRU */ if (movefloor->texture > -1) // flat changing
case instantMoveFloorByFrontSector: movefloor->sector->floorpic = movefloor->texture;
if (movefloor->texture > -1) // flat changing remove = true;
movefloor->sector->floorpic = movefloor->texture; break;
break; case bounceFloor: // Graue 03-12-2004
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; {
else movefloor->floordestheight = lines[movefloor->sourceline].backsector->floorheight;
movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; movefloor->origspeed = lines[movefloor->sourceline].args[3] << (FRACBITS - 2); // return trip, use args[3]
movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1; }
movefloor->sector->floorspeed = movefloor->speed * movefloor->direction; else
movefloor->delaytimer = movefloor->delay; {
P_RecalcPrecipInSector(movefloor->sector); movefloor->floordestheight = lines[movefloor->sourceline].frontsector->floorheight;
return; // not break, why did this work? Graue 04-03-2004 movefloor->origspeed = lines[movefloor->sourceline].args[2] << (FRACBITS - 2); // forward again, use args[2]
case bounceFloorCrush: // Graue 03-27-2004 }
if (movefloor->floordestheight == lines[movefloor->texture].frontsector->floorheight) if (movefloor->type == bounceFloorCrush)
{ movefloor->speed = movefloor->origspeed;
movefloor->floordestheight = lines[movefloor->texture].backsector->floorheight; movefloor->direction = (movefloor->floordestheight < movefloor->sector->floorheight) ? -1 : 1;
movefloor->speed = movefloor->origspeed = FixedDiv(abs(lines[movefloor->texture].dy),4*FRACUNIT); // return trip, use dy movefloor->delaytimer = movefloor->delay;
} remove = false;
else break;
{ case crushFloorOnce:
movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight; if (movefloor->direction == 1)
movefloor->speed = movefloor->origspeed = FixedDiv(abs(lines[movefloor->texture].dx),4*FRACUNIT); // forward again, use dx {
} movefloor->floordestheight = lines[movefloor->sourceline].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 crushFloorOnce:
movefloor->floordestheight = lines[movefloor->texture].frontsector->floorheight;
movefloor->direction = -1; movefloor->direction = -1;
movefloor->speed = lines[movefloor->sourceline].args[3] << (FRACBITS - 2);
movefloor->sector->soundorg.z = movefloor->sector->floorheight; movefloor->sector->soundorg.z = movefloor->sector->floorheight;
S_StartSound(&movefloor->sector->soundorg,sfx_pstop); S_StartSound(&movefloor->sector->soundorg, sfx_pstop);
P_RecalcPrecipInSector(movefloor->sector); remove = false;
return; }
default: else
break; remove = true;
} break;
} default:
else if (movefloor->direction == -1) remove = true;
{ break;
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;
}
} }
}
if (remove)
{
movefloor->sector->floordata = NULL; // Clear up the thinker so others can use it movefloor->sector->floordata = NULL; // Clear up the thinker so others can use it
movefloor->sector->floorspeed = 0; movefloor->sector->floorspeed = 0;
P_RemoveThinker(&movefloor->thinker); P_RemoveThinker(&movefloor->thinker);
dontupdate = true;
} }
if (!dontupdate)
movefloor->sector->floorspeed = movefloor->speed*movefloor->direction;
else else
movefloor->sector->floorspeed = 0; movefloor->sector->floorspeed = movefloor->speed*movefloor->direction;
P_RecalcPrecipInSector(movefloor->sector); P_RecalcPrecipInSector(movefloor->sector);
} }
@ -637,7 +587,6 @@ void T_BounceCheese(bouncecheese_t *bouncer)
sector_t *actionsector; sector_t *actionsector;
boolean remove; boolean remove;
INT32 i; INT32 i;
mtag_t tag = Tag_FGet(&bouncer->sourceline->tags);
if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT
|| bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself! || bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself!
@ -652,7 +601,7 @@ void T_BounceCheese(bouncecheese_t *bouncer)
} }
// You can use multiple target sectors, but at your own risk!!! // 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 = &sectors[i]; actionsector = &sectors[i];
actionsector->moved = true; actionsector->moved = true;
@ -776,7 +725,7 @@ void T_StartCrumble(crumble_t *crumble)
ffloor_t *rover; ffloor_t *rover;
sector_t *sector; sector_t *sector;
INT32 i; 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, // Once done, the no-return thinker just sits there,
// constantly 'returning'... kind of an oxymoron, isn't it? // constantly 'returning'... kind of an oxymoron, isn't it?
@ -1100,23 +1049,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 // This is the Thwomp's 'brain'. It looks around for players nearby, and if
// it finds any, **SMASH**!!! Muahahhaa.... // it finds any, **SMASH**!!! Muahahhaa....
void T_ThwompSector(thwomp_t *thwomp) void T_ThwompSector(thwomp_t *thwomp)
@ -1293,7 +1225,7 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
sector_t *sec = NULL; sector_t *sec = NULL;
INT32 secnum = -1; INT32 secnum = -1;
boolean FOFsector = false; boolean FOFsector = false;
mtag_t tag = Tag_FGet(&nobaddies->sourceline->tags); mtag_t tag = nobaddies->sourceline->args[0];
TAG_ITER_SECTORS(tag, secnum) TAG_ITER_SECTORS(tag, secnum)
{ {
@ -1305,14 +1237,13 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
for (i = 0; i < sec->linecount; i++) for (i = 0; i < sec->linecount; i++)
{ {
INT32 targetsecnum = -1; INT32 targetsecnum = -1;
mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags);
if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300)
continue; continue;
FOFsector = true; FOFsector = true;
TAG_ITER_SECTORS(tag2, targetsecnum) TAG_ITER_SECTORS(sec->lines[i]->args[0], targetsecnum)
{ {
if (T_SectorHasEnemies(&sectors[targetsecnum])) if (T_SectorHasEnemies(&sectors[targetsecnum]))
return; return;
@ -1330,217 +1261,68 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
P_RemoveThinker(&nobaddies->thinker); P_RemoveThinker(&nobaddies->thinker);
} }
// static boolean P_CheckAllTrigger(eachtime_t *eachtime)
// 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)
{ {
// Is the object in reverse gravity? size_t i;
if (mo->eflags & MFE_VERTICALFLIP)
for (i = 0; i < MAXPLAYERS; i++)
{ {
// Detect if the player is on the ceiling. if (P_CanPlayerTrigger(i) && !eachtime->playersInArea[i])
if (mo->z+mo->height >= P_GetSpecialTopZ(mo, sec, sec)) return false;
return true;
} }
// Nope!
else return true;
{
// Detect if the player is on the floor.
if (mo->z <= P_GetSpecialBottomZ(mo, sec, sec))
return true;
}
return false;
} }
static boolean P_IsMobjTouchingSector(mobj_t *mo, sector_t *sec)
{
msecnode_t *node;
if (mo->subsector->sector == sec)
return true;
if (!(sec->flags & SF_TRIGGERSPECIAL_TOUCH))
return false;
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
if (node->m_sector == sec)
return true;
}
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
//
void T_EachTimeThinker(eachtime_t *eachtime) void T_EachTimeThinker(eachtime_t *eachtime)
{ {
size_t i, j; size_t i;
sector_t *sec = NULL;
sector_t *targetsec = NULL;
INT32 secnum = -1;
boolean oldPlayersInArea[MAXPLAYERS]; boolean oldPlayersInArea[MAXPLAYERS];
boolean oldPlayersOnArea[MAXPLAYERS]; sector_t *caller[MAXPLAYERS];
boolean *oldPlayersArea; boolean allPlayersChecked = false;
boolean *playersArea; boolean allPlayersTrigger = false;
boolean FOFsector = false;
boolean floortouch = false;
fixed_t bottomheight, topheight;
ffloor_t *rover;
mtag_t tag = Tag_FGet(&eachtime->sourceline->tags);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
oldPlayersInArea[i] = eachtime->playersInArea[i]; oldPlayersInArea[i] = eachtime->playersInArea[i];
oldPlayersOnArea[i] = eachtime->playersOnArea[i]; caller[i] = P_CanPlayerTrigger(i) ? P_FindPlayerTrigger(&players[i], eachtime->sourceline) : NULL;
eachtime->playersInArea[i] = false; eachtime->playersInArea[i] = caller[i] != NULL;
eachtime->playersOnArea[i] = false;
}
TAG_ITER_SECTORS(tag, secnum)
{
sec = &sectors[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;
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)
{
targetsec = &sectors[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;
} }
// Easy check... nothing has changed // Easy check... nothing has changed
if (!memcmp(playersArea, oldPlayersArea, sizeof(boolean)*MAXPLAYERS)) if (!memcmp(eachtime->playersInArea, oldPlayersInArea, sizeof(boolean)*MAXPLAYERS))
return; 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) // Trigger for every player who has entered (and exited, if triggerOnExit)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playersArea[i] == oldPlayersArea[i]) if (eachtime->playersInArea[i] == oldPlayersInArea[i])
continue; continue;
// If player has just left, check if still valid // If player has just left, check if still valid
if (!playersArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i))) if (!eachtime->playersInArea[i] && (!eachtime->triggerOnExit || !P_CanPlayerTrigger(i)))
continue; continue;
CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", tag); // If sector has an "all players" trigger type, all players need to be in area
if (caller[i] && caller[i]->triggerer == TO_ALLPLAYERS)
{
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_FGet(&eachtime->sourceline->tags));
// 03/08/14 -Monster Iestyn // 03/08/14 -Monster Iestyn
// No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever! // 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. // 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. // 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 if (!eachtime->sourceline->special) // this happens only for "Trigger on X calls" linedefs
P_RemoveThinker(&eachtime->thinker); P_RemoveThinker(&eachtime->thinker);
@ -1809,13 +1591,12 @@ void T_PlaneDisplace(planedisplace_t *pd)
// (egg capsule button), P_PlayerInSpecialSector (buttons), // (egg capsule button), P_PlayerInSpecialSector (buttons),
// and P_SpawnSpecials (continuous floor movers and instant lower). // 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 firstone = 1;
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
floormove_t *dofloor; floormove_t *dofloor;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_SECTORS(tag, secnum) TAG_ITER_SECTORS(tag, secnum)
{ {
@ -1836,34 +1617,25 @@ void EV_DoFloor(line_t *line, floor_e floortype)
dofloor->type = floortype; dofloor->type = floortype;
dofloor->crush = false; // default: types that crush will change this dofloor->crush = false; // default: types that crush will change this
dofloor->sector = sec; dofloor->sector = sec;
dofloor->sourceline = (INT32)(line - lines);
switch (floortype) switch (floortype)
{ {
// Lowers a floor to the lowest surrounding floor. // Used to open the top of an Egg Capsule.
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.
case raiseFloorToNearestFast: case raiseFloorToNearestFast:
dofloor->direction = -1; // down dofloor->direction = -1; // down
dofloor->speed = FLOORSPEED*4; // 4 fracunits per tic dofloor->speed = FLOORSPEED*4; // 4 fracunits per tic
dofloor->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight); dofloor->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight);
break; break;
// Used for sectors tagged to 50 linedefs (effectively // Instantly lower floor to surrounding sectors.
// changing the base height for placing things in that sector). // Used as a hack in the binary map format to allow thing heights above 4096.
case instantLower: case instantLower:
dofloor->direction = -1; // down dofloor->direction = -1; // down
dofloor->speed = INT32_MAX/2; // "instant" means "takes one tic" dofloor->speed = INT32_MAX/2; // "instant" means "takes one tic"
dofloor->floordestheight = P_FindLowestFloorSurrounding(sec); dofloor->floordestheight = P_FindLowestFloorSurrounding(sec);
break; break;
// Linedef executor command, linetype 101.
// Front sector floor = destination height.
case instantMoveFloorByFrontSector: case instantMoveFloorByFrontSector:
dofloor->speed = INT32_MAX/2; // as above, "instant" is one tic dofloor->speed = INT32_MAX/2; // as above, "instant" is one tic
dofloor->floordestheight = line->frontsector->floorheight; dofloor->floordestheight = line->frontsector->floorheight;
@ -1873,22 +1645,12 @@ void EV_DoFloor(line_t *line, floor_e floortype)
else else
dofloor->direction = -1; // down dofloor->direction = -1; // down
// New for 1.09: now you can use the no climb flag to // If flag is set, change floor texture after moving
// DISABLE the flat changing. This makes it work dofloor->texture = line->args[2] ? line->frontsector->floorpic : -1;
// 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;
break; break;
// Linedef executor command, linetype 106.
// Line length = speed, front sector floor = destination height.
case moveFloorByFrontSector: case moveFloorByFrontSector:
dofloor->speed = P_AproxDistance(line->dx, line->dy); dofloor->speed = line->args[2] << (FRACBITS - 3);
dofloor->speed = FixedDiv(dofloor->speed,8*FRACUNIT);
dofloor->floordestheight = line->frontsector->floorheight; dofloor->floordestheight = line->frontsector->floorheight;
if (dofloor->floordestheight >= sec->floorheight) if (dofloor->floordestheight >= sec->floorheight)
@ -1897,85 +1659,31 @@ void EV_DoFloor(line_t *line, floor_e floortype)
dofloor->direction = -1; // down dofloor->direction = -1; // down
// chained linedef executing ability // chained linedef executing ability
if (line->flags & ML_BLOCKMONSTERS) // Only set it on one of the moving sectors (the smallest numbered)
{ if (line->args[3])
// Only set it on one of the moving sectors (the dofloor->tag = firstone ? (INT16)line->args[3] : -1;
// 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;
}
// flat changing ability // flat changing ability
else if (line->flags & ML_NOCLIMB) dofloor->texture = line->args[4] ? line->frontsector->floorpic : -1;
dofloor->texture = line->frontsector->floorpic;
else
dofloor->texture = -1; // nothing special to do after movement completes
break; break;
case moveFloorByFrontTexture: case moveFloorByDistance:
if (line->flags & ML_NOCLIMB) if (line->args[4])
dofloor->speed = INT32_MAX/2; // as above, "instant" is one tic dofloor->speed = INT32_MAX/2; // as above, "instant" is one tic
else else
dofloor->speed = FixedDiv(sides[line->sidenum[0]].textureoffset,8*FRACUNIT); // texture x offset dofloor->speed = line->args[3] << (FRACBITS - 3);
dofloor->floordestheight = sec->floorheight + sides[line->sidenum[0]].rowoffset; // texture y offset dofloor->floordestheight = sec->floorheight + (line->args[2] << FRACBITS);
if (dofloor->floordestheight > sec->floorheight) if (dofloor->floordestheight > sec->floorheight)
dofloor->direction = 1; // up dofloor->direction = 1; // up
else else
dofloor->direction = -1; // down dofloor->direction = -1; // down
break; break;
/* // Move floor up and down indefinitely.
// Linedef executor command, linetype 108. // bounceFloor has slowdown at the top and bottom of movement.
// 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: 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: 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->origspeed = dofloor->speed;
dofloor->floordestheight = line->frontsector->floorheight; dofloor->floordestheight = line->frontsector->floorheight;
@ -1985,27 +1693,18 @@ void EV_DoFloor(line_t *line, floor_e floortype)
dofloor->direction = -1; // down dofloor->direction = -1; // down
// Any delay? // Any delay?
dofloor->delay = sides[line->sidenum[0]].textureoffset >> FRACBITS; dofloor->delay = line->args[5];
dofloor->delaytimer = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Initial delay dofloor->delaytimer = line->args[4]; // Initial delay
dofloor->texture = (fixed_t)(line - lines); // hack: store source line number
break; break;
case crushFloorOnce: case crushFloorOnce:
dofloor->speed = FixedDiv(abs(line->dx),4*FRACUNIT); dofloor->speed = dofloor->origspeed = line->args[2] << (FRACBITS - 2);
dofloor->origspeed = dofloor->speed;
dofloor->floordestheight = line->frontsector->ceilingheight; dofloor->floordestheight = line->frontsector->ceilingheight;
if (dofloor->floordestheight >= sec->floorheight) if (dofloor->floordestheight >= sec->floorheight)
dofloor->direction = 1; // up dofloor->direction = 1; // up
else else
dofloor->direction = -1; // down 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; break;
default: default:
@ -2029,14 +1728,13 @@ void EV_DoFloor(line_t *line, floor_e floortype)
// //
// jff 2/22/98 new type to move floor and ceiling in parallel // 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)
{ {
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
elevator_t *elevator; elevator_t *elevator;
mtag_t tag = Tag_FGet(&line->tags);
// 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) TAG_ITER_SECTORS(tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -2054,6 +1752,7 @@ void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
elevator->type = elevtype; elevator->type = elevtype;
elevator->sourceline = line; elevator->sourceline = line;
elevator->distance = 1; // Always crush unless otherwise elevator->distance = 1; // Always crush unless otherwise
elevator->sector = sec;
// set up the fields according to the type of elevator action // set up the fields according to the type of elevator action
switch (elevtype) switch (elevtype)
@ -2061,92 +1760,58 @@ void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
// elevator down to next floor // elevator down to next floor
case elevateDown: case elevateDown:
elevator->direction = -1; elevator->direction = -1;
elevator->sector = sec;
elevator->speed = ELEVATORSPEED/2; // half speed elevator->speed = ELEVATORSPEED/2; // half speed
elevator->floordestheight = P_FindNextLowestFloor(sec, sec->floorheight); elevator->floordestheight = P_FindNextLowestFloor(sec, sec->floorheight);
elevator->ceilingdestheight = elevator->floordestheight
+ sec->ceilingheight - sec->floorheight;
break; break;
// elevator up to next floor // elevator up to next floor
case elevateUp: case elevateUp:
elevator->direction = 1; elevator->direction = 1;
elevator->sector = sec;
elevator->speed = ELEVATORSPEED/4; // quarter speed elevator->speed = ELEVATORSPEED/4; // quarter speed
elevator->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight); elevator->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight);
elevator->ceilingdestheight = elevator->floordestheight
+ sec->ceilingheight - sec->floorheight;
break; break;
// elevator up to highest floor // elevator up to highest floor
case elevateHighest: case elevateHighest:
elevator->direction = 1; elevator->direction = 1;
elevator->sector = sec;
elevator->speed = ELEVATORSPEED/4; // quarter speed elevator->speed = ELEVATORSPEED/4; // quarter speed
elevator->floordestheight = P_FindHighestFloorSurrounding(sec); elevator->floordestheight = P_FindHighestFloorSurrounding(sec);
elevator->ceilingdestheight = elevator->floordestheight
+ sec->ceilingheight - sec->floorheight;
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->ceilingdestheight = elevator->floordestheight
+ sec->ceilingheight - sec->floorheight;
elevator->direction = elevator->floordestheight > sec->floorheight? 1 : -1;
break; break;
case elevateContinuous: case elevateContinuous:
if (customspeed) elevator->origspeed = line->args[1] << (FRACBITS - 2);
{ elevator->speed = elevator->origspeed;
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->sector = sec; elevator->low = !line->args[4]; // go down first unless args[4] is set
elevator->low = !(line->flags & ML_NOCLIMB); // go down first unless noclimb is on
if (elevator->low) if (elevator->low)
{ {
elevator->direction = 1; elevator->direction = 1;
elevator->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight); elevator->floordestheight = P_FindNextHighestFloor(sec, sec->floorheight);
elevator->ceilingdestheight = elevator->floordestheight
+ sec->ceilingheight - sec->floorheight;
} }
else else
{ {
elevator->direction = -1; elevator->direction = -1;
elevator->floordestheight = P_FindNextLowestFloor(sec,sec->floorheight); elevator->floordestheight = P_FindNextLowestFloor(sec,sec->floorheight);
elevator->ceilingdestheight = elevator->floordestheight
+ sec->ceilingheight - sec->floorheight;
} }
elevator->floorwasheight = elevator->sector->floorheight; elevator->floorwasheight = elevator->sector->floorheight;
elevator->ceilingwasheight = elevator->sector->ceilingheight; elevator->ceilingwasheight = elevator->sector->ceilingheight;
elevator->delay = sides[line->sidenum[0]].textureoffset >> FRACBITS; elevator->delay = line->args[3];
elevator->delaytimer = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Initial delay elevator->delaytimer = line->args[2]; // Initial delay
break; break;
case bridgeFall: case bridgeFall:
elevator->direction = -1; elevator->direction = -1;
elevator->sector = sec;
elevator->speed = ELEVATORSPEED*4; // quadruple speed elevator->speed = ELEVATORSPEED*4; // quadruple speed
elevator->floordestheight = P_FindNextLowestFloor(sec, sec->floorheight); elevator->floordestheight = P_FindNextLowestFloor(sec, sec->floorheight);
elevator->ceilingdestheight = elevator->floordestheight
+ sec->ceilingheight - sec->floorheight;
break; break;
default: default:
break; break;
} }
elevator->ceilingdestheight = elevator->floordestheight + sec->ceilingheight - sec->floorheight;
// interpolation // interpolation
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, false); R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, true); R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, true);
@ -2159,7 +1824,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
fixed_t leftx, rightx, topy, bottomy, topz, bottomz, widthfactor, heightfactor, a, b, c, spacing; fixed_t leftx, rightx, topy, bottomy, topz, bottomz, widthfactor, heightfactor, a, b, c, spacing;
mobjtype_t type; mobjtype_t type;
tic_t lifetime; tic_t lifetime;
INT16 flags; boolean fromcenter;
sector_t *controlsec = rover->master->frontsector; sector_t *controlsec = rover->master->frontsector;
mtag_t tag = Tag_FGet(&controlsec->tags); mtag_t tag = Tag_FGet(&controlsec->tags);
@ -2189,25 +1854,20 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
spacing = (32<<FRACBITS); spacing = (32<<FRACBITS);
type = MT_ROCKCRUMBLE1; type = MT_ROCKCRUMBLE1;
lifetime = 3*TICRATE; lifetime = 3*TICRATE;
flags = 0; fromcenter = false;
if (tag != 0) if (tag != 0)
{ {
INT32 tagline = Tag_FindLineSpecial(14, tag); INT32 tagline = Tag_FindLineSpecial(14, tag);
if (tagline != -1) if (tagline != -1)
{ {
if (sides[lines[tagline].sidenum[0]].toptexture) if (lines[tagline].stringargs[0])
type = (mobjtype_t)sides[lines[tagline].sidenum[0]].toptexture; // Set as object type in p_setup.c... type = get_number(lines[tagline].stringargs[0]);
if (sides[lines[tagline].sidenum[0]].textureoffset) if (lines[tagline].args[0])
spacing = sides[lines[tagline].sidenum[0]].textureoffset; spacing = lines[tagline].args[0] << FRACBITS;
if (sides[lines[tagline].sidenum[0]].rowoffset) if (lines[tagline].args[1])
{ lifetime = (lines[tagline].args[1] != -1) ? lines[tagline].args[1] : 0;
if (sides[lines[tagline].sidenum[0]].rowoffset>>FRACBITS != -1) fromcenter = !!lines[tagline].args[2];
lifetime = (sides[lines[tagline].sidenum[0]].rowoffset>>FRACBITS);
else
lifetime = 0;
}
flags = lines[tagline].flags;
} }
} }
@ -2242,7 +1902,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
topz = *rover->topheight-(spacing>>1); topz = *rover->topheight-(spacing>>1);
bottomz = *rover->bottomheight; bottomz = *rover->bottomheight;
if (flags & ML_EFFECT1) if (fromcenter)
{ {
widthfactor = (rightx + topy - leftx - bottomy)>>3; widthfactor = (rightx + topy - leftx - bottomy)>>3;
heightfactor = (topz - *rover->bottomheight)>>2; heightfactor = (topz - *rover->bottomheight)>>2;
@ -2265,7 +1925,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
spawned = P_SpawnMobj(a, b, c, type); 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 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_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); P_SetObjectMomZ(spawned, FixedDiv((c - bottomz), heightfactor), false);
@ -2345,7 +2005,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
crumble_t *crumble; crumble_t *crumble;
sector_t *foundsec; sector_t *foundsec;
INT32 i; INT32 i;
mtag_t tag = Tag_FGet(&rover->master->tags); mtag_t tag = rover->master->args[0];
// If floor is already activated, skip it // If floor is already activated, skip it
if (sec->floordata) if (sec->floordata)
@ -2441,7 +2101,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
block->direction = 1; block->direction = 1;
block->floorstartheight = block->sector->floorheight; block->floorstartheight = block->sector->floorheight;
block->ceilingstartheight = block->sector->ceilingheight; block->ceilingstartheight = block->sector->ceilingheight;
block->tag = (INT16)Tag_FGet(&sector->tags); block->tag = (INT16)rover->master->args[0];
// interpolation // interpolation
R_CreateInterpolator_SectorPlane(&block->thinker, roversec, false); R_CreateInterpolator_SectorPlane(&block->thinker, roversec, false);

View file

@ -762,6 +762,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// return; // return;
{ {
UINT8 flagteam = (special->type == MT_REDFLAG) ? 1 : 2; UINT8 flagteam = (special->type == MT_REDFLAG) ? 1 : 2;
sectorspecialflags_t specialflag = (special->type == MT_REDFLAG) ? SSF_REDTEAMBASE : SSF_BLUETEAMBASE;
const char *flagtext; const char *flagtext;
char flagcolor; char flagcolor;
char plname[MAXPLAYERNAME+4]; char plname[MAXPLAYERNAME+4];
@ -791,7 +792,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->fuse = 1; special->fuse = 1;
special->flags2 |= MF2_JUSTATTACKED; 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); CONS_Printf(M_GetText("%s returned the %c%s%c to base.\n"), plname, flagcolor, flagtext, 0x80);
@ -1380,19 +1381,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return; return;
case MT_AXE: case MT_AXE:
{ {
line_t junk;
thinker_t *th; thinker_t *th;
mobj_t *mo2; mobj_t *mo2;
if (player->bot && player->bot != BOT_MPAI) if (player->bot && player->bot != BOT_MPAI)
return; return;
// Initialize my junk if (special->spawnpoint)
junk.tags.tags = NULL; EV_DoElevator(special->spawnpoint->args[0], NULL, bridgeFall);
junk.tags.count = 0;
Tag_FSet(&junk.tags, LE_AXE);
EV_DoElevator(&junk, bridgeFall, false);
// scan the remaining thinkers to find koopa // scan the remaining thinkers to find koopa
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
@ -1441,7 +1437,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Misc touchables // // Misc touchables //
// *************** // // *************** //
case MT_STARPOST: 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; return;
case MT_FAKEMOBILE: case MT_FAKEMOBILE:
@ -2775,7 +2771,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
case MT_BLASTEXECUTOR: case MT_BLASTEXECUTOR:
if (target->spawnpoint) 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; break;
case MT_SPINBOBERT: case MT_SPINBOBERT:

View file

@ -30,7 +30,7 @@ void P_RemoveLighting(sector_t *sector)
// The thinker is the first member in all the lighting action structs, // 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 // so just let the thinker get freed, and that will free the whole
// structure. // structure.
P_RemoveThinker(&((elevator_t *)sector->lightingdata)->thinker); P_RemoveThinker(&((thinkerdata_t *)sector->lightingdata)->thinker);
sector->lightingdata = NULL; sector->lightingdata = NULL;
} }
} }
@ -54,43 +54,36 @@ void T_FireFlicker(fireflicker_t *flick)
amount = (INT16)((UINT8)(P_RandomByte() & 3) * 16); amount = (INT16)((UINT8)(P_RandomByte() & 3) * 16);
if (flick->sector->lightlevel - amount < flick->minlight) if (flick->sector->lightlevel - amount < flick->minlight)
flick->sector->lightlevel = (INT16)flick->minlight; flick->sector->lightlevel = flick->minlight;
else else
flick->sector->lightlevel = (INT16)((INT16)flick->maxlight - amount); flick->sector->lightlevel = flick->maxlight - amount;
flick->count = flick->resetcount; flick->count = flick->resetcount;
} }
/** Spawns an adjustable fire flicker effect in a sector. /** Spawns an adjustable fire flicker effect in a sector.
* *
* \param minsector Sector whose light level is used as the darkest. * \param sector Target sector for the effect.
* \param maxsector Sector whose light level is used as the brightest, * \param lighta One of the two light levels to move between.
* and also the target sector for the effect. * \param lightb The other light level.
* \param length Four times the number of tics between flickers. * \param length Four times the number of tics between flickers.
* \sa T_FireFlicker * \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; 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); flick = Z_Calloc(sizeof (*flick), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &flick->thinker); P_AddThinker(THINK_MAIN, &flick->thinker);
flick->thinker.function.acp1 = (actionf_p1)T_FireFlicker; flick->thinker.function.acp1 = (actionf_p1)T_FireFlicker;
flick->sector = maxsector; flick->sector = sector;
flick->maxlight = maxsector->lightlevel; flick->maxlight = max(lighta, lightb);
flick->minlight = minsector->lightlevel; flick->minlight = min(lighta, lightb);
if (flick->minlight > flick->maxlight)
{
// You mixed them up, you dummy.
INT32 oops = flick->minlight;
flick->minlight = flick->maxlight;
flick->maxlight = oops;
}
flick->count = flick->resetcount = length/4; flick->count = flick->resetcount = length/4;
maxsector->lightingdata = flick; sector->lightingdata = flick;
// input bounds checking and stuff // input bounds checking and stuff
if (!flick->resetcount) if (!flick->resetcount)
@ -103,6 +96,9 @@ fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *minsector, sector_t *maxse
flick->maxlight++; flick->maxlight++;
} }
// Make sure the starting light level is in range.
sector->lightlevel = max(flick->minlight, min(flick->maxlight, sector->lightlevel));
return flick; return flick;
} }
@ -148,7 +144,7 @@ void P_SpawnLightningFlash(sector_t *sector)
minlight = ((lightflash_t *)sector->lightingdata)->minlight; minlight = ((lightflash_t *)sector->lightingdata)->minlight;
} }
P_RemoveThinker(&((elevator_t *)sector->lightingdata)->thinker); P_RemoveThinker(&((thinkerdata_t *)sector->lightingdata)->thinker);
} }
sector->lightingdata = NULL; sector->lightingdata = NULL;
@ -182,21 +178,21 @@ void T_StrobeFlash(strobe_t *flash)
if (flash->sector->lightlevel == flash->minlight) if (flash->sector->lightlevel == flash->minlight)
{ {
flash->sector->lightlevel = (INT16)flash->maxlight; flash->sector->lightlevel = flash->maxlight;
flash->count = flash->brighttime; flash->count = flash->brighttime;
} }
else else
{ {
flash->sector->lightlevel = (INT16)flash->minlight; flash->sector->lightlevel = flash->minlight;
flash->count = flash->darktime; flash->count = flash->darktime;
} }
} }
/** Spawns an adjustable strobe light effect in a sector. /** Spawns an adjustable strobe light effect in a sector.
* *
* \param minsector Sector whose light level is used as the darkest. * \param sector Target sector for the effect.
* \param maxsector Sector whose light level is used as the brightest, * \param lighta One of the two light levels to move between.
* and also the target sector for the effect. * \param lightb The other light level.
* \param darktime Time in tics for the light to be dark. * \param darktime Time in tics for the light to be dark.
* \param brighttime Time in tics for the light to be bright. * \param brighttime Time in tics for the light to be bright.
* \param inSync If true, the effect will be kept in sync * \param inSync If true, the effect will be kept in sync
@ -207,29 +203,21 @@ void T_StrobeFlash(strobe_t *flash)
* the strobe flash is random. * the strobe flash is random.
* \sa T_StrobeFlash * \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; 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); flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &flash->thinker); P_AddThinker(THINK_MAIN, &flash->thinker);
flash->sector = maxsector; flash->sector = sector;
flash->darktime = darktime; flash->darktime = darktime;
flash->brighttime = brighttime; flash->brighttime = brighttime;
flash->thinker.function.acp1 = (actionf_p1)T_StrobeFlash; flash->thinker.function.acp1 = (actionf_p1)T_StrobeFlash;
flash->maxlight = maxsector->lightlevel; flash->maxlight = max(lighta, lightb);
flash->minlight = minsector->lightlevel; flash->minlight = min(lighta, lightb);
if (flash->minlight > flash->maxlight)
{
// You mixed them up, you dummy.
INT32 oops = flash->minlight;
flash->minlight = flash->maxlight;
flash->maxlight = oops;
}
if (flash->minlight == flash->maxlight) if (flash->minlight == flash->maxlight)
flash->minlight = 0; flash->minlight = 0;
@ -239,7 +227,10 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector,
else else
flash->count = 1; flash->count = 1;
maxsector->lightingdata = flash; // Make sure the starting light level is in range.
sector->lightlevel = max(flash->minlight, min(flash->maxlight, sector->lightlevel));
sector->lightingdata = flash;
return flash; return flash;
} }
@ -254,20 +245,20 @@ void T_Glow(glow_t *g)
{ {
case -1: case -1:
// DOWN // DOWN
g->sector->lightlevel = (INT16)(g->sector->lightlevel - (INT16)g->speed); g->sector->lightlevel -= g->speed;
if (g->sector->lightlevel <= g->minlight) if (g->sector->lightlevel <= g->minlight)
{ {
g->sector->lightlevel = (INT16)(g->sector->lightlevel + (INT16)g->speed); g->sector->lightlevel += g->speed;
g->direction = 1; g->direction = 1;
} }
break; break;
case 1: case 1:
// UP // UP
g->sector->lightlevel = (INT16)(g->sector->lightlevel + (INT16)g->speed); g->sector->lightlevel += g->speed;
if (g->sector->lightlevel >= g->maxlight) if (g->sector->lightlevel >= g->maxlight)
{ {
g->sector->lightlevel = (INT16)(g->sector->lightlevel - (INT16)g->speed); g->sector->lightlevel -= g->speed;
g->direction = -1; g->direction = -1;
} }
break; break;
@ -276,34 +267,27 @@ void T_Glow(glow_t *g)
/** Spawns an adjustable glowing light effect in a sector. /** Spawns an adjustable glowing light effect in a sector.
* *
* \param minsector Sector whose light level is used as the darkest. * \param sector Target sector for the effect.
* \param maxsector Sector whose light level is used as the brightest, * \param lighta One of the two light levels to move between.
* and also the target sector for the effect. * \param lightb The other light level.
* \param length The speed of the effect. * \param length The speed of the effect.
* \sa T_Glow * \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; 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); g = Z_Calloc(sizeof (*g), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &g->thinker); P_AddThinker(THINK_MAIN, &g->thinker);
g->sector = maxsector; g->sector = sector;
g->minlight = minsector->lightlevel; g->minlight = min(lighta, lightb);
g->maxlight = maxsector->lightlevel; g->maxlight = max(lighta, lightb);
if (g->minlight > g->maxlight)
{
// You mixed them up, you dummy.
INT32 oops = g->minlight;
g->minlight = g->maxlight;
g->maxlight = oops;
}
g->thinker.function.acp1 = (actionf_p1)T_Glow; g->thinker.function.acp1 = (actionf_p1)T_Glow;
g->direction = 1; 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 if (g->speed > (g->maxlight - g->minlight)/2) // don't make it ridiculous speed
g->speed = (g->maxlight - g->minlight)/2; g->speed = (g->maxlight - g->minlight)/2;
@ -317,7 +301,10 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector,
g->speed = (g->maxlight - g->minlight)/2; g->speed = (g->maxlight - g->minlight)/2;
} }
maxsector->lightingdata = g; // Make sure the starting light level is in range.
sector->lightlevel = max(g->minlight, min(g->maxlight, sector->lightlevel));
sector->lightingdata = g;
return g; return g;
} }
@ -371,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 i;
INT32 realdestvalue;
// search all sectors for ones with tag // search all sectors for ones with tag
TAG_ITER_SECTORS(tag, i) TAG_ITER_SECTORS(tag, i)
@ -386,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); CONS_Debug(DBG_GAMELOGIC, "Line type 420 Executor: Fade light thinker already exists, timer: %d\n", ((lightlevel_t*)sectors[i].lightingdata)->timer);
continue; continue;
} }
P_FadeLightBySector(&sectors[i], destvalue, speed, ticbased);
realdestvalue = relative ? max(0, min(255, sectors[i].lightlevel + destvalue)) : destvalue;
P_FadeLightBySector(&sectors[i], realdestvalue, speed, ticbased);
} }
} }

View file

@ -148,7 +148,6 @@ boolean P_PlayerShouldUseSpinHeight(player_t *player);
boolean P_IsObjectInGoop(mobj_t *mo); boolean P_IsObjectInGoop(mobj_t *mo);
boolean P_IsObjectOnGround(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_InSpaceSector(mobj_t *mo);
boolean P_InQuicksand(mobj_t *mo); boolean P_InQuicksand(mobj_t *mo);
boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff); boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff);
@ -373,7 +372,7 @@ void P_NewChaseDir(mobj_t *actor);
boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed_t dist); 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); 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) #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_InternalFlickyBubble(mobj_t *actor);
void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez); void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez);

View file

@ -517,7 +517,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
switch (spring->type) switch (spring->type)
{ {
case MT_FAN: // fan 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; break;
if (flipval*object->momz >= FixedMul(speed, spring->scale)) // if object's already moving faster than your best, don't bother if (flipval*object->momz >= FixedMul(speed, spring->scale)) // if object's already moving faster than your best, don't bother
break; break;
@ -2356,7 +2356,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
mapcampointer = thiscam; mapcampointer = thiscam;
if (GETSECSPECIAL(newsubsec->sector->special, 4) == 12) if (newsubsec->sector->flags & MSF_NOCLIPCAMERA)
{ // Camera noclip on entire sector. { // Camera noclip on entire sector.
tmfloorz = tmdropoffz = thiscam->z; tmfloorz = tmdropoffz = thiscam->z;
tmceilingz = tmdrpoffceilz = thiscam->z + thiscam->height; tmceilingz = tmdrpoffceilz = thiscam->z + thiscam->height;
@ -2396,7 +2396,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
for (rover = newsubsec->sector->ffloors; rover; rover = rover->next) for (rover = newsubsec->sector->ffloors; rover; rover = rover->next)
{ {
fixed_t topheight, bottomheight; 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; continue;
topheight = P_CameraGetFOFTopZ(thiscam, newsubsec->sector, rover, x, y, NULL); topheight = P_CameraGetFOFTopZ(thiscam, newsubsec->sector, rover, x, y, NULL);
@ -2468,7 +2468,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
// We're inside it! Yess... // We're inside it! Yess...
polysec = po->lines[0]->backsector; polysec = po->lines[0]->backsector;
if (GETSECSPECIAL(polysec->special, 4) == 12) if (polysec->flags & MSF_NOCLIPCAMERA)
{ // Camera noclip polyobj. { // Camera noclip polyobj.
plink = (polymaplink_t *)(plink->link.next); plink = (polymaplink_t *)(plink->link.next);
continue; continue;
@ -2736,14 +2736,14 @@ increment_move
if (thing->player) if (thing->player)
{ {
// If using type Section1:13, double the maxstep. // If using SSF_DOUBLESTEPUP, double the maxstep.
if (P_PlayerTouchingSectorSpecial(thing->player, 1, 13) if (P_PlayerTouchingSectorSpecialFlag(thing->player, SSF_DOUBLESTEPUP)
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13) || (R_PointInSubsector(x, y)->sector->specialflags & SSF_DOUBLESTEPUP))
maxstep <<= 1; maxstep <<= 1;
// If using type Section1:14, no maxstep. // If using SSF_NOSTEPDOWN, no maxstep.
if (P_PlayerTouchingSectorSpecial(thing->player, 1, 14) if (P_PlayerTouchingSectorSpecialFlag(thing->player, SSF_NOSTEPDOWN)
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14) || (R_PointInSubsector(x, y)->sector->specialflags & SSF_NOSTEPDOWN))
maxstep = 0; maxstep = 0;
// Don't 'step up' while springing, // Don't 'step up' while springing,
@ -2754,12 +2754,12 @@ increment_move
} }
else if (thing->flags & MF_PUSHABLE) else if (thing->flags & MF_PUSHABLE)
{ {
// If using type Section1:13, double the maxstep. // If using SSF_DOUBLESTEPUP, double the maxstep.
if (GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13) if (R_PointInSubsector(x, y)->sector->specialflags & SSF_DOUBLESTEPUP)
maxstep <<= 1; maxstep <<= 1;
// If using type Section1:14, no maxstep. // If using SSF_NOSTEPDOWN, no maxstep.
if (GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14) if (R_PointInSubsector(x, y)->sector->specialflags & SSF_NOSTEPDOWN)
maxstep = 0; maxstep = 0;
} }
@ -3523,7 +3523,7 @@ static boolean PTR_SlideTraverse(intercept_t *in)
// see if it is closer than best so far // see if it is closer than best so far
if (li->polyobj && slidemo->player) 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); P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector);
} }
@ -3662,10 +3662,7 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
if (!(rover->flags & FF_SWIMMABLE)) if (!(rover->flags & FF_SWIMMABLE))
continue; continue;
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 3) if (rover->master->frontsector->damagetype != SD_LAVA)
continue;
if (rover->master->flags & ML_BLOCKMONSTERS)
continue; continue;
topheight = P_GetFFloorTopZAt(rover, mo->x, mo->y); topheight = P_GetFFloorTopZAt(rover, mo->x, mo->y);

View file

@ -374,7 +374,7 @@ void P_CameraLineOpening(line_t *linedef)
for (rover = front->ffloors; rover; rover = rover->next) for (rover = front->ffloors; rover; rover = rover->next)
{ {
fixed_t topheight, bottomheight; 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; continue;
topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, tmx, tmy, linedef); 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) for (rover = back->ffloors; rover; rover = rover->next)
{ {
fixed_t topheight, bottomheight; 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; continue;
topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tmx, tmy, linedef); topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tmx, tmy, linedef);
@ -491,7 +491,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
fixed_t thingtop = mobj->z + mobj->height; fixed_t thingtop = mobj->z + mobj->height;
// Check for collision with front side's midtexture if Effect 4 is set // 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 && !linedef->polyobj // don't do anything for polyobjects! ...for now
) { ) {
side_t *side = &sides[linedef->sidenum[0]]; 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 // don't remove this code unless solid midtextures
// on non-solid polyobjects should NEVER happen in the future // on non-solid polyobjects should NEVER happen in the future
if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { 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; texbottom = back->floorheight + side->rowoffset;
textop = back->ceilingheight + 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; texbottom = back->floorheight + side->rowoffset;
textop = texbottom + texheight*(side->repeatcnt+1); textop = texbottom + texheight*(side->repeatcnt+1);
} else { } else {
@ -521,10 +521,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
} else } else
#endif #endif
{ {
if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat
texbottom = openbottom + side->rowoffset; texbottom = openbottom + side->rowoffset;
textop = opentop + side->rowoffset; textop = opentop + side->rowoffset;
} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { } else if (linedef->flags & ML_MIDPEG) {
texbottom = openbottom + side->rowoffset; texbottom = openbottom + side->rowoffset;
textop = texbottom + texheight*(side->repeatcnt+1); textop = texbottom + texheight*(side->repeatcnt+1);
} else { } else {

File diff suppressed because it is too large Load diff

View file

@ -118,7 +118,7 @@ typedef enum
// Don't apply gravity (every tic); object will float, keeping current height // Don't apply gravity (every tic); object will float, keeping current height
// or changing it actively. // or changing it actively.
MF_NOGRAVITY = 1<<9, 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, MF_AMBIENT = 1<<10,
// Slide this object when it hits a wall. // Slide this object when it hits a wall.
MF_SLIDEME = 1<<11, MF_SLIDEME = 1<<11,

View file

@ -964,7 +964,7 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
else else
Polyobj_pushThing(po, line, mo); 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); P_ProcessSpecialSector(mo->player, mo->subsector->sector, po->lines[0]->backsector);
hitflags |= 1; hitflags |= 1;
@ -1092,7 +1092,7 @@ static void Polyobj_rotateLine(line_t *ld)
} }
// Causes objects resting on top of the rotating polyobject to 'ride' with its movement. // 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; static INT32 pomovecount = 10000;
INT32 x, y; INT32 x, y;
@ -1154,7 +1154,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
Polyobj_slideThing(mo, newxoff, newyoff); Polyobj_slideThing(mo, newxoff, newyoff);
if (turnthings == 2 || (turnthings == 1 && !mo->player)) { if ((turnplayers && mo->player) || (turnothers && !mo->player)) {
mo->angle += delta; mo->angle += delta;
if (mo->player) if (mo->player)
P_SetPlayerAngle(mo->player, (angle_t)(mo->player->angleturn << 16) + delta); P_SetPlayerAngle(mo->player, (angle_t)(mo->player->angleturn << 16) + delta);
@ -1166,7 +1166,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
} }
// Rotates a polyobject around its start point. // 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; size_t i;
angle_t angle; angle_t angle;
@ -1204,7 +1204,7 @@ boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean c
for (i = 0; i < po->numLines; ++i) for (i = 0; i < po->numLines; ++i)
hitflags |= Polyobj_clipThings(po, po->lines[i]); hitflags |= Polyobj_clipThings(po, po->lines[i]);
Polyobj_rotateThings(po, origin, delta, turnthings); Polyobj_rotateThings(po, origin, delta, turnplayers, turnothers);
} }
if (hitflags & 2) if (hitflags & 2)
@ -1412,7 +1412,7 @@ void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y)
fixed_t dx, dy; fixed_t dx, dy;
// first, rotate to the saved angle // first, rotate to the saved angle
Polyobj_rotate(po, angle, false, false); Polyobj_rotate(po, angle, false, false, false);
// determine component distances to translate // determine component distances to translate
dx = x - po->spawnSpot.x; dx = x - po->spawnSpot.x;
@ -1455,7 +1455,7 @@ void T_PolyObjRotate(polyrotate_t *th)
// rotate by 'speed' angle per frame // rotate by 'speed' angle per frame
// if distance == -1, this polyobject rotates perpetually // 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); INT32 avel = abs(th->speed);
@ -1857,7 +1857,7 @@ void T_PolyDoorSwing(polyswingdoor_t *th)
// rotate by 'speed' angle per frame // rotate by 'speed' angle per frame
// if distance == -1, this polyobject rotates perpetually // 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); INT32 avel = abs(th->speed);
@ -1988,7 +1988,7 @@ void T_PolyObjRotDisplace(polyrotdisplace_t *th)
rotangle = FixedMul(th->rotscale, delta); 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; th->oldHeights = newheights;
} }
@ -2017,7 +2017,7 @@ boolean EV_DoPolyObjRotate(polyrotdata_t *prdata)
return false; return false;
// check for override if this polyobj already has a thinker // check for override if this polyobj already has a thinker
if (po->thinker && !prdata->overRide) if (po->thinker && !(prdata->flags & TMPR_OVERRIDE))
return false; return false;
// create a new thinker // create a new thinker
@ -2032,10 +2032,10 @@ boolean EV_DoPolyObjRotate(polyrotdata_t *prdata)
// use Hexen-style byte angles for speed and distance // use Hexen-style byte angles for speed and distance
th->speed = Polyobj_AngSpeed(prdata->speed * prdata->direction); th->speed = Polyobj_AngSpeed(prdata->speed * prdata->direction);
if (prdata->distance == 360) // 360 means perpetual if (prdata->flags & TMPR_CONTINUOUS)
th->distance = -1; th->distance = -1;
else if (prdata->distance == 0) // 0 means 360 degrees else if (prdata->distance == 360)
th->distance = 0xffffffff - 1; th->distance = ANGLE_MAX - 1;
else else
th->distance = FixedAngle(prdata->distance*FRACUNIT); th->distance = FixedAngle(prdata->distance*FRACUNIT);
@ -2052,8 +2052,12 @@ boolean EV_DoPolyObjRotate(polyrotdata_t *prdata)
// interpolation // interpolation
R_CreateInterpolator_Polyobj(&th->thinker, po); R_CreateInterpolator_Polyobj(&th->thinker, 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 // apply action to mirroring polyobjects as well
start = 0; start = 0;

View file

@ -137,7 +137,7 @@ typedef struct polyrotate_s
INT32 polyObjNum; // numeric id of polyobject (avoid C pointers here) INT32 polyObjNum; // numeric id of polyobject (avoid C pointers here)
INT32 speed; // speed of movement per frame INT32 speed; // speed of movement per frame
INT32 distance; // distance to move 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; } polyrotate_t;
typedef struct polymove_s typedef struct polymove_s
@ -247,14 +247,27 @@ typedef struct polyfade_s
// Line Activation Data Structures // 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 typedef struct polyrotdata_s
{ {
INT32 polyObjNum; // numeric id of polyobject to affect INT32 polyObjNum; // numeric id of polyobject to affect
INT32 direction; // direction of rotation INT32 direction; // direction of rotation
INT32 speed; // angular speed INT32 speed; // angular speed
INT32 distance; // distance to move INT32 distance; // distance to move
UINT8 turnobjs; // rotate objects being carried? UINT8 flags; // TMPR_ flags
UINT8 overRide; // if true, will override any action on the object
} polyrotdata_t; } polyrotdata_t;
typedef struct polymovedata_s typedef struct polymovedata_s
@ -281,6 +294,20 @@ typedef struct polywaypointdata_s
UINT8 flags; // PWF_ flags UINT8 flags; // PWF_ flags
} polywaypointdata_t; } 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 // polyobject door types
typedef enum typedef enum
{ {
@ -322,6 +349,15 @@ typedef struct polyflagdata_s
fixed_t momx; fixed_t momx;
} polyflagdata_t; } 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 typedef struct polyfadedata_s
{ {
INT32 polyObjNum; INT32 polyObjNum;
@ -337,7 +373,7 @@ typedef struct polyfadedata_s
// //
boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs); 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); polyobj_t *Polyobj_GetForNum(INT32 id);
void Polyobj_InitLevel(void); void Polyobj_InitLevel(void);
void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y); void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y);

View file

@ -851,6 +851,17 @@ static void P_NetUnArchiveWaypoints(void)
#define SD_TAGLIST 0x01 #define SD_TAGLIST 0x01
#define SD_COLORMAP 0x02 #define SD_COLORMAP 0x02
#define SD_CRUMBLESTATE 0x04 #define SD_CRUMBLESTATE 0x04
#define SD_FLOORLIGHT 0x08
#define SD_CEILLIGHT 0x10
#define SD_FLAG 0x20
#define SD_SPECIALFLAG 0x40
#define SD_DIFF4 0x80
//diff4 flags
#define SD_DAMAGETYPE 0x01
#define SD_TRIGGERTAG 0x02
#define SD_TRIGGERER 0x04
#define SD_GRAVITY 0x08
#define LD_FLAG 0x01 #define LD_FLAG 0x01
#define LD_SPECIAL 0x02 #define LD_SPECIAL 0x02
@ -989,11 +1000,11 @@ static void ArchiveSectors(void)
size_t i, j; size_t i, j;
const sector_t *ss = sectors; const sector_t *ss = sectors;
const sector_t *spawnss = spawnsectors; const sector_t *spawnss = spawnsectors;
UINT8 diff, diff2, diff3; UINT8 diff, diff2, diff3, diff4;
for (i = 0; i < numsectors; i++, ss++, spawnss++) for (i = 0; i < numsectors; i++, ss++, spawnss++)
{ {
diff = diff2 = diff3 = 0; diff = diff2 = diff3 = diff4 = 0;
if (ss->floorheight != spawnss->floorheight) if (ss->floorheight != spawnss->floorheight)
diff |= SD_FLOORHT; diff |= SD_FLOORHT;
if (ss->ceilingheight != spawnss->ceilingheight) if (ss->ceilingheight != spawnss->ceilingheight)
@ -1032,9 +1043,29 @@ static void ArchiveSectors(void)
if (ss->crumblestate) if (ss->crumblestate)
diff3 |= SD_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->flags != spawnss->flags)
diff3 |= SD_FLAG;
if (ss->specialflags != spawnss->specialflags)
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;
if (ss->ffloors && CheckFFloorDiff(ss)) if (ss->ffloors && CheckFFloorDiff(ss))
diff |= SD_FFLOORS; diff |= SD_FFLOORS;
if (diff4)
diff3 |= SD_DIFF4;
if (diff3) if (diff3)
diff2 |= SD_DIFF3; diff2 |= SD_DIFF3;
@ -1049,6 +1080,8 @@ static void ArchiveSectors(void)
WRITEUINT8(save_p, diff2); WRITEUINT8(save_p, diff2);
if (diff2 & SD_DIFF3) if (diff2 & SD_DIFF3)
WRITEUINT8(save_p, diff3); WRITEUINT8(save_p, diff3);
if (diff3 & SD_DIFF4)
WRITEUINT8(save_p, diff4);
if (diff & SD_FLOORHT) if (diff & SD_FLOORHT)
WRITEFIXED(save_p, ss->floorheight); WRITEFIXED(save_p, ss->floorheight);
if (diff & SD_CEILHT) if (diff & SD_CEILHT)
@ -1085,6 +1118,28 @@ static void ArchiveSectors(void)
// returns existing index if already added, or appends to net_colormaps and returns new index // returns existing index if already added, or appends to net_colormaps and returns new index
if (diff3 & SD_CRUMBLESTATE) if (diff3 & SD_CRUMBLESTATE)
WRITEINT32(save_p, ss->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 (diff3 & SD_FLAG)
WRITEUINT32(save_p, ss->flags);
if (diff3 & SD_SPECIALFLAG)
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) if (diff & SD_FFLOORS)
ArchiveFFloors(ss); ArchiveFFloors(ss);
} }
@ -1096,7 +1151,7 @@ static void ArchiveSectors(void)
static void UnArchiveSectors(void) static void UnArchiveSectors(void)
{ {
UINT16 i, j; UINT16 i, j;
UINT8 diff, diff2, diff3; UINT8 diff, diff2, diff3, diff4;
for (;;) for (;;)
{ {
i = READUINT16(save_p); i = READUINT16(save_p);
@ -1116,6 +1171,10 @@ static void UnArchiveSectors(void)
diff3 = READUINT8(save_p); diff3 = READUINT8(save_p);
else else
diff3 = 0; diff3 = 0;
if (diff3 & SD_DIFF4)
diff4 = READUINT8(save_p);
else
diff4 = 0;
if (diff & SD_FLOORHT) if (diff & SD_FLOORHT)
sectors[i].floorheight = READFIXED(save_p); sectors[i].floorheight = READFIXED(save_p);
@ -1176,6 +1235,31 @@ static void UnArchiveSectors(void)
sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p)); sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p));
if (diff3 & SD_CRUMBLESTATE) if (diff3 & SD_CRUMBLESTATE)
sectors[i].crumblestate = READINT32(save_p); 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 (diff3 & SD_FLAG)
{
sectors[i].flags = READUINT32(save_p);
CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP);
}
if (diff3 & SD_SPECIALFLAG)
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);
if (diff & SD_FFLOORS) if (diff & SD_FFLOORS)
UnArchiveFFloors(&sectors[i]); UnArchiveFFloors(&sectors[i]);
@ -1986,7 +2070,6 @@ static void SaveEachTimeThinker(const thinker_t *th, const UINT8 type)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
WRITECHAR(save_p, ht->playersInArea[i]); WRITECHAR(save_p, ht->playersInArea[i]);
WRITECHAR(save_p, ht->playersOnArea[i]);
} }
WRITECHAR(save_p, ht->triggerOnExit); WRITECHAR(save_p, ht->triggerOnExit);
} }
@ -2014,14 +2097,12 @@ static void SaveCeilingThinker(const thinker_t *th, const UINT8 type)
WRITEFIXED(save_p, ht->bottomheight); WRITEFIXED(save_p, ht->bottomheight);
WRITEFIXED(save_p, ht->topheight); WRITEFIXED(save_p, ht->topheight);
WRITEFIXED(save_p, ht->speed); WRITEFIXED(save_p, ht->speed);
WRITEFIXED(save_p, ht->oldspeed);
WRITEFIXED(save_p, ht->delay); WRITEFIXED(save_p, ht->delay);
WRITEFIXED(save_p, ht->delaytimer); WRITEFIXED(save_p, ht->delaytimer);
WRITEUINT8(save_p, ht->crush); WRITEUINT8(save_p, ht->crush);
WRITEINT32(save_p, ht->texture); WRITEINT32(save_p, ht->texture);
WRITEINT32(save_p, ht->direction); 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->origspeed);
WRITEFIXED(save_p, ht->sourceline); WRITEFIXED(save_p, ht->sourceline);
} }
@ -2040,6 +2121,8 @@ static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type)
WRITEFIXED(save_p, ht->origspeed); WRITEFIXED(save_p, ht->origspeed);
WRITEFIXED(save_p, ht->delay); WRITEFIXED(save_p, ht->delay);
WRITEFIXED(save_p, ht->delaytimer); 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) static void SaveLightflashThinker(const thinker_t *th, const UINT8 type)
@ -2057,8 +2140,8 @@ static void SaveStrobeThinker(const thinker_t *th, const UINT8 type)
WRITEUINT8(save_p, type); WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector)); WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->count); WRITEINT32(save_p, ht->count);
WRITEINT32(save_p, ht->minlight); WRITEINT16(save_p, ht->minlight);
WRITEINT32(save_p, ht->maxlight); WRITEINT16(save_p, ht->maxlight);
WRITEINT32(save_p, ht->darktime); WRITEINT32(save_p, ht->darktime);
WRITEINT32(save_p, ht->brighttime); WRITEINT32(save_p, ht->brighttime);
} }
@ -2068,10 +2151,10 @@ static void SaveGlowThinker(const thinker_t *th, const UINT8 type)
const glow_t *ht = (const void *)th; const glow_t *ht = (const void *)th;
WRITEUINT8(save_p, type); WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSector(ht->sector)); WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->minlight); WRITEINT16(save_p, ht->minlight);
WRITEINT32(save_p, ht->maxlight); WRITEINT16(save_p, ht->maxlight);
WRITEINT32(save_p, ht->direction); WRITEINT16(save_p, ht->direction);
WRITEINT32(save_p, ht->speed); WRITEINT16(save_p, ht->speed);
} }
static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type) static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type)
@ -2081,8 +2164,8 @@ static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type)
WRITEUINT32(save_p, SaveSector(ht->sector)); WRITEUINT32(save_p, SaveSector(ht->sector));
WRITEINT32(save_p, ht->count); WRITEINT32(save_p, ht->count);
WRITEINT32(save_p, ht->resetcount); WRITEINT32(save_p, ht->resetcount);
WRITEINT32(save_p, ht->maxlight); WRITEINT16(save_p, ht->maxlight);
WRITEINT32(save_p, ht->minlight); WRITEINT16(save_p, ht->minlight);
} }
static void SaveElevatorThinker(const thinker_t *th, const UINT8 type) static void SaveElevatorThinker(const thinker_t *th, const UINT8 type)
@ -2156,13 +2239,9 @@ static inline void SavePusherThinker(const thinker_t *th, const UINT8 type)
const pusher_t *ht = (const void *)th; const pusher_t *ht = (const void *)th;
WRITEUINT8(save_p, type); WRITEUINT8(save_p, type);
WRITEUINT8(save_p, ht->type); WRITEUINT8(save_p, ht->type);
WRITEINT32(save_p, ht->x_mag); WRITEFIXED(save_p, ht->x_mag);
WRITEINT32(save_p, ht->y_mag); WRITEFIXED(save_p, ht->y_mag);
WRITEINT32(save_p, ht->magnitude); WRITEFIXED(save_p, ht->z_mag);
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->affectee);
WRITEUINT8(save_p, ht->roverpusher); WRITEUINT8(save_p, ht->roverpusher);
WRITEINT32(save_p, ht->referrer); WRITEINT32(save_p, ht->referrer);
@ -2260,18 +2339,30 @@ static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type)
WRITEUINT8(save_p, ht->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, type);
WRITEUINT8(save_p, ht->type); WRITEUINT8(save_p, ht->type);
WRITEUINT32(save_p, SaveSlope(ht->slope)); WRITEUINT32(save_p, SaveSlope(ht->slope));
WRITEUINT32(save_p, SaveLine(ht->sourceline)); WRITEUINT32(save_p, SaveLine(ht->sourceline));
WRITEFIXED(save_p, ht->extent); WRITEFIXED(save_p, ht->extent);
}
WRITEMEM(save_p, ht->tags, sizeof(ht->tags)); static inline void SaveDynamicVertexSlopeThinker(const thinker_t *th, const UINT8 type)
WRITEMEM(save_p, ht->vex, sizeof(ht->vex)); {
size_t i;
const dynvertexplanethink_t* ht = (const void*)th;
WRITEUINT8(save_p, type);
WRITEUINT32(save_p, SaveSlope(ht->slope));
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) static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type)
@ -2596,12 +2687,12 @@ static void P_NetArchiveThinkers(void)
} }
else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine) else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine)
{ {
SaveDynamicSlopeThinker(th, tc_dynslopeline); SaveDynamicLineSlopeThinker(th, tc_dynslopeline);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert) else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert)
{ {
SaveDynamicSlopeThinker(th, tc_dynslopevert); SaveDynamicVertexSlopeThinker(th, tc_dynslopevert);
continue; continue;
} }
#ifdef PARANOIA #ifdef PARANOIA
@ -2716,7 +2807,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
{ {
UINT16 spawnpointnum = READUINT16(save_p); 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]); P_SpawnHoop(&mapthings[spawnpointnum]);
return NULL; return NULL;
@ -3093,7 +3184,6 @@ static thinker_t* LoadEachTimeThinker(actionf_p1 thinker)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
ht->playersInArea[i] = READCHAR(save_p); ht->playersInArea[i] = READCHAR(save_p);
ht->playersOnArea[i] = READCHAR(save_p);
} }
ht->triggerOnExit = READCHAR(save_p); ht->triggerOnExit = READCHAR(save_p);
return &ht->thinker; return &ht->thinker;
@ -3123,14 +3213,12 @@ static thinker_t* LoadCeilingThinker(actionf_p1 thinker)
ht->bottomheight = READFIXED(save_p); ht->bottomheight = READFIXED(save_p);
ht->topheight = READFIXED(save_p); ht->topheight = READFIXED(save_p);
ht->speed = READFIXED(save_p); ht->speed = READFIXED(save_p);
ht->oldspeed = READFIXED(save_p);
ht->delay = READFIXED(save_p); ht->delay = READFIXED(save_p);
ht->delaytimer = READFIXED(save_p); ht->delaytimer = READFIXED(save_p);
ht->crush = READUINT8(save_p); ht->crush = READUINT8(save_p);
ht->texture = READINT32(save_p); ht->texture = READINT32(save_p);
ht->direction = 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->origspeed = READFIXED(save_p);
ht->sourceline = READFIXED(save_p); ht->sourceline = READFIXED(save_p);
if (ht->sector) if (ht->sector)
@ -3152,6 +3240,8 @@ static thinker_t* LoadFloormoveThinker(actionf_p1 thinker)
ht->origspeed = READFIXED(save_p); ht->origspeed = READFIXED(save_p);
ht->delay = READFIXED(save_p); ht->delay = READFIXED(save_p);
ht->delaytimer = READFIXED(save_p); ht->delaytimer = READFIXED(save_p);
ht->tag = READINT16(save_p);
ht->sourceline = READFIXED(save_p);
if (ht->sector) if (ht->sector)
ht->sector->floordata = ht; ht->sector->floordata = ht;
return &ht->thinker; return &ht->thinker;
@ -3175,8 +3265,8 @@ static thinker_t* LoadStrobeThinker(actionf_p1 thinker)
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(READUINT32(save_p));
ht->count = READINT32(save_p); ht->count = READINT32(save_p);
ht->minlight = READINT32(save_p); ht->minlight = READINT16(save_p);
ht->maxlight = READINT32(save_p); ht->maxlight = READINT16(save_p);
ht->darktime = READINT32(save_p); ht->darktime = READINT32(save_p);
ht->brighttime = READINT32(save_p); ht->brighttime = READINT32(save_p);
if (ht->sector) if (ht->sector)
@ -3189,10 +3279,10 @@ static thinker_t* LoadGlowThinker(actionf_p1 thinker)
glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(READUINT32(save_p));
ht->minlight = READINT32(save_p); ht->minlight = READINT16(save_p);
ht->maxlight = READINT32(save_p); ht->maxlight = READINT16(save_p);
ht->direction = READINT32(save_p); ht->direction = READINT16(save_p);
ht->speed = READINT32(save_p); ht->speed = READINT16(save_p);
if (ht->sector) if (ht->sector)
ht->sector->lightingdata = ht; ht->sector->lightingdata = ht;
return &ht->thinker; return &ht->thinker;
@ -3205,8 +3295,8 @@ static thinker_t* LoadFireflickerThinker(actionf_p1 thinker)
ht->sector = LoadSector(READUINT32(save_p)); ht->sector = LoadSector(READUINT32(save_p));
ht->count = READINT32(save_p); ht->count = READINT32(save_p);
ht->resetcount = READINT32(save_p); ht->resetcount = READINT32(save_p);
ht->maxlight = READINT32(save_p); ht->maxlight = READINT16(save_p);
ht->minlight = READINT32(save_p); ht->minlight = READINT16(save_p);
if (ht->sector) if (ht->sector)
ht->sector->lightingdata = ht; ht->sector->lightingdata = ht;
return &ht->thinker; return &ht->thinker;
@ -3298,19 +3388,14 @@ static thinker_t* LoadPusherThinker(actionf_p1 thinker)
pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker; ht->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p); ht->type = READUINT8(save_p);
ht->x_mag = READINT32(save_p); ht->x_mag = READFIXED(save_p);
ht->y_mag = READINT32(save_p); ht->y_mag = READFIXED(save_p);
ht->magnitude = READINT32(save_p); ht->z_mag = READFIXED(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->affectee = READINT32(save_p);
ht->roverpusher = READUINT8(save_p); ht->roverpusher = READUINT8(save_p);
ht->referrer = READINT32(save_p); ht->referrer = READINT32(save_p);
ht->exclusive = READINT32(save_p); ht->exclusive = READINT32(save_p);
ht->slider = READINT32(save_p); ht->slider = READINT32(save_p);
ht->source = P_GetPushThing(ht->affectee);
return &ht->thinker; return &ht->thinker;
} }
@ -3434,17 +3519,31 @@ static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker)
return &ht->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->thinker.function.acp1 = thinker;
ht->type = READUINT8(save_p); ht->type = READUINT8(save_p);
ht->slope = LoadSlope(READUINT32(save_p)); ht->slope = LoadSlope(READUINT32(save_p));
ht->sourceline = LoadLine(READUINT32(save_p)); ht->sourceline = LoadLine(READUINT32(save_p));
ht->extent = READFIXED(save_p); ht->extent = READFIXED(save_p);
READMEM(save_p, ht->tags, sizeof(ht->tags)); return &ht->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));
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->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; return &ht->thinker;
} }
@ -3757,11 +3856,11 @@ static void P_NetUnArchiveThinkers(void)
break; break;
case tc_dynslopeline: case tc_dynslopeline:
th = LoadDynamicSlopeThinker((actionf_p1)T_DynamicSlopeLine); th = LoadDynamicLineSlopeThinker((actionf_p1)T_DynamicSlopeLine);
break; break;
case tc_dynslopevert: case tc_dynslopevert:
th = LoadDynamicSlopeThinker((actionf_p1)T_DynamicSlopeVert); th = LoadDynamicVertexSlopeThinker((actionf_p1)T_DynamicSlopeVert);
break; break;
case tc_scroll: case tc_scroll:

File diff suppressed because it is too large Load diff

View file

@ -107,7 +107,7 @@ boolean P_AddFolder(const char *folderpath);
boolean P_RunSOC(const char *socfilename); boolean P_RunSOC(const char *socfilename);
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
void P_LoadMusicsRange(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); size_t P_PrecacheLevelFlats(void);
void P_AllocMapHeader(INT16 i); void P_AllocMapHeader(INT16 i);

View file

@ -122,7 +122,7 @@ static void ReconfigureViaConstants (pslope_t *slope, const fixed_t a, const fix
} }
/// Recalculate dynamic slopes. /// Recalculate dynamic slopes.
void T_DynamicSlopeLine (dynplanethink_t* th) void T_DynamicSlopeLine (dynlineplanethink_t* th)
{ {
pslope_t* slope = th->slope; pslope_t* slope = th->slope;
line_t* srcline = th->sourceline; line_t* srcline = th->sourceline;
@ -162,50 +162,59 @@ void T_DynamicSlopeLine (dynplanethink_t* th)
} }
/// Mapthing-defined /// Mapthing-defined
void T_DynamicSlopeVert (dynplanethink_t* th) void T_DynamicSlopeVert (dynvertexplanethink_t* th)
{ {
pslope_t* slope = th->slope;
size_t i; size_t i;
INT32 l;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++)
l = Tag_FindLineSpecial(799, th->tags[i]); {
if (l != -1) { if (th->relative & (1 << i))
th->vex[i].z = lines[l].frontsector->floorheight; th->vex[i].z = th->origvecheights[i] + (th->secs[i]->floorheight - th->origsecheights[i]);
}
else 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_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); dynlineplanethink_t* th = Z_Calloc(sizeof (*th), PU_LEVSPEC, NULL);
switch (type) th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeLine;
{
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;
}
th->slope = slope; th->slope = slope;
th->type = type; th->type = type;
th->sourceline = sourceline;
th->extent = extent;
P_AddThinker(THINK_DYNSLOPE, &th->thinker); P_AddThinker(THINK_DYNSLOPE, &th->thinker);
// interpolation // interpolation
R_CreateInterpolator_DynSlope(&th->thinker, slope); R_CreateInterpolator_DynSlope(&th->thinker, slope);
} }
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;
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<<i;
}
P_AddThinker(THINK_DYNSLOPE, &th->thinker);
}
/// Create a new slope and add it to the slope list. /// Create a new slope and add it to the slope list.
static inline pslope_t* Slope_Add (const UINT8 flags) static inline pslope_t* Slope_Add (const UINT8 flags)
@ -272,6 +281,27 @@ static fixed_t GetExtent(sector_t *sector, line_t *line)
return fardist; 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. /// 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) static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
{ {
@ -362,7 +392,7 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
P_CalculateSlopeNormal(fslope); P_CalculateSlopeNormal(fslope);
if (spawnthinker && (flags & SL_DYNAMIC)) if (spawnthinker && (flags & SL_DYNAMIC))
P_AddDynSlopeThinker(fslope, DP_FRONTFLOOR, line, extent, NULL, NULL); P_AddDynLineSlopeThinker(fslope, DP_FRONTFLOOR, line, extent);
} }
if(frontceil) if(frontceil)
{ {
@ -379,7 +409,7 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
P_CalculateSlopeNormal(cslope); P_CalculateSlopeNormal(cslope);
if (spawnthinker && (flags & SL_DYNAMIC)) if (spawnthinker && (flags & SL_DYNAMIC))
P_AddDynSlopeThinker(cslope, DP_FRONTCEIL, line, extent, NULL, NULL); P_AddDynLineSlopeThinker(cslope, DP_FRONTCEIL, line, extent);
} }
} }
if(backfloor || backceil) if(backfloor || backceil)
@ -419,7 +449,7 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
P_CalculateSlopeNormal(fslope); P_CalculateSlopeNormal(fslope);
if (spawnthinker && (flags & SL_DYNAMIC)) if (spawnthinker && (flags & SL_DYNAMIC))
P_AddDynSlopeThinker(fslope, DP_BACKFLOOR, line, extent, NULL, NULL); P_AddDynLineSlopeThinker(fslope, DP_BACKFLOOR, line, extent);
} }
if(backceil) if(backceil)
{ {
@ -436,9 +466,26 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
P_CalculateSlopeNormal(cslope); P_CalculateSlopeNormal(cslope);
if (spawnthinker && (flags & SL_DYNAMIC)) if (spawnthinker && (flags & SL_DYNAMIC))
P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL); 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 /// Creates a new slope from three mapthings with the specified IDs
@ -473,14 +520,14 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
vx[i].x = mt->x << FRACBITS; vx[i].x = mt->x << FRACBITS;
vx[i].y = mt->y << FRACBITS; vx[i].y = mt->y << FRACBITS;
vx[i].z = mt->z << 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; vx[i].z += R_PointInSubsector(vx[i].x, vx[i].y)->sector->floorheight;
} }
ReconfigureViaVertexes(ret, vx[0], vx[1], vx[2]); ReconfigureViaVertexes(ret, vx[0], vx[1], vx[2]);
if (spawnthinker && (flags & SL_DYNAMIC)) if (spawnthinker && (flags & SL_DYNAMIC))
P_AddDynSlopeThinker(ret, DP_VERTEX, NULL, 0, tags, vx); P_AddDynVertexSlopeThinker(ret, tags, vx);
return ret; return ret;
} }
@ -595,27 +642,6 @@ static boolean P_SetSlopeFromTag(sector_t *sec, INT32 tag, boolean ceiling)
return false; 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 // P_CopySectorSlope
// //
@ -705,9 +731,6 @@ void P_SpawnSlopes(const boolean fromsave) {
for (i = 0; i < numlines; i++) for (i = 0; i < numlines; i++)
switch (lines[i].special) switch (lines[i].special)
{ {
case 700:
if (lines[i].flags & ML_TFERLINE) P_CopySectorSlope(&lines[i]);
break;
case 720: case 720:
P_CopySectorSlope(&lines[i]); P_CopySectorSlope(&lines[i]);
default: default:

View file

@ -44,7 +44,8 @@ typedef enum
typedef enum typedef enum
{ {
TMSL_NOPHYSICS = 1, TMSL_NOPHYSICS = 1,
TMSL_DYNAMIC = 2, TMSL_DYNAMIC = 1<<1,
TMSL_COPY = 1<<2,
} textmapslopeflags_t; } textmapslopeflags_t;
void P_LinkSlopeThinkers (void); void P_LinkSlopeThinkers (void);
@ -95,26 +96,29 @@ typedef enum {
DP_FRONTCEIL, DP_FRONTCEIL,
DP_BACKFLOOR, DP_BACKFLOOR,
DP_BACKCEIL, DP_BACKCEIL,
DP_VERTEX
} dynplanetype_t; } dynplanetype_t;
/// Permit slopes to be dynamically altered through a thinker. /// Permit slopes to be dynamically altered through a thinker.
typedef struct typedef struct
{ {
thinker_t thinker; thinker_t thinker;
pslope_t *slope;
pslope_t* slope;
dynplanetype_t type; dynplanetype_t type;
line_t *sourceline;
// Used by line slopes.
line_t* sourceline;
fixed_t extent; fixed_t extent;
} dynlineplanethink_t;
// Used by mapthing vertex slopes. typedef struct
INT16 tags[3]; {
thinker_t thinker;
pslope_t *slope;
sector_t *secs[3];
vector3_t vex[3]; vector3_t vex[3];
} dynplanethink_t; fixed_t origsecheights[3];
fixed_t origvecheights[3];
UINT8 relative;
} dynvertexplanethink_t;
void T_DynamicSlopeLine (dynplanethink_t* th); void T_DynamicSlopeLine (dynlineplanethink_t* th);
void T_DynamicSlopeVert (dynplanethink_t* th); void T_DynamicSlopeVert (dynvertexplanethink_t* th);
#endif // #ifndef P_SLOPES_H__ #endif // #ifndef P_SLOPES_H__

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,449 @@ 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 *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs
extern mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint 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
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;
typedef enum
{
TMDA_BOTTOMOFFSET = 1,
TMDA_BOTTOM = 1<<1,
TMDA_MIDDLE = 1<<2,
TMDA_TOP = 1<<3,
} textmapdronealignment_t;
typedef enum
{
TMSF_RETRACTED = 1,
TMSF_INTANGIBLE = 1<<1,
} textmapspikeflags_t;
typedef enum
{
TMFF_AIMLESS = 1,
TMFF_STATIONARY = 1<<1,
TMFF_HOP = 1<<2,
} textmapflickyflags_t;
typedef enum
{
TMFH_NOFLAME = 1,
TMFH_CORONA = 1<<1,
} textmapflameholderflags_t;
typedef enum
{
TMDS_NOGRAVITY = 1,
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;
typedef enum
{
TMNI_BONUSONLY = 1,
TMNI_REVEAL = 1<<1,
} textmapnightsitem_t;
typedef enum
{
TMP_NORMAL = 0,
TMP_SLIDE = 1,
TMP_IMMOVABLE = 2,
TMP_CLASSIC = 3,
} textmappushabletype_t;
typedef enum
{
TMED_NONE = 0,
TMED_RIGHT = 1,
TMED_LEFT = 2,
} textmapeggrobodirection_t;
typedef enum
{
TMMR_SAME = 0,
TMMR_WEAK = 1,
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;
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
{
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
{
TMFT_INTANGIBLETOP = 1,
TMFT_INTANGIBLEBOTTOM = 1<<1,
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
{
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
{
TMFB_REVERSE = 1,
TMFB_SPINDASH = 1<<1,
TMFB_DYNAMIC = 1<<2,
} textmapfofbobbing_t;
typedef enum
{
TMFC_NOSHADE = 1,
TMFC_NORETURN = 1<<1,
TMFC_AIRBOB = 1<<2,
TMFC_FLOATBOB = 1<<3,
TMFC_SPLAT = 1<<4,
} textmapfofcrumbling_t;
typedef enum
{
TMFR_REVERSE = 1,
TMFR_SPINDASH = 1<<1,
} textmapfofrising_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,
TMFB_SPLAT = 1<<3,
} textmapfofbustflags_t;
typedef enum
{
TMFL_NOBOSSES = 1,
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
{
TMXT_CONTINUOUS = 0,
TMXT_EACHTIMEMASK = TMXT_CONTINUOUS,
TMXT_EACHTIMEENTER = 1,
TMXT_EACHTIMEENTERANDEXIT = 2,
} textmapxtriggertype_t;
typedef enum
{
TMF_HASALL = 0,
TMF_HASANY = 1,
TMF_HASEXACTLY = 2,
TMF_DOESNTHAVEALL = 3,
TMF_DOESNTHAVEANY = 4,
} textmapflagcheck_t;
typedef enum
{
TMT_RED = 0,
TMT_BLUE = 1,
} textmapteam_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,
TMP_CEILING = 1,
TMP_BOTH = 2,
} textmapplanes_t;
typedef enum
{
TMT_ADD = 0,
TMT_REMOVE = 1,
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
{
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,
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,
TML_FLOOR = 1,
TML_CEILING = 2,
} textmaplightareas_t;
typedef enum
{
TMLC_NOSECTOR = 1,
TMLC_NOFLOOR = 1<<1,
TMLC_NOCEILING = 1<<2,
} textmaplightcopyflags_t;
typedef enum
{
TMF_RELATIVE = 1,
TMF_OVERRIDE = 1<<1,
TMF_TICBASED = 1<<2,
} textmapfadeflags_t;
typedef enum
{
TMB_USETARGET = 1,
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,
TMS_CENTERPOINT = 1,
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
{
TMF_NOCHANGE = 0,
TMF_ADD = 1,
TMF_REMOVE = 2,
} textmapsetflagflags_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_NONEXCLUSIVE = 4,
} textmapscrolltype_t;
typedef enum
{
TMPF_SLIDE = 1,
TMPF_NONEXCLUSIVE = 1<<1,
} textmappusherflags_t;
typedef enum
{
TMPP_NOZFADE = 1,
TMPP_PUSHZ = 1<<1,
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) // GETSECSPECIAL (specialval, section)
// //
// Pulls out the special # from a particular section. // Pulls out the special # from a particular section.
@ -38,12 +481,21 @@ void P_SetupLevelFlatAnims(void);
// at map load // at map load
void P_InitSpecials(void); 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); void P_SpawnSpecials(boolean fromnetsave);
// every tic // every tic
void P_UpdateSpecials(void); 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_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_PlayerInSpecialSector(player_t *player);
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);
void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector); void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector);
fixed_t P_FindLowestFloorSurrounding(sector_t *sec); fixed_t P_FindLowestFloorSurrounding(sector_t *sec);
@ -60,6 +512,10 @@ INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max);
void P_SetupSignExit(player_t *player); void P_SetupSignExit(player_t *player);
boolean P_IsFlagAtBase(mobjtype_t flag); 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); void P_SwitchWeather(INT32 weathernum);
boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller); boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller);
@ -72,6 +528,12 @@ void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean e
UINT16 P_GetFFloorID(ffloor_t *fflr); UINT16 P_GetFFloorID(ffloor_t *fflr);
ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id); 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 // P_LIGHTS
// //
@ -83,8 +545,8 @@ typedef struct
sector_t *sector; ///< The sector where action is taking place. sector_t *sector; ///< The sector where action is taking place.
INT32 count; INT32 count;
INT32 resetcount; INT32 resetcount;
INT32 maxlight; ///< The brightest light level to use. INT16 maxlight; ///< The brightest light level to use.
INT32 minlight; ///< The darkest light level to use. INT16 minlight; ///< The darkest light level to use.
} fireflicker_t; } fireflicker_t;
typedef struct typedef struct
@ -112,8 +574,8 @@ typedef struct
thinker_t thinker; ///< The thinker in use for the effect. thinker_t thinker; ///< The thinker in use for the effect.
sector_t *sector; ///< The sector where the action is taking place. sector_t *sector; ///< The sector where the action is taking place.
INT32 count; INT32 count;
INT32 minlight; ///< The minimum light level to use. INT16 minlight; ///< The minimum light level to use.
INT32 maxlight; ///< The maximum light level to use. INT16 maxlight; ///< The maximum light level to use.
INT32 darktime; ///< How INT32 to use minlight. INT32 darktime; ///< How INT32 to use minlight.
INT32 brighttime; ///< How INT32 to use maxlight. INT32 brighttime; ///< How INT32 to use maxlight.
} strobe_t; } strobe_t;
@ -122,10 +584,10 @@ typedef struct
{ {
thinker_t thinker; thinker_t thinker;
sector_t *sector; sector_t *sector;
INT32 minlight; INT16 minlight;
INT32 maxlight; INT16 maxlight;
INT32 direction; INT16 direction;
INT32 speed; INT16 speed;
} glow_t; } glow_t;
/** Thinker struct for fading lights. /** Thinker struct for fading lights.
@ -151,18 +613,18 @@ typedef struct
void P_RemoveLighting(sector_t *sector); void P_RemoveLighting(sector_t *sector);
void T_FireFlicker(fireflicker_t *flick); 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_LightningFlash(lightflash_t *flash);
void T_StrobeFlash(strobe_t *flash); void T_StrobeFlash(strobe_t *flash);
void P_SpawnLightningFlash(sector_t *sector); 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); 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_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); void T_LightFade(lightlevel_t *ll);
typedef enum typedef enum
@ -178,22 +640,19 @@ typedef enum
typedef enum typedef enum
{ {
raiseToHighest, raiseToHighest,
lowerToLowest,
raiseToLowest,
lowerToLowestFast, lowerToLowestFast,
instantRaise, // instant-move for ceilings instantRaise, // instant-move for ceilings
lowerAndCrush,
crushAndRaise, crushAndRaise,
fastCrushAndRaise, raiseAndCrush,
crushCeilOnce, crushCeilOnce,
crushBothOnce, crushBothOnce,
moveCeilingByFrontSector, moveCeilingByFrontSector,
instantMoveCeilingByFrontSector, instantMoveCeilingByFrontSector,
moveCeilingByFrontTexture, moveCeilingByDistance,
bounceCeiling, bounceCeiling,
bounceCeilingCrush, bounceCeilingCrush,
@ -209,7 +668,6 @@ typedef struct
fixed_t bottomheight; ///< The lowest height to move to. fixed_t bottomheight; ///< The lowest height to move to.
fixed_t topheight; ///< The highest height to move to. fixed_t topheight; ///< The highest height to move to.
fixed_t speed; ///< Ceiling speed. fixed_t speed; ///< Ceiling speed.
fixed_t oldspeed;
fixed_t delay; fixed_t delay;
fixed_t delaytimer; fixed_t delaytimer;
UINT8 crush; ///< Whether to crush things or not. UINT8 crush; ///< Whether to crush things or not.
@ -218,17 +676,16 @@ typedef struct
INT32 direction; ///< 1 = up, 0 = waiting, -1 = down. INT32 direction; ///< 1 = up, 0 = waiting, -1 = down.
// ID // ID
INT32 tag; INT16 tag; ///< Tag of linedef executor to run when movement is done.
INT32 olddirection;
fixed_t origspeed; ///< The original, "real" speed. fixed_t origspeed; ///< The original, "real" speed.
INT32 sourceline; ///< Index of the source linedef INT32 sourceline; ///< Index of the source linedef
} ceiling_t; } ceiling_t;
#define CEILSPEED (FRACUNIT) #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_CrushCeiling(ceiling_t *ceiling);
void T_MoveCeiling(ceiling_t *ceiling); void T_MoveCeiling(ceiling_t *ceiling);
@ -238,9 +695,6 @@ void T_MoveCeiling(ceiling_t *ceiling);
// //
typedef enum typedef enum
{ {
// lower floor to lowest surrounding floor
lowerFloorToLowest,
// raise floor to next highest surrounding floor // raise floor to next highest surrounding floor
raiseFloorToNearestFast, raiseFloorToNearestFast,
@ -250,7 +704,7 @@ typedef enum
moveFloorByFrontSector, moveFloorByFrontSector,
instantMoveFloorByFrontSector, instantMoveFloorByFrontSector,
moveFloorByFrontTexture, moveFloorByDistance,
bounceFloor, bounceFloor,
bounceFloorCrush, bounceFloorCrush,
@ -262,7 +716,6 @@ typedef enum
{ {
elevateUp, elevateUp,
elevateDown, elevateDown,
elevateCurrent,
elevateContinuous, elevateContinuous,
elevateBounce, elevateBounce,
elevateHighest, elevateHighest,
@ -282,6 +735,8 @@ typedef struct
fixed_t origspeed; fixed_t origspeed;
fixed_t delay; fixed_t delay;
fixed_t delaytimer; fixed_t delaytimer;
INT16 tag;
INT32 sourceline;
} floormove_t; } floormove_t;
typedef struct typedef struct
@ -403,7 +858,6 @@ typedef struct
thinker_t thinker; thinker_t thinker;
line_t *sourceline; // Source line of the thinker line_t *sourceline; // Source line of the thinker
boolean playersInArea[MAXPLAYERS]; boolean playersInArea[MAXPLAYERS];
boolean playersOnArea[MAXPLAYERS];
boolean triggerOnExit; boolean triggerOnExit;
} eachtime_t; } eachtime_t;
@ -439,8 +893,8 @@ typedef enum
result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crush, result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crush,
boolean ceiling, INT32 direction); boolean ceiling, INT32 direction);
void EV_DoFloor(line_t *line, floor_e floortype); void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype);
void EV_DoElevator(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_CrumbleChain(sector_t *sec, ffloor_t *rover);
void EV_BounceSector(sector_t *sector, fixed_t momz, line_t *sourceline); void EV_BounceSector(sector_t *sector, fixed_t momz, line_t *sourceline);
@ -525,30 +979,20 @@ void T_Friction(friction_t *f);
typedef enum typedef enum
{ {
p_push, ///< Point pusher or puller.
p_wind, ///< Wind. p_wind, ///< Wind.
p_current, ///< Current. p_current, ///< Current.
p_upcurrent, ///< Upwards current.
p_downcurrent, ///< Downwards current.
p_upwind, ///< Upwards wind.
p_downwind ///< Downwards wind.
} pushertype_e; } pushertype_e;
// Model for pushers for push/pull effects // Model for pushers for push/pull effects
typedef struct typedef struct
{ {
thinker_t thinker; ///< Thinker structure for push/pull effect. thinker_t thinker; ///< Thinker structure for pusher effect.
/** Types of push/pull effects. pushertype_e type; ///< Type of pusher effect.
*/ fixed_t x_mag; ///< X strength.
pushertype_e type; ///< Type of push/pull effect. fixed_t y_mag; ///< Y strength.
mobj_t *source; ///< Point source if point pusher/puller. fixed_t z_mag; ///< Z strength.
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.
INT32 affectee; ///< Number of affected sector. 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 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 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? INT32 slider; /// < Should the player go into an uncontrollable slide?
@ -610,9 +1054,8 @@ typedef struct
void T_FadeColormap(fadecolormap_t *d); void T_FadeColormap(fadecolormap_t *d);
// Prototype functions for pushers // Prototype function for pushers
void T_Pusher(pusher_t *p); void T_Pusher(pusher_t *p);
mobj_t *P_GetPushThing(UINT32 s);
// Plane displacement // Plane displacement
typedef struct typedef struct
@ -637,6 +1080,4 @@ void T_PlaneDisplace(planedisplace_t *pd);
void P_CalcHeight(player_t *player); void P_CalcHeight(player_t *player);
sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo);
#endif #endif

View file

@ -707,8 +707,7 @@ static void P_DeNightserizePlayer(player_t *player)
// If you screwed up, kiss your score and ring bonus goodbye. // 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. // But only do this in special stage (and instakill!) In regular stages, wait til we hit the ground.
player->marescore = player->spheres =\ player->marescore = player->spheres = player->rings = 0;
player->rings = 0;
} }
// Check to see if the player should be killed. // Check to see if the player should be killed.
@ -718,13 +717,12 @@ static void P_DeNightserizePlayer(player_t *player)
continue; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (!(mo2->type == MT_NIGHTSDRONE)) if (mo2->type != MT_NIGHTSDRONE)
continue; continue;
if (mo2->flags2 & MF2_AMBUSH) if (mo2->flags2 & MF2_AMBUSH)
{ {
player->marescore = player->spheres =\ player->marescore = player->spheres = player->rings = 0;
player->rings = 0;
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL);
// Reset music to beginning if MIXNIGHTSCOUNTDOWN // Reset music to beginning if MIXNIGHTSCOUNTDOWN
@ -778,7 +776,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
UINT8 oldmare, oldmarelap, oldmarebonuslap; UINT8 oldmare, oldmarelap, oldmarebonuslap;
// Bots can't be NiGHTSerized, silly!1 :P // Bots can't be NiGHTSerized, silly!1 :P
if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) if (player->bot)
return; return;
if (player->powers[pw_carry] != CR_NIGHTSMODE) if (player->powers[pw_carry] != CR_NIGHTSMODE)
@ -970,9 +968,6 @@ pflags_t P_GetJumpFlags(player_t *player)
// //
boolean P_PlayerInPain(player_t *player) boolean P_PlayerInPain(player_t *player)
{ {
// If the player doesn't have a mobj, it can't be in pain.
if (!player->mo)
return false;
// no silly, sliding isn't pain // no silly, sliding isn't pain
if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]) if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing])
return true; return true;
@ -1239,8 +1234,8 @@ void P_GivePlayerSpheres(player_t *player, INT32 num_spheres)
if (!player) if (!player)
return; return;
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader) if (player->bot)
player = player->botleader; player = &players[consoleplayer];
if (!player->mo) if (!player->mo)
return; return;
@ -1266,8 +1261,8 @@ void P_GivePlayerLives(player_t *player, INT32 numlives)
if (!player) if (!player)
return; return;
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader) if (player->bot)
player = player->botleader; player = &players[consoleplayer];
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ {
@ -1733,89 +1728,6 @@ boolean P_IsObjectOnGround(mobj_t *mo)
return false; 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 // P_SetObjectMomZ
// //
@ -2292,13 +2204,12 @@ void P_DoPlayerExit(player_t *player)
P_RestoreMusic(player); P_RestoreMusic(player);
} }
#define SPACESPECIAL 12
boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space
{ {
sector_t *sector = mo->subsector->sector; sector_t *sector = mo->subsector->sector;
fixed_t topheight, bottomheight; fixed_t topheight, bottomheight;
if (GETSECSPECIAL(sector->special, 1) == SPACESPECIAL) if (sector->specialflags & SSF_OUTERSPACE)
return true; return true;
if (sector->ffloors) if (sector->ffloors)
@ -2310,7 +2221,7 @@ boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space
if (!(rover->flags & FF_EXISTS)) if (!(rover->flags & FF_EXISTS))
continue; continue;
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != SPACESPECIAL) if (!(rover->master->frontsector->specialflags & SSF_OUTERSPACE))
continue; continue;
topheight = P_GetFFloorTopZAt (rover, mo->x, mo->y); topheight = P_GetFFloorTopZAt (rover, mo->x, mo->y);
bottomheight = P_GetFFloorBottomZAt(rover, mo->x, mo->y); bottomheight = P_GetFFloorBottomZAt(rover, mo->x, mo->y);
@ -2593,58 +2504,60 @@ static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover)
/*if (rover->master->frontsector->crumblestate != CRUMBLE_NONE) /*if (rover->master->frontsector->crumblestate != CRUMBLE_NONE)
return false;*/ return false;*/
// If it's an FF_SHATTER, you can break it just by touching it. switch (rover->busttype)
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)
{ {
case BT_TOUCH: // Shatters on contact
return true;
case BT_SPINBUST: // Can be busted by spinning (either from jumping or spindashing)
if ((player->pflags & PF_SPINNING) && !(player->pflags & PF_STARTDASH)) if ((player->pflags & PF_SPINNING) && !(player->pflags & PF_STARTDASH))
return true; return true;
if ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE)) if ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE))
return true; return true;
/* FALLTHRU */
case BT_REGULAR:
// Spinning (and not jumping)
if ((player->pflags & PF_SPINNING) && !(player->pflags & PF_JUMPED))
return true;
// Strong abilities can break even FF_STRONGBUST.
if (player->charflags & SF_CANBUSTWALLS)
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->charflags & SF_CANBUSTWALLS)
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; return false;
} }
@ -2695,7 +2608,7 @@ static void P_CheckBustableBlocks(player_t *player)
} }
// Height checks // Height checks
if (rover->flags & FF_SHATTERBOTTOM) if (rover->bustflags & FB_ONLYBOTTOM)
{ {
if (player->mo->z + player->mo->momz + player->mo->height < bottomheight) if (player->mo->z + player->mo->momz + player->mo->height < bottomheight)
continue; continue;
@ -2703,35 +2616,41 @@ static void P_CheckBustableBlocks(player_t *player)
if (player->mo->z + player->mo->height > bottomheight) if (player->mo->z + player->mo->height > bottomheight)
continue; 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 else
{ {
if (player->mo->z >= topheight) switch (rover->busttype)
continue; {
case BT_TOUCH:
if (player->mo->z + player->mo->momz > topheight)
continue;
if (player->mo->z + player->mo->height < bottomheight) if (player->mo->z + player->mo->momz + player->mo->height < bottomheight)
continue; continue;
break;
case BT_SPINBUST:
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 // 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_SPINBUST)) && player->mo->z >= topheight)
player->mo->momz >>= 1; player->mo->momz >>= 1;
else if (rover->flags & FF_SHATTER) else if (rover->busttype == BT_TOUCH)
{ {
player->mo->momx >>= 1; player->mo->momx >>= 1;
player->mo->momy >>= 1; player->mo->momy >>= 1;
@ -2743,8 +2662,8 @@ static void P_CheckBustableBlocks(player_t *player)
EV_CrumbleChain(NULL, rover); // node->m_sector EV_CrumbleChain(NULL, rover); // node->m_sector
// Run a linedef executor?? // Run a linedef executor??
if (rover->master->flags & ML_EFFECT5) if (rover->bustflags & FB_EXECUTOR)
P_LinedefExecute((INT16)(P_AproxDistance(rover->master->dx, rover->master->dy)>>FRACBITS), player->mo, node->m_sector); P_LinedefExecute(rover->busttag, player->mo, node->m_sector);
goto bustupdone; goto bustupdone;
} }
@ -2789,14 +2708,20 @@ static void P_CheckBouncySectors(player_t *player)
for (rover = node->m_sector->ffloors; rover; rover = rover->next) for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{ {
fixed_t bouncestrength;
fixed_t topheight, bottomheight; fixed_t topheight, bottomheight;
if (!(rover->flags & FF_EXISTS)) if (!(rover->flags & FF_EXISTS))
continue; // FOFs should not be bouncy if they don't even "exist" continue; // FOFs should not be bouncy if they don't even "exist"
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 15) // Handle deprecated bouncy FOF sector type
continue; // this sector type is required for FOFs to be bouncy if (!udmf && GETSECSPECIAL(rover->master->frontsector->special, 1) == 15)
{
rover->flags |= FF_BOUNCY;
rover->bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100;
}
if (!(rover->flags & FF_BOUNCY))
continue;
topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); 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); bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
@ -2807,14 +2732,11 @@ static void P_CheckBouncySectors(player_t *player)
if (player->mo->z + player->mo->height < bottomheight) if (player->mo->z + player->mo->height < bottomheight)
continue; continue;
bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100;
if (oldz < P_GetFOFTopZ(player->mo, node->m_sector, rover, oldx, oldy, NULL) 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)) && 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->momx = -FixedMul(player->mo->momx,rover->bouncestrength);
player->mo->momy = -FixedMul(player->mo->momy,bouncestrength); player->mo->momy = -FixedMul(player->mo->momy,rover->bouncestrength);
} }
else else
{ {
@ -2827,9 +2749,9 @@ static void P_CheckBouncySectors(player_t *player)
if (slope) if (slope)
P_ReverseQuantizeMomentumToSlope(&momentum, slope); P_ReverseQuantizeMomentumToSlope(&momentum, slope);
momentum.z = -FixedMul(momentum.z,bouncestrength)/2; momentum.z = -FixedMul(momentum.z,rover->bouncestrength)/2;
if (abs(momentum.z) < (bouncestrength*2)) if (abs(momentum.z) < (rover->bouncestrength*2))
goto bouncydone; goto bouncydone;
if (momentum.z > FixedMul(24*FRACUNIT, player->mo->scale)) //half of the default player height if (momentum.z > FixedMul(24*FRACUNIT, player->mo->scale)) //half of the default player height
@ -2863,7 +2785,7 @@ bouncydone:
static void P_CheckQuicksand(player_t *player) static void P_CheckQuicksand(player_t *player)
{ {
ffloor_t *rover; ffloor_t *rover;
fixed_t sinkspeed, friction; fixed_t sinkspeed;
fixed_t topheight, bottomheight; fixed_t topheight, bottomheight;
if (!(player->mo->subsector->sector->ffloors && player->mo->momz <= 0)) if (!(player->mo->subsector->sector->ffloors && player->mo->momz <= 0))
@ -2881,9 +2803,7 @@ static void P_CheckQuicksand(player_t *player)
if (topheight >= player->mo->z && bottomheight < player->mo->z + player->mo->height) if (topheight >= player->mo->z && bottomheight < player->mo->z + player->mo->height)
{ {
sinkspeed = abs(rover->master->v1->x - rover->master->v2->x)>>1; sinkspeed = FixedDiv(rover->sinkspeed,TICRATE*FRACUNIT);
sinkspeed = FixedDiv(sinkspeed,TICRATE*FRACUNIT);
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
{ {
@ -2910,10 +2830,8 @@ static void P_CheckQuicksand(player_t *player)
P_PlayerHitFloor(player, false); P_PlayerHitFloor(player, false);
} }
friction = abs(rover->master->v1->y - rover->master->v2->y)>>6; player->mo->momx = FixedMul(player->mo->momx, rover->friction);
player->mo->momy = FixedMul(player->mo->momy, rover->friction);
player->mo->momx = FixedMul(player->mo->momx, friction);
player->mo->momy = FixedMul(player->mo->momy, friction);
} }
} }
} }
@ -4797,7 +4715,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
if (onground && player->pflags & PF_SPINNING && !(player->pflags & PF_STARTDASH) if (onground && player->pflags & PF_SPINNING && !(player->pflags & PF_STARTDASH)
&& player->speed < 5*player->mo->scale && canstand) && 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); P_InstaThrust(player->mo, player->mo->angle, 10*player->mo->scale);
else else
{ {
@ -5691,6 +5609,22 @@ INT32 P_GetPlayerControlDirection(player_t *player)
return 1; // Controls pointing in player's general direction 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. // Control scheme for 2d levels.
static void P_2dMovement(player_t *player) static void P_2dMovement(player_t *player)
{ {
@ -5725,16 +5659,7 @@ static void P_2dMovement(player_t *player)
} }
} }
// cmomx/cmomy stands for the conveyor belt speed. if (P_ShouldResetConveyorMomentum(player))
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)
player->cmomx = player->cmomy = 0; player->cmomx = player->cmomy = 0;
player->rmomx = player->mo->momx - player->cmomx; player->rmomx = player->mo->momx - player->cmomx;
@ -5917,16 +5842,7 @@ static void P_3dMovement(player_t *player)
} }
movepushsideangle = movepushangle-ANGLE_90; movepushsideangle = movepushangle-ANGLE_90;
// cmomx/cmomy stands for the conveyor belt speed. if (P_ShouldResetConveyorMomentum(player))
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)
player->cmomx = player->cmomy = 0; player->cmomx = player->cmomy = 0;
player->rmomx = player->mo->momx - player->cmomx; player->rmomx = player->mo->momx - player->cmomx;
@ -7639,8 +7555,8 @@ static void P_NiGHTSMovement(player_t *player)
} }
} }
if (objectplacing) //if (objectplacing)
OP_NightsObjectplace(player); // OP_NightsObjectplace(player);
} }
// May be used in future for CTF // May be used in future for CTF
@ -8701,7 +8617,7 @@ void P_MovePlayer(player_t *player)
#endif #endif
// Look for blocks to bust up // 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 // not just when spinning or playing as Knuckles
if (CheckForBustableBlocks) if (CheckForBustableBlocks)
P_CheckBustableBlocks(player); P_CheckBustableBlocks(player);
@ -10165,7 +10081,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
for (rover = newsubsec->sector->ffloors; rover; rover = rover->next) for (rover = newsubsec->sector->ffloors; rover; rover = rover->next)
{ {
fixed_t topheight, bottomheight; 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; continue;
topheight = P_CameraGetFOFTopZ(thiscam, newsubsec->sector, rover, midx, midy, NULL); topheight = P_CameraGetFOFTopZ(thiscam, newsubsec->sector, rover, midx, midy, NULL);
@ -10229,7 +10145,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
// We're inside it! Yess... // We're inside it! Yess...
polysec = po->lines[0]->backsector; polysec = po->lines[0]->backsector;
if (GETSECSPECIAL(polysec->special, 4) == 12) if (polysec->flags & MSF_NOCLIPCAMERA)
{ // Camera noclip polyobj. { // Camera noclip polyobj.
plink = (polymaplink_t *)(plink->link.next); plink = (polymaplink_t *)(plink->link.next);
continue; continue;
@ -10291,7 +10207,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
for (rover = newsubsec->sector->ffloors; rover; rover = rover->next) for (rover = newsubsec->sector->ffloors; rover; rover = rover->next)
{ {
fixed_t topheight, bottomheight; 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); topheight = P_CameraGetFOFTopZ(thiscam, newsubsec->sector, rover, midx, midy, NULL);
bottomheight = P_CameraGetFOFBottomZ(thiscam, newsubsec->sector, rover, midx, midy, NULL); bottomheight = P_CameraGetFOFBottomZ(thiscam, newsubsec->sector, rover, midx, midy, NULL);
@ -10367,7 +10283,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
thiscam->momx = FixedMul(x - thiscam->x, camspeed); thiscam->momx = FixedMul(x - thiscam->x, camspeed);
thiscam->momy = FixedMul(y - thiscam->y, 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 && thiscam->z < thiscam->subsector->sector->floorheight + 256*FRACUNIT
&& FixedMul(z - thiscam->z, camspeed) < 0) && FixedMul(z - thiscam->z, camspeed) < 0)
{ {
@ -10574,7 +10490,6 @@ static void P_CalcPostImg(player_t *player)
postimg_t *type; postimg_t *type;
INT32 *param; INT32 *param;
fixed_t pviewheight; fixed_t pviewheight;
size_t i;
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
pviewheight = player->mo->z + player->mo->height - player->viewheight; pviewheight = player->mo->z + player->mo->height - player->viewheight;
@ -10599,45 +10514,30 @@ static void P_CalcPostImg(player_t *player)
} }
// see if we are in heat (no, not THAT kind of heat...) // 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) ffloor_t *rover;
{ fixed_t topheight;
*type = postimg_heat; fixed_t bottomheight;
break;
}
else if (sector->ffloors)
{
ffloor_t *rover;
fixed_t topheight;
fixed_t bottomheight;
boolean gotres = false;
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; *type = postimg_heat;
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)
break; break;
}
} }
} }
@ -10876,7 +10776,7 @@ static mobj_t *P_LookForRails(mobj_t* mobj, fixed_t c, fixed_t s, angle_t target
fixed_t nx, ny; fixed_t nx, ny;
angle_t nang, dummy, angdiff; angle_t nang, dummy, angdiff;
mobj_t *mark; 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) if (!snax)
return NULL; return NULL;
P_GetAxisPosition(x, y, snax, &nx, &ny, &nang, &dummy); P_GetAxisPosition(x, y, snax, &nx, &ny, &nang, &dummy);
@ -10978,7 +10878,7 @@ static void P_MinecartThink(player_t *player)
// Update axis if the cart is standing on a rail. // Update axis if the cart is standing on a rail.
if (sec && lnum != -1) 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; fixed_t newx, newy;
angle_t targetangle, grind; angle_t targetangle, grind;
angle_t prevangle, angdiff; angle_t prevangle, angdiff;
@ -12360,7 +12260,10 @@ static boolean P_MobjAboveLava(mobj_t *mobj)
for (rover = sector->ffloors; rover; rover = rover->next) 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))
continue;
if (rover->master->frontsector->damagetype != SD_FIRE && rover->master->frontsector->damagetype != SD_LAVA)
continue; continue;
if (mobj->eflags & MFE_VERTICALFLIP) if (mobj->eflags & MFE_VERTICALFLIP)

View file

@ -238,11 +238,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
{ {
if (floorlightlevel) if (floorlightlevel)
*floorlightlevel = sec->floorlightsec == -1 ? *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) if (ceilinglightlevel)
*ceilinglightlevel = sec->ceilinglightsec == -1 ? *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) // if (sec->midmap != -1)
// mapnum = sec->midmap; // mapnum = sec->midmap;
@ -301,11 +301,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
tempsec->lightlevel = s->lightlevel; tempsec->lightlevel = s->lightlevel;
if (floorlightlevel) 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; : sectors[s->floorlightsec].lightlevel;
if (ceilinglightlevel) 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; : sectors[s->ceilinglightsec].lightlevel;
} }
else if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight 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; tempsec->lightlevel = s->lightlevel;
if (floorlightlevel) 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; : sectors[s->floorlightsec].lightlevel;
if (ceilinglightlevel) 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; : sectors[s->ceilinglightsec].lightlevel;
} }
sec = tempsec; 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->ceiling_yoffs == front->ceiling_yoffs
&& back->ceilingpic_angle == front->ceilingpic_angle && back->ceilingpic_angle == front->ceilingpic_angle
// Consider altered lighting. // Consider altered lighting.
&& back->floorlightlevel == front->floorlightlevel
&& back->floorlightabsolute == front->floorlightabsolute
&& back->ceilinglightlevel == front->ceilinglightlevel
&& back->ceilinglightabsolute == front->ceilinglightabsolute
&& back->floorlightsec == front->floorlightsec && back->floorlightsec == front->floorlightsec
&& back->ceilinglightsec == front->ceilinglightsec && back->ceilinglightsec == front->ceilinglightsec
// Consider colormaps // Consider colormaps
@ -889,12 +893,12 @@ static void R_Subsector(size_t num)
} }
light = R_GetPlaneLight(frontsector, floorcenterz, false); light = R_GetPlaneLight(frontsector, floorcenterz, false);
if (frontsector->floorlightsec == -1) if (frontsector->floorlightsec == -1 && !frontsector->floorlightabsolute)
floorlightlevel = *frontsector->lightlist[light].lightlevel; floorlightlevel = max(0, min(255, *frontsector->lightlist[light].lightlevel + frontsector->floorlightlevel));
floorcolormap = *frontsector->lightlist[light].extra_colormap; floorcolormap = *frontsector->lightlist[light].extra_colormap;
light = R_GetPlaneLight(frontsector, ceilingcenterz, false); light = R_GetPlaneLight(frontsector, ceilingcenterz, false);
if (frontsector->ceilinglightsec == -1) if (frontsector->ceilinglightsec == -1 && !frontsector->ceilinglightabsolute)
ceilinglightlevel = *frontsector->lightlist[light].lightlevel; ceilinglightlevel = max(0, min(255, *frontsector->lightlist[light].lightlevel + frontsector->ceilinglightlevel));
ceilingcolormap = *frontsector->lightlist[light].extra_colormap; ceilingcolormap = *frontsector->lightlist[light].extra_colormap;
} }

View file

@ -139,21 +139,34 @@ typedef enum
FF_FLOATBOB = 0x40000, ///< Floats on water and bobs if you step on it. 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_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_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_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_BUSTUP = 0x800000, ///< You can spin through/punch this block and it will crumble!
FF_QUICKSAND = 0x1000000, ///< Quicksand! FF_QUICKSAND = 0x1000000, ///< Quicksand!
FF_PLATFORM = 0x2000000, ///< You can jump up through this to the top. 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_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_INTANGIBLEFLATS = 0x6000000, ///< Both flats are intangible, but the sides are still solid.
FF_SHATTER = 0x8000000, ///< Used with ::FF_BUSTUP. Bustable on mere touch. FF_RIPPLE = 0x8000000, ///< Ripple the flats
FF_SPINBUST = 0x10000000, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames. FF_COLORMAPONLY = 0x10000000, ///< Only copy the colormap, not the lightlevel
FF_STRONGBUST = 0x20000000, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee). FF_BOUNCY = 0x20000000, ///< Bounces players
FF_RIPPLE = 0x40000000, ///< Ripple the flats FF_SPLAT = 0x40000000, ///< Use splat flat renderer (treat cyan pixels as invisible)
FF_COLORMAPONLY = 0x80000000, ///< Only copy the colormap, not the lightlevel
FF_GOOWATER = FF_SHATTERBOTTOM, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop.
} ffloortype_e; } ffloortype_e;
typedef enum
{
FB_PUSHABLES = 0x1, // Bustable by pushables
FB_EXECUTOR = 0x2, // Trigger linedef executor
FB_ONLYBOTTOM = 0x4, // Only bustable from below
} ffloorbustflags_e;
typedef enum
{
BT_TOUCH,
BT_SPINBUST,
BT_REGULAR,
BT_STRONG,
} busttype_e;
typedef struct ffloor_s typedef struct ffloor_s
{ {
fixed_t *topheight; fixed_t *topheight;
@ -187,6 +200,18 @@ typedef struct ffloor_s
UINT8 blend; // blendmode UINT8 blend; // blendmode
tic_t norender; // for culling tic_t norender; // for culling
// Only relevant for FF_BUSTUP
ffloorbustflags_e bustflags;
UINT8 busttype;
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! // these are saved for netgames, so do not let Lua touch these!
ffloortype_e spawnflags; // flags the 3D floor spawned with ffloortype_e spawnflags; // flags the 3D floor spawned with
INT32 spawnalpha; // alpha the 3D floor spawned with INT32 spawnalpha; // alpha the 3D floor spawned with
@ -252,16 +277,68 @@ typedef struct pslope_s
typedef enum typedef enum
{ {
// flipspecial - planes with effect // flipspecial - planes with effect
SF_FLIPSPECIAL_FLOOR = 1, MSF_FLIPSPECIAL_FLOOR = 1,
SF_FLIPSPECIAL_CEILING = 1<<1, MSF_FLIPSPECIAL_CEILING = 1<<1,
SF_FLIPSPECIAL_BOTH = (SF_FLIPSPECIAL_FLOOR|SF_FLIPSPECIAL_CEILING), MSF_FLIPSPECIAL_BOTH = (MSF_FLIPSPECIAL_FLOOR|MSF_FLIPSPECIAL_CEILING),
// triggerspecial - conditions under which plane touch causes effect // triggerspecial - conditions under which plane touch causes effect
SF_TRIGGERSPECIAL_TOUCH = 1<<2, MSF_TRIGGERSPECIAL_TOUCH = 1<<2,
SF_TRIGGERSPECIAL_HEADBUMP = 1<<3, 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 // invertprecip - inverts presence of precipitation
SF_INVERTPRECIP = 1<<4, MSF_INVERTPRECIP = 1<<6,
MSF_GRAVITYFLIP = 1<<7,
MSF_HEATWAVE = 1<<8,
MSF_NOCLIPCAMERA = 1<<9,
} sectorflags_t; } 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
{
SD_NONE = 0,
SD_GENERIC = 1,
SD_WATER = 2,
SD_FIRE = 3,
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
{
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 typedef enum
{ {
@ -313,7 +390,11 @@ typedef struct sector_s
INT32 heightsec; // other sector, or -1 if no other sector INT32 heightsec; // other sector, or -1 if no other sector
INT32 camsec; // used for camera clipping 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 INT32 crumblestate; // used for crumbling and bobbing
// list of mobjs that are at least partially in the sector // list of mobjs that are at least partially in the sector
@ -337,10 +418,18 @@ typedef struct sector_s
extracolormap_t *extra_colormap; extracolormap_t *extra_colormap;
boolean colormap_protected; boolean colormap_protected;
// This points to the master's floorheight, so it can be changed in realtime! fixed_t gravity; // per-sector gravity factor
fixed_t *gravity; // per-sector gravity 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; sectorflags_t flags;
sectorspecialflags_t specialflags;
UINT8 damagetype;
// Linedef executor triggering
mtag_t triggertag; // tag to call upon triggering
UINT8 triggerer; // who can trigger?
fixed_t friction;
// Sprite culling feature // Sprite culling feature
struct line_s *cullheight; struct line_s *cullheight;
@ -377,7 +466,7 @@ typedef enum
#define HORIZONSPECIAL 41 #define HORIZONSPECIAL 41
#define NUMLINEARGS 6 #define NUMLINEARGS 10
#define NUMLINESTRINGARGS 2 #define NUMLINESTRINGARGS 2
typedef struct line_s typedef struct line_s

View file

@ -450,7 +450,7 @@ fixed_t R_ScaleFromGlobalAngle(angle_t visangle)
// R_DoCulling // R_DoCulling
// Checks viewz and top/bottom heights of an item against culling planes // 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! // 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) boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph)
{ {
fixed_t cullplane; fixed_t cullplane;
@ -459,7 +459,7 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe
return false; return false;
cullplane = cullheight->frontsector->floorheight; cullplane = cullheight->frontsector->floorheight;
if (cullheight->flags & ML_NOCLIMB) // Group culling if (cullheight->args[1]) // Group culling
{ {
if (!viewcullheight) if (!viewcullheight)
return false; return false;

View file

@ -852,7 +852,7 @@ void R_DrawSinglePlane(visplane_t *pl)
if (pl->ffloor->flags & FF_TRANSLUCENT) 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 // Hacked up support for alpha value in software mode Tails 09-24-2002
// ...unhacked by toaster 04-01-2021, re-hacked a little by sphere 19-11-2021 // ...unhacked by toaster 04-01-2021, re-hacked a little by sphere 19-11-2021

View file

@ -301,7 +301,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
if (ds->curline->sidedef->repeatcnt) if (ds->curline->sidedef->repeatcnt)
repeats = 1 + 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; fixed_t high, low;
@ -345,7 +345,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{ {
dc_texturemid = ds->maskedtextureheight[dc_x]; dc_texturemid = ds->maskedtextureheight[dc_x];
if (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3)) if (curline->linedef->flags & ML_MIDPEG)
dc_texturemid += (textureheight[texnum])*times + textureheight[texnum]; dc_texturemid += (textureheight[texnum])*times + textureheight[texnum];
else else
dc_texturemid -= (textureheight[texnum])*times; dc_texturemid -= (textureheight[texnum])*times;
@ -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 skewslope = *pfloor->t_slope; // skew using top slope by default
if (newline) if (newline)
{ {
if (newline->flags & ML_DONTPEGTOP) if (newline->flags & ML_SKEWTD)
slopeskew = true; slopeskew = true;
} }
else if (pfloor->master->flags & ML_DONTPEGTOP) else if (pfloor->master->flags & ML_SKEWTD)
slopeskew = true; slopeskew = true;
if (slopeskew) if (slopeskew)
@ -1455,9 +1455,9 @@ static void R_RenderSegLoop (void)
maskedtexturecol[rw_x] = (INT16)texturecolumn; maskedtexturecol[rw_x] = (INT16)texturecolumn;
if (maskedtextureheight != NULL) { if (maskedtextureheight != NULL) {
maskedtextureheight[rw_x] = (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3) ? maskedtextureheight[rw_x] = (curline->linedef->flags & ML_MIDPEG) ?
max(rw_midtexturemid, rw_midtextureback) : max(rw_midtexturemid, rw_midtextureback) :
min(rw_midtexturemid, rw_midtextureback)); min(rw_midtexturemid, rw_midtextureback);
} }
} }
@ -1766,7 +1766,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
texheight = textureheight[midtexture]; texheight = textureheight[midtexture];
// a single sided line is terminal, so it must mark ends // a single sided line is terminal, so it must mark ends
markfloor = markceiling = true; markfloor = markceiling = true;
if (linedef->flags & ML_EFFECT2) { if (linedef->flags & ML_NOSKEW) {
if (linedef->flags & ML_DONTPEGBOTTOM) if (linedef->flags & ML_DONTPEGBOTTOM)
rw_midtexturemid = frontsector->floorheight + texheight - viewz; rw_midtexturemid = frontsector->floorheight + texheight - viewz;
else else
@ -1903,18 +1903,20 @@ void R_StoreWallRange(INT32 start, INT32 stop)
else if (worldlow != worldbottom else if (worldlow != worldbottom
|| worldlowslope != worldbottomslope || worldlowslope != worldbottomslope
|| backsector->f_slope != frontsector->f_slope || backsector->f_slope != frontsector->f_slope
|| backsector->floorpic != frontsector->floorpic || backsector->floorpic != frontsector->floorpic
|| backsector->lightlevel != frontsector->lightlevel || backsector->lightlevel != frontsector->lightlevel
//SoM: 3/22/2000: Check floor x and y offsets. //SoM: 3/22/2000: Check floor x and y offsets.
|| backsector->floor_xoffs != frontsector->floor_xoffs || backsector->floor_xoffs != frontsector->floor_xoffs
|| backsector->floor_yoffs != frontsector->floor_yoffs || backsector->floor_yoffs != frontsector->floor_yoffs
|| backsector->floorpic_angle != frontsector->floorpic_angle || backsector->floorpic_angle != frontsector->floorpic_angle
//SoM: 3/22/2000: Prevents bleeding. //SoM: 3/22/2000: Prevents bleeding.
|| (frontsector->heightsec != -1 && frontsector->floorpic != skyflatnum) || (frontsector->heightsec != -1 && frontsector->floorpic != skyflatnum)
|| backsector->floorlightsec != frontsector->floorlightsec || backsector->floorlightlevel != frontsector->floorlightlevel
//SoM: 4/3/2000: Check for colormaps || backsector->floorlightabsolute != frontsector->floorlightabsolute
|| frontsector->extra_colormap != backsector->extra_colormap || backsector->floorlightsec != frontsector->floorlightsec
|| (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags))) //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; markfloor = true;
} }
@ -1934,18 +1936,20 @@ void R_StoreWallRange(INT32 start, INT32 stop)
else if (worldhigh != worldtop else if (worldhigh != worldtop
|| worldhighslope != worldtopslope || worldhighslope != worldtopslope
|| backsector->c_slope != frontsector->c_slope || backsector->c_slope != frontsector->c_slope
|| backsector->ceilingpic != frontsector->ceilingpic || backsector->ceilingpic != frontsector->ceilingpic
|| backsector->lightlevel != frontsector->lightlevel || backsector->lightlevel != frontsector->lightlevel
//SoM: 3/22/2000: Check floor x and y offsets. //SoM: 3/22/2000: Check floor x and y offsets.
|| backsector->ceiling_xoffs != frontsector->ceiling_xoffs || backsector->ceiling_xoffs != frontsector->ceiling_xoffs
|| backsector->ceiling_yoffs != frontsector->ceiling_yoffs || backsector->ceiling_yoffs != frontsector->ceiling_yoffs
|| backsector->ceilingpic_angle != frontsector->ceilingpic_angle || backsector->ceilingpic_angle != frontsector->ceilingpic_angle
//SoM: 3/22/2000: Prevents bleeding. //SoM: 3/22/2000: Prevents bleeding.
|| (frontsector->heightsec != -1 && frontsector->ceilingpic != skyflatnum) || (frontsector->heightsec != -1 && frontsector->ceilingpic != skyflatnum)
|| backsector->ceilinglightsec != frontsector->ceilinglightsec || backsector->ceilinglightlevel != frontsector->ceilinglightlevel
//SoM: 4/3/2000: Check for colormaps || backsector->ceilinglightabsolute != frontsector->ceilinglightabsolute
|| frontsector->extra_colormap != backsector->extra_colormap || backsector->ceilinglightsec != frontsector->ceilinglightsec
|| (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags))) //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; markceiling = true;
} }
@ -1971,23 +1975,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
{ {
fixed_t texheight; fixed_t texheight;
// top texture // top texture
if ((linedef->flags & (ML_DONTPEGTOP) && (linedef->flags & ML_DONTPEGBOTTOM)) toptexture = R_GetTextureNum(sidedef->toptexture);
&& linedef->sidenum[1] != 0xffff) texheight = textureheight[toptexture];
{
// 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);
if (!toptexture) //Second side has no texture, use the first side's instead. if (!(linedef->flags & ML_SKEWTD)) { // Ignore slopes for lower/upper textures unless flag is checked
toptexture = R_GetTextureNum(sidedef->toptexture);
texheight = textureheight[toptexture];
}
else
{
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_DONTPEGTOP) if (linedef->flags & ML_DONTPEGTOP)
rw_toptexturemid = frontsector->ceilingheight - viewz; rw_toptexturemid = frontsector->ceilingheight - viewz;
else else
@ -2012,7 +2003,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
// bottom texture // bottom texture
bottomtexture = R_GetTextureNum(sidedef->bottomtexture); 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) if (linedef->flags & ML_DONTPEGBOTTOM)
rw_bottomtexturemid = frontsector->floorheight - viewz; rw_bottomtexturemid = frontsector->floorheight - viewz;
else else
@ -2243,7 +2234,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (curline->polyseg) if (curline->polyseg)
{ // use REAL front and back floors please, so midtexture rendering isn't mucked up { // use REAL front and back floors please, so midtexture rendering isn't mucked up
rw_midtextureslide = rw_midtexturebackslide = 0; rw_midtextureslide = rw_midtexturebackslide = 0;
if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) if (linedef->flags & ML_MIDPEG)
rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz; rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz;
else else
rw_midtexturemid = rw_midtextureback = min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz; rw_midtexturemid = rw_midtextureback = min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz;
@ -2251,16 +2242,16 @@ void R_StoreWallRange(INT32 start, INT32 stop)
else else
{ {
// Set midtexture starting height // Set midtexture starting height
if (linedef->flags & ML_EFFECT2) if (linedef->flags & ML_NOSKEW)
{ // Ignore slopes when texturing { // Ignore slopes when texturing
rw_midtextureslide = rw_midtexturebackslide = 0; rw_midtextureslide = rw_midtexturebackslide = 0;
if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) if (linedef->flags & ML_MIDPEG)
rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz; rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz;
else else
rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz; 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_MIDPEG)
{ {
rw_midtexturemid = worldbottom; rw_midtexturemid = worldbottom;
rw_midtextureslide = floorfrontslide; rw_midtextureslide = floorfrontslide;

View file

@ -37,6 +37,25 @@ void Tag_Add (taglist_t* list, const mtag_t tag)
list->tags[list->count++] = 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. /// Sets the first tag entry in a taglist.
/// Replicates the old way of accessing element->tag. /// Replicates the old way of accessing element->tag.
void Tag_FSet (taglist_t* list, const mtag_t tag) void Tag_FSet (taglist_t* list, const mtag_t tag)
@ -408,6 +427,22 @@ INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start)
// Ingame list manipulation. // 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 = &sectors[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 = &sectors[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. /// Changes the first tag for a given sector, and updates the global taggroups.
void Tag_SectorFSet (const size_t id, const mtag_t tag) void Tag_SectorFSet (const size_t id, const mtag_t tag)
{ {
@ -420,3 +455,16 @@ void Tag_SectorFSet (const size_t id, const mtag_t tag)
Taggroup_Add(tags_sectors, tag, id); Taggroup_Add(tags_sectors, tag, id);
Tag_FSet(&sec->tags, tag); 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;
}

View file

@ -28,12 +28,15 @@ typedef struct
} taglist_t; } taglist_t;
void Tag_Add (taglist_t* list, const mtag_t tag); 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); void Tag_FSet (taglist_t* list, const mtag_t tag);
mtag_t Tag_FGet (const taglist_t* list); mtag_t Tag_FGet (const taglist_t* list);
boolean Tag_Find (const taglist_t* list, const mtag_t tag); boolean Tag_Find (const taglist_t* list, const mtag_t tag);
boolean Tag_Share (const taglist_t* list1, const taglist_t* list2); boolean Tag_Share (const taglist_t* list1, const taglist_t* list2);
boolean Tag_Compare (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); void Tag_SectorFSet (const size_t id, const mtag_t tag);
/// Taggroup list. It is essentially just an element id list. /// Taggroup list. It is essentially just an element id list.
@ -46,6 +49,8 @@ typedef struct
extern bitarray_t tags_available[]; extern bitarray_t tags_available[];
extern mtag_t Tag_NextUnused(mtag_t start);
extern size_t num_tags; extern size_t num_tags;
extern taggroup_t* tags_sectors[]; extern taggroup_t* tags_sectors[];