diff --git a/appveyor.yml b/appveyor.yml index 348b727b1..e3348d35c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.2.10.{branch}-{build} +version: 2.2.11.{branch}-{build} os: MinGW environment: diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt index de164b23f..dfb2f4180 100644 --- a/assets/CMakeLists.txt +++ b/assets/CMakeLists.txt @@ -29,6 +29,7 @@ set(SRB2_ASSETS_GAME "srb2.pk3" "player.dta" "zones.pk3" + "patch.pk3" "music.dta" "models.dat" ) diff --git a/assets/README.txt b/assets/README.txt index 5480cb7b0..e384333ed 100644 --- a/assets/README.txt +++ b/assets/README.txt @@ -39,7 +39,7 @@ https://facebook.com/SonicRoboBlast2 COPYRIGHT AND DISCLAIMER -Design and content in Sonic Robo Blast 2 is copyright 1998-2022 by Sonic Team Jr. +Design and content in Sonic Robo Blast 2 is copyright 1998-2023 by Sonic Team Jr. All original material in this game is copyrighted by their respective owners, and no copyright infringement is intended. Sonic Team Jr. is in no way affiliated with SEGA or Sonic Team, and we do not claim ownership of any of SEGA's intellectual property used in SRB2. diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 6bae1494f..dd5cdb46b 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -41,6 +41,9 @@ linetagindicatesectors = true; // The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder formatinterface = "SRB2MapSetIO"; + +//Maximum safe map size check (0 means skip check) +safeboundary = 0; //Sky textures for vanilla maps defaultskytextures @@ -77,7 +80,7 @@ defaultskytextures defaultlumpname = "MAP01"; // Default testing parameters -testparameters = "-file \"%AP\" \"%F\" -warp %L"; +testparameters = "-folder \"%AF\" -file \"%AA\" \"%F\" -warp %L"; testshortpaths = true; // Default nodebuilder configurations @@ -437,6 +440,8 @@ sectortypes 144 = "Egg Capsule"; 160 = "Special Stage Time/Spheres Parameters "; 176 = "Custom Global Gravity "; + 512 = "Wind/Current "; + 1024 = "Conveyor Belt "; 1280 = "Speed Pad"; 1536 = "Flip Gravity on Jump"; 4096 = "Star Post Activator"; @@ -496,6 +501,8 @@ gen_sectortypes third { 0 = "Normal"; + 512 = "Wind/Current "; + 1024 = "Conveyor Belt "; 1280 = "Speed Pad"; 1536 = "Flip Gravity on Jump"; } @@ -578,7 +585,7 @@ linedeftypes title = "Per-Sector Gravity"; prefix = "(1)"; flags64text = "[6] Flip in reverse gravity"; - flags8192text = "[13] Reverse while inside"; + flags8192text = "[13] Cancel MF2_OBJECTFLIP"; } 5 @@ -641,35 +648,35 @@ linedeftypes 96 { - title = "Apply Tag to Tagged Sectors"; + title = "Add Front Sector Tag to Tagged Sectors"; prefix = "(96)"; flags1024text = "[10] Offsets are target tags"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 97 { - title = "Apply Tag to Front Sector"; + title = "Add Tag to Front Sector"; prefix = "(97)"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 98 { - title = "Apply Tag to Back Sector"; + title = "Add Tag to Back Sector"; prefix = "(98)"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 99 { - title = "Apply Tag to Front and Back Sectors"; + title = "Add Tag to Front and Back Sectors"; prefix = "(99)"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 540 @@ -990,6 +997,7 @@ linedeftypes flags128text = "[7] Only block non-players"; 3dfloor = true; 3dfloorflags = "47"; + invisiblefof = true; } 140 @@ -1227,6 +1235,7 @@ linedeftypes prefix = "(223)"; 3dfloor = true; 3dfloorflags = "41"; + invisiblefof = true; } } @@ -1524,6 +1533,7 @@ linedeftypes prefix = "(200)"; 3dfloor = true; 3dfloorflags = "20201"; + invisiblefof = true; } 201 @@ -1532,6 +1542,7 @@ linedeftypes prefix = "(201)"; 3dfloor = true; 3dfloorflags = "201"; + invisiblefof = true; } 202 @@ -1539,7 +1550,8 @@ linedeftypes title = "Fog Block"; prefix = "(202)"; 3dfloor = true; - 3dfloorflags = "3EF19"; + 3dfloorflags = "3EF01"; + invisiblefof = true; } 250 @@ -2341,6 +2353,7 @@ linedeftypes { title = "Enable/Disable Gravity Flip"; prefix = "(433)"; + flags2text = "[1] Force MFE_VERTICALFLIP"; flags8text = "[3] Set delay by backside sector"; flags32text = "[5] Invert current gravity"; flags64text = "[6] Return to normal"; @@ -2853,36 +2866,63 @@ linedeftypes { title = "Scroll Floor Texture"; prefix = "(510)"; + flags8192text = "[13] Use angle and X offset"; } 511 { title = "Scroll Floor Texture (Accelerative)"; prefix = "(511)"; + flags8192text = "[13] Use angle and X offset"; } 512 { title = "Scroll Floor Texture (Displacement)"; prefix = "(512)"; + flags8192text = "[13] Use angle and X offset"; } 513 { title = "Scroll Ceiling Texture"; prefix = "(513)"; + flags8192text = "[13] Use angle and X offset"; } 514 { title = "Scroll Ceiling Texture (Accelerative)"; prefix = "(514)"; + flags8192text = "[13] Use angle and X offset"; } 515 { title = "Scroll Ceiling Texture (Displacement)"; prefix = "(515)"; + flags8192text = "[13] Use angle and X offset"; + } + + 516 + { + title = "Scroll Floor and Ceiling Texture"; + prefix = "(516)"; + flags8192text = "[13] Use angle and X offset"; + } + + 517 + { + title = "Scroll Floor and Ceiling Texture (Accelerative)"; + prefix = "(517)"; + flags8192text = "[13] Use angle and X offset"; + } + + 518 + { + title = "Scroll Floor and Ceiling Texture (Displacement)"; + prefix = "(518)"; + flags8192text = "[13] Use angle and X offset"; } 520 @@ -2890,6 +2930,7 @@ linedeftypes title = "Carry Objects on Floor"; prefix = "(520)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 521 @@ -2897,6 +2938,7 @@ linedeftypes title = "Carry Objects on Floor (Accelerative)"; prefix = "(521)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 522 @@ -2904,6 +2946,7 @@ linedeftypes title = "Carry Objects on Floor (Displacement)"; prefix = "(522)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 523 @@ -2911,6 +2954,7 @@ linedeftypes title = "Carry Objects on Ceiling"; prefix = "(523)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 524 @@ -2918,6 +2962,7 @@ linedeftypes title = "Carry Objects on Ceiling (Accelerative)"; prefix = "(524)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 525 @@ -2925,6 +2970,31 @@ linedeftypes title = "Carry Objects on Ceiling (Displacement)"; prefix = "(525)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 526 + { + title = "Carry Objects on Floor and Ceiling"; + prefix = "(526)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 527 + { + title = "Carry Objects on Floor and Ceiling (Accelerative)"; + prefix = "(527)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 528 + { + title = "Carry Objects on Floor and Ceiling (Displacement)"; + prefix = "(528)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 530 @@ -2932,6 +3002,7 @@ linedeftypes title = "Scroll Floor Texture and Carry Objects"; prefix = "(530)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 531 @@ -2939,6 +3010,7 @@ linedeftypes title = "Scroll Floor Texture and Carry Objects (Accelerative)"; prefix = "(531)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 532 @@ -2946,6 +3018,7 @@ linedeftypes title = "Scroll Floor Texture and Carry Objects (Displacement)"; prefix = "(532)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 533 @@ -2953,6 +3026,7 @@ linedeftypes title = "Scroll Ceiling Texture and Carry Objects"; prefix = "(533)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 534 @@ -2960,6 +3034,7 @@ linedeftypes title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; prefix = "(534)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 535 @@ -2967,6 +3042,31 @@ linedeftypes title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; prefix = "(535)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 536 + { + title = "Scroll Floor and Ceiling Texture and Carry Objects"; + prefix = "(536)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 537 + { + title = "Scroll Floor and Ceiling Texture and Carry Objects (Accelerative)"; + prefix = "(537)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 538 + { + title = "Scroll Floor and Ceiling Texture and Carry Objects (Displacement)"; + prefix = "(538)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } } @@ -2978,48 +3078,54 @@ linedeftypes { title = "Wind"; prefix = "(541)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use angle and X offset"; } 542 { title = "Upwards Wind"; prefix = "(542)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use X offset"; } 543 { title = "Downwards Wind"; prefix = "(543)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use X offset"; } 544 { title = "Current"; prefix = "(544)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use angle and X offset"; } 545 { title = "Upwards Current"; prefix = "(545)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use X offset"; } 546 { title = "Downwards Current"; prefix = "(546)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use X offset"; } 547 @@ -3027,6 +3133,7 @@ linedeftypes title = "Push/Pull"; prefix = "(547)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use X offset"; } } @@ -3623,7 +3730,7 @@ thingtypes 3328 = "3D Mode Start"; } - + starts { color = 1; // Blue @@ -3813,7 +3920,7 @@ thingtypes enemies { - color = 9; // Light_Blue + color = 9; // Light Blue arrow = 1; title = "Enemies"; @@ -4123,7 +4230,7 @@ thingtypes bosses { - color = 8; // Dark_Gray + color = 4; // Dark Red arrow = 1; title = "Bosses"; @@ -4222,6 +4329,7 @@ thingtypes sprite = "internal:capsule"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 292 { @@ -4309,13 +4417,13 @@ thingtypes 308 { title = "CTF Team Ring (Red)"; - sprite = "internal:TRNGA0r"; + sprite = "internal:TRNGA0R"; width = 16; } 309 { title = "CTF Team Ring (Blue)"; - sprite = "internal:TRNGA0b"; + sprite = "internal:TRNGA0B"; width = 16; } 330 @@ -4352,7 +4460,7 @@ thingtypes collectibles { - color = 10; // Light_Green + color = 10; // Light Green title = "Other Collectibles"; width = 16; height = 32; @@ -4456,6 +4564,7 @@ thingtypes flags8text = "[8] Random (Weak)"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; 400 { @@ -4588,6 +4697,7 @@ thingtypes flags1text = "[1] Run linedef executor on pop"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; 431 { @@ -4658,7 +4768,7 @@ thingtypes generic { - color = 11; // Light_Cyan + color = 11; // Light Cyan title = "Generic Items & Hazards"; 500 @@ -4764,7 +4874,7 @@ thingtypes springs { - color = 12; // Light_Red + color = 12; // Light Red title = "Springs and Fans"; width = 20; height = 16; @@ -4926,13 +5036,13 @@ thingtypes { arrow = 0; title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; + sprite = "internal:ringverticalyellow"; } 601 { arrow = 0; title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; + sprite = "internal:ringverticalred"; height = 1024; } 602 @@ -4950,7 +5060,7 @@ thingtypes 604 { title = "Circle of Rings"; - sprite = "RINGA0"; + sprite = "internal:circlering"; width = 96; height = 192; unflippable = true; @@ -4959,7 +5069,7 @@ thingtypes 605 { title = "Circle of Rings (Big)"; - sprite = "RINGA0"; + sprite = "internal:circlebigring"; width = 192; unflippable = true; centerHitbox = true; @@ -4967,7 +5077,7 @@ thingtypes 606 { title = "Circle of Blue Spheres"; - sprite = "SPHRA0"; + sprite = "internal:circlesphere"; width = 96; height = 192; unflippable = true; @@ -4976,7 +5086,7 @@ thingtypes 607 { title = "Circle of Blue Spheres (Big)"; - sprite = "SPHRA0"; + sprite = "internal:circlebigsphere"; width = 192; unflippable = true; centerHitbox = true; @@ -4984,7 +5094,7 @@ thingtypes 608 { title = "Circle of Rings and Spheres"; - sprite = "SPHRA0"; + sprite = "internal:circleringsphere"; width = 96; height = 192; unflippable = true; @@ -4993,13 +5103,77 @@ thingtypes 609 { title = "Circle of Rings and Spheres (Big)"; - sprite = "SPHRA0"; + sprite = "internal:circlebigringsphere"; width = 192; unflippable = true; centerHitbox = true; } } + ambience + { + color = 8; // Dark Gray + title = "Ambience"; + width = 8; + height = 16; + sprite = "internal:ambiance"; + + 700 + { + title = "Water Ambience A (Large)"; + } + + 701 + { + title = "Water Ambience B (Large)"; + } + + 702 + { + title = "Water Ambience C (Medium)"; + } + + 703 + { + title = "Water Ambience D (Medium)"; + } + + 704 + { + title = "Water Ambience E (Small)"; + } + + 705 + { + title = "Water Ambience F (Small)"; + } + + 706 + { + title = "Water Ambience G (Extra Large)"; + } + + 707 + { + title = "Water Ambience H (Extra Large)"; + } + + 708 + { + title = "Disco Ambience"; + } + + 709 + { + title = "Volcano Ambience"; + } + + 710 + { + title = "Machine Ambience"; + } + } + invisible { color = 15; // White @@ -5008,72 +5182,6 @@ thingtypes height = 16; sprite = "UNKNA0"; - 700 - { - title = "Water Ambience A (Large)"; - sprite = "internal:ambiance"; - } - - 701 - { - title = "Water Ambience B (Large)"; - sprite = "internal:ambiance"; - } - - 702 - { - title = "Water Ambience C (Medium)"; - sprite = "internal:ambiance"; - } - - 703 - { - title = "Water Ambience D (Medium)"; - sprite = "internal:ambiance"; - } - - 704 - { - title = "Water Ambience E (Small)"; - sprite = "internal:ambiance"; - } - - 705 - { - title = "Water Ambience F (Small)"; - sprite = "internal:ambiance"; - } - - 706 - { - title = "Water Ambience G (Extra Large)"; - sprite = "internal:ambiance"; - } - - 707 - { - title = "Water Ambience H (Extra Large)"; - sprite = "internal:ambiance"; - } - - 708 - { - title = "Disco Ambience"; - sprite = "internal:ambiance"; - } - - 709 - { - title = "Volcano Ambience"; - sprite = "internal:ambiance"; - } - - 710 - { - title = "Machine Ambience"; - sprite = "internal:ambiance"; - } - 750 { title = "Slope Vertex"; @@ -5082,6 +5190,7 @@ thingtypes fixedrotation = 1; parametertext = "Absolute?"; flagsvaluetext = "Absolute Z"; + tagthing = true; } 751 @@ -5127,20 +5236,22 @@ thingtypes 756 { title = "Blast Linedef Executor"; - sprite = "TOADA0"; + sprite = "internal:blastexec"; width = 32; height = 16; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 757 { title = "Fan Particle Generator"; - sprite = "PRTLA0"; + sprite = "internal:fanparticles"; width = 8; height = 16; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 758 { @@ -5153,6 +5264,8 @@ thingtypes sprite = "internal:polyanchor"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; + unflippable = true; } 761 @@ -5161,6 +5274,8 @@ thingtypes sprite = "internal:polycenter"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; + unflippable = true; } 762 @@ -5169,6 +5284,8 @@ thingtypes sprite = "internal:polycentercrush"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; + unflippable = true; } 780 { @@ -5182,7 +5299,7 @@ thingtypes greenflower { - color = 10; // Green + color = 2; // Green title = "Greenflower"; 800 @@ -5287,7 +5404,7 @@ thingtypes technohill { - color = 10; // Green + color = 2; // Green title = "Techno Hill"; 900 @@ -5331,7 +5448,7 @@ thingtypes deepsea { - color = 10; // Green + color = 2; // Green title = "Deep Sea"; 1000 @@ -5466,7 +5583,7 @@ thingtypes castleeggman { - color = 10; // Green + color = 2; // Green title = "Castle Eggman"; 1100 @@ -5515,6 +5632,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1105 { @@ -5527,6 +5645,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1106 { @@ -5539,23 +5658,25 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1107 { title = "Chain Spawnpoint"; - sprite = "BMCHA0"; + sprite = "BMCHB0"; width = 17; height = 34; flags8text = "[8] Double size"; angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1108 { arrow = 1; title = "Hidden Chain Spawnpoint"; - sprite = "internal:chain3"; + sprite = "SMCHA0"; width = 17; height = 34; flags8text = "[8] Double size"; @@ -5571,6 +5692,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1110 { @@ -5582,6 +5704,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1111 { @@ -5735,7 +5858,7 @@ thingtypes aridcanyon { - color = 10; // Green + color = 2; // Green title = "Arid Canyon"; 1200 @@ -5763,6 +5886,7 @@ thingtypes height = 16; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 1203 { @@ -5954,7 +6078,7 @@ thingtypes redvolcano { - color = 10; // Green + color = 2; // Green title = "Red Volcano"; 1300 @@ -6054,7 +6178,7 @@ thingtypes botanicserenity { - color = 10; // Green + color = 2; // Green title = "Botanic Serenity"; width = 16; height = 32; @@ -6297,7 +6421,7 @@ thingtypes azuretemple { - color = 10; // Green + color = 2; // Green title = "Azure Temple"; 1500 @@ -6373,7 +6497,7 @@ thingtypes dreamhill { - color = 10; // Green + color = 2; // Green title = "Dream Hill"; 1600 @@ -6401,8 +6525,8 @@ thingtypes nightstrk { - color = 13; // Pink - title = "NiGHTS Track"; + color = 16; // Light Pink + title = "NiGHTS Track & Basics"; width = 8; height = 4096; sprite = "UNKNA0"; @@ -6437,6 +6561,19 @@ thingtypes flagsvaluetext = "Order"; parametertext = "Mare"; } + 1703 + { + title = "Ideya Drone"; + sprite = "NDRNA1"; + width = 16; + height = 56; + flags1text = "[1] Align player to middle"; + flags4text = "[4] Align player to top"; + flags8text = "[8] Die upon time up"; + angletext = "Time limit"; + fixedrotation = 1; + parametertext = "Height"; + } 1710 { title = "Ideya Capture"; @@ -6454,20 +6591,6 @@ thingtypes title = "NiGHTS Items"; width = 16; height = 32; - - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - flags1text = "[1] Align player to middle"; - flags4text = "[4] Align player to top"; - flags8text = "[8] Die upon time up"; - angletext = "Time limit"; - fixedrotation = 1; - parametertext = "Height"; - } 1704 { arrow = 1; @@ -6478,20 +6601,19 @@ thingtypes unflippable = true; flagsvaluetext = "Pitch"; angletext = "Yaw"; - fixedrotation = 1; } 1705 { arrow = 1; title = "Hoop (Generic)"; - sprite = "HOOPA0"; + sprite = "internal:nightshoop"; width = 80; height = 160; unflippable = true; centerHitbox = true; flagsvaluetext = "Height"; angletext = "Pitch/Yaw"; - fixedrotation = 1; + parametertext = "Degrees?"; } 1706 { @@ -6501,7 +6623,6 @@ thingtypes height = 24; flags8height = 24; flags8text = "[8] Float"; - unflippable = true; } 1707 { @@ -6546,11 +6667,13 @@ thingtypes flags2text = "[2] Radius +32"; flags4text = "[4] Radius +64"; flags8text = "[8] Radius +128"; - sprite = "HOOPA0"; + sprite = "internal:nightshoop"; width = 80; height = 160; unflippable = true; centerHitbox = true; + angletext = "Pitch/Yaw"; + parametertext = "Degrees?"; } 1714 { @@ -6654,7 +6777,7 @@ thingtypes christmasdisco { - color = 10; // Green + color = 2; // Green title = "Christmas & Disco"; 1850 @@ -6757,7 +6880,7 @@ thingtypes stalagmites { - color = 10; // Green + color = 2; // Green title = "Stalagmites"; width = 16; height = 40; @@ -6836,7 +6959,7 @@ thingtypes hauntedheights { - color = 10; // Green + color = 2; // Green title = "Haunted Heights"; 2000 @@ -6925,7 +7048,7 @@ thingtypes frozenhillside { - color = 10; // Green + color = 2; // Green title = "Frozen Hillside"; 2100 @@ -6976,7 +7099,7 @@ thingtypes tutorial { - color = 10; // Green + color = 2; // Green title = "Tutorial"; 799 @@ -6987,10 +7110,11 @@ thingtypes height = 144; parametertext = "Start frame"; } + } flickies { - color = 10; // Green + color = 3; // Teal title = "Flickies"; width = 8; height = 20; diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg index 0ff044a6d..8f37aabaa 100644 --- a/extras/conf/udb/Includes/SRB222_common.cfg +++ b/extras/conf/udb/Includes/SRB222_common.cfg @@ -15,7 +15,7 @@ common ignoredextensions = "wad pk3 pk7 bak backup1 backup2 backup3 zip rar 7z"; // Default testing parameters - testparameters = "-file \"%AP\" \"%F\" -warp %L"; + testparameters = "-folder \"%AF\" -file \"%AA\" \"%F\" -warp %L"; testshortpaths = true; // Action special help @@ -26,7 +26,7 @@ common generalizedsectors = true; // Maximum safe map size check (0 means skip check) - safeboundary = 1; + safeboundary = 0; // Map boundaries. Map objects can only be placed within these boundaries leftboundary = -32768; @@ -40,6 +40,8 @@ common defaultflatscale = 1.0f; scaledtextureoffsets = true; + maxcolormapalpha = 25; + // Thing number for start position in 3D Mode start3dmode = 3328; @@ -68,137 +70,6 @@ common } } -mapformat_doom -{ - // The format interface handles the map data format - formatinterface = "DoomMapSetIO"; - - // Default nodebuilder configurations - defaultsavecompiler = "zennode_normal"; - defaulttestcompiler = "zennode_fast"; - - /* - GAME DETECT PATTERN - Used to guess the game for which a WAD file is made. - - 1 = One of these lumps must exist - 2 = None of these lumps must exist - 3 = All of these lumps must exist - */ - - gamedetect - { - EXTENDED = 2; - - - BEHAVIOR = 2; - - E#M# = 2; - - MAP?? = 1; - } - - /* - MAP LUMP NAMES - Map lumps are loaded with the map as long as they are right after each other. When the editor - meets a lump which is not defined in this list it will ignore the map if not satisfied. - The order of items defines the order in which lumps will be written to WAD file on save. - To indicate the map header lump, use ~MAP - - Legenda: - required = Lump is required to exist. - blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use) - nodebuild = The nodebuilder generates this lump. - allowempty = The nodebuilder is allowed to leave this lump empty. - script = This lump is a text-based script. Specify the filename of the script configuration to use. - */ - - maplumpnames - { - include("SRB222_misc.cfg", "doommaplumpnames"); - } - - // When this is set to true, sectors with the same tag will light up when a line is highlighted - linetagindicatesectors = true; - - // Special linedefs - include("SRB222_misc.cfg", "speciallinedefs"); - - // Default flags for first new thing - defaultthingflags - { - } - - // DEFAULT SECTOR BRIGHTNESS LEVELS - sectorbrightness - { - include("SRB222_misc.cfg", "sectorbrightness"); - } - - // SECTOR TYPES - sectortypes - { - include("SRB222_sectors.cfg", "sectortypes"); - } - - // GENERALISED SECTOR TYPES - gen_sectortypes - { - include("SRB222_sectors.cfg", "gen_sectortypes"); - } - - // LINEDEF FLAGS - linedefflags - { - include("SRB222_misc.cfg", "linedefflags"); - } - - // Linedef flags UDMF translation table - // This is needed for copy/paste and prefabs to work properly - // When the UDMF field name is prefixed with ! it is inverted - linedefflagstranslation - { - include("SRB222_misc.cfg", "linedefflagstranslation"); - } - - // LINEDEF ACTIVATIONS - linedefactivations - { - } - - // LINEDEF TYPES - linedeftypes - { - include("SRB222_linedefs.cfg", "doom"); - } - - // THING FLAGS - thingflags - { - include("SRB222_misc.cfg", "thingflags"); - } - - // Thing flags UDMF translation table - // This is needed for copy/paste and prefabs to work properly - // When the UDMF field name is prefixed with ! it is inverted - thingflagstranslation - { - include("SRB222_misc.cfg", "thingflagstranslation"); - } - - // THING FLAGS ERROR MASK - // Mask for the thing flags which indicates the options - // that make the same thing appear in the same modes - thingflagsmask1 = 7; // 1 + 2 + 4 - thingflagsmask2 = 0; - - // THING TYPES - thingtypes - { - include("SRB222_things.cfg", "doom"); - } -} - mapformat_udmf { // The format interface handles the map data format @@ -222,9 +93,17 @@ mapformat_udmf { include("SRB222_misc.cfg", "universalfields"); } + + // Disable Doom-related modes that don't make sense for SRB2 + soundsupport = false; + automapsupport = false; // When this is set to true, sectors with the same tag will light up when a line is highlighted linetagindicatesectors = false; + localsidedeftextureoffsets = true; + distinctfloorandceilingbrightness = true; + + planeequationsupport = true; // Special linedefs include("SRB222_misc.cfg", "speciallinedefs_udmf"); @@ -240,6 +119,11 @@ mapformat_udmf include("SRB222_misc.cfg", "sectorflags"); } + sectorflagscategories + { + include("SRB222_misc.cfg", "sectorflagscategories"); + } + // DEFAULT SECTOR BRIGHTNESS LEVELS sectorbrightness { @@ -247,6 +131,7 @@ mapformat_udmf } damagetypes = "Generic Water Fire Lava Electric Spike DeathPitTilt DeathPitNoTilt Instakill SpecialStage"; + triggerertypes = "Player AllPlayers Mobj"; // LINEDEF FLAGS linedefflags @@ -282,7 +167,6 @@ mapformat_udmf // How to compare thing flags (for the stuck things error checker) thingflagscompare { - include("UDMF_misc.cfg", "thingflagscompare"); } // THING TYPES diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 99c305659..621b4abd5 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1,1748 +1,3 @@ -doom -{ - misc - { - title = "Miscellaneous"; - - 0 - { - title = "None"; - prefix = "(0)"; - } - 1 - { - title = "Per-Sector Gravity"; - prefix = "(1)"; - } - 5 - { - title = "Camera Scanner "; - prefix = "(5)"; - } - 7 - { - title = "Sector Flat Alignment"; - prefix = "(7)"; - } - 10 - { - title = "Culling Plane"; - prefix = "(10)"; - } - 13 - { - title = "Heat Wave Effect"; - prefix = "(13)"; - } - 40 - { - title = "Visual Portal Between Tagged Linedefs"; - prefix = "(40)"; - } - 41 - { - title = "Horizon Effect"; - prefix = "(41)"; - } - 50 - { - title = "Instantly Lower Floor on Level Load"; - prefix = "(50)"; - } - 51 - { - title = "Instantly Raise Ceiling on Level Load"; - prefix = "(51)"; - } - 63 - { - title = "Fake Floor/Ceiling Planes"; - prefix = "(63)"; - } - 540 - { - title = "Floor Friction"; - prefix = "(540)"; - } - } - - parameters - { - title = "Parameters"; - - 2 - { - title = "Custom Exit"; - prefix = "(2)"; - } - 3 - { - title = "Zoom Tube Parameters"; - prefix = "(3)"; - } - 4 - { - title = "Speed Pad Parameters"; - prefix = "(4)"; - } - 8 - { - title = "Special Sector Properties"; - prefix = "(8)"; - } - 9 - { - title = "Chain Parameters"; - prefix = "(9)"; - } - 11 - { - title = "Rope Hang Parameters"; - prefix = "(11)"; - } - 12 - { - title = "Rock Spawner Parameters"; - prefix = "(12)"; - } - 14 - { - title = "Bustable Block Parameters"; - prefix = "(14)"; - } - 15 - { - title = "Fan Particle Spawner Parameters"; - prefix = "(15)"; - } - 16 - { - title = "Minecart Parameters"; - prefix = "(16)"; - } - 64 - { - title = "Continuously Appearing/Disappearing FOF"; - prefix = "(64)"; - } - 76 - { - title = "Make FOF Bouncy"; - prefix = "(76)"; - } - } - - polyobject - { - title = "PolyObject"; - - 20 - { - title = "First Line"; - prefix = "(20)"; - } - 21 - { - title = "Explicitly Include Line "; - prefix = "(21)"; - } - 22 - { - title = "Parameters"; - prefix = "(22)"; - } - 30 - { - title = "Waving Flag"; - prefix = "(30)"; - } - 31 - { - title = "Displacement by Front Sector"; - prefix = "(31)"; - } - 32 - { - title = "Angular Displacement by Front Sector"; - prefix = "(32)"; - } - } - - planemove - { - title = "Plane Movement"; - - 52 - { - title = "Continuously Falling Sector"; - prefix = "(52)"; - } - 53 - { - title = "Continuous Floor/Ceiling Mover"; - prefix = "(53)"; - } - 54 - { - title = "Continuous Floor Mover"; - prefix = "(54)"; - } - 55 - { - title = "Continuous Ceiling Mover"; - prefix = "(55)"; - } - 56 - { - title = "Continuous Two-Speed Floor/Ceiling Mover"; - prefix = "(56)"; - } - 57 - { - title = "Continuous Two-Speed Floor Mover"; - prefix = "(57)"; - } - 58 - { - title = "Continuous Two-Speed Ceiling Mover"; - prefix = "(58)"; - } - 59 - { - title = "Activate Moving Platform"; - prefix = "(59)"; - } - 60 - { - title = "Activate Moving Platform (Adjustable Speed)"; - prefix = "(60)"; - } - 61 - { - title = "Crusher (Ceiling to Floor)"; - prefix = "(61)"; - } - 62 - { - title = "Crusher (Floor to Ceiling)"; - prefix = "(62)"; - } - 66 - { - title = "Move Floor by Displacement"; - prefix = "(66)"; - } - 67 - { - title = "Move Ceiling by Displacement"; - prefix = "(67)"; - } - 68 - { - title = "Move Floor and Ceiling by Displacement"; - prefix = "(68)"; - } - } - - fofsolid - { - title = "FOF (solid)"; - - 100 - { - title = "Solid, Opaque"; - prefix = "(100)"; - } - 101 - { - title = "Solid, Opaque, No Shadow"; - prefix = "(101)"; - } - 102 - { - title = "Solid, Translucent"; - prefix = "(102)"; - } - 103 - { - title = "Solid, Sides Only"; - prefix = "(103)"; - } - 104 - { - title = "Solid, No Sides"; - prefix = "(104)"; - } - 105 - { - title = "Solid, Invisible"; - prefix = "(105)"; - } - 140 - { - title = "Intangible from Bottom, Opaque"; - prefix = "(140)"; - } - 141 - { - title = "Intangible from Bottom, Translucent"; - prefix = "(141)"; - } - 142 - { - title = "Intangible from Bottom, Translucent, No Sides"; - prefix = "(142)"; - } - 143 - { - title = "Intangible from Top, Opaque"; - prefix = "(143)"; - } - 144 - { - title = "Intangible from Top, Translucent"; - prefix = "(144)"; - } - 145 - { - title = "Intangible from Top, Translucent, No Sides"; - prefix = "(145)"; - } - 146 - { - title = "Only Tangible from Sides"; - prefix = "(146)"; - } - } - - fofintangible - { - title = "FOF (intangible)"; - - 120 - { - title = "Water, Opaque"; - prefix = "(120)"; - } - 121 - { - title = "Water, Translucent"; - prefix = "(121)"; - } - 122 - { - title = "Water, Opaque, No Sides"; - prefix = "(122)"; - } - 123 - { - title = "Water, Translucent, No Sides"; - prefix = "(123)"; - } - 124 - { - title = "Goo Water, Translucent"; - prefix = "(124)"; - } - 125 - { - title = "Goo Water, Translucent, No Sides"; - prefix = "(125)"; - } - 220 - { - title = "Intangible, Opaque"; - prefix = "(220)"; - } - 221 - { - title = "Intangible, Translucent"; - prefix = "(221)"; - } - 222 - { - title = "Intangible, Sides Only"; - prefix = "(222)"; - } - 223 - { - title = "Intangible, Invisible"; - prefix = "(223)"; - } - } - - fofmoving - { - title = "FOF (moving)"; - - 150 - { - title = "Air Bobbing"; - prefix = "(150)"; - } - 151 - { - title = "Air Bobbing (Adjustable)"; - prefix = "(151)"; - } - 152 - { - title = "Reverse Air Bobbing (Adjustable)"; - prefix = "(152)"; - } - 153 - { - title = "Dynamically Sinking Platform"; - prefix = "(153)"; - } - 160 - { - title = "Water Bobbing"; - prefix = "(160)"; - } - 190 - { - title = "Rising Platform, Solid, Opaque"; - prefix = "(190)"; - } - 191 - { - title = "Rising Platform, Solid, Opaque, No Shadow"; - prefix = "(191)"; - } - 192 - { - title = "Rising Platform, Solid, Translucent"; - prefix = "(192)"; - } - 193 - { - title = "Rising Platform, Solid, Invisible"; - prefix = "(193)"; - } - 194 - { - title = "Rising Platform, Intangible from Bottom, Opaque"; - prefix = "(194)"; - } - 195 - { - title = "Rising Platform, Intangible from Bottom, Translucent"; - prefix = "(195)"; - } - } - - fofcrumbling - { - title = "FOF (crumbling)"; - - 170 - { - title = "Crumbling, Respawn"; - prefix = "(170)"; - } - 171 - { - title = "Crumbling, No Respawn"; - prefix = "(171)"; - } - 172 - { - title = "Crumbling, Respawn, Intangible from Bottom"; - prefix = "(172)"; - } - 173 - { - title = "Crumbling, No Respawn, Intangible from Bottom"; - prefix = "(173)"; - } - 174 - { - title = "Crumbling, Respawn, Int. from Bottom, Translucent"; - prefix = "(174)"; - } - 175 - { - title = "Crumbling, No Respawn, Int. from Bottom, Translucent"; - prefix = "(175)"; - } - 176 - { - title = "Crumbling, Respawn, Floating, Bobbing"; - prefix = "(176)"; - } - 177 - { - title = "Crumbling, No Respawn, Floating, Bobbing"; - prefix = "(177)"; - } - 178 - { - title = "Crumbling, Respawn, Floating"; - prefix = "(178)"; - } - 179 - { - title = "Crumbling, No Respawn, Floating"; - prefix = "(179)"; - } - 180 - { - title = "Crumbling, Respawn, Air Bobbing"; - prefix = "(180)"; - } - } - - fofspecial - { - title = "FOF (special)"; - - 200 - { - title = "Light Block"; - prefix = "(200)"; - } - 201 - { - title = "Half Light Block"; - prefix = "(201)"; - } - 202 - { - title = "Fog Block"; - prefix = "(202)"; - } - 250 - { - title = "Mario Block"; - prefix = "(250)"; - } - 251 - { - title = "Thwomp Block"; - prefix = "(251)"; - } - 252 - { - title = "Shatter Block"; - prefix = "(252)"; - } - 253 - { - title = "Shatter Block, Translucent"; - prefix = "(253)"; - } - 254 - { - title = "Bustable Block"; - prefix = "(254)"; - } - 255 - { - title = "Spin-Bustable Block"; - prefix = "(255)"; - } - 256 - { - title = "Spin-Bustable Block, Translucent"; - prefix = "(256)"; - } - 257 - { - title = "Quicksand"; - prefix = "(257)"; - } - 258 - { - title = "Laser"; - prefix = "(258)"; - } - 259 - { - title = "Custom FOF"; - prefix = "(259)"; - } - } - - linedeftrigger - { - title = "Linedef Executor Trigger"; - - 300 - { - title = "Continuous"; - prefix = "(300)"; - } - 301 - { - title = "Each Time"; - prefix = "(301)"; - } - 302 - { - title = "Once"; - prefix = "(302)"; - } - 303 - { - title = "Ring Count - Continuous"; - prefix = "(303)"; - } - 304 - { - title = "Ring Count - Once"; - prefix = "(304)"; - } - 305 - { - title = "Character Ability - Continuous"; - prefix = "(305)"; - } - 306 - { - title = "Character Ability - Each Time"; - prefix = "(306)"; - } - 307 - { - title = "Character Ability - Once"; - prefix = "(307)"; - } - 308 - { - title = "Race Only - Once"; - prefix = "(308)"; - } - 309 - { - title = "CTF Red Team - Continuous"; - prefix = "(309)"; - } - 310 - { - title = "CTF Red Team - Each Time"; - prefix = "(310)"; - } - 311 - { - title = "CTF Blue Team - Continuous"; - prefix = "(311)"; - } - 312 - { - title = "CTF Blue Team - Each Time"; - prefix = "(312)"; - } - 313 - { - title = "No More Enemies - Once"; - prefix = "(313)"; - } - 314 - { - title = "Number of Pushables - Continuous"; - prefix = "(314)"; - } - 315 - { - title = "Number of Pushables - Once"; - prefix = "(315)"; - } - 317 - { - title = "Condition Set Trigger - Continuous"; - prefix = "(317)"; - } - 318 - { - title = "Condition Set Trigger - Once"; - prefix = "(318)"; - } - 319 - { - title = "Unlockable - Continuous"; - prefix = "(319)"; - } - 320 - { - title = "Unlockable - Once"; - prefix = "(320)"; - } - 321 - { - title = "Trigger After X Calls - Continuous"; - prefix = "(321)"; - } - 322 - { - title = "Trigger After X Calls - Each Time"; - prefix = "(322)"; - } - 323 - { - title = "NiGHTSerize - Each Time"; - prefix = "(323)"; - } - 324 - { - title = "NiGHTSerize - Once"; - prefix = "(324)"; - } - 325 - { - title = "De-NiGHTSerize - Each Time"; - prefix = "(325)"; - } - 326 - { - title = "De-NiGHTSerize - Once"; - prefix = "(326)"; - } - 327 - { - title = "NiGHTS Lap - Each Time"; - prefix = "(327)"; - } - 328 - { - title = "NiGHTS Lap - Once"; - prefix = "(328)"; - } - 329 - { - title = "Ideya Capture Touch - Each Time"; - prefix = "(329)"; - } - 330 - { - title = "Ideya Capture Touch - Once"; - prefix = "(330)"; - } - 331 - { - title = "Player Skin - Continuous"; - flags64text = "[6] Disable for this skin"; - prefix = "(331)"; - } - 332 - { - title = "Player Skin - Each Time"; - prefix = "(332)"; - } - 333 - { - title = "Player Skin - Once"; - prefix = "(333)"; - } - 334 - { - title = "Object Dye - Continuous"; - prefix = "(334)"; - } - 335 - { - title = "Object Dye - Each Time"; - prefix = "(335)"; - } - 336 - { - title = "Object Dye - Once"; - prefix = "(336)"; - } - 337 - { - title = "Emerald Check - Continuous"; - prefix = "(337)"; - } - 338 - { - title = "Emerald Check - Each Time"; - prefix = "(338)"; - } - 339 - { - title = "Emerald Check - Once"; - prefix = "(339)"; - } - 340 - { - title = "NiGHTS Mare - Continuous"; - prefix = "(340)"; - } - 341 - { - title = "NiGHTS Mare - Each Time"; - prefix = "(341)"; - } - 342 - { - title = "NiGHTS Mare - Once"; - prefix = "(342)"; - } - 343 - { - title = "Gravity Check - Continuous"; - prefix = "(343)"; - } - 344 - { - title = "Gravity Check - Each Time"; - prefix = "(344)"; - } - 345 - { - title = "Gravity Check - Once"; - prefix = "(345)"; - } - 399 - { - title = "Level Load"; - prefix = "(399)"; - } - } - - linedefexecsector - { - title = "Linedef Executor (sector)"; - - 400 - { - title = "Set Tagged Sector's Floor Height/Texture"; - prefix = "(400)"; - } - 401 - { - title = "Set Tagged Sector's Ceiling Height/Texture"; - prefix = "(401)"; - } - 402 - { - title = "Copy Light Level to Tagged Sectors"; - prefix = "(402)"; - } - 408 - { - title = "Set Tagged Sector's Flats"; - prefix = "(408)"; - } - 409 - { - title = "Change Tagged Sector's Tag"; - prefix = "(409)"; - } - 410 - { - title = "Change Front Sector's Tag"; - prefix = "(410)"; - } - 416 - { - title = "Start Adjustable Flickering Light"; - prefix = "(416)"; - } - 417 - { - title = "Start Adjustable Pulsating Light"; - prefix = "(417)"; - } - 418 - { - title = "Start Adjustable Blinking Light (unsynchronized)"; - prefix = "(418)"; - } - 419 - { - title = "Start Adjustable Blinking Light (synchronized)"; - prefix = "(419)"; - } - 420 - { - title = "Fade Light Level"; - prefix = "(420)"; - } - 421 - { - title = "Stop Lighting Effect"; - prefix = "(421)"; - } - 435 - { - title = "Change Plane Scroller Direction"; - prefix = "(435)"; - } - 467 - { - title = "Set Tagged Sector's Light Level"; - prefix = "(467)"; - } - } - - linedefexecplane - { - title = "Linedef Executor (plane movement)"; - - 403 - { - title = "Move Tagged Sector's Floor"; - prefix = "(403)"; - } - 404 - { - title = "Move Tagged Sector's Ceiling"; - prefix = "(404)"; - } - 405 - { - title = "Move Floor According to Front Texture Offsets"; - prefix = "(405)"; - } - 407 - { - title = "Move Ceiling According to Front Texture Offsets"; - prefix = "(407)"; - } - 411 - { - title = "Stop Plane Movement"; - prefix = "(411)"; - } - 428 - { - title = "Start Platform Movement"; - prefix = "(428)"; - } - 429 - { - title = "Crush Ceiling Once"; - prefix = "(429)"; - } - 430 - { - title = "Crush Floor Once"; - prefix = "(430)"; - } - 431 - { - title = "Crush Floor and Ceiling Once"; - prefix = "(431)"; - } - } - - linedefexecplayer - { - title = "Linedef Executor (player/object)"; - - 412 - { - title = "Teleporter"; - prefix = "(412)"; - } - 425 - { - title = "Change Object State"; - prefix = "(425)"; - } - 426 - { - title = "Stop Object"; - prefix = "(426)"; - } - 427 - { - title = "Award Score"; - prefix = "(427)"; - } - 432 - { - title = "Enable/Disable 2D Mode"; - prefix = "(432)"; - } - 433 - { - title = "Enable/Disable Gravity Flip"; - prefix = "(433)"; - } - 434 - { - title = "Award Power-Up"; - prefix = "(434)"; - } - 437 - { - title = "Disable Player Control"; - prefix = "(437)"; - } - 438 - { - title = "Change Object Size"; - prefix = "(438)"; - } - 442 - { - title = "Change Object Type State"; - prefix = "(442)"; - } - 457 - { - title = "Track Object's Angle"; - prefix = "(457)"; - } - 458 - { - title = "Stop Tracking Object's Angle"; - prefix = "(458)"; - } - 460 - { - title = "Award Rings"; - prefix = "(460)"; - } - 461 - { - title = "Spawn Object"; - prefix = "(461)"; - } - 462 - { - title = "Stop Timer/Exit Stage in Record Attack"; - prefix = "(462)"; - } - 463 - { - title = "Dye Object"; - prefix = "(463)"; - } - 464 - { - title = "Trigger Egg Capsule"; - prefix = "(464)"; - } - 466 - { - title = "Set Level Failure State"; - prefix = "(466)"; - } - } - - linedefexecmisc - { - title = "Linedef Executor (misc.)"; - - 413 - { - title = "Change Music"; - prefix = "(413)"; - } - 414 - { - title = "Play Sound Effect"; - prefix = "(414)"; - } - 415 - { - title = "Run Script"; - prefix = "(415)"; - } - 422 - { - title = "Switch to Cut-Away View"; - prefix = "(422)"; - } - 423 - { - title = "Change Sky"; - prefix = "(423)"; - } - 424 - { - title = "Change Weather"; - prefix = "(424)"; - } - 436 - { - title = "Shatter FOF"; - prefix = "(436)"; - } - 439 - { - title = "Change Tagged Linedef's Textures"; - prefix = "(439)"; - } - 440 - { - title = "Start Metal Sonic Race"; - prefix = "(440)"; - } - 441 - { - title = "Condition Set Trigger"; - prefix = "(441)"; - } - 443 - { - title = "Call Lua Function"; - prefix = "(443)"; - } - 444 - { - title = "Earthquake"; - prefix = "(444)"; - } - 445 - { - title = "Make FOF Disappear/Reappear"; - prefix = "(445)"; - } - 446 - { - title = "Make FOF Crumble"; - prefix = "(446)"; - } - 447 - { - title = "Change Tagged Sector's Colormap"; - prefix = "(447)"; - } - 448 - { - title = "Change Skybox"; - prefix = "(448)"; - } - 449 - { - title = "Enable Bosses with Parameter"; - prefix = "(449)"; - } - 450 - { - title = "Execute Linedef Executor (specific tag)"; - prefix = "(450)"; - } - 451 - { - title = "Execute Linedef Executor (random tag in range)"; - prefix = "(451)"; - } - 452 - { - title = "Set FOF Translucency"; - prefix = "(452)"; - } - 453 - { - title = "Fade FOF"; - prefix = "(453)"; - } - 454 - { - title = "Stop Fading FOF"; - prefix = "(454)"; - } - 455 - { - title = "Fade Tagged Sector's Colormap"; - prefix = "(455)"; - } - 456 - { - title = "Stop Fading Tagged Sector's Colormap"; - prefix = "(456)"; - } - 459 - { - title = "Control Text Prompt"; - prefix = "(459)"; - } - } - - linedefexecpoly - { - title = "Linedef Executor (polyobject)"; - - 480 - { - title = "Door Slide"; - prefix = "(480)"; - } - 481 - { - title = "Door Swing"; - prefix = "(481)"; - } - 482 - { - title = "Move"; - prefix = "(482)"; - } - 483 - { - title = "Move, Override"; - prefix = "(483)"; - } - 484 - { - title = "Rotate Right"; - prefix = "(484)"; - } - 485 - { - title = "Rotate Right, Override"; - prefix = "(485)"; - } - 486 - { - title = "Rotate Left"; - prefix = "(486)"; - } - 487 - { - title = "Rotate Left, Override"; - prefix = "(487)"; - } - 488 - { - title = "Move by Waypoints"; - prefix = "(488)"; - } - 489 - { - title = "Turn Invisible, Intangible"; - prefix = "(489)"; - } - 490 - { - title = "Turn Visible, Tangible"; - prefix = "(490)"; - } - 491 - { - title = "Set Translucency"; - prefix = "(491)"; - } - 492 - { - title = "Fade Translucency"; - prefix = "(492)"; - } - } - - wallscroll - { - title = "Wall Scrolling"; - - 500 - { - title = "Scroll Wall Front Side Left"; - prefix = "(500)"; - } - 501 - { - title = "Scroll Wall Front Side Right"; - prefix = "(501)"; - } - 502 - { - title = "Scroll Wall According to Linedef"; - prefix = "(502)"; - } - 503 - { - title = "Scroll Wall According to Linedef (Accelerative)"; - prefix = "(503)"; - } - 504 - { - title = "Scroll Wall According to Linedef (Displacement)"; - prefix = "(504)"; - } - 505 - { - title = "Scroll Texture by Front Side Offsets"; - prefix = "(505)"; - } - 506 - { - title = "Scroll Texture by Back Side Offsets"; - prefix = "(506)"; - } - } - - planescroll - { - title = "Plane Scrolling"; - - 510 - { - title = "Scroll Floor Texture"; - prefix = "(510)"; - } - 511 - { - title = "Scroll Floor Texture (Accelerative)"; - prefix = "(511)"; - } - 512 - { - title = "Scroll Floor Texture (Displacement)"; - prefix = "(512)"; - } - 513 - { - title = "Scroll Ceiling Texture"; - prefix = "(513)"; - } - 514 - { - title = "Scroll Ceiling Texture (Accelerative)"; - prefix = "(514)"; - } - 515 - { - title = "Scroll Ceiling Texture (Displacement)"; - prefix = "(515)"; - } - 520 - { - title = "Carry Objects on Floor"; - prefix = "(520)"; - } - 521 - { - title = "Carry Objects on Floor (Accelerative)"; - prefix = "(521)"; - } - 522 - { - title = "Carry Objects on Floor (Displacement)"; - prefix = "(522)"; - } - 523 - { - title = "Carry Objects on Ceiling"; - prefix = "(523)"; - } - 524 - { - title = "Carry Objects on Ceiling (Accelerative)"; - prefix = "(524)"; - } - 525 - { - title = "Carry Objects on Ceiling (Displacement)"; - prefix = "(525)"; - } - 530 - { - title = "Scroll Floor Texture and Carry Objects"; - prefix = "(530)"; - } - 531 - { - title = "Scroll Floor Texture and Carry Objects (Accelerative)"; - prefix = "(531)"; - } - 532 - { - title = "Scroll Floor Texture and Carry Objects (Displacement)"; - prefix = "(532)"; - } - 533 - { - title = "Scroll Ceiling Texture and Carry Objects"; - prefix = "(533)"; - } - 534 - { - title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; - prefix = "(534)"; - } - 535 - { - title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; - prefix = "(535)"; - } - } - - pusher - { - title = "Pusher"; - - 541 - { - title = "Wind"; - prefix = "(541)"; - } - 542 - { - title = "Upwards Wind"; - prefix = "(542)"; - } - 543 - { - title = "Downwards Wind"; - prefix = "(543)"; - } - 544 - { - title = "Current"; - prefix = "(544)"; - } - 545 - { - title = "Upwards Current"; - prefix = "(545)"; - } - 546 - { - title = "Downwards Current"; - prefix = "(546)"; - } - 547 - { - title = "Push/Pull"; - prefix = "(547)"; - } - } - - light - { - title = "Lighting"; - - 600 - { - title = "Floor Lighting"; - prefix = "(600)"; - } - 601 - { - title = "Ceiling Lighting"; - prefix = "(601)"; - } - 602 - { - title = "Adjustable Pulsating Light"; - prefix = "(602)"; - } - 603 - { - title = "Adjustable Flickering Light"; - prefix = "(603)"; - } - 604 - { - title = "Adjustable Blinking Light (unsynchronized)"; - prefix = "(604)"; - } - 605 - { - title = "Adjustable Blinking Light (synchronized)"; - prefix = "(605)"; - } - 606 - { - title = "Colormap"; - prefix = "(606)"; - } - } - - slope - { - title = "Slope"; - - 700 - { - title = "Slope Frontside Floor"; - prefix = "(700)"; - } - 701 - { - title = "Slope Frontside Ceiling"; - prefix = "(701)"; - } - 702 - { - title = "Slope Frontside Floor and Ceiling"; - prefix = "(702)"; - } - 703 - { - title = "Slope Frontside Floor and Backside Ceiling"; - prefix = "(703)"; -ยด } - 704 - { - title = "Slope Frontside Floor by 3 Tagged Vertex Things"; - prefix = "(704)"; - } - 705 - { - title = "Slope Frontside Ceiling by 3 Tagged Vertex Things"; - prefix = "(705)"; - } - 710 - { - title = "Slope Backside Floor"; - prefix = "(710)"; - } - 711 - { - title = "Slope Backside Ceiling"; - prefix = "(711)"; - } - 712 - { - title = "Slope Backside Floor and Ceiling"; - prefix = "(712)"; - } - 713 - { - title = "Slope Backside Floor and Frontside Ceiling"; - prefix = "(713)"; - } - 714 - { - title = "Slope Backside Floor by 3 Tagged Vertex Things"; - prefix = "(714)"; - } - 715 - { - title = "Slope Backside Ceiling by 3 Tagged Vertex Things"; - prefix = "(715)"; - } - 720 - { - title = "Copy Frontside Floor Slope from Line Tag"; - prefix = "(720)"; - } - 721 - { - title = "Copy Frontside Ceiling Slope from Line Tag"; - prefix = "(721)"; - } - 722 - { - title = "Copy Frontside Floor and Ceiling Slope from Line Tag"; - prefix = "(722)"; - } - 799 - { - title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; - prefix = "(799)"; - } - } - - transwall - { - title = "Translucent Wall"; - - 900 - { - title = "90% Opaque"; - prefix = "(900)"; - } - 901 - { - title = "80% Opaque"; - prefix = "(901)"; - } - 902 - { - title = "70% Opaque"; - prefix = "(902)"; - } - 903 - { - title = "60% Opaque"; - prefix = "(903)"; - } - 904 - { - title = "50% Opaque"; - prefix = "(904)"; - } - 905 - { - title = "40% Opaque"; - prefix = "(905)"; - } - 906 - { - title = "30% Opaque"; - prefix = "(906)"; - } - 907 - { - title = "20% Opaque"; - prefix = "(907)"; - } - 908 - { - title = "10% Opaque"; - prefix = "(908)"; - } - 909 - { - title = "Fog Wall"; - prefix = "(909)"; - } - 910 - { - title = "100% Additive"; - prefix = "(910)"; - } - 911 - { - title = "90% Additive"; - prefix = "(911)"; - } - 912 - { - title = "80% Additive"; - prefix = "(912)"; - } - 913 - { - title = "70% Additive"; - prefix = "(913)"; - } - 914 - { - title = "60% Additive"; - prefix = "(914)"; - } - 915 - { - title = "50% Additive"; - prefix = "(915)"; - } - 916 - { - title = "40% Additive"; - prefix = "(916)"; - } - 917 - { - title = "30% Additive"; - prefix = "(917)"; - } - 918 - { - title = "20% Additive"; - prefix = "(918)"; - } - 919 - { - title = "10% Additive"; - prefix = "(919)"; - } - 920 - { - title = "100% Subtractive"; - prefix = "(920)"; - } - 921 - { - title = "90% Subtractive"; - prefix = "(921)"; - } - 922 - { - title = "80% Subtractive"; - prefix = "(922)"; - } - 923 - { - title = "70% Subtractive"; - prefix = "(923)"; - } - 924 - { - title = "60% Subtractive"; - prefix = "(924)"; - } - 925 - { - title = "50% Subtractive"; - prefix = "(925)"; - } - 926 - { - title = "40% Subtractive"; - prefix = "(926)"; - } - 927 - { - title = "30% Subtractive"; - prefix = "(927)"; - } - 928 - { - title = "20% Subtractive"; - prefix = "(928)"; - } - 929 - { - title = "10% Subtractive"; - prefix = "(929)"; - } - 930 - { - title = "100% Reverse Subtractive"; - prefix = "(930)"; - } - 931 - { - title = "90% Reverse Subtractive"; - prefix = "(931)"; - } - 932 - { - title = "80% Reverse Subtractive"; - prefix = "(932)"; - } - 933 - { - title = "70% Reverse Subtractive"; - prefix = "(933)"; - } - 934 - { - title = "60% Reverse Subtractive"; - prefix = "(934)"; - } - 935 - { - title = "50% Reverse Subtractive"; - prefix = "(935)"; - } - 936 - { - title = "40% Reverse Subtractive"; - prefix = "(936)"; - } - 937 - { - title = "30% Reverse Subtractive"; - prefix = "(937)"; - } - 938 - { - title = "20% Reverse Subtractive"; - prefix = "(938)"; - } - 939 - { - title = "10% Reverse Subtractive"; - prefix = "(939)"; - } - 940 - { - title = "Modulate"; - prefix = "(940)"; - } - } -} - udmf { misc @@ -2457,6 +712,7 @@ udmf { title = "Solid"; prefix = "(100)"; + id = "srb2_fofsolid"; arg0 { title = "Target sector tag"; @@ -2499,6 +755,7 @@ udmf { title = "Water"; prefix = "(120)"; + id = "srb2_fofwater"; arg0 { title = "Target sector tag"; @@ -2535,6 +792,7 @@ udmf { title = "Air Bobbing"; prefix = "(150)"; + id = "srb2_fofsolidopaque"; arg0 { title = "Target sector tag"; @@ -2561,6 +819,7 @@ udmf { title = "Water Bobbing"; prefix = "(160)"; + id = "srb2_fofsolidopaque"; arg0 { title = "Target sector tag"; @@ -2572,6 +831,7 @@ udmf { title = "Crumbling"; prefix = "(170)"; + id = "srb2_fofcrumbling"; arg0 { title = "Target sector tag"; @@ -2608,11 +868,12 @@ udmf } } } - + 190 { title = "Rising"; prefix = "(190)"; + id = "srb2_fofsolid"; arg0 { title = "Target sector tag"; @@ -2669,6 +930,7 @@ udmf { title = "Light Block"; prefix = "(200)"; + id = "srb2_foflight"; arg0 { title = "Target sector tag"; @@ -2686,6 +948,7 @@ udmf { title = "Fog Block"; prefix = "(202)"; + id = "srb2_foffog"; arg0 { title = "Target sector tag"; @@ -2697,6 +960,7 @@ udmf { title = "Intangible"; prefix = "(220)"; + id = "srb2_fofintangible"; arg0 { title = "Target sector tag"; @@ -2733,6 +997,7 @@ udmf { title = "Intangible, Invisible"; prefix = "(223)"; + id = "srb2_fofintangibleinvisible"; arg0 { title = "Target sector tag"; @@ -2744,6 +1009,7 @@ udmf { title = "Mario Block"; prefix = "(250)"; + id = "srb2_fofsolidopaque"; arg0 { title = "Target sector tag"; @@ -2765,6 +1031,7 @@ udmf { title = "Thwomp Block"; prefix = "(251)"; + id = "srb2_fofsolidopaque"; arg0 { title = "Target sector tag"; @@ -2789,6 +1056,7 @@ udmf { title = "Bustable Block"; prefix = "(254)"; + id = "srb2_fofbustable"; arg0 { title = "Target sector tag"; @@ -2840,6 +1108,7 @@ udmf { title = "Quicksand"; prefix = "(257)"; + id = "srb2_fofsolidopaque"; arg0 { title = "Target sector tag"; @@ -2865,6 +1134,7 @@ udmf { title = "Laser"; prefix = "(258)"; + id = "srb2_foflaser"; arg0 { title = "Target sector tag"; @@ -2897,6 +1167,7 @@ udmf { title = "Custom"; prefix = "(259)"; + id = "srb2_fofcustom"; arg0 { title = "Target sector tag"; @@ -4223,6 +2494,16 @@ udmf 1 = "Yes"; } } + arg2 + { + title = "Force MFE_VERTICALFLIP"; + type = 11; + enum + { + 0 = "No"; + 1 = "Yes"; + } + } } 434 @@ -5631,6 +3912,7 @@ udmf { title = "Create Vertex-Based Slope"; prefix = "(704)"; + id = "srb2_vertexslope"; arg0 { title = "Plane"; @@ -5674,6 +3956,7 @@ udmf { title = "Copy Slope"; prefix = "(720)"; + id = "plane_copy"; arg0 { title = "Front floor tag"; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index fcc24741e..e274fece6 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -1,24 +1,3 @@ -linedefflags -{ - 1 = "[0] Impassable"; - 2 = "[1] Block Enemies"; - 4 = "[2] Double-Sided"; - 8 = "[3] Upper Unpegged"; - 16 = "[4] Lower Unpegged"; - 32 = "[5] Slope Skew (E1)"; - 64 = "[6] Not Climbable"; - 128 = "[7] No Midtexture Skew (E2)"; - 256 = "[8] Peg Midtexture (E3)"; - 512 = "[9] Solid Midtexture (E4)"; - 1024 = "[10] Repeat Midtexture (E5)"; - 2048 = "[11] Netgame Only"; - 4096 = "[12] No Netgame"; - 8192 = "[13] Effect 6"; - 16384 = "[14] Bouncy Wall"; - 32768 = "[15] Transfer Line"; -} - - // Linedef flags UDMF translation table // This is needed for copy/paste and prefabs to work properly // When the UDMF field name is prefixed with ! it is inverted @@ -42,7 +21,6 @@ linedefflagstranslation 32768 = "transfer"; } - linedefflags_udmf { blocking = "Impassable"; @@ -74,19 +52,13 @@ linedefrenderstyles sectorflags { - colormapfog = "Fog Planes in Colormap"; - colormapfadesprites = "Fade Fullbright in Colormap"; - colormapprotected = "Protected Colormap"; - flipspecial_nofloor = "No Trigger on Floor Touch"; - flipspecial_ceiling = "Trigger on Ceiling Touch"; - triggerspecial_touch = "Trigger on Edge Touch"; - triggerspecial_headbump = "Trigger on Headbump"; - triggerline_plane = "Linedef Trigger Requires Plane Touch"; - triggerline_mobj = "Non-Pushables Can Trigger Linedef"; invertprecip = "Invert Precipitation"; gravityflip = "Flip Objects in Reverse Gravity"; heatwave = "Heat Wave"; noclipcamera = "Intangible to the Camera"; + colormapfog = "Fog Planes"; + colormapfadesprites = "Fade Fullbright"; + colormapprotected = "Protected from Tagging"; outerspace = "Space Countdown"; doublestepup = "Ramp Sector (double step-up/down)"; nostepdown = "Non-Ramp Sector (No step-down)"; @@ -104,23 +76,59 @@ sectorflags zoomtubeend = "Zoom Tube End"; finishline = "Circuit Finish Line"; ropehang = "Rope Hang"; + jumpflip = "Flip Gravity on Jump"; + gravityoverride = "Make Reverse Gravity Temporary"; + flipspecial_nofloor = "No Trigger on Floor Touch"; + flipspecial_ceiling = "Trigger on Ceiling Touch"; + triggerspecial_touch = "Trigger on Edge Touch"; + triggerspecial_headbump = "Trigger on Headbump"; + triggerline_plane = "Linedef Trigger Requires Plane Touch"; + triggerline_mobj = "Non-Pushables Can Trigger Linedef"; } -thingflags +sectorflagscategories { - 1 = "[1] Extra"; - 2 = "[2] Flip"; - 4 = "[4] Special"; - 8 = "[8] Ambush"; + invertprecip = "regular"; + gravityflip = "regular"; + heatwave = "regular"; + noclipcamera = "regular"; + colormapfog = "colormap"; + colormapfadesprites = "colormap"; + colormapprotected = "colormap"; + outerspace = "special"; + doublestepup = "special"; + nostepdown = "special"; + speedpad = "special"; + starpostactivator = "special"; + exit = "special"; + specialstagepit = "special"; + returnflag = "special"; + redteambase = "special"; + blueteambase = "special"; + fan = "special"; + supertransform = "special"; + forcespin = "special"; + zoomtubestart = "special"; + zoomtubeend = "special"; + finishline = "special"; + ropehang = "special"; + jumpflip = "special"; + gravityoverride = "special"; + flipspecial_nofloor = "trigger"; + flipspecial_ceiling = "trigger"; + triggerspecial_touch = "trigger"; + triggerspecial_headbump = "trigger"; + triggerline_plane = "trigger"; + triggerline_mobj = "trigger"; } // THING FLAGS thingflags_udmf { flip = "Flip"; + absolutez = "Absolute Z height"; } - // Thing flags UDMF translation table // This is needed for copy/paste and prefabs to work properly // When the UDMF field name is prefixed with ! it is inverted @@ -130,9 +138,9 @@ thingflagstranslation 2 = "flip"; 4 = "special"; 8 = "ambush"; + 16 = "absolutez"; } - // DEFAULT SECTOR BRIGHTNESS LEVELS sectorbrightness { @@ -171,6 +179,8 @@ sectorbrightness 0; } +numbrightnesslevels = 32; + /* TEXTURES AND FLAT SOURCES This tells Doom Builder where to find the information for textures @@ -221,151 +231,18 @@ universalfields { sector { - lightalpha - { - type = 0; - default = 25; - } - - fadealpha - { - type = 0; - default = 25; - } - - fadestart - { - type = 0; - default = 0; - } - - fadeend - { - type = 0; - default = 33; - } - - foglighting - { - type = 3; - default = false; - } - - friction - { - type = 1; - default = 0.90625; - } - - triggertag - { - type = 15; - default = 0; - } - - triggerer - { - type = 0; - default = 0; - enum - { - 0 = "Player"; - 1 = "All players"; - 2 = "Object"; - } - } } linedef { - arg5 - { - type = 0; - default = 0; - } - arg6 - { - type = 0; - default = 0; - } - arg7 - { - type = 0; - default = 0; - } - arg8 - { - type = 0; - default = 0; - } - arg9 - { - type = 0; - default = 0; - } - stringarg0 - { - type = 2; - default = ""; - } - stringarg1 - { - type = 2; - default = ""; - } - executordelay - { - type = 0; - default = 0; - } } sidedef { - repeatcnt - { - type = 0; - default = 0; - } } thing { - arg5 - { - type = 0; - default = 0; - } - arg6 - { - type = 0; - default = 0; - } - arg7 - { - type = 0; - default = 0; - } - arg8 - { - type = 0; - default = 0; - } - arg9 - { - type = 0; - default = 0; - } - stringarg0 - { - type = 2; - default = ""; - } - stringarg1 - { - type = 2; - default = ""; - } } } @@ -384,87 +261,6 @@ allowempty = The nodebuilder is allowed to leave this lump empty. scriptbuild = This lump is a text-based script, which should be compiled using current script compiler; script = This lump is a text-based script. Specify the filename of the script configuration to use. */ - -doommaplumpnames -{ - ~MAP - { - required = true; - blindcopy = true; - nodebuild = false; - } - - THINGS - { - required = true; - nodebuild = true; - allowempty = true; - } - - LINEDEFS - { - required = true; - nodebuild = true; - allowempty = false; - } - - SIDEDEFS - { - required = true; - nodebuild = true; - allowempty = false; - } - - VERTEXES - { - required = true; - nodebuild = true; - allowempty = false; - } - - SEGS - { - required = false; - nodebuild = true; - allowempty = false; - } - - SSECTORS - { - required = false; - nodebuild = true; - allowempty = false; - } - - NODES - { - required = false; - nodebuild = true; - allowempty = false; - } - - SECTORS - { - required = true; - nodebuild = true; - allowempty = false; - } - - REJECT - { - required = false; - nodebuild = true; - allowempty = false; - } - - BLOCKMAP - { - required = false; - nodebuild = true; - allowempty = true; - } -} - udmfmaplumpnames { ZNODES @@ -688,48 +484,32 @@ thingsfilters } + //filter3 + //{ + // name = "Normal Gravity"; + // category = ""; + // type = -1; + // + // fields + // { + // 2 = false; + // } + //} - filter3 - { - name = "Normal Gravity"; - category = ""; - type = -1; - - fields - { - 2 = false; - } - - } - - - filter4 - { - name = "Reverse Gravity"; - category = ""; - type = -1; - - fields - { - 2 = true; - } - - } + //filter4 + //{ + // name = "Reverse Gravity"; + // category = ""; + // type = -1; + // + // fields + // { + // 2 = true; + // } + //} } // Special linedefs -speciallinedefs -{ - soundlinedefflag = 64; // See linedefflags - singlesidedflag = 1; // See linedefflags - doublesidedflag = 4; // See linedefflags - impassableflag = 1; - upperunpeggedflag = 8; - lowerunpeggedflag = 16; - repeatmidtextureflag = 1024; - pegmidtextureflag = 256; -} - speciallinedefs_udmf { soundlinedefflag = "noclimb"; @@ -740,6 +520,8 @@ speciallinedefs_udmf lowerunpeggedflag = "dontpegbottom"; repeatmidtextureflag = "wrapmidtex"; pegmidtextureflag = "midpeg"; + slopeskewflag = "skewtd"; + nomidtextureskewflag = "noskew"; } scriptlumpnames diff --git a/extras/conf/udb/Includes/SRB222_sectors.cfg b/extras/conf/udb/Includes/SRB222_sectors.cfg deleted file mode 100644 index 5b3ad4155..000000000 --- a/extras/conf/udb/Includes/SRB222_sectors.cfg +++ /dev/null @@ -1,107 +0,0 @@ -sectortypes -{ - 0 = "Normal"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Tilt)"; - 7 = "Death Pit (No Camera Tilt)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (Anywhere in Sector)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy FOF "; - 16 = "Trigger Line Ex. (Pushable Objects)"; - 32 = "Trigger Line Ex. (Anywhere, All Players)"; - 48 = "Trigger Line Ex. (Floor Touch, All Players)"; - 64 = "Trigger Line Ex. (Anywhere in Sector)"; - 80 = "Trigger Line Ex. (Floor Touch)"; - 96 = "Trigger Line Ex. (Emerald Check) "; - 112 = "Trigger Line Ex. (NiGHTS Mare) "; - 128 = "Check for Linedef Executor on FOFs"; - 144 = "Egg Capsule"; - 160 = "Special Stage Time/Spheres Parameters "; - 176 = "Custom Global Gravity "; - 1280 = "Speed Pad"; - 1536 = "Flip Gravity on Jump"; - 4096 = "Star Post Activator"; - 8192 = "Exit/Special Stage Pit/Return Flag"; - 12288 = "CTF Red Team Base"; - 16384 = "CTF Blue Team Base"; - 20480 = "Fan Sector"; - 24576 = "Super Sonic Transform"; - 28672 = "Force Spin"; - 32768 = "Zoom Tube Start"; - 36864 = "Zoom Tube End"; - 40960 = "Circuit Finish Line"; - 45056 = "Rope Hang"; - 49152 = "Intangible to the Camera"; -} - -gen_sectortypes -{ - first - { - 0 = "Normal"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Tilt)"; - 7 = "Death Pit (No Camera Tilt)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (Anywhere in Sector)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy FOF "; - } - - second - { - 0 = "Normal"; - 16 = "Trigger Line Ex. (Pushable Objects)"; - 32 = "Trigger Line Ex. (Anywhere, All Players)"; - 48 = "Trigger Line Ex. (Floor Touch, All Players)"; - 64 = "Trigger Line Ex. (Anywhere in Sector)"; - 80 = "Trigger Line Ex. (Floor Touch)"; - 96 = "Trigger Line Ex. (Emerald Check) "; - 112 = "Trigger Line Ex. (NiGHTS Mare) "; - 128 = "Check for Linedef Executor on FOFs"; - 144 = "Egg Capsule"; - 160 = "Special Stage Time/Spheres Parameters "; - 176 = "Custom Global Gravity "; - } - - third - { - 0 = "Normal"; - 1280 = "Speed Pad"; - 1536 = "Flip Gravity on Jump"; - } - - fourth - { - 0 = "Normal"; - 4096 = "Star Post Activator"; - 8192 = "Exit/Special Stage Pit/Return Flag"; - 12288 = "CTF Red Team Base"; - 16384 = "CTF Blue Team Base"; - 20480 = "Fan Sector"; - 24576 = "Super Sonic Transform"; - 28672 = "Force Spin"; - 32768 = "Zoom Tube Start"; - 36864 = "Zoom Tube End"; - 40960 = "Circuit Finish Line"; - 45056 = "Rope Hang"; - 49152 = "Intangible to the Camera"; - } -} diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 1de661e29..df08e3ac5 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3,3175 +3,8 @@ // 8-Dark_Gray 9-Blue 10-Green 11-Cyan 12-Red 13-Magenta // 14-Yellow 15-White 16-Pink 17-Orange 18-Gold 19-Cream -doom -{ - editor - { - color = 15; // White - arrow = 1; - title = ""; - error = -1; - width = 8; - height = 16; - sort = 1; - - 3328 = "3D Mode Start"; - } - - starts - { - color = 1; // Blue - arrow = 1; - title = "Player Starts"; - width = 16; - height = 48; - sprite = "PLAYA0"; - - 1 - { - title = "Player 01 Start"; - sprite = "PLAYA0"; - } - 2 - { - title = "Player 02 Start"; - sprite = "PLAYA0"; - } - 3 - { - title = "Player 03 Start"; - sprite = "PLAYA0"; - } - 4 - { - title = "Player 04 Start"; - sprite = "PLAYA0"; - } - 5 - { - title = "Player 05 Start"; - sprite = "PLAYA0"; - } - 6 - { - title = "Player 06 Start"; - sprite = "PLAYA0"; - } - 7 - { - title = "Player 07 Start"; - sprite = "PLAYA0"; - } - 8 - { - title = "Player 08 Start"; - sprite = "PLAYA0"; - } - 9 - { - title = "Player 09 Start"; - sprite = "PLAYA0"; - } - 10 - { - title = "Player 10 Start"; - sprite = "PLAYA0"; - } - 11 - { - title = "Player 11 Start"; - sprite = "PLAYA0"; - } - 12 - { - title = "Player 12 Start"; - sprite = "PLAYA0"; - } - 13 - { - title = "Player 13 Start"; - sprite = "PLAYA0"; - } - 14 - { - title = "Player 14 Start"; - sprite = "PLAYA0"; - } - 15 - { - title = "Player 15 Start"; - sprite = "PLAYA0"; - } - 16 - { - title = "Player 16 Start"; - sprite = "PLAYA0"; - } - 17 - { - title = "Player 17 Start"; - sprite = "PLAYA0"; - } - 18 - { - title = "Player 18 Start"; - sprite = "PLAYA0"; - } - 19 - { - title = "Player 19 Start"; - sprite = "PLAYA0"; - } - 20 - { - title = "Player 20 Start"; - sprite = "PLAYA0"; - } - 21 - { - title = "Player 21 Start"; - sprite = "PLAYA0"; - } - 22 - { - title = "Player 22 Start"; - sprite = "PLAYA0"; - } - 23 - { - title = "Player 23 Start"; - sprite = "PLAYA0"; - } - 24 - { - title = "Player 24 Start"; - sprite = "PLAYA0"; - } - 25 - { - title = "Player 25 Start"; - sprite = "PLAYA0"; - } - 26 - { - title = "Player 26 Start"; - sprite = "PLAYA0"; - } - 27 - { - title = "Player 27 Start"; - sprite = "PLAYA0"; - } - 28 - { - title = "Player 28 Start"; - sprite = "PLAYA0"; - } - 29 - { - title = "Player 29 Start"; - sprite = "PLAYA0"; - } - 30 - { - title = "Player 30 Start"; - sprite = "PLAYA0"; - } - 31 - { - title = "Player 31 Start"; - sprite = "PLAYA0"; - } - 32 - { - title = "Player 32 Start"; - sprite = "PLAYA0"; - } - 33 - { - title = "Match Start"; - sprite = "NDRNA2A8"; - } - 34 - { - title = "CTF Red Team Start"; - sprite = "SIGNG0"; - } - 35 - { - title = "CTF Blue Team Start"; - sprite = "SIGNE0"; - } - } - - enemies - { - color = 9; // Light_Blue - arrow = 1; - title = "Enemies"; - - 100 - { - title = "Crawla (Blue)"; - sprite = "POSSA1"; - width = 24; - height = 32; - } - 101 - { - title = "Crawla (Red)"; - sprite = "SPOSA1"; - width = 24; - height = 32; - } - 102 - { - title = "Stupid Dumb Unnamed RoboFish"; - sprite = "FISHA0"; - width = 8; - height = 28; - } - 103 - { - title = "Buzz (Gold)"; - sprite = "BUZZA1"; - width = 28; - height = 40; - } - 104 - { - title = "Buzz (Red)"; - sprite = "RBUZA1"; - width = 28; - height = 40; - } - 108 - { - title = "Deton"; - sprite = "DETNA1"; - width = 20; - height = 32; - } - 110 - { - title = "Turret"; - sprite = "TRETA1"; - width = 16; - height = 32; - } - 111 - { - title = "Pop-up Turret"; - sprite = "TURRI1"; - width = 12; - height = 64; - } - 122 - { - title = "Spring Shell (Green)"; - sprite = "SSHLA1"; - width = 24; - height = 40; - } - 125 - { - title = "Spring Shell (Yellow)"; - sprite = "SSHLI1"; - width = 24; - height = 40; - } - 109 - { - title = "Skim"; - sprite = "SKIMA1"; - width = 16; - height = 24; - } - 113 - { - title = "Jet Jaw"; - sprite = "JJAWA3A7"; - width = 12; - height = 20; - } - 126 - { - title = "Crushstacean"; - sprite = "CRABA0"; - width = 24; - height = 32; - } - 138 - { - title = "Banpyura"; - sprite = "CR2BA0"; - width = 24; - height = 32; - } - 117 - { - title = "Robo-Hood"; - sprite = "ARCHA1"; - width = 24; - height = 32; - } - 118 - { - title = "Lance-a-Bot"; - sprite = "CBFSA1"; - width = 32; - height = 72; - } - 1113 - { - title = "Suspicious Lance-a-Bot Statue"; - sprite = "CBBSA1"; - width = 32; - height = 72; - } - 119 - { - title = "Egg Guard"; - sprite = "ESHIA1"; - width = 16; - height = 48; - } - 115 - { - title = "Bird Aircraft Strike Hazard"; - sprite = "VLTRF1"; - width = 12; - height = 24; - } - 120 - { - title = "Green Snapper"; - sprite = "GSNPA1"; - width = 24; - height = 24; - } - 121 - { - title = "Minus"; - sprite = "MNUSA0"; - width = 24; - height = 32; - } - 134 - { - title = "Canarivore"; - sprite = "CANAA0"; - width = 12; - height = 80; - hangs = 1; - } - 123 - { - title = "Unidus"; - sprite = "UNIDA1"; - width = 18; - height = 36; - } - 135 - { - title = "Pterabyte Spawner"; - sprite = "PTERA2A8"; - width = 16; - height = 16; - } - 136 - { - title = "Pyre Fly"; - sprite = "PYREA0"; - width = 24; - height = 34; - } - 137 - { - title = "Dragonbomber"; - sprite = "DRABA1"; - width = 28; - height = 48; - } - 105 - { - title = "Jetty-Syn Bomber"; - sprite = "JETBB1"; - width = 20; - height = 50; - } - 106 - { - title = "Jetty-Syn Gunner"; - sprite = "JETGB1"; - width = 20; - height = 48; - } - 112 - { - title = "Spincushion"; - sprite = "SHRPA1"; - width = 16; - height = 24; - } - 114 - { - title = "Snailer"; - sprite = "SNLRA3A7"; - width = 24; - height = 48; - } - 129 - { - title = "Penguinator"; - sprite = "PENGA1"; - width = 24; - height = 32; - } - 130 - { - title = "Pophat"; - sprite = "POPHA1"; - width = 24; - height = 32; - } - 107 - { - title = "Crawla Commander"; - sprite = "CCOMA1"; - width = 16; - height = 32; - } - 131 - { - title = "Spinbobert"; - sprite = "SBOBB0"; - width = 32; - height = 32; - } - 132 - { - title = "Cacolantern"; - sprite = "CACOA0"; - width = 32; - height = 32; - } - 133 - { - title = "Hangster"; - sprite = "HBATC1"; - width = 24; - height = 24; - hangs = 1; - } - 127 - { - title = "Hive Elemental"; - sprite = "HIVEA0"; - width = 32; - height = 80; - } - 128 - { - title = "Bumblebore"; - sprite = "BUMBA1"; - width = 16; - height = 32; - } - 124 - { - title = "Buggle"; - sprite = "BBUZA1"; - width = 20; - height = 24; - } - 116 - { - title = "Pointy"; - sprite = "PNTYA1"; - width = 8; - height = 16; - } - } - - bosses - { - color = 8; // Dark_Gray - arrow = 1; - title = "Bosses"; - - 200 - { - title = "Egg Mobile"; - sprite = "EGGMA1"; - width = 24; - height = 76; - } - 201 - { - title = "Egg Slimer"; - sprite = "EGGNA1"; - width = 24; - height = 76; - } - 202 - { - title = "Sea Egg"; - sprite = "EGGOA1"; - width = 32; - height = 116; - } - 203 - { - title = "Egg Colosseum"; - sprite = "EGGPA1"; - width = 24; - height = 76; - } - 204 - { - title = "Fang"; - sprite = "FANGA1"; - width = 24; - height = 60; - } - 206 - { - title = "Brak Eggman (Old)"; - sprite = "BRAKB1"; - width = 48; - height = 160; - } - 207 - { - title = "Metal Sonic (Race)"; - sprite = "METLI1"; - width = 16; - height = 48; - } - 208 - { - title = "Metal Sonic (Battle)"; - sprite = "METLC1"; - width = 16; - height = 48; - } - 209 - { - title = "Brak Eggman"; - sprite = "BRAK01"; - width = 48; - height = 160; - } - 290 - { - arrow = 0; - title = "Boss Escape Point"; - width = 8; - height = 16; - sprite = "internal:eggmanend"; - } - 291 - { - arrow = 0; - title = "Egg Capsule Center"; - width = 8; - height = 16; - sprite = "internal:capsule"; - } - 292 - { - arrow = 0; - title = "Boss Waypoint"; - width = 8; - height = 16; - sprite = "internal:eggmanway"; - } - 293 - { - title = "Metal Sonic Gather Point"; - sprite = "internal:metal"; - width = 8; - height = 16; - } - 294 - { - title = "Fang Waypoint"; - sprite = "internal:eggmanway"; - width = 8; - height = 16; - } - } - - rings - { - color = 14; // Yellow - title = "Rings and Weapon Panels"; - width = 24; - height = 24; - sprite = "RINGA0"; - - 300 - { - title = "Ring"; - sprite = "RINGA0"; - width = 16; - } - 301 - { - title = "Bounce Ring"; - sprite = "internal:RNGBA0"; - } - 302 - { - title = "Rail Ring"; - sprite = "internal:RNGRA0"; - } - 303 - { - title = "Infinity Ring"; - sprite = "internal:RNGIA0"; - } - 304 - { - title = "Automatic Ring"; - sprite = "internal:RNGAA0"; - } - 305 - { - title = "Explosion Ring"; - sprite = "internal:RNGEA0"; - } - 306 - { - title = "Scatter Ring"; - sprite = "internal:RNGSA0"; - } - 307 - { - title = "Grenade Ring"; - sprite = "internal:RNGGA0"; - } - 308 - { - title = "CTF Team Ring (Red)"; - sprite = "internal:RRNGA0"; - width = 16; - } - 309 - { - title = "CTF Team Ring (Blue)"; - sprite = "internal:BRNGA0"; - width = 16; - } - 330 - { - title = "Bounce Ring Panel"; - sprite = "internal:PIKBA0"; - } - 331 - { - title = "Rail Ring Panel"; - sprite = "internal:PIKRA0"; - } - 332 - { - title = "Automatic Ring Panel"; - sprite = "internal:PIKAA0"; - } - 333 - { - title = "Explosion Ring Panel"; - sprite = "internal:PIKEA0"; - } - 334 - { - title = "Scatter Ring Panel"; - sprite = "internal:PIKSA0"; - } - 335 - { - title = "Grenade Ring Panel"; - sprite = "internal:PIKGA0"; - } - } - - collectibles - { - color = 10; // Light_Green - title = "Other Collectibles"; - width = 16; - height = 32; - sort = 1; - sprite = "CEMGA0"; - - 310 - { - title = "CTF Red Flag"; - sprite = "RFLGA0"; - width = 24; - height = 64; - } - 311 - { - title = "CTF Blue Flag"; - sprite = "BFLGA0"; - width = 24; - height = 64; - } - 312 - { - title = "Emerald Token"; - sprite = "TOKEA0"; - width = 16; - height = 32; - } - 313 - { - title = "Chaos Emerald 1 (Green)"; - sprite = "CEMGA0"; - } - 314 - { - title = "Chaos Emerald 2 (Purple)"; - sprite = "CEMGB0"; - } - 315 - { - title = "Chaos Emerald 3 (Blue)"; - sprite = "CEMGC0"; - } - 316 - { - title = "Chaos Emerald 4 (Cyan)"; - sprite = "CEMGD0"; - } - 317 - { - title = "Chaos Emerald 5 (Orange)"; - sprite = "CEMGE0"; - } - 318 - { - title = "Chaos Emerald 6 (Red)"; - sprite = "CEMGF0"; - } - 319 - { - title = "Chaos Emerald 7 (Gray)"; - sprite = "CEMGG0"; - } - 320 - { - title = "Emerald Hunt Location"; - sprite = "SHRDA0"; - } - 321 - { - title = "Match Chaos Emerald Spawn"; - sprite = "CEMGA0"; - } - 322 - { - title = "Emblem"; - sprite = "EMBMA0"; - width = 16; - height = 30; - } - } - - boxes - { - color = 7; // Gray - blocking = 2; - title = "Monitors"; - width = 18; - height = 40; - - 400 - { - title = "Super Ring (10 Rings)"; - sprite = "TVRIA0"; - } - 401 - { - title = "Pity Shield"; - sprite = "TVPIA0"; - } - 402 - { - title = "Attraction Shield"; - sprite = "TVATA0"; - } - 403 - { - title = "Force Shield"; - sprite = "TVFOA0"; - } - 404 - { - title = "Armageddon Shield"; - sprite = "TVARA0"; - } - 405 - { - title = "Whirlwind Shield"; - sprite = "TVWWA0"; - } - 406 - { - title = "Elemental Shield"; - sprite = "TVELA0"; - } - 407 - { - title = "Super Sneakers"; - sprite = "TVSSA0"; - } - 408 - { - title = "Invincibility"; - sprite = "TVIVA0"; - } - 409 - { - title = "Extra Life"; - sprite = "TV1UA0"; - } - 410 - { - title = "Eggman"; - sprite = "TVEGA0"; - } - 411 - { - title = "Teleporter"; - sprite = "TVMXA0"; - } - 413 - { - title = "Gravity Boots"; - sprite = "TVGVA0"; - } - 414 - { - title = "CTF Team Ring Monitor (Red)"; - sprite = "TRRIA0"; - } - 415 - { - title = "CTF Team Ring Monitor (Blue)"; - sprite = "TBRIA0"; - } - 416 - { - title = "Recycler"; - sprite = "TVRCA0"; - } - 418 - { - title = "Score (1,000 Points)"; - sprite = "TV1KA0"; - } - 419 - { - title = "Score (10,000 Points)"; - sprite = "TVTKA0"; - } - 420 - { - title = "Flame Shield"; - sprite = "TVFLA0"; - } - 421 - { - title = "Water Shield"; - sprite = "TVBBA0"; - } - 422 - { - title = "Lightning Shield"; - sprite = "TVZPA0"; - } - } - - boxes2 - { - color = 18; // Gold - blocking = 2; - title = "Monitors (Respawning)"; - width = 20; - height = 44; - - 431 - { - title = "Pity Shield (Respawn)"; - sprite = "TVPIB0"; - } - 432 - { - title = "Attraction Shield (Respawn)"; - sprite = "TVATB0"; - } - 433 - { - title = "Force Shield (Respawn)"; - sprite = "TVFOB0"; - } - 434 - { - title = "Armageddon Shield (Respawn)"; - sprite = "TVARB0"; - } - 435 - { - title = "Whirlwind Shield (Respawn)"; - sprite = "TVWWB0"; - } - 436 - { - title = "Elemental Shield (Respawn)"; - sprite = "TVELB0"; - } - 437 - { - title = "Super Sneakers (Respawn)"; - sprite = "TVSSB0"; - } - 438 - { - title = "Invincibility (Respawn)"; - sprite = "TVIVB0"; - } - 440 - { - title = "Eggman (Respawn)"; - sprite = "TVEGB0"; - } - 443 - { - title = "Gravity Boots (Respawn)"; - sprite = "TVGVB0"; - } - 450 - { - title = "Flame Shield (Respawn)"; - sprite = "TVFLB0"; - } - 451 - { - title = "Water Shield (Respawn)"; - sprite = "TVBBB0"; - } - 452 - { - title = "Lightning Shield (Respawn)"; - sprite = "TVZPB0"; - } - } - - generic - { - color = 11; // Light_Cyan - title = "Generic Items & Hazards"; - - 500 - { - title = "Air Bubble Patch"; - sprite = "BUBLE0"; - width = 8; - height = 16; - } - 501 - { - title = "Signpost"; - sprite = "SIGND0"; - width = 8; - height = 32; - } - 502 - { - arrow = 1; - title = "Star Post"; - sprite = "STPTA0M0"; - width = 64; - height = 128; - } - 520 - { - title = "Bomb Sphere"; - sprite = "SPHRD0"; - width = 16; - height = 24; - } - 521 - { - title = "Spikeball"; - sprite = "SPIKA0"; - width = 12; - height = 8; - } - 522 - { - title = "Wall Spike"; - sprite = "WSPKALAR"; - width = 16; - height = 14; - arrow = 1; - } - 523 - { - title = "Spike"; - sprite = "USPKA0"; - width = 8; - height = 32; - } - 1130 - { - title = "Small Mace"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1131 - { - title = "Big Mace"; - sprite = "BMCEA0"; - width = 34; - height = 68; - } - 1136 - { - title = "Small Fireball"; - sprite = "SFBRA0"; - width = 17; - height = 34; - } - 1137 - { - title = "Large Fireball"; - sprite = "BFBRA0"; - width = 34; - height = 68; - } - } - - springs - { - color = 12; // Light_Red - title = "Springs and Fans"; - width = 20; - height = 16; - sprite = "RSPRD2"; - - 540 - { - title = "Fan"; - sprite = "FANSA0D0"; - width = 16; - height = 8; - } - 541 - { - title = "Gas Jet"; - sprite = "STEMD0"; - width = 32; - } - 542 - { - title = "Bumper"; - sprite = "BUMPA0"; - width = 32; - height = 64; - } - 543 - { - title = "Balloon"; - sprite = "BLONA0"; - width = 32; - height = 64; - } - 550 - { - title = "Yellow Spring"; - sprite = "SPRYA0"; - } - 551 - { - title = "Red Spring"; - sprite = "SPRRA0"; - } - 552 - { - title = "Blue Spring"; - sprite = "SPRBA0"; - } - 555 - { - arrow = 1; - title = "Diagonal Yellow Spring"; - sprite = "YSPRD2"; - width = 16; - } - 556 - { - arrow = 1; - title = "Diagonal Red Spring"; - sprite = "RSPRD2"; - width = 16; - } - 557 - { - arrow = 1; - title = "Diagonal Blue Spring"; - sprite = "BSPRD2"; - width = 16; - } - 558 - { - arrow = 1; - title = "Horizontal Yellow Spring"; - sprite = "SSWYD2D8"; - width = 16; - height = 32; - } - 559 - { - arrow = 1; - title = "Horizontal Red Spring"; - sprite = "SSWRD2D8"; - width = 16; - height = 32; - } - 560 - { - arrow = 1; - title = "Horizontal Blue Spring"; - sprite = "SSWBD2D8"; - width = 16; - height = 32; - } - 1134 - { - title = "Yellow Spring Ball"; - sprite = "YSPBA0"; - width = 17; - height = 34; - } - 1135 - { - title = "Red Spring Ball"; - sprite = "RSPBA0"; - width = 17; - height = 34; - } - 544 - { - arrow = 1; - title = "Yellow Boost Panel"; - sprite = "BSTYA0"; - width = 28; - height = 2; - } - 545 - { - arrow = 1; - title = "Red Boost Panel"; - sprite = "BSTRA0"; - width = 28; - height = 2; - } - } - - patterns - { - color = 5; // Magenta - arrow = 1; - title = "Special Placement Patterns"; - width = 16; - height = 384; - sprite = "RINGA0"; - - 600 - { - arrow = 0; - title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; - } - 601 - { - arrow = 0; - title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; - height = 1024; - } - 602 - { - title = "5 Diagonal Rings (Yellow Spring)"; - sprite = "RINGA0"; - height = 32; - } - 603 - { - title = "10 Diagonal Rings (Red Spring)"; - sprite = "RINGA0"; - height = 32; - } - 604 - { - title = "Circle of Rings"; - sprite = "RINGA0"; - width = 96; - height = 192; - } - 605 - { - title = "Circle of Rings (Big)"; - sprite = "RINGA0"; - width = 192; - } - 606 - { - title = "Circle of Blue Spheres"; - sprite = "SPHRA0"; - width = 96; - height = 192; - } - 607 - { - title = "Circle of Blue Spheres (Big)"; - sprite = "SPHRA0"; - width = 192; - } - 608 - { - title = "Circle of Rings and Spheres"; - sprite = "SPHRA0"; - width = 96; - height = 192; - } - 609 - { - title = "Circle of Rings and Spheres (Big)"; - sprite = "SPHRA0"; - width = 192; - } - } - - invisible - { - color = 15; // White - title = "Misc. Invisible"; - width = 0; - height = 0; - sprite = "UNKNA0"; - sort = 1; - fixedsize = true; - blocking = 0; - - 700 - { - title = "Water Ambience A (Large)"; - sprite = "internal:ambiance"; - } - - 701 - { - title = "Water Ambience B (Large)"; - sprite = "internal:ambiance"; - } - - 702 - { - title = "Water Ambience C (Medium)"; - sprite = "internal:ambiance"; - } - - 703 - { - title = "Water Ambience D (Medium)"; - sprite = "internal:ambiance"; - } - - 704 - { - title = "Water Ambience E (Small)"; - sprite = "internal:ambiance"; - } - - 705 - { - title = "Water Ambience F (Small)"; - sprite = "internal:ambiance"; - } - - 706 - { - title = "Water Ambience G (Extra Large)"; - sprite = "internal:ambiance"; - } - - 707 - { - title = "Water Ambience H (Extra Large)"; - sprite = "internal:ambiance"; - } - - 708 - { - title = "Disco Ambience"; - sprite = "internal:ambiance"; - } - - 709 - { - title = "Volcano Ambience"; - sprite = "internal:ambiance"; - } - - 710 - { - title = "Machine Ambience"; - sprite = "internal:ambiance"; - } - - 750 - { - title = "Slope Vertex"; - sprite = "internal:vertexslope"; - } - - 751 - { - arrow = 1; - title = "Teleport Destination"; - sprite = "internal:tele"; - } - - 752 - { - arrow = 1; - title = "Alternate View Point"; - sprite = "internal:view"; - } - - 753 - { - title = "Zoom Tube Waypoint"; - sprite = "internal:zoom"; - } - - 754 - { - title = "Push Point"; - sprite = "GWLGA0"; - } - 755 - { - title = "Pull Point"; - sprite = "GWLRA0"; - } - 756 - { - title = "Blast Linedef Executor"; - sprite = "TOADA0"; - width = 32; - height = 16; - } - 757 - { - title = "Fan Particle Generator"; - sprite = "PRTLA0"; - width = 8; - height = 16; - } - 758 - { - title = "Object Angle Anchor"; - sprite = "internal:view"; - } - 760 - { - title = "PolyObject Anchor"; - sprite = "internal:polyanchor"; - } - 761 - { - title = "PolyObject Spawn Point"; - sprite = "internal:polycenter"; - } - 762 - { - title = "PolyObject Spawn Point (Crush)"; - sprite = "internal:polycentercrush"; - } - 780 - { - title = "Skybox View Point"; - sprite = "internal:skyb"; - } - } - - greenflower - { - color = 10; // Green - title = "Greenflower"; - - 800 - { - title = "GFZ Flower"; - sprite = "FWR1A0"; - width = 16; - height = 40; - } - 801 - { - title = "Sunflower"; - sprite = "FWR2A0"; - width = 16; - height = 96; - } - 802 - { - title = "Budding Flower"; - sprite = "FWR3A0"; - width = 8; - height = 32; - } - 803 - { - title = "Blueberry Bush"; - sprite = "BUS3A0"; - width = 16; - height = 32; - } - 804 - { - title = "Berry Bush"; - sprite = "BUS1A0"; - width = 16; - height = 32; - } - 805 - { - title = "Bush"; - sprite = "BUS2A0"; - width = 16; - height = 32; - } - 806 - { - title = "GFZ Tree"; - sprite = "TRE1A0"; - width = 20; - height = 128; - } - 807 - { - title = "GFZ Berry Tree"; - sprite = "TRE1B0"; - width = 20; - height = 128; - } - 808 - { - title = "GFZ Cherry Tree"; - sprite = "TRE1C0"; - width = 20; - height = 128; - } - 809 - { - title = "Checkered Tree"; - sprite = "TRE2A0"; - width = 20; - height = 200; - } - 810 - { - title = "Checkered Tree (Sunset)"; - sprite = "TRE2B0"; - width = 20; - height = 200; - } - 811 - { - title = "Polygon Tree"; - sprite = "TRE4A0"; - width = 20; - height = 200; - } - 812 - { - title = "Bush Tree"; - sprite = "TRE5A0"; - width = 20; - height = 200; - } - 813 - { - title = "Red Bush Tree"; - sprite = "TRE5B0"; - width = 20; - height = 200; - } - } - - technohill - { - color = 10; // Green - title = "Techno Hill"; - - 900 - { - title = "THZ Steam Flower"; - sprite = "THZPA0"; - width = 8; - height = 32; - } - 901 - { - title = "Alarm"; - sprite = "ALRMA0"; - width = 8; - height = 16; - hangs = 1; - } - 902 - { - title = "THZ Spin Flower (Red)"; - sprite = "FWR5A0"; - width = 16; - height = 64; - } - 903 - { - title = "THZ Spin Flower (Yellow)"; - sprite = "FWR6A0"; - width = 16; - height = 64; - } - 904 - { - arrow = 1; - title = "Whistlebush"; - sprite = "THZTA0"; - width = 16; - height = 64; - } - } - - deepsea - { - color = 10; // Green - title = "Deep Sea"; - - 1000 - { - arrow = 1; - blocking = 2; - title = "Gargoyle"; - sprite = "GARGA1"; - width = 16; - height = 40; - } - 1009 - { - arrow = 1; - blocking = 2; - title = "Gargoyle (Big)"; - sprite = "GARGB1"; - width = 32; - height = 80; - } - 1001 - { - title = "Seaweed"; - sprite = "SEWEA0"; - width = 24; - height = 56; - } - 1002 - { - title = "Dripping Water"; - sprite = "DRIPD0"; - width = 8; - height = 16; - hangs = 1; - } - 1003 - { - title = "Coral (Green)"; - sprite = "CORLA0"; - width = 29; - height = 40; - } - 1004 - { - title = "Coral (Red)"; - sprite = "CORLB0"; - width = 30; - height = 53; - } - 1005 - { - title = "Coral (Orange)"; - sprite = "CORLC0"; - width = 28; - height = 41; - } - 1006 - { - title = "Blue Crystal"; - sprite = "BCRYA1"; - width = 8; - height = 16; - } - 1007 - { - title = "Kelp"; - sprite = "KELPA0"; - width = 16; - height = 292; - } - 1008 - { - title = "Stalagmite (DSZ1)"; - sprite = "DSTGA0"; - width = 8; - height = 116; - } - 1010 - { - arrow = 1; - title = "Light Beam"; - sprite = "LIBEARAL"; - width = 16; - height = 16; - } - 1011 - { - title = "Stalagmite (DSZ2)"; - sprite = "DSTGA0"; - width = 8; - height = 116; - } - 1012 - { - arrow = 1; - title = "Big Floating Mine"; - width = 28; - height = 56; - sprite = "BMNEA1"; - } - 1013 - { - title = "Animated Kelp"; - sprite = "ALGAA0"; - width = 48; - height = 120; - } - 1014 - { - title = "Large Coral (Brown)"; - sprite = "CORLD0"; - width = 56; - height = 112; - } - 1015 - { - title = "Large Coral (Beige)"; - sprite = "CORLE0"; - width = 56; - height = 112; - } - } - - castleeggman - { - color = 10; // Green - title = "Castle Eggman"; - - 1100 - { - title = "Chain (Decorative)"; - sprite = "CHANA0"; - width = 4; - height = 128; - hangs = 1; - } - 1101 - { - title = "Torch"; - sprite = "FLAMA0E0"; - width = 8; - height = 32; - } - 1102 - { - arrow = 1; - blocking = 2; - title = "Eggman Statue"; - sprite = "ESTAA1"; - width = 32; - height = 240; - } - 1103 - { - title = "CEZ Flower"; - sprite = "FWR4A0"; - width = 16; - height = 40; - } - 1104 - { - title = "Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1105 - { - title = "Chain with Maces Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1106 - { - title = "Chained Spring Spawnpoint"; - sprite = "YSPBA0"; - width = 17; - height = 34; - } - 1107 - { - title = "Chain Spawnpoint"; - sprite = "BMCHA0"; - width = 17; - height = 34; - } - 1108 - { - arrow = 1; - title = "Hidden Chain Spawnpoint"; - sprite = "internal:chain3"; - width = 17; - height = 34; - } - 1109 - { - title = "Firebar Spawnpoint"; - sprite = "BFBRA0"; - width = 17; - height = 34; - } - 1110 - { - title = "Custom Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1111 - { - arrow = 1; - blocking = 2; - title = "Crawla Statue"; - sprite = "CSTAA1"; - width = 16; - height = 40; - } - 1112 - { - arrow = 1; - blocking = 2; - title = "Lance-a-Bot Statue"; - sprite = "CBBSA1"; - width = 32; - height = 72; - } - 1114 - { - title = "Pine Tree"; - sprite = "PINEA0"; - width = 16; - height = 628; - } - 1115 - { - title = "CEZ Shrub (Small)"; - sprite = "CEZBA0"; - width = 16; - height = 24; - } - 1116 - { - title = "CEZ Shrub (Large)"; - sprite = "CEZBB0"; - width = 32; - height = 48; - } - 1117 - { - arrow = 1; - title = "Pole Banner (Red)"; - sprite = "BANRA0"; - width = 40; - height = 224; - } - 1118 - { - arrow = 1; - title = "Pole Banner (Blue)"; - sprite = "BANRA0"; - width = 40; - height = 224; - } - 1119 - { - title = "Candle"; - sprite = "CNDLA0"; - width = 8; - height = 48; - } - 1120 - { - title = "Candle Pricket"; - sprite = "CNDLB0"; - width = 8; - height = 176; - } - 1121 - { - title = "Flame Holder"; - sprite = "FLMHA0"; - width = 24; - height = 80; - } - 1122 - { - title = "Fire Torch"; - sprite = "CTRCA0"; - width = 16; - height = 80; - } - 1123 - { - title = "Cannonball Launcher"; - sprite = "internal:cannonball"; - width = 8; - height = 16; - } - 1124 - { - blocking = 2; - title = "Cannonball"; - sprite = "CBLLA0"; - width = 20; - height = 40; - } - 1125 - { - title = "Brambles"; - sprite = "CABRALAR"; - width = 48; - height = 32; - } - 1126 - { - title = "Invisible Lockon Object"; - sprite = "LCKNC0"; - width = 16; - height = 32; - } - 1127 - { - title = "Spectator Eggrobo"; - sprite = "EGR1A1"; - width = 20; - height = 72; - } - 1128 - { - arrow = 1; - title = "Waving Flag (Red)"; - sprite = "CFLGA0"; - width = 8; - height = 208; - } - 1129 - { - arrow = 1; - title = "Waving Flag (Blue)"; - sprite = "CFLGA0"; - width = 8; - height = 208; - } - } - - aridcanyon - { - color = 10; // Green - title = "Arid Canyon"; - - 1200 - { - title = "Tumbleweed (Big)"; - sprite = "BTBLA0"; - width = 24; - height = 48; - } - 1201 - { - title = "Tumbleweed (Small)"; - sprite = "STBLA0"; - width = 12; - height = 24; - } - 1202 - { - arrow = 1; - title = "Rock Spawner"; - sprite = "ROIAA0"; - width = 8; - height = 16; - } - 1203 - { - title = "Tiny Red Flower Cactus"; - sprite = "CACTA0"; - width = 13; - height = 24; - } - 1204 - { - title = "Small Red Flower Cactus"; - sprite = "CACTB0"; - width = 15; - height = 52; - } - 1205 - { - title = "Tiny Blue Flower Cactus"; - sprite = "CACTC0"; - width = 13; - height = 24; - } - 1206 - { - title = "Small Blue Flower Cactus"; - sprite = "CACTD0"; - width = 15; - height = 52; - } - 1207 - { - title = "Prickly Pear"; - sprite = "CACTE0"; - width = 32; - height = 96; - } - 1208 - { - title = "Barrel Cactus"; - sprite = "CACTF0"; - width = 20; - height = 128; - } - 1209 - { - title = "Tall Barrel Cactus"; - sprite = "CACTG0"; - width = 24; - height = 224; - } - 1210 - { - title = "Armed Cactus"; - sprite = "CACTH0"; - width = 24; - height = 256; - } - 1211 - { - title = "Ball Cactus"; - sprite = "CACTI0"; - width = 48; - height = 96; - } - 1212 - { - title = "Caution Sign"; - sprite = "WWSGAR"; - width = 22; - height = 64; - } - 1213 - { - title = "Cacti Sign"; - sprite = "WWS2AR"; - width = 22; - height = 64; - } - 1214 - { - title = "Sharp Turn Sign"; - sprite = "WWS3ALAR"; - width = 16; - height = 192; - } - 1215 - { - title = "Mine Oil Lamp"; - sprite = "OILLA0"; - width = 22; - height = 64; - hangs = 1; - } - 1216 - { - title = "TNT Barrel"; - sprite = "BARRA1"; - width = 24; - height = 63; - } - 1217 - { - title = "TNT Proximity Shell"; - sprite = "REMTA0"; - width = 64; - height = 40; - } - 1218 - { - title = "Dust Devil"; - sprite = "TAZDCR"; - width = 80; - height = 416; - } - 1219 - { - title = "Minecart Spawner"; - sprite = "MCRTCLFR"; - width = 22; - height = 32; - } - 1220 - { - title = "Minecart Stopper"; - sprite = "MCRTIR"; - width = 32; - height = 32; - } - 1221 - { - title = "Minecart Saloon Door"; - sprite = "SALDARAL"; - width = 96; - height = 160; - } - 1222 - { - title = "Train Cameo Spawner"; - sprite = "TRAEBRBL"; - width = 28; - height = 32; - } - 1223 - { - title = "Train Dust Spawner"; - sprite = "ADSTA0"; - width = 4; - height = 4; - } - 1224 - { - title = "Train Steam Spawner"; - sprite = "STEAA0"; - width = 4; - height = 4; - } - 1229 - { - title = "Minecart Switch Point"; - sprite = "internal:zoom"; - width = 8; - height = 16; - } - 1230 - { - title = "Tiny Cactus"; - sprite = "CACTJ0"; - width = 13; - height = 28; - } - 1231 - { - title = "Small Cactus"; - sprite = "CACTK0"; - width = 15; - height = 60; - } - } - - redvolcano - { - color = 10; // Green - title = "Red Volcano"; - - 1300 - { - arrow = 1; - title = "Flame Jet (Horizontal)"; - sprite = "internal:flameh"; - width = 16; - height = 40; - } - 1301 - { - title = "Flame Jet (Vertical)"; - sprite = "internal:flamev"; - width = 16; - height = 40; - } - 1302 - { - title = "Spinning Flame Jet (Counter-Clockwise)"; - sprite = "internal:flame2"; - width = 16; - height = 24; - } - 1303 - { - title = "Spinning Flame Jet (Clockwise)"; - sprite = "internal:flame1"; - width = 16; - height = 24; - } - 1304 - { - title = "Lavafall"; - sprite = "LFALF0"; - width = 30; - height = 32; - } - 1305 - { - title = "Rollout Rock"; - sprite = "PUMIA1A5"; - width = 30; - height = 60; - } - 1306 - { - title = "Big Fern"; - sprite = "JPLAB0"; - width = 32; - height = 48; - } - 1307 - { - title = "Jungle Palm"; - sprite = "JPLAC0"; - width = 32; - height = 48; - } - 1308 - { - title = "Torch Flower"; - sprite = "TFLOA0"; - width = 14; - height = 110; - } - 1309 - { - title = "RVZ1 Wall Vine (Long)"; - sprite = "WVINALAR"; - width = 1; - height = 288; - } - 1310 - { - title = "RVZ1 Wall Vine (Short)"; - sprite = "WVINBLBR"; - width = 1; - height = 288; - } - } - - botanicserenity - { - color = 10; // Green - title = "Botanic Serenity"; - width = 16; - height = 32; - sprite = "BSZ1A0"; - 1400 - { - title = "Tall Flower (Red)"; - sprite = "BSZ1A0"; - } - 1401 - { - title = "Tall Flower (Purple)"; - sprite = "BSZ1B0"; - } - 1402 - { - title = "Tall Flower (Blue)"; - sprite = "BSZ1C0"; - } - 1403 - { - title = "Tall Flower (Cyan)"; - sprite = "BSZ1D0"; - } - 1404 - { - title = "Tall Flower (Yellow)"; - sprite = "BSZ1E0"; - } - 1405 - { - title = "Tall Flower (Orange)"; - sprite = "BSZ1F0"; - } - 1410 - { - title = "Medium Flower (Red)"; - sprite = "BSZ2A0"; - } - 1411 - { - title = "Medium Flower (Purple)"; - sprite = "BSZ2B0"; - } - 1412 - { - title = "Medium Flower (Blue)"; - sprite = "BSZ2C0"; - } - 1413 - { - title = "Medium Flower (Cyan)"; - sprite = "BSZ2D0"; - } - 1414 - { - title = "Medium Flower (Yellow)"; - sprite = "BSZ2E0"; - } - 1415 - { - title = "Medium Flower (Orange)"; - sprite = "BSZ2F0"; - } - 1420 - { - title = "Short Flower (Red)"; - sprite = "BSZ3A0"; - } - 1421 - { - title = "Short Flower (Purple)"; - sprite = "BSZ3B0"; - } - 1422 - { - title = "Short Flower (Blue)"; - sprite = "BSZ3C0"; - } - 1423 - { - title = "Short Flower (Cyan)"; - sprite = "BSZ3D0"; - } - 1424 - { - title = "Short Flower (Yellow)"; - sprite = "BSZ3E0"; - } - 1425 - { - title = "Short Flower (Orange)"; - sprite = "BSZ3F0"; - } - 1430 - { - title = "Tulip (Red)"; - sprite = "BST1A0"; - } - 1431 - { - title = "Tulip (Purple)"; - sprite = "BST2A0"; - } - 1432 - { - title = "Tulip (Blue)"; - sprite = "BST3A0"; - } - 1433 - { - title = "Tulip (Cyan)"; - sprite = "BST4A0"; - } - 1434 - { - title = "Tulip (Yellow)"; - sprite = "BST5A0"; - } - 1435 - { - title = "Tulip (Orange)"; - sprite = "BST6A0"; - } - 1440 - { - title = "Cluster (Red)"; - sprite = "BSZ5A0"; - } - 1441 - { - title = "Cluster (Purple)"; - sprite = "BSZ5B0"; - } - 1442 - { - title = "Cluster (Blue)"; - sprite = "BSZ5C0"; - } - 1443 - { - title = "Cluster (Cyan)"; - sprite = "BSZ5D0"; - } - 1444 - { - title = "Cluster (Yellow)"; - sprite = "BSZ5E0"; - } - 1445 - { - title = "Cluster (Orange)"; - sprite = "BSZ5F0"; - } - 1450 - { - title = "Bush (Red)"; - sprite = "BSZ6A0"; - } - 1451 - { - title = "Bush (Purple)"; - sprite = "BSZ6B0"; - } - 1452 - { - title = "Bush (Blue)"; - sprite = "BSZ6C0"; - } - 1453 - { - title = "Bush (Cyan)"; - sprite = "BSZ6D0"; - } - 1454 - { - title = "Bush (Yellow)"; - sprite = "BSZ6E0"; - } - 1455 - { - title = "Bush (Orange)"; - sprite = "BSZ6F0"; - } - 1460 - { - title = "Vine (Red)"; - sprite = "BSZ7A0"; - } - 1461 - { - title = "Vine (Purple)"; - sprite = "BSZ7B0"; - } - 1462 - { - title = "Vine (Blue)"; - sprite = "BSZ7C0"; - } - 1463 - { - title = "Vine (Cyan)"; - sprite = "BSZ7D0"; - } - 1464 - { - title = "Vine (Yellow)"; - sprite = "BSZ7E0"; - } - 1465 - { - title = "Vine (Orange)"; - sprite = "BSZ7F0"; - } - 1470 - { - title = "BSZ Shrub"; - sprite = "BSZ8A0"; - } - 1471 - { - title = "BSZ Clover"; - sprite = "BSZ8B0"; - } - 1473 - { - title = "Palm Tree (Big)"; - width = 16; - height = 160; - sprite = "BSZ8D0"; - } - 1475 - { - title = "Palm Tree (Small)"; - width = 16; - height = 80; - sprite = "BSZ8F0"; - } - } - - azuretemple - { - color = 10; // Green - title = "Azure Temple"; - - 1500 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle"; - sprite = "BGARA1"; - width = 16; - height = 40; - } - 1501 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Up)"; - sprite = "BGARA1"; - width = 16; - height = 40; - } - 1502 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Down)"; - sprite = "BGARA1"; - width = 16; - height = 40; - } - 1503 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Long)"; - sprite = "BGARA1"; - width = 16; - height = 40; - } - 1504 - { - title = "ATZ Target"; - sprite = "RCRYB0"; - width = 24; - height = 32; - } - 1505 - { - title = "Green Flame"; - sprite = "CFLMA0E0"; - width = 8; - height = 32; - } - 1506 - { - arrow = 1; - blocking = 2; - title = "Blue Gargoyle"; - sprite = "BGARD1"; - width = 16; - height = 40; - } - } - - dreamhill - { - color = 10; // Green - title = "Dream Hill"; - - 1600 - { - title = "Spring Tree"; - sprite = "TRE6A0"; - width = 16; - height = 32; - } - 1601 - { - title = "Shleep"; - sprite = "SHLPA0"; - width = 24; - height = 32; - } - 1602 - { - title = "Nightopian"; - sprite = "NTPNA1"; - width = 16; - height = 40; - } - } - - nightstrk - { - color = 13; // Pink - title = "NiGHTS Track"; - width = 8; - height = 4096; - sprite = "UNKNA0"; - - 1700 - { - title = "Axis"; - sprite = "internal:axis1"; - circle = 1; - } - 1701 - { - title = "Axis Transfer"; - sprite = "internal:axis2"; - } - 1702 - { - title = "Axis Transfer Line"; - sprite = "internal:axis3"; - } - 1710 - { - title = "Ideya Capture"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nights - { - color = 13; // Pink - title = "NiGHTS Items"; - width = 16; - height = 32; - - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - } - 1704 - { - arrow = 1; - title = "NiGHTS Bumper"; - sprite = "NBMPG3G7"; - width = 32; - height = 64; - } - 1705 - { - arrow = 1; - title = "Hoop (Generic)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1706 - { - title = "Blue Sphere"; - sprite = "SPHRA0"; - width = 16; - height = 24; - } - 1707 - { - title = "Super Paraloop"; - sprite = "NPRUA0"; - } - 1708 - { - title = "Drill Refill"; - sprite = "NPRUB0"; - } - 1709 - { - title = "Nightopian Helper"; - sprite = "NPRUC0"; - } - 1711 - { - title = "Extra Time"; - sprite = "NPRUD0"; - } - 1712 - { - title = "Link Freeze"; - sprite = "NPRUE0"; - } - 1713 - { - arrow = 1; - title = "Hoop (Customizable)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1714 - { - title = "Ideya Anchor Point"; - sprite = "internal:axis1"; - width = 8; - height = 16; - } - } - - mario - { - color = 6; // Brown - title = "Mario"; - - 1800 - { - title = "Coin"; - sprite = "COINA0"; - width = 16; - height = 24; - } - 1801 - { - arrow = 1; - title = "Goomba"; - sprite = "GOOMA0"; - width = 24; - height = 32; - } - 1802 - { - arrow = 1; - title = "Goomba (Blue)"; - sprite = "BGOMA0"; - width = 24; - height = 32; - } - 1803 - { - title = "Fire Flower"; - sprite = "FFWRB0"; - width = 16; - height = 32; - } - 1804 - { - title = "Koopa Shell"; - sprite = "SHLLA1"; - width = 16; - height = 20; - } - 1805 - { - title = "Puma (Jumping Fireball)"; - sprite = "PUMAA0"; - width = 8; - height = 16; - } - 1806 - { - title = "King Bowser"; - sprite = "KOOPA0"; - width = 16; - height = 48; - } - 1807 - { - title = "Axe"; - sprite = "MAXEA0"; - width = 8; - height = 16; - } - 1808 - { - title = "Bush (Short)"; - sprite = "MUS1A0"; - width = 16; - height = 32; - } - 1809 - { - title = "Bush (Tall)"; - sprite = "MUS2A0"; - width = 16; - height = 32; - } - 1810 - { - title = "Toad"; - sprite = "TOADA0"; - width = 8; - height = 32; - } - } - - christmasdisco - { - color = 10; // Green - title = "Christmas & Disco"; - - 1850 - { - title = "Christmas Pole"; - sprite = "XMS1A0"; - width = 16; - height = 40; - } - 1851 - { - title = "Candy Cane"; - sprite = "XMS2A0"; - width = 8; - height = 32; - } - 1852 - { - blocking = 2; - title = "Snowman"; - sprite = "XMS3A0"; - width = 16; - height = 64; - } - 1853 - { - blocking = 2; - title = "Snowman (With Hat)"; - sprite = "XMS3B0"; - width = 16; - height = 80; - } - 1854 - { - title = "Lamp Post"; - sprite = "XMS4A0"; - width = 8; - height = 120; - } - 1855 - { - title = "Lamp Post (Snow)"; - sprite = "XMS4B0"; - width = 8; - height = 120; - } - 1856 - { - title = "Hanging Star"; - sprite = "XMS5A0"; - width = 4; - height = 80; - hangs = 1; - } - 1857 - { - title = "Berry Bush (Snow)"; - sprite = "BUS1B0"; - width = 16; - height = 32; - } - 1858 - { - title = "Bush (Snow)"; - sprite = "BUS2B0"; - width = 16; - height = 32; - } - 1859 - { - title = "Blueberry Bush (Snow)"; - sprite = "BUS3B0"; - width = 16; - height = 32; - } - 1875 - { - title = "Disco Ball"; - sprite = "DBALA0"; - width = 16; - height = 54; - hangs = 1; - } - 1876 - { - arrow = 1; - blocking = 2; - title = "Eggman Disco Statue"; - sprite = "ESTAB1"; - width = 20; - height = 96; - } - } - - stalagmites - { - color = 10; // Green - title = "Stalagmites"; - width = 16; - height = 40; - - 1900 - { - title = "Brown Stalagmite (Tall)"; - sprite = "STLGA0"; - width = 16; - height = 40; - } - 1901 - { - title = "Brown Stalagmite"; - sprite = "STLGB0"; - width = 16; - height = 40; - } - 1902 - { - title = "Orange Stalagmite (Tall)"; - sprite = "STLGC0"; - width = 16; - height = 40; - } - 1903 - { - title = "Orange Stalagmite"; - sprite = "STLGD0"; - width = 16; - height = 40; - } - 1904 - { - title = "Red Stalagmite (Tall)"; - sprite = "STLGE0"; - width = 16; - height = 40; - } - 1905 - { - title = "Red Stalagmite"; - sprite = "STLGF0"; - width = 16; - height = 40; - } - 1906 - { - title = "Gray Stalagmite (Tall)"; - sprite = "STLGG0"; - width = 24; - height = 96; - } - 1907 - { - title = "Gray Stalagmite"; - sprite = "STLGH0"; - width = 16; - height = 40; - } - 1908 - { - title = "Blue Stalagmite (Tall)"; - sprite = "STLGI0"; - width = 16; - height = 40; - } - 1909 - { - title = "Blue Stalagmite"; - sprite = "STLGJ0"; - width = 16; - height = 40; - } - } - - hauntedheights - { - color = 10; // Green - title = "Haunted Heights"; - - 2000 - { - title = "Smashing Spikeball"; - sprite = "FMCEA0"; - width = 18; - height = 28; - } - 2001 - { - title = "HHZ Grass"; - sprite = "HHZMA0"; - width = 16; - height = 40; - } - 2002 - { - title = "HHZ Tentacle 1"; - sprite = "HHZMB0"; - width = 16; - height = 40; - } - 2003 - { - title = "HHZ Tentacle 2"; - sprite = "HHZMC0"; - width = 16; - height = 40; - } - 2004 - { - title = "HHZ Stalagmite (Tall)"; - sprite = "HHZME0"; - width = 16; - height = 40; - } - 2005 - { - title = "HHZ Stalagmite (Short)"; - sprite = "HHZMF0"; - width = 16; - height = 40; - } - 2006 - { - title = "Jack-o'-lantern 1"; - sprite = "PUMKA0"; - width = 16; - height = 40; - } - 2007 - { - title = "Jack-o'-lantern 2"; - sprite = "PUMKB0"; - width = 16; - height = 40; - } - 2008 - { - title = "Jack-o'-lantern 3"; - sprite = "PUMKC0"; - width = 16; - height = 40; - } - 2009 - { - title = "Purple Mushroom"; - sprite = "SHRMD0"; - width = 16; - height = 48; - } - 2010 - { - title = "HHZ Tree"; - sprite = "HHPLC0"; - width = 12; - height = 40; - } - } - - frozenhillside - { - color = 10; // Green - title = "Frozen Hillside"; - - 2100 - { - title = "Ice Shard (Small)"; - sprite = "FHZIA0"; - width = 8; - height = 32; - } - 2101 - { - title = "Ice Shard (Large)"; - sprite = "FHZIB0"; - width = 8; - height = 32; - } - 2102 - { - title = "Crystal Tree (Aqua)"; - sprite = "TRE3A0"; - width = 20; - height = 200; - } - 2103 - { - title = "Crystal Tree (Pink)"; - sprite = "TRE3B0"; - width = 20; - height = 200; - } - 2104 - { - title = "Amy Cameo"; - sprite = "ROSYA1"; - width = 16; - height = 48; - } - 2105 - { - title = "Mistletoe"; - sprite = "XMS6A0"; - width = 52; - height = 106; - } - } - - tutorial - { - color = 10; // Green - title = "Tutorial"; - - 799 - { - title = "Tutorial Plant"; - sprite = "TUPFH0"; - width = 40; - height = 144; - } - } - - flickies - { - color = 10; // Green - title = "Flickies"; - width = 8; - height = 20; - - 2200 - { - title = "Bluebird"; - sprite = "FL01A1"; - } - 2201 - { - title = "Rabbit"; - sprite = "FL02A1"; - } - 2202 - { - title = "Chicken"; - sprite = "FL03A1"; - } - 2203 - { - title = "Seal"; - sprite = "FL04A1"; - } - 2204 - { - title = "Pig"; - sprite = "FL05A1"; - } - 2205 - { - title = "Chipmunk"; - sprite = "FL06A1"; - } - 2206 - { - title = "Penguin"; - sprite = "FL07A1"; - } - 2207 - { - title = "Fish"; - sprite = "FL08A1"; - } - 2208 - { - title = "Ram"; - sprite = "FL09A1"; - } - 2209 - { - title = "Puffin"; - sprite = "FL10A1"; - } - 2210 - { - title = "Cow"; - sprite = "FL11A1"; - } - 2211 - { - title = "Rat"; - sprite = "FL12A1"; - } - 2212 - { - title = "Bear"; - sprite = "FL13A1"; - } - 2213 - { - title = "Dove"; - sprite = "FL14A1"; - } - 2214 - { - title = "Cat"; - sprite = "FL15A1"; - } - 2215 - { - title = "Canary"; - sprite = "FL16A1"; - } - 2216 - { - title = "Spider"; - sprite = "FS01A1"; - } - 2217 - { - title = "Bat"; - sprite = "FS02A0"; - } - } -} - udmf { - editor - { - color = 15; // White - arrow = 1; - title = ""; - error = -1; - width = 8; - height = 16; - sort = 1; - - 3328 = "3D Mode Start"; - } starts { @@ -3974,7 +807,7 @@ udmf bosses { - color = 8; // Dark_Gray + color = 4; // Dark Red arrow = 1; title = "Bosses"; @@ -4355,95 +1188,185 @@ udmf width = 24; height = 24; sprite = "RINGA0"; - arg0 - { - title = "Float?"; - type = 11; - enum = "yesno"; - } 300 { title = "Ring"; sprite = "RINGA0"; width = 16; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 301 { title = "Bounce Ring"; - sprite = "internal:RNGBA0"; + sprite = "RNGBA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 302 { title = "Rail Ring"; - sprite = "internal:RNGRA0"; + sprite = "RNGRA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 303 { title = "Infinity Ring"; - sprite = "internal:RNGIA0"; + sprite = "RNGIA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 304 { title = "Automatic Ring"; - sprite = "internal:RNGAA0"; + sprite = "RNGAA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 305 { title = "Explosion Ring"; - sprite = "internal:RNGEA0"; + sprite = "RNGEA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 306 { title = "Scatter Ring"; - sprite = "internal:RNGSA0"; + sprite = "RNGSA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 307 { title = "Grenade Ring"; - sprite = "internal:RNGGA0"; + sprite = "RNGGA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 308 { title = "CTF Team Ring (Red)"; - sprite = "internal:RRNGA0"; + sprite = "internal:TRNGA0R"; width = 16; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 309 { title = "CTF Team Ring (Blue)"; - sprite = "internal:BRNGA0"; + sprite = "internal:TRNGA0B"; width = 16; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 330 { title = "Bounce Ring Panel"; - sprite = "internal:PIKBA0"; + sprite = "PIKBA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 331 { title = "Rail Ring Panel"; - sprite = "internal:PIKRA0"; + sprite = "PIKRA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 332 { title = "Automatic Ring Panel"; - sprite = "internal:PIKAA0"; + sprite = "PIKAA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 333 { title = "Explosion Ring Panel"; - sprite = "internal:PIKEA0"; + sprite = "PIKEA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 334 { title = "Scatter Ring Panel"; - sprite = "internal:PIKSA0"; + sprite = "PIKSA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 335 { title = "Grenade Ring Panel"; - sprite = "internal:PIKGA0"; + sprite = "PIKGA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } } @@ -4546,7 +1469,7 @@ udmf sprite = "EMBMA0"; width = 16; height = 30; - arg0 + arg1 { title = "Float?"; type = 11; @@ -4562,16 +1485,16 @@ udmf title = "Monitors"; width = 18; height = 40; - arg0 - { - title = "Death trigger tag"; - type = 15; - } 400 { title = "Super Ring (10 Rings)"; sprite = "TVRIA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4583,6 +1506,11 @@ udmf { title = "Pity Shield"; sprite = "TVPIA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4594,6 +1522,11 @@ udmf { title = "Attraction Shield"; sprite = "TVATA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4605,6 +1538,11 @@ udmf { title = "Force Shield"; sprite = "TVFOA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4616,6 +1554,11 @@ udmf { title = "Armageddon Shield"; sprite = "TVARA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4627,6 +1570,11 @@ udmf { title = "Whirlwind Shield"; sprite = "TVWWA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4638,6 +1586,11 @@ udmf { title = "Elemental Shield"; sprite = "TVELA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4649,6 +1602,11 @@ udmf { title = "Super Sneakers"; sprite = "TVSSA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4660,6 +1618,11 @@ udmf { title = "Invincibility"; sprite = "TVIVA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4671,6 +1634,11 @@ udmf { title = "Extra Life"; sprite = "TV1UA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4692,11 +1660,21 @@ udmf { title = "Eggman"; sprite = "TVEGA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 411 { title = "Teleporter"; sprite = "TVMXA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4708,21 +1686,41 @@ udmf { title = "Gravity Boots"; sprite = "TVGVA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 414 { title = "CTF Team Ring Monitor (Red)"; sprite = "TRRIA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 415 { title = "CTF Team Ring Monitor (Blue)"; sprite = "TBRIA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 416 { title = "Recycler"; sprite = "TVRCA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4734,16 +1732,31 @@ udmf { title = "Score (1,000 Points)"; sprite = "TV1KA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 419 { title = "Score (10,000 Points)"; sprite = "TVTKA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 420 { title = "Flame Shield"; sprite = "TVFLA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4755,6 +1768,11 @@ udmf { title = "Water Shield"; sprite = "TVBBA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4766,6 +1784,11 @@ udmf { title = "Lightning Shield"; sprite = "TVZPA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4782,76 +1805,136 @@ udmf title = "Monitors (Respawning)"; width = 20; height = 44; - arg0 - { - title = "Death trigger tag"; - type = 15; - } 431 { title = "Pity Shield (Respawn)"; sprite = "TVPIB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 432 { title = "Attraction Shield (Respawn)"; sprite = "TVATB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 433 { title = "Force Shield (Respawn)"; sprite = "TVFOB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 434 { title = "Armageddon Shield (Respawn)"; sprite = "TVARB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 435 { title = "Whirlwind Shield (Respawn)"; sprite = "TVWWB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 436 { title = "Elemental Shield (Respawn)"; sprite = "TVELB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 437 { title = "Super Sneakers (Respawn)"; sprite = "TVSSB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 438 { title = "Invincibility (Respawn)"; sprite = "TVIVB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 440 { title = "Eggman (Respawn)"; sprite = "TVEGB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 443 { title = "Gravity Boots (Respawn)"; sprite = "TVGVB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 450 { title = "Flame Shield (Respawn)"; sprite = "TVFLB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 451 { title = "Water Shield (Respawn)"; sprite = "TVBBB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 452 { title = "Lightning Shield (Respawn)"; sprite = "TVZPB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } } @@ -5235,13 +2318,13 @@ udmf { arrow = 0; title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; + sprite = "internal:ringverticalyellow"; } 601 { arrow = 0; title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; + sprite = "internal:ringverticalred"; height = 1024; } 602 @@ -5259,41 +2342,47 @@ udmf 604 { title = "Circle of Rings"; - sprite = "RINGA0"; + sprite = "internal:circlering"; width = 96; height = 192; + centerhitbox = true; } 605 { title = "Circle of Rings (Big)"; - sprite = "RINGA0"; + sprite = "internal:circlebigring"; width = 192; + centerhitbox = true; } 606 { title = "Circle of Blue Spheres"; - sprite = "SPHRA0"; + sprite = "internal:circlesphere"; width = 96; height = 192; + centerhitbox = true; } 607 { title = "Circle of Blue Spheres (Big)"; - sprite = "SPHRA0"; + sprite = "internal:circlebigsphere"; width = 192; + centerhitbox = true; } 608 { title = "Circle of Rings and Spheres"; - sprite = "SPHRA0"; + sprite = "internal:circleringsphere"; width = 96; height = 192; + centerhitbox = true; } 609 { title = "Circle of Rings and Spheres (Big)"; - sprite = "SPHRA0"; + sprite = "internal:circlebigringsphere"; width = 192; + centerhitbox = true; } 610 { @@ -5322,6 +2411,7 @@ udmf sprite = "RINGA0"; width = 96; height = 192; + centerhitbox = true; arg0 { title = "Number of items"; @@ -5429,7 +2519,7 @@ udmf 756 { title = "Blast Linedef Executor"; - sprite = "TOADA0"; + sprite = "internal:blastexec"; width = 32; height = 16; arg0 @@ -5441,7 +2531,7 @@ udmf 757 { title = "Fan Particle Generator"; - sprite = "PRTLA0"; + sprite = "internal:fanparticles"; width = 8; height = 16; arg0 @@ -5490,11 +2580,6 @@ udmf title = "PolyObject Spawn Point"; sprite = "internal:polycenter"; } - 762 - { - title = "PolyObject Spawn Point (Crush)"; - sprite = "internal:polycentercrush"; - } 780 { title = "Skybox View Point"; @@ -5514,7 +2599,7 @@ udmf greenflower { - color = 10; // Green + color = 2; // Green title = "Greenflower"; 800 @@ -5619,7 +2704,7 @@ udmf technohill { - color = 10; // Green + color = 2; // Green title = "Techno Hill"; 900 @@ -5663,7 +2748,7 @@ udmf deepsea { - color = 10; // Green + color = 2; // Green title = "Deep Sea"; 1000 @@ -5823,7 +2908,7 @@ udmf castleeggman { - color = 10; // Green + color = 2; // Green title = "Castle Eggman"; 1100 @@ -6386,7 +3471,7 @@ udmf aridcanyon { - color = 10; // Green + color = 2; // Green title = "Arid Canyon"; 1200 @@ -6511,6 +3596,7 @@ udmf sprite = "WWSGAR"; width = 22; height = 64; + wallsprite = true; } 1213 { @@ -6518,6 +3604,7 @@ udmf sprite = "WWS2AR"; width = 22; height = 64; + wallsprite = true; } 1214 { @@ -6525,6 +3612,7 @@ udmf sprite = "WWS3ALAR"; width = 16; height = 192; + wallsprite = true; } 1215 { @@ -6644,7 +3732,7 @@ udmf redvolcano { - color = 10; // Green + color = 2; // Green title = "Red Volcano"; 1300 @@ -6789,7 +3877,7 @@ udmf botanicserenity { - color = 10; // Green + color = 2; // Green title = "Botanic Serenity"; width = 16; height = 32; @@ -7032,7 +4120,7 @@ udmf azuretemple { - color = 10; // Green + color = 2; // Green title = "Azure Temple"; 1500 @@ -7144,7 +4232,7 @@ udmf dreamhill { - color = 10; // Green + color = 2; // Green title = "Dream Hill"; 1600 @@ -7178,8 +4266,8 @@ udmf nightstrk { - color = 13; // Pink - title = "NiGHTS Track"; + color = 16; // Light Pink + title = "NiGHTS Track & Misc."; width = 8; height = 4096; sprite = "UNKNA0"; @@ -7207,8 +4295,8 @@ udmf type = 11; enum { - 0 = "Clockwise"; - 1 = "Counterclockwise"; + 0 = "Counterclockwise"; + 1 = "Clockwise"; } } } @@ -7238,30 +4326,6 @@ udmf title = "Order"; } } - 1710 - { - title = "Ideya Capture"; - sprite = "CAPSA0"; - width = 72; - height = 144; - arg0 - { - title = "Mare"; - } - arg1 - { - title = "Required spheres"; - } - } - } - - nights - { - color = 13; // Pink - title = "NiGHTS Items"; - width = 16; - height = 32; - 1703 { title = "Ideya Drone"; @@ -7299,6 +4363,41 @@ udmf enum = "noyes"; } } + 1710 + { + title = "Ideya Capture"; + sprite = "CAPSA0"; + width = 72; + height = 144; + arg0 + { + title = "Mare"; + } + arg1 + { + title = "Required spheres"; + } + } + 1714 + { + title = "Ideya Anchor Point"; + sprite = "internal:ideya"; + width = 8; + height = 16; + arg0 + { + title = "Mare"; + } + } + } + + nights + { + color = 13; // Pink + title = "NiGHTS Items"; + width = 16; + height = 32; + 1704 { arrow = 1; @@ -7399,25 +4498,15 @@ udmf { arrow = 1; title = "Hoop"; - sprite = "HOOPA0"; + sprite = "internal:nightshoop"; width = 80; height = 160; + centerhitbox = true; arg0 { title = "Radius"; } } - 1714 - { - title = "Ideya Anchor Point"; - sprite = "internal:axis1"; - width = 8; - height = 16; - arg0 - { - title = "Mare"; - } - } } mario @@ -7528,7 +4617,7 @@ udmf christmasdisco { - color = 10; // Green + color = 2; // Green title = "Christmas & Disco"; 1850 @@ -7643,7 +4732,7 @@ udmf stalagmites { - color = 10; // Green + color = 2; // Green title = "Stalagmites"; width = 16; height = 40; @@ -7722,7 +4811,7 @@ udmf hauntedheights { - color = 10; // Green + color = 2; // Green title = "Haunted Heights"; 2000 @@ -7828,7 +4917,7 @@ udmf frozenhillside { - color = 10; // Green + color = 2; // Green title = "Frozen Hillside"; 2100 @@ -7883,7 +4972,7 @@ udmf tutorial { - color = 10; // Green + color = 2; // Green title = "Tutorial"; 799 @@ -7901,65 +4990,170 @@ udmf flickies { - color = 10; // Green + color = 2; // Green title = "Flickies"; width = 8; height = 20; - arg0 - { - title = "Radius"; - } - arg1 - { - title = "Flags"; - type = 12; - enum - { - 1 = "Move aimlessly"; - 2 = "No movement"; - 4 = "Hop"; - } - } 2200 { title = "Bluebird"; sprite = "FL01A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2201 { title = "Rabbit"; sprite = "FL02A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2202 { title = "Chicken"; sprite = "FL03A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2203 { title = "Seal"; sprite = "FL04A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2204 { title = "Pig"; sprite = "FL05A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2205 { title = "Chipmunk"; sprite = "FL06A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2206 { title = "Penguin"; sprite = "FL07A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2207 { title = "Fish"; sprite = "FL08A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } arg2 { title = "Color"; @@ -7989,51 +5183,214 @@ udmf { title = "Ram"; sprite = "FL09A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2209 { title = "Puffin"; sprite = "FL10A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2210 { title = "Cow"; sprite = "FL11A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2211 { title = "Rat"; sprite = "FL12A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2212 { title = "Bear"; sprite = "FL13A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2213 { title = "Dove"; sprite = "FL14A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2214 { title = "Cat"; sprite = "FL15A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2215 { title = "Canary"; sprite = "FL16A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2216 { title = "Spider"; sprite = "FS01A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2217 { title = "Bat"; sprite = "FS02A0"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } } -} + + editor + { + color = 15; // White + arrow = 1; + title = "3D Mode Start"; + error = -1; + width = 8; + height = 16; + sort = 1; + + 3328 = "3D Mode Start"; + } +} \ No newline at end of file diff --git a/extras/conf/udb/SRB2_22Doom.cfg b/extras/conf/udb/SRB2_22Doom.cfg deleted file mode 100644 index 9e733aa39..000000000 --- a/extras/conf/udb/SRB2_22Doom.cfg +++ /dev/null @@ -1,32 +0,0 @@ -/************************************************************************\ - Ultimate Doom Builder Game Configuration for Sonic Robo Blast 2 Version 2.2 -\************************************************************************/ - -// This is required to prevent accidental use of a different configuration -type = "Doom Builder 2 Game Configuration"; - -// This is the title to show for this game -game = "Sonic Robo Blast 2 - 2.2 (Doom format)"; - -// This is the simplified game engine/sourceport name -engine = "zdoom"; - -// Settings common to all games and all map formats -include("Includes\\SRB222_common.cfg", "common"); - -// Settings common to Doom map format -include("Includes\\SRB222_common.cfg", "mapformat_doom"); - -include("Includes\\Game_SRB222.cfg"); - -// Script lumps detection -scriptlumpnames -{ - include("Includes\\SRB222_misc.cfg", "scriptlumpnames"); -} - -//Default things filters -thingsfilters -{ - include("Includes\\SRB222_misc.cfg", "thingsfilters"); -} \ No newline at end of file diff --git a/libs/libpng-src/projects/visualc10/libpng.vcxproj b/libs/libpng-src/projects/visualc10/libpng.vcxproj index eaa3d4ffb..351b4317d 100644 --- a/libs/libpng-src/projects/visualc10/libpng.vcxproj +++ b/libs/libpng-src/projects/visualc10/libpng.vcxproj @@ -37,51 +37,51 @@ {72B01ACA-7A1A-4F7B-ACEF-2607299CF052} libpng - 10.0.16299.0 + 10.0 StaticLibrary false - v140 + v143 StaticLibrary false - v141 + v143 true StaticLibrary false - v140 + v143 StaticLibrary false - v141 + v143 true StaticLibrary false - v140 + v143 StaticLibrary false - v141 + v143 true StaticLibrary false - v140 + v143 StaticLibrary false - v141 + v143 true @@ -278,7 +278,7 @@ Disabled ..\..;..\..\..\zlib;%(AdditionalIncludeDirectories) WIN32;_DEBUG;DEBUG;PNG_DEBUG=1;PNG_USE_PNGVCRD;PNG_LIBPNG_SPECIALBUILD;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true + false EnableFastChecks MultiThreadedDebugDLL $(ProjectDir)$(Platform)\$(Configuration)\ @@ -288,7 +288,7 @@ true EditAndContinue CompileAsC - false + true _DEBUG;%(PreprocessorDefinitions) diff --git a/libs/zlib/projects/visualc10/zlib.vcxproj b/libs/zlib/projects/visualc10/zlib.vcxproj index de7b2aaab..5c00ea4a9 100644 --- a/libs/zlib/projects/visualc10/zlib.vcxproj +++ b/libs/zlib/projects/visualc10/zlib.vcxproj @@ -37,51 +37,51 @@ {73A5729C-7323-41D4-AB48-8A03C9F81603} zlib - 10.0.16299.0 + 10.0 StaticLibrary false - v140 + v143 StaticLibrary false - v141 + v143 true StaticLibrary false - v140 + v143 StaticLibrary false - v141 + v143 true StaticLibrary false - v140 + v143 true StaticLibrary false - v141 + v143 StaticLibrary false - v140 + v143 StaticLibrary false - v141 + v143 true @@ -144,7 +144,7 @@ Disabled WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true + false Default MultiThreadedDebugDLL $(ProjectDir)$(Platform)\$(Configuration)\ @@ -154,7 +154,7 @@ true EditAndContinue CompileAsC - false + true _DEBUG;%(PreprocessorDefinitions) diff --git a/srb2-vc9.sln b/srb2-vc9.sln deleted file mode 100644 index bbfcf0e77..000000000 --- a/srb2-vc9.sln +++ /dev/null @@ -1,89 +0,0 @@ -๏ปฟ -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual C++ Express 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Srb2win", "src\win32\Srb2win-vc9.vcproj", "{0F554F1D-ED49-4D65-A9A7-F63C57F277BE}" - ProjectSection(ProjectDependencies) = postProject - {73A5729C-7323-41D4-AB48-8A03C9F81603} = {73A5729C-7323-41D4-AB48-8A03C9F81603} - {72B01ACA-7A1A-4F7B-ACEF-2607299CF052} = {72B01ACA-7A1A-4F7B-ACEF-2607299CF052} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "libs\libpng-src\projects\visualc9\libpng.vcproj", "{72B01ACA-7A1A-4F7B-ACEF-2607299CF052}" - ProjectSection(ProjectDependencies) = postProject - {73A5729C-7323-41D4-AB48-8A03C9F81603} = {73A5729C-7323-41D4-AB48-8A03C9F81603} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "r_opengl", "src\hardware\r_opengl\r_opengl-vc9.vcproj", "{51137D5C-4E81-4955-AACF-EA3092006051}" - ProjectSection(ProjectDependencies) = postProject - {0F554F1D-ED49-4D65-A9A7-F63C57F277BE} = {0F554F1D-ED49-4D65-A9A7-F63C57F277BE} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "libs\zlib\projects\visualc9\zlib.vcproj", "{73A5729C-7323-41D4-AB48-8A03C9F81603}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "s_openal", "src\hardware\s_openal\s_openal-vc9.vcproj", "{E662D0B3-412D-4D55-A5EC-8CBD680DDCBE}" - ProjectSection(ProjectDependencies) = postProject - {0F554F1D-ED49-4D65-A9A7-F63C57F277BE} = {0F554F1D-ED49-4D65-A9A7-F63C57F277BE} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Srb2SDL", "src\sdl\Srb2SDL-vc9.vcproj", "{61BA7D3C-F77D-4D31-B718-1177FE482CF2}" - ProjectSection(ProjectDependencies) = postProject - {73A5729C-7323-41D4-AB48-8A03C9F81603} = {73A5729C-7323-41D4-AB48-8A03C9F81603} - {72B01ACA-7A1A-4F7B-ACEF-2607299CF052} = {72B01ACA-7A1A-4F7B-ACEF-2607299CF052} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0F554F1D-ED49-4D65-A9A7-F63C57F277BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {0F554F1D-ED49-4D65-A9A7-F63C57F277BE}.Debug|Win32.Build.0 = Debug|Win32 - {0F554F1D-ED49-4D65-A9A7-F63C57F277BE}.Debug|x64.ActiveCfg = Debug|x64 - {0F554F1D-ED49-4D65-A9A7-F63C57F277BE}.Debug|x64.Build.0 = Debug|x64 - {0F554F1D-ED49-4D65-A9A7-F63C57F277BE}.Release|Win32.ActiveCfg = Release|Win32 - {0F554F1D-ED49-4D65-A9A7-F63C57F277BE}.Release|Win32.Build.0 = Release|Win32 - {0F554F1D-ED49-4D65-A9A7-F63C57F277BE}.Release|x64.ActiveCfg = Release|x64 - {0F554F1D-ED49-4D65-A9A7-F63C57F277BE}.Release|x64.Build.0 = Release|x64 - {72B01ACA-7A1A-4F7B-ACEF-2607299CF052}.Debug|Win32.ActiveCfg = Debug|Win32 - {72B01ACA-7A1A-4F7B-ACEF-2607299CF052}.Debug|Win32.Build.0 = Debug|Win32 - {72B01ACA-7A1A-4F7B-ACEF-2607299CF052}.Debug|x64.ActiveCfg = Debug|x64 - {72B01ACA-7A1A-4F7B-ACEF-2607299CF052}.Debug|x64.Build.0 = Debug|x64 - {72B01ACA-7A1A-4F7B-ACEF-2607299CF052}.Release|Win32.ActiveCfg = Release|Win32 - {72B01ACA-7A1A-4F7B-ACEF-2607299CF052}.Release|Win32.Build.0 = Release|Win32 - {72B01ACA-7A1A-4F7B-ACEF-2607299CF052}.Release|x64.ActiveCfg = Release|x64 - {72B01ACA-7A1A-4F7B-ACEF-2607299CF052}.Release|x64.Build.0 = Release|x64 - {51137D5C-4E81-4955-AACF-EA3092006051}.Debug|Win32.ActiveCfg = Debug|Win32 - {51137D5C-4E81-4955-AACF-EA3092006051}.Debug|Win32.Build.0 = Debug|Win32 - {51137D5C-4E81-4955-AACF-EA3092006051}.Debug|x64.ActiveCfg = Debug|x64 - {51137D5C-4E81-4955-AACF-EA3092006051}.Debug|x64.Build.0 = Debug|x64 - {51137D5C-4E81-4955-AACF-EA3092006051}.Release|Win32.ActiveCfg = Release|Win32 - {51137D5C-4E81-4955-AACF-EA3092006051}.Release|Win32.Build.0 = Release|Win32 - {51137D5C-4E81-4955-AACF-EA3092006051}.Release|x64.ActiveCfg = Release|x64 - {51137D5C-4E81-4955-AACF-EA3092006051}.Release|x64.Build.0 = Release|x64 - {73A5729C-7323-41D4-AB48-8A03C9F81603}.Debug|Win32.ActiveCfg = Debug|Win32 - {73A5729C-7323-41D4-AB48-8A03C9F81603}.Debug|Win32.Build.0 = Debug|Win32 - {73A5729C-7323-41D4-AB48-8A03C9F81603}.Debug|x64.ActiveCfg = Debug|x64 - {73A5729C-7323-41D4-AB48-8A03C9F81603}.Debug|x64.Build.0 = Debug|x64 - {73A5729C-7323-41D4-AB48-8A03C9F81603}.Release|Win32.ActiveCfg = Release|Win32 - {73A5729C-7323-41D4-AB48-8A03C9F81603}.Release|Win32.Build.0 = Release|Win32 - {73A5729C-7323-41D4-AB48-8A03C9F81603}.Release|x64.ActiveCfg = Release|x64 - {73A5729C-7323-41D4-AB48-8A03C9F81603}.Release|x64.Build.0 = Release|x64 - {E662D0B3-412D-4D55-A5EC-8CBD680DDCBE}.Debug|Win32.ActiveCfg = Debug|Win32 - {E662D0B3-412D-4D55-A5EC-8CBD680DDCBE}.Debug|x64.ActiveCfg = Debug|x64 - {E662D0B3-412D-4D55-A5EC-8CBD680DDCBE}.Release|Win32.ActiveCfg = Release|Win32 - {E662D0B3-412D-4D55-A5EC-8CBD680DDCBE}.Release|x64.ActiveCfg = Release|x64 - {61BA7D3C-F77D-4D31-B718-1177FE482CF2}.Debug|Win32.ActiveCfg = Debug|Win32 - {61BA7D3C-F77D-4D31-B718-1177FE482CF2}.Debug|Win32.Build.0 = Debug|Win32 - {61BA7D3C-F77D-4D31-B718-1177FE482CF2}.Debug|x64.ActiveCfg = Debug|x64 - {61BA7D3C-F77D-4D31-B718-1177FE482CF2}.Debug|x64.Build.0 = Debug|x64 - {61BA7D3C-F77D-4D31-B718-1177FE482CF2}.Release|Win32.ActiveCfg = Release|Win32 - {61BA7D3C-F77D-4D31-B718-1177FE482CF2}.Release|Win32.Build.0 = Release|Win32 - {61BA7D3C-F77D-4D31-B718-1177FE482CF2}.Release|x64.ActiveCfg = Release|x64 - {61BA7D3C-F77D-4D31-B718-1177FE482CF2}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6fe260fb4..2f4467a32 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -127,7 +127,9 @@ endif() # Compatibility flag with later versions of GCC # We should really fix our code to not need this if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - target_compile_options(SRB2SDL2 PRIVATE -mno-ms-bitfields) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|x64|amd64|AMD64|em64t|EM64T)") + target_compile_options(SRB2SDL2 PRIVATE -mno-ms-bitfields) + endif() endif() # Compiler warnings configuration diff --git a/src/Makefile b/src/Makefile index 7571c8089..36b1a7efa 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,8 +2,8 @@ # the poly3 Makefile adapted over and over... # # Copyright 1998-2000 DooM Legacy Team. -# Copyright 2020-2022 James R. -# Copyright 2003-2022 Sonic Team Junior. +# Copyright 2020-2023 James R. +# Copyright 2003-2023 Sonic Team Junior. # # This program is free software distributed under the # terms of the GNU General Public License, version 2. diff --git a/src/am_map.c b/src/am_map.c index 65a57c09e..331d1a5e0 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/am_map.h b/src/am_map.h index 89c4ad9fa..a202bece1 100644 --- a/src/am_map.h +++ b/src/am_map.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/android/i_system.c b/src/android/i_system.c index f0edcc17e..ff8b88de5 100644 --- a/src/android/i_system.c +++ b/src/android/i_system.c @@ -24,7 +24,7 @@ static INT64 start_time; // as microseconds since the epoch // I should probably return how much memory is remaining // for this process, considering Android's process memory limit. -UINT32 I_GetFreeMem(UINT32 *total) +size_t I_GetFreeMem(size_t *total) { // what the heck? sysinfo() is partially missing in bionic? /* struct sysinfo si; */ diff --git a/src/apng.c b/src/apng.c index f4c08d979..11d3ab9f5 100644 --- a/src/apng.c +++ b/src/apng.c @@ -1,5 +1,5 @@ /* -Copyright 2019-2022, James R. +Copyright 2019-2023, James R. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/apng.h b/src/apng.h index 6b9347424..ed30549e2 100644 --- a/src/apng.h +++ b/src/apng.h @@ -1,5 +1,5 @@ /* -Copyright 2019-2022, James R. +Copyright 2019-2023, James R. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/asm_defs.inc b/src/asm_defs.inc index a8c60f19e..48f8da0d8 100644 --- a/src/asm_defs.inc +++ b/src/asm_defs.inc @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/b_bot.c b/src/b_bot.c index 6c1495c72..d1465f891 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2007-2016 by John "JTE" Muniz. -// Copyright (C) 2011-2022 by Sonic Team Junior. +// Copyright (C) 2011-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -118,7 +118,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) return; } - // Adapted from CobaltBW's tails_AI.wad + // Adapted from clairebun's tails_AI.wad // Check water if (water) @@ -188,6 +188,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) && !(pcmd->forwardmove || pcmd->sidemove || player->dashspeed) && P_IsObjectOnGround(sonic) && P_IsObjectOnGround(tails) && !(player->pflags & PF_STASIS) + && !(player->exiting) && bot->charability == CA_FLY) mem->thinkstate = AI_THINKFLY; else if (mem->thinkstate == AI_THINKFLY) diff --git a/src/b_bot.h b/src/b_bot.h index c29974c50..bbe0829be 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2007-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/blua/liolib.c b/src/blua/liolib.c index e029650c0..545f9c144 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -24,12 +24,14 @@ #include "../byteptr.h" #include "../lua_script.h" #include "../m_misc.h" +#include "../i_time.h" #define IO_INPUT 1 #define IO_OUTPUT 2 -#define FILELIMIT (1024 * 1024) // Size limit for reading/writing files +#define MAXBYTESPERMINUTE (10 * 1024 * 1024) // Rate limit for writing files +#define MAXOPENSPERMINUTE 50 // Rate limit for opening new files #define FMT_FILECALLBACKID "file_callback_%d" @@ -46,6 +48,10 @@ static const char *whitelist[] = { }; +static INT64 numwrittenbytes = 0; +static INT64 numopenedfiles = 0; + + static int pushresult (lua_State *L, int i, const char *filename) { int en = errno; /* calls to Lua API may change this value */ if (i) { @@ -252,6 +258,17 @@ static int io_openlocal (lua_State *L) { "Files can't be opened while being downloaded\n", filename); + // Reading not restricted + if (client && (strchr(mode, 'w') || strchr(mode, 'a') || strchr(mode, '+'))) + { + if (numopenedfiles >= (I_GetTime() / (60*TICRATE) + 1) * MAXOPENSPERMINUTE) + I_Error("Access denied to %s\n" + "File opening rate exceeded\n", + filename); + + numopenedfiles++; + } + MakePathDirs(realfilename); // Open and return the file @@ -527,9 +544,12 @@ static int g_write (lua_State *L, FILE *f, int arg) { else { size_t l; const char *s = luaL_checklstring(L, arg, &l); - if (ftell(f) + l > FILELIMIT) { - luaL_error(L,"write limit bypassed in file. Changes have been discarded."); - break; + if (client) { + if (numwrittenbytes + l > (I_GetTime() / (60*TICRATE) + 1) * MAXBYTESPERMINUTE) { + luaL_error(L,"file write rate limit exceeded; changes have been discarded"); + break; + } + numwrittenbytes += l; } status = status && (fwrite(s, sizeof(char), l, f) == l); } diff --git a/src/blua/lua.h b/src/blua/lua.h index 4e26c2a79..50e520690 100644 --- a/src/blua/lua.h +++ b/src/blua/lua.h @@ -12,6 +12,10 @@ #include #include +#ifdef _MSC_VER +#include +#endif + #include "luaconf.h" diff --git a/src/blua/luaconf.h b/src/blua/luaconf.h index 9e2948f41..223a85703 100644 --- a/src/blua/luaconf.h +++ b/src/blua/luaconf.h @@ -11,9 +11,7 @@ #include #include -#ifdef _MSC_VER -#define INT32 __int32 -#else +#ifndef _MSC_VER #include #define INT32 int32_t #endif @@ -147,7 +145,7 @@ ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most ** machines, ptrdiff_t gives a good choice between int or long.) */ -#define LUA_INTEGER INT32 +#define LUA_INTEGER int32_t /* @@ -509,13 +507,13 @@ */ //#define LUA_NUMBER_DOUBLE -#define LUA_NUMBER INT32 +#define LUA_NUMBER int32_t /* @@ LUAI_UACNUMBER is the result of an 'usual argument conversion' @* over a number. */ -#define LUAI_UACNUMBER INT32 +#define LUAI_UACNUMBER int32_t /* @@ -778,6 +776,4 @@ union luai_Cast { double l_d; long l_l; }; ** without modifying the main part of the file. */ - - #endif diff --git a/src/byteptr.h b/src/byteptr.h index 33c2c8a4b..8ab359c4c 100644 --- a/src/byteptr.h +++ b/src/byteptr.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -150,7 +150,7 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr) #undef DEALIGNED -#define WRITESTRINGN(p, s, n) ({ \ +#define WRITESTRINGN(p, s, n) { \ size_t tmp_i; \ \ for (tmp_i = 0; tmp_i < n && s[tmp_i] != '\0'; tmp_i++) \ @@ -158,70 +158,70 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr) \ if (tmp_i < n) \ WRITECHAR(p, '\0'); \ -}) +} -#define WRITESTRINGL(p, s, n) ({ \ +#define WRITESTRINGL(p, s, n) { \ size_t tmp_i; \ \ for (tmp_i = 0; tmp_i < n - 1 && s[tmp_i] != '\0'; tmp_i++) \ WRITECHAR(p, s[tmp_i]); \ \ WRITECHAR(p, '\0'); \ -}) +} -#define WRITESTRING(p, s) ({ \ +#define WRITESTRING(p, s) { \ size_t tmp_i; \ \ for (tmp_i = 0; s[tmp_i] != '\0'; tmp_i++) \ WRITECHAR(p, s[tmp_i]); \ \ WRITECHAR(p, '\0'); \ -}) +} -#define WRITEMEM(p, s, n) ({ \ +#define WRITEMEM(p, s, n) { \ memcpy(p, s, n); \ p += n; \ -}) +} #define SKIPSTRING(p) while (READCHAR(p) != '\0') -#define SKIPSTRINGN(p, n) ({ \ +#define SKIPSTRINGN(p, n) { \ size_t tmp_i = 0; \ \ while (tmp_i < n && READCHAR(p) != '\0') \ tmp_i++; \ -}) +} #define SKIPSTRINGL(p, n) SKIPSTRINGN(p, n) -#define READSTRINGN(p, s, n) ({ \ +#define READSTRINGN(p, s, n) { \ size_t tmp_i = 0; \ \ while (tmp_i < n && (s[tmp_i] = READCHAR(p)) != '\0') \ tmp_i++; \ \ s[tmp_i] = '\0'; \ -}) +} -#define READSTRINGL(p, s, n) ({ \ +#define READSTRINGL(p, s, n) { \ size_t tmp_i = 0; \ \ while (tmp_i < n - 1 && (s[tmp_i] = READCHAR(p)) != '\0') \ tmp_i++; \ \ s[tmp_i] = '\0'; \ -}) +} -#define READSTRING(p, s) ({ \ +#define READSTRING(p, s) { \ size_t tmp_i = 0; \ \ while ((s[tmp_i] = READCHAR(p)) != '\0') \ tmp_i++; \ \ s[tmp_i] = '\0'; \ -}) +} -#define READMEM(p, s, n) ({ \ +#define READMEM(p, s, n) { \ memcpy(s, p, n); \ p += n; \ -}) +} diff --git a/src/command.c b/src/command.c index c849341ff..a34d9694a 100644 --- a/src/command.c +++ b/src/command.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -34,6 +34,7 @@ #include "lua_script.h" #include "d_netfil.h" // findfile #include "r_data.h" // Color_cons_t +#include "d_main.h" // D_IsPathAllowed //======== // protos. @@ -57,6 +58,7 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr); static boolean CV_Command(void); consvar_t *CV_FindVar(const char *name); static const char *CV_StringValue(const char *var_name); +static boolean CV_Immutable(const consvar_t *var); static consvar_t *consvar_vars; // list of registered console variables static UINT16 consvar_number_of_netids = 0; @@ -108,6 +110,7 @@ static cmdalias_t *com_alias; // aliases list // ========================================================================= static vsbuf_t com_text; // variable sized buffer +static com_flags_t com_flags = 0; /** Purges control characters out of some text. * @@ -140,7 +143,7 @@ COM_Purge (char *s, int *np) * \param ptext The text to add. * \sa COM_BufInsertTextEx */ -void COM_BufAddTextEx(const char *ptext, int flags) +void COM_BufAddTextEx(const char *ptext, com_flags_t flags) { int l; char *text; @@ -163,7 +166,7 @@ void COM_BufAddTextEx(const char *ptext, int flags) * \param ptext The text to execute. A newline is automatically added. * \sa COM_BufAddTextEx */ -void COM_BufInsertTextEx(const char *ptext, int flags) +void COM_BufInsertTextEx(const char *ptext, com_flags_t flags) { const INT32 old_wait = com_wait; @@ -264,6 +267,8 @@ void COM_BufExecute(void) break; } } + + com_flags = 0; } /** Executes a string immediately. Used for skirting around WAIT commands. @@ -308,6 +313,7 @@ typedef struct xcommand_s const char *name; struct xcommand_s *next; com_func_t function; + com_flags_t flags; } xcommand_t; static xcommand_t *com_commands = NULL; // current commands @@ -317,7 +323,6 @@ static size_t com_argc; static char *com_argv[MAX_ARGS]; static const char *com_null_string = ""; static char *com_args = NULL; // current command args or NULL -static int com_flags; static void Got_NetVar(UINT8 **p, INT32 playernum); @@ -329,16 +334,16 @@ void COM_Init(void) VS_Alloc(&com_text, COM_BUF_SIZE); // add standard commands - COM_AddCommand("alias", COM_Alias_f); - COM_AddCommand("echo", COM_Echo_f); - COM_AddCommand("cecho", COM_CEcho_f); - COM_AddCommand("cechoflags", COM_CEchoFlags_f); - COM_AddCommand("cechoduration", COM_CEchoDuration_f); - COM_AddCommand("exec", COM_Exec_f); - COM_AddCommand("wait", COM_Wait_f); - COM_AddCommand("help", COM_Help_f); - COM_AddCommand("toggle", COM_Toggle_f); - COM_AddCommand("add", COM_Add_f); + COM_AddCommand("alias", COM_Alias_f, 0); + COM_AddCommand("echo", COM_Echo_f, COM_LUA); + COM_AddCommand("cecho", COM_CEcho_f, COM_LUA); + COM_AddCommand("cechoflags", COM_CEchoFlags_f, COM_LUA); + COM_AddCommand("cechoduration", COM_CEchoDuration_f, COM_LUA); + COM_AddCommand("exec", COM_Exec_f, 0); + COM_AddCommand("wait", COM_Wait_f, 0); + COM_AddCommand("help", COM_Help_f, COM_LUA); + COM_AddCommand("toggle", COM_Toggle_f, COM_LUA); + COM_AddCommand("add", COM_Add_f, COM_LUA); RegisterNetXCmd(XD_NETVAR, Got_NetVar); } @@ -440,7 +445,6 @@ static void COM_TokenizeString(char *ptext) com_argc = 0; com_args = NULL; - com_flags = 0; while (com_argc < MAX_ARGS) { @@ -478,7 +482,7 @@ static void COM_TokenizeString(char *ptext) * \param name Name of the command. * \param func Function called when the command is run. */ -void COM_AddCommand(const char *name, com_func_t func) +void COM_AddCommand(const char *name, com_func_t func, com_flags_t flags) { xcommand_t *cmd; @@ -508,6 +512,7 @@ void COM_AddCommand(const char *name, com_func_t func) cmd = ZZ_Alloc(sizeof *cmd); cmd->name = name; cmd->function = func; + cmd->flags = flags; cmd->next = com_commands; com_commands = cmd; } @@ -540,6 +545,7 @@ int COM_AddLuaCommand(const char *name) cmd = ZZ_Alloc(sizeof *cmd); cmd->name = name; cmd->function = COM_Lua_f; + cmd->flags = COM_LUA; cmd->next = com_commands; com_commands = cmd; return 0; @@ -635,6 +641,12 @@ static void COM_ExecuteString(char *ptext) { if (!stricmp(com_argv[0], cmd->name)) //case insensitive now that we have lower and uppercase! { + if ((com_flags & COM_LUA) && !(cmd->flags & COM_LUA)) + { + CONS_Alert(CONS_WARNING, "Command '%s' cannot be run from Lua.\n", cmd->name); + return; + } + cmd->function(); return; } @@ -770,6 +782,9 @@ static void COM_Exec_f(void) return; } + if (!D_CheckPathAllowed(COM_Argv(1), "tried to exec")) + return; + // load file // Try with Argv passed verbatim first, for back compat FIL_ReadFile(COM_Argv(1), &buf); @@ -794,8 +809,8 @@ static void COM_Exec_f(void) CONS_Printf(M_GetText("executing %s\n"), COM_Argv(1)); // insert text file into the command buffer - COM_BufAddText((char *)buf); - COM_BufAddText("\n"); + COM_BufAddTextEx((char *)buf, com_flags); + COM_BufAddTextEx("\n", com_flags); // free buffer Z_Free(buf); @@ -998,6 +1013,9 @@ static void COM_Toggle_f(void) return; } + if (CV_Immutable(cvar)) + return; + if (!(cvar->PossibleValue == CV_YesNo || cvar->PossibleValue == CV_OnOff)) { CONS_Alert(CONS_NOTICE, M_GetText("%s is not a boolean value\n"), COM_Argv(1)); @@ -1027,6 +1045,9 @@ static void COM_Add_f(void) return; } + if (CV_Immutable(cvar)) + return; + if (( cvar->flags & CV_FLOAT )) { float n =FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2)); @@ -1116,7 +1137,7 @@ void VS_Write(vsbuf_t *buf, const void *data, size_t length) M_Memcpy(VS_GetSpace(buf, length), data, length); } -void VS_WriteEx(vsbuf_t *buf, const void *data, size_t length, int flags) +void VS_WriteEx(vsbuf_t *buf, const void *data, size_t length, com_flags_t flags) { char *p; p = VS_GetSpace(buf, 2 + length); @@ -1725,9 +1746,13 @@ void CV_SaveVars(UINT8 **p, boolean in_demo) if ((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) { if (in_demo) + { WRITESTRING(*p, cvar->name); + } else + { WRITEUINT16(*p, cvar->netid); + } WRITESTRING(*p, cvar->string); WRITEUINT8(*p, false); ++count; @@ -2366,7 +2391,7 @@ static boolean CV_Command(void) if (!v) return false; - if (( com_flags & COM_SAFE ) && ( v->flags & CV_NOLUA )) + if (CV_Immutable(v)) { CONS_Alert(CONS_WARNING, "Variable '%s' cannot be changed from Lua.\n", v->name); return true; @@ -2455,6 +2480,22 @@ void CV_SaveVariables(FILE *f) } } +// Returns true if this cvar cannot be modified in current context. +// Such as if the cvar does not have CV_ALLOWLUA. +static boolean CV_Immutable(const consvar_t *var) +{ + // Currently operating from Lua + if (com_flags & COM_LUA) + { + if (!(var->flags & CV_ALLOWLUA)) + { + return true; + } + } + + return false; +} + //============================================================================ // SCRIPT PARSE //============================================================================ diff --git a/src/command.h b/src/command.h index 30d7e5bbe..69d1890d3 100644 --- a/src/command.h +++ b/src/command.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -20,23 +20,23 @@ // Command buffer & command execution //=================================== -/* Lua command registration flags. */ -enum +/* Command registration flags. */ +typedef enum { COM_ADMIN = 1, COM_SPLITSCREEN = 2, COM_LOCAL = 4, -}; -/* Command buffer flags. */ -enum -{ - COM_SAFE = 1, -}; + // COM_BufInsertText etc: can only access cvars + // with CV_ALLOWLUA set. + // COM_AddCommand: without this flag, the command + // CANNOT be run from Lua. + COM_LUA = 8, +} com_flags_t; typedef void (*com_func_t)(void); -void COM_AddCommand(const char *name, com_func_t func); +void COM_AddCommand(const char *name, com_func_t func, com_flags_t flags); int COM_AddLuaCommand(const char *name); size_t COM_Argc(void); @@ -53,11 +53,11 @@ const char *COM_CompleteAlias(const char *partial, INT32 skips); // insert at queu (at end of other command) #define COM_BufAddText(s) COM_BufAddTextEx(s, 0) -void COM_BufAddTextEx(const char *btext, int flags); +void COM_BufAddTextEx(const char *btext, com_flags_t flags); // insert in head (before other command) #define COM_BufInsertText(s) COM_BufInsertTextEx(s, 0) -void COM_BufInsertTextEx(const char *btext, int flags); +void COM_BufInsertTextEx(const char *btext, com_flags_t flags); // don't bother inserting, just do immediately void COM_ImmedExecute(const char *ptext); @@ -89,7 +89,7 @@ void VS_Free(vsbuf_t *buf); void VS_Clear(vsbuf_t *buf); void *VS_GetSpace(vsbuf_t *buf, size_t length); void VS_Write(vsbuf_t *buf, const void *data, size_t length); -void VS_WriteEx(vsbuf_t *buf, const void *data, size_t length, int flags); +void VS_WriteEx(vsbuf_t *buf, const void *data, size_t length, com_flags_t flags); void VS_Print(vsbuf_t *buf, const char *data); // strcats onto the sizebuf //================== @@ -120,7 +120,7 @@ typedef enum // can only be set when we have the pointer to it // used on menus CV_CHEAT = 2048, // Don't let this be used in multiplayer unless cheats are on. - CV_NOLUA = 4096,/* don't let this be called from Lua */ + CV_ALLOWLUA = 4096,/* Let this be called from Lua */ } cvflags_t; typedef struct CV_PossibleValue_s diff --git a/src/config.h.in b/src/config.h.in index 928705b30..3d6d98375 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -27,12 +27,13 @@ * Last updated 2020 / 10 / 02 - v2.2.8 - patch.pk3 * Last updated 2021 / 05 / 06 - v2.2.9 - patch.pk3 & zones.pk3 * Last updated 2022 / 03 / 06 - v2.2.10 - main assets + * Last updated 2023 / 05 / 02 - v2.2.11 - patch.pk3 & zones.pk3 */ #define ASSET_HASH_SRB2_PK3 "ad911f29a28a18968ee5b2d11c2acb39" -#define ASSET_HASH_ZONES_PK3 "86ae55cae4e0a93ceda868635706a093" +#define ASSET_HASH_ZONES_PK3 "1c8adf8d079ecb87d00081f158acf3c7" #define ASSET_HASH_PLAYER_DTA "2e7aaae8a6b1b77d90ffe7606ceadb6c" #ifdef USE_PATCH_DTA -#define ASSET_HASH_PATCH_PK3 "7d467a883f7887b3c311798ee2f56b6a" +#define ASSET_HASH_PATCH_PK3 "2e69558bce3b9610624549a75e29e19b" #endif #endif diff --git a/src/console.c b/src/console.c index 40fb43121..6d273f620 100644 --- a/src/console.c +++ b/src/console.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -61,7 +61,7 @@ static boolean con_started = false; // console has been initialised static boolean con_forcepic = true; // at startup toggle console translucency when first off boolean con_recalc; // set true when screen size has changed -static tic_t con_tick; // console ticker for anim or blinking prompt cursor +static tic_t con_tick; // console ticker for blinking prompt cursor // con_scrollup should use time (currenttime - lasttime).. static boolean consoletoggle; // true when console key pushed, ticker will handle @@ -110,6 +110,7 @@ static void CON_RecalcSize(void); static void CON_ChangeHeight(void); static void CON_DrawBackpic(void); +static void CONS_height_Change(void); static void CONS_hudlines_Change(void); static void CONS_backcolor_Change(void); @@ -136,7 +137,7 @@ static CV_PossibleValue_t speed_cons_t[] = {{0, "MIN"}, {64, "MAX"}, {0, NULL}}; static consvar_t cons_speed = CVAR_INIT ("con_speed", "8", CV_SAVE, speed_cons_t, NULL); // percentage of screen height to use for console -static consvar_t cons_height = CVAR_INIT ("con_height", "50", CV_SAVE, CV_Unsigned, NULL); +static consvar_t cons_height = CVAR_INIT ("con_height", "50", CV_CALL|CV_SAVE, CV_Unsigned, CONS_height_Change); static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"}, {0, NULL}}; // whether to use console background picture, or translucent mode @@ -156,6 +157,18 @@ consvar_t cons_backcolor = CVAR_INIT ("con_backcolor", "Green", CV_CALL|CV_SAVE, static void CON_Print(char *msg); +// Change the console height on demand +// +static void CONS_height_Change(void) +{ + Lock_state(); + + if (con_destlines > 0 && !con_startup) // If the console is open (as in, not using "bind")... + CON_ChangeHeight(); // ...update its height now, not only when it's closed and re-opened + + Unlock_state(); +} + // // static void CONS_hudlines_Change(void) @@ -382,16 +395,16 @@ static void CON_SetupColormaps(void) // 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(yellowmap, 82, 82, 73, 73, 73, 74, 74, 74, 66, 66, 66, 66, 67, 67, 67, 68); + colset(lgreenmap, 96, 96, 98, 98, 98, 100, 100, 100, 103, 103, 103, 103, 105, 105, 105, 107); + colset(bluemap, 146, 146, 147, 147, 147, 148, 148, 148, 149, 149, 149, 149, 150, 150, 150, 151); + colset(redmap, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 35, 37, 37, 37, 39); 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(peridotmap, 73, 73, 188, 188, 188, 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); @@ -443,7 +456,7 @@ void CON_Init(void) // register our commands // - COM_AddCommand("cls", CONS_Clear_f); + COM_AddCommand("cls", CONS_Clear_f, 0); //COM_AddCommand("english", CONS_English_f); // set console full screen for game startup MAKE SURE VID_Init() done !!! Lock_state(); @@ -470,7 +483,7 @@ void CON_Init(void) CV_RegisterVar(&cons_height); CV_RegisterVar(&cons_backpic); CV_RegisterVar(&cons_backcolor); - COM_AddCommand("bind", CONS_Bind_f); + COM_AddCommand("bind", CONS_Bind_f, 0); } else { @@ -643,33 +656,39 @@ static void CON_ChangeHeight(void) // static void CON_MoveConsole(void) { - fixed_t conspeed; + static fixed_t fracmovement = 0; Lock_state(); - conspeed = FixedDiv(cons_speed.value*vid.fdupy, FRACUNIT); - // instant if (!cons_speed.value) { con_curlines = con_destlines; + Unlock_state(); return; } - // up/down move to dest - if (con_curlines < con_destlines) + // Not instant - Increment fracmovement fractionally + fracmovement += FixedMul(cons_speed.value*vid.fdupy, renderdeltatics); + + if (con_curlines < con_destlines) // Move the console downwards { - con_curlines += FixedInt(conspeed); - if (con_curlines > con_destlines) - con_curlines = con_destlines; + con_curlines += FixedInt(fracmovement); // Move by fracmovement's integer value + if (con_curlines > con_destlines) // If we surpassed the destination... + con_curlines = con_destlines; // ...clamp to it! } - else if (con_curlines > con_destlines) + else // Move the console upwards { - con_curlines -= FixedInt(conspeed); + con_curlines -= FixedInt(fracmovement); if (con_curlines < con_destlines) con_curlines = con_destlines; + + if (con_destlines == 0) // If the console is being closed, not just moved up... + con_tick = 0; // ...don't show the blinking cursor } + fracmovement %= FRACUNIT; // Reset fracmovement's integer value, but keep the fraction + Unlock_state(); } @@ -752,10 +771,6 @@ void CON_Ticker(void) CON_ChangeHeight(); } - // console movement - if (con_destlines != con_curlines) - CON_MoveConsole(); - // clip the view, so that the part under the console is not drawn con_clipviewtop = -1; if (cons_backpic.value) // clip only when using an opaque background @@ -1809,41 +1824,41 @@ static void CON_DrawConsole(void) } // draw console text lines from top to bottom - if (con_curlines < minheight) - return; - - i = con_cy - con_scrollup; - - // skip the last empty line due to the cursor being at the start of a new line - i--; - - i -= (con_curlines - minheight) / charheight; - - if (rendermode == render_none) return; - - for (y = (con_curlines-minheight) % charheight; y <= con_curlines-minheight; y += charheight, i++) + if (con_curlines >= minheight) { - INT32 x; - size_t c; + i = con_cy - con_scrollup; - p = (UINT8 *)&con_buffer[((i > 0 ? i : 0)%con_totallines)*con_width]; + // skip the last empty line due to the cursor being at the start of a new line + i--; - for (c = 0, x = charwidth; c < con_width; c++, x += charwidth, p++) + i -= (con_curlines - minheight) / charheight; + + if (rendermode == render_none) return; + + for (y = (con_curlines-minheight) % charheight; y <= con_curlines-minheight; y += charheight, i++) { - while (*p & 0x80) + INT32 x; + size_t c; + + p = (UINT8 *)&con_buffer[((i > 0 ? i : 0)%con_totallines)*con_width]; + + for (c = 0, x = charwidth; c < con_width; c++, x += charwidth, p++) { - charflags = (*p & 0x7f) << V_CHARCOLORSHIFT; - p++; - c++; + while (*p & 0x80) + { + charflags = (*p & 0x7f) << V_CHARCOLORSHIFT; + p++; + c++; + } + if (c >= con_width) + break; + V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true); } - if (c >= con_width) - break; - V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true); } } // draw prompt if enough place (not while game startup) - if ((con_curlines == con_destlines) && (con_curlines >= minheight) && !con_startup) + if ((con_curlines >= (minheight-charheight)) && !con_startup) CON_DrawInput(); } @@ -1866,6 +1881,10 @@ void CON_Drawer(void) CON_ClearHUD(); } + // console movement + if (con_curlines != con_destlines) + CON_MoveConsole(); + if (con_curlines > 0) CON_DrawConsole(); else if (gamestate == GS_LEVEL diff --git a/src/console.h b/src/console.h index 1cd032ac1..f22f8dcbc 100644 --- a/src/console.h +++ b/src/console.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_clisrv.c b/src/d_clisrv.c old mode 100644 new mode 100755 index 4cd6333c5..ca9f4a24e --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -48,6 +48,9 @@ #include "md5.h" #include "m_perfstats.h" +// aaaaaa +#include "i_joy.h" + #ifndef NONET // cl loading screen #include "v_video.h" @@ -650,6 +653,22 @@ static UINT8 Snake_GetOppositeDir(UINT8 dir) return 12 + 5 - dir; } +event_t *snakejoyevents[MAXEVENTS]; +UINT16 joyeventcount = 0; + +// I'm screaming the hack is clean - ashi +static boolean Snake_Joy_Grabber(event_t *ev) +{ + if (ev->type == ev_joystick && ev->key == 0) + { + snakejoyevents[joyeventcount] = ev; + joyeventcount++; + return true; + } + else + return false; +} + static void Snake_FindFreeSlot(UINT8 *freex, UINT8 *freey, UINT8 headx, UINT8 heady) { UINT8 x, y; @@ -676,6 +695,9 @@ static void Snake_Handle(void) UINT8 x, y; UINT8 oldx, oldy; UINT16 i; + UINT16 j; + UINT16 joystate = 0; + static INT32 pjoyx = 0, pjoyy = 0; // Handle retry if (snake->gameover && (PLAYER1INPUTDOWN(GC_JUMP) || gamekeydown[KEY_ENTER])) @@ -704,23 +726,58 @@ static void Snake_Handle(void) oldx = snake->snakex[1]; oldy = snake->snakey[1]; + // process the input events in here dear lord + for (j = 0; j < joyeventcount; j++) + { + event_t *ev = snakejoyevents[j]; + const INT32 jdeadzone = (JOYAXISRANGE * cv_digitaldeadzone.value) / FRACUNIT; + if (ev->y != INT32_MAX) + { + if (Joystick.bGamepadStyle || abs(ev->y) > jdeadzone) + { + if (ev->y < 0 && pjoyy >= 0) + joystate = 1; + else if (ev->y > 0 && pjoyy <= 0) + joystate = 2; + pjoyy = ev->y; + } + else + pjoyy = 0; + } + + if (ev->x != INT32_MAX) + { + if (Joystick.bGamepadStyle || abs(ev->x) > jdeadzone) + { + if (ev->x < 0 && pjoyx >= 0) + joystate = 3; + else if (ev->x > 0 && pjoyx <= 0) + joystate = 4; + pjoyx = ev->x; + } + else + pjoyx = 0; + } + } + joyeventcount = 0; + // Update direction - if (gamekeydown[KEY_LEFTARROW]) + if (PLAYER1INPUTDOWN(GC_STRAFELEFT) || gamekeydown[KEY_LEFTARROW] || joystate == 3) { if (snake->snakelength < 2 || x <= oldx) snake->snakedir[0] = 1; } - else if (gamekeydown[KEY_RIGHTARROW]) + else if (PLAYER1INPUTDOWN(GC_STRAFERIGHT) || gamekeydown[KEY_RIGHTARROW] || joystate == 4) { if (snake->snakelength < 2 || x >= oldx) snake->snakedir[0] = 2; } - else if (gamekeydown[KEY_UPARROW]) + else if (PLAYER1INPUTDOWN(GC_FORWARD) || gamekeydown[KEY_UPARROW] || joystate == 1) { if (snake->snakelength < 2 || y <= oldy) snake->snakedir[0] = 3; } - else if (gamekeydown[KEY_DOWNARROW]) + else if (PLAYER1INPUTDOWN(GC_BACKWARD) || gamekeydown[KEY_DOWNARROW] || joystate == 2) { if (snake->snakelength < 2 || y >= oldy) snake->snakedir[0] = 4; @@ -1261,9 +1318,9 @@ static boolean CL_SendJoin(void) static INT32 FindRejoinerNum(SINT8 node) { - char strippednodeaddress[64]; + char addressbuffer[64]; const char *nodeaddress; - char *port; + const char *strippednodeaddress; INT32 i; // Make sure there is no dead dress before proceeding to the stripping @@ -1274,10 +1331,8 @@ static INT32 FindRejoinerNum(SINT8 node) return -1; // Strip the address of its port - strcpy(strippednodeaddress, nodeaddress); - port = strchr(strippednodeaddress, ':'); - if (port) - *port = '\0'; + strcpy(addressbuffer, nodeaddress); + strippednodeaddress = I_NetSplitAddress(addressbuffer, NULL); // Check if any player matches the stripped address for (i = 0; i < MAXPLAYERS; i++) @@ -1320,8 +1375,9 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.time = (tic_t)LONG(servertime); netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime); - netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers(); - netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value; + // Exclude bots from both counts + netbuffer->u.serverinfo.numberofplayer = (UINT8)(D_NumPlayers() - D_NumBots()); + netbuffer->u.serverinfo.maxplayer = (UINT8)(cv_maxplayers.value - D_NumBots()); netbuffer->u.serverinfo.refusereason = GetRefuseReason(node); @@ -1448,6 +1504,7 @@ static boolean SV_SendServerConfig(INT32 node) netbuffer->u.servercfg.gamestate = (UINT8)gamestate; netbuffer->u.servercfg.gametype = (UINT8)gametype; netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame; + netbuffer->u.servercfg.usedCheats = (UINT8)usedCheats; memcpy(netbuffer->u.servercfg.server_context, server_context, 8); @@ -1934,7 +1991,7 @@ static void M_ConfirmConnect(event_t *ev) #ifndef NONET if (ev->type == ev_keydown) { - if (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER) + if (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER || ev->key == KEY_JOY1) { if (totalfilesrequestednum > 0) { @@ -1949,7 +2006,7 @@ static void M_ConfirmConnect(event_t *ev) M_ClearMenus(true); } - else if (ev->key == 'n' || ev->key == KEY_ESCAPE) + else if (ev->key == 'n' || ev->key == KEY_ESCAPE || ev->key == KEY_JOY1 + 3) { cl_mode = CL_ABORTED; M_ClearMenus(true); @@ -1964,6 +2021,7 @@ static boolean CL_FinishedFileList(void) { INT32 i; char *downloadsize = NULL; + //CONS_Printf(M_GetText("Checking files...\n")); i = CL_CheckFiles(); if (i == 4) // still checking ... @@ -2379,8 +2437,14 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic D_ProcessEvents(); //needed for menu system to receive inputs else { + // my hand has been forced and I am dearly sorry for this awful hack :vomit: for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) - G_MapEventsToControls(&events[eventtail]); + { +#ifndef NONET + if (!Snake_Joy_Grabber(&events[eventtail])) +#endif + G_MapEventsToControls(&events[eventtail]); + } } if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1] || cl_mode == CL_ABORTED) @@ -2421,7 +2485,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic { if (!snake) { - F_MenuPresTicker(true); // title sky + F_MenuPresTicker(); // title sky F_TitleScreenTicker(true); F_TitleScreenDrawer(); } @@ -3442,10 +3506,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}}; consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); -consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_joinnextround = CVAR_INIT ("joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); /// \todo not done static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; -consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR, maxplayers_cons_t, NULL); +consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, maxplayers_cons_t, NULL); 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}}; @@ -3456,7 +3520,7 @@ consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "10", CV_SAVE|CV_NE consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); // max file size to send to a player (in kilobytes) -static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {204800, "MAX"}, {0, NULL}}; consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_cons_t, NULL); consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); @@ -3473,22 +3537,22 @@ void D_ClientServerInit(void) VERSION/100, VERSION%100, SUBVERSION)); #ifndef NONET - COM_AddCommand("getplayernum", Command_GetPlayerNum); - COM_AddCommand("kick", Command_Kick); - COM_AddCommand("ban", Command_Ban); - COM_AddCommand("banip", Command_BanIP); - COM_AddCommand("clearbans", Command_ClearBans); - COM_AddCommand("showbanlist", Command_ShowBan); - COM_AddCommand("reloadbans", Command_ReloadBan); - COM_AddCommand("connect", Command_connect); - COM_AddCommand("nodes", Command_Nodes); - COM_AddCommand("resendgamestate", Command_ResendGamestate); + COM_AddCommand("getplayernum", Command_GetPlayerNum, COM_LUA); + COM_AddCommand("kick", Command_Kick, COM_LUA); + COM_AddCommand("ban", Command_Ban, COM_LUA); + COM_AddCommand("banip", Command_BanIP, COM_LUA); + COM_AddCommand("clearbans", Command_ClearBans, COM_LUA); + COM_AddCommand("showbanlist", Command_ShowBan, COM_LUA); + COM_AddCommand("reloadbans", Command_ReloadBan, COM_LUA); + COM_AddCommand("connect", Command_connect, COM_LUA); + COM_AddCommand("nodes", Command_Nodes, COM_LUA); + COM_AddCommand("resendgamestate", Command_ResendGamestate, COM_LUA); #ifdef PACKETDROP - COM_AddCommand("drop", Command_Drop); - COM_AddCommand("droprate", Command_Droprate); + COM_AddCommand("drop", Command_Drop, COM_LUA); + COM_AddCommand("droprate", Command_Droprate, COM_LUA); #endif #ifdef _DEBUG - COM_AddCommand("numnodes", Command_Numnodes); + COM_AddCommand("numnodes", Command_Numnodes, COM_LUA); #endif #endif @@ -3579,6 +3643,9 @@ void SV_ResetServer(void) CV_RevertNetVars(); + // Ensure synched when creating a new server + M_CopyGameData(serverGamedata, clientGamedata); + DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n"); } @@ -3702,14 +3769,13 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) if (server && I_GetNodeAddress) { + char addressbuffer[64]; const char *address = I_GetNodeAddress(node); - char *port = NULL; if (address) // MI: fix msvcrt.dll!_mbscat crash? { - strcpy(playeraddress[newplayernum], address); - port = strchr(playeraddress[newplayernum], ':'); - if (port) - *port = '\0'; + strcpy(addressbuffer, address); + strcpy(playeraddress[newplayernum], + I_NetSplitAddress(addressbuffer, NULL)); } } } @@ -4013,7 +4079,7 @@ ConnectionRefused (SINT8 node, INT32 rejoinernum) { return va( "Maximum players reached: %d", - cv_maxplayers.value); + cv_maxplayers.value - D_NumBots()); } } @@ -4341,6 +4407,8 @@ static void HandlePacketFromAwayNode(SINT8 node) maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); G_SetGametype(netbuffer->u.servercfg.gametype); modifiedgame = netbuffer->u.servercfg.modifiedgame; + if (netbuffer->u.servercfg.usedCheats) + G_SetUsedCheats(true); memcpy(server_context, netbuffer->u.servercfg.server_context, 8); } @@ -5545,6 +5613,19 @@ INT32 D_NumPlayers(void) return num; } +/** Similar to the above, but counts only bots. + * Purpose is to remove bots from both the player count and the + * max player count on the server view +*/ +INT32 D_NumBots(void) +{ + INT32 num = 0, ix; + for (ix = 0; ix < MAXPLAYERS; ix++) + if (playeringame[ix] && players[ix].bot) + num++; + return num; +} + tic_t GetLag(INT32 node) { return gametic - nettics[node]; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index e07864122..04a7b5ba2 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -158,6 +158,7 @@ typedef struct UINT8 gametype; UINT8 modifiedgame; + UINT8 usedCheats; char server_context[8]; // Unique context id, generated at server startup. } ATTRPACK serverconfig_pak; @@ -447,6 +448,7 @@ extern char motd[254], server_context[8]; extern UINT8 playernode[MAXPLAYERS]; INT32 D_NumPlayers(void); +INT32 D_NumBots(void); void D_ResetTiccmds(void); tic_t GetLag(INT32 node); diff --git a/src/d_event.h b/src/d_event.h index c0b9cef77..5aa435060 100644 --- a/src/d_event.h +++ b/src/d_event.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_main.c b/src/d_main.c index 3566e7f3d..5861f9886 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1224,7 +1224,7 @@ void D_SRB2Main(void) // Print GPL notice for our console users (Linux) CONS_Printf( "\n\nSonic Robo Blast 2\n" - "Copyright (C) 1998-2022 by Sonic Team Junior\n\n" + "Copyright (C) 1998-2023 by Sonic Team Junior\n\n" "This program comes with ABSOLUTELY NO WARRANTY.\n\n" "This is free software, and you are welcome to redistribute it\n" "and/or modify it under the terms of the GNU General Public License\n" @@ -1350,6 +1350,9 @@ void D_SRB2Main(void) CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n"); Z_Init(); + clientGamedata = M_NewGameDataStruct(); + serverGamedata = M_NewGameDataStruct(); + // Do this up here so that WADs loaded through the command line can use ExecCfg COM_Init(); @@ -1473,7 +1476,15 @@ void D_SRB2Main(void) //--------------------------------------------------------- CONFIG.CFG M_FirstLoadConfig(); // WARNING : this do a "COM_BufExecute()" - G_LoadGameData(); + if (M_CheckParm("-gamedata") && M_IsNextParm()) + { + // Moved from G_LoadGameData itself, as it would cause some crazy + // confusion issues when loading mods. + strlcpy(gamedatafilename, M_GetNextParm(), sizeof gamedatafilename); + } + + G_LoadGameData(clientGamedata); + M_CopyGameData(serverGamedata, clientGamedata); #if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen @@ -1500,7 +1511,7 @@ void D_SRB2Main(void) else { if (!M_CheckParm("-server")) - G_SetGameModified(true); + G_SetUsedCheats(true); autostart = true; } } @@ -1704,7 +1715,7 @@ void D_SRB2Main(void) // ... unless you're in a dedicated server. Yes, technically this means you can view any level by // running a dedicated server and joining it yourself, but that's better than making dedicated server's // lives hell. - else if (!dedicated && M_MapLocked(pstartmap)) + else if (!dedicated && M_MapLocked(pstartmap, serverGamedata)) I_Error("You need to unlock this level before you can warp to it!\n"); else { @@ -1777,3 +1788,85 @@ const char *D_Home(void) if (usehome) return userhome; else return NULL; } + +static boolean check_top_dir(const char **path, const char *top) +{ + // empty string does NOT match + if (!strcmp(top, "")) + return false; + + if (!startswith(*path, top)) + return false; + + *path += strlen(top); + + // if it doesn't already end with a path separator, + // check if a separator follows + if (!endswith(top, PATHSEP)) + { + if (startswith(*path, PATHSEP)) + *path += strlen(PATHSEP); + else + return false; + } + + return true; +} + +static int cmp_strlen_desc(const void *a, const void *b) +{ + return ((int)strlen(*(const char*const*)b) - (int)strlen(*(const char*const*)a)); +} + +boolean D_IsPathAllowed(const char *path) +{ + const char *paths[] = { + srb2home, + srb2path, + cv_addons_folder.string + }; + + const size_t n_paths = sizeof paths / sizeof *paths; + + size_t i; + + // Sort folder paths by longest to shortest so + // overlapping paths work. E.g.: + // Path 1: /home/james/.srb2/addons + // Path 2: /home/james/.srb2 + qsort(paths, n_paths, sizeof *paths, cmp_strlen_desc); + + // These paths are allowed to be absolute + // path is offset so ".." can be checked only in the + // rest of the path + for (i = 0; i < n_paths; ++i) + { + if (check_top_dir(&path, paths[i])) + break; + } + + // Only if none of the presets matched + if (i == n_paths) + { + // Cannot be an absolute path + if (M_IsPathAbsolute(path)) + return false; + } + + // Cannot traverse upwards + if (strstr(path, "..")) + return false; + + return true; +} + +boolean D_CheckPathAllowed(const char *path, const char *why) +{ + if (!D_IsPathAllowed(path)) + { + CONS_Alert(CONS_WARNING, "%s: %s, location is not allowed\n", why, path); + return false; + } + + return true; +} diff --git a/src/d_main.h b/src/d_main.h index 8189a9f2b..0a29f929b 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -44,6 +44,9 @@ void D_ProcessEvents(void); const char *D_Home(void); +boolean D_IsPathAllowed(const char *path); +boolean D_CheckPathAllowed(const char *path, const char *why); + // // BASE LEVEL // diff --git a/src/d_net.c b/src/d_net.c index a7e1eb16d..768c9ac7e 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1207,26 +1207,32 @@ static void Internal_FreeNodenum(INT32 nodenum) (void)nodenum; } +char *I_NetSplitAddress(char *host, char **port) +{ + boolean v4 = (strchr(host, '.') != NULL); + + host = strtok(host, v4 ? ":" : "[]"); + + if (port) + *port = strtok(NULL, ":"); + + return host; +} + SINT8 I_NetMakeNode(const char *hostname) { SINT8 newnode = -1; if (I_NetMakeNodewPort) { char *localhostname = strdup(hostname); - char *t = localhostname; - const char *port; + char *port; if (!localhostname) return newnode; + // retrieve portnum from address! - strtok(localhostname, ":"); - port = strtok(NULL, ":"); + hostname = I_NetSplitAddress(localhostname, &port); - // remove the port in the hostname as we've it already - while ((*t != ':') && (*t != '\0')) - t++; - *t = '\0'; - - newnode = I_NetMakeNodewPort(localhostname, port); + newnode = I_NetMakeNodewPort(hostname, port); free(localhostname); } return newnode; diff --git a/src/d_net.h b/src/d_net.h index 5baa593a0..ddedbef4a 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4e90db0dc..af44e53d6 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -49,6 +49,7 @@ #include "m_anigif.h" #include "md5.h" #include "m_perfstats.h" +#include "hardware/u_list.h" // TODO: this should be a standard utility class #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR @@ -202,37 +203,37 @@ static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"}, static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}}; static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}}; -consvar_t cv_showinputjoy = CVAR_INIT ("showinputjoy", "Off", 0, CV_OnOff, NULL); +consvar_t cv_showinputjoy = CVAR_INIT ("showinputjoy", "Off", CV_ALLOWLUA, CV_OnOff, NULL); #ifdef NETGAME_DEVMODE static consvar_t cv_fishcake = CVAR_INIT ("fishcake", "Off", CV_CALL|CV_NOSHOWHELP|CV_RESTRICT, CV_OnOff, Fishcake_OnChange); #endif static consvar_t cv_dummyconsvar = CVAR_INIT ("dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, DummyConsvar_OnChange); -consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "Yes", CV_SAVE|CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); -consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "Yes", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, CV_YesNo, NULL); +consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); -consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, startingliveslimit_cons_t, NULL); +consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, startingliveslimit_cons_t, NULL); static CV_PossibleValue_t respawntime_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL); +consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, respawntime_cons_t, NULL); -consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL); +consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, competitionboxes_cons_t, NULL); 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); +consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE|CV_ALLOWLUA, seenames_cons_t, 0); +consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); // names consvar_t cv_playername = CVAR_INIT ("name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange); consvar_t cv_playername2 = CVAR_INIT ("name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange); // player colors UINT16 lastgoodcolor = SKINCOLOR_BLUE, lastgoodcolor2 = SKINCOLOR_BLUE; -consvar_t cv_playercolor = CVAR_INIT ("color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange); -consvar_t cv_playercolor2 = CVAR_INIT ("color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange); +consvar_t cv_playercolor = CVAR_INIT ("color", "Blue", CV_CALL|CV_NOINIT|CV_ALLOWLUA, Color_cons_t, Color_OnChange); +consvar_t cv_playercolor2 = CVAR_INIT ("color2", "Orange", CV_CALL|CV_NOINIT|CV_ALLOWLUA, Color_cons_t, Color2_OnChange); // player's skin, saved for commodity, when using a favorite skins wad.. -consvar_t cv_skin = CVAR_INIT ("skin", DEFAULTSKIN, CV_CALL|CV_NOINIT, NULL, Skin_OnChange); -consvar_t cv_skin2 = CVAR_INIT ("skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT, NULL, Skin2_OnChange); +consvar_t cv_skin = CVAR_INIT ("skin", DEFAULTSKIN, CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Skin_OnChange); +consvar_t cv_skin2 = CVAR_INIT ("skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Skin2_OnChange); // saved versions of the above six consvar_t cv_defaultplayercolor = CVAR_INIT ("defaultcolor", "Blue", CV_SAVE, Color_cons_t, NULL); @@ -267,43 +268,43 @@ consvar_t cv_mouse2opt = CVAR_INIT ("mouse2opt", "0", CV_SAVE, NULL, NULL); consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "COM2", CV_SAVE, mouse2port_cons_t, NULL); #endif -consvar_t cv_matchboxes = CVAR_INIT ("matchboxes", "Normal", CV_SAVE|CV_NETVAR|CV_CHEAT, matchboxes_cons_t, NULL); -consvar_t cv_specialrings = CVAR_INIT ("specialrings", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_powerstones = CVAR_INIT ("powerstones", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_matchboxes = CVAR_INIT ("matchboxes", "Normal", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, matchboxes_cons_t, NULL); +consvar_t cv_specialrings = CVAR_INIT ("specialrings", "On", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_powerstones = CVAR_INIT ("powerstones", "On", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); -consvar_t cv_recycler = CVAR_INIT ("tv_recycler", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_teleporters = CVAR_INIT ("tv_teleporter", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_superring = CVAR_INIT ("tv_superring", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_supersneakers = CVAR_INIT ("tv_supersneaker", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_invincibility = CVAR_INIT ("tv_invincibility", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_jumpshield = CVAR_INIT ("tv_jumpshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_watershield = CVAR_INIT ("tv_watershield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_ringshield = CVAR_INIT ("tv_ringshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_forceshield = CVAR_INIT ("tv_forceshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_bombshield = CVAR_INIT ("tv_bombshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_1up = CVAR_INIT ("tv_1up", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_eggmanbox = CVAR_INIT ("tv_eggman", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_recycler = CVAR_INIT ("tv_recycler", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_teleporters = CVAR_INIT ("tv_teleporter", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_superring = CVAR_INIT ("tv_superring", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_supersneakers = CVAR_INIT ("tv_supersneaker", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_invincibility = CVAR_INIT ("tv_invincibility", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_jumpshield = CVAR_INIT ("tv_jumpshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_watershield = CVAR_INIT ("tv_watershield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_ringshield = CVAR_INIT ("tv_ringshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_forceshield = CVAR_INIT ("tv_forceshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_bombshield = CVAR_INIT ("tv_bombshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_1up = CVAR_INIT ("tv_1up", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_eggmanbox = CVAR_INIT ("tv_eggman", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_ringslinger = CVAR_INIT ("ringslinger", "No", CV_NETVAR|CV_NOSHOWHELP|CV_CALL|CV_CHEAT, CV_YesNo, Ringslinger_OnChange); -consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL, NULL, Gravity_OnChange); +consvar_t cv_ringslinger = CVAR_INIT ("ringslinger", "No", CV_NETVAR|CV_NOSHOWHELP|CV_CALL|CV_CHEAT|CV_ALLOWLUA, CV_YesNo, Ringslinger_OnChange); +consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL|CV_ALLOWLUA, NULL, Gravity_OnChange); consvar_t cv_soundtest = CVAR_INIT ("soundtest", "0", CV_CALL, NULL, SoundTest_OnChange); static CV_PossibleValue_t minitimelimit_cons_t[] = {{1, "MIN"}, {9999, "MAX"}, {0, NULL}}; -consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL); +consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, minitimelimit_cons_t, NULL); -consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_hidetime = CVAR_INIT ("hidetime", "30", CV_SAVE|CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange); +consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_hidetime = CVAR_INIT ("hidetime", "30", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, minitimelimit_cons_t, Hidetime_OnChange); -consvar_t cv_autobalance = CVAR_INIT ("autobalance", "Off", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange); -consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange); -consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_SAVE|CV_NETVAR, teamscramble_cons_t, NULL); +consvar_t cv_autobalance = CVAR_INIT ("autobalance", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, CV_OnOff, AutoBalance_OnChange); +consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, teamscramble_cons_t, TeamScramble_OnChange); +consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, teamscramble_cons_t, NULL); -consvar_t cv_friendlyfire = CVAR_INIT ("friendlyfire", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_itemfinder = CVAR_INIT ("itemfinder", "Off", CV_CALL, CV_OnOff, ItemFinder_OnChange); +consvar_t cv_friendlyfire = CVAR_INIT ("friendlyfire", "Off", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_itemfinder = CVAR_INIT ("itemfinder", "Off", CV_CALL|CV_ALLOWLUA, CV_OnOff, ItemFinder_OnChange); // Scoring type options -consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); consvar_t cv_rollingdemos = CVAR_INIT ("rollingdemos", "On", CV_SAVE, CV_OnOff, NULL); @@ -314,13 +315,13 @@ static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-pe consvar_t cv_powerupdisplay = CVAR_INIT ("powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL); static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"}, {0, "None"}, {0, NULL}}; -consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange); +consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, pointlimit_cons_t, PointLimit_OnChange); static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}}; -consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange); +consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, timelimit_cons_t, TimeLimit_OnChange); static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, NULL}}; -consvar_t cv_numlaps = CVAR_INIT ("numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange); +consvar_t cv_numlaps = CVAR_INIT ("numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, numlaps_cons_t, NumLaps_OnChange); static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}}; -consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange); +consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT|CV_ALLOWLUA, basenumlaps_cons_t, BaseNumLaps_OnChange); // Point and time limits for every gametype INT32 pointlimits[NUMGAMETYPES]; @@ -329,11 +330,11 @@ INT32 timelimits[NUMGAMETYPES]; // log elemental hazards -- not a netvar, is local to current player consvar_t cv_hazardlog = CVAR_INIT ("hazardlog", "Yes", 0, CV_YesNo, NULL); -consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange); +consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT|CV_ALLOWLUA, NULL, ForceSkin_OnChange); consvar_t cv_downloading = CVAR_INIT ("downloading", "On", 0, CV_OnOff, NULL); -consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); -consvar_t cv_killingdead = CVAR_INIT ("killingdead", "Off", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_killingdead = CVAR_INIT ("killingdead", "Off", CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_netstat = CVAR_INIT ("netstat", "Off", 0, CV_OnOff, NULL); // show bandwidth statistics static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}}; @@ -351,26 +352,26 @@ consvar_t cv_showping = CVAR_INIT ("showping", "Warning", CV_SAVE, showping_cons // Intermission time Tails 04-19-2002 static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}}; -consvar_t cv_inttime = CVAR_INIT ("inttime", "10", CV_SAVE|CV_NETVAR, inttime_cons_t, NULL); +consvar_t cv_inttime = CVAR_INIT ("inttime", "10", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, inttime_cons_t, NULL); static CV_PossibleValue_t coopstarposts_cons_t[] = {{0, "Per-player"}, {1, "Shared"}, {2, "Teamwork"}, {0, NULL}}; -consvar_t cv_coopstarposts = CVAR_INIT ("coopstarposts", "Per-player", CV_SAVE|CV_NETVAR|CV_CALL, coopstarposts_cons_t, CoopStarposts_OnChange); +consvar_t cv_coopstarposts = CVAR_INIT ("coopstarposts", "Per-player", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, coopstarposts_cons_t, CoopStarposts_OnChange); static CV_PossibleValue_t cooplives_cons_t[] = {{0, "Infinite"}, {1, "Per-player"}, {2, "Avoid Game Over"}, {3, "Single pool"}, {0, NULL}}; -consvar_t cv_cooplives = CVAR_INIT ("cooplives", "Avoid Game Over", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange); +consvar_t cv_cooplives = CVAR_INIT ("cooplives", "Avoid Game Over", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT|CV_ALLOWLUA, cooplives_cons_t, CoopLives_OnChange); static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {0, NULL}}; -consvar_t cv_advancemap = CVAR_INIT ("advancemap", "Next", CV_SAVE|CV_NETVAR, advancemap_cons_t, NULL); +consvar_t cv_advancemap = CVAR_INIT ("advancemap", "Next", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, advancemap_cons_t, NULL); static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "1/4"}, {2, "Half"}, {3, "3/4"}, {4, "All"}, {0, NULL}}; -consvar_t cv_playersforexit = CVAR_INIT ("playersforexit", "All", CV_SAVE|CV_NETVAR, playersforexit_cons_t, NULL); +consvar_t cv_playersforexit = CVAR_INIT ("playersforexit", "All", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, playersforexit_cons_t, NULL); -consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange); +consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, CV_OnOff, ExitMove_OnChange); -consvar_t cv_runscripts = CVAR_INIT ("runscripts", "Yes", 0, CV_YesNo, NULL); +consvar_t cv_runscripts = CVAR_INIT ("runscripts", "Yes", CV_ALLOWLUA, CV_YesNo, NULL); -consvar_t cv_pause = CVAR_INIT ("pausepermission", "Server", CV_SAVE|CV_NETVAR, pause_cons_t, NULL); -consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange); +consvar_t cv_pause = CVAR_INIT ("pausepermission", "Server", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, pause_cons_t, NULL); +consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL|CV_ALLOWLUA, CV_OnOff, Mute_OnChange); consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL); @@ -463,57 +464,57 @@ void D_RegisterServerCommands(void) RegisterNetXCmd(XD_LUAFILE, Got_LuaFile); // Remote Administration - COM_AddCommand("password", Command_Changepassword_f); - COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin - COM_AddCommand("promote", Command_Verify_f); + COM_AddCommand("password", Command_Changepassword_f, COM_LUA); + COM_AddCommand("login", Command_Login_f, COM_LUA); // useful in dedicated to kick off remote admin + COM_AddCommand("promote", Command_Verify_f, COM_LUA); RegisterNetXCmd(XD_VERIFIED, Got_Verification); - COM_AddCommand("demote", Command_RemoveAdmin_f); + COM_AddCommand("demote", Command_RemoveAdmin_f, COM_LUA); RegisterNetXCmd(XD_DEMOTED, Got_Removal); - COM_AddCommand("motd", Command_MotD_f); + COM_AddCommand("motd", Command_MotD_f, COM_LUA); RegisterNetXCmd(XD_SETMOTD, Got_MotD_f); // For remote admin RegisterNetXCmd(XD_TEAMCHANGE, Got_Teamchange); - COM_AddCommand("serverchangeteam", Command_ServerTeamChange_f); + COM_AddCommand("serverchangeteam", Command_ServerTeamChange_f, COM_LUA); RegisterNetXCmd(XD_CLEARSCORES, Got_Clearscores); - COM_AddCommand("clearscores", Command_Clearscores_f); - COM_AddCommand("map", Command_Map_f); + COM_AddCommand("clearscores", Command_Clearscores_f, COM_LUA); + COM_AddCommand("map", Command_Map_f, COM_LUA); - COM_AddCommand("exitgame", Command_ExitGame_f); - COM_AddCommand("retry", Command_Retry_f); - COM_AddCommand("exitlevel", Command_ExitLevel_f); - COM_AddCommand("showmap", Command_Showmap_f); - COM_AddCommand("mapmd5", Command_Mapmd5_f); + COM_AddCommand("exitgame", Command_ExitGame_f, COM_LUA); + COM_AddCommand("retry", Command_Retry_f, COM_LUA); + COM_AddCommand("exitlevel", Command_ExitLevel_f, COM_LUA); + COM_AddCommand("showmap", Command_Showmap_f, COM_LUA); + COM_AddCommand("mapmd5", Command_Mapmd5_f, COM_LUA); - COM_AddCommand("addfolder", Command_Addfolder); - COM_AddCommand("addfile", Command_Addfile); - COM_AddCommand("listwad", Command_ListWADS_f); + COM_AddCommand("addfolder", Command_Addfolder, COM_LUA); + COM_AddCommand("addfile", Command_Addfile, COM_LUA); + COM_AddCommand("listwad", Command_ListWADS_f, COM_LUA); - COM_AddCommand("runsoc", Command_RunSOC); - COM_AddCommand("pause", Command_Pause); - COM_AddCommand("suicide", Command_Suicide); + COM_AddCommand("runsoc", Command_RunSOC, COM_LUA); + COM_AddCommand("pause", Command_Pause, COM_LUA); + COM_AddCommand("suicide", Command_Suicide, COM_LUA); - COM_AddCommand("gametype", Command_ShowGametype_f); - COM_AddCommand("version", Command_Version_f); + COM_AddCommand("gametype", Command_ShowGametype_f, COM_LUA); + COM_AddCommand("version", Command_Version_f, COM_LUA); #ifdef UPDATE_ALERT - COM_AddCommand("mod_details", Command_ModDetails_f); + COM_AddCommand("mod_details", Command_ModDetails_f, COM_LUA); #endif - COM_AddCommand("quit", Command_Quit_f); + COM_AddCommand("quit", Command_Quit_f, COM_LUA); - COM_AddCommand("saveconfig", Command_SaveConfig_f); - COM_AddCommand("loadconfig", Command_LoadConfig_f); - COM_AddCommand("changeconfig", Command_ChangeConfig_f); - COM_AddCommand("isgamemodified", Command_Isgamemodified_f); // test - COM_AddCommand("showscores", Command_ShowScores_f); - COM_AddCommand("showtime", Command_ShowTime_f); - COM_AddCommand("cheats", Command_Cheats_f); // test + COM_AddCommand("saveconfig", Command_SaveConfig_f, 0); + COM_AddCommand("loadconfig", Command_LoadConfig_f, 0); + COM_AddCommand("changeconfig", Command_ChangeConfig_f, 0); + COM_AddCommand("isgamemodified", Command_Isgamemodified_f, COM_LUA); // test + COM_AddCommand("showscores", Command_ShowScores_f, COM_LUA); + COM_AddCommand("showtime", Command_ShowTime_f, COM_LUA); + COM_AddCommand("cheats", Command_Cheats_f, COM_LUA); // test #ifdef _DEBUG - COM_AddCommand("togglemodified", Command_Togglemodified_f); - COM_AddCommand("archivetest", Command_Archivetest_f); + COM_AddCommand("togglemodified", Command_Togglemodified_f, COM_LUA); + COM_AddCommand("archivetest", Command_Archivetest_f, COM_LUA); #endif - COM_AddCommand("downloads", Command_Downloads_f); + COM_AddCommand("downloads", Command_Downloads_f, COM_LUA); // for master server connection AddMServCommands(); @@ -600,7 +601,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_blamecfail); #endif - COM_AddCommand("ping", Command_Ping_f); + COM_AddCommand("ping", Command_Ping_f, COM_LUA); CV_RegisterVar(&cv_nettimeout); CV_RegisterVar(&cv_jointimeout); @@ -612,6 +613,10 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_allowseenames); + // Other filesrch.c consvars are defined in D_RegisterClientCommands + CV_RegisterVar(&cv_addons_option); + CV_RegisterVar(&cv_addons_folder); + CV_RegisterVar(&cv_dummyconsvar); } @@ -644,25 +649,25 @@ void D_RegisterClientCommands(void) if (dedicated) return; - COM_AddCommand("numthinkers", Command_Numthinkers_f); - COM_AddCommand("countmobjs", Command_CountMobjs_f); + COM_AddCommand("numthinkers", Command_Numthinkers_f, COM_LUA); + COM_AddCommand("countmobjs", Command_CountMobjs_f, COM_LUA); - COM_AddCommand("changeteam", Command_Teamchange_f); - COM_AddCommand("changeteam2", Command_Teamchange2_f); + COM_AddCommand("changeteam", Command_Teamchange_f, COM_LUA); + COM_AddCommand("changeteam2", Command_Teamchange2_f, COM_LUA); - COM_AddCommand("playdemo", Command_Playdemo_f); - COM_AddCommand("timedemo", Command_Timedemo_f); - COM_AddCommand("stopdemo", Command_Stopdemo_f); - COM_AddCommand("playintro", Command_Playintro_f); + COM_AddCommand("playdemo", Command_Playdemo_f, 0); + COM_AddCommand("timedemo", Command_Timedemo_f, 0); + COM_AddCommand("stopdemo", Command_Stopdemo_f, COM_LUA); + COM_AddCommand("playintro", Command_Playintro_f, COM_LUA); - COM_AddCommand("resetcamera", Command_ResetCamera_f); + COM_AddCommand("resetcamera", Command_ResetCamera_f, COM_LUA); - COM_AddCommand("setcontrol", Command_Setcontrol_f); - COM_AddCommand("setcontrol2", Command_Setcontrol2_f); + COM_AddCommand("setcontrol", Command_Setcontrol_f, 0); + COM_AddCommand("setcontrol2", Command_Setcontrol2_f, 0); - COM_AddCommand("screenshot", M_ScreenShot); - COM_AddCommand("startmovie", Command_StartMovie_f); - COM_AddCommand("stopmovie", Command_StopMovie_f); + COM_AddCommand("screenshot", M_ScreenShot, COM_LUA); + COM_AddCommand("startmovie", Command_StartMovie_f, COM_LUA); + COM_AddCommand("stopmovie", Command_StopMovie_f, COM_LUA); CV_RegisterVar(&cv_screenshot_option); CV_RegisterVar(&cv_screenshot_folder); @@ -724,7 +729,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_ghost_last); CV_RegisterVar(&cv_ghost_guest); - COM_AddCommand("displayplayer", Command_Displayplayer_f); + COM_AddCommand("displayplayer", Command_Displayplayer_f, COM_LUA); // FIXME: not to be here.. but needs be done for config loading CV_RegisterVar(&cv_globalgamma); @@ -793,8 +798,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_digitaldeadzone2); // filesrch.c - CV_RegisterVar(&cv_addons_option); - CV_RegisterVar(&cv_addons_folder); + //CV_RegisterVar(&cv_addons_option); // These two are now defined + //CV_RegisterVar(&cv_addons_folder); // in D_RegisterServerCommands CV_RegisterVar(&cv_addons_md5); CV_RegisterVar(&cv_addons_showall); CV_RegisterVar(&cv_addons_search_type); @@ -880,7 +885,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_ps_descriptor); // ingame object placing - COM_AddCommand("objectplace", Command_ObjectPlace_f); + COM_AddCommand("objectplace", Command_ObjectPlace_f, COM_LUA); //COM_AddCommand("writethings", Command_Writethings_f); CV_RegisterVar(&cv_speed); CV_RegisterVar(&cv_opflags); @@ -892,32 +897,32 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_freedemocamera); // add cheat commands - COM_AddCommand("noclip", Command_CheatNoClip_f); - COM_AddCommand("god", Command_CheatGod_f); - COM_AddCommand("notarget", Command_CheatNoTarget_f); - COM_AddCommand("getallemeralds", Command_Getallemeralds_f); - COM_AddCommand("resetemeralds", Command_Resetemeralds_f); - COM_AddCommand("setrings", Command_Setrings_f); - COM_AddCommand("setlives", Command_Setlives_f); - COM_AddCommand("setcontinues", Command_Setcontinues_f); - COM_AddCommand("devmode", Command_Devmode_f); - COM_AddCommand("savecheckpoint", Command_Savecheckpoint_f); - COM_AddCommand("scale", Command_Scale_f); - COM_AddCommand("gravflip", Command_Gravflip_f); - COM_AddCommand("hurtme", Command_Hurtme_f); - COM_AddCommand("jumptoaxis", Command_JumpToAxis_f); - COM_AddCommand("charability", Command_Charability_f); - COM_AddCommand("charspeed", Command_Charspeed_f); - COM_AddCommand("teleport", Command_Teleport_f); - COM_AddCommand("rteleport", Command_RTeleport_f); - COM_AddCommand("skynum", Command_Skynum_f); - COM_AddCommand("weather", Command_Weather_f); - COM_AddCommand("toggletwod", Command_Toggletwod_f); + COM_AddCommand("noclip", Command_CheatNoClip_f, COM_LUA); + COM_AddCommand("god", Command_CheatGod_f, COM_LUA); + COM_AddCommand("notarget", Command_CheatNoTarget_f, COM_LUA); + COM_AddCommand("getallemeralds", Command_Getallemeralds_f, COM_LUA); + COM_AddCommand("resetemeralds", Command_Resetemeralds_f, COM_LUA); + COM_AddCommand("setrings", Command_Setrings_f, COM_LUA); + COM_AddCommand("setlives", Command_Setlives_f, COM_LUA); + COM_AddCommand("setcontinues", Command_Setcontinues_f, COM_LUA); + COM_AddCommand("devmode", Command_Devmode_f, COM_LUA); + COM_AddCommand("savecheckpoint", Command_Savecheckpoint_f, COM_LUA); + COM_AddCommand("scale", Command_Scale_f, COM_LUA); + COM_AddCommand("gravflip", Command_Gravflip_f, COM_LUA); + COM_AddCommand("hurtme", Command_Hurtme_f, COM_LUA); + COM_AddCommand("jumptoaxis", Command_JumpToAxis_f, COM_LUA); + COM_AddCommand("charability", Command_Charability_f, COM_LUA); + COM_AddCommand("charspeed", Command_Charspeed_f, COM_LUA); + COM_AddCommand("teleport", Command_Teleport_f, COM_LUA); + COM_AddCommand("rteleport", Command_RTeleport_f, COM_LUA); + COM_AddCommand("skynum", Command_Skynum_f, COM_LUA); + COM_AddCommand("weather", Command_Weather_f, COM_LUA); + COM_AddCommand("toggletwod", Command_Toggletwod_f, COM_LUA); #ifdef _DEBUG - COM_AddCommand("causecfail", Command_CauseCfail_f); + COM_AddCommand("causecfail", Command_CauseCfail_f, COM_LUA); #endif #ifdef LUA_ALLOW_BYTECODE - COM_AddCommand("dumplua", Command_Dumplua_f); + COM_AddCommand("dumplua", Command_Dumplua_f, COM_LUA); #endif } @@ -1877,7 +1882,7 @@ static void Command_Map_f(void) const char *gametypename; boolean newresetplayers; - boolean mustmodifygame; + boolean wouldSetCheats; INT32 newmapnum; @@ -1898,11 +1903,11 @@ static void Command_Map_f(void) option_gametype = COM_CheckPartialParm("-g"); newresetplayers = ! COM_CheckParm("-noresetplayers"); - mustmodifygame = - !( netgame || multiplayer ) && - (!modifiedgame || savemoddata ); + wouldSetCheats = + !( netgame || multiplayer ) && + !( usedCheats ); - if (mustmodifygame && !option_force) + if (wouldSetCheats && !option_force) { /* May want to be more descriptive? */ CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n")); @@ -1956,9 +1961,9 @@ static void Command_Map_f(void) return; } - if (mustmodifygame && option_force) + if (wouldSetCheats && option_force) { - G_SetGameModified(false); + G_SetUsedCheats(false); } // new gametype value @@ -2031,7 +2036,7 @@ static void Command_Map_f(void) // ... unless you're in a dedicated server. Yes, technically this means you can view any level by // running a dedicated server and joining it yourself, but that's better than making dedicated server's // lives hell. - if (!dedicated && M_MapLocked(newmapnum)) + if (!dedicated && M_MapLocked(newmapnum, serverGamedata)) { CONS_Alert(CONS_NOTICE, M_GetText("You need to unlock this level before you can warp to it!\n")); Z_Free(realmapname); @@ -3272,6 +3277,69 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum) G_SetGameModified(true); } +// C++ would make this SO much simpler! +typedef struct addedfile_s +{ + struct addedfile_s *next; + struct addedfile_s *prev; + char *value; +} addedfile_t; + +static boolean AddedFileContains(addedfile_t *list, const char *value) +{ + addedfile_t *node; + for (node = list; node; node = node->next) + { + if (!strcmp(value, node->value)) + return true; + } + + return false; +} + +static void AddedFilesAdd(addedfile_t **list, const char *value) +{ + addedfile_t *item = Z_Calloc(sizeof(addedfile_t), PU_STATIC, NULL); + item->value = Z_StrDup(value); + ListAdd(item, (listitem_t**)list); +} + +static void AddedFilesRemove(void *pItem, addedfile_t **itemHead) +{ + addedfile_t *item = (addedfile_t *)pItem; + + if (item == *itemHead) // Start of list + { + *itemHead = item->next; + + if (*itemHead) + (*itemHead)->prev = NULL; + } + else if (item->next == NULL) // end of list + { + item->prev->next = NULL; + } + else // Somewhere in between + { + item->prev->next = item->next; + item->next->prev = item->prev; + } + + Z_Free(item->value); + Z_Free(item); +} + +static void AddedFilesClearList(addedfile_t **itemHead) +{ + addedfile_t *item; + addedfile_t *next; + for (item = *itemHead; item; item = next) + { + next = item->next; + AddedFilesRemove(item, itemHead); + } +} + /** Adds a pwad at runtime. * Searches for sounds, maps, music, new images. */ @@ -3280,8 +3348,7 @@ static void Command_Addfile(void) size_t argc = COM_Argc(); // amount of arguments total size_t curarg; // current argument index - const char *addedfiles[argc]; // list of filenames already processed - size_t numfilesadded = 0; // the amount of filenames processed + addedfile_t *addedfiles = NULL; // list of filenames already processed if (argc < 2) { @@ -3296,25 +3363,14 @@ static void Command_Addfile(void) char buf[256]; char *buf_p = buf; INT32 i; - size_t ii; int musiconly; // W_VerifyNMUSlumps isn't boolean boolean fileadded = false; fn = COM_Argv(curarg); // For the amount of filenames previously processed... - for (ii = 0; ii < numfilesadded; ii++) - { - // If this is one of them, don't try to add it. - if (!strcmp(fn, addedfiles[ii])) - { - fileadded = true; - break; - } - } - - // If we've added this one, skip to the next one. - if (fileadded) + fileadded = AddedFileContains(addedfiles, fn); + if (fileadded) // If this is one of them, don't try to add it. { CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn); continue; @@ -3323,13 +3379,16 @@ static void Command_Addfile(void) // Disallow non-printing characters and semicolons. for (i = 0; fn[i] != '\0'; i++) if (!isprint(fn[i]) || fn[i] == ';') + { + AddedFilesClearList(&addedfiles); return; + } musiconly = W_VerifyNMUSlumps(fn, false); if (musiconly == -1) { - addedfiles[numfilesadded++] = fn; + AddedFilesAdd(&addedfiles, fn); continue; } @@ -3348,7 +3407,7 @@ static void Command_Addfile(void) if (!(netgame || multiplayer) || musiconly) { P_AddWadFile(fn); - addedfiles[numfilesadded++] = fn; + AddedFilesAdd(&addedfiles, fn); continue; } @@ -3363,6 +3422,7 @@ static void Command_Addfile(void) if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); + AddedFilesClearList(&addedfiles); return; } @@ -3402,13 +3462,15 @@ static void Command_Addfile(void) WRITEMEM(buf_p, md5sum, 16); } - addedfiles[numfilesadded++] = fn; + AddedFilesAdd(&addedfiles, fn); if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf); else SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); } + + AddedFilesClearList(&addedfiles); } static void Command_Addfolder(void) @@ -3416,8 +3478,7 @@ static void Command_Addfolder(void) size_t argc = COM_Argc(); // amount of arguments total size_t curarg; // current argument index - const char *addedfolders[argc]; // list of filenames already processed - size_t numfoldersadded = 0; // the amount of filenames processed + addedfile_t *addedfolders = NULL; // list of filenames already processed if (argc < 2) { @@ -3433,24 +3494,13 @@ static void Command_Addfolder(void) char buf[256]; char *buf_p = buf; INT32 i, stat; - size_t ii; boolean folderadded = false; fn = COM_Argv(curarg); // For the amount of filenames previously processed... - for (ii = 0; ii < numfoldersadded; ii++) - { - // If this is one of them, don't try to add it. - if (!strcmp(fn, addedfolders[ii])) - { - folderadded = true; - break; - } - } - - // If we've added this one, skip to the next one. - if (folderadded) + folderadded = AddedFileContains(addedfolders, fn); + if (folderadded) // If we've added this one, skip to the next one. { CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn); continue; @@ -3459,13 +3509,16 @@ static void Command_Addfolder(void) // Disallow non-printing characters and semicolons. for (i = 0; fn[i] != '\0'; i++) if (!isprint(fn[i]) || fn[i] == ';') + { + AddedFilesClearList(&addedfolders); return; + } // Add file on your client directly if you aren't in a netgame. if (!(netgame || multiplayer)) { P_AddFolder(fn); - addedfolders[numfoldersadded++] = fn; + AddedFilesAdd(&addedfolders, fn); continue; } @@ -3487,6 +3540,7 @@ static void Command_Addfolder(void) if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); + AddedFilesClearList(&addedfolders); return; } @@ -3532,7 +3586,7 @@ static void Command_Addfolder(void) Z_Free(fullpath); - addedfolders[numfoldersadded++] = fn; + AddedFilesAdd(&addedfolders, fn); WRITESTRINGN(buf_p,p,240); @@ -3891,18 +3945,12 @@ void ItemFinder_OnChange(void) if (!cv_itemfinder.value) return; // it's fine. - if (!M_SecretUnlocked(SECRET_ITEMFINDER)) + if (!M_SecretUnlocked(SECRET_ITEMFINDER, clientGamedata)) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); CV_StealthSetValue(&cv_itemfinder, 0); return; } - else if (netgame || multiplayer) - { - CONS_Printf(M_GetText("This only works in single player.\n")); - CV_StealthSetValue(&cv_itemfinder, 0); - return; - } } /** Deals with a pointlimit change by printing the change to the console. @@ -4251,7 +4299,7 @@ void D_GameTypeChanged(INT32 lastgametype) static void Ringslinger_OnChange(void) { - if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && cv_ringslinger.value && !cv_debug) + if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !netgame && cv_ringslinger.value && !cv_debug) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); CV_StealthSetValue(&cv_ringslinger, 0); @@ -4259,12 +4307,12 @@ static void Ringslinger_OnChange(void) } if (cv_ringslinger.value) // Only if it's been turned on - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } static void Gravity_OnChange(void) { - if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && !cv_debug + if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !netgame && !cv_debug && strcmp(cv_gravity.string, cv_gravity.defaultvalue)) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); @@ -4280,7 +4328,7 @@ static void Gravity_OnChange(void) #endif if (!CV_IsSetToDefault(&cv_gravity)) - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); gravity = cv_gravity.value; } @@ -4596,7 +4644,7 @@ static void Fishcake_OnChange(void) // so don't make modifiedgame always on! if (cv_debug) { - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } else if (cv_debug != cv_fishcake.value) @@ -4613,11 +4661,11 @@ static void Fishcake_OnChange(void) static void Command_Isgamemodified_f(void) { if (savemoddata) - CONS_Printf(M_GetText("modifiedgame is true, but you can save emblem and time data in this mod.\n")); + CONS_Printf(M_GetText("modifiedgame is true, but you can save time data in this mod.\n")); else if (modifiedgame) - CONS_Printf(M_GetText("modifiedgame is true, extras will not be unlocked\n")); + CONS_Printf(M_GetText("modifiedgame is true, time data can't be saved\n")); else - CONS_Printf(M_GetText("modifiedgame is false, you can unlock extras\n")); + CONS_Printf(M_GetText("modifiedgame is false, you can save time data\n")); } static void Command_Cheats_f(void) diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 0beeae154..26bf4d5c6 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_netfil.c b/src/d_netfil.c index edbef30bb..e60af2c2c 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_netfil.h b/src/d_netfil.h index f778a518f..ecec976be 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_player.h b/src/d_player.h index 42e9c3a82..f407c29e9 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -249,6 +249,38 @@ typedef enum CR_FAN } carrytype_t; // pw_carry +typedef enum +{ + STR_NONE = 0, // All strong powers can stack onto each other + + // Attack powers + STR_ANIM = 0x1, // remove powers when leaving current animation + STR_PUNCH = 0x2, // frontal attack (knuckles glide) + STR_TAIL = 0x4, // rear attack + STR_STOMP = 0x8, // falling onto object (fang bounce) + STR_UPPER = 0x10, // moving upwards into object (tails fly) + STR_GUARD = 0x20, //protect against damage + STR_HEAVY = 0x40, // ignore vertical rebound + STR_DASH = 0x80, // special type for machine dashmode, automatically removes your powers when leaving dashmode + + // Environment powers + STR_WALL = 0x100, // fof busting + STR_FLOOR = 0x200, + STR_CEILING = 0x400, + STR_SPRING = 0x800, // power up hit springs + STR_SPIKE = 0x1000, // break spikes + + // Shortcuts + STR_ATTACK = STR_PUNCH|STR_TAIL|STR_STOMP|STR_UPPER, + STR_BUST = STR_WALL|STR_FLOOR|STR_CEILING, + STR_FLY = STR_ANIM|STR_UPPER, + STR_GLIDE = STR_ANIM|STR_PUNCH, + STR_TWINSPIN = STR_ANIM|STR_ATTACK|STR_BUST|STR_SPRING|STR_SPIKE, + STR_MELEE = STR_ANIM|STR_PUNCH|STR_HEAVY|STR_WALL|STR_FLOOR|STR_SPRING|STR_SPIKE, + STR_BOUNCE = STR_ANIM|STR_STOMP|STR_FLOOR, + STR_METAL = STR_DASH|STR_SPIKE +} strongtype_t; // pw_strong + // Player powers. (don't edit this comment) typedef enum { @@ -293,6 +325,8 @@ typedef enum pw_ignorelatch, // Don't grab onto CR_GENERIC, add 32768 (powers[pw_ignorelatch] & 1<<15) to avoid ALL not-NiGHTS CR_ types + pw_strong, // Additional properties for powerful attacks + NUMPOWERS } powertype_t; @@ -407,6 +441,7 @@ typedef struct player_s // playing animation. panim_t panim; + UINT8 stronganim; // For screen flashing (bright). UINT16 flashcount; diff --git a/src/d_think.h b/src/d_think.h index 90a58ab68..bdb5db3f5 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index e632a74a8..2481ed738 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/deh_lua.c b/src/deh_lua.c index 09dc155cf..6dabb7e2d 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -10,20 +10,7 @@ /// \file deh_lua.c /// \brief Lua SOC library -#include "g_game.h" -#include "s_sound.h" -#include "z_zone.h" -#include "m_menu.h" -#include "m_misc.h" -#include "p_local.h" -#include "st_stuff.h" -#include "fastcmp.h" -#include "lua_script.h" -#include "lua_libs.h" - -#include "dehacked.h" #include "deh_lua.h" -#include "deh_tables.h" // freeslot takes a name (string only!) // and allocates it to the appropriate free slot. @@ -89,6 +76,8 @@ static inline int lib_freeslot(lua_State *L) strncpy(sprnames[j],word,4); //sprnames[j][4] = 0; used_spr[(j-SPR_FIRSTFREESLOT)/8] |= 1<<(j%8); // Okay, this sprite slot has been named now. + // Lua needs to update the value in _G if it exists + LUA_UpdateSprName(word, j); lua_pushinteger(L, j); r++; break; @@ -188,6 +177,9 @@ static inline int lib_freeslot(lua_State *L) lua_remove(L, 1); continue; } + + R_RefreshSprite2(); + return r; } @@ -216,18 +208,27 @@ static int lib_dummysuper(lua_State *L) return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions being called by state changes!"); // convoluted, I know. @_@;; } -static inline int lib_getenum(lua_State *L) +static void CacheAndPushConstant(lua_State *L, const char *name, lua_Integer value) { - const char *word, *p; + // "cache" into _G + lua_pushstring(L, name); + lua_pushinteger(L, value); + lua_rawset(L, LUA_GLOBALSINDEX); + // push + lua_pushinteger(L, value); +} + +// Search for a matching constant variable. +// Result is stored into _G for faster subsequent use. (Except for SPR_ in the SOC parser) +static int ScanConstants(lua_State *L, boolean mathlib, const char *word) +{ + const char *p; fixed_t i; - boolean mathlib = lua_toboolean(L, lua_upvalueindex(1)); - if (lua_type(L,2) != LUA_TSTRING) - return 0; - word = lua_tostring(L,2); + if (strlen(word) == 1) { // Assume sprite frame if length 1. if (*word >= 'A' && *word <= '~') { - lua_pushinteger(L, *word-'A'); + CacheAndPushConstant(L, word, *word-'A'); return 1; } if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word); @@ -237,7 +238,7 @@ static inline int lib_getenum(lua_State *L) p = word+3; for (i = 0; MOBJFLAG_LIST[i]; i++) if (fastcmp(p, MOBJFLAG_LIST[i])) { - lua_pushinteger(L, ((lua_Integer)1< #endif +FILE *fopenfile(const char*, const char*); + //#define NOMD5 // Uncheck this to compile debugging code @@ -150,7 +152,7 @@ extern char logfilename[1024]; // Does this version require an added patch file? // Comment or uncomment this as necessary. -// #define USE_PATCH_DTA +#define USE_PATCH_DTA // Enforce a limit of loaded WAD files. //#define ENFORCE_WAD_LIMIT @@ -259,66 +261,111 @@ typedef enum // Desaturated SKINCOLOR_AETHER, SKINCOLOR_SLATE, + SKINCOLOR_METEORITE, + SKINCOLOR_MERCURY, SKINCOLOR_BLUEBELL, SKINCOLOR_PINK, + SKINCOLOR_ROSEWOOD, SKINCOLOR_YOGURT, + SKINCOLOR_LATTE, SKINCOLOR_BROWN, + SKINCOLOR_BOULDER, SKINCOLOR_BRONZE, + SKINCOLOR_SEPIA, + SKINCOLOR_ECRU, SKINCOLOR_TAN, SKINCOLOR_BEIGE, + SKINCOLOR_ROSEBUSH, SKINCOLOR_MOSS, SKINCOLOR_AZURE, + SKINCOLOR_EGGPLANT, SKINCOLOR_LAVENDER, // Viv's vivid colours (toast 21/07/17) + // Tweaks & additions (Lach, sphere, Alice, MotorRoach 26/10/22) SKINCOLOR_RUBY, + SKINCOLOR_CHERRY, SKINCOLOR_SALMON, + SKINCOLOR_PEPPER, SKINCOLOR_RED, SKINCOLOR_CRIMSON, SKINCOLOR_FLAME, + SKINCOLOR_GARNET, SKINCOLOR_KETCHUP, SKINCOLOR_PEACHY, SKINCOLOR_QUAIL, + SKINCOLOR_FOUNDATION, SKINCOLOR_SUNSET, SKINCOLOR_COPPER, SKINCOLOR_APRICOT, SKINCOLOR_ORANGE, + SKINCOLOR_PUMPKIN, SKINCOLOR_RUST, SKINCOLOR_GOLD, + SKINCOLOR_TOPAZ, SKINCOLOR_SANDY, + SKINCOLOR_GOLDENROD, SKINCOLOR_YELLOW, SKINCOLOR_OLIVE, + SKINCOLOR_PEAR, + SKINCOLOR_LEMON, SKINCOLOR_LIME, SKINCOLOR_PERIDOT, SKINCOLOR_APPLE, + SKINCOLOR_CHARTREUSE, SKINCOLOR_GREEN, SKINCOLOR_FOREST, - SKINCOLOR_EMERALD, + SKINCOLOR_SHAMROCK, + SKINCOLOR_JADE, + SKINCOLOR_HEADLIGHT, SKINCOLOR_MINT, + SKINCOLOR_MASTER, + SKINCOLOR_EMERALD, + SKINCOLOR_BOTTLE, SKINCOLOR_SEAFOAM, + SKINCOLOR_ISLAND, SKINCOLOR_AQUA, SKINCOLOR_TEAL, SKINCOLOR_WAVE, SKINCOLOR_CYAN, + SKINCOLOR_TURQUOISE, + SKINCOLOR_AQUAMARINE, SKINCOLOR_SKY, + SKINCOLOR_MARINE, SKINCOLOR_CERULEAN, + SKINCOLOR_DREAM, SKINCOLOR_ICY, + SKINCOLOR_DAYBREAK, SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave โ€“ slender aphrodite has overcome me with longing for a girl + SKINCOLOR_ARCTIC, SKINCOLOR_CORNFLOWER, SKINCOLOR_BLUE, SKINCOLOR_COBALT, + SKINCOLOR_MIDNIGHT, + SKINCOLOR_GALAXY, SKINCOLOR_VAPOR, SKINCOLOR_DUSK, + SKINCOLOR_MAJESTY, SKINCOLOR_PASTEL, SKINCOLOR_PURPLE, + SKINCOLOR_NOBLE, + SKINCOLOR_FUCHSIA, SKINCOLOR_BUBBLEGUM, + SKINCOLOR_CRYSTAL, SKINCOLOR_MAGENTA, SKINCOLOR_NEON, SKINCOLOR_VIOLET, + SKINCOLOR_ROYAL, SKINCOLOR_LILAC, + SKINCOLOR_MAUVE, + SKINCOLOR_EVENTIDE, SKINCOLOR_PLUM, SKINCOLOR_RASPBERRY, + SKINCOLOR_TAFFY, SKINCOLOR_ROSY, + SKINCOLOR_FANCY, + SKINCOLOR_SANGRIA, + SKINCOLOR_VOLCANIC, FIRSTSUPERCOLOR, diff --git a/src/doomstat.h b/src/doomstat.h index bce43416b..a812cc304 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -75,6 +75,7 @@ extern SINT8 startinglivesbalance[maxgameovers+1]; extern boolean modifiedgame; extern UINT16 mainwads; extern boolean savemoddata; // This mod saves time/emblem data. +extern boolean usedCheats; extern boolean disableSpeedAdjust; // Don't alter the duration of player states if true extern boolean imcontinuing; // Temporary flag while continuing extern boolean metalrecording; @@ -131,8 +132,6 @@ extern INT32 postimgparam2; extern INT32 viewwindowx, viewwindowy; extern INT32 viewwidth, scaledviewwidth; -extern boolean gamedataloaded; - // Player taking events, and displaying. extern INT32 consoleplayer; extern INT32 displayplayer; @@ -494,8 +493,6 @@ typedef struct extern tolinfo_t TYPEOFLEVEL[NUMTOLNAMES]; extern UINT32 lastcustomtol; -extern tic_t totalplaytime; - extern boolean stagefailed; // Emeralds stored as bits to throw savegame hackers off. @@ -514,52 +511,6 @@ extern INT32 luabanks[NUM_LUABANKS]; extern INT32 nummaprings; //keep track of spawned rings/coins -/** Time attack information, currently a very small structure. - */ -typedef struct -{ - tic_t time; ///< Time in which the level was finished. - UINT32 score; ///< Score when the level was finished. - UINT16 rings; ///< Rings when the level was finished. -} recorddata_t; - -/** Setup for one NiGHTS map. - * These are dynamically allocated because I am insane - */ -#define GRADE_F 0 -#define GRADE_E 1 -#define GRADE_D 2 -#define GRADE_C 3 -#define GRADE_B 4 -#define GRADE_A 5 -#define GRADE_S 6 - -typedef struct -{ - // 8 mares, 1 overall (0) - UINT8 nummares; - UINT32 score[9]; - UINT8 grade[9]; - tic_t time[9]; -} nightsdata_t; - -extern nightsdata_t *nightsrecords[NUMMAPS]; -extern recorddata_t *mainrecords[NUMMAPS]; - -// mapvisited is now a set of flags that says what we've done in the map. -#define MV_VISITED 1 -#define MV_BEATEN 2 -#define MV_ALLEMERALDS 4 -#define MV_ULTIMATE 8 -#define MV_PERFECT 16 -#define MV_PERFECTRA 32 -#define MV_MAX 63 // used in gamedata check, update whenever MV's are added -#define MV_MP 128 -extern UINT8 mapvisited[NUMMAPS]; - -// Temporary holding place for nights data for the current map -extern nightsdata_t ntemprecords; - extern UINT32 token; ///< Number of tokens collected in a level extern UINT32 tokenlist; ///< List of tokens collected extern boolean gottoken; ///< Did you get a token? Used for end of act @@ -592,9 +543,12 @@ extern UINT8 useBlackRock; extern UINT8 use1upSound; extern UINT8 maxXtraLife; // Max extra lives from rings + extern UINT8 useContinues; #define continuesInSession (!multiplayer && (ultimatemode || (useContinues && !marathonmode) || (!modeattacking && !(cursaveslot > 0)))) +extern UINT8 shareEmblems; + extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations // For racing @@ -615,10 +569,6 @@ extern INT32 cheats; extern tic_t hidetime; -extern UINT32 timesBeaten; // # of times the game has been beaten. -extern UINT32 timesBeatenWithEmeralds; -extern UINT32 timesBeatenUltimate; - // =========================== // Internal parameters, fixed. // =========================== diff --git a/src/doomtype.h b/src/doomtype.h index b8f602c64..f6c236e20 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -31,18 +31,8 @@ #include #endif -#define UINT8 unsigned __int8 #define SINT8 signed __int8 -#define UINT16 unsigned __int16 -#define INT16 __int16 - -#define INT32 __int32 -#define UINT32 unsigned __int32 - -#define INT64 __int64 -#define UINT64 unsigned __int64 - typedef long ssize_t; /* Older Visual C++ headers don't have the Win64-compatible typedefs... */ @@ -107,6 +97,9 @@ typedef long ssize_t; char *strcasestr(const char *in, const char *what); #define stristr strcasestr +int startswith (const char *base, const char *tag); +int endswith (const char *base, const char *tag); + #if defined (macintosh) //|| defined (__APPLE__) //skip all boolean/Boolean crap #define true 1 #define false 0 diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index 997115ad0..8556c0248 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -8,7 +8,7 @@ UINT8 graphics_started = 0; UINT8 keyboard_started = 0; -UINT32 I_GetFreeMem(UINT32 *total) +size_t I_GetFreeMem(size_t *total) { *total = 0; return 0; diff --git a/src/endian.h b/src/endian.h index 86297f0cb..87f752471 100644 --- a/src/endian.h +++ b/src/endian.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2014-2022 by Sonic Team Junior. +// Copyright (C) 2014-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/f_finale.c b/src/f_finale.c index bca8e3ba6..299a6a054 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -63,7 +63,6 @@ static tic_t stoptimer; static boolean keypressed = false; // (no longer) De-Demo'd Title Screen -static INT32 menuanimtimer; // Title screen: background animation timing mobj_t *titlemapcameraref = NULL; // menu presentation state @@ -75,6 +74,8 @@ INT32 curbgyspeed; boolean curbghide; boolean hidetitlemap; // WARNING: set to false by M_SetupNextMenu and M_ClearMenus +static fixed_t curbgx = 0; +static fixed_t curbgy = 0; static UINT8 curDemo = 0; static UINT32 demoDelayLeft; static UINT32 demoIdleLeft; @@ -223,7 +224,6 @@ static INT32 cutscene_writeptr = 0; static INT32 cutscene_textcount = 0; static INT32 cutscene_textspeed = 0; static UINT8 cutscene_boostspeed = 0; -static tic_t cutscene_lasttextwrite = 0; // STJR Intro char stjrintro[9] = "STJRI000"; @@ -239,11 +239,6 @@ static UINT8 F_WriteText(void) { INT32 numtowrite = 1; const char *c; - tic_t ltw = I_GetTime(); - - if (cutscene_lasttextwrite == ltw) - return 1; // singletics prevention - cutscene_lasttextwrite = ltw; if (cutscene_boostspeed) { @@ -337,7 +332,7 @@ static tic_t introscenetime[NUMINTROSCENES] = }; // custom intros -void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer); +void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer, boolean FLS); void F_StartIntro(void) { @@ -349,7 +344,7 @@ void F_StartIntro(void) if (!cutscenes[introtoplay - 1]) D_StartTitle(); else - F_StartCustomCutscene(introtoplay - 1, false, false); + F_StartCustomCutscene(introtoplay - 1, false, false, false); return; } @@ -1138,7 +1133,7 @@ static const char *credits[] = { "Dave \"DemonTomatoDave\" Bulmer", "Paul \"Boinciel\" Clempson", "\"Cyan Helkaraxe\"", - "Shane \"CobaltBW\" Ellis", + "Claire \"clairebun\" Ellis", "James \"SeventhSentinel\" Hall", "Kepa \"Nev3r\" Iceta", "Iestyn \"Monster Iestyn\" Jealous", @@ -1257,7 +1252,7 @@ void F_StartCredits(void) if (creditscutscene) { - F_StartCustomCutscene(creditscutscene - 1, false, false); + F_StartCustomCutscene(creditscutscene - 1, false, false, false); return; } @@ -1411,7 +1406,7 @@ boolean F_CreditResponder(event_t *event) break; } - if (!(timesBeaten) && !(netgame || multiplayer) && !cv_debug) + if (!(serverGamedata->timesBeaten) && !(netgame || multiplayer) && !cv_debug) return false; if (event->type != ev_keydown) @@ -1573,27 +1568,19 @@ void F_GameEvaluationDrawer(void) #if 0 // the following looks like hot garbage the more unlockables we add, and we now have a lot of unlockables if (finalecount >= 5*TICRATE) { + INT32 startcoord = 32; V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:"); - if (!(netgame) && (!modifiedgame || savemoddata)) + for (i = 0; i < MAXUNLOCKABLES; i++) { - INT32 startcoord = 32; - - for (i = 0; i < MAXUNLOCKABLES; i++) + if (unlockables[i].conditionset && unlockables[i].conditionset < MAXCONDITIONSETS + && unlockables[i].type && !unlockables[i].nocecho) { - if (unlockables[i].conditionset && unlockables[i].conditionset < MAXCONDITIONSETS - && unlockables[i].type && !unlockables[i].nocecho) - { - if (unlockables[i].unlocked) - V_DrawString(8, startcoord, 0, unlockables[i].name); - startcoord += 8; - } + if (clientGamedata->unlocked[i]) + V_DrawString(8, startcoord, 0, unlockables[i].name); + startcoord += 8; } } - else if (netgame) - V_DrawString(8, 96, V_YELLOWMAP, "Multiplayer games\ncan't unlock\nextras!"); - else - V_DrawString(8, 96, V_YELLOWMAP, "Modified games\ncan't unlock\nextras!"); } #endif @@ -1650,35 +1637,27 @@ void F_GameEvaluationTicker(void) if (finalecount == 5*TICRATE) { - if (netgame || multiplayer) // modify this when we finally allow unlocking stuff in 2P + serverGamedata->timesBeaten++; + clientGamedata->timesBeaten++; + + if (ALL7EMERALDS(emeralds)) { - HU_SetCEchoFlags(V_YELLOWMAP|V_RETURN8); - HU_SetCEchoDuration(6); - HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Multiplayer games can't unlock extras!"); + serverGamedata->timesBeatenWithEmeralds++; + clientGamedata->timesBeatenWithEmeralds++; + } + + if (ultimatemode) + { + serverGamedata->timesBeatenUltimate++; + clientGamedata->timesBeatenUltimate++; + } + + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + + if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata)) S_StartSound(NULL, sfx_s3k68); - } - else if (!modifiedgame || savemoddata) - { - ++timesBeaten; - if (ALL7EMERALDS(emeralds)) - ++timesBeatenWithEmeralds; - - if (ultimatemode) - ++timesBeatenUltimate; - - if (M_UpdateUnlockablesAndExtraEmblems()) - S_StartSound(NULL, sfx_s3k68); - - G_SaveGameData(); - } - else - { - HU_SetCEchoFlags(V_YELLOWMAP|V_RETURN8); - HU_SetCEchoDuration(6); - HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Modified games can't unlock extras!"); - S_StartSound(NULL, sfx_s3k68); - } + G_SaveGameData(clientGamedata); } } @@ -2192,7 +2171,7 @@ void F_EndingDrawer(void) //colset(linkmap, 164, 165, 169); -- the ideal purple colour to represent a clicked in-game link, but not worth it just for a soundtest-controlled secret V_DrawCenteredString(BASEVIDWIDTH/2, 8, V_ALLOWLOWERCASE|(trans<'|(trans<= STOPPINGPOINT-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<"); + V_DrawString(40, ((finalecount == STOPPINGPOINT-(20+TICRATE)) ? 1 : 0)+BASEVIDHEIGHT-16, ((serverGamedata->timesBeaten || finalecount >= STOPPINGPOINT-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<"); } if (finalecount > STOPPINGPOINT-(20+(2*TICRATE))) @@ -2258,7 +2237,8 @@ void F_GameEndTicker(void) void F_InitMenuPresValues(void) { - menuanimtimer = 0; + curbgx = 0; + curbgy = 0; prevMenuId = 0; activeMenuId = MainDef.menuid; @@ -2291,17 +2271,11 @@ void F_InitMenuPresValues(void) // // F_SkyScroll // -void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname) +void F_SkyScroll(const char *patchname) { - INT32 xscrolled, x, xneg = (scrollxspeed > 0) - (scrollxspeed < 0), tilex; - INT32 yscrolled, y, yneg = (scrollyspeed > 0) - (scrollyspeed < 0), tiley; - boolean xispos = (scrollxspeed >= 0), yispos = (scrollyspeed >= 0); + INT32 x, basey = 0; INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - INT16 patwidth, patheight; - INT32 pw, ph; // scaled by dupz patch_t *pat; - INT32 i, j; - fixed_t fracmenuanimtimer, xscrolltimer, yscrolltimer; if (rendermode == render_none) return; @@ -2312,43 +2286,34 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname) return; } - if (!scrollxspeed && !scrollyspeed) + pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY); + + if (!curbgxspeed && !curbgyspeed) { - V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY)); + V_DrawPatchFill(pat); + W_UnlockCachedPatch(pat); return; } - pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY); + // Modulo the background scrolling to prevent jumps from integer overflows + // We already load the background patch here, so we can modulo it here + // to avoid also having to load the patch in F_MenuPresTicker + curbgx %= pat->width * 16; + curbgy %= pat->height * 16; - patwidth = pat->width; - patheight = pat->height; - pw = patwidth * dupz; - ph = patheight * dupz; + // Ooh, fancy frame interpolation + x = ((curbgx*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgxspeed*dupz)) / 16; + basey = ((curbgy*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgyspeed*dupz)) / 16; - tilex = max(FixedCeil(FixedDiv(vid.width, pw)) >> FRACBITS, 1)+2; // one tile on both sides of center - tiley = max(FixedCeil(FixedDiv(vid.height, ph)) >> FRACBITS, 1)+2; + if (x > 0) // Make sure that we don't leave the left or top sides empty + x -= pat->width * dupz; + if (basey > 0) + basey -= pat->height * dupz; - fracmenuanimtimer = (menuanimtimer * FRACUNIT) - (FRACUNIT - rendertimefrac); - xscrolltimer = ((fracmenuanimtimer*scrollxspeed)/16 + patwidth*xneg*FRACUNIT) % (patwidth * FRACUNIT); - yscrolltimer = ((fracmenuanimtimer*scrollyspeed)/16 + patheight*yneg*FRACUNIT) % (patheight * FRACUNIT); - - // coordinate offsets - xscrolled = FixedInt(xscrolltimer * dupz); - yscrolled = FixedInt(yscrolltimer * dupz); - - for (x = (xispos) ? -pw*(tilex-1)+pw : 0, i = 0; - i < tilex; - x += pw, i++) + for (; x < vid.width; x += pat->width * dupz) { - for (y = (yispos) ? -ph*(tiley-1)+ph : 0, j = 0; - j < tiley; - y += ph, j++) - { - V_DrawScaledPatch( - (xispos) ? xscrolled - x : x + xscrolled, - (yispos) ? yscrolled - y : y + yscrolled, - V_NOSCALESTART, pat); - } + for (INT32 y = basey; y < vid.height; y += pat->height * dupz) + V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); } W_UnlockCachedPatch(pat); @@ -2503,6 +2468,8 @@ void F_StartTitleScreen(void) { titlemapinaction = TITLEMAP_OFF; gamemap = 1; // g_game.c + if (!mapheaderinfo[gamemap-1]) + P_AllocMapHeader(gamemap-1); CON_ClearHUD(); } @@ -2669,7 +2636,7 @@ void F_TitleScreenDrawer(void) if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS) - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + F_SkyScroll(curbgname); // Don't draw outside of the title screen, or if the patch isn't there. if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS) @@ -3424,10 +3391,10 @@ luahook: // separate animation timer for backgrounds, since we also count // during GS_TIMEATTACK -void F_MenuPresTicker(boolean run) +void F_MenuPresTicker(void) { - if (run) - menuanimtimer++; + curbgx += curbgxspeed; + curbgy += curbgyspeed; } // (no longer) De-Demo'd Title Screen @@ -3857,7 +3824,7 @@ static INT32 scenenum, cutnum; static INT32 picxpos, picypos, picnum, pictime, picmode, numpics, pictoloop; static INT32 textxpos, textypos; static boolean cutsceneover = false; -static boolean runningprecutscene = false, precutresetplayer = false; +static boolean runningprecutscene = false, precutresetplayer = false, precutFLS = false; static void F_AdvanceToNextScene(void) { @@ -3926,7 +3893,7 @@ void F_EndCutScene(void) if (runningprecutscene) { if (server) - D_MapChange(gamemap, gametype, ultimatemode, precutresetplayer, 0, true, false); + D_MapChange(gamemap, gametype, ultimatemode, precutresetplayer, 0, true, precutFLS); } else { @@ -3941,7 +3908,7 @@ void F_EndCutScene(void) } } -void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer) +void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer, boolean FLS) { if (!cutscenes[cutscenenum]) return; @@ -3960,6 +3927,7 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset cutsceneover = false; runningprecutscene = precutscene; precutresetplayer = resetplayer; + precutFLS = FLS; scenenum = picnum = 0; cutnum = cutscenenum; diff --git a/src/f_finale.h b/src/f_finale.h index efdc9d4ad..7f53bfbad 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -40,7 +40,7 @@ void F_TextPromptTicker(void); void F_GameEndDrawer(void); void F_IntroDrawer(void); void F_TitleScreenDrawer(void); -void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname); +void F_SkyScroll(const char *patchname); void F_GameEvaluationDrawer(void); void F_StartGameEvaluation(void); @@ -52,7 +52,7 @@ void F_EndingDrawer(void); void F_CreditTicker(void); void F_CreditDrawer(void); -void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer); +void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer, boolean FLS); void F_CutsceneDrawer(void); void F_EndCutScene(void); @@ -131,7 +131,7 @@ extern UINT16 curtttics; #define TITLEBACKGROUNDACTIVE (curfadevalue >= 0 || curbgname[0]) void F_InitMenuPresValues(void); -void F_MenuPresTicker(boolean run); +void F_MenuPresTicker(void); // // WIPE diff --git a/src/f_wipe.c b/src/f_wipe.c index ab869ca60..6014fb7f9 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/filesrch.c b/src/filesrch.c index 23b8e7f40..9ee64f5ba 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -39,6 +39,7 @@ #define SUFFIX "*" #define SLASH "\\" +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #ifndef INVALID_FILE_ATTRIBUTES @@ -307,6 +308,39 @@ closedir (DIR * dirp) } #endif +// fopen but it REALLY only works on regular files +// Turns out, on linux, anyway, you can fopen directories +// in read mode. (It's supposed to fail in write mode +// though!!) +FILE *fopenfile(const char *path, const char *mode) +{ + FILE *h = fopen(path, mode); + + if (h != NULL) + { + struct stat st; + int eno; + + if (fstat(fileno(h), &st) == -1) + { + eno = errno; + } + else if (!S_ISREG(st.st_mode)) + { + eno = EACCES; // set some kinda error + } + else + { + return h; // ok + } + + fclose(h); + errno = eno; + } + + return NULL; +} + static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"}, #if 1 {1, "HOME"}, {2, "SRB2"}, diff --git a/src/g_demo.c b/src/g_demo.c index 2da5a76ab..0403da16d 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_demo.h b/src/g_demo.h index 37664dc71..f25315a58 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_game.c b/src/g_game.c index 349d90558..b23980044 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -96,6 +96,7 @@ SINT8 startinglivesbalance[maxgameovers+1] = {3, 5, 7, 9, 12, 15, 20, 25, 30, 40 UINT16 mainwads = 0; boolean modifiedgame; // Set if homebrew PWAD stuff has been added. boolean savemoddata = false; +boolean usedCheats = false; // Set when a gamedata-preventing cheat command is used. UINT8 paused; UINT8 modeattacking = ATTACKING_NONE; boolean disableSpeedAdjust = false; @@ -184,18 +185,6 @@ INT32 tokenbits; // Used for setting token bits // Old Special Stage INT32 sstimer; // Time allotted in the special stage -tic_t totalplaytime; -boolean gamedataloaded = false; - -// Time attack data for levels -// These are dynamically allocated for space reasons now -recorddata_t *mainrecords[NUMMAPS] = {NULL}; -nightsdata_t *nightsrecords[NUMMAPS] = {NULL}; -UINT8 mapvisited[NUMMAPS]; - -// Temporary holding place for nights data for the current map -nightsdata_t ntemprecords; - UINT32 bluescore, redscore; // CTF and Team Match team scores // ring count... for PERFECT! @@ -226,6 +215,7 @@ UINT8 ammoremovaltics = 2*TICRATE; UINT8 use1upSound = 0; UINT8 maxXtraLife = 2; // Max extra lives from rings UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scenarioes +UINT8 shareEmblems = 0; // Set to 1 to share all picked up emblems in multiplayer UINT8 introtoplay; UINT8 creditscutscene; @@ -251,11 +241,6 @@ INT32 cheats; //for multiplayer cheat commands tic_t hidetime; -// Grading -UINT32 timesBeaten; -UINT32 timesBeatenWithEmeralds; -UINT32 timesBeatenUltimate; - typedef struct joystickvector2_s { INT32 xaxis; @@ -364,36 +349,36 @@ consvar_t cv_autobrake2 = CVAR_INIT ("autobrake2", "On", CV_SAVE|CV_CALL, CV_OnO // hi here's some new controls static CV_PossibleValue_t zerotoone_cons_t[] = {{0, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}}; consvar_t cv_cam_shiftfacing[2] = { - CVAR_INIT ("cam_shiftfacingchar", "0.375", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), - CVAR_INIT ("cam2_shiftfacingchar", "0.375", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("cam_shiftfacingchar", "0.375", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, zerotoone_cons_t, NULL), + CVAR_INIT ("cam2_shiftfacingchar", "0.375", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, zerotoone_cons_t, NULL), }; consvar_t cv_cam_turnfacing[2] = { - CVAR_INIT ("cam_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), - CVAR_INIT ("cam2_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("cam_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, zerotoone_cons_t, NULL), + CVAR_INIT ("cam2_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, zerotoone_cons_t, NULL), }; consvar_t cv_cam_turnfacingability[2] = { - CVAR_INIT ("cam_turnfacingability", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), - CVAR_INIT ("cam2_turnfacingability", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("cam_turnfacingability", "0.125", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, zerotoone_cons_t, NULL), + CVAR_INIT ("cam2_turnfacingability", "0.125", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, zerotoone_cons_t, NULL), }; consvar_t cv_cam_turnfacingspindash[2] = { - CVAR_INIT ("cam_turnfacingspindash", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), - CVAR_INIT ("cam2_turnfacingspindash", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("cam_turnfacingspindash", "0.25", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, zerotoone_cons_t, NULL), + CVAR_INIT ("cam2_turnfacingspindash", "0.25", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, zerotoone_cons_t, NULL), }; consvar_t cv_cam_turnfacinginput[2] = { - CVAR_INIT ("cam_turnfacinginput", "0.375", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), - CVAR_INIT ("cam2_turnfacinginput", "0.375", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("cam_turnfacinginput", "0.375", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, zerotoone_cons_t, NULL), + CVAR_INIT ("cam2_turnfacinginput", "0.375", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, zerotoone_cons_t, NULL), }; static CV_PossibleValue_t centertoggle_cons_t[] = {{0, "Hold"}, {1, "Toggle"}, {2, "Sticky Hold"}, {0, NULL}}; consvar_t cv_cam_centertoggle[2] = { - CVAR_INIT ("cam_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL), - CVAR_INIT ("cam2_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL), + CVAR_INIT ("cam_centertoggle", "Hold", CV_SAVE|CV_ALLOWLUA, centertoggle_cons_t, NULL), + CVAR_INIT ("cam2_centertoggle", "Hold", CV_SAVE|CV_ALLOWLUA, centertoggle_cons_t, NULL), }; static CV_PossibleValue_t lockedinput_cons_t[] = {{0, "Strafe"}, {1, "Turn"}, {0, NULL}}; consvar_t cv_cam_lockedinput[2] = { - CVAR_INIT ("cam_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL), - CVAR_INIT ("cam2_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL), + CVAR_INIT ("cam_lockedinput", "Strafe", CV_SAVE|CV_ALLOWLUA, lockedinput_cons_t, NULL), + CVAR_INIT ("cam2_lockedinput", "Strafe", CV_SAVE|CV_ALLOWLUA, lockedinput_cons_t, NULL), }; static CV_PossibleValue_t lockedassist_cons_t[] = { @@ -405,14 +390,14 @@ static CV_PossibleValue_t lockedassist_cons_t[] = { {0, NULL} }; consvar_t cv_cam_lockonboss[2] = { - CVAR_INIT ("cam_lockaimassist", "Full", CV_SAVE, lockedassist_cons_t, NULL), - CVAR_INIT ("cam2_lockaimassist", "Full", CV_SAVE, lockedassist_cons_t, NULL), + CVAR_INIT ("cam_lockaimassist", "Full", CV_SAVE|CV_ALLOWLUA, lockedassist_cons_t, NULL), + CVAR_INIT ("cam2_lockaimassist", "Full", CV_SAVE|CV_ALLOWLUA, lockedassist_cons_t, NULL), }; consvar_t cv_moveaxis = CVAR_INIT ("joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_sideaxis = CVAR_INIT ("joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_lookaxis = CVAR_INIT ("joyaxis_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_lookaxis = CVAR_INIT ("joyaxis_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_jumpaxis = CVAR_INIT ("joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_spinaxis = CVAR_INIT ("joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_fireaxis = CVAR_INIT ("joyaxis_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL); @@ -422,8 +407,8 @@ consvar_t cv_digitaldeadzone = CVAR_INIT ("joy_digdeadzone", "0.25", CV_FLOAT|CV consvar_t cv_moveaxis2 = CVAR_INIT ("joyaxis2_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_sideaxis2 = CVAR_INIT ("joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_lookaxis2 = CVAR_INIT ("joyaxis2_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_turnaxis2 = CVAR_INIT ("joyaxis2_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_lookaxis2 = CVAR_INIT ("joyaxis2_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_turnaxis2 = CVAR_INIT ("joyaxis2_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_jumpaxis2 = CVAR_INIT ("joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_spinaxis2 = CVAR_INIT ("joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_fireaxis2 = CVAR_INIT ("joyaxis2_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL); @@ -451,86 +436,86 @@ INT16 rw_maximums[NUM_WEAPONS] = }; // Allocation for time and nights data -void G_AllocMainRecordData(INT16 i) +void G_AllocMainRecordData(INT16 i, gamedata_t *data) { - if (!mainrecords[i]) - mainrecords[i] = Z_Malloc(sizeof(recorddata_t), PU_STATIC, NULL); - memset(mainrecords[i], 0, sizeof(recorddata_t)); + if (!data->mainrecords[i]) + data->mainrecords[i] = Z_Malloc(sizeof(recorddata_t), PU_STATIC, NULL); + memset(data->mainrecords[i], 0, sizeof(recorddata_t)); } -void G_AllocNightsRecordData(INT16 i) +void G_AllocNightsRecordData(INT16 i, gamedata_t *data) { - if (!nightsrecords[i]) - nightsrecords[i] = Z_Malloc(sizeof(nightsdata_t), PU_STATIC, NULL); - memset(nightsrecords[i], 0, sizeof(nightsdata_t)); + if (!data->nightsrecords[i]) + data->nightsrecords[i] = Z_Malloc(sizeof(nightsdata_t), PU_STATIC, NULL); + memset(data->nightsrecords[i], 0, sizeof(nightsdata_t)); } // MAKE SURE YOU SAVE DATA BEFORE CALLING THIS -void G_ClearRecords(void) +void G_ClearRecords(gamedata_t *data) { INT16 i; for (i = 0; i < NUMMAPS; ++i) { - if (mainrecords[i]) + if (data->mainrecords[i]) { - Z_Free(mainrecords[i]); - mainrecords[i] = NULL; + Z_Free(data->mainrecords[i]); + data->mainrecords[i] = NULL; } - if (nightsrecords[i]) + if (data->nightsrecords[i]) { - Z_Free(nightsrecords[i]); - nightsrecords[i] = NULL; + Z_Free(data->nightsrecords[i]); + data->nightsrecords[i] = NULL; } } } // For easy retrieval of records -UINT32 G_GetBestScore(INT16 map) +UINT32 G_GetBestScore(INT16 map, gamedata_t *data) { - if (!mainrecords[map-1]) + if (!data->mainrecords[map-1]) return 0; - return mainrecords[map-1]->score; + return data->mainrecords[map-1]->score; } -tic_t G_GetBestTime(INT16 map) +tic_t G_GetBestTime(INT16 map, gamedata_t *data) { - if (!mainrecords[map-1] || mainrecords[map-1]->time <= 0) + if (!data->mainrecords[map-1] || data->mainrecords[map-1]->time <= 0) return (tic_t)UINT32_MAX; - return mainrecords[map-1]->time; + return data->mainrecords[map-1]->time; } -UINT16 G_GetBestRings(INT16 map) +UINT16 G_GetBestRings(INT16 map, gamedata_t *data) { - if (!mainrecords[map-1]) + if (!data->mainrecords[map-1]) return 0; - return mainrecords[map-1]->rings; + return data->mainrecords[map-1]->rings; } -UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare) +UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare, gamedata_t *data) { - if (!nightsrecords[map-1]) + if (!data->nightsrecords[map-1]) return 0; - return nightsrecords[map-1]->score[mare]; + return data->nightsrecords[map-1]->score[mare]; } -tic_t G_GetBestNightsTime(INT16 map, UINT8 mare) +tic_t G_GetBestNightsTime(INT16 map, UINT8 mare, gamedata_t *data) { - if (!nightsrecords[map-1] || nightsrecords[map-1]->time[mare] <= 0) + if (!data->nightsrecords[map-1] || data->nightsrecords[map-1]->time[mare] <= 0) return (tic_t)UINT32_MAX; - return nightsrecords[map-1]->time[mare]; + return data->nightsrecords[map-1]->time[mare]; } -UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare) +UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare, gamedata_t *data) { - if (!nightsrecords[map-1]) + if (!data->nightsrecords[map-1]) return 0; - return nightsrecords[map-1]->grade[mare]; + return data->nightsrecords[map-1]->grade[mare]; } // For easy adding of NiGHTS records @@ -552,7 +537,7 @@ void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare) // Update replay files/data, etc. for Record Attack // See G_SetNightsRecords for NiGHTS Attack. // -static void G_UpdateRecordReplays(void) +static void G_UpdateRecordReplays(gamedata_t *data) { const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; char *gpath; @@ -560,17 +545,17 @@ static void G_UpdateRecordReplays(void) UINT8 earnedEmblems; // Record new best time - if (!mainrecords[gamemap-1]) - G_AllocMainRecordData(gamemap-1); + if (!data->mainrecords[gamemap-1]) + G_AllocMainRecordData(gamemap-1, data); - if (players[consoleplayer].score > mainrecords[gamemap-1]->score) - mainrecords[gamemap-1]->score = players[consoleplayer].score; + if (players[consoleplayer].score > data->mainrecords[gamemap-1]->score) + data->mainrecords[gamemap-1]->score = players[consoleplayer].score; - if ((mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < mainrecords[gamemap-1]->time)) - mainrecords[gamemap-1]->time = players[consoleplayer].realtime; + if ((data->mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < data->mainrecords[gamemap-1]->time)) + data->mainrecords[gamemap-1]->time = players[consoleplayer].realtime; - if ((UINT16)(players[consoleplayer].rings) > mainrecords[gamemap-1]->rings) - mainrecords[gamemap-1]->rings = (UINT16)(players[consoleplayer].rings); + if ((UINT16)(players[consoleplayer].rings) > data->mainrecords[gamemap-1]->rings) + data->mainrecords[gamemap-1]->rings = (UINT16)(players[consoleplayer].rings); // Save demo! bestdemo[255] = '\0'; @@ -626,14 +611,14 @@ static void G_UpdateRecordReplays(void) free(gpath); // Check emblems when level data is updated - if ((earnedEmblems = M_CheckLevelEmblems())) + if ((earnedEmblems = M_CheckLevelEmblems(data))) CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for Record Attack records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); // Update timeattack menu's replay availability. Nextmap_OnChange(); } -void G_SetNightsRecords(void) +void G_SetNightsRecords(gamedata_t *data) { INT32 i; UINT32 totalscore = 0; @@ -674,9 +659,9 @@ void G_SetNightsRecords(void) { nightsdata_t *maprecords; - if (!nightsrecords[gamemap-1]) - G_AllocNightsRecordData(gamemap-1); - maprecords = nightsrecords[gamemap-1]; + if (!data->nightsrecords[gamemap-1]) + G_AllocNightsRecordData(gamemap-1, data); + maprecords = data->nightsrecords[gamemap-1]; if (maprecords->nummares != ntemprecords.nummares) maprecords->nummares = ntemprecords.nummares; @@ -738,7 +723,7 @@ void G_SetNightsRecords(void) } free(gpath); - if ((earnedEmblems = M_CheckLevelEmblems())) + if ((earnedEmblems = M_CheckLevelEmblems(data))) CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for NiGHTS records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); // If the mare count changed, this will update the score display @@ -755,7 +740,24 @@ void G_SetGameModified(boolean silent) savemoddata = false; if (!silent) - CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to record statistics.\n")); + CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to play Record Attack.\n")); + + // If in record attack recording, cancel it. + if (modeattacking) + M_EndModeAttackRun(); + else if (marathonmode) + Command_ExitGame_f(); +} + +void G_SetUsedCheats(boolean silent) +{ + if (usedCheats) + return; + + usedCheats = true; + + if (!silent) + CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to save progress.\n")); // If in record attack recording, cancel it. if (modeattacking) @@ -1383,7 +1385,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if ( P_MobjWasRemoved(ticcmd_ztargetfocus[forplayer]) || !ticcmd_ztargetfocus[forplayer]->health || - (ticcmd_ztargetfocus[forplayer]->flags2 & MF2_FRET) || (ticcmd_ztargetfocus[forplayer]->type == MT_EGGMOBILE3 && !ticcmd_ztargetfocus[forplayer]->movecount) // Sea Egg is moving around underground and shouldn't be tracked ) P_SetTarget(&ticcmd_ztargetfocus[forplayer], NULL); @@ -1959,6 +1960,85 @@ INT32 pausedelay = 0; boolean pausebreakkey = false; static INT32 camtoggledelay, camtoggledelay2 = 0; +static boolean ViewpointSwitchResponder(event_t *ev) +{ + // ViewpointSwitch Lua hook. + UINT8 canSwitchView = 0; + + INT32 direction = 0; + if (ev->key == KEY_F12 || ev->key == gamecontrol[GC_VIEWPOINTNEXT][0] || ev->key == gamecontrol[GC_VIEWPOINTNEXT][1]) + direction = 1; + if (ev->key == gamecontrol[GC_VIEWPOINTPREV][0] || ev->key == gamecontrol[GC_VIEWPOINTPREV][1]) + direction = -1; + // This enabled reverse-iterating with shift+F12, sadly I had to + // disable this in case your shift key is bound to a control =(( + //if (shiftdown) + // direction = -direction; + + // allow spy mode changes even during the demo + if (!(gamestate == GS_LEVEL && ev->type == ev_keydown && direction != 0)) + return false; + + if (splitscreen || !netgame) + { + displayplayer = consoleplayer; + return false; + } + + // spy mode + do + { + // Wrap in both directions + displayplayer += direction; + displayplayer = (displayplayer + MAXPLAYERS) % MAXPLAYERS; + + if (!playeringame[displayplayer]) + continue; + + // Call ViewpointSwitch hooks here. + canSwitchView = LUA_HookViewpointSwitch(&players[consoleplayer], &players[displayplayer], false); + if (canSwitchView == 1) // Set viewpoint to this player + break; + else if (canSwitchView == 2) // Skip this player + continue; + + if (players[displayplayer].spectator) + continue; + + if (G_GametypeHasTeams()) + { + if (players[consoleplayer].ctfteam + && players[displayplayer].ctfteam != players[consoleplayer].ctfteam) + continue; + } + else if (gametyperules & GTR_HIDEFROZEN) + { + if (players[consoleplayer].pflags & PF_TAGIT) + continue; + } + // Other Tag-based gametypes? + else if (G_TagGametype()) + { + if (!players[consoleplayer].spectator + && (players[consoleplayer].pflags & PF_TAGIT) != (players[displayplayer].pflags & PF_TAGIT)) + continue; + } + else if (G_GametypeHasSpectators() && G_RingSlingerGametype()) + { + if (!players[consoleplayer].spectator) + continue; + } + + break; + } while (displayplayer != consoleplayer); + + // change statusbar also if playing back demo + if (singledemo) + ST_changeDemoView(); + + return true; +} + // // G_Responder // Get info needed to make ticcmd_ts for the players. @@ -2043,74 +2123,8 @@ boolean G_Responder(event_t *ev) if (HU_Responder(ev)) return true; // chat ate the event - // allow spy mode changes even during the demo - if (gamestate == GS_LEVEL && ev->type == ev_keydown - && (ev->key == KEY_F12 || ev->key == gamecontrol[GC_VIEWPOINT][0] || ev->key == gamecontrol[GC_VIEWPOINT][1])) - { - // ViewpointSwitch Lua hook. - UINT8 canSwitchView = 0; - - if (splitscreen || !netgame) - displayplayer = consoleplayer; - else - { - // spy mode - do - { - displayplayer++; - if (displayplayer == MAXPLAYERS) - displayplayer = 0; - - if (!playeringame[displayplayer]) - continue; - - // Call ViewpointSwitch hooks here. - canSwitchView = LUA_HookViewpointSwitch(&players[consoleplayer], &players[displayplayer], false); - if (canSwitchView == 1) // Set viewpoint to this player - break; - else if (canSwitchView == 2) // Skip this player - continue; - - if (players[displayplayer].spectator) - continue; - - if (G_GametypeHasTeams()) - { - if (players[consoleplayer].ctfteam - && players[displayplayer].ctfteam != players[consoleplayer].ctfteam) - continue; - } - else if (gametyperules & GTR_HIDEFROZEN) - { - if (players[consoleplayer].pflags & PF_TAGIT) - continue; - } - // Other Tag-based gametypes? - else if (G_TagGametype()) - { - if (!players[consoleplayer].spectator - && (players[consoleplayer].pflags & PF_TAGIT) != (players[displayplayer].pflags & PF_TAGIT)) - continue; - } - else if (G_GametypeHasSpectators() && G_RingSlingerGametype()) - { - if (!players[consoleplayer].spectator) - continue; - } - - break; - } while (displayplayer != consoleplayer); - - // change statusbar also if playing back demo - if (singledemo) - ST_changeDemoView(); - - // tell who's the view - CONS_Printf(M_GetText("Viewpoint: %s\n"), player_names[displayplayer]); - - return true; - } - } + if (ViewpointSwitchResponder(ev)) + return true; // update keys current state G_MapEventsToControls(ev); @@ -2377,7 +2391,8 @@ void G_Ticker(boolean run) break; case GS_TIMEATTACK: - F_MenuPresTicker(run); + if (run) + F_MenuPresTicker(); break; case GS_INTRO: @@ -2425,7 +2440,8 @@ void G_Ticker(boolean run) // then intentionally fall through /* FALLTHRU */ case GS_WAITINGPLAYERS: - F_MenuPresTicker(run); + if (run) + F_MenuPresTicker(); F_TitleScreenTicker(run); break; @@ -2812,6 +2828,9 @@ void G_MovePlayerToSpawnOrStarpost(INT32 playernum) R_ResetMobjInterpolationState(players[playernum].mo); + if (players[playernum].bot) // don't reset the camera for bots + return; + if (playernum == consoleplayer) P_ResetCamera(&players[playernum], &camera); else if (playernum == secondarydisplayplayer) @@ -3136,6 +3155,9 @@ void G_DoReborn(INT32 playernum) if (resetlevel) { + // Don't give completion emblems for reloading the level... + stagefailed = true; + // reload the level from scratch if (countdowntimeup) { @@ -3805,7 +3827,7 @@ static INT16 RandMap(UINT32 tolflags, INT16 pprevmap) for (ix = 0; ix < NUMMAPS; ix++) if (mapheaderinfo[ix] && (mapheaderinfo[ix]->typeoflevel & tolflags) == tolflags && ix != pprevmap // Don't pick the same map. - && (dedicated || !M_MapLocked(ix+1)) // Don't pick locked maps. + && (dedicated || !M_MapLocked(ix+1, serverGamedata)) // Don't pick locked maps. ) okmaps[numokmaps++] = ix; @@ -3822,41 +3844,52 @@ static INT16 RandMap(UINT32 tolflags, INT16 pprevmap) // // G_UpdateVisited // -static void G_UpdateVisited(void) +static void G_UpdateVisited(gamedata_t *data, boolean silent) { boolean spec = G_IsSpecialStage(gamemap); // Update visitation flags? - if ((!modifiedgame || savemoddata) // Not modified - && !multiplayer && !demoplayback && (gametype == GT_COOP) // SP/RA/NiGHTS mode + if (!demoplayback + && G_CoopGametype() // Campaign mode && !stagefailed) // Did not fail the stage { UINT8 earnedEmblems; // Update visitation flags - mapvisited[gamemap-1] |= MV_BEATEN; + data->mapvisited[gamemap-1] |= MV_BEATEN; + // eh, what the hell if (ultimatemode) - mapvisited[gamemap-1] |= MV_ULTIMATE; + data->mapvisited[gamemap-1] |= MV_ULTIMATE; + // may seem incorrect but IS possible in what the main game uses as mp special stages, and nummaprings will be -1 in NiGHTS if (nummaprings > 0 && players[consoleplayer].rings >= nummaprings) { - mapvisited[gamemap-1] |= MV_PERFECT; + data->mapvisited[gamemap-1] |= MV_PERFECT; if (modeattacking) - mapvisited[gamemap-1] |= MV_PERFECTRA; + data->mapvisited[gamemap-1] |= MV_PERFECTRA; } + if (!spec) { // not available to special stages because they can only really be done in one order in an unmodified game, so impossible for first six and trivial for seventh if (ALL7EMERALDS(emeralds)) - mapvisited[gamemap-1] |= MV_ALLEMERALDS; + data->mapvisited[gamemap-1] |= MV_ALLEMERALDS; } - if (modeattacking == ATTACKING_RECORD) - G_UpdateRecordReplays(); - else if (modeattacking == ATTACKING_NIGHTS) - G_SetNightsRecords(); + if (silent) + { + if (modeattacking) + M_CheckLevelEmblems(data); + } + else + { + if (modeattacking == ATTACKING_RECORD) + G_UpdateRecordReplays(data); + else if (modeattacking == ATTACKING_NIGHTS) + G_SetNightsRecords(data); + } - if ((earnedEmblems = M_CompletionEmblems())) + if ((earnedEmblems = M_CompletionEmblems(data)) && !silent) CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); } } @@ -3895,14 +3928,18 @@ static void G_HandleSaveLevel(void) remove(liveeventbackup); cursaveslot = 0; } - else if ((!modifiedgame || savemoddata) && !(netgame || multiplayer || ultimatemode || demorecording || metalrecording || modeattacking)) + else if (!usedCheats && !(netgame || multiplayer || ultimatemode || demorecording || metalrecording || modeattacking)) + { G_SaveGame((UINT32)cursaveslot, spstage_start); + } } } // and doing THIS here means you don't lose your progress if you close the game mid-intermission else if (!(ultimatemode || netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) - && (!modifiedgame || savemoddata) && cursaveslot > 0 && CanSaveLevel(lastmap+1)) + && !usedCheats && cursaveslot > 0 && CanSaveLevel(lastmap+1)) + { G_SaveGame((UINT32)cursaveslot, lastmap+1); // not nextmap+1 to route around special stages + } } // @@ -4055,7 +4092,8 @@ static void G_DoCompleted(void) if ((skipstats && !modeattacking) || (modeattacking && stagefailed) || (intertype == int_none)) { - G_UpdateVisited(); + G_UpdateVisited(serverGamedata, true); + G_UpdateVisited(clientGamedata, false); G_HandleSaveLevel(); G_AfterIntermission(); } @@ -4064,7 +4102,8 @@ static void G_DoCompleted(void) G_SetGamestate(GS_INTERMISSION); Y_StartIntermission(); Y_LoadIntermissionData(); - G_UpdateVisited(); + G_UpdateVisited(serverGamedata, true); + G_UpdateVisited(clientGamedata, false); G_HandleSaveLevel(); } } @@ -4092,7 +4131,7 @@ void G_AfterIntermission(void) && stagefailed == false) { // Start a custom cutscene. - F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); + F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false, false); } else { @@ -4178,8 +4217,10 @@ static void G_DoContinued(void) tokenlist = 0; token = 0; - if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && (!modifiedgame || savemoddata) && cursaveslot > 0) + if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && !usedCheats && cursaveslot > 0) + { G_SaveGameOver((UINT32)cursaveslot, true); + } // Reset # of lives pl->lives = (ultimatemode) ? 1 : startinglivesbalance[numgameovers]; @@ -4244,13 +4285,17 @@ void G_LoadGameSettings(void) S_InitRuntimeSounds(); } +#define GAMEDATA_ID 0x86E4A27C // Change every major version, as usual +#define COMPAT_GAMEDATA_ID 0xFCAFE211 // Can be removed entirely for 2.3 + // G_LoadGameData // Loads the main data file, which stores information such as emblems found, etc. -void G_LoadGameData(void) +void G_LoadGameData(gamedata_t *data) { size_t length; INT32 i, j; - UINT8 modded = false; + + UINT32 versionID; UINT8 rtemp; //For records @@ -4261,34 +4306,45 @@ void G_LoadGameData(void) UINT8 recmares; INT32 curmare; + // Stop saving, until we successfully load it again. + data->loaded = false; + // Clear things so previously read gamedata doesn't transfer // to new gamedata - G_ClearRecords(); // main and nights records - M_ClearSecrets(); // emblems, unlocks, maps visited, etc - totalplaytime = 0; // total play time (separate from all) + G_ClearRecords(data); // main and nights records + M_ClearSecrets(data); // emblems, unlocks, maps visited, etc + data->totalplaytime = 0; // total play time (separate from all) if (M_CheckParm("-nodata")) - return; // Don't load. - - // Allow saving of gamedata beyond this point - gamedataloaded = true; - - if (M_CheckParm("-gamedata") && M_IsNextParm()) { - strlcpy(gamedatafilename, M_GetNextParm(), sizeof gamedatafilename); + // Don't load at all. + return; } if (M_CheckParm("-resetdata")) - return; // Don't load (essentially, reset). + { + // Don't load, but do save. (essentially, reset) + data->loaded = true; + return; + } length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer); - if (!length) // Aw, no game data. Their loss! + if (!length) + { + // No gamedata. We can save a new one. + data->loaded = true; return; + } save_p = savebuffer; // Version check - if (READUINT32(save_p) != 0xFCAFE211) + versionID = READUINT32(save_p); + if (versionID != GAMEDATA_ID +#ifdef COMPAT_GAMEDATA_ID // backwards compat behavior + && versionID != COMPAT_GAMEDATA_ID +#endif + ) { const char *gdfolder = "the SRB2 folder"; if (strcmp(srb2home,".")) @@ -4299,19 +4355,41 @@ void G_LoadGameData(void) I_Error("Game data is from another version of SRB2.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); } - totalplaytime = READUINT32(save_p); + data->totalplaytime = READUINT32(save_p); - modded = READUINT8(save_p); +#ifdef COMPAT_GAMEDATA_ID + if (versionID == COMPAT_GAMEDATA_ID) + { + // We'll temporarily use the old condition when loading an older file. + // The proper mod-specific hash will get saved in afterwards. + boolean modded = READUINT8(save_p); - // Aha! Someone's been screwing with the save file! - if ((modded && !savemoddata)) - goto datacorrupt; - else if (modded != true && modded != false) - goto datacorrupt; + if (modded && !savemoddata) + { + goto datacorrupt; + } + else if (modded != true && modded != false) + { + goto datacorrupt; + } + } + else +#endif + { + // Quick & dirty hash for what mod this save file is for. + UINT32 modID = READUINT32(save_p); + UINT32 expectedID = quickncasehash(timeattackfolder, sizeof timeattackfolder); + + if (modID != expectedID) + { + // Aha! Someone's been screwing with the save file! + goto datacorrupt; + } + } // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - if ((mapvisited[i] = READUINT8(save_p)) > MV_MAX) + if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX) goto datacorrupt; // To save space, use one bit per collected/achieved/unlocked flag @@ -4319,34 +4397,34 @@ void G_LoadGameData(void) { rtemp = READUINT8(save_p); for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) - emblemlocations[j+i].collected = ((rtemp >> j) & 1); + data->collected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXEXTRAEMBLEMS;) { rtemp = READUINT8(save_p); for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) - extraemblems[j+i].collected = ((rtemp >> j) & 1); + data->extraCollected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXUNLOCKABLES;) { rtemp = READUINT8(save_p); for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) - unlockables[j+i].unlocked = ((rtemp >> j) & 1); + data->unlocked[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXCONDITIONSETS;) { rtemp = READUINT8(save_p); for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) - conditionSets[j+i].achieved = ((rtemp >> j) & 1); + data->achieved[j+i] = ((rtemp >> j) & 1); i += j; } - timesBeaten = READUINT32(save_p); - timesBeatenWithEmeralds = READUINT32(save_p); - timesBeatenUltimate = READUINT32(save_p); + data->timesBeaten = READUINT32(save_p); + data->timesBeatenWithEmeralds = READUINT32(save_p); + data->timesBeatenUltimate = READUINT32(save_p); // Main records for (i = 0; i < NUMMAPS; ++i) @@ -4361,10 +4439,10 @@ void G_LoadGameData(void) if (recscore || rectime || recrings) { - G_AllocMainRecordData((INT16)i); - mainrecords[i]->score = recscore; - mainrecords[i]->time = rectime; - mainrecords[i]->rings = recrings; + G_AllocMainRecordData((INT16)i, data); + data->mainrecords[i]->score = recscore; + data->mainrecords[i]->time = rectime; + data->mainrecords[i]->rings = recrings; } } @@ -4374,27 +4452,36 @@ void G_LoadGameData(void) if ((recmares = READUINT8(save_p)) == 0) continue; - G_AllocNightsRecordData((INT16)i); + G_AllocNightsRecordData((INT16)i, data); for (curmare = 0; curmare < (recmares+1); ++curmare) { - nightsrecords[i]->score[curmare] = READUINT32(save_p); - nightsrecords[i]->grade[curmare] = READUINT8(save_p); - nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); + data->nightsrecords[i]->score[curmare] = READUINT32(save_p); + data->nightsrecords[i]->grade[curmare] = READUINT8(save_p); + data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); - if (nightsrecords[i]->grade[curmare] > GRADE_S) + if (data->nightsrecords[i]->grade[curmare] > GRADE_S) + { goto datacorrupt; + } } - nightsrecords[i]->nummares = recmares; + data->nightsrecords[i]->nummares = recmares; } // done Z_Free(savebuffer); save_p = NULL; + // Don't consider loaded until it's a success! + // It used to do this much earlier, but this would cause the gamedata to + // save over itself when it I_Errors from the corruption landing point below, + // which can accidentally delete players' legitimate data if the code ever has any tiny mistakes! + data->loaded = true; + // Silent update unlockables in case they're out of sync with conditions - M_SilentUpdateUnlockablesAndEmblems(); + M_SilentUpdateUnlockablesAndEmblems(data); + M_SilentUpdateSkinAvailabilites(); return; @@ -4414,7 +4501,7 @@ void G_LoadGameData(void) // G_SaveGameData // Saves the main data file, which stores information such as emblems found, etc. -void G_SaveGameData(void) +void G_SaveGameData(gamedata_t *data) { size_t length; INT32 i, j; @@ -4422,7 +4509,7 @@ void G_SaveGameData(void) INT32 curmare; - if (!gamedataloaded) + if (!data->loaded) return; // If never loaded (-nodata), don't save save_p = savebuffer = (UINT8 *)malloc(GAMEDATASIZE); @@ -4432,7 +4519,7 @@ void G_SaveGameData(void) return; } - if (modifiedgame && !savemoddata) + if (usedCheats) { free(savebuffer); save_p = savebuffer = NULL; @@ -4440,23 +4527,22 @@ void G_SaveGameData(void) } // Version test - WRITEUINT32(save_p, 0xFCAFE211); + WRITEUINT32(save_p, GAMEDATA_ID); - WRITEUINT32(save_p, totalplaytime); + WRITEUINT32(save_p, data->totalplaytime); - btemp = (UINT8)(savemoddata || modifiedgame); - WRITEUINT8(save_p, btemp); + WRITEUINT32(save_p, quickncasehash(timeattackfolder, sizeof timeattackfolder)); // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - WRITEUINT8(save_p, (mapvisited[i] & MV_MAX)); + WRITEUINT8(save_p, (data->mapvisited[i] & MV_MAX)); // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < MAXEMBLEMS;) { btemp = 0; for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) - btemp |= (emblemlocations[j+i].collected << j); + btemp |= (data->collected[j+i] << j); WRITEUINT8(save_p, btemp); i += j; } @@ -4464,7 +4550,7 @@ void G_SaveGameData(void) { btemp = 0; for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) - btemp |= (extraemblems[j+i].collected << j); + btemp |= (data->extraCollected[j+i] << j); WRITEUINT8(save_p, btemp); i += j; } @@ -4472,7 +4558,7 @@ void G_SaveGameData(void) { btemp = 0; for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) - btemp |= (unlockables[j+i].unlocked << j); + btemp |= (data->unlocked[j+i] << j); WRITEUINT8(save_p, btemp); i += j; } @@ -4480,23 +4566,23 @@ void G_SaveGameData(void) { btemp = 0; for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) - btemp |= (conditionSets[j+i].achieved << j); + btemp |= (data->achieved[j+i] << j); WRITEUINT8(save_p, btemp); i += j; } - WRITEUINT32(save_p, timesBeaten); - WRITEUINT32(save_p, timesBeatenWithEmeralds); - WRITEUINT32(save_p, timesBeatenUltimate); + WRITEUINT32(save_p, data->timesBeaten); + WRITEUINT32(save_p, data->timesBeatenWithEmeralds); + WRITEUINT32(save_p, data->timesBeatenUltimate); // Main records for (i = 0; i < NUMMAPS; i++) { - if (mainrecords[i]) + if (data->mainrecords[i]) { - WRITEUINT32(save_p, mainrecords[i]->score); - WRITEUINT32(save_p, mainrecords[i]->time); - WRITEUINT16(save_p, mainrecords[i]->rings); + WRITEUINT32(save_p, data->mainrecords[i]->score); + WRITEUINT32(save_p, data->mainrecords[i]->time); + WRITEUINT16(save_p, data->mainrecords[i]->rings); } else { @@ -4510,19 +4596,19 @@ void G_SaveGameData(void) // NiGHTS records for (i = 0; i < NUMMAPS; i++) { - if (!nightsrecords[i] || !nightsrecords[i]->nummares) + if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares) { WRITEUINT8(save_p, 0); continue; } - WRITEUINT8(save_p, nightsrecords[i]->nummares); + WRITEUINT8(save_p, data->nightsrecords[i]->nummares); - for (curmare = 0; curmare < (nightsrecords[i]->nummares + 1); ++curmare) + for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare) { - WRITEUINT32(save_p, nightsrecords[i]->score[curmare]); - WRITEUINT8(save_p, nightsrecords[i]->grade[curmare]); - WRITEUINT32(save_p, nightsrecords[i]->time[curmare]); + WRITEUINT32(save_p, data->nightsrecords[i]->score[curmare]); + WRITEUINT8(save_p, data->nightsrecords[i]->grade[curmare]); + WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]); } } @@ -4942,7 +5028,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean imcontinuing = false; if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene. - F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer); + F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer, FLS); else G_DoLoadLevel(resetplayer); diff --git a/src/g_game.h b/src/g_game.h index dca043f2e..6cda7ca9c 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,6 +19,7 @@ #include "d_event.h" #include "g_demo.h" #include "m_cheat.h" // objectplacing +#include "m_cond.h" extern char gamedatafilename[64]; extern char timeattackfolder[64]; @@ -183,7 +184,7 @@ boolean G_IsTitleCardAvailable(void); // Can be called by the startup code or M_Responder, calls P_SetupLevel. void G_LoadGame(UINT32 slot, INT16 mapoverride); -void G_SaveGameData(void); +void G_SaveGameData(gamedata_t *data); void G_SaveGame(UINT32 slot, INT16 mapnum); @@ -239,27 +240,28 @@ void G_SetModeAttackRetryFlag(void); void G_ClearModeAttackRetryFlag(void); boolean G_GetModeAttackRetryFlag(void); -void G_LoadGameData(void); +void G_LoadGameData(gamedata_t *data); void G_LoadGameSettings(void); void G_SetGameModified(boolean silent); +void G_SetUsedCheats(boolean silent); void G_SetGamestate(gamestate_t newstate); // Gamedata record shit -void G_AllocMainRecordData(INT16 i); -void G_AllocNightsRecordData(INT16 i); -void G_ClearRecords(void); +void G_AllocMainRecordData(INT16 i, gamedata_t *data); +void G_AllocNightsRecordData(INT16 i, gamedata_t *data); +void G_ClearRecords(gamedata_t *data); -UINT32 G_GetBestScore(INT16 map); -tic_t G_GetBestTime(INT16 map); -UINT16 G_GetBestRings(INT16 map); -UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare); -tic_t G_GetBestNightsTime(INT16 map, UINT8 mare); -UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare); +UINT32 G_GetBestScore(INT16 map, gamedata_t *data); +tic_t G_GetBestTime(INT16 map, gamedata_t *data); +UINT16 G_GetBestRings(INT16 map, gamedata_t *data); +UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare, gamedata_t *data); +tic_t G_GetBestNightsTime(INT16 map, UINT8 mare, gamedata_t *data); +UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare, gamedata_t *data); void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare); -void G_SetNightsRecords(void); +void G_SetNightsRecords(gamedata_t *data); FUNCMATH INT32 G_TicsToHours(tic_t tics); FUNCMATH INT32 G_TicsToMinutes(tic_t tics, boolean full); diff --git a/src/g_input.c b/src/g_input.c index 7bb2e799d..826dcecbd 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -593,7 +593,8 @@ static const char *gamecontrolname[NUM_GAMECONTROLS] = "systemmenu", "screenshot", "recordgif", - "viewpoint", + "viewpoint", // Rename this to "viewpointnext" for the next major version + "viewpointprev", "custom1", "custom2", "custom3", @@ -713,61 +714,61 @@ void G_DefineDefaultControls(void) for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0) { - gamecontroldefault[i][GC_WEAPONNEXT ][0] = KEY_MOUSEWHEELUP+0; - gamecontroldefault[i][GC_WEAPONPREV ][0] = KEY_MOUSEWHEELDOWN+0; - gamecontroldefault[i][GC_WEPSLOT1 ][0] = '1'; - gamecontroldefault[i][GC_WEPSLOT2 ][0] = '2'; - gamecontroldefault[i][GC_WEPSLOT3 ][0] = '3'; - gamecontroldefault[i][GC_WEPSLOT4 ][0] = '4'; - gamecontroldefault[i][GC_WEPSLOT5 ][0] = '5'; - gamecontroldefault[i][GC_WEPSLOT6 ][0] = '6'; - gamecontroldefault[i][GC_WEPSLOT7 ][0] = '7'; - gamecontroldefault[i][GC_WEPSLOT8 ][0] = '8'; - gamecontroldefault[i][GC_WEPSLOT9 ][0] = '9'; - gamecontroldefault[i][GC_WEPSLOT10 ][0] = '0'; - gamecontroldefault[i][GC_TOSSFLAG ][0] = '\''; - gamecontroldefault[i][GC_CAMTOGGLE ][0] = 'v'; - gamecontroldefault[i][GC_CAMRESET ][0] = 'r'; - gamecontroldefault[i][GC_TALKKEY ][0] = 't'; - gamecontroldefault[i][GC_TEAMKEY ][0] = 'y'; - gamecontroldefault[i][GC_SCORES ][0] = KEY_TAB; - gamecontroldefault[i][GC_CONSOLE ][0] = KEY_CONSOLE; - gamecontroldefault[i][GC_PAUSE ][0] = 'p'; - gamecontroldefault[i][GC_SCREENSHOT ][0] = KEY_F8; - gamecontroldefault[i][GC_RECORDGIF ][0] = KEY_F9; - gamecontroldefault[i][GC_VIEWPOINT ][0] = KEY_F12; + gamecontroldefault[i][GC_WEAPONNEXT ][0] = KEY_MOUSEWHEELUP+0; + gamecontroldefault[i][GC_WEAPONPREV ][0] = KEY_MOUSEWHEELDOWN+0; + gamecontroldefault[i][GC_WEPSLOT1 ][0] = '1'; + gamecontroldefault[i][GC_WEPSLOT2 ][0] = '2'; + gamecontroldefault[i][GC_WEPSLOT3 ][0] = '3'; + gamecontroldefault[i][GC_WEPSLOT4 ][0] = '4'; + gamecontroldefault[i][GC_WEPSLOT5 ][0] = '5'; + gamecontroldefault[i][GC_WEPSLOT6 ][0] = '6'; + gamecontroldefault[i][GC_WEPSLOT7 ][0] = '7'; + gamecontroldefault[i][GC_WEPSLOT8 ][0] = '8'; + gamecontroldefault[i][GC_WEPSLOT9 ][0] = '9'; + gamecontroldefault[i][GC_WEPSLOT10 ][0] = '0'; + gamecontroldefault[i][GC_TOSSFLAG ][0] = '\''; + gamecontroldefault[i][GC_CAMTOGGLE ][0] = 'v'; + gamecontroldefault[i][GC_CAMRESET ][0] = 'r'; + gamecontroldefault[i][GC_TALKKEY ][0] = 't'; + gamecontroldefault[i][GC_TEAMKEY ][0] = 'y'; + gamecontroldefault[i][GC_SCORES ][0] = KEY_TAB; + gamecontroldefault[i][GC_CONSOLE ][0] = KEY_CONSOLE; + gamecontroldefault[i][GC_PAUSE ][0] = 'p'; + gamecontroldefault[i][GC_SCREENSHOT ][0] = KEY_F8; + gamecontroldefault[i][GC_RECORDGIF ][0] = KEY_F9; + gamecontroldefault[i][GC_VIEWPOINTNEXT][0] = KEY_F12; // Gamepad controls -- same for both schemes - gamecontroldefault[i][GC_JUMP ][1] = KEY_JOY1+0; // A - gamecontroldefault[i][GC_SPIN ][1] = KEY_JOY1+2; // X - gamecontroldefault[i][GC_CUSTOM1 ][1] = KEY_JOY1+1; // B - gamecontroldefault[i][GC_CUSTOM2 ][1] = KEY_JOY1+3; // Y - gamecontroldefault[i][GC_CUSTOM3 ][1] = KEY_JOY1+8; // Left Stick - gamecontroldefault[i][GC_CENTERVIEW ][1] = KEY_JOY1+9; // Right Stick - gamecontroldefault[i][GC_WEAPONPREV ][1] = KEY_JOY1+4; // LB - gamecontroldefault[i][GC_WEAPONNEXT ][1] = KEY_JOY1+5; // RB - gamecontroldefault[i][GC_SCREENSHOT ][1] = KEY_JOY1+6; // Back - gamecontroldefault[i][GC_SYSTEMMENU ][0] = KEY_JOY1+7; // Start - gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_HAT1+0; // D-Pad Up - gamecontroldefault[i][GC_VIEWPOINT ][1] = KEY_HAT1+1; // D-Pad Down - gamecontroldefault[i][GC_TOSSFLAG ][1] = KEY_HAT1+2; // D-Pad Left - gamecontroldefault[i][GC_SCORES ][1] = KEY_HAT1+3; // D-Pad Right + gamecontroldefault[i][GC_JUMP ][1] = KEY_JOY1+0; // A + gamecontroldefault[i][GC_SPIN ][1] = KEY_JOY1+2; // X + gamecontroldefault[i][GC_CUSTOM1 ][1] = KEY_JOY1+1; // B + gamecontroldefault[i][GC_CUSTOM2 ][1] = KEY_JOY1+3; // Y + gamecontroldefault[i][GC_CUSTOM3 ][1] = KEY_JOY1+8; // Left Stick + gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_JOY1+4; // LB + gamecontroldefault[i][GC_CENTERVIEW ][1] = KEY_JOY1+5; // RB + gamecontroldefault[i][GC_SCREENSHOT ][1] = KEY_JOY1+6; // Back + gamecontroldefault[i][GC_SYSTEMMENU ][0] = KEY_JOY1+7; // Start + gamecontroldefault[i][GC_WEAPONPREV ][1] = KEY_HAT1+2; // D-Pad Left + gamecontroldefault[i][GC_WEAPONNEXT ][1] = KEY_HAT1+3; // D-Pad Right + gamecontroldefault[i][GC_VIEWPOINTNEXT][1] = KEY_JOY1+9; // Right Stick + gamecontroldefault[i][GC_TOSSFLAG ][1] = KEY_HAT1+0; // D-Pad Up + gamecontroldefault[i][GC_SCORES ][1] = KEY_HAT1+1; // D-Pad Down // Second player controls only have joypad defaults - gamecontrolbisdefault[i][GC_JUMP ][1] = KEY_2JOY1+0; // A - gamecontrolbisdefault[i][GC_SPIN ][1] = KEY_2JOY1+2; // X - gamecontrolbisdefault[i][GC_CUSTOM1 ][1] = KEY_2JOY1+1; // B - gamecontrolbisdefault[i][GC_CUSTOM2 ][1] = KEY_2JOY1+3; // Y - gamecontrolbisdefault[i][GC_CUSTOM3 ][1] = KEY_2JOY1+8; // Left Stick - gamecontrolbisdefault[i][GC_CENTERVIEW ][1] = KEY_2JOY1+9; // Right Stick - gamecontrolbisdefault[i][GC_WEAPONPREV ][1] = KEY_2JOY1+4; // LB - gamecontrolbisdefault[i][GC_WEAPONNEXT ][1] = KEY_2JOY1+5; // RB - gamecontrolbisdefault[i][GC_SCREENSHOT ][1] = KEY_2JOY1+6; // Back - //gamecontrolbisdefault[i][GC_SYSTEMMENU ][0] = KEY_2JOY1+7; // Start - gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = KEY_2HAT1+0; // D-Pad Up - gamecontrolbisdefault[i][GC_VIEWPOINT ][1] = KEY_2HAT1+1; // D-Pad Down - gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = KEY_2HAT1+2; // D-Pad Left - //gamecontrolbisdefault[i][GC_SCORES ][1] = KEY_2HAT1+3; // D-Pad Right + gamecontrolbisdefault[i][GC_JUMP ][1] = KEY_2JOY1+0; // A + gamecontrolbisdefault[i][GC_SPIN ][1] = KEY_2JOY1+2; // X + gamecontrolbisdefault[i][GC_CUSTOM1 ][1] = KEY_2JOY1+1; // B + gamecontrolbisdefault[i][GC_CUSTOM2 ][1] = KEY_2JOY1+3; // Y + gamecontrolbisdefault[i][GC_CUSTOM3 ][1] = KEY_2JOY1+8; // Left Stick + gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = KEY_2JOY1+4; // LB + gamecontrolbisdefault[i][GC_CENTERVIEW ][1] = KEY_2JOY1+5; // RB + gamecontrolbisdefault[i][GC_SCREENSHOT ][1] = KEY_2JOY1+6; // Back + //gamecontrolbisdefault[i][GC_SYSTEMMENU ][0] = KEY_2JOY1+7; // Start + gamecontrolbisdefault[i][GC_WEAPONPREV ][1] = KEY_2HAT1+2; // D-Pad Left + gamecontrolbisdefault[i][GC_WEAPONNEXT ][1] = KEY_2HAT1+3; // D-Pad Right + gamecontrolbisdefault[i][GC_VIEWPOINTNEXT][1] = KEY_2JOY1+9; // Right Stick + gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = KEY_2HAT1+0; // D-Pad Up + //gamecontrolbisdefault[i][GC_SCORES ][1] = KEY_2HAT1+1; // D-Pad Down } } @@ -992,7 +993,7 @@ static void setcontrol(INT32 (*gc)[2]) { INT32 numctrl; const char *namectrl; - INT32 keynum, keynum1, keynum2; + INT32 keynum, keynum1, keynum2 = 0; INT32 player = ((void*)gc == (void*)&gamecontrolbis ? 1 : 0); boolean nestedoverride = false; @@ -1008,7 +1009,8 @@ static void setcontrol(INT32 (*gc)[2]) return; } keynum1 = G_KeyNameToNum(COM_Argv(2)); - keynum2 = G_KeyNameToNum(COM_Argv(3)); + if (COM_Argc() > 3) + keynum2 = G_KeyNameToNum(COM_Argv(3)); keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride); if (keynum >= 0) diff --git a/src/g_input.h b/src/g_input.h index bf6ad39b3..e9c909e6e 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -96,7 +96,8 @@ typedef enum GC_SYSTEMMENU, GC_SCREENSHOT, GC_RECORDGIF, - GC_VIEWPOINT, + GC_VIEWPOINTNEXT, + GC_VIEWPOINTPREV, GC_CUSTOM1, // Lua scriptable GC_CUSTOM2, // Lua scriptable GC_CUSTOM3, // Lua scriptable diff --git a/src/g_state.h b/src/g_state.h index a6ac1970d..8f97930bb 100644 --- a/src/g_state.h +++ b/src/g_state.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index f9c6542ae..d1b84a5ee 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by Sonic Team Junior. +// Copyright (C) 2020-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h index df5c478a3..c7fd7afe3 100644 --- a/src/hardware/hw_batching.h +++ b/src/hardware/hw_batching.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by Sonic Team Junior. +// Copyright (C) 2020-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 3e207025c..d6245df64 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_data.h b/src/hardware/hw_data.h index ceefe9abd..af65a4e65 100644 --- a/src/hardware/hw_data.h +++ b/src/hardware/hw_data.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index fca9b80a3..b0859f478 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-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index ada2a6bf8..eb0b9e332 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 3b9b8681c..426d2f283 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 1ec9101c3..b5daba822 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -88,7 +88,7 @@ typedef struct gl_vissprite_s //Hurdler: 25/04/2000: now support colormap in hardware mode UINT8 *colormap; - INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing + INT32 dispoffset; // copy of mobj->dispoffset, affects ordering but not drawing patch_t *gpatch; mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out. diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index eb3c9bbbb..c1f0b3407 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-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_light.h b/src/hardware/hw_light.h index a0a9e93ad..e9d87933d 100644 --- a/src/hardware/hw_light.h +++ b/src/hardware/hw_light.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c1043f8bb..f6bbf01b9 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-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1153,7 +1153,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom else texturevpeg = gl_backsector->ceilingheight + textureheight[gl_toptexture] - gl_frontsector->ceilingheight; - texturevpeg += gl_sidedef->rowoffset; + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_top; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway texturevpeg %= textureheight[gl_toptexture]; @@ -1162,8 +1162,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_frontsector->ceilingheight - gl_backsector->ceilingheight) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_top) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_top) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1213,7 +1213,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom else texturevpeg = gl_frontsector->floorheight - gl_backsector->floorheight; - texturevpeg += gl_sidedef->rowoffset; + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_bot; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway texturevpeg %= textureheight[gl_bottomtexture]; @@ -1222,8 +1222,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_backsector->floorheight - gl_frontsector->floorheight) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_bot) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_bot) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1333,13 +1333,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // Peg it to the floor if (gl_linedef->flags & ML_MIDPEG) { - polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset; + polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; polytop = polybottom + midtexheight; } // Peg it to the ceiling else { - polytop = min(front->ceilingheight, back->ceilingheight) + gl_sidedef->rowoffset; + polytop = min(front->ceilingheight, back->ceilingheight) + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; polybottom = polytop - midtexheight; } @@ -1350,9 +1350,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // Skew the texture, but peg it to the floor else if (gl_linedef->flags & ML_MIDPEG) { - polybottom = popenbottom + gl_sidedef->rowoffset; + polybottom = popenbottom + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; polytop = polybottom + midtexheight; - polybottomslope = popenbottomslope + gl_sidedef->rowoffset; + polybottomslope = popenbottomslope + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; polytopslope = polybottomslope + midtexheight; } // Skew it according to the ceiling's slope @@ -1407,12 +1407,12 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // Left side wallVerts[3].t = texturevpeg * grTex->scaleY; wallVerts[0].t = (h - l + texturevpeg) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX; // Right side wallVerts[2].t = texturevpegslope * grTex->scaleY; wallVerts[1].t = (hS - lS + texturevpegslope) * grTex->scaleY; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX; // set top/bottom coords // Take the texture peg into account, rather than changing the offsets past @@ -1474,19 +1474,19 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // PEGGING if ((gl_linedef->flags & (ML_DONTPEGBOTTOM|ML_NOSKEW)) == (ML_DONTPEGBOTTOM|ML_NOSKEW)) - texturevpeg = gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight + gl_sidedef->rowoffset; + texturevpeg = gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; else if (gl_linedef->flags & ML_DONTPEGBOTTOM) - texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset; + texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; else // top of texture at top - texturevpeg = gl_sidedef->rowoffset; + texturevpeg = gl_sidedef->rowoffset + gl_sidedef->offsety_mid; grTex = HWR_GetTexture(gl_midtexture); wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_frontsector->ceilingheight - gl_frontsector->floorheight) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX; // Texture correction for slopes if (gl_linedef->flags & ML_NOSKEW) { @@ -1634,13 +1634,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // -- Monster Iestyn 26/06/18 if (newline) { - texturevpeg = sides[newline->sidenum[0]].rowoffset; + texturevpeg = sides[newline->sidenum[0]].rowoffset + sides[newline->sidenum[0]].offsety_mid; attachtobottom = !!(newline->flags & ML_DONTPEGBOTTOM); slopeskew = !!(newline->flags & ML_SKEWTD); } else { - texturevpeg = sides[rover->master->sidenum[0]].rowoffset; + texturevpeg = sides[rover->master->sidenum[0]].rowoffset + sides[rover->master->sidenum[0]].offsety_mid; attachtobottom = !!(gl_linedef->flags & ML_DONTPEGBOTTOM); slopeskew = !!(rover->master->flags & ML_SKEWTD); } @@ -1672,8 +1672,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } } - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX; } if (rover->fofflags & FOF_FOG) { @@ -1785,17 +1785,17 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (newline) { - wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset) * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset)) * grTex->scaleY; + wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset + sides[newline->sidenum[0]].offsety_mid) * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset) + sides[newline->sidenum[0]].offsety_mid) * grTex->scaleY; } else { - wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset) * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset)) * grTex->scaleY; + wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset + sides[rover->master->sidenum[0]].offsety_mid) * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset + sides[rover->master->sidenum[0]].offsety_mid)) * grTex->scaleY; } - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX; } if (rover->fofflags & FOF_FOG) @@ -3606,6 +3606,8 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) scalemul = FixedMul(FRACUNIT - floordiff/640, scale); scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height); + if ((thing->scale != thing->old_scale) && (thing->scale >= FRACUNIT/1024)) // Interpolate shadows when scaling mobjs + scalemul = FixedMul(scalemul, FixedDiv(interp.scale, thing->scale)); fscale = FIXED_TO_FLOAT(scalemul); fx = FIXED_TO_FLOAT(interp.x); @@ -4102,7 +4104,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) scale *= spr->shadowscale; if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) - angle = spr->angle; + angle = spr->mobj->angle; else angle = viewangle; @@ -4157,8 +4159,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) // Translate for (i = 0; i < 4; i++) { - wallVerts[i].x = rotated[i].x + spr->x1; - wallVerts[i].z = rotated[i].y + spr->z1; + wallVerts[i].x = rotated[i].x + FIXED_TO_FLOAT(spr->mobj->x); + wallVerts[i].z = rotated[i].y + FIXED_TO_FLOAT(spr->mobj->y); } if (renderflags & (RF_SLOPESPLAT | RF_OBJECTSLOPESPLAT)) @@ -5031,7 +5033,7 @@ static void HWR_ProjectSprite(mobj_t *thing) return; } - dispoffset = thing->info->dispoffset; + dispoffset = thing->dispoffset; if (R_UsingFrameInterpolation() && !paused) @@ -5180,7 +5182,15 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->rollangle && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { - rollangle = R_GetRollAngle(thing->rollangle); + if (papersprite) + { + // a positive rollangle should should pitch papersprites upwards relative to their facing angle + rollangle = R_GetRollAngle(InvAngle(thing->rollangle)); + } + else + { + rollangle = R_GetRollAngle(thing->rollangle); + } rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); if (rotsprite != NULL) @@ -5232,9 +5242,9 @@ static void HWR_ProjectSprite(mobj_t *thing) if (caster && !P_MobjWasRemoved(caster)) { - interpmobjstate_t casterinterp = {}; + interpmobjstate_t casterinterp = { 0 }; fixed_t groundz; - fixed_t floordiff; + fixed_t floordiff; if (R_UsingFrameInterpolation() && !paused) { @@ -5244,7 +5254,7 @@ static void HWR_ProjectSprite(mobj_t *thing) { R_InterpolateMobjState(caster, FRACUNIT, &casterinterp); } - + groundz = R_GetShadowZ(thing, NULL); floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? caster->height : 0) + casterinterp.z - groundz); @@ -5340,7 +5350,7 @@ static void HWR_ProjectSprite(mobj_t *thing) if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) { - interpmobjstate_t tracer_interp = {}; + interpmobjstate_t tracer_interp = { 0 }; if (! R_ThingVisible(thing->tracer)) return; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index cd822c0c1..4a1b412fc 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index f33d67bbb..38e8e8fc4 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1660,7 +1660,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) #endif // SRB2CBTODO: MD2 scaling support - finalscale *= FIXED_TO_FLOAT(spr->mobj->scale); + finalscale *= FIXED_TO_FLOAT(interp.scale); p.flip = atransform.flip; #ifdef USE_FTRANSFORM_MIRROR diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 966ed016b..f1cca763c 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/r_opengl/r_opengl-vc10.vcxproj b/src/hardware/r_opengl/r_opengl-vc10.vcxproj index d1f856e96..c93e47d50 100644 --- a/src/hardware/r_opengl/r_opengl-vc10.vcxproj +++ b/src/hardware/r_opengl/r_opengl-vc10.vcxproj @@ -38,51 +38,51 @@ r_opengl {51137D5C-4E81-4955-AACF-EA3092006051} r_opengl - 10.0.16299.0 + 10.0 DynamicLibrary false - v140 + v143 DynamicLibrary false - v141 + v143 true DynamicLibrary false - v140 + v143 DynamicLibrary false - v141 + v143 true DynamicLibrary false - v140 + v143 DynamicLibrary false - v141 + v143 true DynamicLibrary false - v140 + v143 DynamicLibrary false - v141 + v143 true diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 9d1630abb..569ddfee8 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1998-2022 by Sonic Team Junior. +// Copyright (C) 1998-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1130,7 +1130,7 @@ static void GLPerspective(GLfloat fovy, GLfloat aspect) const GLfloat zNear = NEAR_CLIPPING_PLANE; const GLfloat zFar = FAR_CLIPPING_PLANE; const GLfloat radians = (GLfloat)(fovy / 2.0f * M_PIl / 180.0f); - const GLfloat sine = sin(radians); + const GLfloat sine = (GLfloat)sin(radians); const GLfloat deltaZ = zFar - zNear; GLfloat cotangent; @@ -2042,9 +2042,9 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF if (Surface != NULL) { - UNIFORM_1(shader->uniforms[gluniform_lighting], Surface->LightInfo.light_level, pglUniform1f); - UNIFORM_1(shader->uniforms[gluniform_fade_start], Surface->LightInfo.fade_start, pglUniform1f); - UNIFORM_1(shader->uniforms[gluniform_fade_end], Surface->LightInfo.fade_end, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_lighting], (GLfloat)Surface->LightInfo.light_level, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_start], (GLfloat)Surface->LightInfo.fade_start, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_end], (GLfloat)Surface->LightInfo.fade_end, pglUniform1f); } UNIFORM_1(shader->uniforms[gluniform_leveltime], shader_leveltime, pglUniform1f); @@ -3038,7 +3038,7 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) if (special_splitscreen) { - used_fov = atan(tan(used_fov*M_PI/360)*0.8)*360/M_PI; + used_fov = (float)(atan(tan(used_fov*M_PI/360)*0.8)*360/M_PI); GLPerspective(used_fov, 2*ASPECT_RATIO); } else diff --git a/src/hardware/s_openal/s_openal-vc10.vcxproj b/src/hardware/s_openal/s_openal-vc10.vcxproj index 5039cd006..1480cd3d0 100644 --- a/src/hardware/s_openal/s_openal-vc10.vcxproj +++ b/src/hardware/s_openal/s_openal-vc10.vcxproj @@ -38,52 +38,52 @@ s_openal {E662D0B3-412D-4D55-A5EC-8CBD680DDCBE} s_openal - 10.0.16299.0 + 10.0 DynamicLibrary false MultiByte - v140 + v143 DynamicLibrary false MultiByte - v141 + v143 DynamicLibrary false - v140 + v143 DynamicLibrary false - v141 + v143 DynamicLibrary false MultiByte - v140 + v143 DynamicLibrary false MultiByte - v141 + v143 DynamicLibrary false - v140 + v143 DynamicLibrary false - v141 + v143 diff --git a/src/http-mserv.c b/src/http-mserv.c index b0ef37fa1..b7032e89a 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by James R. +// Copyright (C) 2020-2023 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -65,6 +65,8 @@ static I_mutex hms_api_mutex; static char *hms_server_token; +static char hms_useragent[512]; + struct HMS_buffer { CURL *curl; @@ -81,6 +83,22 @@ Contact_error (void) ); } +static void +get_user_agent(char *buf, size_t len) +{ + if (snprintf(buf, len, "%s/%s (%s; %s; %i; %i) SRB2BASE/%i", SRB2APPLICATION, VERSIONSTRING, compbranch, comprevision, MODID, MODVERSION, CODEBASE) < 0) + I_Error("http-mserv: get_user_agent failed"); +} + +static void +init_user_agent_once(void) +{ + if (hms_useragent[0] != '\0') + return; + + get_user_agent(hms_useragent, 512); +} + static size_t HMS_on_read (char *s, size_t _1, size_t n, void *userdata) { @@ -156,6 +174,8 @@ HMS_connect (const char *format, ...) I_lock_mutex(&hms_api_mutex); #endif + init_user_agent_once(); + seek = strlen(hms_api) + 1;/* + '/' */ va_start (ap, format); @@ -196,12 +216,18 @@ HMS_connect (const char *format, ...) curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + +#ifndef NO_IPV6 + if (M_CheckParm("-noipv6")) +#endif + curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read); curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer); + curl_easy_setopt(curl, CURLOPT_USERAGENT, hms_useragent); + curl_free(quack_token); free(url); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index c037abcd7..091e2b2fb 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -328,10 +328,10 @@ void HU_LoadGraphics(void) void HU_Init(void) { #ifndef NONET - COM_AddCommand("say", Command_Say_f); - COM_AddCommand("sayto", Command_Sayto_f); - COM_AddCommand("sayteam", Command_Sayteam_f); - COM_AddCommand("csay", Command_CSay_f); + COM_AddCommand("say", Command_Say_f, COM_LUA); + COM_AddCommand("sayto", Command_Sayto_f, COM_LUA); + COM_AddCommand("sayteam", Command_Sayteam_f, COM_LUA); + COM_AddCommand("csay", Command_CSay_f, COM_LUA); RegisterNetXCmd(XD_SAY, Got_Saycmd); #endif @@ -2862,18 +2862,6 @@ static void HU_DrawRankings(void) V_DrawCenteredString(256, 16, 0, va("%d", cv_pointlimit.value)); } } - else if (gametyperankings[gametype] == GT_COOP) - { - INT32 totalscore = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - totalscore += players[i].score; - } - - V_DrawCenteredString(256, 8, 0, "TOTAL SCORE"); - V_DrawCenteredString(256, 16, 0, va("%u", totalscore)); - } else { if (circuitmap) @@ -2994,9 +2982,9 @@ static void HU_DrawCoopOverlay(void) V_DrawSmallScaledPatch(148, 172, 0, tokenicon); } - if (LUA_HudEnabled(hud_tabemblems) && (!modifiedgame || savemoddata)) + if (LUA_HudEnabled(hud_tabemblems)) { - V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(), numemblems+numextraemblems)); + V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(clientGamedata), numemblems+numextraemblems)); V_DrawScaledPatch(128, 144 - emblemicon->height/4, 0, emblemicon); } @@ -3029,6 +3017,15 @@ static void HU_DrawNetplayCoopOverlay(void) V_DrawSmallScaledPatch(148, 6, 0, tokenicon); } + if (G_CoopGametype() && LUA_HudEnabled(hud_tabemblems)) + { + V_DrawCenteredString(256, 14, 0, "/"); + V_DrawString(256 + 4, 14, 0, va("%d", numemblems + numextraemblems)); + V_DrawRightAlignedString(256 - 4, 14, 0, va("%d", M_CountEmblems(clientGamedata))); + + V_DrawSmallScaledPatch(256 - (emblemicon->width / 4), 6, 0, emblemicon); + } + if (!LUA_HudEnabled(hud_coopemeralds)) return; diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 110486378..8647e4500 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_addrinfo.c b/src/i_addrinfo.c index 49aadf27d..9efaff4da 100644 --- a/src/i_addrinfo.c +++ b/src/i_addrinfo.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2022 by Sonic Team Junior. +// Copyright (C) 2011-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_addrinfo.h b/src/i_addrinfo.h index 592e693f4..79cfb05b2 100644 --- a/src/i_addrinfo.h +++ b/src/i_addrinfo.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2022 by Sonic Team Junior. +// Copyright (C) 2011-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_joy.h b/src/i_joy.h index 27584cea6..95caed4fd 100644 --- a/src/i_joy.h +++ b/src/i_joy.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_net.h b/src/i_net.h index 62b7528d5..12a07f183 100644 --- a/src/i_net.h +++ b/src/i_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -109,6 +109,17 @@ extern boolean (*I_NetCanSend)(void); */ extern void (*I_NetFreeNodenum)(INT32 nodenum); +/** + \brief split a string into address and port + + \param address string to split + + \param port double pointer to hold port component (optional) + + \return address component +*/ +extern char *I_NetSplitAddress(char *address, char **port); + /** \brief open a connection with specified address \param address address to connect to diff --git a/src/i_sound.h b/src/i_sound.h index 6358fbefb..c51d8e4f4 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_system.h b/src/i_system.h index 7153aa735..deea9f8a8 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -40,7 +40,7 @@ extern UINT8 keyboard_started; \return free memory in the system */ -UINT32 I_GetFreeMem(UINT32 *total); +size_t I_GetFreeMem(size_t *total); /** \brief Returns precise time value for performance measurement. The precise time should be a monotonically increasing counter, and will wrap. diff --git a/src/i_tcp.c b/src/i_tcp.c index 8838ba725..d95b381f4 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -340,8 +340,14 @@ static inline void I_UPnP_rem(const char *port, const char * servicetype) static const char *SOCK_AddrToStr(mysockaddr_t *sk) { - static char s[64]; // 255.255.255.255:65535 or IPv6:65535 + static char s[64]; // 255.255.255.255:65535 or + // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535 #ifdef HAVE_NTOP +#ifdef HAVE_IPV6 + int v6 = (sk->any.sa_family == AF_INET6); +#else + int v6 = 0; +#endif void *addr; if(sk->any.sa_family == AF_INET) @@ -355,14 +361,21 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) if(addr == NULL) sprintf(s, "No address"); - else if(inet_ntop(sk->any.sa_family, addr, s, sizeof (s)) == NULL) + else if(inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL) sprintf(s, "Unknown family type, error #%u", errno); #ifdef HAVE_IPV6 - else if(sk->any.sa_family == AF_INET6 && sk->ip6.sin6_port != 0) - strcat(s, va(":%d", ntohs(sk->ip6.sin6_port))); + else if(sk->any.sa_family == AF_INET6) + { + s[0] = '['; + strcat(s, "]"); + + if (sk->ip6.sin6_port != 0) + strcat(s, va(":%d", ntohs(sk->ip6.sin6_port))); + } #endif else if(sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0) strcat(s, va(":%d", ntohs(sk->ip4.sin_port))); + #else if (sk->any.sa_family == AF_INET) { @@ -427,7 +440,7 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) && (b->ip4.sin_port == 0 || (a->ip4.sin_port == b->ip4.sin_port)); #ifdef HAVE_IPV6 else if (b->any.sa_family == AF_INET6) - return memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr)) + return !memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr)) && (b->ip6.sin6_port == 0 || (a->ip6.sin6_port == b->ip6.sin6_port)); #endif else @@ -735,8 +748,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen unsigned long trueval = true; #endif mysockaddr_t straddr; - struct sockaddr_in sin; - socklen_t len = sizeof(sin); + socklen_t len = sizeof(straddr); if (s == (SOCKET_TYPE)ERRSOCKET) return (SOCKET_TYPE)ERRSOCKET; @@ -754,14 +766,12 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen } #endif - straddr.any = *addr; + memcpy(&straddr, addr, addrlen); I_OutputMsg("Binding to %s\n", SOCK_AddrToStr(&straddr)); if (family == AF_INET) { - mysockaddr_t tmpaddr; - tmpaddr.any = *addr ; - if (tmpaddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY)) + if (straddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY)) { opt = true; opts = (socklen_t)sizeof(opt); @@ -778,7 +788,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen #ifdef HAVE_IPV6 else if (family == AF_INET6) { - if (memcmp(addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL + if (memcmp(&straddr.ip6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL { opt = true; opts = (socklen_t)sizeof(opt); @@ -788,7 +798,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen // make it IPv6 ony opt = true; opts = (socklen_t)sizeof(opt); - if (setsockopt(s, SOL_SOCKET, IPV6_V6ONLY, (char *)&opt, opts)) + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, opts)) { CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore } @@ -830,10 +840,17 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10); } - if (getsockname(s, (struct sockaddr *)&sin, &len) == -1) + if (getsockname(s, &straddr.any, &len) == -1) CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n")); else - current_port = (UINT16)ntohs(sin.sin_port); + { + if (family == AF_INET) + current_port = (UINT16)ntohs(straddr.ip4.sin_port); +#ifdef HAVE_IPV6 + else if (family == AF_INET6) + current_port = (UINT16)ntohs(straddr.ip6.sin6_port); +#endif + } return s; } @@ -844,7 +861,7 @@ static boolean UDP_Socket(void) struct my_addrinfo *ai, *runp, hints; int gaie; #ifdef HAVE_IPV6 - const INT32 b_ipv6 = M_CheckParm("-ipv6"); + const INT32 b_ipv6 = !M_CheckParm("-noipv6"); #endif const char *serv; @@ -1156,6 +1173,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) SINT8 newnode = -1; struct my_addrinfo *ai = NULL, *runp, hints; int gaie; + size_t i; if (!port || !port[0]) port = DEFAULTPORT; @@ -1183,13 +1201,24 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) while (runp != NULL) { - // find ip of the server - if (sendto(mysockets[0], NULL, 0, 0, runp->ai_addr, runp->ai_addrlen) == 0) + // test ip address of server + for (i = 0; i < mysocketses; ++i) { - memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); - break; + /* sendto tests that there is a network to this + address */ + if (runp->ai_addr->sa_family == myfamily[i] && + sendto(mysockets[i], NULL, 0, 0, + runp->ai_addr, runp->ai_addrlen) == 0) + { + memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); + break; + } } - runp = runp->ai_next; + + if (i < mysocketses) + runp = runp->ai_next; + else + break; } I_freeaddrinfo(ai); return newnode; diff --git a/src/i_tcp.h b/src/i_tcp.h index b6e5b9235..ae9983bf1 100644 --- a/src/i_tcp.h +++ b/src/i_tcp.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_threads.h b/src/i_threads.h index c7b71d26c..fe6ab4fb0 100644 --- a/src/i_threads.h +++ b/src/i_threads.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by James R. +// Copyright (C) 2020-2023 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_time.c b/src/i_time.c index c1cc9dfd4..2a22503f1 100644 --- a/src/i_time.c +++ b/src/i_time.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -43,18 +43,20 @@ tic_t I_GetTime(void) void I_InitializeTime(void) { - g_time.time = 0; - g_time.timefrac = 0; - - enterprecise = 0; - oldenterprecise = 0; - tictimer = 0.0; - CV_RegisterVar(&cv_timescale); // I_StartupTimer is preserved for potential subsystems that need to setup // timing information for I_GetPreciseTime and sleeping I_StartupTimer(); + + g_time.time = 0; + g_time.timefrac = 0; + + enterprecise = I_GetPreciseTime(); + oldenterprecise = enterprecise; + entertic = 0; + oldentertics = 0; + tictimer = 0.0; } void I_UpdateTime(fixed_t timescale) diff --git a/src/i_time.h b/src/i_time.h index cab36133b..997ba7ef2 100644 --- a/src/i_time.h +++ b/src/i_time.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_video.h b/src/i_video.h index d66b2d95f..8efca5f9a 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/info.c b/src/info.c index c4c197027..abcf4b499 100644 --- a/src/info.c +++ b/src/info.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1758,14 +1758,14 @@ state_t states[NUMSTATES] = // Metal Sonic {SPR_PLAY, SPR2_STND, -1, {NULL}, 0, 0, S_METALSONIC_RACE}, // S_METALSONIC_RACE - {SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT + {SPR_METL, 4, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_FLOAT {SPR_METL, 16|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN {SPR_METL, 17, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE - {SPR_METL, 18, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER + {SPR_METL, 18, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_GATHER {SPR_METL, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH - {SPR_METL, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_NULL}, // S_METALSONIC_BOUNCE - {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE + {SPR_METL, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_METALSONIC_FLOAT}, // S_METALSONIC_BOUNCE + {SPR_METL, 14, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_BADBOUNCE {SPR_METL, 17, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT {SPR_METL, 15, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN {SPR_METL, 17, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1 @@ -3429,10 +3429,10 @@ state_t states[NUMSTATES] = {SPR_LCKN, 2|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF3 {SPR_LCKN, 3|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF4 - {SPR_TTAG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_TTAG + {SPR_TTAG, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_TTAG // CTF Sign - {SPR_GFLG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG + {SPR_GFLG, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG // Finish flag {SPR_FNSF, FF_TRANS30, -1, {NULL}, 0, 0, S_NULL}, // S_FINISHFLAG @@ -21584,68 +21584,113 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Black", {0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f}, SKINCOLOR_WHITE, 7, V_GRAYMAP, true}, // SKINCOLOR_BLACK // Desaturated - {"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER - {"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE - {"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL - {"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK - {"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT - {"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN - {"Bronze", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BRONZE - {"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN - {"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE - {"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS - {"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE - {"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER + {"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER + {"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE + {"Meteorite", { 0, 4, 8, 9, 11, 12, 14, 15, 171, 172, 173, 174, 175, 27, 29, 31}, SKINCOLOR_TOPAZ, 15, V_GRAYMAP, true}, // SKINCOLOR_METEORITE + {"Mercury", { 0, 3, 4, 7, 11, 12, 14, 15, 171, 172, 173, 155, 157, 159, 253, 254}, SKINCOLOR_ECRU, 15, V_AZUREMAP, true}, // SKINCOLOR_MERCURY + {"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL + {"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK + {"Rosewood", { 209, 210, 211, 212, 213, 214, 228, 230, 232, 234, 235, 237, 26, 27, 28, 29}, SKINCOLOR_SEPIA, 5, V_BROWNMAP, true}, // SKINCOLOR_ROSEWOOD + {"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT + {"Latte", { 48, 217, 219, 221, 223, 224, 226, 228, 68, 69, 70, 70, 44, 45, 46, 47}, SKINCOLOR_BOTTLE, 12, V_BROWNMAP, true}, // SKINCOLOR_LATTE + {"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN + {"Boulder", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BOULDER + {"Bronze", { 82, 84, 50, 51, 223, 228, 230, 232, 234, 236, 237, 238, 239, 239, 30, 31}, SKINCOLOR_VOLCANIC, 9, V_BROWNMAP, true}, // SKINCOLOR_BRONZE + {"Sepia", { 88, 84, 85, 86, 224, 226, 228, 230, 232, 235, 236, 237, 238, 239, 28, 28}, SKINCOLOR_ROSEWOOD, 5, V_BROWNMAP, true}, // SKINCOLOR_SEPIA + {"Ecru", { 80, 83, 84, 85, 86, 242, 243, 245, 230, 232, 234, 236, 238, 239, 47, 47}, SKINCOLOR_MERCURY, 15, V_BROWNMAP, true}, // SKINCOLOR_ECRU + {"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN + {"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE + {"Rosebush", { 208, 216, 209, 85, 90, 91, 91, 92, 191, 93, 94, 107, 109, 110, 111, 111}, SKINCOLOR_EGGPLANT, 5, V_GREENMAP, true}, // SKINCOLOR_ROSEBUSH + {"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS + {"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE + {"Eggplant", { 4, 8, 11, 11, 16, 195, 195, 195, 196, 186, 187, 187, 254, 254, 30, 31}, SKINCOLOR_ROSEBUSH, 5, V_PURPLEMAP, true}, // SKINCOLOR_EGGPLANT + {"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_HEADLIGHT, 8, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER // Viv's vivid colours (toast 21/07/17) + // Tweaks & additions (Lach, sphere, Alice, MotorRoach 26/10/22) {"Ruby", {0xb0, 0xb0, 0xc9, 0xca, 0xcc, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfd}, SKINCOLOR_EMERALD, 10, V_REDMAP, true}, // SKINCOLOR_RUBY + {"Cherry", { 202, 203, 204, 205, 206, 40, 41, 42, 43, 44, 186, 187, 28, 29, 30, 31}, SKINCOLOR_MIDNIGHT, 10, V_REDMAP, true}, // SKINCOLOR_CHERRY {"Salmon", {0xd0, 0xd0, 0xd1, 0xd2, 0x20, 0x21, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e}, SKINCOLOR_FOREST, 6, V_REDMAP, true}, // SKINCOLOR_SALMON - {"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_RED + {"Pepper", { 210, 32, 33, 34, 35, 35, 36, 37, 38, 39, 41, 43, 45, 45, 46, 47}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_PEPPER + {"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_MASTER, 8, V_REDMAP, true}, // SKINCOLOR_RED {"Crimson", {0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, SKINCOLOR_ICY, 10, V_REDMAP, true}, // SKINCOLOR_CRIMSON {"Flame", {0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, SKINCOLOR_PURPLE, 8, V_REDMAP, true}, // SKINCOLOR_FLAME - {"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BRONZE, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP + {"Garnet", { 0, 83, 50, 53, 34, 35, 37, 38, 39, 40, 42, 44, 45, 46, 47, 47}, SKINCOLOR_AQUAMARINE, 6, V_REDMAP, true}, // SKINCOLOR_GARNET + {"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BOULDER, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP {"Peachy", {0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, SKINCOLOR_TEAL, 7, V_ROSYMAP, true}, // SKINCOLOR_PEACHY {"Quail", {0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, SKINCOLOR_WAVE, 5, V_BROWNMAP, true}, // SKINCOLOR_QUAIL + {"Foundation", { 80, 81, 82, 84, 219, 221, 221, 212, 213, 214, 215, 195, 196, 186, 187, 30}, SKINCOLOR_DREAM, 6, V_ORANGEMAP, true}, // SKINCOLOR_FOUNDATION {"Sunset", {0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, SKINCOLOR_SAPPHIRE, 5, V_ORANGEMAP, true}, // SKINCOLOR_SUNSET {"Copper", {0x58, 0x54, 0x40, 0x34, 0x35, 0x38, 0x3a, 0x3c, 0x3d, 0x2a, 0x2b, 0x2c, 0x2c, 0xba, 0xba, 0xbb}, SKINCOLOR_BLUEBELL, 5, V_ORANGEMAP, true}, // SKINCOLOR_COPPER {"Apricot", {0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, SKINCOLOR_CYAN, 4, V_ORANGEMAP, true}, // SKINCOLOR_APRICOT - {"Orange", {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x2c}, SKINCOLOR_BLUE, 4, V_ORANGEMAP, true}, // SKINCOLOR_ORANGE + {"Orange", { 49, 50, 51, 52, 53, 54, 55, 57, 58, 59, 60, 42, 44, 45, 46, 46}, SKINCOLOR_BLUE, 4, V_ORANGEMAP, true}, // SKINCOLOR_ORANGE + {"Pumpkin", { 51, 52, 53, 54, 56, 58, 59, 59, 61, 61, 63, 45, 46, 47, 47, 31}, SKINCOLOR_ARCTIC, 12, V_ORANGEMAP, true}, // SKINCOLOR_PUMPKIN {"Rust", {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, SKINCOLOR_YOGURT, 8, V_ORANGEMAP, true}, // SKINCOLOR_RUST - {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_GOLD + {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_MAUVE, 8, V_YELLOWMAP, true}, // SKINCOLOR_GOLD + {"Topaz", { 0, 81, 83, 73, 74, 74, 65, 52, 53, 54, 56, 58, 60, 42, 43, 45}, SKINCOLOR_METEORITE, 10, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ {"Sandy", {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, SKINCOLOR_SKY, 8, V_YELLOWMAP, true}, // SKINCOLOR_SANDY + {"Goldenrod", { 0, 80, 81, 81, 83, 73, 73, 64, 65, 66, 67, 68, 69, 62, 44, 45}, SKINCOLOR_MAJESTY, 8, V_YELLOWMAP, true}, // SKINCOLOR_GOLDENROD {"Yellow", {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, true}, // SKINCOLOR_YELLOW {"Olive", {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, SKINCOLOR_DUSK, 3, V_YELLOWMAP, true}, // SKINCOLOR_OLIVE + {"Pear", { 88, 89, 188, 189, 189, 76, 76, 67, 67, 68, 69, 70, 45, 46, 47, 47}, SKINCOLOR_MARINE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_PEAR + {"Lemon", { 0, 80, 81, 83, 73, 73, 74, 74, 76, 76, 191, 191, 79, 79, 110, 111}, SKINCOLOR_FUCHSIA, 8, V_YELLOWMAP, true}, // SKINCOLOR_LEMON {"Lime", {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_MAGENTA, 9, V_PERIDOTMAP, true}, // SKINCOLOR_LIME {"Peridot", {0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, SKINCOLOR_COBALT, 2, V_PERIDOTMAP, true}, // SKINCOLOR_PERIDOT {"Apple", {0x49, 0x49, 0xbc, 0xbd, 0xbe, 0xbe, 0xbe, 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d}, SKINCOLOR_RASPBERRY, 13, V_PERIDOTMAP, true}, // SKINCOLOR_APPLE - {"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_GREEN + {"Chartreuse", { 80, 82, 72, 73, 188, 188, 113, 114, 114, 125, 126, 137, 138, 139, 253, 254}, SKINCOLOR_NOBLE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_CHARTREUSE + {"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_PEPPER, 8, V_GREENMAP, true}, // SKINCOLOR_GREEN {"Forest", {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, SKINCOLOR_SALMON, 9, V_GREENMAP, true}, // SKINCOLOR_FOREST - {"Emerald", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_RUBY, 4, V_GREENMAP, true}, // SKINCOLOR_EMERALD + {"Shamrock", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_CRYSTAL, 10, V_GREENMAP, true}, // SKINCOLOR_SHAMROCK + {"Jade", { 128, 120, 121, 122, 122, 113, 114, 114, 115, 116, 117, 118, 119, 110, 111, 30}, SKINCOLOR_ROSY, 7, V_GREENMAP, true}, // SKINCOLOR_JADE + {"Headlight", { 0, 80, 81, 82, 73, 84, 64, 65, 91, 91, 124, 125, 126, 137, 138, 139}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_HEADLIGHT {"Mint", {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, SKINCOLOR_VIOLET, 5, V_GREENMAP, true}, // SKINCOLOR_MINT - {"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM - {"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_ROSY, 7, V_AQUAMAP, true}, // SKINCOLOR_AQUA + {"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_MASTER + {"Emerald", { 80, 96, 112, 113, 114, 114, 125, 125, 126, 126, 137, 137, 138, 138, 139, 139}, SKINCOLOR_RUBY, 9, V_GREENMAP, true}, // SKINCOLOR_EMERALD + {"Bottle", { 0, 1, 3, 4, 5, 140, 141, 141, 124, 125, 126, 127, 118, 119, 111, 111}, SKINCOLOR_LATTE, 14, V_AQUAMAP, true}, // SKINCOLOR_BOTTLE + {"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8b, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM + {"Island", { 96, 97, 113, 113, 114, 124, 142, 136, 136, 150, 151, 153, 168, 168, 169, 169}, SKINCOLOR_GALAXY, 7, V_AQUAMAP, true}, // SKINCOLOR_ISLAND + {"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_TAFFY, 10, V_AQUAMAP, true}, // SKINCOLOR_AQUA {"Teal", {0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, SKINCOLOR_PEACHY, 7, V_SKYMAP, true}, // SKINCOLOR_TEAL {"Wave", {0x00, 0x78, 0x78, 0x79, 0x8d, 0x87, 0x88, 0x89, 0x89, 0xae, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_QUAIL, 5, V_SKYMAP, true}, // SKINCOLOR_WAVE {"Cyan", {0x80, 0x81, 0xff, 0xff, 0x83, 0x83, 0x8d, 0x8d, 0x8d, 0x8e, 0x7e, 0x7f, 0x76, 0x76, 0x77, 0x6e}, SKINCOLOR_APRICOT, 6, V_SKYMAP, true}, // SKINCOLOR_CYAN + {"Turquoise", { 0, 120, 121, 122, 123, 141, 141, 135, 136, 136, 150, 153, 155, 157, 159, 253}, SKINCOLOR_SANGRIA, 12, V_SKYMAP, true}, // SKINCOLOR_TURQUOISE + {"Aquamarine", { 0, 120, 121, 131, 132, 133, 134, 134, 135, 135, 149, 149, 172, 173, 174, 175}, SKINCOLOR_GARNET, 8, V_SKYMAP, true}, // SKINCOLOR_AQUAMARINE {"Sky", {0x80, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b}, SKINCOLOR_SANDY, 1, V_SKYMAP, true}, // SKINCOLOR_SKY + {"Marine", { 144, 146, 147, 147, 148, 135, 136, 136, 137, 137, 127, 118, 119, 111, 111, 111}, SKINCOLOR_PEAR, 13, V_SKYMAP, true}, // SKINCOLOR_MARINE {"Cerulean", {0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0xfd, 0xfd, 0xfd, 0x1f, 0x1f, 0x1f}, SKINCOLOR_NEON, 4, V_SKYMAP, true}, // SKINCOLOR_CERULEAN + {"Dream", { 80, 208, 200, 200, 146, 146, 133, 134, 135, 136, 137, 138, 139, 139, 254, 254}, SKINCOLOR_FOUNDATION, 9, V_SKYMAP, true}, // SKINCOLOR_DREAM {"Icy", {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_CRIMSON, 0, V_SKYMAP, true}, // SKINCOLOR_ICY - {"Sapphire", {0x80, 0x83, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE + {"Daybreak", { 80, 81, 82, 72, 64, 9, 11, 171, 149, 150, 151, 153, 156, 157, 159, 253}, SKINCOLOR_EVENTIDE, 12, V_BLUEMAP, true}, // SKINCOLOR_DAYBREAK + {"Sapphire", {0x80, 0x82, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE + {"Arctic", { 0, 1, 3, 4, 146, 146, 147, 148, 148, 149, 150, 153, 156, 159, 253, 254}, SKINCOLOR_PUMPKIN, 6, V_BLUEMAP, true}, // SKINCOLOR_ARCTIC {"Cornflower", {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, SKINCOLOR_YELLOW, 4, V_BLUEMAP, true}, // SKINCOLOR_CORNFLOWER {"Blue", {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_ORANGE, 5, V_BLUEMAP, true}, // SKINCOLOR_BLUE - {"Cobalt", {0x93, 0x94, 0x95, 0x96, 0x98, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfd, 0xfe, 0xfe}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT + {"Cobalt", { 145, 147, 149, 150, 151, 153, 154, 155, 156, 157, 158, 159, 253, 253, 254, 254}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT + {"Midnight", { 171, 171, 172, 173, 173, 174, 155, 156, 157, 159, 253, 253, 254, 254, 31, 31}, SKINCOLOR_CHERRY, 10, V_GRAYMAP, true}, // SKINCOLOR_MIDNIGHT + {"Galaxy", { 160, 161, 162, 163, 164, 165, 166, 166, 154, 155, 156, 157, 159, 253, 254, 31}, SKINCOLOR_ISLAND, 7, V_PURPLEMAP, true}, // SKINCOLOR_GALAXY {"Vapor", {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_LILAC, 4, V_SKYMAP, true}, // SKINCOLOR_VAPOR {"Dusk", {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_OLIVE, 0, V_BLUEMAP, true}, // SKINCOLOR_DUSK + {"Majesty", { 0, 1, 176, 160, 160, 161, 162, 162, 163, 172, 173, 174, 174, 175, 139, 139}, SKINCOLOR_GOLDENROD, 9, V_PURPLEMAP, true}, // SKINCOLOR_MAJESTY {"Pastel", {0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_BUBBLEGUM, 9, V_PURPLEMAP, true}, // SKINCOLOR_PASTEL {"Purple", {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_FLAME, 7, V_PURPLEMAP, true}, // SKINCOLOR_PURPLE - {"Bubblegum", {0x00, 0xd0, 0xd0, 0xc8, 0xc8, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM + {"Noble", { 144, 146, 147, 148, 149, 164, 164, 165, 166, 185, 186, 186, 187, 187, 28, 29}, SKINCOLOR_CHARTREUSE, 12, V_PURPLEMAP, true}, // SKINCOLOR_NOBLE + {"Fuchsia", { 200, 201, 203, 204, 204, 183, 184, 184, 165, 166, 167, 168, 169, 159, 253, 254}, SKINCOLOR_LEMON, 10, V_PURPLEMAP, true}, // SKINCOLOR_FUCHSIA + {"Bubblegum", { 0, 208, 208, 176, 177, 178, 179, 180, 181, 182, 164, 166, 167, 168, 169, 253}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM + {"Crystal", { 252, 177, 179, 180, 181, 181, 182, 182, 183, 164, 166, 167, 167, 168, 169, 159}, SKINCOLOR_EMERALD, 8, V_MAGENTAMAP, true}, // SKINCOLOR_CRYSTAL {"Magenta", {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, SKINCOLOR_LIME, 6, V_MAGENTAMAP, true}, // SKINCOLOR_MAGENTA {"Neon", {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, SKINCOLOR_CERULEAN, 2, V_MAGENTAMAP, true}, // SKINCOLOR_NEON {"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET + {"Royal", { 208, 209, 192, 192, 192, 193, 193, 194, 194, 172, 173, 174, 175, 175, 139, 139}, SKINCOLOR_FANCY, 9, V_PURPLEMAP, true}, // SKINCOLOR_ROYAL {"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC + {"Mauve", { 176, 177, 178, 192, 193, 194, 195, 195, 196, 185, 185, 186, 186, 187, 187, 253}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_MAUVE + {"Eventide", { 51, 52, 53, 33, 34, 204, 183, 183, 184, 184, 166, 167, 168, 169, 253, 254}, SKINCOLOR_DAYBREAK, 13, V_MAGENTAMAP, true}, // SKINCOLOR_EVENTIDE {"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_ROSYMAP, true}, // SKINCOLOR_RASPBERRY - {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY + {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 205, 206, 207, 44, 45, 46}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_TAFFY + {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_ROSY + {"Fancy", { 0, 208, 49, 210, 210, 202, 202, 203, 204, 204, 205, 206, 207, 207, 186, 186}, SKINCOLOR_ROYAL, 9, V_ROSYMAP, true}, // SKINCOLOR_FANCY + {"Sangria", { 210, 32, 33, 34, 34, 215, 215, 207, 207, 185, 186, 186, 186, 169, 169, 253}, SKINCOLOR_TURQUOISE, 12, V_ROSYMAP, true}, // SKINCOLOR_SANGRIA + {"Volcanic", { 35, 38, 41, 42, 44, 46, 46, 169, 169, 159, 253, 254, 30, 30, 31, 31}, SKINCOLOR_BRONZE, 9, V_REDMAP, true}, // SKINCOLOR_VOLCANIC // super {"Super Silver 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03}, SKINCOLOR_BLACK, 15, 0, false}, // SKINCOLOR_SUPERSILVER1 diff --git a/src/info.h b/src/info.h index a9f68721f..502ecd726 100644 --- a/src/info.h +++ b/src/info.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/keys.h b/src/keys.h index df12c95ae..689f15fef 100644 --- a/src/keys.h +++ b/src/keys.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 29adb478a..25fa38769 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -874,6 +874,7 @@ static int lib_pGetClosestAxis(lua_State *L) static int lib_pSpawnParaloop(lua_State *L) { + mobj_t *ptmthing = tmthing; fixed_t x = luaL_checkfixed(L, 1); fixed_t y = luaL_checkfixed(L, 2); fixed_t z = luaL_checkfixed(L, 3); @@ -890,6 +891,7 @@ static int lib_pSpawnParaloop(lua_State *L) if (nstate >= NUMSTATES) return luaL_error(L, "state %d out of range (0 - %d)", nstate, NUMSTATES-1); P_SpawnParaloop(x, y, z, radius, number, type, nstate, rotangle, spawncenter); + P_SetTarget(&tmthing, ptmthing); return 0; } @@ -2261,6 +2263,18 @@ static int lib_pMobjTouchingSectorSpecial(lua_State *L) return 1; } +static int lib_pThingOnSpecial3DFloor(lua_State *L) +{ + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + INLEVEL + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + LUA_Deprecated(L, "P_ThingOnSpecial3DFloor", "P_MobjTouchingSectorSpecial\" or \"P_MobjTouchingSectorSpecialFlag"); + LUA_PushUserdata(L, P_ThingOnSpecial3DFloor(mo), META_SECTOR); + return 1; +} + static int lib_pMobjTouchingSectorSpecialFlag(lua_State *L) { mobj_t *mo = *((mobj_t**)luaL_checkudata(L, 1, META_MOBJ)); @@ -3529,7 +3543,6 @@ static int lib_gAddPlayer(lua_State *L) return 1; } - newplayernum = i; CL_ClearPlayer(newplayernum); @@ -3541,9 +3554,6 @@ static int lib_gAddPlayer(lua_State *L) newplayer->jointime = 0; newplayer->quittime = 0; - // Set the bot name (defaults to Bot #) - strcpy(player_names[newplayernum], va("Bot %d", botcount)); - // Read the skin argument (defaults to Sonic) if (!lua_isnoneornil(L, 1)) { @@ -3555,7 +3565,10 @@ static int lib_gAddPlayer(lua_State *L) if (!lua_isnoneornil(L, 2)) newplayer->skincolor = R_GetColorByName(luaL_checkstring(L, 2)); else - newplayer->skincolor = skins[newplayer->skin].prefcolor; + newplayer->skincolor = skins[skinnum].prefcolor; + + // Set the bot default name as the skin + strcpy(player_names[newplayernum], skins[skinnum].realname); // Read the bot name, if given if (!lua_isnoneornil(L, 3)) @@ -3571,14 +3584,19 @@ static int lib_gAddPlayer(lua_State *L) // Set the skin (can't do this until AFTER bot type is set!) SetPlayerSkinByNum(newplayernum, skinnum); - if (netgame) { char joinmsg[256]; + // Truncate bot name + player_names[newplayernum][sizeof(*player_names) - 8] = '\0'; // The length of colored [BOT] + 1 + strcpy(joinmsg, M_GetText("\x82*Bot %s has joined the game (player %d)")); strcpy(joinmsg, va(joinmsg, player_names[newplayernum], newplayernum)); HU_AddChatText(joinmsg, false); + + // Append blue [BOT] tag at the end + strlcat(player_names[newplayernum], "\x84[BOT]\x80", sizeof(*player_names)); } LUA_PushUserdata(L, newplayer, META_PLAYER); @@ -3612,6 +3630,16 @@ static int lib_gRemovePlayer(lua_State *L) } +static int lib_gSetUsedCheats(lua_State *L) +{ + // Let large-scale level packs using Lua be able to add cheat commands. + boolean silent = lua_optboolean(L, 1); + //NOHUD + //INLEVEL + G_SetUsedCheats(silent); + return 0; +} + static int Lcheckmapnumber (lua_State *L, int idx, const char *fun) { if (ISINLEVEL) @@ -4132,6 +4160,7 @@ static luaL_Reg lib[] = { {"P_DoSuperTransformation",lib_pDoSuperTransformation}, {"P_ExplodeMissile",lib_pExplodeMissile}, {"P_MobjTouchingSectorSpecial",lib_pMobjTouchingSectorSpecial}, + {"P_ThingOnSpecial3DFloor",lib_pThingOnSpecial3DFloor}, {"P_MobjTouchingSectorSpecialFlag",lib_pMobjTouchingSectorSpecialFlag}, {"P_PlayerTouchingSectorSpecial",lib_pPlayerTouchingSectorSpecial}, {"P_PlayerTouchingSectorSpecialFlag",lib_pPlayerTouchingSectorSpecialFlag}, @@ -4213,6 +4242,7 @@ static luaL_Reg lib[] = { {"G_AddGametype", lib_gAddGametype}, {"G_AddPlayer", lib_gAddPlayer}, {"G_RemovePlayer", lib_gRemovePlayer}, + {"G_SetUsedCheats", lib_gSetUsedCheats}, {"G_BuildMapName",lib_gBuildMapName}, {"G_BuildMapTitle",lib_gBuildMapTitle}, {"G_FindMap",lib_gFindMap}, diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index 8c63a9d6d..8d47f3dc1 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2016-2022 by Iestyn "Monster Iestyn" Jealous. -// Copyright (C) 2016-2022 by Sonic Team Junior. +// Copyright (C) 2016-2023 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2016-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 816051199..1d15b3b14 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -253,7 +253,7 @@ static int lib_comBufAddText(lua_State *L) plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); if (plr && plr != &players[consoleplayer]) return 0; - COM_BufAddTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE); + COM_BufAddTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_LUA); return 0; } @@ -269,7 +269,7 @@ static int lib_comBufInsertText(lua_State *L) plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); if (plr && plr != &players[consoleplayer]) return 0; - COM_BufInsertTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE); + COM_BufInsertTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_LUA); return 0; } @@ -450,6 +450,7 @@ static int lib_cvRegisterVar(lua_State *L) return luaL_error(L, M_GetText("Variable %s has CV_CALL without a function"), cvar->name); } + cvar->flags |= CV_ALLOWLUA; // actually time to register it to the console now! Finally! cvar->flags |= CV_MODIFIED; CV_RegisterVar(cvar); @@ -478,7 +479,7 @@ static int CVarSetFunction ){ consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR); - if (cvar->flags & CV_NOLUA) + if (!(cvar->flags & CV_ALLOWLUA)) return luaL_error(L, "Variable '%s' cannot be set from Lua.", cvar->name); switch (lua_type(L, 2)) @@ -510,7 +511,7 @@ static int lib_cvAddValue(lua_State *L) { consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR); - if (cvar->flags & CV_NOLUA) + if (!(cvar->flags & CV_ALLOWLUA)) return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name); CV_AddValue(cvar, (INT32)luaL_checknumber(L, 2)); @@ -565,27 +566,59 @@ static luaL_Reg lib[] = { {NULL, NULL} }; +enum cvar_e +{ + cvar_name, + cvar_defaultvalue, + cvar_flags, + cvar_value, + cvar_string, + cvar_changed, +}; + +static const char *const cvar_opt[] = { + "name", + "defaultvalue", + "flags", + "value", + "string", + "changed", + NULL, +}; + +static int cvar_fields_ref = LUA_NOREF; + static int cvar_get(lua_State *L) { consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR); - const char *field = luaL_checkstring(L, 2); + enum cvar_e field = Lua_optoption(L, 2, -1, cvar_fields_ref); - if(fastcmp(field,"name")) + switch (field) + { + case cvar_name: lua_pushstring(L, cvar->name); - else if(fastcmp(field,"defaultvalue")) + break; + case cvar_defaultvalue: lua_pushstring(L, cvar->defaultvalue); - else if(fastcmp(field,"flags")) + break; + case cvar_flags: lua_pushinteger(L, cvar->flags); - else if(fastcmp(field,"value")) + break; + case cvar_value: lua_pushinteger(L, cvar->value); - else if(fastcmp(field,"string")) + break; + case cvar_string: lua_pushstring(L, cvar->string); - else if(fastcmp(field,"changed")) + break; + case cvar_changed: lua_pushboolean(L, cvar->changed); - else if (devparm) - return luaL_error(L, LUA_QL("consvar_t") " has no field named " LUA_QS, field); - else - return 0; + break; + default: + if (devparm) + return luaL_error(L, LUA_QL("consvar_t") " has no field named " LUA_QS, field); + else + return 0; + } return 1; } @@ -597,6 +630,8 @@ int LUA_ConsoleLib(lua_State *L) lua_setfield(L, -2, "__index"); lua_pop(L,1); + cvar_fields_ref = Lua_CreateFieldTable(L, cvar_opt); + // Set empty registry tables lua_newtable(L); lua_setfield(L, LUA_REGISTRYINDEX, "COM_Command"); diff --git a/src/lua_hook.h b/src/lua_hook.h index 5a14294c3..cb0e30d87 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -41,6 +41,7 @@ automatically. X (MobjMoveBlocked),/* P_XYMovement (when movement is blocked) */\ X (MapThingSpawn),/* P_SpawnMapThing */\ X (FollowMobj),/* P_PlayerAfterThink Smiles mobj-following */\ + X (HurtMsg),/* imhurttin */\ #define HOOK_LIST(X) \ X (NetVars),/* add to archive table (netsave) */\ @@ -56,7 +57,6 @@ automatically. X (JumpSpinSpecial),/* P_DoJumpStuff (Spin button effect (mid-air)) */\ X (BotTiccmd),/* B_BuildTiccmd */\ X (PlayerMsg),/* chat messages */\ - X (HurtMsg),/* imhurttin */\ X (PlayerSpawn),/* G_SpawnPlayer */\ X (ShieldSpawn),/* P_SpawnShieldOrb */\ X (ShieldSpecial),/* shield abilities */\ diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 0b24b7b53..039a9677f 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -72,7 +72,7 @@ static boolean mobj_hook_available(int hook_type, mobjtype_t mobj_type) return ( mobjHookIds [MT_NULL] [hook_type].numHooks > 0 || - mobjHookIds[mobj_type][hook_type].numHooks > 0 + (mobj_type < NUMMOBJTYPES && mobjHookIds[mobj_type][hook_type].numHooks > 0) ); } @@ -343,8 +343,11 @@ static boolean prepare_mobj_hook Hook_State * hook, int default_status, int hook_type, - mobjtype_t mobj_type + mobj_t * primary_mobj ){ + const mobjtype_t mobj_type = + primary_mobj ? primary_mobj->type : NUMMOBJTYPES; + #ifdef PARANOIA if (mobj_type == MT_NULL) I_Error("MT_NULL has been passed to a mobj hook\n"); @@ -505,7 +508,9 @@ static int call_hooks { /* call generic mobj hooks first */ calls += call_mobj_type_hooks(hook, MT_NULL); - calls += call_mobj_type_hooks(hook, hook->mobj_type); + + if (hook->mobj_type < NUMMOBJTYPES) + calls += call_mobj_type_hooks(hook, hook->mobj_type); ps_lua_mobjhooks.value.i += calls; } @@ -553,7 +558,7 @@ static void res_force(Hook_State *hook) int LUA_HookMobj(mobj_t *mobj, int hook_type) { Hook_State hook; - if (prepare_mobj_hook(&hook, false, hook_type, mobj->type)) + if (prepare_mobj_hook(&hook, false, hook_type, mobj)) { LUA_PushUserdata(gL, mobj, META_MOBJ); call_hooks(&hook, 1, res_true); @@ -564,7 +569,7 @@ int LUA_HookMobj(mobj_t *mobj, int hook_type) int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type) { Hook_State hook; - if (prepare_mobj_hook(&hook, 0, hook_type, t1->type)) + if (prepare_mobj_hook(&hook, 0, hook_type, t1)) { LUA_PushUserdata(gL, t1, META_MOBJ); LUA_PushUserdata(gL, t2, META_MOBJ); @@ -712,7 +717,7 @@ void LUA_HookThinkFrame(void) int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line) { Hook_State hook; - if (prepare_mobj_hook(&hook, 0, MOBJ_HOOK(MobjLineCollide), mobj->type)) + if (prepare_mobj_hook(&hook, 0, MOBJ_HOOK(MobjLineCollide), mobj)) { LUA_PushUserdata(gL, mobj, META_MOBJ); LUA_PushUserdata(gL, line, META_LINE); @@ -724,7 +729,7 @@ int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line) int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher) { Hook_State hook; - if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(TouchSpecial), special->type)) + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(TouchSpecial), special)) { LUA_PushUserdata(gL, special, META_MOBJ); LUA_PushUserdata(gL, toucher, META_MOBJ); @@ -744,7 +749,7 @@ static int damage_hook Hook_Callback results_handler ){ Hook_State hook; - if (prepare_mobj_hook(&hook, 0, hook_type, target->type)) + if (prepare_mobj_hook(&hook, 0, hook_type, target)) { LUA_PushUserdata(gL, target, META_MOBJ); LUA_PushUserdata(gL, inflictor, META_MOBJ); @@ -778,7 +783,7 @@ int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 d int LUA_HookMobjMoveBlocked(mobj_t *t1, mobj_t *t2, line_t *line) { Hook_State hook; - if (prepare_mobj_hook(&hook, 0, MOBJ_HOOK(MobjMoveBlocked), t1->type)) + if (prepare_mobj_hook(&hook, 0, MOBJ_HOOK(MobjMoveBlocked), t1)) { LUA_PushUserdata(gL, t1, META_MOBJ); LUA_PushUserdata(gL, t2, META_MOBJ); @@ -905,7 +910,7 @@ int LUA_HookPlayerMsg(int source, int target, int flags, char *msg) int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) { Hook_State hook; - if (prepare_hook(&hook, false, HOOK(HurtMsg))) + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(HurtMsg), inflictor)) { LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, inflictor, META_MOBJ); @@ -949,7 +954,7 @@ void LUA_HookNetArchive(lua_CFunction archFunc) int LUA_HookMapThingSpawn(mobj_t *mobj, mapthing_t *mthing) { Hook_State hook; - if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(MapThingSpawn), mobj->type)) + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(MapThingSpawn), mobj)) { LUA_PushUserdata(gL, mobj, META_MOBJ); LUA_PushUserdata(gL, mthing, META_MAPTHING); @@ -961,7 +966,7 @@ int LUA_HookMapThingSpawn(mobj_t *mobj, mapthing_t *mthing) int LUA_HookFollowMobj(player_t *player, mobj_t *mobj) { Hook_State hook; - if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(FollowMobj), mobj->type)) + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(FollowMobj), mobj)) { LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, mobj, META_MOBJ); diff --git a/src/lua_hud.h b/src/lua_hud.h index 0d629d233..ba102f2f4 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2022 by Sonic Team Junior. +// Copyright (C) 2014-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 785124fec..c7f67e93a 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2022 by Sonic Team Junior. +// Copyright (C) 2014-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -95,6 +95,8 @@ static const char *const patch_opt[] = { "topoffset", NULL}; +static int patch_fields_ref = LUA_NOREF; + // alignment types for v.drawString enum align { align_left = 0, @@ -196,6 +198,8 @@ static const char *const camera_opt[] = { "momz", NULL}; +static int camera_fields_ref = LUA_NOREF; + static int lib_getHudInfo(lua_State *L) { UINT32 i; @@ -276,7 +280,7 @@ static int colormap_get(lua_State *L) static int patch_get(lua_State *L) { patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); - enum patch field = luaL_checkoption(L, 2, NULL, patch_opt); + enum patch field = Lua_optoption(L, 2, -1, patch_fields_ref); // patches are invalidated when switching renderers if (!patch) { @@ -316,7 +320,7 @@ static int patch_set(lua_State *L) static int camera_get(lua_State *L) { camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA)); - enum cameraf field = luaL_checkoption(L, 2, NULL, camera_opt); + enum cameraf field = Lua_optoption(L, 2, -1, camera_fields_ref); // cameras should always be valid unless I'm a nutter I_Assert(cam != NULL); @@ -372,7 +376,7 @@ static int camera_get(lua_State *L) static int camera_set(lua_State *L) { camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA)); - enum cameraf field = luaL_checkoption(L, 2, NULL, camera_opt); + enum cameraf field = Lua_optoption(L, 2, -1, camera_fields_ref); I_Assert(cam != NULL); @@ -1444,6 +1448,8 @@ int LUA_HudLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L,1); + patch_fields_ref = Lua_CreateFieldTable(L, patch_opt); + luaL_newmetatable(L, META_CAMERA); lua_pushcfunction(L, camera_get); lua_setfield(L, -2, "__index"); @@ -1452,6 +1458,8 @@ int LUA_HudLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L,1); + camera_fields_ref = Lua_CreateFieldTable(L, camera_opt); + luaL_register(L, "hud", lib_hud); return 0; } diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index bcf132ec6..f46f207c1 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2022 by Sonic Team Junior. +// Copyright (C) 2014-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_hudlib_drawlist.h b/src/lua_hudlib_drawlist.h index 57d3de3c3..b2df39747 100644 --- a/src/lua_hudlib_drawlist.h +++ b/src/lua_hudlib_drawlist.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2022-2022 by Sonic Team Junior. +// Copyright (C) 2022-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_infolib.c b/src/lua_infolib.c index ac41de419..4d150347d 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1106,75 +1106,161 @@ static int lib_mobjinfolen(lua_State *L) return 1; } +enum mobjinfo_e +{ + mobjinfo_doomednum, + mobjinfo_spawnstate, + mobjinfo_spawnhealth, + mobjinfo_seestate, + mobjinfo_seesound, + mobjinfo_reactiontime, + mobjinfo_attacksound, + mobjinfo_painstate, + mobjinfo_painchance, + mobjinfo_painsound, + mobjinfo_meleestate, + mobjinfo_missilestate, + mobjinfo_deathstate, + mobjinfo_xdeathstate, + mobjinfo_deathsound, + mobjinfo_speed, + mobjinfo_radius, + mobjinfo_height, + mobjinfo_dispoffset, + mobjinfo_mass, + mobjinfo_damage, + mobjinfo_activesound, + mobjinfo_flags, + mobjinfo_raisestate, +}; + +const char *const mobjinfo_opt[] = { + "doomednum", + "spawnstate", + "spawnhealth", + "seestate", + "seesound", + "reactiontime", + "attacksound", + "painstate", + "painchance", + "painsound", + "meleestate", + "missilestate", + "deathstate", + "xdeathstate", + "deathsound", + "speed", + "radius", + "height", + "dispoffset", + "mass", + "damage", + "activesound", + "flags", + "raisestate", + NULL, +}; + +static int mobjinfo_fields_ref = LUA_NOREF; + // mobjinfo_t *, field -> number static int mobjinfo_get(lua_State *L) { mobjinfo_t *info = *((mobjinfo_t **)luaL_checkudata(L, 1, META_MOBJINFO)); - const char *field = luaL_checkstring(L, 2); + enum mobjinfo_e field = Lua_optoption(L, 2, mobjinfo_doomednum, mobjinfo_fields_ref); I_Assert(info != NULL); I_Assert(info >= mobjinfo); - if (fastcmp(field,"doomednum")) + switch (field) + { + case mobjinfo_doomednum: lua_pushinteger(L, info->doomednum); - else if (fastcmp(field,"spawnstate")) + break; + case mobjinfo_spawnstate: lua_pushinteger(L, info->spawnstate); - else if (fastcmp(field,"spawnhealth")) + break; + case mobjinfo_spawnhealth: lua_pushinteger(L, info->spawnhealth); - else if (fastcmp(field,"seestate")) + break; + case mobjinfo_seestate: lua_pushinteger(L, info->seestate); - else if (fastcmp(field,"seesound")) + break; + case mobjinfo_seesound: lua_pushinteger(L, info->seesound); - else if (fastcmp(field,"reactiontime")) + break; + case mobjinfo_reactiontime: lua_pushinteger(L, info->reactiontime); - else if (fastcmp(field,"attacksound")) + break; + case mobjinfo_attacksound: lua_pushinteger(L, info->attacksound); - else if (fastcmp(field,"painstate")) + break; + case mobjinfo_painstate: lua_pushinteger(L, info->painstate); - else if (fastcmp(field,"painchance")) + break; + case mobjinfo_painchance: lua_pushinteger(L, info->painchance); - else if (fastcmp(field,"painsound")) + break; + case mobjinfo_painsound: lua_pushinteger(L, info->painsound); - else if (fastcmp(field,"meleestate")) + break; + case mobjinfo_meleestate: lua_pushinteger(L, info->meleestate); - else if (fastcmp(field,"missilestate")) + break; + case mobjinfo_missilestate: lua_pushinteger(L, info->missilestate); - else if (fastcmp(field,"deathstate")) + break; + case mobjinfo_deathstate: lua_pushinteger(L, info->deathstate); - else if (fastcmp(field,"xdeathstate")) + break; + case mobjinfo_xdeathstate: lua_pushinteger(L, info->xdeathstate); - else if (fastcmp(field,"deathsound")) + break; + case mobjinfo_deathsound: lua_pushinteger(L, info->deathsound); - else if (fastcmp(field,"speed")) + break; + case mobjinfo_speed: lua_pushinteger(L, info->speed); // sometimes it's fixed_t, sometimes it's not... - else if (fastcmp(field,"radius")) + break; + case mobjinfo_radius: lua_pushfixed(L, info->radius); - else if (fastcmp(field,"height")) + break; + case mobjinfo_height: lua_pushfixed(L, info->height); - else if (fastcmp(field,"dispoffset")) + break; + case mobjinfo_dispoffset: lua_pushinteger(L, info->dispoffset); - else if (fastcmp(field,"mass")) + break; + case mobjinfo_mass: lua_pushinteger(L, info->mass); - else if (fastcmp(field,"damage")) + break; + case mobjinfo_damage: lua_pushinteger(L, info->damage); - else if (fastcmp(field,"activesound")) + break; + case mobjinfo_activesound: lua_pushinteger(L, info->activesound); - else if (fastcmp(field,"flags")) + break; + case mobjinfo_flags: lua_pushinteger(L, info->flags); - else if (fastcmp(field,"raisestate")) + break; + case mobjinfo_raisestate: lua_pushinteger(L, info->raisestate); - else { + break; + default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); lua_pushlightuserdata(L, info); lua_rawget(L, -2); if (!lua_istable(L, -1)) { // no extra values table - CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", lua_tostring(L, 2)); return 0; } - lua_getfield(L, -1, field); + lua_pushvalue(L, 2); // field name + lua_gettable(L, -2); if (lua_isnil(L, -1)) // no value for this field - CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", lua_tostring(L, 2)); + break; } return 1; } @@ -1183,7 +1269,7 @@ static int mobjinfo_get(lua_State *L) static int mobjinfo_set(lua_State *L) { mobjinfo_t *info = *((mobjinfo_t **)luaL_checkudata(L, 1, META_MOBJINFO)); - const char *field = luaL_checkstring(L, 2); + enum mobjinfo_e field = Lua_optoption(L, 2, -1, mobjinfo_fields_ref); if (hud_running) return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!"); @@ -1193,55 +1279,81 @@ static int mobjinfo_set(lua_State *L) I_Assert(info != NULL); I_Assert(info >= mobjinfo); - if (fastcmp(field,"doomednum")) + switch (field) + { + case mobjinfo_doomednum: info->doomednum = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"spawnstate")) + break; + case mobjinfo_spawnstate: info->spawnstate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"spawnhealth")) + break; + case mobjinfo_spawnhealth: info->spawnhealth = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"seestate")) + break; + case mobjinfo_seestate: info->seestate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"seesound")) + break; + case mobjinfo_seesound: info->seesound = luaL_checkinteger(L, 3); - else if (fastcmp(field,"reactiontime")) + break; + case mobjinfo_reactiontime: info->reactiontime = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"attacksound")) + break; + case mobjinfo_attacksound: info->attacksound = luaL_checkinteger(L, 3); - else if (fastcmp(field,"painstate")) + break; + case mobjinfo_painstate: info->painstate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"painchance")) + break; + case mobjinfo_painchance: info->painchance = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"painsound")) + break; + case mobjinfo_painsound: info->painsound = luaL_checkinteger(L, 3); - else if (fastcmp(field,"meleestate")) + break; + case mobjinfo_meleestate: info->meleestate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"missilestate")) + break; + case mobjinfo_missilestate: info->missilestate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"deathstate")) + break; + case mobjinfo_deathstate: info->deathstate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"xdeathstate")) + break; + case mobjinfo_xdeathstate: info->xdeathstate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"deathsound")) + break; + case mobjinfo_deathsound: info->deathsound = luaL_checkinteger(L, 3); - else if (fastcmp(field,"speed")) + break; + case mobjinfo_speed: info->speed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"radius")) + break; + case mobjinfo_radius: info->radius = luaL_checkfixed(L, 3); - else if (fastcmp(field,"height")) + break; + case mobjinfo_height: info->height = luaL_checkfixed(L, 3); - else if (fastcmp(field,"dispoffset")) + break; + case mobjinfo_dispoffset: info->dispoffset = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"mass")) + break; + case mobjinfo_mass: info->mass = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"damage")) + break; + case mobjinfo_damage: info->damage = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"activesound")) + break; + case mobjinfo_activesound: info->activesound = luaL_checkinteger(L, 3); - else if (fastcmp(field,"flags")) + break; + case mobjinfo_flags: info->flags = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"raisestate")) + break; + case mobjinfo_raisestate: info->raisestate = luaL_checkinteger(L, 3); - else { + break; + default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); lua_pushlightuserdata(L, info); @@ -1249,18 +1361,17 @@ static int mobjinfo_set(lua_State *L) if (lua_isnil(L, -1)) { // This index doesn't have a table for extra values yet, let's make one. lua_pop(L, 1); - CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "mobjinfo_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "mobjinfo_t", lua_tostring(L, 2)); lua_newtable(L); lua_pushlightuserdata(L, info); lua_pushvalue(L, -2); // ext value table lua_rawset(L, -4); // LREG_EXTVARS table } + lua_pushvalue(L, 2); // key lua_pushvalue(L, 3); // value to store - lua_setfield(L, -2, field); + lua_settable(L, -3); lua_pop(L, 2); } - //else - //return luaL_error(L, LUA_QL("mobjinfo_t") " has no field named " LUA_QS, field); return 0; } @@ -1788,6 +1899,8 @@ int LUA_InfoLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + mobjinfo_fields_ref = Lua_CreateFieldTable(L, mobjinfo_opt); + luaL_newmetatable(L, META_SKINCOLOR); lua_pushcfunction(L, skincolor_get); lua_setfield(L, -2, "__index"); diff --git a/src/lua_inputlib.c b/src/lua_inputlib.c index 1710b0355..1f75ee6fe 100644 --- a/src/lua_inputlib.c +++ b/src/lua_inputlib.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021-2022 by Sonic Team Junior. +// Copyright (C) 2021-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_libs.h b/src/lua_libs.h index b4a891edb..7f8d21f38 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_maplib.c b/src/lua_maplib.c index d3a00782b..2c0d18cfb 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -104,6 +104,8 @@ static const char *const sector_opt[] = { "gravity", NULL}; +static int sector_fields_ref = LUA_NOREF; + enum subsector_e { subsector_valid = 0, subsector_sector, @@ -120,6 +122,8 @@ static const char *const subsector_opt[] = { "polyList", NULL}; +static int subsector_fields_ref = LUA_NOREF; + enum line_e { line_valid = 0, line_v1, @@ -172,10 +176,18 @@ static const char *const line_opt[] = { "callcount", NULL}; +static int line_fields_ref = LUA_NOREF; + enum side_e { side_valid = 0, side_textureoffset, side_rowoffset, + side_offsetx_top, + side_offsety_top, + side_offsetx_mid, + side_offsety_mid, + side_offsetx_bot, + side_offsety_bot, side_toptexture, side_bottomtexture, side_midtexture, @@ -190,6 +202,12 @@ static const char *const side_opt[] = { "valid", "textureoffset", "rowoffset", + "offsetx_top", + "offsety_top", + "offsetx_mid", + "offsety_mid", + "offsetx_bot", + "offsety_bot", "toptexture", "bottomtexture", "midtexture", @@ -200,6 +218,8 @@ static const char *const side_opt[] = { "text", NULL}; +static int side_fields_ref = LUA_NOREF; + enum vertex_e { vertex_valid = 0, vertex_x, @@ -220,6 +240,8 @@ static const char *const vertex_opt[] = { "ceilingzset", NULL}; +static int vertex_fields_ref = LUA_NOREF; + enum ffloor_e { ffloor_valid = 0, ffloor_topheight, @@ -272,6 +294,8 @@ static const char *const ffloor_opt[] = { "bouncestrength", NULL}; +static int ffloor_fields_ref = LUA_NOREF; + #ifdef HAVE_LUA_SEGS enum seg_e { seg_valid = 0, @@ -301,6 +325,8 @@ static const char *const seg_opt[] = { "polyseg", NULL}; +static int seg_fields_ref = LUA_NOREF; + enum node_e { node_valid = 0, node_x, @@ -321,6 +347,8 @@ static const char *const node_opt[] = { "children", NULL}; +static int node_fields_ref = LUA_NOREF; + enum nodechild_e { nodechild_valid = 0, nodechild_right, @@ -372,6 +400,8 @@ static const char *const slope_opt[] = { "flags", NULL}; +static int slope_fields_ref = LUA_NOREF; + // shared by both vector2_t and vector3_t enum vector_e { vector_x = 0, @@ -591,7 +621,7 @@ static int sectorlines_num(lua_State *L) static int sector_get(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); - enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt); + enum sector_e field = Lua_optoption(L, 2, sector_valid, sector_fields_ref); INT16 i; if (!sector) @@ -749,7 +779,7 @@ static int sector_get(lua_State *L) static int sector_set(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); - enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt); + enum sector_e field = Lua_optoption(L, 2, sector_valid, sector_fields_ref); if (!sector) return luaL_error(L, "accessed sector_t doesn't exist anymore."); @@ -890,7 +920,7 @@ static int sector_num(lua_State *L) static int subsector_get(lua_State *L) { subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR)); - enum subsector_e field = luaL_checkoption(L, 2, subsector_opt[0], subsector_opt); + enum subsector_e field = Lua_optoption(L, 2, subsector_valid, subsector_fields_ref); if (!subsector) { @@ -974,7 +1004,7 @@ static int linestringargs_len(lua_State *L) static int line_get(lua_State *L) { line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE)); - enum line_e field = luaL_checkoption(L, 2, line_opt[0], line_opt); + enum line_e field = Lua_optoption(L, 2, line_valid, line_fields_ref); if (!line) { @@ -1133,7 +1163,7 @@ static int sidenum_get(lua_State *L) static int side_get(lua_State *L) { side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE)); - enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt); + enum side_e field = Lua_optoption(L, 2, side_valid, side_fields_ref); if (!side) { @@ -1155,6 +1185,24 @@ static int side_get(lua_State *L) case side_rowoffset: lua_pushfixed(L, side->rowoffset); return 1; + case side_offsetx_top: + lua_pushfixed(L, side->offsetx_top); + return 1; + case side_offsety_top: + lua_pushfixed(L, side->offsety_top); + return 1; + case side_offsetx_mid: + lua_pushfixed(L, side->offsetx_mid); + return 1; + case side_offsety_mid: + lua_pushfixed(L, side->offsety_mid); + return 1; + case side_offsetx_bot: + lua_pushfixed(L, side->offsetx_bot); + return 1; + case side_offsety_bot: + lua_pushfixed(L, side->offsety_bot); + return 1; case side_toptexture: lua_pushinteger(L, side->toptexture); return 1; @@ -1186,7 +1234,7 @@ static int side_get(lua_State *L) static int side_set(lua_State *L) { side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE)); - enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt); + enum side_e field = Lua_optoption(L, 2, side_valid, side_fields_ref); if (!side) { @@ -1212,6 +1260,24 @@ static int side_set(lua_State *L) case side_rowoffset: side->rowoffset = luaL_checkfixed(L, 3); break; + case side_offsetx_top: + side->offsetx_top = luaL_checkfixed(L, 3); + break; + case side_offsety_top: + side->offsety_top = luaL_checkfixed(L, 3); + break; + case side_offsetx_mid: + side->offsetx_mid = luaL_checkfixed(L, 3); + break; + case side_offsety_mid: + side->offsety_mid = luaL_checkfixed(L, 3); + break; + case side_offsetx_bot: + side->offsetx_bot = luaL_checkfixed(L, 3); + break; + case side_offsety_bot: + side->offsety_bot = luaL_checkfixed(L, 3); + break; case side_toptexture: side->toptexture = luaL_checkinteger(L, 3); break; @@ -1242,7 +1308,7 @@ static int side_num(lua_State *L) static int vertex_get(lua_State *L) { vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX)); - enum vertex_e field = luaL_checkoption(L, 2, vertex_opt[0], vertex_opt); + enum vertex_e field = Lua_optoption(L, 2, vertex_valid, vertex_fields_ref); if (!vertex) { @@ -1296,7 +1362,7 @@ static int vertex_num(lua_State *L) static int seg_get(lua_State *L) { seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG)); - enum seg_e field = luaL_checkoption(L, 2, seg_opt[0], seg_opt); + enum seg_e field = Lua_optoption(L, 2, seg_valid, seg_fields_ref); if (!seg) { @@ -1360,7 +1426,7 @@ static int seg_num(lua_State *L) static int node_get(lua_State *L) { node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE)); - enum node_e field = luaL_checkoption(L, 2, node_opt[0], node_opt); + enum node_e field = Lua_optoption(L, 2, node_valid, node_fields_ref); if (!node) { @@ -1986,17 +2052,17 @@ static INT32 P_GetOldFOFFlags(ffloor_t *fflr) result |= FF_OLD_SPINBUST; if (fflr->busttype == BT_STRONG) result |= FF_OLD_STRONGBUST; - if (fflr->fofflags & FF_OLD_RIPPLE) - result |= FOF_RIPPLE; - if (fflr->fofflags & FF_OLD_COLORMAPONLY) - result |= FOF_COLORMAPONLY; + if (fflr->fofflags & FOF_RIPPLE) + result |= FF_OLD_RIPPLE; + if (fflr->fofflags & FOF_COLORMAPONLY) + result |= FF_OLD_COLORMAPONLY; return result; } static int ffloor_get(lua_State *L) { ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); - enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt); + enum ffloor_e field = Lua_optoption(L, 2, ffloor_valid, ffloor_fields_ref); INT16 i; if (!ffloor) @@ -2178,7 +2244,7 @@ static void P_SetOldFOFFlags(ffloor_t *fflr, oldffloortype_e oldflags) static int ffloor_set(lua_State *L) { ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); - enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt); + enum ffloor_e field = Lua_optoption(L, 2, ffloor_valid, ffloor_fields_ref); if (!ffloor) return luaL_error(L, "accessed ffloor_t doesn't exist anymore."); @@ -2273,7 +2339,7 @@ static int ffloor_set(lua_State *L) static int slope_get(lua_State *L) { pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); - enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt); + enum slope_e field = Lua_optoption(L, 2, slope_valid, slope_fields_ref); if (!slope) { @@ -2317,7 +2383,7 @@ static int slope_get(lua_State *L) static int slope_set(lua_State *L) { pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); - enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt); + enum slope_e field = Lua_optoption(L, 2, slope_valid, slope_fields_ref); if (!slope) return luaL_error(L, "accessed pslope_t doesn't exist anymore."); @@ -2481,110 +2547,258 @@ static int lib_nummapheaders(lua_State *L) // mapheader_t // ///////////////// +enum mapheaderinfo_e +{ + mapheaderinfo_lvlttl, + mapheaderinfo_subttl, + mapheaderinfo_actnum, + mapheaderinfo_typeoflevel, + mapheaderinfo_nextlevel, + mapheaderinfo_marathonnext, + mapheaderinfo_keywords, + mapheaderinfo_musname, + mapheaderinfo_mustrack, + mapheaderinfo_muspos, + mapheaderinfo_musinterfadeout, + mapheaderinfo_musintername, + mapheaderinfo_muspostbossname, + mapheaderinfo_muspostbosstrack, + mapheaderinfo_muspostbosspos, + mapheaderinfo_muspostbossfadein, + mapheaderinfo_musforcereset, + mapheaderinfo_forcecharacter, + mapheaderinfo_weather, + mapheaderinfo_skynum, + mapheaderinfo_skybox_scalex, + mapheaderinfo_skybox_scaley, + mapheaderinfo_skybox_scalez, + mapheaderinfo_interscreen, + mapheaderinfo_runsoc, + mapheaderinfo_scriptname, + mapheaderinfo_precutscenenum, + mapheaderinfo_cutscenenum, + mapheaderinfo_countdown, + mapheaderinfo_palette, + mapheaderinfo_numlaps, + mapheaderinfo_unlockrequired, + mapheaderinfo_levelselect, + mapheaderinfo_bonustype, + mapheaderinfo_ltzzpatch, + mapheaderinfo_ltzztext, + mapheaderinfo_ltactdiamond, + mapheaderinfo_maxbonuslives, + mapheaderinfo_levelflags, + mapheaderinfo_menuflags, + mapheaderinfo_selectheading, + mapheaderinfo_startrings, + mapheaderinfo_sstimer, + mapheaderinfo_ssspheres, + mapheaderinfo_gravity, +}; + +static const char *const mapheaderinfo_opt[] = { + "lvlttl", + "subttl", + "actnum", + "typeoflevel", + "nextlevel", + "marathonnext", + "keywords", + "musname", + "mustrack", + "muspos", + "musinterfadeout", + "musintername", + "muspostbossname", + "muspostbosstrack", + "muspostbosspos", + "muspostbossfadein", + "musforcereset", + "forcecharacter", + "weather", + "skynum", + "skybox_scalex", + "skybox_scaley", + "skybox_scalez", + "interscreen", + "runsoc", + "scriptname", + "precutscenenum", + "cutscenenum", + "countdown", + "palette", + "numlaps", + "unlockrequired", + "levelselect", + "bonustype", + "ltzzpatch", + "ltzztext", + "ltactdiamond", + "maxbonuslives", + "levelflags", + "menuflags", + "selectheading", + "startrings", + "sstimer", + "ssspheres", + "gravity", + NULL, +}; + +static int mapheaderinfo_fields_ref = LUA_NOREF; + static int mapheaderinfo_get(lua_State *L) { mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER)); - const char *field = luaL_checkstring(L, 2); + enum mapheaderinfo_e field = Lua_optoption(L, 2, -1, mapheaderinfo_fields_ref); INT16 i; - if (fastcmp(field,"lvlttl")) + + switch (field) + { + case mapheaderinfo_lvlttl: lua_pushstring(L, header->lvlttl); - else if (fastcmp(field,"subttl")) + break; + case mapheaderinfo_subttl: lua_pushstring(L, header->subttl); - else if (fastcmp(field,"actnum")) + break; + case mapheaderinfo_actnum: lua_pushinteger(L, header->actnum); - else if (fastcmp(field,"typeoflevel")) + break; + case mapheaderinfo_typeoflevel: lua_pushinteger(L, header->typeoflevel); - else if (fastcmp(field,"nextlevel")) + break; + case mapheaderinfo_nextlevel: lua_pushinteger(L, header->nextlevel); - else if (fastcmp(field,"marathonnext")) + break; + case mapheaderinfo_marathonnext: lua_pushinteger(L, header->marathonnext); - else if (fastcmp(field,"keywords")) + break; + case mapheaderinfo_keywords: lua_pushstring(L, header->keywords); - else if (fastcmp(field,"musname")) + break; + case mapheaderinfo_musname: lua_pushstring(L, header->musname); - else if (fastcmp(field,"mustrack")) + break; + case mapheaderinfo_mustrack: lua_pushinteger(L, header->mustrack); - else if (fastcmp(field,"muspos")) + break; + case mapheaderinfo_muspos: lua_pushinteger(L, header->muspos); - else if (fastcmp(field,"musinterfadeout")) + break; + case mapheaderinfo_musinterfadeout: lua_pushinteger(L, header->musinterfadeout); - else if (fastcmp(field,"musintername")) + break; + case mapheaderinfo_musintername: lua_pushstring(L, header->musintername); - else if (fastcmp(field,"muspostbossname")) + break; + case mapheaderinfo_muspostbossname: lua_pushstring(L, header->muspostbossname); - else if (fastcmp(field,"muspostbosstrack")) + break; + case mapheaderinfo_muspostbosstrack: lua_pushinteger(L, header->muspostbosstrack); - else if (fastcmp(field,"muspostbosspos")) + break; + case mapheaderinfo_muspostbosspos: lua_pushinteger(L, header->muspostbosspos); - else if (fastcmp(field,"muspostbossfadein")) + break; + case mapheaderinfo_muspostbossfadein: lua_pushinteger(L, header->muspostbossfadein); - else if (fastcmp(field,"musforcereset")) + break; + case mapheaderinfo_musforcereset: lua_pushinteger(L, header->musforcereset); - else if (fastcmp(field,"forcecharacter")) + break; + case mapheaderinfo_forcecharacter: lua_pushstring(L, header->forcecharacter); - else if (fastcmp(field,"weather")) + break; + case mapheaderinfo_weather: lua_pushinteger(L, header->weather); - else if (fastcmp(field,"skynum")) + break; + case mapheaderinfo_skynum: lua_pushinteger(L, header->skynum); - else if (fastcmp(field,"skybox_scalex")) + break; + case mapheaderinfo_skybox_scalex: lua_pushinteger(L, header->skybox_scalex); - else if (fastcmp(field,"skybox_scaley")) + break; + case mapheaderinfo_skybox_scaley: lua_pushinteger(L, header->skybox_scaley); - else if (fastcmp(field,"skybox_scalez")) + break; + case mapheaderinfo_skybox_scalez: lua_pushinteger(L, header->skybox_scalez); - else if (fastcmp(field,"interscreen")) { + break; + case mapheaderinfo_interscreen: for (i = 0; i < 8; i++) if (!header->interscreen[i]) break; lua_pushlstring(L, header->interscreen, i); - } else if (fastcmp(field,"runsoc")) + break; + case mapheaderinfo_runsoc: lua_pushstring(L, header->runsoc); - else if (fastcmp(field,"scriptname")) + break; + case mapheaderinfo_scriptname: lua_pushstring(L, header->scriptname); - else if (fastcmp(field,"precutscenenum")) + break; + case mapheaderinfo_precutscenenum: lua_pushinteger(L, header->precutscenenum); - else if (fastcmp(field,"cutscenenum")) + break; + case mapheaderinfo_cutscenenum: lua_pushinteger(L, header->cutscenenum); - else if (fastcmp(field,"countdown")) + break; + case mapheaderinfo_countdown: lua_pushinteger(L, header->countdown); - else if (fastcmp(field,"palette")) + break; + case mapheaderinfo_palette: lua_pushinteger(L, header->palette); - else if (fastcmp(field,"numlaps")) + break; + case mapheaderinfo_numlaps: lua_pushinteger(L, header->numlaps); - else if (fastcmp(field,"unlockrequired")) + break; + case mapheaderinfo_unlockrequired: lua_pushinteger(L, header->unlockrequired); - else if (fastcmp(field,"levelselect")) + break; + case mapheaderinfo_levelselect: lua_pushinteger(L, header->levelselect); - else if (fastcmp(field,"bonustype")) + break; + case mapheaderinfo_bonustype: lua_pushinteger(L, header->bonustype); - else if (fastcmp(field,"ltzzpatch")) + break; + case mapheaderinfo_ltzzpatch: lua_pushstring(L, header->ltzzpatch); - else if (fastcmp(field,"ltzztext")) + break; + case mapheaderinfo_ltzztext: lua_pushstring(L, header->ltzztext); - else if (fastcmp(field,"ltactdiamond")) + break; + case mapheaderinfo_ltactdiamond: lua_pushstring(L, header->ltactdiamond); - else if (fastcmp(field,"maxbonuslives")) + break; + case mapheaderinfo_maxbonuslives: lua_pushinteger(L, header->maxbonuslives); - else if (fastcmp(field,"levelflags")) + break; + case mapheaderinfo_levelflags: lua_pushinteger(L, header->levelflags); - else if (fastcmp(field,"menuflags")) + break; + case mapheaderinfo_menuflags: lua_pushinteger(L, header->menuflags); - else if (fastcmp(field,"selectheading")) + break; + case mapheaderinfo_selectheading: lua_pushstring(L, header->selectheading); - else if (fastcmp(field,"startrings")) + break; + case mapheaderinfo_startrings: lua_pushinteger(L, header->startrings); - else if (fastcmp(field, "sstimer")) + break; + case mapheaderinfo_sstimer: lua_pushinteger(L, header->sstimer); - else if (fastcmp(field, "ssspheres")) + break; + case mapheaderinfo_ssspheres: lua_pushinteger(L, header->ssspheres); - else if (fastcmp(field, "gravity")) + break; + case mapheaderinfo_gravity: lua_pushfixed(L, header->gravity); + break; // TODO add support for reading numGradedMares and grades - else { + default: // Read custom vars now // (note: don't include the "LUA." in your lua scripts!) UINT8 j = 0; - for (;j < header->numCustomOptions && !fastcmp(field, header->customopts[j].option); ++j); + for (;j < header->numCustomOptions && !fastcmp(lua_tostring(L, 2), header->customopts[j].option); ++j); if(j < header->numCustomOptions) lua_pushstring(L, header->customopts[j].value); @@ -2615,6 +2829,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + sector_fields_ref = Lua_CreateFieldTable(L, sector_opt); + luaL_newmetatable(L, META_SUBSECTOR); lua_pushcfunction(L, subsector_get); lua_setfield(L, -2, "__index"); @@ -2623,6 +2839,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + subsector_fields_ref = Lua_CreateFieldTable(L, subsector_opt); + luaL_newmetatable(L, META_LINE); lua_pushcfunction(L, line_get); lua_setfield(L, -2, "__index"); @@ -2631,6 +2849,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + line_fields_ref = Lua_CreateFieldTable(L, line_opt); + luaL_newmetatable(L, META_LINEARGS); lua_pushcfunction(L, lineargs_get); lua_setfield(L, -2, "__index"); @@ -2663,6 +2883,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + side_fields_ref = Lua_CreateFieldTable(L, side_opt); + luaL_newmetatable(L, META_VERTEX); lua_pushcfunction(L, vertex_get); lua_setfield(L, -2, "__index"); @@ -2671,6 +2893,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + vertex_fields_ref = Lua_CreateFieldTable(L, vertex_opt); + luaL_newmetatable(L, META_FFLOOR); lua_pushcfunction(L, ffloor_get); lua_setfield(L, -2, "__index"); @@ -2679,6 +2903,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L, 1); + ffloor_fields_ref = Lua_CreateFieldTable(L, ffloor_opt); + #ifdef HAVE_LUA_SEGS luaL_newmetatable(L, META_SEG); lua_pushcfunction(L, seg_get); @@ -2688,6 +2914,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + seg_fields_ref = Lua_CreateFieldTable(L, seg_opt); + luaL_newmetatable(L, META_NODE); lua_pushcfunction(L, node_get); lua_setfield(L, -2, "__index"); @@ -2696,6 +2924,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + node_fields_ref = Lua_CreateFieldTable(L, node_opt); + luaL_newmetatable(L, META_NODEBBOX); //lua_pushcfunction(L, nodebbox_get); //lua_setfield(L, -2, "__index"); @@ -2722,6 +2952,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L, 1); + slope_fields_ref = Lua_CreateFieldTable(L, slope_opt); + luaL_newmetatable(L, META_VECTOR2); lua_pushcfunction(L, vector2_get); lua_setfield(L, -2, "__index"); @@ -2740,6 +2972,8 @@ int LUA_MapLib(lua_State *L) //lua_setfield(L, -2, "__len"); lua_pop(L, 1); + mapheaderinfo_fields_ref = Lua_CreateFieldTable(L, mapheaderinfo_opt); + LUA_PushTaggableObjectArray(L, "sectors", lib_iterateSectors, lib_getSector, diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index c7501da60..d0fe6863f 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 2aec48c90..09d244c91 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -96,7 +96,8 @@ enum mobj_e { mobj_standingslope, mobj_colorized, mobj_mirrored, - mobj_shadowscale + mobj_shadowscale, + mobj_dispoffset }; static const char *const mobj_opt[] = { @@ -173,14 +174,17 @@ static const char *const mobj_opt[] = { "colorized", "mirrored", "shadowscale", + "dispoffset", NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) +static int mobj_fields_ref = LUA_NOREF; + static int mobj_get(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - enum mobj_e field = Lua_optoption(L, 2, NULL, mobj_opt); + enum mobj_e field = Lua_optoption(L, 2, -1, mobj_fields_ref); lua_settop(L, 2); if (!mo || !ISINLEVEL) { @@ -439,6 +443,9 @@ static int mobj_get(lua_State *L) case mobj_shadowscale: lua_pushfixed(L, mo->shadowscale); break; + case mobj_dispoffset: + lua_pushinteger(L, mo->dispoffset); + break; default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -462,7 +469,7 @@ static int mobj_get(lua_State *L) static int mobj_set(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - enum mobj_e field = Lua_optoption(L, 2, mobj_opt[0], mobj_opt); + enum mobj_e field = Lua_optoption(L, 2, mobj_valid, mobj_fields_ref); lua_settop(L, 3); INLEVEL @@ -804,6 +811,9 @@ static int mobj_set(lua_State *L) case mobj_shadowscale: mo->shadowscale = luaL_checkfixed(L, 3); break; + case mobj_dispoffset: + mo->dispoffset = luaL_checkinteger(L, 3); + break; default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -868,14 +878,55 @@ static int thingstringargs_len(lua_State *L) return 1; } +enum mapthing_e { + mapthing_valid = 0, + mapthing_x, + mapthing_y, + mapthing_angle, + mapthing_pitch, + mapthing_roll, + mapthing_type, + mapthing_options, + mapthing_scale, + mapthing_z, + mapthing_extrainfo, + mapthing_tag, + mapthing_taglist, + mapthing_args, + mapthing_stringargs, + mapthing_mobj, +}; + +const char *const mapthing_opt[] = { + "valid", + "x", + "y", + "angle", + "pitch", + "roll", + "type", + "options", + "scale", + "z", + "extrainfo", + "tag", + "taglist", + "args", + "stringargs", + "mobj", + NULL, +}; + +static int mapthing_fields_ref = LUA_NOREF; + static int mapthing_get(lua_State *L) { mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING)); - const char *field = luaL_checkstring(L, 2); - lua_Integer number; + enum mapthing_e field = Lua_optoption(L, 2, -1, mapthing_fields_ref); + lua_settop(L, 2); if (!mt) { - if (fastcmp(field,"valid")) { + if (field == mapthing_valid) { lua_pushboolean(L, false); return 1; } @@ -884,62 +935,71 @@ static int mapthing_get(lua_State *L) return 0; } - if (fastcmp(field,"valid")) { - lua_pushboolean(L, true); - return 1; - } else if(fastcmp(field,"x")) - number = mt->x; - else if(fastcmp(field,"y")) - number = mt->y; - else if(fastcmp(field,"angle")) - number = mt->angle; - else if(fastcmp(field,"pitch")) - number = mt->pitch; - else if(fastcmp(field,"roll")) - number = mt->roll; - else if(fastcmp(field,"type")) - number = mt->type; - else if(fastcmp(field,"options")) - number = mt->options; - else if(fastcmp(field,"scale")) - number = mt->scale; - else if(fastcmp(field,"z")) - number = mt->z; - else if(fastcmp(field,"extrainfo")) - number = mt->extrainfo; - else if(fastcmp(field,"tag")) - number = Tag_FGet(&mt->tags); - else if(fastcmp(field,"taglist")) + switch (field) { - LUA_PushUserdata(L, &mt->tags, META_TAGLIST); - return 1; + case mapthing_valid: + lua_pushboolean(L, true); + break; + case mapthing_x: + lua_pushinteger(L, mt->x); + break; + case mapthing_y: + lua_pushinteger(L, mt->y); + break; + case mapthing_angle: + lua_pushinteger(L, mt->angle); + break; + case mapthing_pitch: + lua_pushinteger(L, mt->pitch); + break; + case mapthing_roll: + lua_pushinteger(L, mt->roll); + break; + case mapthing_type: + lua_pushinteger(L, mt->type); + break; + case mapthing_options: + lua_pushinteger(L, mt->options); + break; + case mapthing_scale: + lua_pushinteger(L, mt->scale); + break; + case mapthing_z: + lua_pushinteger(L, mt->z); + break; + case mapthing_extrainfo: + lua_pushinteger(L, mt->extrainfo); + break; + case mapthing_tag: + lua_pushinteger(L, Tag_FGet(&mt->tags)); + break; + case mapthing_taglist: + LUA_PushUserdata(L, &mt->tags, META_TAGLIST); + break; + case mapthing_args: + LUA_PushUserdata(L, mt->args, META_THINGARGS); + break; + case mapthing_stringargs: + LUA_PushUserdata(L, mt->stringargs, META_THINGSTRINGARGS); + break; + case mapthing_mobj: + LUA_PushUserdata(L, mt->mobj, META_MOBJ); + break; + default: + if (devparm) + return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field); + else + return 0; } - else if(fastcmp(field,"args")) - { - LUA_PushUserdata(L, mt->args, META_THINGARGS); - return 1; - } - else if(fastcmp(field,"stringargs")) - { - LUA_PushUserdata(L, mt->stringargs, META_THINGSTRINGARGS); - return 1; - } - else if(fastcmp(field,"mobj")) { - LUA_PushUserdata(L, mt->mobj, META_MOBJ); - return 1; - } else if (devparm) - return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field); - else - return 0; - lua_pushinteger(L, number); return 1; } static int mapthing_set(lua_State *L) { mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING)); - const char *field = luaL_checkstring(L, 2); + enum mapthing_e field = Lua_optoption(L, 2, -1, mapthing_fields_ref); + lua_settop(L, 3); if (!mt) return luaL_error(L, "accessed mapthing_t doesn't exist anymore."); @@ -949,39 +1009,52 @@ static int mapthing_set(lua_State *L) if (hook_cmd_running) return luaL_error(L, "Do not alter mapthing_t in CMD building code!"); - if(fastcmp(field,"x")) - mt->x = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"y")) - mt->y = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"angle")) - mt->angle = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"pitch")) - mt->pitch = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"roll")) - mt->roll = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"type")) - mt->type = (UINT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"options")) - mt->options = (UINT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"scale")) - mt->scale = luaL_checkfixed(L, 3); - else if(fastcmp(field,"z")) - mt->z = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"extrainfo")) + switch (field) { - INT32 extrainfo = luaL_checkinteger(L, 3); - if (extrainfo & ~15) - return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15); - mt->extrainfo = (UINT8)extrainfo; + case mapthing_x: + mt->x = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_y: + mt->y = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_angle: + mt->angle = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_pitch: + mt->pitch = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_roll: + mt->roll = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_type: + mt->type = (UINT16)luaL_checkinteger(L, 3); + break; + case mapthing_options: + mt->options = (UINT16)luaL_checkinteger(L, 3); + break; + case mapthing_scale: + mt->scale = luaL_checkfixed(L, 3); + break; + case mapthing_z: + mt->z = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_extrainfo: + INT32 extrainfo = luaL_checkinteger(L, 3); + if (extrainfo & ~15) + return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15); + mt->extrainfo = (UINT8)extrainfo; + break; + case mapthing_tag: + Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3)); + break; + case mapthing_taglist: + return LUA_ErrSetDirectly(L, "mapthing_t", "taglist"); + case mapthing_mobj: + mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + break; + default: + return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field); } - 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 - return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field); return 0; } @@ -1043,6 +1116,8 @@ int LUA_MobjLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L,1); + mobj_fields_ref = Lua_CreateFieldTable(L, mobj_opt); + luaL_newmetatable(L, META_THINGARGS); lua_pushcfunction(L, thingargs_get); lua_setfield(L, -2, "__index"); @@ -1070,6 +1145,8 @@ int LUA_MobjLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L,1); + mapthing_fields_ref = Lua_CreateFieldTable(L, mapthing_opt); + LUA_PushTaggableObjectArray(L, "mapthings", lib_iterateMapthings, lib_getMapthing, diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 58cfab76c..f76ec1689 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -80,332 +80,774 @@ static int lib_lenPlayer(lua_State *L) return 1; } +enum player_e +{ + player_valid, + player_name, + player_realmo, + player_mo, + player_cmd, + player_playerstate, + player_camerascale, + player_shieldscale, + player_viewz, + player_viewheight, + player_deltaviewheight, + player_bob, + player_viewrollangle, + player_aiming, + player_drawangle, + player_rings, + player_spheres, + player_pity, + player_currentweapon, + player_ringweapons, + player_ammoremoval, + player_ammoremovaltimer, + player_ammoremovalweapon, + player_powers, + player_pflags, + player_panim, + player_flashcount, + player_flashpal, + player_skincolor, + player_skin, + player_availabilities, + player_score, + player_dashspeed, + player_normalspeed, + player_runspeed, + player_thrustfactor, + player_accelstart, + player_acceleration, + player_charability, + player_charability2, + player_charflags, + player_thokitem, + player_spinitem, + player_revitem, + player_followitem, + player_followmobj, + player_actionspd, + player_mindash, + player_maxdash, + player_jumpfactor, + player_height, + player_spinheight, + player_lives, + player_continues, + player_xtralife, + player_gotcontinue, + player_speed, + player_secondjump, + player_fly1, + player_scoreadd, + player_glidetime, + player_climbing, + player_deadtimer, + player_exiting, + player_homing, + player_dashmode, + player_skidtime, + player_cmomx, + player_cmomy, + player_rmomx, + player_rmomy, + player_numboxes, + player_totalring, + player_realtime, + player_laps, + player_ctfteam, + player_gotflag, + player_weapondelay, + player_tossdelay, + player_starpostx, + player_starposty, + player_starpostz, + player_starpostnum, + player_starposttime, + player_starpostangle, + player_starpostscale, + player_angle_pos, + player_old_angle_pos, + player_axis1, + player_axis2, + player_bumpertime, + player_flyangle, + player_drilltimer, + player_linkcount, + player_linktimer, + player_anotherflyangle, + player_nightstime, + player_drillmeter, + player_drilldelay, + player_bonustime, + player_capsule, + player_drone, + player_oldscale, + player_mare, + player_marelap, + player_marebonuslap, + player_marebegunat, + player_startedtime, + player_finishedtime, + player_lapbegunat, + player_lapstartedtime, + player_finishedspheres, + player_finishedrings, + player_marescore, + player_lastmarescore, + player_totalmarescore, + player_lastmare, + player_lastmarelap, + player_lastmarebonuslap, + player_totalmarelap, + player_totalmarebonuslap, + player_maxlink, + player_texttimer, + player_textvar, + player_lastsidehit, + player_lastlinehit, + player_losstime, + player_timeshit, + player_onconveyor, + player_awayviewmobj, + player_awayviewtics, + player_awayviewaiming, + player_spectator, + player_outofcoop, + player_bot, + player_botleader, + player_lastbuttons, + player_blocked, + player_jointime, + player_quittime, +#ifdef HWRENDER + player_fovadd, +#endif +}; + +static const char *const player_opt[] = { + "valid", + "name", + "realmo", + "mo", + "cmd", + "playerstate", + "camerascale", + "shieldscale", + "viewz", + "viewheight", + "deltaviewheight", + "bob", + "viewrollangle", + "aiming", + "drawangle", + "rings", + "spheres", + "pity", + "currentweapon", + "ringweapons", + "ammoremoval", + "ammoremovaltimer", + "ammoremovalweapon", + "powers", + "pflags", + "panim", + "flashcount", + "flashpal", + "skincolor", + "skin", + "availabilities", + "score", + "dashspeed", + "normalspeed", + "runspeed", + "thrustfactor", + "accelstart", + "acceleration", + "charability", + "charability2", + "charflags", + "thokitem", + "spinitem", + "revitem", + "followitem", + "followmobj", + "actionspd", + "mindash", + "maxdash", + "jumpfactor", + "height", + "spinheight", + "lives", + "continues", + "xtralife", + "gotcontinue", + "speed", + "secondjump", + "fly1", + "scoreadd", + "glidetime", + "climbing", + "deadtimer", + "exiting", + "homing", + "dashmode", + "skidtime", + "cmomx", + "cmomy", + "rmomx", + "rmomy", + "numboxes", + "totalring", + "realtime", + "laps", + "ctfteam", + "gotflag", + "weapondelay", + "tossdelay", + "starpostx", + "starposty", + "starpostz", + "starpostnum", + "starposttime", + "starpostangle", + "starpostscale", + "angle_pos", + "old_angle_pos", + "axis1", + "axis2", + "bumpertime", + "flyangle", + "drilltimer", + "linkcount", + "linktimer", + "anotherflyangle", + "nightstime", + "drillmeter", + "drilldelay", + "bonustime", + "capsule", + "drone", + "oldscale", + "mare", + "marelap", + "marebonuslap", + "marebegunat", + "startedtime", + "finishedtime", + "lapbegunat", + "lapstartedtime", + "finishedspheres", + "finishedrings", + "marescore", + "lastmarescore", + "totalmarescore", + "lastmare", + "lastmarelap", + "lastmarebonuslap", + "totalmarelap", + "totalmarebonuslap", + "maxlink", + "texttimer", + "textvar", + "lastsidehit", + "lastlinehit", + "losstime", + "timeshit", + "onconveyor", + "awayviewmobj", + "awayviewtics", + "awayviewaiming", + "spectator", + "outofcoop", + "bot", + "botleader", + "lastbuttons", + "blocked", + "jointime", + "quittime", +#ifdef HWRENDER + "fovadd", +#endif + NULL, +}; + +static int player_fields_ref = LUA_NOREF; + static int player_get(lua_State *L) { player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - const char *field = luaL_checkstring(L, 2); + enum player_e field = Lua_optoption(L, 2, -1, player_fields_ref); + lua_settop(L, 2); - if (!plr) { - if (fastcmp(field,"valid")) { + if (!plr) + { + if (field == player_valid) + { lua_pushboolean(L, false); return 1; } return LUA_ErrInvalid(L, "player_t"); } - if (fastcmp(field,"valid")) + switch (field) + { + case player_valid: lua_pushboolean(L, true); - else if (fastcmp(field,"name")) + break; + case player_name: lua_pushstring(L, player_names[plr-players]); - else if (fastcmp(field,"realmo")) + break; + case player_realmo: LUA_PushUserdata(L, plr->mo, META_MOBJ); + break; // Kept for backward-compatibility // Should be fixed to work like "realmo" later - else if (fastcmp(field,"mo")) - { + case player_mo: if (plr->spectator) lua_pushnil(L); else LUA_PushUserdata(L, plr->mo, META_MOBJ); - } - else if (fastcmp(field,"cmd")) + break; + case player_cmd: LUA_PushUserdata(L, &plr->cmd, META_TICCMD); - else if (fastcmp(field,"playerstate")) + break; + case player_playerstate: lua_pushinteger(L, plr->playerstate); - else if (fastcmp(field,"camerascale")) + break; + case player_camerascale: lua_pushfixed(L, plr->camerascale); - else if (fastcmp(field,"shieldscale")) + break; + case player_shieldscale: lua_pushfixed(L, plr->shieldscale); - else if (fastcmp(field,"viewz")) + break; + case player_viewz: lua_pushfixed(L, plr->viewz); - else if (fastcmp(field,"viewheight")) + break; + case player_viewheight: lua_pushfixed(L, plr->viewheight); - else if (fastcmp(field,"deltaviewheight")) + break; + case player_deltaviewheight: lua_pushfixed(L, plr->deltaviewheight); - else if (fastcmp(field,"bob")) + break; + case player_bob: lua_pushfixed(L, plr->bob); - else if (fastcmp(field,"viewrollangle")) + break; + case player_viewrollangle: lua_pushangle(L, plr->viewrollangle); - else if (fastcmp(field,"aiming")) + break; + case player_aiming: lua_pushangle(L, plr->aiming); - else if (fastcmp(field,"drawangle")) + break; + case player_drawangle: lua_pushangle(L, plr->drawangle); - else if (fastcmp(field,"rings")) + break; + case player_rings: lua_pushinteger(L, plr->rings); - else if (fastcmp(field,"spheres")) + break; + case player_spheres: lua_pushinteger(L, plr->spheres); - else if (fastcmp(field,"pity")) + break; + case player_pity: lua_pushinteger(L, plr->pity); - else if (fastcmp(field,"currentweapon")) + break; + case player_currentweapon: lua_pushinteger(L, plr->currentweapon); - else if (fastcmp(field,"ringweapons")) + break; + case player_ringweapons: lua_pushinteger(L, plr->ringweapons); - else if (fastcmp(field,"ammoremoval")) + break; + case player_ammoremoval: lua_pushinteger(L, plr->ammoremoval); - else if (fastcmp(field,"ammoremovaltimer")) + break; + case player_ammoremovaltimer: lua_pushinteger(L, plr->ammoremovaltimer); - else if (fastcmp(field,"ammoremovalweapon")) + break; + case player_ammoremovalweapon: lua_pushinteger(L, plr->ammoremovalweapon); - else if (fastcmp(field,"powers")) + break; + case player_powers: LUA_PushUserdata(L, plr->powers, META_POWERS); - else if (fastcmp(field,"pflags")) + break; + case player_pflags: lua_pushinteger(L, plr->pflags); - else if (fastcmp(field,"panim")) + break; + case player_panim: lua_pushinteger(L, plr->panim); - else if (fastcmp(field,"flashcount")) + break; + case player_flashcount: lua_pushinteger(L, plr->flashcount); - else if (fastcmp(field,"flashpal")) + break; + case player_flashpal: lua_pushinteger(L, plr->flashpal); - else if (fastcmp(field,"skincolor")) + break; + case player_skincolor: lua_pushinteger(L, plr->skincolor); - else if (fastcmp(field,"skin")) + break; + case player_skin: lua_pushinteger(L, plr->skin); - else if (fastcmp(field,"availabilities")) + break; + case player_availabilities: lua_pushinteger(L, plr->availabilities); - else if (fastcmp(field,"score")) + break; + case player_score: lua_pushinteger(L, plr->score); - else if (fastcmp(field,"dashspeed")) + break; + case player_dashspeed: lua_pushfixed(L, plr->dashspeed); - else if (fastcmp(field,"normalspeed")) + break; + case player_normalspeed: lua_pushfixed(L, plr->normalspeed); - else if (fastcmp(field,"runspeed")) + break; + case player_runspeed: lua_pushfixed(L, plr->runspeed); - else if (fastcmp(field,"thrustfactor")) + break; + case player_thrustfactor: lua_pushinteger(L, plr->thrustfactor); - else if (fastcmp(field,"accelstart")) + break; + case player_accelstart: lua_pushinteger(L, plr->accelstart); - else if (fastcmp(field,"acceleration")) + break; + case player_acceleration: lua_pushinteger(L, plr->acceleration); - else if (fastcmp(field,"charability")) + break; + case player_charability: lua_pushinteger(L, plr->charability); - else if (fastcmp(field,"charability2")) + break; + case player_charability2: lua_pushinteger(L, plr->charability2); - else if (fastcmp(field,"charflags")) + break; + case player_charflags: lua_pushinteger(L, plr->charflags); - else if (fastcmp(field,"thokitem")) + break; + case player_thokitem: lua_pushinteger(L, plr->thokitem); - else if (fastcmp(field,"spinitem")) + break; + case player_spinitem: lua_pushinteger(L, plr->spinitem); - else if (fastcmp(field,"revitem")) + break; + case player_revitem: lua_pushinteger(L, plr->revitem); - else if (fastcmp(field,"followitem")) + break; + case player_followitem: lua_pushinteger(L, plr->followitem); - else if (fastcmp(field,"followmobj")) + break; + case player_followmobj: LUA_PushUserdata(L, plr->followmobj, META_MOBJ); - else if (fastcmp(field,"actionspd")) + break; + case player_actionspd: lua_pushfixed(L, plr->actionspd); - else if (fastcmp(field,"mindash")) + break; + case player_mindash: lua_pushfixed(L, plr->mindash); - else if (fastcmp(field,"maxdash")) + break; + case player_maxdash: lua_pushfixed(L, plr->maxdash); - else if (fastcmp(field,"jumpfactor")) + break; + case player_jumpfactor: lua_pushfixed(L, plr->jumpfactor); - else if (fastcmp(field,"height")) + break; + case player_height: lua_pushfixed(L, plr->height); - else if (fastcmp(field,"spinheight")) + break; + case player_spinheight: lua_pushfixed(L, plr->spinheight); - else if (fastcmp(field,"lives")) + break; + case player_lives: lua_pushinteger(L, plr->lives); - else if (fastcmp(field,"continues")) + break; + case player_continues: lua_pushinteger(L, plr->continues); - else if (fastcmp(field,"xtralife")) + break; + case player_xtralife: lua_pushinteger(L, plr->xtralife); - else if (fastcmp(field,"gotcontinue")) + break; + case player_gotcontinue: lua_pushinteger(L, plr->gotcontinue); - else if (fastcmp(field,"speed")) + break; + case player_speed: lua_pushfixed(L, plr->speed); - else if (fastcmp(field,"secondjump")) + break; + case player_secondjump: lua_pushinteger(L, plr->secondjump); - else if (fastcmp(field,"fly1")) + break; + case player_fly1: lua_pushinteger(L, plr->fly1); - else if (fastcmp(field,"scoreadd")) + break; + case player_scoreadd: lua_pushinteger(L, plr->scoreadd); - else if (fastcmp(field,"glidetime")) + break; + case player_glidetime: lua_pushinteger(L, plr->glidetime); - else if (fastcmp(field,"climbing")) + break; + case player_climbing: lua_pushinteger(L, plr->climbing); - else if (fastcmp(field,"deadtimer")) + break; + case player_deadtimer: lua_pushinteger(L, plr->deadtimer); - else if (fastcmp(field,"exiting")) + break; + case player_exiting: lua_pushinteger(L, plr->exiting); - else if (fastcmp(field,"homing")) + break; + case player_homing: lua_pushinteger(L, plr->homing); - else if (fastcmp(field,"dashmode")) + break; + case player_dashmode: lua_pushinteger(L, plr->dashmode); - else if (fastcmp(field,"skidtime")) + break; + case player_skidtime: lua_pushinteger(L, plr->skidtime); - else if (fastcmp(field,"cmomx")) + break; + case player_cmomx: lua_pushfixed(L, plr->cmomx); - else if (fastcmp(field,"cmomy")) + break; + case player_cmomy: lua_pushfixed(L, plr->cmomy); - else if (fastcmp(field,"rmomx")) + break; + case player_rmomx: lua_pushfixed(L, plr->rmomx); - else if (fastcmp(field,"rmomy")) + break; + case player_rmomy: lua_pushfixed(L, plr->rmomy); - else if (fastcmp(field,"numboxes")) + break; + case player_numboxes: lua_pushinteger(L, plr->numboxes); - else if (fastcmp(field,"totalring")) + break; + case player_totalring: lua_pushinteger(L, plr->totalring); - else if (fastcmp(field,"realtime")) + break; + case player_realtime: lua_pushinteger(L, plr->realtime); - else if (fastcmp(field,"laps")) + break; + case player_laps: lua_pushinteger(L, plr->laps); - else if (fastcmp(field,"ctfteam")) + break; + case player_ctfteam: lua_pushinteger(L, plr->ctfteam); - else if (fastcmp(field,"gotflag")) + break; + case player_gotflag: lua_pushinteger(L, plr->gotflag); - else if (fastcmp(field,"weapondelay")) + break; + case player_weapondelay: lua_pushinteger(L, plr->weapondelay); - else if (fastcmp(field,"tossdelay")) + break; + case player_tossdelay: lua_pushinteger(L, plr->tossdelay); - else if (fastcmp(field,"starpostx")) + break; + case player_starpostx: lua_pushinteger(L, plr->starpostx); - else if (fastcmp(field,"starposty")) + break; + case player_starposty: lua_pushinteger(L, plr->starposty); - else if (fastcmp(field,"starpostz")) + break; + case player_starpostz: lua_pushinteger(L, plr->starpostz); - else if (fastcmp(field,"starpostnum")) + break; + case player_starpostnum: lua_pushinteger(L, plr->starpostnum); - else if (fastcmp(field,"starposttime")) + break; + case player_starposttime: lua_pushinteger(L, plr->starposttime); - else if (fastcmp(field,"starpostangle")) + break; + case player_starpostangle: lua_pushangle(L, plr->starpostangle); - else if (fastcmp(field,"starpostscale")) + break; + case player_starpostscale: lua_pushfixed(L, plr->starpostscale); - else if (fastcmp(field,"angle_pos")) + break; + case player_angle_pos: lua_pushangle(L, plr->angle_pos); - else if (fastcmp(field,"old_angle_pos")) + break; + case player_old_angle_pos: lua_pushangle(L, plr->old_angle_pos); - else if (fastcmp(field,"axis1")) + break; + case player_axis1: LUA_PushUserdata(L, plr->axis1, META_MOBJ); - else if (fastcmp(field,"axis2")) + break; + case player_axis2: LUA_PushUserdata(L, plr->axis2, META_MOBJ); - else if (fastcmp(field,"bumpertime")) + break; + case player_bumpertime: lua_pushinteger(L, plr->bumpertime); - else if (fastcmp(field,"flyangle")) + break; + case player_flyangle: lua_pushinteger(L, plr->flyangle); - else if (fastcmp(field,"drilltimer")) + break; + case player_drilltimer: lua_pushinteger(L, plr->drilltimer); - else if (fastcmp(field,"linkcount")) + break; + case player_linkcount: lua_pushinteger(L, plr->linkcount); - else if (fastcmp(field,"linktimer")) + break; + case player_linktimer: lua_pushinteger(L, plr->linktimer); - else if (fastcmp(field,"anotherflyangle")) + break; + case player_anotherflyangle: lua_pushinteger(L, plr->anotherflyangle); - else if (fastcmp(field,"nightstime")) + break; + case player_nightstime: lua_pushinteger(L, plr->nightstime); - else if (fastcmp(field,"drillmeter")) + break; + case player_drillmeter: lua_pushinteger(L, plr->drillmeter); - else if (fastcmp(field,"drilldelay")) + break; + case player_drilldelay: lua_pushinteger(L, plr->drilldelay); - else if (fastcmp(field,"bonustime")) + break; + case player_bonustime: lua_pushboolean(L, plr->bonustime); - else if (fastcmp(field,"capsule")) + break; + case player_capsule: LUA_PushUserdata(L, plr->capsule, META_MOBJ); - else if (fastcmp(field,"drone")) + break; + case player_drone: LUA_PushUserdata(L, plr->drone, META_MOBJ); - else if (fastcmp(field,"oldscale")) + break; + case player_oldscale: lua_pushfixed(L, plr->oldscale); - else if (fastcmp(field,"mare")) + break; + case player_mare: lua_pushinteger(L, plr->mare); - else if (fastcmp(field,"marelap")) + break; + case player_marelap: lua_pushinteger(L, plr->marelap); - else if (fastcmp(field,"marebonuslap")) + break; + case player_marebonuslap: lua_pushinteger(L, plr->marebonuslap); - else if (fastcmp(field,"marebegunat")) + break; + case player_marebegunat: lua_pushinteger(L, plr->marebegunat); - else if (fastcmp(field,"startedtime")) + break; + case player_startedtime: lua_pushinteger(L, plr->startedtime); - else if (fastcmp(field,"finishedtime")) + break; + case player_finishedtime: lua_pushinteger(L, plr->finishedtime); - else if (fastcmp(field,"lapbegunat")) + break; + case player_lapbegunat: lua_pushinteger(L, plr->lapbegunat); - else if (fastcmp(field,"lapstartedtime")) + break; + case player_lapstartedtime: lua_pushinteger(L, plr->lapstartedtime); - else if (fastcmp(field,"finishedspheres")) + break; + case player_finishedspheres: lua_pushinteger(L, plr->finishedspheres); - else if (fastcmp(field,"finishedrings")) + break; + case player_finishedrings: lua_pushinteger(L, plr->finishedrings); - else if (fastcmp(field,"marescore")) + break; + case player_marescore: lua_pushinteger(L, plr->marescore); - else if (fastcmp(field,"lastmarescore")) + break; + case player_lastmarescore: lua_pushinteger(L, plr->lastmarescore); - else if (fastcmp(field,"totalmarescore")) + break; + case player_totalmarescore: lua_pushinteger(L, plr->totalmarescore); - else if (fastcmp(field,"lastmare")) + break; + case player_lastmare: lua_pushinteger(L, plr->lastmare); - else if (fastcmp(field,"lastmarelap")) + break; + case player_lastmarelap: lua_pushinteger(L, plr->lastmarelap); - else if (fastcmp(field,"lastmarebonuslap")) + break; + case player_lastmarebonuslap: lua_pushinteger(L, plr->lastmarebonuslap); - else if (fastcmp(field,"totalmarelap")) + break; + case player_totalmarelap: lua_pushinteger(L, plr->totalmarelap); - else if (fastcmp(field,"totalmarebonuslap")) + break; + case player_totalmarebonuslap: lua_pushinteger(L, plr->totalmarebonuslap); - else if (fastcmp(field,"maxlink")) + break; + case player_maxlink: lua_pushinteger(L, plr->maxlink); - else if (fastcmp(field,"texttimer")) + break; + case player_texttimer: lua_pushinteger(L, plr->texttimer); - else if (fastcmp(field,"textvar")) + break; + case player_textvar: lua_pushinteger(L, plr->textvar); - else if (fastcmp(field,"lastsidehit")) + break; + case player_lastsidehit: lua_pushinteger(L, plr->lastsidehit); - else if (fastcmp(field,"lastlinehit")) + break; + case player_lastlinehit: lua_pushinteger(L, plr->lastlinehit); - else if (fastcmp(field,"losstime")) + break; + case player_losstime: lua_pushinteger(L, plr->losstime); - else if (fastcmp(field,"timeshit")) + break; + case player_timeshit: lua_pushinteger(L, plr->timeshit); - else if (fastcmp(field,"onconveyor")) + break; + case player_onconveyor: lua_pushinteger(L, plr->onconveyor); - else if (fastcmp(field,"awayviewmobj")) + break; + case player_awayviewmobj: LUA_PushUserdata(L, plr->awayviewmobj, META_MOBJ); - else if (fastcmp(field,"awayviewtics")) + break; + case player_awayviewtics: lua_pushinteger(L, plr->awayviewtics); - else if (fastcmp(field,"awayviewaiming")) + break; + case player_awayviewaiming: lua_pushangle(L, plr->awayviewaiming); - else if (fastcmp(field,"spectator")) + break; + case player_spectator: lua_pushboolean(L, plr->spectator); - else if (fastcmp(field,"outofcoop")) + break; + case player_outofcoop: lua_pushboolean(L, plr->outofcoop); - else if (fastcmp(field,"bot")) + break; + case player_bot: lua_pushinteger(L, plr->bot); - else if (fastcmp(field,"botleader")) + break; + case player_botleader: LUA_PushUserdata(L, plr->botleader, META_PLAYER); - else if (fastcmp(field,"lastbuttons")) + break; + case player_lastbuttons: lua_pushinteger(L, plr->lastbuttons); - else if (fastcmp(field,"blocked")) + break; + case player_blocked: lua_pushboolean(L, plr->blocked); - else if (fastcmp(field,"jointime")) + break; + case player_jointime: lua_pushinteger(L, plr->jointime); - else if (fastcmp(field,"quittime")) + break; + case player_quittime: lua_pushinteger(L, plr->quittime); + break; #ifdef HWRENDER - else if (fastcmp(field,"fovadd")) + case player_fovadd: lua_pushfixed(L, plr->fovadd); + break; #endif - else { + default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); lua_pushlightuserdata(L, plr); lua_rawget(L, -2); if (!lua_istable(L, -1)) { // no extra values table - CONS_Debug(DBG_LUA, M_GetText("'%s' has no extvars table or field named '%s'; returning nil.\n"), "player_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no extvars table or field named '%s'; returning nil.\n"), "player_t", lua_tostring(L, 2)); return 0; } - lua_getfield(L, -1, field); + lua_pushvalue(L, 2); // field name + lua_gettable(L, -2); if (lua_isnil(L, -1)) // no value for this field - CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "player_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "player_t", lua_tostring(L, 2)); + break; } return 1; } -#define NOSET luaL_error(L, LUA_QL("player_t") " field " LUA_QS " should not be set directly.", field) +#define NOSET luaL_error(L, LUA_QL("player_t") " field " LUA_QS " should not be set directly.", player_opt[field]) static int player_set(lua_State *L) { player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - const char *field = luaL_checkstring(L, 2); + enum player_e field = Lua_optoption(L, 2, player_cmd, player_fields_ref); if (!plr) return LUA_ErrInvalid(L, "player_t"); @@ -414,337 +856,473 @@ static int player_set(lua_State *L) if (hook_cmd_running) return luaL_error(L, "Do not alter player_t in CMD building code!"); - if (fastcmp(field,"mo") || fastcmp(field,"realmo")) { + switch (field) + { + case player_mo: + case player_realmo: + { mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); plr->mo->player = NULL; // remove player pointer from old mobj (newmo->player = plr)->mo = newmo; // set player pointer for new mobj, and set new mobj as the player's mobj + break; } - else if (fastcmp(field,"cmd")) + case player_cmd: return NOSET; - else if (fastcmp(field,"playerstate")) + case player_playerstate: plr->playerstate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"camerascale")) + break; + case player_camerascale: plr->camerascale = luaL_checkfixed(L, 3); - else if (fastcmp(field,"shieldscale")) + break; + case player_shieldscale: plr->shieldscale = luaL_checkfixed(L, 3); - else if (fastcmp(field,"viewz")) + break; + case player_viewz: plr->viewz = luaL_checkfixed(L, 3); - else if (fastcmp(field,"viewheight")) + break; + case player_viewheight: plr->viewheight = luaL_checkfixed(L, 3); - else if (fastcmp(field,"deltaviewheight")) + break; + case player_deltaviewheight: plr->deltaviewheight = luaL_checkfixed(L, 3); - else if (fastcmp(field,"bob")) + break; + case player_bob: plr->bob = luaL_checkfixed(L, 3); - else if (fastcmp(field,"viewrollangle")) + break; + case player_viewrollangle: plr->viewrollangle = luaL_checkangle(L, 3); - else if (fastcmp(field,"aiming")) { + break; + case player_aiming: + { plr->aiming = luaL_checkangle(L, 3); if (plr == &players[consoleplayer]) localaiming = plr->aiming; else if (plr == &players[secondarydisplayplayer]) localaiming2 = plr->aiming; + break; } - else if (fastcmp(field,"drawangle")) + case player_drawangle: plr->drawangle = luaL_checkangle(L, 3); - else if (fastcmp(field,"rings")) + break; + case player_rings: plr->rings = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"spheres")) + break; + case player_spheres: plr->spheres = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"pity")) + break; + case player_pity: plr->pity = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"currentweapon")) + break; + case player_currentweapon: plr->currentweapon = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"ringweapons")) + break; + case player_ringweapons: plr->ringweapons = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"ammoremoval")) + break; + case player_ammoremoval: plr->ammoremoval = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"ammoremovaltimer")) + break; + case player_ammoremovaltimer: plr->ammoremovaltimer = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"ammoremovalweapon")) + break; + case player_ammoremovalweapon: plr->ammoremovalweapon = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"powers")) + break; + case player_powers: return NOSET; - else if (fastcmp(field,"pflags")) + case player_pflags: plr->pflags = luaL_checkinteger(L, 3); - else if (fastcmp(field,"panim")) + break; + case player_panim: plr->panim = luaL_checkinteger(L, 3); - else if (fastcmp(field,"flashcount")) + break; + case player_flashcount: plr->flashcount = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"flashpal")) + break; + case player_flashpal: plr->flashpal = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"skincolor")) + break; + case player_skincolor: { UINT16 newcolor = (UINT16)luaL_checkinteger(L,3); if (newcolor >= numskincolors) return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, numskincolors-1); plr->skincolor = newcolor; + break; } - else if (fastcmp(field,"skin")) + case player_skin: return NOSET; - else if (fastcmp(field,"availabilities")) + case player_availabilities: return NOSET; - else if (fastcmp(field,"score")) + case player_score: plr->score = (UINT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"dashspeed")) + break; + case player_dashspeed: plr->dashspeed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"normalspeed")) + break; + case player_normalspeed: plr->normalspeed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"runspeed")) + break; + case player_runspeed: plr->runspeed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"thrustfactor")) + break; + case player_thrustfactor: plr->thrustfactor = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"accelstart")) + break; + case player_accelstart: plr->accelstart = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"acceleration")) + break; + case player_acceleration: plr->acceleration = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"charability")) + break; + case player_charability: plr->charability = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"charability2")) + break; + case player_charability2: plr->charability2 = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"charflags")) + break; + case player_charflags: plr->charflags = (UINT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"thokitem")) + break; + case player_thokitem: plr->thokitem = luaL_checkinteger(L, 3); - else if (fastcmp(field,"spinitem")) + break; + case player_spinitem: plr->spinitem = luaL_checkinteger(L, 3); - else if (fastcmp(field,"revitem")) + break; + case player_revitem: plr->revitem = luaL_checkinteger(L, 3); - else if (fastcmp(field,"followitem")) + break; + case player_followitem: plr->followitem = luaL_checkinteger(L, 3); - else if (fastcmp(field,"followmobj")) + break; + case player_followmobj: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->followmobj, mo); + break; } - else if (fastcmp(field,"actionspd")) + case player_actionspd: plr->actionspd = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"mindash")) + break; + case player_mindash: plr->mindash = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"maxdash")) + break; + case player_maxdash: plr->maxdash = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"jumpfactor")) + break; + case player_jumpfactor: plr->jumpfactor = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"height")) + break; + case player_height: plr->height = luaL_checkfixed(L, 3); - else if (fastcmp(field,"spinheight")) + break; + case player_spinheight: plr->spinheight = luaL_checkfixed(L, 3); - else if (fastcmp(field,"lives")) + break; + case player_lives: plr->lives = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"continues")) + break; + case player_continues: plr->continues = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"xtralife")) + break; + case player_xtralife: plr->xtralife = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"gotcontinue")) + break; + case player_gotcontinue: plr->gotcontinue = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"speed")) + break; + case player_speed: plr->speed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"secondjump")) + break; + case player_secondjump: plr->secondjump = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"fly1")) + break; + case player_fly1: plr->fly1 = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"scoreadd")) + break; + case player_scoreadd: plr->scoreadd = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"glidetime")) + break; + case player_glidetime: plr->glidetime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"climbing")) + break; + case player_climbing: plr->climbing = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"deadtimer")) + break; + case player_deadtimer: plr->deadtimer = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"exiting")) + break; + case player_exiting: plr->exiting = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"homing")) + break; + case player_homing: plr->homing = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"dashmode")) + break; + case player_dashmode: plr->dashmode = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"skidtime")) + break; + case player_skidtime: plr->skidtime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"cmomx")) + break; + case player_cmomx: plr->cmomx = luaL_checkfixed(L, 3); - else if (fastcmp(field,"cmomy")) + break; + case player_cmomy: plr->cmomy = luaL_checkfixed(L, 3); - else if (fastcmp(field,"rmomx")) + break; + case player_rmomx: plr->rmomx = luaL_checkfixed(L, 3); - else if (fastcmp(field,"rmomy")) + break; + case player_rmomy: plr->rmomy = luaL_checkfixed(L, 3); - else if (fastcmp(field,"numboxes")) + break; + case player_numboxes: plr->numboxes = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"totalring")) + break; + case player_totalring: plr->totalring = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"realtime")) + break; + case player_realtime: plr->realtime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"laps")) + break; + case player_laps: plr->laps = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"ctfteam")) + break; + case player_ctfteam: plr->ctfteam = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"gotflag")) + break; + case player_gotflag: plr->gotflag = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"weapondelay")) + break; + case player_weapondelay: plr->weapondelay = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"tossdelay")) + break; + case player_tossdelay: plr->tossdelay = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starpostx")) + break; + case player_starpostx: plr->starpostx = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starposty")) + break; + case player_starposty: plr->starposty = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starpostz")) + break; + case player_starpostz: plr->starpostz = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starpostnum")) + break; + case player_starpostnum: plr->starpostnum = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starposttime")) + break; + case player_starposttime: plr->starposttime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starpostangle")) + break; + case player_starpostangle: plr->starpostangle = luaL_checkangle(L, 3); - else if (fastcmp(field,"starpostscale")) + break; + case player_starpostscale: plr->starpostscale = luaL_checkfixed(L, 3); - else if (fastcmp(field,"angle_pos")) + break; + case player_angle_pos: plr->angle_pos = luaL_checkangle(L, 3); - else if (fastcmp(field,"old_angle_pos")) + break; + case player_old_angle_pos: plr->old_angle_pos = luaL_checkangle(L, 3); - else if (fastcmp(field,"axis1")) + break; + case player_axis1: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->axis1, mo); + break; } - else if (fastcmp(field,"axis2")) + case player_axis2: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->axis2, mo); + break; } - else if (fastcmp(field,"bumpertime")) + case player_bumpertime: plr->bumpertime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"flyangle")) + break; + case player_flyangle: plr->flyangle = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"drilltimer")) + break; + case player_drilltimer: plr->drilltimer = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"linkcount")) + break; + case player_linkcount: plr->linkcount = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"linktimer")) + break; + case player_linktimer: plr->linktimer = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"anotherflyangle")) + break; + case player_anotherflyangle: plr->anotherflyangle = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"nightstime")) + break; + case player_nightstime: plr->nightstime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"drillmeter")) + break; + case player_drillmeter: plr->drillmeter = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"drilldelay")) + break; + case player_drilldelay: plr->drilldelay = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"bonustime")) + break; + case player_bonustime: plr->bonustime = luaL_checkboolean(L, 3); - else if (fastcmp(field,"capsule")) + break; + case player_capsule: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->capsule, mo); + break; } - else if (fastcmp(field,"drone")) + case player_drone: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->drone, mo); + break; } - else if (fastcmp(field,"oldscale")) + case player_oldscale: plr->oldscale = luaL_checkfixed(L, 3); - else if (fastcmp(field,"mare")) + break; + case player_mare: plr->mare = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"marelap")) + break; + case player_marelap: plr->marelap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"marebonuslap")) + break; + case player_marebonuslap: plr->marebonuslap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"marebegunat")) + break; + case player_marebegunat: plr->marebegunat = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"startedtime")) + break; + case player_startedtime: plr->startedtime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"finishedtime")) + break; + case player_finishedtime: plr->finishedtime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lapbegunat")) + break; + case player_lapbegunat: plr->lapbegunat = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lapstartedtime")) + break; + case player_lapstartedtime: plr->lapstartedtime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"finishedspheres")) + break; + case player_finishedspheres: plr->finishedspheres = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"finishedrings")) + break; + case player_finishedrings: plr->finishedrings = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"marescore")) + break; + case player_marescore: plr->marescore = (UINT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastmarescore")) + break; + case player_lastmarescore: plr->lastmarescore = (UINT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"totalmarescore")) + break; + case player_totalmarescore: plr->totalmarescore = (UINT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastmare")) + break; + case player_lastmare: plr->lastmare = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastmarelap")) + break; + case player_lastmarelap: plr->lastmarelap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastmarebonuslap")) + break; + case player_lastmarebonuslap: plr->lastmarebonuslap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"totalmarelap")) + break; + case player_totalmarelap: plr->totalmarelap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"totalmarebonuslap")) + break; + case player_totalmarebonuslap: plr->totalmarebonuslap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"maxlink")) + break; + case player_maxlink: plr->maxlink = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"texttimer")) + break; + case player_texttimer: plr->texttimer = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"textvar")) + break; + case player_textvar: plr->textvar = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastsidehit")) + break; + case player_lastsidehit: plr->lastsidehit = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastlinehit")) + break; + case player_lastlinehit: plr->lastlinehit = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"losstime")) + break; + case player_losstime: plr->losstime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"timeshit")) + break; + case player_timeshit: plr->timeshit = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"onconveyor")) + break; + case player_onconveyor: plr->onconveyor = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"awayviewmobj")) + break; + case player_awayviewmobj: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->awayviewmobj, mo); + break; } - else if (fastcmp(field,"awayviewtics")) - { + case player_awayviewtics: plr->awayviewtics = (INT32)luaL_checkinteger(L, 3); if (plr->awayviewtics && !plr->awayviewmobj) // awayviewtics must ALWAYS have an awayviewmobj set!! P_SetTarget(&plr->awayviewmobj, plr->mo); // but since the script might set awayviewmobj immediately AFTER setting awayviewtics, use player mobj as filler for now. - } - else if (fastcmp(field,"awayviewaiming")) + break; + case player_awayviewaiming: plr->awayviewaiming = luaL_checkangle(L, 3); - else if (fastcmp(field,"spectator")) + break; + case player_spectator: plr->spectator = lua_toboolean(L, 3); - else if (fastcmp(field,"outofcoop")) + break; + case player_outofcoop: plr->outofcoop = lua_toboolean(L, 3); - else if (fastcmp(field,"bot")) + break; + case player_bot: return NOSET; - else if (fastcmp(field,"botleader")) + case player_botleader: { player_t *player = NULL; if (!lua_isnil(L, 3)) player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER)); plr->botleader = player; + break; } - else if (fastcmp(field,"lastbuttons")) + case player_lastbuttons: plr->lastbuttons = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"blocked")) + break; + case player_blocked: plr->blocked = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"jointime")) + break; + case player_jointime: plr->jointime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"quittime")) + break; + case player_quittime: plr->quittime = (tic_t)luaL_checkinteger(L, 3); + break; #ifdef HWRENDER - else if (fastcmp(field,"fovadd")) + case player_fovadd: plr->fovadd = luaL_checkfixed(L, 3); + break; #endif - else { + default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); lua_pushlightuserdata(L, plr); @@ -752,15 +1330,17 @@ static int player_set(lua_State *L) if (lua_isnil(L, -1)) { // This index doesn't have a table for extra values yet, let's make one. lua_pop(L, 1); - CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "player_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "player_t", lua_tostring(L, 2)); lua_newtable(L); lua_pushlightuserdata(L, plr); lua_pushvalue(L, -2); // ext value table lua_rawset(L, -4); // LREG_EXTVARS table } + lua_pushvalue(L, 2); // key lua_pushvalue(L, 3); // value to store - lua_setfield(L, -2, field); + lua_settable(L, -3); lua_pop(L, 2); + break; } return 0; @@ -812,29 +1392,60 @@ static int power_len(lua_State *L) } #define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field) -#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " should not be set directly.", field) +#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " should not be set directly.", ticcmd_opt[field]) + +enum ticcmd_e +{ + ticcmd_forwardmove, + ticcmd_sidemove, + ticcmd_angleturn, + ticcmd_aiming, + ticcmd_buttons, + ticcmd_latency, +}; + +static const char *const ticcmd_opt[] = { + "forwardmove", + "sidemove", + "angleturn", + "aiming", + "buttons", + "latency", + NULL, +}; + +static int ticcmd_fields_ref = LUA_NOREF; static int ticcmd_get(lua_State *L) { ticcmd_t *cmd = *((ticcmd_t **)luaL_checkudata(L, 1, META_TICCMD)); - const char *field = luaL_checkstring(L, 2); + enum ticcmd_e field = Lua_optoption(L, 2, -1, ticcmd_fields_ref); if (!cmd) return LUA_ErrInvalid(L, "player_t"); - if (fastcmp(field,"forwardmove")) + switch (field) + { + case ticcmd_forwardmove: lua_pushinteger(L, cmd->forwardmove); - else if (fastcmp(field,"sidemove")) + break; + case ticcmd_sidemove: lua_pushinteger(L, cmd->sidemove); - else if (fastcmp(field,"angleturn")) + break; + case ticcmd_angleturn: lua_pushinteger(L, cmd->angleturn); - else if (fastcmp(field,"aiming")) + break; + case ticcmd_aiming: lua_pushinteger(L, cmd->aiming); - else if (fastcmp(field,"buttons")) + break; + case ticcmd_buttons: lua_pushinteger(L, cmd->buttons); - else if (fastcmp(field,"latency")) + break; + case ticcmd_latency: lua_pushinteger(L, cmd->latency); - else + break; + default: return NOFIELD; + } return 1; } @@ -842,27 +1453,35 @@ static int ticcmd_get(lua_State *L) static int ticcmd_set(lua_State *L) { ticcmd_t *cmd = *((ticcmd_t **)luaL_checkudata(L, 1, META_TICCMD)); - const char *field = luaL_checkstring(L, 2); + enum ticcmd_e field = Lua_optoption(L, 2, -1, ticcmd_fields_ref); if (!cmd) return LUA_ErrInvalid(L, "ticcmd_t"); if (hud_running) return luaL_error(L, "Do not alter player_t in HUD rendering code!"); - if (fastcmp(field,"forwardmove")) + switch (field) + { + case ticcmd_forwardmove: cmd->forwardmove = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"sidemove")) + break; + case ticcmd_sidemove: cmd->sidemove = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"angleturn")) + break; + case ticcmd_angleturn: cmd->angleturn = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"aiming")) + break; + case ticcmd_aiming: cmd->aiming = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"buttons")) + break; + case ticcmd_buttons: cmd->buttons = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"latency")) + break; + case ticcmd_latency: return NOSET; - else + default: return NOFIELD; + } return 0; } @@ -883,6 +1502,8 @@ int LUA_PlayerLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L,1); + player_fields_ref = Lua_CreateFieldTable(L, player_opt); + luaL_newmetatable(L, META_POWERS); lua_pushcfunction(L, power_get); lua_setfield(L, -2, "__index"); @@ -902,6 +1523,8 @@ int LUA_PlayerLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L,1); + ticcmd_fields_ref = Lua_CreateFieldTable(L, ticcmd_opt); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getPlayer); diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index a91c354f4..c3d9d9d1a 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by Iestyn "Monster Iestyn" Jealous. -// Copyright (C) 2020-2022 by Sonic Team Junior. +// Copyright (C) 2020-2023 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2020-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_script.c b/src/lua_script.c index 4d4071545..6893265d5 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -204,6 +204,9 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"modifiedgame")) { lua_pushboolean(L, modifiedgame && !savemoddata); return 1; + } else if (fastcmp(word,"usedCheats")) { + lua_pushboolean(L, usedCheats); + return 1; } else if (fastcmp(word,"menuactive")) { lua_pushboolean(L, menuactive); return 1; @@ -303,6 +306,18 @@ int LUA_PushGlobals(lua_State *L, const char *word) lua_pushinteger(L, ammoremovaltics); return 1; // end timers + } else if (fastcmp(word,"use1upSound")) { + lua_pushinteger(L, use1upSound); + return 1; + } else if (fastcmp(word,"maxXtraLife")) { + lua_pushinteger(L, maxXtraLife); + return 1; + } else if (fastcmp(word,"useContinues")) { + lua_pushinteger(L, useContinues); + return 1; + } else if (fastcmp(word,"shareEmblems")) { + lua_pushinteger(L, shareEmblems); + return 1; } else if (fastcmp(word,"gametype")) { lua_pushinteger(L, gametype); return 1; @@ -447,7 +462,7 @@ int LUA_CheckGlobals(lua_State *L, const char *word) if (strlen(str) < strlength) return luaL_error(L, "string must not contain embedded zeros!"); - strncpy(mapmusname, str, strlength); + strlcpy(mapmusname, str, sizeof mapmusname); } else if (fastcmp(word, "mapmusflags")) mapmusflags = (UINT16)luaL_checkinteger(L, 2); @@ -695,20 +710,23 @@ void LUA_DumpFile(const char *filename) fixed_t LUA_EvalMath(const char *word) { - lua_State *L = NULL; + static lua_State *L = NULL; char buf[1024], *b; const char *p; fixed_t res = 0; - // make a new state so SOC can't interefere with scripts - // allocate state - L = lua_newstate(LUA_Alloc, NULL); - lua_atpanic(L, LUA_Panic); + if (!L) + { + // make a new state so SOC can't interefere with scripts + // allocate state + L = lua_newstate(LUA_Alloc, NULL); + lua_atpanic(L, LUA_Panic); - // open only enum lib - lua_pushcfunction(L, LUA_EnumLib); - lua_pushboolean(L, true); - lua_call(L, 1, 0); + // open only enum lib + lua_pushcfunction(L, LUA_EnumLib); + lua_pushboolean(L, true); + lua_call(L, 1, 0); + } // change ^ into ^^ for Lua. strcpy(buf, "return "); @@ -733,8 +751,6 @@ fixed_t LUA_EvalMath(const char *word) else res = lua_tointeger(L, -1); - // clean up and return. - lua_close(L); return res; } @@ -1713,17 +1729,39 @@ void LUA_UnArchive(void) } // For mobj_t, player_t, etc. to take custom variables. -int Lua_optoption(lua_State *L, int narg, - const char *def, const char *const lst[]) +int Lua_optoption(lua_State *L, int narg, int def, int list_ref) { - const char *name = (def) ? luaL_optstring(L, narg, def) : luaL_checkstring(L, narg); - int i; - for (i=0; lst[i]; i++) - if (fastcmp(lst[i], name)) - return i; + if (lua_isnoneornil(L, narg)) + return def; + + I_Assert(lua_checkstack(L, 2)); + luaL_checkstring(L, narg); + + lua_rawgeti(L, LUA_REGISTRYINDEX, list_ref); + I_Assert(lua_istable(L, -1)); + lua_pushvalue(L, narg); + lua_rawget(L, -2); + + if (lua_isnumber(L, -1)) + return lua_tointeger(L, -1); return -1; } +int Lua_CreateFieldTable(lua_State *L, const char *const lst[]) +{ + int i; + + lua_newtable(L); + for (i = 0; lst[i] != NULL; i++) + { + lua_pushstring(L, lst[i]); + lua_pushinteger(L, i); + lua_settable(L, -3); + } + + return luaL_ref(L, LUA_REGISTRYINDEX); +} + void LUA_PushTaggableObjectArray ( lua_State *L, const char *field, diff --git a/src/lua_script.h b/src/lua_script.h index e586b04a8..d0b06a719 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -57,8 +57,8 @@ int LUA_PushGlobals(lua_State *L, const char *word); int LUA_CheckGlobals(lua_State *L, const char *word); void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c void LUA_CVarChanged(void *cvar); // lua_consolelib.c -int Lua_optoption(lua_State *L, int narg, - const char *def, const char *const lst[]); +int Lua_optoption(lua_State *L, int narg, int def, int list_ref); +int Lua_CreateFieldTable(lua_State *L, const char *const lst[]); void LUA_HookNetArchive(lua_CFunction archFunc); void LUA_PushTaggableObjectArray diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 9c7c4ad03..b7890a6c7 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2022 by Sonic Team Junior. +// Copyright (C) 2014-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -55,6 +55,7 @@ enum skin { skin_soundsid, skin_sprites }; + static const char *const skin_opt[] = { "valid", "name", @@ -95,10 +96,12 @@ static const char *const skin_opt[] = { #define UNIMPLEMENTED luaL_error(L, LUA_QL("skin_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", skin_opt[field]) +static int skin_fields_ref = LUA_NOREF; + static int skin_get(lua_State *L) { skin_t *skin = *((skin_t **)luaL_checkudata(L, 1, META_SKIN)); - enum skin field = luaL_checkoption(L, 2, NULL, skin_opt); + enum skin field = Lua_optoption(L, 2, -1, skin_fields_ref); // skins are always valid, only added, never removed I_Assert(skin != NULL); @@ -376,6 +379,8 @@ int LUA_SkinLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L,1); + skin_fields_ref = Lua_CreateFieldTable(L, skin_opt); + luaL_newmetatable(L, META_SOUNDSID); lua_pushcfunction(L, soundsid_get); lua_setfield(L, -2, "__index"); diff --git a/src/lua_taglib.c b/src/lua_taglib.c index b69416362..2ba60df99 100644 --- a/src/lua_taglib.c +++ b/src/lua_taglib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by James R. -// Copyright (C) 2020-2022 by Sonic Team Junior. +// Copyright (C) 2020-2023 by James R. +// Copyright (C) 2020-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c index 963fdbd5a..cff92f34d 100644 --- a/src/lua_thinkerlib.c +++ b/src/lua_thinkerlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_aatree.c b/src/m_aatree.c index 522e38a53..a530395f6 100644 --- a/src/m_aatree.c +++ b/src/m_aatree.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_aatree.h b/src/m_aatree.h index ed011644e..91716f346 100644 --- a/src/m_aatree.h +++ b/src/m_aatree.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_anigif.c b/src/m_anigif.c index 41765e6e1..90e4c69ce 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. // Copyright (C) 2013 by "Ninji". -// Copyright (C) 2013-2022 by Sonic Team Junior. +// Copyright (C) 2013-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_anigif.h b/src/m_anigif.h index ad64dff7b..060c5f585 100644 --- a/src/m_anigif.h +++ b/src/m_anigif.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 2013-2022 by Sonic Team Junior. +// Copyright (C) 2013-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_argv.c b/src/m_argv.c index 1444f0c38..475be23a3 100644 --- a/src/m_argv.c +++ b/src/m_argv.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_argv.h b/src/m_argv.h index cdb6aa246..2d74ca150 100644 --- a/src/m_argv.h +++ b/src/m_argv.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_bbox.c b/src/m_bbox.c index 7fde0c171..75c84385a 100644 --- a/src/m_bbox.c +++ b/src/m_bbox.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_bbox.h b/src/m_bbox.h index 588000fae..046e325a9 100644 --- a/src/m_bbox.h +++ b/src/m_bbox.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cheat.c b/src/m_cheat.c index 89c8009ae..e370335f8 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -72,19 +72,16 @@ static UINT8 cheatf_ultimate(void) static UINT8 cheatf_warp(void) { - if (modifiedgame) - return 0; - if (menuactive && currentMenu != &MainDef) return 0; // Only on the main menu! S_StartSound(0, sfx_itemup); // Temporarily unlock stuff. - G_SetGameModified(false); - unlockables[31].unlocked = true; // credits - unlockables[30].unlocked = true; // sound test - unlockables[28].unlocked = true; // level select + G_SetUsedCheats(false); + clientGamedata->unlocked[31] = true; // credits + clientGamedata->unlocked[30] = true; // sound test + clientGamedata->unlocked[28] = true; // level select // Refresh secrets menu existing. M_ClearMenus(true); @@ -97,18 +94,15 @@ static UINT8 cheatf_devmode(void) { UINT8 i; - if (modifiedgame) - return 0; - if (menuactive && currentMenu != &MainDef) return 0; // Only on the main menu! S_StartSound(0, sfx_itemup); // Just unlock all the things and turn on -debug and console devmode. - G_SetGameModified(false); + G_SetUsedCheats(false); for (i = 0; i < MAXUNLOCKABLES; i++) - unlockables[i].unlocked = true; + clientGamedata->unlocked[i] = true; devparm = true; cv_debug |= 0x8000; @@ -244,7 +238,7 @@ boolean cht_Responder(event_t *ev) } // Console cheat commands rely on these a lot... -#define REQUIRE_PANDORA if (!M_SecretUnlocked(SECRET_PANDORA) && !cv_debug)\ +#define REQUIRE_PANDORA if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !cv_debug)\ { CONS_Printf(M_GetText("You haven't earned this yet.\n")); return; } #define REQUIRE_DEVMODE if (!cv_debug)\ @@ -275,7 +269,7 @@ void Command_CheatNoClip_f(void) plyr->pflags ^= PF_NOCLIP; CONS_Printf(M_GetText("No Clipping %s\n"), plyr->pflags & PF_NOCLIP ? M_GetText("On") : M_GetText("Off")); - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } void Command_CheatGod_f(void) @@ -290,7 +284,7 @@ void Command_CheatGod_f(void) plyr->pflags ^= PF_GODMODE; CONS_Printf(M_GetText("Cheese Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off")); - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } void Command_CheatNoTarget_f(void) @@ -305,7 +299,7 @@ void Command_CheatNoTarget_f(void) plyr->pflags ^= PF_INVIS; CONS_Printf(M_GetText("SEP Field %s\n"), plyr->pflags & PF_INVIS ? M_GetText("On") : M_GetText("Off")); - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } void Command_Scale_f(void) @@ -879,7 +873,7 @@ void Command_Devmode_f(void) return; } - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } void Command_Setrings_f(void) @@ -905,7 +899,7 @@ void Command_Setrings_f(void) // no totalsphere addition to revert } - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } } @@ -928,7 +922,7 @@ void Command_Setlives_f(void) P_GivePlayerLives(&players[consoleplayer], atoi(COM_Argv(1))); } - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } } @@ -955,7 +949,7 @@ void Command_Setcontinues_f(void) players[consoleplayer].continues = numcontinues; - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } } @@ -1004,7 +998,7 @@ static void OP_CycleThings(INT32 amt) } while (mobjinfo[op_currentthing].doomednum == -1 || op_currentthing == MT_NIGHTSDRONE - || mobjinfo[op_currentthing].flags & MF_NOSECTOR + || mobjinfo[op_currentthing].flags & (MF_AMBIENT|MF_NOSECTOR) || (states[mobjinfo[op_currentthing].spawnstate].sprite == SPR_NULL && states[mobjinfo[op_currentthing].seestate].sprite == SPR_NULL) ); @@ -1446,7 +1440,7 @@ void Command_ObjectPlace_f(void) REQUIRE_SINGLEPLAYER; REQUIRE_NOULTIMATE; - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); silent = COM_CheckParm("-silent"); diff --git a/src/m_cheat.h b/src/m_cheat.h index 086117579..f4ac01d84 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cond.c b/src/m_cond.c index 1406317c5..a54988f67 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -21,6 +21,9 @@ #include "r_skins.h" // numskins #include "r_draw.h" // R_GetColorByName +gamedata_t *clientGamedata; // Our gamedata +gamedata_t *serverGamedata; // Server's gamedata + // Map triggers for linedef executors // 32 triggers, one bit each UINT32 unlocktriggers; @@ -41,6 +44,70 @@ unlockable_t unlockables[MAXUNLOCKABLES]; INT32 numemblems = 0; INT32 numextraemblems = 0; +// Temporary holding place for nights data for the current map +nightsdata_t ntemprecords; + +// Create a new gamedata_t, for start-up +gamedata_t *M_NewGameDataStruct(void) +{ + gamedata_t *data = Z_Calloc(sizeof (*data), PU_STATIC, NULL); + M_ClearSecrets(data); + G_ClearRecords(data); + return data; +} + +void M_CopyGameData(gamedata_t *dest, gamedata_t *src) +{ + INT32 i, j; + + M_ClearSecrets(dest); + G_ClearRecords(dest); + + dest->loaded = src->loaded; + dest->totalplaytime = src->totalplaytime; + + dest->timesBeaten = src->timesBeaten; + dest->timesBeatenWithEmeralds = src->timesBeatenWithEmeralds; + dest->timesBeatenUltimate = src->timesBeatenUltimate; + + memcpy(dest->achieved, src->achieved, sizeof(dest->achieved)); + memcpy(dest->collected, src->collected, sizeof(dest->collected)); + memcpy(dest->extraCollected, src->extraCollected, sizeof(dest->extraCollected)); + memcpy(dest->unlocked, src->unlocked, sizeof(dest->unlocked)); + + memcpy(dest->mapvisited, src->mapvisited, sizeof(dest->mapvisited)); + + // Main records + for (i = 0; i < NUMMAPS; ++i) + { + if (!src->mainrecords[i]) + continue; + + G_AllocMainRecordData((INT16)i, dest); + dest->mainrecords[i]->score = src->mainrecords[i]->score; + dest->mainrecords[i]->time = src->mainrecords[i]->time; + dest->mainrecords[i]->rings = src->mainrecords[i]->rings; + } + + // Nights records + for (i = 0; i < NUMMAPS; ++i) + { + if (!src->nightsrecords[i] || !src->nightsrecords[i]->nummares) + continue; + + G_AllocNightsRecordData((INT16)i, dest); + + for (j = 0; j < (src->nightsrecords[i]->nummares + 1); j++) + { + dest->nightsrecords[i]->score[j] = src->nightsrecords[i]->score[j]; + dest->nightsrecords[i]->grade[j] = src->nightsrecords[i]->grade[j]; + dest->nightsrecords[i]->time[j] = src->nightsrecords[i]->time[j]; + } + + dest->nightsrecords[i]->nummares = src->nightsrecords[i]->nummares; + } +} + void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2) { condition_t *cond; @@ -70,89 +137,90 @@ void M_ClearConditionSet(UINT8 set) conditionSets[set - 1].condition = NULL; conditionSets[set - 1].numconditions = 0; } - conditionSets[set - 1].achieved = false; + clientGamedata->achieved[set - 1] = serverGamedata->achieved[set - 1] = false; } // Clear ALL secrets. -void M_ClearSecrets(void) +void M_ClearSecrets(gamedata_t *data) { INT32 i; - memset(mapvisited, 0, sizeof(mapvisited)); + memset(data->mapvisited, 0, sizeof(data->mapvisited)); for (i = 0; i < MAXEMBLEMS; ++i) - emblemlocations[i].collected = false; + data->collected[i] = false; for (i = 0; i < MAXEXTRAEMBLEMS; ++i) - extraemblems[i].collected = false; + data->extraCollected[i] = false; for (i = 0; i < MAXUNLOCKABLES; ++i) - unlockables[i].unlocked = false; + data->unlocked[i] = false; for (i = 0; i < MAXCONDITIONSETS; ++i) - conditionSets[i].achieved = false; + data->achieved[i] = false; - timesBeaten = timesBeatenWithEmeralds = timesBeatenUltimate = 0; + data->timesBeaten = data->timesBeatenWithEmeralds = data->timesBeatenUltimate = 0; // Re-unlock any always unlocked things - M_SilentUpdateUnlockablesAndEmblems(); + M_SilentUpdateUnlockablesAndEmblems(data); + M_SilentUpdateSkinAvailabilites(); } // ---------------------- // Condition set checking // ---------------------- -static UINT8 M_CheckCondition(condition_t *cn) +static UINT8 M_CheckCondition(condition_t *cn, gamedata_t *data) { switch (cn->type) { case UC_PLAYTIME: // Requires total playing time >= x - return (totalplaytime >= (unsigned)cn->requirement); + return (data->totalplaytime >= (unsigned)cn->requirement); case UC_GAMECLEAR: // Requires game beaten >= x times - return (timesBeaten >= (unsigned)cn->requirement); + return (data->timesBeaten >= (unsigned)cn->requirement); case UC_ALLEMERALDS: // Requires game beaten with all 7 emeralds >= x times - return (timesBeatenWithEmeralds >= (unsigned)cn->requirement); + return (data->timesBeatenWithEmeralds >= (unsigned)cn->requirement); case UC_ULTIMATECLEAR: // Requires game beaten on ultimate >= x times (in other words, never) - return (timesBeatenUltimate >= (unsigned)cn->requirement); + return (data->timesBeatenUltimate >= (unsigned)cn->requirement); case UC_OVERALLSCORE: // Requires overall score >= x - return (M_GotHighEnoughScore(cn->requirement)); + return (M_GotHighEnoughScore(cn->requirement, data)); case UC_OVERALLTIME: // Requires overall time <= x - return (M_GotLowEnoughTime(cn->requirement)); + return (M_GotLowEnoughTime(cn->requirement, data)); case UC_OVERALLRINGS: // Requires overall rings >= x - return (M_GotHighEnoughRings(cn->requirement)); + return (M_GotHighEnoughRings(cn->requirement, data)); case UC_MAPVISITED: // Requires map x to be visited - return ((mapvisited[cn->requirement - 1] & MV_VISITED) == MV_VISITED); + return ((data->mapvisited[cn->requirement - 1] & MV_VISITED) == MV_VISITED); case UC_MAPBEATEN: // Requires map x to be beaten - return ((mapvisited[cn->requirement - 1] & MV_BEATEN) == MV_BEATEN); + return ((data->mapvisited[cn->requirement - 1] & MV_BEATEN) == MV_BEATEN); case UC_MAPALLEMERALDS: // Requires map x to be beaten with all emeralds in possession - return ((mapvisited[cn->requirement - 1] & MV_ALLEMERALDS) == MV_ALLEMERALDS); + return ((data->mapvisited[cn->requirement - 1] & MV_ALLEMERALDS) == MV_ALLEMERALDS); case UC_MAPULTIMATE: // Requires map x to be beaten on ultimate - return ((mapvisited[cn->requirement - 1] & MV_ULTIMATE) == MV_ULTIMATE); + return ((data->mapvisited[cn->requirement - 1] & MV_ULTIMATE) == MV_ULTIMATE); case UC_MAPPERFECT: // Requires map x to be beaten with a perfect bonus - return ((mapvisited[cn->requirement - 1] & MV_PERFECT) == MV_PERFECT); + return ((data->mapvisited[cn->requirement - 1] & MV_PERFECT) == MV_PERFECT); case UC_MAPSCORE: // Requires score on map >= x - return (G_GetBestScore(cn->extrainfo1) >= (unsigned)cn->requirement); + return (G_GetBestScore(cn->extrainfo1, data) >= (unsigned)cn->requirement); case UC_MAPTIME: // Requires time on map <= x - return (G_GetBestTime(cn->extrainfo1) <= (unsigned)cn->requirement); + return (G_GetBestTime(cn->extrainfo1, data) <= (unsigned)cn->requirement); case UC_MAPRINGS: // Requires rings on map >= x - return (G_GetBestRings(cn->extrainfo1) >= cn->requirement); + return (G_GetBestRings(cn->extrainfo1, data) >= cn->requirement); case UC_NIGHTSSCORE: - return (G_GetBestNightsScore(cn->extrainfo1, (UINT8)cn->extrainfo2) >= (unsigned)cn->requirement); + return (G_GetBestNightsScore(cn->extrainfo1, (UINT8)cn->extrainfo2, data) >= (unsigned)cn->requirement); case UC_NIGHTSTIME: - return (G_GetBestNightsTime(cn->extrainfo1, (UINT8)cn->extrainfo2) <= (unsigned)cn->requirement); + return (G_GetBestNightsTime(cn->extrainfo1, (UINT8)cn->extrainfo2, data) <= (unsigned)cn->requirement); case UC_NIGHTSGRADE: - return (G_GetBestNightsGrade(cn->extrainfo1, (UINT8)cn->extrainfo2) >= cn->requirement); + return (G_GetBestNightsGrade(cn->extrainfo1, (UINT8)cn->extrainfo2, data) >= cn->requirement); case UC_TRIGGER: // requires map trigger set return !!(unlocktriggers & (1 << cn->requirement)); case UC_TOTALEMBLEMS: // Requires number of emblems >= x - return (M_GotEnoughEmblems(cn->requirement)); + return (M_GotEnoughEmblems(cn->requirement, data)); case UC_EMBLEM: // Requires emblem x to be obtained - return emblemlocations[cn->requirement-1].collected; + return data->collected[cn->requirement-1]; case UC_EXTRAEMBLEM: // Requires extra emblem x to be obtained - return extraemblems[cn->requirement-1].collected; + return data->extraCollected[cn->requirement-1]; case UC_CONDITIONSET: // requires condition set x to already be achieved - return M_Achieved(cn->requirement-1); + return M_Achieved(cn->requirement-1, data); } return false; } -static UINT8 M_CheckConditionSet(conditionset_t *c) +static UINT8 M_CheckConditionSet(conditionset_t *c, gamedata_t *data) { UINT32 i; UINT32 lastID = 0; @@ -173,13 +241,13 @@ static UINT8 M_CheckConditionSet(conditionset_t *c) continue; lastID = cn->id; - achievedSoFar = M_CheckCondition(cn); + achievedSoFar = M_CheckCondition(cn, data); } return achievedSoFar; } -void M_CheckUnlockConditions(void) +void M_CheckUnlockConditions(gamedata_t *data) { INT32 i; conditionset_t *c; @@ -187,30 +255,27 @@ void M_CheckUnlockConditions(void) for (i = 0; i < MAXCONDITIONSETS; ++i) { c = &conditionSets[i]; - if (!c->numconditions || c->achieved) + if (!c->numconditions || data->achieved[i]) continue; - c->achieved = (M_CheckConditionSet(c)); + data->achieved[i] = (M_CheckConditionSet(c, data)); } } -UINT8 M_UpdateUnlockablesAndExtraEmblems(void) +UINT8 M_UpdateUnlockablesAndExtraEmblems(gamedata_t *data) { INT32 i; char cechoText[992] = ""; UINT8 cechoLines = 0; - if (modifiedgame && !savemoddata) - return false; - - M_CheckUnlockConditions(); + M_CheckUnlockConditions(data); // Go through extra emblems for (i = 0; i < numextraemblems; ++i) { - if (extraemblems[i].collected || !extraemblems[i].conditionset) + if (data->extraCollected[i] || !extraemblems[i].conditionset) continue; - if ((extraemblems[i].collected = M_Achieved(extraemblems[i].conditionset - 1)) != false) + if ((data->extraCollected[i] = M_Achieved(extraemblems[i].conditionset - 1, data)) != false) { strcat(cechoText, va(M_GetText("Got \"%s\" emblem!\\"), extraemblems[i].name)); ++cechoLines; @@ -220,14 +285,14 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(void) // Fun part: if any of those unlocked we need to go through the // unlock conditions AGAIN just in case an emblem reward was reached if (cechoLines) - M_CheckUnlockConditions(); + M_CheckUnlockConditions(data); // Go through unlockables for (i = 0; i < MAXUNLOCKABLES; ++i) { - if (unlockables[i].unlocked || !unlockables[i].conditionset) + if (data->unlocked[i] || !unlockables[i].conditionset) continue; - if ((unlockables[i].unlocked = M_Achieved(unlockables[i].conditionset - 1)) != false) + if ((data->unlocked[i] = M_Achieved(unlockables[i].conditionset - 1, data)) != false) { if (unlockables[i].nocecho) continue; @@ -251,45 +316,50 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(void) HU_DoCEcho(slashed); return true; } + return false; } // Used when loading gamedata to make sure all unlocks are synched with conditions -void M_SilentUpdateUnlockablesAndEmblems(void) +void M_SilentUpdateUnlockablesAndEmblems(gamedata_t *data) { INT32 i; boolean checkAgain = false; // Just in case they aren't to sync - M_CheckUnlockConditions(); - M_CheckLevelEmblems(); + M_CheckUnlockConditions(data); + M_CheckLevelEmblems(data); + M_CompletionEmblems(data); // Go through extra emblems for (i = 0; i < numextraemblems; ++i) { - if (extraemblems[i].collected || !extraemblems[i].conditionset) + if (data->extraCollected[i] || !extraemblems[i].conditionset) continue; - if ((extraemblems[i].collected = M_Achieved(extraemblems[i].conditionset - 1)) != false) + if ((data->extraCollected[i] = M_Achieved(extraemblems[i].conditionset - 1, data)) != false) checkAgain = true; } // check again if extra emblems unlocked, blah blah, etc if (checkAgain) - M_CheckUnlockConditions(); + M_CheckUnlockConditions(data); // Go through unlockables for (i = 0; i < MAXUNLOCKABLES; ++i) { - if (unlockables[i].unlocked || !unlockables[i].conditionset) + if (data->unlocked[i] || !unlockables[i].conditionset) continue; - unlockables[i].unlocked = M_Achieved(unlockables[i].conditionset - 1); + data->unlocked[i] = M_Achieved(unlockables[i].conditionset - 1, data); } +} +void M_SilentUpdateSkinAvailabilites(void) +{ players[consoleplayer].availabilities = players[1].availabilities = R_GetSkinAvailabilities(); // players[1] is supposed to be for 2p } // Emblem unlocking shit -UINT8 M_CheckLevelEmblems(void) +UINT8 M_CheckLevelEmblems(gamedata_t *data) { INT32 i; INT32 valToReach; @@ -300,7 +370,7 @@ UINT8 M_CheckLevelEmblems(void) // Update Score, Time, Rings emblems for (i = 0; i < numemblems; ++i) { - if (emblemlocations[i].type <= ET_SKIN || emblemlocations[i].type == ET_MAP || emblemlocations[i].collected) + if (emblemlocations[i].type <= ET_SKIN || emblemlocations[i].type == ET_MAP || data->collected[i]) continue; levelnum = emblemlocations[i].level; @@ -309,32 +379,32 @@ UINT8 M_CheckLevelEmblems(void) switch (emblemlocations[i].type) { case ET_SCORE: // Requires score on map >= x - res = (G_GetBestScore(levelnum) >= (unsigned)valToReach); + res = (G_GetBestScore(levelnum, data) >= (unsigned)valToReach); break; case ET_TIME: // Requires time on map <= x - res = (G_GetBestTime(levelnum) <= (unsigned)valToReach); + res = (G_GetBestTime(levelnum, data) <= (unsigned)valToReach); break; case ET_RINGS: // Requires rings on map >= x - res = (G_GetBestRings(levelnum) >= valToReach); + res = (G_GetBestRings(levelnum, data) >= valToReach); break; case ET_NGRADE: // Requires NiGHTS grade on map >= x - res = (G_GetBestNightsGrade(levelnum, 0) >= valToReach); + res = (G_GetBestNightsGrade(levelnum, 0, data) >= valToReach); break; case ET_NTIME: // Requires NiGHTS time on map <= x - res = (G_GetBestNightsTime(levelnum, 0) <= (unsigned)valToReach); + res = (G_GetBestNightsTime(levelnum, 0, data) <= (unsigned)valToReach); break; default: // unreachable but shuts the compiler up. continue; } - emblemlocations[i].collected = res; + data->collected[i] = res; if (res) ++somethingUnlocked; } return somethingUnlocked; } -UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separate print when awarding emblems and it's sorta different enough. +UINT8 M_CompletionEmblems(gamedata_t *data) // Bah! Duplication sucks, but it's for a separate print when awarding emblems and it's sorta different enough. { INT32 i; INT32 embtype; @@ -345,7 +415,7 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa for (i = 0; i < numemblems; ++i) { - if (emblemlocations[i].type != ET_MAP || emblemlocations[i].collected) + if (emblemlocations[i].type != ET_MAP || data->collected[i]) continue; levelnum = emblemlocations[i].level; @@ -361,9 +431,9 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa if (embtype & ME_PERFECT) flags |= MV_PERFECT; - res = ((mapvisited[levelnum - 1] & flags) == flags); + res = ((data->mapvisited[levelnum - 1] & flags) == flags); - emblemlocations[i].collected = res; + data->collected[i] = res; if (res) ++somethingUnlocked; } @@ -373,48 +443,54 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa // ------------------- // Quick unlock checks // ------------------- -UINT8 M_AnySecretUnlocked(void) +UINT8 M_AnySecretUnlocked(gamedata_t *data) { INT32 i; for (i = 0; i < MAXUNLOCKABLES; ++i) { - if (!unlockables[i].nocecho && unlockables[i].unlocked) + if (!unlockables[i].nocecho && data->unlocked[i]) return true; } return false; } -UINT8 M_SecretUnlocked(INT32 type) +UINT8 M_SecretUnlocked(INT32 type, gamedata_t *data) { INT32 i; for (i = 0; i < MAXUNLOCKABLES; ++i) { - if (unlockables[i].type == type && unlockables[i].unlocked) + if (unlockables[i].type == type && data->unlocked[i]) return true; } return false; } -UINT8 M_MapLocked(INT32 mapnum) +UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data) { if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->unlockrequired < 0) + { return false; - if (!unlockables[mapheaderinfo[mapnum-1]->unlockrequired].unlocked) + } + + if (!data->unlocked[mapheaderinfo[mapnum-1]->unlockrequired]) + { return true; + } + return false; } -INT32 M_CountEmblems(void) +INT32 M_CountEmblems(gamedata_t *data) { INT32 found = 0, i; for (i = 0; i < numemblems; ++i) { - if (emblemlocations[i].collected) + if (data->collected[i]) found++; } for (i = 0; i < numextraemblems; ++i) { - if (extraemblems[i].collected) + if (data->extraCollected[i]) found++; } return found; @@ -426,23 +502,23 @@ INT32 M_CountEmblems(void) // Theoretically faster than using M_CountEmblems() // Stops when it reaches the target number of emblems. -UINT8 M_GotEnoughEmblems(INT32 number) +UINT8 M_GotEnoughEmblems(INT32 number, gamedata_t *data) { INT32 i, gottenemblems = 0; for (i = 0; i < numemblems; ++i) { - if (emblemlocations[i].collected) + if (data->collected[i]) if (++gottenemblems >= number) return true; } for (i = 0; i < numextraemblems; ++i) { - if (extraemblems[i].collected) + if (data->extraCollected[i]) if (++gottenemblems >= number) return true; } return false; } -UINT8 M_GotHighEnoughScore(INT32 tscore) +UINT8 M_GotHighEnoughScore(INT32 tscore, gamedata_t *data) { INT32 mscore = 0; INT32 i; @@ -451,16 +527,16 @@ UINT8 M_GotHighEnoughScore(INT32 tscore) { if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) continue; - if (!mainrecords[i]) + if (!data->mainrecords[i]) continue; - if ((mscore += mainrecords[i]->score) > tscore) + if ((mscore += data->mainrecords[i]->score) > tscore) return true; } return false; } -UINT8 M_GotLowEnoughTime(INT32 tictime) +UINT8 M_GotLowEnoughTime(INT32 tictime, gamedata_t *data) { INT32 curtics = 0; INT32 i; @@ -470,15 +546,15 @@ UINT8 M_GotLowEnoughTime(INT32 tictime) if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) continue; - if (!mainrecords[i] || !mainrecords[i]->time) + if (!data->mainrecords[i] || !data->mainrecords[i]->time) return false; - else if ((curtics += mainrecords[i]->time) > tictime) + else if ((curtics += data->mainrecords[i]->time) > tictime) return false; } return true; } -UINT8 M_GotHighEnoughRings(INT32 trings) +UINT8 M_GotHighEnoughRings(INT32 trings, gamedata_t *data) { INT32 mrings = 0; INT32 i; @@ -487,10 +563,10 @@ UINT8 M_GotHighEnoughRings(INT32 trings) { if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) continue; - if (!mainrecords[i]) + if (!data->mainrecords[i]) continue; - if ((mrings += mainrecords[i]->rings) > trings) + if ((mrings += data->mainrecords[i]->rings) > trings) return true; } return false; diff --git a/src/m_cond.h b/src/m_cond.h index f36c80009..6a3da79ec 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 2012-2022 by Sonic Team Junior. +// Copyright (C) 2012-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -10,7 +10,11 @@ /// \file m_cond.h /// \brief Unlockable condition system for SRB2 version 2.1 +#ifndef __M_COND__ +#define __M_COND__ + #include "doomdef.h" +#include "doomdata.h" // -------- // Typedefs @@ -61,8 +65,6 @@ typedef struct { UINT32 numconditions; /// <- number of conditions. condition_t *condition; /// <- All conditionals to be checked. - UINT8 achieved; /// <- Whether this conditional has been achieved already or not. - /// (Conditional checking is skipped if true -- it's assumed you can't relock an unlockable) } conditionset_t; // Emblem information @@ -94,7 +96,6 @@ typedef struct INT32 var; ///< If needed, specifies information on the target amount to achieve (or target skin) char *stringVar; ///< String version char hint[110]; ///< Hint for emblem hints menu - UINT8 collected; ///< Do you have this emblem? } emblem_t; typedef struct { @@ -104,7 +105,6 @@ typedef struct UINT8 showconditionset; ///< Condition set that shows this emblem. UINT8 sprite; ///< emblem sprite to use, 0 - 25 UINT16 color; ///< skincolor to use - UINT8 collected; ///< Do you have this emblem? } extraemblem_t; // Unlockable information @@ -120,7 +120,6 @@ typedef struct char *stringVar; UINT8 nocecho; UINT8 nochecklist; - UINT8 unlocked; } unlockable_t; #define SECRET_NONE -6 // Does nil. Use with levels locked by UnlockRequired @@ -143,6 +142,83 @@ typedef struct #define MAXEXTRAEMBLEMS 16 #define MAXUNLOCKABLES 32 +/** Time attack information, currently a very small structure. + */ +typedef struct +{ + tic_t time; ///< Time in which the level was finished. + UINT32 score; ///< Score when the level was finished. + UINT16 rings; ///< Rings when the level was finished. +} recorddata_t; + +/** Setup for one NiGHTS map. + * These are dynamically allocated because I am insane + */ +#define GRADE_F 0 +#define GRADE_E 1 +#define GRADE_D 2 +#define GRADE_C 3 +#define GRADE_B 4 +#define GRADE_A 5 +#define GRADE_S 6 + +typedef struct +{ + // 8 mares, 1 overall (0) + UINT8 nummares; + UINT32 score[9]; + UINT8 grade[9]; + tic_t time[9]; +} nightsdata_t; + +// mapvisited is now a set of flags that says what we've done in the map. +#define MV_VISITED 1 +#define MV_BEATEN 2 +#define MV_ALLEMERALDS 4 +#define MV_ULTIMATE 8 +#define MV_PERFECT 16 +#define MV_PERFECTRA 32 +#define MV_MAX 63 // used in gamedata check, update whenever MV's are added + +// Temporary holding place for nights data for the current map +extern nightsdata_t ntemprecords; + +// GAMEDATA STRUCTURE +// Everything that would get saved in gamedata.dat +typedef struct +{ + // WHENEVER OR NOT WE'RE READY TO SAVE + boolean loaded; + + // CONDITION SETS ACHIEVED + boolean achieved[MAXCONDITIONSETS]; + + // EMBLEMS COLLECTED + boolean collected[MAXEMBLEMS]; + + // EXTRA EMBLEMS COLLECTED + boolean extraCollected[MAXEXTRAEMBLEMS]; + + // UNLOCKABLES UNLOCKED + boolean unlocked[MAXUNLOCKABLES]; + + // TIME ATTACK DATA + recorddata_t *mainrecords[NUMMAPS]; + nightsdata_t *nightsrecords[NUMMAPS]; + UINT8 mapvisited[NUMMAPS]; + + // # OF TIMES THE GAME HAS BEEN BEATEN + UINT32 timesBeaten; + UINT32 timesBeatenWithEmeralds; + UINT32 timesBeatenUltimate; + + // PLAY TIME + UINT32 totalplaytime; +} gamedata_t; + +extern gamedata_t *clientGamedata; +extern gamedata_t *serverGamedata; + extern conditionset_t conditionSets[MAXCONDITIONSETS]; extern emblem_t emblemlocations[MAXEMBLEMS]; extern extraemblem_t extraemblems[MAXEXTRAEMBLEMS]; @@ -153,25 +229,30 @@ extern INT32 numextraemblems; extern UINT32 unlocktriggers; +gamedata_t *M_NewGameDataStruct(void); +void M_CopyGameData(gamedata_t *dest, gamedata_t *src); + // Condition set setup void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2); // Clearing secrets void M_ClearConditionSet(UINT8 set); -void M_ClearSecrets(void); +void M_ClearSecrets(gamedata_t *data); // Updating conditions and unlockables -void M_CheckUnlockConditions(void); -UINT8 M_UpdateUnlockablesAndExtraEmblems(void); -void M_SilentUpdateUnlockablesAndEmblems(void); -UINT8 M_CheckLevelEmblems(void); -UINT8 M_CompletionEmblems(void); +void M_CheckUnlockConditions(gamedata_t *data); +UINT8 M_UpdateUnlockablesAndExtraEmblems(gamedata_t *data); +void M_SilentUpdateUnlockablesAndEmblems(gamedata_t *data); +UINT8 M_CheckLevelEmblems(gamedata_t *data); +UINT8 M_CompletionEmblems(gamedata_t *data); + +void M_SilentUpdateSkinAvailabilites(void); // Checking unlockable status -UINT8 M_AnySecretUnlocked(void); -UINT8 M_SecretUnlocked(INT32 type); -UINT8 M_MapLocked(INT32 mapnum); -INT32 M_CountEmblems(void); +UINT8 M_AnySecretUnlocked(gamedata_t *data); +UINT8 M_SecretUnlocked(INT32 type, gamedata_t *data); +UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data); +INT32 M_CountEmblems(gamedata_t *data); // Emblem shit emblem_t *M_GetLevelEmblems(INT32 mapnum); @@ -183,12 +264,14 @@ const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big); // If you're looking to compare stats for unlocks or what not, use these // They stop checking upon reaching the target number so they // should be (theoretically?) slightly faster. -UINT8 M_GotEnoughEmblems(INT32 number); -UINT8 M_GotHighEnoughScore(INT32 tscore); -UINT8 M_GotLowEnoughTime(INT32 tictime); -UINT8 M_GotHighEnoughRings(INT32 trings); +UINT8 M_GotEnoughEmblems(INT32 number, gamedata_t *data); +UINT8 M_GotHighEnoughScore(INT32 tscore, gamedata_t *data); +UINT8 M_GotLowEnoughTime(INT32 tictime, gamedata_t *data); +UINT8 M_GotHighEnoughRings(INT32 trings, gamedata_t *data); INT32 M_UnlockableSkinNum(unlockable_t *unlock); INT32 M_EmblemSkinNum(emblem_t *emblem); -#define M_Achieved(a) ((a) >= MAXCONDITIONSETS || conditionSets[a].achieved) +#define M_Achieved(a, data) ((a) >= MAXCONDITIONSETS || data->achieved[a]) + +#endif diff --git a/src/m_dllist.h b/src/m_dllist.h index d8ca6648a..06a479422 100644 --- a/src/m_dllist.h +++ b/src/m_dllist.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2005 by James Haley -// Copyright (C) 2005-2022 by Sonic Team Junior. +// Copyright (C) 2005-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_easing.c b/src/m_easing.c index 0f1cc1d02..48fe1efbc 100644 --- a/src/m_easing.c +++ b/src/m_easing.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_easing.h b/src/m_easing.h index 229222a15..eaa5d6773 100644 --- a/src/m_easing.h +++ b/src/m_easing.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_fixed.c b/src/m_fixed.c index ded294b0a..ad2831196 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_fixed.h b/src/m_fixed.h index 73e629f44..4a5b7ce2a 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_menu.c b/src/m_menu.c index 83b788fd5..cf61e7fb1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -241,6 +241,7 @@ static void M_EmblemHints(INT32 choice); static void M_HandleEmblemHints(INT32 choice); UINT32 hintpage = 1; static void M_HandleChecklist(INT32 choice); +static void M_PauseLevelSelect(INT32 choice); menu_t SR_MainDef, SR_UnlockChecklistDef; static UINT8 check_on; @@ -388,6 +389,7 @@ static void M_DrawRoomMenu(void); #endif static void M_DrawJoystick(void); static void M_DrawSetupMultiPlayerMenu(void); +static void M_DrawColorRamp(INT32 x, INT32 y, INT32 w, INT32 h, skincolor_t color); // Handling functions static boolean M_ExitPandorasBox(void); @@ -554,26 +556,30 @@ static menuitem_t MPauseMenu[] = { {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8}, {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, - {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_MapChange, 24}, + {IT_STRING | IT_CALL, NULL, "Emblem Hints...", M_EmblemHints, 24}, + {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_MapChange, 32}, - {IT_STRING | IT_CALL, NULL, "Continue", M_SelectableClearMenus,40}, - {IT_STRING | IT_CALL, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen - {IT_STRING | IT_CALL, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen + {IT_STRING | IT_CALL, NULL, "Continue", M_SelectableClearMenus,48}, - {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48}, - {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48}, - {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48}, - {IT_STRING | IT_CALL, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone - {IT_STRING | IT_CALL, NULL, "Options", M_Options, 64}, + {IT_STRING | IT_CALL, NULL, "Player 1 Setup", M_SetupMultiPlayer, 56}, // splitscreen + {IT_STRING | IT_CALL, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 64}, - {IT_STRING | IT_CALL, NULL, "Return to Title", M_EndGame, 80}, - {IT_STRING | IT_CALL, NULL, "Quit Game", M_QuitSRB2, 88}, + {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 56}, // alone + {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 56}, + {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 56}, + {IT_STRING | IT_CALL, NULL, "Player Setup", M_SetupMultiPlayer, 64}, + + {IT_STRING | IT_CALL, NULL, "Options", M_Options, 72}, + + {IT_STRING | IT_CALL, NULL, "Return to Title", M_EndGame, 88}, + {IT_STRING | IT_CALL, NULL, "Quit Game", M_QuitSRB2, 96}, }; typedef enum { mpause_addons = 0, mpause_scramble, + mpause_hints, mpause_switchmap, mpause_continue, @@ -597,7 +603,7 @@ static menuitem_t SPauseMenu[] = // Pandora's Box will be shifted up if both options are available {IT_CALL | IT_STRING, NULL, "Pandora's Box...", M_PandorasBox, 16}, {IT_CALL | IT_STRING, NULL, "Emblem Hints...", M_EmblemHints, 24}, - {IT_CALL | IT_STRING, NULL, "Level Select...", M_LoadGameLevelSelect, 32}, + {IT_CALL | IT_STRING, NULL, "Level Select...", M_PauseLevelSelect, 32}, {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,48}, {IT_CALL | IT_STRING, NULL, "Retry", M_Retry, 56}, @@ -757,12 +763,12 @@ static menuitem_t SR_EmblemHintMenu[] = static menuitem_t SP_MainMenu[] = { // Note: If changing the positions here, also change them in M_SinglePlayerMenu() - {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 76}, - {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 84}, - {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 92}, - {IT_SECRET, NULL, "Marathon Run", M_Marathon, 100}, - {IT_CALL | IT_STRING, NULL, "Tutorial", M_StartTutorial, 108}, - {IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 116} + {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 76}, + {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 84}, + {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 92}, + {IT_SECRET, NULL, "Marathon Run", M_Marathon, 100}, + {IT_CALL | IT_STRING, NULL, "Tutorial", M_StartTutorial, 108}, + {IT_CALL | IT_STRING, NULL, "Statistics", M_Statistics, 116} }; enum @@ -970,7 +976,7 @@ static menuitem_t MP_MainMenu[] = { {IT_HEADER, NULL, "Join a game", NULL, 0}, {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenuModChecks, 12}, - {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 22}, + {IT_STRING|IT_KEYHANDLER, NULL, "Specify server address:", M_HandleConnectIP, 22}, {IT_HEADER, NULL, "Host a game", NULL, 54}, {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 66}, {IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 76}, @@ -1129,10 +1135,11 @@ static menuitem_t OP_ChangeControlsMenu[] = {IT_CALL | IT_STRING2, NULL, "Game Status", M_ChangeControl, GC_SCORES }, {IT_CALL | IT_STRING2, NULL, "Pause / Run Retry", M_ChangeControl, GC_PAUSE }, - {IT_CALL | IT_STRING2, NULL, "Screenshot", M_ChangeControl, GC_SCREENSHOT }, - {IT_CALL | IT_STRING2, NULL, "Toggle GIF Recording", M_ChangeControl, GC_RECORDGIF }, - {IT_CALL | IT_STRING2, NULL, "Open/Close Menu (ESC)", M_ChangeControl, GC_SYSTEMMENU }, - {IT_CALL | IT_STRING2, NULL, "Change Viewpoint", M_ChangeControl, GC_VIEWPOINT }, + {IT_CALL | IT_STRING2, NULL, "Screenshot", M_ChangeControl, GC_SCREENSHOT }, + {IT_CALL | IT_STRING2, NULL, "Toggle GIF Recording", M_ChangeControl, GC_RECORDGIF }, + {IT_CALL | IT_STRING2, NULL, "Open/Close Menu (ESC)", M_ChangeControl, GC_SYSTEMMENU }, + {IT_CALL | IT_STRING2, NULL, "Next Viewpoint", M_ChangeControl, GC_VIEWPOINTNEXT }, + {IT_CALL | IT_STRING2, NULL, "Prev Viewpoint", M_ChangeControl, GC_VIEWPOINTPREV }, {IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, GC_CONSOLE }, {IT_HEADER, NULL, "Multiplayer", NULL, 0}, {IT_SPACE, NULL, NULL, NULL, 0}, // padding @@ -1823,6 +1830,10 @@ menu_t SP_LevelSelectDef = MAPPLATTERMENUSTYLE( MTREE4(MN_SP_MAIN, MN_SP_LOAD, MN_SP_PLAYER, MN_SP_LEVELSELECT), NULL, SP_LevelSelectMenu); +menu_t SP_PauseLevelSelectDef = MAPPLATTERMENUSTYLE( + MTREE4(MN_SP_MAIN, MN_SP_LOAD, MN_SP_PLAYER, MN_SP_LEVELSELECT), + NULL, SP_LevelSelectMenu); + menu_t SP_LevelStatsDef = { MTREE2(MN_SP_MAIN, MN_SP_LEVELSTATS), @@ -2283,6 +2294,7 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt); // Nextmap. Used for Level select. void Nextmap_OnChange(void) { + gamedata_t *data = clientGamedata; char *leveltitle; char tabase[256]; #ifdef OLDNREPLAYNAME @@ -2300,7 +2312,7 @@ void Nextmap_OnChange(void) { CV_StealthSetValue(&cv_dummymares, 0); // Hide the record changing CVAR if only one mare is available. - if (!nightsrecords[cv_nextmap.value-1] || nightsrecords[cv_nextmap.value-1]->nummares < 2) + if (!data->nightsrecords[cv_nextmap.value-1] || data->nightsrecords[cv_nextmap.value-1]->nummares < 2) SP_NightsAttackMenu[narecords].status = IT_DISABLED; else SP_NightsAttackMenu[narecords].status = IT_STRING|IT_CVAR; @@ -2431,14 +2443,15 @@ void Nextmap_OnChange(void) static void Dummymares_OnChange(void) { - if (!nightsrecords[cv_nextmap.value-1]) + gamedata_t *data = clientGamedata; + if (!data->nightsrecords[cv_nextmap.value-1]) { CV_StealthSetValue(&cv_dummymares, 0); return; } else { - UINT8 mares = nightsrecords[cv_nextmap.value-1]->nummares; + UINT8 mares = data->nightsrecords[cv_nextmap.value-1]->nummares; if (cv_dummymares.value < 0) CV_StealthSetValue(&cv_dummymares, mares); @@ -3514,10 +3527,12 @@ boolean M_Responder(event_t *ev) { if (((currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_CALL || (currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_SUBMENU) - && (currentMenu->menuitems[itemOn].status & IT_CALLTYPE)) + && (currentMenu->menuitems[itemOn].status & IT_CALLTYPE)) { #ifndef DEVELOP - if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && modifiedgame && !savemoddata) + // TODO: Replays are scary, so I left the remaining instances of this alone. + // It'd be nice to get rid of this once and for all though! + if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && (modifiedgame && !savemoddata) && !usedCheats) { S_StartSound(NULL, sfx_skid); M_StartMessage(M_GetText("This cannot be done in a modified game.\n\n(Press a key)\n"), NULL, MM_NOTHING); @@ -3667,9 +3682,9 @@ void M_StartControlPanel(void) if (!Playing()) { // Secret menu! - MainMenu[singleplr].alphaKey = (M_AnySecretUnlocked()) ? 76 : 84; - MainMenu[multiplr].alphaKey = (M_AnySecretUnlocked()) ? 84 : 92; - MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + MainMenu[singleplr].alphaKey = (M_AnySecretUnlocked(clientGamedata)) ? 76 : 84; + MainMenu[multiplr].alphaKey = (M_AnySecretUnlocked(clientGamedata)) ? 84 : 92; + MainMenu[secrets].status = (M_AnySecretUnlocked(clientGamedata)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); currentMenu = &MainDef; itemOn = singleplr; @@ -3677,14 +3692,14 @@ void M_StartControlPanel(void) else if (modeattacking) { currentMenu = &MAPauseDef; - MAPauseMenu[mapause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + MAPauseMenu[mapause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS, clientGamedata)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); itemOn = mapause_continue; } else if (!(netgame || multiplayer)) // Single Player { if (gamestate != GS_LEVEL || ultimatemode) // intermission, so gray out stuff. { - SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA)) ? (IT_GRAYEDOUT) : (IT_DISABLED); + SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA, serverGamedata)) ? (IT_GRAYEDOUT) : (IT_DISABLED); SPauseMenu[spause_retry].status = IT_GRAYEDOUT; } else @@ -3693,7 +3708,7 @@ void M_StartControlPanel(void) if (players[consoleplayer].playerstate != PST_LIVE) ++numlives; - SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); // The list of things that can disable retrying is (was?) a little too complex // for me to want to use the short if statement syntax @@ -3704,10 +3719,10 @@ void M_StartControlPanel(void) } // We can always use level select though. :33 - SPauseMenu[spause_levelselect].status = (gamecomplete == 1) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + SPauseMenu[spause_levelselect].status = (maplistoption != 0) ? (IT_STRING | IT_CALL) : (IT_DISABLED); // And emblem hints. - SPauseMenu[spause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + SPauseMenu[spause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS, clientGamedata) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); // Shift up Pandora's Box if both pandora and levelselect are active /*if (SPauseMenu[spause_pandora].status != (IT_DISABLED) @@ -3742,12 +3757,10 @@ void M_StartControlPanel(void) if (splitscreen) { MPauseMenu[mpause_psetupsplit].status = MPauseMenu[mpause_psetupsplit2].status = IT_STRING | IT_CALL; - MPauseMenu[mpause_psetup].text = "Player 1 Setup"; } else { MPauseMenu[mpause_psetup].status = IT_STRING | IT_CALL; - MPauseMenu[mpause_psetup].text = "Player Setup"; if (G_GametypeHasTeams()) MPauseMenu[mpause_switchteam].status = IT_STRING | IT_SUBMENU; @@ -3757,6 +3770,8 @@ void M_StartControlPanel(void) MPauseMenu[mpause_spectate].status = IT_GRAYEDOUT; } + MPauseMenu[mpause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS, clientGamedata) && G_CoopGametype()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + currentMenu = &MPauseDef; itemOn = mpause_continue; } @@ -3908,7 +3923,7 @@ void M_Init(void) { int i; - COM_AddCommand("manual", Command_Manual_f); + COM_AddCommand("manual", Command_Manual_f, COM_LUA); CV_RegisterVar(&cv_nextmap); CV_RegisterVar(&cv_newgametype); @@ -4256,7 +4271,7 @@ static void M_DrawMapEmblems(INT32 mapnum, INT32 x, INT32 y, boolean norecordatt x -= 4; lasttype = curtype; - if (emblem->collected) + if (clientGamedata->collected[emblem - emblemlocations]) V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); else @@ -4689,7 +4704,9 @@ static void M_DrawGenericScrollMenu(void) static void M_DrawPauseMenu(void) { - if (!netgame && !multiplayer && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION)) + gamedata_t *data = clientGamedata; + + if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) { emblem_t *emblem_detail[3] = {NULL, NULL, NULL}; char emblem_text[3][20]; @@ -4717,7 +4734,7 @@ static void M_DrawPauseMenu(void) { case ET_SCORE: snprintf(targettext, 9, "%d", emblem->var); - snprintf(currenttext, 9, "%u", G_GetBestScore(gamemap)); + snprintf(currenttext, 9, "%u", G_GetBestScore(gamemap, data)); targettext[8] = 0; currenttext[8] = 0; @@ -4731,7 +4748,7 @@ static void M_DrawPauseMenu(void) G_TicsToSeconds((tic_t)emblemslot), G_TicsToCentiseconds((tic_t)emblemslot)); - emblemslot = (INT32)G_GetBestTime(gamemap); // dumb hack pt ii + emblemslot = (INT32)G_GetBestTime(gamemap, data); // dumb hack pt ii if ((tic_t)emblemslot == UINT32_MAX) snprintf(currenttext, 9, "-:--.--"); else @@ -4747,7 +4764,7 @@ static void M_DrawPauseMenu(void) break; case ET_RINGS: snprintf(targettext, 9, "%d", emblem->var); - snprintf(currenttext, 9, "%u", G_GetBestRings(gamemap)); + snprintf(currenttext, 9, "%u", G_GetBestRings(gamemap, data)); targettext[8] = 0; currenttext[8] = 0; @@ -4755,8 +4772,8 @@ static void M_DrawPauseMenu(void) emblemslot = 2; break; case ET_NGRADE: - snprintf(targettext, 9, "%u", P_GetScoreForGradeOverall(gamemap, emblem->var)); - snprintf(currenttext, 9, "%u", G_GetBestNightsScore(gamemap, 0)); + snprintf(targettext, 9, "%u", P_GetScoreForGrade(gamemap, 0, emblem->var)); + snprintf(currenttext, 9, "%u", G_GetBestNightsScore(gamemap, 0, data)); targettext[8] = 0; currenttext[8] = 0; @@ -4770,7 +4787,7 @@ static void M_DrawPauseMenu(void) G_TicsToSeconds((tic_t)emblemslot), G_TicsToCentiseconds((tic_t)emblemslot)); - emblemslot = (INT32)G_GetBestNightsTime(gamemap, 0); // dumb hack pt iv + emblemslot = (INT32)G_GetBestNightsTime(gamemap, 0, data); // dumb hack pt iv if ((tic_t)emblemslot == UINT32_MAX) snprintf(currenttext, 9, "-:--.--"); else @@ -4804,7 +4821,7 @@ static void M_DrawPauseMenu(void) if (!emblem) continue; - if (emblem->collected) + if (data->collected[emblem - emblemlocations]) V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); else @@ -5016,7 +5033,9 @@ static void M_PatchSkinNameTable(void) // static boolean M_LevelAvailableOnPlatter(INT32 mapnum) { - if (M_MapLocked(mapnum+1)) + gamedata_t *data = serverGamedata; + + if (M_MapLocked(mapnum+1, data)) return false; // not unlocked switch (levellistmode) @@ -5029,7 +5048,7 @@ static boolean M_LevelAvailableOnPlatter(INT32 mapnum) return true; #ifndef DEVELOP - if (mapvisited[mapnum]) // MV_MP + if (data->mapvisited[mapnum]) #endif return true; @@ -5037,7 +5056,7 @@ static boolean M_LevelAvailableOnPlatter(INT32 mapnum) case LLM_RECORDATTACK: case LLM_NIGHTSATTACK: #ifndef DEVELOP - if (mapvisited[mapnum] & MV_MAX) + if (data->mapvisited[mapnum]) return true; if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) @@ -5068,7 +5087,7 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) if (!mapheaderinfo[mapnum]->lvlttl[0]) return false; - /*if (M_MapLocked(mapnum+1)) + /*if (M_MapLocked(mapnum+1, serverGamedata)) return false; // not unlocked*/ switch (levellistmode) @@ -5963,7 +5982,7 @@ static void M_DrawLevelPlatterMenu(void) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) { - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + F_SkyScroll(curbgname); // Draw and animate foreground if (!strncmp("RECATKBG", curbgname, 8)) M_DrawRecordAttackForeground(); @@ -6225,7 +6244,7 @@ static void M_DrawMessageMenu(void) } else { - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + F_SkyScroll(curbgname); if (!strncmp("RECATKBG", curbgname, 8)) M_DrawRecordAttackForeground(); } @@ -6709,7 +6728,7 @@ static void M_DrawAddons(void) // draw save icon x = BASEVIDWIDTH - x - 16; - V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); + V_DrawSmallScaledPatch(x, y + 4, (!usedCheats ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); if (modifiedgame) V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+2]); @@ -6901,7 +6920,7 @@ static void M_HandleAddons(INT32 choice) closefilemenu(true); // secrets disabled by addfile... - MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + MainMenu[secrets].status = (M_AnySecretUnlocked(clientGamedata)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); @@ -7080,7 +7099,7 @@ static void M_AllowSuper(INT32 choice) M_StartMessage(M_GetText("You are now capable of turning super.\nRemember to get all the emeralds!\n"),NULL,MM_NOTHING); SR_PandorasBox[6].status = IT_GRAYEDOUT; - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } static void M_GetAllEmeralds(INT32 choice) @@ -7091,7 +7110,7 @@ static void M_GetAllEmeralds(INT32 choice) M_StartMessage(M_GetText("You now have all 7 emeralds.\nUse them wisely.\nWith great power comes great ring drain.\n"),NULL,MM_NOTHING); SR_PandorasBox[7].status = IT_GRAYEDOUT; - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } static void M_DestroyRobotsResponse(INT32 ch) @@ -7102,7 +7121,7 @@ static void M_DestroyRobotsResponse(INT32 ch) // Destroy all robots P_DestroyRobots(); - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } static void M_DestroyRobots(INT32 choice) @@ -7115,6 +7134,7 @@ static void M_DestroyRobots(INT32 choice) static void M_LevelSelectWarp(INT32 choice) { boolean fromloadgame = (currentMenu == &SP_LevelSelectDef); + boolean frompause = (currentMenu == &SP_PauseLevelSelectDef); (void)choice; @@ -7125,7 +7145,6 @@ static void M_LevelSelectWarp(INT32 choice) } startmap = (INT16)(cv_nextmap.value); - fromlevelselect = true; if (fromloadgame) @@ -7133,7 +7152,20 @@ static void M_LevelSelectWarp(INT32 choice) else { cursaveslot = 0; - M_SetupChoosePlayer(0); + + if (frompause) + { + M_ClearMenus(true); + + G_DeferedInitNew(false, G_BuildMapName(startmap), cv_skin.value, false, fromlevelselect); // Not sure about using cv_skin here, but it seems fine in testing. + COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this + + if (levelselect.rows) + Z_Free(levelselect.rows); + levelselect.rows = NULL; + } + else + M_SetupChoosePlayer(0); } } @@ -7147,7 +7179,9 @@ static boolean checklist_cangodown; // uuuueeerggghhhh HACK static void M_HandleChecklist(INT32 choice) { + gamedata_t *data = clientGamedata; INT32 j; + switch (choice) { case KEY_DOWNARROW: @@ -7164,7 +7198,7 @@ static void M_HandleChecklist(INT32 choice) continue; if (unlockables[j].conditionset > MAXCONDITIONSETS) continue; - if (!unlockables[j].unlocked && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset)) + if (!data->unlocked[j] && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset, data)) continue; if (unlockables[j].conditionset == unlockables[check_on].conditionset) continue; @@ -7189,7 +7223,7 @@ static void M_HandleChecklist(INT32 choice) continue; if (unlockables[j].conditionset > MAXCONDITIONSETS) continue; - if (!unlockables[j].unlocked && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset)) + if (!data->unlocked[j] && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset, data)) continue; if (j && unlockables[j].conditionset == unlockables[j-1].conditionset) continue; @@ -7215,6 +7249,9 @@ static void M_HandleChecklist(INT32 choice) static void M_DrawChecklist(void) { + gamedata_t *data = clientGamedata; + INT32 emblemCount = M_CountEmblems(data); + INT32 i = check_on, j = 0, y = currentMenu->y, emblems = numemblems+numextraemblems; UINT32 condnum, previd, maxcond; condition_t *cond; @@ -7225,7 +7262,7 @@ static void M_DrawChecklist(void) // draw emblem counter if (emblems > 0) { - V_DrawString(42, 20, (emblems == M_CountEmblems()) ? V_GREENMAP : 0, va("%d/%d", M_CountEmblems(), emblems)); + V_DrawString(42, 20, (emblems == emblemCount) ? V_GREENMAP : 0, va("%d/%d", emblemCount, emblems)); V_DrawSmallScaledPatch(28, 20, 0, W_CachePatchName("EMBLICON", PU_PATCH)); } @@ -7236,13 +7273,13 @@ static void M_DrawChecklist(void) { if (unlockables[i].name[0] == 0 //|| unlockables[i].nochecklist || !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS - || (!unlockables[i].unlocked && unlockables[i].showconditionset && !M_Achieved(unlockables[i].showconditionset))) + || (!data->unlocked[i] && unlockables[i].showconditionset && !M_Achieved(unlockables[i].showconditionset, data))) { i += 1; continue; } - V_DrawString(currentMenu->x, y, ((unlockables[i].unlocked) ? V_GREENMAP : V_TRANSLUCENT)|V_ALLOWLOWERCASE, ((unlockables[i].unlocked || !unlockables[i].nochecklist) ? unlockables[i].name : M_CreateSecretMenuOption(unlockables[i].name))); + V_DrawString(currentMenu->x, y, ((data->unlocked[i]) ? V_GREENMAP : V_TRANSLUCENT)|V_ALLOWLOWERCASE, ((data->unlocked[i] || !unlockables[i].nochecklist) ? unlockables[i].name : M_CreateSecretMenuOption(unlockables[i].name))); for (j = i+1; j < MAXUNLOCKABLES; j++) { @@ -7320,7 +7357,7 @@ static void M_DrawChecklist(void) if (title) { - const char *level = ((M_MapLocked(cond[condnum].requirement) || !((mapheaderinfo[cond[condnum].requirement-1]->menuflags & LF2_NOVISITNEEDED) || (mapvisited[cond[condnum].requirement-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); + const char *level = ((M_MapLocked(cond[condnum].requirement, data) || !((mapheaderinfo[cond[condnum].requirement-1]->menuflags & LF2_NOVISITNEEDED) || (data->mapvisited[cond[condnum].requirement-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); switch (cond[condnum].type) { @@ -7353,7 +7390,7 @@ static void M_DrawChecklist(void) if (title) { - const char *level = ((M_MapLocked(cond[condnum].extrainfo1) || !((mapheaderinfo[cond[condnum].extrainfo1-1]->menuflags & LF2_NOVISITNEEDED) || (mapvisited[cond[condnum].extrainfo1-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); + const char *level = ((M_MapLocked(cond[condnum].extrainfo1, data) || !((mapheaderinfo[cond[condnum].extrainfo1-1]->menuflags & LF2_NOVISITNEEDED) || (data->mapvisited[cond[condnum].extrainfo1-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); switch (cond[condnum].type) { @@ -7422,7 +7459,7 @@ static void M_DrawChecklist(void) if (title) { - const char *level = ((M_MapLocked(cond[condnum].extrainfo1) || !((mapheaderinfo[cond[condnum].extrainfo1-1]->menuflags & LF2_NOVISITNEEDED) || (mapvisited[cond[condnum].extrainfo1-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); + const char *level = ((M_MapLocked(cond[condnum].extrainfo1, data) || !((mapheaderinfo[cond[condnum].extrainfo1-1]->menuflags & LF2_NOVISITNEEDED) || (data->mapvisited[cond[condnum].extrainfo1-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); switch (cond[condnum].type) { @@ -7485,7 +7522,7 @@ static void M_DrawChecklist(void) /*V_DrawString(160, 8+(24*j), V_RETURN8, V_WordWrap(160, 292, 0, unlockables[i].objective)); - if (unlockables[i].unlocked) + if (data->unlocked[i]) V_DrawString(308, 8+(24*j), V_YELLOWMAP, "Y"); else V_DrawString(308, 8+(24*j), V_YELLOWMAP, "N");*/ @@ -7514,7 +7551,7 @@ static void M_EmblemHints(INT32 choice) (void)choice; SR_EmblemHintMenu[0].status = (local > NUMHINTS*2) ? (IT_STRING | IT_ARROWS) : (IT_DISABLED); - SR_EmblemHintMenu[1].status = (M_SecretUnlocked(SECRET_ITEMFINDER)) ? (IT_CVAR|IT_STRING) : (IT_SECRET); + SR_EmblemHintMenu[1].status = (M_SecretUnlocked(SECRET_ITEMFINDER, clientGamedata)) ? (IT_CVAR|IT_STRING) : (IT_SECRET); hintpage = 1; SR_EmblemHintDef.prevMenu = currentMenu; M_SetupNextMenu(&SR_EmblemHintDef); @@ -7574,7 +7611,7 @@ static void M_DrawEmblemHints(void) if (totalemblems >= ((hintpage-1)*(NUMHINTS*2) + 1) && totalemblems < (hintpage*NUMHINTS*2)+1){ - if (emblem->collected) + if (clientGamedata->collected[i]) { collected = V_GREENMAP; V_DrawMappedPatch(x, y+4, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH), @@ -7644,6 +7681,26 @@ static void M_HandleEmblemHints(INT32 choice) } +static void M_PauseLevelSelect(INT32 choice) +{ + (void)choice; + + SP_PauseLevelSelectDef.prevMenu = currentMenu; + levellistmode = LLM_LEVELSELECT; + + // maplistoption is NOT specified, so that this + // transfers the level select list from the menu + // used to enter the game to the pause menu. + + if (!M_PrepareLevelPlatter(-1, true)) + { + M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); + return; + } + + M_SetupNextMenu(&SP_PauseLevelSelectDef); +} + /*static void M_DrawSkyRoom(void) { INT32 i, y = 0; @@ -8114,7 +8171,7 @@ static void M_SecretsMenu(INT32 choice) SR_MainMenu[i].status = IT_SECRET; - if (unlockables[ul].unlocked) + if (clientGamedata->unlocked[ul]) { switch (unlockables[ul].type) { @@ -8151,6 +8208,7 @@ INT32 ultimate_selectable = false; static void M_NewGame(void) { fromlevelselect = false; + maplistoption = 0; startmap = spstage_start; CV_SetValue(&cv_newgametype, GT_COOP); // Graue 09-08-2004 @@ -8162,6 +8220,7 @@ static void M_CustomWarp(INT32 choice) { INT32 ul = skyRoomMenuTranslations[choice-1]; + maplistoption = 0; startmap = (INT16)(unlockables[ul].variable); M_SetupChoosePlayer(0); @@ -8213,7 +8272,7 @@ static void M_SinglePlayerMenu(INT32 choice) levellistmode = LLM_RECORDATTACK; if (M_GametypeHasLevels(-1)) - SP_MainMenu[sprecordattack].status = (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET; + SP_MainMenu[sprecordattack].status = (M_SecretUnlocked(SECRET_RECORDATTACK, clientGamedata)) ? IT_CALL|IT_STRING : IT_SECRET; else // If Record Attack is nonexistent in the current add-on... { SP_MainMenu[sprecordattack].status = IT_NOTHING|IT_DISABLED; // ...hide and disable the Record Attack option... @@ -8223,7 +8282,7 @@ static void M_SinglePlayerMenu(INT32 choice) levellistmode = LLM_NIGHTSATTACK; if (M_GametypeHasLevels(-1)) - SP_MainMenu[spnightsmode].status = (M_SecretUnlocked(SECRET_NIGHTSMODE)) ? IT_CALL|IT_STRING : IT_SECRET; + SP_MainMenu[spnightsmode].status = (M_SecretUnlocked(SECRET_NIGHTSMODE, clientGamedata)) ? IT_CALL|IT_STRING : IT_SECRET; else // If NiGHTS Mode is nonexistent in the current add-on... { SP_MainMenu[spnightsmode].status = IT_NOTHING|IT_DISABLED; // ...hide and disable the NiGHTS Mode option... @@ -8246,7 +8305,7 @@ static void M_SinglePlayerMenu(INT32 choice) SP_MainMenu[spnightsmode] .alphaKey += 8; } else // Otherwise, if Marathon Run is allowed and Record Attack is unlocked, unlock Marathon Run! - SP_MainMenu[spmarathon].status = (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED : IT_SECRET; + SP_MainMenu[spmarathon].status = (M_SecretUnlocked(SECRET_RECORDATTACK, clientGamedata)) ? IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED : IT_SECRET; if (tutorialmap) // If there's a tutorial available in the current add-on... @@ -8354,6 +8413,7 @@ static void M_StartTutorial(INT32 choice) M_ClearMenus(true); gamecomplete = 0; cursaveslot = 0; + maplistoption = 0; G_DeferedInitNew(false, G_BuildMapName(tutorialmap), 0, false, false); } @@ -8461,7 +8521,7 @@ static void M_DrawLoadGameData(void) if (charskin->prefoppositecolor) { col = charskin->prefoppositecolor; - col = skincolors[col].ramp[skincolors[skincolors[col].invcolor].invshade]; + col = skincolors[col].ramp[skincolors[charskin->prefcolor].invshade]; } else { @@ -8702,9 +8762,9 @@ static void M_DrawLoad(void) M_DrawLoadGameData(); - if (modifiedgame && !savemoddata) + if (usedCheats) { - V_DrawCenteredThinString(BASEVIDWIDTH/2, 184, 0, "\x85WARNING: \x80The game is modified."); + V_DrawCenteredThinString(BASEVIDWIDTH/2, 184, 0, "\x85WARNING:\x80 Cheats have been activated."); V_DrawCenteredThinString(BASEVIDWIDTH/2, 192, 0, "Progress will not be saved."); } } @@ -8716,6 +8776,10 @@ static void M_LoadSelect(INT32 choice) { (void)choice; + // Reset here, if we want a level select + // M_LoadGameLevelSelect will set it for us. + maplistoption = 0; + if (saveSlotSelected == NOSAVESLOT) //last slot is play without saving { M_NewGame(); @@ -9008,17 +9072,17 @@ static void M_HandleLoadSave(INT32 choice) break; case KEY_ENTER: - if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !savemoddata && !modifiedgame) + if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !savemoddata) { loadgamescroll = 0; S_StartSound(NULL, sfx_skid); M_StartMessage("Are you sure you want to play\n\x85ultimate mode\x80? It isn't remotely fair,\nand you don't even get an emblem for it.\n\n(Press 'Y' to confirm)\n",M_SaveGameUltimateResponse,MM_YESNO); } - else if (saveSlotSelected != NOSAVESLOT && savegameinfo[saveSlotSelected-1].lives == -42 && !(!modifiedgame || savemoddata)) + else if (saveSlotSelected != NOSAVESLOT && savegameinfo[saveSlotSelected-1].lives == -42 && usedCheats) { loadgamescroll = 0; S_StartSound(NULL, sfx_skid); - M_StartMessage(M_GetText("This cannot be done in a modified game.\n\n(Press a key)\n"), NULL, MM_NOTHING); + M_StartMessage(M_GetText("This cannot be done in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING); } else if (saveSlotSelected == NOSAVESLOT || savegameinfo[saveSlotSelected-1].lives != -666) // don't allow loading of "bad saves" { @@ -9623,7 +9687,7 @@ static void M_Statistics(INT32 choice) if (!(mapheaderinfo[i]->typeoflevel & TOL_SP) || (mapheaderinfo[i]->menuflags & LF2_HIDEINSTATS)) continue; - if (!(mapvisited[i] & MV_MAX)) + if (!(clientGamedata->mapvisited[i] & MV_MAX)) continue; statsMapList[j++] = i; @@ -9640,6 +9704,7 @@ static void M_Statistics(INT32 choice) static void M_DrawStatsMaps(int location) { + gamedata_t *data = clientGamedata; INT32 y = 80, i = -1; INT16 mnum; extraemblem_t *exemblem; @@ -9707,14 +9772,14 @@ static void M_DrawStatsMaps(int location) { exemblem = &extraemblems[i]; - if (exemblem->collected) + if (data->extraCollected[i]) V_DrawSmallMappedPatch(292, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_CACHE)); else V_DrawSmallScaledPatch(292, y, 0, W_CachePatchName("NEEDIT", PU_PATCH)); V_DrawString(20, y, V_YELLOWMAP|V_ALLOWLOWERCASE, - (!exemblem->collected && exemblem->showconditionset && !M_Achieved(exemblem->showconditionset)) + (!data->extraCollected[i] && exemblem->showconditionset && !M_Achieved(exemblem->showconditionset, data)) ? M_CreateSecretMenuOption(exemblem->description) : exemblem->description); } @@ -9731,6 +9796,7 @@ bottomarrow: static void M_DrawLevelStats(void) { + gamedata_t *data = clientGamedata; char beststr[40]; tic_t besttime = 0; @@ -9745,9 +9811,9 @@ static void M_DrawLevelStats(void) V_DrawString(20, 24, V_YELLOWMAP, "Total Play Time:"); V_DrawCenteredString(BASEVIDWIDTH/2, 32, 0, va("%i hours, %i minutes, %i seconds", - G_TicsToHours(totalplaytime), - G_TicsToMinutes(totalplaytime, false), - G_TicsToSeconds(totalplaytime))); + G_TicsToHours(data->totalplaytime), + G_TicsToMinutes(data->totalplaytime, false), + G_TicsToSeconds(data->totalplaytime))); for (i = 0; i < NUMMAPS; i++) { @@ -9756,25 +9822,25 @@ static void M_DrawLevelStats(void) if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) continue; - if (!mainrecords[i]) + if (!data->mainrecords[i]) { mapsunfinished++; bestunfinished[0] = bestunfinished[1] = bestunfinished[2] = true; continue; } - if (mainrecords[i]->score > 0) - bestscore += mainrecords[i]->score; + if (data->mainrecords[i]->score > 0) + bestscore += data->mainrecords[i]->score; else mapunfinished = bestunfinished[0] = true; - if (mainrecords[i]->time > 0) - besttime += mainrecords[i]->time; + if (data->mainrecords[i]->time > 0) + besttime += data->mainrecords[i]->time; else mapunfinished = bestunfinished[1] = true; - if (mainrecords[i]->rings > 0) - bestrings += mainrecords[i]->rings; + if (data->mainrecords[i]->rings > 0) + bestrings += data->mainrecords[i]->rings; else mapunfinished = bestunfinished[2] = true; @@ -9789,7 +9855,7 @@ static void M_DrawLevelStats(void) else V_DrawString(20, 56, V_GREENMAP, "(complete)"); - V_DrawString(36, 64, 0, va("x %d/%d", M_CountEmblems(), numemblems+numextraemblems)); + V_DrawString(36, 64, 0, va("x %d/%d", M_CountEmblems(data), numemblems+numextraemblems)); V_DrawSmallScaledPatch(20, 64, 0, W_CachePatchName("EMBLICON", PU_PATCH)); sprintf(beststr, "%u", bestscore); @@ -9856,6 +9922,7 @@ static void M_HandleLevelStats(INT32 choice) // Drawing function for Time Attack void M_DrawTimeAttackMenu(void) { + gamedata_t *data = clientGamedata; INT32 i, x, y, empatx, empaty, cursory = 0; UINT16 dispstatus; patch_t *PictureOfUrFace; // my WHAT @@ -9872,7 +9939,7 @@ void M_DrawTimeAttackMenu(void) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) { - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + F_SkyScroll(curbgname); // Draw and animate foreground if (!strncmp("RECATKBG", curbgname, 8)) M_DrawRecordAttackForeground(); @@ -10014,7 +10081,7 @@ void M_DrawTimeAttackMenu(void) empatx = empatch->leftoffset / 2; empaty = empatch->topoffset / 2; - if (em->collected) + if (data->collected[em - emblemlocations]) V_DrawSmallMappedPatch(104+76+empatx, yHeight+lsheadingheight/2+empaty, 0, empatch, R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else @@ -10027,34 +10094,34 @@ void M_DrawTimeAttackMenu(void) // Draw in-level emblems. M_DrawMapEmblems(cv_nextmap.value, 288, 28, true); - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score) + if (!data->mainrecords[cv_nextmap.value-1] || !data->mainrecords[cv_nextmap.value-1]->score) sprintf(beststr, "(none)"); else - sprintf(beststr, "%u", mainrecords[cv_nextmap.value-1]->score); + sprintf(beststr, "%u", data->mainrecords[cv_nextmap.value-1]->score); V_DrawString(104-72, 33+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); V_DrawRightAlignedString(104+64, 33+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); V_DrawRightAlignedString(104+72, 43+lsheadingheight/2, V_ALLOWLOWERCASE, reqscore); - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) + if (!data->mainrecords[cv_nextmap.value-1] || !data->mainrecords[cv_nextmap.value-1]->time) sprintf(beststr, "(none)"); else - sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(mainrecords[cv_nextmap.value-1]->time, true), - G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time), - G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time)); + sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(data->mainrecords[cv_nextmap.value-1]->time, true), + G_TicsToSeconds(data->mainrecords[cv_nextmap.value-1]->time), + G_TicsToCentiseconds(data->mainrecords[cv_nextmap.value-1]->time)); V_DrawString(104-72, 53+lsheadingheight/2, V_YELLOWMAP, "TIME:"); V_DrawRightAlignedString(104+64, 53+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); V_DrawRightAlignedString(104+72, 63+lsheadingheight/2, V_ALLOWLOWERCASE, reqtime); - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->rings) + if (!data->mainrecords[cv_nextmap.value-1] || !data->mainrecords[cv_nextmap.value-1]->rings) sprintf(beststr, "(none)"); else - sprintf(beststr, "%hu", mainrecords[cv_nextmap.value-1]->rings); + sprintf(beststr, "%hu", data->mainrecords[cv_nextmap.value-1]->rings); V_DrawString(104-72, 73+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); - V_DrawRightAlignedString(104+64, 73+lsheadingheight/2, V_ALLOWLOWERCASE|((mapvisited[cv_nextmap.value-1] & MV_PERFECTRA) ? V_YELLOWMAP : 0), beststr); + V_DrawRightAlignedString(104+64, 73+lsheadingheight/2, V_ALLOWLOWERCASE|((data->mapvisited[cv_nextmap.value-1] & MV_PERFECTRA) ? V_YELLOWMAP : 0), beststr); V_DrawRightAlignedString(104+72, 83+lsheadingheight/2, V_ALLOWLOWERCASE, reqrings); } @@ -10148,6 +10215,7 @@ static void M_TimeAttack(INT32 choice) // Drawing function for Nights Attack void M_DrawNightsAttackMenu(void) { + gamedata_t *data = clientGamedata; INT32 i, x, y, cursory = 0; UINT16 dispstatus; @@ -10214,10 +10282,10 @@ void M_DrawNightsAttackMenu(void) lumpnum_t lumpnum; char beststr[40]; - //UINT8 bestoverall = G_GetBestNightsGrade(cv_nextmap.value, 0); - UINT8 bestgrade = G_GetBestNightsGrade(cv_nextmap.value, cv_dummymares.value); - UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value); - tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value); + //UINT8 bestoverall = G_GetBestNightsGrade(cv_nextmap.value, 0, data); + UINT8 bestgrade = G_GetBestNightsGrade(cv_nextmap.value, cv_dummymares.value, data); + UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value, data); + tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value, data); M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true, false); @@ -10298,7 +10366,7 @@ void M_DrawNightsAttackMenu(void) goto skipThisOne; } - if (em->collected) + if (data->collected[em - emblemlocations]) V_DrawSmallMappedPatch(xpos, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else @@ -10652,6 +10720,7 @@ static void M_Marathon(INT32 choice) } fromlevelselect = false; + maplistoption = 0; startmap = spmarathon_start; CV_SetValue(&cv_newgametype, GT_COOP); // Graue 09-08-2004 @@ -11668,7 +11737,67 @@ static void M_StartServerMenu(INT32 choice) // CONNECT VIA IP // ============== -static char setupm_ip[28]; +#define CONNIP_LEN 128 +static char setupm_ip[CONNIP_LEN]; +#define DOTS "... " + +static void M_DrawConnectIP(void) +{ + INT32 x = currentMenu->x; + INT32 y = currentMenu->y + 22; + + const INT32 boxwidth = /*16*8 + 6*/ (BASEVIDWIDTH - 2*(x+5)); + const INT32 maxstrwidth = boxwidth - 5; + char *drawnstr = malloc(sizeof(setupm_ip)); + char *drawnstr_orig = drawnstr; + boolean drawthin, shorten = false; + + V_DrawFill(x+5, y+4+5, boxwidth, 8+6, 159); + + strcpy(drawnstr, setupm_ip); + drawthin = V_StringWidth(drawnstr, V_ALLOWLOWERCASE) + V_StringWidth("_", V_ALLOWLOWERCASE) > maxstrwidth; + + // draw name string + if (drawthin) + { + INT32 dotswidth = V_ThinStringWidth(DOTS, V_ALLOWLOWERCASE); + //UINT32 color = 0; + while (V_ThinStringWidth(drawnstr, V_ALLOWLOWERCASE) + V_ThinStringWidth("_", V_ALLOWLOWERCASE) >= maxstrwidth) + { + shorten = true; + drawnstr++; + } + + if (shorten) + { + INT32 initiallen = V_ThinStringWidth(drawnstr, V_ALLOWLOWERCASE); + INT32 cutofflen = 0; + while ((cutofflen = initiallen - V_ThinStringWidth(drawnstr, V_ALLOWLOWERCASE)) < dotswidth) + drawnstr++; + + V_DrawThinString(x+8,y+13, V_ALLOWLOWERCASE|V_GRAYMAP, DOTS); + x += V_ThinStringWidth(DOTS, V_ALLOWLOWERCASE); + } + + V_DrawThinString(x+8,y+13, V_ALLOWLOWERCASE, drawnstr); + } + else + { + V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, drawnstr); + } + + // draw text cursor for name + if (itemOn == 2 //0 + && skullAnimCounter < 4) //blink cursor + { + if (drawthin) + V_DrawCharacter(x+8+V_ThinStringWidth(drawnstr, V_ALLOWLOWERCASE),y+12,'_',false); + else + V_DrawCharacter(x+8+V_StringWidth(drawnstr, V_ALLOWLOWERCASE),y+12,'_',false); + } + + free(drawnstr_orig); +} // Draw the funky Connect IP menu. Tails 11-19-2002 // So much work for such a little thing! @@ -11689,19 +11818,11 @@ static void M_DrawMPMainMenu(void) V_DrawRightAlignedString(BASEVIDWIDTH-x, y+116, ((itemOn == 8) ? V_YELLOWMAP : 0), "(splitscreen)"); - y += 22; - - V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 159); - - // draw name string - V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip); - - // draw text cursor for name - if (itemOn == 2 //0 - && skullAnimCounter < 4) //blink cursor - V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_ALLOWLOWERCASE),y+12,'_',false); + M_DrawConnectIP(); } +#undef DOTS + // Tails 11-19-2002 static void M_ConnectIP(INT32 choice) { @@ -11782,7 +11903,7 @@ static void M_HandleConnectIP(INT32 choice) const char *paste = I_ClipboardPaste(); if (paste != NULL) { - strncat(setupm_ip, paste, 28-1 - l); // Concat the ip field with clipboard + strncat(setupm_ip, paste, CONNIP_LEN-1 - l); // Concat the ip field with clipboard if (strlen(paste) != 0) // Don't play sound if nothing was pasted S_StartSound(NULL,sfx_menu1); // Tails } @@ -11816,7 +11937,7 @@ static void M_HandleConnectIP(INT32 choice) const char *paste = I_ClipboardPaste(); if (paste != NULL) { - strncat(setupm_ip, paste, 28-1 - l); // Concat the ip field with clipboard + strncat(setupm_ip, paste, CONNIP_LEN-1 - l); // Concat the ip field with clipboard if (strlen(paste) != 0) // Don't play sound if nothing was pasted S_StartSound(NULL,sfx_menu1); // Tails } @@ -11833,11 +11954,15 @@ static void M_HandleConnectIP(INT32 choice) } } - if (l >= 28-1) + if (l >= CONNIP_LEN-1) break; // Rudimentary number and period enforcing - also allows letters so hostnames can be used instead - if ((choice >= '-' && choice <= ':') || (choice >= 'A' && choice <= 'Z') || (choice >= 'a' && choice <= 'z')) + // and square brackets for RFC 2732 IPv6 addresses + if ((choice >= '-' && choice <= ':') || + (choice == '[' || choice == ']') || + (choice >= 'A' && choice <= 'Z') || + (choice >= 'a' && choice <= 'z')) { S_StartSound(NULL,sfx_menu1); // Tails setupm_ip[l] = (char)choice; @@ -11874,6 +11999,8 @@ static void M_HandleConnectIP(INT32 choice) static fixed_t multi_tics; static UINT8 multi_frame; static UINT8 multi_spr2; +static boolean multi_paused; +static boolean multi_invcolor; // this is set before entering the MultiPlayer setup menu, // for either player 1 or 2 @@ -11886,6 +12013,7 @@ static consvar_t *setupm_cvdefaultskin; static consvar_t *setupm_cvdefaultcolor; static INT32 setupm_fakeskin; static menucolor_t *setupm_fakecolor; +static boolean colorgrid; static void M_DrawSetupMultiPlayerMenu(void) { @@ -11935,12 +12063,12 @@ static void M_DrawSetupMultiPlayerMenu(void) '\x1D' | V_YELLOWMAP, false); } - x = BASEVIDWIDTH/2; + x = colorgrid ? 92 : BASEVIDWIDTH/2; y += 11; // anim the player in the box multi_tics -= renderdeltatics; - while (multi_tics <= 0) + while (!multi_paused && multi_tics <= 0) { multi_frame++; multi_tics += 4*FRACUNIT; @@ -11949,7 +12077,8 @@ static void M_DrawSetupMultiPlayerMenu(void) #define charw 74 // draw box around character - V_DrawFill(x-(charw/2), y, charw, 84, 159); + V_DrawFill(x-(charw/2), y, charw, 84, + multi_invcolor ?skincolors[skincolors[setupm_fakecolor->color].invcolor].ramp[skincolors[setupm_fakecolor->color].invshade] : 159); sprdef = &skins[setupm_fakeskin].sprites[multi_spr2]; @@ -11992,61 +12121,121 @@ faildraw: #undef chary colordraw: - x = MP_PlayerSetupDef.x; - y += 75; - - M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), "Color", true, false); - if (itemOn == 2) - cursory = y; - - // draw color string - V_DrawRightAlignedString(BASEVIDWIDTH - x, y, - ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|(itemOn == 2 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, - skincolors[setupm_fakecolor->color].name); - - if (itemOn == 2 && (MP_PlayerSetupMenu[2].status & IT_TYPE) != IT_SPACE) - { - V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(skincolors[setupm_fakecolor->color].name, V_ALLOWLOWERCASE) - (skullAnimCounter/5), y, - '\x1C' | V_YELLOWMAP, false); - V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, - '\x1D' | V_YELLOWMAP, false); - } - - y += 11; #define indexwidth 8 + + if (colorgrid) // Draw color grid & skip the later options + { + UINT16 pos; + INT16 cx = 96, cy = 66; + INT16 i, j; + INT32 w = indexwidth; // Width of a singular color block + boolean stoprow = false; + menucolor_t *mc; // Last accessed color + + x = 132; + y = 66; + pos = min(max(0, 16*((M_GetColorIndex(setupm_fakecolor->color)-1)/16) - 64), 16*(M_GetColorIndex(menucolortail->color)/16-1) - 128); + mc = M_GetColorFromIndex(pos); + + // Draw grid + V_DrawFill(x-2, y-2, 132, 132, 159); + for (j = 0; j < 8; j++) + { + for (i = 0; i < 16; i++) + { + if (skincolors[mc->color].accessible && !stoprow) + { + M_DrawColorRamp(x + i*w, y + j*16, w, 1, skincolors[mc->color]); + if (mc->color == setupm_fakecolor->color) // store current color position + { + cx = x + i*w; + cy = y + j*16; + } + } + mc = mc->next; + while (!skincolors[mc->color].accessible && !stoprow) // Find accessible color after this one + { + mc = mc->next; + if (mc == menucolortail) stoprow = true; + } + } + } + + // Draw arrows, if needed + if (pos > 0) + V_DrawCharacter(264, y - (skullAnimCounter/5), '\x1A' | V_YELLOWMAP, false); + if (!stoprow) + V_DrawCharacter(264, y+120 + (skullAnimCounter/5), '\x1B' | V_YELLOWMAP, false); + + // Draw cursor & current skincolor + V_DrawFill(cx - 2, cy - 2, 12, 20, 0); + V_DrawFill(cx - 1, cy - 1, 11, 19, 31); + V_DrawFill( cx, cy, 9, 17, 0); + M_DrawColorRamp(cx, cy, w, 1, skincolors[setupm_fakecolor->color]); + + // Draw color string (with background) + V_DrawFill(55, 148, 74, 1, 73); + V_DrawFill(55, 149, 74, 1, 26); + M_DrawColorRamp(55, 150, 74, 1, skincolors[setupm_fakecolor->color]); + V_DrawRightAlignedString(x-2,166, + ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|(itemOn == 2 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, + skincolors[setupm_fakecolor->color].name); + + return; // Don't draw anything after this + } + else // Draw color strip & the rest of the menu options { const INT32 numcolors = (282-charw)/(2*indexwidth); // Number of colors per side INT32 w = indexwidth; // Width of a singular color block menucolor_t *mc = setupm_fakecolor->prev; // Last accessed color - UINT8 h; INT16 i; + x = MP_PlayerSetupDef.x; + y += 75; + + // Draw color header & string + M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), "Color...", true, false); + V_DrawRightAlignedString(BASEVIDWIDTH - x, y, + ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|(itemOn == 2 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, + skincolors[setupm_fakecolor->color].name); + + // Draw horizontal arrows + if (itemOn == 2) + { + cursory = y; + if ((MP_PlayerSetupMenu[2].status & IT_TYPE) != IT_SPACE) + { + V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(skincolors[setupm_fakecolor->color].name, V_ALLOWLOWERCASE) - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } + } + // Draw color in the middle x += numcolors*w; - for (h = 0; h < 16; h++) - V_DrawFill(x, y+h, charw, 1, skincolors[setupm_fakecolor->color].ramp[h]); + y += 11; + M_DrawColorRamp(x, y, charw, 1, skincolors[setupm_fakecolor->color]); - //Draw colors from middle to left - for (i=0; icolor].accessible) + while (!skincolors[mc->color].accessible) // Find accessible color before this one mc = mc->prev; - for (h = 0; h < 16; h++) - V_DrawFill(x, y+h, w, 1, skincolors[mc->color].ramp[h]); + M_DrawColorRamp(x, y, w, 1, skincolors[mc->color]); mc = mc->prev; } // Draw colors from middle to right mc = setupm_fakecolor->next; x += numcolors*w + charw; - for (i=0; icolor].accessible) + for (i = 0; i < numcolors; i++) + { + while (!skincolors[mc->color].accessible) // Find accessible color after this one mc = mc->next; - for (h = 0; h < 16; h++) - V_DrawFill(x, y+h, w, 1, skincolors[mc->color].ramp[h]); + M_DrawColorRamp(x, y, w, 1, skincolors[mc->color]); x += w; mc = mc->next; } @@ -12071,6 +12260,13 @@ colordraw: W_CachePatchName("M_CURSOR", PU_PATCH)); } +static void M_DrawColorRamp(INT32 x, INT32 y, INT32 w, INT32 h, skincolor_t color) +{ + UINT8 i; + for (i = 0; i < 16; i++) + V_DrawFill(x, y+(i*h), w, h, color.ramp[i]); +} + // Handle 1P/2P MP Setup static void M_HandleSetupMultiPlayer(INT32 choice) { @@ -12081,13 +12277,25 @@ static void M_HandleSetupMultiPlayer(INT32 choice) switch (choice) { case KEY_DOWNARROW: - M_NextOpt(); - S_StartSound(NULL,sfx_menu1); // Tails - break; - case KEY_UPARROW: - M_PrevOpt(); - S_StartSound(NULL,sfx_menu1); // Tails + { + UINT8 i; + if (itemOn == 2 && colorgrid) + { + for (i = 0; i < 16; i++) + { + setupm_fakecolor = (choice == KEY_UPARROW) ? setupm_fakecolor->prev : setupm_fakecolor->next; + while (!skincolors[setupm_fakecolor->color].accessible) // skip inaccessible colors + setupm_fakecolor = (choice == KEY_UPARROW) ? setupm_fakecolor->prev : setupm_fakecolor->next; + } + } + else if (choice == KEY_UPARROW) + M_PrevOpt(); + else + M_NextOpt(); + + S_StartSound(NULL,sfx_menu1); + } break; case KEY_LEFTARROW: @@ -12122,6 +12330,13 @@ static void M_HandleSetupMultiPlayer(INT32 choice) COM_BufAddText (va("%s %d\n",setupm_cvdefaultcolor->name,setupm_fakecolor->color)); break; } + else if (itemOn == 2) + { + if (!colorgrid) + S_StartSound(NULL,sfx_menu1); + colorgrid = !colorgrid; + break; + } /* FALLTHRU */ case KEY_RIGHTARROW: if (itemOn == 1) //player skin @@ -12144,8 +12359,28 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } break; + case KEY_PGUP: + case KEY_PGDN: + { + UINT8 i; + if (itemOn == 2) // player color + { + S_StartSound(NULL,sfx_menu1); + for (i = 0; i < (colorgrid ? 64 : 13); i++) // or (282-charw)/(2*indexwidth) + { + setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next; + while (!skincolors[setupm_fakecolor->color].accessible) // skip inaccessible colors + setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next; + } + } + } + break; + case KEY_ESCAPE: - exitmenu = true; + if (itemOn == 2 && colorgrid) + colorgrid = false; + else + exitmenu = true; break; case KEY_BACKSPACE: @@ -12176,6 +12411,14 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } break; + case KEY_PAUSE: + multi_paused = !multi_paused; + break; + + case KEY_INS: + multi_invcolor = !multi_invcolor; + break; + default: if (itemOn != 0 || choice < 32 || choice > 127) break; @@ -12215,6 +12458,7 @@ static void M_SetupMultiPlayer(INT32 choice) multi_frame = 0; multi_tics = 4*FRACUNIT; + strcpy(setupm_name, cv_playername.string); // set for player 1 @@ -12259,6 +12503,7 @@ static void M_SetupMultiPlayer2(INT32 choice) multi_frame = 0; multi_tics = 4*FRACUNIT; + strcpy (setupm_name, cv_playername2.string); // set for splitscreen secondary player @@ -12455,6 +12700,42 @@ UINT16 M_GetColorAfter(UINT16 color) { } } +UINT16 M_GetColorIndex(UINT16 color) { + menucolor_t *look; + UINT16 i = 0; + + if (color >= numskincolors) { + CONS_Printf("M_GetColorIndex: color %d does not exist.\n",color); + return 0; + } + + for (look=menucolorhead;;look=look->next) { + if (look->color == color) + return i; + if (look==menucolortail) + return 0; + i++; + } +} + +menucolor_t* M_GetColorFromIndex(UINT16 index) { + menucolor_t *look = menucolorhead; + UINT16 i = 0; + + if (index >= numskincolors) { + CONS_Printf("M_GetColorIndex: index %d does not exist.\n",index); + return 0; + } + + for (i = 0; i <= index; i++) { + if (look==menucolortail) + return menucolorhead; + look=look->next; + } + + return look; +} + void M_InitPlayerSetupColors(void) { UINT8 i; numskincolors = SKINCOLOR_FIRSTFREESLOT; @@ -12495,12 +12776,12 @@ static void M_EraseDataResponse(INT32 ch) // Delete the data if (erasecontext != 1) - G_ClearRecords(); + G_ClearRecords(clientGamedata); if (erasecontext != 0) - M_ClearSecrets(); + M_ClearSecrets(clientGamedata); if (erasecontext == 2) { - totalplaytime = 0; + clientGamedata->totalplaytime = 0; F_StartIntro(); } BwehHehHe(); @@ -12750,13 +13031,14 @@ static void M_Setup1PControlsMenu(INT32 choice) OP_ChangeControlsMenu[18+5].status = IT_CALL|IT_STRING2; OP_ChangeControlsMenu[18+6].status = IT_CALL|IT_STRING2; //OP_ChangeControlsMenu[18+7].status = IT_CALL|IT_STRING2; - OP_ChangeControlsMenu[18+8].status = IT_CALL|IT_STRING2; + //OP_ChangeControlsMenu[18+8].status = IT_CALL|IT_STRING2; + OP_ChangeControlsMenu[18+9].status = IT_CALL|IT_STRING2; // ... - OP_ChangeControlsMenu[27+0].status = IT_HEADER; - OP_ChangeControlsMenu[27+1].status = IT_SPACE; + OP_ChangeControlsMenu[28+0].status = IT_HEADER; + OP_ChangeControlsMenu[28+1].status = IT_SPACE; // ... - OP_ChangeControlsMenu[27+2].status = IT_CALL|IT_STRING2; - OP_ChangeControlsMenu[27+3].status = IT_CALL|IT_STRING2; + OP_ChangeControlsMenu[28+2].status = IT_CALL|IT_STRING2; + OP_ChangeControlsMenu[28+3].status = IT_CALL|IT_STRING2; OP_ChangeControlsDef.prevMenu = &OP_P1ControlsDef; OP_ChangeControlsDef.menuid &= ~(((1 << MENUBITS) - 1) << MENUBITS); // remove second level @@ -12781,13 +13063,14 @@ static void M_Setup2PControlsMenu(INT32 choice) OP_ChangeControlsMenu[18+5].status = IT_GRAYEDOUT2; OP_ChangeControlsMenu[18+6].status = IT_GRAYEDOUT2; //OP_ChangeControlsMenu[18+7].status = IT_GRAYEDOUT2; - OP_ChangeControlsMenu[18+8].status = IT_GRAYEDOUT2; + //OP_ChangeControlsMenu[18+8].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[18+9].status = IT_GRAYEDOUT2; // ... - OP_ChangeControlsMenu[27+0].status = IT_GRAYEDOUT2; - OP_ChangeControlsMenu[27+1].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[28+0].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[28+1].status = IT_GRAYEDOUT2; // ... - OP_ChangeControlsMenu[27+2].status = IT_GRAYEDOUT2; - OP_ChangeControlsMenu[27+3].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[28+2].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[28+3].status = IT_GRAYEDOUT2; OP_ChangeControlsDef.prevMenu = &OP_P2ControlsDef; OP_ChangeControlsDef.menuid &= ~(((1 << MENUBITS) - 1) << MENUBITS); // remove second level diff --git a/src/m_menu.h b/src/m_menu.h index a7072b0c1..c925c7f49 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -482,6 +482,8 @@ void M_MoveColorBefore(UINT16 color, UINT16 targ); void M_MoveColorAfter(UINT16 color, UINT16 targ); UINT16 M_GetColorBefore(UINT16 color); UINT16 M_GetColorAfter(UINT16 color); +UINT16 M_GetColorIndex(UINT16 color); +menucolor_t* M_GetColorFromIndex(UINT16 index); void M_InitPlayerSetupColors(void); void M_FreePlayerSetupColors(void); diff --git a/src/m_misc.c b/src/m_misc.c index d98c949cf..c24896600 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -274,8 +274,8 @@ size_t FIL_ReadFileTag(char const *name, UINT8 **buffer, INT32 tag) size_t count, length; UINT8 *buf; - if (FIL_ReadFileOK(name)) - handle = fopen(name, "rb"); + //if (FIL_ReadFileOK(name)) + handle = fopenfile(name, "rb"); if (!handle) return 0; @@ -468,6 +468,7 @@ void Command_SaveConfig_f(void) CONS_Printf(M_GetText("saveconfig [-silent] : save config to a file\n")); return; } + strcpy(tmpstr, COM_Argv(1)); FIL_ForceExtension(tmpstr, ".cfg"); diff --git a/src/m_misc.h b/src/m_misc.h index 2959ba44e..8cad7ba9a 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_perfstats.c b/src/m_perfstats.c index 9f65a7616..17e026b3e 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by Sonic Team Junior. +// Copyright (C) 2020-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_perfstats.h b/src/m_perfstats.h index f6a7c1f74..db250be2a 100644 --- a/src/m_perfstats.h +++ b/src/m_perfstats.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by Sonic Team Junior. +// Copyright (C) 2020-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_queue.c b/src/m_queue.c index 2cc3f7cb8..1c10a6692 100644 --- a/src/m_queue.c +++ b/src/m_queue.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2003 by James Haley -// Copyright (C) 2003-2022 by Sonic Team Junior. +// Copyright (C) 2003-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_queue.h b/src/m_queue.h index 071f9d8fa..b1ad22bf5 100644 --- a/src/m_queue.h +++ b/src/m_queue.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2003 by James Haley -// Copyright (C) 2003-2022 by Sonic Team Junior. +// Copyright (C) 2003-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_random.c b/src/m_random.c index 112795500..8b5138b9c 100644 --- a/src/m_random.c +++ b/src/m_random.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -14,12 +14,11 @@ #include "doomdef.h" #include "doomtype.h" -#include "doomstat.h" // totalplaytime #include "m_random.h" #include "m_fixed.h" - +#include "m_cond.h" // totalplaytime // --------------------------- // RNG functions (not synched) @@ -252,5 +251,5 @@ void P_SetRandSeedD(const char *rfile, INT32 rline, UINT32 seed) */ UINT32 M_RandomizedSeed(void) { - return ((totalplaytime & 0xFFFF) << 16)|M_RandomFixed(); + return ((serverGamedata->totalplaytime & 0xFFFF) << 16) | M_RandomFixed(); } diff --git a/src/m_random.h b/src/m_random.h index aa5ffb0bb..824287e27 100644 --- a/src/m_random.h +++ b/src/m_random.h @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_swap.h b/src/m_swap.h index df5f3e907..b63089bcb 100644 --- a/src/m_swap.h +++ b/src/m_swap.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/mserv.c b/src/mserv.c index bff562c95..62cda96e4 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. -// Copyright (C) 2020-2022 by James R. +// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 2020-2023 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -62,7 +62,7 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = { }; consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://mb.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange); -consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, NULL, Update_parameters); +consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters); consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters); @@ -97,8 +97,8 @@ void AddMServCommands(void) CV_RegisterVar(&cv_masterserver_token); CV_RegisterVar(&cv_servername); #ifdef MASTERSERVER - COM_AddCommand("listserv", Command_Listserv_f); - COM_AddCommand("masterserver_update", Update_parameters); // allows people to updates manually in case you were delisted by accident + COM_AddCommand("listserv", Command_Listserv_f, 0); + COM_AddCommand("masterserver_update", Update_parameters, COM_LUA); // allows people to updates manually in case you were delisted by accident #endif #endif } diff --git a/src/mserv.h b/src/mserv.h index 23b26fbc5..07253da85 100644 --- a/src/mserv.h +++ b/src/mserv.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. -// Copyright (C) 2020-2022 by James R. +// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 2020-2023 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -33,7 +33,7 @@ typedef union typedef struct { msg_header_t header; - char ip[16]; + char ip[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; char port[8]; char name[32]; INT32 room; diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 66f2dd58e..98e931362 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_enemy.c b/src/p_enemy.c index 26465d10e..fe062cffc 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1405,6 +1405,9 @@ void A_StatueBurst(mobj_t *actor) if (LUA_CallAction(A_STATUEBURST, actor)) return; + // make statue intangible upon spawning so you can't stand above the created object for 40 tics + actor->flags &= ~MF_SOLID; + if (!locvar1 || !(new = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar1))) return; @@ -1568,6 +1571,8 @@ void A_PointyThink(mobj_t *actor) // Okay, we found the closest player. Let's move based on his movement. P_SetTarget(&actor->target, player->mo); A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y) < P_AproxDistance(player->mo->x + player->mo->momx - actor->x, player->mo->y + player->mo->momy - actor->y)) sign = -1; // Player is moving away @@ -1586,6 +1591,10 @@ void A_PointyThink(mobj_t *actor) if (!actor->tracer) // For some reason we do not have spike balls... return; + // Catch case where actor lastlook is -1 (which segfaults the following blocks) + if (actor->lastlook < 0) + return; + // Position spike balls relative to the value of 'lastlook'. ball = actor->tracer; @@ -1683,6 +1692,8 @@ void A_HoodFire(mobj_t *actor) } A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (!(arrow = P_SpawnMissile(actor, actor->target, (mobjtype_t)locvar1))) return; @@ -2224,7 +2235,7 @@ void A_CrushclawLaunch(mobj_t *actor) } } - if (!actor->target) + if (P_MobjWasRemoved(actor->target)) return; { @@ -2263,6 +2274,8 @@ void A_VultureVtol(mobj_t *actor) actor->flags |= MF_FLOAT; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; S_StopSound(actor); @@ -2361,6 +2374,9 @@ void A_VultureHover(mobj_t *actor) P_VultureHoverParticle(actor); A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + targetz = actor->target->z + actor->target->height / 2; for (i = -1; i <= 1; i++) { @@ -2668,7 +2684,7 @@ void A_LobShot(mobj_t *actor) fixed_t z; fixed_t dist; fixed_t vertical, horizontal; - fixed_t airtime = var2 & 65535; + fixed_t airtime = max(1, var2 & 65535); if (LUA_CallAction(A_LOBSHOT, actor)) return; @@ -2677,6 +2693,8 @@ void A_LobShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (actor->eflags & MFE_VERTICALFLIP) { @@ -2772,6 +2790,8 @@ void A_FireShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (actor->eflags & MFE_VERTICALFLIP) z = actor->z + actor->height - FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); @@ -2810,6 +2830,8 @@ void A_SuperFireShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (actor->eflags & MFE_VERTICALFLIP) z = actor->z + actor->height - FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); @@ -2857,6 +2879,8 @@ void A_BossFireShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; switch (locvar2) { @@ -2944,6 +2968,8 @@ void A_Boss7FireMissiles(mobj_t *actor) } A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; S_StartSound(NULL, locvar2); @@ -3328,6 +3354,8 @@ void A_SkullAttack(mobj_t *actor) if (actor->info->activesound) S_StartSound(actor, actor->info->activesound); A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); @@ -3439,6 +3467,9 @@ void A_BossZoom(mobj_t *actor) if (actor->info->attacksound) S_StartAttackSound(actor, actor->info->attacksound); A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + an = actor->angle >> ANGLETOFINESHIFT; actor->momx = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINECOSINE(an)); actor->momy = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINESINE(an)); @@ -4856,12 +4887,12 @@ void A_FishJump(mobj_t *actor) else { if (actor->spawnpoint && actor->spawnpoint->args[0]) - jumpval = actor->spawnpoint->args[0]; + jumpval = actor->spawnpoint->args[0] << (FRACBITS - 2); else - jumpval = 44; + jumpval = 44 << (FRACBITS - 2); } - actor->momz = FixedMul(jumpval << (FRACBITS - 2), actor->scale); + actor->momz = FixedMul(jumpval, actor->scale); P_SetMobjStateNF(actor, actor->info->seestate); } @@ -5290,7 +5321,7 @@ void A_SignPlayer(mobj_t *actor) actor->tracer->color = signcolor; if (signcolor && signcolor < numskincolors) - signframe += (15 - skincolors[skincolors[signcolor].invcolor].invshade); + signframe += (15 - skincolors[facecolor].invshade); actor->tracer->frame = signframe; } @@ -5536,6 +5567,9 @@ void A_JetgShoot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + P_SpawnMissile(actor, actor->target, (mobjtype_t)actor->info->raisestate); if (ultimatemode) @@ -5570,6 +5604,9 @@ void A_ShootBullet(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + P_SpawnMissile(actor, actor->target, (mobjtype_t)actor->info->raisestate); if (actor->info->attacksound) @@ -7428,6 +7465,8 @@ void A_Boss7Chase(mobj_t *actor) && (actor->target->player->powers[pw_carry] == CR_GENERIC)) { A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; P_SetMobjState(actor, S_BLACKEGG_SHOOT1); actor->movecount = TICRATE + P_RandomByte()/2; return; @@ -7445,6 +7484,8 @@ void A_Boss7Chase(mobj_t *actor) if (actor->z < 1056*FRACUNIT) { A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; P_SetMobjState(actor, actor->info->xdeathstate); actor->movecount = 7*TICRATE + P_RandomByte(); break; @@ -7453,6 +7494,8 @@ void A_Boss7Chase(mobj_t *actor) /* FALLTHRU */ case 1: // Chaingun Goop A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; P_SetMobjState(actor, S_BLACKEGG_SHOOT1); if (actor->health > actor->info->damage) @@ -7462,6 +7505,8 @@ void A_Boss7Chase(mobj_t *actor) break; case 2: // Homing Missile A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; P_SetMobjState(actor, actor->info->missilestate); S_StartSound(0, sfx_beflap); break; @@ -8179,6 +8224,9 @@ void A_Boss3Path(mobj_t *actor) P_SetTarget(&actor->target, actor->tracer->target); var1 = 0, var2 = 0; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + if (actor->tracer->state == &states[actor->tracer->info->missilestate]) P_SetMobjState(actor, actor->info->missilestate); return; @@ -9853,6 +9901,8 @@ void A_SplitShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; { const angle_t an = (actor->angle + ANGLE_90) >> ANGLETOFINESHIFT; const fixed_t fasin = FINESINE(an); @@ -9917,6 +9967,9 @@ void A_MultiShot(mobj_t *actor) if (actor->target) A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + if(loc1lw > 90) ad = FixedMul(90*FRACUNIT, actor->scale); else @@ -11061,6 +11114,8 @@ void A_VileTarget(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; // Determine object to spawn if (locvar1 <= 0 || locvar1 >= NUMMOBJTYPES) @@ -11148,6 +11203,8 @@ void A_VileAttack(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (locvar1 <= 0 || locvar1 >= NUMSFX) soundtoplay = sfx_brakrx; @@ -11466,6 +11523,8 @@ void A_BrakFireShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; x = actor->x + P_ReturnThrustX(actor, actor->angle, FixedMul(64*FRACUNIT, actor->scale)) @@ -11583,6 +11642,9 @@ void A_BrakLobShot(mobj_t *actor) // Okay, complicated math done. Let's fire our object already, sheesh. A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + if (locvar1 <= 0 || locvar1 >= NUMMOBJTYPES) typeOfShot = MT_CANNONBALL; else typeOfShot = (mobjtype_t)locvar1; @@ -12667,6 +12729,8 @@ void A_WhoCaresIfYourSonIsABee(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (actor->extravalue1) actor->extravalue1--; @@ -13457,6 +13521,9 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing) if (!player) return true; + if (player->spectator) + return true; + if (player->powers[pw_carry] != CR_DUSTDEVIL && (player->powers[pw_ignorelatch] & (1<<15))) return true; diff --git a/src/p_floor.c b/src/p_floor.c index a367a08d8..9c24f5851 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1660,7 +1660,7 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) // chained linedef executing ability // Only set it on one of the moving sectors (the smallest numbered) if (line->args[3]) - dofloor->tag = firstone ? (INT16)line->args[3] : -1; + dofloor->tag = firstone ? (INT16)line->args[3] : 0; // flat changing ability dofloor->texture = line->args[4] ? line->frontsector->floorpic : -1; diff --git a/src/p_inter.c b/src/p_inter.c index dd3e0f9c2..8c57beac8 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -164,6 +164,62 @@ boolean P_CanPickupItem(player_t *player, boolean weapon) return true; } +boolean P_CanPickupEmblem(player_t *player, INT32 emblemID) +{ + emblem_t *emblem = NULL; + + if (emblemID < 0 || emblemID >= numemblems) + { + // Invalid emblem ID, can't pickup. + return false; + } + + emblem = &emblemlocations[emblemID]; + + if (demoplayback) + { + // Never collect emblems in replays. + return false; + } + + if (player->bot && player->bot != BOT_MPAI) + { + // Your little lap-dog can't grab these for you. + return false; + } + + if (emblem->type == ET_SKIN) + { + INT32 skinnum = M_EmblemSkinNum(emblem); + + if (player->skin != skinnum) + { + // Incorrect skin to pick up this emblem. + return false; + } + } + + return true; +} + +boolean P_EmblemWasCollected(INT32 emblemID) +{ + if (emblemID < 0 || emblemID >= numemblems) + { + // Invalid emblem ID, can't pickup. + return true; + } + + if (shareEmblems && !serverGamedata->collected[emblemID]) + { + // It can be worth collecting again if we're sharing emblems + // and the server doesn't have it. + return false; + } + + return clientGamedata->collected[emblemID]; +} + // // P_DoNightsScore // @@ -199,42 +255,19 @@ void P_DoNightsScore(player_t *player) player->linktimer = nightslinktics; } - if (player->linkcount < 10) - { - if (player->bonustime) - { - P_AddPlayerScore(player, player->linkcount*20); - P_SetMobjState(dummymo, dummymo->info->xdeathstate+player->linkcount-1); - } - else - { - P_AddPlayerScore(player, player->linkcount*10); - P_SetMobjState(dummymo, dummymo->info->spawnstate+player->linkcount-1); - } - } - else - { - if (player->bonustime) - { - P_AddPlayerScore(player, 200); - P_SetMobjState(dummymo, dummymo->info->xdeathstate+9); - } - else - { - P_AddPlayerScore(player, 100); - P_SetMobjState(dummymo, dummymo->info->spawnstate+9); - } - } + // Award 10-100 score, doubled if bonus time is active + P_AddPlayerScore(player, min(player->linkcount,10)*(player->bonustime ? 20 : 10)); + P_SetMobjState(dummymo, (player->bonustime ? dummymo->info->xdeathstate : dummymo->info->spawnstate) + min(player->linkcount,10)-1); - // Hoops are the only things that should add to your drill meter - //player->drillmeter += TICRATE; + // Make objects slowly rise & scale up dummymo->momz = FRACUNIT; dummymo->fuse = 3*TICRATE; - - // What?! NO, don't use the camera! Scale up instead! - //P_InstaThrust(dummymo, R_PointToAngle2(dummymo->x, dummymo->y, camera.x, camera.y), 3*FRACUNIT); dummymo->scalespeed = FRACUNIT/25; dummymo->destscale = 2*FRACUNIT; + + // Add extra values used for color variety + dummymo->extravalue1 = player->linkcount-1; + dummymo->extravalue2 = ((player->linkcount-1 >= 300) ? (player->linkcount-1 >= 600) ? 2 : 1 : 0); } // @@ -465,23 +498,20 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->type == MT_PTERABYTE && special->target == player->mo && special->extravalue1 == 1) return; // Can't hurt a Pterabyte if it's trying to pick you up - if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1)) + if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1) && (!(player->powers[pw_strong] & STR_HEAVY))) { - 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 { - 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! - } + boolean underwater = toucher->eflags & MFE_UNDERWATER; + + if (underwater) + toucher->momz /= 2; + toucher->momz -= (toucher->momz/(underwater ? 8 : 4)); // Cap the height! } } if (player->pflags & PF_BOUNCING) @@ -500,8 +530,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) toucher->momx = 7*toucher->momx>>3; toucher->momy = 7*toucher->momy>>3; } - else if (player->dashmode >= DASHMODE_THRESHOLD && (player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) - && player->panim == PA_DASH) + else if ((player->powers[pw_strong] & STR_DASH) && player->panim == PA_DASH) P_DoPlayerPain(player, special, special); } P_DamageMobj(special, toucher, toucher, 1, 0); @@ -563,7 +592,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->momx = special->momy = special->momz = 0; P_GivePlayerSpheres(player, 1); - if (special->type == MT_BLUESPHERE) + if (special->type == MT_BLUESPHERE || special->type == MT_FLINGBLUESPHERE) { special->destscale = ((player->powers[pw_carry] == CR_NIGHTSMODE) ? 4 : 2)*special->scale; if (states[special->info->deathstate].tics > 0) @@ -738,13 +767,70 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Secret emblem thingy case MT_EMBLEM: { - if (demoplayback || (player->bot && player->bot != BOT_MPAI) || special->health <= 0 || special->health > MAXEMBLEMS) - return; - emblemlocations[special->health-1].collected = true; + const boolean toucherIsServer = ((player - players) == serverplayer); + const boolean consoleIsServer = (consoleplayer == serverplayer); + boolean prevCollected = false; - M_UpdateUnlockablesAndExtraEmblems(); - G_SaveGameData(); - break; + if ((special->flags2 & MF2_NIGHTSPULL) + && (toucher == special->tracer)) + { + // Since collecting may not remove the object, + // we need to manually stop it from chasing. + P_SetTarget(&special->tracer, NULL); + special->flags2 &= ~MF2_NIGHTSPULL; + special->movefactor = 0; + special->momx = special->momy = special->momz = 0; + } + + if (!P_CanPickupEmblem(player, special->health - 1)) + { + return; + } + + prevCollected = P_EmblemWasCollected(special->health - 1); + + if (toucherIsServer || shareEmblems) + { + serverGamedata->collected[special->health-1] = true; + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + } + + if (P_IsLocalPlayer(player) || (consoleIsServer && shareEmblems)) + { + clientGamedata->collected[special->health-1] = true; + M_UpdateUnlockablesAndExtraEmblems(clientGamedata); + G_SaveGameData(clientGamedata); + } + + if (netgame) + { + // This always spawns the object to prevent mobjnum issues, + // but makes the effect invisible to whoever it doesn't matter to. + mobj_t *spark = P_SpawnMobjFromMobj(special, 0, 0, 0, MT_SPARK); + + if (prevCollected == false && P_EmblemWasCollected(special->health - 1) == true) + { + // Play the sound if it was collected. + S_StartSound((shareEmblems ? NULL : special), special->info->deathsound); + } + else + { + // We didn't collect it, make it invisible to us. + spark->flags2 |= MF2_DONTDRAW; + } + + return; + } + else + { + if (prevCollected == false && P_EmblemWasCollected(special->health - 1) == true) + { + // Disappear when collecting for local games. + break; + } + + return; + } } // CTF Flags @@ -2583,7 +2669,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && numgameovers < maxgameovers) { numgameovers++; - if ((!modifiedgame || savemoddata) && cursaveslot > 0) + if (!usedCheats && cursaveslot > 0) G_SaveGameOver((UINT32)cursaveslot, (target->player->continues <= 0)); } } @@ -3213,7 +3299,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou return false; // Add pity. - if (!player->powers[pw_flashing] && !player->powers[pw_invulnerability] && !player->powers[pw_super] + if (!player->powers[pw_flashing] && !player->powers[pw_invulnerability] && !player->powers[pw_super] && !(player->powers[pw_strong] & STR_GUARD) && source->player->score > player->score) player->pity++; @@ -3546,6 +3632,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da UINT8 shouldForce = LUA_HookShouldDamage(target, inflictor, source, damage, damagetype); if (P_MobjWasRemoved(target)) return (shouldForce == 1); // mobj was removed + if (P_MobjWasRemoved(source)) + source = NULL; if (shouldForce == 1) force = true; else if (shouldForce == 2) @@ -3683,7 +3771,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } return false; } - else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) // ignore bouncing & such in invulnerability + else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super] || (player->powers[pw_strong] & STR_GUARD)) // ignore bouncing & such in invulnerability { if (force || (inflictor && inflictor->flags & MF_MISSILE && inflictor->flags2 & MF2_SUPERFIRE)) // Super Sonic is stunned! @@ -3763,6 +3851,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da else P_SetMobjState(target, target->info->painstate); + if (P_MobjWasRemoved(target)) + return false; + if (target->type == MT_HIVEELEMENTAL) target->extravalue1 += 3; diff --git a/src/p_lights.c b/src/p_lights.c index 4c783f884..4b6a3673b 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -353,8 +353,8 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean else { // Speed means increment per tic (literally speed). - ll->timer = FixedDiv((destvalue<fixedcurlevel, speed<>FRACBITS; - ll->fixedpertic = speed<timer = abs(FixedDiv((destvalue<fixedcurlevel, speed<>FRACBITS); + ll->fixedpertic = ll->destlevel < ll->sourcelevel ? -speed<info->painchance == 3) ; - else if (object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY) + else if (object->player->powers[pw_strong] & STR_SPRING) strong = 1; - else if (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2) - strong = 2; } if (spring->info->painchance == -1) // Pinball bumper mode. @@ -262,13 +260,15 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) } else { - INT32 pflags = object->player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // Not identical to below... + INT32 pflags = object->player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING|PF_CANCARRY); // Not identical to below... UINT8 secondjump = object->player->secondjump; + UINT16 tailsfly = object->player->powers[pw_tailsfly]; if (object->player->pflags & PF_GLIDING) P_SetPlayerMobjState(object, S_PLAY_FALL); P_ResetPlayer(object->player); object->player->pflags |= pflags; object->player->secondjump = secondjump; + object->player->powers[pw_tailsfly] = tailsfly; } } @@ -418,7 +418,20 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) P_SetPlayerMobjState(object, S_PLAY_ROLL); } else - pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // I still need these. + { + boolean wasSpindashing = object->player->dashspeed > 0 && (object->player->charability2 == CA2_SPINDASH); + + pflags = object->player->pflags & (PF_STARTJUMP | PF_JUMPED | PF_NOJUMPDAMAGE | PF_SPINNING | PF_THOKKED | PF_BOUNCING); // I still need these. + + if (wasSpindashing) // Ensure we're in the rolling state, and not spindash. + P_SetPlayerMobjState(object, S_PLAY_ROLL); + + if (object->player->charability == CA_GLIDEANDCLIMB && object->player->skidtime && (pflags & PF_JUMPED)) + { + object->player->skidtime = 0; // No skidding should be happening, either. + pflags &= ~PF_JUMPED; + } + } secondjump = object->player->secondjump; washoming = object->player->homing; P_ResetPlayer(object->player); @@ -480,7 +493,8 @@ springstate: if (strong) { - P_TwinSpinRejuvenate(object->player, (strong == 1 ? object->player->thokitem : object->player->revitem)); + if (object->player->charability == CA_TWINSPIN || object->player->charability2 == CA2_MELEE) + P_TwinSpinRejuvenate(object->player, (object->player->charability == CA_TWINSPIN ? object->player->thokitem : object->player->revitem)); S_StartSound(object, sfx_sprong); // strong spring. sprong. } } @@ -821,43 +835,25 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - // SF_DASHMODE users destroy spikes and monitors, CA_TWINSPIN users and CA2_MELEE users destroy spikes. - if ((tmthing->player) - && ((((tmthing->player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)) && (tmthing->player->dashmode >= DASHMODE_THRESHOLD) - && (thing->flags & (MF_MONITOR) - || (thing->type == MT_SPIKE - || thing->type == MT_WALLSPIKE))) - || ((((tmthing->player->charability == CA_TWINSPIN) && (tmthing->player->panim == PA_ABILITY)) - || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)) - && (thing->type == MT_SPIKE - || thing->type == MT_WALLSPIKE)))) + // STR_SPIKE users destroy spikes + if ((tmthing->player) && ((tmthing->player->powers[pw_strong] & STR_SPIKE) && (thing->type == MT_SPIKE || thing->type == MT_WALLSPIKE))) { - if ((thing->flags & (MF_MONITOR)) && (thing->health <= 0 || !(thing->flags & MF_SHOOTABLE))) - return true; - blockdist = thing->radius + tmthing->radius; - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) - return true; // didn't hit it - // see if it went over / under - if (tmthing->z > thing->z + thing->height) - return true; // overhead - if (tmthing->z + tmthing->height < thing->z) - return true; // underneath - if (thing->type == MT_SPIKE - || thing->type == MT_WALLSPIKE) - { - mobj_t *iter; - if (thing->flags & MF_SOLID) - S_StartSound(tmthing, thing->info->deathsound); - for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext) - if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale)) - P_KillMobj(iter, tmthing, tmthing, 0); - return true; - } - else - { - if (P_DamageMobj(thing, tmthing, tmthing, 1, 0)) - return true; - } + mobj_t *iter; + blockdist = thing->radius + tmthing->radius; + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + return true; // didn't hit it + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath + + if (thing->flags & MF_SOLID) + S_StartSound(tmthing, thing->info->deathsound); + for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext) + if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale)) + P_KillMobj(iter, tmthing, tmthing, 0); + return true; } // vectorise metal - done in a special case as at this point neither has the right flags for touching @@ -1712,25 +1708,22 @@ static boolean PIT_CheckThing(mobj_t *thing) // Going down? Then bounce back up. if (P_DamageMobj(thing, tmthing, tmthing, 1, 0) // break the monitor && (flipval*(*momz) < 0) // monitor is on the floor and you're going down, or on the ceiling and you're going up - && (elementalpierce != 1)) // you're not piercing through the monitor... + && (elementalpierce != 1) && (!(player->powers[pw_strong] & STR_HEAVY))) // you're not piercing through the monitor... { - 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. + if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY) + P_TwinSpinRejuvenate(player, player->thokitem); + if (elementalpierce == 2) // Reset bubblewrap, part 2 { - fixed_t setmomz = -*momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce + boolean underwater = tmthing->eflags & MFE_UNDERWATER; - if (elementalpierce == 2) // Reset bubblewrap, part 1 - P_DoBubbleBounce(player); - *momz = setmomz; // Therefore, you should be thrust in the opposite direction, vertically. - if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY) - P_TwinSpinRejuvenate(player, player->thokitem); - 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! - } + if (underwater) + *momz /= 2; + *momz -= (*momz/(underwater ? 8 : 4)); // Cap the height! } } if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough. @@ -2713,8 +2706,22 @@ increment_move fixed_t thingtop; floatok = false; - if (radius < MAXRADIUS/2) - radius = MAXRADIUS/2; + // This makes sure that there are no freezes from computing extremely small movements. + // Originally was MAXRADIUS/2, but that can cause some bad inconsistencies for small players. + radius = max(radius, thing->scale); + + // And we also have to prevent Big Large (tm) movements, as those can skip too far + // across slopes and cause us to fail step up checks on them when we otherwise shouldn't. + radius = min(radius, 16 * thing->scale); + + // (This whole "step" system is flawed; it was OK before, but the addition of slopes has + // exposed the problems with doing it like this. The right thing to do would be to use + // raycasting for physics to fix colliding in weird order, double-checking collisions, + // randomly colliding with slopes instead of going up them, etc. I don't feel like porting + // that from RR, as its both a huge sweeping change and still incomplete at the time of + // writing. Clamping radius to make our steps more precise will work just fine as long + // as you keep all of your crazy intentions to poke any of the other deep-rooted movement + // code to yourself. -- Sal 6/5/2023) do { if (thing->flags & MF_NOCLIP) { @@ -3506,11 +3513,9 @@ static void PTR_GlideClimbTraverse(line_t *li) if (fofline) whichside = 0; - if (!whichside) - { - slidemo->player->lastsidehit = checkline->sidenum[whichside]; - slidemo->player->lastlinehit = (INT16)(checkline - lines); - } + // Even if you attach to the second side of a linedef, we want to know the last hit. + slidemo->player->lastsidehit = checkline->sidenum[whichside]; + slidemo->player->lastlinehit = (INT16)(checkline - lines); P_Thrust(slidemo, slidemo->angle, FixedMul(5*FRACUNIT, slidemo->scale)); } @@ -4229,13 +4234,11 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama // the way it was and call P_CheckSector (? was P_ChangeSector - Graue) again // to undo the changes. // -static boolean crushchange; -static boolean nofit; // // PIT_ChangeSector // -static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) +static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush, boolean crunch) { mobj_t *killer = NULL; //If a thing is both pushable and vulnerable, it doesn't block the crusher because it gets killed. @@ -4259,11 +4262,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) if (thing->z + thing->height > thing->ceilingz && thing->z <= thing->ceilingz) { if (immunepushable && thing->z + thing->height > thing->subsector->sector->ceilingheight) - { - //Thing is a pushable and blocks the moving ceiling - nofit = true; - return false; - } + return false; //Thing is a pushable and blocks the moving ceiling //Check FOFs in the sector if (thing->subsector->sector->ffloors && (realcrush || immunepushable)) @@ -4275,47 +4274,54 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) for (rover = thing->subsector->sector->ffloors; rover; rover = rover->next) { - if (!(((rover->fofflags & FOF_BLOCKPLAYER) && thing->player) - || ((rover->fofflags & FOF_BLOCKOTHERS) && !thing->player)) || !(rover->fofflags & FOF_EXISTS)) + thinker_t *think; + + if (!(rover->fofflags & FOF_EXISTS)) + continue; + if (thing->player && !(rover->fofflags & FOF_BLOCKPLAYER)) + continue; + if (!thing->player && !(rover->fofflags & FOF_BLOCKOTHERS)) continue; topheight = *rover->topheight; bottomheight = *rover->bottomheight; - //topheight = P_GetFFloorTopZAt (rover, thing->x, thing->y); - //bottomheight = P_GetFFloorBottomZAt(rover, thing->x, thing->y); + + if (bottomheight > thing->ceilingz) + continue; delta1 = thing->z - (bottomheight + topheight)/2; delta2 = thingtop - (bottomheight + topheight)/2; - if (bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2)) + if (abs(delta1) < abs(delta2)) + continue; + + if (immunepushable) + return false; //FOF is blocked by pushable + + if (!realcrush) + continue; + + //If the thing was crushed by a crumbling FOF, reward the player who made it crumble! + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { - if (immunepushable) - { - //FOF is blocked by pushable - nofit = true; - return false; - } - else - { - //If the thing was crushed by a crumbling FOF, reward the player who made it crumble! - thinker_t *think; - crumble_t *crumbler; + crumble_t *crumbler; - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) - { - if (think->function.acp1 != (actionf_p1)T_StartCrumble) - continue; + if (think->function.acp1 != (actionf_p1)T_StartCrumble) + continue; - crumbler = (crumble_t *)think; + crumbler = (crumble_t *)think; - if (crumbler->player && crumbler->player->mo - && crumbler->player->mo != thing - && crumbler->actionsector == thing->subsector->sector - && crumbler->sector == rover->master->frontsector) - { - killer = crumbler->player->mo; - } - } - } + if (!crumbler->player) + continue; + if (!crumbler->player->mo) + continue; + if (crumbler->player->mo == thing) + continue; + if (crumbler->actionsector != thing->subsector->sector) + continue; + if (crumbler->sector != rover->master->frontsector) + continue; + + killer = crumbler->player->mo; } } } @@ -4331,24 +4337,139 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) } } - if (realcrush && crushchange) + if (realcrush && crunch) P_DamageMobj(thing, NULL, NULL, 1, 0); // keep checking (crush other things) return true; } +static boolean P_CheckSectorPolyObjects(sector_t *sector, boolean realcrush, boolean crunch) +{ + size_t i; + + // Sal: This stupid function chain is required to fix polyobjects not being able to crush. + // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead + validcount++; + + for (i = 0; i < sector->linecount; i++) + { + INT32 x, y; + polyobj_t *po = sector->lines[i]->polyobj; + + if (!po) + continue; + if (po->validcount == validcount) + continue; // skip if already checked + if (!(po->flags & POF_SOLID)) + continue; + if (po->lines[0]->backsector != sector) // Make sure you're currently checking the control sector + continue; + + po->validcount = validcount; + + for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) + { + for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) + { + mobj_t *mo; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + continue; + + mo = blocklinks[y * bmapwidth + x]; + + for (; mo; mo = mo->bnext) + { + // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect + + if (!P_MobjInsidePolyobj(po, mo)) + continue; + + if (!PIT_ChangeSector(mo, realcrush, crunch) && !realcrush) + return false; + } + } + } + } + + return true; +} + +static boolean P_CheckTouchingThinglist(sector_t *sector, boolean realcrush, boolean crunch) +{ + msecnode_t *n; + + for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) + n->visited = false; + + do + { + for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list + { + if (n->visited) + continue; + + n->visited = true; // mark thing as processed + + if (n->m_thing->flags & MF_NOBLOCKMAP) //jff 4/7/98 don't do these + continue; + + if (!PIT_ChangeSector(n->m_thing, realcrush, crunch) && !realcrush) // process it + return false; + + break; // exit and start over + } + } while (n); // repeat from scratch until all things left are marked valid + + return true; +} + +static boolean P_CheckSectorFFloors(sector_t *sector, boolean realcrush, boolean crunch) +{ + sector_t *sec; + size_t i; + + if (!sector->numattached) + return true; + + for (i = 0; i < sector->numattached; i++) + { + sec = §ors[sector->attached[i]]; + + sec->moved = true; + + P_RecalcPrecipInSector(sec); + + if (!sector->attachedsolid[i]) + continue; + + if (!P_CheckTouchingThinglist(sec, realcrush, crunch)) + return false; + } + + return true; +} + +static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush, boolean crunch) +{ + if (!P_CheckSectorPolyObjects(sector, realcrush, crunch)) + return false; + + if (!P_CheckSectorFFloors(sector, realcrush, crunch)) + return false; + + // Mark all things invalid + sector->moved = true; + + return P_CheckTouchingThinglist(sector, realcrush, crunch); +} + // // P_CheckSector // boolean P_CheckSector(sector_t *sector, boolean crunch) { - msecnode_t *n; - size_t i; - - nofit = false; - crushchange = crunch; - // killough 4/4/98: scan list front-to-back until empty or exhausted, // restarting from beginning after each thing is processed. Avoids // crashes, and is sure to examine all things in the sector, and only @@ -4357,218 +4478,14 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) // // killough 4/7/98: simplified to avoid using complicated counter - // First, let's see if anything will keep it from crushing. - - // Sal: This stupid function chain is required to fix polyobjects not being able to crush. - // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead - validcount++; - - for (i = 0; i < sector->linecount; i++) - { - if (sector->lines[i]->polyobj) - { - polyobj_t *po = sector->lines[i]->polyobj; - if (po->validcount == validcount) - continue; // skip if already checked - if (!(po->flags & POF_SOLID)) - continue; - if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector - { - INT32 x, y; - po->validcount = validcount; - - for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) - { - for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) - { - mobj_t *mo; - - if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) - continue; - - mo = blocklinks[y * bmapwidth + x]; - - for (; mo; mo = mo->bnext) - { - // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect - - if (!P_MobjInsidePolyobj(po, mo)) - continue; - - if (!PIT_ChangeSector(mo, false)) - { - nofit = true; - return nofit; - } - } - } - } - } - } - } - - if (sector->numattached) - { - sector_t *sec; - for (i = 0; i < sector->numattached; i++) - { - sec = §ors[sector->attached[i]]; - for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) - n->visited = false; - - sec->moved = true; - - P_RecalcPrecipInSector(sec); - - if (!sector->attachedsolid[i]) - continue; - - do - { - for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) - if (!n->visited) - { - n->visited = true; - if (!(n->m_thing->flags & MF_NOBLOCKMAP)) - { - if (!PIT_ChangeSector(n->m_thing, false)) - { - nofit = true; - return nofit; - } - } - break; - } - } while (n); - } - } - - // Mark all things invalid - sector->moved = true; - - for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) - n->visited = false; - - do - { - for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list - if (!n->visited) // unprocessed thing found - { - n->visited = true; // mark thing as processed - if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these - { - if (!PIT_ChangeSector(n->m_thing, false)) // process it - { - nofit = true; - return nofit; - } - } - break; // exit and start over - } - } while (n); // repeat from scratch until all things left are marked valid + if (!P_CheckSectorHelper(sector, false, crunch)) + return true; // Nothing blocked us, so lets crush for real! + P_CheckSectorHelper(sector, true, crunch); - // Sal: This stupid function chain is required to fix polyobjects not being able to crush. - // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead - validcount++; - - for (i = 0; i < sector->linecount; i++) - { - if (sector->lines[i]->polyobj) - { - polyobj_t *po = sector->lines[i]->polyobj; - if (po->validcount == validcount) - continue; // skip if already checked - if (!(po->flags & POF_SOLID)) - continue; - if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector - { - INT32 x, y; - po->validcount = validcount; - - for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) - { - for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) - { - mobj_t *mo; - - if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) - continue; - - mo = blocklinks[y * bmapwidth + x]; - - for (; mo; mo = mo->bnext) - { - // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect - - if (!P_MobjInsidePolyobj(po, mo)) - continue; - - PIT_ChangeSector(mo, true); - return nofit; - } - } - } - } - } - } - if (sector->numattached) - { - sector_t *sec; - for (i = 0; i < sector->numattached; i++) - { - sec = §ors[sector->attached[i]]; - for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) - n->visited = false; - - sec->moved = true; - - P_RecalcPrecipInSector(sec); - - if (!sector->attachedsolid[i]) - continue; - - do - { - for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) - if (!n->visited) - { - n->visited = true; - if (!(n->m_thing->flags & MF_NOBLOCKMAP)) - { - PIT_ChangeSector(n->m_thing, true); - return nofit; - } - break; - } - } while (n); - } - } - - // Mark all things invalid - sector->moved = true; - - for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) - n->visited = false; - - do - { - for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list - if (!n->visited) // unprocessed thing found - { - n->visited = true; // mark thing as processed - if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these - { - PIT_ChangeSector(n->m_thing, true); // process it - return nofit; - } - break; // exit and start over - } - } while (n); // repeat from scratch until all things left are marked valid - - return nofit; + return false; } /* diff --git a/src/p_maputl.c b/src/p_maputl.c index 260bcc074..e36d5fd72 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -509,26 +509,26 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) // on non-solid polyobjects should NEVER happen in the future if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat - texbottom = back->floorheight + side->rowoffset; - textop = back->ceilingheight + side->rowoffset; + texbottom = back->floorheight + side->rowoffset + side->offsety_mid; + textop = back->ceilingheight + side->rowoffset + side->offsety_mid; } else if (linedef->flags & ML_MIDTEX) { - texbottom = back->floorheight + side->rowoffset; + texbottom = back->floorheight + side->rowoffset + side->offsety_mid; textop = texbottom + texheight*(side->repeatcnt+1); } else { - textop = back->ceilingheight + side->rowoffset; + textop = back->ceilingheight + side->rowoffset + side->offsety_mid; texbottom = textop - texheight*(side->repeatcnt+1); } } else #endif { if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat - texbottom = openbottom + side->rowoffset; - textop = opentop + side->rowoffset; + texbottom = openbottom + side->rowoffset + side->offsety_mid; + textop = opentop + side->rowoffset + side->offsety_mid; } else if (linedef->flags & ML_MIDPEG) { - texbottom = openbottom + side->rowoffset; + texbottom = openbottom + side->rowoffset + side->offsety_mid; textop = texbottom + texheight*(side->repeatcnt+1); } else { - textop = opentop + side->rowoffset; + textop = opentop + side->rowoffset + side->offsety_mid; texbottom = textop - texheight*(side->repeatcnt+1); } } diff --git a/src/p_maputl.h b/src/p_maputl.h index b7779d88a..08de0cb0b 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_mobj.c b/src/p_mobj.c index 4533a2ce8..a43afc9b1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -3139,7 +3139,8 @@ boolean P_SceneryZMovement(mobj_t *mo) if (P_CheckDeathPitCollide(mo)) { - P_RemoveMobj(mo); + if (mo->type != MT_GHOST) // ghosts play death animations instead, so don't remove them + P_RemoveMobj(mo); return false; } @@ -3989,12 +3990,11 @@ void P_NullPrecipThinker(precipmobj_t *mobj) { //(void)mobj; mobj->precipflags &= ~PCF_THUNK; + R_ResetPrecipitationMobjInterpolationState(mobj); } void P_SnowThinker(precipmobj_t *mobj) { - R_ResetPrecipitationMobjInterpolationState(mobj); - P_CycleStateAnimation((mobj_t *)mobj); // adjust height @@ -4007,8 +4007,6 @@ void P_SnowThinker(precipmobj_t *mobj) void P_RainThinker(precipmobj_t *mobj) { - R_ResetPrecipitationMobjInterpolationState(mobj); - P_CycleStateAnimation((mobj_t *)mobj); if (mobj->state != &states[S_RAIN1]) @@ -5664,23 +5662,29 @@ static void P_Boss9Thinker(mobj_t *mobj) { mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER); missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy)); + if (missile->fuse <= 0) // Prevents a division by zero when calculating missile->scalespeed + missile->fuse = 1; if (missile->fuse > mobj->fuse) - P_RemoveMobj(missile); - - if (mobj->health > mobj->info->damage) { - P_SetScale(missile, FRACUNIT/3); - missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power + P_RemoveMobj(missile); } else { - P_SetScale(missile, FRACUNIT/5); - missile->color = SKINCOLOR_SUNSET; // sonic cd electric power + if (mobj->health > mobj->info->damage) + { + P_SetScale(missile, FRACUNIT/3); + missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power + } + else + { + P_SetScale(missile, FRACUNIT/5); + missile->color = SKINCOLOR_SUNSET; // sonic cd electric power + } + missile->destscale = missile->scale*2; + missile->scalespeed = abs(missile->scale - missile->destscale)/missile->fuse; + missile->colorized = true; } - missile->destscale = missile->scale*2; - missile->scalespeed = abs(missile->scale - missile->destscale)/missile->fuse; - missile->colorized = true; } // ...then down. easier than changing the missile's momz after-the-fact @@ -6335,11 +6339,7 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb mobj->fuse = (radius>>(FRACBITS+2)) + 1; if (spawncenter) - { - mobj->x = x; - mobj->y = y; - mobj->z = z; - } + P_SetOrigin(mobj, x, y, z); if (mobj->fuse <= 1) mobj->fuse = 2; @@ -6766,7 +6766,8 @@ void P_RunShields(void) // run shields for (i = 0; i < numshields; i++) { - P_ShieldLook(shields[i], shields[i]->threshold); + if (!P_MobjWasRemoved(shields[i])) + P_ShieldLook(shields[i], shields[i]->threshold); P_SetTarget(&shields[i], NULL); } numshields = 0; @@ -6905,6 +6906,13 @@ static void P_AddOverlay(mobj_t *thing) static void P_RemoveOverlay(mobj_t *thing) { mobj_t *mo; + if (overlaycap == thing) + { + P_SetTarget(&overlaycap, thing->hnext); + P_SetTarget(&thing->hnext, NULL); + return; + } + for (mo = overlaycap; mo; mo = mo->hnext) { if (mo->hnext != thing) @@ -9595,7 +9603,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) case MT_BOSSFLYPOINT: return false; case MT_NIGHTSCORE: - mobj->color = (UINT16)(leveltime % SKINCOLOR_WHITE); + mobj->color = linkColor[mobj->extravalue2][(leveltime + mobj->extravalue1) % NUMLINKCOLORS]; break; case MT_JETFUME1: if (!P_JetFume1Think(mobj)) @@ -9691,7 +9699,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) P_RingThinker(mobj); if (mobj->flags2 & MF2_NIGHTSPULL) P_NightsItemChase(mobj); - else + else if (mobj->type != MT_BOMBSPHERE) // prevent shields from attracting bomb spheres A_AttractChase(mobj); return false; // Flung items @@ -9709,6 +9717,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj) A_AttractChase(mobj); break; case MT_EMBLEM: + if (P_EmblemWasCollected(mobj->health - 1) || !P_CanPickupEmblem(&players[consoleplayer], mobj->health - 1)) + mobj->frame |= (tr_trans50 << FF_TRANSSHIFT); + else + mobj->frame &= ~FF_TRANSMASK; + if (mobj->flags2 & MF2_NIGHTSPULL) P_NightsItemChase(mobj); break; @@ -10066,6 +10079,8 @@ static boolean P_FuseThink(mobj_t *mobj) case MT_SPIKE: case MT_WALLSPIKE: P_SetMobjState(mobj, mobj->state->nextstate); + if (P_MobjWasRemoved(mobj)) + return false; mobj->fuse = mobj->spawnpoint ? mobj->spawnpoint->args[0] : mobj->info->speed; break; case MT_NIGHTSCORE: @@ -10227,7 +10242,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags2 & MF2_FIRING) P_FiringThink(mobj); - if (mobj->type == MT_AMBIENT) + if (mobj->flags & MF_AMBIENT) { if (leveltime % mobj->health) return; @@ -10614,6 +10629,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->reactiontime = info->reactiontime; + mobj->dispoffset = info->dispoffset; + mobj->lastlook = -1; // stuff moved in P_enemy.P_LookForPlayer // do not set the state with P_SetMobjState, @@ -11147,6 +11164,8 @@ void P_RemoveMobj(mobj_t *mobj) memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); #endif + R_RemoveMobjInterpolator(mobj); + // free block if (!mobj->thinker.next) { // Uh-oh, the mobj doesn't think, P_RemoveThinker would never go through! @@ -11163,8 +11182,6 @@ void P_RemoveMobj(mobj_t *mobj) } P_RemoveThinker((thinker_t *)mobj); - - R_RemoveMobjInterpolator(mobj); } // This does not need to be added to Lua. @@ -11195,28 +11212,48 @@ void P_RemovePrecipMobj(precipmobj_t *mobj) void P_RemoveSavegameMobj(mobj_t *mobj) { // unlink from sector and block lists - P_UnsetThingPosition(mobj); - - // Remove touching_sectorlist from mobj. - if (sector_list) + if (((thinker_t *)mobj)->function.acp1 == (actionf_p1)P_NullPrecipThinker) { - P_DelSeclist(sector_list); - sector_list = NULL; + P_UnsetPrecipThingPosition((precipmobj_t *)mobj); + + if (precipsector_list) + { + P_DelPrecipSeclist(precipsector_list); + precipsector_list = NULL; + } + } + else + { + // unlink from sector and block lists + P_UnsetThingPosition(mobj); + + // Remove touching_sectorlist from mobj. + if (sector_list) + { + P_DelSeclist(sector_list); + sector_list = NULL; + } } // stop any playing sound S_StopSound(mobj); + R_RemoveMobjInterpolator(mobj); // free block - P_RemoveThinker((thinker_t *)mobj); - R_RemoveMobjInterpolator(mobj); + // Here we use the same code as R_RemoveThinkerDelayed, but without reference counting (we're removing everything so it shouldn't matter) and without touching currentthinker since we aren't in P_RunThinkers + { + thinker_t *thinker = (thinker_t *)mobj; + thinker_t *next = thinker->next; + (next->prev = thinker->prev)->next = next; + Z_Free(thinker); + } } static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}}; -consvar_t cv_itemrespawntime = CVAR_INIT ("respawnitemtime", "30", CV_SAVE|CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL); -consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_itemrespawntime = CVAR_INIT ("respawnitemtime", "30", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, respawnitemtime_cons_t, NULL); +consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); static CV_PossibleValue_t flagtime_cons_t[] = {{0, "MIN"}, {300, "MAX"}, {0, NULL}}; -consvar_t cv_flagtime = CVAR_INIT ("flagtime", "30", CV_SAVE|CV_NETVAR|CV_CHEAT, flagtime_cons_t, NULL); +consvar_t cv_flagtime = CVAR_INIT ("flagtime", "30", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, flagtime_cons_t, NULL); void P_SpawnPrecipitation(void) { @@ -11830,7 +11867,6 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt case MT_EMERHUNT: case MT_EMERALDSPAWN: case MT_TOKEN: - case MT_EMBLEM: case MT_RING: case MT_REDTEAMRING: case MT_BLUETEAMRING: @@ -11842,6 +11878,10 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt offset += mthing->args[0] ? 0 : 24*FRACUNIT; break; + case MT_EMBLEM: + offset += mthing->args[1] ? 0 : 24 * FRACUNIT; + break; + // Remaining objects. default: if (P_WeaponOrPanel(mobjtype)) @@ -11971,12 +12011,8 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) break; case MT_EMBLEM: - if (netgame || multiplayer) - return false; // Single player - - if (modifiedgame && !savemoddata) - return false; // No cheating!! - + if (!G_CoopGametype()) + return false; // Gametype's not right break; default: break; @@ -12120,7 +12156,6 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) INT32 j; emblem_t* emblem = M_GetLevelEmblems(gamemap); skincolornum_t emcolor; - boolean validEmblem = true; while (emblem) { @@ -12145,42 +12180,19 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting mobj->color = (UINT16)emcolor; - validEmblem = !emblemlocations[j].collected; + mobj->frame &= ~FF_TRANSMASK; - if (emblemlocations[j].type == ET_SKIN) + if (emblemlocations[j].type == ET_GLOBAL) { - INT32 skinnum = M_EmblemSkinNum(&emblemlocations[j]); - - if (players[0].skin != skinnum) + mobj->reactiontime = emblemlocations[j].var; + if (emblemlocations[j].var & GE_NIGHTSITEM) { - validEmblem = false; + mobj->flags |= MF_NIGHTSITEM; + mobj->flags &= ~MF_SPECIAL; + mobj->flags2 |= MF2_DONTDRAW; } } - if (validEmblem == false) - { - P_UnsetThingPosition(mobj); - mobj->flags |= MF_NOCLIP; - mobj->flags &= ~MF_SPECIAL; - mobj->flags |= MF_NOBLOCKMAP; - mobj->frame |= (tr_trans50 << FF_TRANSSHIFT); - P_SetThingPosition(mobj); - } - else - { - mobj->frame &= ~FF_TRANSMASK; - - if (emblemlocations[j].type == ET_GLOBAL) - { - mobj->reactiontime = emblemlocations[j].var; - if (emblemlocations[j].var & GE_NIGHTSITEM) - { - mobj->flags |= MF_NIGHTSITEM; - mobj->flags &= ~MF_SPECIAL; - mobj->flags2 |= MF2_DONTDRAW; - } - } - } return true; } @@ -13254,10 +13266,33 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->flags2 |= MF2_STRONGBOX; } } + // Custom ambient sounds + if ((mobj->flags & MF_AMBIENT) && mobj->type != MT_AMBIENT) + { + mobj->threshold = mobj->info->seesound; + mobj->health = mobj->info->spawnhealth; + } return true; } +// Pre-UDMF backwards compatibility stuff. Remove for 2.3 +static void P_SetAmbush(mapthing_t *mthing, mobj_t *mobj) +{ + if (mobj->type == MT_NIGHTSBUMPER + || mobj->type == MT_AXIS + || mobj->type == MT_AXISTRANSFER + || mobj->type == MT_AXISTRANSFERLINE + || mobj->type == MT_NIGHTSBUMPER + || mobj->type == MT_STARPOST) + return; + + if ((mthing->options & MTF_OBJECTSPECIAL) && (mobj->flags & MF_PUSHABLE)) + return; + + mobj->flags2 |= MF2_AMBUSH; +} + static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, mobjtype_t i) { mobj_t *mobj = NULL; @@ -13280,6 +13315,9 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, mthing->mobj = mobj; + if (!udmf && (mthing->options & MTF_AMBUSH)) + P_SetAmbush(mthing, mobj); + // Generic reverse gravity for individual objects flag. if (mthing->options & MTF_OBJECTFLIP) { @@ -13506,7 +13544,7 @@ static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 numi static void P_SpawnSingularItemRow(mapthing_t *mthing, mobjtype_t itemtype, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle, boolean bonustime) { mobjtype_t itemtypes[1] = { itemtype }; - return P_SpawnItemRow(mthing, itemtypes, 1, numitems, horizontalspacing, verticalspacing, fixedangle, bonustime); + P_SpawnItemRow(mthing, itemtypes, 1, numitems, horizontalspacing, verticalspacing, fixedangle, bonustime); } static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 numitemtypes, INT32 numitems, fixed_t size, boolean bonustime) @@ -13650,7 +13688,6 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) UINT8 numitemtypes; if (!udmf) return; - CONS_Printf("Itemstring: %s\n", mthing->stringargs[0]); P_ParseItemTypes(mthing->stringargs[0], itemtypes, &numitemtypes); P_SpawnItemCircle(mthing, itemtypes, numitemtypes, mthing->args[0], mthing->args[1] << FRACBITS, bonustime); return; diff --git a/src/p_mobj.h b/src/p_mobj.h index 60601692c..6717c4add 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -118,7 +118,7 @@ typedef enum // Don't apply gravity (every tic); object will float, keeping current height // or changing it actively. MF_NOGRAVITY = 1<<9, - // This object is an ambient sound. Obsolete, but keep this around for backwards compatibility. + // This object is an ambient sound. MF_AMBIENT = 1<<10, // Slide this object when it hits a wall. MF_SLIDEME = 1<<11, @@ -399,6 +399,7 @@ typedef struct mobj_s boolean colorized; // Whether the mobj uses the rainbow colormap boolean mirrored; // The object's rotations will be mirrored left to right, e.g., see frame AL from the right and AR from the left fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius + INT32 dispoffset; // copy of info->dispoffset, so mobjs can be sorted independently of their type // WARNING: New fields must be added separately to savegame and Lua. } mobj_t; diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 7ef956ff1..b207bb740 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by James Haley -// Copyright (C) 2006-2022 by Sonic Team Junior. +// Copyright (C) 2006-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_polyobj.h b/src/p_polyobj.h index e9d246168..0573f6350 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by James Haley -// Copyright (C) 2006-2022 by Sonic Team Junior. +// Copyright (C) 2006-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -296,16 +296,16 @@ typedef struct polywaypointdata_s typedef enum { - TMPV_NOCHANGE = 1, - TMPV_VISIBLE = 1<<1, - TMPV_INVISIBLE = 1<<2, + TMPV_NOCHANGE = 0, + TMPV_VISIBLE = 1, + TMPV_INVISIBLE = 2, } textmappolyvisibility_t; typedef enum { - TMPT_NOCHANGE = 1, - TMPT_TANGIBLE = 1<<1, - TMPT_INTANGIBLE = 1<<2, + TMPT_NOCHANGE = 0, + TMPT_TANGIBLE = 1, + TMPT_INTANGIBLE = 2, } textmappolytangibility_t; // polyobject door types diff --git a/src/p_pspr.h b/src/p_pspr.h index 4136c2118..69e5eeeb3 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_saveg.c b/src/p_saveg.c index 464372d68..8eac91105 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -47,6 +47,7 @@ UINT8 *save_p; #define ARCHIVEBLOCK_POBJS 0x7F928546 #define ARCHIVEBLOCK_THINKERS 0x7F37037C #define ARCHIVEBLOCK_SPECIALS 0x7F228378 +#define ARCHIVEBLOCK_EMBLEMS 0x7F4A5445 // Note: This cannot be bigger // than an UINT16 @@ -168,6 +169,7 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].playerstate); WRITEUINT32(save_p, players[i].pflags); WRITEUINT8(save_p, players[i].panim); + WRITEUINT8(save_p, players[i].stronganim); WRITEUINT8(save_p, players[i].spectator); WRITEUINT16(save_p, players[i].flashpal); @@ -395,6 +397,7 @@ static void P_NetUnArchivePlayers(void) players[i].playerstate = READUINT8(save_p); players[i].pflags = READUINT32(save_p); players[i].panim = READUINT8(save_p); + players[i].stronganim = READUINT8(save_p); players[i].spectator = READUINT8(save_p); players[i].flashpal = READUINT16(save_p); @@ -1571,6 +1574,7 @@ typedef enum MD2_SPRITEXOFFSET = 1<<20, MD2_SPRITEYOFFSET = 1<<21, MD2_FLOORSPRITESLOPE = 1<<22, + MD2_DISPOFFSET = 1<<23 } mobj_diff2_t; typedef enum @@ -1805,6 +1809,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) || (slope->normal.z != FRACUNIT)) diff2 |= MD2_FLOORSPRITESLOPE; } + if (mobj->dispoffset != mobj->info->dispoffset) + diff2 |= MD2_DISPOFFSET; if (diff2 != 0) diff |= MD_MORE; @@ -1980,6 +1986,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, slope->normal.y); WRITEFIXED(save_p, slope->normal.z); } + if (diff2 & MD2_DISPOFFSET) + WRITEINT32(save_p, mobj->dispoffset); WRITEUINT32(save_p, mobj->mobjnum); } @@ -3034,6 +3042,10 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) slope->normal.y = READFIXED(save_p); slope->normal.z = READFIXED(save_p); } + if (diff2 & MD2_DISPOFFSET) + mobj->dispoffset = READINT32(save_p); + else + mobj->dispoffset = mobj->info->dispoffset; if (diff & MD_REDFLAG) { @@ -3059,6 +3071,18 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight; } + if (mobj->type == MT_SKYBOX && mobj->spawnpoint) + { + mtag_t tag = Tag_FGet(&mobj->spawnpoint->tags); + if (tag >= 0 && tag <= 15) + { + if (mobj->spawnpoint->args[0]) + skyboxcenterpnts[tag] = mobj; + else + skyboxviewpnts[tag] = mobj; + } + } + mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function R_AddMobjInterpolator(mobj); @@ -3680,10 +3704,14 @@ static void P_NetUnArchiveThinkers(void) { next = currentthinker->next; - if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) + if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker || currentthinker->function.acp1 == (actionf_p1)P_NullPrecipThinker) P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it else + { + (next->prev = currentthinker->prev)->next = next; + R_DestroyLevelInterpolators(currentthinker); Z_Free(currentthinker); + } } } @@ -3885,6 +3913,10 @@ static void P_NetUnArchiveThinkers(void) CONS_Debug(DBG_NETPLAY, "%u thinkers loaded in list %d\n", numloaded, i); } + // Set each skyboxmo to the first skybox (or NULL) + skyboxmo[0] = skyboxviewpnts[0]; + skyboxmo[1] = skyboxcenterpnts[0]; + if (restoreNum) { executor_t *delay = NULL; @@ -4310,6 +4342,8 @@ static void P_NetArchiveMisc(boolean resending) WRITEUINT32(save_p, hidetime); + WRITEUINT32(save_p, unlocktriggers); + // Is it paused? if (paused) WRITEUINT8(save_p, 0x2f); @@ -4408,6 +4442,8 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) hidetime = READUINT32(save_p); + unlocktriggers = READUINT32(save_p); + // Is it paused? if (READUINT8(save_p) == 0x2f) paused = true; @@ -4415,6 +4451,224 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) return true; } + +static inline void P_NetArchiveEmblems(void) +{ + gamedata_t *data = serverGamedata; + INT32 i, j; + UINT8 btemp; + INT32 curmare; + + WRITEUINT32(save_p, ARCHIVEBLOCK_EMBLEMS); + + // These should be synchronized before savegame loading by the wad files being the same anyway, + // but just in case, for now, we'll leave them here for testing. It would be very bad if they mismatch. + WRITEUINT8(save_p, (UINT8)savemoddata); + WRITEINT32(save_p, numemblems); + WRITEINT32(save_p, numextraemblems); + + // The rest of this is lifted straight from G_SaveGameData in g_game.c + // TODO: Optimize this to only send information about emblems, unlocks, etc. which actually exist + // There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same. + + WRITEUINT32(save_p, data->totalplaytime); + + // TODO put another cipher on these things? meh, I don't care... + for (i = 0; i < NUMMAPS; i++) + WRITEUINT8(save_p, (data->mapvisited[i] & MV_MAX)); + + // To save space, use one bit per collected/achieved/unlocked flag + for (i = 0; i < MAXEMBLEMS;) + { + btemp = 0; + for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) + btemp |= (data->collected[j+i] << j); + WRITEUINT8(save_p, btemp); + i += j; + } + for (i = 0; i < MAXEXTRAEMBLEMS;) + { + btemp = 0; + for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) + btemp |= (data->extraCollected[j+i] << j); + WRITEUINT8(save_p, btemp); + i += j; + } + for (i = 0; i < MAXUNLOCKABLES;) + { + btemp = 0; + for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) + btemp |= (data->unlocked[j+i] << j); + WRITEUINT8(save_p, btemp); + i += j; + } + for (i = 0; i < MAXCONDITIONSETS;) + { + btemp = 0; + for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) + btemp |= (data->achieved[j+i] << j); + WRITEUINT8(save_p, btemp); + i += j; + } + + WRITEUINT32(save_p, data->timesBeaten); + WRITEUINT32(save_p, data->timesBeatenWithEmeralds); + WRITEUINT32(save_p, data->timesBeatenUltimate); + + // Main records + for (i = 0; i < NUMMAPS; i++) + { + if (data->mainrecords[i]) + { + WRITEUINT32(save_p, data->mainrecords[i]->score); + WRITEUINT32(save_p, data->mainrecords[i]->time); + WRITEUINT16(save_p, data->mainrecords[i]->rings); + } + else + { + WRITEUINT32(save_p, 0); + WRITEUINT32(save_p, 0); + WRITEUINT16(save_p, 0); + } + } + + // NiGHTS records + for (i = 0; i < NUMMAPS; i++) + { + if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares) + { + WRITEUINT8(save_p, 0); + continue; + } + + WRITEUINT8(save_p, data->nightsrecords[i]->nummares); + + for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare) + { + WRITEUINT32(save_p, data->nightsrecords[i]->score[curmare]); + WRITEUINT8(save_p, data->nightsrecords[i]->grade[curmare]); + WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]); + } + } +} + +static inline void P_NetUnArchiveEmblems(void) +{ + gamedata_t *data = serverGamedata; + INT32 i, j; + UINT8 rtemp; + UINT32 recscore; + tic_t rectime; + UINT16 recrings; + UINT8 recmares; + INT32 curmare; + + if (READUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS) + I_Error("Bad $$$.sav at archive block Emblems"); + + savemoddata = (boolean)READUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason. + + if (numemblems != READINT32(save_p)) + I_Error("numemblems mismatch"); + if (numextraemblems != READINT32(save_p)) + I_Error("numextraemblems mismatch"); + + // This shouldn't happen, but if something really fucked up happens and you transfer + // the SERVER player's gamedata over your own CLIENT gamedata, + // then this prevents it from being saved over yours. + data->loaded = false; + + M_ClearSecrets(data); + G_ClearRecords(data); + + // The rest of this is lifted straight from G_LoadGameData in g_game.c + // TODO: Optimize this to only read information about emblems, unlocks, etc. which actually exist + // There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same. + + data->totalplaytime = READUINT32(save_p); + + // TODO put another cipher on these things? meh, I don't care... + for (i = 0; i < NUMMAPS; i++) + if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX) + I_Error("Bad $$$.sav dearchiving Emblems"); + + // To save space, use one bit per collected/achieved/unlocked flag + for (i = 0; i < MAXEMBLEMS;) + { + rtemp = READUINT8(save_p); + for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) + data->collected[j+i] = ((rtemp >> j) & 1); + i += j; + } + for (i = 0; i < MAXEXTRAEMBLEMS;) + { + rtemp = READUINT8(save_p); + for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) + data->extraCollected[j+i] = ((rtemp >> j) & 1); + i += j; + } + for (i = 0; i < MAXUNLOCKABLES;) + { + rtemp = READUINT8(save_p); + for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) + data->unlocked[j+i] = ((rtemp >> j) & 1); + i += j; + } + for (i = 0; i < MAXCONDITIONSETS;) + { + rtemp = READUINT8(save_p); + for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) + data->achieved[j+i] = ((rtemp >> j) & 1); + i += j; + } + + data->timesBeaten = READUINT32(save_p); + data->timesBeatenWithEmeralds = READUINT32(save_p); + data->timesBeatenUltimate = READUINT32(save_p); + + // Main records + for (i = 0; i < NUMMAPS; ++i) + { + recscore = READUINT32(save_p); + rectime = (tic_t)READUINT32(save_p); + recrings = READUINT16(save_p); + + if (recrings > 10000 || recscore > MAXSCORE) + I_Error("Bad $$$.sav dearchiving Emblems"); + + if (recscore || rectime || recrings) + { + G_AllocMainRecordData((INT16)i, data); + data->mainrecords[i]->score = recscore; + data->mainrecords[i]->time = rectime; + data->mainrecords[i]->rings = recrings; + } + } + + // Nights records + for (i = 0; i < NUMMAPS; ++i) + { + if ((recmares = READUINT8(save_p)) == 0) + continue; + + G_AllocNightsRecordData((INT16)i, data); + + for (curmare = 0; curmare < (recmares+1); ++curmare) + { + data->nightsrecords[i]->score[curmare] = READUINT32(save_p); + data->nightsrecords[i]->grade[curmare] = READUINT8(save_p); + data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); + + if (data->nightsrecords[i]->grade[curmare] > GRADE_S) + { + I_Error("Bad $$$.sav dearchiving Emblems"); + } + } + + data->nightsrecords[i]->nummares = recmares; + } +} + static inline void P_ArchiveLuabanksAndConsistency(void) { UINT8 i, banksinuse = NUM_LUABANKS; @@ -4478,6 +4732,7 @@ void P_SaveNetGame(boolean resending) CV_SaveNetVars(&save_p); P_NetArchiveMisc(resending); + P_NetArchiveEmblems(); // Assign the mobjnumber for pointer tracking for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) @@ -4530,6 +4785,7 @@ boolean P_LoadNetGame(boolean reloading) CV_LoadNetVars(&save_p); if (!P_NetUnArchiveMisc(reloading)) return false; + P_NetUnArchiveEmblems(); P_NetUnArchivePlayers(); if (gamestate == GS_LEVEL) { diff --git a/src/p_saveg.h b/src/p_saveg.h index 9f4a2633f..73fcfd583 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_setup.c b/src/p_setup.c index 20790a48b..bfb70751d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -876,7 +876,7 @@ static void P_SpawnMapThings(boolean spawnemblems) size_t i; mapthing_t *mt; - // Spawn axis points first so they are at the front of the list for fast searching. + // Spawn axis points first so they are at the front of the list for fast searching. for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { switch (mt->type) @@ -1240,6 +1240,9 @@ static void P_LoadSidedefs(UINT8 *data) } sd->rowoffset = SHORT(msd->rowoffset)<offsetx_top = sd->offsetx_mid = sd->offsetx_bot = 0; + sd->offsety_top = sd->offsety_mid = sd->offsety_bot = 0; + P_SetSidedefSector(i, SHORT(msd->sector)); // Special info stored in texture fields! @@ -1761,7 +1764,14 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char else if (fastcmp(param, "triggertag")) sectors[i].triggertag = atol(val); else if (fastcmp(param, "triggerer")) - sectors[i].triggerer = atol(val); + { + if (fastcmp(val, "Player")) + sectors[i].triggerer = TO_PLAYER; + if (fastcmp(val, "AllPlayers")) + sectors[i].triggerer = TO_ALLPLAYERS; + if (fastcmp(val, "Mobj")) + sectors[i].triggerer = TO_MOBJ; + } } static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char *val) @@ -1770,6 +1780,18 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char sides[i].textureoffset = atol(val)<> FRACBITS); if (wsides[i].rowoffset != 0) fprintf(f, "offsety = %d;\n", wsides[i].rowoffset >> FRACBITS); + if (wsides[i].offsetx_top != 0) + fprintf(f, "offsetx_top = %d;\n", wsides[i].offsetx_top >> FRACBITS); + if (wsides[i].offsety_top != 0) + fprintf(f, "offsety_top = %d;\n", wsides[i].offsety_top >> FRACBITS); + if (wsides[i].offsetx_mid != 0) + fprintf(f, "offsetx_mid = %d;\n", wsides[i].offsetx_mid >> FRACBITS); + if (wsides[i].offsety_mid != 0) + fprintf(f, "offsety_mid = %d;\n", wsides[i].offsety_mid >> FRACBITS); + if (wsides[i].offsetx_bot != 0) + fprintf(f, "offsetx_bottom = %d;\n", wsides[i].offsetx_bot >> FRACBITS); + if (wsides[i].offsety_bot != 0) + fprintf(f, "offsety_bottom = %d;\n", wsides[i].offsety_bot >> FRACBITS); if (wsides[i].toptexture > 0 && wsides[i].toptexture < numtextures) fprintf(f, "texturetop = \"%.*s\";\n", 8, textures[wsides[i].toptexture]->name); if (wsides[i].bottomtexture > 0 && wsides[i].bottomtexture < numtextures) @@ -2633,7 +2676,22 @@ static void P_WriteTextmap(void) if (wsectors[i].triggertag != 0) fprintf(f, "triggertag = %d;\n", wsectors[i].triggertag); if (wsectors[i].triggerer != 0) - fprintf(f, "triggerer = %d;\n", wsectors[i].triggerer); + { + switch (wsectors[i].triggerer) + { + case TO_PLAYER: + fprintf(f, "triggerer = \"Player\";\n"); + break; + case TO_ALLPLAYERS: + fprintf(f, "triggerer = \"AllPlayers\";\n"); + break; + case TO_MOBJ: + fprintf(f, "triggerer = \"Mobj\";\n"); + break; + default: + break; + } + } fprintf(f, "}\n"); fprintf(f, "\n"); } @@ -2797,6 +2855,8 @@ static void P_LoadTextmap(void) // Defaults. sd->textureoffset = 0; sd->rowoffset = 0; + sd->offsetx_top = sd->offsetx_mid = sd->offsetx_bot = 0; + sd->offsety_top = sd->offsety_mid = sd->offsety_bot = 0; sd->toptexture = R_TextureNumForName("-"); sd->midtexture = R_TextureNumForName("-"); sd->bottomtexture = R_TextureNumForName("-"); @@ -3009,7 +3069,7 @@ static inline void P_LoadSubsectors(UINT8 *data) for (i = 0; i < numsubsectors; i++, ss++, ms++) { ss->numlines = SHORT(ms->numsegs); - ss->firstline = SHORT(ms->firstseg); + ss->firstline = (UINT16)SHORT(ms->firstseg); P_InitializeSubsector(ss); } } @@ -4187,7 +4247,8 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; lines[i].args[2] = !!(lines[i].flags & ML_SKEWTD); - P_WriteConstant(sides[lines[i].sidenum[0]].toptexture, &lines[i].stringargs[0]); + if (sides[lines[i].sidenum[0]].toptexture) + P_WriteConstant(sides[lines[i].sidenum[0]].toptexture, &lines[i].stringargs[0]); break; case 16: //Minecart parameters lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; @@ -4910,9 +4971,9 @@ static void P_ConvertBinaryLinedefTypes(void) case 331: // Player skin - continuous case 332: // Player skin - each time case 333: // Player skin - once - if (lines[i].special == 303) + if (lines[i].special == 333) lines[i].args[0] = TMT_ONCE; - else if (lines[i].special == 302) + else if (lines[i].special == 332) lines[i].args[0] = (lines[i].flags & ML_BOUNCY) ? TMT_EACHTIMEENTERANDEXIT : TMT_EACHTIMEENTER; else lines[i].args[0] = TMT_CONTINUOUS; @@ -5267,6 +5328,7 @@ static void P_ConvertBinaryLinedefTypes(void) case 433: //Enable/disable gravity flip lines[i].args[0] = !!(lines[i].flags & ML_NOCLIMB); lines[i].args[1] = !!(lines[i].flags & ML_SKEWTD); + lines[i].args[2] = !!(lines[i].flags & ML_BLOCKMONSTERS); break; case 434: //Award power-up if (sides[lines[i].sidenum[0]].text) @@ -5698,22 +5760,31 @@ static void P_ConvertBinaryLinedefTypes(void) case 513: //Scroll ceiling texture case 514: //Scroll ceiling texture (accelerative) case 515: //Scroll ceiling texture (displacement) + case 516: //Scroll floor and ceiling texture + case 517: //Scroll floor and ceiling texture (accelerative) + case 518: //Scroll floor and ceiling texture (displacement) case 520: //Carry objects on floor case 521: //Carry objects on floor (accelerative) case 522: //Carry objects on floor (displacement) case 523: //Carry objects on ceiling case 524: //Carry objects on ceiling (accelerative) case 525: //Carry objects on ceiling (displacement) + case 526: //Carry objects on floor and ceiling + case 527: //Carry objects on floor and ceiling (accelerative) + case 528: //Carry objects on floor and ceiling (displacement) case 530: //Scroll floor texture and carry objects case 531: //Scroll floor texture and carry objects (accelerative) case 532: //Scroll floor texture and carry objects (displacement) case 533: //Scroll ceiling texture and carry objects case 534: //Scroll ceiling texture and carry objects (accelerative) case 535: //Scroll ceiling texture and carry objects (displacement) + case 536: //Scroll floor and ceiling texture and carry objects + case 537: //Scroll floor and ceiling texture and carry objects (accelerative) + case 538: //Scroll floor and ceiling texture and carry objects (displacement) lines[i].args[0] = tag; - lines[i].args[1] = ((lines[i].special % 10) < 3) ? TMP_FLOOR : TMP_CEILING; + lines[i].args[1] = ((lines[i].special % 10) < 6) ? (((lines[i].special % 10) < 3) ? TMP_FLOOR : TMP_CEILING) : TMP_BOTH; lines[i].args[2] = ((lines[i].special - 510)/10 + 1) % 3; - lines[i].args[3] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + lines[i].args[3] = ((lines[i].flags & ML_EFFECT6) ? sides[lines[i].sidenum[0]].textureoffset : R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)) >> FRACBITS; lines[i].args[4] = (lines[i].special % 10) % 3; if (lines[i].args[2] != TMS_SCROLLONLY && !(lines[i].flags & ML_NOCLIMB)) lines[i].args[4] |= TMST_NONEXCLUSIVE; @@ -5744,17 +5815,19 @@ static void P_ConvertBinaryLinedefTypes(void) case 544: //Current case 545: //Upwards current case 546: //Downwards current + { + fixed_t strength = (lines[i].flags & ML_EFFECT6) ? sides[lines[i].sidenum[0]].textureoffset : R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y); lines[i].args[0] = tag; switch ((lines[i].special - 541) % 3) { case 0: - lines[i].args[1] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + lines[i].args[1] = strength >> FRACBITS; break; case 1: - lines[i].args[2] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + lines[i].args[2] = strength >> FRACBITS; break; case 2: - lines[i].args[2] = -R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + lines[i].args[2] = -strength >> FRACBITS; break; } lines[i].args[3] = (lines[i].special >= 544) ? p_current : p_wind; @@ -5764,6 +5837,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[4] |= TMPF_NONEXCLUSIVE; lines[i].special = 541; break; + } case 600: //Floor lighting case 601: //Ceiling lighting lines[i].args[0] = tag; @@ -5986,6 +6060,9 @@ static void P_ConvertBinarySectorTypes(void) case 14: //Non-ramp sector sectors[i].specialflags |= SSF_NOSTEPDOWN; break; + case 15: //Bouncy FOF + CONS_Alert(CONS_WARNING, M_GetText("Deprecated bouncy FOF sector type detected. Please use linedef type 76 instead.\n")); + break; default: break; } @@ -6018,11 +6095,13 @@ static void P_ConvertBinarySectorTypes(void) sectors[i].triggerer = TO_PLAYER; break; case 6: //Trigger linedef executor (Emerald check) + CONS_Alert(CONS_WARNING, M_GetText("Deprecated emerald check sector type detected. Please use linedef types 337-339 instead.\n")); sectors[i].triggertag = tag; sectors[i].flags &= ~MSF_TRIGGERLINE_PLANE; sectors[i].triggerer = TO_PLAYEREMERALDS; break; case 7: //Trigger linedef executor (NiGHTS mare) + CONS_Alert(CONS_WARNING, M_GetText("Deprecated NiGHTS mare sector type detected. Please use linedef types 340-342 instead.\n")); sectors[i].triggertag = tag; sectors[i].flags &= ~MSF_TRIGGERLINE_PLANE; sectors[i].triggerer = TO_PLAYERNIGHTS; @@ -6030,6 +6109,12 @@ static void P_ConvertBinarySectorTypes(void) case 8: //Check for linedef executor on FOFs sectors[i].flags |= MSF_TRIGGERLINE_MOBJ; break; + case 10: //Special stage time/spheres requirements + CONS_Alert(CONS_WARNING, M_GetText("Deprecated sector type for special stage requirements detected. Please use the SpecialStageTime and SpecialStageSpheres level header options instead.\n")); + break; + case 11: //Custom global gravity + CONS_Alert(CONS_WARNING, M_GetText("Deprecated sector type for global gravity detected. Please use the Gravity level header option instead.\n")); + break; default: break; } @@ -6266,7 +6351,6 @@ static void P_ConvertBinaryThingTypes(void) case 312: //Emerald token case 320: //Emerald hunt location case 321: //Match chaos emerald spawn - case 322: //Emblem case 330: //Bounce ring panel case 331: //Rail ring panel case 332: //Automatic ring panel @@ -6279,6 +6363,9 @@ static void P_ConvertBinaryThingTypes(void) case 1800: //Coin mapthings[i].args[0] = !(mapthings[i].options & MTF_AMBUSH); break; + case 322: //Emblem + mapthings[i].args[1] = !(mapthings[i].options & MTF_AMBUSH); + break; case 409: //Extra life monitor mapthings[i].args[2] = !(mapthings[i].options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)); break; @@ -6404,7 +6491,7 @@ static void P_ConvertBinaryThingTypes(void) } mapthings[i].args[0] = mapthings[i].angle; - mapthings[i].args[1] = P_AproxDistance(line->dx >> FRACBITS, line->dy >> FRACBITS); + mapthings[i].args[1] = (line->flags & ML_EFFECT6) ? sides[line->sidenum[0]].textureoffset >> FRACBITS : P_AproxDistance(line->dx >> FRACBITS, line->dy >> FRACBITS); if (mapthings[i].type == 755) mapthings[i].args[1] *= -1; if (mapthings[i].options & MTF_OBJECTSPECIAL) @@ -6627,8 +6714,8 @@ static void P_ConvertBinaryThingTypes(void) case 1713: //Hoop (Customizable) { UINT16 oldangle = mapthings[i].angle; - mapthings[i].angle = ((oldangle >> 8)*360)/256; - mapthings[i].pitch = ((oldangle & 255)*360)/256; + mapthings[i].angle = (mapthings[i].extrainfo == 1) ? oldangle - 90 : ((oldangle >> 8)*360)/256; + mapthings[i].pitch = (mapthings[i].extrainfo == 1) ? oldangle / 360 : ((oldangle & 255)*360)/256; mapthings[i].args[0] = (mapthings[i].type == 1705) ? 96 : (mapthings[i].options & 0xF)*16 + 32; mapthings[i].options &= ~0xF; mapthings[i].type = 1713; @@ -7402,7 +7489,7 @@ static void P_WriteLetter(void) { char *buf, *b; - if (!unlockables[28].unlocked) // pandora's box + if (!serverGamedata->unlocked[28]) // pandora's box return; if (modeattacking) @@ -7746,10 +7833,11 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) nextmapoverride = 0; skipstats = 0; - if (!(netgame || multiplayer || demoplayback) && (!modifiedgame || savemoddata)) - mapvisited[gamemap-1] |= MV_VISITED; - else if (netgame || multiplayer) - mapvisited[gamemap-1] |= MV_MP; // you want to record that you've been there this session, but not permanently + if (!demoplayback) + { + clientGamedata->mapvisited[gamemap-1] |= MV_VISITED; + serverGamedata->mapvisited[gamemap-1] |= MV_VISITED; + } levelloading = false; @@ -7764,8 +7852,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) { // I'd love to do this in the menu code instead of here, but everything's a mess and I can't guarantee saving proper player struct info before the first act's started. You could probably refactor it, but it'd be a lot of effort. Easier to just work off known good code. ~toast 22/06/2020 if (!(ultimatemode || netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking || marathonmode) - && (!modifiedgame || savemoddata) && cursaveslot > 0) + && !usedCheats && cursaveslot > 0) + { G_SaveGame((UINT32)cursaveslot, gamemap); + } // If you're looking for saving sp file progression (distinct from G_SaveGameOver), check G_DoCompleted. } lastmaploaded = gamemap; // HAS to be set after saving!! @@ -7789,6 +7879,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) if (rendermode == render_none || reloadinggamestate) return true; + R_ResetViewInterpolation(0); + R_ResetViewInterpolation(0); + R_UpdateMobjInterpolators(); + // Title card! G_StartTitleCard(); @@ -7896,8 +7990,10 @@ static lumpinfo_t* FindFolder(const char *folName, UINT16 *start, UINT16 *end, l // Add a wadfile to the active wad files, // replace sounds, musics, patches, textures, sprites and maps // -static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps) +static boolean P_LoadAddon(UINT16 numlumps) { + const UINT16 wadnum = (UINT16)(numwadfiles-1); + size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0; char *name; lumpinfo_t *lumpinfo; @@ -7919,6 +8015,12 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps) // UINT16 flaPos, flaNum = 0; // UINT16 mapPos, mapNum = 0; + if (numlumps == INT16_MAX) + { + refreshdirmenu |= REFRESHDIR_NOTLOADED; + return false; + } + switch(wadfiles[wadnum]->type) { case RET_PK3: @@ -8074,7 +8176,7 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps) ST_Start(); // Prevent savefile cheating - if (cursaveslot > 0) + if (modifiedgame && (cursaveslot > 0)) cursaveslot = 0; if (replacedcurrentmap && gamestate == GS_LEVEL && (netgame || multiplayer)) @@ -8089,32 +8191,12 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps) boolean P_AddWadFile(const char *wadfilename) { - UINT16 numlumps, wadnum; - - // Init file. - if ((numlumps = W_InitFile(wadfilename, false, false)) == INT16_MAX) - { - refreshdirmenu |= REFRESHDIR_NOTLOADED; - return false; - } - else - wadnum = (UINT16)(numwadfiles-1); - - return P_LoadAddon(wadnum, numlumps); + return D_CheckPathAllowed(wadfilename, "tried to add file") && + P_LoadAddon(W_InitFile(wadfilename, false, false)); } boolean P_AddFolder(const char *folderpath) { - UINT16 numlumps, wadnum; - - // Init file. - if ((numlumps = W_InitFolder(folderpath, false, false)) == INT16_MAX) - { - refreshdirmenu |= REFRESHDIR_NOTLOADED; - return false; - } - else - wadnum = (UINT16)(numwadfiles-1); - - return P_LoadAddon(wadnum, numlumps); + return D_CheckPathAllowed(folderpath, "tried to add folder") && + P_LoadAddon(W_InitFolder(folderpath, false, false)); } diff --git a/src/p_setup.h b/src/p_setup.h index 36d19f66d..c6f4f741c 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_sight.c b/src/p_sight.c index 4023744dc..3e92bec86 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_slopes.c b/src/p_slopes.c index 8e00d5824..48a13a07d 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2004 by Stephen McGranahan -// Copyright (C) 2015-2022 by Sonic Team Junior. +// Copyright (C) 2015-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -172,6 +172,9 @@ void T_DynamicSlopeVert (dynvertexplanethink_t* th) for (i = 0; i < 3; i++) { + if (!th->secs[i]) + continue; + if (th->relative & (1 << i)) th->vex[i].z = th->origvecheights[i] + (th->secs[i]->floorheight - th->origsecheights[i]); else @@ -205,16 +208,11 @@ static inline void P_AddDynVertexSlopeThinker (pslope_t* slope, const INT16 tags for (i = 0; i < 3; i++) { l = Tag_FindLineSpecial(799, tags[i]); - if (l == -1) - { - Z_Free(th); - return; - } - th->secs[i] = lines[l].frontsector; + th->secs[i] = (l == -1) ? NULL : lines[l].frontsector; th->vex[i] = vx[i]; - th->origsecheights[i] = lines[l].frontsector->floorheight; + th->origsecheights[i] = (l == -1) ? 0 : lines[l].frontsector->floorheight; th->origvecheights[i] = vx[i].z; - if (lines[l].args[0]) + if (l != -1 && lines[l].args[0]) th->relative |= 1<thinker); @@ -871,7 +869,7 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) vector3_t slopemom, axis; angle_t ang; - if (mo->standingslope->flags & SL_NOPHYSICS) + if (slope->flags & SL_NOPHYSICS) return 0; // If there's physics, time for launching. diff --git a/src/p_slopes.h b/src/p_slopes.h index f4b0535e7..096bf8f82 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2004 by Stephen McGranahan -// Copyright (C) 2015-2022 by Sonic Team Junior. +// Copyright (C) 2015-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_spec.c b/src/p_spec.c index d781ea7d7..44bc1faa3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1760,13 +1760,11 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller { if (caller->triggerer == TO_PLAYEREMERALDS) { - CONS_Alert(CONS_WARNING, M_GetText("Deprecated emerald check sector type detected. Please use linedef types 337-339 instead.\n")); if (!(ALL7EMERALDS(emeralds))) return false; } else if (caller->triggerer == TO_PLAYERNIGHTS) { - CONS_Alert(CONS_WARNING, M_GetText("Deprecated NiGHTS mare sector type detected. Please use linedef types 340-342 instead.\n")); if (!P_CheckPlayerMareOld(triggerline)) return false; } @@ -1797,9 +1795,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller { // Unlockable triggers required INT32 trigid = triggerline->args[1]; - if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) - return false; - else if (trigid < 0 || trigid > 31) // limited by 32 bit variable + if (trigid < 0 || trigid > 31) // limited by 32 bit variable { CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", triggerline->sidenum[0], trigid); return false; @@ -1812,14 +1808,12 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller { // An unlockable itself must be unlocked! INT32 unlockid = triggerline->args[1]; - if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) - return false; - else if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count + if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count { CONS_Debug(DBG_GAMELOGIC, "Unlockable check (sidedef %hu): bad unlockable ID %d\n", triggerline->sidenum[0], unlockid); return false; } - else if (!(unlockables[unlockid-1].unlocked)) + else if (!(serverGamedata->unlocked[unlockid-1])) return false; } break; @@ -1882,7 +1876,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller // "Trigger on X calls" linedefs reset if args[2] is set if (specialtype == 321 && triggerline->args[2]) - triggerline->callcount = triggerline->args[3]; + triggerline->callcount = triggerline->args[1]; else { // These special types work only once @@ -2788,6 +2782,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) mo->flags2 &= ~MF2_OBJECTFLIP; else mo->flags2 |= MF2_OBJECTFLIP; + if (line->args[2]) + mo->eflags |= MFE_VERTICALFLIP; if (bot) bot->flags2 = (bot->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); break; @@ -2937,7 +2933,6 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 441: // Trigger unlockable - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer)) { INT32 trigid = line->args[0]; @@ -2948,10 +2943,12 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) unlocktriggers |= 1 << trigid; // Unlocked something? - if (M_UpdateUnlockablesAndExtraEmblems()) + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + + if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata)) { S_StartSound(NULL, sfx_s3k68); - G_SaveGameData(); // only save if unlocked something + G_SaveGameData(clientGamedata); // only save if unlocked something } } } @@ -4180,6 +4177,29 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number) return NULL; } +// Deprecated in favor of P_MobjTouchingSectorSpecial +// Kept for Lua backwards compatibility only +sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) +{ + ffloor_t *rover; + + for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) + { + if (!rover->master->frontsector->special) + continue; + + if (!(rover->fofflags & FOF_EXISTS)) + continue; + + if (!P_IsMobjTouching3DFloor(mo, rover, mo->subsector->sector)) + continue; + + return rover->master->frontsector; + } + + return NULL; +} + sector_t *P_MobjTouchingSectorSpecialFlag(mobj_t *mo, sectorspecialflags_t flag) { msecnode_t *node; @@ -4375,7 +4395,7 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline) return loopsector; } - return false; + return NULL; } boolean P_IsPlayerValid(size_t playernum) @@ -4579,6 +4599,9 @@ static void P_ProcessExitSector(player_t *player, mtag_t sectag) if (player->bot) return; + if (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)) + return; + // Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c) P_DoPlayerFinish(player); @@ -4627,7 +4650,7 @@ static void P_ProcessTeamBase(player_t *player, boolean redteam) // Make sure the team still has their own // flag at their base so they can score. - if (!P_IsFlagAtBase(redteam ? MT_BLUEFLAG : MT_REDFLAG)) + if (!P_IsFlagAtBase(redteam ? MT_REDFLAG : MT_BLUEFLAG)) return; HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE); @@ -5944,8 +5967,6 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto { elevator_t *elevator; // Why not? LOL - CONS_Alert(CONS_WARNING, M_GetText("Detected a camera scanner effect (linedef type 5). This effect is deprecated and will be removed in the future!\n")); - // create and initialize new elevator thinker elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); P_AddThinker(THINK_MAIN, &elevator->thinker); @@ -6200,22 +6221,21 @@ void P_SpawnSpecials(boolean fromnetsave) circuitmap = true; } - if (!sector->special) + if (sector->damagetype == SD_SPIKE) { + //Terrible hack to replace an even worse hack: + //Spike damage automatically sets MSF_TRIGGERSPECIAL_TOUCH. + //Yes, this also affects other specials on the same sector. Sorry. + sector->flags |= MSF_TRIGGERSPECIAL_TOUCH; + } + + // Process deprecated binary sector specials + if (udmf || !sector->special) continue; // Process Section 1 switch(GETSECSPECIAL(sector->special, 1)) { - case 5: // Spikes - //Terrible hack to replace an even worse hack: - //Spike damage automatically sets MSF_TRIGGERSPECIAL_TOUCH. - //Yes, this also affects other specials on the same sector. Sorry. - sector->flags |= MSF_TRIGGERSPECIAL_TOUCH; - break; case 15: // Bouncy FOF - if (udmf) - break; - CONS_Alert(CONS_WARNING, M_GetText("Deprecated bouncy FOF sector type detected. Please use linedef type 76 instead.\n")); CheckForBouncySector = true; break; } @@ -6224,17 +6244,11 @@ void P_SpawnSpecials(boolean fromnetsave) switch(GETSECSPECIAL(sector->special, 2)) { case 10: // Time for special stage - if (udmf) - break; - CONS_Alert(CONS_WARNING, M_GetText("Deprecated sector type for special stage requirements detected. Please use the SpecialStageTime and SpecialStageSpheres level header options instead.\n")); sstimer = (sector->floorheight>>FRACBITS) * TICRATE + 6; // Time to finish ssspheres = sector->ceilingheight>>FRACBITS; // Ring count for special stage break; case 11: // Custom global gravity! - if (udmf) - break; - CONS_Alert(CONS_WARNING, M_GetText("Deprecated sector type for global gravity detected. Please use the Gravity level header option instead.\n")); gravity = sector->floorheight/1000; break; } diff --git a/src/p_spec.h b/src/p_spec.h index cd97efa1a..91dfccb70 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -496,6 +496,7 @@ void P_SpawnSpecials(boolean fromnetsave); // every tic void P_UpdateSpecials(void); sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number); +sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo); sector_t *P_MobjTouchingSectorSpecialFlag(mobj_t *mo, sectorspecialflags_t flag); sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number); sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags_t flag); diff --git a/src/p_telept.c b/src/p_telept.c index 4d10f1df3..66b05ff01 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_tick.c b/src/p_tick.c index fe6a4d33f..b1fd367ed 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -675,7 +675,10 @@ void P_Ticker(boolean run) // Keep track of how long they've been playing! if (!demoplayback) // Don't increment if a demo is playing. - totalplaytime++; + { + clientGamedata->totalplaytime++; + serverGamedata->totalplaytime++; + } if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap)) P_DoSpecialStageStuff(); diff --git a/src/p_tick.h b/src/p_tick.h index d355bc6d7..594bbc7af 100644 --- a/src/p_tick.h +++ b/src/p_tick.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_user.c b/src/p_user.c index 45978d105..1adf6bc3f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1,9 +1,8 @@ - // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -990,6 +989,8 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) if (player->powers[pw_carry] == CR_ROPEHANG) P_SetTarget(&player->mo->tracer, NULL); + player->powers[pw_strong] = STR_NONE; + { angle_t ang; fixed_t fallbackspeed; @@ -1107,6 +1108,7 @@ void P_ResetPlayer(player_t *player) boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) { fixed_t bottomheight, topheight; + boolean allatk = ((player->powers[pw_strong] & STR_PUNCH) && (player->powers[pw_strong] & STR_TAIL) && (player->powers[pw_strong] & STR_STOMP) && (player->powers[pw_strong] & STR_UPPER)); if (!player->mo || player->spectator || !thing || P_MobjWasRemoved(thing)) return false; @@ -1131,22 +1133,33 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) // Jumping. if ((player->pflags & PF_JUMPED) - && (!(player->pflags & PF_NOJUMPDAMAGE) - || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) + && (!(player->pflags & PF_NOJUMPDAMAGE))) return true; // Spinning. if (player->pflags & PF_SPINNING) return true; - if (player->dashmode >= DASHMODE_THRESHOLD && (player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)) + // Shield stomp. + if (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY)) + return true; + + // pw_strong checks below here + + // Omnidirectional attacks. + if (allatk || (player->powers[pw_strong] & STR_DASH)) return true; // From the front. - if (((player->pflags & PF_GLIDING) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) + if ((player->powers[pw_strong] & STR_PUNCH) && (player->drawangle - R_PointToAngle2(player->mo->x - player->mo->momx, player->mo->y - player->mo->momy, thing->x, thing->y) + + ANGLE_90) < ANGLE_180) return true; + // From the back. + if ((player->powers[pw_strong] & STR_TAIL) + && (player->drawangle - R_PointToAngle2(player->mo->x - player->mo->momx, player->mo->y - player->mo->momy, thing->x, thing->y) + + ANGLE_90) >= ANGLE_180) + return true; + // From the top/bottom. bottomheight = player->mo->z; topheight = player->mo->z + player->mo->height; @@ -1160,19 +1173,15 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) if (P_MobjFlip(player->mo)*(bottomheight - (thing->z + thing->height/2)) > 0) { - if ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) < 0)) + if ((player->charflags & SF_STOMPDAMAGE || player->powers[pw_strong] & STR_STOMP) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) < 0)) return true; } else if (P_MobjFlip(player->mo)*(topheight - (thing->z + thing->height/2)) < 0) { - if (player->charability == CA_FLY && player->panim == PA_ABILITY && !(player->mo->eflags & MFE_UNDERWATER) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0)) + if ((player->powers[pw_strong] & STR_UPPER) && (player->mo->sprite2 != SPR2_SWIM) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0)) return true; } - // Shield stomp. - if (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY)) - return true; - return false; } @@ -2334,6 +2343,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; S_StartSound(player->mo, sfx_s3k8b); player->pflags |= PF_FULLSTASIS; + player->powers[pw_strong] = STR_MELEE; // hearticles if (type) @@ -2558,17 +2568,13 @@ static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover) return true; // Passive wall breaking - if (player->charflags & SF_CANBUSTWALLS) + if (player->charflags & SF_CANBUSTWALLS || player->powers[pw_strong] & (STR_WALL|STR_FLOOR|STR_CEILING|STR_DASH)) return true; // Super if (player->powers[pw_super]) return true; - // Dashmode - if ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) && player->dashmode >= DASHMODE_THRESHOLD) - return true; - // NiGHTS drill if (player->pflags & PF_DRILLING) return true; @@ -2579,21 +2585,11 @@ static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover) /* FALLTHRU */ case BT_STRONG: // Requires a "strong ability" - if (player->charflags & SF_CANBUSTWALLS) - return true; - - if (player->pflags & PF_BOUNCING) - return true; - - if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY) - return true; - - if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) + if (player->charflags & SF_CANBUSTWALLS || player->powers[pw_strong] & (STR_WALL|STR_FLOOR|STR_CEILING)) return true; break; } - return false; } @@ -2609,7 +2605,7 @@ static void P_CheckBustableBlocks(player_t *player) oldx = player->mo->x; oldy = player->mo->y; - if (!(player->pflags & PF_BOUNCING)) // Bouncers only get to break downwards, not sideways + if (!((player->powers[pw_strong] & (STR_FLOOR|STR_CEILING)) && (!(player->powers[pw_strong] & STR_WALL)) && (!(player->charflags & SF_CANBUSTWALLS)))) // Don't break sideways without wall powers { P_UnsetThingPosition(player->mo); player->mo->x += player->mo->momx; @@ -2636,8 +2632,24 @@ static void P_CheckBustableBlocks(player_t *player) topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); - if (((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY)) - || ((P_MobjFlip(player->mo)*player->mo->momz < 0) && (player->pflags & PF_BOUNCING || ((player->charability2 == CA2_MELEE) && (player->panim == PA_ABILITY2))))) + // Height checks + if (player->mo->eflags & MFE_VERTICALFLIP) + { + if ((player->powers[pw_strong] & STR_FLOOR) && (!(player->powers[pw_strong] & STR_CEILING)) && player->mo->z > topheight) + continue; + + if ((player->powers[pw_strong] & STR_CEILING) && (!(player->powers[pw_strong] & STR_FLOOR)) && player->mo->z + player->mo->height < bottomheight) + continue; + } + else + { + if ((player->powers[pw_strong] & STR_FLOOR) && (!(player->powers[pw_strong] & STR_CEILING)) && player->mo->z < bottomheight) + continue; + + if ((player->powers[pw_strong] & STR_CEILING) && (!(player->powers[pw_strong] & STR_FLOOR)) && player->mo->z + player->mo->height > topheight) + continue; + } + if (player->powers[pw_strong] & (STR_FLOOR|STR_CEILING)) { topheight -= player->mo->momz; bottomheight -= player->mo->momz; @@ -2705,7 +2717,7 @@ static void P_CheckBustableBlocks(player_t *player) } } bustupdone: - if (!(player->pflags & PF_BOUNCING)) + if (!((player->powers[pw_strong] & (STR_FLOOR|STR_CEILING)) && (!(player->powers[pw_strong] & STR_WALL)) && (!(player->charflags & SF_CANBUSTWALLS)))) { P_UnsetThingPosition(player->mo); player->mo->x = oldx; @@ -2985,7 +2997,7 @@ static void P_CheckInvincibilityTimer(player_t *player) return; if (mariomode && !player->powers[pw_super]) - player->mo->color = (UINT16)(SKINCOLOR_RUBY + (leveltime % (numskincolors - SKINCOLOR_RUBY))); // Passes through all saturated colours + player->mo->color = (UINT16)(SKINCOLOR_RUBY + (leveltime % (FIRSTSUPERCOLOR - SKINCOLOR_RUBY))); // Passes through all saturated colours else if (leveltime % (TICRATE/7) == 0) { mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_IVSP); @@ -3108,14 +3120,25 @@ static void P_DoPlayerHeadSigns(player_t *player) if (G_TagGametype()) { // If you're "IT", show a big "IT" over your head for others to see. - if (player->pflags & PF_TAGIT) + if (player->pflags & PF_TAGIT && !P_IsLocalPlayer(player)) { - if (!P_IsLocalPlayer(player)) // Don't display it on your own view. + mobj_t* it = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TAG); + it->x = player->mo->x; + it->y = player->mo->y; + it->z = player->mo->z; + it->old_x = player->mo->old_x; + it->old_y = player->mo->old_y; + it->old_z = player->mo->old_z; + + if (!(player->mo->eflags & MFE_VERTICALFLIP)) { - if (!(player->mo->eflags & MFE_VERTICALFLIP)) - P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height, MT_TAG); - else - P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z - mobjinfo[MT_TAG].height, MT_TAG)->eflags |= MFE_VERTICALFLIP; + it->z += player->mo->height; + it->old_z += player->mo->height; + } + else + { + it->z -= mobjinfo[MT_TAG].height; + it->old_z -= mobjinfo[MT_TAG].height; } } } @@ -3125,15 +3148,32 @@ static void P_DoPlayerHeadSigns(player_t *player) // has it (but not on your own screen if you have the flag). if (splitscreen || player != &players[consoleplayer]) { - mobj_t *sign = P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, - player->mo->z+player->mo->momz, MT_GOTFLAG); - if (player->mo->eflags & MFE_VERTICALFLIP) + fixed_t zofs; + mobj_t *sign; + boolean player_is_flipped = (player->mo->eflags & MFE_VERTICALFLIP) > 0; + + zofs = player->mo->momz; + if (player_is_flipped) { - sign->z += player->mo->height-P_GetPlayerHeight(player)-mobjinfo[MT_GOTFLAG].height-FixedMul(16*FRACUNIT, player->mo->scale); - sign->eflags |= MFE_VERTICALFLIP; + zofs += player->mo->height - P_GetPlayerHeight(player) - mobjinfo[MT_GOTFLAG].height - FixedMul(16 * FRACUNIT, player->mo->scale); } else - sign->z += P_GetPlayerHeight(player)+FixedMul(16*FRACUNIT, player->mo->scale); + { + zofs += P_GetPlayerHeight(player) + FixedMul(16 * FRACUNIT, player->mo->scale); + } + + sign = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_GOTFLAG); + sign->x = player->mo->x; + sign->y = player->mo->y; + sign->z = player->mo->z + zofs; + sign->old_x = player->mo->old_x; + sign->old_y = player->mo->old_y; + sign->old_z = player->mo->old_z + zofs; + + if (player_is_flipped) + { + sign->eflags |= MFE_VERTICALFLIP; + } if (player->gotflag & GF_REDFLAG) sign->frame = 1|FF_FULLBRIGHT; @@ -4742,6 +4782,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) player->mo->momx += player->cmomx; player->mo->momy += player->cmomy; P_SetPlayerMobjState(player->mo, S_PLAY_MELEE); + player->powers[pw_strong] = STR_MELEE; S_StartSound(player->mo, sfx_s3k42); } player->pflags |= PF_SPINDOWN; @@ -4984,11 +5025,12 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) static void P_DoTwinSpin(player_t *player) { - player->pflags &= ~PF_NOJUMPDAMAGE; + player->pflags &= ~(PF_NOJUMPDAMAGE|PF_SPINNING); player->pflags |= P_GetJumpFlags(player) | PF_THOKKED; S_StartSound(player->mo, sfx_s3k42); player->mo->frame = 0; P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN); + player->powers[pw_strong] = STR_TWINSPIN; } // @@ -5031,6 +5073,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) { player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->pflags &= ~PF_SPINNING; player->mo->momx = player->mo->momy = player->mo->momz = 0; S_StartSound(player->mo, sfx_ngskid); } @@ -5046,11 +5089,13 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock // Armageddon pow case SH_ARMAGEDDON: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->pflags &= ~PF_SPINNING; P_BlackOw(player); break; // Attraction blast case SH_ATTRACT: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->pflags &= ~PF_SPINNING; player->homing = 2; P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockonshield)); if (lockonshield) @@ -5070,6 +5115,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock { boolean elem = ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL); player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->pflags &= ~PF_SPINNING; if (elem) { player->mo->momx = player->mo->momy = 0; @@ -5092,7 +5138,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock player->pflags |= PF_THOKKED|PF_SHIELDABILITY; P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); player->drawangle = player->mo->angle; - player->pflags &= ~PF_NOJUMPDAMAGE; + player->pflags &= ~(PF_NOJUMPDAMAGE|PF_SPINNING); P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); S_StartSound(player->mo, sfx_s3k43); default: @@ -5352,6 +5398,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->pflags |= PF_THOKKED; else player->pflags |= (PF_THOKKED|PF_CANCARRY); + player->powers[pw_strong] = STR_FLY; } break; case CA_GLIDEANDCLIMB: @@ -5378,14 +5425,15 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE); if (playerspeed < glidespeed) P_Thrust(player->mo, player->mo->angle, glidespeed - playerspeed); - player->pflags &= ~(PF_SPINNING|PF_STARTDASH); + player->pflags &= ~(PF_JUMPED|PF_SPINNING|PF_STARTDASH); + player->powers[pw_strong] = STR_GLIDE; } break; case CA_DOUBLEJUMP: // Double-Jump if (!(player->pflags & PF_THOKKED) || ((player->charflags & SF_MULTIABILITY) && (player->secondjump < (player->actionspd >> FRACBITS)))) { player->pflags |= PF_THOKKED; - player->pflags &= ~PF_JUMPED; + player->pflags &= ~(PF_JUMPED|PF_SPINNING); P_DoJump(player, true); player->secondjump++; } @@ -5411,6 +5459,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) P_Telekinesis(player, FixedMul(player->actionspd, player->mo->scale), // +ve thrust (pushing away from player) FixedMul(384*FRACUNIT, player->mo->scale)); + player->pflags &= ~PF_SPINNING; } break; case CA_FALLSWITCH: @@ -5419,6 +5468,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->mo->momz = -player->mo->momz; P_SpawnThokMobj(player); player->pflags |= PF_THOKKED; + player->pflags &= ~PF_SPINNING; } break; case CA_AIRDRILL: @@ -5426,6 +5476,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { player->flyangle = 56 + (60-(player->actionspd>>FRACBITS))/3; player->pflags |= PF_THOKKED; + player->pflags &= ~PF_SPINNING; S_StartSound(player->mo, sfx_spndsh); } break; @@ -5433,8 +5484,9 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if (!(player->pflags & PF_THOKKED) || player->charflags & SF_MULTIABILITY) { P_SetPlayerMobjState(player->mo, S_PLAY_BOUNCE); - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING); player->pflags |= PF_THOKKED|PF_BOUNCING; + player->powers[pw_strong] = STR_BOUNCE; player->mo->momx >>= 1; player->mo->momy >>= 1; player->mo->momz >>= 1; @@ -8465,12 +8517,12 @@ void P_MovePlayer(player_t *player) } } - // End your chain if you're on the ground or climbing a wall. + // End your chain if you're on the ground while not rolling, or climbing a wall. // But not if invincible! Allow for some crazy long chains with it. // Also keep in mind the PF_JUMPED check. // If we lacked this, stepping up while jumping up would reset score. // (for instance, when climbing up off a wall.) - if ((onground || player->climbing) && !(player->pflags & PF_JUMPED) && player->powers[pw_invulnerability] <= 1) + if ((onground || player->climbing) && ((player->pflags & (PF_STARTDASH|PF_SPINNING)) != PF_SPINNING) && !(player->pflags & PF_JUMPED) && player->powers[pw_invulnerability] <= 1) P_ResetScore(player); // Show the "THOK!" graphic when spinning quickly across the ground. (even applies to non-spinners, in the case of zoom tubes) @@ -9052,10 +9104,6 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction, switch (mo->type) { - case MT_TNTBARREL: - if (lockonflags & LOCK_INTERESTS) - break; - /*FALLTHRU*/ case MT_PLAYER: // Don't chase other players! case MT_DETON: continue; // Don't be STUPID, Sonic! @@ -9076,17 +9124,13 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction, /*FALLTHRU*/ default: - if ((lockonflags & LOCK_BOSS) && ((mo->flags & (MF_BOSS|MF_SHOOTABLE)) == (MF_BOSS|MF_SHOOTABLE))) // allows if it has the flags desired XOR it has the invert aimable flag - { - if (mo->flags2 & MF2_FRET) - continue; + if ((lockonflags & LOCK_BOSS) && (mo->flags & MF_BOSS)) // always allow targeting bosses break; - } if ((lockonflags & LOCK_ENEMY) && (!((mo->flags & (MF_ENEMY|MF_SHOOTABLE)) == (MF_ENEMY|MF_SHOOTABLE)) != !(mo->flags2 & MF2_INVERTAIMABLE))) // allows if it has the flags desired XOR it has the invert aimable flag break; - if ((lockonflags & LOCK_INTERESTS) && (mo->flags & (MF_PUSHABLE|MF_MONITOR))) // allows if it has the flags desired XOR it has the invert aimable flag + if ((lockonflags & LOCK_INTERESTS) && (mo->flags & (MF_PUSHABLE|MF_MONITOR))) // allows if it has the flags desired break; continue; // not a valid object @@ -9613,45 +9657,45 @@ static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {25, "MAX"}, {0, NULL static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}}; static CV_PossibleValue_t multiplier_cons_t[] = {{0, "MIN"}, {3*FRACUNIT, "MAX"}, {0, NULL}}; -consvar_t cv_cam_dist = CVAR_INIT ("cam_curdist", "160", CV_FLOAT, NULL, NULL); -consvar_t cv_cam_height = CVAR_INIT ("cam_curheight", "25", CV_FLOAT, NULL, NULL); -consvar_t cv_cam_still = CVAR_INIT ("cam_still", "Off", 0, CV_OnOff, NULL); -consvar_t cv_cam_speed = CVAR_INIT ("cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL); -consvar_t cv_cam_rotate = CVAR_INIT ("cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange); -consvar_t cv_cam_rotspeed = CVAR_INIT ("cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL); -consvar_t cv_cam_turnmultiplier = CVAR_INIT ("cam_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE, multiplier_cons_t, NULL); -consvar_t cv_cam_orbit = CVAR_INIT ("cam_orbit", "Off", CV_SAVE, CV_OnOff, NULL); -consvar_t cv_cam_adjust = CVAR_INIT ("cam_adjust", "On", CV_SAVE, CV_OnOff, NULL); -consvar_t cv_cam2_dist = CVAR_INIT ("cam2_curdist", "160", CV_FLOAT, NULL, NULL); -consvar_t cv_cam2_height = CVAR_INIT ("cam2_curheight", "25", CV_FLOAT, NULL, NULL); -consvar_t cv_cam2_still = CVAR_INIT ("cam2_still", "Off", 0, CV_OnOff, NULL); -consvar_t cv_cam2_speed = CVAR_INIT ("cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL); -consvar_t cv_cam2_rotate = CVAR_INIT ("cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange); -consvar_t cv_cam2_rotspeed = CVAR_INIT ("cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL); -consvar_t cv_cam2_turnmultiplier = CVAR_INIT ("cam2_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE, multiplier_cons_t, NULL); -consvar_t cv_cam2_orbit = CVAR_INIT ("cam2_orbit", "Off", CV_SAVE, CV_OnOff, NULL); -consvar_t cv_cam2_adjust = CVAR_INIT ("cam2_adjust", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_cam_dist = CVAR_INIT ("cam_curdist", "160", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); +consvar_t cv_cam_height = CVAR_INIT ("cam_curheight", "25", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); +consvar_t cv_cam_still = CVAR_INIT ("cam_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_cam_speed = CVAR_INIT ("cam_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL); +consvar_t cv_cam_rotate = CVAR_INIT ("cam_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate_OnChange); +consvar_t cv_cam_rotspeed = CVAR_INIT ("cam_rotspeed", "10", CV_SAVE|CV_ALLOWLUA, rotation_cons_t, NULL); +consvar_t cv_cam_turnmultiplier = CVAR_INIT ("cam_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, multiplier_cons_t, NULL); +consvar_t cv_cam_orbit = CVAR_INIT ("cam_orbit", "Off", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_cam_adjust = CVAR_INIT ("cam_adjust", "On", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_cam2_dist = CVAR_INIT ("cam2_curdist", "160", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); +consvar_t cv_cam2_height = CVAR_INIT ("cam2_curheight", "25", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); +consvar_t cv_cam2_still = CVAR_INIT ("cam2_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_cam2_speed = CVAR_INIT ("cam2_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL); +consvar_t cv_cam2_rotate = CVAR_INIT ("cam2_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate2_OnChange); +consvar_t cv_cam2_rotspeed = CVAR_INIT ("cam2_rotspeed", "10", CV_SAVE|CV_ALLOWLUA, rotation_cons_t, NULL); +consvar_t cv_cam2_turnmultiplier = CVAR_INIT ("cam2_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, multiplier_cons_t, NULL); +consvar_t cv_cam2_orbit = CVAR_INIT ("cam2_orbit", "Off", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_cam2_adjust = CVAR_INIT ("cam2_adjust", "On", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL); // [standard vs simple][p1 or p2] consvar_t cv_cam_savedist[2][2] = { { // standard - CVAR_INIT ("cam_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist), - CVAR_INIT ("cam2_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist), + CVAR_INIT ("cam_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), + CVAR_INIT ("cam2_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), }, { // simple - CVAR_INIT ("cam_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist), - CVAR_INIT ("cam2_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist), + CVAR_INIT ("cam_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), + CVAR_INIT ("cam2_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), } }; consvar_t cv_cam_saveheight[2][2] = { { // standard - CVAR_INIT ("cam_height", "40", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist), - CVAR_INIT ("cam2_height", "40", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist), + CVAR_INIT ("cam_height", "40", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), + CVAR_INIT ("cam2_height", "40", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), }, { // simple - CVAR_INIT ("cam_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist), - CVAR_INIT ("cam2_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist), + CVAR_INIT ("cam_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), + CVAR_INIT ("cam2_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), } }; @@ -11031,6 +11075,21 @@ static void P_MinecartThink(player_t *player) S_StartSound(minecart, minecart->info->activesound); } } + + // Mark interpolation; the old positions need to be relative to the displacement from the minecart _after_ it's moved. + // This isn't quite correct (it captures the landing wobble) but it works well enough + if (detleft) + { + detleft->old_x = detleft->x - (minecart->old_x - minecart->old_x2); + detleft->old_y = detleft->y - (minecart->old_y - minecart->old_y2); + detleft->old_z = detleft->z - (minecart->old_z - minecart->old_z2); + } + if (detright) + { + detright->old_x = detright->x - (minecart->old_x - minecart->old_x2); + detright->old_y = detright->y - (minecart->old_y - minecart->old_y2); + detright->old_z = detright->z - (minecart->old_z - minecart->old_z2); + } } else { @@ -11259,6 +11318,11 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) tails->y = player->mo->y + P_ReturnThrustY(tails, tails->angle, FixedMul(backwards, tails->scale)); tails->z = player->mo->z + zoffs; P_SetThingPosition(tails); + + if (player->mo->flags2 & MF2_SHADOW) + tails->flags2 |= MF2_SHADOW; + else + tails->flags2 &= ~MF2_SHADOW; } // Metal Sonic's jet fume @@ -12006,7 +12070,6 @@ void P_PlayerThink(player_t *player) P_DoBubbleBreath(player); // Spawn Sonic's bubbles P_CheckUnderwaterAndSpaceTimer(player); // Display the countdown drown numbers! P_CheckInvincibilityTimer(player); // Spawn Invincibility Sparkles - P_DoPlayerHeadSigns(player); // Spawn Tag/CTF signs over player's head #if 1 // "Blur" a bit when you have speed shoes and are going fast enough @@ -12127,6 +12190,16 @@ void P_PlayerThink(player_t *player) else player->powers[pw_ignorelatch] = 0; + if (player->powers[pw_strong] & STR_ANIM) + { + if (!(player->stronganim)) + player->stronganim = player->panim; + else if (player->panim != player->stronganim) + player->powers[pw_strong] = STR_NONE; + } + else if (player->stronganim) + player->stronganim = 0; + //pw_super acts as a timer now if (player->powers[pw_super] && (player->mo->state < &states[S_PLAY_SUPER_TRANS1] @@ -12221,6 +12294,8 @@ void P_PlayerThink(player_t *player) { player->normalspeed = skins[player->skin].normalspeed; // Reset to default if not capable of entering dash mode. player->jumpfactor = skins[player->skin].jumpfactor; + if (player->powers[pw_strong] & STR_DASH) + player->powers[pw_strong] = STR_NONE; } } else if (P_IsObjectOnGround(player->mo)) // Activate dash mode if we're on the ground. @@ -12230,6 +12305,9 @@ void P_PlayerThink(player_t *player) if (player->jumpfactor < FixedMul(skins[player->skin].jumpfactor, 5*FRACUNIT/4)) // Boost jump height. player->jumpfactor += FRACUNIT/300; + + if ((player->charflags & SF_MACHINE) && (!(player->powers[pw_strong] == STR_METAL))) + player->powers[pw_strong] = STR_METAL; } if (player->normalspeed >= skins[player->skin].normalspeed*2) @@ -12247,6 +12325,8 @@ void P_PlayerThink(player_t *player) player->normalspeed = skins[player->skin].normalspeed; player->jumpfactor = skins[player->skin].jumpfactor; S_StartSound(player->mo, sfx_kc65); + if (player->powers[pw_strong] & STR_DASH) + player->powers[pw_strong] = STR_NONE; } dashmode = 0; } @@ -12755,7 +12835,7 @@ void P_PlayerAfterThink(player_t *player) P_KillMobj(ptera, player->mo, player->mo, 0); P_SetObjectMomZ(player->mo, 12*FRACUNIT, false); player->pflags |= PF_APPLYAUTOBRAKE|PF_JUMPED|PF_THOKKED; - P_SetMobjState(player->mo, S_PLAY_ROLL); + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); break; } @@ -12871,6 +12951,8 @@ void P_PlayerAfterThink(player_t *player) } } } + + P_DoPlayerHeadSigns(player); // Spawn Tag/CTF signs over player's head } void P_SetPlayerAngle(player_t *player, angle_t angle) diff --git a/src/r_bsp.c b/src/r_bsp.c index 129c6ba00..42e050adf 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -399,8 +399,8 @@ static void R_AddLine(seg_t *line) return; // big room fix - angle1 = R_PointToAngleEx(viewx, viewy, line->v1->x, line->v1->y); - angle2 = R_PointToAngleEx(viewx, viewy, line->v2->x, line->v2->y); + angle1 = R_PointToAngle64(line->v1->x, line->v1->y); + angle2 = R_PointToAngle64(line->v2->x, line->v2->y); curline = line; // Clip to view edges. @@ -620,8 +620,8 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) check = checkcoord[boxpos]; // big room fix - angle1 = R_PointToAngleEx(viewx, viewy, bspcoord[check[0]], bspcoord[check[1]]) - viewangle; - angle2 = R_PointToAngleEx(viewx, viewy, bspcoord[check[2]], bspcoord[check[3]]) - viewangle; + angle1 = R_PointToAngle64(bspcoord[check[0]], bspcoord[check[1]]) - viewangle; + angle2 = R_PointToAngle64(bspcoord[check[2]], bspcoord[check[3]]) - viewangle; if ((signed)angle1 < (signed)angle2) { diff --git a/src/r_bsp.h b/src/r_bsp.h index 88757cf4b..55199405a 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_data.c b/src/r_data.c index 51ed15dd6..4b7492f90 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-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_data.h b/src/r_data.h index 63772e7b0..ef5c967e5 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_defs.h b/src/r_defs.h index 7da162de7..7638dfe28 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -559,6 +559,10 @@ typedef struct // add this to the calculated texture top fixed_t rowoffset; + // per-texture offsets for UDMF + fixed_t offsetx_top, offsetx_mid, offsetx_bot; + fixed_t offsety_top, offsety_mid, offsety_bot; + // Texture indices. // We do not maintain names here. INT32 toptexture, bottomtexture, midtexture; @@ -587,7 +591,7 @@ typedef struct subsector_s { sector_t *sector; INT16 numlines; - UINT16 firstline; + UINT32 firstline; struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects size_t validcount; } subsector_t; diff --git a/src/r_draw.c b/src/r_draw.c index 601fb4bb2..b0467e4f7 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-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_draw.h b/src/r_draw.h index cb4e4482a..ea03a8e3d 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-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_draw16.c b/src/r_draw16.c index 763fd1631..2ed5a2a8e 100644 --- a/src/r_draw16.c +++ b/src/r_draw16.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_draw8.c b/src/r_draw8.c index 31abe70b8..b80a47984 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-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 8b02fb90d..faf1cdba8 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_local.h b/src/r_local.h index a5b590e5c..65fad64d0 100644 --- a/src/r_local.h +++ b/src/r_local.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_main.c b/src/r_main.c index cd5e255ed..55bb9c4ff 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -149,7 +149,7 @@ static void FlipCam2_OnChange(void); void SendWeaponPref(void); void SendWeaponPref2(void); -consvar_t cv_tailspickup = CVAR_INIT ("tailspickup", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_tailspickup = CVAR_INIT ("tailspickup", "On", CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_chasecam = CVAR_INIT ("chasecam", "On", CV_CALL, CV_OnOff, ChaseCam_OnChange); consvar_t cv_chasecam2 = CVAR_INIT ("chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChange); consvar_t cv_flipcam = CVAR_INIT ("flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange); @@ -158,8 +158,8 @@ consvar_t cv_flipcam2 = CVAR_INIT ("flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, consvar_t cv_shadow = CVAR_INIT ("shadow", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_skybox = CVAR_INIT ("skybox", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_ffloorclip = CVAR_INIT ("ffloorclip", "On", CV_SAVE, CV_OnOff, NULL); -consvar_t cv_allowmlook = CVAR_INIT ("allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL); -consvar_t cv_showhud = CVAR_INIT ("showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize); +consvar_t cv_allowmlook = CVAR_INIT ("allowmlook", "Yes", CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); +consvar_t cv_showhud = CVAR_INIT ("showhud", "Yes", CV_CALL|CV_ALLOWLUA, CV_YesNo, R_SetViewSize); consvar_t cv_translucenthud = CVAR_INIT ("translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL); consvar_t cv_translucency = CVAR_INIT ("translucency", "On", CV_SAVE, CV_OnOff, NULL); @@ -266,13 +266,13 @@ INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node) if (!node->dy) return y <= node->y ? node->dx < 0 : node->dx > 0; - x -= node->x; - y -= node->y; + fixed_t dx = (x >> 1) - (node->x >> 1); + fixed_t dy = (y >> 1) - (node->y >> 1); // Try to quickly decide by looking at sign bits. - if ((node->dy ^ node->dx ^ x ^ y) < 0) - return (node->dy ^ x) < 0; // (left is negative) - return FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x); + if ((node->dy ^ node->dx ^ dx ^ dy) < 0) + return (node->dy ^ dx) < 0; // (left is negative) + return FixedMul(dy, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, dx); } // killough 5/2/98: reformatted @@ -289,13 +289,13 @@ INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line) if (!ldy) return y <= ly ? ldx < 0 : ldx > 0; - x -= lx; - y -= ly; + fixed_t dx = (x >> 1) - (lx >> 1); + fixed_t dy = (y >> 1) - (ly >> 1); // Try to quickly decide by looking at sign bits. - if ((ldy ^ ldx ^ x ^ y) < 0) - return (ldy ^ x) < 0; // (left is negative) - return FixedMul(y, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, x); + if ((ldy ^ ldx ^ dx ^ dy) < 0) + return (ldy ^ dx) < 0; // (left is negative) + return FixedMul(dy, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, dx); } // @@ -620,7 +620,7 @@ static struct { 0, 0, - {}, {}, + {0}, {0}, false }; @@ -1092,34 +1092,12 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y) void R_SetupFrame(player_t *player) { camera_t *thiscam; - boolean chasecam = false; - - if (splitscreen && player == &players[secondarydisplayplayer] - && player != &players[consoleplayer]) - { + boolean chasecam = R_ViewpointHasChasecam(player); + + if (splitscreen && player == &players[secondarydisplayplayer] && player != &players[consoleplayer]) thiscam = &camera2; - chasecam = (cv_chasecam2.value != 0); - R_SetViewContext(VIEWCONTEXT_PLAYER2); - } else - { thiscam = &camera; - chasecam = (cv_chasecam.value != 0); - R_SetViewContext(VIEWCONTEXT_PLAYER1); - } - - if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) - chasecam = true; // force chasecam on - else if (player->spectator) // no spectator chasecam - chasecam = false; // force chasecam off - - if (chasecam && !thiscam->chase) - { - P_ResetCamera(player, thiscam); - thiscam->chase = true; - } - else if (!chasecam) - thiscam->chase = false; newview->sky = false; @@ -1348,11 +1326,37 @@ boolean R_ViewpointHasChasecam(player_t *player) { camera_t *thiscam; boolean chasecam = false; + boolean isplayer2 = (splitscreen && player == &players[secondarydisplayplayer] && player != &players[consoleplayer]); - if (splitscreen && player == &players[secondarydisplayplayer] && player != &players[consoleplayer]) + if (isplayer2) { thiscam = &camera2; chasecam = (cv_chasecam2.value != 0); + } + else + { + thiscam = &camera; + chasecam = (cv_chasecam.value != 0); + } + + if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) + chasecam = true; // force chasecam on + else if (player->spectator) // no spectator chasecam + chasecam = false; // force chasecam off + + if (chasecam && !thiscam->chase) + { + P_ResetCamera(player, thiscam); + thiscam->chase = true; + } + else if (!chasecam && thiscam->chase) + { + P_ResetCamera(player, thiscam); + thiscam->chase = false; + } + + if (isplayer2) + { R_SetViewContext(VIEWCONTEXT_PLAYER2); if (thiscam->reset) { @@ -1362,8 +1366,6 @@ boolean R_ViewpointHasChasecam(player_t *player) } else { - thiscam = &camera; - chasecam = (cv_chasecam.value != 0); R_SetViewContext(VIEWCONTEXT_PLAYER1); if (thiscam->reset) { @@ -1372,11 +1374,6 @@ boolean R_ViewpointHasChasecam(player_t *player) } } - if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) - chasecam = true; // force chasecam on - else if (player->spectator) // no spectator chasecam - chasecam = false; // force chasecam off - return chasecam; } diff --git a/src/r_main.h b/src/r_main.h index 94103ceed..f08070d0f 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patch.c b/src/r_patch.c index e771e5c94..7c561e959 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patch.h b/src/r_patch.h index 26c28e1f9..d2106a390 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index b24e065ba..3d3c6c512 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patchrotation.h b/src/r_patchrotation.h index e6bee80ed..a239ac5fa 100644 --- a/src/r_patchrotation.h +++ b/src/r_patchrotation.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_picformats.c b/src/r_picformats.c index 6aa4659b9..9aea8c6c1 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -2,8 +2,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 2005-2009 by Andrey "entryway" Budko. -// Copyright (C) 2018-2022 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019-2022 by Sonic Team Junior. +// Copyright (C) 2018-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -447,7 +447,7 @@ void *Picture_FlatConvert( for (y = 0; y < inheight; y++) for (x = 0; x < inwidth; x++) { - void *input; + void *input = NULL; size_t offs = ((y * inwidth) + x); // Read pixel diff --git a/src/r_picformats.h b/src/r_picformats.h index f3080479f..4f9637460 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2018-2022 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019-2022 by Sonic Team Junior. +// Copyright (C) 2018-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_plane.c b/src/r_plane.c index 56cf869ef..c568484b6 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-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_plane.h b/src/r_plane.h index ea793fce2..9870a43e2 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_portal.c b/src/r_portal.c index 4d4132133..e594f960a 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_portal.h b/src/r_portal.h index 687ee058f..f90f05fbc 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_segs.c b/src/r_segs.c index 681524054..facab62ab 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -49,6 +49,7 @@ fixed_t rw_distance; static INT32 rw_x, rw_stopx; static angle_t rw_centerangle; static fixed_t rw_offset; +static fixed_t rw_offset_top, rw_offset_mid, rw_offset_bot; static fixed_t rw_offset2; // for splats static fixed_t rw_scale, rw_scalestep; static fixed_t rw_midtexturemid, rw_toptexturemid, rw_bottomtexturemid; @@ -778,7 +779,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (newline) { - offsetvalue = sides[newline->sidenum[0]].rowoffset; + offsetvalue = sides[newline->sidenum[0]].rowoffset + sides[newline->sidenum[0]].offsety_mid; if (newline->flags & ML_DONTPEGBOTTOM) { skewslope = *pfloor->b_slope; // skew using bottom slope @@ -790,7 +791,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } else { - offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset; + offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset + sides[pfloor->master->sidenum[0]].offsety_mid; if (curline->linedef->flags & ML_DONTPEGBOTTOM) { skewslope = *pfloor->b_slope; // skew using bottom slope @@ -1335,7 +1336,7 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = yh; dc_texturemid = rw_midtexturemid; - dc_source = R_GetColumn(midtexture,texturecolumn); + dc_source = R_GetColumn(midtexture,texturecolumn + (rw_offset_mid>>FRACBITS)); dc_texheight = textureheight[midtexture]>>FRACBITS; //profile stuff --------------------------------------------------------- @@ -1396,7 +1397,7 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = mid; dc_texturemid = rw_toptexturemid; - dc_source = R_GetColumn(toptexture,texturecolumn); + dc_source = R_GetColumn(toptexture,texturecolumn + (rw_offset_top>>FRACBITS)); dc_texheight = textureheight[toptexture]>>FRACBITS; colfunc(); ceilingclip[rw_x] = (INT16)mid; @@ -1433,7 +1434,7 @@ static void R_RenderSegLoop (void) dc_yh = yh; dc_texturemid = rw_bottomtexturemid; dc_source = R_GetColumn(bottomtexture, - texturecolumn); + texturecolumn + (rw_offset_bot>>FRACBITS)); dc_texheight = textureheight[bottomtexture]>>FRACBITS; colfunc(); floorclip[rw_x] = (INT16)mid; @@ -1452,7 +1453,7 @@ static void R_RenderSegLoop (void) { // save texturecol // for backdrawing of masked mid texture - maskedtexturecol[rw_x] = (INT16)texturecolumn; + maskedtexturecol[rw_x] = (INT16)(texturecolumn + (rw_offset_mid>>FRACBITS)); if (maskedtextureheight != NULL) { maskedtextureheight[rw_x] = (curline->linedef->flags & ML_MIDPEG) ? @@ -1783,7 +1784,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_midtexturemid = worldtop; rw_midtextureslide = ceilingfrontslide; } - rw_midtexturemid += sidedef->rowoffset; + rw_midtexturemid += sidedef->rowoffset + sidedef->offsety_mid; ds_p->silhouette = SIL_BOTH; ds_p->sprtopclip = screenheightarray; @@ -2022,8 +2023,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) } } - rw_toptexturemid += sidedef->rowoffset; - rw_bottomtexturemid += sidedef->rowoffset; + rw_toptexturemid += sidedef->rowoffset + sidedef->offsety_top; + rw_bottomtexturemid += sidedef->rowoffset + sidedef->offsety_bot; // allocate space for masked texture tables if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors)) @@ -2266,8 +2267,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_midtexturebackslide = ceilingbackslide; } } - rw_midtexturemid += sidedef->rowoffset; - rw_midtextureback += sidedef->rowoffset; + rw_midtexturemid += sidedef->rowoffset + sidedef->offsety_mid; + rw_midtextureback += sidedef->rowoffset + sidedef->offsety_mid; maskedtexture = true; } @@ -2305,6 +2306,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) /// don't use texture offset for splats rw_offset2 = rw_offset + curline->offset; rw_offset += sidedef->textureoffset + curline->offset; + rw_offset_top = sidedef->offsetx_top; + rw_offset_mid = sidedef->offsetx_mid; + rw_offset_bot = sidedef->offsetx_bot; rw_centerangle = ANGLE_90 + viewangle - rw_normalangle; // calculate light table diff --git a/src/r_segs.h b/src/r_segs.h index 4075cc0bb..09c68b27e 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_skins.c b/src/r_skins.c index 92fd6cfae..2c031ee85 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -194,7 +194,7 @@ UINT32 R_GetSkinAvailabilities(void) return 0; } - if (unlockables[i].unlocked) + if (clientGamedata->unlocked[i]) { response |= (1 << unlockShift); } @@ -225,7 +225,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) return true; } - if (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) + if (Playing() && mapheaderinfo[gamemap-1] && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) { // Force 1. return true; @@ -242,11 +242,12 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) // Force 3. return true; } + if (playernum != -1 && players[playernum].bot) - { - //Force 4. - return true; - } + { + // Force 4. + return true; + } // We will now check if this skin is supposed to be locked or not. @@ -284,7 +285,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) else { // We want to check our global unlockables. - return (unlockables[unlockID].unlocked); + return (clientGamedata->unlocked[unlockID]); } } @@ -499,7 +500,7 @@ static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) return INT16_MAX; // not found } -static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin) +static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin, UINT8 start_spr2) { UINT16 newlastlump; UINT8 sprite2; @@ -521,7 +522,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski { newlastlump++; // load all sprite sets we are aware of... for super! - for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump); newlastlump--; @@ -529,7 +530,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski } // load all sprite sets we are aware of... for normal stuff. - for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump); if (skin->sprites[0].numframes == 0) @@ -795,7 +796,7 @@ next_token: free(buf2); // Add sprites - R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin, 0); //ST_LoadFaceGraphics(numskins); -- nah let's do this elsewhere R_FlushTranslationColormapCache(); @@ -928,7 +929,7 @@ next_token: } // Patch sprites - R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin, 0); //ST_LoadFaceGraphics(skinnum); -- nah let's do this elsewhere R_FlushTranslationColormapCache(); @@ -941,3 +942,149 @@ next_token: #undef HUDNAMEWRITE #undef SYMBOLCONVERT + +static UINT16 W_CheckForEitherSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) +{ + UINT16 i; + const char *S_SKIN = "S_SKIN"; + const char *P_SKIN = "P_SKIN"; + lumpinfo_t *lump_p; + + // scan forward, start at + if (startlump < wadfiles[wadid]->numlumps) + { + lump_p = wadfiles[wadid]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name,S_SKIN,6)==0 || memcmp(lump_p->name,P_SKIN,6)==0) + return i; + } + return INT16_MAX; // not found +} + +static void R_RefreshSprite2ForWad(UINT16 wadnum, UINT8 start_spr2) +{ + UINT16 lump, lastlump = 0; + char *buf; + char *buf2; + char *stoken; + char *value; + size_t size; + skin_t *skin; + boolean noskincomplain; + + // + // search for all skin patch markers in pwad + // + + while ((lump = W_CheckForEitherSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) + { + INT32 skinnum = 0; + + // advance by default + lastlump = lump + 1; + + buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + // for strtok + buf2 = malloc(size+1); + if (!buf2) + I_Error("R_RefreshSprite2ForWad: No more free memory\n"); + M_Memcpy(buf2,buf,size); + buf2[size] = '\0'; + + skin = NULL; + noskincomplain = false; + + /* + Parse. Has more phases than the parser in R_AddSkins because it needs to have the patching name first (no default skin name is acceptible for patching, unlike skin creation) + */ + + stoken = strtok(buf2, "\r\n= "); + while (stoken) + { + if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#'))// skip comments + { + stoken = strtok(NULL, "\r\n"); // skip end of line + goto next_token; // find the real next token + } + + value = strtok(NULL, "\r\n= "); + + if (!value) + I_Error("R_RefreshSprite2ForWad: syntax error in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + + if (!stricmp(stoken, "name")) + { + strlwr(value); + skinnum = R_SkinAvailable(value); + if (skinnum != -1) + skin = &skins[skinnum]; + else + { + CONS_Debug(DBG_SETUP, "R_RefreshSprite2ForWad: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + noskincomplain = true; + } + } + + if (!skin) + break; + +next_token: + stoken = strtok(NULL, "\r\n= "); + } + free(buf2); + + if (!skin) // Didn't include a name parameter? What a waste. + { + if (!noskincomplain) + CONS_Debug(DBG_SETUP, "R_RefreshSprite2ForWad: no skin name given in P_SKIN lump #%d (WAD %s)\n", lump, wadfiles[wadnum]->filename); + continue; + } + + // Update sprites, in the range of (start_spr2 - free_spr2-1) + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin, start_spr2); + //R_FlushTranslationColormapCache(); // I don't think this is needed for what we're doing? + } +} + +static playersprite_t old_spr2 = SPR2_FIRSTFREESLOT; +void R_RefreshSprite2(void) +{ + // Sprite2s being defined by custom wads can create situations where + // a custom character might want to add support, but due to load order, + // might not be defined in time. + + // The trick where you load characters then level packs to keep savedata + // in particular will practically garantuee a level pack can NEVER add custom animations, + // because custom character's Sprite2s will not be added. + + // So, go through every file, and reload the sprite2s that were added. + + INT32 i; + + if (old_spr2 > free_spr2) + { +#ifdef PARANOIA + I_Error("R_RefreshSprite2: old_spr2 is too high?! (old_spr2: %d, free_spr2: %d)\n", old_spr2, free_spr2); +#else + // Just silently fix + old_spr2 = free_spr2; +#endif + } + + if (old_spr2 == free_spr2) + { + // No sprite2s were added since the last time we did freeslots. + return; + } + + for (i = 0; i < numwadfiles; i++) + { + R_RefreshSprite2ForWad(i, old_spr2); + } + + // Update previous value. + old_spr2 = free_spr2; +} diff --git a/src/r_skins.h b/src/r_skins.h index aeaa9f3e0..082b690dd 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -100,4 +100,6 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile); UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player); +void R_RefreshSprite2(void); + #endif //__R_SKINS__ diff --git a/src/r_sky.c b/src/r_sky.c index e21b7cbf1..c47029f0b 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_sky.h b/src/r_sky.h index 31c821d22..012f47d23 100644 --- a/src/r_sky.h +++ b/src/r_sky.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_splats.c b/src/r_splats.c index a58cfe536..72bfe74b3 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-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,6 +11,7 @@ /// \brief Floor splats #include "r_draw.h" +#include "r_fps.h" #include "r_main.h" #include "r_splats.h" #include "r_bsp.h" @@ -185,7 +186,7 @@ void R_DrawFloorSplat(vissprite_t *spr) splat.scale = FixedMul(splat.scale, ((skin_t *)mobj->skin)->highresscale); if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) - splatangle = spr->centerangle; + splatangle = mobj->angle; else splatangle = spr->viewpoint.angle; @@ -209,8 +210,8 @@ void R_DrawFloorSplat(vissprite_t *spr) xoffset = FixedMul(leftoffset, splat.xscale); yoffset = FixedMul(topoffset, splat.yscale); - x = spr->gx; - y = spr->gy; + x = mobj->x; + y = mobj->y; w = (splat.width * splat.xscale); h = (splat.height * splat.yscale); @@ -263,8 +264,8 @@ void R_DrawFloorSplat(vissprite_t *spr) // Translate for (i = 0; i < 4; i++) { - tr_x = rotated[i].x + x; - tr_y = rotated[i].y + y; + tr_x = rotated[i].x + mobj->x; + tr_y = rotated[i].y + mobj->y; if (splat.slope) { @@ -292,8 +293,8 @@ void R_DrawFloorSplat(vissprite_t *spr) tr_y = v3d->y - spr->viewpoint.y; // rotation around vertical y axis - rot_x = FixedMul(tr_x, sa) - FixedMul(tr_y, ca); - rot_y = FixedMul(tr_x, ca) + FixedMul(tr_y, sa); + rot_x = FixedMul(tr_x - (mobj->x - x), sa) - FixedMul(tr_y - (mobj->y - y), ca); + rot_y = FixedMul(tr_x - (mobj->x - x), ca) + FixedMul(tr_y - (mobj->y - y), sa); rot_z = v3d->z - spr->viewpoint.z; if (rot_y < FRACUNIT) diff --git a/src/r_splats.h b/src/r_splats.h index ec6885e26..dcae2789c 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_state.h b/src/r_state.h index 69989e7ac..b36697f73 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_textures.c b/src/r_textures.c index 98c2788a2..69e64074d 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-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_textures.h b/src/r_textures.h index b9b48da8c..4a3c10b9e 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_things.c b/src/r_things.c index fed873fd6..89b9fe07e 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-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1324,6 +1324,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, if (trans >= 9) return; scalemul = FixedMul(FRACUNIT - floordiff/640, scale); + if ((thing->scale != thing->old_scale) && (thing->scale >= FRACUNIT/1024)) // Interpolate shadows when scaling mobjs + scalemul = FixedMul(scalemul, FixedDiv(interp.scale, thing->scale)); patch = W_CachePatchName("DSHADOW", PU_SPRITE); xscale = FixedDiv(projection, tz); @@ -1477,7 +1479,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; - INT32 dispoffset = thing->info->dispoffset; + INT32 dispoffset = thing->dispoffset; //SoM: 3/17/2000 fixed_t gz = 0, gzt = 0; @@ -1785,7 +1787,11 @@ static void R_ProjectSprite(mobj_t *thing) range++; // fencepost problem - scalestep = ((yscale2 - yscale)/range) ?: 1; + // Compatibility with MSVC - SSNTails + scalestep = ((yscale2 - yscale) / range); + if (!scalestep) + scalestep = 1; + xscale = FixedDiv(range<target; - interpmobjstate_t casterinterp = {}; + interpmobjstate_t casterinterp = { 0 }; // MSVC compatibility - SSNTails if (R_UsingFrameInterpolation() && !paused) { diff --git a/src/r_things.h b/src/r_things.h index 35eeb9ce1..22a37a0ea 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -212,7 +212,7 @@ typedef struct vissprite_s INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; - INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing + INT32 dispoffset; // copy of mobj->dispoffset, affects ordering but not drawing } vissprite_t; extern UINT32 visspritecount; diff --git a/src/s_sound.c b/src/s_sound.c index f28a77a80..ada1a0fd2 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -289,8 +289,8 @@ void S_RegisterSoundStuff(void) CV_RegisterVar(&cv_miditimiditypath); #endif - COM_AddCommand("tunes", Command_Tunes_f); - COM_AddCommand("restartaudio", Command_RestartAudio_f); + COM_AddCommand("tunes", Command_Tunes_f, COM_LUA); + COM_AddCommand("restartaudio", Command_RestartAudio_f, COM_LUA); } static void SetChannelsNum(void) @@ -1692,6 +1692,7 @@ UINT8 soundtestpage = 1; // boolean S_PrepareSoundTest(void) { + gamedata_t *data = clientGamedata; musicdef_t *def; INT32 pos = numsoundtestdefs = 0; @@ -1717,9 +1718,9 @@ boolean S_PrepareSoundTest(void) if (!(def->soundtestpage & soundtestpage)) continue; soundtestdefs[pos++] = def; - if (def->soundtestcond > 0 && !(mapvisited[def->soundtestcond-1] & MV_BEATEN)) + if (def->soundtestcond > 0 && !(data->mapvisited[def->soundtestcond-1] & MV_BEATEN)) continue; - if (def->soundtestcond < 0 && !M_Achieved(-1-def->soundtestcond)) + if (def->soundtestcond < 0 && !M_Achieved(-1-def->soundtestcond, data)) continue; def->allowed = true; } diff --git a/src/s_sound.h b/src/s_sound.h index 6223c4fdb..288859c8d 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/screen.c b/src/screen.c index e984f9ee5..f8af4c504 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -82,7 +82,7 @@ CV_PossibleValue_t cv_renderer_t[] = { {0, NULL} }; -consvar_t cv_renderer = CVAR_INIT ("renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_ChangeRenderer); +consvar_t cv_renderer = CVAR_INIT ("renderer", "Software", CV_SAVE|CV_CALL, cv_renderer_t, SCR_ChangeRenderer); static void SCR_ChangeFullscreen(void); @@ -401,7 +401,6 @@ void SCR_SetDefaultMode(void) // remember the default screen size CV_SetValue(&cv_scr_width, vid.width); CV_SetValue(&cv_scr_height, vid.height); - CV_SetValue(&cv_scr_depth, vid.bpp*8); } // Change fullscreen on/off according to cv_fullscreen @@ -622,7 +621,13 @@ void SCR_ClosedCaptions(void) y = basey-((i + 2)*10); if (closedcaptions[i].b) - y -= (closedcaptions[i].b--)*vid.dupy; + { + y -= closedcaptions[i].b * vid.dupy; + if (renderisnewtic) + { + closedcaptions[i].b--; + } + } if (closedcaptions[i].t < CAPTIONFADETICS) flags |= (((CAPTIONFADETICS-closedcaptions[i].t)/2)*V_10TRANS); diff --git a/src/screen.h b/src/screen.h index add048b25..19103b0df 100644 --- a/src/screen.h +++ b/src/screen.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index d79dde766..c20265ed1 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -39,46 +39,46 @@ {61BA7D3C-F77D-4D31-B718-1177FE482CF2} Win32Proj Srb2SDL - 10.0.16299.0 + 10.0 Srb2Win - v140 + v143 true - v141 + v143 true true - v140 + v143 false true - v141 + v143 false true true - v140 + v143 true - v141 + v143 true true - v140 + v143 false true - v141 + v143 false true true @@ -134,6 +134,9 @@ <_ProjectFileVersion>10.0.30319.1 false + + $(ProjectName)_Debug + ProgramDatabase @@ -154,6 +157,26 @@ setupapi.lib;winmm.lib;imm32.lib;version.lib;ole32.lib;advapi32.lib;shell32.lib;gdi32.lib;oleaut32.lib;uuid.lib;%(AdditionalDependencies) + + + Default + false + 4244;4267;4146 + true + false + stdcpp17 + + + + + stdcpp17 + + + + + 4244;4267;4146;4003 + + {72b01aca-7a1a-4f7b-acef-2607299cf052} @@ -246,11 +269,13 @@ + + @@ -264,6 +289,7 @@ + @@ -272,6 +298,7 @@ + @@ -286,6 +313,7 @@ + @@ -403,11 +431,13 @@ true + + @@ -429,6 +459,7 @@ + @@ -438,6 +469,7 @@ + @@ -464,6 +496,7 @@ true + @@ -478,7 +511,6 @@ - @@ -507,7 +539,7 @@ true - + @@ -524,4 +556,4 @@ - + \ No newline at end of file diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index 4d2532ca4..eb37ce9da 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -144,7 +144,6 @@ D_Doom - D_Doom @@ -511,6 +510,21 @@ R_Rend + + LUA + + + I_Interface + + + R_Rend + + + P_Play + + + M_Misc + @@ -625,7 +639,6 @@ D_Doom - D_Doom @@ -821,9 +834,6 @@ M_Misc - - M_Misc - O_Other @@ -965,9 +975,6 @@ SDLApp - - SDLApp - SDLApp @@ -1023,10 +1030,28 @@ R_Rend + + LUA + + + SDLApp + + + I_Interface + + + R_Rend + + + P_Play + + + M_Misc + SDLApp - + \ No newline at end of file diff --git a/src/sdl/Srb2SDL-vc9.vcproj b/src/sdl/Srb2SDL-vc9.vcproj deleted file mode 100644 index 95f035267..000000000 --- a/src/sdl/Srb2SDL-vc9.vcproj +++ /dev/null @@ -1,6021 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/sdl/Srb2SDL.dsp b/src/sdl/Srb2SDL.dsp deleted file mode 100644 index 9f6dd7b33..000000000 --- a/src/sdl/Srb2SDL.dsp +++ /dev/null @@ -1,1049 +0,0 @@ -# Microsoft Developer Studio Project File - Name="Srb2SDL" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=Srb2SDL - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "Srb2SDL.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "Srb2SDL.mak" CFG="Srb2SDL - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Srb2SDL - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Srb2SDL - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Srb2SDL - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\bin\VC\Release\SDL" -# PROP Intermediate_Dir "..\..\objs\VC\Release\SDL" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -MTL=midl.exe -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G5 /W3 /GX /Zi /Ot /Og /Oi /Op /Oy /Ob1 /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "NDEBUG" /D "SDLMAIN" /D "NO_STDIO_REDIRECT" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "HAVE_SDL" /D "HWRENDER" /D "HW3SOUND" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GF /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -# SUBTRACT RSC /x -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /o"..\..\objs\SDL\Release\SRB2.bsc" -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 SDL.lib SDL_mixer.lib user32.lib advapi32.lib ws2_32.lib /nologo /subsystem:windows /pdb:"C:\srb2demo2\srb2sdl.pdb" /debug /machine:I386 /out:"C:\srb2demo2\srb2sdl.exe" -# SUBTRACT LINK32 /profile /pdb:none /incremental:yes - -!ELSEIF "$(CFG)" == "Srb2SDL - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\bin\VC\Debug\SDL" -# PROP Intermediate_Dir "..\..\objs\VC\Debug\SDL" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -MTL=midl.exe -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /G6 /W4 /WX /Gm /GX /ZI /Od /Op /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "_DEBUG" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "HAVE_SDL" /D "HWRENDER" /D "HW3SOUND" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GZ /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -# SUBTRACT RSC /x -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /o"..\..\objs\SDL\Debug\SRB2.bsc" -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 SDL.lib SDL_mixer.lib user32.lib advapi32.lib ws2_32.lib /nologo /subsystem:console /pdb:"C:\srb2demo2\srb2sdldebug.pdb" /debug /machine:I386 /out:"C:\srb2demo2\srb2sdldebug.exe" /pdbtype:sept -# SUBTRACT LINK32 /pdb:none - -!ENDIF - -# Begin Target - -# Name "Srb2SDL - Win32 Release" -# Name "Srb2SDL - Win32 Debug" -# Begin Group "SDLapp" - -# PROP Default_Filter "" -# Begin Group "filter" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\filter\filters.c -# End Source File -# Begin Source File - -SOURCE=.\filter\filters.h -# End Source File -# Begin Source File - -SOURCE=.\filter\hq2x.c -# End Source File -# Begin Source File - -SOURCE=.\filter\hq2x.h -# End Source File -# Begin Source File - -SOURCE=.\filter\interp.h -# End Source File -# Begin Source File - -SOURCE=.\filter\lq2x.c -# End Source File -# Begin Source File - -SOURCE=.\filter\lq2x.h -# End Source File -# End Group -# Begin Source File - -SOURCE=.\dosstr.c -# End Source File -# Begin Source File - -SOURCE=.\endtxt.c -# End Source File -# Begin Source File - -SOURCE=.\endtxt.h -# End Source File -# Begin Source File - -SOURCE=..\filesrch.c -# End Source File -# Begin Source File - -SOURCE=..\filesrch.h -# End Source File -# Begin Source File - -SOURCE=.\hwsym_sdl.c -# End Source File -# Begin Source File - -SOURCE=.\hwsym_sdl.h -# End Source File -# Begin Source File - -SOURCE=.\i_cdmus.c -# End Source File -# Begin Source File - -SOURCE=.\i_main.c -# End Source File -# Begin Source File - -SOURCE=.\i_net.c -# End Source File -# Begin Source File - -SOURCE=.\i_sound.c -# End Source File -# Begin Source File - -SOURCE=.\i_system.c -# End Source File -# Begin Source File - -SOURCE=.\i_video.c -# End Source File -# Begin Source File - -SOURCE=.\IMG_xpm.c -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=.\ogl_sdl.c -# End Source File -# Begin Source File - -SOURCE=.\ogl_sdl.h -# End Source File -# Begin Source File - -SOURCE=..\hardware\r_opengl\r_opengl.c -# End Source File -# Begin Source File - -SOURCE=..\hardware\r_opengl\r_opengl.h -# End Source File -# Begin Source File - -SOURCE=.\SDL_icon.xpm -# End Source File -# Begin Source File - -SOURCE=.\SDL_main\SDL_win32_main.c - -!IF "$(CFG)" == "Srb2SDL - Win32 Release" - -!ELSEIF "$(CFG)" == "Srb2SDL - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\sdlmain.h -# End Source File -# Begin Source File - -SOURCE=..\win32\Srb2win.rc -# End Source File -# Begin Source File - -SOURCE=..\win32\win_dbg.c -# End Source File -# Begin Source File - -SOURCE=..\win32\win_dbg.h -# End Source File -# Begin Source File - -SOURCE=..\win32\win_main.h -# End Source File -# End Group -# Begin Group "A_Asm" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\p5prof.h -# End Source File -# Begin Source File - -SOURCE=..\tmap.nas - -!IF "$(CFG)" == "Srb2SDL - Win32 Release" - -# PROP Ignore_Default_Tool 1 -# Begin Custom Build - Compiling $(InputName).nas with NASM... -IntDir=.\..\..\objs\VC\Release\SDL -InputPath=..\tmap.nas -InputName=tmap - -"$(IntDir)/$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - nasm -g -o $(IntDir)/$(InputName).obj -f win32 $(InputPath) - -# End Custom Build - -!ELSEIF "$(CFG)" == "Srb2SDL - Win32 Debug" - -# PROP Ignore_Default_Tool 1 -# Begin Custom Build - Compiling $(InputName).nas with NASM... -IntDir=.\..\..\objs\VC\Debug\SDL -InputPath=..\tmap.nas -InputName=tmap - -"$(IntDir)/$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - nasm -g -o $(IntDir)/$(InputName).obj -f win32 $(InputPath) - -# End Custom Build - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\tmap_mmx.nas - -!IF "$(CFG)" == "Srb2SDL - Win32 Release" - -# PROP Ignore_Default_Tool 1 -# Begin Custom Build - Compiling $(InputName).nas with NASM... -IntDir=.\..\..\objs\VC\Release\SDL -InputPath=..\tmap_mmx.nas -InputName=tmap_mmx - -"$(IntDir)/$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - nasm -g -o $(IntDir)/$(InputName).obj -f win32 $(InputPath) - -# End Custom Build - -!ELSEIF "$(CFG)" == "Srb2SDL - Win32 Debug" - -# PROP Ignore_Default_Tool 1 -# Begin Custom Build - Compiling $(InputName).nas with NASM... - -IntDir=.\..\..\objs\VC\Debug\SDL -InputPath=..\tmap_mmx.nas -InputName=tmap_mmx - -"$(IntDir)/$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - nasm -g -o $(IntDir)/$(InputName).obj -f win32 $(InputPath) - -# End Custom Build - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\tmap_vc.nas - -!IF "$(CFG)" == "Srb2SDL - Win32 Release" - -# Begin Custom Build - Compiling $(InputName).nas with NASM... -IntDir=.\..\..\objs\VC\Release\SDL -InputPath=..\tmap_vc.nas -InputName=tmap_vc - -"$(IntDir)/$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - nasm -g -o $(IntDir)/$(InputName).obj -f win32 $(InputPath) - -# End Custom Build - -!ELSEIF "$(CFG)" == "Srb2SDL - Win32 Debug" - -# Begin Custom Build - Compiling $(InputName).nas with NASM... -IntDir=.\..\..\objs\VC\Debug\SDL -InputPath=..\tmap_vc.nas -InputName=tmap_vc - -"$(IntDir)/$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - nasm -g -o $(IntDir)/$(InputName).obj -f win32 $(InputPath) - -# End Custom Build - -!ENDIF - -# End Source File -# End Group -# Begin Group "D_Doom" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\comptime.c -# End Source File -# Begin Source File - -SOURCE=..\d_clisrv.c -# End Source File -# Begin Source File - -SOURCE=..\d_clisrv.h -# End Source File -# Begin Source File - -SOURCE=..\d_event.h -# End Source File -# Begin Source File - -SOURCE=..\d_main.c -# End Source File -# Begin Source File - -SOURCE=..\d_main.h -# End Source File -# Begin Source File - -SOURCE=..\d_net.c -# End Source File -# Begin Source File - -SOURCE=..\d_net.h -# End Source File -# Begin Source File - -SOURCE=..\d_netcmd.c -# End Source File -# Begin Source File - -SOURCE=..\d_netcmd.h -# End Source File -# Begin Source File - -SOURCE=..\d_netfil.c -# End Source File -# Begin Source File - -SOURCE=..\d_netfil.h -# End Source File -# Begin Source File - -SOURCE=..\d_player.h -# End Source File -# Begin Source File - -SOURCE=..\d_think.h -# End Source File -# Begin Source File - -SOURCE=..\d_ticcmd.h -# End Source File -# Begin Source File - -SOURCE=..\dehacked.c -# End Source File -# Begin Source File - -SOURCE=..\dehacked.h -# End Source File -# Begin Source File - -SOURCE=..\doomdata.h -# End Source File -# Begin Source File - -SOURCE=..\doomdef.h -# End Source File -# Begin Source File - -SOURCE=..\doomstat.h -# End Source File -# Begin Source File - -SOURCE=..\doomtype.h -# End Source File -# Begin Source File - -SOURCE=..\z_zone.c -# End Source File -# Begin Source File - -SOURCE=..\z_zone.h -# End Source File -# End Group -# Begin Group "F_Frame" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\f_finale.c -# End Source File -# Begin Source File - -SOURCE=..\f_finale.h -# End Source File -# Begin Source File - -SOURCE=..\f_wipe.c -# End Source File -# End Group -# Begin Group "G_Game" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\g_game.c -# End Source File -# Begin Source File - -SOURCE=..\g_game.h -# End Source File -# Begin Source File - -SOURCE=..\g_input.c -# End Source File -# Begin Source File - -SOURCE=..\g_input.h -# End Source File -# Begin Source File - -SOURCE=..\g_state.h -# End Source File -# End Group -# Begin Group "H_Hud" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\am_map.c -# End Source File -# Begin Source File - -SOURCE=..\am_map.h -# End Source File -# Begin Source File - -SOURCE=..\command.c -# End Source File -# Begin Source File - -SOURCE=..\command.h -# End Source File -# Begin Source File - -SOURCE=..\console.c -# End Source File -# Begin Source File - -SOURCE=..\console.h -# End Source File -# Begin Source File - -SOURCE=..\hu_stuff.c -# End Source File -# Begin Source File - -SOURCE=..\hu_stuff.h -# End Source File -# Begin Source File - -SOURCE=..\st_stuff.c -# End Source File -# Begin Source File - -SOURCE=..\st_stuff.h -# End Source File -# Begin Source File - -SOURCE=..\y_inter.c -# End Source File -# Begin Source File - -SOURCE=..\y_inter.h -# End Source File -# End Group -# Begin Group "Hw_Hardware" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\hardware\hw3dsdrv.h -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw3sound.c -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw3sound.h -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_bsp.c -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_cache.c -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_data.h -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_defs.h -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_dll.h -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_draw.c -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_drv.h -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_glob.h -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_light.c -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_light.h -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_main.c -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_main.h -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_md2.c -# End Source File -# Begin Source File - -SOURCE=..\hardware\hw_md2.h -# End Source File -# Begin Source File - -SOURCE=..\hardware\hws_data.h -# End Source File -# End Group -# Begin Group "I_Interface" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\byteptr.h -# End Source File -# Begin Source File - -SOURCE=..\i_joy.h -# End Source File -# Begin Source File - -SOURCE=..\i_net.h -# End Source File -# Begin Source File - -SOURCE=..\i_sound.h -# End Source File -# Begin Source File - -SOURCE=..\i_system.h -# End Source File -# Begin Source File - -SOURCE=..\i_tcp.c -# End Source File -# Begin Source File - -SOURCE=..\i_tcp.h -# End Source File -# Begin Source File - -SOURCE=..\i_video.h -# End Source File -# Begin Source File - -SOURCE=..\keys.h -# End Source File -# Begin Source File - -SOURCE=..\mserv.c -# End Source File -# Begin Source File - -SOURCE=..\mserv.h -# End Source File -# End Group -# Begin Group "M_Misc" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\m_argv.c -# End Source File -# Begin Source File - -SOURCE=..\m_argv.h -# End Source File -# Begin Source File - -SOURCE=..\m_bbox.c -# End Source File -# Begin Source File - -SOURCE=..\m_bbox.h -# End Source File -# Begin Source File - -SOURCE=..\m_cheat.c -# End Source File -# Begin Source File - -SOURCE=..\m_cheat.h -# End Source File -# Begin Source File - -SOURCE=..\m_dllist.h -# End Source File -# Begin Source File - -SOURCE=..\m_fixed.c -# End Source File -# Begin Source File - -SOURCE=..\m_fixed.h -# End Source File -# Begin Source File - -SOURCE=..\m_menu.c -# End Source File -# Begin Source File - -SOURCE=..\m_menu.h -# End Source File -# Begin Source File - -SOURCE=..\m_misc.c -# End Source File -# Begin Source File - -SOURCE=..\m_misc.h -# End Source File -# Begin Source File - -SOURCE=..\m_queue.c -# End Source File -# Begin Source File - -SOURCE=..\m_queue.h -# End Source File -# Begin Source File - -SOURCE=..\m_random.c -# End Source File -# Begin Source File - -SOURCE=..\m_random.h -# End Source File -# Begin Source File - -SOURCE=..\m_swap.h -# End Source File -# Begin Source File - -SOURCE=..\string.c -# End Source File -# End Group -# Begin Group "P_Play" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\info.c -# End Source File -# Begin Source File - -SOURCE=..\info.h -# End Source File -# Begin Source File - -SOURCE=..\p_ceilng.c -# End Source File -# Begin Source File - -SOURCE=..\p_enemy.c -# End Source File -# Begin Source File - -SOURCE=..\p_fab.c -# End Source File -# Begin Source File - -SOURCE=..\p_floor.c -# End Source File -# Begin Source File - -SOURCE=..\p_inter.c -# End Source File -# Begin Source File - -SOURCE=..\p_lights.c -# End Source File -# Begin Source File - -SOURCE=..\p_local.h -# End Source File -# Begin Source File - -SOURCE=..\p_map.c -# End Source File -# Begin Source File - -SOURCE=..\p_maputl.c -# End Source File -# Begin Source File - -SOURCE=..\p_maputl.h -# End Source File -# Begin Source File - -SOURCE=..\p_mobj.c -# End Source File -# Begin Source File - -SOURCE=..\p_mobj.h -# End Source File -# Begin Source File - -SOURCE=..\p_polyobj.c -# End Source File -# Begin Source File - -SOURCE=..\p_polyobj.h -# End Source File -# Begin Source File - -SOURCE=..\p_pspr.h -# End Source File -# Begin Source File - -SOURCE=..\p_saveg.c -# End Source File -# Begin Source File - -SOURCE=..\p_saveg.h -# End Source File -# Begin Source File - -SOURCE=..\p_setup.c -# End Source File -# Begin Source File - -SOURCE=..\p_setup.h -# End Source File -# Begin Source File - -SOURCE=..\p_sight.c -# End Source File -# Begin Source File - -SOURCE=..\p_spec.c -# End Source File -# Begin Source File - -SOURCE=..\p_spec.h -# End Source File -# Begin Source File - -SOURCE=..\p_telept.c -# End Source File -# Begin Source File - -SOURCE=..\p_tick.c -# End Source File -# Begin Source File - -SOURCE=..\p_tick.h -# End Source File -# Begin Source File - -SOURCE=..\p_user.c -# End Source File -# Begin Source File - -SOURCE=..\tables.c -# End Source File -# Begin Source File - -SOURCE=..\tables.h -# End Source File -# End Group -# Begin Group "R_Rend" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\r_bsp.c -# End Source File -# Begin Source File - -SOURCE=..\r_bsp.h -# End Source File -# Begin Source File - -SOURCE=..\r_data.c -# End Source File -# Begin Source File - -SOURCE=..\r_data.h -# End Source File -# Begin Source File - -SOURCE=..\r_defs.h -# End Source File -# Begin Source File - -SOURCE=..\r_draw.c -# End Source File -# Begin Source File - -SOURCE=..\r_draw.h -# End Source File -# Begin Source File - -SOURCE=..\r_draw16.c -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=..\r_draw8.c -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=..\r_local.h -# End Source File -# Begin Source File - -SOURCE=..\r_main.c -# End Source File -# Begin Source File - -SOURCE=..\r_main.h -# End Source File -# Begin Source File - -SOURCE=..\r_plane.c -# End Source File -# Begin Source File - -SOURCE=..\r_plane.h -# End Source File -# Begin Source File - -SOURCE=..\r_segs.c -# End Source File -# Begin Source File - -SOURCE=..\r_segs.h -# End Source File -# Begin Source File - -SOURCE=..\r_sky.c -# End Source File -# Begin Source File - -SOURCE=..\r_sky.h -# End Source File -# Begin Source File - -SOURCE=..\r_splats.c -# End Source File -# Begin Source File - -SOURCE=..\r_splats.h -# End Source File -# Begin Source File - -SOURCE=..\r_state.h -# End Source File -# Begin Source File - -SOURCE=..\r_things.c -# End Source File -# Begin Source File - -SOURCE=..\r_things.h -# End Source File -# Begin Source File - -SOURCE=..\screen.c -# End Source File -# Begin Source File - -SOURCE=..\screen.h -# End Source File -# Begin Source File - -SOURCE=..\v_video.c -# End Source File -# Begin Source File - -SOURCE=..\v_video.h -# End Source File -# End Group -# Begin Group "S_Sounds" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\s_sound.c -# End Source File -# Begin Source File - -SOURCE=..\s_sound.h -# End Source File -# Begin Source File - -SOURCE=..\sounds.c -# End Source File -# Begin Source File - -SOURCE=..\sounds.h -# End Source File -# End Group -# Begin Group "W_Wad" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\lzf.c -# End Source File -# Begin Source File - -SOURCE=..\lzf.h -# End Source File -# Begin Source File - -SOURCE=..\md5.c -# End Source File -# Begin Source File - -SOURCE=..\md5.h -# End Source File -# Begin Source File - -SOURCE=..\w_wad.c -# End Source File -# Begin Source File - -SOURCE=..\w_wad.h -# End Source File -# End Group -# Begin Group "Docs" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\doc\copying -# End Source File -# Begin Source File - -SOURCE=..\..\doc\faq.txt -# End Source File -# Begin Source File - -SOURCE=..\..\readme.txt -# End Source File -# Begin Source File - -SOURCE=..\..\doc\source.txt -# End Source File -# End Group -# Begin Source File - -SOURCE=..\win32\Srb2win.ico -# End Source File -# End Target -# End Project diff --git a/src/sdl/Srb2SDL.dsw b/src/sdl/Srb2SDL.dsw deleted file mode 100644 index 4f8f7bdce..000000000 --- a/src/sdl/Srb2SDL.dsw +++ /dev/null @@ -1,74 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "Srb2SDL"=.\Srb2SDL.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libpng - End Project Dependency - Begin Project Dependency - Project_Dep_Name zlib - End Project Dependency -}}} - -############################################################################### - -Project: "libpng"="..\..\libs\libpng-src\projects\visualc6\libpng.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name zlib - End Project Dependency -}}} - -############################################################################### - -Project: "s_openal"=..\hardware\s_openal\s_openal.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "zlib"=..\..\libs\zlib\projects\visualc6\zlib.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 818d0f0c4..66eeffa30 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -5,7 +5,7 @@ // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2022 by Sonic Team Junior. +// Copyright (C) 2014-2023 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -2352,7 +2352,7 @@ void I_Quit(void) #ifndef NONET D_SaveBan(); // save the ban list #endif - G_SaveGameData(); // Tails 12-08-2002 + G_SaveGameData(clientGamedata); // Tails 12-08-2002 //added:16-02-98: when recording a demo, should exit using 'q' key, // but sometimes we forget and use 'F10'.. so save here too. @@ -2436,7 +2436,7 @@ void I_Error(const char *error, ...) if (errorcount == 8) { M_SaveConfig(NULL); - G_SaveGameData(); + G_SaveGameData(clientGamedata); } if (errorcount > 20) { @@ -2469,7 +2469,7 @@ void I_Error(const char *error, ...) #ifndef NONET D_SaveBan(); // save the ban list #endif - G_SaveGameData(); // Tails 12-08-2002 + G_SaveGameData(clientGamedata); // Tails 12-08-2002 // Shutdown. Here might be other errors. if (demorecording) @@ -2962,8 +2962,7 @@ static long get_entry(const char* name, const char* buf) } #endif -// quick fix for compil -UINT32 I_GetFreeMem(UINT32 *total) +size_t I_GetFreeMem(size_t *total) { #ifdef FREEBSD struct vmmeter sum; @@ -3011,14 +3010,14 @@ UINT32 I_GetFreeMem(UINT32 *total) info.dwLength = sizeof (MEMORYSTATUS); GlobalMemoryStatus( &info ); if (total) - *total = (UINT32)info.dwTotalPhys; - return (UINT32)info.dwAvailPhys; + *total = (size_t)info.dwTotalPhys; + return (size_t)info.dwAvailPhys; #elif defined (__linux__) /* Linux */ char buf[1024]; char *memTag; - UINT32 freeKBytes; - UINT32 totalKBytes; + size_t freeKBytes; + size_t totalKBytes; INT32 n; INT32 meminfo_fd = -1; long Cached; @@ -3049,7 +3048,7 @@ UINT32 I_GetFreeMem(UINT32 *total) } memTag += sizeof (MEMTOTAL); - totalKBytes = atoi(memTag); + totalKBytes = (size_t)atoi(memTag); if ((memTag = strstr(buf, MEMAVAILABLE)) == NULL) { diff --git a/src/sdl/i_threads.c b/src/sdl/i_threads.c index a182ae197..c05936072 100644 --- a/src/sdl/i_threads.c +++ b/src/sdl/i_threads.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by James R. +// Copyright (C) 2020-2023 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 6e971a5d8..d2fbb9006 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -5,7 +5,7 @@ // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2022 by Sonic Team Junior. +// Copyright (C) 2014-2023 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -102,8 +102,10 @@ rendermode_t chosenrendermode = render_none; // set by command line arguments boolean highcolor = false; +static void VidWaitChanged(void); + // synchronize page flipping with screen refresh -consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE | CV_CALL, CV_OnOff, VidWaitChanged); static consvar_t cv_stretch = CVAR_INIT ("stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL); static consvar_t cv_alwaysgrabmouse = CVAR_INIT ("alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL); @@ -274,6 +276,22 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool } } +static void VidWaitChanged(void) +{ + if (renderer && rendermode == render_soft) + { +#if SDL_VERSION_ATLEAST(2, 0, 18) + SDL_RenderSetVSync(renderer, cv_vidwait.value ? 1 : 0); +#endif + } +#ifdef HWRENDER + else if (rendermode == render_opengl && sdlglcontext != NULL && SDL_GL_GetCurrentContext() == sdlglcontext) + { + SDL_GL_SetSwapInterval(cv_vidwait.value ? 1 : 0); + } +#endif +} + static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code) { if (code >= SDL_SCANCODE_A && code <= SDL_SCANCODE_Z) @@ -1476,15 +1494,19 @@ static SDL_bool Impl_CreateContext(void) int flags = 0; // Use this to set SDL_RENDERER_* flags now if (usesdl2soft) flags |= SDL_RENDERER_SOFTWARE; -#if 0 - // This shit is BROKEN. - // - The version of SDL we're using cannot toggle VSync at runtime. We'll need a new SDL version implemented to have this work properly. - // - cv_vidwait is initialized before config is loaded, so it's forced to default value at runtime, and forced off when switching. The config loading code would need restructured. - // - With both this & frame interpolation on, I_FinishUpdate takes x10 longer. At this point, it is simpler to use a standard FPS cap. - // So you can probably guess why I'm kinda over this, I'm just disabling it. else if (cv_vidwait.value) + { +#if SDL_VERSION_ATLEAST(2, 0, 18) + // If SDL is new enough, we can turn off vsync later. flags |= SDL_RENDERER_PRESENTVSYNC; +#else + // However, if it isn't, we should just silently turn vid_wait off + // This is because the renderer will be created before the config + // is read and vid_wait is set from the user's preferences, and thus + // vid_wait will have no effect. + CV_StealthSetValue(&cv_vidwait, 0); #endif + } if (!renderer) renderer = SDL_CreateRenderer(window, -1, flags); @@ -1571,6 +1593,7 @@ boolean VID_CheckRenderer(void) else if (vid.glstate == VID_GL_LIBRARY_ERROR) rendererchanged = false; } + else #endif if (!contextcreated) @@ -1761,10 +1784,10 @@ void I_StartupGraphics(void) if (graphics_started) return; - COM_AddCommand ("vid_nummodes", VID_Command_NumModes_f); - COM_AddCommand ("vid_info", VID_Command_Info_f); - COM_AddCommand ("vid_modelist", VID_Command_ModeList_f); - COM_AddCommand ("vid_mode", VID_Command_Mode_f); + COM_AddCommand ("vid_nummodes", VID_Command_NumModes_f, COM_LUA); + COM_AddCommand ("vid_info", VID_Command_Info_f, COM_LUA); + COM_AddCommand ("vid_modelist", VID_Command_ModeList_f, COM_LUA); + COM_AddCommand ("vid_mode", VID_Command_Mode_f, 0); CV_RegisterVar (&cv_vidwait); CV_RegisterVar (&cv_stretch); CV_RegisterVar (&cv_alwaysgrabmouse); diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index e56a5bc1b..f13aaef5d 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2014-2022 by Sonic Team Junior. +// Copyright (C) 2014-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 67e98d4f5..db0538195 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2022 by Sonic Team Junior. +// Copyright (C) 2014-2023 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sdl/ogl_sdl.h b/src/sdl/ogl_sdl.h index 9744bc6f1..bd1d699ff 100644 --- a/src/sdl/ogl_sdl.h +++ b/src/sdl/ogl_sdl.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2022 by Sonic Team Junior. +// Copyright (C) 2014-2023 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 0de3788fe..2ca35b954 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2014-2022 by Sonic Team Junior. +// Copyright (C) 2014-2023 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index 6b6e79d97..db736880d 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// Copyright (C) 2006-2022 by Sonic Team Junior. +// Copyright (C) 2006-2023 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sounds.c b/src/sounds.c index 43525d568..19b69dd28 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/sounds.h b/src/sounds.h index eec518689..102881e99 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/st_stuff.c b/src/st_stuff.c index ed130c912..9cac145a7 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -108,6 +108,9 @@ static patch_t *sneakers; static patch_t *gravboots; static patch_t *nonicon; static patch_t *nonicon2; +static patch_t *nightopianhelper; +static patch_t *linkfreeze; +static patch_t *superparaloop; static patch_t *bluestat; static patch_t *byelstat; static patch_t *orngstat; @@ -164,9 +167,18 @@ hudinfo_t hudinfo[NUMHUDITEMS] = { 288, 176, V_SNAPTORIGHT|V_SNAPTOBOTTOM}, // HUD_POWERUPS }; -static huddrawlist_h luahuddrawlist_game; +static huddrawlist_h luahuddrawlist_game[2]; static huddrawlist_h luahuddrawlist_titlecard; +// NiGHTS link colors; 3 sets with increasingly fancy colors (1 to 299, 300 to 599, 600 and above) +skincolornum_t linkColor[3][NUMLINKCOLORS] = { +{SKINCOLOR_SHAMROCK, SKINCOLOR_AQUA, SKINCOLOR_SKY, SKINCOLOR_BLUE, SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, + SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT}, +{SKINCOLOR_EMERALD, SKINCOLOR_AQUAMARINE, SKINCOLOR_WAVE, SKINCOLOR_SAPPHIRE, SKINCOLOR_GALAXY, SKINCOLOR_CRYSTAL, + SKINCOLOR_TAFFY, SKINCOLOR_RUBY, SKINCOLOR_GARNET, SKINCOLOR_TOPAZ, SKINCOLOR_LEMON, SKINCOLOR_LIME}, +{SKINCOLOR_ISLAND, SKINCOLOR_TURQUOISE, SKINCOLOR_DREAM, SKINCOLOR_DAYBREAK, SKINCOLOR_VAPOR, SKINCOLOR_FUCHSIA, + SKINCOLOR_VIOLET, SKINCOLOR_EVENTIDE, SKINCOLOR_KETCHUP, SKINCOLOR_FOUNDATION, SKINCOLOR_HEADLIGHT, SKINCOLOR_CHARTREUSE}}; + // // STATUS BAR CODE // @@ -313,6 +325,10 @@ void ST_LoadGraphics(void) nonicon2 = W_CachePatchName("NONICON2", PU_HUDGFX); // NiGHTS HUD things + nightopianhelper = W_CachePatchName("NHLPICON", PU_HUDGFX); + linkfreeze = W_CachePatchName("NLFZICON", PU_HUDGFX); + superparaloop = W_CachePatchName("NSPRICON", PU_HUDGFX); + bluestat = W_CachePatchName("BLUESTAT", PU_HUDGFX); byelstat = W_CachePatchName("BYELSTAT", PU_HUDGFX); orngstat = W_CachePatchName("ORNGSTAT", PU_HUDGFX); @@ -427,7 +443,8 @@ void ST_Init(void) ST_LoadGraphics(); - luahuddrawlist_game = LUA_HUD_CreateDrawList(); + luahuddrawlist_game[0] = LUA_HUD_CreateDrawList(); + luahuddrawlist_game[1] = LUA_HUD_CreateDrawList(); luahuddrawlist_titlecard = LUA_HUD_CreateDrawList(); } @@ -1411,7 +1428,7 @@ void ST_drawTitleCard(void) lt_lasttic = lt_ticker; luahook: - if (renderisnewtic) + //if (renderisnewtic) { LUA_HUD_ClearDrawList(luahuddrawlist_titlecard); LUA_HUDHOOK(titlecard, luahuddrawlist_titlecard); @@ -1447,6 +1464,21 @@ void ST_drawWipeTitleCard(void) } } +#define ICONSEP (16+4) // matches weapon rings HUD + +static INT32 ST_powerupHUDoffset(UINT16 timer) +{ + if (timer > 7) + return ICONSEP; + else + { + UINT8 a = ICONSEP, b = 7-timer; + while (b--) + a = 2*a/3; + return a; + } +} + static void ST_drawPowerupHUD(void) { patch_t *p = NULL; @@ -1454,7 +1486,6 @@ static void ST_drawPowerupHUD(void) INT32 offs = hudinfo[HUD_POWERUPS].x; const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0); static INT32 flagoffs[2] = {0, 0}, shieldoffs[2] = {0, 0}, finishoffs[2] = {0, 0}; -#define ICONSEP (16+4) // matches weapon rings HUD if (F_GetPromptHideHud(hudinfo[HUD_POWERUPS].y)) return; @@ -1566,15 +1597,7 @@ static void ST_drawPowerupHUD(void) DRAWTIMERICON(invincibility, invulntime) } - if (invulntime > 7) - offs -= ICONSEP; - else - { - UINT8 a = ICONSEP, b = 7-invulntime; - while (b--) - a = 2*a/3; - offs -= a; - } + offs -= ST_powerupHUDoffset(invulntime); // Super Sneakers if (stplyr->powers[pw_sneakers] > 3*TICRATE || (stplyr->powers[pw_sneakers] && leveltime & 1)) @@ -1582,15 +1605,7 @@ static void ST_drawPowerupHUD(void) DRAWTIMERICON(sneakers, stplyr->powers[pw_sneakers]) } - if (stplyr->powers[pw_sneakers] > 7) - offs -= ICONSEP; - else - { - UINT8 a = ICONSEP, b = 7-stplyr->powers[pw_sneakers]; - while (b--) - a = 2*a/3; - offs -= a; - } + offs -= ST_powerupHUDoffset(stplyr->powers[pw_sneakers]); // Gravity Boots if (stplyr->powers[pw_gravityboots] > 3*TICRATE || (stplyr->powers[pw_gravityboots] && leveltime & 1)) @@ -1598,6 +1613,36 @@ static void ST_drawPowerupHUD(void) DRAWTIMERICON(gravboots, stplyr->powers[pw_gravityboots]) } + offs -= ST_powerupHUDoffset(stplyr->powers[pw_gravityboots]); + +// -------------------- +// NiGHTS timer-based powerups +// -------------------- + + // Nightopian Helper + if (stplyr->powers[pw_nights_helper] > 3*TICRATE || (stplyr->powers[pw_nights_helper] && leveltime & 1)) + { + DRAWTIMERICON(nightopianhelper, stplyr->powers[pw_nights_helper]) + } + + offs -= ST_powerupHUDoffset(stplyr->powers[pw_nights_helper]); + + // Link Freeze + if (stplyr->powers[pw_nights_linkfreeze] > 3*TICRATE || (stplyr->powers[pw_nights_linkfreeze] && leveltime & 1)) + { + DRAWTIMERICON(linkfreeze, stplyr->powers[pw_nights_linkfreeze]) + } + + offs -= ST_powerupHUDoffset(stplyr->powers[pw_nights_linkfreeze]); + + // Super Paraloop + if (stplyr->powers[pw_nights_superloop] > 3*TICRATE || (stplyr->powers[pw_nights_superloop] && leveltime & 1)) + { + DRAWTIMERICON(superparaloop, stplyr->powers[pw_nights_superloop]) + } + + //offs -= ST_powerupHUDoffset(stplyr->powers[pw_nights_superloop]); + #undef DRAWTIMERICON #undef ICONSEP } @@ -1696,7 +1741,7 @@ static void ST_drawNightsRecords(void) ST_DrawNightsOverlayNum((BASEVIDWIDTH/2 + 56)<lastmarescore, nightsnum, SKINCOLOR_AZURE); // If new record, say so! - if (!(netgame || multiplayer) && G_GetBestNightsScore(gamemap, stplyr->lastmare + 1) <= stplyr->lastmarescore) + if (!(netgame || multiplayer) && G_GetBestNightsScore(gamemap, stplyr->lastmare + 1, clientGamedata) <= stplyr->lastmarescore) { if (stplyr->texttimer & 16) V_DrawCenteredString(BASEVIDWIDTH/2, 184, V_YELLOWMAP|aflag, "* NEW RECORD *"); @@ -1715,43 +1760,11 @@ static void ST_drawNightsRecords(void) } } -// 2.0-1: [21:42] <+Rob> Beige - Lavender - Steel Blue - Peach - Orange - Purple - Silver - Yellow - Pink - Red - Blue - Green - Cyan - Gold -/*#define NUMLINKCOLORS 14 -static skincolornum_t linkColor[NUMLINKCOLORS] = -{SKINCOLOR_BEIGE, SKINCOLOR_LAVENDER, SKINCOLOR_AZURE, SKINCOLOR_PEACH, SKINCOLOR_ORANGE, - SKINCOLOR_MAGENTA, SKINCOLOR_SILVER, SKINCOLOR_SUPERGOLD4, SKINCOLOR_PINK, SKINCOLOR_RED, - SKINCOLOR_BLUE, SKINCOLOR_GREEN, SKINCOLOR_CYAN, SKINCOLOR_GOLD};*/ - -// 2.2 indev list: (unix time 1470866042) Emerald, Aqua, Cyan, Blue, Pastel, Purple, Magenta, Rosy, Red, Orange, Gold, Yellow, Peridot -/*#define NUMLINKCOLORS 13 -static skincolornum_t linkColor[NUMLINKCOLORS] = -{SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_BLUE, SKINCOLOR_PASTEL, - SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, - SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT};*/ - -// 2.2 indev list again: [19:59:52] Ruby > Red > Flame > Sunset > Orange > Gold > Yellow > Lime > Green > Aqua > cyan > Sky > Blue > Pastel > Purple > Bubblegum > Magenta > Rosy > repeat -// [20:00:25] Also Icy for the link freeze text color -// [20:04:03] I would start it on lime -/*#define NUMLINKCOLORS 18 -static skincolornum_t linkColor[NUMLINKCOLORS] = -{SKINCOLOR_LIME, SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_SKY, - SKINCOLOR_SAPPHIRE, SKINCOLOR_PASTEL, SKINCOLOR_PURPLE, SKINCOLOR_BUBBLEGUM, SKINCOLOR_MAGENTA, - SKINCOLOR_ROSY, SKINCOLOR_RUBY, SKINCOLOR_RED, SKINCOLOR_FLAME, SKINCOLOR_SUNSET, - SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW};*/ - -// 2.2+ list for real this time: https://wiki.srb2.org/wiki/User:Rob/Sandbox (check history around 31/10/17, spoopy) -#define NUMLINKCOLORS 12 -static skincolornum_t linkColor[2][NUMLINKCOLORS] = { -{SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_SKY, SKINCOLOR_BLUE, SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, - SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT}, -{SKINCOLOR_SEAFOAM, SKINCOLOR_CYAN, SKINCOLOR_WAVE, SKINCOLOR_SAPPHIRE, SKINCOLOR_VAPOR, SKINCOLOR_BUBBLEGUM, - SKINCOLOR_VIOLET, SKINCOLOR_RUBY, SKINCOLOR_FLAME, SKINCOLOR_SUNSET, SKINCOLOR_SANDY, SKINCOLOR_LIME}}; - static void ST_drawNiGHTSLink(void) { static INT32 prevsel[2] = {0, 0}, prevtime[2] = {0, 0}; const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0); - INT32 sel = ((stplyr->linkcount-1) / 5) % NUMLINKCOLORS, aflag = V_PERPLAYER, mag = ((stplyr->linkcount-1 >= 300) ? 1 : 0); + INT32 sel = ((stplyr->linkcount-1) / 5) % NUMLINKCOLORS, aflag = V_PERPLAYER, mag = ((stplyr->linkcount-1 >= 300) ? (stplyr->linkcount-1 >= 600) ? 2 : 1 : 0); skincolornum_t colornum; fixed_t x, y, scale; @@ -2544,7 +2557,7 @@ static void ST_doHuntIconsAndSound(void) S_StartSound(NULL, sfx_emfind); } -static void ST_doItemFinderIconsAndSound(void) +static boolean ST_doItemFinderIconsAndSound(void) { INT32 emblems[16]; thinker_t *th; @@ -2555,6 +2568,12 @@ static void ST_doItemFinderIconsAndSound(void) INT32 interval = 0, newinterval = 0; INT32 soffset; + if (!(cv_itemfinder.value && M_SecretUnlocked(SECRET_ITEMFINDER, clientGamedata))) + { + // Not unlocked, or not enabled. Use emerald hunt radar. + return false; + } + for (i = 0; i < numemblems; ++i) { if (emblemlocations[i].type > ET_SKIN || emblemlocations[i].level != gamemap) @@ -2562,15 +2581,21 @@ static void ST_doItemFinderIconsAndSound(void) emblems[stemblems++] = i; - if (!emblemlocations[i].collected) + if (!P_EmblemWasCollected(i) && P_CanPickupEmblem(stplyr, i)) + { ++stunfound; + } if (stemblems >= 16) break; } + // Found all/none exist? Don't waste our time if (!stunfound) - return; + { + // Allow emerald hunt radar to function after they're all collected. + return false; + } // Scan thinkers to find emblem mobj with these ids for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) @@ -2590,6 +2615,9 @@ static void ST_doItemFinderIconsAndSound(void) { if (mo2->health == emblems[i] + 1) { + if (P_EmblemWasCollected(emblems[i]) || !P_CanPickupEmblem(stplyr, emblems[i])) + break; + soffset = (i * 20) - ((stemblems - 1) * 10); newinterval = ST_drawEmeraldHuntIcon(mo2, itemhoming, soffset); @@ -2604,6 +2632,8 @@ static void ST_doItemFinderIconsAndSound(void) if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0 && renderisnewtic) S_StartSound(NULL, sfx_emfind); + + return true; } // @@ -2722,9 +2752,7 @@ static void ST_overlayDrawer(void) ST_drawRaceHUD(); // Emerald Hunt Indicators - if (cv_itemfinder.value && M_SecretUnlocked(SECRET_ITEMFINDER)) - ST_doItemFinderIconsAndSound(); - else + if (!ST_doItemFinderIconsAndSound()) ST_doHuntIconsAndSound(); if(!P_IsLocalPlayer(stplyr)) @@ -2739,28 +2767,29 @@ static void ST_overlayDrawer(void) } // This is where we draw all the fun cheese if you have the chasecam off! - if (!(maptol & TOL_NIGHTS)) + if ((stplyr == &players[displayplayer] && !camera.chase) + || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase)) { - if ((stplyr == &players[displayplayer] && !camera.chase) - || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase)) - { - ST_drawFirstPersonHUD(); - if (cv_powerupdisplay.value) - ST_drawPowerupHUD(); // same as it ever was... - } - else if (cv_powerupdisplay.value == 2) + ST_drawFirstPersonHUD(); + if (cv_powerupdisplay.value) ST_drawPowerupHUD(); // same as it ever was... } + else if (cv_powerupdisplay.value == 2) + ST_drawPowerupHUD(); // same as it ever was... + } else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2) ST_drawPowerupHUD(); // same as it ever was... if (!(netgame || multiplayer) || !hu_showscores) { + INT32 hooklistindex = splitscreen && stplyr == &players[secondarydisplayplayer] ? 1 : 0; if (renderisnewtic) { - LUA_HUDHOOK(game, luahuddrawlist_game); + LUA_HUD_ClearDrawList(luahuddrawlist_game[hooklistindex]); + LUA_HUDHOOK(game, luahuddrawlist_game[hooklistindex]); } + LUA_HUD_DrawList(luahuddrawlist_game[hooklistindex]); } // draw level title Tails @@ -2839,10 +2868,6 @@ void ST_Drawer(void) if (st_overlay) { - if (renderisnewtic) - { - LUA_HUD_ClearDrawList(luahuddrawlist_game); - } // No deadview! stplyr = &players[displayplayer]; ST_overlayDrawer(); @@ -2852,7 +2877,5 @@ void ST_Drawer(void) stplyr = &players[secondarydisplayplayer]; ST_overlayDrawer(); } - - LUA_HUD_DrawList(luahuddrawlist_game); } } diff --git a/src/st_stuff.h b/src/st_stuff.h index c59bc2ac6..603be3c30 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -124,4 +124,7 @@ extern hudinfo_t hudinfo[NUMHUDITEMS]; extern UINT16 objectsdrawn; +#define NUMLINKCOLORS 12 +extern skincolornum_t linkColor[3][NUMLINKCOLORS]; + #endif diff --git a/src/strcasestr.c b/src/strcasestr.c index 6a686d6dc..2796f11d5 100644 --- a/src/strcasestr.c +++ b/src/strcasestr.c @@ -2,7 +2,7 @@ strcasestr -- case insensitive substring searching function. */ /* -Copyright 2019-2022 James R. +Copyright 2019-2023 James R. All rights reserved. Redistribution and use in source forms, with or without modification, is @@ -22,6 +22,16 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef _MSC_VER +#include +#include +#include + +#ifndef strncasecmp +#define strncasecmp _strnicmp +#endif + +#endif static inline int trycmp (char **pp, char *cp, diff --git a/src/string.c b/src/string.c index 5534a3f0c..dd3080a97 100644 --- a/src/string.c +++ b/src/string.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. -// Copyright (C) 2006-2022 by Sonic Team Junior. +// Copyright (C) 2006-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -52,3 +52,19 @@ size_t strlcpy(char *dst, const char *src, size_t siz) #endif #include "strcasestr.c" + +int startswith(const char *path, const char *tag) +{ + return !strncmp(path, tag, strlen(tag)); +} + +int endswith(const char *base, const char *tag) +{ + const size_t base_length = strlen(base); + const size_t tag_length = strlen(tag); + + if (tag_length > base_length) + return false; + + return !memcmp(&base[base_length - tag_length], tag, tag_length); +} diff --git a/src/tables.c b/src/tables.c index f8b8030c9..315fe1d7a 100644 --- a/src/tables.c +++ b/src/tables.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tables.h b/src/tables.h index 172ade378..2736f03e8 100644 --- a/src/tables.h +++ b/src/tables.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/taglist.c b/src/taglist.c index 305b05f04..e4e385b9e 100644 --- a/src/taglist.c +++ b/src/taglist.c @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. -// Copyright (C) 2020-2022 by Nev3r. +// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 2020-2023 by Nev3r. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -472,5 +472,5 @@ mtag_t Tag_NextUnused(mtag_t start) start++; } - return MAXTAGS; + return (mtag_t)MAXTAGS; } diff --git a/src/taglist.h b/src/taglist.h index de6e9abd5..d42a48f05 100644 --- a/src/taglist.h +++ b/src/taglist.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. -// Copyright (C) 2020-2022 by Nev3r. +// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 2020-2023 by Nev3r. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tmap.nas b/src/tmap.nas index f096c8141..85091cbd5 100644 --- a/src/tmap.nas +++ b/src/tmap.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DooM Legacy Team. -;; Copyright (C) 1999-2022 by Sonic Team Junior. +;; Copyright (C) 1999-2023 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/tmap.s b/src/tmap.s index 5bb2dea12..d98d82e25 100644 --- a/src/tmap.s +++ b/src/tmap.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tmap_asm.s b/src/tmap_asm.s index 8e307f42b..d8967178c 100644 --- a/src/tmap_asm.s +++ b/src/tmap_asm.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tmap_mmx.nas b/src/tmap_mmx.nas index 5312f3c76..a45667e23 100644 --- a/src/tmap_mmx.nas +++ b/src/tmap_mmx.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DOSDOOM. -;; Copyright (C) 2010-2022 by Sonic Team Junior. +;; Copyright (C) 2010-2023 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/tmap_vc.nas b/src/tmap_vc.nas index 44b2d2e7b..c85cf7003 100644 --- a/src/tmap_vc.nas +++ b/src/tmap_vc.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DooM Legacy Team. -;; Copyright (C) 1999-2022 by Sonic Team Junior. +;; Copyright (C) 1999-2023 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/v_video.c b/src/v_video.c index 84d7978cb..461a5e3bc 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/v_video.h b/src/v_video.h index 2831230a3..ff03836b5 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/version.h b/src/version.h index 7a12fbbbe..083c53134 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define SRB2VERSION "2.2.10"/* this must be the first line, for cmake !! */ +#define SRB2VERSION "2.2.11"/* this must be the first line, for cmake !! */ // The Modification ID; must be obtained from a Master Server Admin ( https://mb.srb2.org/members/?key=ms_admin ). // DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server. @@ -9,7 +9,7 @@ // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.2.0 is not version "1". -#define MODVERSION 51 +#define MODVERSION 52 // Define this as a prerelease version suffix (pre#, RC#) -// #define BETAVERSION "pre1" +//#define BETAVERSION "pre1" diff --git a/src/vid_copy.s b/src/vid_copy.s index 8e43e23c1..1473a3856 100644 --- a/src/vid_copy.s +++ b/src/vid_copy.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/w_wad.c b/src/w_wad.c index 42c6bf83b..456afef7b 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1035,7 +1035,7 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup) return W_InitFileError(path, startup); } - important = 0; /// \todo Implement a W_VerifyFolder. + important = 1; /// \todo Implement a W_VerifyFolder. // Remove path delimiters. p = path + (strlen(path) - 1); diff --git a/src/w_wad.h b/src/w_wad.h index c4de55d77..ffb9095ba 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index 2236beca1..869c0e7d3 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -77,8 +77,8 @@ END #include "../doomdef.h" // Needed for version string VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,2,10,0 - PRODUCTVERSION 2,2,10,0 + FILEVERSION 2,2,11,0 + PRODUCTVERSION 2,2,11,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -98,7 +98,7 @@ BEGIN VALUE "FileDescription", "Sonic Robo Blast 2\0" VALUE "FileVersion", VERSIONSTRING_RC VALUE "InternalName", "srb2\0" - VALUE "LegalCopyright", "Copyright 1998-2022 by Sonic Team Junior\0" + VALUE "LegalCopyright", "Copyright 1998-2023 by Sonic Team Junior\0" VALUE "LegalTrademarks", "Sonic the Hedgehog and related characters are trademarks of Sega.\0" VALUE "OriginalFilename", "srb2win.exe\0" VALUE "PrivateBuild", "\0" diff --git a/src/y_inter.c b/src/y_inter.c index 7faceff50..6e7d362a7 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2004-2022 by Sonic Team Junior. +// Copyright (C) 2004-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1092,12 +1092,14 @@ void Y_Ticker(void) S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching! // Update when done with tally - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback) + if (!demoplayback) { - if (M_UpdateUnlockablesAndExtraEmblems()) + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + + if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata)) S_StartSound(NULL, sfx_s3k68); - G_SaveGameData(); + G_SaveGameData(clientGamedata); } } else if (!(intertic & 1)) @@ -1133,13 +1135,18 @@ void Y_Ticker(void) } // emerald bounce - if (intertic <= 1) + if (dedicated || !LUA_HudEnabled(hud_intermissionemeralds)) + { + // dedicated servers don't need this, especially since it crashes when stagefailed + // also skip this if Lua disabled intermission emeralds, so it doesn't play sounds + } + else if (intertic <= 1) { data.spec.emeraldbounces = 0; data.spec.emeraldmomy = 20; data.spec.emeraldy = -40; } - else + else if (P_GetNextEmerald() < 7) { if (!stagefailed) { @@ -1223,12 +1230,14 @@ void Y_Ticker(void) S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching! // Update when done with tally - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback) + if (!demoplayback) { - if (M_UpdateUnlockablesAndExtraEmblems()) + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + + if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata)) S_StartSound(NULL, sfx_s3k68); - G_SaveGameData(); + G_SaveGameData(clientGamedata); } } else if (!(intertic & 1)) diff --git a/src/y_inter.h b/src/y_inter.h index 74183066e..6b249ca0d 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2004-2022 by Sonic Team Junior. +// Copyright (C) 2004-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/z_zone.c b/src/z_zone.c index b949730e3..11c4bcb2c 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. -// Copyright (C) 2006-2022 by Sonic Team Junior. +// Copyright (C) 2006-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -106,20 +106,20 @@ static void Command_Memdump_f(void); */ void Z_Init(void) { - UINT32 total, memfree; + size_t total, memfree; memset(&head, 0x00, sizeof(head)); head.next = head.prev = &head; memfree = I_GetFreeMem(&total)>>20; - CONS_Printf("System memory: %uMB - Free: %uMB\n", total>>20, memfree); + CONS_Printf("System memory: %sMB - Free: %sMB\n", sizeu1(total>>20), sizeu2(memfree)); // Note: This allocates memory. Watch out. - COM_AddCommand("memfree", Command_Memfree_f); + COM_AddCommand("memfree", Command_Memfree_f, COM_LUA); #ifdef ZDEBUG - COM_AddCommand("memdump", Command_Memdump_f); + COM_AddCommand("memdump", Command_Memdump_f, COM_LUA); #endif } @@ -791,7 +791,7 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag) */ static void Command_Memfree_f(void) { - UINT32 freebytes, totalbytes; + size_t freebytes, totalbytes; Z_CheckHeap(-1); CONS_Printf("\x82%s", M_GetText("Memory Info\n")); @@ -824,8 +824,8 @@ static void Command_Memfree_f(void) CONS_Printf("\x82%s", M_GetText("System Memory Info\n")); freebytes = I_GetFreeMem(&totalbytes); - CONS_Printf(M_GetText(" Total physical memory: %7u KB\n"), totalbytes>>10); - CONS_Printf(M_GetText("Available physical memory: %7u KB\n"), freebytes>>10); + CONS_Printf(M_GetText(" Total physical memory: %s KB\n"), sizeu1(totalbytes>>10)); + CONS_Printf(M_GetText("Available physical memory: %s KB\n"), sizeu1(freebytes>>10)); } #ifdef ZDEBUG diff --git a/src/z_zone.h b/src/z_zone.h index d7e1ed528..c3cd4f011 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 8fa47ba3a..7aff16601 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -91,6 +91,7 @@ if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}") configure_file("${ZLIB_SOURCE_DIR}/zlib.pc.cmakein" "${ZLIB_BINARY_DIR}/zlib.pc" @ONLY) configure_file("${ZLIB_SOURCE_DIR}/zconf.h.cmakein" "${ZLIB_BINARY_DIR}/include/zconf.h" @ONLY) + configure_file("${ZLIB_SOURCE_DIR}/zlib.h" "${ZLIB_BINARY_DIR}/include/zlib.h" @ONLY) add_library(ZLIB ${SRB2_INTERNAL_LIBRARY_TYPE} ${ZLIB_SRCS}) set_target_properties(ZLIB PROPERTIES @@ -173,8 +174,8 @@ if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}") target_include_directories(png PUBLIC "${png_BINARY_DIR}/include") # ... and these also need to be present only for png build - target_include_directories(png PRIVATE "${zlib_SOURCE_DIR}") - target_include_directories(png PRIVATE "${zlib_BINARY_DIR}") + target_include_directories(png PRIVATE "${ZLIB_SOURCE_DIR}") + target_include_directories(png PRIVATE "${ZLIB_BINARY_DIR}") target_include_directories(png PRIVATE "${png_BINARY_DIR}") target_link_libraries(png PRIVATE ZLIB::ZLIB) @@ -495,7 +496,7 @@ if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}") if("${CMAKE_C_COMPILER_ID}" STREQUAL GNU OR "${CMAKE_C_COMPILER_ID}" STREQUAL Clang OR "${CMAKE_C_COMPILER_ID}" STREQUAL AppleClang) target_compile_options(openmpt PRIVATE "-g0") endif() - if("${CMAKE_SYSTEM_NAME}" STREQUAL Windows) + if("${CMAKE_SYSTEM_NAME}" STREQUAL Windows AND "${CMAKE_C_COMPILER_ID}" STREQUAL MSVC) target_link_libraries(openmpt PRIVATE Rpcrt4) endif() target_compile_features(openmpt PRIVATE cxx_std_11) @@ -521,6 +522,7 @@ if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}") OPTIONS "BUILD_SHARED_LIBS ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" "ENABLE_UBSAN OFF" + "GME_YM2612_EMU MAME" ) target_compile_features(gme PRIVATE cxx_std_11) target_link_libraries(gme PRIVATE ZLIB::ZLIB)