diff --git a/dep/.gitignore b/dep/.gitignore new file mode 100644 index 000000000..fb941664f --- /dev/null +++ b/dep/.gitignore @@ -0,0 +1,2 @@ +#All folders +*.d diff --git a/dep/FreeBSD/SDL/Debug/.gitignore b/dep/FreeBSD/SDL/Debug/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/FreeBSD/SDL/Debug/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/FreeBSD/SDL/Release/.gitignore b/dep/FreeBSD/SDL/Release/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/FreeBSD/SDL/Release/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Linux/SDL/Debug/.gitignore b/dep/Linux/SDL/Debug/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Linux/SDL/Debug/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Linux/SDL/Release/.gitignore b/dep/Linux/SDL/Release/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Linux/SDL/Release/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Linux64/SDL/Debug/.gitignore b/dep/Linux64/SDL/Debug/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Linux64/SDL/Debug/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Linux64/SDL/Release/.gitignore b/dep/Linux64/SDL/Release/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Linux64/SDL/Release/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/MasterClient/.gitignore b/dep/MasterClient/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/MasterClient/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/MasterServer/.gitignore b/dep/MasterServer/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/MasterServer/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Mingw/Debug/.gitignore b/dep/Mingw/Debug/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Mingw/Debug/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Mingw/Release/.gitignore b/dep/Mingw/Release/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Mingw/Release/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Mingw/SDL/Debug/.gitignore b/dep/Mingw/SDL/Debug/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Mingw/SDL/Debug/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Mingw/SDL/Release/.gitignore b/dep/Mingw/SDL/Release/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Mingw/SDL/Release/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Mingw64/Debug/.gitignore b/dep/Mingw64/Debug/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Mingw64/Debug/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Mingw64/Release/.gitignore b/dep/Mingw64/Release/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Mingw64/Release/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Mingw64/SDL/Debug/.gitignore b/dep/Mingw64/SDL/Debug/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Mingw64/SDL/Debug/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/Mingw64/SDL/Release/.gitignore b/dep/Mingw64/SDL/Release/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/Mingw64/SDL/Release/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/SDL/Release/.gitignore b/dep/SDL/Release/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/SDL/Release/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/VC/.gitignore b/dep/VC/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/VC/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/VC9/.gitignore b/dep/VC9/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/VC9/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/cygwin/Debug/.gitignore b/dep/cygwin/Debug/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/cygwin/Debug/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/cygwin/Release/.gitignore b/dep/cygwin/Release/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/cygwin/Release/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/dep/dummy/.gitignore b/dep/dummy/.gitignore new file mode 100644 index 000000000..42c6dc2c6 --- /dev/null +++ b/dep/dummy/.gitignore @@ -0,0 +1,2 @@ +# DON'T REMOVE +# This keeps the folder from disappearing diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index a0d40cdf0..3fd4b6ccd 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -746,13 +746,13 @@ linedeftypes 20 { - title = "First Line"; + title = "PolyObject First Line"; prefix = "(20)"; } 22 { - title = "Parameters"; + title = "PolyObject Parameters"; prefix = "(22)"; flags8text = "[3] Set translucency by X offset"; flags32text = "[5] Render outer sides only"; @@ -765,19 +765,19 @@ linedeftypes 30 { - title = "Waving Flag"; + title = "PolyObject Waving Flag"; prefix = "(30)"; } 31 { - title = "Displacement by Front Sector"; + title = "Move PolyObject by Front Sector Displacement"; prefix = "(31)"; } 32 { - title = "Angular Displacement by Front Sector"; + title = "Rotate PolyObject by Front Sector Displacement"; prefix = "(32)"; flags64text = "[6] Don't turn players"; flags512text = "[9] Turn all objects"; @@ -2498,35 +2498,35 @@ linedeftypes 480 { - title = "Door Slide"; + title = "PolyObject Door Slide"; prefix = "(480)"; flags8text = "[3] Set delay by backside sector"; } 481 { - title = "Door Swing"; + title = "PolyObject Door Swing"; prefix = "(481)"; flags8text = "[3] Set delay by backside sector"; } 482 { - title = "Move"; + title = "Move PolyObject"; prefix = "(482)"; flags8text = "[3] Set delay by backside sector"; } 483 { - title = "Move, Override"; + title = "Move PolyObject, Override"; prefix = "(483)"; flags8text = "[3] Set delay by backside sector"; } 484 { - title = "Rotate Right"; + title = "Rotate PolyObject Right"; prefix = "(484)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Don't turn players"; @@ -2535,7 +2535,7 @@ linedeftypes 485 { - title = "Rotate Right, Override"; + title = "Rotate PolyObject Right, Override"; prefix = "(485)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Don't turn players"; @@ -2544,7 +2544,7 @@ linedeftypes 486 { - title = "Rotate Left"; + title = "Rotate PolyObject Left"; prefix = "(486)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Don't turn players"; @@ -2553,7 +2553,7 @@ linedeftypes 487 { - title = "Rotate Left, Override"; + title = "Rotate PolyObject Left, Override"; prefix = "(487)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Don't turn players"; @@ -2562,7 +2562,7 @@ linedeftypes 488 { - title = "Move by Waypoints"; + title = "Move PolyObject by Waypoints"; prefix = "(488)"; flags8text = "[3] Set delay by backside sector"; flags32text = "[5] Reverse order"; @@ -2573,7 +2573,7 @@ linedeftypes 489 { - title = "Turn Invisible, Intangible"; + title = "Turn PolyObject Invisible, Intangible"; prefix = "(489)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Only invisible"; @@ -2581,7 +2581,7 @@ linedeftypes 490 { - title = "Turn Visible, Tangible"; + title = "Turn PolyObject Visible, Tangible"; prefix = "(490)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Only visible"; @@ -2589,7 +2589,7 @@ linedeftypes 491 { - title = "Set Translucency"; + title = "Set PolyObject Translucency"; prefix = "(491)"; flags8text = "[3] Set delay by backside sector"; flags16text = "[4] Set raw alpha by Front X"; @@ -2598,7 +2598,7 @@ linedeftypes 492 { - title = "Fade Translucency"; + title = "Fade PolyObject Translucency"; prefix = "(492)"; flags8text = "[3] Set delay by backside sector"; flags16text = "[4] Set raw alpha by Front X"; @@ -3393,6 +3393,7 @@ thingtypes width = 8; height = 28; angletext = "Jump strength"; + fixedrotation = 1; } 103 { @@ -3431,6 +3432,7 @@ thingtypes width = 12; height = 64; angletext = "Firing delay"; + fixedrotation = 1; } 122 { @@ -3547,9 +3549,10 @@ thingtypes { title = "Pterabyte Spawner"; sprite = "PTERA2A8"; - width = 16; - height = 16; - parametertext = "No. Pterabytes"; + width = 24; + height = 48; + parametertext = "Spawns +1"; + arrow = 0; } 136 { @@ -3771,6 +3774,7 @@ thingtypes height = 16; sprite = "internal:capsule"; angletext = "Tag"; + fixedrotation = 1; } 292 { @@ -3781,11 +3785,13 @@ thingtypes flags8text = "[8] Sea Egg shooting point"; sprite = "internal:eggmanway"; angletext = "No. (Sea Egg)"; + fixedrotation = 1; flagsvaluetext = "No. (Brak)"; parametertext = "Next"; } 293 { + arrow = 0; title = "Metal Sonic Gather Point"; sprite = "internal:metal"; width = 8; @@ -3793,6 +3799,7 @@ thingtypes } 294 { + arrow = 0; title = "Fang Waypoint"; flags8text = "[8] Center waypoint"; sprite = "internal:eggmanway"; @@ -3820,79 +3827,79 @@ thingtypes 301 { title = "Bounce Ring"; - sprite = "internal:RNGBA0"; + sprite = "RNGBA0"; } 302 { title = "Rail Ring"; - sprite = "internal:RNGRA0"; + sprite = "RNGRA0"; } 303 { title = "Infinity Ring"; - sprite = "internal:RNGIA0"; + sprite = "RNGIA0"; } 304 { title = "Automatic Ring"; - sprite = "internal:RNGAA0"; + sprite = "RNGAA0"; } 305 { title = "Explosion Ring"; - sprite = "internal:RNGEA0"; + sprite = "RNGEA0"; } 306 { title = "Scatter Ring"; - sprite = "internal:RNGSA0"; + sprite = "RNGSA0"; } 307 { title = "Grenade Ring"; - sprite = "internal:RNGGA0"; + sprite = "RNGGA0"; } 308 { title = "CTF Team Ring (Red)"; - sprite = "internal:RRNGA0"; + sprite = "internal:TRNGA0r"; width = 16; } 309 { title = "CTF Team Ring (Blue)"; - sprite = "internal:BRNGA0"; + sprite = "internal:TRNGA0b"; width = 16; } 330 { title = "Bounce Ring Panel"; - sprite = "internal:PIKBA0"; + sprite = "PIKBA0"; } 331 { title = "Rail Ring Panel"; - sprite = "internal:PIKRA0"; + sprite = "PIKRA0"; } 332 { title = "Automatic Ring Panel"; - sprite = "internal:PIKAA0"; + sprite = "PIKAA0"; } 333 { title = "Explosion Ring Panel"; - sprite = "internal:PIKEA0"; + sprite = "PIKEA0"; } 334 { title = "Scatter Ring Panel"; - sprite = "internal:PIKSA0"; + sprite = "PIKSA0"; } 335 { title = "Grenade Ring Panel"; - sprite = "internal:PIKGA0"; + sprite = "PIKGA0"; } } @@ -3986,6 +3993,7 @@ thingtypes flags8height = 24; flags8text = "[8] Float"; angletext = "Tag"; + fixedrotation = 1; } } @@ -4000,6 +4008,7 @@ thingtypes flags4text = "[4] Random (Strong)"; flags8text = "[8] Random (Weak)"; angletext = "Tag"; + fixedrotation = 1; 400 { @@ -4131,6 +4140,7 @@ thingtypes height = 44; flags1text = "[1] Run linedef executor on pop"; angletext = "Tag"; + fixedrotation = 1; 431 { @@ -4228,6 +4238,7 @@ thingtypes height = 128; flags4text = "[4] Respawn at center"; angletext = "Angle/Order"; + fixedrotation = 1; parametertext = "Order"; } 520 @@ -4259,7 +4270,7 @@ thingtypes flags1text = "[1] Start retracted"; flags4text = "[4] Retractable"; flags8text = "[8] Intangible"; - parametertext = "Initial delay"; + parametertext = "Start delay"; } 523 { @@ -4271,7 +4282,8 @@ thingtypes flags4text = "[4] Retractable"; flags8text = "[8] Intangible"; angletext = "Retraction interval"; - parametertext = "Initial delay"; + fixedrotation = 1; + parametertext = "Start delay"; } 1130 { @@ -4320,6 +4332,7 @@ thingtypes flags4text = "[4] Invisible"; flags8text = "[8] No distance check"; angletext = "Lift height"; + fixedrotation = 1; } 541 { @@ -4335,6 +4348,7 @@ thingtypes width = 32; height = 64; angletext = "Strength"; + fixedrotation = 1; } 543 { @@ -4344,6 +4358,7 @@ thingtypes height = 64; flags8text = "[8] Respawn"; angletext = "Color"; + fixedrotation = 1; } 550 { @@ -4617,6 +4632,9 @@ thingtypes title = "Slope Vertex"; sprite = "internal:vertexslope"; angletext = "Tag"; + fixedrotation = 1; + parametertext = "Absolute?"; + flagsvaluetext = "Absolute Z"; } 751 @@ -4638,6 +4656,7 @@ thingtypes title = "Zoom Tube Waypoint"; sprite = "internal:zoom"; angletext = "Order"; + fixedrotation = 1; } 754 @@ -4647,6 +4666,7 @@ thingtypes flags8text = "[8] Push using XYZ"; sprite = "GWLGA0"; angletext = "Radius"; + fixedrotation = 1; } 755 { @@ -4655,6 +4675,7 @@ thingtypes flags8text = "[8] Pull using XYZ"; sprite = "GWLRA0"; angletext = "Radius"; + fixedrotation = 1; } 756 { @@ -4663,6 +4684,7 @@ thingtypes width = 32; height = 16; angletext = "Tag"; + fixedrotation = 1; } 757 { @@ -4671,6 +4693,7 @@ thingtypes width = 8; height = 16; angletext = "Tag"; + fixedrotation = 1; } 758 { @@ -4681,21 +4704,24 @@ thingtypes { title = "PolyObject Anchor"; sprite = "internal:polyanchor"; - angletext = "ID"; + angletext = "Tag"; + fixedrotation = 1; } 761 { title = "PolyObject Spawn Point"; sprite = "internal:polycenter"; - angletext = "ID"; + angletext = "Tag"; + fixedrotation = 1; } 762 { title = "PolyObject Spawn Point (Crush)"; sprite = "internal:polycentercrush"; - angletext = "ID"; + angletext = "Tag"; + fixedrotation = 1; } 780 { @@ -4703,6 +4729,7 @@ thingtypes sprite = "internal:skyb"; flags4text = "[4] In-map centerpoint"; parametertext = "ID"; + fixedrotation = 1; } } @@ -4897,6 +4924,7 @@ thingtypes height = 16; hangs = 1; angletext = "Dripping interval"; + fixedrotation = 1; } 1003 { @@ -4953,7 +4981,7 @@ thingtypes 1011 { title = "Stalagmite (DSZ2)"; - sprite = "DSTGA0"; + sprite = "DSTGB0"; width = 8; height = 116; flags4text = "[4] Double size"; @@ -5038,6 +5066,8 @@ thingtypes flags4text = "[4] No sounds"; flags8text = "[8] Double size"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1105 { @@ -5048,6 +5078,8 @@ thingtypes flags4text = "[4] No sounds"; flags8text = "[8] Double size"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1106 { @@ -5058,6 +5090,8 @@ thingtypes flags4text = "[4] No sounds"; flags8text = "[8] Red spring"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1107 { @@ -5067,6 +5101,8 @@ thingtypes height = 34; flags8text = "[8] Double size"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1108 { @@ -5086,6 +5122,8 @@ thingtypes flags4text = "[4] No sounds"; flags8text = "[8] Double size"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1110 { @@ -5095,6 +5133,8 @@ thingtypes height = 34; flags4text = "[4] No sounds"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1111 { @@ -5224,6 +5264,7 @@ thingtypes sprite = "EGR1A1"; width = 20; height = 72; + arrow = 1; } 1128 { @@ -5272,6 +5313,7 @@ thingtypes width = 8; height = 16; angletext = "Tag"; + fixedrotation = 1; } 1203 { @@ -5342,6 +5384,7 @@ thingtypes sprite = "WWSGAR"; width = 22; height = 64; + arrow = 1; } 1213 { @@ -5349,6 +5392,7 @@ thingtypes sprite = "WWS2AR"; width = 22; height = 64; + arrow = 1; } 1214 { @@ -5356,6 +5400,7 @@ thingtypes sprite = "WWS3ALAR"; width = 16; height = 192; + arrow = 1; } 1215 { @@ -5371,6 +5416,7 @@ thingtypes sprite = "BARRA1"; width = 24; height = 63; + arrow = 1; } 1217 { @@ -5392,6 +5438,7 @@ thingtypes sprite = "MCRTCLFR"; width = 22; height = 32; + arrow = 1; } 1220 { @@ -5399,6 +5446,7 @@ thingtypes sprite = "MCRTIR"; width = 32; height = 32; + arrow = 1; } 1221 { @@ -5406,6 +5454,7 @@ thingtypes sprite = "SALDARAL"; width = 96; height = 160; + arrow = 1; flags8text = "[8] Allow non-minecart players"; } 1222 @@ -5467,6 +5516,7 @@ thingtypes height = 40; flags8text = "[8] Waves vertically"; angletext = "On/Off time"; + fixedrotation = 1; parametertext = "Strength"; } 1301 @@ -5477,6 +5527,7 @@ thingtypes height = 40; flags8text = "[8] Shoot downwards"; angletext = "On/Off time"; + fixedrotation = 1; parametertext = "Strength"; } 1302 @@ -5500,6 +5551,7 @@ thingtypes width = 30; height = 32; angletext = "Initial delay"; + fixedrotation = 1; flags8text = "[8] Double size"; } 1305 @@ -5537,6 +5589,7 @@ thingtypes sprite = "WVINALAR"; width = 1; height = 288; + arrow = 1; } 1310 { @@ -5544,6 +5597,7 @@ thingtypes sprite = "WVINBLBR"; width = 1; height = 288; + arrow = 1; } } @@ -5901,6 +5955,7 @@ thingtypes width = 8; height = 4096; sprite = "UNKNA0"; + fixedrotation = 1; 1700 { @@ -5959,6 +6014,7 @@ thingtypes flags4text = "[4] Align player to top"; flags8text = "[8] Die upon time up"; angletext = "Time limit"; + fixedrotation = 1; parametertext = "Height"; } 1704 @@ -5971,6 +6027,7 @@ thingtypes unflippable = true; flagsvaluetext = "Pitch"; angletext = "Yaw"; + fixedrotation = 1; } 1705 { @@ -5983,6 +6040,7 @@ thingtypes centerHitbox = true; flagsvaluetext = "Height"; angletext = "Pitch/Yaw"; + fixedrotation = 1; } 1706 { @@ -6104,6 +6162,7 @@ thingtypes width = 8; height = 16; angletext = "Jump strength"; + fixedrotation = 1; } 1806 { @@ -6336,6 +6395,7 @@ thingtypes width = 18; height = 28; angletext = "Initial delay"; + fixedrotation = 1; } 2001 { @@ -6459,6 +6519,7 @@ thingtypes sprite = "XMS6A0"; width = 52; height = 106; + hangs = 1; } } @@ -6472,6 +6533,7 @@ thingtypes flags4text = "[4] No movement"; flags8text = "[8] Hop"; angletext = "Radius"; + fixedrotation = 1; 2200 { diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 0ea452155..113c1a4c2 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -1247,6 +1247,7 @@ patterns sprite = "SPHRA0"; width = 96; height = 192; + } 609 { title = "Circle of Rings and Spheres (Big)"; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d35e774e9..87a0499b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -276,6 +276,7 @@ set(SRB2_LUA_SOURCES lua_hudlib.c lua_infolib.c lua_maplib.c + lua_taglib.c lua_mathlib.c lua_mobjlib.c lua_playerlib.c diff --git a/src/Makefile b/src/Makefile index 0c1626fc9..a4c3c4fdb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,7 @@ # GNU Make makefile for SRB2 ############################################################################# # Copyright (C) 1998-2000 by DooM Legacy Team. -# Copyright (C) 2003-2020 by Sonic Team Junior. +# Copyright (C) 2003-2021 by Sonic Team Junior. # # This program is free software distributed under the # terms of the GNU General Public License, version 2. @@ -13,8 +13,7 @@ # -DHAVE_SDL -> use for the SDL interface # # Sets: -# Compile the DirectX/Mingw version with 'make MINGW=1' -# Compile the SDL/Mingw version with 'make MINGW=1 SDL=1' +# Compile the SDL/Mingw version with 'make MINGW=1' # Compile the SDL/Linux version with 'make LINUX=1' # Compile the SDL/Solaris version with 'make SOLARIS=1' # Compile the SDL/FreeBSD version with 'gmake FREEBSD=1' @@ -25,7 +24,9 @@ # clean # Remove all object files # cleandep -# Remove depend.dep +# Remove dependency files +# distclean +# Remove autogenerated files # dll # compile primary HW render DLL/SO # all_dll @@ -80,6 +81,17 @@ # ############################################################################# +,=, + +ifeq (,$(filter-out cleandep clean distclean,$(or $(MAKECMDGOALS),all))) +CLEANONLY=1 +else ifndef SILENT +echo=@echo "$(1)" +ifndef MAKE_RESTARTS +print=$(info $(1)) +endif +endif + ALL_SYSTEMS=\ PANDORA\ LINUX64\ @@ -99,11 +111,10 @@ ALL_SYSTEMS=\ ifeq (,$(filter $(ALL_SYSTEMS),$(.VARIABLES))) ifeq ($(OS),Windows_NT) # all windows are Windows_NT... - $(info Detected a Windows system, compiling for 32-bit MinGW SDL2...) + $(call print,Detected a Windows system$(,) compiling for 32-bit MinGW SDL2...) # go for a 32-bit sdl mingw exe by default MINGW=1 - SDL=1 WINDOWSHELL=1 else # if you on the *nix @@ -125,7 +136,7 @@ else # if you on the *nix new_system:=$(new_system)64 endif - $(info Detected $(system) ($(new_system))...) + $(call print,Detected $(system) ($(new_system))...) $(new_system)=1 endif @@ -239,6 +250,12 @@ endif MSGFMT?=msgfmt +ifdef WINDOWSHELL + COMPTIME=-..\comptime.bat +else + COMPTIME=-../comptime.sh +endif + ifndef ECHO NASM:=@$(NASM) REMOVE:=@$(REMOVE) @@ -253,6 +270,7 @@ ifndef ECHO MSGFMT:=@$(MSGFMT) UPX:=@$(UPX) UPX_OPTS+=-q + COMPTIME:=@$(COMPTIME) endif ifdef NONET @@ -417,7 +435,7 @@ ifdef GCC48 else CFLAGS+=-O0 endif - CFLAGS+= -Wall -DPARANOIA -DRANGECHECK -DPACKETDROP -DMOBJCONSISTANCY + CFLAGS+= -Wall -DPARANOIA -DRANGECHECK -DPACKETDROP else @@ -457,7 +475,6 @@ DBGNAME?=$(EXENAME).debug # not too sophisticated dependency OBJS:=$(i_main_o) \ - $(OBJDIR)/comptime.o \ $(OBJDIR)/string.o \ $(OBJDIR)/d_main.o \ $(OBJDIR)/d_clisrv.o \ @@ -544,7 +561,10 @@ OBJS:=$(i_main_o) \ $(i_sound_o) \ $(OBJS) +DEPS:=$(patsubst $(OBJDIR)/%.o,$(DEPDIR)/%.d,$(filter %.o,$(OBJS))) +OBJS+=$(OBJDIR)/comptime.o +ifndef SILENT ifndef ECHO ifndef NOECHOFILENAMES define echoName = @@ -552,6 +572,7 @@ define echoName = endef endif endif +endif # List of languages to compile. # For reference, this is the command I use to build a srb2.pot file from the source code. @@ -564,18 +585,12 @@ OPTS+=-DGETTEXT endif ifdef PANDORA -all: pre-build $(BIN)/$(PNDNAME) +all: $(BIN)/$(PNDNAME) endif -ifdef MINGW -ifndef SDL -all: pre-build $(BIN)/$(EXENAME) dll -endif -endif - ifdef SDL -all: pre-build $(BIN)/$(EXENAME) +all: $(BIN)/$(EXENAME) endif ifdef DUMMY @@ -583,20 +598,15 @@ all: $(BIN)/$(EXENAME) endif cleandep: - $(REMOVE) $(OBJDIR)/depend.dep + $(REMOVE) $(DEPS) $(REMOVE) comptime.h -pre-build: -ifdef WINDOWSHELL - -..\comptime.bat . -else - -@../comptime.sh . -endif - clean: $(REMOVE) *~ *.flc $(REMOVE) $(OBJDIR)/*.o +distclean: clean cleandep + ifdef MINGW $(REMOVE) $(OBJDIR)/*.res endif @@ -616,11 +626,11 @@ asm: $(BIN)/$(EXENAME): $(POS) $(OBJS) -$(MKDIR) $(BIN) - @echo Linking $(EXENAME)... + $(call echo,Linking $(EXENAME)...) $(LD) $(LDFLAGS) $(OBJS) -o $(BIN)/$(EXENAME) $(LIBS) ifndef VALGRIND ifndef NOOBJDUMP - @echo Dumping debugging info + $(call echo,Dumping debugging info) $(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(EXENAME) > $(BIN)/$(DBGNAME).txt ifdef WINDOWSHELL -$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt @@ -639,10 +649,10 @@ ifndef NOUPX -$(UPX) $(UPX_OPTS) $(BIN)/$(EXENAME) endif endif - @echo Build is done, please look for $(EXENAME) in $(BIN), \(checking for post steps\) + $(call echo,Build is done$(,) please look for $(EXENAME) in $(BIN)$(,) (checking for post steps)) reobjdump: - @echo Redumping debugging info + $(call echo,Redumping debugging info) $(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(DBGNAME) > $(BIN)/$(DBGNAME).txt ifdef WINDOWSHELL -$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt @@ -653,57 +663,6 @@ endif $(OBJDIR): -$(MKDIR) $(OBJDIR) -ifndef SDL -ifdef NOHW -dll : -else -dll : opengl_dll -endif -ifdef MINGW -all_dll: opengl_dll ds3d_dll fmod_dll openal_dll - -opengl_dll: $(BIN)/r_opengl.dll -$(BIN)/r_opengl.dll: $(OBJDIR)/ogl_win.o $(OBJDIR)/r_opengl.o - -$(MKDIR) $(BIN) - @echo Linking R_OpenGL.dll... - $(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -lgdi32 -static-libgcc -ifndef NOUPX - -$(UPX) $(UPX_OPTS) $@ -endif - -ds3d_dll: $(BIN)/s_ds3d.dll -$(BIN)/s_ds3d.dll: $(OBJDIR)/s_ds3d.o - @echo Linking S_DS3d.dll... - $(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -ldsound -luuid - -fmod_dll: $(BIN)/s_fmod.dll -$(BIN)/s_fmod.dll: $(OBJDIR)/s_fmod.o - -$(MKDIR) $(BIN) - @echo Linking S_FMOD.dll... - $(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -lfmod - -openal_dll: $(BIN)/s_openal.dll -$(BIN)/s_openal.dll: $(OBJDIR)/s_openal.o - -$(MKDIR) $(BIN) - @echo Linking S_OpenAL.dll... - $(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -lopenal32 -else -all_dll: fmod_so openal_so - -fmod_so: $(BIN)/s_fmod.so -$(BIN)/s_fmod.so: $(OBJDIR)/s_fmod.o - -$(MKDIR) $(BIN) - @echo Linking S_FMOD.so... - $(CC) --shared $^ -o $@ -g --nostartfiles -lm -lfmod - -openal_so: $(BIN)/s_openal.so -$(BIN)/s_openal.so: $(OBJDIR)/s_openal.o - -$(MKDIR) $(BIN) - @echo Linking S_OpenAL.so... - $(CC) --shared $^ -o $@ -g --nostartfiles -lm -lopenal -endif - -else ifdef SDL ifdef MINGW $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ @@ -728,27 +687,41 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h endif endif -endif - #dependecy made by gcc itself ! -$(OBJS): ifndef DUMMY --include $(OBJDIR)/depend.dep +ifndef CLEANONLY +$(call print,Checking dependency files...) +-include $(DEPS) +endif endif -$(OBJDIR)/depend.dep: - @echo "Creating dependency file, depend.dep" - @echo > comptime.h - -$(MKDIR) $(OBJDIR) - $(CC) $(CFLAGS) -MM *.c > $(OBJDIR)/depend.ped - $(CC) $(CFLAGS) -MM $(INTERFACE)/*.c >> $(OBJDIR)/depend.ped -ifndef NOHW - $(CC) $(CFLAGS) -MM hardware/*.c >> $(OBJDIR)/depend.ped +undefine deps_rule + +# windows makes it too hard ! +ifndef WINDOWSHELL +ifdef echoName +define deps_rule = + @printf "%-20.20s\r" $< + +endef endif - $(CC) $(CFLAGS) -MM blua/*.c >> $(OBJDIR)/depend.ped - @sed -e 's,\(.*\)\.o: ,$(subst /,\/,$(OBJDIR))\/&,g' < $(OBJDIR)/depend.ped > $(OBJDIR)/depend.dep - $(REMOVE) $(OBJDIR)/depend.ped - @echo "Created dependency file, depend.dep" +endif + +define deps_rule += + $(CC) $(CFLAGS) -M -MF $@ -MT $(OBJDIR)/$(<:.c=.o) $< +endef + +$(DEPDIR)/%.d: %.c + $(deps_rule) + +$(DEPDIR)/%.d: $(INTERFACE)/%.c + $(deps_rule) + +$(DEPDIR)/%.d: hardware/%.c + $(deps_rule) + +$(DEPDIR)/%.d: blua/%.c + $(deps_rule) ifdef VALGRIND $(OBJDIR)/z_zone.o: z_zone.c @@ -756,9 +729,12 @@ $(OBJDIR)/z_zone.o: z_zone.c $(CC) $(CFLAGS) $(WFLAGS) -DHAVE_VALGRIND $(VALGRIND_CFLAGS) -c $< -o $@ endif -$(OBJDIR)/comptime.o: comptime.c pre-build - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ +$(OBJDIR)/comptime.o:: +ifdef echoName + @echo -- comptime.c ... +endif + $(COMPTIME) . + $(CC) $(CFLAGS) $(WFLAGS) -c comptime.c -o $@ $(BIN)/%.mo: locale/%.po -$(MKDIR) $(BIN) @@ -804,33 +780,6 @@ $(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h $(WINDRES) -i $< -O rc $(WINDRESFLAGS) --include-dir=win32 -o $@ -O coff -ifdef MINGW -ifndef SDL -ifndef NOHW -$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ - doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ - command.h hardware/hw_data.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ - hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ - am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ - p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@ - -$(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \ - doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ - command.h hardware/hw_data.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ - hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ - am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ - p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@ -endif - -endif -endif - ifdef SDL ifdef MINGW diff --git a/src/Makefile.cfg b/src/Makefile.cfg index db7230bb4..075cd2d3a 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -47,7 +47,8 @@ ifdef MACOSX endif # Automatically set version flag, but not if one was manually set -ifeq (,$(filter GCC%,$(.VARIABLES))) +# And don't bother if this is a clean only run +ifeq (,$(filter GCC% CLEANONLY,$(.VARIABLES))) version:=$(shell $(CC) --version) # check if this is in fact GCC ifneq (,$(or $(findstring gcc,$(version)),$(findstring GCC,$(version)))) @@ -60,12 +61,14 @@ ifeq (,$(filter GCC%,$(.VARIABLES))) # If this version is not in the list, default to the latest supported ifeq (,$(filter $(v),$(SUPPORTED_GCC_VERSIONS))) - $(info\ - Your compiler version, GCC $(version), is not supported by the Makefile.\ - The Makefile will assume GCC $(LATEST_GCC_VERSION).) + define line = + Your compiler version, GCC $(version), is not supported by the Makefile. + The Makefile will assume GCC $(LATEST_GCC_VERSION).)) + endef + $(call print,$(line)) GCC$(subst .,,$(LATEST_GCC_VERSION))=1 else - $(info Detected GCC $(version) (GCC$(v))) + $(call print,Detected GCC $(version) (GCC$(v))) GCC$(v)=1 endif endif @@ -361,6 +364,7 @@ i_main_o=$(OBJDIR)/i_main.o #set OBJDIR and BIN's starting place OBJDIR=../objs BIN=../bin +DEPDIR=../dep #Nasm ASM and rm ifdef YASM NASM?=yasm @@ -383,6 +387,7 @@ ifdef DUMMY INTERFACE=dummy OBJDIR:=$(OBJDIR)/dummy BIN:=$(BIN)/dummy + DEPDIR:=$(DEPDIR)/dummy else ifdef LINUX NASMFORMAT=elf -DLINUX @@ -390,9 +395,11 @@ ifdef LINUX ifdef LINUX64 OBJDIR:=$(OBJDIR)/Linux64 BIN:=$(BIN)/Linux64 + DEPDIR:=$(DEPDIR)/Linux64 else OBJDIR:=$(OBJDIR)/Linux BIN:=$(BIN)/Linux + DEPDIR:=$(DEPDIR)/Linux endif else ifdef FREEBSD @@ -402,6 +409,7 @@ ifdef FREEBSD OBJDIR:=$(OBJDIR)/FreeBSD BIN:=$(BIN)/FreeBSD + DEPDIR:=$(DEPDIR)/Linux else ifdef SOLARIS INTERFACE=sdl @@ -410,6 +418,7 @@ ifdef SOLARIS OBJDIR:=$(OBJDIR)/Solaris BIN:=$(BIN)/Solaris + DEPDIR:=$(DEPDIR)/Solaris else ifdef CYGWIN32 INTERFACE=sdl @@ -418,18 +427,21 @@ ifdef CYGWIN32 OBJDIR:=$(OBJDIR)/cygwin BIN:=$(BIN)/Cygwin + DEPDIR:=$(DEPDIR)/Cygwin else ifdef MINGW64 - INTERFACE=win32 #NASMFORMAT=win64 + SDL=1 OBJDIR:=$(OBJDIR)/Mingw64 BIN:=$(BIN)/Mingw64 + DEPDIR:=$(DEPDIR)/Mingw64 else ifdef MINGW - INTERFACE=win32 NASMFORMAT=win32 + SDL=1 OBJDIR:=$(OBJDIR)/Mingw BIN:=$(BIN)/Mingw + DEPDIR:=$(DEPDIR)/Mingw endif endif endif @@ -441,6 +453,7 @@ endif ifdef ARCHNAME OBJDIR:=$(OBJDIR)/$(ARCHNAME) BIN:=$(BIN)/$(ARCHNAME) + DEPDIR:=$(DEPDIR)/$(ARCHNAME) endif OBJDUMP_OPTS?=--wide --source --line-numbers @@ -449,14 +462,17 @@ LD=$(CC) ifdef SDL INTERFACE=sdl OBJDIR:=$(OBJDIR)/SDL + DEPDIR:=$(DEPDIR)/SDL endif ifndef DUMMY ifdef DEBUGMODE OBJDIR:=$(OBJDIR)/Debug BIN:=$(BIN)/Debug + DEPDIR:=$(DEPDIR)/Debug else OBJDIR:=$(OBJDIR)/Release BIN:=$(BIN)/Release + DEPDIR:=$(DEPDIR)/Release endif endif diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg index eae95ba3a..3a2962e65 100644 --- a/src/blua/Makefile.cfg +++ b/src/blua/Makefile.cfg @@ -47,6 +47,7 @@ OBJS:=$(OBJS) \ $(OBJDIR)/lua_skinlib.o \ $(OBJDIR)/lua_thinkerlib.o \ $(OBJDIR)/lua_maplib.o \ + $(OBJDIR)/lua_taglib.o \ $(OBJDIR)/lua_polyobjlib.o \ $(OBJDIR)/lua_blockmaplib.o \ $(OBJDIR)/lua_hudlib.o diff --git a/src/command.h b/src/command.h index ea5593395..d4033e6ef 100644 --- a/src/command.h +++ b/src/command.h @@ -158,7 +158,7 @@ typedef struct consvar_s //NULL, NULL, 0, NULL, NULL |, 0, NULL, NULL, 0, 0, NUL /* name, defaultvalue, flags, PossibleValue, func */ #define CVAR_INIT( ... ) \ -{ __VA_ARGS__, 0, NULL, NULL, {0}, 0U, (char)0, NULL } +{ __VA_ARGS__, 0, NULL, NULL, {0, {NULL}}, 0U, (char)0, NULL } #ifdef OLD22DEMOCOMPAT typedef struct old_demo_var old_demo_var_t; diff --git a/src/console.c b/src/console.c index bcf01c989..aa023c63f 100644 --- a/src/console.c +++ b/src/console.c @@ -360,30 +360,48 @@ static void CON_SetupColormaps(void) for (i = 0; i < (256*15); i++, ++memorysrc) *memorysrc = (UINT8)(i & 0xFF); // remap each color to itself... -#define colset(map, a, b, c) \ - map[1] = (UINT8)a;\ - map[3] = (UINT8)b;\ - map[9] = (UINT8)c +#define colset(map, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \ + map[0x0] = (UINT8)a;\ + map[0x1] = (UINT8)b;\ + map[0x2] = (UINT8)c;\ + map[0x3] = (UINT8)d;\ + map[0x4] = (UINT8)e;\ + map[0x5] = (UINT8)f;\ + map[0x6] = (UINT8)g;\ + map[0x7] = (UINT8)h;\ + map[0x8] = (UINT8)i;\ + map[0x9] = (UINT8)j;\ + map[0xA] = (UINT8)k;\ + map[0xB] = (UINT8)l;\ + map[0xC] = (UINT8)m;\ + map[0xD] = (UINT8)n;\ + map[0xE] = (UINT8)o;\ + map[0xF] = (UINT8)p; - colset(magentamap, 177, 178, 184); - colset(yellowmap, 82, 73, 66); - colset(lgreenmap, 97, 98, 106); - colset(bluemap, 146, 147, 155); - colset(redmap, 210, 32, 39); - colset(graymap, 6, 8, 14); - colset(orangemap, 51, 52, 57); - colset(skymap, 129, 130, 133); - colset(purplemap, 160, 161, 163); - colset(aquamap, 120, 121, 123); - colset(peridotmap, 88, 188, 190); - colset(azuremap, 144, 145, 170); - colset(brownmap, 219, 221, 224); - colset(rosymap, 200, 201, 203); - colset(invertmap, 27, 26, 22); - invertmap[26] = (UINT8)3; + // Tried to keep the colors vanilla while adding some shades in between them ~SonicX8000 + + // 0x1 0x3 0x9 0xF + colset(magentamap, 177, 177, 178, 178, 178, 180, 180, 180, 182, 182, 182, 182, 184, 184, 184, 185); + colset(yellowmap, 82, 82, 73, 73, 73, 64, 64, 64, 66, 66, 66, 66, 67, 67, 67, 68); + colset(lgreenmap, 96, 96, 98, 98, 98, 101, 101, 101, 104, 104, 104, 104, 106, 106, 106, 107); + colset(bluemap, 146, 146, 147, 147, 147, 149, 149, 149, 152, 152, 152, 152, 155, 155, 155, 157); + colset(redmap, 32, 32, 33, 33, 33, 35, 35, 35, 39, 39, 39, 39, 42, 42, 42, 44); + colset(graymap, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23); + colset(orangemap, 50, 50, 52, 52, 52, 54, 54, 54, 56, 56, 56, 56, 59, 59, 59, 60); + colset(skymap, 129, 129, 130, 130, 130, 131, 131, 131, 133, 133, 133, 133, 135, 135, 135, 136); + colset(purplemap, 160, 160, 161, 161, 161, 162, 162, 162, 163, 163, 163, 163, 164, 164, 164, 165); + colset(aquamap, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123, 123, 123, 124, 124, 124, 125); + colset(peridotmap, 72, 72, 188, 188, 189, 189, 189, 189, 190, 190, 190, 190, 191, 191, 191, 94); + colset(azuremap, 144, 144, 145, 145, 145, 146, 146, 146, 170, 170, 170, 170, 171, 171, 171, 172); + colset(brownmap, 219, 219, 221, 221, 221, 222, 222, 222, 224, 224, 224, 224, 227, 227, 227, 229); + colset(rosymap, 200, 200, 201, 201, 201, 202, 202, 202, 203, 203, 203, 203, 204, 204, 204, 205); #undef colset + // Yeah just straight up invert it like a normal person + for (i = 0x00; i <= 0x1F; i++) + invertmap[0x1F - i] = i; + // Init back colormap CON_SetupBackColormap(); } @@ -808,6 +826,12 @@ static void CON_InputDelSelection(void) Lock_state(); + if (!input_cur) + { + Unlock_state(); + return; + } + if (input_cur > input_sel) { start = input_sel; @@ -1279,10 +1303,6 @@ boolean CON_Responder(event_t *ev) if (key < 32 || key > 127) return true; - // add key to cmd line here - if (key >= 'A' && key <= 'Z' && !(shiftdown ^ capslock)) //this is only really necessary for dedicated servers - key = key + 'a' - 'A'; - if (input_sel != input_cur) CON_InputDelSelection(); CON_InputAddChar(key); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 4f8bbb9a1..7c2dec6a1 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1595,9 +1595,7 @@ static void CL_ReloadReceivedSavegame(void) for (i = 0; i < MAXPLAYERS; i++) { -#ifdef HAVE_BLUA LUA_InvalidatePlayer(&players[i]); -#endif sprintf(player_names[i], "Player %d", i + 1); } @@ -3114,7 +3112,7 @@ consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR, maxpl static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}}; consvar_t cv_joindelay = CVAR_INIT ("joindelay", "10", CV_SAVE|CV_NETVAR, joindelay_cons_t, NULL); static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_rejointimeout = CVAR_INIT ("rejointimeout", "Off", CV_SAVE|CV_NETVAR|CV_FLOAT, rejointimeout_cons_t, NULL); +consvar_t cv_rejointimeout = CVAR_INIT ("rejointimeout", "2", CV_SAVE|CV_NETVAR|CV_FLOAT, rejointimeout_cons_t, NULL); static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}}; consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "10", CV_SAVE|CV_NETVAR, resynchattempts_cons_t, NULL); @@ -4482,70 +4480,73 @@ static INT16 Consistancy(void) ret += P_GetRandSeed(); #ifdef MOBJCONSISTANCY - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + if (gamestate == GS_LEVEL) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo = (mobj_t *)th; - - if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - ret -= mo->type; - ret += mo->x; - ret -= mo->y; - ret += mo->z; - ret -= mo->momx; - ret += mo->momy; - ret -= mo->momz; - ret += mo->angle; - ret -= mo->flags; - ret += mo->flags2; - ret -= mo->eflags; - if (mo->target) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo = (mobj_t *)th; + + if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) { - ret += mo->target->type; - ret -= mo->target->x; - ret += mo->target->y; - ret -= mo->target->z; - ret += mo->target->momx; - ret -= mo->target->momy; - ret += mo->target->momz; - ret -= mo->target->angle; - ret += mo->target->flags; - ret -= mo->target->flags2; - ret += mo->target->eflags; - ret -= mo->target->state - states; - ret += mo->target->tics; - ret -= mo->target->sprite; - ret += mo->target->frame; + ret -= mo->type; + ret += mo->x; + ret -= mo->y; + ret += mo->z; + ret -= mo->momx; + ret += mo->momy; + ret -= mo->momz; + ret += mo->angle; + ret -= mo->flags; + ret += mo->flags2; + ret -= mo->eflags; + if (mo->target) + { + ret += mo->target->type; + ret -= mo->target->x; + ret += mo->target->y; + ret -= mo->target->z; + ret += mo->target->momx; + ret -= mo->target->momy; + ret += mo->target->momz; + ret -= mo->target->angle; + ret += mo->target->flags; + ret -= mo->target->flags2; + ret += mo->target->eflags; + ret -= mo->target->state - states; + ret += mo->target->tics; + ret -= mo->target->sprite; + ret += mo->target->frame; + } + else + ret ^= 0x3333; + if (mo->tracer && mo->tracer->type != MT_OVERLAY) + { + ret += mo->tracer->type; + ret -= mo->tracer->x; + ret += mo->tracer->y; + ret -= mo->tracer->z; + ret += mo->tracer->momx; + ret -= mo->tracer->momy; + ret += mo->tracer->momz; + ret -= mo->tracer->angle; + ret += mo->tracer->flags; + ret -= mo->tracer->flags2; + ret += mo->tracer->eflags; + ret -= mo->tracer->state - states; + ret += mo->tracer->tics; + ret -= mo->tracer->sprite; + ret += mo->tracer->frame; + } + else + ret ^= 0xAAAA; + ret -= mo->state - states; + ret += mo->tics; + ret -= mo->sprite; + ret += mo->frame; } - else - ret ^= 0x3333; - if (mo->tracer && mo->tracer->type != MT_OVERLAY) - { - ret += mo->tracer->type; - ret -= mo->tracer->x; - ret += mo->tracer->y; - ret -= mo->tracer->z; - ret += mo->tracer->momx; - ret -= mo->tracer->momy; - ret += mo->tracer->momz; - ret -= mo->tracer->angle; - ret += mo->tracer->flags; - ret -= mo->tracer->flags2; - ret += mo->tracer->eflags; - ret -= mo->tracer->state - states; - ret += mo->tracer->tics; - ret -= mo->tracer->sprite; - ret += mo->tracer->frame; - } - else - ret ^= 0xAAAA; - ret -= mo->state - states; - ret += mo->tics; - ret -= mo->sprite; - ret += mo->frame; } } #endif diff --git a/src/d_main.c b/src/d_main.c index a89f4ed2d..23a2c0133 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -61,7 +61,7 @@ #include "p_local.h" // chasecam #include "mserv.h" // ms_RoomId #include "m_misc.h" // screenshot functionality -#include "dehacked.h" // Dehacked list test +#include "deh_tables.h" // Dehacked list test #include "m_cond.h" // condition initialization #include "fastcmp.h" #include "keys.h" @@ -1072,7 +1072,7 @@ void D_SRB2Main(void) G_LoadGameSettings(); // Test Dehacked lists - DEH_Check(); + DEH_TableCheck(); // Netgame URL special case: change working dir to EXE folder. ChangeDirForUrlHandler(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 6080b2fd0..09f9d4651 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -214,11 +214,9 @@ consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_ consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL); -#ifdef SEENAMES static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}}; consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0); consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); -#endif // names consvar_t cv_playername = CVAR_INIT ("name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange); @@ -597,9 +595,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_pingtimeout); CV_RegisterVar(&cv_showping); -#ifdef SEENAMES - CV_RegisterVar(&cv_allowseenames); -#endif + CV_RegisterVar(&cv_allowseenames); CV_RegisterVar(&cv_dummyconsvar); } @@ -670,6 +666,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_zlib_strategya); CV_RegisterVar(&cv_zlib_window_bitsa); CV_RegisterVar(&cv_apng_delay); + CV_RegisterVar(&cv_apng_downscale); // GIF variables CV_RegisterVar(&cv_gif_optimize); CV_RegisterVar(&cv_gif_downscale); @@ -690,9 +687,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_defaultplayercolor2); CV_RegisterVar(&cv_defaultskin2); -#ifdef SEENAMES CV_RegisterVar(&cv_seenames); -#endif CV_RegisterVar(&cv_rollingdemos); CV_RegisterVar(&cv_netstat); CV_RegisterVar(&cv_netticbuffer); @@ -878,7 +873,7 @@ void D_RegisterClientCommands(void) // CV_RegisterVar(&cv_snapto); CV_RegisterVar(&cv_freedemocamera); - + // add cheat commands COM_AddCommand("noclip", Command_CheatNoClip_f); COM_AddCommand("god", Command_CheatGod_f); @@ -2135,7 +2130,7 @@ static void Command_Pause(void) if (cv_pause.value || server || (IsPlayerAdmin(consoleplayer))) { - if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION)) + if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) || (marathonmode && gamestate == GS_INTERMISSION)) { CONS_Printf(M_GetText("You can't pause here.\n")); return; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 98d8f1425..ac39626a4 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -31,9 +31,7 @@ extern consvar_t cv_defaultskin; extern consvar_t cv_defaultplayercolor2; extern consvar_t cv_defaultskin2; -#ifdef SEENAMES extern consvar_t cv_seenames, cv_allowseenames; -#endif extern consvar_t cv_usemouse; extern consvar_t cv_usejoystick; extern consvar_t cv_usejoystick2; diff --git a/src/d_netfil.c b/src/d_netfil.c index 8f661bb5f..50dc2ba60 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -562,7 +562,7 @@ static void SV_PrepareSendLuaFileToNextNode(void) // Find a client to send the file to for (i = 1; i < MAXNETNODES; i++) - if (nodeingame[i] && luafiletransfers->nodestatus[i] == LFTNS_WAITING) // Node waiting + if (luafiletransfers->nodestatus[i] == LFTNS_WAITING) // Node waiting { // Tell the client we're about to send them the file netbuffer->packettype = PT_SENDINGLUAFILE; @@ -570,6 +570,7 @@ static void SV_PrepareSendLuaFileToNextNode(void) I_Error("Failed to send a PT_SENDINGLUAFILE packet\n"); // !!! Todo: Handle failure a bit better lol luafiletransfers->nodestatus[i] = LFTNS_ASKED; + luafiletransfers->nodetimeouts[i] = I_GetTime() + 30 * TICRATE; return; } @@ -588,7 +589,7 @@ void SV_PrepareSendLuaFile(void) // Set status to "waiting" for everyone for (i = 0; i < MAXNETNODES; i++) - luafiletransfers->nodestatus[i] = LFTNS_WAITING; + luafiletransfers->nodestatus[i] = (nodeingame[i] ? LFTNS_WAITING : LFTNS_NONE); if (FIL_ReadFileOK(luafiletransfers->realfilename)) { @@ -649,12 +650,14 @@ void RemoveAllLuaFileTransfers(void) void SV_AbortLuaFileTransfer(INT32 node) { - if (luafiletransfers - && (luafiletransfers->nodestatus[node] == LFTNS_ASKED - || luafiletransfers->nodestatus[node] == LFTNS_SENDING)) + if (luafiletransfers) { - luafiletransfers->nodestatus[node] = LFTNS_WAITING; - SV_PrepareSendLuaFileToNextNode(); + if (luafiletransfers->nodestatus[node] == LFTNS_ASKED + || luafiletransfers->nodestatus[node] == LFTNS_SENDING) + { + SV_PrepareSendLuaFileToNextNode(); + } + luafiletransfers->nodestatus[node] = LFTNS_NONE; } } @@ -928,6 +931,22 @@ void FileSendTicker(void) filetx_t *f; INT32 packetsent, ram, i, j; + // If someone is taking too long to download, kick them with a timeout + // to prevent blocking the rest of the server... + if (luafiletransfers) + { + for (i = 1; i < MAXNETNODES; i++) + { + luafiletransfernodestatus_t status = luafiletransfers->nodestatus[i]; + + if (status != LFTNS_NONE && status != LFTNS_WAITING && status != LFTNS_SENT + && I_GetTime() > luafiletransfers->nodetimeouts[i]) + { + Net_ConnectionTimeout(i); + } + } + } + if (!filestosend) // No file to send return; diff --git a/src/d_netfil.h b/src/d_netfil.h index 1b399be75..158149477 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -85,10 +85,11 @@ boolean PT_RequestFile(INT32 node); typedef enum { + LFTNS_NONE, // This node is not connected LFTNS_WAITING, // This node is waiting for the server to send the file - LFTNS_ASKED, // The server has told the node they're ready to send the file + LFTNS_ASKED, // The server has told the node they're ready to send the file LFTNS_SENDING, // The server is sending the file to this node - LFTNS_SENT // The node already has the file + LFTNS_SENT // The node already has the file } luafiletransfernodestatus_t; typedef struct luafiletransfer_s @@ -99,6 +100,7 @@ typedef struct luafiletransfer_s INT32 id; // Callback ID boolean ongoing; luafiletransfernodestatus_t nodestatus[MAXNETNODES]; + tic_t nodetimeouts[MAXNETNODES]; struct luafiletransfer_s *next; } luafiletransfer_t; diff --git a/src/d_player.h b/src/d_player.h index 79f2a3b92..2e7afed88 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -52,6 +52,8 @@ typedef enum SF_NOSUPERSPRITES = 1<<16, // Don't use super sprites while super SF_NOSUPERJUMPBOOST = 1<<17, // Disable the jump boost given while super (i.e. Knuckles) SF_CANBUSTWALLS = 1<<18, // Can naturally bust walls on contact? (i.e. Knuckles) + SF_NOSHIELDABILITY = 1<<19, // Disable shield abilities + // free up to and including 1<<31 } skinflags_t; diff --git a/src/deh_tables.c b/src/deh_tables.c index 7877903c5..dd6d7d69f 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1522,6 +1522,13 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_SPINFIRE5", "S_SPINFIRE6", + "S_TEAM_SPINFIRE1", + "S_TEAM_SPINFIRE2", + "S_TEAM_SPINFIRE3", + "S_TEAM_SPINFIRE4", + "S_TEAM_SPINFIRE5", + "S_TEAM_SPINFIRE6", + // Spikes "S_SPIKE1", "S_SPIKE2", @@ -3478,9 +3485,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_BLUEBRICKDEBRIS", "S_YELLOWBRICKDEBRIS", -#ifdef SEENAMES "S_NAMECHECK", -#endif }; // RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1", @@ -4260,9 +4265,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_BLUEBRICKDEBRIS", "MT_YELLOWBRICKDEBRIS", -#ifdef SEENAMES "MT_NAMECHECK", -#endif }; const char *const MOBJFLAG_LIST[] = { @@ -5019,6 +5022,7 @@ struct int_const_s const INT_CONST[] = { {"SF_NOSUPERSPRITES",SF_NOSUPERSPRITES}, {"SF_NOSUPERJUMPBOOST",SF_NOSUPERJUMPBOOST}, {"SF_CANBUSTWALLS",SF_CANBUSTWALLS}, + {"SF_NOSHIELDABILITY",SF_NOSHIELDABILITY}, // Dashmode constants {"DASHMODE_THRESHOLD",DASHMODE_THRESHOLD}, @@ -5453,3 +5457,27 @@ struct int_const_s const INT_CONST[] = { {NULL,0} }; + +// For this to work compile-time without being in this file, +// this function would need to check sizes at runtime, without sizeof +void DEH_TableCheck(void) +{ +#if defined(_DEBUG) || defined(PARANOIA) + const size_t dehstates = sizeof(STATE_LIST)/sizeof(const char*); + const size_t dehmobjs = sizeof(MOBJTYPE_LIST)/sizeof(const char*); + const size_t dehpowers = sizeof(POWERS_LIST)/sizeof(const char*); + const size_t dehcolors = sizeof(COLOR_ENUMS)/sizeof(const char*); + + if (dehstates != S_FIRSTFREESLOT) + I_Error("You forgot to update the Dehacked states list, you dolt!\n(%d states defined, versus %s in the Dehacked list)\n", S_FIRSTFREESLOT, sizeu1(dehstates)); + + if (dehmobjs != MT_FIRSTFREESLOT) + I_Error("You forgot to update the Dehacked mobjtype list, you dolt!\n(%d mobj types defined, versus %s in the Dehacked list)\n", MT_FIRSTFREESLOT, sizeu1(dehmobjs)); + + if (dehpowers != NUMPOWERS) + I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d powers defined, versus %s in the Dehacked list)\n", NUMPOWERS, sizeu1(dehpowers)); + + if (dehcolors != SKINCOLOR_FIRSTFREESLOT) + I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", SKINCOLOR_FIRSTFREESLOT, sizeu1(dehcolors)); +#endif +} diff --git a/src/deh_tables.h b/src/deh_tables.h index 2c6b3e204..d094bcbad 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -72,4 +72,7 @@ extern const char *const MENUTYPES_LIST[]; extern struct int_const_s const INT_CONST[]; +// Moved to this file because it can't work compile-time otherwise +void DEH_TableCheck(void); + #endif diff --git a/src/dehacked.c b/src/dehacked.c index b42663267..c2ea28d27 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -645,25 +645,3 @@ void DEH_LoadDehackedLump(lumpnum_t lumpnum) { DEH_LoadDehackedLumpPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum), false); } - -void DEH_Check(void) -{ -#if defined(_DEBUG) || defined(PARANOIA) - const size_t dehstates = sizeof(STATE_LIST)/sizeof(const char*); - const size_t dehmobjs = sizeof(MOBJTYPE_LIST)/sizeof(const char*); - const size_t dehpowers = sizeof(POWERS_LIST)/sizeof(const char*); - const size_t dehcolors = sizeof(COLOR_ENUMS)/sizeof(const char*); - - if (dehstates != S_FIRSTFREESLOT) - I_Error("You forgot to update the Dehacked states list, you dolt!\n(%d states defined, versus %s in the Dehacked list)\n", S_FIRSTFREESLOT, sizeu1(dehstates)); - - if (dehmobjs != MT_FIRSTFREESLOT) - I_Error("You forgot to update the Dehacked mobjtype list, you dolt!\n(%d mobj types defined, versus %s in the Dehacked list)\n", MT_FIRSTFREESLOT, sizeu1(dehmobjs)); - - if (dehpowers != NUMPOWERS) - I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d powers defined, versus %s in the Dehacked list)\n", NUMPOWERS, sizeu1(dehpowers)); - - if (dehcolors != SKINCOLOR_FIRSTFREESLOT) - I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", SKINCOLOR_FIRSTFREESLOT, sizeu1(dehcolors)); -#endif -} diff --git a/src/dehacked.h b/src/dehacked.h index d5256be23..1620314ca 100644 --- a/src/dehacked.h +++ b/src/dehacked.h @@ -30,8 +30,6 @@ typedef enum void DEH_LoadDehackedLump(lumpnum_t lumpnum); void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump, boolean mainfile); -void DEH_Check(void); - fixed_t get_number(const char *word); FUNCPRINTF void deh_warning(const char *first, ...); void deh_strlcpy(char *dst, const char *src, size_t size, const char *warntext); diff --git a/src/doomdef.h b/src/doomdef.h index d0b7ea0c2..52abc9597 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -582,9 +582,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Dumps the contents of a network save game upon consistency failure for debugging. //#define DUMPCONSISTENCY -/// See name of player in your crosshair -#define SEENAMES - /// Who put weights on my recycler? ... Inuyasha did. /// \note XMOD port. //#define WEIGHTEDRECYCLER diff --git a/src/doomtype.h b/src/doomtype.h index c239c7b8e..950f50856 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -379,6 +379,28 @@ Needed for some lua shenanigans. #define FIELDFROM( type, field, have, want ) \ (void *)((intptr_t)(field) - offsetof (type, have) + offsetof (type, want)) +typedef UINT8 bitarray_t; + +#define BIT_ARRAY_SIZE(n) (((n) + 7) >> 3) + +static inline int +in_bit_array (const bitarray_t * const array, const int value) +{ + return (array[value >> 3] & (1<<(value & 7))); +} + +static inline void +set_bit_array (bitarray_t * const array, const int value) +{ + array[value >> 3] |= (1<<(value & 7)); +} + +static inline void +unset_bit_array (bitarray_t * const array, const int value) +{ + array[value >> 3] &= ~(1<<(value & 7)); +} + #ifdef HAVE_SDL typedef UINT64 precise_t; #endif diff --git a/src/f_finale.c b/src/f_finale.c index 688cd4fc7..fdcfad279 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1074,6 +1074,7 @@ static const char *credits[] = { "\1Programming", "Alam \"GBC\" Arias", "Logan \"GBA\" Arias", + "Zolton \"Zippy_Zolton\" Auburn", "Colette \"fickleheart\" Bordelon", "Andrew \"orospakr\" Clunis", "Sally \"TehRealSalt\" Cochenour", @@ -1104,6 +1105,7 @@ static const char *credits[] = { "Sean \"Sryder13\" Ryder", "Ehab \"Wolfy\" Saeed", "Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible + "Riku \"Ors\" Salminen", // Demo consistency improvements "Jonas \"MascaraSnake\" Sauer", "Wessel \"sphere\" Smit", "\"SSNTails\"", @@ -1136,6 +1138,7 @@ static const char *credits[] = { "Iestyn \"Monster Iestyn\" Jealous", "William \"GuyWithThePie\" Kloppenberg", "Alice \"Alacroix\" de Lemos", + "Logan \"Hyperchaotix\" McCloud", "Alexander \"DrTapeworm\" Moench-Ford", "Andrew \"Senku Niola\" Moran", "\"MotorRoach\"", @@ -2543,28 +2546,28 @@ static void F_UnloadAlacroixGraphics(SINT8 oldttscale) oldttscale--; // zero-based index for (i = 0; i < TTMAX_ALACROIX; i++) { - if(ttembl[oldttscale][i]) { Z_Free(ttembl[oldttscale][i]); ttembl[oldttscale][i] = 0; } - if(ttribb[oldttscale][i]) { Z_Free(ttribb[oldttscale][i]); ttribb[oldttscale][i] = 0; } - if(ttsont[oldttscale][i]) { Z_Free(ttsont[oldttscale][i]); ttsont[oldttscale][i] = 0; } - if(ttrobo[oldttscale][i]) { Z_Free(ttrobo[oldttscale][i]); ttrobo[oldttscale][i] = 0; } - if(tttwot[oldttscale][i]) { Z_Free(tttwot[oldttscale][i]); tttwot[oldttscale][i] = 0; } - if(ttrbtx[oldttscale][i]) { Z_Free(ttrbtx[oldttscale][i]); ttrbtx[oldttscale][i] = 0; } - if(ttsoib[oldttscale][i]) { Z_Free(ttsoib[oldttscale][i]); ttsoib[oldttscale][i] = 0; } - if(ttsoif[oldttscale][i]) { Z_Free(ttsoif[oldttscale][i]); ttsoif[oldttscale][i] = 0; } - if(ttsoba[oldttscale][i]) { Z_Free(ttsoba[oldttscale][i]); ttsoba[oldttscale][i] = 0; } - if(ttsobk[oldttscale][i]) { Z_Free(ttsobk[oldttscale][i]); ttsobk[oldttscale][i] = 0; } - if(ttsodh[oldttscale][i]) { Z_Free(ttsodh[oldttscale][i]); ttsodh[oldttscale][i] = 0; } - if(tttaib[oldttscale][i]) { Z_Free(tttaib[oldttscale][i]); tttaib[oldttscale][i] = 0; } - if(tttaif[oldttscale][i]) { Z_Free(tttaif[oldttscale][i]); tttaif[oldttscale][i] = 0; } - if(tttaba[oldttscale][i]) { Z_Free(tttaba[oldttscale][i]); tttaba[oldttscale][i] = 0; } - if(tttabk[oldttscale][i]) { Z_Free(tttabk[oldttscale][i]); tttabk[oldttscale][i] = 0; } - if(tttabt[oldttscale][i]) { Z_Free(tttabt[oldttscale][i]); tttabt[oldttscale][i] = 0; } - if(tttaft[oldttscale][i]) { Z_Free(tttaft[oldttscale][i]); tttaft[oldttscale][i] = 0; } - if(ttknib[oldttscale][i]) { Z_Free(ttknib[oldttscale][i]); ttknib[oldttscale][i] = 0; } - if(ttknif[oldttscale][i]) { Z_Free(ttknif[oldttscale][i]); ttknif[oldttscale][i] = 0; } - if(ttknba[oldttscale][i]) { Z_Free(ttknba[oldttscale][i]); ttknba[oldttscale][i] = 0; } - if(ttknbk[oldttscale][i]) { Z_Free(ttknbk[oldttscale][i]); ttknbk[oldttscale][i] = 0; } - if(ttkndh[oldttscale][i]) { Z_Free(ttkndh[oldttscale][i]); ttkndh[oldttscale][i] = 0; } + if(ttembl[oldttscale][i]) { Patch_Free(ttembl[oldttscale][i]); ttembl[oldttscale][i] = 0; } + if(ttribb[oldttscale][i]) { Patch_Free(ttribb[oldttscale][i]); ttribb[oldttscale][i] = 0; } + if(ttsont[oldttscale][i]) { Patch_Free(ttsont[oldttscale][i]); ttsont[oldttscale][i] = 0; } + if(ttrobo[oldttscale][i]) { Patch_Free(ttrobo[oldttscale][i]); ttrobo[oldttscale][i] = 0; } + if(tttwot[oldttscale][i]) { Patch_Free(tttwot[oldttscale][i]); tttwot[oldttscale][i] = 0; } + if(ttrbtx[oldttscale][i]) { Patch_Free(ttrbtx[oldttscale][i]); ttrbtx[oldttscale][i] = 0; } + if(ttsoib[oldttscale][i]) { Patch_Free(ttsoib[oldttscale][i]); ttsoib[oldttscale][i] = 0; } + if(ttsoif[oldttscale][i]) { Patch_Free(ttsoif[oldttscale][i]); ttsoif[oldttscale][i] = 0; } + if(ttsoba[oldttscale][i]) { Patch_Free(ttsoba[oldttscale][i]); ttsoba[oldttscale][i] = 0; } + if(ttsobk[oldttscale][i]) { Patch_Free(ttsobk[oldttscale][i]); ttsobk[oldttscale][i] = 0; } + if(ttsodh[oldttscale][i]) { Patch_Free(ttsodh[oldttscale][i]); ttsodh[oldttscale][i] = 0; } + if(tttaib[oldttscale][i]) { Patch_Free(tttaib[oldttscale][i]); tttaib[oldttscale][i] = 0; } + if(tttaif[oldttscale][i]) { Patch_Free(tttaif[oldttscale][i]); tttaif[oldttscale][i] = 0; } + if(tttaba[oldttscale][i]) { Patch_Free(tttaba[oldttscale][i]); tttaba[oldttscale][i] = 0; } + if(tttabk[oldttscale][i]) { Patch_Free(tttabk[oldttscale][i]); tttabk[oldttscale][i] = 0; } + if(tttabt[oldttscale][i]) { Patch_Free(tttabt[oldttscale][i]); tttabt[oldttscale][i] = 0; } + if(tttaft[oldttscale][i]) { Patch_Free(tttaft[oldttscale][i]); tttaft[oldttscale][i] = 0; } + if(ttknib[oldttscale][i]) { Patch_Free(ttknib[oldttscale][i]); ttknib[oldttscale][i] = 0; } + if(ttknif[oldttscale][i]) { Patch_Free(ttknif[oldttscale][i]); ttknif[oldttscale][i] = 0; } + if(ttknba[oldttscale][i]) { Patch_Free(ttknba[oldttscale][i]); ttknba[oldttscale][i] = 0; } + if(ttknbk[oldttscale][i]) { Patch_Free(ttknbk[oldttscale][i]); ttknbk[oldttscale][i] = 0; } + if(ttkndh[oldttscale][i]) { Patch_Free(ttkndh[oldttscale][i]); ttkndh[oldttscale][i] = 0; } } ttloaded[oldttscale] = false; } diff --git a/src/g_demo.c b/src/g_demo.c index 9d3b86015..593fd7723 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1956,9 +1956,7 @@ void G_DoPlayDemo(char *defdemoname) // Set skin SetPlayerSkin(0, skin); -#ifdef HAVE_BLUA LUAh_MapChange(gamemap); -#endif displayplayer = consoleplayer = 0; memset(playeringame,0,sizeof(playeringame)); playeringame[0] = true; diff --git a/src/g_game.c b/src/g_game.c index e9b275e05..13423ce77 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -444,9 +444,7 @@ consvar_t cv_firenaxis2 = CVAR_INIT ("joyaxis2_firenormal", "Z-Axis", CV_SAVE, j consvar_t cv_deadzone2 = CVAR_INIT ("joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); consvar_t cv_digitaldeadzone2 = CVAR_INIT ("joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); -#ifdef SEENAMES player_t *seenplayer; // player we're aiming at right now -#endif // now automatically allocated in D_RegisterClientCommands // so that it doesn't have to be updated depending on the value of MAXPLAYERS @@ -1680,7 +1678,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // At this point, cmd doesn't contain the final angle yet, // So we need to temporarily transform it so Lua scripters // don't need to handle it differently than in other hooks. - if (gamestate == GS_LEVEL) + if (addedtogame && gamestate == GS_LEVEL) { INT16 extra = ticcmd_oldangleturn[forplayer] - player->oldrelangleturn; INT16 origangle = cmd->angleturn; @@ -2293,14 +2291,21 @@ void G_Ticker(boolean run) { if (playeringame[i]) { + INT16 received; + G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); + received = (players[i].cmd.angleturn & TICCMD_RECEIVED); + players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn; players[i].oldrelangleturn = players[i].cmd.angleturn; if (P_ControlStyle(&players[i]) == CS_LMAOGALOG) P_ForceLocalAngle(&players[i], players[i].angleturn << 16); else players[i].cmd.angleturn = players[i].angleturn; + + players[i].cmd.angleturn &= ~TICCMD_RECEIVED; + players[i].cmd.angleturn |= received; } } @@ -3968,6 +3973,7 @@ static void G_DoCompleted(void) { G_SetGamestate(GS_INTERMISSION); Y_StartIntermission(); + Y_LoadIntermissionData(); G_UpdateVisited(); G_HandleSaveLevel(); } diff --git a/src/g_game.h b/src/g_game.h index 2bcf444c2..744d6755a 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -25,9 +25,7 @@ extern char timeattackfolder[64]; extern char customversionstring[32]; #define GAMEDATASIZE (4*8192) -#ifdef SEENAMES extern player_t *seenplayer; -#endif extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; extern INT32 player_name_changes[MAXPLAYERS]; diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index fb3417158..b13ad03ea 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -137,6 +137,8 @@ static int comparePolygons(const void *p1, const void *p2) PolygonArrayEntry* poly2 = &polygonArray[index2]; int diff; INT64 diff64; + UINT32 downloaded1 = 0; + UINT32 downloaded2 = 0; int shader1 = poly1->shader; int shader2 = poly2->shader; @@ -152,7 +154,11 @@ static int comparePolygons(const void *p1, const void *p2) if (shader1 == -1 && shader2 == -1) return index1 - index2; - diff64 = poly1->texture - poly2->texture; + if (poly1->texture) + downloaded1 = poly1->texture->downloaded; // there should be a opengl texture name here, usable for comparisons + if (poly2->texture) + downloaded2 = poly2->texture->downloaded; + diff64 = downloaded1 - downloaded2; if (diff64 != 0) return diff64; diff = poly1->polyFlags - poly2->polyFlags; @@ -184,16 +190,21 @@ static int comparePolygonsNoShaders(const void *p1, const void *p2) GLMipmap_t *texture1 = poly1->texture; GLMipmap_t *texture2 = poly2->texture; + UINT32 downloaded1 = 0; + UINT32 downloaded2 = 0; if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) texture1 = NULL; if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) texture2 = NULL; - diff64 = texture1 - texture2; - if (diff64 != 0) return diff64; - + if (texture1) + downloaded1 = texture1->downloaded; // there should be a opengl texture name here, usable for comparisons + if (texture2) + downloaded2 = texture2->downloaded; // skywalls and horizon lines must retain their order for horizon lines to work - if (texture1 == NULL && texture2 == NULL) + if (!texture1 && !texture2) return index1 - index2; + diff64 = downloaded1 - downloaded2; + if (diff64 != 0) return diff64; diff = poly1->polyFlags - poly2->polyFlags; if (diff != 0) return diff; diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h index 3d22324ac..42291a0df 100644 --- a/src/hardware/hw_batching.h +++ b/src/hardware/hw_batching.h @@ -16,7 +16,7 @@ #include "hw_data.h" #include "hw_drv.h" -typedef struct +typedef struct { FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused unsigned int vertsIndex;// location of verts in unsortedVertexArray diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index b4fa7ec6c..83a4e2e03 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -108,7 +108,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm //Hurdler: 25/04/2000: now support colormap in hardware mode if (mipmap->colormap) - texel = mipmap->colormap[texel]; + texel = mipmap->colormap->data[texel]; // hope compiler will get this switch out of the loops (dreams...) // gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?) @@ -218,7 +218,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, //Hurdler: 25/04/2000: now support colormap in hardware mode if (mipmap->colormap) - texel = mipmap->colormap[texel]; + texel = mipmap->colormap->data[texel]; // hope compiler will get this switch out of the loops (dreams...) // gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?) @@ -659,7 +659,10 @@ void HWR_FreeTextureColormaps(patch_t *patch) // Free image data from memory. if (next->data) Z_Free(next->data); + if (next->colormap) + Z_Free(next->colormap); next->data = NULL; + next->colormap = NULL; HWD.pfnDeleteTexture(next); // Free the old colormap mipmap from memory. @@ -667,16 +670,29 @@ void HWR_FreeTextureColormaps(patch_t *patch) } } +static boolean FreeTextureCallback(void *mem) +{ + patch_t *patch = (patch_t *)mem; + HWR_FreeTexture(patch); + return false; +} + +static boolean FreeColormapsCallback(void *mem) +{ + patch_t *patch = (patch_t *)mem; + HWR_FreeTextureColormaps(patch); + return false; +} + static void HWR_FreePatchCache(boolean freeall) { - INT32 i; + boolean (*callback)(void *mem) = FreeTextureCallback; - for (i = 0; i < numwadfiles; i++) - { - INT32 j = 0; - for (; j < wadfiles[i]->numlumps; j++) - (freeall ? HWR_FreeTexture : HWR_FreeTextureColormaps)(wadfiles[i]->patchcache[j]); - } + if (!freeall) + callback = FreeColormapsCallback; + + Z_IterateTags(PU_PATCH, PU_PATCH_ROTATED, callback); + Z_IterateTags(PU_SPRITE, PU_HUDGFX, callback); } // free all textures after each level @@ -850,7 +866,7 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum) } // Download a Doom 'flat' to the hardware cache and make it ready for use -void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum) +void HWR_GetRawFlat(lumpnum_t flatlumpnum) { GLMipmap_t *grmip; patch_t *patch; @@ -879,7 +895,7 @@ void HWR_GetLevelFlat(levelflat_t *levelflat) return; if (levelflat->type == LEVELFLAT_FLAT) - HWR_LiterallyGetFlat(levelflat->u.flat.lumpnum); + HWR_GetRawFlat(levelflat->u.flat.lumpnum); else if (levelflat->type == LEVELFLAT_TEXTURE) { GLMapTexture_t *grtex; @@ -918,15 +934,17 @@ void HWR_GetLevelFlat(levelflat_t *levelflat) #ifndef NO_PNG_LUMPS else if (levelflat->type == LEVELFLAT_PNG) { - INT32 pngwidth = 0, pngheight = 0; GLMipmap_t *mipmap = levelflat->mipmap; - UINT8 *flat; - size_t size; // Cache the picture. - if (!levelflat->picture) + if (!levelflat->mippic) { - levelflat->picture = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0); + INT32 pngwidth = 0, pngheight = 0; + void *pic = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0); + + Z_ChangeTag(pic, PU_LEVEL); + Z_SetUser(pic, &levelflat->mippic); + levelflat->width = (UINT16)pngwidth; levelflat->height = (UINT16)pngheight; } @@ -934,7 +952,7 @@ void HWR_GetLevelFlat(levelflat_t *levelflat) // Make the mipmap. if (mipmap == NULL) { - mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_LEVEL, NULL); + mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_STATIC, NULL); mipmap->format = GL_TEXFMT_P_8; mipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; levelflat->mipmap = mipmap; @@ -942,17 +960,22 @@ void HWR_GetLevelFlat(levelflat_t *levelflat) if (!mipmap->data && !mipmap->downloaded) { + UINT8 *flat; + size_t size; + + if (levelflat->mippic == NULL) + I_Error("HWR_GetLevelFlat: levelflat->mippic == NULL"); + mipmap->width = levelflat->width; mipmap->height = levelflat->height; + size = (mipmap->width * mipmap->height); flat = Z_Malloc(size, PU_LEVEL, &mipmap->data); - if (levelflat->picture == NULL) - I_Error("HWR_GetLevelFlat: levelflat->picture == NULL"); - M_Memcpy(flat, levelflat->picture, size); + M_Memcpy(flat, levelflat->mippic, size); } // Tell the hardware driver to bind the current texture to the flat's mipmap - HWD.pfnSetTexture(mipmap); + HWR_SetCurrentTexture(mipmap); } #endif else // set no texture @@ -977,8 +1000,28 @@ static void HWR_LoadPatchMipmap(patch_t *patch, GLMipmap_t *grMipmap) Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED); } +// ----------------------+ +// HWR_UpdatePatchMipmap : Updates a mipmap. +// ----------------------+ +static void HWR_UpdatePatchMipmap(patch_t *patch, GLMipmap_t *grMipmap) +{ + GLPatch_t *grPatch = patch->hardware; + HWR_MakePatch(patch, grPatch, grMipmap, true); + + // If hardware does not have the texture, then call pfnSetTexture to upload it + // If it does have the texture, then call pfnUpdateTexture to update it + if (!grMipmap->downloaded) + HWD.pfnSetTexture(grMipmap); + else + HWD.pfnUpdateTexture(grMipmap); + HWR_SetCurrentTexture(grMipmap); + + // The system-memory data can be purged now. + Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED); +} + // -----------------+ -// HWR_GetPatch : Download a patch to the hardware cache and make it ready for use +// HWR_GetPatch : Downloads a patch to the hardware cache and make it ready for use // -----------------+ void HWR_GetPatch(patch_t *patch) { @@ -1006,14 +1049,20 @@ void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap) return; } - // search for the mimmap + // search for the mipmap // skip the first (no colormap translated) for (grMipmap = grPatch->mipmap; grMipmap->nextcolormap; ) { grMipmap = grMipmap->nextcolormap; - if (grMipmap->colormap == colormap) + if (grMipmap->colormap && grMipmap->colormap->source == colormap) { - HWR_LoadPatchMipmap(patch, grMipmap); + if (memcmp(grMipmap->colormap->data, colormap, 256 * sizeof(UINT8))) + { + M_Memcpy(grMipmap->colormap->data, colormap, 256 * sizeof(UINT8)); + HWR_UpdatePatchMipmap(patch, grMipmap); + } + else + HWR_LoadPatchMipmap(patch, grMipmap); return; } } @@ -1029,7 +1078,10 @@ void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap) I_Error("%s: Out of memory", "HWR_GetMappedPatch"); grMipmap->nextcolormap = newMipmap; - newMipmap->colormap = colormap; + newMipmap->colormap = Z_Calloc(sizeof(*newMipmap->colormap), PU_HWRPATCHCOLMIPMAP, NULL); + newMipmap->colormap->source = colormap; + M_Memcpy(newMipmap->colormap->data, colormap, 256 * sizeof(UINT8)); + HWR_LoadPatchMipmap(patch, newMipmap); } @@ -1039,7 +1091,6 @@ void HWR_UnlockCachedPatch(GLPatch_t *gpatch) return; Z_ChangeTag(gpatch->mipmap->data, PU_HWRCACHE_UNLOCKED); - Z_ChangeTag(gpatch, PU_HWRPATCHINFO_UNLOCKED); } static const INT32 picmode2GR[] = diff --git a/src/hardware/hw_data.h b/src/hardware/hw_data.h index 3ae4ef8bc..7e56a14d0 100644 --- a/src/hardware/hw_data.h +++ b/src/hardware/hw_data.h @@ -39,45 +39,53 @@ typedef enum GLTextureFormat_e GL_TEXFMT_ALPHA_INTENSITY_88 = 0x22, } GLTextureFormat_t; -// data holds the address of the graphics data cached in heap memory -// NULL if the texture is not in Doom heap cache. +// Colormap structure for mipmaps. +struct GLColormap_s +{ + const UINT8 *source; + UINT8 data[256]; +}; +typedef struct GLColormap_s GLColormap_t; + + +// Texture information (misleadingly named "mipmap" all over the code.) +// The *data pointer holds the address of the graphics data cached in heap memory. +// NULL if the texture is not in SRB2's heap cache. struct GLMipmap_s { - // for TexDownloadMipMap + // for UpdateTexture GLTextureFormat_t format; void *data; UINT32 flags; UINT16 height; UINT16 width; - UINT32 downloaded; // The GPU has this texture. + UINT32 downloaded; // The GPU has this texture. struct GLMipmap_s *nextcolormap; - const UINT8 *colormap; - - struct GLMipmap_s *nextmipmap; // Linked list of all textures + struct GLColormap_s *colormap; }; typedef struct GLMipmap_s GLMipmap_t; // -// Doom texture info, as cached for hardware rendering +// Level textures, as cached for hardware rendering. // struct GLMapTexture_s { GLMipmap_t mipmap; - float scaleX; //used for scaling textures on walls + float scaleX; // Used for scaling textures on walls float scaleY; }; typedef struct GLMapTexture_s GLMapTexture_t; -// a cached patch as converted to hardware format +// Patch information for the hardware renderer. struct GLPatch_s { - float max_s,max_t; - GLMipmap_t *mipmap; -} ATTRPACK; + GLMipmap_t *mipmap; // Texture data. Allocated whenever the patch is. + float max_s, max_t; +}; typedef struct GLPatch_s GLPatch_t; #endif //_HWR_DATA_ diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index a782762a3..4bff8fc6a 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -216,14 +216,13 @@ enum EPolyFlags PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pixels are discarded (holes in texture) PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency PF_Environment = 0x00000004, // Poly should be drawn environment mapped. (Hurdler: used for text drawing) - PF_Additive = 0x00000008, // Additive color blending - PF_AdditiveSource = 0x00000010, // Source blending factor is additive. This is the opposite of regular additive blending. - PF_Subtractive = 0x00000020, // Subtractive color blending - PF_ReverseSubtract = 0x00000040, // Reverse subtract, used in wall splats (decals) - PF_Multiplicative = 0x00000080, // Multiplicative color blending + PF_Additive = 0x00000008, // Source blending factor is additive. + PF_Subtractive = 0x00000010, // Subtractive color blending + PF_ReverseSubtract = 0x00000020, // Reverse subtract, used in wall splats (decals) + PF_Multiplicative = 0x00000040, // Multiplicative color blending PF_Fog = 0x20000000, // Fog blocks PF_NoAlphaTest = 0x40000000, // Disables alpha testing - PF_Blending = (PF_Masked|PF_Translucent|PF_Environment|PF_Additive|PF_AdditiveSource|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative|PF_Fog) & ~PF_NoAlphaTest, + PF_Blending = (PF_Masked|PF_Translucent|PF_Environment|PF_Additive|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative|PF_Fog) & ~PF_NoAlphaTest, // other flag bits PF_Occlude = 0x00000100, // Updates the depth buffer @@ -255,7 +254,16 @@ enum ETextureFlags TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0 }; -typedef struct GLMipmap_s FTextureInfo; +struct FTextureInfo +{ + UINT32 width, height; + UINT32 downloaded; + UINT32 format; + + struct GLMipmap_s *texture; + struct FTextureInfo *prev, *next; +}; +typedef struct FTextureInfo FTextureInfo; // jimita 14032019 struct FLightInfo diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 0322e9d27..8722495e4 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -712,7 +712,7 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum v[0].t = v[1].t = (float)((y & flatflag)/dflatsize); v[2].t = v[3].t = (float)(v[0].t + h/dflatsize); - HWR_LiterallyGetFlat(flatlumpnum); + HWR_GetRawFlat(flatlumpnum); //Hurdler: Boris, the same comment as above... but maybe for pics // it not a problem since they don't have any transparent pixel diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 5a2e0e44e..da4ee8614 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -40,13 +40,12 @@ EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutV EXPORT void HWRAPI(RenderSkyDome) (gl_sky_t *sky); EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); -EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); -EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo); -EXPORT void HWRAPI(DeleteTexture) (FTextureInfo *TexInfo); +EXPORT void HWRAPI(SetTexture) (GLMipmap_t *TexInfo); +EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *TexInfo); +EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *TexInfo); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(ClearMipMapCache) (void); -EXPORT void HWRAPI(ClearCacheList) (void); //Hurdler: added for backward compatibility EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); @@ -101,7 +100,6 @@ struct hwdriver_s ReadRect pfnReadRect; GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; - ClearCacheList pfnClearCacheList; SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility DrawModel pfnDrawModel; CreateModelVBOs pfnCreateModelVBOs; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 87405d3d4..2aba62248 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -118,7 +118,7 @@ patch_t *HWR_GetPic(lumpnum_t lumpnum); GLMapTexture_t *HWR_GetTexture(INT32 tex); void HWR_GetLevelFlat(levelflat_t *levelflat); -void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum); +void HWR_GetRawFlat(lumpnum_t flatlumpnum); void HWR_FreeTexture(patch_t *patch); void HWR_FreeTextureData(patch_t *patch); diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 987d70c69..e83d9a6ec 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -35,7 +35,7 @@ #define DL_HIGH_QUALITY //#define STATICLIGHT //Hurdler: TODO! -#define LIGHTMAPFLAGS (PF_Modulated|PF_AdditiveSource) +#define LIGHTMAPFLAGS (PF_Modulated|PF_Additive) #ifdef ALAM_LIGHTING static dynlights_t view_dynlights[2]; // 2 players in splitscreen mode @@ -253,6 +253,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_SIGN &lspr[NOLIGHT], // SPR_SPIK &lspr[NOLIGHT], // SPR_SFLM + &lspr[NOLIGHT], // SPR_TFLM &lspr[NOLIGHT], // SPR_USPK &lspr[NOLIGHT], // SPR_WSPK &lspr[NOLIGHT], // SPR_WSPB @@ -1055,7 +1056,7 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gl_vissprite_t *spr) HWR_GetPic(coronalumpnum); /// \todo use different coronas - HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_Corona | PF_NoDepthTest); + HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Corona | PF_NoDepthTest); } } #endif @@ -1143,7 +1144,7 @@ void HWR_DrawCoronas(void) light[3].y = cy+size*1.33f; light[3].s = 0.0f; light[3].t = 1.0f; - HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_NoDepthTest | PF_Corona); + HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_NoDepthTest | PF_Corona); } } #endif diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c5f63654b..460a01788 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -706,6 +706,9 @@ FBITFIELD HWR_GetBlendModeFlag(INT32 ast) { switch (ast) { + case AST_COPY: + case AST_OVERLAY: + return PF_Masked; case AST_ADD: return PF_Additive; case AST_SUBTRACT: @@ -744,7 +747,7 @@ UINT8 HWR_GetTranstableAlpha(INT32 transtablenum) FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf) { - if (!transtablenum) + if (!transtablenum || style == AST_COPY || style == AST_OVERLAY) { pSurf->PolyColor.s.alpha = 0xff; return PF_Masked; @@ -3665,7 +3668,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts, const boolean precip) { if (cv_glspritebillboarding.value - && spr && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE) + && spr && spr->mobj && !R_ThingIsPaperSprite(spr->mobj) && wallVerts) { float basey = FIXED_TO_FLOAT(spr->mobj->z); @@ -3707,7 +3710,6 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) FBITFIELD blend = 0; FBITFIELD occlusion; boolean use_linkdraw_hack = false; - boolean splat = R_ThingIsFloorSprite(spr->mobj); UINT8 alpha; INT32 i; @@ -3766,22 +3768,19 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) baseWallVerts[0].t = baseWallVerts[1].t = ((GLPatch_t *)gpatch->hardware)->max_t; } - if (!splat) - { - // if it has a dispoffset, push it a little towards the camera - if (spr->dispoffset) { - float co = -gl_viewcos*(0.05f*spr->dispoffset); - float si = -gl_viewsin*(0.05f*spr->dispoffset); - baseWallVerts[0].z = baseWallVerts[3].z = baseWallVerts[0].z+si; - baseWallVerts[1].z = baseWallVerts[2].z = baseWallVerts[1].z+si; - baseWallVerts[0].x = baseWallVerts[3].x = baseWallVerts[0].x+co; - baseWallVerts[1].x = baseWallVerts[2].x = baseWallVerts[1].x+co; - } - - // Let dispoffset work first since this adjust each vertex - HWR_RotateSpritePolyToAim(spr, baseWallVerts, false); + // if it has a dispoffset, push it a little towards the camera + if (spr->dispoffset) { + float co = -gl_viewcos*(0.05f*spr->dispoffset); + float si = -gl_viewsin*(0.05f*spr->dispoffset); + baseWallVerts[0].z = baseWallVerts[3].z = baseWallVerts[0].z+si; + baseWallVerts[1].z = baseWallVerts[2].z = baseWallVerts[1].z+si; + baseWallVerts[0].x = baseWallVerts[3].x = baseWallVerts[0].x+co; + baseWallVerts[1].x = baseWallVerts[2].x = baseWallVerts[1].x+co; } + // Let dispoffset work first since this adjust each vertex + HWR_RotateSpritePolyToAim(spr, baseWallVerts, false); + realtop = top = baseWallVerts[3].y; realbot = bot = baseWallVerts[0].y; ttop = baseWallVerts[3].t; @@ -3817,8 +3816,6 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) else if (spr->mobj->frame & FF_TRANSMASK) { INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; - if (spr->mobj->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) - return; blend = HWR_SurfaceBlend(spr->mobj->blendmode, trans, &Surf); } else @@ -3914,7 +3911,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) // The x and y only need to be adjusted in the case that it's not a papersprite if (cv_glspritebillboarding.value - && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE)) + && spr->mobj && !R_ThingIsPaperSprite(spr->mobj)) { // Get the x and z of the vertices so billboarding draws correctly realheight = realbot - realtop; @@ -3983,7 +3980,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) static void HWR_DrawSprite(gl_vissprite_t *spr) { FOutVector wallVerts[4]; - patch_t *gpatch; // sprite patch converted to hardware + patch_t *gpatch; FSurfaceInfo Surf; const boolean splat = R_ThingIsFloorSprite(spr->mobj); @@ -4141,6 +4138,11 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) wallVerts[1].z = wallVerts[2].z = spr->z2; } + // cache the patch in the graphics card memory + //12/12/99: Hurdler: same comment as above (for md2) + //Hurdler: 25/04/2000: now support colormap in hardware mode + HWR_GetMappedPatch(gpatch, spr->colormap); + if (spr->flip) { wallVerts[0].s = wallVerts[3].s = ((GLPatch_t *)gpatch->hardware)->max_s; @@ -4160,11 +4162,6 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) wallVerts[0].t = wallVerts[1].t = ((GLPatch_t *)gpatch->hardware)->max_t; } - // cache the patch in the graphics card memory - //12/12/99: Hurdler: same comment as above (for md2) - //Hurdler: 25/04/2000: now support colormap in hardware mode - HWR_GetMappedPatch(gpatch, spr->colormap); - if (!splat) { // if it has a dispoffset, push it a little towards the camera @@ -4244,8 +4241,6 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) else if (spr->mobj->frame & FF_TRANSMASK) { INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; - if (spr->mobj->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) - return; blend = HWR_SurfaceBlend(spr->mobj->blendmode, trans, &Surf); } else @@ -4284,7 +4279,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) { FBITFIELD blend = 0; FOutVector wallVerts[4]; - patch_t *gpatch; // sprite patch converted to hardware + patch_t *gpatch; FSurfaceInfo Surf; if (!spr->mobj) @@ -4337,7 +4332,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) // Always use the light at the top instead of whatever I was doing before INT32 light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); - if (!(spr->mobj->frame & FF_FULLBRIGHT)) + if (!R_ThingIsFullBright(spr->mobj)) lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel; if (*sector->lightlist[light].extra_colormap) @@ -4345,7 +4340,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) } else { - if (!(spr->mobj->frame & FF_FULLBRIGHT)) + if (!R_ThingIsFullBright(spr->mobj)) lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; if (sector->extra_colormap) @@ -4358,9 +4353,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) if (spr->mobj->frame & FF_TRANSMASK) { INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; - if (spr->mobj->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) - return; - blend = HWR_SurfaceBlend(spr->mobj->blendmode, trans, &Surf); + blend = HWR_SurfaceBlend(AST_TRANSLUCENT, trans, &Surf); } else { @@ -4921,8 +4914,8 @@ static void HWR_ProjectSprite(mobj_t *thing) angle_t ang; INT32 heightsec, phs; - const boolean papersprite = R_ThingIsPaperSprite(thing); const boolean splat = R_ThingIsFloorSprite(thing); + const boolean papersprite = (R_ThingIsPaperSprite(thing) && !splat); angle_t mobjangle = (thing->player ? thing->player->drawangle : thing->angle); float z1, z2; @@ -4939,6 +4932,13 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->spritexscale < 1 || thing->spriteyscale < 1) return; + // Visibility check by the blend mode. + if (thing->frame & FF_TRANSMASK) + { + if (!R_BlendLevelVisible(thing->blendmode, (thing->frame & FF_TRANSMASK)>>FF_TRANSSHIFT)) + return; + } + dispoffset = thing->info->dispoffset; this_scale = FIXED_TO_FLOAT(thing->scale); @@ -5295,7 +5295,7 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->colormap = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color ? vis->mobj->color : SKINCOLOR_CYAN, GTC_CACHE); } else - vis->colormap = colormaps; + vis->colormap = NULL; // set top/bottom coords vis->gzt = gzt; @@ -5325,6 +5325,13 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) unsigned rot = 0; UINT8 flip; + // Visibility check by the blend mode. + if (thing->frame & FF_TRANSMASK) + { + if (!R_BlendLevelVisible(thing->blendmode, (thing->frame & FF_TRANSMASK)>>FF_TRANSSHIFT)) + return; + } + // transform the origin point tr_x = FIXED_TO_FLOAT(thing->x) - gl_viewx; tr_y = FIXED_TO_FLOAT(thing->y) - gl_viewy; @@ -5358,7 +5365,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) return; #endif - sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK]; + sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK]; // use single rotation for all views lumpoff = sprframe->lumpid[0]; @@ -5396,7 +5403,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->flip = flip; vis->mobj = (mobj_t *)thing; - vis->colormap = colormaps; + vis->colormap = NULL; // set top/bottom coords vis->gzt = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); @@ -6514,7 +6521,7 @@ void HWR_DoPostProcessor(player_t *player) Surf.PolyColor.s.alpha = 0xc0; // match software mode - HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_AdditiveSource|PF_NoTexture|PF_NoDepthTest); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest); } // Capture the screen for intermission and screen waving diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 9c786e67e..5caf344f7 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -158,7 +158,7 @@ static GLTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_ jmp_buf jmpbuf; #endif #endif - png_FILE_p png_FILE; + volatile png_FILE_p png_FILE; //Filename checking fixed ~Monster Iestyn and Golden char *pngfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2home, filename); @@ -1106,11 +1106,19 @@ static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 ski for (grMipmap = grPatch->mipmap; grMipmap->nextcolormap; ) { grMipmap = grMipmap->nextcolormap; - if (grMipmap->colormap == colormap) + if (grMipmap->colormap && grMipmap->colormap->source == colormap) { if (grMipmap->downloaded && grMipmap->data) { - HWD.pfnSetTexture(grMipmap); // found the colormap, set it to the correct texture + if (memcmp(grMipmap->colormap->data, colormap, 256 * sizeof(UINT8))) + { + M_Memcpy(grMipmap->colormap->data, colormap, 256 * sizeof(UINT8)); + HWR_CreateBlendedTexture(patch, blendpatch, grMipmap, skinnum, color); + HWD.pfnUpdateTexture(grMipmap); + } + else + HWD.pfnSetTexture(grMipmap); // found the colormap, set it to the correct texture + Z_ChangeTag(grMipmap->data, PU_HWRMODELTEXTURE_UNLOCKED); return; } @@ -1128,7 +1136,10 @@ static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 ski if (newMipmap == NULL) I_Error("%s: Out of memory", "HWR_GetBlendedTexture"); grMipmap->nextcolormap = newMipmap; - newMipmap->colormap = colormap; + + newMipmap->colormap = Z_Calloc(sizeof(*newMipmap->colormap), PU_HWRPATCHCOLMIPMAP, NULL); + newMipmap->colormap->source = colormap; + M_Memcpy(newMipmap->colormap->data, colormap, 256 * sizeof(UINT8)); HWR_CreateBlendedTexture(patch, blendpatch, newMipmap, skinnum, color); @@ -1303,7 +1314,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before - if (!(spr->mobj->frame & FF_FULLBRIGHT)) + if (!R_ThingIsFullBright(spr->mobj)) lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel; if (*sector->lightlist[light].extra_colormap) @@ -1311,7 +1322,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) } else { - if (!(spr->mobj->frame & FF_FULLBRIGHT)) + if (!R_ThingIsFullBright(spr->mobj)) lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; if (sector->extra_colormap) @@ -1329,10 +1340,9 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL; INT32 durs = spr->mobj->state->tics; INT32 tics = spr->mobj->tics; - //mdlframe_t *next = NULL; - const boolean papersprite = (spr->mobj->frame & FF_PAPERSPRITE); - const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP)); - const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !(spr->mobj->frame & FF_HORIZONTALFLIP)); + const boolean papersprite = (R_ThingIsPaperSprite(spr->mobj) && !R_ThingIsFloorSprite(spr->mobj)); + const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !R_ThingVerticallyFlipped(spr->mobj)); + const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !R_ThingHorizontallyFlipped(spr->mobj)); spritedef_t *sprdef; spriteframe_t *sprframe; spriteinfo_t *sprinfo; @@ -1394,6 +1404,11 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) || ((!hwrBlendPatch->mipmap->format || !hwrBlendPatch->mipmap->downloaded) && !md2->noblendfile))) md2_loadBlendTexture(md2); + // Load it again, because it isn't being loaded into blendgpatch after md2_loadblendtexture... + blendgpatch = md2->blendgrpatch; + if (blendgpatch) + hwrBlendPatch = ((GLPatch_t *)blendgpatch->hardware); + if (md2->error) return false; // we already failed loading this before :( if (!md2->model) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 8cd948eea..aee0ffc45 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -58,8 +58,9 @@ static GLuint tex_downloaded = 0; static GLfloat fov = 90.0f; static FBITFIELD CurrentPolyFlags; -static FTextureInfo *gl_cachetail = NULL; -static FTextureInfo *gl_cachehead = NULL; +// Linked list of all textures. +static FTextureInfo *TexCacheTail = NULL; +static FTextureInfo *TexCacheHead = NULL; RGBA_t myPaletteData[256]; GLint screen_width = 0; // used by Draw2DLine() @@ -961,8 +962,6 @@ EXPORT boolean HWRAPI(CompileShaders) (void) } } - SetShader(SHADER_DEFAULT); - return true; #else return false; @@ -1287,10 +1286,34 @@ void SetStates(void) // -----------------+ // DeleteTexture : Deletes a texture from the GPU and frees its data // -----------------+ -EXPORT void HWRAPI(DeleteTexture) (FTextureInfo *pTexInfo) +EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *pTexInfo) { - if (pTexInfo->downloaded) + FTextureInfo *head = TexCacheHead; + + if (!pTexInfo) + return; + else if (pTexInfo->downloaded) pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded); + + while (head) + { + if (head->downloaded == pTexInfo->downloaded) + { + if (head->next) + head->next->prev = head->prev; + else // no next -> tail is being deleted -> update TexCacheTail + TexCacheTail = head->prev; + if (head->prev) + head->prev->next = head->next; + else // no prev -> head is being deleted -> update TexCacheHead + TexCacheHead = head->next; + free(head); + break; + } + + head = head->next; + } + pTexInfo->downloaded = 0; } @@ -1303,26 +1326,29 @@ void Flush(void) { //GL_DBG_Printf ("HWR_Flush()\n"); - while (gl_cachehead) + while (TexCacheHead) { - DeleteTexture(gl_cachehead); - gl_cachehead = gl_cachehead->nextmipmap; + FTextureInfo *pTexInfo = TexCacheHead; + GLMipmap_t *texture = pTexInfo->texture; + + if (pTexInfo->downloaded) + { + pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded); + pTexInfo->downloaded = 0; + } + + if (texture) + texture->downloaded = 0; + + TexCacheHead = pTexInfo->next; + free(pTexInfo); } - ClearCacheList(); //Hurdler: well, gl_cachehead is already NULL + TexCacheTail = TexCacheHead = NULL; //Hurdler: well, TexCacheHead is already NULL tex_downloaded = 0; } -// -----------------+ -// ClearCacheList : Clears the texture cache tail and head -// -----------------+ -EXPORT void HWRAPI(ClearCacheList) (void) -{ - gl_cachetail = gl_cachehead = NULL; -} - - // -----------------+ // isExtAvailable : Look if an OpenGL extension is available // Returns : true if extension available @@ -1554,12 +1580,11 @@ static void SetBlendMode(FBITFIELD flags) case PF_Additive & PF_Blending: case PF_Subtractive & PF_Blending: case PF_ReverseSubtract & PF_Blending: + pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest + break; case PF_Environment & PF_Blending: pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); break; - case PF_AdditiveSource & PF_Blending: - pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest - break; case PF_Multiplicative & PF_Blending: pglBlendFunc(GL_DST_COLOR, GL_ZERO); break; @@ -1598,7 +1623,6 @@ static void SetBlendMode(FBITFIELD flags) break; case PF_Translucent & PF_Blending: case PF_Additive & PF_Blending: - case PF_AdditiveSource & PF_Blending: case PF_Subtractive & PF_Blending: case PF_ReverseSubtract & PF_Blending: case PF_Environment & PF_Blending: @@ -1718,7 +1742,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) // -----------------+ // UpdateTexture : Updates the texture data. // -----------------+ -EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *pTexInfo) +EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) { // Download a mipmap boolean updatemipmap = true; @@ -1920,7 +1944,7 @@ EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *pTexInfo) // -----------------+ // SetTexture : The mipmap becomes the current texture source // -----------------+ -EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) +EXPORT void HWRAPI(SetTexture) (GLMipmap_t *pTexInfo) { if (!pTexInfo) { @@ -1937,17 +1961,25 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } else { + FTextureInfo *newTex = calloc(1, sizeof (*newTex)); + UpdateTexture(pTexInfo); - pTexInfo->nextmipmap = NULL; + + newTex->texture = pTexInfo; + newTex->downloaded = (UINT32)pTexInfo->downloaded; + newTex->width = (UINT32)pTexInfo->width; + newTex->height = (UINT32)pTexInfo->height; + newTex->format = (UINT32)pTexInfo->format; // insertion at the tail - if (gl_cachetail) + if (TexCacheTail) { - gl_cachetail->nextmipmap = pTexInfo; - gl_cachetail = pTexInfo; + newTex->prev = TexCacheTail; + TexCacheTail->next = newTex; + TexCacheTail = newTex; } else // initialization of the linked list - gl_cachetail = gl_cachehead = pTexInfo; + TexCacheTail = TexCacheHead = newTex; } } @@ -2722,7 +2754,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 fade.alpha = byte2float[Surface->FadeColor.s.alpha]; flags = (Surface->PolyFlags | PF_Modulated); - if (Surface->PolyFlags & (PF_Additive|PF_AdditiveSource|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative)) + if (Surface->PolyFlags & (PF_Additive|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative)) flags |= PF_Occlude; else if (Surface->PolyColor.s.alpha == 0xFF) flags |= (PF_Occlude | PF_Masked); @@ -3011,7 +3043,7 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) EXPORT INT32 HWRAPI(GetTextureUsed) (void) { - FTextureInfo *tmp = gl_cachehead; + FTextureInfo *tmp = TexCacheHead; INT32 res = 0; while (tmp) @@ -3028,7 +3060,7 @@ EXPORT INT32 HWRAPI(GetTextureUsed) (void) // Add it up! res += tmp->height*tmp->width*bpp; - tmp = tmp->nextmipmap; + tmp = tmp->next; } return res; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 7e9144f98..7c4f1acf1 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -98,6 +98,7 @@ patch_t *emeraldpics[3][8]; // 0 = normal, 1 = tiny, 2 = coinbox static patch_t *emblemicon; patch_t *tokenicon; static patch_t *exiticon; +static patch_t *nopingicon; //------------------------------------------- // misc vars @@ -286,6 +287,7 @@ void HU_LoadGraphics(void) emblemicon = W_CachePatchName("EMBLICON", PU_HUDGFX); tokenicon = W_CachePatchName("TOKNICON", PU_HUDGFX); exiticon = W_CachePatchName("EXITICON", PU_HUDGFX); + nopingicon = W_CachePatchName("NOPINGICON", PU_HUDGFX); emeraldpics[0][0] = W_CachePatchName("CHAOS1", PU_HUDGFX); emeraldpics[0][1] = W_CachePatchName("CHAOS2", PU_HUDGFX); @@ -2109,15 +2111,18 @@ void HU_Drawer(void) return; // draw the crosshair, not when viewing demos nor with chasecam - if (!automapactive && cv_crosshair.value && !demoplayback && - (!camera.chase || ticcmd_ztargetfocus[0]) - && !players[displayplayer].spectator) - HU_DrawCrosshair(); + if (LUA_HudEnabled(hud_crosshair)) + { + if (!automapactive && cv_crosshair.value && !demoplayback && + (!camera.chase || ticcmd_ztargetfocus[0]) + && !players[displayplayer].spectator) + HU_DrawCrosshair(); - if (!automapactive && cv_crosshair2.value && !demoplayback && - (!camera2.chase || ticcmd_ztargetfocus[1]) - && !players[secondarydisplayplayer].spectator) - HU_DrawCrosshair2(); + if (!automapactive && cv_crosshair2.value && !demoplayback && + (!camera2.chase || ticcmd_ztargetfocus[1]) + && !players[secondarydisplayplayer].spectator) + HU_DrawCrosshair2(); + } // draw desynch text if (hu_redownloadinggamestate) @@ -2243,8 +2248,8 @@ void HU_Erase(void) // void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags) { - UINT8 numbars = 1; // how many ping bars do we draw? - UINT8 barcolor = 35; // color we use for the bars (green, yellow or red) + UINT8 numbars = 0; // how many ping bars do we draw? + UINT8 barcolor = 31; // color we use for the bars (green, yellow, red or black) SINT8 i = 0; SINT8 yoffset = 6; INT32 dx = x+1 - (V_SmallStringWidth(va("%dms", ping), @@ -2257,11 +2262,16 @@ void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags) } else if (ping < 256) { - numbars = 2; // Apparently ternaries w/ multiple statements don't look good in C so I decided against it. + numbars = 2; barcolor = 73; } + else if (ping < UINT32_MAX) + { + numbars = 1; + barcolor = 35; + } - if (!notext || vid.width >= 640) // how sad, we're using a shit resolution. + if (ping < UINT32_MAX && (!notext || vid.width >= 640)) // how sad, we're using a shit resolution. V_DrawSmallString(dx, y+4, V_ALLOWLOWERCASE|flags, va("%dms", ping)); for (i=0; (i<3); i++) // Draw the ping bar @@ -2272,6 +2282,9 @@ void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags) yoffset -= 2; } + + if (ping == UINT32_MAX) + V_DrawSmallScaledPatch(x + 4 - nopingicon->width/2, y + 9 - nopingicon->height/2, 0, nopingicon); } // @@ -2298,16 +2311,17 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I if (!splitscreen) // don't draw it on splitscreen, { - if (!(tab[i].num == serverplayer || players[tab[i].num].quittime)) - HU_drawPing(x+ 253, y, playerpingtable[tab[i].num], false, 0); + if (tab[i].num != serverplayer) + HU_drawPing(x + 253, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], false, 0); //else // V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER"); } - V_DrawString(x + 20, y, - ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | (greycheck ? V_60TRANS : 0) - | V_ALLOWLOWERCASE, tab[i].name); + if (!players[tab[i].num].quittime || (leveltime / (TICRATE/2) & 1)) + V_DrawString(x + 20, y, + ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) + | (greycheck ? V_60TRANS : 0) + | V_ALLOWLOWERCASE, tab[i].name); // Draw emeralds if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1)) @@ -2455,10 +2469,11 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) supercheck = supercheckdef; strlcpy(name, tab[i].name, 8); - V_DrawString(x + 10, y, - ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | (greycheck ? 0 : V_TRANSLUCENT) - | V_ALLOWLOWERCASE, name); + if (!players[tab[i].num].quittime || (leveltime / (TICRATE/2) & 1)) + V_DrawString(x + 10, y, + ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) + | (greycheck ? 0 : V_TRANSLUCENT) + | V_ALLOWLOWERCASE, name); if (gametyperules & GTR_TEAMFLAGS) { @@ -2497,10 +2512,10 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); if (!splitscreen) { - if (!(tab[i].num == serverplayer || players[tab[i].num].quittime)) - HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0); - //else - //V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); + if (tab[i].num != serverplayer) + HU_drawPing(x + 135, y+1, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], true, 0); + //else + //V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); } } } @@ -2583,10 +2598,11 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) supercheck = supercheckdef; strlcpy(name, tab[i].name, 7); - V_DrawString(x + 20, y, - ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | (greycheck ? V_TRANSLUCENT : 0) - | V_ALLOWLOWERCASE, name); + if (!players[tab[i].num].quittime || (leveltime / (TICRATE/2) & 1)) + V_DrawString(x + 20, y, + ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) + | (greycheck ? V_TRANSLUCENT : 0) + | V_ALLOWLOWERCASE, name); if (gametyperules & GTR_TEAMFLAGS) { @@ -2621,10 +2637,10 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) V_DrawRightAlignedThinString(x+100, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count)); if (!splitscreen) { - if (!(tab[i].num == serverplayer || players[tab[i].num].quittime)) - HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0); - //else - // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); + if (tab[i].num != serverplayer) + HU_drawPing(x+ 113, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], false, 0); + //else + // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); } } } @@ -2652,15 +2668,16 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline supercheck = supercheckdef; strlcpy(name, tab[i].name, 7); - if (!(tab[i].num == serverplayer || players[tab[i].num].quittime)) - HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0); + if (tab[i].num != serverplayer) + HU_drawPing(x+ 113, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], false, 0); //else // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); - V_DrawString(x + 20, y, - ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | (greycheck ? V_TRANSLUCENT : 0) - | V_ALLOWLOWERCASE, name); + if (!players[tab[i].num].quittime || (leveltime / (TICRATE/2) & 1)) + V_DrawString(x + 20, y, + ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) + | (greycheck ? V_TRANSLUCENT : 0) + | V_ALLOWLOWERCASE, name); if (G_GametypeUsesLives() && !(G_GametypeUsesCoopLives() && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives)); @@ -2760,16 +2777,17 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor strlcpy(name, tab[i].name, 7); if (!splitscreen) // don't draw it on splitscreen, { - if (!(tab[i].num == serverplayer || players[tab[i].num].quittime)) - HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0); - //else - // V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); + if (tab[i].num != serverplayer) + HU_drawPing(x+ 135, y+1, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], true, 0); + //else + // V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); } - V_DrawString(x + 10, y, - ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | (greycheck ? 0 : V_TRANSLUCENT) - | V_ALLOWLOWERCASE, name); + if (!players[tab[i].num].quittime || (leveltime / (TICRATE/2) & 1)) + V_DrawString(x + 10, y, + ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) + | (greycheck ? 0 : V_TRANSLUCENT) + | V_ALLOWLOWERCASE, name); if (G_GametypeUsesLives()) //show lives V_DrawRightAlignedThinString(x-1, y, V_ALLOWLOWERCASE, va("%d", players[tab[i].num].lives)); diff --git a/src/i_tcp.c b/src/i_tcp.c index 5180869a5..ab8a69a9f 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -20,127 +20,121 @@ #endif #ifndef NO_IPV6 -#define HAVE_IPV6 + #define HAVE_IPV6 #endif #ifdef _WIN32 -#define USE_WINSOCK -#if defined (_WIN64) || defined (HAVE_IPV6) -#define USE_WINSOCK2 -#else //_WIN64/HAVE_IPV6 -#define USE_WINSOCK1 -#endif + #define USE_WINSOCK + #if defined (_WIN64) || defined (HAVE_IPV6) + #define USE_WINSOCK2 + #else //_WIN64/HAVE_IPV6 + #define USE_WINSOCK1 + #endif #endif //WIN32 OS #ifdef USE_WINSOCK2 -#include + #include #endif #include "doomdef.h" #if defined (NOMD5) && !defined (NONET) -//#define NONET + //#define NONET #endif #ifdef NONET -#undef HAVE_MINIUPNPC + #undef HAVE_MINIUPNPC #else -#ifdef USE_WINSOCK1 -#include -#elif !defined (SCOUW2) && !defined (SCOUW7) -#ifndef USE_WINSOCK -#include -#endif //normal BSD API + #ifdef USE_WINSOCK1 + #include + #else + #ifndef USE_WINSOCK + #include + #ifdef __APPLE_CC__ + #ifndef _BSD_SOCKLEN_T_ + #define _BSD_SOCKLEN_T_ + #endif //_BSD_SOCKLEN_T_ + #endif //__APPLE_CC__ + #include + #include + #include + #include + #endif //normal BSD API -#ifndef USE_WINSOCK -#ifdef __APPLE_CC__ -#ifndef _BSD_SOCKLEN_T_ -#define _BSD_SOCKLEN_T_ -#endif //_BSD_SOCKLEN_T_ -#endif //__APPLE_CC__ -#include -#include -#endif //normal BSD API + #include + #include -#ifndef USE_WINSOCK -#include -#include -#endif //normal BSD API + #if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) + #include + #endif // UNIXCOMMON + #endif -#include -#include + #ifdef USE_WINSOCK + // some undefined under win32 + #undef errno + //#define errno WSAGetLastError() //Alam_GBC: this is the correct way, right? + #define errno h_errno // some very strange things happen when not using h_error?!? + #ifdef EWOULDBLOCK + #undef EWOULDBLOCK + #endif + #define EWOULDBLOCK WSAEWOULDBLOCK + #ifdef EMSGSIZE + #undef EMSGSIZE + #endif + #define EMSGSIZE WSAEMSGSIZE + #ifdef ECONNREFUSED + #undef ECONNREFUSED + #endif + #define ECONNREFUSED WSAECONNREFUSED + #ifdef ETIMEDOUT + #undef ETIMEDOUT + #endif + #define ETIMEDOUT WSAETIMEDOUT + #ifndef IOC_VENDOR + #define IOC_VENDOR 0x18000000 + #endif + #ifndef _WSAIOW + #define _WSAIOW(x,y) (IOC_IN|(x)|(y)) + #endif + #ifndef SIO_UDP_CONNRESET + #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) + #endif + #ifndef AI_ADDRCONFIG + #define AI_ADDRCONFIG 0x00000400 + #endif + #ifndef STATUS_INVALID_PARAMETER + #define STATUS_INVALID_PARAMETER 0xC000000D + #endif + #endif // USE_WINSOCK -#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) - #include -#endif // UNIXCOMMON -#endif // !NONET + #ifdef __DJGPP__ + #ifdef WATTCP // Alam_GBC: Wattcp may need this + #include + #define strerror strerror_s + #else // wattcp + #include + #endif // libsocket + #endif // djgpp -#ifdef USE_WINSOCK - // some undefined under win32 - #undef errno - //#define errno WSAGetLastError() //Alam_GBC: this is the correct way, right? - #define errno h_errno // some very strange things happen when not using h_error?!? - #ifdef EWOULDBLOCK - #undef EWOULDBLOCK + typedef union + { + struct sockaddr any; + struct sockaddr_in ip4; + #ifdef HAVE_IPV6 + struct sockaddr_in6 ip6; #endif - #define EWOULDBLOCK WSAEWOULDBLOCK - #ifdef EMSGSIZE - #undef EMSGSIZE - #endif - #define EMSGSIZE WSAEMSGSIZE - #ifdef ECONNREFUSED - #undef ECONNREFUSED - #endif - #define ECONNREFUSED WSAECONNREFUSED - #ifdef ETIMEDOUT - #undef ETIMEDOUT - #endif - #define ETIMEDOUT WSAETIMEDOUT - #ifndef IOC_VENDOR - #define IOC_VENDOR 0x18000000 - #endif - #ifndef _WSAIOW - #define _WSAIOW(x,y) (IOC_IN|(x)|(y)) - #endif - #ifndef SIO_UDP_CONNRESET - #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) - #endif - #ifndef AI_ADDRCONFIG - #define AI_ADDRCONFIG 0x00000400 - #endif - #ifndef STATUS_INVALID_PARAMETER - #define STATUS_INVALID_PARAMETER 0xC000000D - #endif -#endif + } mysockaddr_t; -#ifdef __DJGPP__ -#ifdef WATTCP // Alam_GBC: Wattcp may need this -#include -#define strerror strerror_s -#else // wattcp -#include -#endif // libsocket -#endif // djgpp - -typedef union -{ - struct sockaddr any; - struct sockaddr_in ip4; -#ifdef HAVE_IPV6 - struct sockaddr_in6 ip6; -#endif -} mysockaddr_t; - -#ifdef HAVE_MINIUPNPC -#ifdef STATIC_MINIUPNPC -#define STATICLIB -#endif -#include "miniupnpc/miniwget.h" -#include "miniupnpc/miniupnpc.h" -#include "miniupnpc/upnpcommands.h" -#undef STATICLIB -static UINT8 UPNP_support = TRUE; -#endif + #ifdef HAVE_MINIUPNPC + #ifdef STATIC_MINIUPNPC + #define STATICLIB + #endif + #include "miniupnpc/miniwget.h" + #include "miniupnpc/miniupnpc.h" + #include "miniupnpc/upnpcommands.h" + #undef STATICLIB + static UINT8 UPNP_support = TRUE; + #endif // HAVE_MINIUPNC #endif // !NONET @@ -177,32 +171,32 @@ static UINT8 UPNP_support = TRUE; #define DEFAULTPORT "5029" #if defined (USE_WINSOCK) && !defined (NONET) -typedef SOCKET SOCKET_TYPE; -#define ERRSOCKET (SOCKET_ERROR) + typedef SOCKET SOCKET_TYPE; + #define ERRSOCKET (SOCKET_ERROR) #else -#if (defined (__unix__) && !defined (MSDOS)) || defined (__APPLE__) || defined (__HAIKU__) -typedef int SOCKET_TYPE; -#else -typedef unsigned long SOCKET_TYPE; -#endif -#define ERRSOCKET (-1) -#endif - -#if (defined (WATTCP) && !defined (__libsocket_socklen_t)) || defined (USE_WINSOCK1) -typedef int socklen_t; + #if (defined (__unix__) && !defined (MSDOS)) || defined (__APPLE__) || defined (__HAIKU__) + typedef int SOCKET_TYPE; + #else + typedef unsigned long SOCKET_TYPE; + #endif + #define ERRSOCKET (-1) #endif #ifndef NONET -static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET}; -static size_t mysocketses = 0; -static int myfamily[MAXNETNODES+1] = {0}; -static SOCKET_TYPE nodesocket[MAXNETNODES+1] = {ERRSOCKET}; -static mysockaddr_t clientaddress[MAXNETNODES+1]; -static mysockaddr_t broadcastaddress[MAXNETNODES+1]; -static size_t broadcastaddresses = 0; -static boolean nodeconnected[MAXNETNODES+1]; -static mysockaddr_t banned[MAXBANS]; -static UINT8 bannedmask[MAXBANS]; + // define socklen_t in DOS/Windows if it is not already defined + #if (defined (WATTCP) && !defined (__libsocket_socklen_t)) || defined (USE_WINSOCK1) + typedef int socklen_t; + #endif + static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET}; + static size_t mysocketses = 0; + static int myfamily[MAXNETNODES+1] = {0}; + static SOCKET_TYPE nodesocket[MAXNETNODES+1] = {ERRSOCKET}; + static mysockaddr_t clientaddress[MAXNETNODES+1]; + static mysockaddr_t broadcastaddress[MAXNETNODES+1]; + static size_t broadcastaddresses = 0; + static boolean nodeconnected[MAXNETNODES+1]; + static mysockaddr_t banned[MAXBANS]; + static UINT8 bannedmask[MAXBANS]; #endif static size_t numbans = 0; diff --git a/src/info.c b/src/info.c index 56e764b5d..ee836a372 100644 --- a/src/info.c +++ b/src/info.c @@ -150,6 +150,7 @@ char sprnames[NUMSPRITES + 1][5] = "SIGN", // Level end sign "SPIK", // Spike Ball "SFLM", // Spin fire + "TFLM", // Spin fire (team) "USPK", // Floor spike "WSPK", // Wall spike "WSPB", // Wall spike base @@ -1894,6 +1895,13 @@ state_t states[NUMSTATES] = {SPR_SFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_SPINFIRE6}, // S_SPINFIRE5 {SPR_SFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_SPINFIRE1}, // S_SPINFIRE6 + {SPR_TFLM, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE2}, // S_TEAM_SPINFIRE1 + {SPR_TFLM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE3}, // S_TEAM_SPINFIRE2 + {SPR_TFLM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE4}, // S_TEAM_SPINFIRE3 + {SPR_TFLM, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE5}, // S_TEAM_SPINFIRE4 + {SPR_TFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE6}, // S_TEAM_SPINFIRE5 + {SPR_TFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE1}, // S_TEAM_SPINFIRE6 + // Floor Spike {SPR_USPK, 0,-1, {A_SpikeRetract}, 1, 0, S_SPIKE2}, // S_SPIKE1 -- Fully extended {SPR_USPK, 1, 2, {A_Pain}, 0, 0, S_SPIKE3}, // S_SPIKE2 @@ -3291,18 +3299,18 @@ state_t states[NUMSTATES] = {SPR_WZAP, FF_TRANS10|FF_ANIMATE|FF_RANDOMANIM, 4, {NULL}, 3, 2, S_NULL}, // S_WATERZAP // Spindash dust - {SPR_DUST, 0, 7, {NULL}, 0, 0, S_SPINDUST2}, // S_SPINDUST1 - {SPR_DUST, 1, 6, {NULL}, 0, 0, S_SPINDUST3}, // S_SPINDUST2 - {SPR_DUST, FF_TRANS30|2, 4, {NULL}, 0, 0, S_SPINDUST4}, // S_SPINDUST3 - {SPR_DUST, FF_TRANS60|3, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST4 - {SPR_BUBL, 0, 7, {NULL}, 0, 0, S_SPINDUST_BUBBLE2}, // S_SPINDUST_BUBBLE1 - {SPR_BUBL, 0, 6, {NULL}, 0, 0, S_SPINDUST_BUBBLE3}, // S_SPINDUST_BUBBLE2 - {SPR_BUBL, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_BUBBLE4}, // S_SPINDUST_BUBBLE3 - {SPR_BUBL, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_BUBBLE4 - {SPR_FPRT, 0, 7, {NULL}, 0, 0, S_SPINDUST_FIRE2}, // S_SPINDUST_FIRE1 - {SPR_FPRT, 0, 6, {NULL}, 0, 0, S_SPINDUST_FIRE3}, // S_SPINDUST_FIRE2 - {SPR_FPRT, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_FIRE4}, // S_SPINDUST_FIRE3 - {SPR_FPRT, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_FIRE4 + {SPR_DUST, 0, 7, {NULL}, 0, 0, S_SPINDUST2}, // S_SPINDUST1 + {SPR_DUST, 1, 6, {NULL}, 0, 0, S_SPINDUST3}, // S_SPINDUST2 + {SPR_DUST, FF_TRANS30|2, 4, {NULL}, 0, 0, S_SPINDUST4}, // S_SPINDUST3 + {SPR_DUST, FF_TRANS60|3, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST4 + {SPR_BUBL, 0, 7, {NULL}, 0, 0, S_SPINDUST_BUBBLE2}, // S_SPINDUST_BUBBLE1 + {SPR_BUBL, 0, 6, {NULL}, 0, 0, S_SPINDUST_BUBBLE3}, // S_SPINDUST_BUBBLE2 + {SPR_BUBL, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_BUBBLE4}, // S_SPINDUST_BUBBLE3 + {SPR_BUBL, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_BUBBLE4 + {SPR_FPRT, FF_FULLBRIGHT|0, 7, {NULL}, 0, 0, S_SPINDUST_FIRE2}, // S_SPINDUST_FIRE1 + {SPR_FPRT, FF_FULLBRIGHT|0, 6, {NULL}, 0, 0, S_SPINDUST_FIRE3}, // S_SPINDUST_FIRE2 + {SPR_FPRT, FF_FULLBRIGHT|FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_FIRE4}, // S_SPINDUST_FIRE3 + {SPR_FPRT, FF_FULLBRIGHT|FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_FIRE4 {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50, 2, {NULL}, 0, 0, S_FOG2}, // S_FOG1 @@ -3924,9 +3932,7 @@ state_t states[NUMSTATES] = {SPR_BRIB, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_BLUEBRICKDEBRIS {SPR_BRIY, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_YELLOWBRICKDEBRIS -#ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK -#endif }; mobjinfo_t mobjinfo[NUMMOBJTYPES] = @@ -21653,7 +21659,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, -#ifdef SEENAMES { // MT_NAMECHECK -1, // doomednum S_NAMECHECK, // spawnstate @@ -21680,7 +21685,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY|MF_NOSECTOR, // flags S_NULL // raisestate }, -#endif }; skincolor_t skincolors[MAXSKINCOLORS] = { diff --git a/src/info.h b/src/info.h index 604922beb..60e970246 100644 --- a/src/info.h +++ b/src/info.h @@ -684,6 +684,7 @@ typedef enum sprite SPR_SIGN, // Level end sign SPR_SPIK, // Spike Ball SPR_SFLM, // Spin fire + SPR_TFLM, // Spin fire (team) SPR_USPK, // Floor spike SPR_WSPK, // Wall spike SPR_WSPB, // Wall spike base @@ -2324,6 +2325,13 @@ typedef enum state S_SPINFIRE5, S_SPINFIRE6, + S_TEAM_SPINFIRE1, + S_TEAM_SPINFIRE2, + S_TEAM_SPINFIRE3, + S_TEAM_SPINFIRE4, + S_TEAM_SPINFIRE5, + S_TEAM_SPINFIRE6, + // Spikes S_SPIKE1, S_SPIKE2, @@ -4280,9 +4288,7 @@ typedef enum state S_BLUEBRICKDEBRIS, // for CEZ3 S_YELLOWBRICKDEBRIS, // for CEZ3 -#ifdef SEENAMES S_NAMECHECK, -#endif S_FIRSTFREESLOT, S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1, @@ -5082,9 +5088,7 @@ typedef enum mobj_type MT_BLUEBRICKDEBRIS, // for CEZ3 MT_YELLOWBRICKDEBRIS, // for CEZ3 -#ifdef SEENAMES MT_NAMECHECK, -#endif MT_FIRSTFREESLOT, MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1, diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 515f6f0ba..a59ba546e 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -155,6 +155,8 @@ static const struct { {META_PIVOTLIST, "spriteframepivot_t[]"}, {META_FRAMEPIVOT, "spriteframepivot_t"}, + {META_TAGLIST, "taglist"}, + {META_MOBJ, "mobj_t"}, {META_MAPTHING, "mapthing_t"}, @@ -186,6 +188,9 @@ static const struct { {META_CVAR, "consvar_t"}, {META_SECTORLINES, "sector_t.lines"}, +#ifdef MUTABLE_TAGS + {META_SECTORTAGLIST, "sector_t.taglist"}, +#endif {META_SIDENUM, "line_t.sidenum"}, {META_LINEARGS, "line_t.args"}, {META_LINESTRINGARGS, "line_t.stringargs"}, @@ -427,7 +432,7 @@ static int lib_pAproxDistance(lua_State *L) fixed_t dx = luaL_checkfixed(L, 1); fixed_t dy = luaL_checkfixed(L, 2); //HUDSAFE - lua_pushfixed(L, P_AproxDistance(dx, dy)); + lua_pushfixed(L, R_PointToDist2(0, 0, dx, dy)); return 1; } @@ -1666,6 +1671,26 @@ static int lib_pSwitchShield(lua_State *L) return 0; } +static int lib_pPlayerCanEnterSpinGaps(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushboolean(L, P_PlayerCanEnterSpinGaps(player)); + return 1; +} + +static int lib_pPlayerShouldUseSpinHeight(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushboolean(L, P_PlayerShouldUseSpinHeight(player)); + return 1; +} + // P_MAP /////////// @@ -3867,6 +3892,8 @@ static luaL_Reg lib[] = { {"P_SpawnSpinMobj",lib_pSpawnSpinMobj}, {"P_Telekinesis",lib_pTelekinesis}, {"P_SwitchShield",lib_pSwitchShield}, + {"P_PlayerCanEnterSpinGaps",lib_pPlayerCanEnterSpinGaps}, + {"P_PlayerShouldUseSpinHeight",lib_pPlayerShouldUseSpinHeight}, // p_map {"P_CheckPosition",lib_pCheckPosition}, diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 84bfeaee2..5344fee76 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -285,8 +285,8 @@ static void Lua_OnChange(void) /// \todo Network this! XD_LUAVAR - lua_settop(gL, 0); // Just in case... lua_pushcfunction(gL, LUA_GetErrorMessage); + lua_insert(gL, 1); // Because LUA_Call wants it at index 1. // From CV_OnChange registry field, get the function for this cvar by name. lua_getfield(gL, LUA_REGISTRYINDEX, "CV_OnChange"); @@ -301,6 +301,7 @@ static void Lua_OnChange(void) LUA_Call(gL, 1, 0, 1); // call function(cvar) lua_pop(gL, 1); // pop CV_OnChange table + lua_remove(gL, 1); // remove LUA_GetErrorMessage } static int lib_cvRegisterVar(lua_State *L) diff --git a/src/lua_hook.h b/src/lua_hook.h index dd41814b5..0d631aa4e 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -61,6 +61,8 @@ enum hook { hook_GameQuit, hook_PlayerCmd, hook_MusicChange, + hook_PlayerHeight, + hook_PlayerCanEnterSpinGaps, hook_MAX // last hook }; @@ -112,11 +114,11 @@ void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player qui void LUAh_IntermissionThinker(void); // Hook for Y_Ticker boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode -#ifdef SEENAMES boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK -#endif #define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing void LUAh_GameQuit(boolean quitting); // Hook for game quitting boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart) -boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes \ No newline at end of file +boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes +fixed_t LUAh_PlayerHeight(player_t *player); +UINT8 LUAh_PlayerCanEnterSpinGaps(player_t *player); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 387c243dc..1665e36b0 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -77,6 +77,8 @@ const char *const hookNames[hook_MAX+1] = { "GameQuit", "PlayerCmd", "MusicChange", + "PlayerHeight", + "PlayerCanEnterSpinGaps", NULL }; @@ -221,6 +223,8 @@ static int lib_addHook(lua_State *L) case hook_ShieldSpawn: case hook_ShieldSpecial: case hook_PlayerThink: + case hook_PlayerHeight: + case hook_PlayerCanEnterSpinGaps: lastp = &playerhooks; break; case hook_LinedefExecute: @@ -469,7 +473,7 @@ void LUAh_ThinkFrame(void) hook_p hookp; // variables used by perf stats int hook_index = 0; - int time_taken = 0; + precise_t time_taken = 0; if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8)))) return; @@ -1754,7 +1758,6 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean } // Hook for MT_NAMECHECK -#ifdef SEENAMES boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend) { hook_p hookp; @@ -1798,7 +1801,6 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend) return hasSeenPlayer; } -#endif // SEENAMES boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname) { @@ -1972,4 +1974,90 @@ boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boo lua_settop(gL, 0); newname[6] = 0; return hooked; -} \ No newline at end of file +} + +// Hook for determining player height +fixed_t LUAh_PlayerHeight(player_t *player) +{ + hook_p hookp; + fixed_t newheight = -1; + if (!gL || !(hooksAvailable[hook_PlayerHeight/8] & (1<<(hook_PlayerHeight%8)))) + return newheight; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_PlayerHeight) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + LUA_PushUserdata(gL, player, META_PLAYER); + PushHook(gL, hookp); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { + fixed_t returnedheight = lua_tonumber(gL, -1); + // 0 height has... strange results, but it's not problematic like negative heights are. + // when an object's height is set to a negative number directly with lua, it's forced to 0 instead. + // here, I think it's better to ignore negatives so that they don't replace any results of previous hooks! + if (returnedheight >= 0) + newheight = returnedheight; + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return newheight; +} + +// Hook for determining whether players are allowed passage through spin gaps +UINT8 LUAh_PlayerCanEnterSpinGaps(player_t *player) +{ + hook_p hookp; + UINT8 canEnter = 0; // 0 = default, 1 = force yes, 2 = force no. + if (!gL || !(hooksAvailable[hook_PlayerCanEnterSpinGaps/8] & (1<<(hook_PlayerCanEnterSpinGaps%8)))) + return 0; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_PlayerCanEnterSpinGaps) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + LUA_PushUserdata(gL, player, META_PLAYER); + PushHook(gL, hookp); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave canEnter = 0. + if (lua_toboolean(gL, -1)) + canEnter = 1; // Force yes + else + canEnter = 2; // Force no + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return canEnter; +} diff --git a/src/lua_hud.h b/src/lua_hud.h index 4a7c596c8..1e9dca00b 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -13,6 +13,7 @@ enum hud { hud_stagetitle = 0, hud_textspectator, + hud_crosshair, // Singleplayer / Co-op hud_score, hud_time, diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 20eb33f37..bd2d3a9fc 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -39,6 +39,7 @@ static UINT8 hudAvailable; // hud hooks field static const char *const hud_disable_options[] = { "stagetitle", "textspectator", + "crosshair", "score", "time", diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 4c6ef3528..6e86f47b7 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1635,8 +1635,10 @@ static int skincolor_get(lua_State *L) lua_pushinteger(L, info->chatcolor); else if (fastcmp(field,"accessible")) lua_pushboolean(L, info->accessible); - else + else { CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "skincolor_t", field); + return 0; + } return 1; } diff --git a/src/lua_libs.h b/src/lua_libs.h index 54ac89bcc..fbe8d4878 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -12,6 +12,8 @@ extern lua_State *gL; +#define MUTABLE_TAGS + #define LREG_VALID "VALID_USERDATA" #define LREG_EXTVARS "LUA_VARS" #define LREG_STATEACTION "STATE_ACTION" @@ -27,6 +29,8 @@ extern lua_State *gL; #define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]" #define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*" +#define META_TAGLIST "TAGLIST" + #define META_MOBJ "MOBJ_T*" #define META_MAPTHING "MAPTHING_T*" @@ -58,6 +62,9 @@ extern lua_State *gL; #define META_CVAR "CONSVAR_T*" #define META_SECTORLINES "SECTOR_T*LINES" +#ifdef MUTABLE_TAGS +#define META_SECTORTAGLIST "sector_t.taglist" +#endif #define META_SIDENUM "LINE_T*SIDENUM" #define META_LINEARGS "LINE_T*ARGS" #define META_LINESTRINGARGS "LINE_T*STRINGARGS" @@ -95,6 +102,7 @@ int LUA_PlayerLib(lua_State *L); int LUA_SkinLib(lua_State *L); int LUA_ThinkerLib(lua_State *L); int LUA_MapLib(lua_State *L); +int LUA_TagLib(lua_State *L); int LUA_PolyObjLib(lua_State *L); int LUA_BlockmapLib(lua_State *L); int LUA_HudLib(lua_State *L); diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 83744c74d..016141796 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -37,6 +37,7 @@ enum sector_e { sector_lightlevel, sector_special, sector_tag, + sector_taglist, sector_thinglist, sector_heightsec, sector_camsec, @@ -55,6 +56,7 @@ static const char *const sector_opt[] = { "lightlevel", "special", "tag", + "taglist", "thinglist", "heightsec", "camsec", @@ -89,6 +91,7 @@ enum line_e { line_flags, line_special, line_tag, + line_taglist, line_args, line_stringargs, line_sidenum, @@ -113,6 +116,7 @@ static const char *const line_opt[] = { "flags", "special", "tag", + "taglist", "args", "stringargs", "sidenum", @@ -579,7 +583,10 @@ static int sector_get(lua_State *L) lua_pushinteger(L, sector->special); return 1; case sector_tag: - lua_pushinteger(L, Tag_FGet(§or->tags)); + lua_pushinteger(L, (UINT16)Tag_FGet(§or->tags)); + return 1; + case sector_taglist: + LUA_PushUserdata(L, §or->tags, META_SECTORTAGLIST); return 1; case sector_thinglist: // thinglist lua_pushcfunction(L, lib_iterateSectorThinglist); @@ -682,6 +689,8 @@ static int sector_set(lua_State *L) case sector_tag: Tag_SectorFSet((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3)); break; + case sector_taglist: + return LUA_ErrSetDirectly(L, "sector_t", "taglist"); } return 0; } @@ -819,8 +828,22 @@ static int line_get(lua_State *L) lua_pushinteger(L, line->special); return 1; case line_tag: + // HELLO + // THIS IS LJ SONIC + // HOW IS YOUR DAY? + // BY THE WAY WHEN 2.3 OR 3.0 OR 4.0 OR SRB3 OR SRB4 OR WHATEVER IS OUT + // YOU SHOULD REMEMBER TO CHANGE THIS SO IT ALWAYS RETURNS A UNSIGNED VALUE + // HAVE A NICE DAY + // + // + // + // + // you are ugly lua_pushinteger(L, Tag_FGet(&line->tags)); return 1; + case line_taglist: + LUA_PushUserdata(L, &line->tags, META_TAGLIST); + return 1; case line_args: LUA_PushUserdata(L, line->args, META_LINEARGS); return 1; @@ -1385,25 +1408,15 @@ static int lib_iterateSectors(lua_State *L) static int lib_getSector(lua_State *L) { - int field; INLEVEL - lua_settop(L, 2); - lua_remove(L, 1); // dummy userdata table is unused. - if (lua_isnumber(L, 1)) + if (lua_isnumber(L, 2)) { - size_t i = lua_tointeger(L, 1); + size_t i = lua_tointeger(L, 2); if (i >= numsectors) return 0; LUA_PushUserdata(L, §ors[i], META_SECTOR); return 1; } - field = luaL_checkoption(L, 1, NULL, array_opt); - switch(field) - { - case 0: // iterate - lua_pushcfunction(L, lib_iterateSectors); - return 1; - } return 0; } @@ -1489,25 +1502,15 @@ static int lib_iterateLines(lua_State *L) static int lib_getLine(lua_State *L) { - int field; INLEVEL - lua_settop(L, 2); - lua_remove(L, 1); // dummy userdata table is unused. - if (lua_isnumber(L, 1)) + if (lua_isnumber(L, 2)) { - size_t i = lua_tointeger(L, 1); + size_t i = lua_tointeger(L, 2); if (i >= numlines) return 0; LUA_PushUserdata(L, &lines[i], META_LINE); return 1; } - field = luaL_checkoption(L, 1, NULL, array_opt); - switch(field) - { - case 0: // iterate - lua_pushcfunction(L, lib_iterateLines); - return 1; - } return 0; } @@ -2360,15 +2363,13 @@ int LUA_MapLib(lua_State *L) //lua_setfield(L, -2, "__len"); lua_pop(L, 1); - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getSector); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_numsectors); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "sectors"); + LUA_PushTaggableObjectArray(L, "sectors", + lib_iterateSectors, + lib_getSector, + lib_numsectors, + tags_sectors, + &numsectors, §ors, + sizeof (sector_t), META_SECTOR); lua_newuserdata(L, 0); lua_createtable(L, 0, 2); @@ -2380,15 +2381,13 @@ int LUA_MapLib(lua_State *L) lua_setmetatable(L, -2); lua_setglobal(L, "subsectors"); - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getLine); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_numlines); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "lines"); + LUA_PushTaggableObjectArray(L, "lines", + lib_iterateLines, + lib_getLine, + lib_numlines, + tags_lines, + &numlines, &lines, + sizeof (line_t), META_LINE); lua_newuserdata(L, 0); lua_createtable(L, 0, 2); diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index 10ba42ee0..b6046ab53 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -15,6 +15,7 @@ #include "tables.h" #include "p_local.h" #include "doomstat.h" // for ALL7EMERALDS +#include "r_main.h" // for R_PointToDist2 #include "lua_script.h" #include "lua_libs.h" @@ -129,7 +130,7 @@ static int lib_fixedsqrt(lua_State *L) static int lib_fixedhypot(lua_State *L) { - lua_pushfixed(L, FixedHypot(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2))); + lua_pushfixed(L, R_PointToDist2(0, 0, luaL_checkfixed(L, 1), luaL_checkfixed(L, 2))); return 1; } diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 7aae18c90..65adceb15 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -22,8 +22,6 @@ #include "lua_hud.h" // hud_running errors #include "lua_hook.h" // hook_cmd_running errors -static const char *const array_opt[] ={"iterate",NULL}; - enum mobj_e { mobj_valid = 0, mobj_x, @@ -904,6 +902,11 @@ static int mapthing_get(lua_State *L) number = mt->extrainfo; else if(fastcmp(field,"tag")) number = Tag_FGet(&mt->tags); + else if(fastcmp(field,"taglist")) + { + LUA_PushUserdata(L, &mt->tags, META_TAGLIST); + return 1; + } else if(fastcmp(field,"args")) { LUA_PushUserdata(L, mt->args, META_THINGARGS); @@ -966,6 +969,8 @@ static int mapthing_set(lua_State *L) } else if (fastcmp(field,"tag")) Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3)); + else if (fastcmp(field,"taglist")) + return LUA_ErrSetDirectly(L, "mapthing_t", "taglist"); else if(fastcmp(field,"mobj")) mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); else @@ -1003,25 +1008,15 @@ static int lib_iterateMapthings(lua_State *L) static int lib_getMapthing(lua_State *L) { - int field; INLEVEL - lua_settop(L, 2); - lua_remove(L, 1); // dummy userdata table is unused. - if (lua_isnumber(L, 1)) + if (lua_isnumber(L, 2)) { - size_t i = lua_tointeger(L, 1); + size_t i = lua_tointeger(L, 2); if (i >= nummapthings) return 0; LUA_PushUserdata(L, &mapthings[i], META_MAPTHING); return 1; } - field = luaL_checkoption(L, 1, NULL, array_opt); - switch(field) - { - case 0: // iterate - lua_pushcfunction(L, lib_iterateMapthings); - return 1; - } return 0; } @@ -1068,14 +1063,13 @@ int LUA_MobjLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L,1); - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getMapthing); - lua_setfield(L, -2, "__index"); + LUA_PushTaggableObjectArray(L, "mapthings", + lib_iterateMapthings, + lib_getMapthing, + lib_nummapthings, + tags_mapthings, + &nummapthings, &mapthings, + sizeof (mapthing_t), META_MAPTHING); - lua_pushcfunction(L, lib_nummapthings); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "mapthings"); return 0; } diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index 365d97056..2a5bcfbf1 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -417,7 +417,7 @@ static int lib_getPolyObject(lua_State *L) { i = luaL_checkinteger(L, 2); if (i < 0 || i >= numPolyObjects) - return luaL_error(L, "PolyObjects[] index %d out of range (0 - %d)", i, numPolyObjects-1); + return luaL_error(L, "polyobjects[] index %d out of range (0 - %d)", i, numPolyObjects-1); LUA_PushUserdata(L, &PolyObjects[i], META_POLYOBJ); return 1; } @@ -481,6 +481,6 @@ int LUA_PolyObjLib(lua_State *L) lua_pushcfunction(L, lib_numPolyObjects); lua_setfield(L, -2, "__len"); lua_setmetatable(L, -2); - lua_setglobal(L, "PolyObjects"); + lua_setglobal(L, "polyobjects"); return 0; } diff --git a/src/lua_script.c b/src/lua_script.c index eb4737f76..7fd5a98e6 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -53,6 +53,7 @@ static lua_CFunction liblist[] = { LUA_SkinLib, // skin_t, skins[] LUA_ThinkerLib, // thinker_t LUA_MapLib, // line_t, side_t, sector_t, subsector_t + LUA_TagLib, // tags LUA_PolyObjLib, // polyobj_t LUA_BlockmapLib, // blockmap stuff LUA_HudLib, // HUD stuff @@ -332,7 +333,7 @@ int LUA_PushGlobals(lua_State *L, const char *word) return 1; // local player variables, by popular request } else if (fastcmp(word,"consoleplayer")) { // player controlling console (aka local player 1) - if (consoleplayer < 0 || !playeringame[consoleplayer]) + if (!addedtogame || consoleplayer < 0 || !playeringame[consoleplayer]) return 0; LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER); return 1; @@ -739,25 +740,37 @@ void LUA_PushLightUserdata (lua_State *L, void *data, const char *meta) // Pushes it to the stack and stores it in the registry. void LUA_PushUserdata(lua_State *L, void *data, const char *meta) { + if (LUA_RawPushUserdata(L, data) == LPUSHED_NEW) + { + luaL_getmetatable(L, meta); + lua_setmetatable(L, -2); + } +} + +// Same as LUA_PushUserdata but don't set a metatable yet. +lpushed_t LUA_RawPushUserdata(lua_State *L, void *data) +{ + lpushed_t status = LPUSHED_NIL; + void **userdata; if (!data) { // push a NULL lua_pushnil(L); - return; + return status; } lua_getfield(L, LUA_REGISTRYINDEX, LREG_VALID); I_Assert(lua_istable(L, -1)); + lua_pushlightuserdata(L, data); lua_rawget(L, -2); + if (lua_isnil(L, -1)) { // no userdata? deary me, we'll have to make one. lua_pop(L, 1); // pop the nil // create the userdata userdata = lua_newuserdata(L, sizeof(void *)); *userdata = data; - luaL_getmetatable(L, meta); - lua_setmetatable(L, -2); // Set it in the registry so we can find it again lua_pushlightuserdata(L, data); // k (store the userdata via the data's pointer) @@ -765,8 +778,15 @@ void LUA_PushUserdata(lua_State *L, void *data, const char *meta) lua_rawset(L, -4); // stack is left with the userdata on top, as if getting it had originally succeeded. + + status = LPUSHED_NEW; } + else + status = LPUSHED_EXISTING; + lua_remove(L, -2); // remove LREG_VALID + + return status; } // When userdata is freed, use this function to remove it from Lua. @@ -826,6 +846,7 @@ void LUA_InvalidateLevel(void) { LUA_InvalidateUserdata(§ors[i]); LUA_InvalidateUserdata(§ors[i].lines); + LUA_InvalidateUserdata(§ors[i].tags); if (sectors[i].ffloors) { for (rover = sectors[i].ffloors; rover; rover = rover->next) @@ -835,6 +856,7 @@ void LUA_InvalidateLevel(void) for (i = 0; i < numlines; i++) { LUA_InvalidateUserdata(&lines[i]); + LUA_InvalidateUserdata(&lines[i].tags); LUA_InvalidateUserdata(lines[i].sidenum); } for (i = 0; i < numsides; i++) @@ -866,7 +888,10 @@ void LUA_InvalidateMapthings(void) return; for (i = 0; i < nummapthings; i++) + { LUA_InvalidateUserdata(&mapthings[i]); + LUA_InvalidateUserdata(&mapthings[i].tags); + } } void LUA_InvalidatePlayer(player_t *player) @@ -1681,3 +1706,36 @@ int Lua_optoption(lua_State *L, int narg, return i; return -1; } + +void LUA_PushTaggableObjectArray +( lua_State *L, + const char *field, + lua_CFunction iterator, + lua_CFunction indexer, + lua_CFunction counter, + taggroup_t *garray[], + size_t * max_elements, + void * element_array, + size_t sizeof_element, + const char *meta) +{ + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, iterator); + lua_setfield(L, -2, "iterate"); + + LUA_InsertTaggroupIterator(L, garray, + max_elements, element_array, sizeof_element, meta); + + lua_createtable(L, 0, 1); + lua_pushcfunction(L, indexer); + lua_setfield(L, -2, "__index"); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, counter); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, field); +} diff --git a/src/lua_script.h b/src/lua_script.h index 79ba0bb38..77fbb7c1d 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -10,10 +10,14 @@ /// \file lua_script.h /// \brief Lua scripting basics +#ifndef LUA_SCRIPT_H +#define LUA_SCRIPT_H + #include "m_fixed.h" #include "doomtype.h" #include "d_player.h" #include "g_state.h" +#include "taglist.h" #include "blua/lua.h" #include "blua/lualib.h" @@ -46,12 +50,6 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults); void LUA_DumpFile(const char *filename); #endif fixed_t LUA_EvalMath(const char *word); -void LUA_PushLightUserdata(lua_State *L, void *data, const char *meta); -void LUA_PushUserdata(lua_State *L, void *data, const char *meta); -void LUA_InvalidateUserdata(void *data); -void LUA_InvalidateLevel(void); -void LUA_InvalidateMapthings(void); -void LUA_InvalidatePlayer(player_t *player); void LUA_Step(void); void LUA_Archive(void); void LUA_UnArchive(void); @@ -63,11 +61,49 @@ int Lua_optoption(lua_State *L, int narg, const char *def, const char *const lst[]); void LUAh_NetArchiveHook(lua_CFunction archFunc); +void LUA_PushTaggableObjectArray +( lua_State *L, + const char *field, + lua_CFunction iterator, + lua_CFunction indexer, + lua_CFunction counter, + taggroup_t *garray[], + size_t * max_elements, + void * element_array, + size_t sizeof_element, + const char *meta); + +void LUA_InsertTaggroupIterator +( lua_State *L, + taggroup_t *garray[], + size_t * max_elements, + void * element_array, + size_t sizeof_element, + const char * meta); + +typedef enum { + LPUSHED_NIL, + LPUSHED_NEW, + LPUSHED_EXISTING, +} lpushed_t; + +void LUA_PushLightUserdata(lua_State *L, void *data, const char *meta); +void LUA_PushUserdata(lua_State *L, void *data, const char *meta); +lpushed_t LUA_RawPushUserdata(lua_State *L, void *data); + +void LUA_InvalidateUserdata(void *data); + +void LUA_InvalidateLevel(void); +void LUA_InvalidateMapthings(void); +void LUA_InvalidatePlayer(player_t *player); + // Console wrapper void COM_Lua_f(void); #define LUA_ErrInvalid(L, type) luaL_error(L, "accessed " type " doesn't exist anymore, please check 'valid' before using " type "."); +#define LUA_ErrSetDirectly(L, type, field) luaL_error(L, type " field " LUA_QL(field) " cannot be set directly.") + // Deprecation warnings // Shows once upon use. Then doesn't show again. #define LUA_Deprecated(L,this_func,use_instead)\ @@ -98,3 +134,5 @@ void COM_Lua_f(void); #define INLEVEL if (! ISINLEVEL)\ return luaL_error(L, "This can only be used in a level!"); + +#endif/*LUA_SCRIPT_H*/ diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index ea368a9cd..56be6bf4f 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -214,7 +214,7 @@ static int skin_get(lua_State *L) break; case skin_sprites: LUA_PushLightUserdata(L, skin->sprites, META_SKINSPRITES); - break; + break; } return 1; } diff --git a/src/lua_taglib.c b/src/lua_taglib.c new file mode 100644 index 000000000..c9f320fe8 --- /dev/null +++ b/src/lua_taglib.c @@ -0,0 +1,451 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by James R. +// Copyright (C) 2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file lua_taglib.c +/// \brief tag list iterator for Lua scripting + +#include "doomdef.h" +#include "taglist.h" +#include "r_state.h" + +#include "lua_script.h" +#include "lua_libs.h" + +#ifdef MUTABLE_TAGS +#include "z_zone.h" +#endif + +static int tag_iterator(lua_State *L) +{ + INT32 tag = lua_isnil(L, 2) ? -1 : lua_tonumber(L, 2); + do + { + if (++tag >= MAXTAGS) + return 0; + } + while (! in_bit_array(tags_available, tag)) ; + lua_pushnumber(L, tag); + return 1; +} + +enum { +#define UPVALUE lua_upvalueindex + up_garray = UPVALUE(1), + up_max_elements = UPVALUE(2), + up_element_array = UPVALUE(3), + up_sizeof_element = UPVALUE(4), + up_meta = UPVALUE(5), +#undef UPVALUE +}; + +static INT32 next_element(lua_State *L, const mtag_t tag, const size_t p) +{ + taggroup_t ** garray = lua_touserdata(L, up_garray); + const size_t * max_elements = lua_touserdata(L, up_max_elements); + return Taggroup_Iterate(garray, *max_elements, tag, p); +} + +static void push_element(lua_State *L, void *element) +{ + if (LUA_RawPushUserdata(L, element) == LPUSHED_NEW) + { + lua_pushvalue(L, up_meta); + lua_setmetatable(L, -2); + } +} + +static void push_next_element(lua_State *L, const INT32 element) +{ + char * element_array = *(char **)lua_touserdata(L, up_element_array); + const size_t sizeof_element = lua_tonumber(L, up_sizeof_element); + push_element(L, &element_array[element * sizeof_element]); +} + +struct element_iterator_state { + mtag_t tag; + size_t p; +}; + +static int element_iterator(lua_State *L) +{ + struct element_iterator_state * state = lua_touserdata(L, 1); + if (lua_isnoneornil(L, 3)) + state->p = 0; + lua_pushnumber(L, ++state->p); + lua_gettable(L, 1); + return 1; +} + +static int lib_iterateTags(lua_State *L) +{ + if (lua_gettop(L) < 2) + { + lua_pushcfunction(L, tag_iterator); + return 1; + } + else + return tag_iterator(L); +} + +static int lib_numTags(lua_State *L) +{ + lua_pushnumber(L, num_tags); + return 1; +} + +static int lib_getTaggroup(lua_State *L) +{ + struct element_iterator_state *state; + + mtag_t tag; + + if (lua_gettop(L) > 1) + return luaL_error(L, "too many arguments"); + + if (lua_isnoneornil(L, 1)) + { + tag = MTAG_GLOBAL; + } + else + { + tag = lua_tonumber(L, 1); + luaL_argcheck(L, tag >= -1, 1, "tag out of range"); + } + + state = lua_newuserdata(L, sizeof *state); + state->tag = tag; + state->p = 0; + + lua_pushvalue(L, lua_upvalueindex(1)); + lua_setmetatable(L, -2); + + return 1; +} + +static int lib_getTaggroupElement(lua_State *L) +{ + const size_t p = luaL_checknumber(L, 2) - 1; + const mtag_t tag = *(mtag_t *)lua_touserdata(L, 1); + const INT32 element = next_element(L, tag, p); + + if (element == -1) + return 0; + else + { + push_next_element(L, element); + return 1; + } +} + +static int lib_numTaggroupElements(lua_State *L) +{ + const mtag_t tag = *(mtag_t *)lua_touserdata(L, 1); + if (tag == MTAG_GLOBAL) + lua_pushnumber(L, *(size_t *)lua_touserdata(L, up_max_elements)); + else + { + const taggroup_t ** garray = lua_touserdata(L, up_garray); + lua_pushnumber(L, Taggroup_Count(garray[tag])); + } + return 1; +} + +#ifdef MUTABLE_TAGS +static int meta_ref[2]; +#endif + +static int has_valid_field(lua_State *L) +{ + int equal; + lua_rawgeti(L, LUA_ENVIRONINDEX, 1); + equal = lua_rawequal(L, 2, -1); + lua_pop(L, 1); + return equal; +} + +static taglist_t * valid_taglist(lua_State *L, int idx, boolean getting) +{ + taglist_t *list = *(taglist_t **)lua_touserdata(L, idx); + + if (list == NULL) + { + if (getting && has_valid_field(L)) + lua_pushboolean(L, 0); + else + LUA_ErrInvalid(L, "taglist");/* doesn't actually return */ + return NULL; + } + else + return list; +} + +static taglist_t * check_taglist(lua_State *L, int idx) +{ + if (lua_isuserdata(L, idx) && lua_getmetatable(L, idx)) + { + lua_getref(L, meta_ref[0]); + lua_getref(L, meta_ref[1]); + + if (lua_rawequal(L, -3, -2) || lua_rawequal(L, -3, -1)) + { + lua_pop(L, 3); + return valid_taglist(L, idx, false); + } + } + + return luaL_argerror(L, idx, "must be a tag list"), NULL; +} + +static int taglist_get(lua_State *L) +{ + const taglist_t *list = valid_taglist(L, 1, true); + + if (list == NULL)/* valid check */ + return 1; + + if (lua_isnumber(L, 2)) + { + const size_t i = lua_tonumber(L, 2); + + if (list && i <= list->count) + { + lua_pushnumber(L, list->tags[i - 1]); + return 1; + } + else + return 0; + } + else if (has_valid_field(L)) + { + lua_pushboolean(L, 1); + return 1; + } + else + { + lua_getmetatable(L, 1); + lua_replace(L, 1); + lua_rawget(L, 1); + return 1; + } +} + +static int taglist_len(lua_State *L) +{ + const taglist_t *list = valid_taglist(L, 1, false); + lua_pushnumber(L, list->count); + return 1; +} + +static int taglist_equal(lua_State *L) +{ + const taglist_t *lhs = check_taglist(L, 1); + const taglist_t *rhs = check_taglist(L, 2); + lua_pushboolean(L, Tag_Compare(lhs, rhs)); + return 1; +} + +static int taglist_iterator(lua_State *L) +{ + const taglist_t *list = valid_taglist(L, 1, false); + const size_t i = 1 + lua_tonumber(L, lua_upvalueindex(1)); + if (i <= list->count) + { + lua_pushnumber(L, list->tags[i - 1]); + /* watch me exploit an upvalue as a control because + I want to use the control as the value */ + lua_pushnumber(L, i); + lua_replace(L, lua_upvalueindex(1)); + return 1; + } + else + return 0; +} + +static int taglist_iterate(lua_State *L) +{ + check_taglist(L, 1); + lua_pushnumber(L, 0); + lua_pushcclosure(L, taglist_iterator, 1); + lua_pushvalue(L, 1); + return 2; +} + +static int taglist_find(lua_State *L) +{ + const taglist_t *list = check_taglist(L, 1); + const mtag_t tag = luaL_checknumber(L, 2); + lua_pushboolean(L, Tag_Find(list, tag)); + return 1; +} + +static int taglist_shares(lua_State *L) +{ + const taglist_t *lhs = check_taglist(L, 1); + const taglist_t *rhs = check_taglist(L, 2); + lua_pushboolean(L, Tag_Share(lhs, rhs)); + return 1; +} + +/* only sector tags are mutable... */ + +#ifdef MUTABLE_TAGS +static size_t sector_of_taglist(taglist_t *list) +{ + return (sector_t *)((char *)list - offsetof (sector_t, tags)) - sectors; +} + +static int this_taglist(lua_State *L) +{ + lua_settop(L, 1); + return 1; +} + +static int taglist_add(lua_State *L) +{ + taglist_t *list = *(taglist_t **)luaL_checkudata(L, 1, META_SECTORTAGLIST); + const mtag_t tag = luaL_checknumber(L, 2); + + if (! Tag_Find(list, tag)) + { + Taggroup_Add(tags_sectors, tag, sector_of_taglist(list)); + Tag_Add(list, tag); + } + + return this_taglist(L); +} + +static int taglist_remove(lua_State *L) +{ + taglist_t *list = *(taglist_t **)luaL_checkudata(L, 1, META_SECTORTAGLIST); + const mtag_t tag = luaL_checknumber(L, 2); + + size_t i; + + for (i = 0; i < list->count; ++i) + { + if (list->tags[i] == tag) + { + if (list->count > 1) + { + memmove(&list->tags[i], &list->tags[i + 1], + (list->count - 1 - i) * sizeof (mtag_t)); + list->tags = Z_Realloc(list->tags, + (--list->count) * sizeof (mtag_t), PU_LEVEL, NULL); + Taggroup_Remove(tags_sectors, tag, sector_of_taglist(list)); + } + else/* reset to default tag */ + Tag_SectorFSet(sector_of_taglist(list), 0); + break; + } + } + + return this_taglist(L); +} +#endif/*MUTABLE_TAGS*/ + +void LUA_InsertTaggroupIterator +( lua_State *L, + taggroup_t *garray[], + size_t * max_elements, + void * element_array, + size_t sizeof_element, + const char * meta) +{ + lua_createtable(L, 0, 3); + lua_pushlightuserdata(L, garray); + lua_pushlightuserdata(L, max_elements); + + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_pushlightuserdata(L, element_array); + lua_pushnumber(L, sizeof_element); + luaL_getmetatable(L, meta); + lua_pushcclosure(L, lib_getTaggroupElement, 5); + lua_setfield(L, -4, "__index"); + + lua_pushcclosure(L, lib_numTaggroupElements, 2); + lua_setfield(L, -2, "__len"); + + lua_pushcfunction(L, element_iterator); + lua_setfield(L, -2, "__call"); + lua_pushcclosure(L, lib_getTaggroup, 1); + lua_setfield(L, -2, "tagged"); +} + +static luaL_Reg taglist_lib[] = { + {"iterate", taglist_iterate}, + {"find", taglist_find}, + {"shares", taglist_shares}, +#ifdef MUTABLE_TAGS + {"add", taglist_add}, + {"remove", taglist_remove}, +#endif + {0} +}; + +static void open_taglist(lua_State *L) +{ + luaL_register(L, "taglist", taglist_lib); + + lua_getfield(L, -1, "find"); + lua_setfield(L, -2, "has"); +} + +#define new_literal(L, s) \ + (lua_pushliteral(L, s), luaL_ref(L, -2)) + +#ifdef MUTABLE_TAGS +static int +#else +static void +#endif +set_taglist_metatable(lua_State *L, const char *meta) +{ + luaL_newmetatable(L, meta); + lua_pushcfunction(L, taglist_get); + lua_createtable(L, 0, 1); + new_literal(L, "valid"); + lua_setfenv(L, -2); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, taglist_len); + lua_setfield(L, -2, "__len"); + + lua_pushcfunction(L, taglist_equal); + lua_setfield(L, -2, "__eq"); +#ifdef MUTABLE_TAGS + return luaL_ref(L, LUA_REGISTRYINDEX); +#endif +} + +int LUA_TagLib(lua_State *L) +{ + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_createtable(L, 0, 1); + lua_pushcfunction(L, lib_iterateTags); + lua_setfield(L, -2, "iterate"); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_numTags); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "tags"); + + open_taglist(L); + +#ifdef MUTABLE_TAGS + meta_ref[0] = set_taglist_metatable(L, META_TAGLIST); + meta_ref[1] = set_taglist_metatable(L, META_SECTORTAGLIST); +#else + set_taglist_metatable(L, META_TAGLIST); +#endif + + return 0; +} diff --git a/src/m_menu.c b/src/m_menu.c index 003e308b0..5f95ce3ce 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1356,9 +1356,7 @@ static menuitem_t OP_VideoOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Score/Time/Rings", &cv_timetic, 71}, {IT_STRING | IT_CVAR, NULL, "Show Powerups", &cv_powerupdisplay, 76}, {IT_STRING | IT_CVAR, NULL, "Local ping display", &cv_showping, 81}, // shows ping next to framerate if we want to. -#ifdef SEENAMES {IT_STRING | IT_CVAR, NULL, "Show player names", &cv_seenames, 86}, -#endif {IT_HEADER, NULL, "Console", NULL, 95}, {IT_STRING | IT_CVAR, NULL, "Background color", &cons_backcolor, 101}, @@ -1551,18 +1549,19 @@ static menuitem_t OP_ScreenshotOptionsMenu[] = {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bits, 57}, {IT_HEADER, NULL, "Movie Mode (F9)", NULL, 64}, - {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_movie_option, 70}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_movie_folder, 75}, - {IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 90}, + {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_movie_option, 70}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_movie_folder, 75}, + {IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 90}, - {IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 95}, - {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 100}, + {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 95}, + {IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 100}, {IT_STRING|IT_CVAR, NULL, "Local Color Table", &cv_gif_localcolortable, 105}, - {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 95}, - {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 100}, - {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 105}, - {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 110}, + {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_apng_downscale, 95}, + {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 100}, + {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 105}, + {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 110}, + {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 115}, }; enum @@ -1575,7 +1574,7 @@ enum op_screenshot_gif_start = 13, op_screenshot_gif_end = 15, op_screenshot_apng_start = 16, - op_screenshot_apng_end = 19, + op_screenshot_apng_end = 20, }; static menuitem_t OP_EraseDataMenu[] = @@ -1613,53 +1612,54 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 21}, {IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 26}, {IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 31}, + {IT_STRING | IT_CVAR, NULL, "Minutes for reconnecting", &cv_rejointimeout, 36}, #endif - {IT_STRING | IT_CVAR, NULL, "Map progression", &cv_advancemap, 36}, - {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 41}, + {IT_STRING | IT_CVAR, NULL, "Map progression", &cv_advancemap, 41}, + {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 46}, - {IT_HEADER, NULL, "Characters", NULL, 50}, - {IT_STRING | IT_CVAR, NULL, "Force a character", &cv_forceskin, 56}, - {IT_STRING | IT_CVAR, NULL, "Restrict character changes", &cv_restrictskinchange, 61}, + {IT_HEADER, NULL, "Characters", NULL, 55}, + {IT_STRING | IT_CVAR, NULL, "Force a character", &cv_forceskin, 61}, + {IT_STRING | IT_CVAR, NULL, "Restrict character changes", &cv_restrictskinchange, 66}, - {IT_HEADER, NULL, "Items", NULL, 70}, - {IT_STRING | IT_CVAR, NULL, "Item respawn delay", &cv_itemrespawntime, 76}, - {IT_STRING | IT_SUBMENU, NULL, "Mystery Item Monitor Toggles...", &OP_MonitorToggleDef, 81}, + {IT_HEADER, NULL, "Items", NULL, 75}, + {IT_STRING | IT_CVAR, NULL, "Item respawn delay", &cv_itemrespawntime, 81}, + {IT_STRING | IT_SUBMENU, NULL, "Mystery Item Monitor Toggles...", &OP_MonitorToggleDef, 86}, - {IT_HEADER, NULL, "Cooperative", NULL, 90}, - {IT_STRING | IT_CVAR, NULL, "Players required for exit", &cv_playersforexit, 96}, - {IT_STRING | IT_CVAR, NULL, "Starposts", &cv_coopstarposts, 101}, - {IT_STRING | IT_CVAR, NULL, "Life sharing", &cv_cooplives, 106}, - {IT_STRING | IT_CVAR, NULL, "Post-goal free roaming", &cv_exitmove, 111}, + {IT_HEADER, NULL, "Cooperative", NULL, 95}, + {IT_STRING | IT_CVAR, NULL, "Players required for exit", &cv_playersforexit, 101}, + {IT_STRING | IT_CVAR, NULL, "Starposts", &cv_coopstarposts, 106}, + {IT_STRING | IT_CVAR, NULL, "Life sharing", &cv_cooplives, 111}, + {IT_STRING | IT_CVAR, NULL, "Post-goal free roaming", &cv_exitmove, 116}, - {IT_HEADER, NULL, "Race, Competition", NULL, 120}, - {IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 126}, - {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_competitionboxes, 131}, + {IT_HEADER, NULL, "Race, Competition", NULL, 125}, + {IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 131}, + {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_competitionboxes, 136}, - {IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 140}, - {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 146}, - {IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 151}, - {IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 156}, - {IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 161}, + {IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 145}, + {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 151}, + {IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 156}, + {IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 161}, + {IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 166}, - {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_matchboxes, 171}, - {IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 176}, - {IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 181}, + {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_matchboxes, 176}, + {IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 181}, + {IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 186}, - {IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 191}, - {IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 196}, + {IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 196}, + {IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 201}, - {IT_HEADER, NULL, "Teams", NULL, 205}, - {IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 211}, - {IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 216}, + {IT_HEADER, NULL, "Teams", NULL, 210}, + {IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 216}, + {IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 221}, #ifndef NONET - {IT_HEADER, NULL, "Advanced", NULL, 225}, - {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 231}, + {IT_HEADER, NULL, "Advanced", NULL, 230}, + {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 236}, - {IT_STRING | IT_CVAR, NULL, "Join delay", &cv_joindelay, 246}, - {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 251}, + {IT_STRING | IT_CVAR, NULL, "Join delay", &cv_joindelay, 251}, + {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 256}, - {IT_STRING | IT_CVAR, NULL, "Show IP Address of Joiners", &cv_showjoinaddress, 256}, + {IT_STRING | IT_CVAR, NULL, "Show IP Address of Joiners", &cv_showjoinaddress, 261}, #endif }; @@ -8422,7 +8422,7 @@ static void M_DrawLoadGameData(void) sprdef = &charbotskin->sprites[SPR2_SIGN]; if (!sprdef->numframes) goto skipbot; - colormap = R_GetTranslationColormap(savegameinfo[savetodraw].botskin-1, charbotskin->prefcolor, 0); + colormap = R_GetTranslationColormap(savegameinfo[savetodraw].botskin-1, charbotskin->prefcolor, GTC_CACHE); sprframe = &sprdef->spriteframes[0]; patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); @@ -8432,8 +8432,6 @@ static void M_DrawLoadGameData(void) charbotskin->highresscale, 0, patch, colormap); - Z_Free(colormap); - tempx -= (20<sprites[SPR2_SIGN]; - colormap = R_GetTranslationColormap(savegameinfo[savetodraw].skinnum, charskin->prefcolor, 0); + colormap = R_GetTranslationColormap(savegameinfo[savetodraw].skinnum, charskin->prefcolor, GTC_CACHE); if (!sprdef->numframes) goto skipsign; sprframe = &sprdef->spriteframes[0]; @@ -8482,8 +8480,6 @@ skipsign: charskin->highresscale/2, 0, patch, colormap); skiplife: - if (colormap) - Z_Free(colormap); patch = W_CachePatchName("STLIVEX", PU_PATCH); @@ -11423,9 +11419,9 @@ static void M_ServerOptions(INT32 choice) OP_ServerOptionsMenu[ 2].status = IT_GRAYEDOUT; // Max players OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow add-on downloading OP_ServerOptionsMenu[ 4].status = IT_GRAYEDOUT; // Allow players to join - OP_ServerOptionsMenu[35].status = IT_GRAYEDOUT; // Master server - OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Minimum delay between joins - OP_ServerOptionsMenu[37].status = IT_GRAYEDOUT; // Attempts to resynchronise + OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Master server + OP_ServerOptionsMenu[37].status = IT_GRAYEDOUT; // Minimum delay between joins + OP_ServerOptionsMenu[38].status = IT_GRAYEDOUT; // Attempts to resynchronise } else { @@ -11433,11 +11429,11 @@ static void M_ServerOptions(INT32 choice) OP_ServerOptionsMenu[ 2].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[ 3].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[ 4].status = IT_STRING | IT_CVAR; - OP_ServerOptionsMenu[35].status = (netgame + OP_ServerOptionsMenu[36].status = (netgame ? IT_GRAYEDOUT : (IT_STRING | IT_CVAR | IT_CV_STRING)); - OP_ServerOptionsMenu[36].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[37].status = IT_STRING | IT_CVAR; + OP_ServerOptionsMenu[38].status = IT_STRING | IT_CVAR; } #endif @@ -11754,7 +11750,7 @@ static void M_DrawSetupMultiPlayerMenu(void) goto faildraw; // ok, draw player sprite for sure now - colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor->color, 0); + colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor->color, GTC_CACHE); if (multi_frame >= sprdef->numframes) multi_frame = 0; @@ -11772,7 +11768,6 @@ static void M_DrawSetupMultiPlayerMenu(void) FixedDiv(skins[setupm_fakeskin].highresscale, skins[setupm_fakeskin].shieldscale), flags, patch, colormap); - Z_Free(colormap); goto colordraw; faildraw: diff --git a/src/m_misc.c b/src/m_misc.c index d97d8f94b..17a398b83 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -163,6 +163,11 @@ consvar_t cv_zlib_levela = CVAR_INIT ("apng_compress_level", "4", CV_SAVE, zlib_ consvar_t cv_zlib_strategya = CVAR_INIT ("apng_strategy", "RLE", CV_SAVE, zlib_strategy_t, NULL); consvar_t cv_zlib_window_bitsa = CVAR_INIT ("apng_window_size", "32k", CV_SAVE, zlib_window_bits_t, NULL); consvar_t cv_apng_delay = CVAR_INIT ("apng_speed", "1x", CV_SAVE, apng_delay_t, NULL); +consvar_t cv_apng_downscale = CVAR_INIT ("apng_downscale", "On", CV_SAVE, CV_OnOff, NULL); + +#ifdef USE_APNG +static boolean apng_downscale = false; // So nobody can do something dumb like changing cvars mid output +#endif boolean takescreenshot = false; // Take a screenshot this tic @@ -981,25 +986,38 @@ static inline boolean M_PNGLib(void) static void M_PNGFrame(png_structp png_ptr, png_infop png_info_ptr, png_bytep png_buf) { + png_uint_16 downscale = apng_downscale ? vid.dupx : 1; + png_uint_32 pitch = png_get_rowbytes(png_ptr, png_info_ptr); - PNG_CONST png_uint_32 height = vid.height; - png_bytepp row_pointers = png_malloc(png_ptr, height* sizeof (png_bytep)); - png_uint_32 y; + PNG_CONST png_uint_32 width = vid.width / downscale; + PNG_CONST png_uint_32 height = vid.height / downscale; + png_bytepp row_pointers = png_malloc(png_ptr, height * sizeof (png_bytep)); + png_uint_32 x, y; png_uint_16 framedelay = (png_uint_16)cv_apng_delay.value; apng_frames++; for (y = 0; y < height; y++) { - row_pointers[y] = png_buf; - png_buf += pitch; + row_pointers[y] = malloc(pitch * sizeof(png_byte)); + for (x = 0; x < width; x++) + row_pointers[y][x] = png_buf[x * downscale]; + png_buf += pitch * (downscale * downscale); } + //for (x = 0; x < width; x++) + //{ + // printf("%d", x); + // row_pointers[y][x] = 0; + //} + /* row_pointers[y] = calloc(1, sizeof(png_bytep)); + png_buf += pitch * 2; + }*/ #ifndef PNG_STATIC if (aPNG_write_frame_head) #endif aPNG_write_frame_head(apng_ptr, apng_info_ptr, row_pointers, - vid.width, /* width */ + width, /* width */ height, /* height */ 0, /* x offset */ 0, /* y offset */ @@ -1030,6 +1048,12 @@ static void M_PNGfix_acTL(png_structp png_ptr, png_infop png_info_ptr, static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal) { + png_uint_16 downscale; + + apng_downscale = (!!cv_apng_downscale.value); + + downscale = apng_downscale ? vid.dupx : 1; + apng_FILE = fopen(filename,"wb+"); // + mode for reading if (!apng_FILE) { @@ -1080,7 +1104,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal) png_set_compression_strategy(apng_ptr, cv_zlib_strategya.value); png_set_compression_window_bits(apng_ptr, cv_zlib_window_bitsa.value); - M_PNGhdr(apng_ptr, apng_info_ptr, vid.width, vid.height, pal); + M_PNGhdr(apng_ptr, apng_info_ptr, vid.width / downscale, vid.height / downscale, pal); M_PNGText(apng_ptr, apng_info_ptr, true); diff --git a/src/m_misc.h b/src/m_misc.h index dbded37d0..c5ef9f9f2 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -33,7 +33,7 @@ extern consvar_t cv_screenshot_option, cv_screenshot_folder, cv_screenshot_color extern consvar_t cv_moviemode, cv_movie_folder, cv_movie_option; extern consvar_t cv_zlib_memory, cv_zlib_level, cv_zlib_strategy, cv_zlib_window_bits; extern consvar_t cv_zlib_memorya, cv_zlib_levela, cv_zlib_strategya, cv_zlib_window_bitsa; -extern consvar_t cv_apng_delay; +extern consvar_t cv_apng_delay, cv_apng_downscale; void M_StartMovie(void); void M_SaveFrame(void); diff --git a/src/m_perfstats.c b/src/m_perfstats.c index 1596a87e5..b58599b6d 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -62,7 +62,7 @@ int thinkframe_hooks_capacity = 16; static INT32 draw_row; -void PS_SetThinkFrameHookInfo(int index, UINT32 time_taken, char* short_src) +void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) { if (!thinkframe_hooks) { @@ -565,7 +565,7 @@ void M_DrawPerfStats(void) len = (int)strlen(str); if (len > 20) str += len - 20; - snprintf(s, sizeof s - 1, "%20s: %u", str, thinkframe_hooks[i].time_taken); + snprintf(s, sizeof s - 1, "%20s: %d", str, I_PreciseToMicros(thinkframe_hooks[i].time_taken)); V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | text_color, s); y += 4; // repeated code! if (y > 192) diff --git a/src/m_perfstats.h b/src/m_perfstats.h index 132bea38c..1ca71957f 100644 --- a/src/m_perfstats.h +++ b/src/m_perfstats.h @@ -30,11 +30,11 @@ extern int ps_lua_mobjhooks; typedef struct { - UINT32 time_taken; + precise_t time_taken; char short_src[LUA_IDSIZE]; } ps_hookinfo_t; -void PS_SetThinkFrameHookInfo(int index, UINT32 time_taken, char* short_src); +void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src); void M_DrawPerfStats(void); diff --git a/src/p_enemy.c b/src/p_enemy.c index 63a14636d..59176d6cc 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4060,7 +4060,7 @@ bossjustdie: // Initialize my junk junk.tags.tags = NULL; junk.tags.count = 0; - + Tag_FSet(&junk.tags, LE_KOOPA); EV_DoCeiling(&junk, raiseToHighest); return; @@ -4912,7 +4912,7 @@ void A_ThrownRing(mobj_t *actor) } if (actor->tracer && (actor->tracer->health) - && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC))// Already found someone to follow. + && (actor->tracer->player && actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC))// Already found someone to follow. { const INT32 temp = actor->threshold; actor->threshold = 32000; @@ -5920,13 +5920,18 @@ void A_DetonChase(mobj_t *actor) if (actor->reactiontime == -42) { - fixed_t xyspeed; + fixed_t xyspeed, speed; + + if (actor->target->player) + speed = actor->target->player->normalspeed; + else + speed = actor->target->info->speed; actor->reactiontime = -42; exact = actor->movedir>>ANGLETOFINESHIFT; - xyspeed = FixedMul(FixedMul(actor->tracer->player->normalspeed,3*FRACUNIT/4), FINECOSINE(exact)); - actor->momz = FixedMul(FixedMul(actor->tracer->player->normalspeed,3*FRACUNIT/4), FINESINE(exact)); + xyspeed = FixedMul(FixedMul(speed,3*FRACUNIT/4), FINECOSINE(exact)); + actor->momz = FixedMul(FixedMul(speed,3*FRACUNIT/4), FINESINE(exact)); exact = actor->angle>>ANGLETOFINESHIFT; actor->momx = FixedMul(xyspeed, FINECOSINE(exact)); @@ -7521,7 +7526,7 @@ void A_Boss2PogoTarget(mobj_t *actor) } // Target hit, retreat! - if (actor->target->player->powers[pw_flashing] > TICRATE || actor->flags2 & MF2_FRET) + if ((actor->target->player && actor->target->player->powers[pw_flashing] > TICRATE) || actor->flags2 & MF2_FRET) { UINT8 prandom = P_RandomByte(); actor->z++; // unstick from the floor @@ -7532,7 +7537,7 @@ void A_Boss2PogoTarget(mobj_t *actor) // Try to land on top of the player. else if (P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) < FixedMul(512*FRACUNIT, actor->scale)) { - fixed_t airtime, gravityadd, zoffs; + fixed_t airtime, gravityadd, zoffs, height; // check gravity in the sector (for later math) P_CheckGravity(actor, true); @@ -7554,7 +7559,13 @@ void A_Boss2PogoTarget(mobj_t *actor) // Remember, kids! // Reduced down Calculus lets you avoid bad 'logic math' loops! //airtime = FixedDiv(-actor->momz<<1, gravityadd)<<1; // going from 0 to 0 is much simpler - zoffs = (P_GetPlayerHeight(actor->target->player)>>1) + (actor->target->floorz - actor->floorz); // offset by the difference in floor height plus half the player height, + + if (actor->target->player) + height = P_GetPlayerHeight(actor->target->player) >> 1; + else + height = actor->target->height >> 1; + + zoffs = height + (actor->target->floorz - actor->floorz); // offset by the difference in floor height plus half the player height, airtime = FixedDiv((-actor->momz - FixedSqrt(FixedMul(actor->momz,actor->momz)+zoffs)), gravityadd)<<1; // to try and land on their head rather than on their feet actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); @@ -9868,22 +9879,23 @@ void A_Custom3DRotate(mobj_t *actor) if (LUA_CallAction(A_CUSTOM3DROTATE, actor)) return; + if (!actor->target) // Ensure we actually have a target first. + { + CONS_Printf("Error: A_Custom3DRotate: Object has no target.\n"); + P_RemoveMobj(actor); + return; + } + if (actor->target->health == 0) { P_RemoveMobj(actor); return; } - if (!actor->target) // This should NEVER happen. - { - if (cv_debug) - CONS_Printf("Error: Object has no target\n"); - P_RemoveMobj(actor); - return; - } if (hspeed==0 && vspeed==0) { - CONS_Printf("Error: A_Custom3DRotate: Object has no speed.\n"); + if (cv_debug) + CONS_Printf("Error: A_Custom3DRotate: Object has no speed.\n"); return; } diff --git a/src/p_floor.c b/src/p_floor.c index ed49b03a3..7c26065b5 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1064,9 +1064,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_HOOP: case MT_HOOPCOLLIDE: case MT_NIGHTSCORE: -#ifdef SEENAMES case MT_NAMECHECK: // DEFINITELY not this, because it is client-side. -#endif continue; default: break; diff --git a/src/p_inter.c b/src/p_inter.c index 9bfe54e54..e9a16a3dd 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -470,14 +470,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) { fixed_t setmomz = -toucher->momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce - + if (elementalpierce == 2) // Reset bubblewrap, part 1 P_DoBubbleBounce(player); toucher->momz = setmomz; if (elementalpierce == 2) // Reset bubblewrap, part 2 { boolean underwater = toucher->eflags & MFE_UNDERWATER; - + if (underwater) toucher->momz /= 2; toucher->momz -= (toucher->momz/(underwater ? 8 : 4)); // Cap the height! @@ -1617,7 +1617,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX)) macespin = true; - + if (macespin ? (player->powers[pw_ignorelatch] & (1<<15)) : (player->powers[pw_ignorelatch])) return; diff --git a/src/p_local.h b/src/p_local.h index 8a5084962..8568dd4f8 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -143,6 +143,8 @@ angle_t P_GetLocalAngle(player_t *player); void P_SetLocalAngle(player_t *player, angle_t angle); void P_ForceLocalAngle(player_t *player, angle_t angle); boolean P_PlayerFullbright(player_t *player); +boolean P_PlayerCanEnterSpinGaps(player_t *player); +boolean P_PlayerShouldUseSpinHeight(player_t *player); boolean P_IsObjectInGoop(mobj_t *mo); boolean P_IsObjectOnGround(mobj_t *mo); @@ -326,9 +328,7 @@ mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za, mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t x, fixed_t y, fixed_t z, INT32 shiftingAngle); mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 aimtype, UINT32 flags2); #define P_SpawnPlayerMissile(s,t,f) P_SPMAngle(s,t,s->angle,true,f) -#ifdef SEENAMES #define P_SpawnNameFinder(s,t) P_SPMAngle(s,t,s->angle,true,0) -#endif void P_ColorTeamMissile(mobj_t *missile, player_t *source); SINT8 P_MobjFlip(mobj_t *mobj); fixed_t P_GetMobjGravity(mobj_t *mo); diff --git a/src/p_map.c b/src/p_map.c index 69af85608..bf668ba3e 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -727,9 +727,8 @@ static boolean PIT_CheckThing(mobj_t *thing) || (thing->player && thing->player->spectator)) return true; -#ifdef SEENAMES - // Do name checks all the way up here - // So that NOTHING ELSE can see MT_NAMECHECK because it is client-side. + // Do name checks all the way up here + // So that NOTHING ELSE can see MT_NAMECHECK because it is client-side. if (tmthing->type == MT_NAMECHECK) { // Ignore things that aren't players, ignore spectators, ignore yourself. @@ -753,7 +752,6 @@ static boolean PIT_CheckThing(mobj_t *thing) seenplayer = thing->player; return false; } -#endif // Metal Sonic destroys tiny baby objects. if (tmthing->type == MT_METALSONIC_RACE @@ -1685,7 +1683,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) { fixed_t setmomz = -*momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce - + if (elementalpierce == 2) // Reset bubblewrap, part 1 P_DoBubbleBounce(player); *momz = setmomz; // Therefore, you should be thrust in the opposite direction, vertically. @@ -1694,7 +1692,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (elementalpierce == 2) // Reset bubblewrap, part 2 { boolean underwater = tmthing->eflags & MFE_UNDERWATER; - + if (underwater) *momz /= 2; *momz -= (*momz/(underwater ? 8 : 4)); // Cap the height! @@ -2259,6 +2257,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (!P_BlockThingsIterator(bx, by, PIT_CheckThing)) blockval = false; + else + tmhitthing = tmfloorthing; if (P_MobjWasRemoved(tmthing)) return false; } @@ -2723,7 +2723,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->type == MT_SKIM) maxstep = 0; - if (tmceilingz - tmfloorz < thing->height) + if (tmceilingz - tmfloorz < thing->height + || (thing->player + && tmceilingz - tmfloorz < P_GetPlayerHeight(thing->player) + && !P_PlayerCanEnterSpinGaps(thing->player))) { if (tmfloorthing) tmhitthing = tmfloorthing; @@ -3331,6 +3334,11 @@ static boolean PTR_LineIsBlocking(line_t *li) if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale)) return true; // too big a step up + if (slidemo->player + && openrange < P_GetPlayerHeight(slidemo->player) + && !P_PlayerCanEnterSpinGaps(slidemo->player)) + return true; // nonspin character should not take this path + return false; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 1f87762bc..49db6daee 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3188,13 +3188,16 @@ boolean P_SceneryZMovement(mobj_t *mo) // boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) { - fixed_t topheight = P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y); + boolean flip = player->mo->eflags & MFE_VERTICALFLIP; + fixed_t surfaceheight = flip ? P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y) : P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y); + fixed_t playerbottom = flip ? (player->mo->z + player->mo->height) : player->mo->z; + boolean doifit = flip ? (surfaceheight - player->mo->floorz >= player->mo->height) : (player->mo->ceilingz - surfaceheight >= player->mo->height); if (!player->powers[pw_carry] && !player->homing - && ((player->powers[pw_super] || player->charflags & SF_RUNONWATER || player->dashmode >= DASHMODE_THRESHOLD) && player->mo->ceilingz-topheight >= player->mo->height) + && ((player->powers[pw_super] || player->charflags & SF_RUNONWATER || player->dashmode >= DASHMODE_THRESHOLD) && doifit) && (rover->flags & FF_SWIMMABLE) && !(player->pflags & PF_SPINNING) && player->speed > FixedMul(player->runspeed, player->mo->scale) && !(player->pflags & PF_SLIDING) - && abs(player->mo->z - topheight) < FixedMul(30*FRACUNIT, player->mo->scale)) + && abs(playerbottom - surfaceheight) < FixedMul(30*FRACUNIT, player->mo->scale)) return true; return false; @@ -9837,7 +9840,7 @@ static void P_FlagFuseThink(mobj_t *mobj) if (mobj->type == MT_REDFLAG) { if (!(mobj->flags2 & MF2_JUSTATTACKED)) - CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x85, M_GetText("Red flag"), 0x80); + CONS_Printf(M_GetText("The \205Red flag\200 has returned to base.\n")); // Assumedly in splitscreen players will be on opposing teams if (players[consoleplayer].ctfteam == 1 || splitscreen) @@ -9850,7 +9853,7 @@ static void P_FlagFuseThink(mobj_t *mobj) else // MT_BLUEFLAG { if (!(mobj->flags2 & MF2_JUSTATTACKED)) - CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x84, M_GetText("Blue flag"), 0x80); + CONS_Printf(M_GetText("The \204Blue flag\200 has returned to base.\n")); // Assumedly in splitscreen players will be on opposing teams if (players[consoleplayer].ctfteam == 2 || splitscreen) @@ -10483,9 +10486,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) P_SetThingPosition(mobj); I_Assert(mobj->subsector != NULL); - // Make sure scale matches destscale immediately when spawned - P_SetScale(mobj, mobj->destscale); - mobj->floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y); mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y); @@ -11398,7 +11398,7 @@ void P_SpawnPlayer(INT32 playernum) p->normalspeed = skins[p->skin].normalspeed; p->jumpfactor = skins[p->skin].jumpfactor; } - + // Clear lastlinehit and lastsidehit p->lastsidehit = -1; p->lastlinehit = -1; @@ -11798,7 +11798,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) if (!(G_CoopGametype() || (mthing->options & MTF_EXTRA))) return false; // she doesn't hang out here - if (!mariomode && !(netgame || multiplayer) && players[consoleplayer].skin == 3) + if (!(netgame || multiplayer) && players[consoleplayer].skin == 3) return false; // no doubles break; diff --git a/src/p_saveg.c b/src/p_saveg.c index adedea049..03229e740 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1506,7 +1506,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) { const mobj_t *mobj = (const mobj_t *)th; UINT32 diff; - UINT16 diff2; + UINT32 diff2; // Ignore stationary hoops - these will be respawned from mapthings. if (mobj->type == MT_HOOP) @@ -1638,7 +1638,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_SHADOWSCALE; if (mobj->renderflags) diff2 |= MD2_RENDERFLAGS; - if (mobj->renderflags) + if (mobj->blendmode != AST_TRANSLUCENT) diff2 |= MD2_BLENDMODE; if (mobj->spritexscale != FRACUNIT) diff2 |= MD2_SPRITEXSCALE; @@ -1646,6 +1646,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_SPRITEYSCALE; if (mobj->spritexoffset) diff2 |= MD2_SPRITEXOFFSET; + if (mobj->spriteyoffset) + diff2 |= MD2_SPRITEYOFFSET; if (mobj->floorspriteslope) { pslope_t *slope = mobj->floorspriteslope; @@ -1667,7 +1669,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, type); WRITEUINT32(save_p, diff); if (diff & MD_MORE) - WRITEUINT16(save_p, diff2); + WRITEUINT32(save_p, diff2); // save pointer, at load time we will search this pointer to reinitilize pointers WRITEUINT32(save_p, (size_t)mobj); @@ -2615,14 +2617,14 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) thinker_t *next; mobj_t *mobj; UINT32 diff; - UINT16 diff2; + UINT32 diff2; INT32 i; fixed_t z, floorz, ceilingz; ffloor_t *floorrover = NULL, *ceilingrover = NULL; diff = READUINT32(save_p); if (diff & MD_MORE) - diff2 = READUINT16(save_p); + diff2 = READUINT32(save_p); else diff2 = 0; @@ -2843,10 +2845,16 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->renderflags = READUINT32(save_p); if (diff2 & MD2_BLENDMODE) mobj->blendmode = READINT32(save_p); + else + mobj->blendmode = AST_TRANSLUCENT; if (diff2 & MD2_SPRITEXSCALE) mobj->spritexscale = READFIXED(save_p); + else + mobj->spritexscale = FRACUNIT; if (diff2 & MD2_SPRITEYSCALE) mobj->spriteyscale = READFIXED(save_p); + else + mobj->spriteyscale = FRACUNIT; if (diff2 & MD2_SPRITEXOFFSET) mobj->spritexoffset = READFIXED(save_p); if (diff2 & MD2_SPRITEYOFFSET) diff --git a/src/p_setup.c b/src/p_setup.c index 41d8822e2..40dd1a284 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3171,7 +3171,7 @@ static void P_ConvertBinaryMap(void) switch (mapthings[i].type) { case 750: - Tag_Add(&mapthings[i].tags, mapthings[i].angle); + Tag_FSet(&mapthings[i].tags, mapthings[i].angle); break; case 760: case 761: @@ -4135,7 +4135,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) #ifdef HWRENDER // Free GPU textures before freeing patches. - if (vid.glstate == VID_GL_LIBRARY_LOADED) + if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) HWR_ClearAllTextures(); #endif @@ -4500,7 +4500,7 @@ boolean P_AddWadFile(const char *wadfilename) #ifdef HWRENDER // Free GPU textures before freeing patches. - if (vid.glstate == VID_GL_LIBRARY_LOADED) + if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) HWR_ClearAllTextures(); #endif diff --git a/src/p_setup.h b/src/p_setup.h index 34de9c93d..5d13ae7d4 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -80,6 +80,7 @@ typedef struct UINT8 *picture; #ifdef HWRENDER void *mipmap; + void *mippic; #endif } levelflat_t; diff --git a/src/p_spec.c b/src/p_spec.c index 5b9e05c61..226e58d15 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4304,7 +4304,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (leveltime % (TICRATE/2) == 0 && player->rings > 0) { player->rings--; - S_StartSound(player->mo, sfx_itemup); + S_StartSound(player->mo, sfx_antiri); } break; case 11: // Special Stage Damage @@ -4604,7 +4604,7 @@ DoneSection2: HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE); HU_SetCEchoDuration(5); - HU_DoCEcho(va(M_GetText("%s%s%s\\CAPTURED THE %sBLUE FLAG%s.\\\\\\\\"), "\x85", player_names[player-players], "\x80", "\x84", "\x80")); + HU_DoCEcho(va(M_GetText("\205%s\200\\CAPTURED THE \204BLUE FLAG\200.\\\\\\\\"), player_names[player-players])); if (splitscreen || players[consoleplayer].ctfteam == 1) S_StartSound(NULL, sfx_flgcap); @@ -4637,7 +4637,7 @@ DoneSection2: HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE); HU_SetCEchoDuration(5); - HU_DoCEcho(va(M_GetText("%s%s%s\\CAPTURED THE %sRED FLAG%s.\\\\\\\\"), "\x84", player_names[player-players], "\x80", "\x85", "\x80")); + HU_DoCEcho(va(M_GetText("\204%s\200\\CAPTURED THE \205RED FLAG\200.\\\\\\\\"), player_names[player-players])); if (splitscreen || players[consoleplayer].ctfteam == 2) S_StartSound(NULL, sfx_flgcap); @@ -4827,6 +4827,8 @@ DoneSection2: if (player->laps >= (UINT8)cv_numlaps.value) CONS_Printf(M_GetText("%s has finished the race.\n"), player_names[player-players]); + else if (player->laps == (UINT8)cv_numlaps.value-1) + CONS_Printf(M_GetText("%s started the \205final lap\200!\n"), player_names[player-players]); else CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1); diff --git a/src/p_user.c b/src/p_user.c index 892f4b678..4413cc6cd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -190,7 +190,7 @@ fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move) boolean P_AutoPause(void) { // Don't pause even on menu-up or focus-lost in netgames or record attack - if (netgame || modeattacking || gamestate == GS_TITLESCREEN) + if (netgame || modeattacking || gamestate == GS_TITLESCREEN || (marathonmode && gamestate == GS_INTERMISSION)) return false; return (menuactive || ( window_notinfocus && cv_pauseifunfocused.value )); @@ -2613,10 +2613,10 @@ static void P_CheckBustableBlocks(player_t *player) if ((netgame || multiplayer) && player->spectator) return; - + oldx = player->mo->x; oldy = player->mo->y; - + if (!(player->pflags & PF_BOUNCING)) // Bouncers only get to break downwards, not sideways { P_UnsetThingPosition(player->mo); @@ -2635,7 +2635,7 @@ static void P_CheckBustableBlocks(player_t *player) if (!node->m_sector->ffloors) continue; - + for (rover = node->m_sector->ffloors; rover; rover = rover->next) { if (!P_PlayerCanBust(player, rover)) @@ -4499,7 +4499,7 @@ void P_DoJump(player_t *player, boolean soundandstate) if (twodlevel || (player->mo->flags2 & MF2_TWOD)) factor += player->jumpfactor / 10; - if (player->charflags & SF_MULTIABILITY && player->charability == CA_DOUBLEJUMP) + if (player->charflags & SF_MULTIABILITY && player->charability == CA_DOUBLEJUMP && (player->actionspd >> FRACBITS) != -1) factor -= max(0, player->secondjump * player->jumpfactor / ((player->actionspd >> FRACBITS) + 1)); // Reduce the jump height each time //if (maptol & TOL_NIGHTS) @@ -4525,7 +4525,7 @@ void P_DoJump(player_t *player, boolean soundandstate) player->mo->eflags &= ~MFE_APPLYPMOMZ; player->pflags |= P_GetJumpFlags(player);; - + if (player->charflags & SF_NOJUMPDAMAGE) player->pflags &= ~PF_SPINNING; @@ -4880,22 +4880,28 @@ void P_DoBubbleBounce(player_t *player) // void P_DoAbilityBounce(player_t *player, boolean changemomz) { - fixed_t prevmomz; if (player->mo->state-states == S_PLAY_BOUNCE_LANDING) return; + if (changemomz) { - fixed_t minmomz; - prevmomz = player->mo->momz; + fixed_t prevmomz = player->mo->momz, minmomz; + if (P_MobjFlip(player->mo)*prevmomz < 0) prevmomz = 0; else if (player->mo->eflags & MFE_UNDERWATER) prevmomz /= 2; + P_DoJump(player, false); player->pflags &= ~(PF_STARTJUMP|PF_JUMPED); minmomz = FixedMul(player->mo->momz, 3*FRACUNIT/2); - player->mo->momz = max(minmomz, (minmomz + prevmomz)/2); + + if (player->mo->eflags & MFE_VERTICALFLIP) // Use "min" or "max" depending on if the player is flipped + player->mo->momz = min(minmomz, (minmomz + prevmomz)/2); + else + player->mo->momz = max(minmomz, (minmomz + prevmomz)/2); } + S_StartSound(player->mo, sfx_boingf); P_SetPlayerMobjState(player->mo, S_PLAY_BOUNCE_LANDING); player->pflags |= PF_BOUNCING|PF_THOKKED; @@ -5024,7 +5030,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SPINDOWN) && ((!(player->pflags & PF_THOKKED) || (((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP || (player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) && player->secondjump == UINT8_MAX) ))) // thokked is optional if you're bubblewrapped / 3dblasted { - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT && !(player->charflags & SF_NOSHIELDABILITY)) { if ((lockonshield = P_LookForEnemies(player, false, false))) { @@ -5047,7 +5053,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock } } } - if (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player)) // Spin button effects + if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player))) // Spin button effects { // Force stop if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) @@ -5495,7 +5501,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) break; } } - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super]) + else if ((!(player->charflags & SF_NOSHIELDABILITY)) && ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super] && !LUAh_ShieldSpecial(player))) P_DoJumpShield(player); } @@ -7756,6 +7762,11 @@ void P_ElementalFire(player_t *player, boolean cropcircle) flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); P_InstaThrust(flame, flame->angle, FixedMul(3*FRACUNIT, flame->scale)); P_SetObjectMomZ(flame, 3*FRACUNIT, false); + if (!(gametyperules & GTR_FRIENDLY)) + { + P_SetMobjState(flame, S_TEAM_SPINFIRE1); + flame->color = player->mo->color; + } } #undef limitangle #undef numangles @@ -7783,6 +7794,11 @@ void P_ElementalFire(player_t *player, boolean cropcircle) flame->destscale = player->mo->scale; P_SetScale(flame, player->mo->scale); flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); + if (!(gametyperules & GTR_FRIENDLY)) + { + P_SetMobjState(flame, S_TEAM_SPINFIRE1); + flame->color = player->mo->color; + } flame->momx = 8; // this is a hack which is used to ensure it still behaves as a missile and can damage others P_XYMovement(flame); @@ -8635,14 +8651,16 @@ void P_MovePlayer(player_t *player) { boolean atspinheight = false; fixed_t oldheight = player->mo->height; + fixed_t luaheight = LUAh_PlayerHeight(player); + if (luaheight != -1) + { + player->mo->height = luaheight; + if (luaheight <= P_GetPlayerSpinHeight(player)) + atspinheight = true; // spinning will not save you from being crushed + } // Less height while spinning. Good for spinning under things...? - if ((player->mo->state == &states[player->mo->info->painstate]) - || ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE)) - || (player->pflags & PF_SPINNING) - || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING - || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) - || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) + else if (P_PlayerShouldUseSpinHeight(player)) { player->mo->height = P_GetPlayerSpinHeight(player); atspinheight = true; @@ -11346,7 +11364,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) angle_t angle = player->drawangle; fixed_t dist; panim_t panim = player->panim; - tic_t dashmode = player->dashmode; + tic_t dashmode = min(player->dashmode, DASHMODE_MAX); boolean underwater = mo->eflags & MFE_UNDERWATER; statenum_t stat = fume->state-states; @@ -11484,7 +11502,6 @@ void P_PlayerThink(player_t *player) } } -#ifdef SEENAMES if (netgame && player == &players[displayplayer] && !(leveltime % (TICRATE/5))) { seenplayer = NULL; @@ -11509,7 +11526,6 @@ void P_PlayerThink(player_t *player) } } } -#endif if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj)) { @@ -12939,3 +12955,33 @@ boolean P_PlayerFullbright(player_t *player) || !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] && player->mo->state < &states[S_PLAY_NIGHTS_TRANS6])))); // Note the < instead of <= } + +#define JUMPCURLED(player) ((player->pflags & PF_JUMPED)\ + && (!(player->charflags & SF_NOJUMPSPIN))\ + && (player->panim == PA_JUMP || player->panim == PA_ROLL))\ + +// returns true if the player can enter a sector that they could not if standing at their skin's full height +boolean P_PlayerCanEnterSpinGaps(player_t *player) +{ + UINT8 canEnter = LUAh_PlayerCanEnterSpinGaps(player); + if (canEnter == 1) + return true; + else if (canEnter == 2) + return false; + + return ((player->pflags & (PF_SPINNING|PF_GLIDING)) // players who are spinning or gliding + || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) // players who are landing from a glide + || JUMPCURLED(player)); // players who are jumpcurled, but only if they would normally jump that way +} + +// returns true if the player should use their skin's spinheight instead of their skin's height +boolean P_PlayerShouldUseSpinHeight(player_t *player) +{ + return ((player->pflags & (PF_SPINNING|PF_GLIDING)) + || (player->mo->state == &states[player->mo->info->painstate]) + || (player->panim == PA_ROLL) + || ((player->powers[pw_tailsfly] || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) + && !(player->charflags & SF_NOJUMPSPIN)) + || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) + || JUMPCURLED(player)); +} diff --git a/src/r_data.c b/src/r_data.c index af672f6dc..2cfe9cb7a 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -30,10 +30,6 @@ #include "byteptr.h" #include "dehacked.h" -#ifdef _WIN32 -#include // alloca(sizeof) -#endif - // // Graphics. // SRB2 graphics for walls and sprites diff --git a/src/r_draw.c b/src/r_draw.c index d9ea942a2..9a835ee58 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -134,19 +134,51 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; #define DEFAULT_STARTTRANSCOLOR 96 #define NUM_PALETTE_ENTRIES 256 -static UINT8** translationtablecache[MAXSKINS + 7] = {NULL}; +static UINT8 **translationtablecache[MAXSKINS + 7] = {NULL}; UINT8 skincolor_modified[MAXSKINCOLORS]; -CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; +static INT32 SkinToCacheIndex(INT32 skinnum) +{ + switch (skinnum) + { + case TC_DEFAULT: return DEFAULT_TT_CACHE_INDEX; + case TC_BOSS: return BOSS_TT_CACHE_INDEX; + case TC_METALSONIC: return METALSONIC_TT_CACHE_INDEX; + case TC_ALLWHITE: return ALLWHITE_TT_CACHE_INDEX; + case TC_RAINBOW: return RAINBOW_TT_CACHE_INDEX; + case TC_BLINK: return BLINK_TT_CACHE_INDEX; + case TC_DASHMODE: return DASHMODE_TT_CACHE_INDEX; + default: break; + } -#define TRANSTAB_AMTMUL10 (256.0f / 10.0f) + return skinnum; +} + +static INT32 CacheIndexToSkin(INT32 ttc) +{ + switch (ttc) + { + case DEFAULT_TT_CACHE_INDEX: return TC_DEFAULT; + case BOSS_TT_CACHE_INDEX: return TC_BOSS; + case METALSONIC_TT_CACHE_INDEX: return TC_METALSONIC; + case ALLWHITE_TT_CACHE_INDEX: return TC_ALLWHITE; + case RAINBOW_TT_CACHE_INDEX: return TC_RAINBOW; + case BLINK_TT_CACHE_INDEX: return TC_BLINK; + case DASHMODE_TT_CACHE_INDEX: return TC_DASHMODE; + default: break; + } + + return ttc; +} + +CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; /** \brief Initializes the translucency tables used by the Software renderer. */ void R_InitTranslucencyTables(void) { - // Load here the transparency lookup tables 'TINTTAB' - // NOTE: the TINTTAB resource MUST BE aligned on 64k for the asm + // Load here the transparency lookup tables 'TRANSx0' + // NOTE: the TRANSx0 resources MUST BE aligned on 64k for the asm // optimised code (in other words, transtables pointer low word is 0) transtables = Z_MallocAlign(NUMTRANSTABLES*0x10000, PU_STATIC, NULL, 16); @@ -164,42 +196,14 @@ void R_InitTranslucencyTables(void) R_GenerateBlendTables(); } -void R_GenerateBlendTables(void) -{ - INT32 i; - - for (i = 0; i < NUMBLENDMAPS; i++) - { - if (i == blendtab_modulate) - continue; - blendtables[i] = Z_MallocAlign((NUMTRANSTABLES + 1) * 0x10000, PU_STATIC, NULL, 16); - } - - for (i = 0; i <= 9; i++) - { - const size_t offs = (0x10000 * i); - const UINT8 alpha = TRANSTAB_AMTMUL10 * i; - - R_GenerateTranslucencyTable(blendtables[blendtab_add] + offs, AST_ADD, alpha); - R_GenerateTranslucencyTable(blendtables[blendtab_subtract] + offs, AST_SUBTRACT, alpha); - R_GenerateTranslucencyTable(blendtables[blendtab_reversesubtract] + offs, AST_REVERSESUBTRACT, alpha); - } - - // Modulation blending only requires a single table - blendtables[blendtab_modulate] = Z_MallocAlign(0x10000, PU_STATIC, NULL, 16); - R_GenerateTranslucencyTable(blendtables[blendtab_modulate], AST_MODULATE, 0); -} - static colorlookup_t transtab_lut; -void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt) +static void BlendTab_Translucent(UINT8 *table, int style, UINT8 blendamt) { INT16 bg, fg; if (table == NULL) - I_Error("R_GenerateTranslucencyTable: input table was NULL!"); - - InitColorLUT(&transtab_lut, pMasterPalette, false); + I_Error("BlendTab_Translucent: input table was NULL!"); for (bg = 0; bg < 0xFF; bg++) { @@ -209,12 +213,123 @@ void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt) RGBA_t frontrgba = V_GetMasterColor(fg); RGBA_t result; - result.rgba = ASTBlendPixel(backrgba, frontrgba, style, blendamt); + result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF); + result.rgba = ASTBlendPixel(result, frontrgba, AST_TRANSLUCENT, blendamt); + table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue); } } } +static void BlendTab_Subtractive(UINT8 *table, int style, UINT8 blendamt) +{ + INT16 bg, fg; + + if (table == NULL) + I_Error("BlendTab_Subtractive: input table was NULL!"); + + if (blendamt == 0xFF) + { + memset(table, GetColorLUT(&transtab_lut, 0, 0, 0), 0x10000); + return; + } + + for (bg = 0; bg < 0xFF; bg++) + { + for (fg = 0; fg < 0xFF; fg++) + { + RGBA_t backrgba = V_GetMasterColor(bg); + RGBA_t frontrgba = V_GetMasterColor(fg); + RGBA_t result; + + result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF); + result.s.red = max(0, result.s.red - blendamt); + result.s.green = max(0, result.s.green - blendamt); + result.s.blue = max(0, result.s.blue - blendamt); + + table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue); + } + } +} + +static void BlendTab_Modulative(UINT8 *table) +{ + INT16 bg, fg; + + if (table == NULL) + I_Error("BlendTab_Modulative: input table was NULL!"); + + for (bg = 0; bg < 0xFF; bg++) + { + for (fg = 0; fg < 0xFF; fg++) + { + RGBA_t backrgba = V_GetMasterColor(bg); + RGBA_t frontrgba = V_GetMasterColor(fg); + RGBA_t result; + result.rgba = ASTBlendPixel(backrgba, frontrgba, AST_MODULATE, 0); + table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue); + } + } +} + +static INT32 BlendTab_Count[NUMBLENDMAPS] = +{ + NUMTRANSTABLES+1, // blendtab_add + NUMTRANSTABLES+1, // blendtab_subtract + NUMTRANSTABLES+1, // blendtab_reversesubtract + 1 // blendtab_modulate +}; + +static INT32 BlendTab_FromStyle[] = +{ + 0, // AST_COPY + 0, // AST_TRANSLUCENT + blendtab_add, // AST_ADD + blendtab_subtract, // AST_SUBTRACT + blendtab_reversesubtract, // AST_REVERSESUBTRACT + blendtab_modulate, // AST_MODULATE + 0 // AST_OVERLAY +}; + +static void BlendTab_GenerateMaps(INT32 tab, INT32 style, void (*genfunc)(UINT8 *, int, UINT8)) +{ + INT32 i = 0, num = BlendTab_Count[tab]; + const float amtmul = (256.0f / (float)(NUMTRANSTABLES + 1)); + for (; i < num; i++) + { + const size_t offs = (0x10000 * i); + const UINT16 alpha = min(amtmul * i, 0xFF); + genfunc(blendtables[tab] + offs, style, alpha); + } +} + +void R_GenerateBlendTables(void) +{ + INT32 i; + + for (i = 0; i < NUMBLENDMAPS; i++) + blendtables[i] = Z_MallocAlign(BlendTab_Count[i] * 0x10000, PU_STATIC, NULL, 16); + + InitColorLUT(&transtab_lut, pMasterPalette, false); + + // Additive + BlendTab_GenerateMaps(blendtab_add, AST_ADD, BlendTab_Translucent); + + // Subtractive +#if 1 + BlendTab_GenerateMaps(blendtab_subtract, AST_SUBTRACT, BlendTab_Subtractive); +#else + BlendTab_GenerateMaps(blendtab_subtract, AST_SUBTRACT, BlendTab_Translucent); +#endif + + // Reverse subtractive + BlendTab_GenerateMaps(blendtab_reversesubtract, AST_REVERSESUBTRACT, BlendTab_Translucent); + + // Modulative blending only requires a single table + BlendTab_Modulative(blendtables[blendtab_modulate]); +} + +#define ClipBlendLevel(style, trans) max(min((trans), BlendTab_Count[BlendTab_FromStyle[style]]-1), 0) #define ClipTransLevel(trans) max(min((trans), NUMTRANSMAPS-2), 0) UINT8 *R_GetTranslucencyTable(INT32 alphalevel) @@ -224,7 +339,12 @@ UINT8 *R_GetTranslucencyTable(INT32 alphalevel) UINT8 *R_GetBlendTable(int style, INT32 alphalevel) { - size_t offs = (ClipTransLevel(alphalevel) << FF_TRANSSHIFT); + size_t offs; + + if (style == AST_COPY || style == AST_OVERLAY) + return NULL; + + offs = (ClipBlendLevel(style, alphalevel) << FF_TRANSSHIFT); // Lactozilla: Returns the equivalent to AST_TRANSLUCENT // if no alpha style matches any of the blend tables. @@ -249,6 +369,14 @@ UINT8 *R_GetBlendTable(int style, INT32 alphalevel) return NULL; } +boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel) +{ + if (blendmode == AST_COPY || blendmode == AST_SUBTRACT || blendmode == AST_MODULATE || blendmode == AST_OVERLAY) + return true; + + return (alphalevel < BlendTab_Count[BlendTab_FromStyle[blendmode]]); +} + // Define for getting accurate color brightness readings according to how the human eye sees them. // https://en.wikipedia.org/wiki/Relative_luminance // 0.2126 to red @@ -308,7 +436,7 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT16 skincolor) /** \brief Generates a translation colormap. \param dest_colormap colormap to populate - \param skinnum number of skin, TC_DEFAULT or TC_BOSS + \param skinnum skin number, or a translation mode \param color translation color \return void @@ -412,6 +540,9 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U if (color >= numskincolors) I_Error("Invalid skin color #%hu.", (UINT16)color); + if (skinnum < 0 && skinnum > TC_DEFAULT) + I_Error("Invalid translation colormap index %d.", skinnum); + starttranscolor = (skinnum != TC_DEFAULT) ? skins[skinnum].starttranscolor : DEFAULT_STARTTRANSCOLOR; if (starttranscolor >= NUM_PALETTE_ENTRIES) @@ -448,25 +579,11 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags) { UINT8* ret; - INT32 skintableindex; + INT32 skintableindex = SkinToCacheIndex(skinnum); // Adjust if we want the default colormap INT32 i; - // Adjust if we want the default colormap - switch (skinnum) - { - case TC_DEFAULT: skintableindex = DEFAULT_TT_CACHE_INDEX; break; - case TC_BOSS: skintableindex = BOSS_TT_CACHE_INDEX; break; - case TC_METALSONIC: skintableindex = METALSONIC_TT_CACHE_INDEX; break; - case TC_ALLWHITE: skintableindex = ALLWHITE_TT_CACHE_INDEX; break; - case TC_RAINBOW: skintableindex = RAINBOW_TT_CACHE_INDEX; break; - case TC_BLINK: skintableindex = BLINK_TT_CACHE_INDEX; break; - case TC_DASHMODE: skintableindex = DASHMODE_TT_CACHE_INDEX; break; - default: skintableindex = skinnum; break; - } - if (flags & GTC_CACHE) { - // Allocate table for skin if necessary if (!translationtablecache[skintableindex]) translationtablecache[skintableindex] = Z_Calloc(MAXSKINCOLORS * sizeof(UINT8**), PU_STATIC, NULL); @@ -479,7 +596,8 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags { for (i = 0; i < (INT32)(sizeof(translationtablecache) / sizeof(translationtablecache[0])); i++) if (translationtablecache[i] && translationtablecache[i][color]) - R_GenerateTranslationColormap(translationtablecache[i][color], i>=MAXSKINS ? MAXSKINS-i-1 : i, color); + R_GenerateTranslationColormap(translationtablecache[i][color], CacheIndexToSkin(i), color); + skincolor_modified[color] = false; } } diff --git a/src/r_draw.h b/src/r_draw.h index d1eb83033..caf43fd89 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -140,11 +140,12 @@ extern UINT8 *blendtables[NUMBLENDMAPS]; void R_InitTranslucencyTables(void); void R_GenerateBlendTables(void); -void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt); UINT8 *R_GetTranslucencyTable(INT32 alphalevel); UINT8 *R_GetBlendTable(int style, INT32 alphalevel); +boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel); + // Color ramp modification should force a recache extern UINT8 skincolor_modified[]; diff --git a/src/r_draw8.c b/src/r_draw8.c index e78ba8a6c..1f451115e 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1447,10 +1447,7 @@ void R_DrawFloorSprite_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - // - // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[0] = colormap[translation[val & 0xFF]]; @@ -1458,7 +1455,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[1] = colormap[translation[val & 0xFF]]; @@ -1466,7 +1462,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[2] = colormap[translation[val & 0xFF]]; @@ -1474,7 +1469,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[3] = colormap[translation[val & 0xFF]]; @@ -1482,7 +1476,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[4] = colormap[translation[val & 0xFF]]; @@ -1490,7 +1483,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[5] = colormap[translation[val & 0xFF]]; @@ -1498,7 +1490,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[6] = colormap[translation[val & 0xFF]]; @@ -1506,7 +1497,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[7] = colormap[translation[val & 0xFF]]; diff --git a/src/r_main.c b/src/r_main.c index f82fb589e..04bdebc58 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1089,8 +1089,6 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y) // 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out) static void R_SetupFreelook(player_t *player, boolean skybox) { - INT32 dy = 0; - #ifndef HWRENDER (void)player; (void)skybox; @@ -1109,14 +1107,15 @@ static void R_SetupFreelook(player_t *player, boolean skybox) G_SoftwareClipAimingPitch((INT32 *)&aimingangle); } - if (rendermode == render_soft) - { - dy = (AIMINGTODY(aimingangle)>>FRACBITS) * viewwidth/BASEVIDWIDTH; - yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)]; - } + centeryfrac = (viewheight/2)<width : SHORT(patch->width)); + width = (isdoompatch ? SHORT(doompatch->width) : patch->width); if (x >= 0 && x < width) { INT32 colx = (flags & PICFLAGS_XFLIP) ? (width-1)-x : x; INT32 topdelta, prevdelta = -1; - INT32 colofs = (Picture_IsDoomPatchFormat(informat) ? LONG(patch->columnofs[colx]) : patch->columnofs[colx]); + INT32 colofs = (isdoompatch ? LONG(doompatch->columnofs[colx]) : patch->columnofs[colx]); - // Column offsets are pointers so no casting required - if (Picture_IsDoomPatchFormat(informat)) + // Column offsets are pointers, so no casting is required. + if (isdoompatch) column = (column_t *)((UINT8 *)doompatch + colofs); else column = (column_t *)((UINT8 *)patch->columns + colofs); diff --git a/src/r_plane.c b/src/r_plane.c index c54b32382..ea4dfa4e8 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -154,14 +154,10 @@ static void R_UpdatePlaneRipple(void) // R_MapPlane // // Uses global vars: +// planeheight // basexscale // baseyscale // centerx -// viewx -// viewy -// viewsin -// viewcos -// viewheight void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { @@ -580,7 +576,7 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) // void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) { - // Alam: from r_splats's R_RenderFloorSplat + // Alam: from r_splats's R_RasterizeFloorSplat if (t1 >= vid.height) t1 = vid.height-1; if (b1 >= vid.height) b1 = vid.height-1; if (t2 >= vid.height) t2 = vid.height-1; @@ -705,9 +701,9 @@ void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planev n.z = -xscale * cos(ang); ang = ANG2RAD(planeangle); - temp = P_GetSlopeZAt(slope, planeviewx + yscale * FLOAT_TO_FIXED(sin(ang)), planeviewy + yscale * FLOAT_TO_FIXED(cos(ang))); + temp = P_GetSlopeZAt(slope, planeviewx + FLOAT_TO_FIXED(yscale * sin(ang)), planeviewy + FLOAT_TO_FIXED(yscale * cos(ang))); m.y = FIXED_TO_FLOAT(temp) - zeroheight; - temp = P_GetSlopeZAt(slope, planeviewx + xscale * FLOAT_TO_FIXED(cos(ang)), planeviewy - xscale * FLOAT_TO_FIXED(sin(ang))); + temp = P_GetSlopeZAt(slope, planeviewx + FLOAT_TO_FIXED(xscale * cos(ang)), planeviewy - FLOAT_TO_FIXED(xscale * sin(ang))); n.y = FIXED_TO_FLOAT(temp) - zeroheight; if (ds_powersoftwo) @@ -788,7 +784,6 @@ void R_DrawSinglePlane(visplane_t *pl) ffloor_t *rover; int type; int spanfunctype = BASEDRAWFUNC; - angle_t viewang = viewangle; if (!(pl->minx <= pl->maxx)) return; @@ -1153,8 +1148,6 @@ using the palette colors. } } #endif - - viewangle = viewang; } void R_PlaneBounds(visplane_t *plane) diff --git a/src/r_segs.c b/src/r_segs.c index c79071e9b..a6772f964 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1649,23 +1649,26 @@ void R_StoreWallRange(INT32 start, INT32 stop) // left temp = xtoviewangle[start]+viewangle; +#define FIXED_TO_DOUBLE(x) (((double)(x)) / ((double)FRACUNIT)) +#define DOUBLE_TO_FIXED(x) (fixed_t)((x) * ((double)FRACUNIT)) + { // Both lines can be written in slope-intercept form, so figure out line intersection - float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... - ///TODO: convert to FPU + double a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... + ///TODO: convert to fixed point - a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y); - b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x); - c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y); + a1 = FIXED_TO_DOUBLE(curline->v2->y-curline->v1->y); + b1 = FIXED_TO_DOUBLE(curline->v1->x-curline->v2->x); + c1 = a1*FIXED_TO_DOUBLE(curline->v1->x) + b1*FIXED_TO_DOUBLE(curline->v1->y); - a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT)); - b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT)); - c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy); + a2 = -FIXED_TO_DOUBLE(FINESINE(temp>>ANGLETOFINESHIFT)); + b2 = FIXED_TO_DOUBLE(FINECOSINE(temp>>ANGLETOFINESHIFT)); + c2 = a2*FIXED_TO_DOUBLE(viewx) + b2*FIXED_TO_DOUBLE(viewy); det = a1*b2 - a2*b1; - ds_p->leftpos.x = segleft.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det); - ds_p->leftpos.y = segleft.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det); + ds_p->leftpos.x = segleft.x = DOUBLE_TO_FIXED((b2*c1 - b1*c2)/det); + ds_p->leftpos.y = segleft.y = DOUBLE_TO_FIXED((a1*c2 - a2*c1)/det); } // right @@ -1673,22 +1676,26 @@ void R_StoreWallRange(INT32 start, INT32 stop) { // Both lines can be written in slope-intercept form, so figure out line intersection - float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... - ///TODO: convert to FPU + double a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... + ///TODO: convert to fixed point - a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y); - b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x); - c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y); + a1 = FIXED_TO_DOUBLE(curline->v2->y-curline->v1->y); + b1 = FIXED_TO_DOUBLE(curline->v1->x-curline->v2->x); + c1 = a1*FIXED_TO_DOUBLE(curline->v1->x) + b1*FIXED_TO_DOUBLE(curline->v1->y); - a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT)); - b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT)); - c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy); + a2 = -FIXED_TO_DOUBLE(FINESINE(temp>>ANGLETOFINESHIFT)); + b2 = FIXED_TO_DOUBLE(FINECOSINE(temp>>ANGLETOFINESHIFT)); + c2 = a2*FIXED_TO_DOUBLE(viewx) + b2*FIXED_TO_DOUBLE(viewy); det = a1*b2 - a2*b1; - ds_p->rightpos.x = segright.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det); - ds_p->rightpos.y = segright.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det); + ds_p->rightpos.x = segright.x = DOUBLE_TO_FIXED((b2*c1 - b1*c2)/det); + ds_p->rightpos.y = segright.y = DOUBLE_TO_FIXED((a1*c2 - a2*c1)/det); } + +#undef FIXED_TO_DOUBLE +#undef DOUBLE_TO_FIXED + } diff --git a/src/r_skins.c b/src/r_skins.c index 522d9236a..6f150f234 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -514,6 +514,7 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) GETFLAG(NOSUPERSPRITES) GETFLAG(NOSUPERJUMPBOOST) GETFLAG(CANBUSTWALLS) + GETFLAG(NOSHIELDABILITY) #undef GETFLAG else // let's check if it's a sound, otherwise error out diff --git a/src/r_splats.c b/src/r_splats.c index a3fad82d8..72cac9fd9 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,11 +28,12 @@ static void prepare_rastertab(void); // FLOOR SPLATS // ========================================================================== +static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis); + #ifdef USEASM void ASMCALL rasterize_segment_tex_asm(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir); #endif -// Lactozilla static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir) { #ifdef USEASM @@ -137,7 +138,7 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 } } -void R_DrawFloorSprite(vissprite_t *spr) +void R_DrawFloorSplat(vissprite_t *spr) { floorsplat_t splat; mobj_t *mobj = spr->mobj; @@ -187,7 +188,7 @@ void R_DrawFloorSprite(vissprite_t *spr) if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) splatangle = mobj->angle; else - splatangle = viewangle; + splatangle = spr->viewangle; if (!(spr->cut & SC_ISROTATED)) splatangle += mobj->rollangle; @@ -265,7 +266,6 @@ void R_DrawFloorSprite(vissprite_t *spr) if (splat.tilted) { - // Lactozilla: Just copy the entire slope LMFAOOOO pslope_t *s = &splat.slope; s->o.x = slope->o.x; @@ -330,7 +330,7 @@ void R_DrawFloorSprite(vissprite_t *spr) v2d[i].y = (centeryfrac + FixedMul(rot_z, yscale))>>FRACBITS; } - R_RenderFloorSplat(&splat, v2d, spr); + R_RasterizeFloorSplat(&splat, v2d, spr); } // -------------------------------------------------------------------------- @@ -338,7 +338,7 @@ void R_DrawFloorSprite(vissprite_t *spr) // fill the polygon with linear interpolation, call span drawer for each // scan line // -------------------------------------------------------------------------- -void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis) +static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis) { // rasterizing INT32 miny = viewheight + 1, maxy = 0; @@ -416,11 +416,10 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis if (R_CheckPowersOfTwo()) R_CheckFlatLength(ds_flatwidth * ds_flatheight); - // Lactozilla: I don't know what I'm doing if (pSplat->tilted) { R_SetTiltedSpan(0); - R_CalculateSlopeVectors(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, viewangle, pSplat->angle, 1.0f); + R_CalculateSlopeVectors(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewangle, pSplat->angle, 1.0f); spanfunctype = SPANDRAWFUNC_TILTEDSPRITE; } else @@ -533,7 +532,7 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis fixed_t xstep, ystep; fixed_t distance, span; - angle_t angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT; + angle_t angle = (vis->viewangle + pSplat->angle)>>ANGLETOFINESHIFT; angle_t planecos = FINECOSINE(angle); angle_t planesin = FINESINE(angle); @@ -543,17 +542,13 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); span = abs(centery - y); - if (span) // don't divide by zero + if (span) // Don't divide by zero { xstep = FixedMul(planesin, planeheight) / span; ystep = FixedMul(planecos, planeheight) / span; } else - { - // ah - xstep = FRACUNIT; - ystep = FRACUNIT; - } + xstep = ystep = FRACUNIT; cachedxstep[y] = xstep; cachedystep[y] = ystep; diff --git a/src/r_splats.h b/src/r_splats.h index e1f836f48..05d8b66b0 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -42,7 +42,6 @@ typedef struct floorsplat_s mobj_t *mobj; // Mobj it is tied to } floorsplat_t; -void R_DrawFloorSprite(vissprite_t *spr); -void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis); +void R_DrawFloorSplat(vissprite_t *spr); #endif /*__R_SPLATS_H__*/ diff --git a/src/r_textures.c b/src/r_textures.c index 9de9649e2..d5da69018 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,11 +28,6 @@ #include "byteptr.h" #include "dehacked.h" -// I don't know what this is even for, but r_data.c had it. -#ifdef _WIN32 -#include // alloca(sizeof) -#endif - #ifdef HWRENDER #include "hardware/hw_glob.h" // HWR_LoadMapTextures #endif @@ -604,7 +599,7 @@ void *R_GetLevelFlat(levelflat_t *levelflat) levelflat->height = ds_flatheight = SHORT(patch->height); levelflat->picture = Z_Malloc(levelflat->width * levelflat->height, PU_LEVEL, NULL); - converted = Picture_FlatConvert(PICFMT_DOOMPATCH, patch, PICFMT_FLAT, 0, &size, levelflat->width, levelflat->height, patch->topoffset, patch->leftoffset, 0); + converted = Picture_FlatConvert(PICFMT_DOOMPATCH, patch, PICFMT_FLAT, 0, &size, levelflat->width, levelflat->height, SHORT(patch->topoffset), SHORT(patch->leftoffset), 0); M_Memcpy(levelflat->picture, converted, size); Z_Free(converted); } @@ -626,7 +621,7 @@ void *R_GetLevelFlat(levelflat_t *levelflat) // // R_CheckPowersOfTwo // -// Self-explanatory? +// Sets ds_powersoftwo true if the flat's dimensions are powers of two, and returns that. // boolean R_CheckPowersOfTwo(void) { diff --git a/src/r_things.c b/src/r_things.c index 083373927..a7c44c237 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -796,7 +796,7 @@ static void R_DrawVisSprite(vissprite_t *vis) INT32 pwidth; fixed_t frac; patch_t *patch = vis->patch; - fixed_t this_scale = vis->mobj->scale; + fixed_t this_scale = vis->thingscale; INT32 x1, x2; INT64 overflow_test; @@ -1078,6 +1078,14 @@ static void R_SplitSprite(vissprite_t *sprite) sprite->sz = cutfrac; newsprite->szt = (INT16)(sprite->sz - 1); + if (testheight < sprite->pzt && testheight > sprite->pz) + sprite->pz = newsprite->pzt = testheight; + else + { + newsprite->pz = newsprite->gz; + newsprite->pzt = newsprite->gzt; + } + newsprite->szt -= 8; newsprite->cut |= SC_TOP; @@ -1300,12 +1308,16 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, shadow->patch = patch; shadow->heightsec = vis->heightsec; + shadow->thingheight = FRACUNIT; + shadow->pz = groundz + (isflipped ? -shadow->thingheight : 0); + shadow->pzt = shadow->pz + shadow->thingheight; + shadow->mobjflags = 0; shadow->sortscale = vis->sortscale; shadow->dispoffset = vis->dispoffset - 5; shadow->gx = thing->x; shadow->gy = thing->y; - shadow->gzt = groundz + patch->height * shadowyscale / 2; + shadow->gzt = (isflipped ? shadow->pzt : shadow->pz) + patch->height * shadowyscale / 2; shadow->gz = shadow->gzt - patch->height * shadowyscale; shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) @@ -1320,6 +1332,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, shadow->xscale = FixedMul(xscale, shadowxscale); //SoM: 4/17/2000 shadow->scale = FixedMul(yscale, shadowyscale); + shadow->thingscale = thing->scale; shadow->sector = vis->sector; shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewz, yscale))>>FRACBITS); shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS); @@ -1411,7 +1424,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t sheartan = 0; fixed_t shadowscale = FRACUNIT; - fixed_t basetx; // drop shadows + fixed_t basetx, basetz; // drop shadows boolean shadowdraw, shadoweffects, shadowskew; boolean splat = R_ThingIsFloorSprite(thing); @@ -1441,7 +1454,7 @@ static void R_ProjectSprite(mobj_t *thing) tr_x = thing->x - viewx; tr_y = thing->y - viewy; - tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance + basetz = tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance // thing is behind view plane? if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later @@ -1790,7 +1803,7 @@ static void R_ProjectSprite(mobj_t *thing) else if (oldthing->frame & FF_TRANSMASK) { trans = (oldthing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; - if (oldthing->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) + if (!R_BlendLevelVisible(oldthing->blendmode, trans)) return; } else @@ -1935,11 +1948,15 @@ static void R_ProjectSprite(mobj_t *thing) vis->gy = thing->y; vis->gz = gz; vis->gzt = gzt; + vis->thingheight = thing->height; + vis->pz = thing->z; + vis->pzt = vis->pz + vis->thingheight; vis->texturemid = FixedDiv(gzt - viewz, spriteyscale); vis->scalestep = scalestep; vis->paperoffset = paperoffset; vis->paperdistance = paperdistance; vis->centerangle = centerangle; + vis->viewangle = viewangle; vis->shear.tan = sheartan; vis->shear.offset = 0; @@ -1960,6 +1977,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->xscale = FixedMul(spritexscale, xscale); //SoM: 4/17/2000 vis->scale = FixedMul(spriteyscale, yscale); //<thingscale = oldthing->scale; vis->spritexscale = spritexscale; vis->spriteyscale = spriteyscale; @@ -2037,7 +2055,7 @@ static void R_ProjectSprite(mobj_t *thing) R_SplitSprite(vis); if (oldthing->shadowscale && cv_shadow.value) - R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, tz); + R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, basetz); // Debug ++objectsdrawn; @@ -2151,6 +2169,9 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis->gy = thing->y; vis->gz = gz; vis->gzt = gzt; + vis->thingheight = 4*FRACUNIT; + vis->pz = thing->z; + vis->pzt = vis->pz + vis->thingheight; vis->texturemid = vis->gzt - viewz; vis->scalestep = 0; vis->paperdistance = 0; @@ -2179,7 +2200,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) // specific translucency if (thing->frame & FF_TRANSMASK) - vis->transmap = (thing->frame & FF_TRANSMASK) - 0x10000 + transtables; + vis->transmap = R_GetTranslucencyTable((thing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT); else vis->transmap = NULL; @@ -2544,15 +2565,19 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps planeobjectz = P_GetZAt(r2->plane->slope, rover->gx, rover->gy, r2->plane->height); planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy, r2->plane->height); - // bird: if any part of the sprite peeks in front the plane - if (planecameraz < viewz) + if (rover->mobjflags & MF_NOCLIPHEIGHT) { - if (rover->gzt >= planeobjectz) + //Objects with NOCLIPHEIGHT can appear halfway in. + if (planecameraz < viewz && rover->pz+(rover->thingheight/2) >= planeobjectz) + continue; + if (planecameraz > viewz && rover->pzt-(rover->thingheight/2) <= planeobjectz) continue; } - else if (planecameraz > viewz) + else { - if (rover->gz <= planeobjectz) + if (planecameraz < viewz && rover->pz >= planeobjectz) + continue; + if (planecameraz > viewz && rover->pzt <= planeobjectz) continue; } @@ -2585,7 +2610,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps } else if (r2->thickseg) { - //fixed_t topplaneobjectz, topplanecameraz, botplaneobjectz, botplanecameraz; + fixed_t topplaneobjectz, topplanecameraz, botplaneobjectz, botplanecameraz; if (rover->x1 > r2->thickseg->x2 || rover->x2 < r2->thickseg->x1) continue; @@ -2596,11 +2621,6 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps if (scale <= rover->sortscale) continue; - // bird: Always sort sprites behind segs. This helps the plane - // sorting above too. Basically if the sprite gets sorted behind - // the seg here, it will be behind the plane too, since planes - // are added after segs in the list. -#if 0 topplaneobjectz = P_GetFFloorTopZAt (r2->ffloor, rover->gx, rover->gy); topplanecameraz = P_GetFFloorTopZAt (r2->ffloor, viewx, viewy); botplaneobjectz = P_GetFFloorBottomZAt(r2->ffloor, rover->gx, rover->gy); @@ -2609,7 +2629,6 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps if ((topplanecameraz > viewz && botplanecameraz < viewz) || (topplanecameraz < viewz && rover->gzt < topplaneobjectz) || (botplanecameraz > viewz && rover->gz > botplaneobjectz)) -#endif { entry = R_CreateDrawNode(NULL); (entry->prev = r2->prev)->next = entry; @@ -2650,11 +2669,23 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps if (!behind) { - // FIXME: calculate gz and gzt for splats properly and use that - if (rover->mobj->z < viewz) - infront = (r2->sprite->mobj->z >= rover->mobj->z); + fixed_t z1 = 0, z2 = 0; + + if (rover->mobj->z - viewz > 0) + { + z1 = rover->pz; + z2 = r2->sprite->pz; + } else - infront = (r2->sprite->mobj->z <= rover->mobj->z); + { + z1 = r2->sprite->pz; + z2 = rover->pz; + } + + z1 -= viewz; + z2 -= viewz; + + infront = (z1 >= z2); } } else @@ -2753,7 +2784,7 @@ static void R_DrawSprite(vissprite_t *spr) mceilingclip = spr->cliptop; if (spr->cut & SC_SPLAT) - R_DrawFloorSprite(spr); + R_DrawFloorSplat(spr); else R_DrawVisSprite(spr); } diff --git a/src/r_things.h b/src/r_things.h index d15ae818c..95b4215af 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -151,10 +151,12 @@ typedef struct vissprite_s INT32 x1, x2; fixed_t gx, gy; // for line side calculation - fixed_t gz, gzt; // global bottom/top for silhouette clipping and sorting with 3D floors + fixed_t gz, gzt; // global bottom/top for silhouette clipping + fixed_t pz, pzt; // physical bottom/top for sorting with 3D floors fixed_t startfrac; // horizontal position of x1 - fixed_t scale; + fixed_t xscale, scale; // projected horizontal and vertical scales + fixed_t thingscale; // the object's scale fixed_t sortscale; // sortscale only differs from scale for paper sprites, floor sprites, and MF2_LINKDRAW fixed_t sortsplat; // the sortscale from behind the floor sprite fixed_t scalestep; // only for paper sprites, 0 otherwise @@ -162,6 +164,7 @@ typedef struct vissprite_s fixed_t xiscale; // negative if flipped angle_t centerangle; // for paper sprites + angle_t viewangle; // for floor sprites, the viewpoint's current angle struct { fixed_t tan; // The amount to shear the sprite vertically per row @@ -182,9 +185,8 @@ typedef struct vissprite_s extracolormap_t *extra_colormap; // global colormaps - fixed_t xscale; - // Precalculated top and bottom screen coords for the sprite. + fixed_t thingheight; // The actual height of the thing (for 3D floors) sector_t *sector; // The sector containing the thing. INT16 sz, szt; diff --git a/src/s_sound.c b/src/s_sound.c index 36bd454c1..392a5b453 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2143,7 +2143,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst) static lumpnum_t S_GetMusicLumpNum(const char *mname) { boolean midipref = cv_musicpref.value; - + if (S_PrefAvailable(midipref, mname)) return W_GetNumForName(va(midipref ? "d_%s":"o_%s", mname)); else if (S_PrefAvailable(!midipref, mname)) @@ -2291,7 +2291,7 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 I_FadeSong(0, prefadems, S_ChangeMusicToQueue); return; } - else if (strnicmp(music_name, newmusic, 6) || (mflags & MUSIC_FORCERESET) || + else if (strnicmp(music_name, newmusic, 6) || (mflags & MUSIC_FORCERESET) || (midipref != currentmidi && S_PrefAvailable(midipref, newmusic))) { CONS_Debug(DBG_DETAILED, "Now playing song %s\n", newmusic); diff --git a/src/screen.c b/src/screen.c index 9d36eee39..d37724390 100644 --- a/src/screen.c +++ b/src/screen.c @@ -33,6 +33,11 @@ #include "s_sound.h" // ditto #include "g_game.h" // ditto #include "p_local.h" // P_AutoPause() +#ifdef HWRENDER +#include "hardware/hw_main.h" +#include "hardware/hw_light.h" +#include "hardware/hw_model.h" +#endif #if defined (USEASM) && !defined (NORUSEASM)//&& (!defined (_MSC_VER) || (_MSC_VER <= 1200)) @@ -217,7 +222,7 @@ void SCR_SetMode(void) // Set the video mode in the video interface. if (setmodeneeded) - VID_SetMode(--setmodeneeded); + VID_SetMode(setmodeneeded - 1); V_SetPalette(0); @@ -423,6 +428,10 @@ void SCR_ChangeRenderer(void) CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); return; } + + if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) // Clear these out before switching to software + HWR_ClearAllTextures(); + #endif // Set the new render mode diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 398508662..96e3d7d69 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -90,7 +90,6 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(ReadRect); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); - GETFUNC(ClearCacheList); GETFUNC(SetSpecialState); GETFUNC(GetTextureUsed); GETFUNC(DrawModel); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index d2c819c37..a0dd6e1da 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -137,6 +137,12 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include #endif +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) +#include +#include +#define UNIXBACKTRACE +#endif + // Locations for searching the srb2.pk3 #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) #define DEFAULTWADLOCATION1 "/usr/local/share/games/SRB2" @@ -238,6 +244,71 @@ SDL_bool framebuffer = SDL_FALSE; UINT8 keyboard_started = false; +#ifdef UNIXBACKTRACE +#define STDERR_WRITE(string) if (fd != -1) I_OutputMsg("%s", string) +#define CRASHLOG_WRITE(string) if (fd != -1) write(fd, string, strlen(string)) +#define CRASHLOG_STDERR_WRITE(string) \ + if (fd != -1)\ + write(fd, string, strlen(string));\ + I_OutputMsg("%s", string) + +static void write_backtrace(INT32 signal) +{ + int fd = -1; + size_t size; + time_t rawtime; + struct tm timeinfo; + + enum { BT_SIZE = 1024, STR_SIZE = 32 }; + void *array[BT_SIZE]; + char timestr[STR_SIZE]; + + const char *error = "An error occurred within SRB2! Send this stack trace to someone who can help!\n"; + const char *error2 = "(Or find crash-log.txt in your SRB2 directory.)\n"; // Shown only to stderr. + + fd = open(va("%s" PATHSEP "%s", srb2home, "crash-log.txt"), O_CREAT|O_APPEND|O_RDWR, S_IRUSR|S_IWUSR); + + if (fd == -1) + I_OutputMsg("\nWARNING: Couldn't open crash log for writing! Make sure your permissions are correct. Please save the below report!\n"); + + // Get the current time as a string. + time(&rawtime); + localtime_r(&rawtime, &timeinfo); + strftime(timestr, STR_SIZE, "%a, %d %b %Y %T %z", &timeinfo); + + CRASHLOG_WRITE("------------------------\n"); // Nice looking seperator + + CRASHLOG_STDERR_WRITE("\n"); // Newline to look nice for both outputs. + CRASHLOG_STDERR_WRITE(error); // "Oops, SRB2 crashed" message + STDERR_WRITE(error2); // Tell the user where the crash log is. + + // Tell the log when we crashed. + CRASHLOG_WRITE("Time of crash: "); + CRASHLOG_WRITE(timestr); + CRASHLOG_WRITE("\n"); + + // Give the crash log the cause and a nice 'Backtrace:' thing + // The signal is given to the user when the parent process sees we crashed. + CRASHLOG_WRITE("Cause: "); + CRASHLOG_WRITE(strsignal(signal)); + CRASHLOG_WRITE("\n"); // Newline for the signal name + + CRASHLOG_STDERR_WRITE("\nBacktrace:\n"); + + // Flood the output and log with the backtrace + size = backtrace(array, BT_SIZE); + backtrace_symbols_fd(array, size, fd); + backtrace_symbols_fd(array, size, STDERR_FILENO); + + CRASHLOG_WRITE("\n"); // Write another newline to the log so it looks nice :) + + close(fd); +} +#undef STDERR_WRITE +#undef CRASHLOG_WRITE +#undef CRASHLOG_STDERR_WRITE +#endif // UNIXBACKTRACE + static void I_ReportSignal(int num, int coredumped) { //static char msg[] = "oh no! back to reality!\r\n"; @@ -297,6 +368,9 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) { D_QuitNetGame(); // Fix server freezes CL_AbortDownloadResume(); +#ifdef UNIXBACKTRACE + write_backtrace(num); +#endif I_ReportSignal(num, 0); I_ShutdownSystem(); signal(num, SIG_DFL); //default signal action @@ -687,6 +761,28 @@ static void I_RegisterSignals (void) #endif } +#ifdef NEWSIGNALHANDLER +static void signal_handler_child(INT32 num) +{ +#ifdef UNIXBACKTRACE + write_backtrace(num); +#endif + + signal(num, SIG_DFL); //default signal action + raise(num); +} + +static void I_RegisterChildSignals(void) +{ + // If these defines don't exist, + // then compilation would have failed above us... + signal(SIGILL , signal_handler_child); + signal(SIGSEGV , signal_handler_child); + signal(SIGABRT , signal_handler_child); + signal(SIGFPE , signal_handler_child); +} +#endif + // //I_OutputMsg // @@ -2123,6 +2219,7 @@ static void I_Fork(void) newsignalhandler_Warn("fork()"); break; case 0: + I_RegisterChildSignals(); break; default: if (logstream) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 5ebff8700..0ed10463f 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1862,7 +1862,6 @@ void VID_StartupOpenGL(void) HWD.pfnReadRect = hwSym("ReadRect",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); - HWD.pfnClearCacheList = hwSym("ClearCacheList",NULL); HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); HWD.pfnSetPalette = hwSym("SetPalette",NULL); HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index c64164caa..412a21ea0 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -1298,6 +1298,10 @@ boolean I_PlaySong(boolean looping) if (gme) { gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; +#if defined (GME_VERSION) && GME_VERSION >= 0x000603 + if (looping) + gme_set_autoload_playback_limit(gme, 0); +#endif gme_set_equalizer(gme, &eq); gme_start_track(gme, 0); current_track = 0; diff --git a/src/st_stuff.c b/src/st_stuff.c index b25538d88..a1fbbec03 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -299,10 +299,6 @@ void ST_LoadGraphics(void) gravboots = W_CachePatchName("TVGVICON", PU_HUDGFX); tagico = W_CachePatchName("TAGICO", PU_HUDGFX); - rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX); - bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX); - rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX); - bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX); gotrflag = W_CachePatchName("GOTRFLAG", PU_HUDGFX); gotbflag = W_CachePatchName("GOTBFLAG", PU_HUDGFX); fnshico = W_CachePatchName("FNSHICO", PU_HUDGFX); @@ -2363,27 +2359,29 @@ static inline void ST_drawRaceHUD(void) static void ST_drawTeamHUD(void) { - patch_t *p; #define SEP 20 if (F_GetPromptHideHud(0)) // y base is 0 return; - if (gametyperules & GTR_TEAMFLAGS) - p = bflagico; - else - p = bmatcico; + rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX); + bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX); + rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX); + bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX); if (LUA_HudEnabled(hud_teamscores)) - V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (p->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); - - if (gametyperules & GTR_TEAMFLAGS) - p = rflagico; - else - p = rmatcico; - - if (LUA_HudEnabled(hud_teamscores)) - V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (p->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); + { + if (gametyperules & GTR_TEAMFLAGS) + { + V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (bflagico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bflagico); + V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (rflagico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rflagico); + } + else + { + V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (bmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bmatcico); + V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (rmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rmatcico); + } + } if (!(gametyperules & GTR_TEAMFLAGS)) goto num; @@ -2751,7 +2749,6 @@ static void ST_overlayDrawer(void) void ST_Drawer(void) { -#ifdef SEENAMES if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo) { INT32 c = 0; @@ -2775,7 +2772,6 @@ void ST_Drawer(void) V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF|c, player_names[seenplayer-players]); } -#endif // Doom's status bar only updated if necessary. // However, ours updates every frame regardless, so the "refresh" param was removed diff --git a/src/taglist.c b/src/taglist.c index b11216b6c..a759f4d02 100644 --- a/src/taglist.c +++ b/src/taglist.c @@ -15,6 +15,11 @@ #include "z_zone.h" #include "r_data.h" +// Bit array of whether a tag exists for sectors/lines/things. +bitarray_t tags_available[BIT_ARRAY_SIZE (MAXTAGS)]; + +size_t num_tags; + // Taggroups are used to list elements of the same tag, for iteration. // Since elements can now have multiple tags, it means an element may appear // in several taggroups at the same time. These are built on level load. @@ -105,6 +110,39 @@ size_t Taggroup_Find (const taggroup_t *group, const size_t id) return -1; } +/// group->count, but also checks for NULL +size_t Taggroup_Count (const taggroup_t *group) +{ + return group ? group->count : 0; +} + +/// Iterate thru elements in a global taggroup. +INT32 Taggroup_Iterate +( taggroup_t *garray[], + const size_t max_elements, + const mtag_t tag, + const size_t p) +{ + const taggroup_t *group; + + if (tag == MTAG_GLOBAL) + { + if (p < max_elements) + return p; + return -1; + } + + group = garray[(UINT16)tag]; + + if (group) + { + if (p < group->count) + return group->elements[p]; + return -1; + } + return -1; +} + /// Add an element to a global taggroup. void Taggroup_Add (taggroup_t *garray[], const mtag_t tag, size_t id) { @@ -120,6 +158,12 @@ void Taggroup_Add (taggroup_t *garray[], const mtag_t tag, size_t id) if (Taggroup_Find(group, id) != (size_t)-1) return; + if (! in_bit_array(tags_available, tag)) + { + num_tags++; + set_bit_array(tags_available, tag); + } + // Create group if empty. if (!group) { @@ -133,25 +177,34 @@ void Taggroup_Add (taggroup_t *garray[], const mtag_t tag, size_t id) for (i = 0; i < group->count; i++) if (group->elements[i] > id) break; - - group->elements = Z_Realloc(group->elements, (group->count + 1) * sizeof(size_t), PU_LEVEL, NULL); - - // Offset existing elements to make room for the new one. - if (i < group->count) - memmove(&group->elements[i + 1], &group->elements[i], group->count - i); } + group->elements = Z_Realloc(group->elements, (group->count + 1) * sizeof(size_t), PU_LEVEL, NULL); + + // Offset existing elements to make room for the new one. + if (i < group->count) + memmove(&group->elements[i + 1], &group->elements[i], group->count - i); + group->count++; - group->elements = Z_Realloc(group->elements, group->count * sizeof(size_t), PU_LEVEL, NULL); group->elements[i] = id; } +static size_t total_elements_with_tag (const mtag_t tag) +{ + return + ( + Taggroup_Count(tags_sectors[tag]) + + Taggroup_Count(tags_lines[tag]) + + Taggroup_Count(tags_mapthings[tag]) + ); +} + /// Remove an element from a global taggroup. void Taggroup_Remove (taggroup_t *garray[], const mtag_t tag, size_t id) { taggroup_t *group; size_t rempos; - size_t newcount; + size_t oldcount; if (tag == MTAG_GLOBAL) return; @@ -161,8 +214,14 @@ void Taggroup_Remove (taggroup_t *garray[], const mtag_t tag, size_t id) if ((rempos = Taggroup_Find(group, id)) == (size_t)-1) return; + if (group->count == 1 && total_elements_with_tag(tag) == 1) + { + num_tags--; + unset_bit_array(tags_available, tag); + } + // Strip away taggroup if no elements left. - if (!(newcount = --group->count)) + if (!(oldcount = group->count--)) { Z_Free(group->elements); Z_Free(group); @@ -170,19 +229,18 @@ void Taggroup_Remove (taggroup_t *garray[], const mtag_t tag, size_t id) } else { - size_t *newelements = Z_Malloc(newcount * sizeof(size_t), PU_LEVEL, NULL); + size_t *newelements = Z_Malloc(group->count * sizeof(size_t), PU_LEVEL, NULL); size_t i; // Copy the previous entries save for the one to remove. for (i = 0; i < rempos; i++) newelements[i] = group->elements[i]; - for (i = rempos + 1; i < group->count; i++) + for (i = rempos + 1; i < oldcount; i++) newelements[i - 1] = group->elements[i]; Z_Free(group->elements); group->elements = newelements; - group->count = newcount; } } @@ -209,6 +267,9 @@ void Taglist_InitGlobalTables(void) { size_t i, j; + memset(tags_available, 0, sizeof tags_available); + num_tags = 0; + for (i = 0; i < MAXTAGS; i++) { tags_sectors[i] = NULL; @@ -236,56 +297,17 @@ void Taglist_InitGlobalTables(void) INT32 Tag_Iterate_Sectors (const mtag_t tag, const size_t p) { - if (tag == MTAG_GLOBAL) - { - if (p < numsectors) - return p; - return -1; - } - - if (tags_sectors[(UINT16)tag]) - { - if (p < tags_sectors[(UINT16)tag]->count) - return tags_sectors[(UINT16)tag]->elements[p]; - return -1; - } - return -1; + return Taggroup_Iterate(tags_sectors, numsectors, tag, p); } INT32 Tag_Iterate_Lines (const mtag_t tag, const size_t p) { - if (tag == MTAG_GLOBAL) - { - if (p < numlines) - return p; - return -1; - } - - if (tags_lines[(UINT16)tag]) - { - if (p < tags_lines[(UINT16)tag]->count) - return tags_lines[(UINT16)tag]->elements[p]; - return -1; - } - return -1; + return Taggroup_Iterate(tags_lines, numlines, tag, p); } INT32 Tag_Iterate_Things (const mtag_t tag, const size_t p) { - if (tag == MTAG_GLOBAL) - { - if (p < nummapthings) - return p; - return -1; - } - - if (tags_mapthings[(UINT16)tag]) - { - if (p < tags_mapthings[(UINT16)tag]->count) - return tags_mapthings[(UINT16)tag]->elements[p]; - return -1; - } - return -1; + return Taggroup_Iterate(tags_mapthings, nummapthings, tag, p); } INT32 Tag_FindLineSpecial(const INT16 special, const mtag_t tag) diff --git a/src/taglist.h b/src/taglist.h index 0e6d9f842..a0529ab6b 100644 --- a/src/taglist.h +++ b/src/taglist.h @@ -43,6 +43,10 @@ typedef struct size_t count; } taggroup_t; +extern bitarray_t tags_available[]; + +extern size_t num_tags; + extern taggroup_t* tags_sectors[]; extern taggroup_t* tags_lines[]; extern taggroup_t* tags_mapthings[]; @@ -50,6 +54,13 @@ extern taggroup_t* tags_mapthings[]; void Taggroup_Add (taggroup_t *garray[], const mtag_t tag, size_t id); void Taggroup_Remove (taggroup_t *garray[], const mtag_t tag, size_t id); size_t Taggroup_Find (const taggroup_t *group, const size_t id); +size_t Taggroup_Count (const taggroup_t *group); + +INT32 Taggroup_Iterate +( taggroup_t *garray[], + const size_t max_elements, + const mtag_t tag, + const size_t p); void Taglist_InitGlobalTables(void); diff --git a/src/w_wad.c b/src/w_wad.c index 2429eaf92..6149aec6e 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -821,7 +821,10 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) } if (important && !mainfile) - G_SetGameModified(true); + { + //G_SetGameModified(true); + modifiedgame = true; // avoid savemoddata being set to false + } // // link wad file to search files @@ -1682,26 +1685,12 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) // read the lump in full W_ReadLumpHeaderPwad(wad, lump, lumpdata, 0, 0); + ptr = lumpdata; #ifndef NO_PNG_LUMPS - // lump is a png so convert it if (Picture_IsLumpPNG((UINT8 *)lumpdata, len)) - { - size_t newlen; - void *converted = Picture_PNGConvert((UINT8 *)lumpdata, PICFMT_DOOMPATCH, NULL, NULL, NULL, NULL, len, &newlen, 0); - ptr = Z_Malloc(newlen, PU_STATIC, NULL); - M_Memcpy(ptr, converted, newlen); - Z_Free(converted); - len = newlen; - } - else // just copy it into the patch cache + ptr = Picture_PNGConvert((UINT8 *)lumpdata, PICFMT_DOOMPATCH, NULL, NULL, NULL, NULL, len, &len, 0); #endif - { - ptr = Z_Malloc(len, PU_STATIC, NULL); - M_Memcpy(ptr, lumpdata, len); - } - - Z_Free(lumpdata); dest = Z_Calloc(sizeof(patch_t), tag, &lumpcache[lump]); Patch_Create(ptr, len, dest); @@ -1747,6 +1736,9 @@ void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag) void W_UnlockCachedPatch(void *patch) { + if (!patch) + return; + // The hardware code does its own memory management, as its patches // have different lifetimes from software's. #ifdef HWRENDER @@ -2144,7 +2136,7 @@ int W_VerifyNMUSlumps(const char *filename, boolean exit_on_error) {"LT", 2}, // Titlecard changes {"SLID", 4}, // Continue - {"CONT", 4}, + {"CONT", 4}, {"MINICAPS", 8}, // NiGHTS graphics here and below {"BLUESTAT", 8}, // Sphere status diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg index 486616f2d..702ae3765 100644 --- a/src/win32/Makefile.cfg +++ b/src/win32/Makefile.cfg @@ -56,14 +56,6 @@ ifndef GCC44 #OPTS+=-mms-bitfields endif -ifndef SDL - OPTS+=-D_WINDOWS -endif - -ifndef SDL - LIBS+=-lmingw32 -mwindows -ldinput -ldxguid -lgdi32 -lwinmm -endif - LIBS+=-ladvapi32 -lkernel32 -lmsvcrt -luser32 ifdef MINGW64 LIBS+=-lws2_32 @@ -76,11 +68,7 @@ endif endif # name of the exefile -ifdef SDL EXENAME?=srb2win.exe -else - EXENAME?=srb2dd.exe -endif ifdef SDL i_system_o+=$(OBJDIR)/SRB2.res @@ -88,22 +76,6 @@ ifdef SDL ifndef NOHW OPTS+=-DUSE_WGL_SWAP endif -else - D_FILES+=$(D_DIR)/fmodex.dll - CFLAGS+=-I../libs/fmodex/inc - LDFLAGS+=-L../libs/fmodex/lib -ifdef MINGW64 - LIBS+=-lfmodex64_vc -else - LIBS+=-lfmodex_vc -endif - i_cdmus_o=$(OBJDIR)/win_cd.o - i_net_o=$(OBJDIR)/win_net.o - i_system_o=$(OBJDIR)/win_sys.o $(OBJDIR)/SRB2.res - i_sound_o=$(OBJDIR)/win_snd.o - i_main_o=$(OBJDIR)/win_main.o - #i_main_o+=$(OBJDIR)/win_dbg.o - OBJS=$(OBJDIR)/dx_error.o $(OBJDIR)/fabdxlib.o $(OBJDIR)/win_vid.o $(OBJDIR)/win_dll.o endif @@ -161,4 +133,4 @@ ifdef MINGW64 else CURL_LDFLAGS+=-L../libs/curl/lib32 -lcurl endif #MINGW64 -endif \ No newline at end of file +endif diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index d942d8cd4..4743cec34 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -111,7 +111,6 @@ static loadfunc_t hwdFuncTable[] = { {"ReadRect@24", &hwdriver.pfnReadRect}, {"GClipRect@20", &hwdriver.pfnGClipRect}, {"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache}, - {"ClearCacheList@0", &hwdriver.pfnClearCacheList}, {"SetSpecialState@8", &hwdriver.pfnSetSpecialState}, {"DrawModel@16", &hwdriver.pfnDrawModel}, {"SetTransform@4", &hwdriver.pfnSetTransform}, @@ -145,7 +144,6 @@ static loadfunc_t hwdFuncTable[] = { {"ReadRect", &hwdriver.pfnReadRect}, {"GClipRect", &hwdriver.pfnGClipRect}, {"ClearMipMapCache", &hwdriver.pfnClearMipMapCache}, - {"ClearCacheList", &hwdriver.pfnClearCacheList}, {"SetSpecialState", &hwdriver.pfnSetSpecialState}, {"DrawModel", &hwdriver.pfnDrawModel}, {"SetTransform", &hwdriver.pfnSetTransform}, diff --git a/src/y_inter.c b/src/y_inter.c index f2f676919..8d831ded5 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -215,6 +215,89 @@ static void Y_IntermissionTokenDrawer(void) V_DrawCroppedPatch(32<width<interscreen[0] != '#') + interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); + break; + } + case int_spec: + { + for (i = 0; i < 2; ++i) + data.spec.bonuspatches[i] = W_CachePatchName(data.spec.bonuses[i].patch, PU_PATCH); + + data.spec.pscore = W_CachePatchName("YB_SCORE", PU_PATCH); + data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH); + + // get background tile + bgtile = W_CachePatchName("SPECTILE", PU_PATCH); + + // grab an interscreen if appropriate + if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') + interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); + break; + } + case int_ctf: + case int_teammatch: + { + if (!rflagico) //prevent a crash if we haven't cached our team graphics yet + { + rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX); + bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX); + rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX); + bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX); + } + + data.match.redflag = (intertype == int_ctf) ? rflagico : rmatcico; + data.match.blueflag = (intertype == int_ctf) ? bflagico : bmatcico; + } + /* FALLTHRU */ + case int_match: + case int_race: + case int_comp: + { + if (intertype == int_match || intertype == int_race) + { + // get RESULT header + data.match.result = W_CachePatchName("RESULT", PU_PATCH); + } + + // get background tile + bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); + break; + } + case int_none: + default: + break; + } +} + // // Y_ConsiderScreenBuffer // @@ -1181,10 +1264,9 @@ void Y_DetermineIntermissionType(void) // // Called by G_DoCompleted. Sets up data for intermission drawer/ticker. // +// void Y_StartIntermission(void) { - INT32 i; - intertic = -1; #ifdef PARANOIA @@ -1228,20 +1310,12 @@ void Y_StartIntermission(void) // setup time data data.coop.tics = players[consoleplayer].realtime; - for (i = 0; i < 4; ++i) - data.coop.bonuspatches[i] = W_CachePatchName(data.coop.bonuses[i].patch, PU_PATCH); - data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_PATCH); - // get act number data.coop.actnum = mapheaderinfo[gamemap-1]->actnum; - // get background patches - bgpatch = W_CachePatchName("INTERSCR", PU_PATCH); - // grab an interscreen if appropriate if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') { - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); useinterpic = true; usebuffer = false; } @@ -1298,21 +1372,9 @@ void Y_StartIntermission(void) // give out ring bonuses Y_AwardSpecialStageBonus(); - for (i = 0; i < 2; ++i) - data.spec.bonuspatches[i] = W_CachePatchName(data.spec.bonuses[i].patch, PU_PATCH); - - data.spec.pscore = W_CachePatchName("YB_SCORE", PU_PATCH); - data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH); - - // get background tile - bgtile = W_CachePatchName("SPECTILE", PU_PATCH); - // grab an interscreen if appropriate if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') - { - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); useinterpic = true; - } else useinterpic = false; @@ -1405,11 +1467,6 @@ void Y_StartIntermission(void) data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; - // get RESULT header - data.match.result = - W_CachePatchName("RESULT", PU_PATCH); - - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1434,10 +1491,6 @@ void Y_StartIntermission(void) data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; - // get RESULT header - data.match.result = W_CachePatchName("RESULT", PU_PATCH); - - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1463,18 +1516,6 @@ void Y_StartIntermission(void) data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; - if (intertype == int_ctf) - { - data.match.redflag = rflagico; - data.match.blueflag = bflagico; - } - else // team match - { - data.match.redflag = rmatcico; - data.match.blueflag = bmatcico; - } - - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1499,8 +1540,6 @@ void Y_StartIntermission(void) data.competition.levelstring[sizeof data.competition.levelstring - 1] = '\0'; - // get background tile - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1733,7 +1772,6 @@ static void Y_SetNullBonus(player_t *player, y_bonus_t *bstruct) { (void)player; memset(bstruct, 0, sizeof(y_bonus_t)); - strncpy(bstruct->patch, "MISSING", sizeof(bstruct->patch)); } // diff --git a/src/y_inter.h b/src/y_inter.h index 859144b1d..7268b1a47 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -14,6 +14,7 @@ extern boolean usebuffer; void Y_IntermissionDrawer(void); void Y_Ticker(void); +void Y_LoadIntermissionData(void); void Y_StartIntermission(void); void Y_EndIntermission(void); diff --git a/src/z_zone.c b/src/z_zone.c index ad64a3a07..d7da17e51 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -813,12 +813,12 @@ static void Command_Memfree_f(void) #ifdef HWRENDER if (rendermode == render_opengl) { - CONS_Printf(M_GetText("Patch info headers: %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10)); - CONS_Printf(M_GetText("Mipmap patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10)); - CONS_Printf(M_GetText("HW Texture cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRCACHE)>>10)); - CONS_Printf(M_GetText("Plane polygons : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPLANE)>>10)); - CONS_Printf(M_GetText("HW model textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRMODELTEXTURE)>>10)); - CONS_Printf(M_GetText("HW Texture used : %7d KB\n"), HWR_GetTextureUsed()>>10); + CONS_Printf(M_GetText("Patch info headers : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10)); + CONS_Printf(M_GetText("Cached textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRCACHE)>>10)); + CONS_Printf(M_GetText("Texture colormaps : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10)); + CONS_Printf(M_GetText("Model textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRMODELTEXTURE)>>10)); + CONS_Printf(M_GetText("Plane polygons : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPLANE)>>10)); + CONS_Printf(M_GetText("All GPU textures : %7d KB\n"), HWR_GetTextureUsed()>>10); } #endif diff --git a/src/z_zone.h b/src/z_zone.h index e80a45e7f..7b58be8f3 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -68,8 +68,7 @@ enum PU_HWRCACHE_UNLOCKED = 102, // 'unlocked' PU_HWRCACHE memory: // 'second-level' cache for graphics // stored in hardware format and downloaded as needed - PU_HWRPATCHINFO_UNLOCKED = 103, // 'unlocked' PU_HWRPATCHINFO memory - PU_HWRMODELTEXTURE_UNLOCKED = 104, // 'unlocked' PU_HWRMODELTEXTURE memory + PU_HWRMODELTEXTURE_UNLOCKED = 103, // 'unlocked' PU_HWRMODELTEXTURE memory }; //