Compare commits

..

301 commits

Author SHA1 Message Date
NepDisk
2d1903f026 Don't spawn in bots if map does not have new waypoints 2025-10-22 11:56:00 -04:00
NepDisk
31794448c7 Disallow respawning after finishing the race 2025-10-22 11:36:23 -04:00
GenericHeroGuy
2dfbd66031 Forgot to extend names in standings + bugfixes 2025-10-22 17:14:32 +02:00
NepDisk
fe33d2e9b5 Reenable hashing 2025-10-22 11:12:42 -04:00
Gustaf Alhäll
4801c68755 Merge pull request 'Port optimized path traversal algorithm from Antimony' (#168) from optimize-path-traversal into next
Reviewed-on: https://codeberg.org/srb2classic/srb2classic/pulls/168
2025-10-22 11:08:03 -04:00
NepDisk
aeedd2fd10 remove unused defines and update hash 2025-10-22 11:04:13 -04:00
Frivolous Aqua
be491c2a19 Add PlayerSkinRealName as an ACS function 2025-10-22 10:48:52 -04:00
NepDisk
762815a064 Don't arrow here
Mr. Game Gears likes it like this
2025-10-22 10:29:33 -04:00
NepDisk
0daed03ba0 Fix moving floor thinker type not synching 2025-10-21 22:23:44 -04:00
NepDisk
9a168ee63b Calloc netsave thinkers for extra safety 2025-10-21 19:32:05 -04:00
NepDisk
547faa57be Don't do extra code for writing 2025-10-21 19:32:05 -04:00
GenericHeroGuy
b4bf747a17 One more thing: long player names! 2025-10-22 00:08:15 +02:00
NepDisk
b35b1d9f51 Merge pull request 'Record Attack Preset rework' (#174) from softpresets into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/174
2025-10-21 22:58:17 +02:00
GenericHeroGuy
94fd921db0 Set bumpspark/bumpspring to their correct values
Version 1 = before Sep 15, Version 2 = after Sep 22
(ignoring the 1-week timeframe where bumpspark was On in all modes)
(also ignoring that bumpspring has been On in all modes since Sep 15?)

Also correct the compatlevel check for these
2025-10-21 22:27:40 +02:00
GenericHeroGuy
8f13c49e10 Hopefully the last few bug fixes 2025-10-21 21:22:05 +02:00
GenericHeroGuy
389c2da098 Fix lap times (the rest of f1f7edbe) 2025-10-21 21:07:32 +02:00
GenericHeroGuy
7471c89734 Genius! 2025-10-21 20:35:03 +02:00
GenericHeroGuy
308e3c1171 Update statistics screen 2025-10-21 18:34:16 +02:00
GenericHeroGuy
23caae02e0 Add backwards compat for old kartdata files 2025-10-21 17:28:27 +02:00
GenericHeroGuy
7e9e648784 Merge branch 'blankart-dev' into softpresets 2025-10-21 16:34:25 +02:00
Alug
76a43e4bdb R_FlushQuad: dont use 64bit/8byte copy on 32bit targets
on 32bit targets this will just compile into two 32bit copies which gcc cant optimize as well as it can with the byte copy (it seems to love to do some AVX stuff atleast in my tests)
so this is only useful for 64bit capable platforms (compiler does not seem to do 64bit copys for the byte copy case, so this ends up being faster)
2025-10-20 22:32:50 -04:00
Indev
3c7b01cd93 Fix possible buffer overflow in M_TextInputSetString when string length is greatter than buffer length 2025-10-20 19:29:31 -04:00
NepDisk
1a33deff34 Fix server description infinite loop and raise max length 2025-10-20 19:13:06 -04:00
NepDisk
7723e414e4 Clean up P_InitMapData and fix maps not working of loaded before header 2025-10-20 15:42:34 -04:00
NepDisk
a5f89b769d Rename this so it fits 2025-10-20 10:32:40 -04:00
Alug
70407fe357 R_FlushQuad: also check "source" for alignment 2025-10-20 10:30:23 -04:00
NepDisk
160b0f6a7e Small fixes 2025-10-20 10:29:48 -04:00
haya
2fc24b795a fix: inline string dance not resetting y offset 2025-10-20 10:23:14 -04:00
NepDisk
efb610713f Revert "Add SIGSEGV guard to highlight patch loading."
This reverts commit f6b2f4bd23.
2025-10-19 22:01:02 -04:00
NepDisk
65cf091573 Don't do stuff for dedicated in ST_LoadGraphics 2025-10-19 21:57:44 -04:00
NepDisk
2f746d4307 Experiment: Don't load hud assets in dedicated 2025-10-19 21:51:35 -04:00
NepDisk
3f9986a31e Update CPM 2025-10-19 20:49:19 -04:00
Alug
07d054f3ad R_FlushQuad: fix column flush on odd width resolutions
lets hope this is the end of our software woes Zzz...
2025-10-20 00:48:29 +02:00
NepDisk
bd08b0c39d Revert "Don't draw the sky if we aren't supposed to"
This reverts commit 858fb1c916.
2025-10-19 18:18:34 -04:00
GenericHeroGuy
27b01065d5 Add even more pointer types to the SYNC macro
Also split relinked pointers into RSYNC, to hopefully prevent dumb mistakes
2025-10-19 23:11:41 +02:00
NepDisk
fbf10dbf9e More optimized code path for different pow2 sizes 2025-10-19 16:54:06 -04:00
Alug
3fa76c409c R_FlushQuad: fix unaligned memory access 2025-10-19 16:39:59 -04:00
NepDisk
858fb1c916 Don't draw the sky if we aren't supposed to 2025-10-19 16:38:28 -04:00
NepDisk
df581ae69f Remove dead renderer code
based on 0eeacaf51e

remove
- broken viewborder code (if we really want it back for some reason, we should rather port RR´s fixed version of it)
- remove console clipping code for software (this was broken eiherway)
- remove hud message clearing stuff
- remove renderscreen and linesize variables (they just pointed to vid.screen and vid.widht)
2025-10-19 16:34:38 -04:00
Alug
a06aa1590f add allocation failure case in R_DrawMasked 2025-10-19 15:29:30 -04:00
LJ Sonic
71f14c1a0e Do not archive nil table keys 2025-10-19 15:28:07 -04:00
NepDisk
9868cf7915 set CURLOPT_MAXREDIRS to 30 2025-10-19 15:20:30 -04:00
NepDisk
a2dc0e7190 Merge pull request 'Implement Column buffering system' (#172) from columbuf into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/172
2025-10-19 21:11:11 +02:00
Alug
e332959262 fix I_ReadScreen warning
use uintptr to ensure same signdness, taken from srb2classic
2025-10-19 21:10:54 +02:00
Alug
a802a49647 rename to stride
more sensible name in this new case
2025-10-19 21:06:34 +02:00
Alug
6b31428b08 use DEFINE_COLUMN_COMBO macro for flush function definitions 2025-10-19 21:04:36 +02:00
Alug
f0e0edbc1d use aligned alloc for screen and column buffers
16 byte alingment

should speed up everything a bit
2025-10-19 20:48:16 +02:00
Alug
bad7b9f980 remove unused hires variable from drawcolumndata 2025-10-19 20:40:51 +02:00
Alug
e8e72db32f fix columnbuf crashes
-our buffered uhh buffer needs to be only advanced per column not per screenwidth, caused the buffer to advance beyond its boundaries

-brightmap drawers get the DC_DIRECT flag to make sure they never attempt to draw buffered

removed tempbuffer alignment for now as reported by ubsan
2025-10-19 20:38:22 +02:00
NepDisk
2ce83bb48d Revert "Add brightmap versions"
This reverts commit a3689c694c.
2025-10-19 13:07:23 -04:00
GenericHeroGuy
dbafe1da7a Fix sky texture syncing 2025-10-19 18:21:56 +02:00
NepDisk
a3689c694c Add brightmap versions 2025-10-19 12:19:13 -04:00
NepDisk
659aa667eb Software Renderer: Implement Column buffering system
A port of https://github.com/Indev450/SRB2Kart-Saturn/pull/205, currently doesn't work
2025-10-19 12:12:33 -04:00
GenericHeroGuy
f48aaba125 Thoroughly unfuck mobj syncing 2025-10-19 18:03:37 +02:00
minenice55
b10611670d idem for lines (seems to be the same code) 2025-10-19 11:01:30 -04:00
NepDisk
8288b6779f Merge pull request 'remove ylookup, columnofs and topleft' (#171) from murderylookupcolumntopleft into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/171
2025-10-19 16:43:15 +02:00
Alug
230cd7d450 fix splitscreen viewmorph
copy paste oopsie
2025-10-19 16:37:54 +02:00
GenericHeroGuy
1ea44d8707 Fix FOF unarchival 2025-10-19 16:31:45 +02:00
NepDisk
1d2d386d04 Merge pull request 'Implement other algorithms for network savegame compression' (#170) from netsavecompresscompare into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/170
2025-10-19 15:42:33 +02:00
NepDisk
a4f9f90471 We are using LZ4, got it 2025-10-19 09:40:45 -04:00
Anonimus
86403b35d8 CV_GUARD Alt. Invin. values 2025-10-19 13:23:44 +02:00
GenericHeroGuy
c1ffa1e109 Merge branch 'blankart-dev' into softpresets 2025-10-19 13:21:12 +02:00
NepDisk
fb2ad713cb Implement ZLib as an option as well.
Holy heck this is quite good
2025-10-19 03:05:57 -04:00
NepDisk
81337d6400 Implement LZ4 as a replacement for save game compression. Also mention size during compression / decompression in console 2025-10-19 02:12:32 -04:00
minenice55
c5c287ffb0 experiment with sector archival 2025-10-18 22:45:46 -04:00
NepDisk
d14455bcd4 Gold stars on intermission 2025-10-18 20:46:38 -04:00
GenericHeroGuy
5f50adb269 Enable -Wextra, kill MSVC, add UBSan option 2025-10-19 01:57:54 +02:00
GenericHeroGuy
8fa2b9f94b Fix warnings 2025-10-19 01:41:28 +02:00
GenericHeroGuy
459f0d9da7 Add CV_GUARD flag 2025-10-19 01:13:14 +02:00
Anonimus
b51473a2de Some clarity 2025-10-18 17:16:41 -04:00
Anonimus
0901ea89de Anti-bump 2025-10-18 17:13:31 -04:00
GenericHeroGuy
3a7fe7f7ed Cleanup and bugfixes 2025-10-18 22:43:27 +02:00
GenericHeroGuy
c9c56886aa Wire up the stat counters 2025-10-18 22:20:52 +02:00
NepDisk
7efc3adf6f [Patch] vid.buffer 2025-10-18 16:05:01 -04:00
NepDisk
5ef24abba4 Merge pull request '[FEAT] High Player Count Support' (#169) from 32p into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/169
2025-10-18 21:11:21 +02:00
minenice55
2a09d16282 don't touch non-gp methods that are in the gp class (lol) 2025-10-18 15:05:16 -04:00
minenice55
6d0a7552b2 max GP players 2025-10-18 15:01:06 -04:00
minenice55
617013cb74 Merge branch 'blankart-dev' into 32p 2025-10-18 20:32:05 +02:00
NepDisk
39e17bce4b remove ylookup, columnofs and topleft lookups
based on 2da89f1946
move screens array to vid struct
remove a bunch of unused stuff

this speeds up 4 player splitscreen ever so slighty
mostly just alot cleaner than the mess it was before
2025-10-18 13:04:39 -04:00
NepDisk
83f20d4c4e Make flame and invin stack 2025-10-18 11:42:14 -04:00
NepDisk
735600b0a7 invalidate more things for safety 2025-10-18 11:19:14 -04:00
NepDisk
b69eaff9f6 Player validation for player->mo 2025-10-18 10:30:23 -04:00
minenice55
dffc6eb3e3 get this to actually run in a netgame
capping to 32 now because netsync breaks with more players
2025-10-17 22:21:43 -04:00
minenice55
c03ae540b5 Merge branch 'blankart-dev' into 32p 2025-10-17 20:45:28 -04:00
GenericHeroGuy
2a761e18aa Restructure replay folder, remove RA flag suffixes 2025-10-18 01:59:36 +02:00
GenericHeroGuy
96bf11c706 WIP: User-defined time attack presets 2025-10-17 22:00:57 +02:00
GenericHeroGuy
27b22fee94 I have a better idea... 2025-10-17 21:50:08 +02:00
minenice55
ff7dea704c thing saturn 126p does 2025-10-17 15:25:21 -04:00
GenericHeroGuy
9392cc1bd7 Fix ring underflow 2025-10-17 20:44:25 +02:00
GenericHeroGuy
4623afe0be Flame shield rebalance: better offroad, lower top speed 2025-10-17 19:44:07 +02:00
NepDisk
bf93fafa27 Use a constant for file path stuff 2025-10-17 12:21:54 -04:00
NepDisk
b9a2878c11 Fix filepath size 2025-10-17 12:08:06 -04:00
minenice55
36527b7aa1 Merge branch 'blankart-dev' into 32p 2025-10-17 12:05:34 -04:00
GenericHeroGuy
4530947eaf Spare some external libraries from the MSVC purge 2025-10-17 18:02:13 +02:00
minenice55
5678e4471c Merge branch 'blankart-dev' into 32p 2025-10-17 11:51:27 -04:00
NepDisk
f7378caf66 Use more vars for multireads to vid.height and vid.width 2025-10-17 10:53:45 -04:00
NepDisk
ff467c676c port over most fixes from srb2classics clang-tidy pr
Based on 939354f483
2025-10-17 10:32:21 -04:00
NepDisk
166648f008 Kill BUGTRAP
This probably never worked
2025-10-17 09:55:24 -04:00
NepDisk
0ffe70f313 Update Discord RPC
Based on some of the changes from RR.
Accounts for the fact discord does not have tags anymore and makes skin code easier to manage
2025-10-17 09:15:34 -04:00
minenice55
de3697dec0 tweaks to intermission score tally 2025-10-16 23:29:08 -04:00
minenice55
ae60481eb4 Merge branch 'blankart-dev' into 32p 2025-10-16 22:46:26 -04:00
NepDisk
816753501f Doom Guy is called doom 2025-10-16 22:09:15 -04:00
NepDisk
a61002bf79 Port Litesteer from RR and make turn easing per player 2025-10-16 22:07:00 -04:00
minenice55
3d9b9f6750 Merge branch 'blankart-dev' into 32p 2025-10-16 21:03:38 -04:00
NepDisk
d5a7d3e22f Add MSVC deprecation notice and add statics here 2025-10-16 20:56:09 -04:00
NepDisk
0450f45635 Kill MSVC
We are a GCC and Clang household, get this shit outta here
2025-10-16 20:42:11 -04:00
Alug
81a616b843 change wheel input "sensitivity"
200 maps perfectly to our turn values
so the wheel now actually better reflects the inputs and does not turn fully super early uhh
2025-10-16 17:40:48 -04:00
Indev
c4aeef0216 Use str.resize(size) instead of str = str.substr(0, size) (ty lug <3) 2025-10-16 14:18:13 -04:00
NepDisk
cef5e93c93 Fix ub in R_PointOnSide Kart version 2025-10-16 14:11:32 -04:00
NepDisk
bb0f368080 G_SaveDemo: fix oob reads/writes for replay names
66f67c91e8
2025-10-16 14:07:44 -04:00
Alug
9081c4d177 let replays with empty name save
this does not crash for us
2025-10-16 14:01:34 -04:00
toaster
6a4e8916e6 G_SaveDemo: Resolve memory errors that could result in crashes
- Empty `demo.titlename` case
    - Don't try to save demo of name `.lmp`
    - Doesn't fall back to anything, because emptying out the name field can be reasonably treated as not wanting to save
- `demo.titlename` consists only of invalid characters
    - Don't try to save demo of name `-.lmp`
    - Falls back to the default demo title, because the user clearly wanted to save and just happened to provide invalid text
2025-10-16 13:59:31 -04:00
NepDisk
7fd49282d4 use const for player losing 2025-10-16 13:53:31 -04:00
NepDisk
76257fed20 Prevent rival name code from overflowing 2025-10-16 11:17:07 -04:00
NepDisk
1d6ad4415a Move rival insertion to R_ProcessPatchableFields 2025-10-16 11:02:34 -04:00
Anonimus
1b05f1af97 Implement a damage-control system for NULL highlights 2025-10-16 00:40:10 -04:00
Anonimus
f6b2f4bd23 Add SIGSEGV guard to highlight patch loading. 2025-10-15 23:54:55 -04:00
NepDisk
c1395c5da0 Fix boot crash due too small array 2025-10-15 20:43:29 -04:00
Anonimus
81f8fe0fdf Fix stupid fullcreds nitpick 2025-10-15 20:05:40 -04:00
minenice55
0d079836eb 42 + server host (also use 42 playerinfo slots) 2025-10-15 19:28:17 -04:00
GenericHeroGuy
06c2238ff6 Update hashes 2025-10-15 23:47:41 +02:00
minenice55
35a9c61ddf Merge branch 'blankart-dev' into 32p 2025-10-15 16:37:51 -04:00
NepDisk
c1d16124e5 Port Saturn timestuff branch
Should be better then I_UpdateTime spam
https://github.com/Indev450/SRB2Kart-Saturn/commits/timestuff/
2025-10-15 16:33:18 -04:00
NepDisk
0444108088 Revert "Funny shitpost idea to improve smoothness"
This reverts commit ae14b55006.
2025-10-15 16:23:03 -04:00
NepDisk
5d6595327f Update hash 2025-10-15 16:21:28 -04:00
minenice55
dce399f23f Merge branch 'blankart-dev' into 32p 2025-10-15 16:11:12 -04:00
GenericHeroGuy
febc28a172 Revive the v2 death animation 2025-10-15 21:59:17 +02:00
minenice55
91924aac7d vote screen for high player count 2025-10-15 15:49:02 -04:00
minenice55
da4add120f ping num in neo tab ranking (will need additions later too) 2025-10-15 14:47:06 -04:00
minenice55
65dec93f7c add battle royale player start wrapping 2025-10-15 14:34:13 -04:00
minenice55
1f25a2b4a2 Merge branch 'blankart-dev' into 32p 2025-10-15 13:50:36 -04:00
NepDisk
c8863472af Update hash 2025-10-15 12:53:05 -04:00
NepDisk
e1083d9d74 Add toggle to force rivals 2025-10-15 12:45:26 -04:00
NepDisk
5d8579dd56 Merge pull request 'More flexible per-item cooldowns' (#168) from wdgaster into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/168
2025-10-15 16:15:51 +02:00
Anonimus
3302248326 Get rid of debug shield namer 2025-10-15 09:24:42 -04:00
Anonimus
fd5da2dd73 Adjust INVFORCEODDS
It's now half of INVFORCEODDS instead of 75%
2025-10-15 09:23:20 -04:00
Anonimus
e3fa439f27 Add Doomguy to indev notice 2025-10-15 09:21:27 -04:00
Anonimus
98fd13adf7 More goner system stuff
* Adjust item cooldowns
* Re-add Hyuu cooldown (I forgot)
* Force-set shield cooldowns for as long as one is being held
2025-10-15 09:21:01 -04:00
Anonimus
a697f924c8 Introduce the goner table
I'm Wing Gaster, the royal scientist!
2025-10-15 07:30:50 -04:00
minenice55
b92417085f nuh uh 2025-10-14 23:03:44 -04:00
minenice55
810d6a16e0 fuck it the intermission rankings can fit this much 2025-10-14 22:59:35 -04:00
minenice55
c9ee96010b idem for minirankings 2025-10-14 22:58:06 -04:00
minenice55
32311ac45d port rankings intermission from neptune
will 100% need cleanup
2025-10-14 22:42:20 -04:00
minenice55
01688db2e2 I'ma jumpstart this 2025-10-14 21:50:25 -04:00
NepDisk
d1f4503566 Merge pull request '[ENHANCEMENT] Implement Flamometer UI Element' (#166) from flamometer into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/166
2025-10-15 02:29:17 +02:00
NepDisk
f20ace5915 Buff bots a bit 2025-10-14 19:13:00 -04:00
GenericHeroGuy
28e341ce92 Restore kartbot_modifiermax and the mapheader option
It now uses the raw value directly, so maps using it will need to be updated
2025-10-14 21:57:04 +02:00
minenice55
3e694b6ca2 make flameometer fire not crash 2025-10-14 12:18:34 -04:00
GenericHeroGuy
a67fd02a86 Fix bubble shield reflections segfaulting 2025-10-14 15:31:04 +02:00
GenericHeroGuy
9b2a4d52b2 Fix player pointer relinking being utterly broken
Courtesy of be5d651d
2025-10-14 15:03:01 +02:00
minenice55
881dadd6a5 start flamometer 2025-10-13 21:29:14 -04:00
Anonimus
0a9eeacb95 Push Hyudoro odds further up 2025-10-13 20:30:13 -04:00
Anonimus
76565d70c0 More odds shit
* Increase rarity of Orbinauts, prevent them from being rolled in the bottom half entirely
* Prevent single Jawz from being rolled in the bottom half
* Move Hyudoro odds up one tier
* Move Sneaker odds back a good few tiers
* Nerf Flame Shield odds, push it further back
* 4x Orbinaut max probability is 1.3%
* 2x Jawx odds have been adjusted
2025-10-13 20:09:39 -04:00
NepDisk
243359659c init 0 2025-10-13 16:57:41 -04:00
GenericHeroGuy
aa64b9aeed Let flame shield punt hazards 2025-10-13 21:41:48 +02:00
GenericHeroGuy
1736fa10a9 Fix IF_HOLDREADY not being reset properly 2025-10-13 21:35:30 +02:00
Anonimus
d86e0af31f More odds bullshit
* Thunder Shield has been removed from Useodds 2 thru 4, preventing it from being an annoying midpack roll
* As compensation, Orbinaut, Bubble Shield, and Mine probabilities have been increased for those Useodds tiers
* Grow's odds have been significantly reduced, tapering off the closer you get to Useodds 15
* Odds for Rocket Sneakers have been slightly modified
2025-10-13 14:39:36 -04:00
GenericHeroGuy
efd6779ef7 Refactor player shield management
shieldtracer has been moved to player_t, replacing curshield, in order to
maintain a Single Source of Truth(tm) and to help ourselves and Lua
scripters in the future
2025-10-13 20:23:17 +02:00
NepDisk
fc53a73f9b Kill ->localfile 2025-10-13 11:43:35 -04:00
NepDisk
62e78fbe72 Update to Saturns modified and fixed qs22j 2025-10-13 11:32:04 -04:00
Alug
30e1cdb404 use floats for calculating ticratescaled
this does not need to be double lel
actually improves performance in some cases
2025-10-13 11:29:39 -04:00
NepDisk
f7626d9898 dont update hud during skipped frames
513613d83b
is was to fix issues with some lua huds looking really bad during frameskip
but this causes issues with the hud flashing during gif recording
2025-10-13 11:25:06 -04:00
NepDisk
d24238a0fe Use higher amount of vissprites in 64bit 2025-10-13 11:23:13 -04:00
NepDisk
24e15786a2 clear thicksides with memset instead of loop 2025-10-13 11:19:05 -04:00
NepDisk
6a1bd29cb6 Clear g_dc each frame 2025-10-13 11:17:43 -04:00
NepDisk
64353a043e Always initialize all column offsets inside multi-patch textures
3964d4e188
2025-10-13 11:15:09 -04:00
NepDisk
d6d0377f6b inline R_ThingLightLevel
b3106d55d1
2025-10-13 11:10:04 -04:00
Alug
ca3ddf744d speed up masked sprites a bit
thx eternity engine!
2025-10-13 11:08:02 -04:00
NepDisk
8405ff27e4 Merge pull request 'Fix up some visual issues with MK64 characters (closes #150)' (#163) from bingbingwahoo into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/163
2025-10-13 00:44:13 +02:00
GenericHeroGuy
614e3f650c Cleanup and fix shield item stacks 2025-10-13 00:17:42 +02:00
GenericHeroGuy
9ddeabc55b Fixup bubble shield reflections
* Reflecting now sends the object directly away from the player, instead of
  flipping their momentum. May or may not help some awkward interactions
* Fixed collisions in general by making the bubble shield run collision
  checks after moving
* Various items now get flung into the air like they're supposed to
* Eggboxes no longer noclip through bubble shields
* Made the debris landing sound less obnoxiously loud
2025-10-12 22:10:59 +02:00
Anonimus
2db8925c28 More odds adjustments
These feel pretty good in offline testing, given the new odds
2025-10-12 11:56:57 -04:00
Anonimus
c27975f145 Minenice suggestion: default new items to Off
Preserves the vibes of "vanilla until you discover it isn't"
2025-10-12 06:38:09 -04:00
Anonimus
96a7bc74a1 More stupid odds finagling 2025-10-12 06:37:29 -04:00
Anonimus
6a85a3f41e Revert cvar changes 2025-10-12 06:25:43 -04:00
Anonimus
becc80290d Remove Bubble Shields from cooldown item pool, move it to top half only 2025-10-12 05:37:19 -04:00
Anonimus
1f392e1cee Item littering toggle
With item littering off, dropped items immediately despawn themselves
2025-10-12 01:19:19 -04:00
Anonimus
9449e5aa28 Anti-frustration odds revision
* HEAVILY neuter the chances for Ballhog and 4x Orbinaut in item rolls
* Default Ballhog and 4x Orbi's cvars to "Off"
* Add a system to prevent certain "dudrolls" from appearing in lower placements
* Adjust the chances of 2x Jawz, 2x Sneaker, Invincibility, Sneaker, and Thunder Shield
* Reduce distvars further
2025-10-12 01:19:19 -04:00
GenericHeroGuy
9e3658d4f4 Fix the C stack overflow too 2025-10-11 14:37:53 +02:00
Anonimus
3e2ad4d542 Update credits after god knows how long 2025-10-11 07:54:18 -04:00
GenericHeroGuy
1d4c4cef9e Reset spechit count after moving, not before
Doesn't fix any Lua stack overflows, but at least it doesn't segfault
2025-10-11 13:43:19 +02:00
NepDisk
77fdea2b98 Don't sloperoll other either to keep parity with Bubble 2025-10-10 21:03:33 -04:00
NepDisk
80f363dec8 walltransfeboost 2025-10-10 16:02:20 -04:00
Anonimus
b67e9d07bb Prevent RF_DONTDRAW (and MF2_DONTDRAW) overrides due to eflags 2025-10-10 15:50:23 -04:00
Anonimus
dc9ee0bc95 Legacy mode for ghost objects 2025-10-10 12:42:46 -04:00
Anonimus
324bd3b117 Back-compat: Even more visibility eflags fixes 2025-10-10 12:42:45 -04:00
GenericHeroGuy
85088392eb Fix MK64 chars drift sprite angle
Also don't allow accessing "drawangle" in compatmode, which...
half-fixes grindrails
2025-10-09 23:29:23 +02:00
GenericHeroGuy
3ac73cf9c7 Fix MK64 chars displaying incorrect sprite frames 2025-10-09 22:07:02 +02:00
GenericHeroGuy
7620420c95 Fix several issues with mobj default values 2025-10-09 21:12:30 +02:00
NepDisk
f9013acca3 Port old water splash effects 2025-10-09 15:03:19 -04:00
GenericHeroGuy
8114ece18a Don't overwrite mobj fields with defaults in write mode (whoops!) 2025-10-09 20:43:35 +02:00
NepDisk
1dfb32495b Use transparency 2025-10-09 03:12:51 -04:00
NepDisk
1ad7d23e6b Port old ping display from Saturn 2025-10-09 03:07:39 -04:00
NepDisk
47a95ac76b Port Saturn alternative FPS Counters 2025-10-09 02:46:34 -04:00
NepDisk
82a6edce5d Port old inaccurate fps sample as toggle
For Jon-sama 🥹
2025-10-09 02:34:50 -04:00
NepDisk
6143d8088b Reset to mapobjectscale 2025-10-08 17:45:45 -04:00
toaster
f3c9fb9c82 Correctly NULL thumbnailPic and minimapPic when map lumpnum changes
Fixes the core part of Chengi's graphical issue
2025-10-08 22:01:10 +02:00
Sally Coolatta
cbac99fb90 Don't pad flags in the warning 2025-10-08 22:00:43 +02:00
NepDisk
88626fdf96 Fix lack of discord ifdef here 2025-10-08 13:41:58 -04:00
NepDisk
08d94c4b1b Revert "Repair demos that finish without crashing inexplicably returning to titlescreen after their completion"
This reverts commit a16e800e6e.
2025-10-08 11:50:28 -04:00
James R
868c7777e5 Add cv_palette and cv_palettenum
Cheats; override the current palette
2025-10-08 10:07:57 -04:00
toaster
a16e800e6e Repair demos that finish without crashing inexplicably returning to titlescreen after their completion
It's because of cv_cheats' default value in DEVELOP builds...
2025-10-08 10:05:33 -04:00
NepDisk
6417a7f1f2 Add missing write sets 2025-10-07 20:40:39 -04:00
Anonimus
a2e2f2cbb2 Revert "Fix lap split icon position"
This reverts commit b4be36df23.
Maybe hopefully perhaps this spells the end of our alignment woes.
Ignore the SPB reticle looking like that.
2025-10-07 17:46:15 -04:00
Anonimus
62457690a5 Add pivot vectors and alignment flags to patches
Having to rely on offsets for rotation alignment is annoying and breaks Lua.
So... let's not!
2025-10-07 14:46:03 -04:00
NepDisk
9f8af1a7dd Merge pull request 'Refactor Netsaves' (#160) from refactornetsave into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/160
2025-10-07 19:02:45 +02:00
NepDisk
028d368765 Remove unused functions 2025-10-07 13:03:05 -04:00
NepDisk
151bb79d85 Combine LUA_Archive and LUA_Unarchive 2025-10-07 12:36:36 -04:00
NepDisk
0d7d460cb8 Fix polyobject resyncs 2025-10-07 12:09:24 -04:00
NepDisk
36a01ba0af Refactor polyobjects 2025-10-07 11:50:24 -04:00
NepDisk
ce70e05d30 Merge branch 'blankart-dev' into refactornetsave 2025-10-07 10:57:10 -04:00
Anonimus
6960c52e91 Rework eflags compat (closes #150) 2025-10-07 10:47:02 -04:00
NepDisk
ef95e49e12 Merge pull request 'Fix ground followers phasing through FOFs' (#157) from Wumbo/blankart:followerstuff into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/157
2025-10-06 05:18:28 +02:00
Wumbo
506631c235 Fix ground followers phasing through FOFs 2025-10-05 22:45:42 -04:00
GenericHeroGuy
38898596de Forgot to set a default gravity 2025-10-05 22:55:08 +02:00
GenericHeroGuy
99760c1cc7 Cleanup and some fixes 2025-10-05 22:28:12 +02:00
GenericHeroGuy
fa9c99ff45 Macro the shit out of the thinker tables
These were all out of sync lmao
Now you can join without crashing, but mobjs are fucked
2025-10-05 22:11:11 +02:00
NepDisk
e20841c54f Merge pull request 'Fix build error if latest commit message contains double quotes' (#156) from Wumbo/blankart:lastcommit into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/156
2025-10-05 21:05:37 +02:00
NepDisk
ba1b91b3a3 Sorry 2025-10-05 15:06:30 -04:00
Wumbo
8fc129d003 Fix build error if latest commit message contains double quotes 2025-10-05 14:58:14 -04:00
NepDisk
186fa924cf Revert "Optimize line checks on line interception"
This reverts commit bd9924b794.
2025-10-05 13:37:57 -04:00
NepDisk
3a486311ca Revert "Inline P_PointOnLineSide"
This reverts commit 8f624e664e.
2025-10-05 13:37:50 -04:00
NepDisk
a9c3a9950d Refactor thinkers (currently not working) 2025-10-05 13:36:34 -04:00
NepDisk
72925adaca Merge pull request 'Improve appearance of followers in player setup menu' (#155) from Wumbo/blankart:followerstuff into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/155
2025-10-05 13:17:45 +02:00
Wumbo
c17f5672f6 Improve appearance of followers in player setup menu
- Ground followers now animate correctly and bounce once again
- Improved positioning of followers within the blue box
2025-10-05 02:42:33 -04:00
GenericHeroGuy
d65156d696 Refactor FOF archiving too! 2025-10-05 00:58:23 +02:00
GenericHeroGuy
433f9ea195 Refactor the world 2025-10-05 00:06:28 +02:00
GenericHeroGuy
de7c89bffd A little bit of cleanup 2025-10-04 19:20:03 +02:00
NepDisk
a4e59679fa Whoops forgot to change these 2025-10-04 13:01:24 -04:00
NepDisk
10aeacbe4d Refactor colormaps 2025-10-04 12:19:05 -04:00
NepDisk
649c53b5d9 Refactor waypoints 2025-10-04 12:03:13 -04:00
NepDisk
c0cc66fd40 Sync invintype 2025-10-04 11:40:14 -04:00
NepDisk
1f06351a29 Adapt existing code to SYNC macro 2025-10-04 11:38:55 -04:00
GenericHeroGuy
e3f70bc7fd Red: before C11 generics. Green: after C11 generics 2025-10-04 17:15:46 +02:00
NepDisk
bdfe3344f0 Fix follower using mobjnum on load end 2025-10-04 10:44:57 -04:00
NepDisk
b25cef1d69 Don't keep track of objects that use MF2_DONTSYNC 2025-10-04 10:30:31 -04:00
NepDisk
6f7a01614a Reinstant tracy czone in P_NetSyncTubeWaypoints 2025-10-04 10:01:16 -04:00
NepDisk
17f0c6222f Refactor tubewaypoints and specials 2025-10-04 09:58:41 -04:00
NepDisk
42464d57d8 Merge pull request 'Fix lap split icon position' (#154) from Wumbo/blankart:satisfyocdagain into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/154
2025-10-04 06:17:41 +02:00
Wumbo
b4be36df23 Fix lap split icon position 2025-10-04 00:07:12 -04:00
NepDisk
1ca099ae48 Merge pull request 'Fix player start zpos being ignored on UDMF maps (fixes #152)' (#153) from Wumbo/blankart:fixudmfspawns into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/153
2025-10-04 04:34:41 +02:00
Wumbo
3d188777ac Fix player start zpos being ignored on UDMF maps 2025-10-03 21:47:26 -04:00
NepDisk
944cfa0cc9 Refactor NetSync for Parties 2025-10-03 21:26:28 -04:00
Oni
0fad3c882b Merge branch 'increase-minz' into 'master'
Increase MINZ from 4 fracunits to 16

See merge request KartKrew/Kart!1122
2025-10-03 21:09:18 -04:00
NepDisk
4e8bb42fc5 Refactor NetSync for misc 2025-10-03 20:54:05 -04:00
NepDisk
42532d6bc7 Refactor NetSync for players
This is based on stuff from SRB2Classic adjust for Blan.

This uses a bunch of new functions but later I plan to switch to a _Generic for these.
2025-10-03 19:48:01 -04:00
NepDisk
9ce4fcb2b8 Save a loop for battle init 2025-10-03 13:48:24 -04:00
NepDisk
74d646f39c Why was newz never used? 2025-10-03 13:33:47 -04:00
NepDisk
4ee7e0a253 Warning cleanup 2025-10-03 13:14:27 -04:00
NepDisk
2529cd4abb Fix INT64 print warnings 2025-10-03 13:02:06 -04:00
NepDisk
7547f6224d Merge pull request 'Apply skin wildcards in SPRTINFO to v2 chars only' (#151) from Wumbo/blankart:leavekartskinsalone into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/151
2025-10-03 05:46:07 +02:00
Wumbo
c1b7f089c8 Apply skin wildcards in SPRTINFO to v2 chars only 2025-10-02 23:30:47 -04:00
NepDisk
49e72d15c5 Fix DTF failing if shortcut path is the only path 2025-10-02 17:30:13 -04:00
NepDisk
b860ee3db4 Fix battle conflict 2025-10-02 16:22:39 -04:00
NepDisk
5834d6ea5a Fix battlemode item boxes not respawning (closes #135) 2025-10-02 15:46:58 -04:00
NepDisk
15aded75f9 Split battlebox respawning into its own function 2025-10-02 15:13:15 -04:00
GenericHeroGuy
ef1596caeb Fix karteliminatelast 'No' not working in replays (closes #145) 2025-10-02 15:49:17 +02:00
NepDisk
ba549c0524 Remove duplicate K_StatRound 2025-10-02 09:35:27 -04:00
NepDisk
44605bbce6 Port RR karteliminate last changes 2025-10-01 17:46:24 -04:00
GenericHeroGuy
4eaf109786 Update p.exiting and exitcountdown to match Kart (closes #142)
exitcountdown is now manually set and G_BeginLevelExit doesn't touch it
g_exit now has an "already finished" flag to avoid relying on these
2025-10-01 22:28:41 +02:00
Anonimus
2c75e46855 Return to 32-bit land 2025-10-01 11:10:00 -04:00
NepDisk
200d5e6b08 Merge pull request 'Refactor conga' (#146) from keepdancingbabies into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/146
2025-10-01 16:29:48 +02:00
Anonimus
96063d36ea Refactor conga (yet again)
* Uses IntDistance to get accurate integer-based distancing
* Does not use divisors or multipliers until after distances are chained
* Does a single exaggeration multiplier (currently cuts the distance to 2/3 actual dist) in post
2025-10-01 10:12:10 -04:00
Anonimus
30614c758c 64-bit FixedMul and FixedSqrt, integer sqrt functions 2025-10-01 10:09:31 -04:00
Anonimus
6e6a94a6af Add fixed-point math parity test
Makes sure the more complex functions match regardless of bitdepth
Currently (and very likely to stay) only FixedSqrt
2025-10-01 10:08:57 -04:00
NepDisk
49e9ef1e95 Fix wipes for credits 2025-09-30 21:23:50 -04:00
NepDisk
79df024b62 Fix ITF_STICKER not accounting for width and always compile sticker drawer 2025-09-30 21:01:53 -04:00
toaster
7efef93f6f w_wad for lumpnums: Use bitwise and instead of addition
Makes the mathematical logic of what's being done clearer
2025-09-30 20:03:27 -04:00
GenericHeroGuy
313e291fb6 Fix specator -> spectator teamchanges blocking joins (closes #96)
No longer causes forfeits too!
2025-09-30 21:39:13 +02:00
GenericHeroGuy
9c9041484a Recursively renormalize line endings 2025-09-30 17:37:45 +02:00
NepDisk
ce6cee5f60 Apply hud transparency to itembar and flamebar 2025-09-30 00:54:21 -04:00
NepDisk
2d30b4774f Add fov to menu code 2025-09-30 00:39:23 -04:00
Sally Coolatta
1082667117 Fix human vs bot P_CheckRacers conditions 2025-09-30 00:03:13 -04:00
NepDisk
630b75a504 P_DoPlayerExit changes
12ecb1f7a4
2025-09-30 00:01:05 -04:00
NepDisk
837b28e358 Fix compile warnings 2025-09-29 22:46:01 -04:00
NepDisk
42173120f4 Merge pull request '[ENHANCEMENT] VFX for Bubble Shield' (#144) from dappleup into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/144
2025-09-30 04:40:46 +02:00
Anonimus
7ffb9d6ed4 OH NO ME HEART STOPPED 2025-09-29 22:31:34 -04:00
Anonimus
a2d83f4b5f Dapple up
Add all the bubble shield VFX
2025-09-29 22:31:34 -04:00
minenice55
641f6ae865 Merge pull request '[ENHANCEMENT] Add last minute, last five seconds, and overtime alarms' (#143) from timelimit_alarms into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/143
2025-09-30 04:23:56 +02:00
minenice55
9e88716d39 Merge branch 'blankart-dev' into timelimit_alarms 2025-09-30 04:22:58 +02:00
minenice55
034e24a44f overtime!!! 2025-09-29 21:57:43 -04:00
NepDisk
9e648d859d Fix saltyhop being broken in software 2025-09-29 21:02:02 -04:00
minenice55
c7db0acf59 add last minute and last five seconds sounds to game modes with time limit
guys it's a bell it's just like splatoon guys
2025-09-29 20:15:47 -04:00
GenericHeroGuy
7e810c6923 Fix item boxes inside bustable FOFs messing up collision (closes #100) 2025-09-30 00:26:27 +02:00
GenericHeroGuy
db41399690 Fix flame shield not melting items (closes #140) 2025-09-29 22:27:56 +02:00
GenericHeroGuy
307001611e Make exploding dragged mines hit the player dragging it again (closes #133)
baby mine explosions lmao
2025-09-29 22:01:43 +02:00
GenericHeroGuy
a56213921e Let's see if initializing localfile properly closes #131 2025-09-29 16:37:11 +02:00
Anonimus
fbc33d1517 2D vector rotation 2025-09-29 09:13:50 -04:00
Anonimus
d013159ad9 Get rid of the initial boost thrust
Could easily be abused to skip and cheese ramp setpieces
2025-09-29 09:13:50 -04:00
NepDisk
f29ba22cc8 Make mobj spritex/yoffsets consistant with highresscale
https://git.do.srb2.org/STJr/SRB2/-/merge_requests/2722
2025-09-29 01:13:06 -04:00
Jisk
0621d8f2ce Fix no-physics textmap vertex slopes 2025-09-28 23:46:23 -04:00
Anonimus
8c61f607b1 Initial thrust of a bubble boost now uses movement angle 2025-09-28 21:10:21 -04:00
NepDisk
63cbeed7a6 AAAAA 2025-09-28 16:40:33 -04:00
NepDisk
b665744f45 Revert "Fix addon rejoins (Closes #131)"
This reverts commit 81bd0046b6.
2025-09-28 16:38:59 -04:00
Anonimus
5f337c0a6c Make bubble shield pop boosts cancel on spinouts
Fixes #132 point 2
2025-09-28 15:45:10 -04:00
Anonimus
d9accbd575 Make bubble shields pop if you "overinflate" them 2025-09-28 15:42:59 -04:00
GenericHeroGuy
7a2fd0be42 Fix sneakertimer not resetting for explosions... and APNG AAAAAAACK 2025-09-28 21:39:30 +02:00
GenericHeroGuy
107d3ed6b2 Update hash 2025-09-28 21:27:04 +02:00
NepDisk
857849dba6 Make flameshield damage use the same boost cancel as sneakers 2025-09-28 15:19:51 -04:00
NepDisk
105782c759 Make landmine do flipover damage 2025-09-28 15:17:12 -04:00
NepDisk
81bd0046b6 Fix addon rejoins (Closes #131) 2025-09-28 14:53:11 -04:00
166 changed files with 13009 additions and 9719 deletions

16
.gitattributes vendored
View file

@ -1,9 +1,13 @@
#Source code
/src/*.c text=auto
/src/*.h text=auto
/src/*.s text=auto
/src/*.m text=auto
/src/*.xpm text=auto
/src/**/*.c text=auto
/src/**/*.cpp text=auto
/src/**/*.h text=auto
/src/**/*.hpp text=auto
/src/**/*.s text=auto
/src/**/*.m text=auto
/src/**/*.xpm text=auto
/src/**/Sourcefile text=auto
/src/**/*.mk text=auto
/src/Makefile text=auto
/src/Make*.cfg text=auto
/src/CMakeLists.txt text=auto
@ -20,8 +24,6 @@
*.csproj* -crlf -whitespace
*.vcxproj* -crlf -whitespace
*.manifest -crlf -whitespace
# Patches
/tools/SDL-1.2.14-gc/SDL-1.2.14-gc.patch -whitespace
#Appveyor
/appveyor.yml -crlf -whitespace
# Other

View file

@ -84,6 +84,7 @@ option(SRB2_CONFIG_ZDEBUG "Compile with ZDEBUG defined." OFF)
option(SRB2_CONFIG_PROFILEMODE "Compile for profiling (GCC only)." OFF)
option(SRB2_CONFIG_TRACY "Compile with Tracy profiling enabled" OFF)
option(SRB2_CONFIG_ASAN "Compile with AddressSanitizer (libasan)." OFF)
option(SRB2_CONFIG_UBSAN "Compile with UndefinedBehaviorSanitizer (libubsan)." OFF)
set(SRB2_CONFIG_ASSET_DIRECTORY "" CACHE PATH "Path to directory that contains all asset files for the installer. If set, assets will be part of installation and cpack.")
option(SRB2_CONFIG_LTO "Enable link time optimizations, improves performance at the cost of longer link times." ON)
option(SRB2_CONFIG_TIDY "Enable clang tiny, checks compiled code for issues at the cost of longer compile times." OFF)

View file

@ -59,7 +59,10 @@ POSSIBILITY OF SUCH DAMAGE.
2-Clause BSD License
applies to:
- xxHash Library
Copyright (c) 2012-2021 Yann Collet
Copyright (c) 2012-2023 Yann Collet
All rights reserved.
- LZ4 Library
Copyright (c) 2011-2025 Yann Collet
All rights reserved.
--------------------------------------------------------------------------------

View file

@ -41,6 +41,8 @@ This is still in active development and things are going to change. If you find
## Compiling
Notice: MSVC is unsupported!
Linux:
```
git clone https://codeberg.org/NepDisk/blankart.git
@ -52,6 +54,7 @@ make -j$(nproc)
```
Windows MSYS2:
```
git clone https://codeberg.org/NepDisk/blankart.git
cd blankart

View file

@ -2,8 +2,8 @@
#
# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors
set(CPM_DOWNLOAD_VERSION 0.40.2)
set(CPM_HASH_SUM "c8cdc32c03816538ce22781ed72964dc864b2a34a310d3b7104812a5ca2d835d")
set(CPM_DOWNLOAD_VERSION 0.42.0)
set(CPM_HASH_SUM "2020b4fc42dba44817983e06342e682ecfc3d2f484a581f11cc5731fbe4dce8a")
if(CPM_SOURCE_CACHE)
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")

View file

@ -12,7 +12,8 @@ git_current_branch(SRB2_COMP_BRANCH)
git_working_tree_dirty(SRB2_COMP_UNCOMMITTED)
git_latest_commit(SRB2_COMP_REVISION)
git_subject(SRB2_COMP_LASTCOMMIT)
git_subject(subject)
string(REGEX REPLACE "([\"\\])" "\\\\\\1" SRB2_COMP_LASTCOMMIT "${subject}")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/config.h")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/build/src/config.h")

View file

@ -64,6 +64,11 @@ if(SRB2_CONFIG_ASAN)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=address)
endif()
if(SRB2_CONFIG_UBSAN)
target_compile_options(SRB2SDL2 PRIVATE -fsanitize=undefined)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=undefined)
endif()
if(SRB2_CONFIG_TIDY)
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=*")
endif()
@ -220,7 +225,7 @@ endif()
target_compile_options(SRB2SDL2 PRIVATE -fwrapv)
if (${CMAKE_BUILD_TYPE} MATCHES Debug)
target_compile_options(SRB2SDL2 PRIVATE -O0)
else()
target_compile_options(SRB2SDL2 PRIVATE -O3)
endif()
@ -233,6 +238,7 @@ target_compile_options(SRB2SDL2 PRIVATE
# This is a direct translation from versions.mk
$<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:GNU>>:
-Wall
-Wextra
-Wno-trigraphs
-W # Was controlled by RELAXWARNINGS
-Wfloat-equal
@ -314,6 +320,7 @@ target_compile_options(SRB2SDL2 PRIVATE
# C, Clang and Apple Clang
$<$<AND:$<COMPILE_LANGUAGE:C>,$<OR:$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>>:
-Wall
-Wextra
-Wno-absolute-value
-Wno-trigraphs
-Wno-error=non-literal-null-conversion
@ -322,13 +329,6 @@ target_compile_options(SRB2SDL2 PRIVATE
-Wno-error=unused-but-set-variable
>
# C, MSVC
$<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:MSVC>>:
# All warnings at and before Visual Studio 2019 RTM
# https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warnings-by-compiler-version?view=msvc-170
/Wv:19.20.27004.0
>
# C++, GNU, Clang and Apple Clang
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<OR:$<C_COMPILER_ID:GNU>,$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>>:
-Wall
@ -337,11 +337,6 @@ target_compile_options(SRB2SDL2 PRIVATE
-Wno-unused-private-field
>
# C++, MSVC
$<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:MSVC>>:
/Wv:19.20.27004.0
>
# GNU
$<$<C_COMPILER_ID:GNU>:
-fmax-errors=5
@ -352,10 +347,6 @@ if(SRB2_CONFIG_ERRORMODE)
$<$<OR:$<C_COMPILER_ID:GNU>,$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>:
-Werror
>
$<$<C_COMPILER_ID:MSVC>:
/WX
>
)
endif()
@ -373,7 +364,7 @@ target_compile_definitions(SRB2SDL2 PRIVATE -DCMAKECONFIG)
# Misc. build options from Makefiles
if(SRB2_CONFIG_DEBUGMODE)
target_compile_definitions(SRB2SDL2 PRIVATE -DZDEBUG -DPARANOIA -DRANGECHECK -DPACKETDROP)
target_compile_definitions(SRB2SDL2 PRIVATE -D_DEBUG -DZDEBUG -DPARANOIA -DRANGECHECK -DPACKETDROP)
endif()
if(SRB2_CONFIG_MOBJCONSISTANCY)
target_compile_definitions(SRB2SDL2 PRIVATE -DMOBJCONSISTANCY)

View file

@ -1,71 +1,71 @@
#
# Makefile for feature flags.
#
passthru_opts+=\
NO_IPV6 NOHW NOPOSTPROCESSING\
MOBJCONSISTANCY PACKETDROP ZDEBUG\
HAVE_MINIUPNPC\
HAVE_DISCORDRPC DEVELOP
# build with debugging information
ifdef DEBUGMODE
MOBJCONSISTANCY=1
PACKETDROP=1
opts+=-DPARANOIA -DRANGECHECK
endif
ifndef NOHW
opts+=-DHWRENDER
sources+=$(call List,hardware/Sourcefile)
endif
ifndef NOZLIB
ifndef NOPNG
ifdef PNG_PKGCONFIG
$(eval $(call Use_pkg_config,PNG_PKGCONFIG))
else
PNG_CONFIG?=$(call Prefix,libpng-config)
$(eval $(call Configure,PNG,$(PNG_CONFIG) \
$(if $(PNG_STATIC),--static),,--ldflags))
endif
ifdef LINUX
opts+=-D_LARGEFILE64_SOURCE
endif
opts+=-DHAVE_PNG
sources+=apng.c
endif
endif
ifndef NOCURL
CURLCONFIG?=curl-config
$(eval $(call Configure,CURL,$(CURLCONFIG)))
opts+=-DHAVE_CURL
endif
ifdef HAVE_MINIUPNPC
libs+=-lminiupnpc
endif
ifdef HAVE_DISCORDRPC
$(eval $(call Propogate_flags,DISCORDRPC))
libs+=-ldiscord-rpc
opts+=-DUSE_STUN
sources+=discord.c stun.c
endif
# (Valgrind is a memory debugger.)
ifdef VALGRIND
VALGRIND_PKGCONFIG?=valgrind
$(eval $(call Use_pkg_config,VALGRIND))
ZDEBUG=1
opts+=-DHAVE_VALGRIND
endif
default_packages:=\
GME/libgme/LIBGME\
OPENMPT/libopenmpt/LIBOPENMPT\
ZLIB/zlib\
$(foreach p,$(default_packages),\
$(eval $(call Check_pkg_config,$(p))))
#
# Makefile for feature flags.
#
passthru_opts+=\
NO_IPV6 NOHW NOPOSTPROCESSING\
MOBJCONSISTANCY PACKETDROP ZDEBUG\
HAVE_MINIUPNPC\
HAVE_DISCORDRPC DEVELOP
# build with debugging information
ifdef DEBUGMODE
MOBJCONSISTANCY=1
PACKETDROP=1
opts+=-DPARANOIA -DRANGECHECK
endif
ifndef NOHW
opts+=-DHWRENDER
sources+=$(call List,hardware/Sourcefile)
endif
ifndef NOZLIB
ifndef NOPNG
ifdef PNG_PKGCONFIG
$(eval $(call Use_pkg_config,PNG_PKGCONFIG))
else
PNG_CONFIG?=$(call Prefix,libpng-config)
$(eval $(call Configure,PNG,$(PNG_CONFIG) \
$(if $(PNG_STATIC),--static),,--ldflags))
endif
ifdef LINUX
opts+=-D_LARGEFILE64_SOURCE
endif
opts+=-DHAVE_PNG
sources+=apng.c
endif
endif
ifndef NOCURL
CURLCONFIG?=curl-config
$(eval $(call Configure,CURL,$(CURLCONFIG)))
opts+=-DHAVE_CURL
endif
ifdef HAVE_MINIUPNPC
libs+=-lminiupnpc
endif
ifdef HAVE_DISCORDRPC
$(eval $(call Propogate_flags,DISCORDRPC))
libs+=-ldiscord-rpc
opts+=-DUSE_STUN
sources+=discord.c stun.c
endif
# (Valgrind is a memory debugger.)
ifdef VALGRIND
VALGRIND_PKGCONFIG?=valgrind
$(eval $(call Use_pkg_config,VALGRIND))
ZDEBUG=1
opts+=-DHAVE_VALGRIND
endif
default_packages:=\
GME/libgme/LIBGME\
OPENMPT/libopenmpt/LIBOPENMPT\
ZLIB/zlib\
$(foreach p,$(default_packages),\
$(eval $(call Check_pkg_config,$(p))))

View file

@ -11,7 +11,7 @@
makedir:=$(makedir)/SDL
sources+=$(call List,sdl/Sourcefile)
opts+=-DDIRECTFULLSCREEN -DHAVE_SDL
opts+=-DHAVE_SDL
ifndef NOHW
sources+=sdl/ogl_sdl.c

View file

@ -97,6 +97,7 @@ mserv.c
http-mserv.c
i_tcp.c
lzf.c
lz4.c
lua_script.c
lua_baselib.c
lua_mathlib.c

View file

@ -1633,6 +1633,32 @@ bool CallFunc_PlayerSkin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::
return false;
}
/*--------------------------------------------------
bool CallFunc_PlayerSkinRealName(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
Returns the activating player's skin real name.
--------------------------------------------------*/
bool CallFunc_PlayerSkinRealName(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
{
Environment *env = &ACSEnv;
auto info = &static_cast<Thread *>(thread)->info;
(void)argV;
(void)argC;
if ((info != NULL)
&& (info->mo != NULL && P_MobjWasRemoved(info->mo) == false)
&& (info->mo->player != NULL))
{
UINT16 skin = info->mo->player->skin;
thread->dataStk.push(~env->getString( skins[skin].realname )->idx);
return false;
}
thread->dataStk.push(0);
return false;
}
/*--------------------------------------------------
bool CallFunc_PlayerBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)

View file

@ -76,6 +76,7 @@ bool CallFunc_CountPushables(ACSVM::Thread *thread, const ACSVM::Word *argV, ACS
//bool CallFunc_HaveUnlockableTrigger(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
//bool CallFunc_HaveUnlockable(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
bool CallFunc_PlayerSkin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
bool CallFunc_PlayerSkinRealName(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
bool CallFunc_PlayerBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
bool CallFunc_PlayerLosing(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
bool CallFunc_PlayerExiting(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)

View file

@ -213,7 +213,7 @@ Environment::Environment()
addFuncDataACS0( 319, addCallFunc(CallFunc_PlayerLosing));
addFuncDataACS0( 320, addCallFunc(CallFunc_PlayerExiting));
addFuncDataACS0( 321, addCallFunc(CallFunc_PlayerSkinRealName));
addFuncDataACS0( 322, addCallFunc(CallFunc_Teleport));
addFuncDataACS0( 323, addCallFunc(CallFunc_SetViewpoint));

View file

@ -265,6 +265,11 @@ static void AM_findMinMaxBoundaries(void)
max_w = minimapinfo.map_w << MAPBITS;
max_h = minimapinfo.map_h << MAPBITS;
if (max_w == 0)
max_w = 1;
if (max_h == 0)
max_h = 1;
a = FixedDiv(f_w<<FRACBITS, max_w);
b = FixedDiv(f_h<<FRACBITS, max_h);
@ -340,7 +345,7 @@ static void AM_FrameBufferInit(void)
f_x = f_y = 0;
f_w = vid.width;
f_h = vid.height;
am_buf = screens[0];
am_buf = vid.screens[0];
}
//
@ -352,7 +357,9 @@ static void AM_LevelInit(void)
AM_findMinMaxBoundaries();
scale_mtof = FixedDiv(min_scale_mtof*10, 7*FRACUNIT);
if (scale_mtof > max_scale_mtof)
scale_mtof = min_scale_mtof;
scale_mtof = max_scale_mtof;
if (scale_mtof == 0)
scale_mtof = 1;
scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
}

View file

@ -23,11 +23,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef APNG_H
#define APNG_H
#ifndef _MSC_VER
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#endif
#ifndef _LFS64_LARGEFILE
#define _LFS64_LARGEFILE

View file

@ -46,10 +46,6 @@
** =======================================================
*/
#ifdef _MSC_VER
#pragma warning(disable : 4324)
#endif
/* chain list of long jump buffers */
struct lua_longjmp {
struct lua_longjmp *previous;
@ -57,10 +53,6 @@ struct lua_longjmp {
volatile int status; /* error code */
};
#ifdef _MSC_VER
#pragma warning(default : 4324)
#endif
void luaD_seterrorobj (lua_State *L, int lerrcode, StkId oldtop) {
switch (lerrcode) {
case LUA_ERRMEM: {

View file

@ -48,12 +48,6 @@ LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
LUAI_FUNC void luaD_growstack (lua_State *L, int n);
#ifdef _MSC_VER
#ifndef ATTRNORETURN
#define ATTRNORETURN __declspec(noreturn)
#endif
#endif
#ifndef ATTRNORETURN
#define ATTRNORETURN
#endif

View file

@ -11,12 +11,8 @@
#include <limits.h>
#include <stddef.h>
#ifdef _MSC_VER
#define INT32 __int32
#else
#include <stdint.h>
#define INT32 int32_t
#endif
/*
@ -559,9 +555,6 @@
#define luai_numshl(a,b) ((unsigned)(a)<<(unsigned)(b))
#define luai_numshr(a,b) ((unsigned)(a)>>(unsigned)(b))
#define luai_numnot(a) (~((unsigned)(a)))
#ifdef _MSC_VER
#pragma warning(disable : 4244)
#endif
#endif

View file

@ -232,6 +232,7 @@ FUNCINLINE static ATTRINLINE UINT64 readulonglong(void *ptr)
tmp_i++; \
\
s[tmp_i] = '\0'; \
if (tmp_i == n - 1 && *p == '\0') p++; \
} while (0)
#define READSTRING(p, s) do { \

View file

@ -797,12 +797,10 @@ static void COM_CEcho_f(void)
for (i = 1; i < COM_Argc(); i++)
{
strncat(cechotext, COM_Argv(i), sizeof(cechotext)-1);
strncat(cechotext, " ", sizeof(cechotext)-1);
strlcpy(cechotext, COM_Argv(i), sizeof(cechotext)-1);
strlcpy(cechotext, " ", sizeof(cechotext)-1);
}
cechotext[sizeof(cechotext) - 1] = '\0';
HU_DoCEcho(cechotext);
}
@ -1536,6 +1534,9 @@ void CV_RegisterVar(consvar_t *variable)
}
}
if ((variable->flags & (CV_NETVAR|CV_GUARD)) == CV_GUARD)
I_Error("%s has CV_GUARD but not CV_NETVAR", variable->name);
// link the variable in
if (!(variable->flags & CV_HIDEN))
{
@ -2324,6 +2325,34 @@ void CV_AddValue(consvar_t *var, INT32 increment)
var->changed = 1; // user has changed it now
}
// a GETTER for cvars!?
// used along with CV_GUARD to protect cvar values
INT32 CV_Get(consvar_t *cvar)
{
if (!(cvar->flags & CV_GUARD))
I_Error("CV_Get used with non-CV_GUARD variable %s", cvar->name);
if (modeattacking != ATTACKING_NONE /*|| !K_CanChangeRules()*/)
{
const char *string = cvar->defaultvalue;
INT32 value;
if (CV_CompleteValue(cvar, &string, &value))
return value;
else
I_Error("CV_Get oops");
}
return cvar->value;
}
// reset all CV_GUARD cvars to defaults
void CV_ResetGuardVars(void)
{
for (consvar_t *cvar = consvar_vars; cvar; cvar = cvar->next)
if (cvar->flags & CV_GUARD)
Setvalue(cvar, cvar->defaultvalue, true);
}
void CV_InitFilterVar(void)
{
#if 0

View file

@ -129,6 +129,7 @@ typedef enum
// 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_GUARD = 8192, // protect this cvar's value in singleplayer modes
} cvflags_t;
struct CV_PossibleValue_t
@ -232,6 +233,12 @@ void CV_StealthSet(consvar_t *var, const char *value);
// it a setvalue but with a modulo at the maximum
void CV_AddValue(consvar_t *var, INT32 increment);
// returns the filtered value of a variable
INT32 CV_Get(consvar_t *cvar);
// reset all guarded vars to default
void CV_ResetGuardVars(void);
// write all CV_SAVE variables to config file
void CV_SaveVariables(FILE *f);

View file

@ -73,14 +73,9 @@ static boolean consoleready; // console prompt is ready
INT32 con_destlines; // vid lines used by console at final position
static INT32 con_curlines; // vid lines currently used by console
INT32 con_clipviewtop; // (useless)
static INT32 con_hudlines; // number of console heads up message lines
static INT32 con_hudtime[MAXHUDLINES]; // remaining time of display for hud msg lines
INT32 con_clearlines; // top screen lines to refresh when view reduced
boolean con_hudupdate; // when messages scroll, we need a backgrnd refresh
// console text output
static char *con_line; // console text output current line
static size_t con_cx; // cursor position in current line
@ -440,9 +435,6 @@ void CON_Init(void)
Lock_state();
//note: CON_Ticker should always execute at least once before D_Display()
con_clipviewtop = -1; // -1 does not clip
con_hudlines = atoi(cons_hudlines.defaultvalue);
Unlock_state();
@ -724,7 +716,6 @@ void CON_ToggleOff(void)
con_curlines = 0;
CON_ClearHUD();
con_forcepic = 0;
con_clipviewtop = -1; // remove console clipping of view
I_UpdateMouseGrab();
@ -773,18 +764,6 @@ void CON_Ticker(void)
CON_ChangeHeight();
}
// 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
{
if (con_curlines > 0)
con_clipviewtop = con_curlines - viewwindowy - 1 - 10;
// NOTE: BIG HACK::SUBTRACT 10, SO THAT WATER DON'T COPY LINES OF THE CONSOLE
// WINDOW!!! (draw some more lines behind the bottom of the console)
if (con_clipviewtop < 0)
con_clipviewtop = -1; // maybe not necessary, provided it's < 0
}
// check if console ready for prompt
if (con_destlines >= minheight)
consoleready = true;
@ -1111,9 +1090,6 @@ static void CON_Linefeed(void)
con_line = &con_buffer[(con_cy%con_totallines)*con_width];
memset(con_line, ' ', con_width);
// make sure the view borders are refreshed if hud messages scroll
con_hudupdate = true; // see HU_Erase()
}
// Outputs text into the console text buffer
@ -1486,9 +1462,6 @@ static void CON_DrawHudlines(void)
//V_DrawCharacter(x, y, (p[c]&0xff) | cv_constextsize.value | V_NOSCALESTART, true);
y += charheight;
}
// top screen lines that might need clearing when view is reduced
con_clearlines = y; // this is handled by HU_Erase();
}
// Lactozilla: Draws the console's background picture.
@ -1554,10 +1527,6 @@ static void CON_DrawConsole(void)
if (con_curlines <= 0)
return;
//FIXME: refresh borders only when console bg is translucent
con_clearlines = con_curlines; // clear console draw from view borders
con_hudupdate = true; // always refresh while console is on
// draw console background
if (cons_backpic.value || con_forcepic)
CON_DrawBackpic();
@ -1654,6 +1623,7 @@ static const char *CON_LoadingStrings[LOADED_ALLDONE+1] =
"Init rendering daemon...", //LOADED_RINIT
"Init audio subsystem...", //LOADED_SINITSFXCHANNELS
"Cache HUD...", //LOADED_STINIT
"Test fixed-point arithmetic...", //LOADED_MATHINIT
"Init ACSVM...", //LOADED_ACSINIT
"Check game status...", //LOADED_DCHECKNETGAME
"Now starting..."

View file

@ -52,6 +52,7 @@ typedef enum
LOADED_RINIT,
LOADED_SINITSFXCHANNELS,
LOADED_STINIT,
LOADED_MATHINIT,
LOADED_ACSINIT,
LOADED_DCHECKNETGAME,
LOADED_ALLDONE = LOADED_DCHECKNETGAME,
@ -59,14 +60,9 @@ typedef enum
extern con_loadprogress_t con_startup_loadprogress;
// top clip value for view render: do not draw part of view hidden by console
extern INT32 con_clipviewtop;
// 0 means console if off, or moving out
extern INT32 con_destlines;
extern INT32 con_clearlines; // lines of top of screen to refresh
extern boolean con_hudupdate; // hud messages have changed, need refresh
extern UINT32 con_scalefactor; // console text scale factor
extern consvar_t cons_backcolor, cons_menuhighlight;

View file

@ -42,7 +42,6 @@
#include "r_local.h"
#include "m_argv.h"
#include "p_setup.h"
#include "lzf.h"
#include "lua_script.h"
#include "lua_hook.h"
#include "lonesha256.h"
@ -69,6 +68,14 @@
#include "discord.h"
#endif
#ifdef USE_LZ4
#include "lz4.h"
#elif defined HAVE_ZLIB
#include <zlib.h>
#else
#include "lzf.h"
#endif
//
// NETWORKING
//
@ -85,6 +92,8 @@
#define MAX_REASONLENGTH 30
#define FORCECLOSE 0x8000
I_StaticAssert(sizeof(doomdata_t) < MAXPACKETLENGTH); // can't send a packet larger than the max packet length!
boolean server = true; // true or false but !server == client
#define client (!server)
boolean nodownload = false;
@ -93,7 +102,7 @@ INT32 serverplayer = 0;
char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support)
UINT8 playerconsole[MAXPLAYERS];
plrinfo playerinfo[MAXPLAYERS];
plrinfo playerinfo[MAXPLAYERINFO];
// Server specific vars
UINT8 playernode[MAXPLAYERS];
@ -1067,7 +1076,7 @@ static void SV_SendPlayerInfo(INT32 node)
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
netbuffer->packettype = PT_PLAYERINFO;
for (i = 0; i < MSCOMPAT_MAXPLAYERS; i++)
for (i = 0; i < MAXPLAYERINFO; i++)
{
if (i >= MAXPLAYERS || playernode[i] == UINT8_MAX || !playeringame[i])
{
@ -1081,10 +1090,6 @@ static void SV_SendPlayerInfo(INT32 node)
netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0';
//fetch IP address
//No, don't do that, you fuckface.
memset(netbuffer->u.playerinfo[i].address, 0, 4);
if (G_GametypeHasTeams())
{
if (!players[i].ctfteam)
@ -1108,7 +1113,7 @@ static void SV_SendPlayerInfo(INT32 node)
netbuffer->u.playerinfo[i].data = 0; //players[i].skincolor;
}
HSendPacket(node, false, 0, sizeof(plrinfo) * MSCOMPAT_MAXPLAYERS);
HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERINFO);
}
/** Sends a PT_SERVERCFG packet
@ -1224,8 +1229,18 @@ static void SV_SendSaveGame(INT32 node, boolean resending)
}
// Attempt to compress it.
#if defined USE_LZ4
if ((compressedlen = LZ4_compress_fast((char*)(save.buffer + sizeof(UINT32)), (char*)(compressedsave + sizeof(UINT32)), length - sizeof(UINT32), length - sizeof(UINT32) - 1, LZ4_ACCEL)))
#elif defined HAVE_ZLIB
int compresstatus = compress2(compressedsave + sizeof(UINT32), &compressedlen, save.buffer + sizeof(UINT32), length - sizeof(UINT32), ZLIB_LEVEL);
if (compresstatus == Z_OK)
#else
if ((compressedlen = lzf_compress(save.buffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1)))
#endif
{
CONS_Printf("Compressed savegame of size %zu\n", length - sizeof(UINT32));
CONS_Printf("Compressed savegame is %zu\n", compressedlen);
// Compressing succeeded; send compressed data
P_SaveBufferFree(&save);
@ -1236,6 +1251,8 @@ static void SV_SendSaveGame(INT32 node, boolean resending)
}
else
{
CONS_Alert(CONS_WARNING, "Compressing failed, sending original save game\n");
// Compression failed to make it smaller; send original
Z_Free(compressedsave);
@ -1318,7 +1335,17 @@ static void CL_LoadReceivedSavegame(boolean reloading)
{
UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL);
CONS_Printf("Decompressing compressed savegame of size %zu\n", length - sizeof(UINT32));
#if defined USE_LZ4
LZ4_decompress_safe((char*)save.p, (char*)decompressedbuffer, length - sizeof(UINT32), decompressedlen);
#elif defined HAVE_ZLIB
uncompress(decompressedbuffer, &decompressedlen, save.p, length - sizeof(UINT32));
#else
lzf_decompress(save.p, length - sizeof(UINT32), decompressedbuffer, decompressedlen);
#endif
CONS_Printf("Decompressed save is %zu\n", decompressedlen);
P_SaveBufferFree(&save);
P_SaveBufferFromExisting(&save, decompressedbuffer, decompressedlen);
@ -2695,7 +2722,7 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
playeringame[playernum] = false;
demo_extradata[playernum] |= DXD_PLAYSTATE;
playernode[playernum] = UINT8_MAX;
while (!playeringame[doomcom->numslots-1] && doomcom->numslots > 1)
while (doomcom->numslots > 1 && !playeringame[doomcom->numslots-1])
doomcom->numslots--;
// Reset the name
@ -3623,7 +3650,7 @@ static void SV_GenContext(void)
void D_QuitNetGame(void)
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
if (!netgame || !netbuffer)
if (!netgame || !doomcom)
return;
DEBFILE("===========================================================================\n"
@ -4495,7 +4522,7 @@ static void HandlePlayerInfo(SINT8 node)
{
(void)node;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
for (INT32 i = 0; i < MAXPLAYERS; i++)
for (INT32 i = 0; i < MAXPLAYERINFO; i++)
{
playerinfo[i] = netbuffer->u.playerinfo[i];
}

View file

@ -42,9 +42,9 @@ applications may follow different packet versions.
// be transmitted.
#define MAXSERVERNAME 32
#define MAXSERVERCONTACT 320
#define MAXSERVERDESCRIPTION 320
#define MAXSERVERDESCRIPTIONLINE 40
#define MAXSERVERCONTACT 350
#define MAXSERVERDESCRIPTION 1024
#define MAXSERVERDESCRIPTIONLINE 80
#define DEFAULTDESCSTRING "Welcome to my SRB2Kart server!\n"
// Sends over info via packets to client players.
@ -143,10 +143,6 @@ void Command_Droprate(void);
void Command_Numnodes(void);
#endif
#if defined(_MSC_VER)
#pragma pack(1)
#endif
// Client to server packet
struct clientcmd_pak
{
@ -186,10 +182,6 @@ struct client4cmd_pak
ticcmd_t cmd, cmd2, cmd3, cmd4;
} ATTRPACK;
#ifdef _MSC_VER
#pragma warning(disable : 4200)
#endif
// Server to client packet
// this packet is too large
struct servertics_pak
@ -252,10 +244,6 @@ struct fileack_pak
fileacksegment_t segments[];
} ATTRPACK;
#ifdef _MSC_VER
#pragma warning(default : 4200)
#endif
#define MAXAPPLICATION 16
struct clientconfig_pak
@ -339,7 +327,6 @@ struct plrinfo
{
UINT8 num;
char name[MAXPLAYERNAME+1];
UINT8 address[4]; // sending another string would run us up against MAXPACKETLENGTH
UINT8 team;
UINT16 skin;
UINT8 data; // Color is first four bits, hasflag, isit and issuper have one bit each, the last is unused.
@ -347,17 +334,6 @@ struct plrinfo
UINT16 timeinserver; // In seconds.
} ATTRPACK;
// Shortest player information for join during intermission.
struct plrconfig
{
char name[MAXPLAYERNAME+1];
UINT16 skin;
UINT16 color;
UINT32 pflags;
UINT32 score;
UINT8 ctfteam;
} ATTRPACK;
struct filesneededconfig_pak
{
INT32 first;
@ -404,18 +380,13 @@ struct doomdata_t
serverinfoupdate_pak serverinfoupdate;
askinfo_pak askinfo;
msaskinfo_pak msaskinfo;
plrinfo playerinfo[MSCOMPAT_MAXPLAYERS];
plrconfig playerconfig[MAXPLAYERS];
plrinfo playerinfo[MAXPLAYERINFO];
INT32 filesneedednum;
filesneededconfig_pak filesneededcfg;
netinfo_pak netinfo;
} u; // This is needed to pack diff packet types data together
} ATTRPACK;
#if defined(_MSC_VER)
#pragma pack()
#endif
#define MAXSERVERLIST (MAXNETNODES-1)
struct serverelem_t
{
@ -596,7 +567,7 @@ extern char motd[254], server_context[8];
extern UINT8 playernode[MAXPLAYERS];
/* consoleplayer of this player (splitscreen) */
extern UINT8 playerconsole[MAXPLAYERS];
extern plrinfo playerinfo[MAXPLAYERS];
extern plrinfo playerinfo[MAXPLAYERINFO];
extern SINT8 joinnode;
#define SERVMUS_1 "SRVMS1"

View file

@ -82,6 +82,9 @@
#include "m_random.h" // P_ClearRandom
#include "acs/interface.h"
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <tracy/tracy/Tracy.hpp>
// Put hashes here to get them out of header hell.
@ -90,8 +93,8 @@
#define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291
#define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b
#define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9
#define ASSET_HASH_MAIN_PK3 0xd0bf225260f749ed
#define ASSET_HASH_MAPPATCH_PK3 0xefe28bb9de73a31c
#define ASSET_HASH_MAIN_PK3 0xa49f63046b23999e
#define ASSET_HASH_MAPPATCH_PK3 0x7d1f6b96dd119296
#define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461
#ifdef USE_PATCH_FILE
#define ASSET_HASH_PATCH_PK3 0x0000000000000000
@ -290,7 +293,6 @@ boolean D_RenderLevel(void)
viewwindowy = 0;
viewwindowx = 0;
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
ps_rendercalltime = I_GetPreciseTime();
@ -302,12 +304,12 @@ boolean D_RenderLevel(void)
if (cv_homremoval.value == 1)
{
// Clear the software screen buffer to remove HOM
memset(screens[0], 31, vid.width * vid.height * vid.bpp);
memset(vid.screens[0], 31, vid.width * vid.height);
}
else
{
//'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
memset(screens[0], 32+(timeinmap&15), vid.width * vid.height * vid.bpp);
memset(vid.screens[0], 32+(timeinmap&15), vid.width * vid.height);
}
}
@ -354,29 +356,20 @@ boolean D_RenderLevel(void)
viewwindowx = 0;
viewwindowy = viewheight;
}
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
break;
case 2:
viewwindowx = 0;
viewwindowy = viewheight;
M_Memcpy(ylookup, ylookup3, viewheight*sizeof (ylookup[0]));
break;
case 3:
viewwindowx = viewwidth;
viewwindowy = viewheight;
M_Memcpy(ylookup, ylookup4, viewheight*sizeof (ylookup[0]));
default:
break;
}
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
}
R_RenderPlayerView();
if (i > 0)
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
}
@ -533,19 +526,16 @@ static void D_Display(void)
case GS_LEVEL:
if (!gametic)
break;
HU_Erase();
AM_Drawer();
break;
case GS_INTERMISSION:
Y_IntermissionDrawer();
HU_Erase();
HU_Drawer();
break;
case GS_VOTING:
Y_VoteDrawer();
HU_Erase();
HU_Drawer();
break;
@ -563,31 +553,26 @@ static void D_Display(void)
case GS_CUTSCENE:
F_CutsceneDrawer();
HU_Erase();
HU_Drawer();
break;
case GS_EVALUATION:
F_GameEvaluationDrawer();
HU_Erase();
HU_Drawer();
break;
case GS_CREDITS:
F_CreditDrawer();
HU_Erase();
HU_Drawer();
break;
case GS_BLANCREDITS:
F_BlanCreditDrawer();
HU_Erase();
HU_Drawer();
break;
case GS_SECRETCREDITS:
F_SecretCreditsDrawer();
HU_Erase();
HU_Drawer();
break;
@ -597,7 +582,6 @@ static void D_Display(void)
{
// I don't think HOM from nothing drawing is independent...
F_WaitingPlayersDrawer();
HU_Erase();
HU_Drawer();
}
case GS_DEDICATEDSERVER:
@ -655,7 +639,7 @@ static void D_Display(void)
V_DrawFadeScreen(TC_RAINBOW, (leveltime & 0x20) ? SKINCOLOR_PASTEL : SKINCOLOR_MOONSLAM);
// vid size change is now finished if it was on...
vid.recalc = 0;
vid.recalc = false;
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
@ -777,7 +761,6 @@ static void D_WipeDraw(boolean menu)
I_UpdateNoBlit();
HU_Erase();
HU_Drawer();
if (menu)
{
@ -796,7 +779,6 @@ static void D_WipeDraw(boolean menu)
static double D_EndFrame(precise_t enterprecise, int *frameskip)
{
I_UpdateTime(cv_timescale.value);
// Fully completed frame made.
precise_t finishprecise = I_GetPreciseTime();
@ -818,7 +800,6 @@ static double D_EndFrame(precise_t enterprecise, int *frameskip)
*frameskip = 0;
}
I_UpdateTime(cv_timescale.value);
if (!singletics)
{
precise_t elapsed = finishprecise - enterprecise;
@ -835,7 +816,6 @@ static double D_EndFrame(precise_t enterprecise, int *frameskip)
}
}
I_UpdateTime(cv_timescale.value);
// Capture the time once more to get the real delta time.
finishprecise = I_GetPreciseTime();
deltasecs = (double)((INT64)(finishprecise - enterprecise)) / I_GetPrecisePrecision();
@ -994,7 +974,7 @@ void D_SRB2Loop(void)
{
precise_t enterprecise = I_GetPreciseTime();
g_dc = {};
memset(&g_dc, 0, sizeof(g_dc));
Z_Frame_Reset();
I_UpdateTime(cv_timescale.value);
@ -1030,7 +1010,6 @@ void D_SRB2Loop(void)
#ifdef HW3SOUND
HW3S_BeginFrameUpdate();
#endif
I_UpdateTime(cv_timescale.value);
if (realtics > 0 || singletics)
{
@ -1039,8 +1018,6 @@ void D_SRB2Loop(void)
if (realtics > 8)
realtics = 1;
I_UpdateTime(cv_timescale.value);
// process tics (but maybe not if realtic == 0)
{
ZoneScopedN("TryRunTics");
@ -1078,17 +1055,13 @@ void D_SRB2Loop(void)
renderisnewtic = false;
}
I_UpdateTime(cv_timescale.value);
if (interp)
{
renderdeltatics = FLOAT_TO_FIXED(deltatics);
const boolean lagging = ((deltatics >= 1.0) || hu_stopped);
I_UpdateTime(cv_timescale.value);
R_SetTimeFrac(lagging ? FRACUNIT : g_time.timefrac);
R_SetTimeFrac(lagging ? FRACUNIT : I_GetTimeFrac());
}
else
{
@ -1096,8 +1069,6 @@ void D_SRB2Loop(void)
R_SetTimeFrac(FRACUNIT);
}
I_UpdateTime(cv_timescale.value);
if (interp || doDisplay)
{
if (!frameskip)
@ -1109,12 +1080,6 @@ void D_SRB2Loop(void)
// always update console and hud
// otherwise it may take minutes to open it
CON_Drawer();
if (gamestate == GS_LEVEL)
{
ST_Drawer();
HU_Drawer();
}
}
}
@ -1624,6 +1589,7 @@ void D_SRB2Main(void)
if (!dedicated)
{
CV_RegisterVar(&cv_ticrate);
CV_RegisterVar(&cv_accuratefps);
CV_RegisterVar(&cv_constextsize);
}
@ -1735,9 +1701,7 @@ void D_SRB2Main(void)
//--------------------------------------------------------- CONFIG.CFG
M_FirstLoadConfig(); // WARNING : this do a "COM_BufExecute()"
#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen
#endif
// set user default mode or mode set at cmdline
SCR_CheckDefaultMode();
@ -1814,6 +1778,61 @@ void D_SRB2Main(void)
ST_Init();
CON_SetLoadingProgress(LOADED_STINIT);
CONS_Printf("FixedSqrt of 32767 fracunits: %d; FixedSqrt64: %" PRId64 "\n",
FixedSqrt(0x7FFF0000),
FixedSqrt64(0x7FFF0000));
if (FixedSqrt(0x7FFF0000) == FixedSqrt64(0x7FFF0000))
{
CONS_Printf("\x83" "32767: Test OK!" "\x80" "\n");
}
else
{
CONS_Printf("\x85" "32767: Test NG!" "\x80" "\n");
}
CONS_Printf("FixedSqrt of 4 fracunits: %d; FixedSqrt64: %" PRId64 "\n",
FixedSqrt(0x40000),
FixedSqrt64(0x40000));
if (FixedSqrt(0x40000) == FixedSqrt64(0x40000))
{
CONS_Printf("\x83" "4: Test OK!" "\x80" "\n");
}
else
{
CONS_Printf("\x85" "4: Test NG!" "\x80" "\n");
}
// You should probably generate the weird number with RANDOM.org
#define WEIRDNUMBER 3886284 /* 59.3 fracunits; this should approximate to around 7 */
CONS_Printf("FixedSqrt of 59.3 fracunits: %d; FixedSqrt64: %" PRId64 "\n",
FixedSqrt(WEIRDNUMBER),
FixedSqrt64(WEIRDNUMBER));
if (FixedSqrt(WEIRDNUMBER) == FixedSqrt64(WEIRDNUMBER))
{
CONS_Printf("\x83" "59.3: Test OK!" "\x80" "\n");
}
else
{
CONS_Printf("\x85" "59.3: Test NG!" "\x80" "\n");
}
#undef WEIRDNUMBER
CONS_Printf("FixedSqrt64 of 65535 fracunits: %" PRId64 "(not possible at 32-bit scale)\n",
FixedSqrt64(0xFFFFFFFF));
CONS_Printf("IntSqrt of 32767: %d; IntSqrt64: %" PRId64 "\n",
IntSqrt(0x7FFF),
IntSqrt64(0x7FFF));
CONS_Printf("IntSqrt of 4: %d; IntSqrt64: %" PRId64 "\n",
IntSqrt(4),
IntSqrt64(4));
CON_SetLoadingProgress(LOADED_MATHINIT);
CONS_Printf("ACS_Init(): Init Action Code Script VM.\n");
ACS_Init();
CON_SetLoadingProgress(LOADED_ACSINIT);
@ -1833,6 +1852,10 @@ void D_SRB2Main(void)
I_Error("Bad '%s' level warp.\n"
#if defined (_WIN32)
"Are you using MSDOS 8.3 filenames in Zone Builder?\n"
"\n"
"To check: edit the BlanKart game configuration in Ultimate Lowee Builder.\n"
"Go to the Testing tab and make sure \"Use short paths and file names\" is turned off.\n"
"(The option is hidden by default. Check \"Customize parameters\" to show it.)\n"
#endif
, word);
}
@ -1894,7 +1917,7 @@ void D_SRB2Main(void)
}
else if (M_CheckParm("-record") && M_IsNextParm())
{
G_RecordDemo(M_GetNextParm());
G_RecordDemo(va("%s.lmp", M_GetNextParm()));
autostart = true;
}

View file

@ -161,6 +161,8 @@ static void KartSlipdash_OnChange(void);
static void KartSlopeBoost_OnChange(void);
static void KartDrafting_OnChange(void);
static void KartAirDrop_OnChange(void);
static void KartItemLitter_OnChange(void);
static void KartAntiBump_OnChange(void);
static void KartItemBreaker_OnChange(void);
static void KartInvinType_OnChange(void);
static void KartBumpSpark_OnChange(void);
@ -289,7 +291,7 @@ static CV_PossibleValue_t ingamecap_cons_t[] = {{0, "MIN"}, {MAXPLAYERS-1, "MAX"
consvar_t cv_ingamecap = CVAR_INIT ("ingamecap", "0", CV_NETVAR, ingamecap_cons_t, NULL);
static CV_PossibleValue_t spectatorreentry_cons_t[] = {{0, "MIN"}, {10*60, "MAX"}, {0, NULL}};
consvar_t cv_spectatorreentry = CVAR_INIT ("spectatorreentry", "30", CV_NETVAR, spectatorreentry_cons_t, NULL);
consvar_t cv_spectatorreentry = CVAR_INIT ("spectatorreentry", "0", CV_NETVAR, spectatorreentry_cons_t, NULL); // bugged in kart, default to 0 to match expected behavior
static CV_PossibleValue_t antigrief_cons_t[] = {{20, "MIN"}, {60, "MAX"}, {0, "Off"}, {0, NULL}};
consvar_t cv_antigrief = CVAR_INIT ("antigrief", "30", CV_NETVAR, antigrief_cons_t, NULL);
@ -387,7 +389,7 @@ consvar_t cv_eggmanmonitor = CVAR_INIT ("eggmanmonitor", "On", CV_NETVAR|CV_C
consvar_t cv_orbinaut = CVAR_INIT ("orbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_jawz = CVAR_INIT ("jawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_mine = CVAR_INIT ("mine", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_ballhog = CVAR_INIT ("ballhog", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_ballhog = CVAR_INIT ("ballhog", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_selfpropelledbomb = CVAR_INIT ("selfpropelledbomb", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_grow = CVAR_INIT ("grow", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_shrink = CVAR_INIT ("shrink", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
@ -395,17 +397,17 @@ consvar_t cv_thundershield = CVAR_INIT ("thundershield", "On", CV_NETVAR|CV_C
consvar_t cv_hyudoro = CVAR_INIT ("hyudoro", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_pogospring = CVAR_INIT ("pogospring", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_kitchensink = CVAR_INIT ("kitchensink", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_superring = CVAR_INIT ("superring", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_landmine = CVAR_INIT ("landmine", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_bubbleshield = CVAR_INIT ("bubbleshield", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_flameshield = CVAR_INIT ("flameshield", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_superring = CVAR_INIT ("superring", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_landmine = CVAR_INIT ("landmine", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_bubbleshield = CVAR_INIT ("bubbleshield", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_flameshield = CVAR_INIT ("flameshield", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_dualsneaker = CVAR_INIT ("dualsneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_triplesneaker = CVAR_INIT ("triplesneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_triplebanana = CVAR_INIT ("triplebanana", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_decabanana = CVAR_INIT ("decabanana", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_tripleorbinaut = CVAR_INIT ("tripleorbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_quadorbinaut = CVAR_INIT ("quadorbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_quadorbinaut = CVAR_INIT ("quadorbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_dualjawz = CVAR_INIT ("dualjawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
static CV_PossibleValue_t kartminimap_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}};
@ -456,7 +458,7 @@ consvar_t cv_kartbot_basetrackcomplexity = CVAR_INIT ("kartbot_basetrackcomplexi
consvar_t cv_karteliminatelast = CVAR_INIT ("karteliminatelast", "Yes", CV_NETVAR|CV_CALL, CV_YesNo, KartEliminateLast_OnChange);
// Toggles for new features
consvar_t cv_kartrings = CVAR_INIT ("kartrings", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartRings_OnChange);
consvar_t cv_kartrings = CVAR_INIT ("kartrings", "No", CV_NETVAR|CV_CALL|CV_NOINIT|CV_GUARD, CV_YesNo, KartRings_OnChange);
static CV_PossibleValue_t ringsmin_cons_t[] = {{INT8_MIN, "MIN"}, {0, "MAX"}, {0, NULL}};
static CV_PossibleValue_t ringsmax_cons_t[] = {{0, "MIN"}, {INT8_MAX, "MAX"}, {0, NULL}};
@ -468,67 +470,71 @@ static CV_PossibleValue_t ringsstart_cons_t[] = {{INT8_MIN, "MIN"}, {INT8_MAX, "
consvar_t cv_kartringsstart = CVAR_INIT ("kartringsstart", "5", CV_NETVAR, ringsstart_cons_t, NULL);
// Stacking related
consvar_t cv_kartstacking = CVAR_INIT ("kartstacking", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartStacking_OnChange);
consvar_t cv_kartstacking_diminishparam = CVAR_INIT ("kartstacking_diminishparam", "0.32", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_maxvanillaboost = CVAR_INIT ("kartstacking_maxvanillaboost", "0.375", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_speedboostdropoff = CVAR_INIT ("kartstacking_speedboostdropoff", "0.01", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_speedboostdropoff_brake = CVAR_INIT ("kartstacking_speedboostdropoff_brake", "0.05", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking = CVAR_INIT ("kartstacking", "No", CV_NETVAR|CV_CALL|CV_NOINIT|CV_GUARD, CV_YesNo, KartStacking_OnChange);
consvar_t cv_kartstacking_diminishparam = CVAR_INIT ("kartstacking_diminishparam", "0.32", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_maxvanillaboost = CVAR_INIT ("kartstacking_maxvanillaboost", "0.375", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_speedboostdropoff = CVAR_INIT ("kartstacking_speedboostdropoff", "0.01", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_speedboostdropoff_brake = CVAR_INIT ("kartstacking_speedboostdropoff_brake", "0.05", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
// V recreates neptunes old ass misread of stacking code lmao
consvar_t cv_kartstacking_accelstack = CVAR_INIT ("kartstacking_accelstack", "Off", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartstacking_accelstack = CVAR_INIT ("kartstacking_accelstack", "Off", CV_NETVAR|CV_GUARD, CV_OnOff, NULL);
// Vanilla Stacking boosts.
consvar_t cv_kartstacking_sneaker_easyspeedboost = CVAR_INIT ("vanillaboost_sneaker_easyspeedboost", "0.8317", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_sneaker_normalspeedboost = CVAR_INIT ("vanillaboost_sneaker_normalspeedboost", "0.5", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_sneaker_hardspeedboost = CVAR_INIT ("vanillaboost_sneaker_hardspeedboost", "0.2756", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_sneaker_expertspeedboost = CVAR_INIT ("vanillaboost_sneaker_expertspeedboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_sneaker_accelboost = CVAR_INIT ("vanillaboost_sneaker_accelboost", "8.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_sneaker_maxgrade = CVAR_INIT ("vanillaboost_sneaker_maxgrade", "3", CV_NETVAR|CV_CHEAT, CV_Natural, NULL);
consvar_t cv_kartstacking_sneaker_stackable = CVAR_INIT ("vanillaboost_sneaker_stackable", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartstacking_sneaker_easyspeedboost = CVAR_INIT ("vanillaboost_sneaker_easyspeedboost", "0.8317", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_sneaker_normalspeedboost = CVAR_INIT ("vanillaboost_sneaker_normalspeedboost", "0.5", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_sneaker_hardspeedboost = CVAR_INIT ("vanillaboost_sneaker_hardspeedboost", "0.2756", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_sneaker_expertspeedboost = CVAR_INIT ("vanillaboost_sneaker_expertspeedboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_sneaker_accelboost = CVAR_INIT ("vanillaboost_sneaker_accelboost", "8.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_sneaker_maxgrade = CVAR_INIT ("vanillaboost_sneaker_maxgrade", "3", CV_NETVAR|CV_CHEAT|CV_GUARD, CV_Natural, NULL);
consvar_t cv_kartstacking_sneaker_stackable = CVAR_INIT ("vanillaboost_sneaker_stackable", "On", CV_NETVAR|CV_GUARD, CV_OnOff, NULL);
consvar_t cv_kartstacking_invincibility_legacyspeedboost = CVAR_INIT ("vanillaboost_invincibility_legacyspeedboost", "0.375", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_legacyaccelboost = CVAR_INIT ("vanillaboost_invincibility_legacyaccelboost", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_alternatespeedboost = CVAR_INIT ("vanillaboost_invincibility_alternatespeedboost", "0.68", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_alternateaccelboost = CVAR_INIT ("vanillaboost_invincibility_alternateaccelboost", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_stackable = CVAR_INIT ("vanillaboost_invincibility_stackable", "Off", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartstacking_invincibility_legacyspeedboost = CVAR_INIT ("vanillaboost_invincibility_legacyspeedboost", "0.375", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_legacyaccelboost = CVAR_INIT ("vanillaboost_invincibility_legacyaccelboost", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_alternatespeedboost = CVAR_INIT ("vanillaboost_invincibility_alternatespeedboost", "0.68", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_alternateaccelboost = CVAR_INIT ("vanillaboost_invincibility_alternateaccelboost", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_stackable = CVAR_INIT ("vanillaboost_invincibility_stackable", "On", CV_NETVAR|CV_GUARD, CV_OnOff, NULL);
consvar_t cv_kartstacking_grow_speedboost = CVAR_INIT ("vanillaboost_grow_speedboost", "0.2", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_grow_accelboost = CVAR_INIT ("vanillaboost_grow_accelboost", "0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_grow_stackable = CVAR_INIT ("vanillaboost_grow_stackable", "Off", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartstacking_grow_speedboost = CVAR_INIT ("vanillaboost_grow_speedboost", "0.2", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_grow_accelboost = CVAR_INIT ("vanillaboost_grow_accelboost", "0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_grow_stackable = CVAR_INIT ("vanillaboost_grow_stackable", "Off", CV_NETVAR|CV_GUARD, CV_OnOff, NULL);
consvar_t cv_kartstacking_flame_speedval = CVAR_INIT ("vanillaboost_flame_speedval", "0.90", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_flame_accelboost = CVAR_INIT ("vanillaboost_flame_accelboost", "6.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_flame_stackable = CVAR_INIT ("vanillaboost_flame_stackable", "Off", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartstacking_bubble_speedboost = CVAR_INIT ("vanillaboost_bubble_speedboost", "0.3", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_bubble_accelboost = CVAR_INIT ("vanillaboost_bubble_accelboost", "4.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_bubble_stackable = CVAR_INIT ("vanillaboost_bubble_stackable", "Off", CV_NETVAR|CV_GUARD, CV_OnOff, NULL);
consvar_t cv_kartstacking_start_speedboost = CVAR_INIT ("vanillaboost_start_speedboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_start_accelboost = CVAR_INIT ("vanillaboost_start_accelboost", "6.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_start_stackable = CVAR_INIT ("vanillaboost_start_stackable", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartstacking_flame_speedval = CVAR_INIT ("vanillaboost_flame_speedval", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_flame_accelboost = CVAR_INIT ("vanillaboost_flame_accelboost", "6.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_flame_stackable = CVAR_INIT ("vanillaboost_flame_stackable", "On", CV_NETVAR|CV_GUARD, CV_OnOff, NULL);
consvar_t cv_kartstacking_walltransfer_speedboost = CVAR_INIT ("vanillaboost_walltransfer_speedboost", "0.10", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_walltransfer_accelboost = CVAR_INIT ("vanillaboost_walltransfer_accelboost", "5.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_walltransfer_stackable = CVAR_INIT ("vanillaboost_walltransfer_stackable", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartstacking_start_speedboost = CVAR_INIT ("vanillaboost_start_speedboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_start_accelboost = CVAR_INIT ("vanillaboost_start_accelboost", "6.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_start_stackable = CVAR_INIT ("vanillaboost_start_stackable", "On", CV_NETVAR|CV_GUARD, CV_OnOff, NULL);
consvar_t cv_kartstacking_drift_speedboost = CVAR_INIT ("vanillaboost_drift_speedboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_drift_accelboost = CVAR_INIT ("vanillaboost_drift_accelboost", "4.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_drift_stackable = CVAR_INIT ("vanillaboost_drift_stackable", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartstacking_walltransfer_speedboost = CVAR_INIT ("vanillaboost_walltransfer_speedboost", "0.10", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_walltransfer_accelboost = CVAR_INIT ("vanillaboost_walltransfer_accelboost", "5.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_walltransfer_stackable = CVAR_INIT ("vanillaboost_walltransfer_stackable", "On", CV_NETVAR|CV_GUARD, CV_OnOff, NULL);
consvar_t cv_kartstacking_ring_speedboost = CVAR_INIT ("vanillaboost_ring_speedboost", "0.2", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_ring_accelboost = CVAR_INIT ("vanillaboost_ring_accelboost", "4.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_ring_stackable = CVAR_INIT ("vanillaboost_ring_stackable", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_kartstacking_drift_speedboost = CVAR_INIT ("vanillaboost_drift_speedboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_drift_accelboost = CVAR_INIT ("vanillaboost_drift_accelboost", "4.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_drift_stackable = CVAR_INIT ("vanillaboost_drift_stackable", "On", CV_NETVAR|CV_GUARD, CV_OnOff, NULL);
consvar_t cv_kartstacking_slope_decay = CVAR_INIT ("vanillaboost_slope_decay", "0.004", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_slope_brakemod = CVAR_INIT ("vanillaboost_slope_brakemod", "0.01", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_slope_speedboost_max = CVAR_INIT ("vanillaboost_slope_speedboost_max", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_slope_speedboost_cap = CVAR_INIT ("vanillaboost_slope_speedboost_cap", "1.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_slope_accelboost = CVAR_INIT ("vanillaboost_slope_accelboost", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_slope_stackable = CVAR_INIT ("vanillaboost_slope_stackable", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartstacking_ring_speedboost = CVAR_INIT ("vanillaboost_ring_speedboost", "0.2", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_ring_accelboost = CVAR_INIT ("vanillaboost_ring_accelboost", "4.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_ring_stackable = CVAR_INIT ("vanillaboost_ring_stackable", "On", CV_NETVAR|CV_CHEAT|CV_GUARD, CV_OnOff, NULL);
consvar_t cv_kartstacking_slope_decay = CVAR_INIT ("vanillaboost_slope_decay", "0.004", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_slope_brakemod = CVAR_INIT ("vanillaboost_slope_brakemod", "0.01", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_slope_speedboost_max = CVAR_INIT ("vanillaboost_slope_speedboost_max", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_slope_speedboost_cap = CVAR_INIT ("vanillaboost_slope_speedboost_cap", "1.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_slope_accelboost = CVAR_INIT ("vanillaboost_slope_accelboost", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartstacking_slope_stackable = CVAR_INIT ("vanillaboost_slope_stackable", "On", CV_NETVAR|CV_GUARD, CV_OnOff, NULL);
// Max speed for high speeds
consvar_t cv_kartstacking_drafting_minspeed = CVAR_INIT ("vanillaboost_draft_minspeed", "0.16", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_drafting_minspeed = CVAR_INIT ("vanillaboost_draft_minspeed", "0.16", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
// Max speed for low speeds
consvar_t cv_kartstacking_drafting_maxspeed = CVAR_INIT ("vanillaboost_draft_maxspeed", "0.26", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_drafting_maxspeed = CVAR_INIT ("vanillaboost_draft_maxspeed", "0.26", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartchaining = CVAR_INIT ("kartchaining", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartChaining_OnChange);
consvar_t cv_kartchaining = CVAR_INIT ("kartchaining", "No", CV_NETVAR|CV_CALL|CV_NOINIT|CV_GUARD, CV_YesNo, KartChaining_OnChange);
consvar_t cv_kartchainingoffroad = CVAR_INIT ("kartchaining_chainoffroad", "No", CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_kartitembreaker = CVAR_INIT ("kartitembreaker", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartItemBreaker_OnChange);
@ -537,7 +543,7 @@ consvar_t cv_kartitembreaker = CVAR_INIT ("kartitembreaker", "No", CV_NETVAR|CV_
consvar_t cv_kartusepwrlv = CVAR_INIT ("kartusepwrlv", "Yes", CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_kartpurpledrift = CVAR_INIT ("kartpurpledrift", "No", CV_NETVAR, CV_YesNo, KartPurpleDrift_OnChange);
consvar_t cv_kartpurpledrift = CVAR_INIT ("kartpurpledrift", "No", CV_NETVAR|CV_CALL|CV_NOINIT|CV_GUARD, CV_YesNo, KartPurpleDrift_OnChange);
static CV_PossibleValue_t bumpspark_cons_t[] = {{BUMPSPARK_NONE, "Off"},
{BUMPSPARK_NOCHARGE, "Remove Charge Only"},
@ -547,32 +553,39 @@ static CV_PossibleValue_t bumpspark_cons_t[] = {{BUMPSPARK_NONE, "Off"},
consvar_t cv_kartbumpspark = CVAR_INIT("kartbumpspark",
"Remove Charge Only",
CV_NETVAR | CV_CALL,
CV_NETVAR | CV_CALL | CV_NOINIT | CV_GUARD,
bumpspark_cons_t,
KartBumpSpark_OnChange);
consvar_t cv_kartbumpspring = CVAR_INIT ("kartbumpspring", "Yes", CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_kartslipdash = CVAR_INIT ("kartslipdash", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartSlipdash_OnChange);
consvar_t cv_kartslipdash = CVAR_INIT ("kartslipdash", "No", CV_NETVAR|CV_CALL|CV_NOINIT|CV_GUARD, CV_YesNo, KartSlipdash_OnChange);
consvar_t cv_kartslopeboost = CVAR_INIT ("kartslopeboost", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartSlopeBoost_OnChange);
consvar_t cv_kartdrafting = CVAR_INIT ("kartdrafting", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartDrafting_OnChange);
consvar_t cv_kartdrafting = CVAR_INIT ("kartdrafting", "No", CV_NETVAR|CV_CALL|CV_NOINIT|CV_GUARD, CV_YesNo, KartDrafting_OnChange);
consvar_t cv_kartdrafting_closedraft = CVAR_INIT ("kartdrafting_closedraft", "Off", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartdrafting_closedeadzone = CVAR_INIT ("kartdrafting_closedeadzone", "640", CV_NETVAR|CV_CHEAT, CV_Unsigned, NULL);
consvar_t cv_kartdrafting_basedistance = CVAR_INIT ("kartdrafting_basedistance", "2560", CV_NETVAR|CV_CHEAT, CV_Unsigned, NULL);
consvar_t cv_kartairdrop = CVAR_INIT ("kartairdrop", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartAirDrop_OnChange);
consvar_t cv_kartairdrop = CVAR_INIT ("kartairdrop", "No", CV_NETVAR|CV_CALL|CV_NOINIT|CV_GUARD, CV_YesNo, KartAirDrop_OnChange);
consvar_t cv_kartitemlitter = CVAR_INIT ("kartitemlitter", "On", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartItemLitter_OnChange);
#define ANTIBUMP_MAX (UINT32_MAX / TICRATE)
static CV_PossibleValue_t antibump_cons_t[] = {{0, "MIN"}, {ANTIBUMP_MAX, "MAX"}, {0, NULL}};
consvar_t cv_kartantibump = CVAR_INIT ("kartantibump", "0", CV_NETVAR|CV_CALL|CV_NOINIT, antibump_cons_t, KartAntiBump_OnChange);
#undef ANTIBUMP_MAX
// Odds distancing
#define MAXODDSDIST ((INT32_MAX / FRACUNIT) / 2)
static CV_PossibleValue_t distvar_cons_t[] = {{1, "MIN"}, {MAXODDSDIST, "MAX"}, {0, NULL}};
consvar_t cv_kartoddsdist = CVAR_INIT ("kartoddsdist", "2048", CV_NETVAR|CV_CHEAT, distvar_cons_t, NULL);
consvar_t cv_kartlegacyoddsdist = CVAR_INIT ("kartlegacyoddsdist", "2048", CV_NETVAR|CV_CHEAT, distvar_cons_t, NULL);
consvar_t cv_kartoddsdist = CVAR_INIT ("kartoddsdist", "1024", CV_NETVAR|CV_CHEAT|CV_GUARD, distvar_cons_t, NULL);
consvar_t cv_kartlegacyoddsdist = CVAR_INIT ("kartlegacyoddsdist", "1472", CV_NETVAR|CV_CHEAT|CV_GUARD, distvar_cons_t, NULL);
// SPB distance; no legacy modifiers currently (lazy)
static CV_PossibleValue_t spbdist_cons_t[] = {{1, "MIN"}, {32000, "MAX"}, {0, NULL}};
consvar_t cv_kartspbdist = CVAR_INIT ("kartspbdist", "8192", CV_NETVAR|CV_CHEAT, spbdist_cons_t, NULL);
consvar_t cv_kartspbdist = CVAR_INIT ("kartspbdist", "6144", CV_NETVAR|CV_CHEAT|CV_GUARD, spbdist_cons_t, NULL);
#undef MAXODDSDIST
// Invincibility modifiers
@ -581,12 +594,12 @@ consvar_t cv_kartinvintype = CVAR_INIT ("kartinvintype", "Legacy", CV_NETVAR|CV_
// How far the player must be from the cluster to begin frequently rolling Invincibility.
static CV_PossibleValue_t invindist_cons_t[] = {{1, "MIN"}, {32000, "MAX"}, {0, NULL}};
consvar_t cv_kartinvindist = CVAR_INIT ("kartinvindist", "8400", CV_NETVAR|CV_CHEAT, invindist_cons_t, NULL);
consvar_t cv_kartinvindist = CVAR_INIT ("kartinvindist", "8400", CV_NETVAR|CV_CHEAT|CV_GUARD, invindist_cons_t, NULL);
consvar_t cv_kartinvindistmul = CVAR_INIT ("kartinvindistmul", "0.54", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartinvindistmul = CVAR_INIT ("kartinvindistmul", "0.54", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartinvin_maxtime = CVAR_INIT ("kartinvin_maxtime", "35.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartinvin_midtime = CVAR_INIT ("kartinvin_midtime", "23.333", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartinvin_maxtime = CVAR_INIT ("kartinvin_maxtime", "35.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
consvar_t cv_kartinvin_midtime = CVAR_INIT ("kartinvin_midtime", "23.333", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL);
static CV_PossibleValue_t kartdebugitem_cons_t[] =
{
@ -682,6 +695,10 @@ consvar_t cv_showping = CVAR_INIT ("showping", "Always", CV_SAVE, showping_cons_
static CV_PossibleValue_t pingmeasurement_cons_t[] = {{0, "Frames"}, {1, "Milliseconds"}, {0, NULL}};
consvar_t cv_pingmeasurement = CVAR_INIT ("pingmeasurement", "Frames", CV_SAVE, pingmeasurement_cons_t, NULL);
consvar_t cv_pingicon = CVAR_INIT ("pingicon", "On", CV_SAVE, CV_OnOff, NULL);
static CV_PossibleValue_t cv_pingstyle_cons_t[] = {{0, "New"}, {1, "Old"}, {0, NULL}};
consvar_t cv_pingstyle = CVAR_INIT ("pingstyle", "New", CV_SAVE, cv_pingstyle_cons_t, NULL);
static CV_PossibleValue_t showlapemblem_cons_t[] = {{0, "Off"}, {1, "Emblem Only"}, {2, "Splits Only"}, {3, "All"}, {0, NULL}};
consvar_t cv_showlapemblem = CVAR_INIT ("showlapemblem", "All", CV_SAVE, showlapemblem_cons_t, NULL);
@ -1012,6 +1029,8 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_pingtimeout);
CV_RegisterVar(&cv_showping);
CV_RegisterVar(&cv_pingmeasurement);
CV_RegisterVar(&cv_pingicon);
CV_RegisterVar(&cv_pingstyle);
CV_RegisterVar(&cv_showminimapnames);
CV_RegisterVar(&cv_showminimapangle);
CV_RegisterVar(&cv_minihead);
@ -1219,6 +1238,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_csaturation);
CV_RegisterVar(&cv_bsaturation);
CV_RegisterVar(&cv_msaturation);
CV_RegisterVar(&cv_palette);
CV_RegisterVar(&cv_palettenum);
// m_menu.c
//CV_RegisterVar(&cv_compactscoreboard);
@ -1245,6 +1266,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_shrinkme[i]);
CV_RegisterVar(&cv_deadzone[i]);
CV_RegisterVar(&cv_deadzonestyle[i]);
CV_RegisterVar(&cv_litesteer[i]);
CV_RegisterVar(&cv_turnsmooth[i]);
}
// filesrch.c
@ -1256,7 +1279,6 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_addons_search_case);
CV_RegisterVar(&cv_controlperkey);
CV_RegisterVar(&cv_turnsmooth);
CV_RegisterVar(&cv_usemouse);
CV_RegisterVar(&cv_invertmouse);
@ -1975,11 +1997,6 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
// set follower
K_SetFollowerByNum(playernum, follower);
#ifdef HAVE_DISCORDRPC
if (playernum == consoleplayer)
DRPC_UpdatePresence();
#endif
}
enum {
@ -3622,6 +3639,12 @@ static void HandleRespawnCommand(UINT8 localplayer)
return;
}
if (players[g_localplayers[localplayer]].mo && players[g_localplayers[localplayer]].exiting)
{
CONS_Printf(M_GetText("You have no reason to respawn.\n"));
return;
}
WRITEUINT8(cp, g_localplayers[localplayer]);
SendNetXCmdForPlayer(localplayer, XD_RESPAWN, &buf, sizeof(buf));
}
@ -4202,7 +4225,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
demo_extradata[playernum] |= DXD_PLAYSTATE;
// Clear player score and rings if a spectator.
if (players[playernum].spectator)
if (players[playernum].spectator && !wasspectator)
{
players[playernum].spectatorreentry = (cv_spectatorreentry.value * TICRATE);
@ -5617,7 +5640,7 @@ retryscramble:
memset(&scrambleplayers, 0, sizeof(scrambleplayers));
memset(&scrambleteams, 0, sizeof(scrambleplayers));
scrambletotal = scramblecount = 0;
blue = red = maxcomposition = newteam = playercount = 0;
blue = red = newteam = playercount = 0;
repick = true;
// Put each player's node in the array.
@ -6161,7 +6184,7 @@ static void Got_Cheat(UINT8 **cp, INT32 playernum)
case CHEAT_DEVMODE: {
UINT32 flags = READUINT32(*cp);
cht_debug = flags;
CV_CheaterWarning(targetPlayer, va("devmode %08x", flags));
CV_CheaterWarning(targetPlayer, va("devmode %x", flags));
break;
}
@ -6437,8 +6460,9 @@ static void Command_Archivetest_f(void)
}
// test archive
CONS_Printf("LUA_Archive...\n");
LUA_Archive(&save, true);
CONS_Printf("LUA_Sync Archive...\n");
save.write = true;
LUA_Sync(&save, true, false);
WRITEUINT8(save.p, 0x7F);
wrote = (UINT32)(save.p - save.buffer);
@ -6448,8 +6472,9 @@ static void Command_Archivetest_f(void)
// test unarchive
save.p = save.buffer;
CONS_Printf("LUA_UnArchive...\n");
LUA_UnArchive(&save, true, false);
save.write = false;
CONS_Printf("LUA_Sync Unarchive...\n");
LUA_Sync(&save, true, false);
i = READUINT8(save.p);
if (i != 0x7F || wrote != (UINT32)(save.p - save.buffer))
{
@ -7399,11 +7424,6 @@ static void KartComeback_OnChange(void)
static void KartEliminateLast_OnChange(void)
{
if (K_CanChangeRules() == false)
{
CV_StealthSet(&cv_karteliminatelast, cv_karteliminatelast.defaultvalue);
}
P_CheckRacers();
}
@ -7622,7 +7642,6 @@ static void KartDrafting_OnChange(void)
}
}
static void KartAirDrop_OnChange(void)
{
if (K_CanChangeRules() == false)
@ -7656,6 +7675,63 @@ static void KartAirDrop_OnChange(void)
}
}
static void KartItemLitter_OnChange(void)
{
if (K_CanChangeRules() == false)
{
return;
}
if (!K_ItemLitterActive() && cv_kartitemlitter.value)
{
if (leveltime < starttime)
{
itemlittering = true;
CONS_Printf(M_GetText("Item littering has been turned \"On\".\n"));
}
else
{
CONS_Printf(M_GetText("Item littering will be turned \"On\" Next Round.\n"));
}
}
else if (K_ItemLitterActive() && !cv_kartitemlitter.value)
{
if (leveltime < starttime)
{
itemlittering = false;
CONS_Printf(M_GetText("Item littering has been turned \"Off\".\n"));
}
else
{
CONS_Printf(M_GetText("Item littering will be turned \"Off\" next round.\n"));
}
}
}
static void KartAntiBump_OnChange(void)
{
if (K_CanChangeRules() == false)
{
return;
}
if (leveltime < starttime)
{
CONS_Printf(
M_GetText("Player collision delay has been changed to %s seconds.\n"),
cv_kartantibump.string
);
antibumptime = (tic_t)cv_kartantibump.value * TICRATE;
}
else
{
CONS_Printf(
M_GetText("Player collision delay will be changed to %s seconds next round.\n"),
cv_kartantibump.string
);
}
}
static void KartItemBreaker_OnChange(void)
{
if (K_CanChangeRules() == false)

View file

@ -156,6 +156,10 @@ extern consvar_t cv_kartstacking_grow_speedboost;
extern consvar_t cv_kartstacking_grow_accelboost;
extern consvar_t cv_kartstacking_grow_stackable;
extern consvar_t cv_kartstacking_bubble_speedboost;
extern consvar_t cv_kartstacking_bubble_accelboost;
extern consvar_t cv_kartstacking_bubble_stackable;
extern consvar_t cv_kartstacking_start_speedboost;
extern consvar_t cv_kartstacking_start_accelboost;
extern consvar_t cv_kartstacking_start_stackable;
@ -204,6 +208,10 @@ extern consvar_t cv_kartinvin_midtime;
extern consvar_t cv_kartairdrop;
extern consvar_t cv_kartitemlitter;
extern consvar_t cv_kartantibump;
extern consvar_t cv_kartoddsdist;
extern consvar_t cv_kartlegacyoddsdist;
extern consvar_t cv_kartspbdist;
@ -233,6 +241,8 @@ extern consvar_t cv_lagless;
extern consvar_t cv_pingtimeout;
extern consvar_t cv_showping;
extern consvar_t cv_pingmeasurement;
extern consvar_t cv_pingicon;
extern consvar_t cv_pingstyle;
extern consvar_t cv_showminimapnames;
extern consvar_t cv_showminimapangle;
@ -309,14 +319,6 @@ typedef enum
extern const char *netxcmdnames[MAXNETXCMD - 1];
#if defined(_MSC_VER)
#pragma pack(1)
#endif
#ifdef _MSC_VER
#pragma warning(disable : 4214)
#endif
//Packet composition for Command_TeamChange_f() ServerTeamChange, etc.
//bitwise structs make packing bits a little easier, but byte alignment harder?
//todo: decide whether to make the other netcommands conform, or just get rid of this experiment.
@ -328,10 +330,6 @@ struct changeteam_packet_t {
UINT32 scrambled : 1; // value 0 to 1
} ATTRPACK;
#ifdef _MSC_VER
#pragma warning(default : 4214)
#endif
struct changeteam_value_t {
UINT16 l; // liitle endian
UINT16 b; // big enian
@ -345,10 +343,6 @@ typedef union {
changeteam_value_t value;
} ATTRPACK changeteam_union;
#if defined(_MSC_VER)
#pragma pack()
#endif
// add game commands, needs cleanup
void D_RegisterServerCommands(void);
void D_RegisterClientCommands(void);

View file

@ -563,7 +563,7 @@ INT32 CL_CheckFiles(void)
// CONS_Printf("checking %d of %d / %d of %d?\n", i, fileneedednum, j, numwadfiles);
// CONS_Printf("i: %s / j: %s \n", fileneeded[i].filename, wadfiles[j]->filename);
if (j < numwadfiles && !wadfiles[j]->important && !wadfiles[j]->localfile)
if (j < numwadfiles && !wadfiles[j]->important)
{
// Unimportant on our side.
++j;

View file

@ -694,10 +694,13 @@ struct player_t
UINT8 airdroptime; // Tracks how long airdrop has been active, used for delay before airdrop kicks in.
boolean ringdrop; // Set when having ringdrop applied.
UINT8 curshield; // see kartshields_t
mobj_t *shieldtracer; // Blankart: Shield mobj
UINT8 bubblecool; // Bubble Shield use cooldown
UINT8 bubbleblowup; // Bubble Shield usage blowup
UINT8 bubblehealth; // Bubble Shield health
UINT16 bubbleboost; // Bubble shield boost timer
UINT16 flamedash; // Flame Shield dash power
INT32 flametimer; // Flame Shield dash meter left
UINT8 flamestore; // Flame Shield reserve boost

View file

@ -58,10 +58,6 @@ typedef enum
#define TICCMD_TYPING (0x02) /* chat window or console open */
#define TICCMD_KEYSTROKE (0x04) /* chat character input */
#if defined(_MSC_VER)
#pragma pack(1)
#endif
struct ticcmd_t
{
SINT8 forwardmove; // -MAXPLMOVE to MAXPLMOVE (50)
@ -75,10 +71,6 @@ struct ticcmd_t
UINT8 flags;
} ATTRPACK;
#if defined(_MSC_VER)
#pragma pack()
#endif
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -158,9 +158,6 @@ void clear_levels(void)
P_DeleteFlickies(nummapheaders);
for (SINT8 k = 0; k < MAXMAPRECORDS; k++)
Z_Free(mapheaderinfo[nummapheaders]->mainrecord[k]);
Patch_Free(mapheaderinfo[nummapheaders]->thumbnailPic);
Patch_Free(mapheaderinfo[nummapheaders]->minimapPic);
@ -405,7 +402,7 @@ void readskincolor(MYFILE *f, INT32 num, boolean mainfile)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
if (fastcmp(word, "NAME"))
{
@ -867,7 +864,7 @@ void readlevelheader(MYFILE *f, char * name)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
i = atoi(word2); // used for numerical settings
@ -1947,7 +1944,7 @@ static void readmenuitem(MYFILE *f, menuitem_t *menuitem)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
//strupr(word2);
if (fastcmp(word, "X"))
@ -2525,7 +2522,7 @@ void readsound(MYFILE *f, INT32 num)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
value = atoi(word2); // used for numerical settings
if (fastcmp(word, "SINGULAR"))
@ -2631,7 +2628,7 @@ void reademblemdata(MYFILE *f, INT32 num)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
value = atoi(word2); // used for numerical settings
// Up here to allow lowercase in hints
@ -2738,7 +2735,7 @@ void readextraemblemdata(MYFILE *f, INT32 num)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
value = atoi(word2); // used for numerical settings
@ -2821,7 +2818,7 @@ void readunlockable(MYFILE *f, INT32 num)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
i = atoi(word2); // used for numerical settings
@ -3082,7 +3079,7 @@ void readconditionset(MYFILE *f, UINT8 setnum)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
strupr(word2);
if (fastncmp(word, "CONDITION", 9))
@ -3146,7 +3143,7 @@ void readmaincfg(MYFILE *f)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
strupr(word2);
value = atoi(word2); // used for numerical settings
@ -3437,7 +3434,7 @@ void readwipes(MYFILE *f)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word = s;
char *pword = word;
char *pword;
char *word2;
char *tmp;
INT32 value;
@ -3470,7 +3467,7 @@ void readwipes(MYFILE *f)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
value = atoi(word2); // used for numerical settings
if (value < -1 || value > 99)
@ -3615,7 +3612,7 @@ void readcupheader(MYFILE *f, cupheader_t *cup)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
i = atoi(word2); // used for numerical settings
strupr(word2);
@ -4009,7 +4006,7 @@ void readweather(MYFILE *f, INT32 num)
strupr(word);
// Now get the part after
word2 = tmp += 2;
word2 = tmp + 2;
if (fastcmp(word, "TYPE"))
{

View file

@ -48,8 +48,31 @@ struct discordInfo_s discordInfo;
discordRequest_t *discordRequestList = NULL;
size_t g_discord_skins = 0;
static char self_ip[IP_SIZE];
/*--------------------------------------------------
* const char *DRPC_HideUsername(const char *input)
*
* See header file for description.
* --------------------------------------------------*/
const char *DRPC_HideUsername(const char *input)
{
static char buffer[5];
int i;
buffer[0] = input[0];
for (i = 1; i < 4; ++i)
{
buffer[i] = '.';
}
buffer[4] = '\0';
return buffer;
}
boolean drpc_init = false;
/*--------------------------------------------------
@ -102,11 +125,11 @@ static void DRPC_HandleReady(const DiscordUser *user)
{
if (cv_discordstreamer.value)
{
CONS_Printf("Discord: connected to %s\n", user->username);
CONS_Printf("Discord: connected to %s\n", DRPC_HideUsername(user->username));
}
else
{
CONS_Printf("Discord: connected to %s#%s (%s)\n", user->username, user->discriminator, user->userId);
CONS_Printf("Discord: connected to %s (%s)\n", user->username, user->userId);
}
}
@ -242,8 +265,10 @@ static void DRPC_HandleJoinRequest(const DiscordUser *requestUser)
newRequest->username = Z_Calloc(344, PU_STATIC, NULL);
snprintf(newRequest->username, 344, "%s", requestUser->username);
#if 0
newRequest->discriminator = Z_Calloc(8, PU_STATIC, NULL);
snprintf(newRequest->discriminator, 8, "%s", requestUser->discriminator);
#endif
newRequest->userID = Z_Calloc(32, PU_STATIC, NULL);
snprintf(newRequest->userID, 32, "%s", requestUser->userId);
@ -309,6 +334,9 @@ void DRPC_RemoveRequest(discordRequest_t *removeRequest)
}
Z_Free(removeRequest->username);
#if 0
Z_Free(removeRequest->discriminator);
#endif
Z_Free(removeRequest->userID);
Z_Free(removeRequest);
}
@ -412,7 +440,7 @@ static void DRPC_GotServerIP(UINT32 address)
--------------------------------------------------*/
static const char *DRPC_GetServerIP(void)
{
const char *address;
const char *address;
// If you're connected
if (I_GetNodeAddress && (address = I_GetNodeAddress(servernode)) != NULL)
@ -563,17 +591,8 @@ void DRPC_UpdatePresence(void)
{
if (modeattacking)
{
SINT8 recordpreset = G_RecordPresetIndex();
const char *currenttamode = "SRB2Kart";
if (recordpreset == RP_TECH)
currenttamode = "Tech";
else if (recordpreset == RP_BLAN)
currenttamode = "BlanKart";
else if (recordpreset == RP_CUST)
currenttamode = "Custom";
discordPresence.details = va("Time Attack: %s Mode", currenttamode);
const char *realname = G_GetRecordPresetName(currentrecordpreset);
discordPresence.details = va("Time Attack: %s", realname ? realname : "Unknown Mode");
}
else
{
@ -770,66 +789,13 @@ void DRPC_UpdatePresence(void)
// Character info
if (Playing() && playeringame[consoleplayer] && !players[consoleplayer].spectator)
{
// Supported skin names
static const char *supportedSkins[] = {
// base game
"sonic",
"tails",
"knuckles",
"eggman",
"metalsonic",
// bonus chars
"flicky",
"motobug",
"amy",
"mighty",
"ray",
"espio",
"vector",
"chao",
"gamma",
"chaos",
"shadow",
"rouge",
"herochao",
"darkchao",
"cream",
"omega",
"blaze",
"silver",
"wonderboy",
"arle",
"nights",
"sakura",
"ulala",
"beat",
"vyse",
"aiai",
"kiryu",
"aigis",
"miku",
"doom",
NULL
};
boolean customChar = true;
UINT8 checkSkin = 0;
// Character image
while (supportedSkins[checkSkin] != NULL)
if ((unsigned)players[consoleplayer].skin < g_discord_skins) // Supported skins
{
if (!strcmp(skins[players[consoleplayer].skin].name, supportedSkins[checkSkin]))
{
snprintf(charimg, 22, "char_%s", supportedSkins[checkSkin]);
discordPresence.smallImageKey = charimg;
customChar = false;
break;
}
checkSkin++;
snprintf(charimg, 22, "char_%s", skins[ players[consoleplayer].skin ].name);
discordPresence.smallImageKey = charimg;
}
if (customChar == true)
else
{
// Use the custom character icon!
discordPresence.smallImageKey = "charcustom";

View file

@ -33,7 +33,9 @@ extern struct discordInfo_s {
struct discordRequest_t {
char *username; // Discord user name.
#if 0 // Good night, sweet prince...
char *discriminator; // Discord discriminator (The little hashtag thing after the username). Separated for a "hide discriminators" cvar.
#endif
char *userID; // The ID of the Discord user, gets used with Discord_Respond()
// HAHAHA, no.
@ -48,6 +50,17 @@ struct discordRequest_t {
extern discordRequest_t *discordRequestList;
extern size_t g_discord_skins;
/*--------------------------------------------------
* const char *DRPC_HideUsername(const char *input);
*
* Handle usernames while cv_discordstreamer is activated.
* (The loss of discriminators is still a dumbass regression
* that I will never forgive the Discord developers for.)
* --------------------------------------------------*/
const char *DRPC_HideUsername(const char *input);
/*--------------------------------------------------
void DRPC_RemoveRequest(void);

View file

@ -72,10 +72,6 @@ enum
// Do not use bit five or after, as they are used for object z-offsets.
#if defined(_MSC_VER)
#pragma pack(1)
#endif
// A single Vertex.
struct mapvertex_t
{
@ -235,10 +231,6 @@ struct mapnode_t
UINT16 children[2];
} ATTRPACK;
#if defined(_MSC_VER)
#pragma pack()
#endif
typedef enum
{
USER_PROP_BOOL,

View file

@ -61,18 +61,6 @@
#define ASMCALL
#endif
#ifdef _MSC_VER
#pragma warning(disable : 4127 4152 4213 4514)
#ifdef _WIN64
#pragma warning(disable : 4306)
#endif
#endif
// warning level 4
// warning C4127: conditional expression is constant
// warning C4152: nonstandard extension, function/data pointer conversion in expression
// warning C4213: nonstandard extension used : cast on l-value
#include "version.h"
#include "doomtype.h"
@ -201,8 +189,7 @@ extern char logfilename[1024];
// The maximum number of players, multiplayer/networking.
// NOTE: it needs more than this to increase the number of players...
#define MAXPLAYERS 16
#define PLAYERSMASK (MAXPLAYERS-1)
#define MAXPLAYERS 32 // 32 + host slot
#define MAXPLAYERNAME 21
#define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer
#define MAXGAMEPADS (MAXSPLITSCREENPLAYERS * 2) // Number of gamepads we'll be allowing
@ -214,12 +201,26 @@ extern char logfilename[1024];
#define MAXCOLORNAME 32
#define NUMCOLORFREESLOTS 32768
#define MAXGPPLAYERS 16 // max players in Grand Prix only
// Net savegame compression stuff
// Uses ZLib if LZ4 is not defined.
// if theres no ZLib then use LZF
// ZLib Options
//#define ZLIB_LEVEL 5
// LZ4 Options
#define USE_LZ4 // Use LZ4 for network savegame compression
#define LZ4_ACCEL 1
// surely nobody's gonna change the palette a second time :Clueless:
#define FADECOLOR 0 // 120
#define ENCOREFADECOLOR 209 // 122
// Master Server compatibility ONLY
#define MSCOMPAT_MAXPLAYERS (32)
// the highest number of playerinfo entries we can fit into a single packet
#define MAXPLAYERINFO 32
// State updates, number of tics / second.
// NOTE: used to setup the timer rate, see I_StartupTimer().
@ -316,7 +317,6 @@ extern char liveeventbackup[256];
void M_StartupLocale(void);
void *M_Memcpy(void* dest, const void* src, size_t n);
char *va(const char *format, ...) FUNCPRINTF;
char *xva(const char *format, ...) FUNCPRINTF;
char *M_GetToken(const char *inputString);
void M_UnGetToken(void);
@ -468,7 +468,7 @@ UINT32 quickncasehash (const char *p, size_t n)
#endif
#ifdef __cplusplus
#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
#if defined(__GNUC__) || defined(__clang__)
#define restrict __restrict
#else
#define restrict

View file

@ -115,7 +115,6 @@ struct recorddata_t
//UINT32 score; ///< Score when the level was finished.
//UINT16 rings; ///< Rings when the level was finished.
};
#define MAXMAPRECORDS 4
// mapvisited is now a set of flags that says what we've done in the map.
#define MV_VISITED (1)
@ -180,7 +179,7 @@ extern boolean lastdraw;
extern INT32 postimgparam[MAXSPLITSCREENPLAYERS];
extern INT32 viewwindowx, viewwindowy;
extern INT32 viewwidth, scaledviewwidth;
extern INT32 viewwidth;
extern boolean gamedataloaded;
@ -373,9 +372,6 @@ struct mapheader_t
void *thumbnailPic; ///< Lump data for the level select thumbnail.
void *minimapPic; ///< Lump data for the minimap graphic.
UINT8 mapvisited; ///< A set of flags that says what we've done in the map.
recorddata_t *mainrecord[MAXMAPRECORDS]; ///< Stores best time attack data
cupheader_t *cup; ///< Cached cup
// Titlecard information
@ -636,6 +632,7 @@ struct exitcondition_t
{
boolean losing;
boolean retry;
boolean hasfinished;
};
// For racing
@ -676,7 +673,7 @@ extern SINT8 mostwanted;
extern SINT8 battlewanted[4];
extern tic_t wantedcalcdelay;
extern tic_t indirectitemcooldown;
extern tic_t hyubgone;
//extern tic_t hyubgone;
extern tic_t mapreset;
extern boolean thwompsactive;
extern UINT8 lastLowestLap;
@ -686,7 +683,7 @@ extern boolean startedInFreePlay;
extern tic_t bombflashtimer; // Used to avoid causing seizures if multiple mines explode close to you :)
extern boolean legitimateexit;
extern boolean comebackshowninfo;
extern tic_t curlap, bestlap;
extern tic_t antibumptime;
extern INT16 votelevels[12][2];
extern SINT8 votes[MAXPLAYERS];

View file

@ -28,37 +28,7 @@ extern "C" {
#endif
/* 7.18.1.1 Exact-width integer types */
#ifdef _MSC_VER
// libopenmpt.h will include stdint.h later;
// include it now so that INT8_MAX etc. don't get redefined
#ifdef HAVE_OPENMPT
#include <stdint.h>
#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... */
#if (_MSC_VER <= 1200)
#ifndef DWORD_PTR
#define DWORD_PTR DWORD
#endif
#ifndef PDWORD_PTR
#define PDWORD_PTR PDWORD
#endif
#endif
#else
#define __STDC_LIMIT_MACROS
#include <stdint.h>
@ -72,37 +42,14 @@ typedef long ssize_t;
#define UINT32 uint32_t
#define INT64 int64_t
#define UINT64 uint64_t
#endif
#ifdef __APPLE_CC__
#define DIRECTFULLSCREEN 1
#define DEBUG_LOG
#define NOIPX
#endif
/* Strings and some misc platform specific stuff */
#ifdef _MSC_VER
// Microsoft VisualC++
#if (_MSC_VER <= 1800) // MSVC 2013 and back
#define snprintf _snprintf
#if (_MSC_VER <= 1200) // MSVC 6.0 and back
#define vsnprintf _vsnprintf
#endif
#endif
#define strncasecmp strnicmp
#define strcasecmp stricmp
#ifndef __cplusplus
#define inline __inline
#endif
#elif defined (__WATCOMC__)
#include <dos.h>
#include <sys\types.h>
#include <direct.h>
#include <malloc.h>
#define strncasecmp strnicmp
#define strcasecmp strcmpi
#endif
#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
#undef stricmp
#define stricmp(x,y) strcasecmp(x,y)
@ -269,12 +216,6 @@ enum {false = 0, true = 1};
#endif
#define ATTRUNUSED __attribute__((unused))
#elif defined (_MSC_VER)
#define ATTRNORETURN __declspec(noreturn)
#define ATTRINLINE __forceinline
#if _MSC_VER > 1200 // >= MSVC 6.0
#define ATTRNOINLINE __declspec(noinline)
#endif
#endif
#ifndef FUNCPRINTF

View file

@ -91,6 +91,8 @@ static patch_t *dsbuildings[NUMDSBUILDINGS];
std::chrono::high_resolution_clock timer;
std::chrono::high_resolution_clock::time_point start, curr;
#define FULLCREDITSBGCOLOR (254)
#define CREDSKINCOUNT (MAXPLAYERS + DSUNIQUEPLAYERS)
#define MAXMISCOBJS (MAXDSOBJECTS - CREDSKINCOUNT)
@ -1382,7 +1384,7 @@ void F_SecretCreditsDrawer(void)
if ((dscredits.creditsscene > 2) && (dscredits.creditsscene < 19))
{
bgcolor = 198;
bgcolor = FULLCREDITSBGCOLOR;
}
V_DrawFill(-vidxdiff - 2, -vidydiff - 2, w + 2, h + 2, bgcolor);

View file

@ -439,8 +439,14 @@ void F_IntroTicker(void)
}
if (finalecount == 80)
{
char chars[5][10] = {"tails", "chao", "aiai", "sakura"};
SINT8 random = M_RandomRange(0, 3);
// I'm assuming these are all representative of a "dev character".
// Tails: NepDisk
// Chao: Alug
// Aiai: GHG
// Sakura: Anon
// Doomguy: Minenice
char chars[6][10] = {"tails", "chao", "aiai", "sakura", "doom"};
SINT8 random = M_RandomRange(0, 4);
sfxenum_t rsound = skins[R_SkinAvailable(chars[random])].soundsid[SKSKWIN];
S_StartSound(NULL, sfx_flgcap);
S_StartSound(NULL, rsound);
@ -884,15 +890,16 @@ const char *blancredits[] = {
"\"GenericHeroGuy\"",
"\"Alug\"",
"\"Indev\"",
"\"Anonimus\" aka \"yama\"",
"\"minenice\"",
"",
"\1Support Programming",
"\"hayaunderscore\" aka \"DeltaKaynx\"",
"\"WumboSpasm\"",
"\"Anonimus\"",
"",
"\1Item Programming",
"\"NepDisk\"",
"\"Anonimus\"",
"\"Anonimus\" aka \"yama\"",
"",
"\1External Programming",
"\"Hanicef\"",
@ -915,19 +922,21 @@ const char *blancredits[] = {
"",
"\1Item Design",
"\"NepDisk\"",
"\"Anonimus\"",
"\"Anonimus\" aka \"yama\"",
"",
"\1Design Support",
"\"Rim Jobless\"",
"\"JonUD\"",
"\"luna\"",
"\"White Mage (guy who picked up controller)\"",
"\"minenice\"",
"",
"\1New Item Art",
"\"Spee\"",
"\"Jin\"",
"\"NepDisk\"",
"\"Mayo\"",
"\"Anonimus\" aka \"yama\"",
"",
"\1New HUD Art",
"\"Spee\"",
@ -952,10 +961,11 @@ const char *blancredits[] = {
"\1Super Special SIGSEGV Search and Smash Squad",
"\"NepDisk\"",
"\"GenericHeroGuy\"",
"\"Anonimus\"",
"\"Anonimus\" aka \"yama\"",
"\"MotoBugger\"",
"\"Rim Jobless\"",
"\"Toad The Fungus\"",
"\"SkylarDream\"", // Discovered the Cookie Country linedef from hell
"",
"\1Testing",
"\"NepDisk\"",
@ -966,7 +976,7 @@ const char *blancredits[] = {
"\"JonUD\"",
"\"MotoBugger\"",
"\"Toad The Fungus\"",
"\"Anonimus\"",
"\"Anonimus\" aka \"yama\"",
"\"luna\"",
"\"swift\"",
"\"Rim Jobless\"",
@ -974,11 +984,25 @@ const char *blancredits[] = {
"\"Mayo\"",
"\"minenice\"",
"\"LabrysXII\"",
"\"merrit\"",
"\"merritt\"",
"\"ArcadeStriker\"",
"\"Frank_th\"",
"\"Tsuko\"",
"\"SkylarDream\"",
"\"MC\"",
"\"dairychoco\"",
"\"Lurker\"",
"\"Herculad\"",
"\"Yohomes\"",
"\"Yunxmi\"",
"\"Gemini0\"",
"\"PX8916\"",
"\"Tom\"",
"\"Phoenix\"",
"",
"\1Special Thanks",
"\"merritt\"",
"\"luna\"",
"\"Sunflower\" aka \"AnimeSonic\"",
"Sunflower's Garden",
"The Moe Mansion and Birdhouse Team",

View file

@ -168,9 +168,10 @@ enum
wipe_titlescreen_toblack,
wipe_timeattack_toblack,
wipe_credits_toblack,
wipe_blancredits_toblack,
wipe_fullcredits_toblack,
wipe_evaluation_toblack,
wipe_intro_toblack,
wipe_ending_toblack,
wipe_cutscene_toblack,
// Specialized wipes
@ -184,9 +185,10 @@ enum
wipe_titlescreen_final,
wipe_timeattack_final,
wipe_credits_final,
wipe_blancredits_final,
wipe_fullcredits_final,
wipe_evaluation_final,
wipe_intro_final,
wipe_ending_final,
wipe_cutscene_final,
// custom intermissions

View file

@ -59,9 +59,10 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
0, // wipe_titlescreen_toblack
0, // wipe_timeattack_toblack
99, // wipe_credits_toblack
99, // wipe_blancredits_toblack
99, // wipe_fullcredits_toblack
0, // wipe_evaluation_toblack
UINT8_MAX, // wipe_intro_toblack (hardcoded)
99, // wipe_ending_toblack (hardcoded)
99, // wipe_cutscene_toblack (hardcoded)
72, // wipe_encore_toinvert
@ -73,9 +74,10 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
0, // wipe_titlescreen_final
0, // wipe_timeattack_final
99, // wipe_credits_final
99, // wipe_blancredits_final
UINT8_MAX, // wipe_fullcredits_final
0, // wipe_evaluation_final
99, // wipe_intro_final (hardcoded)
99, // wipe_ending_final (hardcoded)
99 // wipe_cutscene_final (hardcoded)
};
@ -315,7 +317,7 @@ void F_WipeStartScreen(void)
return;
}
#endif
wipe_scr_start = screens[3];
wipe_scr_start = vid.screens[3];
I_ReadScreen(wipe_scr_start, 1);
#endif
}
@ -332,7 +334,7 @@ void F_WipeEndScreen(void)
return;
}
#endif
wipe_scr_end = screens[4];
wipe_scr_end = vid.screens[4];
I_ReadScreen(wipe_scr_end, 1);
V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start);
#endif
@ -362,7 +364,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
paldiv = FixedDiv(257<<FRACBITS, 11<<FRACBITS);
// Init the wipe
wipe_scr = screens[0];
wipe_scr = vid.screens[0];
D_WipeLoop(WIPELOOP_RUNWIPE, wipetype, drawMenu);
#endif

View file

@ -30,286 +30,7 @@
#include "z_zone.h"
#include "m_menu.h" // Addons_option_Onchange
#if defined (_WIN32) && defined (_MSC_VER) && !defined (_XBOX)
#include <errno.h>
#include <io.h>
#include <tchar.h>
#define SUFFIX "*"
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#ifndef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
struct dirent
{
long d_ino; /* Always zero. */
unsigned short d_reclen; /* Always zero. */
unsigned short d_namlen; /* Length of name in d_name. */
char d_name[FILENAME_MAX]; /* File name. */
};
/*
* This is an internal data structure. Good programmers will not use it
* except as an argument to one of the functions below.
* dd_stat field is now int (was short in older versions).
*/
typedef struct
{
/* disk transfer area for this dir */
struct _finddata_t dd_dta;
/* dirent struct to return from dir (NOTE: this makes this thread
* safe as long as only one thread uses a particular DIR struct at
* a time) */
struct dirent dd_dir;
/* _findnext handle */
#if _MSC_VER > 1200
intptr_t dd_handle;
#else
long dd_handle;
#endif
/*
* Status of search:
* 0 = not started yet (next entry to read is first entry)
* -1 = off the end
* positive = 0 based index of next entry
*/
int dd_stat;
/* given path for dir with search pattern (struct is extended) */
CHAR dd_name[1];
} DIR;
/*
* opendir
*
* Returns a pointer to a DIR structure appropriately filled in to begin
* searching a directory.
*/
DIR *
opendir (const CHAR *szPath)
{
DIR *nd;
DWORD rc;
CHAR szFullPath[MAX_PATH];
errno = 0;
if (!szPath)
{
errno = EFAULT;
return (DIR *) 0;
}
if (szPath[0] == '\0')
{
errno = ENOTDIR;
return (DIR *) 0;
}
/* Attempt to determine if the given path really is a directory. */
rc = GetFileAttributesA(szPath);
if (rc == INVALID_FILE_ATTRIBUTES)
{
/* call GetLastError for more error info */
errno = ENOENT;
return (DIR *) 0;
}
if (!(rc & FILE_ATTRIBUTE_DIRECTORY))
{
/* Error, entry exists but not a directory. */
errno = ENOTDIR;
return (DIR *) 0;
}
/* Make an absolute pathname. */
_fullpath (szFullPath, szPath, MAX_PATH);
/* Allocate enough space to store DIR structure and the complete
* directory path given. */
nd = (DIR *) malloc (sizeof (DIR) + (strlen(szFullPath) + strlen (SLASH) +
strlen(PATHSEP) + 1) * sizeof (CHAR));
if (!nd)
{
/* Error, out of memory. */
errno = ENOMEM;
return (DIR *) 0;
}
/* Create the search expression. */
strcpy (nd->dd_name, szFullPath);
/* Add on a slash if the path does not end with one. */
if (nd->dd_name[0] != '\0' &&
nd->dd_name[strlen (nd->dd_name) - 1] != PATHSEP[0])
{
strcat (nd->dd_name, PATHSEP);
}
/* Add on the search pattern */
strcat (nd->dd_name, SUFFIX);
/* Initialize handle to -1 so that a premature closedir doesn't try
* to call _findclose on it. */
nd->dd_handle = -1;
/* Initialize the status. */
nd->dd_stat = 0;
/* Initialize the dirent structure. ino and reclen are invalid under
* Win32, and name simply points at the appropriate part of the
* findfirst_t structure. */
nd->dd_dir.d_ino = 0;
nd->dd_dir.d_reclen = 0;
nd->dd_dir.d_namlen = 0;
ZeroMemory(nd->dd_dir.d_name, FILENAME_MAX);
return nd;
}
/*
* readdir
*
* Return a pointer to a dirent structure filled with the information on the
* next entry in the directory.
*/
struct dirent *
readdir (DIR * dirp)
{
errno = 0;
/* Check for valid DIR struct. */
if (!dirp)
{
errno = EFAULT;
return (struct dirent *) 0;
}
if (dirp->dd_stat < 0)
{
/* We have already returned all files in the directory
* (or the structure has an invalid dd_stat). */
return (struct dirent *) 0;
}
else if (dirp->dd_stat == 0)
{
/* We haven't started the search yet. */
/* Start the search */
dirp->dd_handle = _findfirst (dirp->dd_name, &(dirp->dd_dta));
if (dirp->dd_handle == -1)
{
/* Whoops! Seems there are no files in that
* directory. */
dirp->dd_stat = -1;
}
else
{
dirp->dd_stat = 1;
}
}
else
{
/* Get the next search entry. */
if (_findnext (dirp->dd_handle, &(dirp->dd_dta)))
{
/* We are off the end or otherwise error.
_findnext sets errno to ENOENT if no more file
Undo this. */
DWORD winerr = GetLastError();
if (winerr == ERROR_NO_MORE_FILES)
errno = 0;
_findclose (dirp->dd_handle);
dirp->dd_handle = -1;
dirp->dd_stat = -1;
}
else
{
/* Update the status to indicate the correct
* number. */
dirp->dd_stat++;
}
}
if (dirp->dd_stat > 0)
{
/* Successfully got an entry. Everything about the file is
* already appropriately filled in except the length of the
* file name. */
dirp->dd_dir.d_namlen = (unsigned short)strlen (dirp->dd_dta.name);
strcpy (dirp->dd_dir.d_name, dirp->dd_dta.name);
return &dirp->dd_dir;
}
return (struct dirent *) 0;
}
/*
* rewinddir
*
* Makes the next readdir start from the beginning.
*/
int
rewinddir (DIR * dirp)
{
errno = 0;
/* Check for valid DIR struct. */
if (!dirp)
{
errno = EFAULT;
return -1;
}
dirp->dd_stat = 0;
return 0;
}
/*
* closedir
*
* Frees up resources allocated by opendir.
*/
int
closedir (DIR * dirp)
{
int rc;
errno = 0;
rc = 0;
if (!dirp)
{
errno = EFAULT;
return -1;
}
if (dirp->dd_handle != -1)
{
rc = _findclose (dirp->dd_handle);
}
/* Delete the dir structure. */
free (dirp);
return rc;
}
#endif
static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"},
#if 1
{1, "HOME"}, {2, "SRB2KART"},
#endif
{3, "CUSTOM"}, {0, NULL}};
static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"}, {1, "HOME"}, {2, "SRB2KART"}, {3, "CUSTOM"}, {0, NULL}};
consvar_t cv_addons_option = CVAR_INIT ("addons_option", "Default", CV_SAVE|CV_CALL|CV_NOINIT, addons_cons_t, Addons_option_Onchange);
consvar_t cv_addons_folder = CVAR_INIT ("addons_folder", "", CV_SAVE, NULL, NULL);
@ -323,7 +44,7 @@ consvar_t cv_addons_search_case = CVAR_INIT ("addons_search_case", "No", CV_SAVE
static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}};
consvar_t cv_addons_search_type = CVAR_INIT ("addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL);
char menupath[1024];
char menupath[MAXFILEPATH];
size_t menupathindex[menudepth];
size_t menudepthleft = menudepth;
@ -336,40 +57,6 @@ size_t dir_on[menudepth];
UINT8 refreshdirmenu = 0;
char *refreshdirname = NULL;
#if defined (_XBOX) && defined (_MSC_VER)
filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash,
boolean completepath, int maxsearchdepth)
{
//NONE?
startpath = filename = NULL;
wantedhash = 0;
maxsearchdepth = 0;
completepath = false;
return FS_NOTFOUND;
}
void closefilemenu(boolean validsize)
{
(void)validsize;
return;
}
void searchfilemenu(char *tempname)
{
(void)tempname;
return;
}
boolean preparefilemenu(boolean samedepth, boolean replayhut)
{
(void)samedepth;
(void)replayhut;
return false;
}
#else
filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash, boolean completepath, int maxsearchdepth)
{
filestatus_t retval = FS_NOTFOUND;
@ -381,7 +68,7 @@ filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash
int found = 0;
char *searchname = strdup(filename);
int depthleft = maxsearchdepth;
char searchpath[1024];
char searchpath[MAXFILEPATH];
size_t *searchpathindex;
dirhandle = (DIR**) malloc(maxsearchdepth * sizeof (DIR*));
@ -686,10 +373,13 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
Z_Free(dirmenu);
dirmenu = NULL;
for (; sizecoredirmenu > 0; sizecoredirmenu--) // clear out existing items
if (coredirmenu != NULL)
{
Z_Free(coredirmenu[sizecoredirmenu-1]);
coredirmenu[sizecoredirmenu-1] = NULL;
for (; sizecoredirmenu > 0; sizecoredirmenu--) // clear out existing items
{
Z_Free(coredirmenu[sizecoredirmenu-1]);
coredirmenu[sizecoredirmenu-1] = NULL;
}
}
while (true)
@ -876,4 +566,3 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
return true;
}
#endif

View file

@ -35,7 +35,8 @@ filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash
#define menudepth 20
extern char menupath[1024];
#define MAXFILEPATH 1024
extern char menupath[MAXFILEPATH];
extern size_t menupathindex[menudepth];
extern size_t menudepthleft;

View file

@ -45,7 +45,7 @@
// SRB2Kart
#include "d_netfil.h" // nameonly
#include "lua_script.h" // LUA_ArchiveDemo and LUA_UnArchiveDemo
#include "lua_script.h" // LUA_Sync
#include "lua_libs.h" // gL (Lua state)
#include "k_kart.h"
@ -54,7 +54,7 @@
#include "k_color.h"
#include "k_follower.h"
#include "k_grandprix.h"
#include "g_party.h"
#include "strbuf.h"
static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}};
consvar_t cv_recordmultiplayerdemos = CVAR_INIT ("netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL);
@ -73,7 +73,6 @@ static char demoname[MAX_WADPATH];
static savebuffer_t demobuf = {0};
static UINT8 *demotime_p, *demoinfo_p;
static UINT8 demoflags;
UINT32 raflags = 0; // Time to do some hacky shit....
boolean demosynced = true; // console warning message
struct demovars_s demo;
@ -112,7 +111,7 @@ demoghost *ghosts = NULL;
// DEMO RECORDING
//
#define DEMOVERSION 0x000C
#define DEMOVERSION 0x000D
#define DEMOHEADER "\xF0" "BlanReplay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too!
@ -218,7 +217,7 @@ typedef struct
boolean rival;
} bot;
char name[16+1];
char name[21+1];
char skin[16+1];
char color[16+1];
char follower[16+1];
@ -242,6 +241,8 @@ typedef struct
UINT64 mapchecksum;
UINT8 demoflags;
UINT32 raflags;
char rapreset[MAXPRESETNAME+1];
UINT8 rapresetversion;
UINT8 gametype;
UINT8 numlaps;
char servername[MAXSERVERNAME];
@ -337,7 +338,7 @@ typedef struct
UINT8 playstate;
// DXD_NAME
char playername[17];
char playername[21+1];
// DXD_SKIN
char skinname[17];
@ -605,21 +606,36 @@ static UINT8 *G_ReadRawExtraData(extradata_t *extra, UINT8 *dp, UINT16 version)
}
if (extradata & DXD_NAME)
{
READMEM(dp, extra->playername, 16);
extra->playername[16] = '\0';
if (version <= 0x000C)
{
READMEM(dp, extra->playername, 16);
extra->playername[16] = '\0';
}
else
READSTRINGL(dp, extra->playername, 21+1);
}
}
if (extradata & DXD_SKIN)
{
READMEM(dp, extra->skinname, 16);
extra->skinname[16] = '\0';
if (version <= 0x000C)
{
READMEM(dp, extra->skinname, 16);
extra->skinname[16] = '\0';
}
else
READSTRINGL(dp, extra->skinname, 16+1);
extra->kartspeed = READUINT8(dp);
extra->kartweight = READUINT8(dp);
}
if (extradata & DXD_COLOR)
{
READMEM(dp, extra->colorname, 16);
extra->colorname[16] = '\0';
if (version <= 0x000C)
{
READMEM(dp, extra->colorname, 16);
extra->colorname[16] = '\0';
}
else
READSTRINGL(dp, extra->colorname, 16+1);
}
if (kart)
{
@ -635,10 +651,18 @@ static UINT8 *G_ReadRawExtraData(extradata_t *extra, UINT8 *dp, UINT16 version)
}
if (extradata & DXD_FOLLOWER)
{
READMEM(dp, extra->followername, 16);
extra->followername[16] = '\0';
READMEM(dp, extra->followercolor, 16);
extra->followercolor[16] = '\0';
if (version <= 0x000C)
{
READMEM(dp, extra->followername, 16);
extra->followername[16] = '\0';
READMEM(dp, extra->followercolor, 16);
extra->followercolor[16] = '\0';
}
else
{
READSTRINGL(dp, extra->followername, 16+1);
READSTRINGL(dp, extra->followercolor, 16+1);
}
}
if (extradata & DXD_WEAPONPREF)
{
@ -655,8 +679,9 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header)
UINT8 *startdp = dp;
UINT8 attack;
boolean kart = false, oldkart = false;
boolean raflag = true;
boolean raflag = false;
boolean serverinfo = true;
boolean rapreset = true; // + extended serverinfo length
// these may not be present in old demo formats, so initialize them
// also initialize them so the header can be free'd without issues
@ -683,13 +708,14 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header)
case DEMOVERSION: // latest always supported
break;
case 0x000B:
break;
case 0x000A:
break;
case 0x0009:
serverinfo = false;
/* FALLTHRU */
case 0x000A:
case 0x000B:
case 0x000C:
rapreset = false;
raflag = true;
break;
default: // too old, cannot support.
@ -698,7 +724,7 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header)
}
else if (!memcmp(startdp, "\xF0" "KartReplay" "\x0F", 12))
{
raflag = false;
rapreset = raflag = false;
serverinfo = false;
switch (header->demoversion)
{
@ -753,11 +779,20 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header)
header->raflags = READUINT32(dp);
}
if (rapreset)
{
READSTRINGL(dp, header->rapreset, sizeof(header->rapreset));
header->rapresetversion = READUINT8(dp);
}
if (serverinfo)
{
size_t maxservercontact = rapreset ? MAXSERVERCONTACT : 320;
size_t maxdescription = rapreset ? MAXSERVERDESCRIPTION : 320;
READSTRINGN(dp, header->servername, MAXSERVERNAME);
READSTRINGN(dp, header->servercontact, MAXSERVERCONTACT);
READSTRINGN(dp, header->serverdescription, MAXSERVERDESCRIPTION);
READSTRINGN(dp, header->servercontact, maxservercontact);
READSTRINGN(dp, header->serverdescription, maxdescription);
}
if (oldkart)
@ -906,23 +941,34 @@ skipfiles:
plr->bot.rival = (boolean)READUINT8(dp);
}
READMEM(dp, plr->name, 16);
plr->name[16] = '\0';
READMEM(dp, plr->skin, 16);
plr->skin[16] = '\0';
READMEM(dp, plr->color, 16);
plr->color[16] = '\0';
if (!kart)
if (rapreset)
{
READMEM(dp, plr->follower, 16);
plr->follower[16] = '\0';
READMEM(dp, plr->followercolor, 16);
plr->followercolor[16] = '\0';
READSTRINGL(dp, plr->name, 21+1);
READSTRINGL(dp, plr->skin, 16+1);
READSTRINGL(dp, plr->color, 16+1);
READSTRINGL(dp, plr->follower, 16+1);
READSTRINGL(dp, plr->followercolor, 16+1);
}
else
{
strcpy(plr->follower, "None");
strcpy(plr->followercolor, "Default");
READMEM(dp, plr->name, 16);
plr->name[16] = '\0';
READMEM(dp, plr->skin, 16);
plr->skin[16] = '\0';
READMEM(dp, plr->color, 16);
plr->color[16] = '\0';
if (!kart)
{
READMEM(dp, plr->follower, 16);
plr->follower[16] = '\0';
READMEM(dp, plr->followercolor, 16);
plr->followercolor[16] = '\0';
}
else
{
strcpy(plr->follower, "None");
strcpy(plr->followercolor, "Default");
}
}
plr->score = READUINT32(dp);
@ -969,6 +1015,52 @@ static void G_FreeDemoHeader(demoheader_t *header)
#endif
}
enum // legacy RA flags
{
// 0x0009
RAF_RINGS = 1<<0,
RAF_STACKING = 1<<1,
RAF_CHAINING = 1<<2,
RAF_SLIPDASH = 1<<3,
RAF_PURPLEDRIFT = 1<<4,
RAF_SLOPEBOOST = 1<<5,
// 0x000C
RAF_AIRDROP = 1<<6,
RAF_BUMPDRIFT = 1<<7,
RAF_BUMPSPARK = 2<<7,
RAF_BS_RESET100 = 3<<7,
RAF_BUMPSPARKMASK = 0x3<<7,
};
static strbuf_t *G_GetRecordPresetVersionForDemo(demoheader_t *header)
{
if (header->demoversion >= 0x000D)
return G_GetRecordPresetVersion(header->rapreset, header->rapresetversion);
// oh dear... this demo predates softcoded presets.
// we'll have to try and figure out the corresponding preset
UINT32 test, raflags = header->raflags;
if (raflags == 0)
return G_GetRecordPresetVersion("kart", 1);
test = RAF_STACKING|RAF_CHAINING|RAF_SLOPEBOOST;
if (header->demoversion == 0x000C)
test |= RAF_AIRDROP|RAF_BUMPSPARK;
if (raflags == test)
return G_GetRecordPresetVersion("tech", header->demoversion == 0x000C ? 2 : 1);
test = RAF_RINGS|RAF_STACKING|RAF_CHAINING|RAF_SLIPDASH|RAF_PURPLEDRIFT|RAF_SLOPEBOOST;
if (header->demoversion == 0x000C)
test |= RAF_AIRDROP|RAF_BUMPDRIFT;
if (raflags == test)
return G_GetRecordPresetVersion("blankart", header->demoversion == 0x000C ? 2 : 1);
// supporting custom raflags is a pain in the ass, so no thanks
// if it really is necessary, just add another preset to the defaults...
return NULL;
}
// and now, the rest of g_demo.c
boolean G_CompatLevel(UINT16 level)
@ -1211,8 +1303,6 @@ void G_ReadDemoExtraData(void)
void G_WriteDemoExtraData(void)
{
INT32 i;
char name[16];
for (i = 0; i < MAXPLAYERS; i++)
{
if (demo_extradata[i])
@ -1253,18 +1343,12 @@ void G_WriteDemoExtraData(void)
if (demo_extradata[i] & DXD_NAME)
{
// Name
memset(name, 0, 16);
strncpy(name, player_names[i], 16);
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, player_names[i], 21+1);
}
if (demo_extradata[i] & DXD_SKIN)
{
// Skin
memset(name, 0, 16);
strncpy(name, skins[players[i].skin].name, 16);
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, skins[players[i].skin].name, 16+1);
WRITEUINT8(demobuf.p, skins[players[i].skin].kartspeed);
WRITEUINT8(demobuf.p, skins[players[i].skin].kartweight);
@ -1273,27 +1357,18 @@ void G_WriteDemoExtraData(void)
if (demo_extradata[i] & DXD_COLOR)
{
// Color
memset(name, 0, 16);
strncpy(name, skincolors[players[i].skincolor].name, 16);
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, skincolors[players[i].skincolor].name, 16+1);
}
if (demo_extradata[i] & DXD_FOLLOWER)
{
// write follower
memset(name, 0, 16);
if (players[i].followerskin == -1)
strncpy(name, "None", 16);
WRITESTRINGL(demobuf.p, "None", 16+1);
else
strncpy(name, followers[players[i].followerskin].skinname, 16);
M_Memcpy(demobuf.p, name, 16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, followers[players[i].followerskin].skinname, 16+1);
// write follower color
memset(name, 0, 16);
strncpy(name, Followercolor_cons_t[(UINT16)(players[i].followercolor+2)].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, Followercolor_cons_t[(UINT16)(players[i].followercolor+2)].strvalue, 16+1);
}
//if (demo_extradata[i] & DXD_RESPAWN) has no extra data
@ -2664,7 +2739,6 @@ void G_RecordDemo(const char *name)
INT32 maxsize;
strcpy(demoname, name);
strcat(demoname, ".lmp");
maxsize = 1024 * 1024 * cv_netdemosize.value;
P_SaveBufferAlloc(&demobuf, maxsize);
@ -2727,41 +2801,6 @@ void G_BeginRecording(void)
if (multiplayer)
demoflags |= DF_LUAVARS;
// RAFlag stuff
if (!dedicated && modeattacking != ATTACKING_NONE)
{
if (cv_dummyattackingrings.value)
raflags |= RAF_RINGS;
if (cv_dummyattackingstacking.value)
raflags |= RAF_STACKING;
if (cv_dummyattackingchaining.value)
raflags |= RAF_CHAINING;
if (cv_dummyattackingslipdash.value)
raflags |= RAF_SLIPDASH;
if (cv_dummyattackingpurpledrift.value)
raflags |= RAF_PURPLEDRIFT;
if (cv_dummyattackingslopeboost.value)
raflags |= RAF_SLOPEBOOST;
if (cv_dummyattackingairdrop.value)
raflags |= RAF_AIRDROP;
switch (cv_dummyattackingbumpspark.value)
{
case BUMPSPARK_ALL:
raflags |= RAF_BUMPSPARK;
break;
case BUMPSPARK_RESET100:
raflags |= RAF_BS_RESET100;
break;
case BUMPSPARK_NOCHARGE:
raflags |= RAF_BUMPDRIFT;
break;
}
}
else
{
raflags = 0;
}
// Setup header.
M_Memcpy(demobuf.p, DEMOHEADER, 12); demobuf.p += 12;
WRITEUINT8(demobuf.p,VERSION);
@ -2793,7 +2832,8 @@ void G_BeginRecording(void)
WRITEUINT64(demobuf.p, maphash);
WRITEUINT8(demobuf.p, demoflags);
WRITEUINT32(demobuf.p, raflags);
WRITESTRINGL(demobuf.p, currentrecordpreset, MAXPRESETNAME+1);
WRITEUINT8(demobuf.p, currentrecordpresetversion);
WRITESTRINGN(demobuf.p, connectedservername, MAXSERVERNAME);
WRITESTRINGN(demobuf.p, connectedservercontact, MAXSERVERCONTACT);
WRITESTRINGN(demobuf.p, connectedserverdescription, MAXSERVERDESCRIPTION);
@ -2885,41 +2925,26 @@ void G_BeginRecording(void)
}
// Name
memset(name, 0, 16);
strncpy(name, player_names[p], 16);
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, player_names[p], 21+1);
// Skin
memset(name, 0, 16);
strncpy(name, skins[player->skin].name, 16);
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, skins[player->skin].name, 16+1);
// Color
memset(name, 0, 16);
strncpy(name, skincolors[player->skincolor].name, 16);
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, skincolors[player->skincolor].name, 16+1);
// Save follower's skin name
// PS: We must check for 'follower' to determine if the followerskin is valid. It's going to be 0 if we don't have a follower, but 0 is also absolutely a valid follower!
// Doesn't really matter if the follower mobj is valid so long as it exists in a way or another.
memset(name, 0, 16);
if (player->follower)
strncpy(name, followers[player->followerskin].skinname, 16);
WRITESTRINGL(demobuf.p, followers[player->followerskin].skinname, 16+1);
else
strncpy(name, "None", 16); // Say we don't have one, then.
M_Memcpy(demobuf.p,name,16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, "None", 16+1); // Say we don't have one, then.
// Save follower's colour
memset(name, 0, 16);
strncpy(name, Followercolor_cons_t[(UINT16)(player->followercolor+2)].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
M_Memcpy(demobuf.p, name, 16);
demobuf.p += 16;
// Not KartColor_Names because followercolor has extra values such as "Match"
WRITESTRINGL(demobuf.p, Followercolor_cons_t[(UINT16)(player->followercolor+2)].strvalue, 16+1);
// Score, since Kart uses this to determine where you start on the map
WRITEUINT32(demobuf.p, player->score);
@ -2940,7 +2965,10 @@ void G_BeginRecording(void)
// player lua vars, always saved even if empty
if (demoflags & DF_LUAVARS)
LUA_Archive(&demobuf, false);
{
demobuf.write = true;
LUA_Sync(&demobuf, false, false);
}
memset(&oldcmd,0,sizeof(oldcmd));
memset(&oldghost,0,sizeof(oldghost));
@ -3000,8 +3028,6 @@ void G_BeginMetal(void)
void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT16 color, UINT32 val)
{
char temp[16];
if (demoinfo_p && *(UINT32 *)demoinfo_p == 0)
{
WRITEUINT8(demobuf.p, DEMOMARKER); // add the demo end marker
@ -3012,22 +3038,13 @@ void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT16 color, UIN
WRITEUINT8(demobuf.p, ranking);
// Name
memset(temp, 0, 16);
strncpy(temp, name, 16);
M_Memcpy(demobuf.p,temp,16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, name, 21+1);
// Skin
memset(temp, 0, 16);
strncpy(temp, skins[skinnum].name, 16);
M_Memcpy(demobuf.p,temp,16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, skins[skinnum].name, 16+1);
// Color
memset(temp, 0, 16);
strncpy(temp, skincolors[color].name, 16);
M_Memcpy(demobuf.p,temp,16);
demobuf.p += 16;
WRITESTRINGL(demobuf.p, skincolors[color].name, 16+1);
// Score/time/whatever
WRITEUINT32(demobuf.p, val);
@ -3354,17 +3371,27 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
while (READUINT8(extrainfo_p) == DW_STANDING) // Assume standings are always first in the extrainfo
{
INT32 i;
char temp[16];
char temp[17];
pdemo->standings[count].ranking = READUINT8(extrainfo_p);
// Name
M_Memcpy(pdemo->standings[count].name, extrainfo_p, 16);
extrainfo_p += 16;
if (header.demoversion <= 0x000C)
{
READMEM(extrainfo_p, pdemo->standings[count].name, 16);
pdemo->standings[count].name[16] = '\0';
}
else
READSTRINGL(extrainfo_p, pdemo->standings[count].name, 21+1);
// Skin
M_Memcpy(temp,extrainfo_p,16);
extrainfo_p += 16;
if (header.demoversion <= 0x000C)
{
READMEM(extrainfo_p, temp, 16);
temp[16] = '\0';
}
else
READSTRINGL(extrainfo_p, temp, 16+1);
pdemo->standings[count].skin = UINT16_MAX;
for (i = 0; i < numskins; i++)
if (stricmp(skins[i].name, temp) == 0)
@ -3374,8 +3401,13 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
}
// Color
M_Memcpy(temp,extrainfo_p,16);
extrainfo_p += 16;
if (header.demoversion <= 0x000C)
{
READMEM(extrainfo_p, temp, 16);
temp[16] = '\0';
}
else
READSTRINGL(extrainfo_p, temp, 16+1);
pdemo->standings[count].color = SKINCOLOR_NONE;
for (i = 0; i < numskincolors; i++)
if (!stricmp(skincolors[i].name,temp)) // SRB2kart
@ -3616,7 +3648,6 @@ void G_DoPlayDemo(char *defdemoname)
gamemap = G_MapNumber(header.maptitle)+1;
demoflags = header.demoflags;
raflags = header.raflags;
gametype = header.gametype;
G_SetGametype(gametype);
numlaps = header.numlaps;
@ -3671,6 +3702,19 @@ void G_DoPlayDemo(char *defdemoname)
// net var data
CV_LoadDemoVars(&header);
if (modeattacking != ATTACKING_NONE)
{
strbuf_t *pv = G_GetRecordPresetVersionForDemo(&header);
if (pv)
{
const char *faulted = G_CheckPresetCvars(pv);
if (faulted && !G_CompatLevel(0x000C))
M_StartMessage(va("Demo cvar %s doesn't match the preset! This may be a mistake, or the demo is cheated!\n", faulted), NULL, MM_NOTHING);
}
else
CONS_Alert(CONS_WARNING, "Couldn't find record preset '%s' version %d\n", header.rapreset, header.rapresetversion);
}
memset(&grandprixinfo, 0, sizeof grandprixinfo);
if ((demoflags & DF_GRANDPRIX))
{
@ -3741,7 +3785,7 @@ void G_DoPlayDemo(char *defdemoname)
}
// Name
M_Memcpy(player_names[p], plr->name, 16);
strcpy(player_names[p], plr->name);
/*if (players[p].spectator)
{
@ -3793,7 +3837,8 @@ void G_DoPlayDemo(char *defdemoname)
LUA_ClearState();
// No modeattacking check, DF_LUAVARS won't be present here.
LUA_UnArchive(&demobuf, false, G_CompatLevel(0x0002));
demobuf.write = false;
LUA_Sync(&demobuf, false, G_CompatLevel(0x0002));
}
splitscreen = 0;
@ -3847,7 +3892,6 @@ void G_AddGhost(char *defdemoname)
CLEANUP(Z_Pfree) char *pdemoname = NULL;
const char *n;
UINT64 demohash;
UINT32 raflags;
demoghost *gh;
UINT8 flags;
CLEANUP(Z_Pfree) UINT8 *buffer = NULL;
@ -3911,7 +3955,7 @@ void G_AddGhost(char *defdemoname)
flags = header.demoflags;
raflags = header.raflags;
if (!(flags & DF_GHOST))
{
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname);
@ -3930,50 +3974,13 @@ void G_AddGhost(char *defdemoname)
return;
}
// Check RA flags.
// Check record preset.
{
UINT32 ourraflags = 0;
UINT16 demoversion = header.demoversion;
strbuf_t *ghostpre = G_GetRecordPresetVersionForDemo(&header);
strbuf_t *ourpre = G_GetRecordPresetVersion(currentrecordpreset, currentrecordpresetversion);
if (cv_dummyattackingrings.value)
ourraflags |= RAF_RINGS;
if (cv_dummyattackingstacking.value)
ourraflags |= RAF_STACKING;
if (cv_dummyattackingchaining.value)
ourraflags |= RAF_CHAINING;
if (cv_dummyattackingslipdash.value)
ourraflags |= RAF_SLIPDASH;
if (cv_dummyattackingpurpledrift.value)
ourraflags |= RAF_PURPLEDRIFT;
if (cv_dummyattackingslopeboost.value)
ourraflags |= RAF_SLOPEBOOST;
if (cv_dummyattackingairdrop.value)
ourraflags |= RAF_AIRDROP;
switch (cv_dummyattackingbumpspark.value)
{
case BUMPSPARK_ALL:
raflags |= RAF_BUMPSPARK;
break;
case BUMPSPARK_RESET100:
raflags |= RAF_BS_RESET100;
break;
case BUMPSPARK_NOCHARGE:
raflags |= RAF_BUMPDRIFT;
break;
}
if (demoversion <= 0x000B)
{
ourraflags &= ~RAF_AIRDROP;
ourraflags &= ~RAF_BUMPSPARKMASK;
}
if (ourraflags != raflags)
{
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay doesn't match current RA mode.\n"), pdemoname);
if (ghostpre == NULL || !G_CompareRecordPresetVersions(ghostpre, ourpre))
return;
}
}
demoplayer_t *plr = &header.playerdata[0];
@ -4393,7 +4400,8 @@ void G_SaveDemo(void)
size_t i, strindex = 0;
boolean dash = true;
for (i = 0; demo.titlename[i] && i < 127; i++)
//for (i = 0; demo.titlename[i] && i < 127; i++) ?????
for (i = 0; i < 64 && demo.titlename[i]; i++)
{
if ((demo.titlename[i] >= 'a' && demo.titlename[i] <= 'z') ||
(demo.titlename[i] >= '0' && demo.titlename[i] <= '9'))
@ -4408,7 +4416,7 @@ void G_SaveDemo(void)
strindex++;
dash = false;
}
else if (!dash)
else if (strindex && !dash)
{
demo_slug[strindex] = '-';
strindex++;
@ -4416,12 +4424,29 @@ void G_SaveDemo(void)
}
}
demo_slug[strindex] = 0;
if (dash) demo_slug[strindex-1] = 0;
if (dash && strindex)
{
strindex--;
}
demo_slug[strindex] = '\0';
writepoint = strstr(strrchr(demoname, *PATHSEP), "-") + 1;
demo_slug[128 - (writepoint - demoname) - 4] = 0;
sprintf(writepoint, "%s.lmp", demo_slug);
if (demo_slug[0] != '\0')
{
// Slug is valid, write the chosen filename.
writepoint = strstr(strrchr(demoname, *PATHSEP), "-");
if (!writepoint)
return;
writepoint++;
size_t flen = 128 - (writepoint - demoname) - 4;
if (flen > 0 && flen < 128)
{
demo_slug[flen] = '\0';
sprintf(writepoint, "%s.lmp", demo_slug);
}
}
}
length = *(UINT32 *)demoinfo_p;

View file

@ -18,6 +18,7 @@
#include "doomstat.h"
#include "d_event.h"
#include "m_textinput.h"
#include "filesrch.h"
#ifdef __cplusplus
extern "C" {
@ -32,24 +33,6 @@ extern consvar_t cv_resyncdemo;
extern tic_t demostarttime;
extern UINT32 raflags;
typedef enum
{
RAF_RINGS = 1<<0,
RAF_STACKING = 1<<1,
RAF_CHAINING = 1<<2,
RAF_SLIPDASH = 1<<3,
RAF_PURPLEDRIFT = 1<<4,
RAF_SLOPEBOOST = 1<<5,
RAF_AIRDROP = 1<<6,
RAF_BUMPDRIFT = 1<<7,
RAF_BUMPSPARK = 2<<7,
RAF_BS_RESET100 = 3<<7,
RAF_BUMPSPARKMASK = 0x3<<7,
// up to 1<<31 is free
} raflags_t;
// Publicly-accessible demo vars
struct demovars_s {
char titlename[65];
@ -91,7 +74,7 @@ typedef enum {
} menudemotype_e;
struct menudemo_t {
char filepath[256];
char filepath[MAXFILEPATH];
menudemotype_e type;
char title[65]; // Null-terminated for string prints
@ -103,7 +86,7 @@ struct menudemo_t {
struct {
UINT8 ranking;
char name[17];
char name[21+1];
UINT16 skin, color;
UINT32 timeorscore;
} standings[MAXPLAYERS];

File diff suppressed because it is too large Load diff

View file

@ -92,6 +92,8 @@ extern consvar_t cv_resetspecialmusic;
extern consvar_t cv_resume;
extern consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_turnsmooth[MAXSPLITSCREENPLAYERS];
void weaponPrefChange(void);
void weaponPrefChange2(void);
@ -253,19 +255,87 @@ void G_SetGamestate(gamestate_t newstate);
boolean G_GamestateUsesLevel(void);
// Gamedata record shit
#define MAXPRESETNAME 16
typedef struct
{
char name[MAXPRESETNAME+1];
char *realname;
UINT8 numversions;
strbuf_t **versions;
// yep, array of strbufs. byte 0 is version ID, then cvar NUL value NUL cvar ...
// i'm honestly tired of multi-layered structs, let's simplify things...
// we're also gonna need to compare these lists of cvars pretty often!
} recordpreset_t;
typedef enum
{
RP_KART = 0,
RP_KART,
RP_TECH,
RP_BLAN,
RP_CUST,
} recordpreset_e;
SINT8 G_RecordPresetIndex(void);
void G_AllocMainRecordData(INT16 i, SINT8 preset);
void G_ClearRecords(void);
RP_FIRSTFREESLOT,
RP_LASTFREESLOT = RP_FIRSTFREESLOT + 100,
MAXRECORDPRESETS,
} ATTRPACK recordpresetnum_e;
boolean K_EmblemsEnabled(void);
extern recordpreset_t **recordpresets;
extern recordpresetnum_e numrecordpresets;
extern char currentrecordpreset[MAXPRESETNAME+1];
extern UINT8 currentrecordpresetversion;
recordpreset_t *G_AddRecordPreset(const char *name, const char *realname);
const char *G_GetRecordPresetName(const char *name);
strbuf_t *G_AddRecordPresetVersion(recordpreset_t *preset, UINT8 version);
strbuf_t *G_GetRecordPresetVersion(const char *name, UINT8 version);
void G_SetCurrentRecordPreset(recordpreset_t *preset);
const char *G_CheckPresetCvars(strbuf_t *pv);
void G_SetPresetCvars(strbuf_t *pv);
boolean G_CompareRecordPresetVersions(strbuf_t *pre1, strbuf_t *pre2);
typedef struct
{
char prename[MAXPRESETNAME+1];
UINT8 version;
tic_t besttime;
tic_t bestlap;
tic_t playtime;
} maprecordpreset_t;
typedef struct
{
char name[MAXMAPLUMPNAME];
UINT8 visited;
tic_t playtime;
UINT32 roundsplayed;
UINT32 roundswon;
UINT16 numpresets;
maprecordpreset_t *presets;
} maprecord_t;
typedef enum
{
REPLAY_BESTTIME,
REPLAY_BESTLAP,
REPLAY_LAST,
REPLAY_GUEST,
REPLAY__MAX,
} recordreplay_e;
extern maprecord_t **maprecords;
extern size_t nummaprecords;
maprecord_t *G_AllocateMapRecord(const char *mapname);
maprecord_t *G_GetMapRecord(const char *mapname);
maprecordpreset_t *G_AllocateMapRecordPreset(maprecord_t *record, const char *presetname, UINT8 version);
maprecordpreset_t *G_GetMapRecordPreset(maprecord_t *record, const char *presetname);
void G_ClearRecords(void);
tic_t G_GetBestTime(INT16 map);
boolean G_EmblemsEnabled(void);
char *G_GetRecordReplayFolder(boolean home, boolean breaker);
char *G_GetRecordReplay(const char *folder, UINT16 mapnum, UINT16 skinnum, recordreplay_e which);
boolean G_CheckRecordReplay(const char *folder, UINT16 mapnum, UINT16 skinnum, recordreplay_e which);
FUNCMATH INT32 G_TicsToHours(tic_t tics);
FUNCMATH INT32 G_TicsToMinutes(tic_t tics, boolean full);

View file

@ -26,7 +26,6 @@
static CV_PossibleValue_t mousesens_cons_t[] = {{1, "MIN"}, {MAXMOUSESENSITIVITY, "MAX"}, {0, NULL}};
static CV_PossibleValue_t onecontrolperkey_cons_t[] = {{1, "One"}, {2, "Several"}, {0, NULL}};
static CV_PossibleValue_t turnsmooth_cons_t[] = {{2, "Slow"}, {1, "Fast"}, {0, "Off"}, {0, NULL}};
// mouse values are used once
consvar_t cv_mousesens = CVAR_INIT ("mousesens", "20", CV_SAVE, mousesens_cons_t, NULL);
@ -34,8 +33,6 @@ consvar_t cv_mousesens2 = CVAR_INIT ("mousesens2", "20", CV_SAVE, mousesens_cons
consvar_t cv_mouseysens = CVAR_INIT ("mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL);
consvar_t cv_mouseysens2 = CVAR_INIT ("mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL);
consvar_t cv_controlperkey = CVAR_INIT ("controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL);
consvar_t cv_turnsmooth = CVAR_INIT ("turnsmoothing", "Off", CV_SAVE, turnsmooth_cons_t, NULL);
// current state of the keys
// JOYAXISRANGE for fully pressed, 0 for not pressed
INT32 gamekeydown[MAXDEVICES][NUMINPUTS];

View file

@ -93,7 +93,7 @@ typedef enum
// mouse values are used once
extern consvar_t cv_mousesens, cv_mouseysens;
extern consvar_t cv_mousesens2, cv_mouseysens2;
extern consvar_t cv_controlperkey, cv_turnsmooth;
extern consvar_t cv_controlperkey;
// current state of the keys: JOYAXISRANGE or 0 when boolean.
// Or anything inbetween for analog values

View file

@ -34,6 +34,8 @@ typedef enum
GS_TIMEATTACK, // time attack menu
GS_CREDITS, // credit sequence
GS_BLANCREDITS, // BlanKart: Credits for BlanKart
GS_SECRETCREDITS, // BlanKart: Secret/full credits
GS_EVALUATION, // Evaluation at the end of a game.
// Hardcoded fades or other fading methods
@ -43,10 +45,6 @@ typedef enum
// Not fadable
GS_DEDICATEDSERVER, // new state for dedicated server
GS_WAITINGPLAYERS, // waiting for players in a net game
// New
GS_BLANCREDITS, // BlanKart: Credits for BlanKart
GS_SECRETCREDITS, // BlanKart: Secret/full credits
} gamestate_t;
typedef enum

File diff suppressed because it is too large Load diff

View file

@ -1572,7 +1572,9 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum)
break;
default: // Bad lump
CONS_Alert(CONS_WARNING, "Fade mask lump of incorrect size, ignored\n"); // I should avoid this by checking the lumpnum in HWR_RunWipe
break;
fmwidth = 0;
fmheight = 0;
return;
}
// Thankfully, this will still work for this scenario

View file

@ -33,15 +33,7 @@
#include "../r_plane.h" // R_FlatDimensionsFromLumpSize
#include <fcntl.h>
#include "../i_video.h" // for rendermode != render_glide
#ifndef O_BINARY
#define O_BINARY 0
#endif
#if defined(_MSC_VER)
#pragma pack(1)
#endif
typedef struct
{
UINT8 id_field_length ; // 1
@ -55,80 +47,11 @@ typedef struct
UINT8 image_pix_size ; //17
UINT8 image_descriptor; //18
} ATTRPACK TGAHeader; // sizeof is 18
#if defined(_MSC_VER)
#pragma pack()
#endif
static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255};
static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255};
static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111,127};
//
// -----------------+
// HWR_DrawPatch : Draw a 'tile' graphic
// Notes : x,y : positions relative to the original Doom resolution
// : textes(console+score) + menus + status bar
// -----------------+
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
{
FOutVector v[4];
FBITFIELD flags;
GLPatch_t *hwrPatch;
// 3--2
// | /|
// |/ |
// 0--1
float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f;
float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f;
float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f;
float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f;
// make patch ready in hardware cache
HWR_GetPatch(gpatch);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
switch (option & V_SCALEPATCHMASK)
{
case V_NOSCALEPATCH:
pdupx = pdupy = 2.0f;
break;
case V_SMALLSCALEPATCH:
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx);
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy);
break;
case V_MEDSCALEPATCH:
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx);
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy);
break;
}
if (option & V_NOSCALESTART)
sdupx = sdupy = 2.0f;
v[0].x = v[3].x = (x*sdupx-(gpatch->leftoffset)*pdupx)/vid.width - 1;
v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1;
v[0].y = v[1].y = 1-(y*sdupy-(gpatch->topoffset)*pdupy)/vid.height;
v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = hwrPatch->max_s;
v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest;
/*if (option & V_WRAPX)
flags |= PF_ForceWrapX;
if (option & V_WRAPY)
flags |= PF_ForceWrapY;*/
// clip it since it is used for bunny scroll in doom I
HWD.pfnDrawPolygon(NULL, v, 4, flags);
}
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap)
{
FOutVector v[4];
@ -781,137 +704,6 @@ void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight)
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
}
// ==========================================================================
// R_DRAW.C STUFF
// ==========================================================================
// ------------------
// HWR_DrawViewBorder
// Fill the space around the view window with a Doom flat texture, draw the
// beveled edges.
// 'clearlines' is useful to clear the heads up messages, when the view
// window is reduced, it doesn't refresh all the view borders.
// ------------------
void HWR_DrawViewBorder(INT32 clearlines)
{
INT32 x, y;
INT32 top, side;
INT32 baseviewwidth, baseviewheight;
INT32 basewindowx, basewindowy;
patch_t *patch;
// if (gl_viewwidth == vid.width)
// return;
if (!clearlines)
clearlines = BASEVIDHEIGHT; // refresh all
// calc view size based on original game resolution
baseviewwidth = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwidth), vid.fdupx)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7;
baseviewheight = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewheight), vid.fdupy));
top = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowy), vid.fdupy));
side = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwindowx), vid.fdupx));
// top
HWR_DrawFlatFill(0, 0,
BASEVIDWIDTH, (top < clearlines ? top : clearlines),
st_borderpatchnum);
// left
if (top < clearlines)
HWR_DrawFlatFill(0, top, side,
(clearlines-top < baseviewheight ? clearlines-top : baseviewheight),
st_borderpatchnum);
// right
if (top < clearlines)
HWR_DrawFlatFill(side + baseviewwidth, top, side,
(clearlines-top < baseviewheight ? clearlines-top : baseviewheight),
st_borderpatchnum);
// bottom
if (top + baseviewheight < clearlines)
HWR_DrawFlatFill(0, top + baseviewheight,
BASEVIDWIDTH, BASEVIDHEIGHT, st_borderpatchnum);
//
// draw the view borders
//
basewindowx = (BASEVIDWIDTH - baseviewwidth)>>1;
if (baseviewwidth == BASEVIDWIDTH)
basewindowy = 0;
else
basewindowy = top;
// top edge
if (clearlines > basewindowy - 8)
{
patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH);
for (x = 0; x < baseviewwidth; x += 8)
HWR_DrawPatch(patch, basewindowx + x, basewindowy - 8,
0);
}
// bottom edge
if (clearlines > basewindowy + baseviewheight)
{
patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH);
for (x = 0; x < baseviewwidth; x += 8)
HWR_DrawPatch(patch, basewindowx + x,
basewindowy + baseviewheight, 0);
}
// left edge
if (clearlines > basewindowy)
{
patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH);
for (y = 0; y < baseviewheight && basewindowy + y < clearlines;
y += 8)
{
HWR_DrawPatch(patch, basewindowx - 8, basewindowy + y,
0);
}
}
// right edge
if (clearlines > basewindowy)
{
patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH);
for (y = 0; y < baseviewheight && basewindowy+y < clearlines;
y += 8)
{
HWR_DrawPatch(patch, basewindowx + baseviewwidth,
basewindowy + y, 0);
}
}
// Draw beveled corners.
if (clearlines > basewindowy - 8)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TL],
PU_PATCH),
basewindowx - 8, basewindowy - 8, 0);
if (clearlines > basewindowy - 8)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TR],
PU_PATCH),
basewindowx + baseviewwidth, basewindowy - 8, 0);
if (clearlines > basewindowy+baseviewheight)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BL],
PU_PATCH),
basewindowx - 8, basewindowy + baseviewheight, 0);
if (clearlines > basewindowy + baseviewheight)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BR],
PU_PATCH),
basewindowx + baseviewwidth,
basewindowy + baseviewheight, 0);
}
// ==========================================================================
// AM_MAP.C DRAWING STUFF
// ==========================================================================
@ -1182,11 +974,9 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
#ifdef HAVE_PNG
#ifndef _MSC_VER
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#endif
#ifndef _LFS64_LARGEFILE
#define _LFS64_LARGEFILE
@ -1214,7 +1004,7 @@ static inline boolean saveTGA(const char *file_name, void *buffer,
INT32 i;
UINT8 *buf8 = buffer;
fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0)
return false;

View file

@ -43,10 +43,6 @@ typedef struct
float z;
} polyvertex_t;
#ifdef _MSC_VER
#pragma warning(disable : 4200)
#endif
// a convex 'plane' polygon, clockwise order
typedef struct
{
@ -54,10 +50,6 @@ typedef struct
polyvertex_t pts[];
} poly_t;
#ifdef _MSC_VER
#pragma warning(default : 4200)
#endif
// holds extra info for 3D render, for each subsector in subsectors[]
typedef struct
{

View file

@ -3386,7 +3386,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
tmult = (tbot - ttop) / (top - bot);
endrealtop = endtop = baseWallVerts[2].y;
endrealbot = endbot = baseWallVerts[1].y;
endrealbot = baseWallVerts[1].y;
// copy the contents of baseWallVerts into the drawn wallVerts array
// baseWallVerts is used to know the final shape to easily get the vertex
@ -4683,6 +4683,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
float x1, x2;
float rightsin, rightcos;
float this_scale, this_xscale, this_yscale;
fixed_t highresscale;
float spritexscale, spriteyscale;
float shadowheight = 1.0f, shadowscale = 1.0f;
float gz, gzt;
@ -4858,7 +4859,15 @@ static void HWR_ProjectSprite(mobj_t *thing)
}
if (thing->skin && ((skin_t *)thing->skin)->highresscale != FRACUNIT)
this_scale *= FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale);
{
float hi_res = ((skin_t *)thing->skin)->highresscale;
this_scale *= FIXED_TO_FLOAT(hi_res);
highresscale = hi_res;
}
else
{
highresscale = FRACUNIT;
}
spr_width = spritecachedinfo[lumpoff].width;
spr_height = spritecachedinfo[lumpoff].height;
@ -4911,11 +4920,11 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (thing->renderflags & RF_ABSOLUTEOFFSETS)
{
spr_offset = interp.spritexoffset;
spr_offset = FixedDiv(interp.spritexoffset,highresscale);
#ifdef ROTSPRITE
spr_topoffset = (interp.spriteyoffset + FixedDiv((visoffs.y * visoffymul), mapobjectscale) + (rotoffset.y * visoffymul));
spr_topoffset = (FixedDiv(interp.spriteyoffset,highresscale) + FixedDiv((visoffs.y * visoffymul), mapobjectscale) + (rotoffset.y * visoffymul));
#else
spr_topoffset = interp.spriteyoffset;
spr_topoffset = FixedDiv(interp.spriteyoffset,highresscale);
#endif
}
else
@ -4925,12 +4934,12 @@ static void HWR_ProjectSprite(mobj_t *thing)
if ((thing->renderflags & RF_FLIPOFFSETS) && flip)
flipoffset = -1;
spr_offset += interp.spritexoffset * flipoffset;
spr_offset += FixedDiv(interp.spritexoffset,highresscale) * flipoffset;
#ifdef ROTSPRITE
spr_topoffset += (interp.spriteyoffset + FixedDiv((visoffs.y * visoffymul),
spr_topoffset += (FixedDiv(interp.spriteyoffset,highresscale) + FixedDiv((visoffs.y * visoffymul),
mapobjectscale) + (rotoffset.y * visoffymul)) * flipoffset;
#else
spr_topoffset += interp.spriteyoffset * flipoffset;
spr_topoffset += FixedDiv(interp.spriteyoffset,highresscale) * flipoffset;
#endif
}
@ -5475,8 +5484,6 @@ void HWR_BuildSkyDome(void)
sky->loops[sky->loopcount].use_texture = false;
sky->loopcount++;
delta = 0.0f;
for (c = 0; c < col_count; c++)
{
HWR_SkyDomeVertex(sky, vertex_p, 1, c, yflip, 0.0f, true);

View file

@ -38,11 +38,9 @@ void HWR_RenderSkyboxView(player_t *player);
void HWR_RenderPlayerView(void);
void HWR_ClearSkyDome(void);
void HWR_BuildSkyDome(void);
void HWR_DrawViewBorder(INT32 clearlines);
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum);
void HWR_InitTextureMapping(void);
void HWR_SetViewSize(void);
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option);
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);

View file

@ -51,11 +51,9 @@
#ifdef HAVE_PNG
#ifndef _MSC_VER
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#endif
#ifndef _LFS64_LARGEFILE
#define _LFS64_LARGEFILE
@ -1009,25 +1007,7 @@ static void HWR_CreateBlendedTexture(patch_t *gpatch, patch_t *blendgpatch, GLMi
continue;
}
firsti = 0;
mul = 0;
mulmax = 1;
/*for (i = 0; i < translen; i++)
{
if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is)
continue;
compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness));
if (compare < brightdif)
{
brightdif = (UINT16)compare;
firsti = i; // best matching color that's equal brightness or darker
}
}*/
firsti = color_match_lookup[brightness];
secondi = firsti+1; // next color in line
m = (INT16)brightness - (INT16)colorbrightnesses[secondi];
@ -1362,10 +1342,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
FTransform p;
FSurfaceInfo Surf;
if (!cv_glmodels.value)
return false;
if (spr->precip)
if (!cv_glmodels.value || spr->precip)
return false;
// Lactozilla: Disallow certain models from rendering

View file

@ -21,10 +21,6 @@
extern "C" {
#endif
#if defined(_MSC_VER)
#pragma pack()
#endif
typedef struct
{
char filename[32];

View file

@ -23,16 +23,8 @@
#ifdef HAVE_SDL
#define _MATH_DEFINES_DEFINED
#ifdef _MSC_VER
#pragma warning(disable : 4214 4244)
#endif
#include "SDL_opengl.h" //Alam_GBC: Simple, yes?
#ifdef _MSC_VER
#pragma warning(default : 4214 4244)
#endif
#else
#include <GL/gl.h>

View file

@ -450,11 +450,6 @@ EXPORT void HWRAPI( Shutdown ) ( void )
//TODO:check?
}
#ifdef _MSC_VER
#pragma warning(disable : 4200)
#pragma pack(1)
#endif
typedef struct
{
ALushort header; // 3?
@ -464,11 +459,6 @@ typedef struct
ALubyte data[0]; // data;
} ATTRPACK dssfx_t;
#ifdef _MSC_VER
#pragma pack()
#pragma warning(default : 4200)
#endif
static ALsizei getfreq(ALvoid *sfxdata, size_t len)
{
dssfx_t *dsfx = sfxdata;

View file

@ -224,6 +224,7 @@ HMS_connect (const char *format, ...)
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, (long)CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)cv_masterserver_timeout.value);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 30L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer);

View file

@ -784,7 +784,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|| target == 0 // To everyone
|| consoleplayer == target-1) // To you
{
const char *prefix = "", *cstart = "", *cend = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt2, *textcolor = "\x80";
const char *prefix, *cstart, *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt2, *textcolor = "\x80";
char *tempchar = NULL;
char color_prefix[2];
@ -877,13 +877,13 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
// name, color end, and the message itself.
// '\4' makes the message yellow and beeps; '\3' just beeps.
if (action)
fmt2 = "* %s%s%s%s \x82%s%s";
fmt2 = "* %s%s%s %s%s";
else if (target-1 == consoleplayer) // To you
{
prefix = "\x82[PM]";
cstart = "\x82";
textcolor = "\x82";
fmt2 = "%s<%s%s>%s\x80 %s%s";
fmt2 = "%s<%s%s> %s%s";
}
else if (target > 0) // By you, to another player
{
@ -891,11 +891,11 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
dispname = player_names[target-1];
prefix = "\x82[TO]";
cstart = "\x82";
fmt2 = "%s<%s%s>%s\x80 %s%s";
fmt2 = "%s<%s%s> %s%s";
}
else // To everyone or sayteam, it doesn't change anything.
fmt2 = "%s<%s%s%s>\x80 %s%s";
fmt2 = "%s<%s%s> %s%s";
/*else // To your team
{
if (players[playernum].ctfteam == 1) // red
@ -908,7 +908,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
fmt2 = "%s<%s%s>\x80%s %s%s";
}*/
HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, textcolor, msg), (cv_chatnotifications.value) && !(flags & HU_SHOUT)); // add to chat
HU_AddChatText(va(fmt2, prefix, cstart, dispname, textcolor, msg), (cv_chatnotifications.value) && !(flags & HU_SHOUT)); // add to chat
if ((cv_chatnotifications.value) && (flags & HU_SHOUT))
S_StartSound(NULL, sfx_sysmsg);
@ -2176,76 +2176,6 @@ void HU_Drawer(void)
}
}
//======================================================================
// HUD MESSAGES CLEARING FROM SCREEN
//======================================================================
// Clear old messages from the borders around the view window
// (only for reduced view, refresh the borders when needed)
//
// startline: y coord to start clear,
// clearlines: how many lines to clear.
//
static INT32 oldclearlines;
void HU_Erase(void)
{
INT32 topline, bottomline;
INT32 y, yoffset;
#ifdef HWRENDER
// clear hud msgs on double buffer (OpenGL mode)
boolean secondframe;
static INT32 secondframelines;
#endif
if (con_clearlines == oldclearlines && !con_hudupdate && !chat_on)
return;
#ifdef HWRENDER
// clear the other frame in double-buffer modes
secondframe = (con_clearlines != oldclearlines);
if (secondframe)
secondframelines = oldclearlines;
#endif
// clear the message lines that go away, so use _oldclearlines_
bottomline = oldclearlines;
oldclearlines = con_clearlines;
if (chat_on && OLDCHAT)
if (bottomline < 8)
bottomline = 8; // only do it for consolechat. consolechat is gay.
if (automapactive || viewwindowx == 0) // hud msgs don't need to be cleared
return;
// software mode copies view border pattern & beveled edges from the backbuffer
if (rendermode == render_soft)
{
topline = 0;
for (y = topline, yoffset = y*vid.width; y < bottomline; y++, yoffset += vid.width)
{
if (y < viewwindowy || y >= viewwindowy + viewheight)
R_VideoErase(yoffset, vid.width); // erase entire line
else
{
R_VideoErase(yoffset, viewwindowx); // erase left border
// erase right border
R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx);
}
}
con_hudupdate = false; // if it was set..
}
#ifdef HWRENDER
else if (rendermode != render_none)
{
// refresh just what is needed from the view borders
HWR_DrawViewBorder(secondframelines);
con_hudupdate = secondframe;
}
#endif
}
//======================================================================
// IN-LEVEL MULTIPLAYER RANKINGS
//======================================================================
@ -2373,6 +2303,75 @@ void HU_drawPing(INT32 x, INT32 y, UINT32 ping, UINT32 mindelay, UINT32 pl, INT3
V_DrawMappedPatch(x+1 - pingmeasure[measureid]->width, y+11, flags, pingmeasure[measureid], colormap);
}
//
// HU_drawOldPing
//
void HU_drawOldPing(INT32 x, INT32 y, UINT32 ping, UINT32 mindelay, UINT32 pl, INT32 flags)
{
INT32 measureid = cv_pingmeasurement.value ? 1 : 0;
UINT32 lag = max(ping, mindelay);
//SRB2/Kart v1.0 style
UINT8 numbars = 0; // how many ping bars do we draw?
UINT8 barcolor = 31; // color we use for the bars (green, yellow, red or black)
SINT8 i = 0;
SINT8 yoffset = 6;
if (vid.width >= 640) // how sad, we're using a shit resolution.
{
if (measureid == 1)
{
V_DrawRightAlignedSmallString(x+12, y+13, V_ALLOWLOWERCASE|flags, va("%dms", Ping_conversion(lag)));
}
else if (measureid == 0)
{
V_DrawRightAlignedSmallString(x+12, y+13, flags, va("d%d", Ping_conversion(lag)));
}
}
if (cv_pingicon.value)
{
switch (lag)
{
case 0 ... 1:
numbars = 3;
barcolor = 215; // Blue
break;
case 2 ... 3:
numbars = 3;
barcolor = 184; // Green
break;
case 4 ... 6:
numbars = 2; // Apparently ternaries w/ multiple statements don't look good in C so I decided against it.
barcolor = 103; // Yellow
break;
case 7 ... 9:
numbars = 1;
barcolor = 155; // Red
break;
default: // Brazil
numbars = 0;
barcolor = 31; // black
break;
}
if (pl)
{
barcolor = 194; // make it purplish
// bars get indirectly set earlier
}
for (i = 0; (i < 3); i++) // Draw the ping bar
{
V_DrawFill(x+2 *(i-1)+7, y+8+yoffset-4, 2, 8-yoffset, 31|flags);
if (i < numbars)
V_DrawFill(x+2 *(i-1)+7, y+8+yoffset-3, 1, 8-yoffset-1, barcolor|flags);
yoffset -= 2;
}
}
}
void
HU_drawMiniPing (INT32 x, INT32 y, UINT32 ping, UINT32 lag, INT32 flags)
{

View file

@ -131,9 +131,9 @@ void HU_TickSongCredits(void);
void HU_DrawSongCredits(void);
void HU_Drawer(void);
char HU_dequeueChatChar(void);
void HU_Erase(void);
void HU_clearChatChars(void);
void HU_drawPing(INT32 x, INT32 y, UINT32 ping, UINT32 mindelay, UINT32 pl, INT32 flags, boolean icon);
void HU_drawOldPing(INT32 x, INT32 y, UINT32 ping, UINT32 mindelay, UINT32 pl, INT32 flags);
void HU_drawMiniPing (INT32 x, INT32 y, UINT32 ping, UINT32 lag, INT32 flags);
INT32 HU_CreateTeamScoresTbl(playersort_t *tab, UINT32 dmtotals[]);

View file

@ -39,11 +39,7 @@
#ifndef I_getaddrinfo
#if !defined (_MSC_VER) || (_MSC_VER >= 1800) // MSVC 2013 and forward
#include <stdbool.h>
#else
typedef char bool;
#endif
#ifdef _WIN32
// it seems windows doesn't define that... maybe some other OS? OS/2

View file

@ -22,10 +22,10 @@
/// \def MAXPACKETLENGTH
/// For use in a LAN
#define MAXPACKETLENGTH 1450
#define MAXPACKETLENGTH 2048
/// \def INETPACKETLENGTH
/// For use on the internet
#define INETPACKETLENGTH 1024
#define INETPACKETLENGTH 1450
#define NO_BAN_TIME (time_t)(-1)
@ -36,10 +36,6 @@ extern "C" {
extern INT16 hardware_MAXPACKETLENGTH;
extern INT32 net_bandwidth; // in byte/s
#if defined(_MSC_VER)
#pragma pack(1)
#endif
struct doomcom_t
{
/// Supposed to be DOOMCOM_ID
@ -90,10 +86,6 @@ struct holepunch_t
#define HOLEPUNCH_DATA(d) (holepunch_t *)&(d)->data
#if defined(_MSC_VER)
#pragma pack()
#endif
extern doomcom_t *doomcom;
/** \brief return packet in doomcom struct

View file

@ -29,6 +29,25 @@ consvar_t cv_timescale = CVAR_INIT ("timescale", "1.0", CV_NETVAR|CV_CHEAT|CV_FL
static precise_t enterprecise, oldenterprecise;
static fixed_t entertic, oldentertics;
static double tictimer;
static double ticratescaled;
// experiment to prevent timing issues
// this returns the global time state accounted with how much time has passed
// since it was last updated
static void I_GetTimeAndFrac(tic_t *outtics, fixed_t *outfrac)
{
double elapsedseconds;
elapsedseconds = (double)(I_GetPreciseTime() - oldenterprecise) / I_GetPrecisePrecision();
double fractional, integral;
fractional = modf((tictimer + elapsedseconds) * ticratescaled, &integral);
if (outtics)
*outtics = g_time.time + (tic_t)integral;
if (outfrac)
*outfrac = DoubleToFixed(fractional);
}
// A little more than the minimum sleep duration on Windows.
// May be incorrect for other platforms, but we don't currently have a way to
@ -42,8 +61,16 @@ static double tictimer;
tic_t I_GetTime(void)
{
I_UpdateTime(cv_timescale.value);
return g_time.time;
tic_t tic;
I_GetTimeAndFrac(&tic, NULL);
return tic;
}
fixed_t I_GetTimeFrac(void)
{
fixed_t frac;
I_GetTimeAndFrac(NULL, &frac);
return frac;
}
void I_InitializeTime(void)
@ -54,6 +81,7 @@ void I_InitializeTime(void)
enterprecise = 0;
oldenterprecise = 0;
tictimer = 0.0;
ticratescaled = 1.0;
CV_RegisterVar(&cv_timescale);
@ -64,12 +92,11 @@ void I_InitializeTime(void)
void I_UpdateTime(fixed_t timescale)
{
double ticratescaled;
double elapsedseconds;
tic_t realtics;
// get real tics
ticratescaled = (double)TICRATE * FIXED_TO_FLOAT(timescale);
ticratescaled = (double)((float)TICRATE * FixedToFloat(timescale));
enterprecise = I_GetPreciseTime();
elapsedseconds = (double)(enterprecise - oldenterprecise) / I_GetPrecisePrecision();

View file

@ -34,6 +34,8 @@ extern consvar_t cv_timescale;
*/
tic_t I_GetTime(void);
fixed_t I_GetTimeFrac(void);
/** \brief Initializes timing system.
*/
void I_InitializeTime(void);

View file

@ -108,8 +108,8 @@ void VID_CheckGLLoaded(rendermode_t oldrender);
\return name of video mode
*/
const char *VID_GetModeName(INT32 modenum);
void VID_PrepareModeList(void); /// note hack for SDL
void VID_PrepareModeList(void);
/** \brief can video system do fullscreen
*/

View file

@ -5,6 +5,8 @@ _(UNKNOWN)
_(THOK) // Thok! mobj
_(SHADOW) // Linkdraw Shadow (for invisible objects)
_(PLAYER)
_(KART_LEFTOVER)
_(KART_TIRE)
// Enemies
_(BLUECRAWLA) // Crawla (Blue)
@ -612,6 +614,7 @@ _(THUNDERSHIELD) // Shields
_(BUBBLESHIELD)
_(FLAMESHIELD)
_(BUBBLESHIELDTRAP)
_(BUBBLESHLD_DEBRIS)
_(SINK) // Kitchen Sink Stuff
_(SINK_SHIELD)

View file

@ -843,6 +843,7 @@ _(requst)
_(syfail)
_(itfree)
_(dbgsal)
_(bhurry) // mine: wasn't here already?
// Chaining Sound
_(bstchn)

View file

@ -7,6 +7,8 @@ _(UNKN)
_(THOK) // Thok! mobj
_(PLAY)
_(KART)
_(TIRE)
// Enemies
_(POSS) // Crawla (Blue)
@ -445,6 +447,8 @@ _(BHBM) // Ballhog BOOM
_(SPBM) // Self-Propelled Bomb
_(THNS) // Thunder Shield
_(BUBS) // Bubble Shield (not Bubs)
_(BUBC) // Bubble Shield damage
_(BSDB) // Bubble Shield shatter debris
_(BWVE) // Bubble Shield waves
_(FLMS) // Flame Shield
_(FLMD) // Flame Shield dash

View file

@ -48,6 +48,10 @@ _(KART_SIGN)
// technically the player goes here but it's an infinite tic state
_(OBJPLACE_DUMMY)
_(KART_LEFTOVER)
_(KART_LEFTOVER_NOTIRES)
_(KART_TIRE)
// Blue Crawla
_(POSS_STND)
_(POSS_RUN1)
@ -2888,7 +2892,7 @@ _(THUNDERSHIELD22)
_(THUNDERSHIELD23)
_(THUNDERSHIELD24)
// Bubble Shield
// Bubble Shield: Standard Sprites
_(BUBBLESHIELD1)
_(BUBBLESHIELD2)
_(BUBBLESHIELD3)
@ -2917,6 +2921,17 @@ _(BUBBLESHIELDTRAP6)
_(BUBBLESHIELDTRAP7)
_(BUBBLESHIELDTRAP8)
// Bubble Shield: Damage Visuals
_(BUBLSHLD_DMG_1)
_(BUBLSHLD_DMG_2)
_(BUBLSHLD_DMG_3)
_(BUBLSHLD_DMG_4)
_(BUBBLEDEBRIS_1)
_(BUBBLEDEBRIS_2)
_(BUBBLEDEBRIS_3)
_(BUBBLEDEBRIS_4)
_(BUBBLEDEBRIS_5)
// Flame Shield
_(FLAMESHIELD1)
_(FLAMESHIELD2)

View file

@ -265,11 +265,7 @@ void K_CheckBumpers(void)
{
if (nobumpers)
{
for (i = 0; i < MAXPLAYERS; i++)
{
players[i].pflags |= PF_NOCONTEST;
P_DoPlayerExit(&players[i]);
}
P_DoAllPlayersExit(PF_NOCONTEST, false);
}
return;
}
@ -284,11 +280,7 @@ void K_CheckBumpers(void)
{
if (nobumpers)
{
for (i = 0; i < MAXPLAYERS; i++)
{
players[i].pflags |= PF_NOCONTEST;
P_DoPlayerExit(&players[i]);
}
P_DoAllPlayersExit(PF_NOCONTEST, false);
}
}
@ -306,14 +298,7 @@ void K_CheckBumpers(void)
for (i = 0; i < MAXPLAYERS; i++) // This can't go in the earlier loop because winning adds points
K_KartUpdatePosition(&players[i]);
for (i = 0; i < MAXPLAYERS; i++) // and it can't be merged with this loop because it needs to be all updated before exiting... multi-loops suck...
{
if (!playeringame[i])
continue;
if (players[i].spectator)
continue;
P_DoPlayerExit(&players[i]);
}
P_DoAllPlayersExit(0, false);
}
UINT8 K_NumEmeralds(player_t *player)
@ -501,27 +486,16 @@ void K_SpawnPlayerBattleBumpers(player_t *p)
}
}
void K_BattleInit(void)
void K_BattleInit(UINT8 numPlayers)
{
size_t i;
if ((gametyperules & GTR_ITEMBREAKER) && !itembreaker && !bossinfo.boss)
{
if (modeattacking != ATTACKING_ITEMBREAK)
{
UINT8 n = 0;
if (!cv_kartitembreaker.value)
goto afteritembreaker;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
n++;
}
if (n > 1)
if (numPlayers > 1)
goto afteritembreaker;
}
@ -532,6 +506,7 @@ afteritembreaker:
if (gametyperules & GTR_BUMPERS)
{
INT32 maxbumpers = K_StartingBumperCount();
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
@ -542,3 +517,53 @@ afteritembreaker:
}
}
}
// Handle respawning the battle boxes.
void K_RespawnBattleBoxes(void)
{
if (!(gametyperules & GTR_BATTLEBOXES))
return;
if (itembreaker)
return;
if (numgotboxes < (4*nummapboxes/5))
return;
thinker_t *th;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
mobj_t *box;
mobj_t *newmobj;
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
box = (mobj_t *)th;
if (box->type != MT_RANDOMITEM || box->threshold != 68 || box->fuse) // only popped items
continue;
// Respawn from mapthing if you have one!
if (box->spawnpoint)
{
P_SpawnMapThing(box->spawnpoint);
newmobj = box->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing
P_SpawnMobj(box->spawnpoint->mobj->x, box->spawnpoint->mobj->y, box->spawnpoint->mobj->z, MT_EXPLODE); // poof into existance
}
else
{
newmobj = P_SpawnMobj(box->x, box->y, box->z, box->type);
P_SpawnMobj(newmobj->x, newmobj->y, newmobj->z, MT_EXPLODE); // poof into existance
}
// Transfer flags2 (strongbox, objectflip)
newmobj->flags2 = box->flags2;
P_RemoveMobj(box); // make sure they disappear
numgotboxes--; // you've restored a box, remove it from the count
}
if (numgotboxes < 0)
numgotboxes = 0;
}

View file

@ -21,7 +21,8 @@ void K_CheckBumpers(void);
UINT8 K_NumEmeralds(player_t *player);
void K_RunPaperItemSpawners(void);
void K_SpawnPlayerBattleBumpers(player_t *p);
void K_BattleInit(void);
void K_BattleInit(UINT8 numPlayers);
void K_RespawnBattleBoxes(void);
#ifdef __cplusplus
} // extern "C"

View file

@ -46,6 +46,7 @@
consvar_t cv_forcebots = CVAR_INIT ("kartforcebots", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_botcontrol = CVAR_INIT ("kartbotcontrol", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_forcerival = CVAR_INIT ("kartbot_forcerival", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
botdata_t botdata[MAXPLAYERS];
@ -159,6 +160,12 @@ void K_SetBot(UINT8 newplayernum, UINT16 skinnum, UINT8 difficulty, botStyle_e s
players[newplayernum].botvars.style = style;
players[newplayernum].lives = 9;
// Does the server want to force rivals? enforce this here.
if (cv_forcerival.value)
{
players[newplayernum].botvars.rival = true;
}
// The bot may immediately become a spectator AT THE START of a GP.
// For each subsequent round of GP, K_UpdateGrandPrixBots will handle this.
players[newplayernum].spectator = grandprixinfo.gp && grandprixinfo.initalize;
@ -256,6 +263,11 @@ void K_UpdateMatchRaceBots(void)
{
difficulty = 0;
}
else if (K_UsingLegacyCheckpoints() == true && !cv_forcebots.value)
{
CONS_Alert(CONS_ERROR, "This map does not use waypoints so bot functionality will not work.\nConsider adding new waypoints directly or via map patching for bot support.\n");
difficulty = 0;
}
else
{
difficulty = cv_kartbot.value;
@ -279,6 +291,16 @@ void K_UpdateMatchRaceBots(void)
// Enforce normal style for Match Race
players[i].botvars.style = BOT_STYLE_NORMAL;
// Does the server want to force rivals? enforce this here.
if (cv_forcerival.value)
{
players[i].botvars.rival = true;
}
else
{
players[i].botvars.rival = false;
}
}
else
{
@ -551,8 +573,11 @@ botcontroller_t *K_GetBotController(const mobj_t *mobj)
fixed_t K_BotMapModifier(void)
{
// fuck it we ball
return 5*FRACUNIT/10;
//return 5*FRACUNIT/10;
// ...with a bit of customization
return K_TrackModifierMax();
#if 0
constexpr INT32 complexity_scale = 10000;
fixed_t modifier_max = K_TrackModifierMax();
@ -568,6 +593,7 @@ fixed_t K_BotMapModifier(void)
);
return FRACUNIT + complexity_value;
#endif
}
/*--------------------------------------------------

View file

@ -24,6 +24,7 @@ extern "C" {
extern consvar_t cv_forcebots;
extern consvar_t cv_botcontrol;
extern consvar_t cv_forcerival;
// Maximum value of botvars.difficulty
#define MAXBOTDIFFICULTY (13)

View file

@ -63,7 +63,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
if (t2->player->hyudorotimer)
return true; // no interaction
if (t2->player->flamestore && (K_GetShieldFromPlayer(t2->player) == KITEM_FLAMESHIELD))
if (t2->player->flamestore && (K_GetShieldFromPlayer(t2->player) == KSHIELD_FLAME))
{
// Melt item
S_StartSound(t2, sfx_s3k43);
@ -159,7 +159,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
damageitem = true;
if (t2->player->flamestore && (K_GetShieldFromPlayer(t2->player) == KITEM_FLAMESHIELD))
if (t2->player->flamestore && (K_GetShieldFromPlayer(t2->player) == KSHIELD_FLAME))
{
// Melt item
S_StartSound(t2, sfx_s3k43);
@ -249,7 +249,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
t2->player->roulettetype = KROULETTETYPE_EGGMAN;
}
if (t2->player->flamestore && (K_GetShieldFromPlayer(t2->player) == KITEM_FLAMESHIELD))
if (t2->player->flamestore && (K_GetShieldFromPlayer(t2->player) == KSHIELD_FLAME))
{
// Melt item
S_StartSound(t2, sfx_s3k43);
@ -381,7 +381,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
if (t1->health > 1)
S_StartSound(t2, sfx_bsnipe);
if (t2->player->flamestore && (K_GetShieldFromPlayer(t2->player) == KITEM_FLAMESHIELD))
if (t2->player->flamestore && (K_GetShieldFromPlayer(t2->player) == KSHIELD_FLAME))
{
// Melt item
S_StartSound(t2, sfx_s3k43);
@ -389,7 +389,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
else
{
// Player Damage
P_DamageMobj(t2, t1, t1->target, 1, DMG_EXPLODE);
P_DamageMobj(t2, t1, t1->target, 1, DMG_FLIPOVER);
}
P_SpawnMobj(t1->x, t1->y, t1->z, MT_MINEEXPLOSIONSOUND);
@ -545,44 +545,46 @@ static void K_BubbleShieldCollideDrain(player_t *player, mobj_t *bubble)
}
}
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2, boolean isplayer)
static boolean K_BubbleReflectingTrapItem(const mobj_t *t)
{
return t->type == MT_BANANA || (t->type == MT_ORBINAUT && t->flags2 & MF2_AMBUSH) || t->type == MT_JAWZ_DUD ||
t->type == MT_EGGMANITEM || t->type == MT_SSMINE || t->type == MT_SSMINE_SHIELD || t->type == MT_LANDMINE;
}
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2)
{
if (t2->threshold && !t2->player)
return false;
mobj_t *owner = t1->player ? t1 : t1->target;
INT32 div = 2;
if (isplayer)
angle_t angle = R_PointToAngle2(t1->x, t1->y, t2->x, t2->y);
fixed_t momentum = max(FixedHypot(owner->momx, owner->momy), FixedHypot(t2->momx, t2->momy));
momentum = max(3*momentum/4, 16*mapobjectscale); // do SOMETHING!
P_InstaThrust(t2, angle, momentum);
if (!t2->player)
t2->angle = angle;
if (K_BubbleReflectingTrapItem(t2))
{
div = 1;
// Stupid hack: Toss trap/dud items into the air
t2->momz += (24*t2->scale) * P_MobjFlip(t2);
t2->z += t2->momz;
}
if ((!t2->threshold)||(isplayer))
if (!t2->player)
{
if (!t2->momx && !t2->momy)
{
t2->momz += (24*t2->scale) * P_MobjFlip(t2);
}
if (t2->type == MT_JAWZ)
P_SetTarget(&t2->tracer, t2->target); // Back to the source!
P_SetTarget(&t2->target, owner); // Let the source reflect it back again!
if ((t2->type == MT_ORBINAUT && t2->flags2 & MF2_AMBUSH) || t2->type == MT_JAWZ_DUD)
t2->flags |= MF_NOCLIPTHING;
else
{
t2->momx = (-1*t2->momx)/div;
t2->momy = (-1*t2->momy)/div;
t2->momz = (-1*t2->momz)/div;
if (!isplayer)
{
t2->angle += ANGLE_180;
}
}
if (!isplayer)
{
if (t2->type == MT_JAWZ)
P_SetTarget(&t2->tracer, t2->target); // Back to the source!
P_SetTarget(&t2->target, owner); // Let the source reflect it back again!
t2->threshold = 10;
}
S_StartSound(t1, sfx_s3k44);
}
S_StartSound(t1, sfx_s3k44);
return true;
}
@ -591,6 +593,7 @@ boolean K_BubbleShieldCanReflect(mobj_t *t1, mobj_t *t2)
return (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD
|| t2->type == MT_BANANA || t2->type == MT_EGGMANITEM || t2->type == MT_BALLHOG
|| t2->type == MT_SSMINE || t2->type == MT_LANDMINE || t2->type == MT_SINK
|| t2->type == MT_KART_LEFTOVER
|| (t2->type == MT_PLAYER && t1->target != t2));
}
@ -616,12 +619,15 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
if (K_BubbleShieldCanReflect(t1, t2))
{
if ((!t2->threshold)||(t2->player))
boolean reflected = K_BubbleShieldReflect(t1, t2);
if (reflected)
{
// Drain my stuff please.
K_BubbleShieldCollideDrain(t1->target->player, t1);
}
return K_BubbleShieldReflect(t1, t2, (t2->player) ? true : false);
return reflected;
}
if (t2->flags & MF_SHOOTABLE)

View file

@ -17,7 +17,7 @@ boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2);
boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2);
void K_ThunderShieldAttack(mobj_t *actor, fixed_t size);
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2, boolean isplayer);
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2);
boolean K_BubbleShieldCanReflect(mobj_t *t1, mobj_t *t2);
boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2);

View file

@ -410,10 +410,8 @@ void K_HandleFollower(player_t *player)
if (fl.mode == FOLLOWERMODE_GROUND)
{
sector_t *sec = R_PointInSubsector(sx, sy)->sector;
fh = min(fh, P_GetFloorZ(player->follower, sec, sx, sy, NULL));
ch = max(ch, P_GetCeilingZ(player->follower, sec, sx, sy, NULL) - ourheight);
fh = min(fh, P_FloorzAtPos(sx, sy, player->follower->z, ourheight));
ch = max(ch, P_CeilingzAtPos(sx, sy, player->follower->z, ourheight) - ourheight);
if (P_IsObjectOnGround(player->mo) == false)
{

View file

@ -104,7 +104,7 @@ UINT8 K_GetGPPlayerCount(UINT8 humans)
// 3P -> 12 total
// 4P -> 16 total
return max(min(humans * 4, MAXPLAYERS), 8);
return max(min(humans * 4, MAXGPPLAYERS), 8);
}
/*--------------------------------------------------
@ -117,7 +117,7 @@ void K_InitGrandPrixBots(void)
const UINT16 defaultbotskin = K_BotDefaultSkin();
const UINT8 startingdifficulty = K_BotStartingDifficulty(grandprixinfo.gamespeed);
UINT8 difficultylevels[MAXPLAYERS];
UINT8 difficultylevels[MAXGPPLAYERS];
UINT8 playercount = 8;
UINT8 wantedbots = 0;
@ -128,13 +128,13 @@ void K_InitGrandPrixBots(void)
UINT16 usableskins, skincount = numskins;
UINT16 grabskins[MAXSKINS+1];
UINT16 botskinlist[MAXPLAYERS];
UINT16 botskinlist[MAXGPPLAYERS];
UINT16 botskinlistpos = 0;
UINT8 newplayernum = 0;
UINT16 i, j;
memset(competitors, MAXPLAYERS, sizeof (competitors));
memset(competitors, MAXGPPLAYERS, sizeof (competitors));
memset(botskinlist, defaultbotskin, sizeof (botskinlist));
// Init usable bot skins list
@ -144,7 +144,7 @@ void K_InitGrandPrixBots(void)
}
grabskins[usableskins] = MAXSKINS;
#if MAXPLAYERS != 16
#if MAXGPPLAYERS != 16
I_Error("GP bot difficulty levels need rebalanced for the new player count!\n");
#endif
@ -178,7 +178,7 @@ void K_InitGrandPrixBots(void)
{
if (playeringame[i])
{
if (players[i].bot == true)
if (players[i].bot == true || i > MAXGPPLAYERS)
{
// Remove existing bots.
CL_RemovePlayer(i, KR_LEAVE);
@ -298,7 +298,7 @@ static INT16 K_RivalScore(player_t *bot)
roundsleft = grandprixinfo.cup->numlevels - grandprixinfo.roundnum;
}
for (i = 0; i < MAXPLAYERS; i++)
for (i = 0; i < MAXGPPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
{
@ -333,9 +333,10 @@ void K_UpdateGrandPrixBots(void)
player_t *oldrival = NULL;
player_t *newrival = NULL;
UINT16 newrivalscore = 0;
boolean validbots = (K_UsingLegacyCheckpoints() == false);
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
for (i = 0; i < MAXGPPLAYERS; i++)
{
if (!playeringame[i] || !players[i].bot)
{
@ -343,10 +344,15 @@ void K_UpdateGrandPrixBots(void)
}
players[i].spectator = (grandprixinfo.eventmode != GPEVENT_NONE);
if (!validbots)
{
players[i].spectator = true;
}
}
// Find the rival.
for (i = 0; i < MAXPLAYERS; i++)
for (i = 0; i < MAXGPPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || !players[i].bot)
{
@ -382,7 +388,7 @@ void K_UpdateGrandPrixBots(void)
}
// Find the bot with the best average of score & difficulty.
for (i = 0; i < MAXPLAYERS; i++)
for (i = 0; i < MAXGPPLAYERS; i++)
{
UINT16 ns = 0;
@ -421,6 +427,12 @@ void K_UpdateGrandPrixBots(void)
// Set our new rival!
newrival->botvars.rival = true;
}
if (!validbots)
{
CONS_Alert(CONS_ERROR, "This map does not use waypoints so bot functionality will not work.\nConsider adding new waypoints directly or via map patching for bot support.\n");
}
}
/*--------------------------------------------------
@ -440,7 +452,7 @@ static UINT8 K_BotExpectedStanding(player_t *bot)
UINT8 pos = 1;
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
for (i = 0; i < MAXGPPLAYERS; i++)
{
if (i == (bot - players))
{

View file

@ -149,9 +149,12 @@ static patch_t *kp_speedometerlabel[4];
static patch_t *kp_kartzspeedo[25];
static patch_t *kp_kartzspeedo_smol[25];
static patch_t *kp_driftgauge[13];
static patch_t *kp_driftgauge[14];
static patch_t *kp_driftgaugeparts[5];
static patch_t *kp_flamometer[4];
static patch_t *kp_flamefire[4];
static patch_t *kp_rankbumper;
static patch_t *kp_tinybumper[2];
static patch_t *kp_ranknobumpers;
@ -269,6 +272,9 @@ void K_RegisterKartHUDStuff(void)
CV_RegisterVar(&cv_draftindicator);
}
// YOUR TOO TOO (try limit for NULL HUD patches)
#define YOURTAKINGTOOLONG 64
void K_LoadKartHUDGraphics(void)
{
INT32 i, j;
@ -375,8 +381,9 @@ void K_LoadKartHUDGraphics(void)
buffer[7] = '0'+(i+1);
HU_UpdatePatch(&kp_facehighlight[i], "%s", buffer);
kp_facehighlight[i]->leftoffset = kp_facehighlight[i]->width / 2;
kp_facehighlight[i]->topoffset = kp_facehighlight[i]->height / 2;
kp_facehighlight[i]->pivot.x = kp_facehighlight[i]->width / 2;
kp_facehighlight[i]->pivot.y = kp_facehighlight[i]->height / 2;
kp_facehighlight[i]->alignflags |= PATCHALIGN_USEPIVOTS;
}
// Special minimap icons
@ -422,7 +429,27 @@ void K_LoadKartHUDGraphics(void)
HU_UpdatePatch(&kp_driftgaugeparts[2], "K_WDGM3");
HU_UpdatePatch(&kp_driftgaugeparts[3], "K_WDGM4");
HU_UpdatePatch(&kp_driftgaugeparts[4], "K_DGAU3M");
// Flamometer UI Elements
HU_UpdatePatch(&kp_flamometer[0], "THERMOBACK");
HU_UpdatePatch(&kp_flamometer[1], "THERMOFUEL");
HU_UpdatePatch(&kp_flamometer[2], "THERMOTEMP");
HU_UpdatePatch(&kp_flamometer[3], "THERMOMETRE");
//Flamometer Fire
{
const char* patchNames[] = {
"THFIRE1",
"THFIRE2",
"THFIRE3",
"THFIRE4"
};
for (size_t m = 0; m < sizeof(patchNames) / sizeof(patchNames[0]); ++m)
{
kp_flamefire[m] = W_CachePatchName(patchNames[m], PU_HUDGFX);
}
}
// Speedometer labels
HU_UpdatePatch(&kp_speedometerlabel[0], "SP_MKMH");
@ -1524,14 +1551,14 @@ static void K_drawKartItem(void)
V_DrawScaledPatch(fx+x, fy+y, V_HUDTRANS|fflags, kp_itemtimer[offset]);
// The left dark "AA" edge
V_DrawFill(fx+x+1, fy+y+1, (length == 2 ? 2 : 1), height, 12|fflags);
V_DrawFill(fx+x+1, fy+y+1, (length == 2 ? 2 : 1), height, 12|fflags|V_HUDTRANS);
// The bar itself
if (length > 2)
{
V_DrawFill(fx+x+length, fy+y+1, 1, height, 12|fflags); // the right one
V_DrawFill(fx+x+length, fy+y+1, 1, height, 12|fflags|V_HUDTRANS); // the right one
if (height == 2)
V_DrawFill(fx+x+2, fy+y+2, length-2, 1, 8|fflags); // the dulled underside
V_DrawFill(fx+x+2, fy+y+1, length-2, 1, 0|fflags); // the shine
V_DrawFill(fx+x+2, fy+y+2, length-2, 1, 8|fflags|V_HUDTRANS); // the dulled underside
V_DrawFill(fx+x+2, fy+y+1, length-2, 1, 0|fflags|V_HUDTRANS); // the shine
}
}
@ -1544,14 +1571,14 @@ static void K_drawKartItem(void)
V_DrawScaledPatch(fx+x, fy+y-8, V_HUDTRANS|fflags, kp_itemtimer[offset]);
// The left dark "AA" edge
V_DrawFill(fx+x+1, fy+y+1-8, (length == 2 ? 2 : 1), height, 55|fflags);
V_DrawFill(fx+x+1, fy+y+1-8, (length == 2 ? 2 : 1), height, 55|fflags|V_HUDTRANS);
// The bar itself
if (length > 2)
{
V_DrawFill(fx+x+length, fy+y+1-8, 1, height, 55|fflags); // the right one
V_DrawFill(fx+x+length, fy+y+1-8, 1, height, 55|fflags|V_HUDTRANS); // the right one
if (height == 2)
V_DrawFill(fx+x+2, fy+y+2-8, length-2, 1, 36|fflags); // the dulled underside
V_DrawFill(fx+x+2, fy+y+1-8, length-2, 1, 51|fflags); // the shine
V_DrawFill(fx+x+2, fy+y+2-8, length-2, 1, 36|fflags|V_HUDTRANS); // the dulled underside
V_DrawFill(fx+x+2, fy+y+1-8, length-2, 1, 51|fflags|V_HUDTRANS); // the shine
}
}
@ -1567,7 +1594,8 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
tic_t worktime;
boolean dontdraw = false;
boolean emblemenabled = K_EmblemsEnabled();
boolean overtime = false;
UINT8 *textcolor = 0;
INT32 splitflags = 0;
if (!mode)
@ -1582,14 +1610,16 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
if (bossinfo.boss == true)
;
else if (timelimitintics > 0 && (gametyperules & GTR_TIMELIMIT)) // TODO
{
{
if (drawtime >= (timelimitintics - 5*TICRATE) && ((drawtime*4)/TICRATE) % 2 == 0)
{
dontdraw = true;
}
if (drawtime >= timelimitintics)
{
if (((drawtime-timelimitintics)/TICRATE) & 1)
{
dontdraw = true;
}
drawtime = 0;
overtime = true;
// drawtime = 0;
}
else
{
@ -1610,10 +1640,34 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
worktime = drawtime/(60*TICRATE);
if (mode && !drawtime)
if (mode && drawtime == UINT32_MAX)
V_DrawKartString(TX, TY+3, splitflags, va("--'--\"--"));
else if (dontdraw) // overtime flash
;
else if (overtime)
{
if (((drawtime*2)/TICRATE) % 2 == 0)
{
textcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE);
}
else
{
textcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_ORANGE, GTC_CACHE);
}
V_DrawStringScaledEx(
(TIME_X + 33) << FRACBITS,
(TIME_Y + 3) << FRACBITS,
FRACUNIT,
FRACUNIT,
FRACUNIT,
FRACUNIT,
splitflags,
textcolor,
KART_FONT,
va("OVERTIME!")
);
}
else if (worktime < 100) // 99:99:99 only
{
// zero minute
@ -1662,7 +1716,7 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
else if ((drawtime/TICRATE) & 1)
V_DrawKartString(TX, TY+3, splitflags, va("99'59\"99"));
if ((modeattacking || (mode == 1)) && emblemenabled && !demo.playback) // emblem time!
if ((modeattacking || (mode == 1)) && G_EmblemsEnabled()) // emblem time!
{
INT32 workx = TX + 96, worky = TY+18;
SINT8 curemb = 0;
@ -2089,10 +2143,12 @@ static boolean K_drawKartPositionFaces(void)
else
{
INT32 pos = players[rankplayer[i]].position;
if (pos < 0 || pos > MAXPLAYERS)
pos = 0;
// Draws the little number over the face
V_DrawScaledPatch(FACE_X-5, Y+10, V_HUDTRANS|V_SNAPTOLEFT, kp_facenum[pos]);
if (pos < 0 || pos > 16)
V_DrawPingNum(FACE_X+2, Y+10, V_HUDTRANS|V_SNAPTOLEFT, pos, NULL);
else
V_DrawScaledPatch(FACE_X-5, Y+10, V_HUDTRANS|V_SNAPTOLEFT, kp_facenum[pos]);
}
Y -= 18;
@ -2291,7 +2347,10 @@ INT32 K_DrawNeoTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines
hightlightcolor = skincolors[players[tab[i].num].mo->color].chatcolor;
}
V_DrawScaledPatch(x-5, y+1, 0, kp_facenum[pos]);
if (pos < 0 || pos > 16)
V_DrawPingNum(x+2, y+1, 0, pos, NULL);
else
V_DrawScaledPatch(x-5, y+1, 0, kp_facenum[pos]);
x2 = netgame ? x + (BASEVIDWIDTH/20) : x;
y2 = y;
@ -2394,7 +2453,7 @@ void K_SetScoreboardModStatus(const char *name, SINT8 active)
CONS_Alert(CONS_WARNING, "Server mod '%s' does not exist so status cannot be changed.\n", name);
}
#define BASEMODS 14
#define BASEMODS 15
static void K_DrawServerMods(INT32 x, INT32 y)
{
UINT8 i, j;
@ -2403,8 +2462,9 @@ static void K_DrawServerMods(INT32 x, INT32 y)
servermods_t basemods[BASEMODS] =
{
{"Item Litter", 0, NULL, K_ItemLitterActive() > 0, true},
{"Rings", 0, NULL, K_RingsActive() > 0, true},
{"4-Tier Drifts", 0, NULL, K_PurpleDriftActive() > 0, true},
{"4-Tier Drift", 0, NULL, K_PurpleDriftActive() > 0, true},
{"Slipdash", 0, NULL, K_SlipdashActive() > 0, true},
{"Stacking", 0, NULL, K_StackingActive() > 0, true},
{"Chaining", 0, NULL, K_ChainingActive() > 0, true},
@ -2467,7 +2527,7 @@ static void K_DrawServerMods(INT32 x, INT32 y)
void K_DrawServerDescrption(INT32 x, INT32 y)
{
UINT8 i, newlinecount = 0;
INT32 i, newlinecount = 0;
if (connectedservername[0] != '\0')
V_DrawThinString(x, y, V_6WIDTHSPACE|V_ALLOWLOWERCASE, connectedservername);
@ -4027,8 +4087,6 @@ static void K_drawKartMinimap(void)
minimaptrans = ((10-minimaptrans)<<FF_TRANSSHIFT);
fixed_t minimapscale = (cv_minihead.value) ? MINIHEADSCALE : FRACUNIT;
if (encoremode)
V_DrawScaledPatch(x+minimapinfo.minimap_pic->width, y, splitflags|minimaptrans|V_FLIP, minimapinfo.minimap_pic);
else
@ -4069,8 +4127,19 @@ static void K_drawKartMinimap(void)
interpy = R_InterpolateFixed(g->mo->old_y, g->mo->y);
patch_t *ghostPic = faceprefix[skin][FACE_MINIMAP];
iconoffsets.x = ((ghostPic->width) / 2) - FixedMul(ghostPic->leftoffset, minimapscale);
iconoffsets.y = ((ghostPic->height) / 2) - FixedMul(ghostPic->topoffset, minimapscale);
widthhalf = ((ghostPic->width) / 2);
heighthalf = ((ghostPic->height) / 2);
if (cv_minihead.value)
{
adjustx = FixedMul(4, (widthhalf - ghostPic->leftoffset) * FRACUNIT / widthhalf);
adjusty = FixedMul(4, (heighthalf - ghostPic->topoffset) *
FRACUNIT / heighthalf);
}
iconoffsets.x = widthhalf - ghostPic->leftoffset - adjustx;
iconoffsets.y = heighthalf - ghostPic->topoffset - adjusty;
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, ghostPic, colormap, &iconoffsets);
g = g->next;
@ -4116,8 +4185,18 @@ static void K_drawKartMinimap(void)
{
workingPic = kp_nocontestminimap;
iconoffsets.x = ((workingPic->width) / 2);
iconoffsets.y = ((workingPic->height) / 2);
widthhalf = ((workingPic->width) / 2);
heighthalf = ((workingPic->height) / 2);
if (cv_minihead.value)
{
adjustx = FixedMul(4, (widthhalf - workingPic->leftoffset) * FRACUNIT / widthhalf);
adjusty = FixedMul(4, (heighthalf - workingPic->topoffset) *
FRACUNIT / heighthalf);
}
iconoffsets.x = widthhalf - workingPic->leftoffset - adjustx;
iconoffsets.y = heighthalf - workingPic->topoffset - adjusty;
colormap = R_GetTranslationColormap(TC_DEFAULT, mobj->color, GTC_CACHE);
}
@ -4340,8 +4419,18 @@ static void K_drawKartMinimap(void)
{
workingPic = kp_nocontestminimap;
iconoffsets.x = ((workingPic->width) / 2);
iconoffsets.y = ((workingPic->height) / 2);
widthhalf = ((workingPic->width) / 2);
heighthalf = ((workingPic->height) / 2);
if (cv_minihead.value)
{
adjustx = FixedMul(4, (widthhalf - workingPic->leftoffset) * FRACUNIT / widthhalf);
adjusty = FixedMul(4, (heighthalf - workingPic->topoffset) *
FRACUNIT / heighthalf);
}
iconoffsets.x = widthhalf - workingPic->leftoffset - adjustx;
iconoffsets.y = heighthalf - workingPic->topoffset - adjusty;
colormap = R_GetTranslationColormap(TC_DEFAULT, mobj->color, GTC_CACHE);
@ -4977,7 +5066,7 @@ static void K_drawInput(void)
target = 0;
else // turning of multiple strengths!
{
target = ((abs(stplyr->cmd.turning) - 1)/125)+1;
target = ((abs(stplyr->cmd.turning) - 1)/200)+1; // was 125, do we need another toggle for this? Zzz...
if (target > 4)
target = 4;
if (stplyr->cmd.turning < 0)
@ -5437,7 +5526,7 @@ static void K_drawDistributionDebugger(void)
INT32 i;
INT32 item;
INT32 x = -9, y = -9;
boolean dontforcespb = false;
//boolean dontforcespb = false;
boolean spbrush = false;
//if (stplyrnum != 0) // only for p1
@ -5449,8 +5538,8 @@ static void K_drawDistributionDebugger(void)
if (!playeringame[i] || players[i].spectator)
continue;
pingame++;
if (players[i].exiting)
dontforcespb = true;
//if (players[i].exiting)
//dontforcespb = true;
if (players[i].bumper > bestbumper)
bestbumper = players[i].bumper;
}
@ -5479,7 +5568,8 @@ static void K_drawDistributionDebugger(void)
stplyr->distancetofinish,
stplyr->distancefromcluster,
0,
spbrush, stplyr->bot, (stplyr->bot && stplyr->botvars.rival)
spbrush, stplyr->bot, (stplyr->bot && stplyr->botvars.rival),
K_IsPlayerLosing(stplyr)
);
if (itemodds <= 0)
@ -5616,7 +5706,7 @@ static void K_SlipstreamIndicator(boolean tiny)
if (!cv_draftindicator.value)
return;
char *fullstr = "DRAFTING";
const char *fullstr = "DRAFTING";
char str[256] = {0};
SINT8 stringlen = strlen(fullstr);
SINT8 len = min(stplyr->draftpower / (FRACUNIT / stringlen), stringlen);
@ -5709,6 +5799,8 @@ void K_drawKartHUD(void)
// Drift gauge should ideally be drawn behind other hud stuff, right?
// right?
K_DrawDriftGauge();
// new flame shield bars (player-space)
K_DrawFlamometer();
if (battlefullscreen && !freecam)
{
@ -6119,8 +6211,9 @@ void K_DrawDriftGauge(void)
if (rainbow)
{
INT32 backsize = sizeof(backcolors);
backcmap = cmap;
for (i = 0; i < sizeof(backcolors); i++)
for (i = 0; i < backsize; i++)
backcolors[i] = driftrainbow[leveltime % sizeof(driftrainbow)] + i;
// HOT HOT HOT HOT HOOOOOOOT AAAAIIIIIIIIEEEEEEEEEEEEEEEEE
@ -6233,3 +6326,68 @@ doafterimage:;
va("%03d", charge)
);*/
}
void K_DrawFlamometer(void)
{
// Make sure we actually have one, lmao
if (stplyr->mo == NULL || P_MobjWasRemoved(stplyr->mo))
return;
// Check for chasecam
// TODO: Check for this better ffs
if (!cv_chasecam[R_GetViewNumber()].value)
return;
// I WANT TO LIVE
if (stplyr->playerstate != PST_LIVE)
return;
if (stplyr->flametimer <= 0)
return;
mobj_t *mo = stplyr->mo;
vector3_t pos = {
R_InterpolateFixed(mo->old_x, mo->x) + mo->sprxoff,
R_InterpolateFixed(mo->old_y, mo->y) + mo->spryoff,
R_InterpolateFixed(mo->old_z, mo->z) + mo->sprzoff + (mo->eflags & MFE_VERTICALFLIP ? mo->height : 0),
};
trackingResult_t res;
INT32 basex, basey, barextraflags = 0;
INT32 flags = V_SPLITSCREEN|V_HUDTRANS;
INT32 fuelbarheight = 41;
INT32 tempbarheight = 48;
K_ObjectTracking(&res, &pos, false);
basex = res.x + (16<<FRACBITS);
basey = res.y - (48<<FRACBITS);
// fire animation
if (stplyr->flamestore >= FLAMESTOREMAX-1)
{
V_DrawFixedPatch(basex, basey, FRACUNIT, flags|V_ADD, kp_flamefire[CLAMP((leveltime / 3) % 4, 0, 4)], NULL);
if (leveltime % 3 != 0)
{
barextraflags = V_ADD;
}
}
// back
V_DrawFixedPatch(basex, basey, FRACUNIT, flags, kp_flamometer[0], NULL);
// bars
// fuel
fuelbarheight *= FixedDiv(stplyr->flametimer, itemtime*3);
V_SetClipRect(basex + 2*FRACUNIT, basey + 49*FRACUNIT - fuelbarheight, 2*FRACUNIT, fuelbarheight, flags);
V_DrawFixedPatch(basex, basey, FRACUNIT, flags, kp_flamometer[1], NULL);
V_ClearClipRect();
// temperature
tempbarheight *= FixedDiv(stplyr->flamestore, FLAMESTOREMAX);
V_SetClipRect(basex + 5*FRACUNIT, basey + 53*FRACUNIT - tempbarheight, 5*FRACUNIT, tempbarheight, flags);
V_DrawFixedPatch(basex, basey, FRACUNIT, flags|barextraflags, kp_flamometer[2], NULL);
V_ClearClipRect();
// front
V_DrawFixedPatch(basex, basey, FRACUNIT, flags, kp_flamometer[3], NULL);
}

View file

@ -132,6 +132,7 @@ void K_SetScoreboardModStatus(const char *name, SINT8 active);
void K_DrawServerDescrption(INT32 x, INT32 y);
void K_DrawDriftGauge(void);
void K_DrawFlamometer(void);
void K_ResetAfterImageValues(void);
#ifdef __cplusplus
} // extern "C"

View file

@ -74,6 +74,8 @@ consvar_t cv_kartstacking_sneakerstacksound = CVAR_INIT ("kartstacking_sneakerst
consvar_t cv_kartchainingsound = CVAR_INIT ("kartchaining_chainsound", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_kartdriftsounds = CVAR_INIT ("kartdriftsounds", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_kartdriftefx = CVAR_INIT ("kartdriftefx", "On", CV_SAVE, CV_OnOff, NULL);
static CV_PossibleValue_t splash_cons_t[] = {{0, "Old"}, {1, "New"}, {0, NULL}};
consvar_t cv_kartsplashefx = CVAR_INIT ("kartsplashefx", "New", CV_SAVE, splash_cons_t, NULL);
static CV_PossibleValue_t driftsparkpulse_cons_t[] = {{0, "MIN"}, {FRACUNIT*3, "MAX"}, {0, NULL}};
consvar_t cv_driftsparkpulse = CVAR_INIT ("driftsparkpulse", "1.4", CV_SAVE|CV_FLOAT, driftsparkpulse_cons_t, NULL);
consvar_t cv_saltyhop = CVAR_INIT ("hardcodehop", "Off", CV_SAVE, CV_OnOff, NULL);
@ -130,7 +132,7 @@ void K_TimerInit(void)
}
// NOW you can try to setup Item Breaker, if there's not enough players for a match
K_BattleInit();
K_BattleInit(numPlayers);
timelimitintics = extratimeintics = secretextratime = 0;
if ((gametyperules & GTR_TIMELIMIT) && !bossinfo.boss)
@ -269,6 +271,7 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartbot_basetrackcomplexity);
CV_RegisterVar(&cv_forcebots);
CV_RegisterVar(&cv_botcontrol);
CV_RegisterVar(&cv_forcerival);
CV_RegisterVar(&cv_karteliminatelast);
CV_RegisterVar(&cv_kartusepwrlv);
CV_RegisterVar(&cv_votetime);
@ -330,6 +333,10 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartstacking_grow_accelboost);
CV_RegisterVar(&cv_kartstacking_grow_stackable);
CV_RegisterVar(&cv_kartstacking_bubble_speedboost);
CV_RegisterVar(&cv_kartstacking_bubble_accelboost);
CV_RegisterVar(&cv_kartstacking_bubble_stackable);
CV_RegisterVar(&cv_kartstacking_flame_speedval);
CV_RegisterVar(&cv_kartstacking_flame_accelboost);
CV_RegisterVar(&cv_kartstacking_flame_stackable);
@ -370,6 +377,10 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartairdrop);
CV_RegisterVar(&cv_kartitemlitter);
CV_RegisterVar(&cv_kartantibump);
CV_RegisterVar(&cv_kartitembreaker);
//CV_RegisterVar(&cv_kartwalltransfer);
@ -397,6 +408,7 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartdriftsounds);
CV_RegisterVar(&cv_kartdriftefx);
CV_RegisterVar(&cv_kartsplashefx);
CV_RegisterVar(&cv_driftsparkpulse);
CV_RegisterVar(&cv_itemtimers);
CV_RegisterVar(&cv_saltyhop);
@ -406,7 +418,7 @@ void K_RegisterKartStuff(void)
//}
boolean K_IsPlayerLosing(player_t *player)
boolean K_IsPlayerLosing(const player_t *player)
{
INT32 winningpos = 1;
UINT8 i, pcount = 0;
@ -491,6 +503,14 @@ fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against)
break;
weight = K_PlayerWeight(mobj, against);
break;
case MT_KART_LEFTOVER:
weight = 5*FRACUNIT/2;
if (mobj->extravalue1 > 0)
{
weight = mobj->extravalue1 * (FRACUNIT >> 1);
}
break;
case MT_BUBBLESHIELD:
if (!mobj->target)
break;
@ -902,6 +922,14 @@ static void K_UpdateOffroad(player_t *player)
offroad = offroadstrength / (TICRATE/2);
if (player->flamestore)
{
// flame shield doesn't resist offroad, but slows its effect
// it doesn't suffer the offroad speedboost cut; increase offroadstrength to compensate
offroad = 2*offroad/3;
offroadstrength *= 2;
}
player->offroad += offroad;
}
@ -2027,6 +2055,7 @@ tripwirepass_t K_TripwirePassConditions(const player_t *player)
{
if (
player->invincibilitytimer ||
player->bubbleboost ||
(player->sneakertimer && player->realsneakertimer)
)
return TRIPWIRE_BLASTER;
@ -2051,35 +2080,10 @@ boolean K_TripwirePass(const player_t *player)
return (player->tripwirePass != TRIPWIRE_NONE);
}
// Safe guard cvars to prevent cheating in RA.
INT32 K_RAGuard(consvar_t cvar)
boolean K_PlayerCanPunt(const player_t *player)
{
if (modeattacking != ATTACKING_NONE)
{
if (cvar.flags & CV_FLOAT)
{
// This is a float, atof the value and run it through FloatToFixed
return FloatToFixed(atof(cvar.defaultvalue));
}
else
{
// Handle string bools first.
if (!strcmp(cvar.defaultvalue, "On") || !strcmp(cvar.defaultvalue, "Yes"))
{
return true;
}
if (!strcmp(cvar.defaultvalue, "Off") || !strcmp(cvar.defaultvalue, "No"))
{
return false;
}
// This is a int, just use atoi the value normally.
return atoi(cvar.defaultvalue);
}
}
return cvar.value;
return player->invincibilitytimer > 0 || player->growshrinktimer > 0 ||
(player->flamestore > 0 && K_GetShieldFromPlayer(player) == KSHIELD_FLAME);
}
boolean K_ItemMobjAllowedtoWaterRun(mobj_t *item)
@ -2128,6 +2132,7 @@ void K_SpawnWaterTrail(mobj_t *mobj)
fixed_t speed = INT32_MAX;
fixed_t runspd = 14 * mobj->scale;
fixed_t trailScale = FRACUNIT;
mobj_t *water = NULL;
if (mobj->momz != 0)
{
@ -2178,87 +2183,110 @@ void K_SpawnWaterTrail(mobj_t *mobj)
return;
}
if (topspeed > runspd)
if (cv_kartsplashefx.value)
{
trailScale = FixedMul(FixedDiv(speed - runspd, topspeed - runspd), mapobjectscale);
}
else
trailScale = mapobjectscale; // Scaling is based off difference between runspeed and top speed
if (trailScale > 0)
{
const angle_t forwardangle = K_MomentumAngle(mobj);
const fixed_t visualradius = mobj->radius + (8 * mobj->scale);
const SINT8 numFrames = 5;
const INT32 curFrame = (leveltime % numFrames)|FF_PAPERSPRITE;
fixed_t x1, x2, y1, y2;
mobj_t *water;
x1 = mobj->x + mobj->momx + P_ReturnThrustX(mobj, forwardangle + ANGLE_90, visualradius);
y1 = mobj->y + mobj->momy + P_ReturnThrustY(mobj, forwardangle + ANGLE_90, visualradius);
x1 = x1 + P_ReturnThrustX(mobj, forwardangle, visualradius);
y1 = y1 + P_ReturnThrustY(mobj, forwardangle, visualradius);
x2 = mobj->x + mobj->momx + P_ReturnThrustX(mobj, forwardangle - ANGLE_90, visualradius);
y2 = mobj->y + mobj->momy + P_ReturnThrustY(mobj, forwardangle - ANGLE_90, visualradius);
x2 = x2 + P_ReturnThrustX(mobj, forwardangle, visualradius);
y2 = y2 + P_ReturnThrustY(mobj, forwardangle, visualradius);
// Left
// underlay
water = P_SpawnMobj(x1, y1,
((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, mobj->scale) : mobj->watertop), MT_WATERTRAILUNDERLAY);
water->angle = forwardangle - ANGLE_180 - ANGLE_22h;
water->destscale = trailScale;
water->momx = mobj->momx;
water->momy = mobj->momy;
water->momz = mobj->momz;
P_SetScale(water, trailScale);
P_SetMobjState(water, S_WATERTRAILSUNDERLAY);
water->frame = curFrame|FF_ADD|FF_TRANS40;
// overlay
water = P_SpawnMobj(x1, y1,
((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, mobj->scale) : mobj->watertop), MT_WATERTRAIL);
water->angle = forwardangle - ANGLE_180 - ANGLE_22h;
water->destscale = trailScale;
water->momx = mobj->momx;
water->momy = mobj->momy;
water->momz = mobj->momz;
P_SetScale(water, trailScale);
P_SetMobjState(water, S_WATERTRAILS);
water->frame = curFrame;
// Right
// Underlay
water = P_SpawnMobj(x2, y2,
((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, mobj->scale) : mobj->watertop), MT_WATERTRAILUNDERLAY);
water->angle = forwardangle - ANGLE_180 + ANGLE_22h;
water->destscale = trailScale;
water->momx = mobj->momx;
water->momy = mobj->momy;
water->momz = mobj->momz;
P_SetScale(water, trailScale);
P_SetMobjState(water, S_WATERTRAILSUNDERLAY);
water->frame = curFrame|FF_ADD|FF_TRANS40;
// Overlay
water = P_SpawnMobj(x2, y2,
((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, mobj->scale) : mobj->watertop), MT_WATERTRAIL);
water->angle = forwardangle - ANGLE_180 + ANGLE_22h;
water->destscale = trailScale;
water->momx = mobj->momx;
water->momy = mobj->momy;
water->momz = mobj->momz;
P_SetScale(water, trailScale);
P_SetMobjState(water, S_WATERTRAILS);
water->frame = curFrame;
if (!S_SoundPlaying(mobj, sfx_s3kdbs))
if (topspeed > runspd)
{
const INT32 volume = (min(trailScale, FRACUNIT) * 255) / FRACUNIT;
S_StartSoundAtVolume(mobj, sfx_s3kdbs, volume);
trailScale = FixedMul(FixedDiv(speed - runspd, topspeed - runspd), mapobjectscale);
}
else
trailScale = mapobjectscale; // Scaling is based off difference between runspeed and top speed
if (trailScale > 0)
{
const angle_t forwardangle = K_MomentumAngle(mobj);
const fixed_t visualradius = mobj->radius + (8 * mobj->scale);
const SINT8 numFrames = 5;
const INT32 curFrame = (leveltime % numFrames)|FF_PAPERSPRITE;
fixed_t x1, x2, y1, y2;
x1 = mobj->x + mobj->momx + P_ReturnThrustX(mobj, forwardangle + ANGLE_90, visualradius);
y1 = mobj->y + mobj->momy + P_ReturnThrustY(mobj, forwardangle + ANGLE_90, visualradius);
x1 = x1 + P_ReturnThrustX(mobj, forwardangle, visualradius);
y1 = y1 + P_ReturnThrustY(mobj, forwardangle, visualradius);
x2 = mobj->x + mobj->momx + P_ReturnThrustX(mobj, forwardangle - ANGLE_90, visualradius);
y2 = mobj->y + mobj->momy + P_ReturnThrustY(mobj, forwardangle - ANGLE_90, visualradius);
x2 = x2 + P_ReturnThrustX(mobj, forwardangle, visualradius);
y2 = y2 + P_ReturnThrustY(mobj, forwardangle, visualradius);
// Left
// underlay
water = P_SpawnMobj(x1, y1,
((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, mobj->scale) : mobj->watertop), MT_WATERTRAILUNDERLAY);
water->angle = forwardangle - ANGLE_180 - ANGLE_22h;
water->destscale = trailScale;
water->momx = mobj->momx;
water->momy = mobj->momy;
water->momz = mobj->momz;
P_SetScale(water, trailScale);
P_SetMobjState(water, S_WATERTRAILSUNDERLAY);
water->frame = curFrame|FF_ADD|FF_TRANS40;
water->flags2 |= MF2_DONTSYNC;
// overlay
water = P_SpawnMobj(x1, y1,
((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, mobj->scale) : mobj->watertop), MT_WATERTRAIL);
water->angle = forwardangle - ANGLE_180 - ANGLE_22h;
water->destscale = trailScale;
water->momx = mobj->momx;
water->momy = mobj->momy;
water->momz = mobj->momz;
P_SetScale(water, trailScale);
P_SetMobjState(water, S_WATERTRAILS);
water->frame = curFrame;
water->flags2 |= MF2_DONTSYNC;
// Right
// Underlay
water = P_SpawnMobj(x2, y2,
((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, mobj->scale) : mobj->watertop), MT_WATERTRAILUNDERLAY);
water->angle = forwardangle - ANGLE_180 + ANGLE_22h;
water->destscale = trailScale;
water->momx = mobj->momx;
water->momy = mobj->momy;
water->momz = mobj->momz;
P_SetScale(water, trailScale);
P_SetMobjState(water, S_WATERTRAILSUNDERLAY);
water->frame = curFrame|FF_ADD|FF_TRANS40;
water->flags2 |= MF2_DONTSYNC;
// Overlay
water = P_SpawnMobj(x2, y2,
((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, mobj->scale) : mobj->watertop), MT_WATERTRAIL);
water->angle = forwardangle - ANGLE_180 + ANGLE_22h;
water->destscale = trailScale;
water->momx = mobj->momx;
water->momy = mobj->momy;
water->momz = mobj->momz;
P_SetScale(water, trailScale);
P_SetMobjState(water, S_WATERTRAILS);
water->frame = curFrame;
water->flags2 |= MF2_DONTSYNC;
if (!S_SoundPlaying(mobj, sfx_s3kdbs))
{
const INT32 volume = (min(trailScale, FRACUNIT) * 255) / FRACUNIT;
S_StartSoundAtVolume(mobj, sfx_s3kdbs, volume);
}
}
}
else if (leveltime % (TICRATE/7) == 0)
{
water = P_SpawnMobj(mobj->x, mobj->y,
((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_SPLISH].height, mobj->scale) :mobj->watertop), MT_SPLISH);
if (mobj->eflags & MFE_GOOWATER)
S_StartSound(water, sfx_ghit);
else
S_StartSound(water, sfx_wslap);
if (mobj->eflags & MFE_VERTICALFLIP)
{
water->flags2 |= MF2_OBJECTFLIP;
water->eflags |= MFE_VERTICALFLIP;
}
water->destscale = mobj->scale;
P_SetScale(water, mobj->scale);
water->flags2 |= MF2_DONTSYNC;
}
// Little water sound while touching water - just a nicety.
@ -2271,8 +2299,8 @@ void K_SpawnWaterTrail(mobj_t *mobj)
static fixed_t K_FlameShieldDashVar(INT32 val)
{
// 1 second = 15% + ????% top speed
return (FRACUNIT/6) + (((val * (FRACUNIT)) / TICRATE) / 2);
// 1 second = base% + ~16.8% top speed
return FixedMul(val * 500, FixedDiv(FRACUNIT, FRACUNIT + val*FRACUNIT/60));
}
static inline fixed_t K_GetProjectileSpeed(void)
@ -2585,7 +2613,10 @@ static void K_GetKartBoostPower(player_t *player)
{
fixed_t invspeedboost = K_GetInvincibilitySpeed(player->invincibilitytimer);
fixed_t invaccelboost = K_GetInvincibilityAccel(player->invincibilitytimer);
K_DoBoost(player, invspeedboost, invaccelboost, INVINSTACKABLE, INVINSTACKABLE); // + 37.5% top speed, + 300% acceleration
// Legacy: + 37.5% top speed, + 300% acceleration
// Alternative: + ???% top speed, + ???% acceleration
K_DoBoost(player, invspeedboost, invaccelboost, INVINSTACKABLE, INVINSTACKABLE);
}
if (player->growshrinktimer > 0) // Grow
@ -2593,17 +2624,15 @@ static void K_GetKartBoostPower(player_t *player)
K_DoBoost(player, GROWSPEEDBOOST, GROWACCELBOOST, GROWSTACKABLE, GROWSTACKABLE); // + 20% top speed, + 0% acceleration
}
if (player->bubbleboost) // Bubble Shield popping boost
{
K_DoBoost(player, BUBBLESPEEDBOOST, BUBBLEACCELBOOST, BUBBLESTACKABLE, BUBBLESTACKABLE); // + 30% top speed, + 400% acceleration
}
if (player->flamestore) // Flame Shield dash
{
fixed_t dash = K_FlameShieldDashVar(player->flamedash);
fixed_t intermediate = 0;
fixed_t boost = 0;
fixed_t val = FLAMESPEEDVAL; // Rim idea: diminish starts around 1.2x sneaker speed and plateaus around 1.4-1.5x
intermediate = FixedDiv(FixedMul(val, FRACUNIT*-1/2) - FRACUNIT/4,-val+FRACUNIT/2);
boost = FixedMul(val,(FRACUNIT-FixedDiv(FRACUNIT,(dash+intermediate))));
K_DoBoost(player, boost, FLAMEACCELBOOST, FLAMESTACKABLE, FLAMESTACKABLE);
K_DoBoost(player, FLAMESPEEDVAL + dash, FLAMEACCELBOOST, FLAMESTACKABLE, FLAMESTACKABLE);
}
if (player->startboost) // Startup Boost
@ -2674,7 +2703,7 @@ static void K_GetKartBoostPower(player_t *player)
// value smoothing
if (K_StackingActive())
{
if (player->offroad && K_ApplyOffroad(player))
if (player->offroad && K_ApplyOffroad(player) && !player->flamestore)
{
player->speedboost = max(finalspeedboost, player->speedboost)/2;
player->accelboost = max(finalaccelboost, player->accelboost)/2;
@ -4015,7 +4044,7 @@ void K_SpawnBoostTrail(player_t *player)
newz -= FixedMul(mobjinfo[MT_SNEAKERTRAIL].height, player->mo->scale);
}
flame = P_SpawnMobj(newx, newy, ground, MT_SNEAKERTRAIL);
flame = P_SpawnMobj(newx, newy, newz, MT_SNEAKERTRAIL);
P_SetTarget(&flame->target, player->mo);
flame->angle = travelangle;
@ -5193,6 +5222,12 @@ void K_DropHnextList(player_t *player)
dropwork->flags &= ~MF_NOCLIPTHING;
}
if (!itemlittering)
{
// Bring it to life... just to kill it.
P_KillMobj(dropwork, NULL, NULL, DMG_NORMAL);
}
P_RemoveMobj(work);
}
@ -5214,18 +5249,78 @@ void K_DropHnextList(player_t *player)
}
}
// Bubble shield break SFX and VFX (maybe, hopefully)
static void K_BreakBubbleShield(player_t *player)
#define MAXSHARDCOUNT 40
#define SHARDROT (360 * FRACUNIT / 40)
static void K_BreakBubbleShield(player_t* player)
{
if (K_GetShieldFromPlayer(player) != KSHIELD_BUBBLE)
return;
// TODO: Some more dramatic SFX and VFX (DSS3K59, bubble shield shards fly all over)
S_StartSound(player->mo, sfx_s3k4b);
mobj_t* shard;
fixed_t move_magnitude, shieldrad, shieldscale, scalediff;
vector2_t mul_vec;
vector3_t mom;
fixed_t randang, randzang;
INT32 flip = P_MobjFlip(player->mo);
shieldscale = player->shieldtracer->scale;
scalediff = shieldscale - mapobjectscale;
shieldrad = FixedMul(player->shieldtracer->radius, shieldscale);
mul_vec.x = FRACUNIT;
mul_vec.y = 0;
INT32 i;
for (i = 0; i < MAXSHARDCOUNT; i++)
{
mul_vec.x = FRACUNIT;
mul_vec.y = 0;
randang = (SHARDROT * (i + 1));
randzang = (P_RandomRange(23, 157) * FRACUNIT);
move_magnitude =
FixedMul((P_RandomRange(4, 16) * FRACUNIT), mapobjectscale + (scalediff / 4));
FV2_Rotate(&mul_vec, randzang);
// Do shitty initial 3D rotations around the shield's radius.
shard = P_SpawnMobj(
player->shieldtracer->x +
FixedMul(FixedMul(mul_vec.x, shieldrad), FCOS(FixedAngle(randang))),
player->shieldtracer->y +
FixedMul(FixedMul(mul_vec.x, shieldrad), FSIN(FixedAngle(randang))),
player->shieldtracer->z + FixedMul(mul_vec.y * flip, shieldrad),
MT_BUBBLESHLD_DEBRIS);
if (shard)
{
//CONS_Printf(M_GetText("randzang: %d, randang: %d\n"), randzang / FRACUNIT, randang / FRACUNIT);
mul_vec.x = FixedMul(move_magnitude, mul_vec.x);
mul_vec.y = FixedMul(move_magnitude, mul_vec.y * flip);
mom.x = FixedMul(mul_vec.x, FCOS(FixedAngle(randang)));
mom.y = FixedMul(mul_vec.x, FSIN(FixedAngle(randang)));
mom.z = mul_vec.y;
shard->momx = mom.x + player->mo->momx;
shard->momy = mom.y + player->mo->momy;
shard->momz = mom.z + player->mo->momz;
}
}
S_StartSound(player->mo, sfx_kc41);
}
#undef MAXSHARDCOUNT
#undef SHARDROT
// For getting hit!
void K_PopPlayerShield(player_t *player)
{
INT32 shield = K_GetShieldFromPlayer(player);
boolean isbubble = false;
// Doesn't apply if player is invalid.
if (player->mo == NULL || P_MobjWasRemoved(player->mo))
@ -5237,33 +5332,30 @@ void K_PopPlayerShield(player_t *player)
{
case KSHIELD_THUNDER:
K_DoThunderShield(player);
player->itemtype = KITEM_NONE;
player->itemamount = 0;
break;
case KSHIELD_BUBBLE:
isbubble = true;
if (player->bubblehealth > 0)
K_BreakBubbleShield(player); // Nice whiff; see ya!
player->bubbleblowup = 0;
player->bubblecool = 0;
player->bubblehealth = 0;
if (player->itemamount > 0)
if (--player->itemamount == 0)
player->itemtype = KITEM_NONE;
break;
case KSHIELD_FLAME:
S_StartSound(player->mo, sfx_s3k47);
S_StopSoundByID(player->mo, sfx_s3kc2l);
player->flametimer = 0;
break;
}
if ((isbubble) && (player->bubblehealth > 0))
{
// Nice whiff; see ya!
K_BreakBubbleShield(player);
}
player->curshield = KSHIELD_NONE;
player->itemtype = KITEM_NONE;
player->itemamount = 0;
player->flametimer = 0;
//player->flamestore = 0
//player->flamedash = 0;
player->bubbleblowup = 0;
player->bubblecool = 0;
player->bubblehealth = 0;
if (!P_MobjWasRemoved(player->shieldtracer))
P_RemoveMobj(player->shieldtracer);
K_UnsetItemOut(player);
}
@ -5310,7 +5402,7 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8
UINT32_MAX,
0,
0,
false, false, false
false, false, false, false
)
);
}
@ -6421,7 +6513,7 @@ static void K_RaceStart(player_t *player)
player->boostcharge = player->cmd.latency;
// RA ez charge for less annoying starts.
if (modeattacking != ATTACKING_NONE && !G_CompatLevel(0x0009))
if (modeattacking != ATTACKING_NONE && !G_CompatLevel(0x000A))
{
SINT8 clampsize = 0;
// Let players choose between startboost and sneaker boost by holding item.
@ -6843,7 +6935,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
// Speed lines
if (player->sneakertimer || player->ringboost
|| player->driftboost || player->startboost
|| player->walltransferboost)
|| player->walltransferboost
|| player->bubbleboost)
{
#if 0
if (player->invincibilitytimer)
@ -6878,9 +6971,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
}
}
if (player->itemtype == KITEM_NONE && player->flametimer == 0)
player->itemflags &= ~IF_HOLDREADY;
if (player->driftlock)
player->driftlock--;
@ -7094,6 +7184,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
}
}
if (player->bubbleboost)
{
player->bubbleboost--;
}
if (player->growshrinktimer != 0)
{
if (player->growshrinktimer > 0)
@ -7252,27 +7347,17 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->flamestore)
{
player->flamestore--;
if (player->flametimer == 0 || player->flamestore == 0)
{
if (--player->flamestore == 0)
S_StopSoundByID(player->mo, sfx_s3kc2l);
}
}
if (player->flametimer > 0)
{
if (player->stealingtimer == 0 && player->stolentimer == 0)
{
player->flametimer--;
}
if (player->flametimer == 0)
{
S_StopSoundByID(player->mo, sfx_s3kc2l);
S_StartSound(player->mo, sfx_s3k47);
K_PopPlayerShield(player);
}
}
else
{
@ -7345,7 +7430,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
player->mo->flags |= MF_NOCLIP;
}
if ((player->mo->eflags & MFE_UNDERWATER) && player->curshield != KSHIELD_BUBBLE)
if ((player->mo->eflags & MFE_UNDERWATER) && K_GetShieldFromPlayer(player) != KSHIELD_BUBBLE)
{
if (player->breathTimer < UINT16_MAX)
player->breathTimer++;
@ -7446,7 +7531,7 @@ void K_KartResetPlayerColor(player_t *player)
finalise:
if (player->curshield)
if (K_GetShieldFromPlayer(player) != KSHIELD_NONE)
{
fullbright = true;
}
@ -8128,6 +8213,14 @@ static void K_UpdateDistanceFromFinishLine(player_t *player)
pathfindsuccess =
K_PathfindToWaypoint(player->nextwaypoint, finishline, &pathtofinish, useshortcuts, huntbackwards);
if (!pathfindsuccess)
{
// We failed...
// Lets try shortcut waypoints if that happens to be the only path.
pathfindsuccess =
K_PathfindToWaypoint(player->nextwaypoint, finishline, &pathtofinish, true, huntbackwards);
}
// Update the player's distance to the finish line if a path was found.
// Using shortcuts won't find a path, so distance won't be updated until the player gets back on track
if (pathfindsuccess == true)
@ -8765,7 +8858,7 @@ INT16 K_GetKartTurnValue(const player_t *player, INT16 turnvalue)
if (K_SlipdashActive() && K_Sliptiding(player)) // slight handling boost based on weight
turnvalue = FixedMul(turnvalue, FRACUNIT + (10 - player->kartweight)*FRACUNIT/48);
if (player->invincibilitytimer || player->sneakertimer || player->growshrinktimer > 0)
if (player->invincibilitytimer || player->sneakertimer || player->bubbleboost || player->growshrinktimer > 0)
turnvalue = FixedMul(turnvalue, FixedDiv(5*FRACUNIT, 4*FRACUNIT));
if (player->flamedash && player->flamestore) // Reduce turning
@ -9030,7 +9123,7 @@ static void K_KartDrift(player_t *player, boolean onground)
player->pflags &= ~(PF_BRAKEDRIFT|PF_GETSPARKS);
}
if ( (!(player->sneakertimer || player->flamestore || K_AltInvinSliptideCondition(player)))
if ( (!(player->sneakertimer || player->flamestore || player->bubbleboost || K_AltInvinSliptideCondition(player)))
|| (!player->cmd.turning)
|| (!player->aizdriftstrat)
|| (player->cmd.turning > 0) != (player->aizdriftstrat > 0))
@ -9164,6 +9257,10 @@ INT32 K_GetDriftAngleOffset(player_t *player)
INT32 a = 0;
boolean onground = P_IsObjectOnGround(player->mo);
boolean compat = wadfiles[skins[player->skin].wadnum]->compatmode;
if (player->pogospring)
return a; // not if you're spinning
if (player->aizdriftturn)
{
a = player->aizdriftturn;
@ -9174,6 +9271,7 @@ INT32 K_GetDriftAngleOffset(player_t *player)
{
a = (ANGLE_45 / 5) * player->drift;
}
return a;
}
@ -9387,20 +9485,11 @@ void K_KartUpdatePosition(player_t *player)
}
else
{
if (player->exiting) // End of match standings
{
// Only score matters
if (players[i].roundscore > player->roundscore)
position++;
}
else
{
// I have less points than but the same bumpers as this player OR
// I have less bumpers than this player
if ((players[i].bumper == player->bumper && players[i].roundscore > player->roundscore)
|| (players[i].bumper > player->bumper))
position++;
}
// I have less points than but the same bumpers as this player OR
// I have less bumpers than this player
if ((players[i].bumper == player->bumper && players[i].roundscore > player->roundscore)
|| (players[i].bumper > player->bumper))
position++;
}
}
}
@ -9686,7 +9775,8 @@ void K_StripItems(player_t *player)
K_DropKitchenSink(player);
player->itemtype = KITEM_NONE;
player->itemamount = 0;
player->itemflags &= ~(IF_ITEMOUT|IF_EGGMANOUT);
player->itemflags &= ~IF_EGGMANOUT;
K_UnsetItemOut(player);
if (!player->itemroulette || player->roulettetype != 2)
{
@ -9698,9 +9788,9 @@ void K_StripItems(player_t *player)
player->stealingtimer = 0;
player->stolentimer = 0;
player->curshield = KSHIELD_NONE;
if (!P_MobjWasRemoved(player->shieldtracer))
P_RemoveMobj(player->shieldtracer);
player->flametimer = 0;
player->bananadrag = 0;
player->sadtimer = 0;
@ -9909,19 +9999,16 @@ boolean K_SlopeResistance(const player_t *player)
return false;
}
INT32 K_GetShieldFromPlayer(player_t *player)
INT32 K_GetShieldFromPlayer(const player_t *player)
{
if (P_MobjWasRemoved(player->shieldtracer))
return KSHIELD_NONE;
if (player->flametimer > 0)
switch (player->shieldtracer->type)
{
return KSHIELD_FLAME;
}
switch (player->itemtype)
{
case KITEM_THUNDERSHIELD: return KSHIELD_THUNDER;
case KITEM_BUBBLESHIELD: return KSHIELD_BUBBLE;
//case KITEM_FLAMESHIELD: return KSHIELD_FLAME; not active until flametimer is active.
case MT_THUNDERSHIELD: return KSHIELD_THUNDER;
case MT_BUBBLESHIELD: return KSHIELD_BUBBLE;
case MT_FLAMESHIELD: return KSHIELD_FLAME;
default: return KSHIELD_NONE;
}
}
@ -9944,7 +10031,7 @@ void K_SetItemOut(player_t *player)
void K_UnsetItemOut(player_t *player)
{
player->itemflags &= ~IF_ITEMOUT;
player->itemflags &= ~(IF_ITEMOUT|IF_HOLDREADY);
player->bananadrag = 0;
}
@ -10146,11 +10233,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}*/
if (player->flametimer <= 0)
{
player->flametimer = 0;
S_StartSound(player->mo, sfx_s3k47);
K_PopPlayerShield(player);
}
}
else
{
@ -10533,13 +10616,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
break;
case KITEM_THUNDERSHIELD:
if (player->curshield != KSHIELD_THUNDER)
if (K_GetShieldFromPlayer(player) != KSHIELD_THUNDER)
{
mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THUNDERSHIELD);
P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2));
P_SetTarget(&shield->target, player->mo);
P_SetTarget(&player->shieldtracer, shield);
S_StartSound(player->mo, sfx_s3k41);
player->curshield = KSHIELD_THUNDER;
}
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
@ -10559,14 +10642,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
break;
case KITEM_BUBBLESHIELD:
if (player->curshield != KSHIELD_BUBBLE)
if (K_GetShieldFromPlayer(player) != KSHIELD_BUBBLE)
{
mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BUBBLESHIELD);
P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2));
P_SetTarget(&shield->target, player->mo);
P_SetTarget(&player->shieldtracer, shield);
S_StartSound(player->mo, sfx_s3k3f);
player->curshield = KSHIELD_BUBBLE;
player->bubblehealth = MAXBUBBLEHEALTH;
}
@ -10583,15 +10665,27 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
// (was blowup x4 before)
player->bubblecool = player->bubbleblowup*2;
if (player->bubbleblowup > bubbletime*2)
if (player->bubbleblowup > bubbletime*4)
{
// Jump straight to deflating the bubble.
goto bubbledeflate;
// If you overcharge the Bubble Shield at
// any point, it pops and gives you a boost.
K_BreakBubbleShield(player);
K_PopPlayerShield(player);
if (onground)
{
// If you're on the ground, you're going to
// immediately feel the effects of this boost.
// Play a sound to let everyone know!
S_StartSoundAtVolume(player->mo, sfx_cdfm57, 170);
K_PlayBoostTaunt(player->mo);
}
player->bubbleboost = 7 * sneakertime / 10;
}
}
else
{
bubbledeflate:
{
boolean popped = false;
if (player->bubbleblowup > bubbletime)
@ -10630,17 +10724,15 @@ bubbledeflate:
}
break;
case KITEM_FLAMESHIELD:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO && player->flametimer == 0)
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO && K_GetShieldFromPlayer(player) != KSHIELD_FLAME)
{
player->itemamount--;
player->flametimer = (itemtime*3);
mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FLAMESHIELD);
P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2));
P_SetTarget(&shield->target, player->mo);
P_SetTarget(&player->shieldtracer, shield);
S_StartSound(player->mo, sfx_s3k3e);
player->curshield = KSHIELD_FLAME;
}
break;
case KITEM_HYUDORO:
@ -10720,15 +10812,8 @@ bubbledeflate:
{
player->itemflags &= ~IF_ITEMOUT;
player->itemtype = KITEM_NONE;
}
if (K_GetShieldFromPlayer(player) == KSHIELD_NONE)
{
player->curshield = KSHIELD_NONE; // RESET shield type
player->bubbleblowup = 0;
player->bubblecool = 0;
//player->flamedash = 0;
player->flametimer = 0;
if (K_GetShieldFromPlayer(player) != KSHIELD_NONE && K_GetShieldFromPlayer(player) != KSHIELD_FLAME)
P_RemoveMobj(player->shieldtracer);
}
if (player->growshrinktimer <= 0)
@ -11142,6 +11227,17 @@ boolean K_AirDropActive(void)
return false;
}
boolean K_ItemLitterActive(void)
{
if (itemlittering)
{
// Item littering is enabled!
return true;
}
return false;
}
boolean K_GetKartInvinType(void)
{
return invintype;

View file

@ -82,67 +82,71 @@ extern vector3_t clusterpoint, clusterdtf;
#define BUBBLEITMDAMAGE (MAXBUBBLEHEALTH)
// Invincibility-related constants
#define INVINDIST K_RAGuard(cv_kartinvindist)
#define INVINDISTMUL K_RAGuard(cv_kartinvindistmul)
#define INVINMIDTIME K_RAGuard(cv_kartinvin_midtime)
#define INVINMAXTIME K_RAGuard(cv_kartinvin_maxtime)
#define INVINDIST CV_Get(&cv_kartinvindist)
#define INVINDISTMUL CV_Get(&cv_kartinvindistmul)
#define INVINMIDTIME CV_Get(&cv_kartinvin_midtime)
#define INVINMAXTIME CV_Get(&cv_kartinvin_maxtime)
// Precalculated constants for stacked boost diminishing
// *Somewhat* matches old calc but doesn't use arrays, which makes it faster and more memory efficent
#define DIMINISHPARAM K_RAGuard(cv_kartstacking_diminishparam)
#define MAXVANILLABOOST K_RAGuard(cv_kartstacking_maxvanillaboost)
#define SPEEDBOOSTDROPOFF K_RAGuard(cv_kartstacking_speedboostdropoff)
#define SPEEDBOOSTDROPOFF_BRAKE K_RAGuard(cv_kartstacking_speedboostdropoff_brake)
#define ACCELSTACK K_RAGuard(cv_kartstacking_accelstack)
#define DIMINISHPARAM CV_Get(&cv_kartstacking_diminishparam)
#define MAXVANILLABOOST CV_Get(&cv_kartstacking_maxvanillaboost)
#define SPEEDBOOSTDROPOFF CV_Get(&cv_kartstacking_speedboostdropoff)
#define SPEEDBOOSTDROPOFF_BRAKE CV_Get(&cv_kartstacking_speedboostdropoff_brake)
#define ACCELSTACK CV_Get(&cv_kartstacking_accelstack)
// Vanilla Boosts
#define EASYSNEAKERSPEEDBOOST K_RAGuard(cv_kartstacking_sneaker_easyspeedboost)
#define NORMALSNEAKERSPEEDBOOST K_RAGuard(cv_kartstacking_sneaker_normalspeedboost)
#define HARDSNEAKERSPEEDBOOST K_RAGuard(cv_kartstacking_sneaker_hardspeedboost)
#define EXPERTSNEAKERSPEEDBOOST K_RAGuard(cv_kartstacking_sneaker_expertspeedboost)
#define SNEAKERACCELBOOST K_RAGuard(cv_kartstacking_sneaker_accelboost)
#define MAXSNEAKERSTACK K_RAGuard(cv_kartstacking_sneaker_maxgrade)
#define SNEAKERSTACKABLE K_RAGuard(cv_kartstacking_sneaker_stackable)
#define EASYSNEAKERSPEEDBOOST CV_Get(&cv_kartstacking_sneaker_easyspeedboost)
#define NORMALSNEAKERSPEEDBOOST CV_Get(&cv_kartstacking_sneaker_normalspeedboost)
#define HARDSNEAKERSPEEDBOOST CV_Get(&cv_kartstacking_sneaker_hardspeedboost)
#define EXPERTSNEAKERSPEEDBOOST CV_Get(&cv_kartstacking_sneaker_expertspeedboost)
#define SNEAKERACCELBOOST CV_Get(&cv_kartstacking_sneaker_accelboost)
#define MAXSNEAKERSTACK CV_Get(&cv_kartstacking_sneaker_maxgrade)
#define SNEAKERSTACKABLE CV_Get(&cv_kartstacking_sneaker_stackable)
#define INVINSPEEDBOOSTLGC K_RAGuard(cv_kartstacking_invincibility_legacyspeedboost)
#define INVINACCELBOOSTLGC K_RAGuard(cv_kartstacking_invincibility_legacyaccelboost)
#define INVINSPEEDBOOSTALT K_RAGuard(cv_kartstacking_invincibility_alternatespeedboost)
#define INVINACCELBOOSTALT K_RAGuard(cv_kartstacking_invincibility_alternateaccelboost)
#define INVINSTACKABLE K_RAGuard(cv_kartstacking_invincibility_stackable)
#define INVINSPEEDBOOSTLGC CV_Get(&cv_kartstacking_invincibility_legacyspeedboost)
#define INVINACCELBOOSTLGC CV_Get(&cv_kartstacking_invincibility_legacyaccelboost)
#define INVINSPEEDBOOSTALT CV_Get(&cv_kartstacking_invincibility_alternatespeedboost)
#define INVINACCELBOOSTALT CV_Get(&cv_kartstacking_invincibility_alternateaccelboost)
#define INVINSTACKABLE CV_Get(&cv_kartstacking_invincibility_stackable)
#define GROWSPEEDBOOST K_RAGuard(cv_kartstacking_grow_speedboost)
#define GROWACCELBOOST K_RAGuard(cv_kartstacking_grow_accelboost)
#define GROWSTACKABLE K_RAGuard(cv_kartstacking_grow_stackable)
#define GROWSPEEDBOOST CV_Get(&cv_kartstacking_grow_speedboost)
#define GROWACCELBOOST CV_Get(&cv_kartstacking_grow_accelboost)
#define GROWSTACKABLE CV_Get(&cv_kartstacking_grow_stackable)
#define FLAMESPEEDVAL K_RAGuard(cv_kartstacking_flame_speedval)
#define FLAMEACCELBOOST K_RAGuard(cv_kartstacking_flame_accelboost)
#define FLAMESTACKABLE K_RAGuard(cv_kartstacking_flame_stackable)
#define BUBBLESPEEDBOOST CV_Get(&cv_kartstacking_bubble_speedboost)
#define BUBBLEACCELBOOST CV_Get(&cv_kartstacking_bubble_accelboost)
#define BUBBLESTACKABLE CV_Get(&cv_kartstacking_bubble_stackable)
#define STARTSPEEDBOOST K_RAGuard(cv_kartstacking_start_speedboost)
#define STARTACCELBOOST K_RAGuard(cv_kartstacking_start_accelboost)
#define STARTSTACKABLE K_RAGuard(cv_kartstacking_start_stackable)
#define FLAMESPEEDVAL CV_Get(&cv_kartstacking_flame_speedval)
#define FLAMEACCELBOOST CV_Get(&cv_kartstacking_flame_accelboost)
#define FLAMESTACKABLE CV_Get(&cv_kartstacking_flame_stackable)
#define WALLTRANSFERSPEEDBOOST K_RAGuard(cv_kartstacking_walltransfer_speedboost)
#define WALLTRANSFERACCELBOOST K_RAGuard(cv_kartstacking_walltransfer_accelboost)
#define WALLTRANSFERSTACKABLE K_RAGuard(cv_kartstacking_walltransfer_stackable)
#define STARTSPEEDBOOST CV_Get(&cv_kartstacking_start_speedboost)
#define STARTACCELBOOST CV_Get(&cv_kartstacking_start_accelboost)
#define STARTSTACKABLE CV_Get(&cv_kartstacking_start_stackable)
#define DRIFTSPEEDBOOST K_RAGuard(cv_kartstacking_drift_speedboost)
#define DRIFTACCELBOOST K_RAGuard(cv_kartstacking_drift_accelboost)
#define DRIFTSTACKABLE K_RAGuard(cv_kartstacking_drift_stackable)
#define WALLTRANSFERSPEEDBOOST CV_Get(&cv_kartstacking_walltransfer_speedboost)
#define WALLTRANSFERACCELBOOST CV_Get(&cv_kartstacking_walltransfer_accelboost)
#define WALLTRANSFERSTACKABLE CV_Get(&cv_kartstacking_walltransfer_stackable)
#define RINGSPEEDBOOST K_RAGuard(cv_kartstacking_ring_speedboost)
#define RINGACCELBOOST K_RAGuard(cv_kartstacking_ring_accelboost)
#define RINGSTACKABLE K_RAGuard(cv_kartstacking_ring_stackable)
#define DRIFTSPEEDBOOST CV_Get(&cv_kartstacking_drift_speedboost)
#define DRIFTACCELBOOST CV_Get(&cv_kartstacking_drift_accelboost)
#define DRIFTSTACKABLE CV_Get(&cv_kartstacking_drift_stackable)
#define SLOPEDECAY K_RAGuard(cv_kartstacking_slope_decay)
#define SLOPEBRAKEMOD K_RAGuard(cv_kartstacking_slope_brakemod)
#define SLOPESPEEDBOOSTMAX K_RAGuard(cv_kartstacking_slope_speedboost_max)
#define SLOPESPEEDBOOSTCAP K_RAGuard(cv_kartstacking_slope_speedboost_cap)
#define SLOPEACCELBOOST K_RAGuard(cv_kartstacking_slope_accelboost)
#define SLOPESTACKABLE K_RAGuard(cv_kartstacking_slope_stackable)
#define RINGSPEEDBOOST CV_Get(&cv_kartstacking_ring_speedboost)
#define RINGACCELBOOST CV_Get(&cv_kartstacking_ring_accelboost)
#define RINGSTACKABLE CV_Get(&cv_kartstacking_ring_stackable)
#define DRAFTMINSPEED K_RAGuard(cv_kartstacking_drafting_minspeed)
#define DRAFTMAXSPEED K_RAGuard(cv_kartstacking_drafting_maxspeed)
#define SLOPEDECAY CV_Get(&cv_kartstacking_slope_decay)
#define SLOPEBRAKEMOD CV_Get(&cv_kartstacking_slope_brakemod)
#define SLOPESPEEDBOOSTMAX CV_Get(&cv_kartstacking_slope_speedboost_max)
#define SLOPESPEEDBOOSTCAP CV_Get(&cv_kartstacking_slope_speedboost_cap)
#define SLOPEACCELBOOST CV_Get(&cv_kartstacking_slope_accelboost)
#define SLOPESTACKABLE CV_Get(&cv_kartstacking_slope_stackable)
#define DRAFTMINSPEED CV_Get(&cv_kartstacking_drafting_minspeed)
#define DRAFTMAXSPEED CV_Get(&cv_kartstacking_drafting_maxspeed)
#define CANTCHAINOFFROAD (cv_kartchaining.value && !cv_kartchainingoffroad.value)
@ -179,15 +183,13 @@ typedef enum
#define RINGVOLUMEREGEN 1
#define RINGTRANSPARENCYREGEN 3
INT32 K_RAGuard(consvar_t cvar);
angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed);
void K_RegisterKartStuff(void);
void K_TimerInit(void);
UINT32 K_GetPlayerDontDrawFlag(player_t *player);
boolean K_IsPlayerLosing(player_t *player);
boolean K_IsPlayerLosing(const player_t *player);
fixed_t K_GetKartGameSpeedScalar(SINT8 value);
fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against);
@ -275,6 +277,7 @@ boolean K_ApplyOffroad(const player_t *player);
fixed_t K_PlayerTripwireSpeedThreshold(const player_t *player);
tripwirepass_t K_TripwirePassConditions(const player_t *player);
boolean K_TripwirePass(const player_t *player);
boolean K_PlayerCanPunt(const player_t *player);
boolean K_WaterRun(mobj_t *mobj);
void K_SpawnWaterTrail(mobj_t *mobj);
boolean K_ItemMobjAllowedtoWaterRun(mobj_t *item);
@ -311,7 +314,7 @@ void K_PlayHitEmSound(mobj_t *source, mobj_t *other);
void K_TryHurtSoundExchange(mobj_t *victim, mobj_t *attacker);
void K_PlayPowerGloatSound(mobj_t *source);
INT32 K_GetShieldFromPlayer(player_t *player);
INT32 K_GetShieldFromPlayer(const player_t *player);
INT32 K_GetShieldFromItem(INT32 item);
void K_SetItemOut(player_t *player);
@ -327,6 +330,7 @@ boolean K_SlipdashActive(void);
boolean K_SlopeBoostActive(void);
boolean K_DraftingActive(void);
boolean K_AirDropActive(void);
boolean K_ItemLitterActive(void);
boolean K_GetKartInvinType(void);
INT32 K_GetBumpSpark(void);
boolean K_BoostChain(player_t *player, INT32 timer, boolean chainsound);

View file

@ -91,33 +91,33 @@ static UINT8 K_KartItemOddsRace[NUMKARTRESULTS-1][MAXODDS] =
{
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
//B C D E F G H I J K L M N O P Q
{ 0, 0, 0, 11, 22, 18, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Sneaker
{ 0, 0, 0, 0, 0, 0, 0, 0, 3, 17, 37, 48, 60, 48, 37, 37}, // Rocket Sneaker
{ 0, 0, 0, 0, 0, 0, 0, 3, 7, 18, 30, 37, 45, 60, 75, 75}, // Invincibility
{67, 48, 30, 22, 15, 11, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0}, // Banana
{22, 18, 15, 11, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Eggman Monitor
{37, 41, 45, 37, 30, 22, 15, 7, 0, 0, 0, 0, 0, 0, 0, 0}, // Orbinaut
{ 0, 11, 22, 18, 15, 11, 7, 7, 7, 3, 0, 0, 0, 0, 0, 0}, // Jawz
{ 0, 7, 15, 15, 15, 11, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0}, // Mine
{ 0, 0, 0, 7, 15, 11, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0}, // Ballhog
{ 0, 0, 3, 5, 7, 9, 12, 13, 10, 9, 7, 5, 2, 2, 2, 0}, // Self-Propelled Bomb
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 15, 26, 37, 45, 52, 52}, // Grow
{ 0, 0, 0, 0, 9, 18, 28, 8, 0, 0, 0, 0, 0, 0, 0, 0}, // Sneaker
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 15, 42, 48, 37, 37}, // Rocket Sneaker
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 33, 60, 75, 75}, // Invincibility
{67, 52, 24, 22, 15, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Banana
{18, 15, 12, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Eggman Monitor
{15, 30, 25, 12, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Orbinaut
{ 0, 11, 22, 9, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Jawz
{ 0, 0, 10, 9, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Mine
{ 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Ballhog
{ 0, 0, 2, 3, 4, 5, 6, 9, 10, 12, 8, 5, 2, 2, 2, 0}, // Self-Propelled Bomb
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 18, 9, 0, 0, 0}, // Grow
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 3, 0, 0}, // Shrink
{15, 11, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Thunder Shield
{ 0, 0, 0, 0, 0, 3, 7, 11, 15, 11, 7, 3, 0, 0, 0, 0}, // Hyudoro
{18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Thunder Shield
{ 0, 0, 0, 0, 3, 5, 7, 9, 5, 0, 0, 0, 0, 0, 0, 0}, // Hyudoro
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Pogo Spring
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Kitchen Sink
{ 7, 11, 15, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Super Ring
{22, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Land Mine
{ 0, 3, 12, 22, 15, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Bubble Shield
{ 0, 0, 0, 0, 0, 0, 3, 7, 14, 26, 37, 48, 37, 18, 7, 0}, // Flame Shield
{ 0, 0, 0, 11, 22, 40, 38, 35, 7, 0, 0, 0, 0, 0, 0, 0}, // Sneaker x2
{ 0, 0, 0, 0, 0, 3, 19, 35, 45, 22, 7, 0, 0, 0, 0, 0}, // Sneaker x3
{ 0, 3, 7, 7, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Banana x3
{ 0, 0, 0, 0, 0, 3, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0}, // Banana x10
{ 0, 0, 0, 3, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Orbinaut x3
{ 0, 0, 0, 0, 0, 3, 7, 7, 7, 3, 0, 0, 0, 0, 0, 0}, // Orbinaut x4
{ 0, 0, 0, 3, 7, 11, 15, 7, 0, 0, 0, 0, 0, 0, 0, 0} // Jawz x2
{ 0, 3, 18, 32, 20, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Bubble Shield
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 18, 36, 37, 18, 7, 0}, // Flame Shield
{ 0, 0, 0, 0, 0, 3, 5, 25, 20, 15, 9, 0, 0, 0, 0, 0}, // Sneaker x2
{ 0, 0, 0, 0, 0, 0, 0, 0, 4, 7, 21, 45, 32, 7, 0, 0}, // Sneaker x3
{ 0, 7, 7, 7, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Banana x3
{ 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Banana x10
{ 0, 0, 0, 2, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Orbinaut x3
{ 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Orbinaut x4
{ 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // Jawz x2
};
static UINT8 K_KartItemOddsBattle[NUMKARTRESULTS][2] =
@ -152,6 +152,80 @@ static UINT8 K_KartItemOddsBattle[NUMKARTRESULTS][2] =
{ 5, 1 } // Jawz x2
};
// Cooldown time table; contains both base (index 0) and current (index 1)
// times. Base times are in seconds, current times are in tics.
tic_t ItemBGone[NUMKARTRESULTS][2] =
{
//BASE CURR
{ 0, 0 }, // Null/Sad Face
{ 0, 0 }, // Sneaker
{ 0, 0 }, // Rocket Sneaker
{ 0, 0 }, // Invincibility
{ 0, 0 }, // Banana
{ 10, 0 }, // Eggman Monitor
{ 0, 0 }, // Orbinaut
{ 5, 0 }, // Jawz
{ 0, 0 }, // Mine
{ 10, 0 }, // Ballhog
{ 20, 0 }, // Self-Propelled Bomb
{ 3, 0 }, // Grow
{ 20, 0 }, // Shrink
{ 0, 0 }, // Thunder Shield
{ 20, 0 }, // Hyudoro
{ 0, 0 }, // Pogo Spring
{ 0, 0 }, // Kitchen Sink
{ 0, 0 }, // Super Ring
{ 0, 0 }, // Land Mine
{ 5, 0 }, // Bubble Shield
{ 8, 0 }, // Flame Shield
{ 0, 0 }, // Sneaker x2
{ 0, 0 }, // Sneaker x3
{ 0, 0 }, // Banana x3
{ 30, 0 }, // Banana x10
{ 10, 0 }, // Orbinaut x3
{ 20, 0 }, // Orbinaut x4
{ 10, 0 } // Jawz x2
};
// TODO: Vectorize all item tables and shove them into gamemode-uniqe pools (k_oddstable.cpp?).
// Basically necessary for any hopes of easy SOC support in the near future.
/** \brief Sets the cooldown timer for an item. When active, the item is removed
* from all players' item pools for some time.
\param item (SINT8) item to assign cooldown for
\param time (tic_t) cooldown time
\return void
*/
void K_SetBGone(SINT8 item, tic_t time)
{
ItemBGone[item][GONER_CURRCOOLDOWN] = time;
}
/** \brief Sets the cooldown timer for an item to its "base" (intended) time.
\param item (SINT8) item to assign base cooldown for
\return void
*/
void K_SetBGoneToBase(SINT8 item)
{
ItemBGone[item][GONER_CURRCOOLDOWN] = (ItemBGone[item][GONER_BASECOOLDOWN] * TICRATE);
}
/** \brief Gets the cooldown timer for an item.
\param item (SINT8) item to retrieve cooldown for
\param base (bool) if true, returns the "base" (intended) cooldown instead
\return (tic_t) cooldown time
*/
tic_t K_GetBGone(SINT8 item, boolean base)
{
return ItemBGone[item][base ? GONER_BASECOOLDOWN : GONER_CURRCOOLDOWN] * (base ? TICRATE : 1);
}
// Magic number distance for use with item roulette tiers
#define ACTIVEDISTVAR (K_UsingLegacyCheckpoints() ? DISTVAR_LEGACY : DISTVAR)
@ -160,6 +234,58 @@ static UINT8 K_KartItemOddsBattle[NUMKARTRESULTS][2] =
#define ENDDIST (12*ACTIVEDISTVAR) // Distance when the game stops giving you bananas
// 1/21/2025: I hate tiptoeing around the integer limit.
// This is at a smaller scale.
static UINT32 K_Dist2D(INT32 x1, INT32 y1, INT32 x2, INT32 y2)
{
// d = √((x2 - x1)² + (y2 - y1)²)
INT32 xdiff, ydiff;
INT64 xprod, yprod;
xdiff = (x2 - x1);
ydiff = (y2 - y1);
xprod = ((INT64)xdiff * (INT64)xdiff);
yprod = ((INT64)ydiff * (INT64)ydiff);
return (UINT32)(IntSqrt64(xprod + yprod));
}
// Basic integer distancing, to quote myself:
// "Even if you did 256 units for 1 fracunit in distancing, it'd be a better result than trying to
// deal with overflows on a system that's already being pushed to the limit by needing 65536 units
// for precision. No seriously, I don't think anyone's losing sleep over "hmmmmm, 0.0000152 or
// 0.0039?????" when most 2D game engines only give a fuck about MAYBE 0.001"
/*static UINT32 K_IntDistance(fixed_t curx,
fixed_t cury,
fixed_t curz,
fixed_t destx,
fixed_t desty,
fixed_t destz)
{
return K_Dist2D(0,
curz / FRACUNIT,
K_Dist2D(curx / FRACUNIT, cury / FRACUNIT, destx / FRACUNIT, desty / FRACUNIT),
destz / FRACUNIT);
}*/
// This one uses map scaling instead, use in case of loss of depth on mobjscaled maps.
static UINT32 K_IntDistanceForMap(fixed_t curx,
fixed_t cury,
fixed_t curz,
fixed_t destx,
fixed_t desty,
fixed_t destz)
{
return K_Dist2D(0,
curz / mapobjectscale,
K_Dist2D(curx / mapobjectscale,
cury / mapobjectscale,
destx / mapobjectscale,
desty / mapobjectscale),
destz / mapobjectscale);
}
SINT8 K_ItemResultToType(SINT8 getitem)
{
if (getitem <= 0 || getitem >= NUMKARTRESULTS) // Sad (Fallback)
@ -236,8 +362,10 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem)
if (getitem == KITEM_SPB || getitem == KITEM_SHRINK) // Indirect items
indirectitemcooldown = 20*TICRATE;
if (getitem == KITEM_HYUDORO) // Hyudoro cooldown
hyubgone = 20*TICRATE;
if (K_GetBGone(getitem, true) > 0) // Item cooldowns
{
K_SetBGoneToBase(getitem);
}
K_BotResetItemConfirm(player, true);
@ -248,7 +376,7 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem)
player->itemamount = itemamount;
}
fixed_t K_ItemOddsScale(UINT8 numPlayers, boolean spbrush)
static fixed_t K_ItemOddsScale(UINT8 numPlayers, boolean spbrush)
{
// CEP: due to how baseplayer works, 17P+ lobbies will STILL have the disastrous odds of 0.22 prior, if not WORSE
// let's try adding another condition
@ -325,6 +453,9 @@ UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush)
#define INVINDESPERATION 4
#define MAXINVODDS ((MAXPROBABILITY * 2) * INVINDESPERATION)
// Odds value for Alt. Invin. to force itself on trailing players.
#define INVFORCEODDS (MAXINVODDS / 2)
static INT32 K_KartGetInvincibilityOdds(UINT32 dist)
{
UINT32 invindist = INVINDIST/2;
@ -356,6 +487,47 @@ static INT32 K_KartGetInvincibilityOdds(UINT32 dist)
return min(MAXINVODDS, finodds);
}
// Assigns general cooldowns to shield items.
void K_KartHandleShieldCooldown(SINT8 item)
{
INT32 i;
UINT8 pingame = 0, pexiting = 0;
INT32 shieldtype = KSHIELD_NONE;
shieldtype = K_GetShieldFromItem(item);
if (shieldtype == KSHIELD_NONE)
{
// Not a shield!
return;
}
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (!(gametyperules & GTR_BUMPERS) || players[i].bumper)
pingame++;
if (players[i].exiting)
pexiting++;
if (((shieldtype == K_GetShieldFromItem(players[i].itemtype))
|| (shieldtype == K_GetShieldFromPlayer(&players[i]))))
{
// If this shield has a cooldown, force-apply the cooldown preeemptively for
// the entire time the shield is being held by a player.
if (K_GetBGone(item, true) > 0)
{
K_SetBGoneToBase(item);
break;
}
}
}
}
/** \brief Item Roulette for Kart
\param player player object passed from P_KartPlayerThink
@ -368,7 +540,7 @@ INT32 K_KartGetItemOdds(
UINT32 ourDist,
UINT32 clusterDist,
fixed_t mashed,
boolean spbrush, boolean bot, boolean rival)
boolean spbrush, boolean bot, boolean rival, boolean inBottom)
{
INT32 newodds;
INT32 i;
@ -383,6 +555,7 @@ INT32 K_KartGetItemOdds(
boolean cooldownOnStart = false;
boolean indirectItem = false;
boolean notNearEnd = false;
boolean notForBottom = false;
INT32 shieldtype = KSHIELD_NONE;
@ -497,11 +670,20 @@ INT32 K_KartGetItemOdds(
switch (item)
{
case KITEM_BANANA:
case KITEM_EGGMAN:
notNearEnd = true;
notForBottom = true;
break;
case KITEM_EGGMAN:
// It blows you up and is overall ridiculous. This was *overdue*.
cooldownOnStart = true;
powerItem = true;
notNearEnd = true;
notForBottom = true;
break;
case KITEM_SUPERRING:
notNearEnd = true;
notForBottom = true;
if ((K_RingsActive() == false)) // No rings rolled if rings are turned off.
{
@ -510,18 +692,25 @@ INT32 K_KartGetItemOdds(
break;
case KITEM_ROCKETSNEAKER:
case KITEM_JAWZ:
case KITEM_LANDMINE:
case KITEM_BALLHOG:
case KRITEM_TRIPLESNEAKER:
powerItem = true;
break;
case KITEM_BUBBLESHIELD:
// Experiment: Given the refactoring of the item, remove it from the cooldown pool.
// Also: a given.
case KITEM_BALLHOG:
case KITEM_JAWZ:
case KRITEM_DUALJAWZ:
case KRITEM_TRIPLEORBINAUT:
case KRITEM_QUADORBINAUT:
case KRITEM_DUALJAWZ:
notForBottom = true;
powerItem = true;
break;
case KRITEM_TRIPLEBANANA:
case KRITEM_TENFOLDBANANA:
powerItem = true;
notForBottom = true;
notNearEnd = true;
break;
case KITEM_INVINCIBILITY:
@ -537,6 +726,13 @@ INT32 K_KartGetItemOdds(
// Unique odds for Invincibility.
newodds = K_KartGetInvincibilityOdds(clusterDist);
// Special case: if you're SERIOUSLY far behind before the cooldown
// finishes, remove the cooldown flag.
if (newodds >= INVFORCEODDS)
{
cooldownOnStart = false;
}
newodds *= BASEODDSMUL;
break;
@ -544,7 +740,6 @@ INT32 K_KartGetItemOdds(
/*FALLTHRU*/
case KITEM_MINE:
case KITEM_GROW:
case KITEM_BUBBLESHIELD:
case KITEM_FLAMESHIELD:
cooldownOnStart = true;
powerItem = true;
@ -554,7 +749,7 @@ INT32 K_KartGetItemOdds(
indirectItem = true;
notNearEnd = true;
if (!K_UsingLegacyCheckpoints() && firstDist < ENDDIST) // No SPB near the end of the race
if (!K_UsingLegacyCheckpoints() && firstDist < (UINT32)ENDDIST) // No SPB near the end of the race
{
newodds = 0;
}
@ -596,9 +791,6 @@ INT32 K_KartGetItemOdds(
break;
case KITEM_HYUDORO:
cooldownOnStart = true;
if (hyubgone > 0)
newodds = 0;
break;
default:
break;
@ -610,7 +802,12 @@ INT32 K_KartGetItemOdds(
return newodds;
}
if ((indirectItem == true) && (indirectitemcooldown > 0))
if (K_GetBGone(item, false) > 0)
{
// (Replaces hyubgone) This item is on cooldown; don't let it get rolled.
newodds = 0;
}
else if ((indirectItem == true) && (indirectitemcooldown > 0))
{
// Too many items that act indirectly in a match can feel kind of bad.
newodds = 0;
@ -620,11 +817,16 @@ INT32 K_KartGetItemOdds(
// This item should not appear at the beginning of a race. (Usually really powerful crowd-breaking items)
newodds = 0;
}
else if (!K_UsingLegacyCheckpoints() && (notNearEnd == true) && (ourDist < ENDDIST))
else if (!K_UsingLegacyCheckpoints() && (notNearEnd == true) && (ourDist < (UINT32)ENDDIST))
{
// This item should not appear at the end of a race. (Usually trap items that lose their effectiveness)
newodds = 0;
}
else if ((notForBottom == true) && (inBottom == true))
{
// This item should not appear for losing players. (Usually items that feel less effective at these positions)
newodds = 0;
}
else if (powerItem == true)
{
// This item is a "power item". This activates "frantic item" toggle related functionality.
@ -689,7 +891,10 @@ UINT8 K_FindUseodds(const player_t *player, fixed_t mashed, UINT32 pdis, UINT8 b
player->distancetofinish,
player->distancefromcluster,
mashed,
spbrush, player->bot, (player->bot && player->botvars.rival)
spbrush,
player->bot,
(player->bot && player->botvars.rival),
K_IsPlayerLosing(player)
) > 0)
{
available = true;
@ -839,11 +1044,17 @@ INT32 K_GetRollingRouletteItem(player_t *player)
return translation[(player->itemroulette % roulette_size) / 3];
}
// Legacy odds are fickle and finicky, so we exaggerate distances
// to simulate parity with pathfind odds.
#define LEGACYODDSEXAGGERATE (2*FRACUNIT/3)
UINT32 K_CalculateInitalPDIS(const player_t *player, UINT8 pingame)
{
UINT8 i;
UINT32 pdis = 0;
(void)pingame;
if (!K_UsingLegacyCheckpoints())
{
for (i = 0; i < MAXPLAYERS; i++)
@ -969,25 +1180,16 @@ UINT32 K_CalculateInitalPDIS(const player_t *player, UINT8 pingame)
secondPlayer = &players[secondIndex];
// Add the distance to the player behind you.
// Distances are divided by 4, then further divided by a fracunit
// to prevent overflow issues.
pdis += (P_AproxDistance(P_AproxDistance(
firstPlayer->mo->x/4 - secondPlayer->mo->x/4,
firstPlayer->mo->y/4 - secondPlayer->mo->y/4),
firstPlayer->mo->z/4 - secondPlayer->mo->z/4)
/ FRACUNIT);
// Scale it to mostly return to normalcy.
pdis = (pdis * 2);
// Again, but this time base it on playercount, same form as
// the following vanilla adjustment, but much weaker since it
// stacks with it
// MAXODDS should always match the number of players the game is designed
// around, so there shouldn't be any issues with basing this calc around that.
// Hacky solution to the overflow problem: use 64-bit integers!
pdis = (UINT32)(((UINT64)(100 + MAXODDS - min(pingame, 16)) * pdis) / 100);
// At a (relative to map) integer scale using basic distancing
// arithmetic; more accurate and less concern for overflows.
// TODO: Overflow-safe addition (caps at UINT32_MAX).
pdis += K_IntDistanceForMap(
secondPlayer->mo->x,
secondPlayer->mo->y,
secondPlayer->mo->z,
firstPlayer->mo->x,
firstPlayer->mo->y,
firstPlayer->mo->z);
// Advance to next index.
firstIndex = secondIndex;
@ -998,9 +1200,14 @@ UINT32 K_CalculateInitalPDIS(const player_t *player, UINT8 pingame)
}
}
// Exaggerate odds; don't you love the legacy system? :Trollic:
pdis = FixedMul(pdis, LEGACYODDSEXAGGERATE);
return pdis;
}
#undef LEGACYODDSEXAGGERATE
UINT32 K_CalculatePDIS(const player_t *player, UINT8 numPlayers, boolean *spbrush)
{
UINT32 pdis = 0;
@ -1034,7 +1241,7 @@ static boolean K_CanForceSPB(player_t *player, UINT32 pdis)
boolean battlecond, racecond;
battlecond = ((gametyperules & GTR_WANTED) && (gametyperules & GTR_WANTEDSPB) && (mostwanted != -1) && (!K_IsPlayerMostWanted(player)));
racecond = ((gametyperules & GTR_CIRCUIT) && player->position == 2 && pdis > SPBFORCEDIST);
racecond = ((gametyperules & GTR_CIRCUIT) && player->position == 2 && pdis > (UINT32)SPBFORCEDIST);
return ((battlecond) || (racecond));
}
@ -1254,7 +1461,10 @@ void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
player->distancetofinish,
player->distancefromcluster,
mashed,
spbrush, player->bot, (player->bot && player->botvars.rival))
spbrush,
player->bot,
(player->bot && player->botvars.rival),
K_IsPlayerLosing(player))
);
}

View file

@ -20,7 +20,6 @@
#include "d_player.h" // Need for player_t
#include "d_ticcmd.h"
#include "m_fixed.h"
#include "k_kart.h" // K_RAGuard
#ifdef __cplusplus
extern "C" {
@ -30,17 +29,33 @@ extern "C" {
#define MAXODDS 16
// Distance variables
#define DISTVAR K_RAGuard(cv_kartoddsdist)
#define DISTVAR_LEGACY K_RAGuard(cv_kartlegacyoddsdist)
#define SPBDISTVAR K_RAGuard(cv_kartspbdist)
#define DISTVAR CV_Get(&cv_kartoddsdist)
#define DISTVAR_LEGACY CV_Get(&cv_kartlegacyoddsdist)
#define SPBDISTVAR CV_Get(&cv_kartspbdist)
extern consvar_t *KartItemCVars[NUMKARTRESULTS-1];
// Goner; tracks how long an item should be "gone" for.
// AKA a time-based cooldown so Hyudoro and whatever else piss off to prevent
// spamming.
typedef enum goner_sect_e {
GONER_BASECOOLDOWN = 0,
GONER_CURRCOOLDOWN = 1,
} goner_sect_t;
extern tic_t ItemBGone[NUMKARTRESULTS][2];
void K_SetBGone(SINT8 item, tic_t time);
void K_SetBGoneToBase(SINT8 item);
tic_t K_GetBGone(SINT8 item, boolean base);
void K_KartHandleShieldCooldown(SINT8 item);
UINT32 K_CalculateInitalPDIS(const player_t *player, UINT8 pingame);
UINT32 K_CalculatePDIS(const player_t *player, UINT8 numPlayers, boolean *spbrush);
UINT8 K_FindUseodds(const player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbumper, boolean spbrush);
UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush);
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, UINT32 ourDist, UINT32 clusterDist, fixed_t mashed, boolean spbrush, boolean bot, boolean rival);
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, UINT32 ourDist, UINT32 clusterDist, fixed_t mashed, boolean spbrush, boolean bot, boolean rival, boolean inBottom);
INT32 K_GetRollingRouletteItem(player_t *player);
SINT8 K_ItemResultToType(SINT8 getitem);
UINT8 K_ItemResultToAmount(SINT8 getitem);

View file

@ -11,12 +11,20 @@ void K_StatTicker(void)
if (demo.playback)
return;
maprecord_t *record = G_AllocateMapRecord(G_BuildMapName(gamemap));
record->playtime++;
kartstats.totalplaytime++;
if (netgame)
{
kartstats.onlineplaytime++;
}
else if (modeattacking)
{
maprecordpreset_t *preset = G_AllocateMapRecordPreset(record, currentrecordpreset, currentrecordpresetversion);
preset->playtime++;
kartstats.raplaytime++;
}
if (gametype == GT_RACE)
kartstats.raceplaytime++;
@ -68,6 +76,10 @@ void K_StatRound(void)
if (demo.playback)
return;
maprecord_t *record = G_AllocateMapRecord(G_BuildMapName(gamemap));
record->roundsplayed++;
kartstats.matchesplayed++;
int numplayers = 0;
for (int i = 0; i < MAXPLAYERS; ++i)
@ -79,9 +91,14 @@ void K_StatRound(void)
if (numplayers > 1 && !players[consoleplayer].spectator)
{
if (players[consoleplayer].position == 1)
{
record->roundswon++;
kartstats.totalwins++;
}
else if (players[consoleplayer].position <= 3) // Should this check if there are more than 3 players in game?
{
kartstats.totalpodium++;
}
}
}

View file

@ -33,6 +33,7 @@
#include "k_color.h"
#include "k_hud.h"
#include "k_waypoint.h"
#include "k_odds.h"
#include "d_netcmd.h" // IsPlayerAdmin
#include "m_menu.h" // Player Setup menu color stuff
#include "p_spec.h" // P_StartQuake
@ -1372,7 +1373,7 @@ static int lib_pSpawnGhostMobj(lua_State *L)
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
LUA_PushUserdata(L, P_SpawnGhostMobj(mobj), META_MOBJ);
LUA_PushUserdata(L, P_SpawnGhostMobjEX(mobj, lua_compatmode), META_MOBJ);
return 1;
}
@ -1417,11 +1418,12 @@ static int lib_pMovePlayer(lua_State *L)
static int lib_pDoPlayerExit(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
pflags_t flags = luaL_checkinteger(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_DoPlayerExit(player);
P_DoPlayerExit(player, flags);
return 0;
}
@ -4109,10 +4111,48 @@ static int lib_kSetHyuCountdown(lua_State *L)
{
tic_t c = (tic_t)luaL_checkinteger(L, 1);
NOHUD
hyubgone = c;
K_SetBGone(KITEM_HYUDORO, c);
return 0;
}
static int lib_kSetBGone(lua_State *L)
{
SINT8 item = (SINT8)luaL_checkinteger(L, 1);
tic_t c = (tic_t)luaL_checkinteger(L, 2);
NOHUD
if (item < KITEM_SNEAKER || item > (NUMKARTRESULTS - 1))
{
luaL_error(L, "given item ID is outside bgone range");
}
K_SetBGone(item, c);
return 0;
}
static int lib_kSetBGoneToBase(lua_State *L)
{
SINT8 item = (SINT8)luaL_checkinteger(L, 1);
NOHUD
if (item < KITEM_SNEAKER || item > (NUMKARTRESULTS - 1))
{
luaL_error(L, "given item ID is outside bgone range");
}
K_SetBGoneToBase(item);
return 0;
}
static int lib_kGetBGone(lua_State *L)
{
SINT8 item = (SINT8)luaL_checkinteger(L, 1);
boolean base = lua_isnoneornil(L, 2) ? false : luaL_checkboolean(L, 2);
NOHUD
if (item < KITEM_SNEAKER || item > (NUMKARTRESULTS - 1))
{
luaL_error(L, "given item ID is outside bgone range");
}
lua_pushinteger(L, K_GetBGone(item, base));
return 1;
}
// Checks if the floor closet floor under an object would be safe to respawn/land on.
static int lib_kSafeRespawnPosition(lua_State *L)
{
@ -4180,6 +4220,13 @@ static int lib_kAirDropActive(lua_State *L)
return 1;
}
// Checks if item littering is active.
static int lib_kItemLitterActive(lua_State *L)
{
lua_pushboolean(L, K_ItemLitterActive());
return 1;
}
// Grabs the currently active invintype.
static int lib_kGetKartInvinType(lua_State *L)
{
@ -4369,6 +4416,28 @@ static int lib_kAwardScaledPlayerRings(lua_State *L)
return 0;
}
static int lib_kGetShieldFromPlayer(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushinteger(L, K_GetShieldFromPlayer(player));
return 1;
}
static int lib_kPlayerCanPunt(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, K_PlayerCanPunt(player));
return 1;
}
static int lib_kAddNewScoreboardMod(lua_State *L)
{
const char *modname = luaL_checkstring(L, 1);
@ -5272,6 +5341,9 @@ static luaL_Reg lib[] = {
{"K_SetExitCountdown",lib_kSetExitCountdown},
{"K_SetIndirectItemCooldown",lib_kSetIndirectItemCountdown},
{"K_SetHyudoroCooldown",lib_kSetHyuCountdown},
{"K_SetBGone", lib_kSetBGone},
{"K_SetBGoneToBase", lib_kSetBGoneToBase},
{"K_GetBGone", lib_kGetBGone},
{"K_SafeRespawnPosition",lib_kSafeRespawnPosition},
{"K_GetCollideAngle",lib_kGetCollideAngle},
@ -5284,6 +5356,7 @@ static luaL_Reg lib[] = {
{"K_SlopeBoostActive",lib_kSlopeBoostActive},
{"K_DraftingActive",lib_kDraftingActive},
{"K_AirDropActive",lib_kAirDropActive},
{"K_ItemLitterActive",lib_kItemLitterActive},
{"K_GetBumpSpark",lib_kGetBumpSpark},
{"K_GetKartInvinType",lib_kGetKartInvinType},
{"K_UsingLegacyCheckpoints",lib_kUsingLegacyCheckpoints},
@ -5301,6 +5374,8 @@ static luaL_Reg lib[] = {
{"K_GetForwardMove", lib_kGetForwardMove},
{"K_AwardPlayerRings", lib_kAwardPlayerRings},
{"K_AwardScaledPlayerRings", lib_kAwardScaledPlayerRings},
{"K_GetShieldFromPlayer", lib_kGetShieldFromPlayer},
{"K_PlayerCanPunt", lib_kPlayerCanPunt},
// k_hud
{"K_AddNewScoreboardMod", lib_kAddNewScoreboardMod},

View file

@ -402,9 +402,16 @@ static int mobj_get(lua_State *L)
}
case mobj_eflags:
{
UINT32 eflags = mo->eflags; // yes, not UINT16
UINT32 eflags = mo->eflags; // yes, not UINT16
if (lua_compatmode)
eflags |= (~mo->renderflags & RF_DONTDRAW);
{
// The old eflags compat system causes rendering issues for characters like
// the MK64 cast. This system causes rendering issues in certain gameplay
// mods. At least in this case, character mods take priority, so we set
// up compatibility like so:
eflags |=
mo->renderflags & RF_DONTDRAW ? ~mo->renderflags & RF_DONTDRAW : 0;
}
lua_pushinteger(L, eflags);
break;
}
@ -608,6 +615,23 @@ static int mobj_get(lua_State *L)
return 1;
}
static inline UINT32 eflags_vischeck(UINT32 eflags)
{
UINT8 playerhide;
playerhide = 0;
if (eflags & RF_DONTDRAW)
{
// Visibility checks are necessary
playerhide = (UINT8)((eflags & RF_DONTDRAW) >> RF_HIDESHIFT);
// Hiding is the opposite of visibility.
playerhide = (~playerhide) & 0x0F;
}
return ((UINT32)(playerhide) << RF_HIDESHIFT);
}
#define NOSET luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly.", mobj_opt[field])
#define NOSETPOS luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("P_Move") ", " LUA_QL("P_TryMove") ", or " LUA_QL("P_SetOrigin") ", or " LUA_QL("P_MoveOrigin") " instead.", mobj_opt[field])
static int mobj_set(lua_State *L)
@ -669,11 +693,18 @@ static int mobj_set(lua_State *L)
case mobj_sprite:
{
spritenum_t newsprite = luaL_checkinteger(L, 3);
if (lua_compatmode && mo->sprite != SPR_PLAY && newsprite == SPR_PLAY)
if (lua_compatmode)
{
UINT8 outframe;
mo->sprite2 = P_KartFrameToSprite2(mo->skin, mo->frame, &outframe);
mo->frame = (mo->frame & ~FF_FRAMEMASK) | outframe;
if (mo->sprite != SPR_PLAY && newsprite == SPR_PLAY) // switch to spr2
{
UINT8 outframe;
mo->sprite2 = P_KartFrameToSprite2(mo->skin, mo->frame, &outframe);
mo->frame = (mo->frame & ~FF_FRAMEMASK) | outframe;
}
else if (mo->sprite == SPR_PLAY && newsprite != SPR_PLAY) // switch from spr2
{
mo->frame = spr2frame(mo->sprite2, mo->frame);
}
}
mo->sprite = newsprite;
break;
@ -824,8 +855,19 @@ static int mobj_set(lua_State *L)
case mobj_eflags:
{
UINT32 eflags = luaL_checkinteger(L, 3);
UINT32 visflags = 0;
if (lua_compatmode)
mo->renderflags = (mo->renderflags & ~RF_DONTDRAW) | (~eflags & RF_DONTDRAW); // eeeyup.
{
// eeeyup.
// Mhm. Yeah.
visflags = eflags_vischeck(eflags);
if ((visflags) && ((mo->renderflags & RF_DONTDRAW) != RF_DONTDRAW))
{
mo->renderflags &= ~RF_DONTDRAW;
mo->renderflags |= visflags;
}
}
mo->eflags = (UINT16)eflags;
break;
}

View file

@ -265,10 +265,11 @@ enum player_e
player_ringtransparency,
player_airdroptime,
player_ringdrop,
player_curshield,
player_shieldtracer,
player_bubblecool,
player_bubbleblowup,
player_bubblehealth,
player_bubbleboost,
player_flamedash,
player_flametimer,
player_flamestore,
@ -468,10 +469,11 @@ static const char *const player_opt[] = {
"ringtransparency",
"airdroptime",
"ringdrop",
"curshield",
"shieldtracer",
"bubblecool",
"bubbleblowup",
"bubblehealth",
"bubbleboost",
"flamedash",
"flametimer",
"flamestore",
@ -565,7 +567,7 @@ static const char *const player_opt[] = {
"loop",
"prevonground",
"walltransfered",
"walltransfeboost",
"walltransferboost",
#ifdef HWRENDER
"fovadd",
#endif
@ -600,7 +602,7 @@ static int player_get(lua_State *L)
LUA_PushUserdata(L, plr->mo, META_MOBJ);
break;
case player_mo:
if (plr->spectator)
if (!plr || plr->spectator)
lua_pushnil(L); // sigh
else
LUA_PushUserdata(L, plr->mo, META_MOBJ);
@ -635,9 +637,17 @@ static int player_get(lua_State *L)
lua_pushangle(L, plr->aiming);
break;
case player_drawangle:
if (lua_compatmode)
goto noexist;
/* FALLTHRU */
case player_frameangle:
lua_pushangle(L, plr->drawangle);
{
angle_t angle = plr->drawangle;
if (lua_compatmode)
angle -= K_GetDriftAngleOffset(plr);
lua_pushangle(L, angle);
break;
}
case player_powers:
LUA_PushUserdata(L, plr->powers, META_POWERS);
break;
@ -893,8 +903,8 @@ static int player_get(lua_State *L)
case player_ringdrop:
lua_pushinteger(L, plr->ringdrop);
break;
case player_curshield:
lua_pushinteger(L, plr->curshield);
case player_shieldtracer:
LUA_PushUserdata(L, plr->shieldtracer, META_MOBJ);
break;
case player_bubblecool:
lua_pushinteger(L, plr->bubblecool);
@ -905,6 +915,9 @@ static int player_get(lua_State *L)
case player_bubblehealth:
lua_pushinteger(L, plr->bubblehealth);
break;
case player_bubbleboost:
lua_pushinteger(L, plr->bubbleboost);
break;
case player_flamedash:
lua_pushinteger(L, plr->flamedash);
break;
@ -1213,6 +1226,7 @@ static int player_get(lua_State *L)
break;
#endif
default:
noexist:
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, plr);
@ -1289,6 +1303,9 @@ static int player_set(lua_State *L)
break;
}
case player_drawangle:
if (lua_compatmode)
goto noexist;
/* FALLTHRU */
case player_frameangle:
{
angle_t angle = luaL_checkangle(L, 3);
@ -1591,9 +1608,8 @@ static int player_set(lua_State *L)
case player_ringdrop:
plr->ringdrop = luaL_checkinteger(L, 3);
break;
case player_curshield:
plr->curshield = luaL_checkinteger(L, 3);
break;
case player_shieldtracer:
return NOSET;
case player_bubblecool:
plr->bubblecool = luaL_checkinteger(L, 3);
break;
@ -1603,6 +1619,9 @@ static int player_set(lua_State *L)
case player_bubblehealth:
plr->bubblehealth = luaL_checkinteger(L, 3);
break;
case player_bubbleboost:
plr->bubbleboost = luaL_checkinteger(L, 3);
break;
case player_flamedash:
plr->flamedash = luaL_checkinteger(L, 3);
break;
@ -1882,14 +1901,17 @@ static int player_set(lua_State *L)
return NOSET;
case player_walltransfered:
plr->walltransfered = lua_toboolean(L, 3);
break;
case player_walltransferboost:
plr->walltransferboost= lua_tointeger(L, 3);
break;
#ifdef HWRENDER
case player_fovadd:
plr->fovadd = luaL_checkfixed(L, 3);
break;
#endif
default:
noexist:
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, plr);
@ -2143,7 +2165,7 @@ static int kartstuff_get(lua_State *L)
lua_pushinteger(L, (plr->itemflags & IF_ITEMOUT));
return 1;
case k_curshield:
lua_pushinteger(L, plr->curshield);
lua_pushinteger(L, K_GetShieldFromPlayer(plr));
return 1;
case k_hyudorotimer:
lua_pushinteger(L, plr->hyudorotimer);
@ -2405,7 +2427,9 @@ static int kartstuff_set(lua_State *L)
plr->itemflags |= IF_ITEMOUT;
break;
case k_curshield:
plr->curshield = i;
// i have no clue where you'd find a script that sets k_curshield, but... this will do?
if (!P_MobjWasRemoved(plr->shieldtracer) && K_GetShieldFromPlayer(plr) != i)
P_RemoveMobj(plr->shieldtracer);
break;
case k_hyudorotimer:
plr->hyudorotimer = i;

View file

@ -27,6 +27,7 @@
#include "p_slopes.h" // for P_SlopeById and slopelist
#include "p_polyobj.h" // polyobj_t, PolyObjects
#include "k_battle.h"
#include "k_odds.h"
#ifdef LUA_ALLOW_BYTECODE
#include "d_netfil.h" // for LUA_DumpFile
#endif
@ -402,17 +403,21 @@ int LUA_PushGlobals(lua_State *L, const char *word)
return 1;
} else if (fastcmp(word,"airdropactive")) {
lua_pushinteger(L, airdropactive);
return 1;
} else if (fastcmp(word,"bumpsparkactive")) {
lua_pushinteger(L, bumpsparkactive);
return 1;
} else if (fastcmp(word,"purpledriftactive")) {
lua_pushinteger(L, purpledriftactive);
return 1;
} else if (fastcmp(word,"itemlittering")) {
lua_pushinteger(L, itemlittering);
return 1;
} else if (fastcmp(word,"invintype")) {
lua_pushinteger(L, invintype);
return 1;
} else if (fastcmp(word,"hyubgone")) {
lua_pushinteger(L, hyubgone);
lua_pushinteger(L, K_GetBGone(KITEM_HYUDORO, false));
return 1;
} else if (fastcmp(word,"encoremode")) {
lua_pushboolean(L, encoremode);
@ -555,7 +560,9 @@ int LUA_WriteGlobals(lua_State *L, const char *word)
else if (fastcmp(word,"indirectitemcooldown"))
indirectitemcooldown = (tic_t)luaL_checkinteger(L, 2);
else if (fastcmp(word,"hyubgone"))
hyubgone = (tic_t)luaL_checkinteger(L, 2);
{
K_SetBGone(KITEM_HYUDORO, (tic_t)luaL_checkinteger(L, 2));
}
else if (fastcmp(word,"starttime"))
starttime = (tic_t)luaL_checkinteger(L, 2);
else if (fastcmp(word,"introtime"))
@ -1003,6 +1010,7 @@ void LUA_InvalidateLevel(void)
LUA_InvalidateUserdata(&sectors[i]);
LUA_InvalidateUserdata(&sectors[i].lines);
LUA_InvalidateUserdata(&sectors[i].tags);
LUA_InvalidateUserdata(&sectors[i].args);
if (sectors[i].ffloors)
{
for (rover = sectors[i].ffloors; rover; rover = rover->next)
@ -1061,6 +1069,8 @@ void LUA_InvalidateMapthings(void)
LUA_InvalidateUserdata(&mapthings[i]);
LUA_InvalidateUserdata(mapthings[i].args);
LUA_InvalidateUserdata(mapthings[i].stringargs);
LUA_InvalidateUserdata(mapthings[i].script_args);
LUA_InvalidateUserdata(mapthings[i].script_stringargs);
}
}
@ -1072,6 +1082,7 @@ void LUA_InvalidatePlayer(player_t *player)
LUA_InvalidateUserdata(player->karthud);
LUA_InvalidateUserdata(player->kartstuff);
LUA_InvalidateUserdata(player->powers);
LUA_InvalidateUserdata(&player->loop);
LUA_InvalidateUserdata(&player->cmd);
}
@ -1131,8 +1142,8 @@ static const struct {
{META_FFLOOR, ARCH_FFLOOR},
{META_POLYOBJ, ARCH_POLYOBJ},
{META_SLOPE, ARCH_SLOPE},
{META_MAPHEADER, ARCH_MAPHEADER},
{META_SKINCOLOR, ARCH_SKINCOLOR},
{META_MAPHEADER,ARCH_MAPHEADER},
{META_SKINCOLOR,ARCH_SKINCOLOR},
{NULL, ARCH_NULL}
};
@ -1281,8 +1292,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{
mobj_t *mobj = *((mobj_t **)lua_touserdata(gL, myindex));
if (!mobj)
{
WRITEUINT8(*p, ARCH_NULL);
else {
return 3;
}
else
{
WRITEUINT8(*p, ARCH_MOBJ);
WRITEUINT32(*p, mobj->mobjnum);
}
@ -1292,8 +1307,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{
player_t *player = *((player_t **)lua_touserdata(gL, myindex));
if (!player)
{
WRITEUINT8(*p, ARCH_NULL);
else {
return 3;
}
else
{
WRITEUINT8(*p, ARCH_PLAYER);
WRITEUINT8(*p, player - players);
}
@ -1303,8 +1322,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{
mapthing_t *mapthing = *((mapthing_t **)lua_touserdata(gL, myindex));
if (!mapthing)
{
WRITEUINT8(*p, ARCH_NULL);
else {
return 3;
}
else
{
WRITEUINT8(*p, ARCH_MAPTHING);
WRITEUINT16(*p, mapthing - mapthings);
}
@ -1314,8 +1337,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{
vertex_t *vertex = *((vertex_t **)lua_touserdata(gL, myindex));
if (!vertex)
{
WRITEUINT8(*p, ARCH_NULL);
else {
return 3;
}
else
{
WRITEUINT8(*p, ARCH_VERTEX);
WRITEUINT16(*p, vertex - vertexes);
}
@ -1325,8 +1352,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{
line_t *line = *((line_t **)lua_touserdata(gL, myindex));
if (!line)
{
WRITEUINT8(*p, ARCH_NULL);
else {
return 3;
}
else
{
WRITEUINT8(*p, ARCH_LINE);
WRITEUINT16(*p, line - lines);
}
@ -1336,8 +1367,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{
side_t *side = *((side_t **)lua_touserdata(gL, myindex));
if (!side)
{
WRITEUINT8(*p, ARCH_NULL);
else {
return 3;
}
else
{
WRITEUINT8(*p, ARCH_SIDE);
WRITEUINT16(*p, side - sides);
}
@ -1347,8 +1382,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{
subsector_t *subsector = *((subsector_t **)lua_touserdata(gL, myindex));
if (!subsector)
{
WRITEUINT8(*p, ARCH_NULL);
else {
return 3;
}
else
{
WRITEUINT8(*p, ARCH_SUBSECTOR);
WRITEUINT16(*p, subsector - subsectors);
}
@ -1358,8 +1397,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{
sector_t *sector = *((sector_t **)lua_touserdata(gL, myindex));
if (!sector)
{
WRITEUINT8(*p, ARCH_NULL);
else {
return 3;
}
else
{
WRITEUINT8(*p, ARCH_SECTOR);
WRITEUINT16(*p, sector - sectors);
}
@ -1422,8 +1465,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{
pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex));
if (!slope)
{
WRITEUINT8(*p, ARCH_NULL);
else {
return 3;
}
else
{
WRITEUINT8(*p, ARCH_SLOPE);
WRITEUINT16(*p, slope->id);
}
@ -1433,8 +1480,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{
mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex));
if (!header)
{
WRITEUINT8(*p, ARCH_NULL);
else {
return 3;
}
else
{
WRITEUINT8(*p, ARCH_MAPHEADER);
WRITEUINT16(*p, header - *mapheaderinfo);
}
@ -1543,15 +1594,25 @@ static void ArchiveTables(UINT8 **p)
{
// Write key
e = ArchiveValue(p, TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this.
if (e == 1)
n++; // the table contained a new table we'll have to archive. :(
else if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise)
{
CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -2), luaL_typename(gL, -2), i);
}
else if (e == 3) // nil key due to invalid userdata. NOT an error.
{
lua_pop(gL, 1);
continue;
}
// Write value
e = ArchiveValue(p, TABLESINDEX, -1);
if (e == 1)
{
n++; // the table contained a new table we'll have to archive. :(
}
else if (e == 2) // invalid value type
CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -2), luaL_typename(gL, -1));
@ -1846,8 +1907,9 @@ void LUA_Step(void)
}
}
void LUA_Archive(savebuffer_t *save, boolean network)
void LUA_Sync(savebuffer_t *save, boolean network, boolean compat)
{
UINT32 mobjnum;
INT32 i;
thinker_t *th;
@ -1858,71 +1920,60 @@ void LUA_Archive(savebuffer_t *save, boolean network)
{
if (!playeringame[i] && i > 0) // NEVER skip player 0, this is for dedi servs.
continue;
// all players in game will be archived, even if they just add a 0.
ArchiveExtVars(&save->p, &players[i], "player");
if (save->write)
ArchiveExtVars(&save->p, &players[i], "player");
else
UnArchiveExtVars(&save->p, &players[i], compat);
}
if (network == true)
if (save->write)
{
if (gamestate == GS_LEVEL)
if (network == true)
{
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
if (gamestate == GS_LEVEL)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
// archive function will determine when to skip mobjs,
// and write mobjnum in otherwise.
ArchiveExtVars(&save->p, th, "mobj");
// archive function will determine when to skip mobjs,
// and write mobjnum in otherwise.
ArchiveExtVars(&save->p, th, "mobj");
}
}
WRITEUINT32(save->p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
LUA_HookNetArchive(NetArchive, save); // call the NetArchive hook in archive mode
}
WRITEUINT32(save->p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
LUA_HookNetArchive(NetArchive, save); // call the NetArchive hook in archive mode
ArchiveTables(&save->p);
}
ArchiveTables(&save->p);
if (gL)
lua_pop(gL, 1); // pop tables
}
void LUA_UnArchive(savebuffer_t *save, boolean network, boolean compat)
{
UINT32 mobjnum;
INT32 i;
thinker_t *th;
if (gL)
lua_newtable(gL); // tables to be read
for (i = 0; i < MAXPLAYERS; i++)
else
{
if (!playeringame[i] && i > 0) // same here, this is to synch dediservs properly.
continue;
UnArchiveExtVars(&save->p, &players[i], compat);
if (network == true)
{
do {
mobjnum = READUINT32(save->p); // read a mobjnum
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj
continue;
UnArchiveExtVars(&save->p, th, false); // apply variables
}
} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
LUA_HookNetArchive(NetUnArchive, save); // call the NetArchive hook in unarchive mode
}
UnArchiveTables(&save->p, compat);
}
if (network == true)
{
do {
mobjnum = READUINT32(save->p); // read a mobjnum
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj
continue;
UnArchiveExtVars(&save->p, th, false); // apply variables
}
} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
LUA_HookNetArchive(NetUnArchive, save); // call the NetArchive hook in unarchive mode
}
UnArchiveTables(&save->p, compat);
if (gL)
lua_pop(gL, 1); // pop tables
}

View file

@ -61,8 +61,7 @@ void LUA_DumpFile(const char *filename);
#endif
fixed_t LUA_EvalMath(const char *word);
void LUA_Step(void);
void LUA_Archive(savebuffer_t *save, boolean network);
void LUA_UnArchive(savebuffer_t *save, boolean network, boolean compat);
void LUA_Sync(savebuffer_t *save, boolean network, boolean compat);
void LUA_SetCFunctionField(lua_State *L, const char *name, lua_CFunction value);

2832
src/lz4.c Normal file

File diff suppressed because it is too large Load diff

886
src/lz4.h Normal file
View file

@ -0,0 +1,886 @@
/*
* LZ4 - Fast LZ compression algorithm
* Header File
* Copyright (c) Yann Collet. All rights reserved.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 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.
You can contact the author at :
- LZ4 homepage : http://www.lz4.org
- LZ4 source repository : https://github.com/lz4/lz4
*/
#if defined (__cplusplus)
extern "C" {
#endif
#ifndef LZ4_H_2983827168210
#define LZ4_H_2983827168210
/* --- Dependency --- */
#include <stddef.h> /* size_t */
/**
Introduction
LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core,
scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
The LZ4 compression library provides in-memory compression and decompression functions.
It gives full buffer control to user.
Compression can be done in:
- a single step (described as Simple Functions)
- a single step, reusing a context (described in Advanced Functions)
- unbounded multiple steps (described as Streaming compression)
lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md).
Decompressing such a compressed block requires additional metadata.
Exact metadata depends on exact decompression function.
For the typical case of LZ4_decompress_safe(),
metadata includes block's compressed size, and maximum bound of decompressed size.
Each application is free to encode and pass such metadata in whichever way it wants.
lz4.h only handle blocks, it can not generate Frames.
Blocks are different from Frames (doc/lz4_Frame_format.md).
Frames bundle both blocks and metadata in a specified manner.
Embedding metadata is required for compressed data to be self-contained and portable.
Frame format is delivered through a companion API, declared in lz4frame.h.
The `lz4` CLI can only manage frames.
*/
/*^***************************************************************
* Export parameters
*****************************************************************/
/*
* LZ4_DLL_EXPORT :
* Enable exporting of functions when building a Windows DLL
* LZ4LIB_VISIBILITY :
* Control library symbols visibility.
*/
#ifndef LZ4LIB_VISIBILITY
# if defined(__GNUC__) && (__GNUC__ >= 4)
# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default")))
# else
# define LZ4LIB_VISIBILITY
# endif
#endif
#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY
#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
#else
# define LZ4LIB_API LZ4LIB_VISIBILITY
#endif
/*! LZ4_FREESTANDING :
* When this macro is set to 1, it enables "freestanding mode" that is
* suitable for typical freestanding environment which doesn't support
* standard C library.
*
* - LZ4_FREESTANDING is a compile-time switch.
* - It requires the following macros to be defined:
* LZ4_memcpy, LZ4_memmove, LZ4_memset.
* - It only enables LZ4/HC functions which don't use heap.
* All LZ4F_* functions are not supported.
* - See tests/freestanding.c to check its basic setup.
*/
#if defined(LZ4_FREESTANDING) && (LZ4_FREESTANDING == 1)
# define LZ4_HEAPMODE 0
# define LZ4HC_HEAPMODE 0
# define LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION 1
# if !defined(LZ4_memcpy)
# error "LZ4_FREESTANDING requires macro 'LZ4_memcpy'."
# endif
# if !defined(LZ4_memset)
# error "LZ4_FREESTANDING requires macro 'LZ4_memset'."
# endif
# if !defined(LZ4_memmove)
# error "LZ4_FREESTANDING requires macro 'LZ4_memmove'."
# endif
#elif ! defined(LZ4_FREESTANDING)
# define LZ4_FREESTANDING 0
#endif
/*------ Version ------*/
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
#define LZ4_VERSION_MINOR 10 /* for new (non-breaking) interface capabilities */
#define LZ4_VERSION_RELEASE 0 /* for tweaks, bug-fixes, or development */
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
#define LZ4_QUOTE(str) #str
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) /* requires v1.7.3+ */
LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version; requires v1.3.0+ */
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version; requires v1.7.5+ */
/*-************************************
* Tuning memory usage
**************************************/
/*!
* LZ4_MEMORY_USAGE :
* Can be selected at compile time, by setting LZ4_MEMORY_USAGE.
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB)
* Increasing memory usage improves compression ratio, generally at the cost of speed.
* Reduced memory usage may improve speed at the cost of ratio, thanks to better cache locality.
* Default value is 14, for 16KB, which nicely fits into most L1 caches.
*/
#ifndef LZ4_MEMORY_USAGE
# define LZ4_MEMORY_USAGE LZ4_MEMORY_USAGE_DEFAULT
#endif
/* These are absolute limits, they should not be changed by users */
#define LZ4_MEMORY_USAGE_MIN 10
#define LZ4_MEMORY_USAGE_DEFAULT 14
#define LZ4_MEMORY_USAGE_MAX 20
#if (LZ4_MEMORY_USAGE < LZ4_MEMORY_USAGE_MIN)
# error "LZ4_MEMORY_USAGE is too small !"
#endif
#if (LZ4_MEMORY_USAGE > LZ4_MEMORY_USAGE_MAX)
# error "LZ4_MEMORY_USAGE is too large !"
#endif
/*-************************************
* Simple Functions
**************************************/
/*! LZ4_compress_default() :
* Compresses 'srcSize' bytes from buffer 'src'
* into already allocated 'dst' buffer of size 'dstCapacity'.
* Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
* It also runs faster, so it's a recommended setting.
* If the function cannot compress 'src' into a more limited 'dst' budget,
* compression stops *immediately*, and the function result is zero.
* In which case, 'dst' content is undefined (invalid).
* srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
* dstCapacity : size of buffer 'dst' (which must be already allocated)
* @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
* or 0 if compression fails
* Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
*/
LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
/*! LZ4_decompress_safe() :
* @compressedSize : is the exact complete size of the compressed block.
* @dstCapacity : is the size of destination buffer (which must be already allocated),
* presumed an upper bound of decompressed size.
* @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
* If destination buffer is not large enough, decoding will stop and output an error code (negative value).
* If the source stream is detected malformed, the function will stop decoding and return a negative result.
* Note 1 : This function is protected against malicious data packets :
* it will never writes outside 'dst' buffer, nor read outside 'source' buffer,
* even if the compressed block is maliciously modified to order the decoder to do these actions.
* In such case, the decoder stops immediately, and considers the compressed block malformed.
* Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them.
* The implementation is free to send / store / derive this information in whichever way is most beneficial.
* If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead.
*/
LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
/*-************************************
* Advanced Functions
**************************************/
#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
/*! LZ4_compressBound() :
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
This function is primarily useful for memory allocation purposes (destination buffer size).
Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize)
inputSize : max supported value is LZ4_MAX_INPUT_SIZE
return : maximum output size in a "worst case" scenario
or 0, if input size is incorrect (too large or negative)
*/
LZ4LIB_API int LZ4_compressBound(int inputSize);
/*! LZ4_compress_fast() :
Same as LZ4_compress_default(), but allows selection of "acceleration" factor.
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
An acceleration value of "1" is the same as regular LZ4_compress_default()
Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c).
Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c).
*/
LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_compress_fast_extState() :
* Same as LZ4_compress_fast(), using an externally allocated memory space for its state.
* Use LZ4_sizeofState() to know how much memory must be allocated,
* and allocate it on 8-bytes boundaries (using `malloc()` typically).
* Then, provide this buffer as `void* state` to compression function.
*/
LZ4LIB_API int LZ4_sizeofState(void);
LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_compress_destSize() :
* Reverse the logic : compresses as much data as possible from 'src' buffer
* into already allocated buffer 'dst', of size >= 'dstCapacity'.
* This function either compresses the entire 'src' content into 'dst' if it's large enough,
* or fill 'dst' buffer completely with as much data as possible from 'src'.
* note: acceleration parameter is fixed to "default".
*
* *srcSizePtr : in+out parameter. Initially contains size of input.
* Will be modified to indicate how many bytes where read from 'src' to fill 'dst'.
* New value is necessarily <= input value.
* @return : Nb bytes written into 'dst' (necessarily <= dstCapacity)
* or 0 if compression fails.
*
* Note : 'targetDstSize' must be >= 1, because it's the smallest valid lz4 payload.
*
* Note 2:from v1.8.2 to v1.9.1, this function had a bug (fixed in v1.9.2+):
* the produced compressed content could, in rare circumstances,
* require to be decompressed into a destination buffer
* larger by at least 1 byte than decompressesSize.
* If an application uses `LZ4_compress_destSize()`,
* it's highly recommended to update liblz4 to v1.9.2 or better.
* If this can't be done or ensured,
* the receiving decompression function should provide
* a dstCapacity which is > decompressedSize, by at least 1 byte.
* See https://github.com/lz4/lz4/issues/859 for details
*/
LZ4LIB_API int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize);
/*! LZ4_decompress_safe_partial() :
* Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',
* into destination buffer 'dst' of size 'dstCapacity'.
* Up to 'targetOutputSize' bytes will be decoded.
* The function stops decoding on reaching this objective.
* This can be useful to boost performance
* whenever only the beginning of a block is required.
*
* @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize)
* If source stream is detected malformed, function returns a negative result.
*
* Note 1 : @return can be < targetOutputSize, if compressed block contains less data.
*
* Note 2 : targetOutputSize must be <= dstCapacity
*
* Note 3 : this function effectively stops decoding on reaching targetOutputSize,
* so dstCapacity is kind of redundant.
* This is because in older versions of this function,
* decoding operation would still write complete sequences.
* Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize,
* it could write more bytes, though only up to dstCapacity.
* Some "margin" used to be required for this operation to work properly.
* Thankfully, this is no longer necessary.
* The function nonetheless keeps the same signature, in an effort to preserve API compatibility.
*
* Note 4 : If srcSize is the exact size of the block,
* then targetOutputSize can be any value,
* including larger than the block's decompressed size.
* The function will, at most, generate block's decompressed size.
*
* Note 5 : If srcSize is _larger_ than block's compressed size,
* then targetOutputSize **MUST** be <= block's decompressed size.
* Otherwise, *silent corruption will occur*.
*/
LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
/*-*********************************************
* Streaming Compression Functions
***********************************************/
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
/*!
Note about RC_INVOKED
- RC_INVOKED is predefined symbol of rc.exe (the resource compiler which is part of MSVC/Visual Studio).
https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros
- Since rc.exe is a legacy compiler, it truncates long symbol (> 30 chars)
and reports warning "RC4011: identifier truncated".
- To eliminate the warning, we surround long preprocessor symbol with
"#if !defined(RC_INVOKED) ... #endif" block that means
"skip this block when rc.exe is trying to read it".
*/
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
#endif
/*! LZ4_resetStream_fast() : v1.9.0+
* Use this to prepare an LZ4_stream_t for a new chain of dependent blocks
* (e.g., LZ4_compress_fast_continue()).
*
* An LZ4_stream_t must be initialized once before usage.
* This is automatically done when created by LZ4_createStream().
* However, should the LZ4_stream_t be simply declared on stack (for example),
* it's necessary to initialize it first, using LZ4_initStream().
*
* After init, start any new stream with LZ4_resetStream_fast().
* A same LZ4_stream_t can be re-used multiple times consecutively
* and compress multiple streams,
* provided that it starts each new stream with LZ4_resetStream_fast().
*
* LZ4_resetStream_fast() is much faster than LZ4_initStream(),
* but is not compatible with memory regions containing garbage data.
*
* Note: it's only useful to call LZ4_resetStream_fast()
* in the context of streaming compression.
* The *extState* functions perform their own resets.
* Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive.
*/
LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);
/*! LZ4_loadDict() :
* Use this function to reference a static dictionary into LZ4_stream_t.
* The dictionary must remain available during compression.
* LZ4_loadDict() triggers a reset, so any previous data will be forgotten.
* The same dictionary will have to be loaded on decompression side for successful decoding.
* Dictionary are useful for better compression of small data (KB range).
* While LZ4 itself accepts any input as dictionary, dictionary efficiency is also a topic.
* When in doubt, employ the Zstandard's Dictionary Builder.
* Loading a size of 0 is allowed, and is the same as reset.
* @return : loaded dictionary size, in bytes (note: only the last 64 KB are loaded)
*/
LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
/*! LZ4_loadDictSlow() : v1.10.0+
* Same as LZ4_loadDict(),
* but uses a bit more cpu to reference the dictionary content more thoroughly.
* This is expected to slightly improve compression ratio.
* The extra-cpu cost is likely worth it if the dictionary is re-used across multiple sessions.
* @return : loaded dictionary size, in bytes (note: only the last 64 KB are loaded)
*/
LZ4LIB_API int LZ4_loadDictSlow(LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
/*! LZ4_attach_dictionary() : stable since v1.10.0
*
* This allows efficient re-use of a static dictionary multiple times.
*
* Rather than re-loading the dictionary buffer into a working context before
* each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a
* working LZ4_stream_t, this function introduces a no-copy setup mechanism,
* in which the working stream references @dictionaryStream in-place.
*
* Several assumptions are made about the state of @dictionaryStream.
* Currently, only states which have been prepared by LZ4_loadDict() or
* LZ4_loadDictSlow() should be expected to work.
*
* Alternatively, the provided @dictionaryStream may be NULL,
* in which case any existing dictionary stream is unset.
*
* If a dictionary is provided, it replaces any pre-existing stream history.
* The dictionary contents are the only history that can be referenced and
* logically immediately precede the data compressed in the first subsequent
* compression call.
*
* The dictionary will only remain attached to the working stream through the
* first compression call, at the end of which it is cleared.
* @dictionaryStream stream (and source buffer) must remain in-place / accessible / unchanged
* through the completion of the compression session.
*
* Note: there is no equivalent LZ4_attach_*() method on the decompression side
* because there is no initialization cost, hence no need to share the cost across multiple sessions.
* To decompress LZ4 blocks using dictionary, attached or not,
* just employ the regular LZ4_setStreamDecode() for streaming,
* or the stateless LZ4_decompress_safe_usingDict() for one-shot decompression.
*/
LZ4LIB_API void
LZ4_attach_dictionary(LZ4_stream_t* workingStream,
const LZ4_stream_t* dictionaryStream);
/*! LZ4_compress_fast_continue() :
* Compress 'src' content using data from previously compressed blocks, for better compression ratio.
* 'dst' buffer must be already allocated.
* If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
*
* @return : size of compressed block
* or 0 if there is an error (typically, cannot fit into 'dst').
*
* Note 1 : Each invocation to LZ4_compress_fast_continue() generates a new block.
* Each block has precise boundaries.
* Each block must be decompressed separately, calling LZ4_decompress_*() with relevant metadata.
* It's not possible to append blocks together and expect a single invocation of LZ4_decompress_*() to decompress them together.
*
* Note 2 : The previous 64KB of source data is __assumed__ to remain present, unmodified, at same address in memory !
*
* Note 3 : When input is structured as a double-buffer, each buffer can have any size, including < 64 KB.
* Make sure that buffers are separated, by at least one byte.
* This construction ensures that each block only depends on previous block.
*
* Note 4 : If input buffer is a ring-buffer, it can have any size, including < 64 KB.
*
* Note 5 : After an error, the stream status is undefined (invalid), it can only be reset or freed.
*/
LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_saveDict() :
* If last 64KB data cannot be guaranteed to remain available at its current memory location,
* save it into a safer place (char* safeBuffer).
* This is schematically equivalent to a memcpy() followed by LZ4_loadDict(),
* but is much faster, because LZ4_saveDict() doesn't need to rebuild tables.
* @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error.
*/
LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize);
/*-**********************************************
* Streaming Decompression Functions
* Bufferless synchronous API
************************************************/
typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */
/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() :
* creation / destruction of streaming decompression tracking context.
* A tracking context can be re-used multiple times.
*/
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
#endif
/*! LZ4_setStreamDecode() :
* An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
* Use this function to start decompression of a new stream of blocks.
* A dictionary can optionally be set. Use NULL or size 0 for a reset order.
* Dictionary is presumed stable : it must remain accessible and unmodified during next decompression.
* @return : 1 if OK, 0 if error
*/
LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
/*! LZ4_decoderRingBufferSize() : v1.8.2+
* Note : in a ring buffer scenario (optional),
* blocks are presumed decompressed next to each other
* up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize),
* at which stage it resumes from beginning of ring buffer.
* When setting such a ring buffer for streaming decompression,
* provides the minimum size of this ring buffer
* to be compatible with any source respecting maxBlockSize condition.
* @return : minimum ring buffer size,
* or 0 if there is an error (invalid maxBlockSize).
*/
LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);
#define LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize) (65536 + 14 + (maxBlockSize)) /* for static allocation; maxBlockSize presumed valid */
/*! LZ4_decompress_safe_continue() :
* This decoding function allows decompression of consecutive blocks in "streaming" mode.
* The difference with the usual independent blocks is that
* new blocks are allowed to find references into former blocks.
* A block is an unsplittable entity, and must be presented entirely to the decompression function.
* LZ4_decompress_safe_continue() only accepts one block at a time.
* It's modeled after `LZ4_decompress_safe()` and behaves similarly.
*
* @LZ4_streamDecode : decompression state, tracking the position in memory of past data
* @compressedSize : exact complete size of one compressed block.
* @dstCapacity : size of destination buffer (which must be already allocated),
* must be an upper bound of decompressed size.
* @return : number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
* If destination buffer is not large enough, decoding will stop and output an error code (negative value).
* If the source stream is detected malformed, the function will stop decoding and return a negative result.
*
* The last 64KB of previously decoded data *must* remain available and unmodified
* at the memory position where they were previously decoded.
* If less than 64KB of data has been decoded, all the data must be present.
*
* Special : if decompression side sets a ring buffer, it must respect one of the following conditions :
* - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize).
* maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes.
* In which case, encoding and decoding buffers do not need to be synchronized.
* Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize.
* - Synchronized mode :
* Decompression buffer size is _exactly_ the same as compression buffer size,
* and follows exactly same update rule (block boundaries at same positions),
* and decoding function is provided with exact decompressed size of each block (exception for last block of the stream),
* _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB).
* - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes.
* In which case, encoding and decoding buffers do not need to be synchronized,
* and encoding ring buffer can have any size, including small ones ( < 64 KB).
*
* Whenever these conditions are not possible,
* save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
* then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
*/
LZ4LIB_API int
LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode,
const char* src, char* dst,
int srcSize, int dstCapacity);
/*! LZ4_decompress_safe_usingDict() :
* Works the same as
* a combination of LZ4_setStreamDecode() followed by LZ4_decompress_safe_continue()
* However, it's stateless: it doesn't need any LZ4_streamDecode_t state.
* Dictionary is presumed stable : it must remain accessible and unmodified during decompression.
* Performance tip : Decompression speed can be substantially increased
* when dst == dictStart + dictSize.
*/
LZ4LIB_API int
LZ4_decompress_safe_usingDict(const char* src, char* dst,
int srcSize, int dstCapacity,
const char* dictStart, int dictSize);
/*! LZ4_decompress_safe_partial_usingDict() :
* Behaves the same as LZ4_decompress_safe_partial()
* with the added ability to specify a memory segment for past data.
* Performance tip : Decompression speed can be substantially increased
* when dst == dictStart + dictSize.
*/
LZ4LIB_API int
LZ4_decompress_safe_partial_usingDict(const char* src, char* dst,
int compressedSize,
int targetOutputSize, int maxOutputSize,
const char* dictStart, int dictSize);
#endif /* LZ4_H_2983827168210 */
/*^*************************************
* !!!!!! STATIC LINKING ONLY !!!!!!
***************************************/
/*-****************************************************************************
* Experimental section
*
* Symbols declared in this section must be considered unstable. Their
* signatures or semantics may change, or they may be removed altogether in the
* future. They are therefore only safe to depend on when the caller is
* statically linked against the library.
*
* To protect against unsafe usage, not only are the declarations guarded,
* the definitions are hidden by default
* when building LZ4 as a shared/dynamic library.
*
* In order to access these declarations,
* define LZ4_STATIC_LINKING_ONLY in your application
* before including LZ4's headers.
*
* In order to make their implementations accessible dynamically, you must
* define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.
******************************************************************************/
#ifdef LZ4_STATIC_LINKING_ONLY
#ifndef LZ4_STATIC_3504398509
#define LZ4_STATIC_3504398509
#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS
# define LZ4LIB_STATIC_API LZ4LIB_API
#else
# define LZ4LIB_STATIC_API
#endif
/*! LZ4_compress_fast_extState_fastReset() :
* A variant of LZ4_compress_fast_extState().
*
* Using this variant avoids an expensive initialization step.
* It is only safe to call if the state buffer is known to be correctly initialized already
* (see above comment on LZ4_resetStream_fast() for a definition of "correctly initialized").
* From a high level, the difference is that
* this function initializes the provided state with a call to something like LZ4_resetStream_fast()
* while LZ4_compress_fast_extState() starts with a call to LZ4_resetStream().
*/
LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_compress_destSize_extState() : introduced in v1.10.0
* Same as LZ4_compress_destSize(), but using an externally allocated state.
* Also: exposes @acceleration
*/
int LZ4_compress_destSize_extState(void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize, int acceleration);
/*! In-place compression and decompression
*
* It's possible to have input and output sharing the same buffer,
* for highly constrained memory environments.
* In both cases, it requires input to lay at the end of the buffer,
* and decompression to start at beginning of the buffer.
* Buffer size must feature some margin, hence be larger than final size.
*
* |<------------------------buffer--------------------------------->|
* |<-----------compressed data--------->|
* |<-----------decompressed size------------------>|
* |<----margin---->|
*
* This technique is more useful for decompression,
* since decompressed size is typically larger,
* and margin is short.
*
* In-place decompression will work inside any buffer
* which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize).
* This presumes that decompressedSize > compressedSize.
* Otherwise, it means compression actually expanded data,
* and it would be more efficient to store such data with a flag indicating it's not compressed.
* This can happen when data is not compressible (already compressed, or encrypted).
*
* For in-place compression, margin is larger, as it must be able to cope with both
* history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX,
* and data expansion, which can happen when input is not compressible.
* As a consequence, buffer size requirements are much higher,
* and memory savings offered by in-place compression are more limited.
*
* There are ways to limit this cost for compression :
* - Reduce history size, by modifying LZ4_DISTANCE_MAX.
* Note that it is a compile-time constant, so all compressions will apply this limit.
* Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX,
* so it's a reasonable trick when inputs are known to be small.
* - Require the compressor to deliver a "maximum compressed size".
* This is the `dstCapacity` parameter in `LZ4_compress*()`.
* When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail,
* in which case, the return code will be 0 (zero).
* The caller must be ready for these cases to happen,
* and typically design a backup scheme to send data uncompressed.
* The combination of both techniques can significantly reduce
* the amount of margin required for in-place compression.
*
* In-place compression can work in any buffer
* which size is >= (maxCompressedSize)
* with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success.
* LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX,
* so it's possible to reduce memory requirements by playing with them.
*/
#define LZ4_DECOMPRESS_INPLACE_MARGIN(compressedSize) (((compressedSize) >> 8) + 32)
#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize) ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize)) /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */
#ifndef LZ4_DISTANCE_MAX /* history window size; can be user-defined at compile time */
# define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */
#endif
#define LZ4_COMPRESS_INPLACE_MARGIN (LZ4_DISTANCE_MAX + 32) /* LZ4_DISTANCE_MAX can be safely replaced by srcSize when it's smaller */
#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize) ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN) /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */
#endif /* LZ4_STATIC_3504398509 */
#endif /* LZ4_STATIC_LINKING_ONLY */
#ifndef LZ4_H_98237428734687
#define LZ4_H_98237428734687
/*-************************************************************
* Private Definitions
**************************************************************
* Do not use these definitions directly.
* They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
* Accessing members will expose user code to API and/or ABI break in future versions of the library.
**************************************************************/
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
# include <stdint.h>
typedef int8_t LZ4_i8;
typedef unsigned char LZ4_byte;
typedef uint16_t LZ4_u16;
typedef uint32_t LZ4_u32;
#else
typedef signed char LZ4_i8;
typedef unsigned char LZ4_byte;
typedef unsigned short LZ4_u16;
typedef unsigned int LZ4_u32;
#endif
/*! LZ4_stream_t :
* Never ever use below internal definitions directly !
* These definitions are not API/ABI safe, and may change in future versions.
* If you need static allocation, declare or allocate an LZ4_stream_t object.
**/
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
struct LZ4_stream_t_internal {
LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];
const LZ4_byte* dictionary;
const LZ4_stream_t_internal* dictCtx;
LZ4_u32 currentOffset;
LZ4_u32 tableType;
LZ4_u32 dictSize;
/* Implicit padding to ensure structure is aligned */
};
#define LZ4_STREAM_MINSIZE ((1UL << (LZ4_MEMORY_USAGE)) + 32) /* static size, for inter-version compatibility */
union LZ4_stream_u {
char minStateSize[LZ4_STREAM_MINSIZE];
LZ4_stream_t_internal internal_donotuse;
}; /* previously typedef'd to LZ4_stream_t */
/*! LZ4_initStream() : v1.9.0+
* An LZ4_stream_t structure must be initialized at least once.
* This is automatically done when invoking LZ4_createStream(),
* but it's not when the structure is simply declared on stack (for example).
*
* Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t.
* It can also initialize any arbitrary buffer of sufficient size,
* and will @return a pointer of proper type upon initialization.
*
* Note : initialization fails if size and alignment conditions are not respected.
* In which case, the function will @return NULL.
* Note2: An LZ4_stream_t structure guarantees correct alignment and size.
* Note3: Before v1.9.0, use LZ4_resetStream() instead
**/
LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* stateBuffer, size_t size);
/*! LZ4_streamDecode_t :
* Never ever use below internal definitions directly !
* These definitions are not API/ABI safe, and may change in future versions.
* If you need static allocation, declare or allocate an LZ4_streamDecode_t object.
**/
typedef struct {
const LZ4_byte* externalDict;
const LZ4_byte* prefixEnd;
size_t extDictSize;
size_t prefixSize;
} LZ4_streamDecode_t_internal;
#define LZ4_STREAMDECODE_MINSIZE 32
union LZ4_streamDecode_u {
char minStateSize[LZ4_STREAMDECODE_MINSIZE];
LZ4_streamDecode_t_internal internal_donotuse;
} ; /* previously typedef'd to LZ4_streamDecode_t */
/*-************************************
* Obsolete Functions
**************************************/
/*! Deprecation warnings
*
* Deprecated functions make the compiler generate a warning when invoked.
* This is meant to invite users to update their source code.
* Should deprecation warnings be a problem, it is generally possible to disable them,
* typically with -Wno-deprecated-declarations for gcc
* or _CRT_SECURE_NO_WARNINGS in Visual.
*
* Another method is to define LZ4_DISABLE_DEPRECATE_WARNINGS
* before including the header file.
*/
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
# define LZ4_DEPRECATED(message) /* disable deprecation warnings */
#else
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
# define LZ4_DEPRECATED(message) [[deprecated(message)]]
# elif defined(_MSC_VER)
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45))
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
# elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31)
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
# else
# pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler")
# define LZ4_DEPRECATED(message) /* disabled */
# endif
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
/*! Obsolete compression functions (since v1.7.3) */
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* src, char* dest, int srcSize);
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
/*! Obsolete decompression functions (since v1.8.0) */
LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
/* Obsolete streaming functions (since v1.7.0)
* degraded functionality; do not use!
*
* In order to perform streaming compression, these functions depended on data
* that is no longer tracked in the state. They have been preserved as well as
* possible: using them will still produce a correct output. However, they don't
* actually retain any history between compression calls. The compression ratio
* achieved will therefore be no better than compressing each chunk
* independently.
*/
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer);
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void);
LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);
LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);
/*! Obsolete streaming decoding functions (since v1.7.0) */
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
/*! Obsolete LZ4_decompress_fast variants (since v1.9.0) :
* These functions used to be faster than LZ4_decompress_safe(),
* but this is no longer the case. They are now slower.
* This is because LZ4_decompress_fast() doesn't know the input size,
* and therefore must progress more cautiously into the input buffer to not read beyond the end of block.
* On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability.
* As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated.
*
* The last remaining LZ4_decompress_fast() specificity is that
* it can decompress a block without knowing its compressed size.
* Such functionality can be achieved in a more secure manner
* by employing LZ4_decompress_safe_partial().
*
* Parameters:
* originalSize : is the uncompressed size to regenerate.
* `dst` must be already allocated, its size must be >= 'originalSize' bytes.
* @return : number of bytes read from source buffer (== compressed size).
* The function expects to finish at block's end exactly.
* If the source stream is detected malformed, the function stops decoding and returns a negative result.
* note : LZ4_decompress_fast*() requires originalSize. Thanks to this information, it never writes past the output buffer.
* However, since it doesn't know its 'src' size, it may read an unknown amount of input, past input buffer bounds.
* Also, since match offsets are not validated, match reads from 'src' may underflow too.
* These issues never happen if input (compressed) data is correct.
* But they may happen if input data is invalid (error or intentional tampering).
* As a consequence, use these functions in trusted environments with trusted data **only**.
*/
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_partial() instead")
LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider migrating towards LZ4_decompress_safe_continue() instead. "
"Note that the contract will change (requires block's compressed size, instead of decompressed size)")
LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_partial_usingDict() instead")
LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);
/*! LZ4_resetStream() :
* An LZ4_stream_t structure must be initialized at least once.
* This is done with LZ4_initStream(), or LZ4_resetStream().
* Consider switching to LZ4_initStream(),
* invoking LZ4_resetStream() will trigger deprecation warnings in the future.
*/
LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
#endif /* LZ4_H_98237428734687 */
#if defined (__cplusplus)
}
#endif

View file

@ -71,11 +71,7 @@
* this is usually a loss, even with glibc's optimized memcpy
*/
#ifndef USE_MEMCPY
#ifdef _MSC_VER
# define USE_MEMCPY 0
#else
# define USE_MEMCPY 1
#endif
#define USE_MEMCPY 1
#endif
/*

View file

@ -650,7 +650,7 @@ void Command_CauseCfail_f(void)
players[consoleplayer].mo->y = 123311; //cfail cansuled kthxbye
players[consoleplayer].mo->z = 123311;
players[consoleplayer].score = 1337;
players[consoleplayer].rings = 1337;
players[consoleplayer].rings = (SINT8)1337;
players[consoleplayer].mo->destscale = 25;
P_SetThingPosition(players[consoleplayer].mo);
}

View file

@ -148,10 +148,8 @@ void M_ClearSecrets(void)
{
INT32 i;
for (i = 0; i < nummapheaders; ++i)
{
mapheaderinfo[i]->mapvisited = 0;
}
for (size_t j = 0; j < nummaprecords; j++)
maprecords[j]->visited = 0;
for (i = 0; i < MAXEMBLEMS; ++i)
emblemlocations[i].collected = false;
@ -195,9 +193,11 @@ UINT8 M_CheckCondition(condition_t *cn)
else if (cn->type == UC_MAPENCORE)
mvtype = MV_ENCORE;
return ((cn->requirement < nummapheaders)
&& (mapheaderinfo[cn->requirement])
&& ((mapheaderinfo[cn->requirement]->mapvisited & mvtype) == mvtype));
const char *mapname = G_BuildMapName(cn->requirement+1);
if (mapname == NULL)
return false;
maprecord_t *record = G_GetMapRecord(mapname);
return record ? (record->visited & mvtype) == mvtype : false;
}
case UC_MAPTIME: // Requires time on map <= x
return (G_GetBestTime(cn->extrainfo1) <= (unsigned)cn->requirement);
@ -360,7 +360,7 @@ UINT8 M_CheckLevelEmblems(void)
UINT8 res;
UINT8 somethingUnlocked = 0;
if (!K_EmblemsEnabled())
if (!G_EmblemsEnabled())
return false;
// Update Score, Time, Rings emblems
@ -534,12 +534,14 @@ UINT8 M_GotEnoughEmblems(INT32 number)
UINT8 M_GotLowEnoughTime(INT32 tictime)
{
I_Error("fixme M_GotLowEnoughTime");
/*
INT32 curtics = 0;
INT32 i;
for (i = 0; i < nummapheaders; ++i)
{
SINT8 preset = G_RecordPresetIndex();
recordpresetnum_e preset = G_RecordPresetIndex();
if (!mapheaderinfo[i] || (mapheaderinfo[i]->menuflags & LF2_NOTIMEATTACK))
continue;
@ -549,6 +551,7 @@ UINT8 M_GotLowEnoughTime(INT32 tictime)
return false;
}
return true;
*/
}
// ----------------

View file

@ -29,10 +29,6 @@
extern "C" {
#endif
#ifdef _MSC_VER
#pragma warning(disable : 4706)
#endif
struct mdllistitem_t
{
mdllistitem_t *next;

View file

@ -81,7 +81,7 @@ void M_LoadEmotes(UINT16 wadnum)
if (emote_name.size() > MAXEMOTENAME)
{
CONS_Alert(CONS_WARNING, "EMOTES: Emote name is too long, truncating. (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
emote_name = emote_name.substr(0, MAXEMOTENAME);
emote_name.resize(MAXEMOTENAME);
}
emote = &emotes[emote_name];
@ -128,7 +128,7 @@ void M_LoadEmotes(UINT16 wadnum)
if (framelumpname.size() > 8)
{
CONS_Alert(CONS_WARNING, "EMOTES: Frame %d name is too long. (file %s, line %d)", numframes, wadfiles[wadnum]->filename, linenum);
framelumpname = framelumpname.substr(0, 8);
framelumpname.resize(8);
}
std::strncpy(emote->frames[numframes], framelumpname.c_str(), framelumpname.size()+1);

Some files were not shown because too many files have changed in this diff Show more