Compare commits

...

290 commits

Author SHA1 Message Date
NepDisk
417a1714d1 Clear keepstuff when you land after respawn 2026-05-02 12:20:20 -04:00
NepDisk
5f1fb9a07b Whoops forgot to update this srb2back ref 2026-05-02 12:16:02 -04:00
NepDisk
ee3402e72a Screentextures toggle port from saturn 2026-05-02 12:02:53 -04:00
yamamama
b622ed1333 Toggle for bananadrag (trailslow) 2026-05-02 07:40:57 -04:00
NepDisk
01ce7b0221 Hardcoded Keep Stuff
Toggles allows certain item timers to maintain on death. Also handles setting up the state of said items again..
2026-05-02 03:48:08 -04:00
minenice55
c43b1228c5 Update d_main.cpp 2026-05-01 14:06:09 -04:00
yamamama
84f5592c76 Fix conversion bug with linedefs 403 and 404 in Kart maps
Should fix issues with certain maps, like Pandaemonium's cycle hazard
2026-05-01 01:39:14 -04:00
NepDisk
54a59937af Add shader stage for final screen texture draw 2026-04-30 22:09:22 -04:00
NepDisk
494eb9b5bd Fix encoremusic mapheader not falling back and do some clean up 2026-04-30 17:34:13 -04:00
NepDisk
3b48ca6c9c Encoremusic mapheader option 2026-04-30 16:56:25 -04:00
NepDisk
3604abdfcc Update this comment to be accurate 2026-04-30 15:58:46 -04:00
Alug
af7b843690 Fix models binding the lighttable texture to the the palette lookup texture
This fixes stuff becoming blue when models are on
2026-04-30 13:00:27 -04:00
NepDisk
799b1ec0d3 Revert "Expose water ripple as a uniform to allow for water ripple shaders"
This reverts commit 0c8d2efce0.

I had the idea of applying this flag to more surfaces in hardcode but not so sure thats a good idea anymore
2026-04-30 12:06:43 -04:00
NepDisk
35edca61db Revert "Fix Water_Ripple uniform"
This reverts commit ec53fd6511.
2026-04-30 12:06:43 -04:00
minenice55
3e2d14c42a separate out item equipping
also can be used from lua (untested)
2026-04-30 01:28:43 -04:00
minenice55
24faa9b8d7 Update d_main.cpp 2026-04-29 21:42:23 -04:00
NepDisk
41078f189f Cancel Heavy Airdrop with dash rings 2026-04-29 21:40:15 -04:00
NepDisk
ec53fd6511 Fix Water_Ripple uniform 2026-04-29 17:10:20 -04:00
NepDisk
0c8d2efce0 Expose water ripple as a uniform to allow for water ripple shaders 2026-04-29 16:36:04 -04:00
minenice55
d06ffdd9af Update d_main.cpp 2026-04-29 16:05:44 -04:00
minenice55
854edbe2ff always have *some* gravity to return the kart to neutral 2026-04-29 14:59:50 -04:00
NepDisk
d4ac123d19 Fix directional model lightning 2026-04-29 13:53:15 -04:00
NepDisk
abd4566fc0 Fix model lighting toggle 2026-04-29 13:31:33 -04:00
yamamama
3c2a60c8c5 cast from function call of type ‘lua_Number’ {aka ‘int’} to deez nuts 2026-04-29 05:40:12 -04:00
yamamama
d493dd9029 G_MapIsSafe
Generalized safety test for maps, in an attempt to curb G_GetNextMap
producing an I_Error due to an unchecked override
2026-04-29 05:36:27 -04:00
yamamama
aff2b6939a pnum 2026-04-29 05:06:23 -04:00
yamamama
daf9d3aaea d_netcmd cleanup
Clang-formatted GotNameAndColor, clang-formatted the voice command function, removed leftover (commented out) definitions
2026-04-29 04:57:57 -04:00
yamamama
416885a7c7 Voice system overhaul
Lots of things to bring it up to speed with the Lua dubs system.

To note:
- The `voice` cvars have been replaced with commands that are more robust
  in scope. These commands accept multiple arguments:
  - 1 arg (`voice` alone): Displays your current voice
  - 2 args (`voice <vox_name>`): Sets your voice to the provided voice,
    given it exists.
  - 3 args (`voice <skin_name> <vox_name>`): Sets your voice
    (given you're playing as the skin) and logs a preference.
  - `voice --help`: Explains everything above
- A preferenecs system now exists, which is loaded in on-boot and saved
  when quitting:
  - When you swap skins, the game checks an unordered map of preferences,
    indexed by skin name. If the skin you're changing to both exists in
    your preference list, and has your preferred voice loaded in the
    server, a notice will appear and you'll automatically use your
    preferred voice.
  - `listvoiceprefs` now exists, displaying voice preferences for the
    given splitscreen player. If no additional args are provided,
    it defaults to Player 1's first page of preferences.
  - `voicepref_auto` now exists for all splitscreen players to
    automatically assign preferences when you change your voice away
    from the default. The default voice is not logged by `voicepref_auto`;
    you have to do that manually. This cvar is toggled On by default.
- Voice settings and preferences are now saved to a `blanpreferences.cfg`
  file, which is unique for each local player; each local player has their
  own preference file.
2026-04-29 04:51:22 -04:00
yamamama
adf647b66e Global voice search
Ignores skins without multiple voices
2026-04-29 04:42:38 -04:00
yamamama
ce6215a768 Add the cvector library 2026-04-29 04:42:38 -04:00
minenice55
3eeca1c73e Update d_main.cpp 2026-04-29 02:15:56 -04:00
NepDisk
af439ac09f Softcode shaders 2026-04-28 20:53:41 -04:00
NepDisk
e6b1826d3e Port Saturn's Light dither shader for OGL 2026-04-28 14:26:47 -04:00
Alug
dc5f42cdaf Fix broken palette render switching 2026-04-28 13:04:03 -04:00
NepDisk
0c22fb24d2 Fix FlashPals not working in palette rendering 2026-04-28 12:05:30 -04:00
NepDisk
52d31ee6b5 Add support for building with JEMALLOC 2026-04-28 11:41:36 -04:00
NepDisk
ea6105a007 Kill dummy backend stuff 2026-04-28 11:25:57 -04:00
NepDisk
c2ef7949f0 More clean up 2026-04-28 11:20:27 -04:00
NepDisk
43c9f1223e Kill Old ALAMLIGHTING code 2026-04-28 11:14:34 -04:00
NepDisk
62764b8f48 Split portal stuff into its own file 2026-04-28 11:02:37 -04:00
minenice55
2164aa71b4 disallow loading mismatching map patches
should 0 hashes be always allowed?
2026-04-28 10:53:45 -04:00
minenice55
ea8e1e2dbf bumpy road particle effect
I should really do that thing I wanted to do soon
2026-04-28 00:01:10 -04:00
minenice55
7b1df12ed0 experimental attraction shield EMP attack option
AoE attack can put opponent items on a cooldown
2026-04-27 22:45:28 -04:00
minenice55
9d7d74467f only passively drain flame shield while in first place 2026-04-27 21:46:48 -04:00
minenice55
3c68db5cba make inflated bubble shield a tiny bit more generous defensively 2026-04-27 21:42:37 -04:00
minenice55
20c6981d61 let bubble shield tank damage for a bit after being spawned 2026-04-27 21:28:03 -04:00
NepDisk
0867eff8b0 Use case insensitive string hashing and compare for cvar hashtable + compatnetid support
Based on this commit 27f22e4b5b
2026-04-27 18:24:43 -04:00
Alug
9d2b6eda55 Speed up CV_Findvar & CV_FindNetVar with hashtable 2026-04-27 17:33:17 -04:00
Alug
d2c9a3e1b6 BLUA: simplify lua number hash 2026-04-27 17:17:06 -04:00
Alug
e59aad944c d_cliserv: check for splitscreen nodes first in clientcmd handler
so we dont always have to check a bunch of things that most of the time wont apply anyways
2026-04-27 17:14:00 -04:00
Alug
4a820bcaf6 check I_GetNodeAddress is set before use
this might´ve not been init yet at that point
2026-04-27 17:12:13 -04:00
Alug
a54b259a3f attempt to fix a plethora of buffer overflows when trying to connect to a server that does not exist
ex: if you typo´d the serveraddress
this really aint pretty but idk how to make things not turn into limbo hell otherwise
2026-04-27 17:11:52 -04:00
Alug
3383778c88 prevent buffer underflow within holepunching 2026-04-27 17:09:38 -04:00
NepDisk
865df4ed26 Only reverse with wrong way on the ground 2026-04-27 16:18:27 -04:00
NepDisk
4669f11385 Let bots block items with thundershield 2026-04-27 15:58:30 -04:00
NepDisk
0578050179 Allow regular damage after finishing
BLOWS UP!?!?!??!?!??!?!?!??!?!?!?!??!?!
2026-04-27 15:42:14 -04:00
minenice55
3fbc6dd0df use a nicer physical model for kart tilt gravity
also can remove the momentum cap with this
2026-04-27 14:34:44 -04:00
minenice55
5b714e9ccf don't skip spawning driftsparks if player is airborne
also this effect should probably be applied to other particles that come from the tyres
2026-04-27 01:21:14 -04:00
NepDisk
9596a00e74 Update masterserver to proper address
We have a domain name now :D
2026-04-26 20:05:43 -04:00
minenice55
73d68691cf cap download size to total size in the connection UI 2026-04-26 19:36:07 -04:00
minenice55
4d7d931c73 fix freelook bind not working online 2026-04-26 18:32:09 -04:00
minenice55
28fcee9214 why wasn't this already done 2026-04-26 16:32:28 -04:00
minenice55
35b8ddcf77 a bit more 2026-04-26 16:17:45 -04:00
minenice55
4e47388191 Merge branch 'next' of https://codeberg.org/NepDisk/blankart into next 2026-04-26 16:13:22 -04:00
minenice55
c76b147920 we can do this anyways 2026-04-26 16:13:10 -04:00
yamamama
a1ba38b882 Truncate shortname checks so names past the 8-character limit still get picked up
Missed a spot with the WAD search optimizations, it seems...
2026-04-26 07:46:14 -04:00
yamamama
8c698c61d4 NOAPPENDBUILD
An option to toggle off the build type suffix, mainly for more public-facing releases (try saying blankart_relwithdebinfo out loud!)
2026-04-26 07:46:14 -04:00
minenice55
695d1118bc fix weird bug with 0 speedboost boost powers (specifically for recovery spin)
accel and handling boost would lock up if they're changed via K_DoBoost while keeping speedboost at 0
2026-04-26 01:06:58 -04:00
minenice55
f99d9f160d Merge branch 'next' of https://codeberg.org/NepDisk/blankart into next 2026-04-25 20:52:30 -04:00
minenice55
cc5c23aa49 hope this fixes the seeking reticule thing properly 2026-04-25 20:52:17 -04:00
NepDisk
4141de4414 Upgrade masterserver cvar to our selfhosted one 2026-04-25 19:55:11 -04:00
NepDisk
1f9701c898 Revert "Always accept tics received from the server" for testing
This reverts commit 699153fd52.
2026-04-25 14:36:42 -04:00
minenice55
e28519f2d1 make disabling COMMITVERSION define actually compile 2026-04-25 14:14:05 -04:00
minenice55
992677ad42 some debug prints 2026-04-25 14:03:23 -04:00
minenice55
477e2d70e1 Merge branch 'next' of https://codeberg.org/NepDisk/blankart into next 2026-04-25 12:53:00 -04:00
minenice55
d2b83696d4 use CV_Get again 2026-04-25 12:51:44 -04:00
yamamama
5c33d3c0c7 Experiment: Add a suffix based on the build type 2026-04-25 06:44:55 -04:00
minenice55
c20ee615f9 places I didn't catch jawz reticule unsetting 2026-04-25 01:21:42 -04:00
minenice55
bc26ad20c1 tune tilt controls to not feel as touchy
needed after fixing that bug that made em feel stiffer than they were supposed to since the old value was to counteract that
2026-04-25 01:18:11 -04:00
minenice55
cff2882db6 not float 2026-04-25 00:11:01 -04:00
minenice55
7e2f8963ec TIL CV_Guard blocks using CV_Get 2026-04-25 00:09:59 -04:00
minenice55
76e7a8c66e only play bumpy road sound if it's yourself
shit was *loud* when many players are around
2026-04-25 00:05:22 -04:00
minenice55
1462e90631 forgot to name this 2026-04-25 00:02:51 -04:00
minenice55
06a90d9809 configurable attraction shield player damage
was told we want this
2026-04-24 23:58:28 -04:00
Gustaf Alhäll
699153fd52 Always accept tics received from the server 2026-04-24 20:24:00 -04:00
NepDisk
b0f8492c94 Revert boundedfragmentsize 2026-04-24 11:43:20 -04:00
yamamama
fb7271bc92 Comment this out
This messes with softcode tumblegems
2026-04-24 05:00:30 -04:00
yamamama
72931e7713 Make balloons use UDMF arg 0, MTF_AMBUSH not being set turns on respawning 2026-04-24 02:17:16 -04:00
yamamama
677075bfbf Add a failsafe for a NULL leader 2026-04-24 02:16:07 -04:00
minenice55
82078c1421 file 2026-04-24 02:11:15 -04:00
minenice55
7a4bcf763e Merge branch 'next' of https://codeberg.org/NepDisk/blankart into next 2026-04-24 02:07:04 -04:00
minenice55
887f696dfb looks like this is closest to srb2classic so
make file downloading closer to srb2classic
WILL NEED TESTING
2026-04-24 02:06:39 -04:00
NepDisk
6fc3a62f09 Mark these as NULL on init
These can cause garbage read in some rare cases
2026-04-24 01:22:35 -04:00
minenice55
e51325f67d new assets hash 2026-04-23 23:37:44 -04:00
yamamama
fd6a3b72b9 Fix comment nitpick, update credits comment 2026-04-23 21:22:07 -04:00
toaster
5b74a50f9b Fix writing followers into demos
Does not require a demoversion bump, was a plain mistake in write condition. Previously dependent on whether the memory of `player->follower` - a mobj_t reference - was nonzero, instead of the actual followerskin ID. We essentially got REALLY lucky that TA properly saved 'em currently so we don't have to do a ton of hex editing just to make them visible again
2026-04-23 21:17:08 -04:00
minenice55
c2fadb25ea re-tune null drift now that gravity is higher 2026-04-23 18:50:35 -04:00
NepDisk
71a2697fae Add director option to multiplayer replays 2026-04-23 18:39:22 -04:00
minenice55
b16b6de345 looks alot better now
and more damping to reduce bounciness
2026-04-23 14:19:07 -04:00
minenice55
c874bea990 fix this being exaggerated
real solution would be to change the sprite's pivot point in real time somehow
2026-04-23 13:08:53 -04:00
NepDisk
e3664a1cca Add compat flag to disable compat sprite rotation
This is to accmodate skins that place skins in the range of drift rnage unrotated ie simple animal skins such as pepsiman or ShadowSkates
2026-04-23 13:00:10 -04:00
minenice55
b9553e4c9e redo kart tilt offsetting code
also caught some more issues with sprite offsets, should be perfect now(?)
2026-04-23 12:59:06 -04:00
yamamama
532826f61d Fix spritexoffset not playing nice with affines 2026-04-23 08:32:14 -04:00
minenice55
da10eb5a75 more fixes for kart tilt
spritexoffset seems to be broken? should investigate
2026-04-23 01:52:47 -04:00
minenice55
627ed318ed fix respawn angle being wrong 2026-04-22 18:09:46 -04:00
NepDisk
47089d2c23 Let args3 on dash rings force player angle 2026-04-22 05:07:42 -04:00
NepDisk
8ebac27f83 Expose NOSCALEGRAVITY to Lua 2026-04-21 15:57:54 -04:00
minenice55
8a8466bae8 fix grow on dashrings for real 2026-04-21 15:51:09 -04:00
minenice55
8a91fdfa43 fix mobjscale issues with bumpy road effect
and tune it to shake faster
2026-04-21 13:17:30 -04:00
NepDisk
7b3c198aca Expose bumpyroad visual function to Lua 2026-04-21 03:08:20 -04:00
NepDisk
a1aeb422d8 Allow bumpyroad with gameplay terrain off since its just an effect 2026-04-21 02:16:01 -04:00
NepDisk
6890883ef6 Allow bumpy road visual to be applied as a SSF as well 2026-04-21 01:34:57 -04:00
NepDisk
80b508aa19 Extend dash rings to allow more customization 2026-04-21 01:11:30 -04:00
minenice55
7355e69eed disable the debug prints 2026-04-21 00:46:00 -04:00
minenice55
412e09c098 fix mobjscale related issues with kart tilt
also make RR bumpy terrain tilt the kart here
2026-04-21 00:45:30 -04:00
minenice55
2b5af7d302 Update d_main.cpp 2026-04-20 17:13:11 -04:00
minenice55
73768b0fc4 remove the special cases related to the PAUSE key
don't get why these exist
2026-04-19 21:41:49 -04:00
minenice55
f2a3b38f1e Merge pull request '[Enhancement] Generalize Null Drift Tilt' (#236) from karttilt into next
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/236
2026-04-20 01:22:05 +02:00
minenice55
164aa5e1cc Merge branch 'next' into karttilt 2026-04-19 19:15:04 -04:00
minenice55
af527247e3 angular dampening, fix issues with null drift tilt
also fix the sprite offset not working
2026-04-19 19:07:05 -04:00
NepDisk
600d1363b2 Revert "Try to make sure consoleplayer is set up before game ticks run"
This reverts commit b6804b1ded.
2026-04-19 12:22:27 -04:00
yamamama
b6804b1ded Try to make sure consoleplayer is set up before game ticks run 2026-04-19 09:40:25 -04:00
yamamama
b876e585b1 Don't optimize out getstack, please! 2026-04-19 09:40:25 -04:00
minenice55
57c80633d1 rewrite nulldrifttilt into a more general system
karttilt can now be used by other systems
karttilt now also respects physics more
2026-04-19 02:04:32 -04:00
NepDisk
0eea55d4b7 Expose more mapheader stuff to Lua 2026-04-17 11:51:23 -04:00
NepDisk
4b50dd0ead we are hitting a hard limit so do this for now.
Packet fragmenting is bad since many firewalls consider it bad traffic, we are going to have to rework stuff around this fact later.
2026-04-16 15:57:08 -04:00
NepDisk
c581e5c5e1 Clamp softwarepacketlength to work around issues that have arozen on some networks 2026-04-16 10:29:32 -04:00
Eidolon
29348dc2c1 gl: Fix sky dome VBO leak 2026-04-15 14:02:48 -04:00
NepDisk
00115f9b11 Merge pull request 'Add some missing snap flags' (#229) from indev/blankart:add-snap-flags into next
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/229
2026-04-14 23:36:42 +02:00
NepDisk
8e0b52c1fb Lower minimum vote time
I need this for smoketesting something but this is good QOL either way
2026-04-13 17:50:10 -04:00
NepDisk
821afa350c Add automation state for level starts
Could be useful for map start changes
2026-04-13 17:26:17 -04:00
GenericHeroGuy
d4fae7e807 Fix asan error when pressing shift and arrow key
Also fix addons menu ignoring shift when capslock is on!
Also also fix capslock+rshift still typing uppercase letters!
2026-04-13 18:47:12 +02:00
minenice55
8e4fa6fbde make gravityscale be base when carried by dashring
not entirely sure if this works
2026-04-13 10:04:44 -04:00
NepDisk
c85c020ba4 Fix bad copypaste
Wow I need to sleep more lmao
2026-04-12 21:46:53 -04:00
NepDisk
bb962c3d5a Validate next waypoint in quick exit path 2026-04-12 20:51:29 -04:00
minenice55
198f994f53 make waypoint respawn search more than the immediate neighbours
this is a graph structure
2026-04-12 20:03:26 -04:00
NepDisk
4ffc163c0d Rework ring sounds and ring burn visual change
caching only play player side now
ringburn adds an extra sound to ring usage
ringburn makes rings turn white
2026-04-12 16:49:06 -04:00
NepDisk
25e5ac73e4 Expose ringpower stuff to Lua 2026-04-12 12:30:24 -04:00
NepDisk
e49684044f Make ringpower stuff more modular
This will be super helpful to prevent duped code when I start on visuals
2026-04-12 12:20:08 -04:00
NepDisk
284a86c7b9 Nerf ring chains by improving ring burnout performance
Finally its halfed then smoothed down rather then just dropping to 2 then 1.

Makes Ring Chains still exist but less broken since you can't chain as large of sections anymore.

I need to add better visuals and sound design for this since its much more noticable now.
2026-04-12 12:00:48 -04:00
yamamama
00f5eca7ae Yama's Kludgy Sprite Two-Pass
Can't just force compatmode to check only 8 rotations because Neptune exists and has 16-angle rotations
2026-04-12 05:34:45 -04:00
NepDisk
83fdcd00c0 Fix Lua being able to crash the game by removing an Mobj with MobjSpawn 2026-04-11 12:28:14 -04:00
Eidolon
9f8d2d9296 Enable dedi gpu on laptops by default 2026-04-10 07:53:07 -04:00
NepDisk
4f8993668b Clean up thirdparty licenses 2026-04-10 07:46:07 -04:00
NepDisk
b24cbafafe Kill cmake assets packing 2026-04-10 07:46:07 -04:00
NepDisk
e883c6968e Update Lua compat logic for Damage 2026-04-09 12:19:26 -04:00
Alug
95a018c82c set MAXVIDWIDTH and MAXVIDHEIGHT to 8192
should accomidate absolutely everything
2026-04-09 11:42:29 -04:00
yamamama
52d1c4313b Compatmode: load maps in PK3s outside of a designated folder
Fixes #189
2026-04-08 16:52:56 -04:00
yamamama
4a735d7d66 Make demosaves more robust (fixes #167) 2026-04-06 19:19:49 -04:00
yamamama
8b777cb251 P_SpawnSpecialsThatRequireObjects Saturn parity
Fixes the netgame midjoin issue described in #202
2026-04-06 17:31:18 -04:00
minenice55
6aa091d019 player death too 2026-04-06 16:05:14 -04:00
minenice55
32fbacd51f hyuu steal too 2026-04-06 15:51:45 -04:00
minenice55
af92121c9d more places to disable seeking reticule 2026-04-06 15:50:46 -04:00
minenice55
925a56a48c re-tune attraction shield a bit
weaken steer assist, go faster
2026-04-06 14:45:42 -04:00
minenice55
a6efdf7e2b fix the weird perf drop when drawing stat bars
this is stupid
2026-04-06 14:45:18 -04:00
GenericHeroGuy
2eaa0cd39c Post-roundqueue updates
Was just going to fix some bugs, but you know me...
* `map +` works again (now yields the calculated nextmap, ignoring advancemap)
* `showmap` prints the correct map title when previewing
* Roundqueue no longer trips ASan (aww, just one byte short!)
* Added NEXTMAP_RANDOM so the intermission drawer can now be smart, and not
  just go off of cv_advancemap but actually show where you're going!
2026-04-06 01:46:15 +02:00
minenice55
0b7fbbbb62 proper setter for seeking flag
will need more changes to fix that one bug
2026-04-05 18:59:47 -04:00
minenice55
782f3b6184 Merge pull request 'Clean up Controller Sensors code, Gyro calibration, Gyro cameras' (#234) from gyrostuff into next
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/234
2026-04-05 22:50:22 +02:00
minenice55
75c6c21f91 Merge branch 'next' into gyrostuff 2026-04-05 22:49:12 +02:00
minenice55
84cfa132c6 Update d_main.cpp 2026-04-05 16:46:25 -04:00
minenice55
41e1899809 only calibrate controllers while in controls setup
calibration will need its own screen eventually
2026-04-05 16:38:35 -04:00
GenericHeroGuy
bc465faada And now for my own personal take on COM_CEcho_f
Actually works, is properly centered, allows 1023 characters instead of 1022!
2026-04-05 21:05:26 +02:00
Gustaf Alhäll
3d43d01ca6 Fix buffer overflow when linedef type 415 executes 2026-04-05 20:21:23 +02:00
GenericHeroGuy
dce0dca850 Restore binary conversion for linedef special 415 2026-04-05 20:18:00 +02:00
toaster
e30b0c273d G_Responder: Call HU_Responder in Playing(), instead of a whitelisted set of gamestates
Neatly sidesteps a class of bugs where whenever we added a new gamestate accessible in netplay, chat was console-only.
2026-04-05 17:47:58 +02:00
GenericHeroGuy
7ebda658f6 Fix kart gibs bouncing off death pit FOFs 2026-04-05 16:51:12 +02:00
yamamama
500790ef64 Make S-Monitors pass through players using Alt-Shrink 2026-04-04 22:31:58 -04:00
minenice55
03554c03ed freelook bind, fix issues with spectator gyro 2026-04-04 19:13:50 -04:00
NepDisk
c3f4f0e096 Fix some damagetypes not giving flashtics 2026-04-04 16:26:15 -04:00
minenice55
4b5658d487 greatly improve responsiveness of tilt steering
is more correct to the GyroWiki article now
2026-04-02 16:48:05 -04:00
minenice55
493e6e96fa player space gyro and split off from cmd turning 2026-04-02 13:39:08 -04:00
minenice55
9730882fe4 gyro calibration, spectator aiming using gyro
also moves all of the motion sensor stuff to g_input.c
2026-04-02 01:32:10 -04:00
minenice55
6ee6291fd8 on est prêts 2026-03-31 23:17:40 -04:00
NepDisk
c5695bef75 Dummy out stricter RRID checks for now.... 2026-03-31 21:55:58 -04:00
minenice55
5c36309cab don't turn spectator camera with tilt steer 2026-03-31 20:45:32 -04:00
minenice55
4c9166e297 tighten this now that we check stillness 2026-03-31 20:30:52 -04:00
minenice55
858a1979b6 comment this 2026-03-31 20:22:11 -04:00
minenice55
74bf43d7b0 Merge branch 'next' of https://codeberg.org/NepDisk/blankart into next 2026-03-31 20:18:55 -04:00
minenice55
5fbb364575 some tuning to tilt steering
eventually should add calibration and better instant correction when the controller is held still
2026-03-31 20:18:42 -04:00
yamamama
315d2a9d6c Update credits 2026-03-31 19:21:40 -04:00
NepDisk
e802b1ef07 Also apply this to EAXREVERB 2026-03-31 18:35:59 -04:00
NepDisk
bdd64944dc Apply the same fix to shields that apply rings 2026-03-31 18:29:41 -04:00
NepDisk
316b4d388a Yes I english how can you tell 2026-03-31 18:18:13 -04:00
NepDisk
270e0ad2a6 Properly do SPB rings check 2026-03-31 18:17:22 -04:00
minenice55
8eafc426b9 Update m_menu.c 2026-03-31 17:16:03 -04:00
minenice55
b33f90b6ea get this to compile on windows clang with asan on 2026-03-31 16:36:47 -04:00
GenericHeroGuy
9abfea075b asama 2026-03-31 20:39:05 +02:00
NepDisk
8f9faad7fd Multiplayer in GP 2026-03-31 13:16:00 -04:00
NepDisk
4a00cce049 Still allow random map to work with the comment 2026-03-31 12:24:21 -04:00
NepDisk
080ace7b91 Fix waypoint related crashes in battle mode 2026-03-31 11:55:27 -04:00
toaster
02ba3e2557 Rework the map command suite a little
The following funcs are now a suite with almost-identical argument lists.

- `map` is for immediately going to a map
    - Add `-random`/`-r`
- `queuemap` is for interacting with the live Round Queue
    - Add `-random`/`-r`
        - Performed server-side
    - `-clear` and `-show` now accept partial params `-c` and `-s`
    - Fix minor error with 0-argument print's text
- `showmap` is for printing information
    - Add arbitrary map name/ID input
        - `showmap robo` prints the course `map robo` would resolve to
    - Add `-gametype`/`-gt`/`-g`
        - For compatibility testing
    - Add `-random`/`-r`
        - Combine with `-gametype` for extra guarantees
- `randommap` was deprecated
    - Will only print replacement instructions of `map -random`, and nothing else
2026-03-31 11:50:33 -04:00
NepDisk
dd98ee93e2 Merge pull request 'RRIDs' (#233) from rridport into next
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/233
2026-03-31 16:00:11 +02:00
NepDisk
85f6ea3b53 Put a reminder here 2026-03-31 09:56:14 -04:00
NepDisk
829448cd28 Comment as reminder for future attempting 2026-03-31 09:54:09 -04:00
NepDisk
ac80a8d8d1 Rename this cvar 2026-03-31 09:27:03 -04:00
minenice55
a9d5799589 tweak attraction shield performance
tackle is slower but handles better
tackle is made weaker when in first
fixed issue with dropping items not clearing seeking flag
2026-03-30 22:10:54 -04:00
NepDisk
6a44fc25bb Rename RRID as suggested 2026-03-30 21:35:50 -04:00
NepDisk
88a8600693 Merge branch 'next' into rridport 2026-03-30 21:34:58 -04:00
AJ Martinez
991bf3a4c9 Oops, servernode isn't a player index 2026-03-30 21:31:43 -04:00
AJ Martinez
c47c32dcc6 Fix chat messages being krangled on dedicated servers 2026-03-30 21:29:29 -04:00
NepDisk
d602e8b590 Merge branch 'next' into rridport 2026-03-30 20:10:58 -04:00
NepDisk
096e91f23a Fix Attraction shield being broken 2026-03-30 20:10:13 -04:00
NepDisk
e82de32832 Merge branch 'next' into rridport 2026-03-30 19:58:46 -04:00
minenice55
ceebaba534 clean up like bubble 2026-03-30 19:55:45 -04:00
minenice55
abf9d3ff39 don't steal bubble and attraction shield when using 2026-03-30 19:51:43 -04:00
NepDisk
de9197e73f Merge branch 'next' into rridport 2026-03-30 19:42:49 -04:00
NepDisk
dd402c43ee Make PT_SERVERCHALLENGE get sent in reliable mode 2026-03-30 19:36:21 -04:00
minenice55
5bce8b2a2e c'est maintenant jaune 2026-03-30 18:52:02 -04:00
NepDisk
12a2e13a58 Merge branch 'next' into rridport 2026-03-30 18:02:00 -04:00
NepDisk
78087afecd Clean up Roundqueue archival 2026-03-30 16:50:48 -04:00
minenice55
bdfa63161f proper attraction shield 2026-03-30 16:18:23 -04:00
NepDisk
f89e01c936 Use P_SyncMem for player pubkey 2026-03-30 16:01:44 -04:00
NepDisk
0ab3ba7f4a Merge branch 'next' into rridport 2026-03-30 15:54:00 -04:00
NepDisk
08efd4321c Fix map music not playing on Join 2026-03-30 15:15:57 -04:00
NepDisk
a291f8d9b4 Show connection notices in console as well 2026-03-30 13:56:21 -04:00
NepDisk
d4753b3d1e Mention the 32P size 2026-03-30 11:50:35 -04:00
NepDisk
6299cff152 Make pubkey validation on by default
People who don't want this can just turn it off.
2026-03-30 10:38:39 -04:00
NepDisk
24b6a7faa2 Not anymore! 2026-03-30 10:01:45 -04:00
NepDisk
989b6b6f53 Notate packet byte sizes
These should be correct unlike the nonsense in baseline SRB2
2026-03-30 09:56:58 -04:00
NepDisk
e9361d5f33 Lower max packet size, remove duplicated server_name, server_contact and server_desc fields 2026-03-30 09:36:43 -04:00
NepDisk
13a82ca079 Port pubkey validation from RR and make it optional
For more competitve servers they can enable this to prevent unfair play while letting casual servers still have flexibility
2026-03-29 21:32:34 -04:00
NepDisk
a81aef27e2 Move PT_ cases into their own methods 2026-03-29 21:04:44 -04:00
NepDisk
fcc1b10ada On second thought, lets put them in a seperate folder with a readme 2026-03-29 19:15:49 -04:00
NepDisk
19d700b386 Write RRID keys outside gamefolder if possible 2026-03-29 18:04:51 -04:00
NepDisk
a90f2ea2d3 Rename our Public and private key globals 2026-03-29 16:50:31 -04:00
AJ Martinez
e79ba678c4 More lax + more helpful RRID timestamp errors 2026-03-29 16:39:53 -04:00
NepDisk
6f7c466459 Use defines for lengths 2026-03-29 16:33:24 -04:00
SteelT
7f134d27ce Fix players RRID getting wiped on join
Fixes #1075
2026-03-29 16:33:06 -04:00
NepDisk
71dd15ab6b Remove debug print 2026-03-29 16:30:40 -04:00
NepDisk
c44ae94137 Add kick msg for SIGFAIL 2026-03-29 16:27:33 -04:00
NepDisk
0f5d93873b RRID credits 2026-03-29 16:22:34 -04:00
NepDisk
0857a1d8a2 RRID port part 3
last commit was 535fc1787589cc8135470cef0e09005cf97e6cab
2026-03-29 16:19:01 -04:00
NepDisk
5bafcbf3f8 RRID port part 2
last commit was 78b30802
2026-03-29 15:32:51 -04:00
NepDisk
163d4a0e72 Actually on second thought, I do want splitscreen 2026-03-29 13:59:39 -04:00
NepDisk
d6eab04a7a RRID port part 1
last commit of this set is 2925843e
2026-03-29 13:09:06 -04:00
GenericHeroGuy
ca51695870 dt7 stuff
also fixed model loading on my machine
2026-03-29 14:44:26 +02:00
NepDisk
4208ddfd5d Use old tab ranking for GP
The info on the side is not very helpful in GP. Maybe we can go back to using the new one if we decide to shove some GP related info in there?
2026-03-29 08:13:24 -04:00
NepDisk
5cf04f9df4 Single player menu should only occur in Grandprix and add lives logic 2026-03-29 08:06:19 -04:00
NepDisk
f2a0789189 Fix bots not spectating in itembreaker
I hate this stupid fucking multiplayer variable
2026-03-29 07:16:10 -04:00
NepDisk
11c63396cd Reload minimap info if it could get replaced 2026-03-29 06:49:34 -04:00
NepDisk
d8142d7bd6 Revert "Fix MR_SetupMonitorToggles using string literals"
This reverts commit e802edb628.
2026-03-29 06:33:06 -04:00
toaster
8ce9681bd8 Got_TeamChange: Successfully remove PF_WANTSTOJOIN if you use changeteam spectator to cancel your join 2026-03-29 06:22:45 -04:00
NepDisk
8273c91adf Port various RR related spectating fixes 2026-03-29 06:04:52 -04:00
Alug
e802edb628 Fix MR_SetupMonitorToggles using string literals 2026-03-29 05:47:11 -04:00
minenice55
48fd545e40 fix tilt steering dot being flipped in mirror mode 2026-03-28 22:21:41 -04:00
NepDisk
770ae2e9c2 Fix bots instantly eating multi-sneakers 2026-03-28 18:36:13 -04:00
NepDisk
c2746b8954 Merge pull request 'Port roundqueue, PT_SAY, vote buffer rewrite and various other internal map improvements from RR' (#232) from roundqueue into next
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/232
2026-03-28 07:31:01 +01:00
NepDisk
070feef061 Merge branch 'master' into next 2026-03-28 02:25:52 -04:00
NepDisk
86f6b7851d Merge pull request 'Make lookback instant locally' (#230) from indev/blankart:local-lookback into master
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/230
2026-03-28 07:20:05 +01:00
NepDisk
dcdbd049e7 Split votescreen stuff into its own file 2026-03-28 02:18:11 -04:00
NepDisk
dad79270d1 Split vote finalize into its own func 2026-03-28 01:52:58 -04:00
NepDisk
5ae78d1d7e Update credits 2026-03-28 01:28:17 -04:00
JugadorXEI
040cb9d298 Clamp justPlayed to the upper limit (prevents SOC Hidden level weirdness) 2026-03-28 01:18:10 -04:00
JugadorXEI
1723ba407b Add guard so justPlayed does not get set/decrease for maps in player-less dedicated servers
Works in tandem with the previous commits so that justPlayed stays at 0 for all levels until someone joins.
2026-03-28 01:17:02 -04:00
JugadorXEI
b08f2ca388 Clear justPlayed and anger records from map headers when all players leave a dedicated server 2026-03-28 01:16:53 -04:00
JugadorXEI
6892abcb8c Fix off-by-one error when setting justPlayed on a map header (plus debug code)
This is because although the map value per gametype is decreased by 4 (VOTE_NUM_LEVELS) to account for 4 vote selections, it doesn't account for the prevmap being one of those four levels, so we decrease by one to account for that also.
2026-03-28 01:15:51 -04:00
Sally Coolatta
1f521d21da Rewrite random map buffer
Each map now just has a countdown for when they'll reappear (stored in mapheader), which gets decremented each time a new map is played. This means it's now compatible across gametype switches, is a lot less complex, and is easy to retrieve the value for a specific map without needing to iterate constantly.

Lots of the old unused code surrounding this function was also removed. Lastly, added a PARANOIA check for callAgainSoon being mishandled.

NEP: I've added back map hell and gametype switching here since it was not in RR
2026-03-28 01:09:00 -04:00
NepDisk
31d8e671cb Comment out cases of "comparison is always true" 2026-03-27 23:54:58 -04:00
NepDisk
3014d6b46b Use NEXTMAP_INVALID instead of -1 2026-03-27 23:44:52 -04:00
NepDisk
ec2d406222 Fix titlecard round count 2026-03-27 23:42:14 -04:00
NepDisk
c1bf171a3a Raise roundqueue maximum to 20
most events do 12-20 maps so this makes sense.
2026-03-27 23:40:31 -04:00
toaster
5557aa312d Add roundqueue -show
Reveals the next Round in the queue via server shout message.
Can be used manually, or with automate commands for tournament rulesets that permit foreknowledge of the next Round without requiring the host to work off memory or document.
2026-03-27 23:39:36 -04:00
toaster
ec5b8fcf04 XD_REQMAPQUEUE --> PT_REQMAPQUEUE
It was technically possible for custom clients to spoil future rounds of a tournament queued while they are connected to a server.
Making it a PT direct packet to the servernode both solves this problem AND reduces irrelevant NetXCmd traffic for clients.
2026-03-27 23:37:08 -04:00
Skirlez
4c5ed80162 don't allocate 2 extra bytes in DoSayPacketFromCommand 2026-03-27 23:29:24 -04:00
NepDisk
06245c7ecc Update credits 2026-03-27 23:27:55 -04:00
Skirlez
4b03990167 Fix a crash on some setups when using the say or csay commands 2026-03-27 23:25:45 -04:00
JugadorXEI
0e53d5dfd7 Lua: Hook PlayerMsg to code, remove vestigial mute variable from it¨ 2026-03-27 23:19:51 -04:00
NepDisk
90026bc683 Port PT_SAY from RR
Based on the various commits by tyron
2026-03-27 23:18:00 -04:00
NepDisk
2166bfa7c2 Fix random icon not displaying 2026-03-27 22:22:00 -04:00
NepDisk
fddcf9c2af Merge branch 'next' into roundqueue 2026-03-27 22:16:42 -04:00
NepDisk
857af5beec Fix EFX crashing with mines 2026-03-27 22:14:55 -04:00
NepDisk
f7f1a10a7b Cast this 2026-03-27 21:17:12 -04:00
NepDisk
50bbd3c561 Merge branch 'next' into roundqueue 2026-03-27 21:01:47 -04:00
NepDisk
5d38c24f41 Fix copy paste mistake in file header 2026-03-27 21:00:59 -04:00
NepDisk
045e6170c1 Create and use mapnum enumtype 2026-03-27 13:37:36 -04:00
NepDisk
a2f1b430a7 Make mapbuffer use UINT16 2026-03-26 16:51:14 -04:00
NepDisk
a6006e0980 Go to vote instead of returning to menu 2026-03-26 16:45:11 -04:00
NepDisk
3ebe925669 `Raise extbuffer 2026-03-26 16:42:50 -04:00
NepDisk
4bde2e7452 Fix some missed INT16 cases and update G_GetNextMap 2026-03-26 15:46:41 -04:00
NepDisk
820db79d18 Raise most map numbers to UINT16
I've probably missed a few...
2026-03-26 14:55:20 -04:00
toaster
cf2eb1dc70 Promote gametypes in XD_MAP, XD_MAPQUEUE and XD_REQMAPQUEUE to UINT16
Since new-voting repermitted custom gametypes to go beyond the bounds of a UINT8, here's some extra anti-footgun protection.
2026-03-25 23:38:12 -04:00
toaster
c877362772 queuemap: Add -clear parameter
- Can be used to clear all entries in the round queue
- Stores the special state in the gametype field
- Returns a message if the queue is already empty
2026-03-25 23:32:57 -04:00
toaster
1d4e3b50b0 Handle_MapQueueSend
All XD_MAPQUEUE/XD_REQMAPQUEUE packets are now handled in one function, to guarantee requests are made consistently.
2026-03-25 23:20:19 -04:00
toaster
b30dd43ec6 Got_MapQueuecmd: Add a success message for adding a map to the round queue (visible only to admins) 2026-03-25 23:05:21 -04:00
toaster
9a1212f32e Command_Map_f, Command_QueueMap_f: Prevent memory leak on cheat-limited early-return 2026-03-25 23:02:28 -04:00
toaster
04697e94f3 Console command queuemap
- Full valid format: queuemap [name/num] -gametype [name] -encore -force
- Server is fully authoriative about the order of maps in the round-queue
    - Server sends XD_MAPQUEUE (which contains gametype, encore, and ordering)
    - Admin clients have to send XD_REQMAPQUEUE (which contains gametype, encore, and mapnum)
        - Servers spit out a processed XD_MAPQUEUE on reciept
    - Done this way just in case an XD_MAPQUEUE is not recieved and has to be resent, guarantees ordering
- Will create a UI for this post-launch, this is primarily for testing but may be useful for user-ran tournaments
2026-03-25 23:01:42 -04:00
NepDisk
24373da780 Port basics of roundqueue 2026-03-25 22:52:54 -04:00
Indev
9f31eeaa72 Make lookback instant locally, also add toggle to do same in replays 2026-03-25 01:55:54 +03:00
Indev
338667870a Add snap to top flag for pause gfx 2026-03-22 00:07:10 +03:00
Indev
e0208291e4 Add some missing snap flags 2026-03-21 23:54:12 +03:00
169 changed files with 13222 additions and 8354 deletions

View file

@ -29,32 +29,6 @@ if(APPLE)
enable_language(OBJC)
endif()
##### PACKAGE CONFIGURATION #####
set(SRB2_CPACK_GENERATOR "" CACHE STRING "Generator to use for making a package. E.g., ZIP, TGZ, DragNDrop (OSX only). Leave blank for default generator.")
if("${SRB2_CPACK_GENERATOR}" STREQUAL "")
if("${CMAKE_SYSTEM_NAME}" MATCHES "Windows")
set(SRB2_CPACK_GENERATOR "ZIP")
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(SRB2_CPACK_GENERATOR "TGZ")
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
set(SRB2_CPACK_GENERATOR "TGZ")
endif()
endif()
set(CPACK_GENERATOR ${SRB2_CPACK_GENERATOR})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "BlanKart" CACHE STRING "Program name for display purposes")
set(CPACK_PACKAGE_VENDOR "Team BlanKart" CACHE STRING "Vendor name for display purposes")
#set(CPACK_PACKAGE_DESCRIPTION_FILE )
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION_MAJOR ${SRB2_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${SRB2_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${SRB2_VERSION_PATCH})
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CMake ${CMAKE_VERSION_MAJOR}.${CMAKE_VERSION_MINOR}")
SET(CPACK_OUTPUT_FILE_PREFIX package)
include(CPack)
# Options
if(("${CMAKE_SYSTEM_NAME}" MATCHES Windows) OR ("${CMAKE_SYSTEM_NAME}" MATCHES Darwin))
@ -190,7 +164,6 @@ set(BLANKART_EXE_SUFFIX "" CACHE STRING "Optional executable suffix, separated b
include_directories(${CMAKE_CURRENT_BINARY_DIR}/src)
add_subdirectory(src)
add_subdirectory(assets)
## config.h generation
set(GIT_EXECUTABLE "git" CACHE FILEPATH "Path to git binary")
@ -210,6 +183,11 @@ if("${BLANKART_EXE_NAME}" STREQUAL "")
list(APPEND EXE_NAME_PARTS ${SRB2_GIT_BRANCH})
endif()
if(NOT "${NOAPPENDBUILD}")
string(TOLOWER "${CMAKE_BUILD_TYPE}" BLDTYPE_READOUT)
list(APPEND EXE_NAME_PARTS ${BLDTYPE_READOUT})
endif()
if(SRB2_CONFIG_COMPILEAPPIMAGE AND "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
list(APPEND EXE_NAME_PARTS "appimagebuild")
endif()

View file

@ -64,6 +64,10 @@ POSSIBILITY OF SUCH DAMAGE.
- LZ4 Library
Copyright (c) 2011-2025 Yann Collet
All rights reserved.
- monocypher
Copyright (c) 2017-2020, Loup Vaillant
All rights reserved.
https://monocypher.org/
--------------------------------------------------------------------------------
@ -1670,6 +1674,9 @@ freely, subject to the following restrictions:
- Verstable
Copyright (c) 2026 Jackson Allan
https://github.com/JacksonAllan/Verstable
- c-vector
Copyright (c) 2015 Evan Teran
https://github.com/eteran/c-vector
--------------------------------------------------------------------------------

12
assets/.gitignore vendored
View file

@ -1,12 +0,0 @@
*.srb
*.pk3
*.dta
*.wad
*.txt
*.kart
!README.txt
!HISTORY.txt
!LICENSE.txt
!LICENSE-3RD-PARTY.txt
!CMakeLists.txt
!debian-template/*

View file

@ -1,53 +0,0 @@
## Assets Target Configuration ##
if(${CMAKE_SYSTEM} MATCHES Linux)
# Asset installation isn't part of the Linux target
return()
endif()
if("${SRB2_CONFIG_ASSET_DIRECTORY}" STREQUAL "")
message(WARNING "SRB2_CONFIG_ASSET_DIRECTORY is not set, so installation will not contain data files.")
return()
endif()
get_filename_component(SRB2_ASSET_DIRECTORY_ABSOLUTE "${SRB2_CONFIG_ASSET_DIRECTORY}" ABSOLUTE)
set(SRB2_ASSETS_DOCS
"README.txt"
"HISTORY.txt"
"README-SDL.txt"
"LICENSE.txt"
"LICENSE-3RD-PARTY.txt"
)
list(TRANSFORM SRB2_ASSETS_DOCS PREPEND "/")
list(TRANSFORM SRB2_ASSETS_DOCS PREPEND "${SRB2_ASSET_DIRECTORY_ABSOLUTE}")
####################
# POST-V2.2 NOTE: Do not forget to add patch.pk3 to the end of this list!
####################
set(SRB2_ASSETS_GAME
"main.pk3"
"gfx.pk3"
"textures.pk3"
"chars.pk3"
"maps.pk3"
"followers.pk3"
"patch.pk3"
)
list(TRANSFORM SRB2_ASSETS_GAME PREPEND "/")
list(TRANSFORM SRB2_ASSETS_GAME PREPEND "${SRB2_ASSET_DIRECTORY_ABSOLUTE}")
set(SRB2_ASSETS ${SRB2_ASSET_DOCS} ${SRB2_ASSETS_GAME})
# Installation
if(${CMAKE_SYSTEM} MATCHES Darwin)
get_target_property(outname BLANKART OUTPUT_NAME)
install(FILES ${SRB2_ASSETS} DESTINATION "${outname}.app/Contents/Resources")
install(DIRECTORY "${SRB2_ASSET_DIRECTORY_ABSOLUTE}/models" DESTINATION "${outname}.app/Contents/Resources")
install(FILES ${SRB2_ASSETS_DOCS} DESTINATION .)
else()
install(FILES ${SRB2_ASSETS} DESTINATION .)
install(DIRECTORY "${SRB2_ASSET_DIRECTORY_ABSOLUTE}/models" DESTINATION .)
endif()

View file

@ -1,202 +0,0 @@
KartKrew: Chapter 1.0 - Who Would Actually Read All This???? [LIVE DOC]
-beep-
[Chromatian dual-wields onto the interview set, stage left, and takes a seat next to VelocitOni. Oni stands up to look at the confused camera-men before opening a binder to stoically show both of his redone Tails sprites for Kart 1.0 and Vanilla 2.2. He closes it and sits back down, the three sofa cushions being Sryder, toaster, and Lats limp timezoned bodies respectively; throwing arm over the side of the Fooruman pillow]
Chrome: Uh…......anyway Chaos Zero 64, a Vanilla SRB2 Developer at the time, during the “heyday” of Sonic Riders started working on his own side project of recreating that game in SRB2 v1.09.4. After programming a functional recreation, he went a step further and threw together a new race mode for all of the characters in the playable exe. After THAT, he took it another step further and made a Mario Kart game type as well. A bunch of young mappers (Including current KartKrew™ dev members Blade & I) tossed him a few maps and he called it a complete exe.
While fully functional, it was as barebones as you could get. Character stats were altered Vanilla stats (lowered jump, speed, no spindash, and no drifting!) weapon rings reskinned into mario items, and a bunch of checkpoints that you had to hit to count as a lap around the course. It was pretty jank, but seeing all of those dents in the core gameplay is what gave way to the inspiration to push it further than what it initially was.
Oni: Theres only one way to describe how I found it in 1.09.4, and the phrasing kinda caught on (to my pleasure), “ghetto footrace”. It was definitely an absolute MIRACLE at the time to even have SRB2 do anything different from its main gameplay scheme, bare ass open maps with collapsing FOFs; and the entire community as a whole was younger… so we all ate it up anyways. Standards were lower, times were simpler, we still really appreciate CZ for trying something new. When you pulled the wool off though, it was just ghetto footrace with reskinned buttons and totally unique…but also totally random weapon panels.
[FlareBlade pops out of loose pipe in the room for some reason and hits his head on a kitchen sink.]
Blade: While most of the maps back then harkened back to the simpler style of the 1.09.4 era; and were scrapped as SRB2 as a whole improved, Pipe Speedway has survived all the way to the present, although with a heavy style change, including a new name! (Now Daytona Speedway)
Oni: [laughs] You really like that map, dont you?
Random Audience Member:[shouting] PICK, PICK STARDUST!!
[The audience member is immediately shot through the heart with striking accuracy... the vote-screen SFX of a map being picked and Palmtree Panic Zone kids screaming "Yeah!" sounds. Cut to SeventhSentinel who just logged into the middle of the room with a shocked expression, smoking quality-controlling Desert Eagle in hand. The audience member's mask falls off, turning out to be Stardust Speedway Battle himself, now dead from the rotation.]
Sev: Why would Blade do this…?
Chrome: Pipe Speedway opened the PIPES for Karts 2.0 development, you could say. [laughs]
Blade: Well, it WAS the first one to be slope-ified! Mostly as a proof-of-concept to show what could be done. (the rest of you lot were too busy with that “TD” thing…) And then you all went and upstaged it anyway with some of the other maps. [chuckles] //shade
Oni: Yeah, while we finished ANOTHER full fledged mod, you actually got about 54% done with Pipe Speedway after 4 years! I was impressed. ////clapback
Chrome: Still, Blade kept the campfire lit while we went in search of food, that takes some dedication.
Oni: No. That was Blitz-T who continued making entire maps the whole time--
Blade --Thank you. Overall though, the original kart was more-or-less a side feature of Riders. Never really the main focus of the mod, but without a doubt the most popular part of it. The other two modes never really caught on. (Though we did have that ill-fated “Rivals” mod…) =P
Oni: [Holding a knife up to the two] The “what” mod?? Anywho, I was a frequent player of 1.09.4 but never really in the community much until 2.0. It wasnt until CZ ported his mod to be up to date, that I jumped in with the idea that I actually had enough of a brain to contribute to things… the problem was that my standards from the get-go were way way too high, and my skill as a spriter and general design experience were a lot lower. Nevertheless, when SRB2Riders hype died down, I approached him in DMs with all my expectations and ideas for his mod...and… surprisingly he didnt laugh me out! I guess hed never had anyone directly tell him theyd help outright before (besides Ground The Fox), but he was a bit noticeably bummed that I only cared for what hed considered the minor Mario mod within the mod.
This is what kickstarted the chain of events. All my plans that I bugged CZ for every other day in PMs never came to fruition, he actually lost interest and began to slowly fade out of the SRB2 community as a whole. Instead out of LITERALLY nowhere, D00D64 decided to revive the SRB2Riders mod himself by releasing a pretty expansive mod...of a mod within a mod OF a mod himself. Naturally, everyone jumped onto this, it exploded in popularity pretty much right away, because there were finally more than just a few mediocre maps to play “kart mode” on. There were PORTS, glorious glorious ports. Of course, I flocked to D00D to help out.
Blade: Flat, boring, ports. Though the crazy item spam helped. Also we FINALLY got DRIFTING! Separating the characters from the bloat of the other 2 modes also made making custom racers easier to make.
Oni: ...yeah, the truth is, once the “D00DKart” era started, it didnt help that there were so many more por-- er, maps to play kart-mode on that people realized the formula for a kart racer was just inherently more exciting than what CZd pulled off with the Riders half of it. I remember a LOT of content for kart, and then like 2 maps for the more fleshed out and polished main focus of the thing. Everyone just sorta... forgot about Riders mode, sadly. It didnt help that someone else also exploded onto the scene in a siamese feedback loop once D00D churned out enough maps a day to actually make a full game out of; ZarroTsu, who also saw opportunity too.
D00DKart and “Super SRB2Kart Z”, a continuation of ChaosZeros mod, combined into one super project. A team just kinda assembled naturally out of this, and more original content started to, slowly but surely, get made by a wider variety of people. The train continued to accelerate, lots of familiar faces coming into play. All the basics youd expect out of a Mario Kart clone were coded by Zarro, basically updates every single day, stuff just kept getting done by this specific group of people.
Chrome: Thats about when things for kart started to die down. D00DKart kept the entire game afloat, but Kart was always a sideline to Vanilla. Once D00DKart finally got comfortable, people moved back to Vanilla to see what else they could do with that. Servers stopped popping up as quickly as they used to, and eventually Super SRB2 Kart Z fell into obscurity. It was at this point that the small group still excited for the game tried to push for an even better project.
Oni: Yep. When steam on this makeshift game finally died, Zarro lost interest too, and outright just vanished for a year or two(?) and when then, when he returned, he had very little momentum to continue. So in the meanwhile we kinda came closer together under the team “Kart Krew”, and in his place Sryder took the helm. Zarros vision was always to be a Mario clone, so when he was absent I wanted to push my idea of getting rid of most if not all references to Mario pronto, going for a Sonic aesthetic instead. The idea was that well never be as good as a Nintendo game, and comparisons will always be drawn, so why not do something more unique?
Progress boomed again, but in private this time. 2013 ended up being the “2.0 indev” period. Standards kept increasing and increasing internally, because no one was satisfied with “ghetto footrace” anymore, we grew out of it and wanted an actual game this time… not play-pretend with all the instathrust hacks and poor game design decisions we were left with. Like shields.
NOBODY liked those shields. We just couldnt force Zarro to do what he didnt want with his mod of a mod in a mod of a mod.
Chrome: [laughs] Whirlwind was just a bit too broken for everyone.
Oni: Using a Whirlwind Shield felt like playing a game of fucking Twister with my fingers just to reach the convoluted buttons, and youre rewarded with the equivalent of bomb-jumping into the sky, except your kart is a runaway shower tub on pig grease. Awful. But good going, you ruined the entire race! Your slap on the wrist is now an unavoidable Armageddon Shield to the entire server by that Brazilian player who accidentally somehow made it to Lap 2 by RNG.
Mechanics were being edited, handling changed a bit, sprites were getting updated (notably the karts themselves), videos were being released from each of our channels, maps were bloating, notorious bug fixes at light speed. Unfortunately, literally at the same time, the new “Kart Krew” decided to sink their teeth into the Top Down experiment (we were on a high of too much confidence from all the progress) WHILE the release of Vanilla 2.1 invalidated all thre-- BOTH of our projects in one fell swoop. These were the dark ages, and it only got worse when I decided to disappear TOO before TD even got done. The story behind that development cycle (Top Down took all our Kart focus away when it was in progress) is known by now, but the real unexpected meat happened when we finally pushed that abortion out the door.
Chrome: You probably should have listened to Blade and stuck with our guns on Kart, and not take a “break” for a new experiment. [laughs]
[A silhouette outside the window in the rain can be seen with glowing cones, waving. Before anyone can process it, American Airlines smashes through the studio. For some reason Charybdizs walks out of the left-frontmost hatch]
Charyb: For the record, Top Down wasn't bad by any means! People are just jumping on it because its dev cycle was complicated and a big learning experience for everyone. There were numerous members who poured their hearts into it! Im proud of them! But yeah… the dev cycle…
[wolfs can be seen frantically searching for a point in this interview to be relevant, unscheduled anime forcing him to miss most of it]
wolfs: Oh man, TDs dev cycle. What a shitshow. Youd either get a response in 3 seconds or 3 days depending on who was around. Motivation was at an all-time low back then. I felt like I was talking into a vacuum sometime--
Oni: Why the fuck would you interrupt THIS moment, talking about 3 day responses when youll be “online” and wont say anything until Konys live fucking body is found. Get outta here.
wolfs: says the guy who disappeared for two years
Oni: 'ey fuk you mane
[Oni can be seen across the room from the plane, his TD_PTSD.td filled breathing into a brown paper bag]
Oni: No, if Top Down were bad it wouldnt have made half the hype of what Kart is doing now by ITSELF and manage to make it on Retros front page. But the dev cycle was purgatory, a big explosion at the start that dwindled to a candlefire, put out by the rain of inactivity...and then reignited by the power of Discord Chat. The actual product itself was pretty decent, and another fresh multiplayer experience not ever done in SRB2. It had hype.
Blade: ...When you say the karts were updated, you mean “Oni nit-picked them to death and redid them like 10 times”.
Oni: I wish he were joking about that number.
Chrome: It all worked out for the better though. That (rather lengthy!) experiment taught us a lot about time management and what not to do for the far more important modification. Discord got popular around this time, and Top Down hopped into that plane, and quickly parachuted out into the community. This gathered a few new, very important members into KartKrew™. TehRealSalt, host of the Sugoi series, Seventh Sentinel, a new mapper with a fresh take on level design, and toaster, a Vanilla dev programmer with a fire for Kart so hot keeping up with her pace is a job in itself. Seriously, without these three members, Kart wouldnt have the polish it does now.
Its around this time that the pioneer in Kart level design returned, Blitz-T. Every map he made for 2.0 indev kart was a jawdropper to everyone on the team, and his attention to the small details were more than impressive. On top of all of this, SRB2 version 2.1 supported sloped planes, something that was as unbelievable for this game as cell phones were back in the 50s.
This is where 2.1 Kart really started to shine, Zarro ported the entire game in the span of a few weeks, Blitz-T took his old maps and revamped them with slopes to nearly unrecognizable new iterations, TehRealSalt made the entire Battle mode in the span of a *single* night, and Seventh Sentinel finally gave us looped music and consistent sound quality.
Blade: Yeah, they really picked up the slack of some of the older members that lost steam, such as myself.
Oni: Sev, Sal, and toast were the most unexpected things to ever happen to this thing. This shit was literally overnight. Its really crazy how new blood can help bring a new perspective and vision to the game, along with skills you didnt know the team was lacking. SO much pressure was taken off of Sryder as Sal and toaster literally slapped the exe until it cried, like frame-perfect Ice Climber handoffs into a 300% wobble. EVERYONE was overwhelmed. I saw the chance and took it, so we decided to go with my vision while Zarro took a backseat. Most, if not all the remaining broken code was just thrown out the window at this point, the game was rapidly feeling cleaner in just nights.
If you took your eyes off of it for a few hours, something changed massively. The physics went from instathrust to momentum based, Zarro coded new acceleration code, toaster put in 2.2 friction physics as a test that turned out overwhelmingly positive...and also divisive with the previous vision of the mod. These changes were all happening so fast, despite being in kinda stored with me idea-wise for years, that it caused a bit of a rift in what this game was supposed to be. Zarro decided to take a step back and dip because itd changed so much in just the span of 4 months, he took one good look at 4-Player Splitscreen… a never seen before feat, and just breathed. It didnt feel like his mod anymore, his personal connection with it felt lost…
[Oni wiping sweat off his brow] Things only got more drastically revamped… very very rapidly.
The Mario aesthetic was entirely tossed out, as Sal was willing to work with me night and day on redoing most of everything about items… and then sounds. My power level for sprites massively jumped during TD development, so I decided to take it upon myself to do almost everything. Theyre such friendly and cooperative coders that I cant help but push a little harder than I used to (I was WAY lazier before they got here) to keep up.
Chrome: Those kart sprites took a good 6 months longer than they needed to for sure! [laughs]
Oni: [laughs in Latin] Its not as easy as sloping a single sector in Misty Maze, thats for sure!
The mappers went bonkers, especially Blitz-T and TyrannoChao aka “Ezo” (previously ChaoticChao) whos content probably makes up half the game combined. The creative freedom and supportive style/mentality of how the team is led pretty much went to an unstoppable feedback loop of content AND polish, surprisingly. We got to a point where we could not only lay any remaining ChaosZero64 code that mightve seeped to rest, but also throw out almost every direct Mario port or reference right down to the sounds. It became a Sonic game, in one year.
Blade: Stuff was added so rapidly, even right up to release it always felt like there was something new being added. Bonuschars alone got 2 extra characters added in the week before release!
Oni: Really, if you asked me, Id say that most of kart just happened since TD released til now, and the rest was just a confused fever dream of passing torches until it all just got thrown out and re-done anyway. Thats why a changelog is pretty pointless, its like going to a shop...sitting down…and getting a recommendation for your vehicle; but the papers blank and just reads “get new car”. Honestly, playing this and playing the old 2.0 public builds that people like Super Chris still host for some reason is like aging backwards, except youre really just amputating your skeleton to appear small and young again, its HORRIBLE. So if they all liked that… hopefully theyll like an actually good game...even more??
[Sounds of an angry midnight release crowd erupting outside, muffled. D00D64 can be seen at the forefront...slapping yet another unnaturally high quality gif meme onto the glass window. The camera pans out, theres hundreds of gif memes all over the outer walls]
Oni: Is it midnight?? I told them to fuck off, theres no midnight release! @Chromatian FIND SOMETHING TO SAY AFTER ME TO CLOSE THIS UP ALREADY
Chrome: [this shitty Iwata Asks atmosphere cracking at the seams of its own immersion, reality warping his professional and calm demeanor, but he laughs regardless...shakily] You just dont know when to stop!!
[TehRealSalt struggles trying to get into the room through the tiny doggy door for 5 awkward minutes, before giving up and just opening the door] … [she doesnt know what to say.]
Oni: EZO
[The towering dinosaur just nonchalantly sits in his chair on-stage, legs crossed, resting his head on his hand]
Ezo: Sticky Kart was a shitshow. [referring to the old controls/physics]
Oni: holy shit YOU CANT SAY THAT ZARRO MIGHT BE READING
Ezo: I have no regretties. Except for maybe Arid S--wait, thats a secret, isnt it? Hm. Anyway, yeah, working on this was fun. Usually. Learning to sprite was annoying but it paid off since I got to cram Wonder Boy in everyones faces like the scaly fucko I am. Though Gammas pretty cool too. I hope you all enjoy my Sonic Adventure references and that you all suffer an appropriately huge amount in Egg Quarters and Spotlight Syndicate.
Oni: THIS IS A NON FURRY DOCUMENT :boi:
Ezo: Speciesism UwU
Boinciel: [screaming from a speaker contained offstage] HI MY NAME IS BOINCIEL I DESIGNED KART MAPS TO DESTROY YOUR EYES AND/OR YOUR SOUL OKAY BYE I HAVE TO DO MY JOB NOW
Oni: With a map like Kodachrome…..clearly...
[Off in the corner, a lone wooden coat rack stands, although upon further inspection... It turns out to be, well, CoatRack in a disguise!]
[The entire server pauses for Coat to come up with something]
Coat: You know, these guys all did an awesome job. The controls, the graphics, music too! I just, uh… Had an engine stall on my map, sad how many times I ran out of fuel at a petroleum refinery when making it. Huh. But as one of the more outside members of the krew, just ask anyone, I could be placed under the decorative ornament members with how rarely I dropped in. But each time I did I was blown away by the leaps and bounds, filling me with joy to see this racer come to life. Even if I am a living example of why inanimate objects shouldnt drive!
[The entire Krew stares at the literal coat rack, smiling wholesomely until Blade opens his mouth]
Blade: Whatever. Enough talking, LETS GO AWAY!!!!!!!! DAYTONNNAAAAAAAAAAAAAAAA
[...the .txt file itself cringes to a halt.]
doot

View file

@ -1 +0,0 @@
../LICENSE-3RD-PARTY

View file

@ -1 +0,0 @@
../LICENSE

View file

@ -1,65 +0,0 @@
SONIC ROBO BLAST 2 KART
SRB2Kart is a kart racer based on SRB2, the 3D Sonic the Hedgehog
fangame based on a modified version of Doom Legacy.
LICENSE
The source code for SRB2 & SRB2Kart is licensed under the GNU General
Public License, Version 2. See LICENSE.txt for the full text of this
license.
SRB2 & SRB2Kart uses various third-party libraries, including SDL, SDL
Mixer, and their dependencies. See LICENSE-3RD-PARTY.txt for the
licenses of these libraries.
SOURCE CODE
You may obtain the source code for SRB2Kart, including the source code
for specific version releases, at the following web site:
STJr GitLab:
https://git.magicalgirl.moe/KartKrew/Kart-Public
You may obtain the source code for the parent game, SRB2, at the
following web sites:
STJr GitLab:
https://git.magicalgirl.moe/STJr/SRB2
GitHub:
https://github.com/STJr/SRB2
CONTACT
You may contact Kart Krew via the following web site:
Kart Krew Official Discord:
https://discord.gg/WJmqDtN
You may contact Sonic Team Junior via the following web sites:
SRB2.ORG:
https://www.srb2.org
SRB2 Message Board:
https://mb.srb2.org
SRB2 Official Discord:
https://discord.gg/pYDXzpX (13+)
COPYRIGHT AND DISCLAIMER
Design and content on SRB2Kart is copyright 2020 by Kart Krew.
Design and content on SRB2 is copyright 1998-2020 by Sonic Team Junior.
All non-original material on SRB2.ORG is copyrighted by their
respective owners, and no copyright infringement is intended. The owner
of the SRB2.ORG domain is only acting as an ISP, and is therefore not
responsible for any content on SRB2.ORG under the 1998 DMCA. This
site, its webmaster, and its staff make no profit whatsoever (in fact,
we lose money). Sonic Team Junior assumes no responsibility for the
content on any Sonic Team Junior fan sites.
Kart Krew nor Sonic Team Junior is in no way affiliated with SEGA or
Sonic Team. We do not claim ownership of any of SEGA's intellectual
property used in SRB2 or SRB2Kart.

View file

@ -1,73 +0,0 @@
srb2 for Debian
---------------
SRB2 Debian package!
Hi there, to rebuild this package just use the SRB2 Makefile system, or, optionally, run
dpkg-buildpackage in the in /assets directory. You can build these with or without a key
if you want, but if you want to put these on a repo, generate your own GnuPG key as per the
https://help.ubuntu.com/community/GnuPrivacyGuardHowto instructions and pass the -k<keyid>
command to debuild. Make sure you export the key footprint and give them to your users to install
with apt-key add. Thanks!
-- Callum Dickinson <gcfreak_ag20@hotmail.com> Fri, 26 Nov 2010 18:25:31 +1300
---------------
Templating
Note that you MUST run [repo-root]/debian_template.sh before running debuild
on these scripts! debian_template.sh fills these template files with working values.
You should also set PACKAGE_NAME_EMAIL="John Doe <jdoe@example.com>" to match
the identity of the key you will use to sign the package.
Building for Launchpad PPA
Run this step first:
1. source [repo-root]/debian_template.sh
* Initializes defaults for the package variables and fills in templates.
Use these steps to prepare building a source package for Launchpad:
1. cd [repo-root]/assets/
2. debuild -T clean-all (optional; if you already have asset files, this clears them)
Build the source package:
1. debuild -T build (this downloads the asset files from srb2.org if necessary)
2. debuild -S (builds the source package for Launchpad, including the asset files)
Signing for Launchpad PPA
First, follow Callum's instructions to generate a GnuPG key with your identity. You will need
to publish the fingerprint of that key to Ubuntu's key server.
https://help.ubuntu.com/community/GnuPrivacyGuardHowto#Uploading_the_key_to_Ubuntu_keyserver
Next, you will have to add that key fingerprint to your Launchpad account. Go to your Launchpad
profile and click the yellow Edit button next to "OpenPGP keys". Once you add the key, you can
upload signed source packages and publish them onto your PPA.
IF YOU UPLOAD A PACKAGE and Launchpad does NOT send you a confirmation or rejection email, that
means your key is not set up correctly with your Launchpad account.
Finally, if your packages have not already been signed, follow these steps:
1. cd ..
* Packages are located in the parent folder of where debuild was called
2. debsign "srb2-data_[version]_source.changes"
* You may need to specify -k [key-fingerprint]
Uploading for Launchpad PPA
Follow the instructions at <https://help.launchpad.net/Packaging/PPA/Uploading> to upload
to your PPA and have Launchpad build your binary deb packages.
-- Marco Zafra <marco.a.zafra@gmail.com> Mon, 26 Nov 2018 21:13:00 -0500

View file

@ -1,4 +0,0 @@
srb2-data for Debian
---------------
Look in main SRB2 README.source for more information.

View file

@ -1,5 +0,0 @@
${PACKAGE_NAME}-data (${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION}) ${PACKAGE_DISTRO}; urgency=${PACKAGE_URGENCY}
* ${PROGRAM_NAME} v${PROGRAM_VERSION} asset data
-- ${PACKAGE_NAME_EMAIL} ${__PACKAGE_DATETIME}

View file

@ -1 +0,0 @@
7

View file

@ -1,22 +0,0 @@
# SRB2-data Debian package control file.
Source: ${PACKAGE_NAME}-data
Section: games
Priority: extra
Maintainer: ${PACKAGE_GROUP_NAME_EMAIL}
Build-Depends: debhelper (>= 7.0.50~),
wget
Standards-Version: 3.8.4
Homepage: ${PACKAGE_WEBSITE}
Package: ${PACKAGE_NAME}-data
Architecture: all
Description: A cross-platform 3D Sonic fangame
Sonic Robo Blast 2 is a 3D open-source Sonic the Hedgehog
fangame built using a modified version of the Doom Legacy
port of Doom. SRB2 is closely inspired by the original
Sonic games from the Sega Genesis, and attempts to recreate
the design in 3D. It features tons of levels, enemies, speed,
and quite a lot of the fun that the original Sonic games provided.
This is the data package that provides the data files that
SRB2 requires to run; it will not work without it.

View file

@ -1,27 +0,0 @@
This work was packaged for Debian by:
${PACKAGE_NAME_EMAIL} ${__PACKAGE_DATETIME}
It was downloaded from:
${PACKAGE_WEBSITE}
Upstream Author(s):
${PACKAGE_GROUP_NAME_EMAIL}
Copyright:
Copyright (C) 1998-2018 by Sonic Team Junior
License:
GNU General Public License, version 2
The Debian packaging is:
Copyright (C) 2010 Callum Dickinson <gcfreak_ag20@hotmail.com>
Copyright (C) 2010-2018 by Sonic Team Junior <stjr@srb2.org>
and is licensed under the GPL version 2,
see "/usr/share/common-licenses/GPL-2".

View file

@ -1,129 +0,0 @@
#!/usr/bin/make -f
# -*- makefile -*-
#############################################################################
#
# GNU Make Debian package makefile for SRB2-data
#
# Copyright (C) 1998-2011 by Callum Dickinson
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# This file most likely will not need to be modified to make
# branches of SRB2 capable of making their own Debian packages,
# instead look at the /debian/control file for configuration.
#
#############################################################################
#############################################################################
#
# !!!!!!!!!! DEPLOYER NOTE !!!!!!!!!!
#
# Variables to be templated are curly-braced ${PACKAGE_INSTALL_PATH}
# Variables used by the rules script are parenthese'd $(DATADIR)
# See [repo-root]/debian_template.sh
#
#############################################################################
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# user/group of to-be-installed files
ROOT_USER := 0
ROOT_GROUP := 0
MKDIR := mkdir -p
INSTALL := install -o $(ROOT_USER) -g $(ROOT_GROUP) -m 644
MV := mv
RM := rm -rf
DIR := $(shell pwd)
PACKAGE := $(shell cat $(DIR)/debian/control | grep 'Package:' | sed -e 's/Package: //g')
ARCHIVEPATH := ${ASSET_ARCHIVE_PATH}
ARCHIVEOPTIONALPATH := ${ASSET_ARCHIVE_OPTIONAL_PATH}
GETOPTIONALFILES := ${ASSET_FILES_OPTIONAL_GET}
DATADIR := $(shell echo "${PACKAGE_INSTALL_PATH}" | sed -e 's/^\///')
RESOURCEDIR := .
STAGINGDIR := $(RESOURCEDIR)/installer
WGET := wget -P $(RESOURCEDIR) -c -nc
build:
$(MKDIR) $(DIR)/debian/tmp/$(DATADIR)
> $(DIR)/debian/source/include-binaries
# Copy data files to their install locations, and add data files to include-binaries
if [ ! -d $(STAGINGDIR) ]; then \
mkdir -p "$(STAGINGDIR)"; \
$(WGET) $(ARCHIVEPATH); \
7z x "$(RESOURCEDIR)/$(shell basename $(ARCHIVEPATH))" -aos; \
if [ "$(GETOPTIONALFILES)" = "1" ]; then \
$(WGET) $(ARCHIVEOPTIONALPATH); \
7z x "$(RESOURCEDIR)/$(shell basename $(ARCHIVEOPTIONALPATH))" -aos; \
fi; \
fi
# Install asset directory and add asset file to include-binaries
cp -vr "$(STAGINGDIR)/." "$(DIR)/debian/tmp/$(DATADIR)"
find "$(STAGINGDIR)" >> $(DIR)/debian/source/include-binaries
binary-indep:
# Generate install folder file
echo $(DATADIR) > $(DIR)/debian/$(PACKAGE).install
binary-arch:
# only here to kill Lintian warning
echo "no need to do any arch-specific stuff"
binary: binary-indep
dh_testdir
dh_testroot
dh_installchangelogs
# dh_installdocs
# dh_installexamples
dh_install --sourcedir=$(DIR)/debian/tmp
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_python
# dh_installinit
# dh_installcron
# dh_installinfo
# dh_installman
# dh_link
dh_compress
dh_fixperms
# dh_perl
# dh_makeshlibs
dh_installdeb
# -dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
clean:
$(RM) $(DIR)/debian/tmp/*; \
$(RM) $(DIR)/debian/$(PACKAGE).install; \
$(RM) $(DIR)/debian/files; \
clean-all: clean
$(RM) $(RESOURCEDIR)/*.wad; \
$(RM) $(RESOURCEDIR)/*.dta; \
$(RM) $(RESOURCEDIR)/*.plr; \
$(RM) $(RESOURCEDIR)/*.wpn; \
$(RM) $(RESOURCEDIR)/*.srb; \
$(RM) $(RESOURCEDIR)/*.dll; \
$(RM) $(RESOURCEDIR)/*.txt; \
$(RM) $(DIR)/debian/source/include-binaries; \
.PHONY: all clean binary binary-arch binary-indep build

View file

@ -1 +0,0 @@
3.0 (native)

View file

@ -1 +0,0 @@
tar-ignore = "tmp/*"

View file

@ -233,6 +233,7 @@ BlanKart's namespace implements the following additional fields:
redpogospring = <bool>; // true = players are bounced into the air by this sector.
yellowpogospring = <bool>; // true = players are bounced into the air and then speedcapped by this sector.
walltransfer = <bool>; // true = players are allowed to slide up walls from this sector.
bumpyroad = <bool>; // true = players are visually tilted by this sector to simulate a bumpy road. Does not effect gameplay.
repeatspecial = <bool>; // true = repeatable action.
continuousspecial = <bool>; // true = action is executed every game tick.
@ -318,3 +319,6 @@ BK 1.0: 11.03.2025
BK 1.0 22.03.2026
- Added more effects.
BK 1.0 21.04.2026
- Added bumpy road effect.

View file

@ -77,6 +77,7 @@ add_executable(BLANKART MACOSX_BUNDLE WIN32
r_plane.cpp
r_segs.cpp
r_skins.c
r_voicepreference.cpp
r_sky.c
r_splats.c
r_things.cpp
@ -152,6 +153,7 @@ add_executable(BLANKART MACOSX_BUNDLE WIN32
k_mapuser.c
k_stats.c
k_specialstage.c
k_vote.c
h_timers.cpp
stun.c
lonesha256.c
@ -181,6 +183,9 @@ set(SRB2_CONFIG_STD23 OFF CACHE BOOL
set(SRB2_CONFIG_COMPILEAPPIMAGE OFF CACHE BOOL
"Compiles the game then attempts turning it into an appimage.")
set(SRB2_CONFIG_JEMALLOC OFF CACHE BOOL
"Links jemalloc Allocator to replace GLibc malloc.")
if(SRB2_CONFIG_COMPILEAPPIMAGE AND "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
message("-- Generating Appimage at build time.")
add_custom_command(
@ -203,6 +208,18 @@ else()
set_property(TARGET BLANKART PROPERTY CXX_STANDARD 17)
endif()
# Thanks https://stackoverflow.com/a/63320046
if(SRB2_CONFIG_JEMALLOC)
message("-- Using JEMALLOC.")
find_package(PkgConfig REQUIRED)
pkg_check_modules(JEMALLOC jemalloc)
pkg_search_module(JEMALLOC REQUIRED jemalloc)
include_directories(${JEMALLOC_INCLUDE_DIRS})
target_link_libraries(BLANKART PRIVATE ${JEMALLOC_LIBRARIES})
endif()
### Configuration
set(SRB2_CONFIG_DEV_BUILD OFF CACHE BOOL
"Compile a development build of SRB2Kart.")
@ -275,6 +292,7 @@ add_subdirectory(sdl)
add_subdirectory(objects)
add_subdirectory(core)
add_subdirectory(acs)
add_subdirectory(monocypher)
# OS macros
if (UNIX)

View file

@ -3066,7 +3066,7 @@ bool CallFunc_MapWarp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Wor
return false;
}
nextmapoverride = (nextmap + 1);
nextmapoverride = (mapnum_t)(nextmap + 1);
if (argV[1] == 0)
skipstats = 1;

View file

@ -275,7 +275,7 @@ void Environment::loadModule(ACSVM::Module *module)
if (name->i) // this module is from a map!
{
INT32 mapnum = G_MapNumber(name->s->str);
mapnum_t mapnum = G_MapNumber(name->s->str);
if (mapnum < NEXTMAP_INVALID)
lumpnum = mapheaderinfo[mapnum]->lumpnum;
}

View file

@ -1,43 +0,0 @@
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file asm_defs.inc
/// \brief must match the C structures
#ifndef __ASM_DEFS__
#define __ASM_DEFS__
// this makes variables more noticable,
// and make the label match with C code
// Linux, unlike DOS, has no "_" 19990119 by Kin
// and nasm needs .data code segs under linux 20010210 by metzgermeister
// FIXME: nasm ignores these settings, so I put the macros into the makefile
#ifdef __ELF__
#define C(label) label
#define CODE_SEG .data
#else
#define C(label) _##label
#define CODE_SEG .text
#endif
/* This is a more readable way to access the arguments passed from C code */
/* PLEASE NOTE: it is supposed that all arguments passed from C code are */
/* 32bit integer (INT32, long, and most *pointers) */
#define ARG1 8(%ebp)
#define ARG2 12(%ebp)
#define ARG3 16(%ebp)
#define ARG4 20(%ebp)
#define ARG5 24(%ebp)
#define ARG6 28(%ebp)
#define ARG7 32(%ebp)
#define ARG8 36(%ebp)
#define ARG9 40(%ebp) //(c)tm ... Allegro by Shawn Hargreaves.
#endif

View file

@ -84,7 +84,7 @@ LUA_API int lua_gethookcount (lua_State *L) {
}
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
__attribute__((used)) LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
int status;
CallInfo *ci;
lua_lock(L);

View file

@ -81,6 +81,7 @@ static /*const*/ Node dummynode_ = {
/*
** hash for lua_Numbers
*/
#if 0
static Node *hashnum (const Table *t, lua_Number n) {
unsigned int a[numints];
int i;
@ -90,6 +91,12 @@ static Node *hashnum (const Table *t, lua_Number n) {
for (i = 1; i < numints; i++) a[0] += a[i];
return hashmod(t, a[0]);
}
#else
// our lua_Number is just typedef´d int32 so no need to do any of the above
static inline Node *hashnum (const Table *t, lua_Number n) {
return hashmod(t, cast(unsigned int, n));
}
#endif

View file

@ -331,7 +331,7 @@ typedef struct lua_Debug lua_Debug; /* activation record */
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
__attribute__((used)) LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);

View file

@ -810,12 +810,14 @@ static void COM_Echo_f(void)
static void COM_CEcho_f(void)
{
size_t i;
char cechotext[1024] = "";
char cechotext[1024];
for (i = 1; i < COM_Argc(); i++)
strlcpy(cechotext, COM_Argc() > 1 ? COM_Argv(1) : "", sizeof(cechotext));
for (i = 2; i < COM_Argc(); i++)
{
strlcpy(cechotext, COM_Argv(i), sizeof(cechotext)-1);
strlcpy(cechotext, " ", sizeof(cechotext)-1);
strlcat(cechotext, " ", sizeof(cechotext));
strlcat(cechotext, COM_Argv(i), sizeof(cechotext));
}
HU_DoCEcho(cechotext);
@ -1441,6 +1443,60 @@ void VS_Print(vsbuf_t *buf, const char *data)
//
// =========================================================================
static UINT32 xxHashString32(const char *name)
{
size_t len = strlen(name);
char *uname = (char *)alloca(len + 1);
strlcpy(uname, name, len + 1);
strlwr(uname);
return HASH32(uname, len);
}
#define NAME cvar_map_t
#define KEY_TY const char *
#define VAL_TY consvar_t *
#define HASH_FN xxHashString32
#define CMPR_FN vt_cmpr_casestring
#include "verstable.h"
#define NAME netvar_map_t
#define KEY_TY UINT16
#define VAL_TY consvar_t *
#define HASH_FN vt_hash_integer
#define CMPR_FN vt_cmpr_integer
#include "verstable.h"
#define NAME compatnetvar_map_t
#define KEY_TY UINT16
#define VAL_TY consvar_t *
#define HASH_FN vt_hash_integer
#define CMPR_FN vt_cmpr_integer
#include "verstable.h"
static cvar_map_t cvar_map;
static netvar_map_t netvar_map;
static compatnetvar_map_t compatnetvar_map;
CONSTRUCTOR static void CV_InitMap(void)
{
// ensure the map is initialized
cvar_map_t_init(&cvar_map);
cvar_map_t_reserve(&cvar_map, 512);
netvar_map_t_init(&netvar_map);
netvar_map_t_reserve(&netvar_map, 256);
compatnetvar_map_t_init(&compatnetvar_map);
compatnetvar_map_t_reserve(&compatnetvar_map, 256);
}
DESTRUCTOR static void CV_DestroyMap(void)
{
cvar_map_t_cleanup(&cvar_map);
netvar_map_t_cleanup(&netvar_map);
compatnetvar_map_t_cleanup(&compatnetvar_map);
}
static const char *cv_null_string = "";
/** Searches if a variable has been registered.
@ -1451,11 +1507,17 @@ static const char *cv_null_string = "";
*/
consvar_t *CV_FindVar(const char *name)
{
consvar_t *cvar;
cvar_map_t_itr it = cvar_map_t_get(&cvar_map, name);
if (!cvar_map_t_is_end(it))
return it.data->val;
// fallback linear search
/*
consvar_t *cvar;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
if (fasticmp(name, cvar->name))
return cvar;
*/
return NULL;
}
@ -1482,6 +1544,10 @@ static inline UINT16 CV_ComputeLegacyNetid(const char *s)
*/
static consvar_t *CV_FindNetVar(UINT16 netid)
{
netvar_map_t_itr it = netvar_map_t_get(&netvar_map, netid);
if (!netvar_map_t_is_end(it))
return it.data->val;
/*
consvar_t *cvar;
if (netid > consvar_number_of_netids)
@ -1490,6 +1556,7 @@ static consvar_t *CV_FindNetVar(UINT16 netid)
for (cvar = consvar_vars; cvar; cvar = cvar->next)
if (cvar->netid == netid)
return cvar;
*/
if (netid == 44542) // ouch this hack
return &cv_karteliminatelast;
@ -1499,11 +1566,17 @@ static consvar_t *CV_FindNetVar(UINT16 netid)
consvar_t *CV_FindLegacyNetVar(UINT16 netid)
{
compatnetvar_map_t_itr it = compatnetvar_map_t_get(&compatnetvar_map, netid);
if (!compatnetvar_map_t_is_end(it))
return it.data->val;
/*
consvar_t *cvar;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
if (cvar->compatnetid == netid)
return cvar;
*/
if (netid == 44542) // ouch this hack
return &cv_karteliminatelast;
@ -1583,6 +1656,13 @@ void CV_RegisterVar(consvar_t *variable)
// the SetValue will set this bit
variable->flags &= ~CV_MODIFIED;
cvar_map_t_insert(&cvar_map, variable->name, variable);
if (variable->flags & CV_NETVAR)
netvar_map_t_insert(&netvar_map, variable->netid, variable);
if (variable->compatnetid)
compatnetvar_map_t_insert(&compatnetvar_map, variable->compatnetid, variable);
}
/** Finds the string value of a console variable.
@ -1969,6 +2049,25 @@ static void CV_LoadVars(UINT8 **p,
// prevent "invalid command received"
serverloading = true;
// we can use our netvar map instead of going through all cvars each time
netvar_map_t_itr it;
for (it = netvar_map_t_first(&netvar_map);
!netvar_map_t_is_end(it);
it = netvar_map_t_next(it))
{
cvar = it.data->val;
if (store && cvar->revert.v.string == NULL)
{
cvar->revert.v.const_munge = cvar->string;
cvar->revert.allocated = ( cvar->zstring != NULL );
cvar->zstring = NULL; // don't free this
}
Setvalue(cvar, cvar->defaultvalue, true);
}
/*
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->flags & CV_NETVAR)
@ -1977,12 +2076,12 @@ static void CV_LoadVars(UINT8 **p,
{
cvar->revert.v.const_munge = cvar->string;
cvar->revert.allocated = ( cvar->zstring != NULL );
cvar->zstring = NULL;/* don't free this */
cvar->zstring = NULL; // don't free this
}
Setvalue(cvar, cvar->defaultvalue, true);
}
}
}*/
if (got == NULL)
G_LoadDemoCvars((void **)p, Setvalue);
@ -2418,9 +2517,22 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr)
if (!(v->flags & CV_SAVE))
return true;
// nothing to see here...
(void)valstr;
if (GETMAJOREXECVERSION(cv_execversion.value) == 12 && GETMINOREXECVERSION(cv_execversion.value) < 1) // 12.1 = BK Indev 25-04-26
{
if (fasticmp(v->name, "masterserver")) // Upgrade the masterserver from SRB2Classic's to our own.
return false;
}
if (GETMAJOREXECVERSION(cv_execversion.value) == 12 && GETMINOREXECVERSION(cv_execversion.value) < 2) // 12.2 = BK Indev 29-04-26
{
if (fasticmp(v->name, "gr_modellighting")) // This needs to be on for directional lighting to look right on models.
return false;
if (fasticmp(v->name, "gr_palettedepth")) // 24 bit looks best.
return false;
}
return true;
}

View file

@ -227,14 +227,6 @@ static void CONS_Clear_f(void)
Unlock_state();
}
// Choose english keymap
//
/*static void CONS_English_f(void)
{
shiftxform = english_shiftxform;
CONS_Printf(M_GetText("%s keymap.\n"), M_GetText("English"));
}*/
static char *bindtable[NUMINPUTS];
static void CONS_Bind_f(void)
@ -675,23 +667,57 @@ void CON_MoveConsole(void)
Unlock_state();
}
static char shiftxform[] =
{
0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31,
' ', '!', '"', '#', '$', '%', '&',
'"', // shift-'
'(', ')', '*', '+',
'<', // shift-,
'_', // shift--
'>', // shift-.
'?', // shift-/
')', // shift-0
'!', // shift-1
'@', // shift-2
'#', // shift-3
'$', // shift-4
'%', // shift-5
'^', // shift-6
'&', // shift-7
'*', // shift-8
'(', // shift-9
':',
':', // shift-;
'<',
'+', // shift-=
'>', '?', '@',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'{', // shift-[
'|', // shift-backslash - OH MY GOD DOES WATCOM SUCK
'}', // shift-]
'"', '_',
'~', // shift-`
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'{', '|', '}', '~', 127
};
INT32 CON_ShiftChar(INT32 ch)
{
if (I_UseNativeKeyboard())
if (I_UseNativeKeyboard() || ch >= sizeof(shiftxform))
return ch;
// warning: shiftdown is NOT a boolean, it's 1 or 2 for lshift/rshift
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
{
if (shiftdown ^ capslock)
ch = shiftxform[ch];
}
return !!shiftdown != capslock ? shiftxform[ch] : ch;
else // if we're holding shift we should still shift non letter symbols
{
if (shiftdown)
ch = shiftxform[ch];
}
return ch;
return shiftdown ? shiftxform[ch] : ch;
}
// Clear time of console heads up messages

483
src/cvector.h Normal file
View file

@ -0,0 +1,483 @@
#ifndef CVECTOR_H_
#define CVECTOR_H_
/**
* @copyright Copyright (c) 2015 Evan Teran,
* License: The MIT License (MIT)
* @brief cvector heap implemented using C library malloc()
* @file cvector.h
*/
/* in case C library malloc() needs extra protection,
* allow these defines to be overridden.
*/
/* functions for allocation and deallocation need to correspond to each other, fall back to C library functions if not all are overridden */
#if !defined(cvector_clib_free) || !defined(cvector_clib_malloc) || !defined(cvector_clib_calloc) || !defined(cvector_clib_realloc)
#ifdef cvector_clib_free
#undef cvector_clib_free
#endif
#ifdef cvector_clib_malloc
#undef cvector_clib_malloc
#endif
#ifdef cvector_clib_calloc
#undef cvector_clib_calloc
#endif
#ifdef cvector_clib_realloc
#undef cvector_clib_realloc
#endif
#include <stdlib.h>
#define cvector_clib_free free
#define cvector_clib_malloc malloc
#define cvector_clib_calloc calloc
#define cvector_clib_realloc realloc
#endif
/* functions independent of memory allocation */
#ifndef cvector_clib_assert
#include <assert.h> /* for assert */
#define cvector_clib_assert assert
#endif
#ifndef cvector_clib_memcpy
#include <string.h> /* for memcpy */
#define cvector_clib_memcpy memcpy
#endif
#ifndef cvector_clib_memmove
#include <string.h> /* for memmove */
#define cvector_clib_memmove memmove
#endif
/* NOTE: Similar to C's qsort and bsearch, you will receive a T*
* for a vector of Ts. This means that you cannot use `free` directly
* as a destructor. Instead if you have for example a cvector_vector_type(int *)
* you will need to supply a function which casts `elem_ptr` to an `int**`
* and then does a free on what that pointer points to:
*
* ex:
*
* void free_int(void *p) { free(*(int **)p); }
*/
typedef void (*cvector_elem_destructor_t)(void *elem_ptr);
typedef struct cvector_metadata_t {
size_t size;
size_t capacity;
cvector_elem_destructor_t elem_destructor;
} cvector_metadata_t;
/**
* @brief cvector_vector_type - The vector type used in this library
* @param type The type of vector to act on.
*/
#define cvector_vector_type(type) type *
/**
* @brief cvector - Syntactic sugar to retrieve a vector type
* @param type The type of vector to act on.
*/
#define cvector(type) cvector_vector_type(type)
/**
* @brief cvector_iterator - The iterator type used for cvector
* @param type The type of iterator to act on.
*/
#define cvector_iterator(type) cvector_vector_type(type)
/**
* @brief cvector_vec_to_base - For internal use, converts a vector pointer to a metadata pointer
* @param vec - the vector
* @return the metadata pointer of the vector
* @internal
*/
#define cvector_vec_to_base(vec) \
(&((cvector_metadata_t *)(void *)(vec))[-1])
/**
* @brief cvector_base_to_vec - For internal use, converts a metadata pointer to a vector pointer
* @param ptr - pointer to the metadata
* @return the vector
* @internal
*/
#define cvector_base_to_vec(ptr) \
((void *)&((cvector_metadata_t *)(ptr))[1])
/**
* @brief cvector_capacity - gets the current capacity of the vector
* @param vec - the vector
* @return the capacity as a size_t
*/
#define cvector_capacity(vec) \
((vec) ? cvector_vec_to_base(vec)->capacity : (size_t)0)
/**
* @brief cvector_size - gets the current size of the vector
* @param vec - the vector
* @return the size as a size_t
*/
#define cvector_size(vec) \
((vec) ? cvector_vec_to_base(vec)->size : (size_t)0)
/**
* @brief cvector_elem_destructor - get the element destructor function used
* to clean up elements
* @param vec - the vector
* @return the function pointer as cvector_elem_destructor_t
*/
#define cvector_elem_destructor(vec) \
((vec) ? cvector_vec_to_base(vec)->elem_destructor : NULL)
/**
* @brief cvector_empty - returns non-zero if the vector is empty
* @param vec - the vector
* @return non-zero if empty, zero if non-empty
*/
#define cvector_empty(vec) \
(cvector_size(vec) == 0)
/**
* @brief cvector_reserve - Requests that the vector capacity be at least enough
* to contain n elements. If n is greater than the current vector capacity, the
* function causes the container to reallocate its storage increasing its
* capacity to n (or greater).
* @param vec - the vector
* @param n - Minimum capacity for the vector.
* @return void
*/
#define cvector_reserve(vec, n) \
do { \
size_t cv_reserve_cap__ = cvector_capacity(vec); \
if (cv_reserve_cap__ < (n)) { \
cvector_grow((vec), (n)); \
} \
} while (0)
/**
* @brief cvector_init - Initialize a vector. The vector must be NULL for this to do anything.
* @param vec - the vector
* @param capacity - vector capacity to reserve
* @param elem_destructor_fn - element destructor function
* @return void
*/
#define cvector_init(vec, capacity, elem_destructor_fn) \
do { \
if (!(vec)) { \
cvector_reserve((vec), capacity); \
cvector_set_elem_destructor((vec), (elem_destructor_fn)); \
} \
} while (0)
/**
* @brief cvector_erase - removes the element at index i from the vector
* @param vec - the vector
* @param i - index of element to remove
* @return void
*/
#define cvector_erase(vec, i) \
do { \
if (vec) { \
const size_t cv_erase_sz__ = cvector_size(vec); \
if ((i) < cv_erase_sz__) { \
cvector_elem_destructor_t cv_erase_elem_dtor__ = cvector_elem_destructor(vec); \
if (cv_erase_elem_dtor__) { \
cv_erase_elem_dtor__(&(vec)[i]); \
} \
cvector_set_size((vec), cv_erase_sz__ - 1); \
cvector_clib_memmove( \
(vec) + (i), \
(vec) + (i) + 1, \
sizeof(*(vec)) * (cv_erase_sz__ - 1 - (i))); \
} \
} \
} while (0)
/**
* @brief cvector_clear - erase all of the elements in the vector
* @param vec - the vector
* @return void
*/
#define cvector_clear(vec) \
do { \
if (vec) { \
cvector_elem_destructor_t cv_clear_elem_dtor__ = cvector_elem_destructor(vec); \
if (cv_clear_elem_dtor__) { \
size_t cv_clear_i__; \
for (cv_clear_i__ = 0; cv_clear_i__ < cvector_size(vec); ++cv_clear_i__) { \
cv_clear_elem_dtor__(&(vec)[cv_clear_i__]); \
} \
} \
cvector_set_size(vec, 0); \
} \
} while (0)
/**
* @brief cvector_free - frees all memory associated with the vector
* @param vec - the vector
* @return void
*/
#define cvector_free(vec) \
do { \
if (vec) { \
void *cv_free_p__ = cvector_vec_to_base(vec); \
cvector_elem_destructor_t cv_free_elem_dtor__ = cvector_elem_destructor(vec); \
if (cv_free_elem_dtor__) { \
size_t cv_free_i__; \
for (cv_free_i__ = 0; cv_free_i__ < cvector_size(vec); ++cv_free_i__) { \
cv_free_elem_dtor__(&(vec)[cv_free_i__]); \
} \
} \
cvector_clib_free(cv_free_p__); \
} \
} while (0)
/**
* @brief cvector_begin - returns an iterator to first element of the vector
* @param vec - the vector
* @return a pointer to the first element (or NULL)
*/
#define cvector_begin(vec) \
(vec)
/**
* @brief cvector_end - returns an iterator to one past the last element of the vector
* @param vec - the vector
* @return a pointer to one past the last element (or NULL)
*/
#define cvector_end(vec) \
((vec) ? &((vec)[cvector_size(vec)]) : NULL)
/* user request to use linear growth algorithm */
#ifdef CVECTOR_LINEAR_GROWTH
/**
* @brief cvector_compute_next_grow - returns an the computed size in next vector grow
* size is increased by 1
* @param size - current size
* @return size after next vector grow
*/
#define cvector_compute_next_grow(size) \
((size) + 1)
#else
/**
* @brief cvector_compute_next_grow - returns an the computed size in next vector grow
* size is increased by multiplication of 2
* @param size - current size
* @return size after next vector grow
*/
#define cvector_compute_next_grow(size) \
((size) ? ((size) << 1) : 1)
#endif /* CVECTOR_LINEAR_GROWTH */
/**
* @brief cvector_push_back - adds an element to the end of the vector
* @param vec - the vector
* @param value - the value to add
* @return void
*/
#define cvector_push_back(vec, value) \
do { \
size_t cv_push_back_cap__ = cvector_capacity(vec); \
if (cv_push_back_cap__ <= cvector_size(vec)) { \
cvector_grow((vec), cvector_compute_next_grow(cv_push_back_cap__)); \
} \
(vec)[cvector_size(vec)] = (value); \
cvector_set_size((vec), cvector_size(vec) + 1); \
} while (0)
/**
* @brief cvector_insert - insert element at position pos to the vector
* @param vec - the vector
* @param pos - position in the vector where the new elements are inserted.
* @param val - value to be copied (or moved) to the inserted elements.
* @return void
*/
#define cvector_insert(vec, pos, val) \
do { \
size_t cv_insert_cap__ = cvector_capacity(vec); \
if (cv_insert_cap__ <= cvector_size(vec)) { \
cvector_grow((vec), cvector_compute_next_grow(cv_insert_cap__)); \
} \
if ((pos) < cvector_size(vec)) { \
cvector_clib_memmove( \
(vec) + (pos) + 1, \
(vec) + (pos), \
sizeof(*(vec)) * ((cvector_size(vec)) - (pos))); \
} \
(vec)[(pos)] = (val); \
cvector_set_size((vec), cvector_size(vec) + 1); \
} while (0)
/**
* @brief cvector_pop_back - removes the last element from the vector
* @param vec - the vector
* @return void
*/
#define cvector_pop_back(vec) \
do { \
cvector_elem_destructor_t cv_pop_back_elem_dtor__ = cvector_elem_destructor(vec); \
if (cv_pop_back_elem_dtor__) { \
cv_pop_back_elem_dtor__(&(vec)[cvector_size(vec) - 1]); \
} \
cvector_set_size((vec), cvector_size(vec) - 1); \
} while (0)
/**
* @brief cvector_copy - copy a vector
* @param from - the original vector
* @param to - destination to which the function copy to
* @return void
*/
#define cvector_copy(from, to) \
do { \
if ((from)) { \
cvector_grow(to, cvector_size(from)); \
cvector_set_size(to, cvector_size(from)); \
cvector_clib_memcpy((to), (from), cvector_size(from) * sizeof(*(from))); \
} \
} while (0)
/**
* @brief cvector_swap - exchanges the content of the vector by the content of another vector of the same type
* @param vec - the original vector
* @param other - the other vector to swap content with
* @param type - the type of both vectors
* @return void
*/
#define cvector_swap(vec, other, type) \
do { \
if (vec && other) { \
cvector_vector_type(type) cv_swap__ = vec; \
vec = other; \
other = cv_swap__; \
} \
} while (0)
/**
* @brief cvector_set_capacity - For internal use, sets the capacity variable of the vector
* @param vec - the vector
* @param size - the new capacity to set
* @return void
* @internal
*/
#define cvector_set_capacity(vec, size) \
do { \
if (vec) { \
cvector_vec_to_base(vec)->capacity = (size); \
} \
} while (0)
/**
* @brief cvector_set_size - For internal use, sets the size variable of the vector
* @param vec - the vector
* @param _size - the new capacity to set
* @return void
* @internal
*/
#define cvector_set_size(vec, _size) \
do { \
if (vec) { \
cvector_vec_to_base(vec)->size = (_size); \
} \
} while (0)
/**
* @brief cvector_set_elem_destructor - set the element destructor function
* used to clean up removed elements. The vector must NOT be NULL for this to do anything.
* @param vec - the vector
* @param elem_destructor_fn - function pointer of type cvector_elem_destructor_t used to destroy elements
* @return void
*/
#define cvector_set_elem_destructor(vec, elem_destructor_fn) \
do { \
if (vec) { \
cvector_vec_to_base(vec)->elem_destructor = (elem_destructor_fn); \
} \
} while (0)
/**
* @brief cvector_grow - For internal use, ensures that the vector is at least `count` elements big
* @param vec - the vector
* @param count - the new capacity to set
* @return void
* @internal
*/
#define cvector_grow(vec, count) \
do { \
const size_t cv_grow_sz__ = (count) * sizeof(*(vec)) + sizeof(cvector_metadata_t); \
if (vec) { \
void *cv_grow_p1__ = cvector_vec_to_base(vec); \
void *cv_grow_p2__ = cvector_clib_realloc(cv_grow_p1__, cv_grow_sz__); \
cvector_clib_assert(cv_grow_p2__); \
(vec) = cvector_base_to_vec(cv_grow_p2__); \
} else { \
void *cv_grow_p__ = cvector_clib_malloc(cv_grow_sz__); \
cvector_clib_assert(cv_grow_p__); \
(vec) = cvector_base_to_vec(cv_grow_p__); \
cvector_set_size((vec), 0); \
cvector_set_elem_destructor((vec), NULL); \
} \
cvector_set_capacity((vec), (count)); \
} while (0)
/**
* @brief cvector_shrink_to_fit - requests the container to reduce its capacity to fit its size
* @param vec - the vector
* @return void
*/
#define cvector_shrink_to_fit(vec) \
do { \
if (vec) { \
const size_t cv_shrink_to_fit_sz__ = cvector_size(vec); \
cvector_grow(vec, cv_shrink_to_fit_sz__); \
} \
} while (0)
/**
* @brief cvector_at - returns a reference to the element at position n in the vector.
* @param vec - the vector
* @param n - position of an element in the vector.
* @return the element at the specified position in the vector.
*/
#define cvector_at(vec, n) \
((vec) ? (((int)(n) < 0 || (size_t)(n) >= cvector_size(vec)) ? NULL : &(vec)[n]) : NULL)
/**
* @brief cvector_front - returns a reference to the first element in the vector. Unlike member cvector_begin, which returns an iterator to this same element, this function returns a direct reference.
* @param vec - the vector
* @return a reference to the first element in the vector container.
*/
#define cvector_front(vec) \
((vec) ? ((cvector_size(vec) > 0) ? cvector_at(vec, 0) : NULL) : NULL)
/**
* @brief cvector_back - returns a reference to the last element in the vector.Unlike member cvector_end, which returns an iterator just past this element, this function returns a direct reference.
* @param vec - the vector
* @return a reference to the last element in the vector.
*/
#define cvector_back(vec) \
((vec) ? ((cvector_size(vec) > 0) ? cvector_at(vec, cvector_size(vec) - 1) : NULL) : NULL)
/**
* @brief cvector_resize - resizes the container to contain count elements.
* @param vec - the vector
* @param count - new size of the vector
* @param value - the value to initialize new elements with
* @return void
*/
#define cvector_resize(vec, count, value) \
do { \
size_t cv_resize_count__ = (size_t)(count); \
size_t cv_resize_sz__ = cvector_size(vec); \
if (cv_resize_count__ > cv_resize_sz__) { \
cvector_reserve((vec), cv_resize_count__); \
cvector_set_size((vec), cv_resize_count__); \
do { \
(vec)[cv_resize_sz__++] = (value); \
} while (cv_resize_sz__ < cv_resize_count__); \
} else { \
while (cv_resize_count__ < cv_resize_sz__--) { \
cvector_pop_back(vec); \
} \
} \
} while (0)
#endif /* CVECTOR_H_ */

35
src/cvector_utils.h Normal file
View file

@ -0,0 +1,35 @@
#ifndef CVECTOR_UTILS_H_
#define CVECTOR_UTILS_H_
/**
* @copyright Copyright (c) 2022 Evan Teran,
* License: The MIT License (MIT)
* @brief extends the cvector library
* @file cvector_utils.h
*/
/**
* @brief cvector_for_each_in - for header to iterate over vector each element's address
* @param it - iterator of type pointer to vector element
* @param vec - the vector
* @return void
*/
#define cvector_for_each_in(it, vec) \
for (it = cvector_begin(vec); it < cvector_end(vec); it++)
/**
* @brief cvector_for_each - call function func on each element of the vector
* @param vec - the vector
* @param func - function to be called on each element that takes each element as argument
* @return void
*/
#define cvector_for_each(vec, func) \
do { \
if ((vec) && (func) != NULL) { \
size_t i; \
for (i = 0; i < cvector_size(vec); i++) { \
func((vec)[i]); \
} \
} \
} while (0)
#endif /* CVECTOR_UTILS_H_ */

File diff suppressed because it is too large Load diff

View file

@ -17,6 +17,7 @@
#include "d_net.h"
#include "d_netcmd.h"
#include "d_net.h"
#include "doomdef.h"
#include "tables.h"
#include "d_player.h"
#include "mserv.h"
@ -41,6 +42,8 @@ applications may follow different packet versions.
// one that defines the actual packets to
// be transmitted.
#define HU_MAXMSGLEN 223
#define MAXSERVERNAME 32
#define MAXSERVERCONTACT 350
#define MAXSERVERDESCRIPTION 1024
@ -132,9 +135,27 @@ typedef enum
PT_PING, // Packet sent to tell clients the other client's latency to server.
PT_SERVERINFOUPDATE, // Update server info for clients.
PT_SAY, // "Hey server, please send this chat message to everyone via XD_SAY"
PT_REQMAPQUEUE, // Client requesting a roundqueue operation
PT_CLIENTKEY, // "Here's my public key"
PT_SERVERCHALLENGE, // "Prove it"
PT_CHALLENGEALL, // Prove to the other clients you are who you say you are, sign this random bullshit!
PT_RESPONSEALL, // OK, here is my signature on that random bullshit
PT_RESULTSALL, // Here's what everyone responded to PT_CHALLENGEALL with, if this is wrong or you don't receive it disconnect
NUMPACKETTYPE
} packettype_t;
typedef enum
{
SIGN_OK,
SIGN_BADTIME, // Timestamp differs by too much, suspect reuse of an old challenge.
SIGN_BADIP // Asked to sign the wrong IP by an external host, suspect reuse of another server's challenge.
} shouldsign_t;
typedef struct consistancy_s
{
INT16 checksum; // Total consistancy checksum
@ -166,9 +187,7 @@ void SPrintConsistancy(char *out, consistancy_t *c);
void Command_Drop(void);
void Command_Droprate(void);
#endif
#ifdef _DEBUG
void Command_Numnodes(void);
#endif
// Client to server packet
struct clientcmd_pak
@ -242,10 +261,6 @@ struct serverconfig_pak
UINT8 maxplayer;
boolean allownewplayer;
boolean discordinvites;
char server_name[MAXSERVERNAME];
char server_contact[MAXSERVERCONTACT];
char server_description[MAXSERVERDESCRIPTION];
} ATTRPACK;
struct filetx_pak
@ -285,6 +300,7 @@ struct clientconfig_pak
UINT8 mode;
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME];
UINT8 availabilities[MAXAVAILABILITY];
uint8_t challengeResponse[MAXSPLITSCREENPLAYERS][SIGNATURELENGTH];
} ATTRPACK;
#define SV_SPEEDMASK 0x03 // used to send kartspeed
@ -371,6 +387,40 @@ struct filesneededconfig_pak
UINT8 files[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
} ATTRPACK;
struct reqmapqueue_pak
{
UINT16 newmapnum;
UINT16 newgametype;
UINT8 flags;
UINT8 source;
} ATTRPACK;
struct clientkey_pak
{
uint8_t key[MAXSPLITSCREENPLAYERS][PUBKEYLENGTH];
} ATTRPACK;
struct serverchallenge_pak
{
uint8_t secret[CHALLENGELENGTH];
} ATTRPACK;
struct challengeall_pak
{
uint8_t secret[CHALLENGELENGTH];
} ATTRPACK;
struct responseall_pak
{
uint8_t signature[MAXSPLITSCREENPLAYERS][SIGNATURELENGTH];
} ATTRPACK;
struct resultsall_pak
{
// Maybe use a FAM in the future for space saving?
uint8_t signature[MAXPLAYERS][SIGNATURELENGTH];
} ATTRPACK;
struct netinfo_pak
{
UINT32 pingtable[MAXPLAYERS+1];
@ -378,6 +428,14 @@ struct netinfo_pak
UINT32 delay[MAXPLAYERS+1];
} ATTRPACK;
struct say_pak
{
char message[HU_MAXMSGLEN + 1];
UINT8 target;
UINT8 flags;
UINT8 source;
} ATTRPACK;
//
// Network packet data
//
@ -388,31 +446,42 @@ struct doomdata_t
UINT8 ackreturn; // The return of the ack number
UINT8 packettype;
#ifdef SIGNGAMETRAFFIC
uint8_t signature[MAXSPLITSCREENPLAYERS][SIGNATURELENGTH];
#endif
UINT8 packetindex;
union
{
clientcmd_pak clientpak;
client2cmd_pak client2pak;
client3cmd_pak client3pak;
client4cmd_pak client4pak;
servertics_pak serverpak;
serverconfig_pak servercfg;
UINT8 textcmd[MAXTEXTCMD+1];
char filetxpak[sizeof (filetx_pak)];
char fileack[sizeof (fileack_pak)];
UINT8 filereceived;
clientconfig_pak clientcfg;
char salt[9];
UINT8 sha256sum[32];
serverinfo_pak serverinfo;
serverrefuse_pak serverrefuse;
serverinfoupdate_pak serverinfoupdate;
askinfo_pak askinfo;
msaskinfo_pak msaskinfo;
plrinfo playerinfo[MAXPLAYERINFO];
INT32 filesneedednum;
filesneededconfig_pak filesneededcfg;
netinfo_pak netinfo;
// NOTICE: UPDATE THE COMMENT SIZES WHEN YOU CHANGE STUFF.
clientcmd_pak clientpak; // 96 bytes
client2cmd_pak client2pak; // 110 bytes
client3cmd_pak client3pak; // 124 bytes
client4cmd_pak client4pak; // 138 bytes
servertics_pak serverpak; // 633 bytes
serverconfig_pak servercfg; // 33 bytes
UINT8 textcmd[MAXTEXTCMD+1]; // 257 bytes
char filetxpak[sizeof (filetx_pak)]; // 12 bytes
char fileack[sizeof (fileack_pak)]; // 3 bytes
UINT8 filereceived; // 1 byte
clientconfig_pak clientcfg; // 378 bytes
char salt[9]; // 9 bytes
UINT8 sha256sum[32]; // 32 bytes
serverinfo_pak serverinfo; // 1311 bytes
serverrefuse_pak serverrefuse; // 255 bytes
serverinfoupdate_pak serverinfoupdate; // 1406 bytes
askinfo_pak askinfo; // 5 bytes
msaskinfo_pak msaskinfo; // 26 bytes
plrinfo playerinfo[MAXPLAYERINFO]; // 1056 bytes
INT32 filesneedednum; // 4 bytes
filesneededconfig_pak filesneededcfg; // 921 bytes
netinfo_pak netinfo; // 396 bytes
say_pak say; // 227 bytes
reqmapqueue_pak reqmapqueue; // 6 bytes. Formerly XD_REQMAPQUEUE
clientkey_pak clientkey; // 32 bytes
serverchallenge_pak serverchallenge; // 256 bytes
challengeall_pak challengeall; // 256 bytes
responseall_pak responseall; // 256 bytes
resultsall_pak resultsall; // 1024 bytes (2048 bytes in 32P)
} u; // This is needed to pack diff packet types data together
} ATTRPACK;
@ -454,6 +523,7 @@ extern consvar_t cv_serverinfoscreen;
#define KICK_MSG_GRIEF 7
#define KICK_MSG_CUSTOM_KICK 8
#define KICK_MSG_CUSTOM_BAN 9
#define KICK_MSG_SIGFAIL 10
typedef enum
{
@ -481,9 +551,18 @@ extern char connectedservername[MAXSERVERNAME];
extern char connectedservercontact[MAXSERVERCONTACT];
extern char connectedserverdescription[MAXSERVERDESCRIPTION];
extern UINT32 ourIP;
extern uint8_t lastReceivedKey[MAXNETNODES][MAXSPLITSCREENPLAYERS][PUBKEYLENGTH];
extern uint8_t lastSentChallenge[MAXNETNODES][CHALLENGELENGTH];
extern uint8_t lastChallengeAll[CHALLENGELENGTH];
extern uint8_t lastReceivedSignature[MAXPLAYERS][SIGNATURELENGTH];
extern uint8_t knownWhenChallenged[MAXPLAYERS][PUBKEYLENGTH];
extern boolean expectChallenge;
void Command_Ping_f(void);
extern tic_t connectiontimeout;
extern tic_t jointimeout;
extern tic_t freezetimeout[MAXNETNODES];
extern UINT16 pingmeasurecount;
extern UINT32 realpingtable[MAXPLAYERS];
extern UINT32 playerpingtable[MAXPLAYERS];
@ -504,10 +583,25 @@ extern consvar_t cv_joinnextround;
extern consvar_t cv_discordinvites;
#ifdef DEVELOP
extern consvar_t cv_badjoin;
extern consvar_t cv_badtraffic;
extern consvar_t cv_badresponse;
extern consvar_t cv_noresponse;
extern consvar_t cv_nochallenge;
extern consvar_t cv_badresults;
extern consvar_t cv_noresults;
extern consvar_t cv_badtime;
extern consvar_t cv_badip;
#endif
// Used in d_net, the only dependence
tic_t ExpandTics(INT32 low, tic_t basetic);
void D_ClientServerInit(void);
void GenerateChallenge(uint8_t *buf);
shouldsign_t ShouldSignChallenge(uint8_t *message);
// Initialise the other field
void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum));
void SendNetXCmdForPlayer(UINT8 playerid, netxcmd_t id, const void *param, size_t nparam);
@ -534,6 +628,8 @@ typedef enum
CL_PREPAREHTTPFILES,
CL_DOWNLOADHTTPFILES,
#endif
CL_SENDKEY,
CL_WAITCHALLENGE,
} cl_mode_t;
// Create any new ticcmds and broadcast to other players.
@ -649,6 +745,21 @@ void CL_ClearRewinds(void);
rewind_t *CL_SaveRewindPoint(size_t demopos);
rewind_t *CL_RewindToTime(tic_t time);
void HandleSigfail(const char *string);
void DoSayPacket(SINT8 target, UINT8 flags, UINT8 source, char *message);
void DoSayPacketFromCommand(SINT8 target, size_t usedargs, UINT8 flags);
void SendServerNotice(SINT8 target, char *message);
// We give clients a chance to verify each other once per race.
// When is that challenge sent, and when should clients bail if they don't receive the responses?
#define CHALLENGEALL_START (TICRATE*10)
#define CHALLENGEALL_KICKUNRESPONSIVE (TICRATE*12)
#define CHALLENGEALL_SENDRESULTS (TICRATE*14)
#define CHALLENGEALL_CLIENTCUTOFF (TICRATE*16)
extern uint8_t awaitingChallenge[CHALLENGELENGTH]; // The message the server asked our client to sign when joining;
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -15,6 +15,7 @@
/// plus functions to parse command line parameters, configure game
/// parameters, and call the startup functions.
#include "g_mapnum.h"
#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
#include <sys/stat.h>
#include <sys/types.h>
@ -53,6 +54,7 @@
#include "p_saveg.h"
#include "r_main.h"
#include "r_local.h"
#include "r_voicepreference.hpp" // Preferences directory
#include "s_sound.h"
#include "st_stuff.h"
#include "v_video.h"
@ -73,6 +75,9 @@
#include "m_perfstats.h"
#include "core/memory.h"
#include "monocypher/monocypher.h"
#include "stun.h"
// SRB2Kart
#include "k_grandprix.h"
#include "k_boss.h"
@ -81,19 +86,24 @@
#include "m_random.h" // P_ClearRandom
#include "acs/interface.h"
#include "k_specialstage.h"
#include "k_vote.h"
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <tracy/tracy/Tracy.hpp>
#ifdef HAVE_SDL
#include <SDL3/SDL_filesystem.h>
#endif
// Put hashes here to get them out of header hell.
#define ASSET_HASH_SRB2_SRB 0xf3ec1ea4d0eca4a9
#define ASSET_HASH_GFX_KART 0xc91b0d43f5ba131f
#define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291
#define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b
#define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9
#define ASSET_HASH_MAIN_PK3 0x28ffde2e8c416914
#define ASSET_HASH_MAPS_KART 0x2be29dfb3a146dfa
#define ASSET_HASH_MAIN_PK3 0x4ea7e79e2d5d0d63
#define ASSET_HASH_MAPPATCH_PK3 0x1745690024efbaf8
#define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461
#ifdef USE_PATCH_FILE
@ -115,9 +125,9 @@
// Version numbers for netplay :upside_down_face:
int VERSION;
int SUBVERSION;
#ifdef COMMITVERSION
// #ifdef COMMITVERSION
UINT8 comprevision_abbrev_bin[GIT_SHA_ABBREV];
#endif
// #endif
#ifdef HAVE_DISCORDRPC
#include "discord.h"
@ -177,6 +187,10 @@ INT32 eventhead, eventtail;
boolean dedicated = false;
// For identity negotiation with netgame servers
uint8_t g_public_key[MAXSPLITSCREENPLAYERS][PUBKEYLENGTH];
uint8_t g_secret_key[MAXSPLITSCREENPLAYERS][PRIVKEYLENGTH];
boolean loaded_config = false;
//
@ -325,13 +339,12 @@ boolean D_RenderLevel(void)
if (r_splitscreen == 2) // Draw over the fourth screen so you don't have to stare at a HOM :V
{
// V_DrawPatchFill, but for the fourth screen only
patch_t *pat = static_cast<patch_t*>(W_CachePatchName("SRB2BACK", PU_CACHE));
INT32 x, y, pw = SHORT(pat->width) * vid.dup, ph = SHORT(pat->height) * vid.dup;
INT32 x, y, pw = SHORT(srb2back->width) * vid.dup, ph = SHORT(srb2back->height) * vid.dup;
for (x = vid.width>>1; x < vid.width; x += pw)
{
for (y = vid.height>>1; y < vid.height; y += ph)
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
V_DrawScaledPatch(x, y, V_NOSCALESTART, srb2back);
}
}
}
@ -644,7 +657,7 @@ static void D_Display(void)
else
py = viewwindowy + 4;
patch = static_cast<patch_t*>(W_CachePatchName("M_PAUSE", PU_PATCH));
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - patch->width)/2, py, 0, patch);
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - patch->width)/2, py, V_SNAPTOTOP, patch);
}
if (demo.rewinding)
@ -1172,7 +1185,7 @@ void D_StartTitle(void)
if (i > nummapheaders)
I_Error("D_StartTitle: No valid map ID found!?");
COM_BufAddText(va("map %s\n", G_BuildMapName(i)));
COM_BufAddText(va("map %s\n", G_BuildMapName((mapnum_t)(i))));
}
return;
@ -1200,8 +1213,9 @@ void D_StartTitle(void)
modeattacking = ATTACKING_NONE;
marathonmode = static_cast<marathonmode_t>(0);
// Reset GP
// Reset GP and roundqueue
memset(&grandprixinfo, 0, sizeof(struct grandprixinfo));
memset(&roundqueue, 0, sizeof(struct roundqueue));
// Reset Server mods
numcustomservermods = 0;
@ -1399,7 +1413,7 @@ static void IdentifyVersion(void)
#endif
}
#ifdef COMMITVERSION
// #ifdef COMMITVERSION
static void D_AbbrevCommit (void)
{
UINT8 i;
@ -1410,7 +1424,7 @@ static void D_AbbrevCommit (void)
&comprevision_abbrev_bin[i]);
}
}
#endif
// #endif
static void
D_ConvertVersionNumbers (void)
@ -1455,7 +1469,7 @@ void D_SRB2Main(void)
{
INT32 p;
INT32 pstartmap = 1;
mapnum_t pstartmap = (mapnum_t)1;
boolean autostart = false;
/* break the version string into version numbers, for netplay */
@ -1550,6 +1564,7 @@ void D_SRB2Main(void)
strcatbf(liveeventbackup, srb2home, PATHSEP);
snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", srb2home);
snprintf(preferencesdir, sizeof preferencesdir, "%s" PATHSEP "preferences" PATHSEP, srb2home);
#else // DEFAULTDIR
snprintf(srb2home, sizeof srb2home, "%s", userhome);
if (dedicated)
@ -1562,6 +1577,7 @@ void D_SRB2Main(void)
strcatbf(liveeventbackup, userhome, PATHSEP);
snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome);
snprintf(preferencesdir, sizeof preferencesdir, "%s" PATHSEP "preferences" PATHSEP, userhome);
#endif // DEFAULTDIR
}
@ -1782,6 +1798,8 @@ void D_SRB2Main(void)
//--------------------------------------------------------- CONFIG.CFG
M_FirstLoadConfig(); // WARNING : this do a "COM_BufExecute()"
R_LoadVoicePreferences();
VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen
// set user default mode or mode set at cmdline
@ -1865,6 +1883,57 @@ void D_SRB2Main(void)
ACS_Init();
CON_SetLoadingProgress(LOADED_ACSINIT);
// Read / create RRID key files in srb2home/private_keys
// About as obvious as I can make this say DONT SHARE.
#define RRIDWARNINGNAME "DO_NOT_SHARE_THESE"
#define RRIDWARNINGMESSAGE "This folder contains keys that should not be shared.\nThe base game and mods may use these to keep track of gamedata."
static char keyfile[MAXSPLITSCREENPLAYERS][10] = {"bkid1.dat", "bkid2.dat", "bkid3.dat", "bkid4.dat"};
INT32 snum;
for (snum = 0; snum < MAXSPLITSCREENPLAYERS; snum++)
{
char base_path[MAX_WADPATH];
char file[MAX_WADPATH];
strcpy(base_path, srb2home);
strcat(base_path, PATHSEP "private_keys" PATHSEP);
M_MkdirEach(base_path, M_PathParts(base_path) - 2, 0755);
strcpy(file, base_path);
strcat(file, keyfile[snum]);
static uint8_t seed[32];
csprng(seed, 32);
crypto_eddsa_key_pair(g_secret_key[snum], g_public_key[snum], seed);
int sk_size = sizeof(g_secret_key[snum]);
int pk_size = sizeof(g_public_key[snum]);
int totalsize = sk_size + pk_size;
if (FIL_ReadFileOK(file))
{
UINT8 *readbuffer = NULL;
UINT16 lengthRead = FIL_ReadFile(file, &readbuffer);
if (readbuffer == NULL || lengthRead != totalsize)
I_Error("Malformed keyfile %d", snum);
memcpy(g_secret_key[snum], readbuffer, sk_size);
memcpy(g_public_key[snum], readbuffer + sk_size, pk_size);
}
else
{
uint8_t *keybuffer = (uint8_t *)malloc(totalsize);
memcpy(keybuffer, g_secret_key[snum], sk_size);
memcpy(keybuffer + sk_size, g_public_key[snum], pk_size);
if (!FIL_WriteFile(file, keybuffer, totalsize))
I_Error("Couldn't open key file %d", snum);
if (!FIL_WriteFile(va("%s%s",base_path , RRIDWARNINGNAME), RRIDWARNINGMESSAGE, strlen(RRIDWARNINGMESSAGE)))
I_Error("Failed to create BKID warning file.");
free(keybuffer);
}
}
#undef RRIDWARNINGNAME
#undef RRIDWARNINGMESSAGE
//------------------------------------------------ COMMAND LINE PARAMS
// this must be done after loading gamedata,
@ -1901,14 +1970,13 @@ void D_SRB2Main(void)
// Start up a "minor" grand prix session
memset(&grandprixinfo, 0, sizeof(struct grandprixinfo));
memset(&roundqueue, 0, sizeof(struct roundqueue));
grandprixinfo.gamespeed = KARTSPEED_HARD;
grandprixinfo.encore = false;
grandprixinfo.masterbots = false;
grandprixinfo.lunaticmode = false;
grandprixinfo.gp = true;
grandprixinfo.roundnum = 0;
grandprixinfo.cup = NULL;
grandprixinfo.wonround = false;
@ -2006,7 +2074,7 @@ void D_SRB2Main(void)
// rei/miru: bootmap (Idea: starts the game on a predefined map)
if (bootmap && !(M_CheckParm("-warp") && M_IsNextParm()))
{
pstartmap = G_MapNumber(bootmap)+1;
pstartmap = (mapnum_t)(G_MapNumber(bootmap)+1);
if (pstartmap > nummapheaders)
{

View file

@ -64,6 +64,9 @@ extern char srb2path[256]; //Alam: SRB2's Home
const char *D_GetFancyBranchName(void);
extern uint8_t g_public_key[MAXSPLITSCREENPLAYERS][PUBKEYLENGTH];
extern uint8_t g_secret_key[MAXSPLITSCREENPLAYERS][PRIVKEYLENGTH];
// the infinite loop of D_SRB2Loop() called from win_main for windows version
void D_SRB2Loop(void) FUNCNORETURN;

View file

@ -31,6 +31,7 @@
#include "d_main.h" // srb2home
#include "stun.h"
#include "byteptr.h"
#include "monocypher/monocypher.h"
#include "qs22j.h"
@ -81,6 +82,7 @@ boolean (*I_NetOpenSocket)(void) = NULL;
boolean (*I_Ban) (INT32 node) = NULL;
void (*I_ClearBans)(void) = NULL;
const char *(*I_GetNodeAddress) (INT32 node) = NULL;
UINT32 (*I_GetNodeAddressInt) (INT32 node) = NULL;
const char *(*I_GetBanAddress) (size_t ban) = NULL;
const char *(*I_GetBanMask) (size_t ban) = NULL;
const char *(*I_GetBanUsername) (size_t ban) = NULL;
@ -90,6 +92,7 @@ boolean (*I_SetBanAddress) (const char *address, const char *mask) = NULL;
boolean (*I_SetBanUsername) (const char *username) = NULL;
boolean (*I_SetBanReason) (const char *reason) = NULL;
boolean (*I_SetUnbanTime) (time_t timestamp) = NULL;
boolean (*I_IsExternalAddress) (const void *p) = NULL;
bannednode_t *bannednode = NULL;
@ -470,7 +473,12 @@ static void InitAck(void)
ackpak[i].acknum = 0;
for (i = 0; i < MAXNETNODES; i++)
{
InitNode(&nodes[i]);
csprng(lastSentChallenge[i], sizeof(lastSentChallenge[i]));
csprng(lastReceivedKey[i], sizeof(lastReceivedKey[i]));
}
}
/** Removes all acks of a given packet type
@ -547,6 +555,9 @@ void Net_CloseConnection(INT32 node)
if (server)
SV_AbortLuaFileTransfer(node);
I_NetFreeNodenum(node);
csprng(lastSentChallenge[node], sizeof(lastSentChallenge[node]));
csprng(lastReceivedKey[node], sizeof(lastReceivedKey[node]));
}
//
@ -647,12 +658,31 @@ static const char *packettypename[NUMPACKETTYPE] =
"TEXTCMD2",
"TEXTCMD3",
"TEXTCMD4",
"TELLFILESNEEDED",
"MOREFILESNEEDED",
"CLIENTJOIN",
"NODETIMEOUT",
"LOGIN",
"LOGINCHALLENGE",
"LOGINAUTH",
"PING"
"PING",
"SERVERINFOUPDATE",
"SAY",
"REQMAPQUEUE",
"CLIENTKEY",
"SERVERCHALLENGE",
"CHALLENGEALL",
"RESPONSEALL",
"RESULTSALL"
};
static void DebugPrintpacket(const char *header)
@ -835,6 +865,34 @@ static boolean ShouldDropPacket(void)
}
#endif
// Unused because Eidolon correctly pointed out that +512b on every packet was scary.
#ifdef SIGNGAMETRAFFIC
boolean IsPacketSigned(int packettype)
{
switch (packettype)
{
case PT_CLIENTCMD:
case PT_CLIENT2CMD:
case PT_CLIENT3CMD:
case PT_CLIENT4CMD:
case PT_CLIENTMIS:
case PT_CLIENT2MIS:
case PT_CLIENT3MIS:
case PT_CLIENT4MIS:
case PT_TEXTCMD:
case PT_TEXTCMD2:
case PT_TEXTCMD3:
case PT_TEXTCMD4:
case PT_LOGIN:
case PT_ASKLUAFILE:
case PT_SENDINGLUAFILE:
return true;
default:
return false;
}
}
#endif
//
// HSendPacket
//
@ -842,6 +900,36 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
doomcom->datalength = (INT16)(packetlength + BASEPACKETSIZE);
#ifdef SIGNGAMETRAFFIC
if (IsPacketSigned(netbuffer->packettype))
{
int i;
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
const void* message = &netbuffer->u;
//CONS_Printf("Signing packet type %d of length %d\n", netbuffer->packettype, packetlength);
crypto_eddsa_sign(netbuffer->signature[i], g_secret_key[i], message, packetlength);
}
#ifdef DEVELOP
if (cv_badtraffic.value)
{
CV_AddValue(&cv_badtraffic, -1);
CONS_Alert(CONS_WARNING, "cv_badtraffic enabled, scrubbing signature from HSendPacket\n");
memset(netbuffer->signature, 0, sizeof(netbuffer->signature));
}
#endif
}
else
{
//CONS_Printf("NOT signing PT_%d of length %d, it doesn't need to be\n", netbuffer->packettype, packetlength);
memset(netbuffer->signature, 0, sizeof(netbuffer->signature));
}
#endif
if (node == 0) // Packet is to go back to us
{
if ((rebound_head+1) % MAXREBOUND == rebound_tail)
@ -1154,7 +1242,12 @@ boolean D_CheckNetGame(void)
I_Error("usage: -bandwidth <byte_per_sec>");
}
#if 0
software_MAXPACKETLENGTH = hardware_MAXPACKETLENGTH;
#else
// MTU, IPV4, UDP header.
software_MAXPACKETLENGTH = 1500 - 20 - 8;
#endif
if (M_CheckParm("-packetsize"))
{
if (M_IsNextParm())

View file

@ -51,6 +51,7 @@ extern SINT8 nodetoplayer3[MAXNETNODES]; // Say the numplayer for this node if a
extern SINT8 nodetoplayer4[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen == 3)
extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
extern boolean nodeneedsauth[MAXNETNODES];
extern boolean serverrunning;
@ -72,6 +73,8 @@ void Net_AbortPacketType(UINT8 packettype);
void Net_SendAcks(INT32 node);
void Net_WaitAllAckReceived(UINT32 timeout);
boolean IsPacketSigned(int packettype);
#ifdef __cplusplus
} // extern "C"
#endif

File diff suppressed because it is too large Load diff

View file

@ -16,11 +16,17 @@
#define __D_NETCMD__
#include "command.h"
#include "g_mapnum.h"
#ifdef __cplusplus
extern "C" {
#endif
// Big overshoot
#define PREFLISTSIZE (4096)
extern char prefvoiceliststr[PREFLISTSIZE];
extern consvar_t cv_showgremlins;
// console vars
@ -29,7 +35,7 @@ extern consvar_t cv_playercolor[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_skin[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_follower[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_followercolor[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_voice[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_autovoxpref[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_dummyrestatspeed[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_dummyrestatweight[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_dummyrestatrandom[MAXSPLITSCREENPLAYERS];
@ -188,11 +194,9 @@ extern consvar_t cv_kartstacking_ssmt_speedboost;
extern consvar_t cv_kartstacking_ssmt_accelboost;
extern consvar_t cv_kartstacking_ssmt_handleboost;
extern consvar_t cv_kartstacking_recspin_speedboost_lo;
extern consvar_t cv_kartstacking_recspin_accelboost_lo;
extern consvar_t cv_kartstacking_recspin_handleboost_lo;
extern consvar_t cv_kartstacking_recspin_speedboost_hi;
extern consvar_t cv_kartstacking_recspin_accelboost_hi;
extern consvar_t cv_kartstacking_recspin_handleboost_hi;
@ -235,6 +239,9 @@ extern consvar_t cv_kartbubble_boost_allow;
extern consvar_t cv_kartbubble_boost_offroadignore;
extern consvar_t cv_kartflame_fastfuel;
extern consvar_t cv_kartflame_offroadburn;
extern consvar_t cv_kartattraction_assistpower;
extern consvar_t cv_kartattraction_aoedmg;
extern consvar_t cv_kartattraction_aoeemp;
extern consvar_t cv_kartaltshrink_arrowbullet;
extern consvar_t cv_kartaltshrink_arrowbulletthres;
@ -255,6 +262,8 @@ extern consvar_t cv_kartitemlitter, cv_kartitempush;
extern consvar_t cv_kartantibump;
extern consvar_t cv_trailslow;
extern consvar_t cv_kartforcelegacyodds;
extern consvar_t cv_handleboostslip;
@ -262,6 +271,8 @@ extern consvar_t cv_handleboostslip;
extern consvar_t cv_kartrecoverydash;
extern consvar_t cv_kartrecoverydash_spinspeed;
extern consvar_t cv_kartkeepstuff;
extern consvar_t cv_kartoddsdist;
extern consvar_t cv_kartlegacyoddsdist;
@ -322,6 +333,8 @@ extern consvar_t cv_schedule;
extern consvar_t cv_debugmappatch;
extern consvar_t cv_allowmismatchmappatch;
extern char timedemo_name[256];
extern boolean timedemo_csv;
extern char timedemo_csv_id[256];
@ -369,6 +382,7 @@ typedef enum
XD_SCHEDULECLEAR, // 36
XD_AUTOMATE, // 37
XD_CHEAT, // 38
XD_MAPQUEUE, // 39
MAXNETXCMD
} netxcmd_t;
@ -411,7 +425,7 @@ void D_SendPlayerConfig(UINT8 n);
void Command_ExitGame_f(void);
void Command_Retry_f(void);
void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore
void D_MapChange(INT32 pmapnum, INT32 pgametype, boolean pencoremode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pfromlevelselect);
void D_MapChange(mapnum_t pmapnum, INT32 pgametype, boolean pencoremode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pforcespecialstage);
void D_SetupVote(void);
void D_ModifyClientVote(UINT8 player, SINT8 voted);
void D_PickVote(void);
@ -447,6 +461,9 @@ typedef enum
AEV_ROUNDSTART,
AEV_INTERMISSIONSTART,
AEV_VOTESTART,
AEV_QUEUESTART,
AEV_QUEUEEND,
AEV_LEVELSTART,
AEV__MAX
} automateEvents_t;

View file

@ -52,6 +52,8 @@
#include "m_misc.h"
#include "m_menu.h"
#include "filesrch.h"
#include "stun.h"
#include <errno.h>
@ -1339,6 +1341,45 @@ void PT_FileReceived(SINT8 node)
SV_EndFileSend(doomcom->remotenode);
}
// Someone knocked on the door with their public key.
// Give them a challenge to sign in their PT_CLIENTJOIN.
void PT_ClientKey(INT32 node)
{
if (!server)
return;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
clientkey_pak *packet = (void*)&netbuffer->u.clientkey;
memcpy(lastReceivedKey[node], packet->key, sizeof(lastReceivedKey[node]));
netbuffer->packettype = PT_SERVERCHALLENGE;
GenerateChallenge(lastSentChallenge[node]);
memcpy(&netbuffer->u.serverchallenge, lastSentChallenge[node], sizeof(serverchallenge_pak));
HSendPacket(node, true, 0, sizeof (serverchallenge_pak));
// Client's not in the server yet, but we still need to lock up the node.
// Otherwise, someone else could request a challenge on the same node and trash it.
nodeneedsauth[node] = true;
freezetimeout[node] = I_GetTime() + jointimeout;
}
void PT_ServerChallenge(INT32 node, cl_mode_t *cl_mode)
{
if (server && serverrunning && node != servernode)
{
Net_CloseConnection(node);
return;
}
if (*cl_mode != CL_WAITCHALLENGE)
return;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
memcpy(awaitingChallenge, netbuffer->u.serverchallenge.secret, sizeof(awaitingChallenge));
*cl_mode = CL_ASKJOIN;
}
static void SendAckPacket(fileack_pak *packet, UINT8 fileid)
{
size_t packetsize;
@ -1360,6 +1401,9 @@ static void SendAckPacket(fileack_pak *packet, UINT8 fileid)
memcpy(&netbuffer->u.fileack, packet, packetsize);
HSendPacket(servernode, false, 0, packetsize);
CONS_Printf("Sending file transfer ACKs for %d segments (time = %d, last sent %d)\n", packet->numsegments, I_GetTime(), lasttimeackpacketsent);
lasttimeackpacketsent = I_GetTime();
// Clear the packet
memset(packet, 0, sizeof(*packet) + 512);
}
@ -1423,6 +1467,23 @@ void FileReceiveTicker(void)
}
}
static void OpenNewFileForDownload(doomdata_t *netbuffer, fileneeded_t *file, const char *filename)
{
filetx_pak *pak = (void*)&netbuffer->u.filetxpak;
file->file = fopen(filename, "wb");
if (!file->file)
I_Error("Can't create file %s: %s", filename, strerror(errno));
file->currentsize = 0;
file->totalsize = LONG(pak->filesize);
file->ackresendposition = UINT32_MAX; // Only used for resumed downloads
file->receivedfragments = calloc(file->totalsize / file->fragmentsize + 1, sizeof(*file->receivedfragments));
if (!file->receivedfragments)
I_Error("FileSendTicker: No more memory\n");
}
void PT_FileFragment(SINT8 node, INT32 netconsole)
{
if (nodeingame[node])
@ -1499,13 +1560,22 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
{
file->file = fopen(filename, "r+b");
if (!file->file)
{
I_Error("Can't reopen file %s: %s", filename, strerror(errno));
CONS_Printf("\r%s...\n", filename);
CONS_Printf("Resuming download...\n");
file->currentsize = pauseddownload->currentsize;
file->receivedfragments = pauseddownload->receivedfragments;
file->ackresendposition = 0;
free(pauseddownload->receivedfragments);
CONS_Printf("Restarting download of file \"%s\"...\n", filename);
OpenNewFileForDownload(netbuffer, file, file->filename);
}
else
{
CONS_Printf("Resuming download of file \"%s\"...\n", filename);
file->currentsize = pauseddownload->currentsize;
file->receivedfragments = pauseddownload->receivedfragments;
file->ackresendposition = 0;
}
free(pauseddownload);
pauseddownload = NULL;
@ -1513,20 +1583,8 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
else
{
CL_AbortDownloadResume();
file->file = fopen(filename, "wb");
if (!file->file)
I_Error("Can't create file %s: %s", filename, strerror(errno));
CONS_Printf("\r%s...\n",filename);
file->currentsize = 0;
file->totalsize = LONG(pak->filesize);
file->ackresendposition = UINT32_MAX; // Only used for resumed downloads
file->receivedfragments = calloc(file->totalsize / fragmentsize + 1, sizeof(*file->receivedfragments));
if (!file->receivedfragments)
I_Error("FileSendTicker: No more memory\n");
OpenNewFileForDownload(netbuffer, file, file->filename);
CONS_Printf("Downloading file \"%s\" from the server...\n", filename);
}
lasttimeackpacketsent = I_GetTime();
@ -1539,10 +1597,14 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
file->iteration = max(file->iteration, pak->iteration);
CONS_Printf("Download %d/%d of \"%s\"...\n", file->currentsize, file->totalsize, filename);
if (!file->receivedfragments[fragmentpos / fragmentsize]) // Not received yet
{
file->receivedfragments[fragmentpos / fragmentsize] = true;
CONS_Printf("Received no. %d fragment (fragmentsize = %d, boundedfragmentsize = %d) \n", fragmentpos / fragmentsize, fragmentsize, boundedfragmentsize);
// We can receive packets in the wrong order, anyway all OSes support gaped files
fseek(file->file, fragmentpos, SEEK_SET);
if (fragmentsize && fwrite(pak->data, boundedfragmentsize, 1, file->file) != 1)
@ -1560,27 +1622,29 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
free(file->ackpacket);
file->status = FS_FOUND;
file->justdownloaded = true;
CONS_Printf(M_GetText("Downloading %s...(done)\n"),
filename);
// Tell the server we have received the file
netbuffer->packettype = PT_FILERECEIVED;
netbuffer->u.filereceived = filenum;
HSendPacket(servernode, true, 0, 1);
if (luafiletransfers)
{
// Tell the server we have received the file
netbuffer->packettype = PT_HASLUAFILE;
HSendPacket(servernode, true, 0, 0);
}
downloadcompletednum++;
downloadcompletedsize += file->totalsize;
CONS_Printf(M_GetText("Downloading %s...(done)\n"),
filename);
}
}
else // Already received
{
CONS_Printf("Re-Received no. %d fragment (fragmentsize = %d, boundedfragmentsize = %d) \n", fragmentpos / fragmentsize, fragmentsize, boundedfragmentsize);
// If they are sending us the fragment again, it's probably because
// they missed our previous ack, so we must re-acknowledge it
AddFragmentToAckPacket(file->ackpacket, file->iteration, fragmentpos / fragmentsize, filenum);

View file

@ -116,6 +116,10 @@ boolean CL_CheckDownloadable(void);
boolean CL_SendFileRequest(void);
void PT_RequestFile(INT32 node);
void PT_ClientKey(INT32 node);
void PT_ServerChallenge(INT32 node, cl_mode_t *cl_mode);
typedef enum
{
LFTNS_NONE, // This node is not connected

View file

@ -33,11 +33,14 @@
extern "C" {
#endif
typedef UINT16 kartvoicenum_t;
// Extra abilities/settings for skins (combinable stuff)
typedef enum
{
SF_MACHINE = 1, // Beep boop. Are you a robot?
SF_OLDDEATH = 1<<1, // Kart V1 styled death animation
SF_NOCOMPATROTATE = 1<<2, // Kart V1 skins that should not be rotated (simple animal, etc)
// free up to and including 1<<31
} skinflags_t;
@ -72,7 +75,9 @@ typedef enum
PF_GAINAX = 1<<3,
PF_KICKSTARTACCEL = 1<<4, // Accessibility feature: Is accelerate in kickstart mode?
// free: 1<<5 and 1<<6
// free: 1<<5
PF_NOSCALEGRAVITY = 1<<6, // Don't scale gravity by player object scale (cleared when grounded)
PF_WANTSTOJOIN = 1<<7, // Spectator that wants to join
@ -157,6 +162,7 @@ typedef enum
KSHIELD_THUNDER = 1,
KSHIELD_BUBBLE = 2,
KSHIELD_FLAME = 3,
KSHIELD_ATTRACTION = 4,
NUMKARTSHIELDS
} kartshields_t;
@ -487,6 +493,32 @@ typedef enum
LAP__MAX
} laptime_e;
typedef enum
{
KEEPSTUFF_ROCKET = 1,
KEEPSTUFF_INVIN = 1<<1,
KEEPSTUFF_SMON = 1<<2,
KEEPSTUFF_GROWSHRINK = 1<<3,
KEEPSTUFF_FLAME = 1<<4,
} keepstuffflags_t;
struct keepstuff_t
{
UINT16 flags;
UINT16 rocketsneakertimer;
UINT16 invincibilitytimer;
UINT16 smonitortimer;
UINT16 smonitorexpiring;
UINT16 maxsmonitortime;
INT16 growshrinktimer;
UINT16 flametimer;
};
// ========================================================================
// PLAYER STRUCTURE
// ========================================================================
@ -623,9 +655,13 @@ struct player_t
INT32 drift_wannaturn; // Turn values the game uses to determine the direction you want to drift.
INT32 nulldrift; // When you drift without accelerating, this value ticks up/down depending on your drift's angle.
INT32 nulldrifttilt; // Sliptide-like kart tilting! (Can be toggled off)
tic_t nulldrifttime;
fixed_t karttilt; // Generalized sliptide-like kart tilting as an angle_t (Can be toggled off by clients)
fixed_t karttiltmomentum; // angular velocity in rad/sec
SINT8 bumpyroadside; // last side lifted up by bumpy road
// (Delay-drift) - Delay in tics before the final drift angle is determined.
// Potentially influenced by player lag.
tic_t driftdelay;
@ -890,6 +926,10 @@ struct player_t
boolean walltransfered;
UINT8 walltransferboost;
uint8_t public_key[PUBKEYLENGTH];
keepstuff_t keepstuff;
#ifdef HWRENDER
fixed_t fovadd; // adjust FOV for hw rendering
#endif

View file

@ -64,17 +64,15 @@ typedef enum
// 16 bytes long now!
struct ticcmd_t
{
SINT8 forwardmove; // -MAXPLMOVE to MAXPLMOVE (50)
SINT8 sidemove; // -MAXPLMOVE to MAXPLMOVE (50)
INT16 turning; // Turn speed
SINT8 forwardmove; // -MAXPLMOVE to MAXPLMOVE (50) (has anticheat)
SINT8 sidemove; // -MAXPLMOVE to MAXPLMOVE (50) (has anticheat)
INT16 turning; // "Steering Wheel" turn speed when driving (has anticheat)
INT16 angle; // Predicted angle, use me if you can!
INT16 throwdir; // Aiming direction
INT16 throwdir; // Forwards/Backwards item use direction (has anticheat)
INT16 aiming; // vertical aiming, see G_BuildTicCmd
UINT16 buttons;
UINT8 latency; // Netgames: how many tics ago was this ticcmd generated from this player's end?
UINT8 flags;
SINT8 tilt;
UINT8 shake;
} ATTRPACK;
#ifdef __cplusplus

View file

@ -36,10 +36,6 @@
#include "d_clisrv.h"
#include "v_video.h"
#ifdef HWRENDER
#include "hardware/hw_light.h"
#endif
#include "m_cond.h"
#include "dehacked.h"
@ -519,77 +515,6 @@ void readskincolor(MYFILE *f, INT32 num, boolean mainfile)
Z_Free(s);
}
#ifdef HWRENDER
void readlight(MYFILE *f, INT32 num)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word;
char *tmp;
INT32 value;
float fvalue;
do
{
if (myfgets(s, MAXLINELEN, f))
{
if (s[0] == '\n')
break;
tmp = strchr(s, '#');
if (tmp)
*tmp = '\0';
if (s == tmp)
continue; // Skip comment lines, but don't break.
fvalue = searchfvalue(s);
value = searchvalue(s);
word = strtok(s, " ");
if (word)
strupr(word);
else
break;
if (fastcmp(word, "TYPE"))
{
lspr[num].type = (UINT16)value;
}
else if (fastcmp(word, "OFFSETX"))
{
lspr[num].light_xoffset = fvalue;
}
else if (fastcmp(word, "OFFSETY"))
{
lspr[num].light_yoffset = fvalue;
}
else if (fastcmp(word, "CORONACOLOR"))
{
lspr[num].corona_color = value;
}
else if (fastcmp(word, "CORONARADIUS"))
{
lspr[num].corona_radius = fvalue;
}
else if (fastcmp(word, "DYNAMICCOLOR"))
{
lspr[num].dynamic_color = value;
}
else if (fastcmp(word, "DYNAMICRADIUS"))
{
lspr[num].dynamic_radius = fvalue;
/// \note Update the sqrradius! unnecessary?
lspr[num].dynamic_sqrradius = fvalue * fvalue;
}
else
deh_warning("Light %d: unknown word '%s'", num, word);
}
} while (!myfeof(f)); // finish when the line is empty
Z_Free(s);
}
#endif // HWRENDER
void readsprite2(MYFILE *f, INT32 num)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
@ -790,7 +715,7 @@ void readgametype(MYFILE *f, char *gtname)
CONS_Printf("Added gametype %s\n", gtname);
}
static mapheader_lighting_t *usemaplighting(INT32 mapnum, const char *word)
static mapheader_lighting_t *usemaplighting(mapnum_t mapnum, const char *word)
{
if (fastncmp(word, "ENCORE", 6))
{
@ -853,7 +778,7 @@ if (fastcmp(word, name)) \
OUTOFRANGE_CONSTANT(name, word2, minname, maxname); \
}
static void processvector(const char* name, INT32 mapnum, char *word2, f_vector3_t *vec, float min, float max)
static void processvector(const char* name, mapnum_t mapnum, char *word2, f_vector3_t *vec, float min, float max)
{
char *tmp = strtok(word2,",");
float vector[3];
@ -878,7 +803,7 @@ static void processvector(const char* name, INT32 mapnum, char *word2, f_vector3
}
// Handle parsing globalefx info
static void globalmapefxparameters(INT32 mapnum, INT32 i, char *word, char *word2)
static void globalmapefxparameters(mapnum_t mapnum, INT32 i, char *word, char *word2)
{
// Take off GLOBALEFX_
word += 10;
@ -1068,7 +993,7 @@ void readlevelheader(MYFILE *f, char * name)
name = va("MAP%s", name);
}
INT32 num = G_MapNumber(name);
mapnum_t num = G_MapNumber(name);
if (num >= nummapheaders)
{
@ -1338,6 +1263,30 @@ void readlevelheader(MYFILE *f, char * name)
mapheaderinfo[num]->musname_size = j;
}
}
else if (fastcmp(word, "ENCOREMUSIC"))
{
if (fastcmp(word2, "NONE"))
{
mapheaderinfo[num]->encoremusname[0][0] = 0; // becomes empty string
mapheaderinfo[num]->encoremusname_size = 0;
}
else
{
UINT8 j = 0; // i was declared elsewhere
tmp = strtok(word2, ",");
do {
if (j >= MAXMUSNAMES)
break;
deh_strlcpy(mapheaderinfo[num]->encoremusname[j], tmp,
sizeof(mapheaderinfo[num]->encoremusname[j]), va("Level header %d: encore music", num));
j++;
} while ((tmp = strtok(NULL,",")) != NULL);
if (tmp != NULL)
deh_warning("Level header %d: additional music slots past %d discarded", num, MAXMUSNAMES);
mapheaderinfo[num]->encoremusname_size = j;
}
}
else if (fastcmp(word, "MUSICSLOT"))
deh_warning("Level header %d: MusicSlot parameter is deprecated and will be removed.\nUse \"Music\" instead.", num);
else if (fastcmp(word, "MUSICTRACK"))
@ -3166,7 +3115,7 @@ void readunlockable(MYFILE *f, INT32 num)
{
Z_Free(unlockables[num].stringVar);
unlockables[num].stringVar = Z_StrDup(word2);
unlockables[num].variable = (INT16)G_MapNumber(word2);
unlockables[num].variable = G_MapNumber(word2);
}
else
deh_warning("Unlockable %d: unknown word '%s'", num+1, word);
@ -3722,6 +3671,41 @@ void readmaincfg(MYFILE *f)
Z_Free(s);
}
//
// SRB2KART
//
static void invalidateacrosscups(UINT16 map)
{
cupheader_t *cup = kartcupheaders;
UINT8 i;
if (map >= nummapheaders)
return;
while (cup)
{
for (i = 0; i < CUPCACHE_MAX; i++)
{
if (cup->cachedlevels[i] != map)
continue;
cup->cachedlevels[i] = NEXTMAP_INVALID;
}
cup = cup->next;
}
mapheaderinfo[map]->cup = NULL;
}
static char *MapNameOrRemoval(char *name)
{
if (name[0] == '\0'
|| (name[0] == '/' && name[1] == '\0'))
return NULL;
return Z_StrDup(name);
}
void readwipes(MYFILE *f)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
@ -3931,7 +3915,7 @@ void readcupheader(MYFILE *f, cupheader_t *cup)
cup->levellist[cup->numlevels] = NULL;
if (cup->cachedlevels[cup->numlevels] == NEXTMAP_INVALID)
continue;
mapheaderinfo[cup->cachedlevels[cup->numlevels]]->cup = NULL;
invalidateacrosscups(cup->cachedlevels[cup->numlevels]);
}
tmp = strtok(word2,",");
@ -3949,9 +3933,32 @@ void readcupheader(MYFILE *f, cupheader_t *cup)
}
else if (fastcmp(word, "BONUSGAME"))
{
Z_Free(cup->levellist[CUPCACHE_BONUS]);
cup->levellist[CUPCACHE_BONUS] = Z_StrDup(word2);
cup->cachedlevels[CUPCACHE_BONUS] = NEXTMAP_INVALID;
while (cup->numbonus > 0)
{
cup->numbonus--;
Z_Free(cup->levellist[CUPCACHE_BONUS + cup->numbonus]);
cup->levellist[CUPCACHE_BONUS + cup->numbonus] = NULL;
if (cup->cachedlevels[CUPCACHE_BONUS + cup->numbonus] == NEXTMAP_INVALID)
continue;
invalidateacrosscups(cup->cachedlevels[CUPCACHE_BONUS + cup->numbonus]);
}
tmp = strtok(word2,",");
do {
if (cup->numbonus >= MAXBONUSLIST)
{
deh_warning("%s Cup: reached max bonus list (%d)\n", cup->name, MAXBONUSLIST);
break;
}
cup->levellist[CUPCACHE_BONUS + cup->numbonus] = MapNameOrRemoval(tmp);
cup->cachedlevels[CUPCACHE_BONUS + cup->numbonus] = NEXTMAP_INVALID;
if (cup->levellist[CUPCACHE_BONUS + cup->numbonus] == NULL)
break;
cup->numbonus++;
} while((tmp = strtok(NULL,",")) != NULL);
}
else if (fastcmp(word, "SPECIALSTAGE"))
{

View file

@ -37,10 +37,6 @@
#include "d_clisrv.h"
#include "k_items.h"
#ifdef HWRENDER
#include "hardware/hw_light.h"
#endif
#include "info.h"
#include "dehacked.h"
#include "doomdef.h" // HWRENDER
@ -80,9 +76,6 @@ void readcutscene(MYFILE *f, INT32 num);
void readlevelheader(MYFILE *f, char * name);
void readgametype(MYFILE *f, char *gtname);
void readsprite2(MYFILE *f, INT32 num);
#ifdef HWRENDER
void readlight(MYFILE *f, INT32 num);
#endif
void readskincolor(MYFILE *f, INT32 num, boolean mainfile);
void readthing(MYFILE *f, INT32 num);
void readfreeslots(MYFILE *f);

View file

@ -350,7 +350,7 @@ const char *const PLAYERFLAG_LIST[] = {
"GAINAX",
"KICKSTARTACCEL", // Accessibility feature: Is accelerate in kickstart mode?
"\x01",
"\x01",
"NOSCALEGRAVITY",
"WANTSTOJOIN", // Spectator that wants to join
@ -831,6 +831,7 @@ struct menu_routine_s const MENU_ROUTINES[] = {
{ "PLAYBACKSETVIEWS", &MR_PlaybackSetViews },
{ "PLAYBACKADJUSTVIEW", &MR_PlaybackAdjustView },
{ "PLAYBACKTOGGLEFREECAM", &MR_PlaybackToggleFreecam },
{ "PLAYBACKTOGGLEDIRECTOR", &MR_PlaybackToggleDirector },
{ "PLAYBACKQUIT", &MR_PlaybackQuit },
{ "HANDLEIMAGEDEF", &MR_HandleImageDef },
{ "HANDLEMUSICTEST", &MR_HandleMusicTest },
@ -1040,11 +1041,6 @@ struct int_const_s const INT_CONST[] = {
{"RF_DROPSHADOW",RF_DROPSHADOW},
{"RF_ABSOLUTELIGHTLEVEL",RF_ABSOLUTELIGHTLEVEL},
{"RF_HIDEINSKYBOX",RF_HIDEINSKYBOX},
#ifdef HWRENDER
{"RF_NOMODEL",RF_NOMODEL},
#else
{"RF_NOMODEL",0},
#endif
{"RF_NOAFFINE",RF_NOAFFINE},
{"RF_DONTDRAW",RF_DONTDRAW},
{"RF_DONTDRAWP1",RF_DONTDRAWP1},
@ -1579,6 +1575,7 @@ struct int_const_s const INT_CONST[] = {
{"GC_RESPAWN",gc_respawn},
{"GC_DIRECTOR",gc_director},
{"GC_HORNCODE",gc_horncode},
{"GC_FREELOOK",gc_freelook},
{"NUM_GAMECONTROLS",num_gamecontrols},
// screen.h constants
@ -1591,6 +1588,7 @@ struct int_const_s const INT_CONST[] = {
{"KSHIELD_LIGHTNING",KSHIELD_THUNDER},
{"KSHIELD_BUBBLE",KSHIELD_BUBBLE},
{"KSHIELD_FLAME",KSHIELD_FLAME},
{"KSHIELD_ATTRACTION",KSHIELD_ATTRACTION},
{"NUMKARTSHIELDS",NUMKARTSHIELDS},
// kartitemequip_e
@ -1755,6 +1753,7 @@ struct int_const_s const INT_CONST[] = {
{"TRF_TRIPWIRE",TRF_TRIPWIRE},
{"TRF_REMAP",TRF_REMAP},
{"TRF_BYPASSBOOST", TRF_BYPASSBOOST},
{"TRF_BUMPY", TRF_BUMPY},
// facepatches
{"FACE_RANK", FACE_RANK},
@ -1913,5 +1912,12 @@ struct int_const_s const INT_CONST[] = {
{"RINGMOD_SAW", RINGMOD_SAW},
{"RINGMOD_SQUARE", RINGMOD_SQUARE},
// keepstuffflags_t
{"KEEPSTUFF_ROCKET", KEEPSTUFF_ROCKET},
{"KEEPSTUFF_INVIN", KEEPSTUFF_INVIN},
{"KEEPSTUFF_SMON", KEEPSTUFF_SMON},
{"KEEPSTUFF_GROWSHRINK", KEEPSTUFF_GROWSHRINK},
{"KEEPSTUFF_FLAME", KEEPSTUFF_FLAME},
{NULL,0}
};

View file

@ -560,19 +560,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
ignorelines(f);
}
}
#ifdef HWRENDER
else if (fastcmp(word, "LIGHT"))
{
// TODO: Read lights by name
if (i > 0 && i < NUMLIGHTS)
readlight(f, i);
else
{
deh_warning("Light number %d out of range (1 - %d)", i, NUMLIGHTS-1);
ignorelines(f);
}
}
#endif
else if (fastcmp(word, "LEVEL"))
{
size_t len = strlen(word2);

View file

@ -141,7 +141,7 @@ extern char logfilename[1024];
// to an increment in MODVERSION. This might never happen in practice.
// If MODVERSION increases, set MINOREXECVERSION to 0.
#define MAJOREXECVERSION MODVERSION
#define MINOREXECVERSION 0
#define MINOREXECVERSION 2
// (It would have been nice to use VERSION and SUBVERSION but those are zero'd out for DEVELOP builds)
// Macros
@ -312,10 +312,10 @@ extern int SUBVERSION;
// abbreviation. Maybe in another 20k commits, more than 8
// characters will be required! =P
// P.S. 8 is also what comptime generates
#ifdef COMMITVERSION
// #ifdef COMMITVERSION
#define GIT_SHA_ABBREV (4)
extern UINT8 comprevision_abbrev_bin[GIT_SHA_ABBREV];
#endif
// #endif
extern boolean devparm; // development mode (-debug)
@ -440,6 +440,13 @@ INT32 I_GetKey(void);
// NOTE: you WILL have nasal troubles if the variable is not initialized
#define CLEANUP(f) __attribute__((__cleanup__(f)))
// the GNU constructor and destructor attributes
// The constructor attribute causes the function to be called automatically before execution enters main ().
// Similarly, the destructor attribute causes the function to be called automatically after main () has completed or exit () has been called.
// Functions with these attributes are useful for initializing data that will be used implicitly during the execution of the program.
#define CONSTRUCTOR __attribute__((constructor, used))
#define DESTRUCTOR __attribute__((destructor, used))
// An assert-type mechanism.
// NOTE: USE SRB2_ASSERT FOR C++ CODE INSTEAD
#ifdef PARANOIA
@ -528,6 +535,12 @@ extern int compuncommitted;
#define MAX_VOLUME 100
// Crypto/RRID primitives
#define PUBKEYLENGTH 32 // Enforced by Monocypher EdDSA
#define PRIVKEYLENGTH 64 // Enforced by Monocypher EdDSA
#define SIGNATURELENGTH 64 // Enforced by Monocypher EdDSA
#define CHALLENGELENGTH 64 // Servers verify client identity by giving them messages to sign. How long are these messages?
#ifdef HAVE_CURL
#define MASTERSERVER
#else

View file

@ -23,6 +23,8 @@
extern "C" {
#endif
#include "g_mapnum.h"
// We need globally shared data structures, for defining the global state variables.
#include "doomdata.h"
@ -35,8 +37,14 @@ extern "C" {
// Selected map etc.
// =============================
#define ROUNDQUEUE_MAX 20 // sane max? maybe make dynamically allocated later
// These two live in gametype field of packets
#define ROUNDQUEUE_CMD_CLEAR UINT16_MAX
#define ROUNDQUEUE_CMD_SHOW UINT16_MAX-1
// The roundqueue itself is resident in g_game.h
// Selected by user.
extern INT16 gamemap;
extern mapnum_t gamemap;
extern char mapmusname[7];
extern UINT16 mapmusflags;
extern UINT32 mapmusposition;
@ -152,8 +160,7 @@ extern UINT8 splitscreen;
extern int r_splitscreen;
extern boolean circuitmap; // Does this level have 'circuit mode'?
extern boolean fromlevelselect;
extern boolean forceresetplayers, deferencoremode;
extern boolean forceresetplayers, deferencoremode, forcespecialstage;
// ========================================
// Internal parameters for sound rendering.
@ -285,7 +292,7 @@ struct textprompt_t
extern textprompt_t *textprompts[MAX_PROMPTS];
// For the Custom Exit linedef.
extern INT16 nextmapoverride;
extern mapnum_t nextmapoverride;
extern UINT8 skipstats;
// Fun extra stuff
@ -330,8 +337,10 @@ struct mapheader_lighting_t
// Keep in mind that it may encourage people making overly long cups just because they "can", and would be a waste of memory.
#define MAXLEVELLIST 5
#define CUPCACHE_BONUS MAXLEVELLIST
#define CUPCACHE_SPECIAL MAXLEVELLIST+1
#define CUPCACHE_MAX CUPCACHE_SPECIAL+1
#define MAXBONUSLIST 2
#define CUPCACHE_SPECIAL (CUPCACHE_BONUS+MAXBONUSLIST)
#define CUPCACHE_PODIUM (CUPCACHE_SPECIAL+1)
#define CUPCACHE_MAX (CUPCACHE_PODIUM+1)
#define MAXCUPNAME 16 // includes \0, for cleaner savedata
@ -346,8 +355,9 @@ struct cupheader_t
char icon[9]; ///< Name of the icon patch
char *levellist[CUPCACHE_MAX]; ///< List of levels that belong to this cup
INT16 cachedlevels[CUPCACHE_MAX]; ///< IDs in levellist, bonusgame, and specialstage
mapnum_t cachedlevels[CUPCACHE_MAX]; ///< IDs in levellist, bonusgame, and specialstage
UINT8 numlevels; ///< Number of levels defined in levellist
UINT8 numbonus; ///< Number of bonus stages defined
UINT8 emeraldnum; ///< ID of Emerald to use for special stage (1-7 for Chaos Emeralds, 8-14 for Super Emeralds, 0 for no emerald)
SINT8 unlockrequired; ///< An unlockable is required to select this cup. -1 for no unlocking required.
cupheader_t *next; ///< Next cup in linked list
@ -372,6 +382,8 @@ struct mapheader_t
cupheader_t *cup; ///< Cached cup
size_t justPlayed; ///< Prevent this map from showing up in votes if it was recently picked.
// Titlecard information
char lvlttl[22]; ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway)
char subttl[33]; ///< Subtitle for level
@ -394,9 +406,11 @@ struct mapheader_t
// Music information
char musname[MAXMUSNAMES][7]; ///< Music tracks to play. First dimension is the track number, second is the music string. "" for no music.
char encoremusname[MAXMUSNAMES][7]; ///< Music tracks to play in Encore. First dimension is the track number, second is the music string. "" for no music.
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
UINT32 muspos; ///< Music position to jump to.
UINT8 musname_size; ///< Number of music tracks defined
UINT8 encoremusname_size; ///< Number of Encore music tracks defined
// Sky information
UINT8 weather; ///< See preciptype_t
@ -766,6 +780,7 @@ extern consvar_t cv_forceskin; // force clients to use the server's skin
extern consvar_t cv_downloading; // allow clients to downloading WADs.
extern consvar_t cv_nettimeout; // SRB2Kart: Advanced server options menu
extern consvar_t cv_jointimeout;
extern consvar_t cv_validate_pubkey;
extern ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
extern INT32 serverplayer;
extern INT32 adminplayers[MAXPLAYERS];

View file

@ -1,38 +0,0 @@
#include "../command.h"
#include "../s_sound.h"
#include "../i_sound.h"
//
// CD MUSIC I/O
//
UINT8 cdaudio_started = 0;
consvar_t cd_volume = CVAR_INIT ("cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL);
consvar_t cdUpdate = CVAR_INIT ("cd_update","1",CV_SAVE, NULL, NULL);
void I_InitCD(void){}
void I_StopCD(void){}
void I_PauseCD(void){}
void I_ResumeCD(void){}
void I_ShutdownCD(void){}
void I_UpdateCD(void){}
void I_PlayCD(UINT8 track, UINT8 looping)
{
(void)track;
(void)looping;
}
boolean I_SetVolumeCD(int volume)
{
(void)volume;
return false;
}

View file

@ -1,21 +0,0 @@
#include "../doomdef.h"
#include "../d_main.h"
#include "../m_argv.h"
int main(int argc, char **argv)
{
myargc = argc;
myargv = argv; /// \todo pull out path to exe from this string
// startup SRB2
CONS_Printf("Setting up SRB2...\n");
D_SRB2Main();
CONS_Printf("Entering main game loop...\n");
// never return
D_SRB2Loop();
// return to OS
#ifndef __GNUC__
return 0;
#endif
}

View file

@ -1,6 +0,0 @@
#include "../i_net.h"
boolean I_InitNetwork(void)
{
return false;
}

View file

@ -1,217 +0,0 @@
#include "../i_sound.h"
UINT8 sound_started = 0;
void *I_GetSfx(sfxinfo_t *sfx)
{
(void)sfx;
return NULL;
}
void I_FreeSfx(sfxinfo_t *sfx)
{
(void)sfx;
}
void I_StartupSound(void){}
void I_ShutdownSound(void){}
void I_UpdateSound(void){};
//
// SFX I/O
//
INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel)
{
(void)id;
(void)vol;
(void)sep;
(void)pitch;
(void)priority;
(void)channel;
return -1;
}
void I_StopSound(INT32 handle)
{
(void)handle;
}
boolean I_SoundIsPlaying(INT32 handle)
{
(void)handle;
return false;
}
void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch)
{
(void)handle;
(void)vol;
(void)sep;
(void)pitch;
}
void I_SetSfxVolume(UINT8 volume)
{
(void)volume;
}
/// ------------------------
// MUSIC SYSTEM
/// ------------------------
void I_InitMusic(void){}
void I_ShutdownMusic(void){}
/// ------------------------
// MUSIC PROPERTIES
/// ------------------------
musictype_t I_SongType(void)
{
return MU_NONE;
}
boolean I_SongPlaying(void)
{
return false;
}
boolean I_SongPaused(void)
{
return false;
}
/// ------------------------
// MUSIC EFFECTS
/// ------------------------
boolean I_SetSongSpeed(float speed)
{
(void)speed;
return false;
}
/// ------------------------
// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void)
{
return 0;
}
boolean I_SetSongLoopPoint(UINT32 looppoint)
{
(void)looppoint;
return false;
}
UINT32 I_GetSongLoopPoint(void)
{
return 0;
}
boolean I_SetSongPosition(UINT32 position)
{
(void)position;
return false;
}
UINT32 I_GetSongPosition(void)
{
return 0;
}
/// ------------------------
// MUSIC PLAYBACK
/// ------------------------
boolean I_LoadSong(char *data, size_t len)
{
(void)data;
(void)len;
return -1;
}
void I_UnloadSong(void)
{
(void)handle;
}
boolean I_PlaySong(boolean looping)
{
(void)handle;
(void)looping;
return false;
}
void I_StopSong(void)
{
(void)handle;
}
void I_PauseSong(void)
{
(void)handle;
}
void I_ResumeSong(void)
{
(void)handle;
}
void I_SetMusicVolume(UINT8 volume)
{
(void)volume;
}
boolean I_SetSongTrack(int track)
{
(void)track;
return false;
}
/// ------------------------
// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume)
{
(void)volume;
}
void I_StopFadingSong(void)
{
}
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)source_volume;
(void)ms;
return false;
}
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)ms;
return false;
}
boolean I_FadeOutStopSong(UINT32 ms)
{
(void)ms;
return false;
}
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
{
(void)ms;
(void)looping;
return false;
}

View file

@ -1,180 +0,0 @@
#include "../doomdef.h"
#include "../i_system.h"
UINT8 graphics_started = 0;
UINT8 keyboard_started = 0;
UINT32 I_GetFreeMem(UINT32 *total)
{
*total = 0;
return 0;
}
void I_Sleep(UINT32 ms){}
precise_t I_GetPreciseTime(void) {
return 0;
}
UINT64 I_GetPrecisePrecision(void) {
return 1000000;
}
void I_GetEvent(void){}
void I_OsPolling(void){}
ticcmd_t *I_BaseTiccmd(void)
{
return NULL;
}
ticcmd_t *I_BaseTiccmd2(void)
{
return NULL;
}
void I_Quit(void)
{
exit(0);
}
void I_Error(const char *error, ...)
{
(void)error;
exit(-1);
}
void I_Tactile(FFType Type, const JoyFF_t *Effect)
{
(void)Type;
(void)Effect;
}
void I_Tactile2(FFType Type, const JoyFF_t *Effect)
{
(void)Type;
(void)Effect;
}
void I_ControllerScale(void){}
void I_ControllerScale2(void){}
void I_InitController(void){}
void I_InitController2(void){}
INT32 I_NumControllers(void)
{
return 0;
}
const char *I_GetControllerName(INT32 joyid)
{
(void)joyid;
return NULL;
}
#ifndef NOMUMBLE
void I_UpdateMumble(const mobj_t *mobj, const listener_t listener)
{
(void)mobj;
(void)listener;
}
#endif
void I_OutputMsg(const char *error, ...)
{
(void)error;
}
void I_StartupMouse(void){}
void I_StartupMouse2(void){}
void I_StartupKeyboard(void){}
INT32 I_GetKey(void)
{
return 0;
}
void I_StartupTimer(void){}
void I_AddExitFunc(void (*func)())
{
(void)func;
}
void I_RemoveExitFunc(void (*func)())
{
(void)func;
}
INT32 I_StartupSystem(void)
{
return -1;
}
void I_ShutdownSystem(void){}
void I_GetDiskFreeSpace(INT64* freespace)
{
*freespace = 0;
}
char *I_GetUserName(void)
{
return NULL;
}
INT32 I_mkdir(const char *dirname, INT32 unixright)
{
(void)dirname;
(void)unixright;
return -1;
}
const char *I_LocateWad(void)
{
return NULL;
}
void I_GetJoystickEvents(void){}
void I_GetJoystick2Events(void){}
void I_GetMouseEvents(void){}
void I_UpdateMouseGrab(void){}
char *I_GetEnv(const char *name)
{
(void)name;
return NULL;
}
INT32 I_PutEnv(char *variable)
{
(void)variable;
return -1;
}
INT32 I_ClipboardCopy(const char *data, size_t size)
{
(void)data;
(void)size;
return -1;
}
char *I_ClipboardPaste(void)
{
return NULL;
}
void I_RegisterSysCommands(void) {}
#include "../sdl/dosstr.c"

View file

@ -1,79 +0,0 @@
#include "../doomdef.h"
#include "../command.h"
#include "../i_video.h"
rendermode_t rendermode = render_none;
rendermode_t chosenrendermode = render_none;
boolean highcolor = false;
boolean allow_fullscreen = false;
consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL);
void I_StartupGraphics(void){}
void I_ShutdownGraphics(void){}
void VID_StartupOpenGL(void){}
void I_SetPalette(RGBA_t *palette)
{
(void)palette;
}
INT32 VID_NumModes(void)
{
return 0;
}
INT32 VID_GetModeForSize(INT32 w, INT32 h)
{
(void)w;
(void)h;
return 0;
}
void VID_PrepareModeList(void){}
INT32 VID_SetMode(INT32 modenum)
{
(void)modenum;
return 0;
}
boolean VID_CheckRenderer(void)
{
return false;
}
void VID_CheckGLLoaded(rendermode_t oldrender)
{
(void)oldrender;
}
const char *VID_GetModeName(INT32 modenum)
{
(void)modenum;
return NULL;
}
void I_UpdateNoBlit(void){}
void I_FinishUpdate(void){}
void I_UpdateNoVsync(void) {}
void I_WaitVBL(INT32 count)
{
(void)count;
}
void I_ReadScreen(UINT8 * restrict scr, INT32 scale)
{
(void)scr;
}
void I_BeginRead(void){}
void I_EndRead(void){}

View file

@ -924,18 +924,22 @@ const char *blancredits[] = {
"\"Chearii\"",
"\"hayaunderscore\" aka \"DeltaKanyx\"",
"\"Guilmon35249vr\"",
"Vivian \"toaster\" Grannell", // Horncode
"AJ \"Tyron\" Martinez", // Horncode
"Vivian \"toaster\" Grannell", // Horncode, fix for Followers in demos
"AJ \"Tyron\" Martinez", // Horncode, PT_SAY, RRID
"\"Superstarxalien\"", // Horncode
"\"Freaky Mutant Man\"", // Color profiles menu
"\"blondedradio\"", // Screen-tracking item roulette, lifted near-directly from RadioRacers
"\"Antoine De Grandpré\"", // Zero Deadzone fix
"\"Skirlez\"", // PT_SAY packet fixes
"Sally \"TehRealSalt\" Cochenour", // Map Buffer rewrite, Voting rewrites
"\"Jartha\"", // Various bugfixes, RRID
"",
"\1Item Design",
"\"NepDisk\"",
"\"yama\"",
"\"GenericHeroGuy\"",
"\"minenice\"",
"\"Miguelius256\"", // Initial Attraction Shield design
"",
"\1Design Support",
"\"Rim Jobless\"",
@ -955,6 +959,7 @@ const char *blancredits[] = {
"\"yama\"",
"\"minenice\"",
"\"Mompi\"",
"\"Chuckles troll\"", // Attraction Shield, S-Monitor
"",
"\1New HUD Art",
"\"Spee\"",
@ -969,6 +974,7 @@ const char *blancredits[] = {
"\"RetroStation\"",
"\"StarrydustNova\"",
"\"joshyflip\"",
"\"Chuckles troll\"", // Timer icons for: Attraction Shield, S-Monitor
"",
"\1New Misc Art",
"\"scizor300\"",
@ -1740,7 +1746,7 @@ void F_TitleScreenTicker(boolean run)
// prevent console spam if failed
demoIdleLeft = demoIdleTime;
mapnum = G_RandMap(TOL_RACE, -2, 2, 0, NULL);
mapnum = G_RandMap(TOL_RACE, UINT16_MAX, true, 0, false, NULL);
if (mapnum == 0) // gotta have ONE
{
return;

View file

@ -54,9 +54,17 @@
#include "k_color.h"
#include "k_follower.h"
#include "k_grandprix.h"
#include "k_vote.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);
static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {
{DEMOSAVE_NONE, "Disabled"},
{DEMOSAVE_MANUAL, "Manual Save"},
{DEMOSAVE_AUTO_NETONLY, "Auto Save Online"},
{DEMOSAVE_AUTO, "Auto Save All"},
{0, NULL}};
consvar_t cv_recordmultiplayerdemos =
CVAR_INIT("netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL);
static CV_PossibleValue_t netdemosyncquality_cons_t[] = {{1, "MIN"}, {35, "MAX"}, {0, NULL}};
consvar_t cv_netdemosyncquality = CVAR_INIT ("netdemo_syncquality", "1", CV_SAVE, netdemosyncquality_cons_t, NULL);
@ -144,8 +152,6 @@ demoghost *ghosts = NULL;
#define ZT_AIMING 0x0040
#define ZT_LATENCY 0x0080
#define ZT_FLAGS 0x0100
#define ZT_IMUTILT 0x0200
#define ZT_IMUSHAKE 0x0400
// Ziptics are UINT16 now, go nuts
#define DEMOMARKER 0x80 // demobuf.end
@ -191,6 +197,23 @@ static ticcmd_t oldcmd[MAXPLAYERS];
#define FZT_SCALE 0x10 // different scale to object
// spare FZT slots 0x20 to 0x80
//
// Checks if auto-saving demos is allowed.
//
boolean G_DemoWillAutoSave(void)
{
if (cv_recordmultiplayerdemos.value == DEMOSAVE_AUTO_NETONLY)
{
return (netgame);
}
else if (cv_recordmultiplayerdemos.value == DEMOSAVE_AUTO)
{
return true;
}
return false;
}
typedef struct
{
char *filename;
@ -402,10 +425,6 @@ static UINT8 *G_ReadZipTic(ticcmd_t *cmd, UINT8 *dp, UINT16 version)
cmd->latency = READUINT8(dp);
if (ziptic & ZT_FLAGS)
cmd->flags = READUINT8(dp);
if (ziptic & ZT_IMUTILT)
cmd->tilt = READSINT8(dp);
if (ziptic & ZT_IMUSHAKE)
cmd->shake = READUINT8(dp);
if (version < 0x000a && ziptic & 0x8000) // ZT_BOT
{
@ -1589,20 +1608,6 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
ziptic |= ZT_FLAGS;
}
if (cmd->tilt != oldcmd[playernum].tilt)
{
WRITESINT8(demobuf.p,cmd->tilt);
oldcmd[playernum].tilt = cmd->tilt;
ziptic |= ZT_IMUTILT;
}
if (cmd->shake != oldcmd[playernum].shake)
{
WRITESINT8(demobuf.p,cmd->shake);
oldcmd[playernum].shake = cmd->shake;
ziptic |= ZT_IMUSHAKE;
}
WRITEUINT16(ziptic_p, ziptic);
// attention here for the ticcmd size!
@ -3048,17 +3053,20 @@ void G_BeginRecording(void)
WRITESTRINGL(demobuf.p, skins[player->skin].voices[player->voice_id].name, 32+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.
if (player->follower)
WRITESTRINGL(demobuf.p, followers[player->followerskin].skinname, 16+1);
if (player->followerskin == -1)
WRITESTRINGL(demobuf.p, "None", 16+1);
else
WRITESTRINGL(demobuf.p, "None", 16+1); // Say we don't have one, then.
WRITESTRINGL(demobuf.p, followers[player->followerskin].name, 16+1);
// Save follower's colour
for (j = (numskincolors+2)-1; j > 0; j--)
{
if (Followercolor_cons_t[j].value == players[i].followercolor)
break;
}
// Not KartColor_Names because followercolor has extra values such as "Match"
WRITESTRINGL(demobuf.p, Followercolor_cons_t[(UINT16)(player->followercolor+2)].strvalue, 16+1);
WRITESTRINGL(demobuf.p, Followercolor_cons_t[j].strvalue, 16+1);
// Score, since Kart uses this to determine where you start on the map
WRITEUINT32(demobuf.p, player->score);
@ -4001,7 +4009,7 @@ void G_DoPlayDemo(char *defdemoname)
R_ExecuteSetViewSize();
P_SetRandSeed(header.randseed);
G_InitNew(demoflags & DF_ENCORE, gamemap, true, true, false); // Doesn't matter whether you reset or not here, given changes to resetplayer.
G_InitNew(demoflags & DF_ENCORE, gamemap, true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer.
// Setup server name, contact and description.
CopyCaretColors(connectedservername, header.servername, MAXSERVERNAME);
@ -4633,7 +4641,7 @@ boolean G_DemoTitleResponder(event_t *ev)
// Only ESC and non-keyboard keys abort connection
if (ch == KEY_ESCAPE)
{
demo.savemode = (cv_recordmultiplayerdemos.value == 2) ? DSM_WILLAUTOSAVE : DSM_NOTSAVING;
demo.savemode = (G_DemoWillAutoSave()) ? DSM_WILLAUTOSAVE : DSM_NOTSAVING;
return true;
}

View file

@ -28,6 +28,13 @@ extern "C" {
// DEMO playback/recording related stuff.
// ======================================
typedef enum {
DEMOSAVE_NONE = 0,
DEMOSAVE_MANUAL,
DEMOSAVE_AUTO_NETONLY,
DEMOSAVE_AUTO
} demosavemode_e;
extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality, cv_netdemosize;
extern consvar_t cv_resyncdemo;
@ -183,6 +190,7 @@ extern demoghost *ghosts;
#define DFILE_ERROR_CANNOTLOAD 0x04 // Files are missing and cannot be loaded.
#define DFILE_ERROR_EXTRAFILES 0x05 // Extra files outside of the replay's file list are loaded.
boolean G_DemoWillAutoSave(void);
void G_DeferedPlayDemo(const char *demo);
void G_DoPlayDemo(char *defdemoname);
void G_SetupDemoPlayer(INT32 i);

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,7 @@
#ifndef __G_GAME__
#define __G_GAME__
#include "g_mapnum.h"
#include "doomdef.h"
#include "doomstat.h"
#include "d_event.h"
@ -38,29 +39,36 @@ extern boolean playeringame[MAXPLAYERS];
extern tic_t levelstarttic;
// for modding?
extern INT16 prevmap, nextmap;
extern mapnum_t prevmap, nextmap;
// see also G_MapNumber
typedef enum
struct roundentry_t
{
NEXTMAP_RESERVED = INT16_MAX, // so nextmap+1 doesn't roll over -- remove when gamemap is made 0-indexed
NEXTMAP_TITLE = INT16_MAX-1,
NEXTMAP_EVALUATION = INT16_MAX-2,
NEXTMAP_CREDITS = INT16_MAX-3,
NEXTMAP_CEREMONY = INT16_MAX-4,
NEXTMAP_VOTING = INT16_MAX-5,
NEXTMAP_INVALID = INT16_MAX-6, // Always last
NEXTMAP_SPECIAL = NEXTMAP_INVALID
} nextmapspecial_t;
UINT16 mapnum; // Map number at this position
UINT16 gametype; // Gametype we want to play this in
boolean encore; // Whether this will be flipped
boolean rankrestricted; // For grand prix progression
};
extern INT16 kartmap2native[NEXTMAP_SPECIAL], nativemap2kart[NEXTMAP_SPECIAL];
extern INT16 nextexnum;
extern struct roundqueue
{
UINT8 roundnum; // Visible number on HUD
UINT8 position; // Head position in the round queue
UINT8 size; // Number of entries in the round queue
boolean netcommunicate; // As server, should we net-communicate this in XD_MAP?
roundentry_t entries[ROUNDQUEUE_MAX]; // Entries in the round queue
} roundqueue;
void G_MapSlipIntoRoundQueue(UINT8 position, UINT16 map, UINT8 setgametype, boolean setencore, boolean rankrestricted);
void G_MapIntoRoundQueue(UINT16 map, UINT8 setgametype, boolean setencore, boolean rankrestricted);
void G_GPCupIntoRoundQueue(cupheader_t *cup, UINT8 setgametype, boolean setencore);
extern mapnum_t kartmap2native[NEXTMAP_SPECIAL], nativemap2kart[NEXTMAP_SPECIAL];
extern mapnum_t nextexnum;
extern INT32 gameovertics;
extern UINT8 ammoremovaltics;
extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
extern INT32 pausedelay;
extern boolean pausebreakkey;
extern boolean promptactive;
@ -106,11 +114,14 @@ void weaponPrefChange4(void);
#define MAXPLMOVE (50)
const char *G_BuildMapName(INT32 map);
INT32 G_MapNumber(const char *mapname);
INT32 G_LevelTitleToMapNum(const char * leveltitle);
INT16 G_KartMapToNative(INT16 mapnum);
INT16 G_NativeMapToKart(INT16 mapnum);
const char *G_BuildMapName(mapnum_t map);
mapnum_t G_MapNumber(const char *mapname);
mapnum_t G_LevelTitleToMapNum(const char * leveltitle);
mapnum_t G_KartMapToNative(mapnum_t mapnum);
mapnum_t G_NativeMapToKart(mapnum_t mapnum);
#define GAMEPADSHAKETHRESHOLD (UINT8_MAX/2)
#define TILTTOSTICKEASE 6
void G_ResetAnglePrediction(player_t *player);
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer);
@ -128,31 +139,6 @@ void G_FinalClipAimingPitch(INT32 *aiming, player_t *player, boolean skybox);
extern angle_t localangle[MAXSPLITSCREENPLAYERS];
extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed
typedef enum
{
DEADZONE_X,
DEADZONE_Y,
DEADZONE_BUTTON,
} analogdeadzone_e;
typedef enum
{
ACCELEROMETER,
GYROSCOPE,
} motionsensortype_e;
#define MAXGAMEPADTILT (50*FRACUNIT/100)
// #define ACCELEROMETERGRAVITY ((fixed_t)(9.80665f * ((float)FRACUNIT)))
#define ACCELEROMETERGRAVITY 642688
#define GAMEPADSHAKETHRESHOLD (UINT8_MAX/2)
#define TILTTOSTICKEASE 6
boolean G_GetGamepadCanUseTilt(INT32 p);
void G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel);
INT32 G_GetGamepadTilt(INT32 p);
vector3_t G_GetGamepadShake(INT32 p);
vector3_t G_GetGamepadGravity(INT32 p);
vector3_t G_PlayerInputSensor(UINT8 p, motionsensortype_e sensor);
fixed_t G_GetDeadZoneType(INT32 p, SINT8 type);
INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean digital, SINT8 type);
boolean G_PlayerInputDown(UINT8 p, INT32 gc, boolean digital, SINT8 type);
@ -166,9 +152,9 @@ boolean G_AxisInDeadzone(UINT8 p, event_t *ev);
void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo);
void G_DoReborn(INT32 playernum);
void G_PlayerReborn(INT32 player, boolean betweenmaps);
void G_InitNew(UINT8 pencoremode, INT32 map, boolean resetplayer,
boolean skipprecutscene, boolean FLS);
char *G_BuildMapTitle(INT32 mapnum);
void G_InitNew(UINT8 pencoremode, mapnum_t map, boolean resetplayer,
boolean skipprecutscene);
char *G_BuildMapTitle(mapnum_t mapnum);
struct searchdim
{
@ -186,12 +172,12 @@ struct mapsearchfreq_t
UINT8 total;/* total hits */
};
INT32 G_FindMap(const char *query, char **foundmapnamep,
mapnum_t G_FindMap(const char *query, char **foundmapnamep,
mapsearchfreq_t **freqp, INT32 *freqc);
void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc);
/* Match map name by search + 2 digit map code or map number. */
INT32 G_FindMapByNameOrCode(const char *query, char **foundmapnamep);
mapnum_t G_FindMapByNameOrCode(const char *query, char **foundmapnamep);
// XMOD spawning
mapthing_t *G_FindTeamStart(INT32 playernum);
@ -203,7 +189,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost);
// Can be called by the startup code or M_Responder.
// A normal game starts at map 1, but a warp test can start elsewhere
void G_DeferedInitNew(boolean pencoremode, INT32 map, INT32 pickedchar,
void G_DeferedInitNew(boolean pencoremode, mapnum_t map, INT32 pickedchar,
UINT8 ssplayers, boolean FLS);
void G_DoLoadLevel(boolean resetplayer);
@ -212,21 +198,22 @@ void G_PreLevelTitleCard(void);
boolean G_IsTitleCardAvailable(void);
// Can be called by the startup code or M_Responder, calls P_SetupLevel.
void G_LoadGame(UINT32 slot, INT16 mapoverride);
void G_LoadGame(UINT32 slot, mapnum_t mapoverride);
void G_SaveGameData(void);
void G_SaveGame(UINT32 slot, INT16 mapnum);
void G_SaveGame(UINT32 slot, mapnum_t mapnum);
void G_SaveGameOver(UINT32 slot, boolean modifylives);
void G_SetGametype(INT16 gametype);
char *G_PrepareGametypeConstant(const char *newgtconst);
void G_UpdateGametypeSelections(void);
void G_SetGametypeColor(INT16 gtype,INT32 color);
void G_AddTOL(UINT32 newtol, const char *tolname);
void G_UpdateGametypeSelections(void);
INT32 G_GetGametypeByName(const char *gametypestr);
boolean G_IsSpecialStage(INT32 mapnum);
INT32 G_GuessGametypeByTOL(UINT32 tol);
boolean G_IsSpecialStage(mapnum_t mapnum);
boolean G_GametypeUsesLives(void);
boolean G_GametypeHasTeams(void);
boolean G_GametypeHasSpectators(void);
@ -236,6 +223,9 @@ UINT8 G_GetGametypeColor(INT16 gt);
void G_BeginLevelExit(void);
void G_FinishExitLevel(void);
void G_NextLevel(void);
boolean G_MapIsSafe(mapnum_t map);
mapnum_t G_CheckNextMap(boolean noadvancemap);
void G_GetNextMap(void);
void G_Continue(void);
void G_UseContinue(void);
void G_AfterIntermission(void);
@ -257,6 +247,7 @@ void G_AdjustViewEx(UINT8 viewnum, INT32 offset, boolean onlyactive, boolean res
#define G_AdjustView(v,o,oa) G_AdjustViewEx(v,o,oa, true)
void G_AddPlayer(INT32 playernum, INT32 console);
void G_SpectatePlayerOnJoin(INT32 playernum);
void G_SetExitGameFlag(void);
void G_ClearExitGameFlag(void);
@ -356,11 +347,11 @@ 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);
tic_t G_GetBestTime(mapnum_t 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);
char *G_GetRecordReplay(const char *folder, mapnum_t mapnum, UINT16 skinnum, recordreplay_e which);
boolean G_CheckRecordReplay(const char *folder, mapnum_t mapnum, UINT16 skinnum, recordreplay_e which);
FUNCMATH INT32 G_TicsToHours(tic_t tics);
FUNCMATH INT32 G_TicsToMinutes(tic_t tics, boolean full);
@ -370,10 +361,13 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics);
// Don't split up TOL handling
UINT32 G_TOLFlag(INT32 pgametype);
INT16 G_GetFirstMapOfGametype(UINT8 pgametype);
mapnum_t G_GetFirstMapOfGametype(UINT8 pgametype);
INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, UINT8 ignorebuffer, UINT8 maphell, INT16 *extbuffer);
void G_AddMapToBuffer(INT16 map);
void G_AddMapToBuffer(mapnum_t map);
extern UINT8 g_countToGametype;
mapnum_t G_RandMap(UINT32 tolflags, mapnum_t pprevmap, boolean ignoreBuffers, UINT8 maphell, boolean callAgainSoon, mapnum_t *extBuffer);
typedef struct
{

View file

@ -26,6 +26,8 @@
#include "v_video.h"
#include "p_local.h"
#include "k_kart.h"
#include "m_fixed.h"
#include "m_easing.h"
#define MAXMOUSESENSITIVITY 100 // sensitivity steps
@ -162,7 +164,7 @@ INT32 gamecontroldefault[num_gamecontrols][MAXINPUTMAPPING] = {
[gc_lookback ] = {KEY_LSHIFT, KEY_JOY1+2 }, // North
[gc_horncode ] = {'r', KEY_JOY1+8 }, // R-Stick Click
[gc_pause ] = {KEY_PAUSE, KEY_JOY1+4 }, // Back
[gc_pause ] = {KEY_PAUSE }, // Back
[gc_systemmenu ] = { KEY_JOY1+6 }, // Start
[gc_console ] = {KEY_CONSOLE },
[gc_screenshot ] = {KEY_F8 },
@ -177,6 +179,7 @@ INT32 gamecontroldefault[num_gamecontrols][MAXINPUTMAPPING] = {
[gc_centerview ] = {KEY_END },
[gc_camreset ] = {KEY_HOME },
[gc_camtoggle ] = {KEY_BACKSPACE },
[gc_freelook ] = {KEY_RCTRL },
};
// lists of GC codes for selective operation
@ -1226,3 +1229,344 @@ void Command_Setcontrol4_f(void)
setcontrol(3);
}
// accelerometer and gyro stuff
// when holding the controller still (shaking and turning included), correct this quickly to resolve error
#define GyroCalibrationRollingAvgSamples (TICRATE/2)
#define GyroCalibrationStart (TICRATE/2)
#define GyroCalibrationTrust (1*FRACUNIT/100)
boolean localgyrocalibrating[MAXSPLITSCREENPLAYERS];
vector3_t localgyrovectors[MAXSPLITSCREENPLAYERS];
tic_t localgyrocalibrationsamples[MAXSPLITSCREENPLAYERS];
vector3_t localgyrocalibrationlastoffset[MAXSPLITSCREENPLAYERS];
vector3_t localgyrocalibrationoffset[MAXSPLITSCREENPLAYERS];
// assume the accelerometer doesn't need calibration, use this to determine if gyro can be calibrated
vector3_t localaccelcalibrationoffset[MAXSPLITSCREENPLAYERS];
fixed_t localshakinessfac[MAXSPLITSCREENPLAYERS];
vector3_t localsmoothedaccel[MAXSPLITSCREENPLAYERS];
vector3_t localgravityvectors[MAXSPLITSCREENPLAYERS];
vector4_t localquaternions[MAXSPLITSCREENPLAYERS];
// copy/pasted from the lua version of these routines
inline static vector3_t *QuaternionMulVec3(vector3_t *out, vector3_t *a, vector4_t *b)
{
fixed_t ax = a->x, ay = a->y, az = a->z, aw = 0;
fixed_t bx = b->x, by = b->y, bz = b->z, bw = b->a;
FV3_NormalizeEx(out, FV3_Load(out,
FixedMul(aw, bx) + FixedMul(ax, bw) + FixedMul(ay, bz) - FixedMul(az, by),
FixedMul(aw, by) - FixedMul(ax, bz) + FixedMul(ay, bw) + FixedMul(az, bx),
FixedMul(aw, bz) + FixedMul(ax, by) - FixedMul(ay, bx) + FixedMul(az, bw)
));
return out;
}
inline static fixed_t FV3_LengthSquared(const vector3_t *vec)
{
return FixedMul(vec->x, vec->x) + FixedMul(vec->y, vec->y) + FixedMul(vec->z, vec->z);
}
inline static vector4_t AngleAxis(fixed_t angle, fixed_t x, fixed_t y, fixed_t z)
{
fixed_t sinangle = FINESINE(FixedAngle(angle/2) >> ANGLETOFINESHIFT);
fixed_t cosangle = FINECOSINE(FixedAngle(angle/2) >> ANGLETOFINESHIFT);
vector3_t axis = {x, y, z};
vector4_t result;
FV3_Normalize(&axis);
FV4_Load(&result,
FixedMul(axis.x, sinangle),
FixedMul(axis.y, sinangle),
FixedMul(axis.z, sinangle),
cosangle
);
return result;
}
vector3_t G_GetCalibratedGyroOffset(INT32 p)
{
return localgyrocalibrationoffset[p];
}
void G_UpdateGamepadAutoCalibration(INT32 p, vector3_t accel, vector3_t gyro, boolean allowautocalibration)
{
fixed_t trust = FV3_Distance(&localaccelcalibrationoffset[p], &accel);
FV3_Load(
&localaccelcalibrationoffset[p],
(localaccelcalibrationoffset[p].x + accel.x)/2,
(localaccelcalibrationoffset[p].y + accel.y)/2,
(localaccelcalibrationoffset[p].z + accel.z)/2
);
CONS_Debug(DBG_IMU, "== Gyro Update ==\n");
CONS_Debug(DBG_IMU, "Gyro calibration safety: %4.3f\n", FixedToFloat(trust));
if (allowautocalibration && (trust < GyroCalibrationTrust))
{
if (!localgyrocalibrating[p])
{
localgyrocalibrationsamples[p] = 0;
FV3_Copy(&localgyrocalibrationlastoffset[p], &localgyrocalibrationoffset[p]);
FV3_Load(
&localgyrocalibrationoffset[p],
0, 0, 0
);
localgyrocalibrating[p] = true;
}
}
else
{
// incomplete calibration
if (localgyrocalibrating[p] && localgyrocalibrationsamples[p] <= (GyroCalibrationRollingAvgSamples + GyroCalibrationStart))
{
FV3_Copy(&localgyrocalibrationoffset[p], &localgyrocalibrationlastoffset[p]);
localgyrocalibrationsamples[p] = 0;
}
localgyrocalibrating[p] = false;
}
}
void G_UpdateGamepadGyro(INT32 p, vector3_t gyro)
{
vector3_t offset = {0};
if (p >= MAXSPLITSCREENPLAYERS)
{
#ifdef PARANOIA
CONS_Debug(DBG_GAMELOGIC, "G_UpdateGamepadGyro: Invalid player ID %d\n", p);
#endif
return;
}
if (!I_ControllerSupportsSensorGyro(p)) return;
if (localgyrocalibrating[p])
{
localgyrocalibrationsamples[p]++;
if (localgyrocalibrationsamples[p] > GyroCalibrationStart)
{
FV3_Load(
&localgyrocalibrationoffset[p],
(((GyroCalibrationRollingAvgSamples-1)*localgyrocalibrationoffset[p].x) + gyro.x)/GyroCalibrationRollingAvgSamples,
(((GyroCalibrationRollingAvgSamples-1)*localgyrocalibrationoffset[p].y) + gyro.y)/GyroCalibrationRollingAvgSamples,
(((GyroCalibrationRollingAvgSamples-1)*localgyrocalibrationoffset[p].z) + gyro.z)/GyroCalibrationRollingAvgSamples
);
}
}
CONS_Debug(DBG_IMU, "Gyro calibration samples: %d\n", localgyrocalibrationsamples[p]);
offset = G_GetCalibratedGyroOffset(p);
FV3_SubEx(&gyro, &offset, &localgyrovectors[p]);
}
// math sourced from this article
// http://gyrowiki.jibbsmart.com/blog:finding-gravity-with-sensor-fusion
// the time it takes in our acceleration smoothing for 'A' to get halfway to 'B'
#define SmoothingHalfTime (0.25)
// thresholds of trust for accel shakiness. less shakiness = more trust
#define ShakinessMaxThreshold (40*FRACUNIT/100)
#define ShakinessMinThreshold (1*FRACUNIT/100)
// when we trust the accel a lot (the controller is "still"), how quickly do we correct our gravity vector?
#define CorrectionStillRate (FRACUNIT)
// when we don't trust the accel (the controller is "shaky"), how quickly do we correct our gravity vector?
#define CorrectionShakyRate (1*FRACUNIT/100)
// if our old gravity vector is close enough to our new one, limit further corrections to this proportion of the rotation speed
#define CorrectionGyroFactor (5*FRACUNIT/100)
// thresholds for what's considered "close enough"
#define CorrectionGyroMinThreshold (5*FRACUNIT/100)
#define CorrectionGyroMaxThreshold (FRACUNIT/4)
// no matter what, always apply a minimum of this much correction to our gravity vector
#define CorrectionMinimumSpeed (1*FRACUNIT/100)
void G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel)
{
// convert gyro input to reverse rotation
vector3_t invAccel = {-accel.x, -accel.y, -accel.z};
fixed_t correctionRate = 0;
// scaling is reversed, smaller time scales = larger steps in this code
// (1/timescale)/dt
fixed_t deltaseconds = FixedDiv(FRACUNIT, max(cv_timescale.value, FRACUNIT/20))/TICRATE;
// we don't have exp2 and we actually need it here to take timescale into account :(
fixed_t smoothFactor = FloatToFixed(exp2(-FixedToFloat(deltaseconds) / SmoothingHalfTime));
fixed_t angleRate = FixedMul(FV3_Magnitude(&gyro), M_PI_FIXED)/180;
fixed_t correctionLimit;
vector4_t invRotation = {0};
vector3_t gravityDelta = {0};
vector3_t gravityDeltaDirection = {0};
vector3_t correction = {0};
if (!G_GetGamepadCanUseTilt(p)) return;
CONS_Debug(DBG_IMU, "= Update Gravity Delta Time: %4.3f =\n", FixedToFloat(deltaseconds));
invRotation = AngleAxis(
FixedMul(FixedMul(FV3_Magnitude(&gyro), deltaseconds), 190*FRACUNIT/100),
-gyro.x,
-gyro.y,
-gyro.z
);
// rotate gravity vector
QuaternionMulVec3(&localgravityvectors[p], &localgravityvectors[p], &invRotation);
QuaternionMulVec3(&localsmoothedaccel[p], &localsmoothedaccel[p], &invRotation);
localshakinessfac[p] = FixedMul(localshakinessfac[p], smoothFactor),
FV3_SubEx(&accel, &localsmoothedaccel[p], &correction);
localshakinessfac[p] = max(localshakinessfac[p], FV3_Magnitude(&correction));
FV3_Load(&localsmoothedaccel[p],
Easing_Linear(smoothFactor, accel.x, localsmoothedaccel[p].x),
Easing_Linear(smoothFactor, accel.y, localsmoothedaccel[p].y),
Easing_Linear(smoothFactor, accel.z, localsmoothedaccel[p].z)
);
CONS_Debug(DBG_IMU, "Shakiness: %4.2f\n", FixedToFloat(localshakinessfac[p]));
FV3_SubEx(&invAccel, &localgravityvectors[p], &gravityDelta);
if (FV3_Magnitude(&gravityDelta) > 0)
{
FV3_NormalizeEx(&gravityDelta, &gravityDeltaDirection);
}
CONS_Debug(DBG_IMU, "Gravity Delta Magnitude: %4.3f\n", FixedToFloat(FV3_Magnitude(&gravityDelta)));
if (ShakinessMaxThreshold > ShakinessMinThreshold)
{
fixed_t stillness = CLAMP(FixedDiv((localshakinessfac[p] - ShakinessMinThreshold), (ShakinessMaxThreshold - ShakinessMinThreshold)), 0, FRACUNIT);
correctionRate = CorrectionStillRate + FixedMul((CorrectionShakyRate - CorrectionStillRate), stillness);
}
else if (localshakinessfac[p] > ShakinessMaxThreshold)
{
correctionRate = CorrectionShakyRate;
}
else
{
correctionRate = CorrectionStillRate;
}
// limit in proportion to rotation rate
correctionLimit = FixedMul(angleRate, CorrectionGyroFactor);
CONS_Debug(DBG_IMU, "Angle Rate: %4.3f\n", FixedToFloat(angleRate));
CONS_Debug(DBG_IMU, "Correction Limit: %4.3f\n", FixedToFloat(correctionLimit));
if (correctionRate > correctionLimit) {
fixed_t closeEnoughFactor;
if (CorrectionGyroMaxThreshold > CorrectionGyroMinThreshold)
{
closeEnoughFactor = CLAMP(FixedDiv((FV3_Magnitude(&gravityDelta) - CorrectionGyroMinThreshold), (CorrectionGyroMaxThreshold - CorrectionGyroMinThreshold)), 0, FRACUNIT);
}
else if (FV3_Magnitude(&gravityDelta) > CorrectionGyroMaxThreshold)
{
closeEnoughFactor = FRACUNIT;
}
else
{
closeEnoughFactor = 0;
}
CONS_Debug(DBG_IMU, "'Close Enough' Fac: %4.3f\n", FixedToFloat(closeEnoughFactor));
correctionRate = correctionLimit + FixedMul((correctionRate - correctionLimit), closeEnoughFactor);
}
correctionRate = max(correctionRate, CorrectionMinimumSpeed);
CONS_Debug(DBG_IMU, "Correction Rate: %4.2f\n", FixedToFloat(correctionRate));
FV3_Load(&correction,
FixedMul(gravityDeltaDirection.x, FixedMul(deltaseconds, correctionRate)),
FixedMul(gravityDeltaDirection.y, FixedMul(deltaseconds, correctionRate)),
FixedMul(gravityDeltaDirection.z, FixedMul(deltaseconds, correctionRate))
);
if ((FV3_LengthSquared(&correction) < FV3_LengthSquared(&gravityDelta)))
{
FV3_Add(&localgravityvectors[p], &correction);
}
else
{
FV3_Add(&localgravityvectors[p], &gravityDelta);
}
}
INT32 G_GetGamepadTilt(INT32 p)
{
fixed_t tilt;
fixed_t curve;
if (!G_GetGamepadCanUseTilt(p)) return 0;
tilt = CLAMP(FixedDiv(G_GetGamepadGravity(p).x + MAXGAMEPADTILT, 2*MAXGAMEPADTILT), 0, FRACUNIT);
CONS_Debug(DBG_IMU, "Tilt: %4.2f\n", FixedToFloat(tilt));
curve = FSIN(FixedAngle(180*(tilt-FRACUNIT/2)));
CONS_Debug(DBG_IMU, "Pinched Tilt: %4.2f\n", FixedToFloat(curve));
return (JOYAXISRANGE * curve)/FRACUNIT;
}
vector3_t G_GetGamepadGravity(INT32 p)
{
const vector3_t zero = {0, -ACCELEROMETERGRAVITY, 0};
if (!G_GetGamepadCanUseTilt(p)) return zero;
return localgravityvectors[p];
}
vector3_t G_GetGamepadShake(INT32 p)
{
vector3_t accel = {0};
if (!G_GetGamepadCanUseTilt(p)) return accel;
accel = G_PlayerInputSensor(p, ACCELEROMETER);
FV3_Add(&accel, &localgravityvectors[p]);
return accel;
}
fixed_t G_GetGamepadShakinessFactor(INT32 p)
{
if (!G_GetGamepadCanUseTilt(p)) return 0;
return localshakinessfac[p];
}
vector3_t G_GetGamepadCalibratedGyro(INT32 p)
{
vector3_t zero = {0};
if (p >= MAXSPLITSCREENPLAYERS)
{
#ifdef PARANOIA
CONS_Debug(DBG_GAMELOGIC, "G_GetGamepadGyro: Invalid player ID %d\n", p);
#endif
return zero;
}
if (!I_ControllerSupportsSensorGyro(p)) return zero;
return localgyrovectors[p];
}
boolean G_GetGamepadCanUseTilt(INT32 p)
{
if (p >= MAXSPLITSCREENPLAYERS)
{
#ifdef PARANOIA
CONS_Debug(DBG_GAMELOGIC, "G_GetGamepadCanUseTilt: Invalid player ID %d\n", p);
#endif
return false;
}
return (I_ControllerSupportsSensorAccelerometer(p) && I_ControllerSupportsSensorGyro(p));
}
#undef ShakinessMaxThreshold
#undef ShakinessMinThreshold
#undef CorrectionStillRate
#undef CorrectionShakyRate
#undef CorrectionGyroFactor
#undef CorrectionGyroMinThreshold
#undef CorrectionGyroMaxThreshold
#undef CorrectionMinimumSpeed
#undef SmoothingHalfTime
#undef GyroCalibrationTrust
#undef GyroCalibrationStart
#undef GyroCalibrationRollingAvgSamples

View file

@ -95,9 +95,23 @@ typedef enum
gc_respawn,
gc_director,
gc_horncode,
gc_freelook,
num_gamecontrols
} gamecontrols_e;
typedef enum
{
DEADZONE_X,
DEADZONE_Y,
DEADZONE_BUTTON,
} analogdeadzone_e;
typedef enum
{
ACCELEROMETER,
GYROSCOPE,
} motionsensortype_e;
// mouse values are used once
extern consvar_t cv_mousesens, cv_mouseysens;
extern consvar_t cv_mousesens2, cv_mouseysens2;
@ -178,6 +192,21 @@ void G_ResetControls(UINT8 p);
void G_SaveKeySetting(FILE *f, INT32 (*fromcontrolsa)[MAXINPUTMAPPING], INT32 (*fromcontrolsb)[MAXINPUTMAPPING], INT32 (*fromcontrolsc)[MAXINPUTMAPPING], INT32 (*fromcontrolsd)[MAXINPUTMAPPING]);
INT32 G_CheckDoubleUsage(INT32 keynum, INT32 playernum, boolean modify);
#define MAXGAMEPADTILT (55*FRACUNIT/100)
#define ACCELEROMETERGRAVITY (642688) // 9.80665
boolean G_GetGamepadCanUseTilt(INT32 p);
void G_ResetGyroCalibration(INT32 p);
void G_UpdateGamepadAutoCalibration(INT32 p, vector3_t accel, vector3_t gyro, boolean allowautocalibration);
void G_UpdateGamepadGyro(INT32 p, vector3_t gyro);
void G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel);
fixed_t G_GetGamepadShakinessFactor(INT32 p);
vector3_t G_GetGamepadShake(INT32 p);
vector3_t G_GetGamepadGravity(INT32 p);
vector3_t G_GetCalibratedGyroOffset(INT32 p);
vector3_t G_GetGamepadCalibratedGyro(INT32 p);
vector3_t G_PlayerInputSensor(UINT8 p, motionsensortype_e sensor);
INT32 G_GetGamepadTilt(INT32 p);
#ifdef __cplusplus
} // extern "C"
#endif

39
src/g_mapnum.h Normal file
View file

@ -0,0 +1,39 @@
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 2026 by Team BlanKart.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file g_mapnum.h
/// \brief Map number type
#ifndef __MAPNUM__
#define __MAPNUM__
#include "doomdef.h"
#ifdef __cplusplus
extern "C" {
#endif
// see also G_MapNumber
typedef enum
{
NEXTMAP_RESERVED = UINT16_MAX, // so nextmap+1 doesn't roll over -- remove when gamemap is made 0-indexed
NEXTMAP_TITLE = UINT16_MAX-1,
NEXTMAP_EVALUATION = UINT16_MAX-2,
NEXTMAP_CREDITS = UINT16_MAX-3,
NEXTMAP_CEREMONY = UINT16_MAX-4,
NEXTMAP_VOTING = UINT16_MAX-5,
NEXTMAP_RANDOM = UINT16_MAX-6,
NEXTMAP_INVALID = UINT16_MAX-7, // Always last
NEXTMAP_SPECIAL = NEXTMAP_INVALID
} ATTRPACK mapnum_t;
#ifdef __cplusplus
} // extern "C"
#endif
#endif

View file

@ -2,7 +2,6 @@ target_sources(BLANKART PRIVATE
hw_map.c
hw_bsp.c
hw_draw.c
hw_light.c
hw_main.c
hw_sky.c
hw_things.c
@ -18,5 +17,6 @@ target_sources(BLANKART PRIVATE
hw_plane.c
hw_segs.c
hw_shaders.c
hw_portal.c
r_opengl/r_opengl.c
)

View file

@ -283,6 +283,7 @@ static int compareDrawCalls(const void *p1, const void *p2)
if (diff != 0) return diff;
diff = poly1->surf.LightInfo.directional - poly2->surf.LightInfo.directional;
if (diff != 0) return diff;
return diff;
}
@ -400,7 +401,8 @@ static unsigned int HWR_MarkStateChanges(DrawCallInfo *current, DrawCallInfo *ne
currentSI->FadeColor.rgba != nextSI->FadeColor.rgba ||
currentSI->LightInfo.light_level != nextSI->LightInfo.light_level ||
currentSI->LightInfo.fade_start != nextSI->LightInfo.fade_start ||
currentSI->LightInfo.fade_end != nextSI->LightInfo.fade_end)
currentSI->LightInfo.fade_end != nextSI->LightInfo.fade_end ||
currentSI->LightInfo.directional != nextSI->LightInfo.directional)
{
stateChanges |= SURFACEINFO_CHANGED;
}

View file

@ -1,4 +1,4 @@
// SONIC ROBO BLAST 2
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2022 by Sonic Team Junior.

View file

@ -166,6 +166,7 @@ enum
SHADER_SKY,
SHADER_PALETTE_POSTPROCESS,
SHADER_UI_COLORMAP_FADE,
SHADER_FINAL_POST_PROCESS,
NUMSHADERTARGETS
};
@ -315,6 +316,7 @@ enum hwdsetspecialstate
HWD_SET_SHADERS,
HWD_SET_TEXTUREFILTERMODE,
HWD_SET_TEXTUREANISOTROPICMODE,
HWD_SET_SCREEN_TEXTURES,
HWD_NUMSTATE
};
typedef enum hwdsetspecialstate hwdspecialstate_t;

View file

@ -1,4 +1,4 @@
// SONIC ROBO BLAST 2
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2022 by Sonic Team Junior.

View file

@ -116,6 +116,38 @@ typedef struct gl_vissprite_s
void HWR_ObjectLightLevelPost(gl_vissprite_t *spr, const sector_t *sector, INT32 *lightlevel, boolean model);
typedef struct
{
// Viewport.
fixed_t viewx;
fixed_t viewy;
fixed_t viewz;
angle_t viewangle;
seg_t *seg; // seg that is used for drawing to the stencil buffer
line_t *clipline;
// angles for the left and right edges of the portal
// relative to the viewpoint
angle_t angle1;
angle_t angle2;
} gl_portal_t;
typedef struct
{
gl_portal_t *portals;
unsigned int size;
unsigned int capacity;
} gl_portal_array_t;
// --------
// hw_main.c
// -------
void HWR_RenderViewpoint(player_t *player, boolean drawSkyTexture, boolean is_skybox, boolean timing, gl_portal_t *rootportal);
void HWR_PrepareTransform(player_t *player, boolean is_skybox);
void HWR_ResetClipper(void);
// --------
// hw_map.c
// --------
@ -204,8 +236,8 @@ void HWR_CompileShaders(void);
int HWR_GetShaderFromTarget(int shader_target);
void HWR_LoadAllCustomShaders(void);
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3);
void HWR_LoadAllBaseShaders(void);
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3, boolean startup);
const char *HWR_GetShaderName(INT32 shader);
extern customshaderxlat_t shaderxlat[];
@ -230,6 +262,32 @@ UINT32 HWR_SortVisSprites(void);
void HWR_DrawSprites(void);
void HWR_ProjectBoundingBox(mobj_t *thing);
// --------
// hw_portal.c
// --------
#define INIT_PORTAL_ARRAY_SIZE 4
void HWR_PortalFrame(gl_portal_t *portal, boolean set_culling);
gl_portal_array_t *HWR_GetPortalArray(void);
boolean HWR_AddPortal(line_t *start, line_t *dest, seg_t *seg);
void HWR_ClearPortals(void);
void HWR_PortalClipping(gl_portal_t *portal);
void HWR_RenderPortalSeg(seg_t *seg);
void HWR_SetStencilState(INT32 state);
void HWR_RenderDepthEraser(boolean visible);
void HWR_RenderPortal(gl_portal_t *portal, gl_portal_t *rootportal, player_t *player, boolean is_skybox);
extern INT32 gl_portal_level;
extern boolean gl_drawing_stencil;
extern sector_t *gl_portalcullsector;
extern line_t *gl_portalclipline;
extern boolean gl_printportals;
extern INT32 gl_debugportal;
#ifdef __cplusplus
} // extern "C"
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,103 +0,0 @@
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file hw_light.h
/// \brief Dynamic lighting & coronas add on by Hurdler
#ifndef _HW_LIGHTS_
#define _HW_LIGHTS_
#include "hw_glob.h"
#include "hw_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NUMLIGHTFREESLOTS 32 // Free light slots (for SOCs)
#ifdef ALAM_LIGHTING
#define NEWCORONAS
#define DL_MAX_LIGHT 256 // maximum number of lights (extra lights are ignored)
void HWR_InitLight(void);
void HWR_DL_AddLight(gl_vissprite_t *spr, GLPatch_t *patch);
void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts);
void HWR_WallLighting(FOutVector *wlVerts);
void HWR_ResetLights(void);
void HWR_SetLights(int viewnumber);
#ifdef NEWCORONAS
void HWR_DrawCoronas(void);
#else
void HWR_DoCoronasLighting(FOutVector *outVerts, gl_vissprite_t *spr);
#endif
typedef struct
{
int nb;
light_t *p_lspr[DL_MAX_LIGHT];
FVector position[DL_MAX_LIGHT]; // actually maximum DL_MAX_LIGHT lights
mobj_t *mo[DL_MAX_LIGHT];
} dynlights_t;
#endif
typedef enum
{
NOLIGHT = 0,
RINGSPARK_L,
SUPERSONIC_L, // Cool. =)
SUPERSPARK_L,
INVINCIBLE_L,
GREENSHIELD_L,
BLUESHIELD_L,
YELLOWSHIELD_L,
REDSHIELD_L,
BLACKSHIELD_L,
WHITESHIELD_L,
SMALLREDBALL_L,
RINGLIGHT_L,
GREENSMALL_L,
REDSMALL_L,
GREENSHINE_L,
ORANGESHINE_L,
PINKSHINE_L,
BLUESHINE_L,
REDSHINE_L,
LBLUESHINE_L,
GREYSHINE_L,
REDBALL_L,
GREENBALL_L,
BLUEBALL_L,
NIGHTSLIGHT_L,
JETLIGHT_L,
GOOPLIGHT_L,
STREETLIGHT_L,
// free slots for SOCs at run-time --------------------
FREESLOT0_L,
//
// ... 32 free lights here ...
//
LASTFREESLOT_L = (FREESLOT0_L+NUMLIGHTFREESLOTS-1),
// end of freeslots ---------------------------------------------
NUMLIGHTS
} lightspritenum_t;
extern light_t lspr[NUMLIGHTS];
extern light_t *t_lspr[NUMSPRITES];
#ifdef __cplusplus
} // extern "C"
#endif
#endif

View file

@ -20,7 +20,6 @@
#ifdef HWRENDER
#include "hw_clip.h"
#include "hw_glob.h"
#include "hw_light.h"
#include "hw_gpu.h"
#include "hw_batching.h"
@ -111,195 +110,6 @@ static float gl_fovlud;
static angle_t gl_aimingangle;
/* Portal stuff */
// TODO probably put this to a separate file?
typedef struct
{
// Viewport.
fixed_t viewx;
fixed_t viewy;
fixed_t viewz;
angle_t viewangle;
seg_t *seg; // seg that is used for drawing to the stencil buffer
line_t *clipline;
// angles for the left and right edges of the portal
// relative to the viewpoint
angle_t angle1;
angle_t angle2;
} gl_portal_t;
#define INIT_PORTAL_ARRAY_SIZE 4
typedef struct
{
gl_portal_t *portals;
unsigned int size;
unsigned int capacity;
} gl_portal_array_t;
// TODO magic number 16
gl_portal_array_t gl_portal_arrays[MAXPORTALS_CAP+1] = {0};
INT32 gl_portal_level = 0; // portal recursion level
boolean gl_drawing_stencil = false; // used when drawing segs to stencil buffer
sector_t *gl_portalcullsector = NULL;
line_t *gl_portalclipline = NULL;
// debug tools
boolean gl_printportals = false; // print info about portals on this frame
INT32 gl_debugportal = 0; // hide main viewpoint and only render this portal without stencil
static void HWR_PortalFrame(gl_portal_t *portal, boolean set_culling)
{
viewx = portal->viewx;
viewy = portal->viewy;
viewz = portal->viewz;
viewangle = portal->viewangle;
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
// set_culling will be true if RenderBSPNode is about to be called
// so need to enable portal culling for that
if (set_culling)
{
gl_portalcullsector = portal->clipline->frontsector;
gl_portalclipline = portal->clipline;
}
}
// get currently used portal array
static gl_portal_array_t *HWR_GetPortalArray(void)
{
INT32 level = gl_portal_level;
if (gl_rendering_skybox)
level++;
return &gl_portal_arrays[level];
}
// TODO move to r_main.c next to fixed point functions?
// More precise version of R_PointToAngle2 using floats and atan2.
static angle_t R_PointToAngle2Precise(fixed_t pviewx, fixed_t pviewy, fixed_t x, fixed_t y)
{
fixed_t dx = x - pviewx;
fixed_t dy = y - pviewy;
float radians;
if (!dx && !dy)
return 0;
// no need for correct scale with FIXED_TO_FLOAT here
// since we're just calculating the angle
radians = atan2(dy, dx);
return (angle_t)(radians / M_PI * ANGLE_180);
}
// More precise version of R_PointToDist2 using floats and sqrt.
static fixed_t R_PointToDist2Precise(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1)
{
// float-fixed conversions can be omitted here
// because they cancel each other out in this case
float dx = px1 - px2;
float dy = py1 - py2;
double result = sqrt(dx*dx + dy*dy);
return (fixed_t)result;
}
boolean HWR_AddPortal(line_t *start, line_t *dest, seg_t *seg)
{
gl_portal_array_t *array;
gl_portal_t *portal;
angle_t dangle;
fixed_t disttopoint;
angle_t angtopoint;
vertex_t dest_c, start_c;
if ((gl_portal_level + gl_rendering_skybox) >= cv_maxportals.value ||
(gl_debugportal &&
(gl_debugportal != (start-lines) || gl_portal_level)))
{
return false;
}
if (gl_debugportal)
gl_debugportal = -1; // skip other portal segs from the same line
array = HWR_GetPortalArray();
// yet another dynamic array
if (!array->portals)
{
array->capacity = INIT_PORTAL_ARRAY_SIZE;
array->portals = Z_Malloc(sizeof(gl_portal_t) * array->capacity, PU_LEVEL,
&array->portals);
}
else if (array->size == array->capacity)
{
array->capacity *= 2;
array->portals = Z_Realloc(array->portals, sizeof(gl_portal_t) * array->capacity,
PU_LEVEL, &array->portals);
}
portal = &array->portals[array->size++];
// Most fixed-point calculations and trigonometric function tables are replaced by
// floats and cmath library calls in this part to improve the precision of the
// location and angle of the new viewpoint.
//
// This reduces artefacts on the edges of portals, showing thin lines/pixels
// of the underlying graphics. (for example the sky texture) It's not 100%
// perfectly aligned and artefact-free, but looks noticeably
// better than the original code. I'm not even sure if it's this
// code or the nodebuilder or hw_map or something else causing the remaining issues..
//#define R_PointToAngle2Precise R_PointToAngle2
//#define R_PointToDist2Precise R_PointToDist2
dangle = R_PointToAngle2Precise(0,0,dest->dx,dest->dy) - R_PointToAngle2Precise(start->dx,start->dy,0,0);
// looking glass center
start_c.x = start->v1->x/2 + start->v2->x/2;
start_c.y = start->v1->y/2 + start->v2->y/2;
// other side center
dest_c.x = dest->v1->x/2 + dest->v2->x/2;
dest_c.y = dest->v1->y/2 + dest->v2->y/2;
disttopoint = R_PointToDist2Precise(start_c.x, start_c.y, viewx, viewy);
angtopoint = R_PointToAngle2Precise(start_c.x, start_c.y, viewx, viewy);
angtopoint += dangle;
float fang = ((float)angtopoint / 4294967296.0f) * 2.0f * M_PI;
//portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
//portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
//portal->viewx = dest_c.x + FixedMul(FLOAT_TO_FIXED(cos(fang)), disttopoint);
//portal->viewy = dest_c.y + FixedMul(FLOAT_TO_FIXED(sin(fang)), disttopoint);
// cos and sin are just scaling disttopoint so no need for float-fixed conversions
portal->viewx = dest_c.x + (fixed_t)(cos(fang) * disttopoint);
portal->viewy = dest_c.y + (fixed_t)(sin(fang) * disttopoint);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->viewangle = viewangle + dangle;
portal->seg = seg;
portal->clipline = dest;
portal->angle1 = R_PointToAngle64(seg->v1->x, seg->v1->y) + dangle;
portal->angle2 = R_PointToAngle64(seg->v2->x, seg->v2->y) + dangle;
return true;
}
static void HWR_ClearPortals(void)
{
HWR_GetPortalArray()->size = 0;
}
// ==========================================================================
// Lighting
// ==========================================================================
@ -618,7 +428,7 @@ void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox,
gl_aimingangle = temp_aimingangle;
}
static void HWR_ResetClipper(void)
void HWR_ResetClipper(void)
{
angle_t a1 = gld_FrustumAngle(gl_aimingangle);
gld_clipper_Clear();
@ -628,12 +438,6 @@ static void HWR_ResetClipper(void)
#endif
}
// clip the area outside the portal destination window
static void HWR_PortalClipping(gl_portal_t *portal)
{
gld_clipper_SafeAddClipRange(portal->angle1, portal->angle2);
}
// Tells the backend are shaders being used for 3d rendering.
static void HWR_SetShaderState(void)
{
@ -642,7 +446,7 @@ static void HWR_SetShaderState(void)
// prepare all transform related variables based on the current "frame"
// (R_SetupFrame etc)
static void HWR_PrepareTransform(player_t *player, boolean is_skybox)
void HWR_PrepareTransform(player_t *player, boolean is_skybox)
{
UINT8 viewnum = R_GetViewNumber();
camera_t *thiscam = &camera[viewnum];
@ -707,88 +511,7 @@ static void HWR_LeaveSkyboxState(void)
gl_rendering_skybox = false;
}
static void HWR_RenderPortalSeg(seg_t *seg)
{
gl_drawing_stencil = true;
gl_curline = seg;
gl_frontsector = seg->frontsector;
gl_backsector = seg->backsector;
HWR_ProcessSeg();
gl_drawing_stencil = false;
// need to work around the r_opengl PF_Invisible bug with this call
// similarly as in the linkdraw hack in HWR_DrawSprites
GL_SetBlend(PF_Translucent|PF_Occlude|PF_Masked);
}
static void HWR_SetStencilState(INT32 state)
{
GL_SetStencilMode(state, gl_portal_level);
}
// clear the depth buffer from the stenciled area so portal
// content doesn't get clipped by previous buffer content
// (glClear ignores the stencil buffer so can't be used for this purpose)
static void HWR_RenderDepthEraser(boolean visible)
{
FOutVector verts[4] = {0};
FBITFIELD blendflags = PF_Occlude|PF_NoDepthTest|PF_NoTexture|PF_NoAlphaTest;
if (!visible)
blendflags |= PF_Invisible;
// so this is apparently how you draw the far clipping plane when
// pfnSetTransform(NULL) is active
const float a = FAR_CLIPPING_PLANE;
verts[0].x = -a; verts[0].y = -a; verts[0].z = a;
verts[1].x = -a; verts[1].y = a; verts[1].z = a;
verts[2].x = a; verts[2].y = a; verts[2].z = a;
verts[3].x = a; verts[3].y = -a; verts[3].z = a;
GL_SetTransform(NULL);
GL_DrawPolygon(NULL, verts, 4, blendflags);
}
static void HWR_RenderViewpoint(player_t *player, boolean drawSkyTexture, boolean is_skybox, boolean timing, gl_portal_t *rootportal);
static void HWR_RenderPortal(gl_portal_t *portal, gl_portal_t *rootportal, player_t *player, boolean is_skybox)
{
HWR_PushSpriteState();
HWR_PushDrawNodeState();
if (!gl_debugportal)
{
HWR_SetStencilState(HWD_STENCIL_PORTAL_BEGIN);
HWR_RenderPortalSeg(portal->seg);
}
gl_portal_level++;
if (!gl_debugportal)
HWR_SetStencilState(HWD_STENCIL_PORTAL_INSIDE);
HWR_RenderDepthEraser(true);
HWR_PortalFrame(portal, true);
HWR_RenderViewpoint(player, true, is_skybox, false, portal);
// restore previous frame and transform
if (rootportal)
HWR_PortalFrame(rootportal, false);
else if (is_skybox)
R_SkyboxFrame(viewssnum);
else
R_SetupFrame(viewssnum, is_skybox);
HWR_PrepareTransform(player, is_skybox);
GL_SetTransform(&atransform);
HWR_ResetClipper();
if (!gl_debugportal)
{
HWR_SetStencilState(HWD_STENCIL_PORTAL_FINISH);
HWR_RenderPortalSeg(portal->seg);
}
gl_portal_level--;
HWR_PopSpriteState();
HWR_PopDrawNodeState();
}
static void HWR_RenderViewpoint(player_t *player, boolean drawSkyTexture, boolean is_skybox, boolean timing, gl_portal_t *rootportal)
void HWR_RenderViewpoint(player_t *player, boolean drawSkyTexture, boolean is_skybox, boolean timing, gl_portal_t *rootportal)
{
unsigned int i;
gl_portal_array_t *portal_array;
@ -804,9 +527,6 @@ static void HWR_RenderViewpoint(player_t *player, boolean drawSkyTexture, boolea
if (rootportal)
HWR_PortalClipping(rootportal);
// check for new console commands.
NetUpdate();
if (timing)
{
ps_numbspcalls = 0;
@ -911,15 +631,6 @@ static void HWR_RenderViewpoint(player_t *player, boolean drawSkyTexture, boolea
gl_portal_level = 0;
}
// Check for new console commands.
NetUpdate();
#ifdef ALAM_LIGHTING
//14/11/99: Hurdler: moved here because it doesn't work with
// subsector, see other comments;
HWR_ResetLights();
#endif
// Draw MD2 and sprites
if (timing)
@ -962,9 +673,6 @@ static void HWR_RenderViewpoint(player_t *player, boolean drawSkyTexture, boolea
// hack for debugportal, see earlier comment
if (gl_debugportal && !gl_portal_level)
HWR_SetStencilState(HWD_STENCIL_INACTIVE);
// Check for new console commands.
NetUpdate();
}
// ==========================================================================
@ -1021,16 +729,32 @@ void HWR_RenderPlayerView(void)
ClearColor.alpha = 1.0f;
if (cv_glshaders.value)
{
GL_SetShaderInfo(HWD_SHADERINFO_LEVELTIME, (INT32)leveltime); // The water surface shader needs the leveltime.
const angle_t light_angle = maplighting.angle - viewangle + ANGLE_90; // I fucking hate OGL's coordinate system
GL_SetShaderInfo(HWD_SHADERINFO_LIGHT_X, FINECOSINE(light_angle >> ANGLETOFINESHIFT));
GL_SetShaderInfo(HWD_SHADERINFO_LIGHT_Y, 0);
GL_SetShaderInfo(HWD_SHADERINFO_LIGHT_Z, -FINESINE(light_angle >> ANGLETOFINESHIFT));
GL_SetShaderInfo(HWD_SHADERINFO_LIGHT_CONTRAST, maplighting.contrast);
GL_SetShaderInfo(HWD_SHADERINFO_LIGHT_BACKLIGHT, maplighting.backlight);
}
if (viewssnum == 0) // Only do it if it's the first screen being rendered
GL_ClearBuffer(true, true, true, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs.
ps_hw_skyboxtime = I_GetPreciseTime();
if (skybox) // If there's a skybox and we should be drawing the sky, draw the skybox
{
// Check for new console commands.
NetUpdate();
HWR_ClearView();
HWR_RenderSkyboxView(player); // This is drawn before everything else so it is placed behind
// Check for new console commands.
NetUpdate();
}
ps_hw_skyboxtime = I_GetPreciseTime() - ps_hw_skyboxtime;
@ -1041,9 +765,6 @@ void HWR_RenderPlayerView(void)
stplyr = player;
ST_doPaletteStuff();
stplyr = saved_player;
#ifdef ALAM_LIGHTING
HWR_SetLights(viewssnum);
#endif
}
// Reset the shader state.
@ -1132,11 +853,6 @@ static void HWR_TogglePaletteRendering(void)
void HWR_LoadLevel(void)
{
#ifdef ALAM_LIGHTING
// BP: reset light between levels (we draw preview frame lights on current frame)
HWR_ResetLights();
#endif
HWR_CreatePlanePolygons((INT32)numnodes - 1);
// Build the sky dome
@ -1161,6 +877,7 @@ static CV_PossibleValue_t glshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Thi
static void CV_glfiltermode_OnChange(void);
static void CV_glanisotropic_OnChange(void);
static void CV_screentextures_OnChange(void);
static CV_PossibleValue_t glfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"},
{HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"},
@ -1176,18 +893,20 @@ consvar_t cv_glallowshaders = CVAR_INIT ("gr_allowclientshaders", "On", CV_NETVA
consvar_t cv_fovchange = CVAR_INIT ("gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glsecbright = CVAR_INIT("gr_secbright", "0", CV_SAVE, glsecbright_cons_t, NULL);
#ifdef ALAM_LIGHTING
consvar_t cv_gldynamiclighting = CVAR_INIT ("gr_dynamiclighting", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glstaticlighting = CVAR_INIT ("gr_staticlighting", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glcoronas = CVAR_INIT ("gr_coronas", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glcoronasize = CVAR_INIT ("gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0, NULL);
#endif
// The current screen texture implementation is inefficient and disabling it can result in significant
// performance gains on lower end hardware. The game is still quite playable without this functionality.
// Features that break when disabling this:
// - water and heat wave effects
// - intermission background
// - full screen scaling (use native resolution or windowed mode to avoid this)
static CV_PossibleValue_t glscreentextures_cons_t[] = {{0, "Off"}, {1, "Wipes Only"}, {2, "All"}, {0, NULL}};
consvar_t cv_glscreentextures = CVAR_INIT("gr_screentextures", "All", CV_CALL|CV_SAVE, glscreentextures_cons_t, CV_screentextures_OnChange);
consvar_t cv_glmodels = CVAR_INIT ("gr_models", "Off", CV_SAVE, CV_OnOff, NULL);
#ifdef BAD_MODEL_OPTIONS
consvar_t cv_glmodelinterpolation = CVAR_INIT ("gr_modelinterpolation", "Sometimes", CV_SAVE, glmodelinterpolation_cons_t, NULL);
consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "On", CV_SAVE, CV_OnOff, NULL);
#endif
consvar_t cv_glshearing = CVAR_INIT ("gr_shearing", "Off", CV_SAVE, glshearing_cons_t, NULL);
@ -1215,9 +934,12 @@ consvar_t cv_glbatching = CVAR_INIT ("gr_batching", "On", 0, CV_OnOff, NULL);
CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 bits"}, {0, NULL}};
void CV_glpaletterendering_OnChange(void);
void CV_glpalettedepth_OnChange(void);
void CV_gllightdithering_OnChange(void);
consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletteshader", "Off", CV_CALL|CV_SAVE, CV_OnOff, CV_glpaletterendering_OnChange);
consvar_t cv_glpalettedepth = CVAR_INIT ("gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_glpalettedepth_OnChange);
consvar_t cv_glpalettedepth = CVAR_INIT ("gr_palettedepth", "24 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_glpalettedepth_OnChange);
consvar_t cv_gllightdither = CVAR_INIT ("gr_lightdithering", "Off", CV_CALL|CV_SAVE, CV_OnOff, CV_gllightdithering_OnChange);
// Isolates rendering to one of the top level portals.
// (Stencil cutting of the portal is also disabled)
@ -1228,6 +950,17 @@ consvar_t cv_glskydebug = CVAR_INIT ("gr_skydebug", "0", 0, CV_Unsigned, NULL);
#define ONLY_IF_GL_LOADED if (vid.glstate != VID_GL_LIBRARY_LOADED) return;
static void CV_screentextures_OnChange(void)
{
ONLY_IF_GL_LOADED
if (cv_glscreentextures.value != 2)
{
if (cv_glpaletterendering.value != 0)
CV_SetValue(&cv_glpaletterendering, 0);
}
GL_SetSpecialState(HWD_SET_SCREEN_TEXTURES, cv_glscreentextures.value);
}
static void CV_glfiltermode_OnChange(void)
{
ONLY_IF_GL_LOADED
@ -1252,14 +985,27 @@ void CV_glmodellighting_OnChange(void)
void CV_glpaletterendering_OnChange(void)
{
ONLY_IF_GL_LOADED
if (cv_glpaletterendering.value != 0 && cv_glscreentextures.value != 2) // can't do palette rendering without screen textures
CV_SetValue(&cv_glpaletterendering, 0);
if (gl_shadersavailable)
{
HWR_CompileShaders();
HWR_TogglePaletteRendering();
HWR_PrecacheLevel();
}
}
void CV_gllightdithering_OnChange(void)
{
ONLY_IF_GL_LOADED
if (gl_shadersavailable)
{
HWR_CompileShaders();
}
}
void CV_glpalettedepth_OnChange(void);
void CV_glpalettedepth_OnChange(void)
{
ONLY_IF_GL_LOADED
@ -1298,13 +1044,6 @@ void HWR_AddCommands(void)
{
CV_RegisterVar(&cv_fovchange);
#ifdef ALAM_LIGHTING
CV_RegisterVar(&cv_glstaticlighting);
CV_RegisterVar(&cv_gldynamiclighting);
CV_RegisterVar(&cv_glcoronasize);
CV_RegisterVar(&cv_glcoronas);
#endif
#ifdef BAD_MODEL_OPTIONS
CV_RegisterVar(&cv_glmodellighting);
CV_RegisterVar(&cv_glmodelinterpolation);
@ -1332,10 +1071,14 @@ void HWR_AddCommands(void)
CV_RegisterVar(&cv_glpaletterendering);
CV_RegisterVar(&cv_glpalettedepth);
CV_RegisterVar(&cv_gllightdither);
COM_AddCommand("gr_printportals", Command_Glprintportals_f);
CV_RegisterVar(&cv_gldebugportal);
CV_RegisterVar(&cv_glskydebug);
CV_RegisterVar(&cv_glscreentextures);
}
void HWR_AddSessionCommands(void)
@ -1361,14 +1104,19 @@ void HWR_Startup(void)
HWR_AddSessionCommands();
HWR_InitMapTextures();
HWR_InitModels();
#ifdef ALAM_LIGHTING
HWR_InitLight();
#endif
HWR_LoadAllBaseShaders();
gl_shadersavailable = HWR_InitShaders();
HWR_SetShaderState();
HWR_LoadAllCustomShaders();
HWR_TogglePaletteRendering();
if (cv_glscreentextures.value != 2)
{
if (cv_glpaletterendering.value != 0)
CV_SetValue(&cv_glpaletterendering, 0);
}
GL_SetSpecialState(HWD_SET_SCREEN_TEXTURES, cv_glscreentextures.value);
}
gl_init = true;
@ -1468,6 +1216,9 @@ void HWR_DoPostProcessor(player_t *player)
GL_DrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest);
}
if (cv_glscreentextures.value != 2) // screen textures are needed for the rest of the effects
return;
// Capture the screen for intermission and screen waving
if (gamestate != GS_INTERMISSION)
GL_MakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
@ -1578,6 +1329,12 @@ static boolean HWR_WipeCheck(UINT8 wipenum, UINT8 scrnnum)
void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
{
if (cv_glscreentextures.value == 0)
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // just draw a black screen instead of flashing and crap
return;
}
if (!HWR_WipeCheck(wipenum, scrnnum))
return;

View file

@ -85,15 +85,8 @@ boolean HWR_ShouldUsePaletteRendering(void);
extern CV_PossibleValue_t glanisotropicmode_cons_t[];
#ifdef ALAM_LIGHTING
extern consvar_t cv_gldynamiclighting;
extern consvar_t cv_glstaticlighting;
extern consvar_t cv_glcoronas;
extern consvar_t cv_glcoronasize;
#endif
extern consvar_t cv_glshaders, cv_glallowshaders;
extern consvar_t cv_glmodels;
extern consvar_t cv_glmodels, cv_glscreentextures;
// SRB2Kart: We don't like these options.
// Interpolation should be up to who animated the model.
@ -120,6 +113,7 @@ extern consvar_t cv_glsolvetjoin, cv_glpolytile, cv_glpolyshape;
extern consvar_t cv_glbatching;
extern consvar_t cv_glpaletterendering;
extern consvar_t cv_glpalettedepth;
extern consvar_t cv_gllightdither;
extern consvar_t cv_gldebugportal;
extern consvar_t cv_glskydebug;
@ -164,21 +158,6 @@ extern boolean gl_shadersavailable;
extern boolean gl_rendering_skybox;
/* Portal stuff */
// TODO probably put this to a separate file?
boolean HWR_AddPortal(line_t *start, line_t *dest, seg_t *seg);
extern INT32 gl_portal_level;
extern boolean gl_drawing_stencil;
extern sector_t *gl_portalcullsector;
extern line_t *gl_portalclipline;
extern boolean gl_printportals;
extern INT32 gl_debugportal;
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -2034,7 +2034,7 @@ static void loading_status(void)
x = BASEVIDWIDTH/2;
y = BASEVIDHEIGHT/2;
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); // Black background to match fade in effect
//V_DrawPatchFill(W_CachePatchName("SRB2BACK",PU_CACHE)); // SRB2 background, ehhh too bright.
//V_DrawPatchFill(srb2back); // SRB2 background, ehhh too bright.
M_DrawTextBox(x-58, y-8, 13, 1);
V_DrawString(x-50, y, V_YELLOWMAP, "Loading...");
V_DrawRightAlignedString(x+50, y, V_YELLOWMAP, s);

View file

@ -25,7 +25,6 @@
#ifdef HWRENDER
#include "hw_gpu.h"
#include "hw_light.h"
#include "hw_md2.h"
#include "../d_main.h"
#include "../r_bsp.h"
@ -535,17 +534,7 @@ void HWR_InitModels(void)
}
loadmodelfile:
if (loaded == MD2M_MODELS)
{
modelfile = "models.dat";
}
else if (loaded == MD2M_BLANMODELS)
{
modelfile = "blanmodels.dat";
}
if (!modelfile)
return; // No modelfile somehow?
modelfile = loaded == MD2M_MODELS ? "models.dat" : "blanmodels.dat";
// read the models.dat/blanmodels.dat file
//Filename checking fixed ~Monster Iestyn and Golden
@ -556,6 +545,11 @@ loadmodelfile:
f = fopen(va("%s"PATHSEP"%s", srb2path, modelfile), "rt");
if (!f)
{
if (loaded == MD2M_MODELS)
{
loaded = MD2M_BLANMODELS;
goto loadmodelfile;
}
CONS_Printf("Error while loading %s: %s\n", modelfile, strerror(errno));
nomd2s = true;
return;

View file

@ -1,4 +1,4 @@
// SONIC ROBO BLAST 2
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2022 by Sonic Team Junior.
@ -290,11 +290,6 @@ void HWR_RenderPlane(subsector_t *subsector, poly_subsector_t *xsub, boolean isc
}
}
}
#ifdef ALAM_LIGHTING
// add here code for dynamic lighting on planes
HWR_PlaneLighting(planeVerts, nrPlaneVerts);
#endif
}
void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,

235
src/hardware/hw_portal.c Normal file
View file

@ -0,0 +1,235 @@
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2022 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file hw_portal.c
/// \brief Visual Portal rendering
#ifdef HWRENDER
#include "hw_glob.h"
#include "hw_clip.h"
#include "hw_gpu.h"
#include "../r_local.h"
#include "../g_game.h"
#include "../r_fps.h"
#include "../z_zone.h"
// TODO magic number 16
gl_portal_array_t gl_portal_arrays[MAXPORTALS_CAP+1] = {0};
INT32 gl_portal_level = 0; // portal recursion level
boolean gl_drawing_stencil = false; // used when drawing segs to stencil buffer
sector_t *gl_portalcullsector = NULL;
line_t *gl_portalclipline = NULL;
// debug tools
boolean gl_printportals = false; // print info about portals on this frame
INT32 gl_debugportal = 0; // hide main viewpoint and only render this portal without stencil
void HWR_PortalFrame(gl_portal_t *portal, boolean set_culling)
{
viewx = portal->viewx;
viewy = portal->viewy;
viewz = portal->viewz;
viewangle = portal->viewangle;
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
// set_culling will be true if RenderBSPNode is about to be called
// so need to enable portal culling for that
if (set_culling)
{
gl_portalcullsector = portal->clipline->frontsector;
gl_portalclipline = portal->clipline;
}
}
// get currently used portal array
gl_portal_array_t *HWR_GetPortalArray(void)
{
INT32 level = gl_portal_level;
if (gl_rendering_skybox)
level++;
return &gl_portal_arrays[level];
}
boolean HWR_AddPortal(line_t *start, line_t *dest, seg_t *seg)
{
gl_portal_array_t *array;
gl_portal_t *portal;
angle_t dangle;
fixed_t disttopoint;
angle_t angtopoint;
vertex_t dest_c, start_c;
if ((gl_portal_level + gl_rendering_skybox) >= cv_maxportals.value ||
(gl_debugportal &&
(gl_debugportal != (start-lines) || gl_portal_level)))
{
return false;
}
if (gl_debugportal)
gl_debugportal = -1; // skip other portal segs from the same line
array = HWR_GetPortalArray();
// yet another dynamic array
if (!array->portals)
{
array->capacity = INIT_PORTAL_ARRAY_SIZE;
array->portals = Z_Malloc(sizeof(gl_portal_t) * array->capacity, PU_LEVEL,
&array->portals);
}
else if (array->size == array->capacity)
{
array->capacity *= 2;
array->portals = Z_Realloc(array->portals, sizeof(gl_portal_t) * array->capacity,
PU_LEVEL, &array->portals);
}
portal = &array->portals[array->size++];
// Most fixed-point calculations and trigonometric function tables are replaced by
// floats and cmath library calls in this part to improve the precision of the
// location and angle of the new viewpoint.
//
// This reduces artefacts on the edges of portals, showing thin lines/pixels
// of the underlying graphics. (for example the sky texture) It's not 100%
// perfectly aligned and artefact-free, but looks noticeably
// better than the original code. I'm not even sure if it's this
// code or the nodebuilder or hw_map or something else causing the remaining issues..
//#define R_PointToAngle2Precise R_PointToAngle2
//#define R_PointToDist2Precise R_PointToDist2
dangle = R_PointToAngle2Precise(0,0,dest->dx,dest->dy) - R_PointToAngle2Precise(start->dx,start->dy,0,0);
// looking glass center
start_c.x = start->v1->x/2 + start->v2->x/2;
start_c.y = start->v1->y/2 + start->v2->y/2;
// other side center
dest_c.x = dest->v1->x/2 + dest->v2->x/2;
dest_c.y = dest->v1->y/2 + dest->v2->y/2;
disttopoint = R_PointToDist2Precise(start_c.x, start_c.y, viewx, viewy);
angtopoint = R_PointToAngle2Precise(start_c.x, start_c.y, viewx, viewy);
angtopoint += dangle;
float fang = ((float)angtopoint / 4294967296.0f) * 2.0f * M_PI;
//portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
//portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
//portal->viewx = dest_c.x + FixedMul(FLOAT_TO_FIXED(cos(fang)), disttopoint);
//portal->viewy = dest_c.y + FixedMul(FLOAT_TO_FIXED(sin(fang)), disttopoint);
// cos and sin are just scaling disttopoint so no need for float-fixed conversions
portal->viewx = dest_c.x + (fixed_t)(cos(fang) * disttopoint);
portal->viewy = dest_c.y + (fixed_t)(sin(fang) * disttopoint);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->viewangle = viewangle + dangle;
portal->seg = seg;
portal->clipline = dest;
portal->angle1 = R_PointToAngle64(seg->v1->x, seg->v1->y) + dangle;
portal->angle2 = R_PointToAngle64(seg->v2->x, seg->v2->y) + dangle;
return true;
}
void HWR_ClearPortals(void)
{
HWR_GetPortalArray()->size = 0;
}
// clip the area outside the portal destination window
void HWR_PortalClipping(gl_portal_t *portal)
{
gld_clipper_SafeAddClipRange(portal->angle1, portal->angle2);
}
void HWR_RenderPortalSeg(seg_t *seg)
{
gl_drawing_stencil = true;
gl_curline = seg;
gl_frontsector = seg->frontsector;
gl_backsector = seg->backsector;
HWR_ProcessSeg();
gl_drawing_stencil = false;
// need to work around the r_opengl PF_Invisible bug with this call
// similarly as in the linkdraw hack in HWR_DrawSprites
GL_SetBlend(PF_Translucent|PF_Occlude|PF_Masked);
}
void HWR_SetStencilState(INT32 state)
{
GL_SetStencilMode(state, gl_portal_level);
}
// clear the depth buffer from the stenciled area so portal
// content doesn't get clipped by previous buffer content
// (glClear ignores the stencil buffer so can't be used for this purpose)
void HWR_RenderDepthEraser(boolean visible)
{
FOutVector verts[4] = {0};
FBITFIELD blendflags = PF_Occlude|PF_NoDepthTest|PF_NoTexture|PF_NoAlphaTest;
if (!visible)
blendflags |= PF_Invisible;
// so this is apparently how you draw the far clipping plane when
// pfnSetTransform(NULL) is active
const float a = FAR_CLIPPING_PLANE;
verts[0].x = -a; verts[0].y = -a; verts[0].z = a;
verts[1].x = -a; verts[1].y = a; verts[1].z = a;
verts[2].x = a; verts[2].y = a; verts[2].z = a;
verts[3].x = a; verts[3].y = -a; verts[3].z = a;
GL_SetTransform(NULL);
GL_DrawPolygon(NULL, verts, 4, blendflags);
}
void HWR_RenderPortal(gl_portal_t *portal, gl_portal_t *rootportal, player_t *player, boolean is_skybox)
{
HWR_PushSpriteState();
HWR_PushDrawNodeState();
if (!gl_debugportal)
{
HWR_SetStencilState(HWD_STENCIL_PORTAL_BEGIN);
HWR_RenderPortalSeg(portal->seg);
}
gl_portal_level++;
if (!gl_debugportal)
HWR_SetStencilState(HWD_STENCIL_PORTAL_INSIDE);
HWR_RenderDepthEraser(true);
HWR_PortalFrame(portal, true);
HWR_RenderViewpoint(player, true, is_skybox, false, portal);
// restore previous frame and transform
if (rootportal)
HWR_PortalFrame(rootportal, false);
else if (is_skybox)
R_SkyboxFrame(viewssnum);
else
R_SetupFrame(viewssnum, is_skybox);
HWR_PrepareTransform(player, is_skybox);
GL_SetTransform(&atransform);
HWR_ResetClipper();
if (!gl_debugportal)
{
HWR_SetStencilState(HWD_STENCIL_PORTAL_FINISH);
HWR_RenderPortalSeg(portal->seg);
}
gl_portal_level--;
HWR_PopSpriteState();
HWR_PopDrawNodeState();
}
#endif

View file

@ -1,4 +1,4 @@
// SONIC ROBO BLAST 2
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2022 by Sonic Team Junior.

View file

@ -1,4 +1,4 @@
// SONIC ROBO BLAST 2
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 2021 by Sonic Team Junior.
//
@ -21,41 +21,9 @@
// ================
static struct {
const char *vertex;
const char *fragment;
} const gl_shadersources[] = {
// Floor shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FLOOR_FRAGMENT_SHADER},
// Wall shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER},
// Sprite shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER},
// Model shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER},
// Model shader + diffuse lighting from above
{GLSL_MODEL_LIGHTING_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER},
// Water shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER},
// Fog shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER},
// Sky shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER},
// Palette postprocess shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER},
// UI colormap fade shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER},
{NULL, NULL},
};
char *vertex;
char *fragment;
} gl_baseshaders[NUMSHADERTARGETS];
typedef struct
{
@ -81,6 +49,7 @@ static shadertarget_t gl_shadertargets[NUMSHADERTARGETS];
#define MODEL_LIGHTING_DEFINE "#define SRB2_MODEL_LIGHTING"
#define PALETTE_RENDERING_DEFINE "#define SRB2_PALETTE_RENDERING"
#define LIGHT_DITHERING_DEFINE "#define SRB2_LIGHT_DITHER"
// Initialize shader variables and the backend's shader system. Load the base shaders.
// Returns false if shaders cannot be used.
@ -94,8 +63,28 @@ boolean HWR_InitShaders(void)
for (i = 0; i < NUMSHADERTARGETS; i++)
{
// set up string pointers for base shaders
gl_shaders[i].vertex = Z_StrDup(gl_shadersources[i].vertex);
gl_shaders[i].fragment = Z_StrDup(gl_shadersources[i].fragment);
if (gl_baseshaders[i].vertex)
{
gl_shaders[i].vertex = Z_StrDup(gl_baseshaders[i].vertex);
}
else
{
CONS_Alert(CONS_ERROR, "HWR_InitShaders: Could not load base vertex shader for%s\n", shaderxlat[i].type);
gl_shaders[i].vertex = Z_StrDup(GLSL_FALLBACK_VERTEX_SHADER);
}
if (gl_baseshaders[i].fragment)
{
gl_shaders[i].fragment = Z_StrDup(gl_baseshaders[i].fragment);
}
else
{
CONS_Alert(CONS_ERROR, "HWR_InitShaders: Could not load base fragment shader for%s\n", shaderxlat[i].type);
gl_shaders[i].fragment = Z_StrDup(GLSL_FALLBACK_FRAGMENT_SHADER);
}
// set shader target indices to correct values
gl_shadertargets[i].base_shader = i;
gl_shadertargets[i].custom_shader = -1;
@ -284,6 +273,9 @@ static char *HWR_PreprocessShader(char *original)
if (cv_glpaletterendering.value)
ADD_TO_LEN(PALETTE_RENDERING_DEFINE)
if (cv_gllightdither.value)
ADD_TO_LEN(LIGHT_DITHERING_DEFINE)
#undef ADD_TO_LEN
#define VERSION_PART "#version "
@ -329,6 +321,9 @@ static char *HWR_PreprocessShader(char *original)
if (cv_glpaletterendering.value)
WRITE_DEFINE(PALETTE_RENDERING_DEFINE)
if (cv_gllightdither.value)
WRITE_DEFINE(LIGHT_DITHERING_DEFINE)
#undef WRITE_DEFINE
// Write a #line directive, so compiler errors will report line numbers from the
@ -440,21 +435,23 @@ customshaderxlat_t shaderxlat[] =
{"Sky", SHADER_SKY},
{"PalettePostprocess", SHADER_PALETTE_POSTPROCESS},
{"UIColormapFade", SHADER_UI_COLORMAP_FADE},
{"FinalPostProcess", SHADER_FINAL_POST_PROCESS},
{NULL, 0},
};
void HWR_LoadAllCustomShaders(void)
void HWR_LoadAllBaseShaders(void)
{
/*
INT32 i;
// read every custom shader
// read every base shader added by iwads.
for (i = 0; i < numwadfiles; i++)
HWR_LoadCustomShadersFromFile(i, (type == RET_PK3)));
*/
{
HWR_LoadCustomShadersFromFile(i, (wadfiles[i]->type == RET_PK3), true);
}
}
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3, boolean startup)
{
UINT16 lump;
char *shaderdef, *line;
@ -466,7 +463,7 @@ void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
int i;
boolean modified_shaders[NUMSHADERTARGETS] = {0};
if (!gl_shadersavailable)
if (!startup && !gl_shadersavailable)
return;
lump = HWR_FindShaderDefs(wadnum);
@ -563,7 +560,11 @@ skip_lump:
W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source);
shader_source[shader_string_length-1] = '\0';
shader_index = shaderxlat[i].id + NUMSHADERTARGETS;
if (startup)
shader_index = shaderxlat[i].id;
else
shader_index = shaderxlat[i].id + NUMSHADERTARGETS;
if (!modified_shaders[shaderxlat[i].id])
{
// this will clear any old custom shaders from previously loaded files
@ -572,26 +573,59 @@ skip_lump:
gl_shaders[shader_index].vertex = NULL;
Z_Free(gl_shaders[shader_index].fragment);
gl_shaders[shader_index].fragment = NULL;
if (startup)
{
Z_Free(gl_baseshaders[shader_index].vertex);
gl_baseshaders[shader_index].vertex = NULL;
Z_Free(gl_baseshaders[shader_index].fragment);
gl_baseshaders[shader_index].fragment = NULL;
}
}
modified_shaders[shaderxlat[i].id] = true;
if (shadertype == 1)
{
if (gl_shaders[shader_index].vertex)
if (startup)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s vertex shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
Z_Free(gl_shaders[shader_index].vertex);
if (gl_baseshaders[shader_index].vertex)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s vertex shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
Z_Free(gl_baseshaders[shader_index].vertex);
}
gl_baseshaders[shader_index].vertex = Z_StrDup(shader_source);
}
else
{
if (gl_shaders[shader_index].vertex)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s vertex shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
Z_Free(gl_shaders[shader_index].vertex);
}
gl_shaders[shader_index].vertex = shader_source;
}
gl_shaders[shader_index].vertex = shader_source;
}
else
{
if (gl_shaders[shader_index].fragment)
if (startup)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s fragment shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
Z_Free(gl_shaders[shader_index].fragment);
if (gl_baseshaders[shader_index].fragment)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s fragment shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
Z_Free(gl_baseshaders[shader_index].fragment);
}
gl_baseshaders[shader_index].fragment = Z_StrDup(shader_source);
}
else
{
if (gl_shaders[shader_index].fragment)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s fragment shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
Z_Free(gl_shaders[shader_index].fragment);
}
gl_shaders[shader_index].fragment = shader_source;
}
gl_shaders[shader_index].fragment = shader_source;
}
Z_Free(shader_lumpname);
@ -604,21 +638,24 @@ skip_field:
}
}
for (i = 0; i < NUMSHADERTARGETS; i++)
if (!startup)
{
if (modified_shaders[i])
for (i = 0; i < NUMSHADERTARGETS; i++)
{
int shader_index = i + NUMSHADERTARGETS; // index to gl_shaders
gl_shadertargets[i].custom_shader = shader_index;
// if only one stage (vertex/fragment) is defined, the other one
// is copied from the base shaders.
if (!gl_shaders[shader_index].fragment)
gl_shaders[shader_index].fragment = Z_StrDup(gl_shadersources[i].fragment);
if (!gl_shaders[shader_index].vertex)
gl_shaders[shader_index].vertex = Z_StrDup(gl_shadersources[i].vertex);
HWR_CompileShader(shader_index);
if (!gl_shaders[shader_index].compiled)
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename);
if (modified_shaders[i])
{
int shader_index = i + NUMSHADERTARGETS; // index to gl_shaders
gl_shadertargets[i].custom_shader = shader_index;
// if only one stage (vertex/fragment) is defined, the other one
// is copied from the base shaders.
if (!gl_shaders[shader_index].fragment)
gl_shaders[shader_index].fragment = Z_StrDup(gl_baseshaders[i].fragment);
if (!gl_shaders[shader_index].vertex)
gl_shaders[shader_index].vertex = Z_StrDup(gl_baseshaders[i].vertex);
HWR_CompileShader(shader_index);
if (!gl_shaders[shader_index].compiled)
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename);
}
}
}

View file

@ -1,4 +1,4 @@
// SONIC ROBO BLAST 2
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 2021 by Sonic Team Junior.
//
@ -22,392 +22,6 @@
// Generic vertex shader
//
#define GLSL_DEFAULT_VERTEX_SHADER \
"void main()\n" \
"{\n" \
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
"gl_FrontColor = gl_Color;\n" \
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
"}\0"
// reinterpretation of sprite lighting for models
// it's a combination of how it works for normal sprites & papersprites
#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \
"uniform float lighting;\n" \
"uniform vec3 light_dir;\n" \
"uniform float light_contrast;\n" \
"uniform float light_backlight;\n" \
"void main()\n" \
"{\n" \
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
"float light = lighting;\n" \
"if (length(light_dir) > 0.000001) {\n" \
"mat4 m4 = gl_ProjectionMatrix * gl_ModelViewMatrix;\n" \
"mat3 m3 = mat3( m4[0].xyz, m4[1].xyz, m4[2].xyz );\n" \
"float extralight = -dot(normalize(gl_Normal * m3), normalize(light_dir));\n" \
"extralight *= light_contrast - light_backlight;\n" \
"extralight *= lighting / 255.0;\n" \
"light += extralight * 2.5;\n" \
"}\n" \
"light = clamp(light / 255.0, 0.0, 1.0);\n" \
"gl_FrontColor = vec4(light, light, light, 1.0);\n" \
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
"}\0"
// ==================
// Fragment shaders
// ==================
//
// Generic fragment shader
//
#define GLSL_DEFAULT_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"void main(void) {\n" \
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
"}\0"
//
// Software fragment shader
//
// Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro.
#define GLSL_DOOM_COLORMAP \
"float R_DoomColormap(float light, float z)\n" \
"{\n" \
"float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \
"float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \
"float startmap = (15.0 - lightnum) * 4.0;\n" \
"float scale = 160.0 / (lightz + 1.0);\n" \
"float cap = (155.0 - light) * 0.26;\n" \
"return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \
"}\n"
// lighting cap adjustment:
// first num (155.0), increase to make it start to go dark sooner
// second num (0.26), increase to make it go dark faster
#define GLSL_DOOM_LIGHT_EQUATION \
"float R_DoomLightingEquation(float light)\n" \
"{\n" \
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
"float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \
"return clamp(colormap, 0.0, 31.0) / 32.0;\n" \
"}\n"
#define GLSL_SOFTWARE_TINT_EQUATION \
"if (mix(tint_color.a, 0.0, brightmap_mix) > 0.0) {\n" \
"float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \
"float strength = sqrt(mix(9.0 * tint_color.a, 0.0, brightmap_mix));\n" \
"final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \
"final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \
"final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \
"}\n"
#define GLSL_SOFTWARE_FADE_EQUATION \
"float darkness = R_DoomLightingEquation(final_lighting);\n" \
"if (fade_start > 0.0 || fade_end < 31.0) {\n" \
"float fs = fade_start / 31.0;\n" \
"float fe = fade_end / 31.0;\n" \
"float fd = fe - fs;\n" \
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
"}\n" \
"if (newfade)\n" \
"{\n" \
"float colorBrightness = sqrt((final_color.r * final_color.r) + (final_color.g * final_color.g) + (final_color.b * final_color.b));\n" \
"float fogBrightness = sqrt((fade_color.r * fade_color.r) + (fade_color.g * fade_color.g) + (fade_color.b * fade_color.b));\n" \
"float colorIntensity = 0.0;\n" \
"if (colorBrightness < fogBrightness) {\n" \
"colorIntensity = 1.0 - min(final_color.r, min(final_color.g, final_color.b));\n" \
"colorIntensity = abs(colorIntensity - (1.0 - max(fade_color.r, max(fade_color.g, fade_color.b))));\n" \
"} else {\n" \
"colorIntensity = max(final_color.r, max(final_color.g, final_color.b));\n" \
"colorIntensity = abs(colorIntensity - min(fade_color.r, min(fade_color.g, fade_color.b)));\n" \
"}\n" \
"colorIntensity *= darkness;\n" \
"colorIntensity *= fade_color.a * 10.0;\n" \
"if (abs(final_color.r - fade_color.r) <= colorIntensity) {\n" \
"final_color.r = fade_color.r;\n" \
"} else if (final_color.r < fade_color.r) {\n" \
"final_color.r += colorIntensity;\n" \
"} else {\n" \
"final_color.r -= colorIntensity;\n" \
"}\n" \
"if (abs(final_color.g - fade_color.g) <= colorIntensity) {\n" \
"final_color.g = fade_color.g;\n" \
"} else if (final_color.g < fade_color.g) {\n" \
"final_color.g += colorIntensity;\n" \
"} else {\n" \
"final_color.g -= colorIntensity;\n" \
"}\n" \
"if (abs(final_color.b - fade_color.b) <= colorIntensity) {\n" \
"final_color.b = fade_color.b;\n" \
"} else if (final_color.b < fade_color.b) {\n" \
"final_color.b += colorIntensity;\n" \
"} else {\n" \
"final_color.b -= colorIntensity;\n" \
"}\n" \
"} else {\n" \
"final_color = mix(final_color, fade_color, darkness);\n" \
"}\n"
#define GLSL_PALETTE_RENDERING \
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
"float light_y = clamp(floor(R_DoomColormap(final_lighting, z)), 0.0, 31.0);\n" \
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \
"vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
#define GLSL_SOFTWARE_FRAGMENT_SHADER \
"#ifdef SRB2_PALETTE_RENDERING\n" \
"uniform sampler2D tex;\n" \
"uniform sampler2D brightmap;\n" \
"uniform vec4 poly_color;\n" \
"uniform float lighting;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
"uniform sampler2D lighttable_tex;\n" \
GLSL_DOOM_COLORMAP \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - lighting) * brightmap_mix;\n" \
"float final_lighting = lighting + light_gain;\n" \
GLSL_PALETTE_RENDERING \
"}\n" \
"#else\n" \
"uniform sampler2D tex;\n" \
"uniform sampler2D brightmap;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
"uniform bool newfade;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"vec4 base_color = texel * poly_color;\n" \
"vec4 final_color = base_color;\n" \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - lighting) * brightmap_mix;\n" \
"float final_lighting = lighting + light_gain;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
"}\n" \
"#endif\0"
// hand tuned adjustments for light level calculation
#define GLSL_FLOOR_FUDGES \
"#define STARTMAP_FUDGE 1.06\n" \
"#define SCALE_FUDGE 1.15\n"
#define GLSL_WALL_FUDGES \
"#define STARTMAP_FUDGE 1.05\n" \
"#define SCALE_FUDGE 2.2\n"
#define GLSL_FLOOR_FRAGMENT_SHADER \
"#version 120\n" \
GLSL_FLOOR_FUDGES \
GLSL_SOFTWARE_FRAGMENT_SHADER
#define GLSL_WALL_FRAGMENT_SHADER \
"#version 120\n" \
GLSL_WALL_FUDGES \
GLSL_SOFTWARE_FRAGMENT_SHADER
// same as above but multiplies results with the lighting value from the
// accompanying vertex shader (stored in gl_Color)
#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \
GLSL_WALL_FUDGES \
"#ifdef SRB2_PALETTE_RENDERING\n" \
"uniform sampler2D tex;\n" \
"uniform sampler2D brightmap;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
"uniform sampler2D lighttable_tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform float lighting;\n" \
GLSL_DOOM_COLORMAP \
"void main(void) {\n" \
" vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"#ifdef SRB2_MODEL_LIGHTING\n" \
"texel *= gl_Color;\n" \
"#endif\n" \
"float final_lighting = gl_Color.r * 255.0;\n" \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - final_lighting) * brightmap_mix;\n" \
"final_lighting += light_gain;\n" \
GLSL_PALETTE_RENDERING \
"}\n" \
"#else\n" \
"uniform sampler2D tex;\n" \
"uniform sampler2D brightmap;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
"uniform bool newfade;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"vec4 base_color = texel * poly_color;\n" \
"vec4 final_color = base_color;\n" \
"float final_lighting = gl_Color.r * 255.0;\n" \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - final_lighting) * brightmap_mix;\n" \
"final_lighting += light_gain;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
"}\n" \
"#endif\0"
//
// Water surface shader
//
// Mostly guesstimated, rather than the rest being built off Software science.
// Still needs to distort things underneath/around the water...
//
#define GLSL_WATER_TEXEL \
"float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
"float a = -pi * (water_z * freq) + (leveltime * speed);\n" \
"float sdistort = sin(a) * amp * 1.5;\n" \
"float cdistort = cos(a) * amp * 2.2;\n" \
"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n"
#define GLSL_WATER_FRAGMENT_SHADER \
"#version 120\n" \
GLSL_FLOOR_FUDGES \
"const float freq = 0.03;\n" \
"const float amp = 0.025;\n" \
"const float speed = 1.6;\n" \
"const float pi = 3.14159;\n" \
"#ifdef SRB2_PALETTE_RENDERING\n" \
"uniform sampler2D tex;\n" \
"uniform sampler2D brightmap;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
"uniform sampler2D lighttable_tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform float lighting;\n" \
"uniform float leveltime;\n" \
GLSL_DOOM_COLORMAP \
"void main(void) {\n" \
GLSL_WATER_TEXEL \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - lighting) * brightmap_mix;\n" \
"float final_lighting = lighting + light_gain;\n" \
GLSL_PALETTE_RENDERING \
"}\n" \
"#else\n" \
"uniform sampler2D tex;\n" \
"uniform sampler2D brightmap;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
"uniform bool newfade;\n" \
"uniform float leveltime;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
GLSL_WATER_TEXEL \
"vec4 base_color = texel * poly_color;\n" \
"vec4 final_color = base_color;\n" \
"float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \
"float light_gain = (255.0 - lighting) * brightmap_mix;\n" \
"float final_lighting = lighting + light_gain;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
"}\n" \
"#endif\0"
//
// Fog block shader
//
// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha
//
// The floor fudges are used, but should the wall fudges be used instead? or something inbetween?
// or separate values for floors and walls? (need to change more than this shader for that)
#define GLSL_FOG_FRAGMENT_SHADER \
"#version 120\n" \
GLSL_FLOOR_FUDGES \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
"uniform bool newfade;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 base_color = gl_Color;\n" \
"vec4 final_color = base_color;\n" \
"float brightmap_mix = 0.0;\n" \
"float light_gain = 0.0;\n" \
"float final_lighting = lighting + light_gain;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"gl_FragColor = final_color;\n" \
"}\0"
//
// Sky fragment shader
// Modulates poly_color with gl_Color
//
#define GLSL_SKY_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"void main(void) {\n" \
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
"}\0"
// Shader for the palette rendering postprocess step
#define GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
"uniform sampler1D palette_tex;\n" \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
"float palette_coord = (tex_pal_idx + 0.5) / 256.0;\n" \
"vec4 final_color = texture1D(palette_tex, palette_coord);\n" \
"gl_FragColor = final_color;\n" \
"}\0"
// Applies a palettized colormap fade to tex
#define GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform float lighting;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
"uniform sampler2D lighttable_tex;\n" \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (lighting + 0.5) / 32.0);\n" \
"gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \
"}\0"
//
// Generic vertex shader
//
#define GLSL_FALLBACK_VERTEX_SHADER \
"void main()\n" \
"{\n" \
@ -428,15 +42,4 @@
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
"}\0"
//
// Sky fragment shader
// Modulates poly_color with gl_Color
//
#define GLSL_SKY_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"void main(void) {\n" \
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
"}\0"
#endif

View file

@ -78,7 +78,6 @@ void HWR_ClearSkyDome(void)
sky->loops = NULL;
sky->data = NULL;
sky->vbo = 0;
sky->rows = sky->columns = 0;
sky->loopcount = 0;

View file

@ -796,11 +796,6 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
gpatch = spr->gpatch;
#ifdef ALAM_LIGHTING
if (!(spr->mobj->flags2 & MF2_DEBRIS) && (spr->mobj->sprite != SPR_PLAY))
HWR_DL_AddLight(spr, gpatch);
#endif
// create the sprite billboard
//
// 3--2
@ -1443,7 +1438,7 @@ void HWR_DrawSprites(void)
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
{
if (LIKELY(!cv_glmodels.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f || (spr->renderflags & RF_NOMODEL)))
if (LIKELY(!cv_glmodels.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f))
HWR_DrawSprite(spr);
else
{
@ -1453,7 +1448,7 @@ void HWR_DrawSprites(void)
}
else
{
if (LIKELY(!cv_glmodels.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f || (spr->renderflags & RF_NOMODEL)))
if (LIKELY(!cv_glmodels.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f))
HWR_DrawSprite(spr);
else
{
@ -1849,6 +1844,18 @@ static void HWR_ProjectSprite(mobj_t *thing)
use_xoffset = spr_width - spr_offset;
}
if (thing->renderflags & RF_ABSOLUTEOFFSETS)
{
use_xoffset = FixedDiv(interp.spritexoffset,highresscale);
}
else
{
SINT8 flipoffset = 1;
if ((thing->renderflags & RF_FLIPOFFSETS) && flip)
flipoffset = -1;
use_xoffset += (FixedDiv(interp.spritexoffset,highresscale) * flipoffset);
}
affine_pivotoffsetdiff.x = FIXED_TO_FLOAT(affine_pivot.x - use_xoffset);
affine_pivotoffsetdiff.y = FIXED_TO_FLOAT(affine_pivot.y - spr_topoffset);
@ -1861,8 +1868,9 @@ static void HWR_ProjectSprite(mobj_t *thing)
angle = R_ConvToRollAngle(spriterotangle) * flipsign;
const fixed_t rolloffs_x = FixedDiv(interptarg->rollingxoffset * FRACUNIT, highresscale) * (((thing->renderflags & RF_FLIPOFFSETS) && flip) ? -1 : 1);
const fixed_t rolloffs_y = FixedDiv(interptarg->rollingyoffset * FRACUNIT, highresscale);
const boolean renderflip = ((thing->renderflags & RF_FLIPOFFSETS) == RF_FLIPOFFSETS);
const fixed_t rolloffs_x = FixedDiv(interptarg->rollingxoffset * FRACUNIT, highresscale) * (((!renderflip) && flip) ? -1 : 1);
const fixed_t rolloffs_y = FixedDiv(interptarg->rollingyoffset * FRACUNIT, highresscale) * (((!renderflip) && vflip) ? -1 : 1);
fixed_t y_piv = affine_pivot.y;
if (vflip)

View file

@ -1,555 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>r_opengl</ProjectName>
<ProjectGuid>{51137D5C-4E81-4955-AACF-EA3092006051}</ProjectGuid>
<RootNamespace>r_opengl</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v141</PlatformToolset>
<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v141</PlatformToolset>
<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v141</PlatformToolset>
<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v141</PlatformToolset>
<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\..\..\objs\VC10\$(Platform)\$(Configuration)\r_opengl\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">.\..\..\..\objs\VC10\$(Platform)\$(Configuration)\r_opengl\</IntDir>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IgnoreImportLibrary>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</IgnoreImportLibrary>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\..\..\objs\VC10\$(Platform)\$(Configuration)\r_opengl\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">.\..\..\..\objs\VC10\$(Platform)\$(Configuration)\r_opengl\</IntDir>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</IgnoreImportLibrary>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\..\..\objs\VC10\$(Platform)\$(Configuration)\r_opengl\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">.\..\..\..\objs\VC10\$(Platform)\$(Configuration)\r_opengl\</IntDir>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</IgnoreImportLibrary>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</IgnoreImportLibrary>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\..\..\objs\VC10\$(Platform)\$(Configuration)\r_opengl\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">.\..\..\..\objs\VC10\$(Platform)\$(Configuration)\r_opengl\</IntDir>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</IgnoreImportLibrary>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ProgramDataBaseFileName>$(IntDir)r_opengl.pdb</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level4</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<OutputFile>$(OutDir)r_opengl.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)r_opengl.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)r_opengl.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<Midl>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TypeLibraryName>.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ProgramDataBaseFileName>$(IntDir)r_opengl.pdb</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level4</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<OutputFile>$(OutDir)r_opengl.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)r_opengl.pdb</ProgramDatabaseFile>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)r_opengl.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>X64</TargetEnvironment>
<TypeLibraryName>.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ProgramDataBaseFileName>$(IntDir)r_opengl.pdb</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level4</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<OutputFile>$(OutDir)r_opengl.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)r_opengl.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)r_opengl.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<Midl>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TypeLibraryName>.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ProgramDataBaseFileName>$(IntDir)r_opengl.pdb</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level4</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<OutputFile>$(OutDir)r_opengl.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)r_opengl.pdb</ProgramDatabaseFile>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)r_opengl.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ProgramDataBaseFileName>$(IntDir)r_opengl.pdb</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<OutputFile>$(OutDir)r_opengl.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)r_opengl.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)r_opengl.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TypeLibraryName>.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ProgramDataBaseFileName>$(IntDir)r_opengl.pdb</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<OutputFile>$(OutDir)r_opengl.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)r_opengl.pdb</ProgramDatabaseFile>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)r_opengl.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>X64</TargetEnvironment>
<TypeLibraryName>.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ProgramDataBaseFileName>$(IntDir)r_opengl.pdb</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<OutputFile>$(OutDir)r_opengl.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)r_opengl.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)r_opengl.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TypeLibraryName>.\..\..\..\bin\VC10\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ProgramDataBaseFileName>$(IntDir)r_opengl.pdb</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<OutputFile>$(OutDir)r_opengl.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)r_opengl.pdb</ProgramDatabaseFile>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)r_opengl.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ogl_win.c">
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="r_opengl.c">
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="r_opengl.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\win32\Srb2win-vc10.vcxproj">
<Project>{0f554f1d-ed49-4d65-a9a7-f63c57f277be}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -1,480 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="r_opengl"
ProjectGUID="{51137D5C-4E81-4955-AACF-EA3092006051}"
RootNamespace="r_opengl"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\..\..\..\bin\VC9\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory=".\..\..\..\objs\VC9\$(PlatformName)\$(ConfigurationName)\r_opengl"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\..\..\..\bin\VC9\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
AssemblerListingLocation="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\r_opengl.pdb"
BrowseInformation="1"
WarningLevel="4"
SuppressStartupBanner="true"
DebugInformationFormat="4"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
IgnoreImportLibrary="true"
OutputFile="$(OutDir)\r_opengl.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)\r_opengl.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(IntDir)\r_opengl.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile="$(OutDir)\r_opengl.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory=".\..\..\..\bin\VC9\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory=".\..\..\..\objs\VC9\$(PlatformName)\$(ConfigurationName)\r_opengl"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\..\..\..\bin\VC9\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
AssemblerListingLocation="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\r_opengl.pdb"
BrowseInformation="1"
WarningLevel="4"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
IgnoreImportLibrary="true"
OutputFile="$(OutDir)\r_opengl.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)\r_opengl.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(IntDir)\r_opengl.lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile="$(OutDir)\r_opengl.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\..\..\..\bin\VC9\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory=".\..\..\..\objs\VC9\$(PlatformName)\$(ConfigurationName)\r_opengl"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\..\..\..\bin\VC9\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP"
Optimization="2"
InlineFunctionExpansion="1"
PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
AssemblerListingLocation="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\r_opengl.pdb"
BrowseInformation="1"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
IgnoreImportLibrary="true"
OutputFile="$(OutDir)\r_opengl.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)\r_opengl.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(IntDir)\r_opengl.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile="$(OutDir)\r_opengl.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory=".\..\..\..\bin\VC9\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory=".\..\..\..\objs\VC9\$(PlatformName)\$(ConfigurationName)\r_opengl"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\..\..\..\bin\VC9\$(Platform)\$(Configuration)\r_opengl\r_opengl.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP"
Optimization="2"
InlineFunctionExpansion="1"
PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;__WIN32__;__MSC__;USE_WGL_SWAP;_CRT_SECURE_NO_WARNINGS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
AssemblerListingLocation="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\r_opengl.pdb"
BrowseInformation="1"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
IgnoreImportLibrary="true"
OutputFile="$(OutDir)\r_opengl.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)\r_opengl.pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(IntDir)\r_opengl.lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile="$(OutDir)\r_opengl.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="ogl_win.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="r_opengl.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="r_opengl.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -628,6 +628,9 @@ static PFNglUniform3fv pglUniform3fv;
static PFNglGetUniformLocation pglGetUniformLocation;
// 13062019
static INT32 gl_enable_screen_textures = 2;
typedef enum
{
// textures
@ -654,6 +657,8 @@ typedef enum
// misc.
gluniform_leveltime,
gluniform_scr_resolution,
gluniform_max,
} gluniform_t;
@ -864,6 +869,10 @@ void GL_SetShader(int slot)
return;
}
// If using model lighting, set the appropriate shader.
if (slot == SHADER_MODEL && model_lighting)
slot = SHADER_MODEL_LIGHTING;
if (gl_allowshaders)
{
gl_shader_t *next_shader = &gl_shaders[slot]; // the gl_shader_t we are going to switch to
@ -1935,6 +1944,8 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
UNIFORM_1(shader->uniforms[gluniform_leveltime], shader_leveltime, pglUniform1f);
UNIFORM_2(shader->uniforms[gluniform_scr_resolution], (GLfloat)vid.width, (GLfloat)vid.height, pglUniform2f);
#undef UNIFORM_1
#undef UNIFORM_2
#undef UNIFORM_3
@ -2050,24 +2061,26 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i)
shader->uniforms[gluniform_brightmap] = GETUNI("brightmap");
// lighting
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
shader->uniforms[gluniform_newfade] = GETUNI("newfade");
shader->uniforms[gluniform_light_dir] = GETUNI("light_dir");
shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast");
shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight");
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
shader->uniforms[gluniform_newfade] = GETUNI("newfade");
shader->uniforms[gluniform_light_dir] = GETUNI("light_dir");
shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast");
shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight");
// palette rendering
shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex");
shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex");
shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex");
shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex");
shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex");
shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex");
shader->uniforms[gluniform_scr_resolution] = GETUNI("scr_resolution");
// misc. (custom shaders)
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
#undef GETUNI
@ -2086,7 +2099,7 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i)
// restore gl shader state
pglUseProgram(gl_shaderstate.program);
#undef UNIFORM_1
#undef UNIFORM_1
return true;
}
@ -2401,6 +2414,10 @@ void GL_SetSpecialState(hwdspecialstate_t IdState, INT32 Value)
Flush(); //??? if we want to change filter mode by texture, remove this
break;
case HWD_SET_SCREEN_TEXTURES:
gl_enable_screen_textures = Value;
break;
default:
break;
}
@ -2724,7 +2741,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
if (Surface->LightTableId && Surface->LightTableId != lt_downloaded)
{
pglActiveTexture(GL_TEXTURE2);
pglActiveTexture(GL_TEXTURE3);
pglBindTexture(GL_TEXTURE_2D, Surface->LightTableId);
pglActiveTexture(GL_TEXTURE0);
lt_downloaded = Surface->LightTableId;
@ -3033,6 +3050,9 @@ void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2])
float float_x, float_y, float_nextx, float_nexty;
float xfix, yfix;
if (gl_enable_screen_textures != 2)
return;
const float blackBack[16] =
{
-16.0f, -16.0f, 6.0f,
@ -3125,6 +3145,9 @@ void GL_DrawScreenTexture(int tex, FSurfaceInfo *surf, FBITFIELD polyflags)
{
float xfix, yfix;
if (gl_enable_screen_textures != 2)
return;
const float screenVerts[12] =
{
-1.0f, -1.0f, 1.0f,
@ -3173,6 +3196,9 @@ void GL_DoScreenWipe(int wipeStart, int wipeEnd)
INT32 fademaskdownloaded = tex_downloaded; // the fade mask that has been set
if (!gl_enable_screen_textures)
return;
const float screenVerts[12] =
{
-1.0f, -1.0f, 1.0f,
@ -3250,6 +3276,9 @@ void GL_MakeScreenTexture(int tex)
{
boolean firstTime = (screenTextures[tex] == 0);
if (!gl_enable_screen_textures)
return;
// Create screen texture
if (firstTime)
pglGenTextures(1, &screenTextures[tex]);
@ -3275,6 +3304,9 @@ void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8
float fix[8];
float i;
if (gl_enable_screen_textures != 2)
return;
GLubyte color[4] = {255, 255, 255, 255};
float screenVerts[12] =
@ -3392,6 +3424,9 @@ void GL_DrawScreenFinalTexture(int tex, int width, int height)
float off[12];
float fix[8];
if (gl_enable_screen_textures != 2)
return;
xfix = 1/((float)(texsize)/((float)((screen_width))));
yfix = 1/((float)(texsize)/((float)((screen_height))));
@ -3439,6 +3474,8 @@ void GL_DrawScreenFinalTexture(int tex, int width, int height)
GL_ClearBuffer(true, false, false, &clearColour);
pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]);
Shader_SetUniforms(NULL, NULL, NULL, NULL); // prepare shader, if it is enabled
pglColor4ubv(white);
pglTexCoordPointer(2, GL_FLOAT, 0, fix);

View file

@ -16,6 +16,7 @@
#include "hu_stuff.h"
#include "font.h"
#include "k_grandprix.h"
#include "m_menu.h" // gametype_cons_t
#include "m_cond.h" // emblems
#include "m_misc.h" // word jumping
@ -67,12 +68,6 @@
#define HU_INPUTX 0
#define HU_INPUTY 0
typedef enum
{
HU_SHOUT = 1, // Shout message
HU_CSAY = 1<<1, // Middle-of-screen server message
} sayflags_t;
//-------------------------------------------
// heads up font
//-------------------------------------------
@ -87,6 +82,8 @@ patch_t *pinglocal[2]; // mindelay indecator
patch_t *framecounter;
patch_t *frameslash; // framerate stuff. Used in screen.c
patch_t *srb2back = NULL;
static player_t *plr;
boolean hu_keystrokes; // :)
boolean chat_on; // entering a chat message?
@ -119,49 +116,6 @@ static void HU_DrawRankings(void);
// KEYBOARD LAYOUTS FOR ENTERING TEXT
//======================================================================
char *shiftxform;
char english_shiftxform[] =
{
0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31,
' ', '!', '"', '#', '$', '%', '&',
'"', // shift-'
'(', ')', '*', '+',
'<', // shift-,
'_', // shift--
'>', // shift-.
'?', // shift-/
')', // shift-0
'!', // shift-1
'@', // shift-2
'#', // shift-3
'$', // shift-4
'%', // shift-5
'^', // shift-6
'&', // shift-7
'*', // shift-8
'(', // shift-9
':',
':', // shift-;
'<',
'+', // shift-=
'>', '?', '@',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'{', // shift-[
'|', // shift-backslash - OH MY GOD DOES WATCOM SUCK
'}', // shift-]
'"', '_',
'~', // shift-`
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'{', '|', '}', '~', 127
};
static char cechotext[1024];
static tic_t cechotimer = 0;
static tic_t cechoduration = 5*TICRATE;
@ -214,6 +168,8 @@ void HU_LoadGraphics(void)
// fps stuff
HU_UpdatePatch(&framecounter, "FRAMER");
HU_UpdatePatch(&frameslash, "FRAMESL");
HU_UpdatePatch(&srb2back, "SRB2BACK");
}
// Initialise Heads up
@ -240,9 +196,6 @@ void HU_Init(void)
missingpat = W_CachePatchNum(missingnum, PU_STATIC);
}
// set shift translation table
shiftxform = english_shiftxform;
/*
Setup fonts
*/
@ -491,96 +444,29 @@ void HU_AddChatText(const char *text, boolean playsound)
* \author Graue <graue@oceanbase.org>
*/
static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
void DoSayCommand(char *message, SINT8 target, UINT8 flags, UINT8 source)
{
char buf[2 + HU_MAXMSGLEN + 1];
size_t numwords, ix;
char *msg = &buf[2];
const size_t msgspace = sizeof buf - 2;
numwords = COM_Argc() - usedargs;
I_Assert(numwords > 0);
if (CHAT_MUTE) // TODO: Per Player mute.
{
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
return;
}
// Only servers/admins can shout or CSAY.
if (!server && !IsPlayerAdmin(consoleplayer))
{
flags &= ~(HU_SHOUT|HU_CSAY);
}
char *msg = &buf[3];
// Enforce shout for the dedicated server.
if (dedicated && !(flags & HU_CSAY))
if (dedicated && source == serverplayer && !(flags & HU_CSAY))
{
flags |= HU_SHOUT;
}
buf[0] = target;
buf[1] = flags;
buf[2] = source;
msg[0] = '\0';
for (ix = 0; ix < numwords; ix++)
{
if (ix > 0)
strlcat(msg, " ", msgspace);
strlcat(msg, COM_Argv(ix + usedargs), msgspace);
}
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
{
// what we're gonna do now is check if the player exists
// with that logic, characters 4 and 5 are our numbers:
const char *newmsg;
char playernum[3];
INT32 spc = 1; // used if playernum[1] is a space.
strncpy(playernum, msg+3, 3);
// check for undesirable characters in our "number"
if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
{
// check if playernum[1] is a space
if (playernum[1] == ' ')
spc = 0;
// let it slide
else
{
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
return;
}
}
// I'm very bad at C, I swear I am, additional checks eww!
if (spc != 0 && msg[5] != ' ')
{
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
return;
}
target = atoi(playernum); // turn that into a number
//CONS_Printf("%d\n", target);
// check for target player, if it doesn't exist then we can't send the message!
if (target < MAXPLAYERS && playeringame[target]) // player exists
target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
else
{
HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same
return;
}
buf[0] = target;
newmsg = msg+5+spc;
strlcpy(msg, newmsg, HU_MAXMSGLEN + 1);
}
strcpy(msg, message);
SendNetXCmd(XD_SAY, buf, strlen(msg) + 1 + msg-buf);
}
/** Send a message to everyone.
* \sa DoSayCommand, Command_Sayteam_f, Command_Sayto_f
* \sa DoSayPacket, Command_Sayteam_f, Command_Sayto_f
* \author Graue <graue@oceanbase.org>
*/
static void Command_Say_f(void)
@ -593,11 +479,11 @@ static void Command_Say_f(void)
// Autoshout is handled by HU_queueChatChar.
// If you're using the say command, you can use the shout command, lol.
DoSayCommand(0, 1, 0);
DoSayPacketFromCommand(0, 1, 0);
}
/** Send a message to a particular person.
* \sa DoSayCommand, Command_Sayteam_f, Command_Say_f
* \sa DoSayPacket, Command_Sayteam_f, Command_Say_f
* \author Graue <graue@oceanbase.org>
*/
static void Command_Sayto_f(void)
@ -618,11 +504,11 @@ static void Command_Sayto_f(void)
}
target++; // Internally we use 0 to 31, but say command uses 1 to 32.
DoSayCommand((SINT8)target, 2, 0);
DoSayPacketFromCommand((SINT8)target, 2, 0);
}
/** Send a message to members of the player's team.
* \sa DoSayCommand, Command_Say_f, Command_Sayto_f
* \sa DoSayPacket, Command_Say_f, Command_Sayto_f
* \author Graue <graue@oceanbase.org>
*/
static void Command_Sayteam_f(void)
@ -640,9 +526,9 @@ static void Command_Sayteam_f(void)
}
if (G_GametypeHasTeams()) // revert to normal say if we don't have teams in this gametype.
DoSayCommand(-1, 1, 0);
DoSayPacketFromCommand(-1, 1, 0);
else
DoSayCommand(0, 1, 0);
DoSayPacketFromCommand(0, 1, 0);
}
/** Send a message to everyone, to be displayed by CECHO. Only
@ -662,7 +548,7 @@ static void Command_CSay_f(void)
return;
}
DoSayCommand(0, 1, HU_CSAY);
DoSayPacketFromCommand(0, 1, HU_CSAY);
}
static void Command_Shout(void)
@ -679,13 +565,11 @@ static void Command_Shout(void)
return;
}
DoSayCommand(0, 1, HU_SHOUT);
DoSayPacketFromCommand(0, 1, HU_SHOUT);
}
static tic_t stop_spamming[MAXPLAYERS];
/** Receives a message, processing an ::XD_SAY command.
* \sa DoSayCommand
* \sa DoSayPacket
* \author Graue <graue@oceanbase.org>
*/
static void Got_Saycmd(UINT8 **p, INT32 playernum)
@ -696,25 +580,19 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
char *msg;
boolean action = false;
char *ptr;
INT32 spam_eatmsg = 0;
CONS_Debug(DBG_NETPLAY,"Received SAY cmd from Player %d (%s)\n", playernum+1, player_names[playernum]);
// Only server can ever legitimately send this
if (playernum != serverplayer)
return;
target = READSINT8(*p);
flags = READUINT8(*p);
playernum = READUINT8(*p);
msg = (char *)*p;
SKIPSTRINGL(*p, HU_MAXMSGLEN + 1);
if ((cv_mute.value || flags & (HU_CSAY|HU_SHOUT)) && playernum != serverplayer && !(IsPlayerAdmin(playernum)))
{
CONS_Alert(CONS_WARNING, cv_mute.value ?
M_GetText("Illegal say command received from %s while muted\n") : M_GetText("Illegal csay command received from non-admin %s\n"),
player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
return;
}
//check for invalid characters (0x80 or above)
{
size_t i;
@ -730,27 +608,10 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
}
}
}
// before we do anything, let's verify the guy isn't spamming, get this easier on us.
//if (stop_spamming[playernum] != 0 && cv_chatspamprotection.value && !(flags & HU_CSAY))
if (stop_spamming[playernum] != 0 && consoleplayer != playernum && cv_chatspamprotection.value && !(flags & (HU_CSAY|HU_SHOUT)))
{
CONS_Debug(DBG_NETPLAY,"Received SAY cmd too quickly from Player %d (%s), assuming as spam and blocking message.\n", playernum+1, player_names[playernum]);
stop_spamming[playernum] = 4;
spam_eatmsg = 1;
}
else
stop_spamming[playernum] = 4; // you can hold off for 4 tics, can you?
// run the lua hook even if we were supposed to eat the msg, netgame consistency goes first.
if (LUA_HookPlayerMsg(playernum, target, flags, msg, spam_eatmsg))
if (LUA_HookPlayerMsg(playernum, target, flags, msg))
return;
if (spam_eatmsg)
return; // don't proceed if we were supposed to eat the message.
// If it's a CSAY, just CECHO and be done with it.
if (flags & HU_CSAY)
{
@ -890,6 +751,13 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
cstart = "\x82";
textcolor = "\x82";
fmt2 = "%s<%s%s> %s%s";
if (flags & HU_PRIVNOTICE)
{
dispname = "SERVER";
prefix = "\x82";
fmt2 = "%s[%s%s]%s %s%s";
}
}
else if (target > 0) // By you, to another player
{
@ -899,6 +767,12 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
cstart = "\x82";
fmt2 = "%s<%s%s> %s%s";
if (flags & HU_PRIVNOTICE)
{
if (tempchar)
Z_Free(tempchar);
return; // I pretend I do not see it
}
}
else // To everyone or sayteam, it doesn't change anything.
fmt2 = "%s<%s%s> %s%s";
@ -1011,13 +885,6 @@ void HU_Ticker(void)
{
size_t i = 0;
// handle spam while we're at it:
for(; (i<MAXPLAYERS); i++)
{
if (stop_spamming[i] > 0)
stop_spamming[i]--;
}
// handle chat timers
for (i=0; (i<chat_nummsg_min); i++)
{
@ -1081,29 +948,12 @@ static void HU_sendChatMessage(void)
M_TextInputClear(&w_chat);
// last minute mute check
if (CHAT_MUTE)
{
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
return;
}
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
{
INT32 spc = 1; // used if playernum[1] is a space.
char playernum[3];
const char *newmsg;
// what we're gonna do now is check if the player exists
// with that logic, characters 4 and 5 are our numbers:
// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
if (teamtalk)
{
HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85"), false);
return;
}
strncpy(playernum, msg+3, 3);
// check for undesirable characters in our "number"
if (!(isdigit(playernum[0]) && isdigit(playernum[1])))
@ -1148,7 +998,7 @@ static void HU_sendChatMessage(void)
buf[0] = target;
buf[1] = ((server || IsPlayerAdmin(consoleplayer)) && cv_autoshout.value) ? HU_SHOUT : 0; // flags
SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1);
DoSayPacket(target, buf[1], consoleplayer, msg);
}
}
@ -2206,7 +2056,7 @@ void HU_Drawer(void)
V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_YELLOWMAP | V_ALLOWLOWERCASE, resynch_text);
}
if (modeattacking && pausedelay > 0 && !pausebreakkey)
if (modeattacking && pausedelay > 0)
{
INT32 strength = ((pausedelay - 1 - NEWTICRATE/2)*10)/(NEWTICRATE/3);
INT32 x = BASEVIDWIDTH/2, y = BASEVIDHEIGHT/2; // obviously incorrect values while we scrap hudinfo
@ -2656,7 +2506,7 @@ static void HU_DrawRankings(void)
#endif
}
if (cv_newtabranking.value)
if (!grandprixinfo.gp && cv_newtabranking.value)
{
INT32 xoffset = K_DrawNeoTabRankings(0, 33, tab, scorelines, whiteplayer, hilicol, true);
K_DrawServerDescrption(xoffset+10, 33);

View file

@ -68,9 +68,6 @@ enum
};
#undef X
extern char *shiftxform; // english translation shift table
extern char english_shiftxform[];
//------------------------------------
// sorted player lines
//------------------------------------
@ -85,7 +82,6 @@ struct playersort_t
//------------------------------------
// chat stuff
//------------------------------------
#define HU_MAXMSGLEN 223
#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand.
#define NETSPLITSCREEN // why the hell WOULDN'T we want this?
#ifdef NETSPLITSCREEN
@ -96,6 +92,13 @@ struct playersort_t
#define CHAT_MUTE (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot.
#define OLD_MUTE (OLDCHAT && cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted.
typedef enum
{
HU_SHOUT = 1, // Shout message
HU_CSAY = 1<<1, // Middle-of-screen server message
HU_PRIVNOTICE = 1<<2, // Special server sayto, we don't want to see it as the sender.
} sayflags_t;
// some functions
void HU_AddChatText(const char *text, boolean playsound);
@ -108,6 +111,7 @@ extern boolean hu_keystrokes;
extern patch_t *pinggfx[5];
extern patch_t *framecounter;
extern patch_t *frameslash;
extern patch_t *srb2back;
// set true whenever the tab rankings are being shown for any reason
extern boolean hu_showscores;
@ -144,6 +148,8 @@ void HU_SetCEchoDuration(INT32 seconds);
void HU_SetCEchoFlags(INT32 flags);
void HU_DoCEcho(const char *msg);
void DoSayCommand(char *message, SINT8 target, UINT8 flags, UINT8 source);
// Demo playback info
extern UINT32 hu_demotime;
extern UINT32 hu_demolap;

View file

@ -22,7 +22,7 @@
/// \def MAXPACKETLENGTH
/// For use in a LAN
#define MAXPACKETLENGTH 2048
#define MAXPACKETLENGTH 2063
/// \def INETPACKETLENGTH
/// For use on the internet
#define INETPACKETLENGTH 1450
@ -157,6 +157,7 @@ extern void (*I_NetRegisterHolePunch)(void);
extern boolean (*I_Ban) (INT32 node);
extern void (*I_ClearBans)(void);
extern const char *(*I_GetNodeAddress) (INT32 node);
extern UINT32 (*I_GetNodeAddressInt) (INT32 node);
extern const char *(*I_GetBanAddress) (size_t ban);
extern const char *(*I_GetBanMask) (size_t ban);
extern const char *(*I_GetBanUsername) (size_t ban);
@ -166,6 +167,7 @@ extern boolean (*I_SetBanAddress) (const char *address,const char *mask);
extern boolean (*I_SetBanUsername) (const char *username);
extern boolean (*I_SetBanReason) (const char *reason);
extern boolean (*I_SetUnbanTime) (time_t timestamp);
extern boolean (*I_IsExternalAddress) (const void *p);
struct bannednode_t
{

View file

@ -452,11 +452,33 @@ static const char *SOCK_GetNodeAddress(INT32 node)
{
if (node == 0)
return "self";
if (node < 0 || node > MAXNETNODES)
return NULL;
if (!nodeconnected[node])
return NULL;
return SOCK_AddrToStr(&clientaddress[node]);
}
static UINT32 SOCK_GetNodeAddressInt(INT32 node)
{
if (node < 0 || node > MAXNETNODES)
return 0;
if (nodeconnected[node] && clientaddress[node].any.sa_family == AF_INET)
{
return clientaddress[node].ip4.sin_addr.s_addr;
}
else
{
I_Error("SOCK_GetNodeAddressInt: Node %d is not IPv4!\n", node);
}
return 0;
}
static const char *SOCK_GetBanAddress(size_t ban)
{
if (ban >= numbans)
@ -549,7 +571,7 @@ static void cleanupnodes(void)
// Why can't I start at zero?
for (j = 1; j < MAXNETNODES; j++)
if (!(nodeingame[j] || SendingFile(j)))
if (!(nodeingame[j] || nodeneedsauth[j] || SendingFile(j)))
nodeconnected[j] = false;
}
@ -579,7 +601,6 @@ static SINT8 getfreenode(void)
return -1;
}
#ifdef _DEBUG
void Command_Numnodes(void)
{
INT32 connected = 0;
@ -617,7 +638,6 @@ void Command_Numnodes(void)
"Ingame: %d\n",
connected, ingame);
}
#endif
static boolean hole_punch(ssize_t c)
{
@ -1691,6 +1711,30 @@ static void SOCK_ClearBans(void)
banned = NULL;
}
// https://github.com/jameds/holepunch/blob/master/holepunch.c#L75
static int SOCK_IsExternalAddress (const void *p)
{
const int a = ((const unsigned char*)p)[0];
const int b = ((const unsigned char*)p)[1];
if (*(const UINT32*)p == (UINT32)~0)/* 255.255.255.255 */
return 0;
switch (a)
{
case 0:
case 10:
case 127:
return 0;
case 172:
return (b & ~15) != 16;/* 16 - 31 */
case 192:
return b != 168;
default:
return 1;
}
}
boolean I_InitTcpNetwork(void)
{
char serverhostname[255];
@ -1782,6 +1826,7 @@ boolean I_InitTcpNetwork(void)
I_Ban = SOCK_Ban;
I_ClearBans = SOCK_ClearBans;
I_GetNodeAddress = SOCK_GetNodeAddress;
I_GetNodeAddressInt = SOCK_GetNodeAddressInt;
I_GetBanAddress = SOCK_GetBanAddress;
I_GetBanMask = SOCK_GetBanMask;
I_GetBanUsername = SOCK_GetBanUsername;
@ -1791,6 +1836,7 @@ boolean I_InitTcpNetwork(void)
I_SetBanUsername = SOCK_SetBanUsername;
I_SetBanReason = SOCK_SetBanReason;
I_SetUnbanTime = SOCK_SetUnbanTime;
I_IsExternalAddress = SOCK_IsExternalAddress;
bannednode = SOCK_bannednode;
return ret;

View file

@ -196,6 +196,7 @@ _(A_SpawnParticleRelative, SPAWNPARTICLERELATIVE)
_(A_ParticleSpawn, PARTICLESPAWN)
_(A_MultiShotDist, MULTISHOTDIST)
_(A_CheckFlags2, CHECKFLAGS2)
_(A_CheckScriptArg, CHECKSCRIPTARG)
_(A_DoNPCSkid, DONPCSKID)
_(A_DoNPCPain, DONPCPAIN)
_(A_PrepareRepeat, PREPAREREPEAT)

View file

@ -617,6 +617,7 @@ _(SPBEXPLOSION)
_(THUNDERSHIELD) // Shields
_(BUBBLESHIELD)
_(FLAMESHIELD)
_(ATTRACTIONSHIELD)
_(BUBBLESHIELDTRAP)
_(BUBBLESHIELD_DEBRIS)

View file

@ -1300,8 +1300,11 @@ static INT32 K_HandleBotTrack(botdata_t *bd, const player_t *player, angle_t des
if (anglediff > ANGLE_67h)
{
// Wrong way!
bd->acceldown = false;
bd->brakedown = true;
if (onground)
{
bd->acceldown = false;
bd->brakedown = true;
}
}
else
{

View file

@ -361,9 +361,9 @@ INT32 K_PositionBully(const player_t *player);
/*--------------------------------------------------
boolean K_GetBlockedBubbleItem(const player_t *player, , fixed_t radius)
boolean K_GetBlockedShieldItem(const player_t *player, , fixed_t radius)
Searches the blockmap for items to block with the Bubble Shield
Searches the blockmap for items to block with Shields
Input Arguments:-
player - Bot to run this for.
@ -373,7 +373,7 @@ INT32 K_PositionBully(const player_t *player);
false if couldn't find anything, otherwise true to attempt blocking item.
--------------------------------------------------*/
boolean K_GetBlockedBubbleItem(const player_t *player, fixed_t radius);
boolean K_GetBlockedShieldItem(const player_t *player, fixed_t radius);
/*--------------------------------------------------
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd);

View file

@ -442,11 +442,14 @@ static void K_BotItemSneaker(botdata_t *bd, const player_t *player)
if ((player->offroad && K_ApplyOffroad(player)) // Stuck in offroad, use it NOW
|| K_GetWaypointIsShortcut(player->nextwaypoint) == true // Going toward a shortcut!
|| player->speed < K_GetKartSpeed(player, false, true) / 2 // Being slowed down too much
|| (sneakerstack && player->sneakertimer < stacktime && player->sneakertimer > 0 && (bd->acceldown && !bd->brakedown)) // Stack them sneakers!
|| (stack && player->speedboost > (FRACUNIT/8)) // Have another type of boost (drafting)
|| (sneakerstack && player->sneakertimer > 0 && player->sneakertimer < stacktime && (bd->acceldown && !bd->brakedown)) // Stack them sneakers!
|| (stack && player->speedboost > (FRACUNIT/8) && !player->sneakertimer) // Have another type of boost (drafting)
|| bd->itemconfirm > 4*TICRATE) // Held onto it for too long
{
if (((sneakerstack && player->sneakertimer < stacktime) || player->sneakertimer == 0 || stack) && !bd->itemwasdown)
if (((sneakerstack && player->sneakertimer > 0 && player->sneakertimer < stacktime)
|| player->sneakertimer == 0
|| (stack && player->speedboost > (FRACUNIT/8) && !player->sneakertimer))
&& !bd->itemwasdown)
{
bd->itemdown = true;
//bd->itemconfirm = 2*TICRATE;
@ -881,7 +884,7 @@ static void K_BotItemJawz(botdata_t *bd, const player_t *player)
tryLookback = true;
}
if (lastTarg != -1
if (lastTarg >= 0 && lastTarg < MAXPLAYERS
&& playeringame[lastTarg] == true
&& players[lastTarg].spectator == false
&& players[lastTarg].mo != NULL
@ -933,7 +936,7 @@ static void K_BotItemLightning(botdata_t *bd, const player_t *player)
if (K_BotUseItemNearPlayer(bd, player, radius) == false)
{
if (bd->itemconfirm > 10*TICRATE)
if (K_GetBlockedShieldItem(player, radius) || bd->itemconfirm > 10*TICRATE)
{
K_BotGenericPressItem(bd, 0);
}
@ -968,7 +971,7 @@ static void K_BotItemBubble(botdata_t *bd, const player_t *player)
{
fixed_t radius = 192 * player->mo->scale;
radius = Easing_Linear(FRACUNIT * player->botvars.difficulty / MAXBOTDIFFICULTY, 2*radius, radius);
hold = K_GetBlockedBubbleItem(player, radius);
hold = K_GetBlockedShieldItem(player, radius);
}
else if (player->bubblecool < bubbletime)
{

View file

@ -983,13 +983,13 @@ INT32 K_PositionBully(const player_t *player)
return KART_FULLTURN;
}
static mobj_t *bubbleSource;
static fixed_t bubbleDist;
static boolean bubbleBlock;
static mobj_t *shieldSource = NULL;
static fixed_t shieldDist = 0;
static boolean shieldBlock = 0;
static inline BlockItReturn_t PIT_BubbleShieldBlock(mobj_t *thing)
static inline BlockItReturn_t PIT_ShieldBlock(mobj_t *thing)
{
if (bubbleSource == NULL || P_MobjWasRemoved(bubbleSource))
if (shieldSource == NULL || P_MobjWasRemoved(shieldSource))
{
// Invalid?
return BMIT_ABORT;
@ -1001,7 +1001,7 @@ static inline BlockItReturn_t PIT_BubbleShieldBlock(mobj_t *thing)
return BMIT_ABORT;
}
if (thing == bubbleSource)
if (thing == shieldSource)
{
// Don't block yourself!!
return BMIT_CONTINUE;
@ -1026,9 +1026,9 @@ static inline BlockItReturn_t PIT_BubbleShieldBlock(mobj_t *thing)
}
if (P_AproxDistance(P_AproxDistance(
bubbleSource->x - thing->x,
bubbleSource->y - thing->y),
(bubbleSource->z - thing->z) / 4) > bubbleDist)
shieldSource->x - thing->x,
shieldSource->y - thing->y),
(shieldSource->z - thing->z) / 4) > shieldDist)
{
// Too far away
return BMIT_CONTINUE;
@ -1042,30 +1042,30 @@ static inline BlockItReturn_t PIT_BubbleShieldBlock(mobj_t *thing)
}
#endif
bubbleBlock = true;
shieldBlock = true;
return BMIT_CONTINUE;
}
// Searches the blockmap for items to block with the Bubble Shield
boolean K_GetBlockedBubbleItem(const player_t *player, fixed_t radius)
// Searches the blockmap for items to block with Shields
boolean K_GetBlockedShieldItem(const player_t *player, fixed_t radius)
{
INT32 bx, by, xl, xh, yl, yh;
bubbleSource = player->mo;
bubbleDist = radius;
bubbleBlock = false;
shieldSource = player->mo;
shieldDist = radius;
shieldBlock = false;
// Use blockmap to check for nearby harmful items.
yh = (unsigned)(bubbleSource->y + bubbleDist - bmaporgy)>>MAPBLOCKSHIFT;
yl = (unsigned)(bubbleSource->y - bubbleDist - bmaporgy)>>MAPBLOCKSHIFT;
xh = (unsigned)(bubbleSource->x + bubbleDist - bmaporgx)>>MAPBLOCKSHIFT;
xl = (unsigned)(bubbleSource->x - bubbleDist - bmaporgx)>>MAPBLOCKSHIFT;
yh = (unsigned)(shieldSource->y + shieldDist - bmaporgy)>>MAPBLOCKSHIFT;
yl = (unsigned)(shieldSource->y - shieldDist - bmaporgy)>>MAPBLOCKSHIFT;
xh = (unsigned)(shieldSource->x + shieldDist - bmaporgx)>>MAPBLOCKSHIFT;
xl = (unsigned)(shieldSource->x - shieldDist - bmaporgx)>>MAPBLOCKSHIFT;
BMBOUNDFIX (xl, xh, yl, yh);
for (by = yl; by <= yh; by++)
for (bx = xl; bx <= xh; bx++)
P_BlockThingsIterator(bx, by, PIT_BubbleShieldBlock);
P_BlockThingsIterator(bx, by, PIT_ShieldBlock);
return bubbleBlock;
return shieldBlock;
}

View file

@ -596,6 +596,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
static mobj_t *lightningSource;
static fixed_t lightningDist;
static boolean attractionhipower;
static inline BlockItReturn_t PIT_ThunderShieldAttack(mobj_t *thing)
{
@ -696,11 +697,13 @@ static inline BlockItReturn_t PIT_AttractionShieldAttack(mobj_t *thing)
return BMIT_ABORT;
}
if (thing->player)
#if 0
if (thing->player && (ATTRACTIONAOEDAMAGE == 0 || (!attractionhipower)))
{
// Don't damage players
return BMIT_CONTINUE;
}
#endif
if (thing == lightningSource)
{
@ -729,11 +732,13 @@ static inline BlockItReturn_t PIT_AttractionShieldAttack(mobj_t *thing)
return BMIT_CONTINUE;
}
#if 0
if (P_CheckSight(lightningSource, thing) == false)
{
// Not in sight
return BMIT_CONTINUE;
}
#endif
if (thing->type == MT_SPB) // If you destroy a SPB, you don't get the luxury of a cooldown.
{
@ -741,16 +746,32 @@ static inline BlockItReturn_t PIT_AttractionShieldAttack(mobj_t *thing)
K_SetIndirectItemCooldown(0);
}
P_DamageMobj(thing, lightningSource, lightningSource, 1, DMG_VOLTAGE|DMG_CANTHURTSELF);
if (thing->player)
{
if (ATTRACTIONAOEDAMAGE && attractionhipower)
{
P_DamageMobj(thing, lightningSource, lightningSource, 1, ATTRACTIONAOEDAMAGE|DMG_CANTHURTSELF);
}
if (ATTRACTIONAOEEMP && attractionhipower && thing != lightningSource)
{
//todo: filter out teammates
K_SetPlayerItemCooldown(thing->player, TICRATE * ATTRACTIONAOEEMP, false);
}
}
else
{
P_DamageMobj(thing, lightningSource, lightningSource, 1, DMG_VOLTAGE|DMG_CANTHURTSELF);
}
return BMIT_CONTINUE;
}
void K_AttractionShieldAttack(mobj_t *actor, fixed_t size)
void K_AttractionShieldAttack(mobj_t *actor, fixed_t size, boolean hipower)
{
INT32 bx, by, xl, xh, yl, yh;
lightningDist = FixedMul(size, actor->scale);
lightningSource = actor;
attractionhipower = hipower;
// Use blockmap to check for nearby shootables
yh = (unsigned)(actor->y + lightningDist - bmaporgy)>>MAPBLOCKSHIFT;
@ -818,8 +839,7 @@ static boolean K_BubbleReflectingTrapItem(const mobj_t *t)
static boolean K_StrongPlayerBump(const player_t *player)
{
return ((player->invincibilitytimer)
|| (player->growshrinktimer > 0)
|| (player->attractionattack));
|| (player->growshrinktimer > 0));
}
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2)
@ -867,7 +887,11 @@ boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2)
else if (t2->player->attractionattack)
{
// trolled
t2->player->attractioncharge = 0;
t2->player->attractionattack = 0;
t2->player->attractionattack_hipower = 0;
t2->player->attractionboost = 0;
K_DisableSeekingReticule(t2->player);
}
S_StartSound(t1, sfx_s3k44);
@ -1096,7 +1120,28 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
t1Condition = (t1->scale > t2->scale + (mapobjectscale/8));
t2Condition = (t2->scale > t1->scale + (mapobjectscale/8));
// Merritt suggestion: ONLY make Alt. Shrink squish/flipover interactions happen if and only
// if the crushing player doesn't have an S-Monitor active
if (t1Condition && (t1->player && t1->player->smonitortimer) && (t2->player && K_IsAltShrunk(t2->player)))
{
// t1Condition: t1's player has an S-Monitor, don't do squat
// Extend some mercy to the players phasing through one another
t1->player->justbumped = 6;
t2->player->justbumped = 6;
return false;
}
if (t2Condition && (t2->player && t2->player->smonitortimer) && (t1->player && K_IsAltShrunk(t1->player)))
{
// t2Condition: t2's player has an S-Monitor, don't do squat
// Extend some mercy to the players phasing through one another
t1->player->justbumped = 6;
t2->player->justbumped = 6;
return false;
}
if ((t1Condition == true || flameT1 == true) && (t2Condition == true || flameT2 == true))
{
return false;
@ -1207,8 +1252,9 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
}
// Attraction Shield tackle damage
t1Condition = (t1->player->attractionattack && t1->player->attractionattack_hipower);
t2Condition = (t2->player->attractionattack && t2->player->attractionattack_hipower);
// players with Bubble Shield equipped are protected
t1Condition = (t1->player->attractionattack && t1->player->attractionattack_hipower && (K_GetShieldFromPlayer(t2->player) != KSHIELD_BUBBLE));
t2Condition = (t2->player->attractionattack && t2->player->attractionattack_hipower && (K_GetShieldFromPlayer(t1->player) != KSHIELD_BUBBLE));
if (t1Condition == true && t2Condition == false)
{
P_DamageMobj(t2, t1, t1, 1, DMG_FLIPOVER);

View file

@ -20,7 +20,7 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2);
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);
void K_AttractionShieldAttack(mobj_t *actor, fixed_t size);
void K_AttractionShieldAttack(mobj_t *actor, fixed_t size, boolean hipower);
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2);
boolean K_BubbleShieldCanReflect(mobj_t *t);

View file

@ -19,6 +19,7 @@
#include "k_bot.h"
#include "k_kart.h"
#include "m_random.h"
#include "p_local.h"
#include "r_things.h"
#include "lua_hook.h"
#include "k_battle.h"
@ -294,10 +295,10 @@ static INT16 K_RivalScore(player_t *bot)
UINT8 lowestdifficulty = MAXBOTDIFFICULTY;
UINT8 i;
if (grandprixinfo.cup != NULL)
if (grandprixinfo.cup != NULL && roundqueue.size > 0)
{
roundnum = grandprixinfo.roundnum;
roundsleft = grandprixinfo.cup->numlevels - grandprixinfo.roundnum;
roundnum = roundqueue.roundnum;
roundsleft = grandprixinfo.cup->numlevels - roundnum;
}
for (i = 0; i < MAXGPPLAYERS; i++)
@ -343,10 +344,15 @@ void K_UpdateGrandPrixBots(void)
{
continue;
}
players[i].spectator = K_BotDefaultSpectator();
}
if (grandprixinfo.wonround == false)
{
return;
}
// Find the rival.
for (i = 0; i < MAXGPPLAYERS; i++)
{
@ -539,8 +545,10 @@ void K_RetireBots(void)
UINT16 i;
if (grandprixinfo.gp == true
&& (((grandprixinfo.cup != NULL) && (grandprixinfo.roundnum >= grandprixinfo.cup->numlevels))
|| grandprixinfo.eventmode != GPEVENT_NONE))
&& (grandprixinfo.eventmode != GPEVENT_NONE
|| (grandprixinfo.cup != NULL
&& roundqueue.size > 0
&& roundqueue.roundnum >= grandprixinfo.cup->numlevels)))
{
// No replacement.
return;
@ -580,6 +588,10 @@ void K_RetireBots(void)
{
const UINT8 startingdifficulty = K_BotStartingDifficulty(grandprixinfo.gamespeed);
newDifficulty = startingdifficulty - 4;
if (roundqueue.size > 0)
{
newDifficulty += roundqueue.roundnum;
}
}
}
else
@ -738,7 +750,7 @@ void K_PlayerLoseLife(player_t *player)
--------------------------------------------------*/
boolean K_CanChangeRules(boolean allowdemos)
{
if (grandprixinfo.gp == true && grandprixinfo.roundnum > 0)
if (grandprixinfo.gp == true)
{
// Don't cheat the rules of the GP!
return false;

View file

@ -20,14 +20,16 @@
extern "C" {
#endif
#define GPEVENT_NONE 0
#define GPEVENT_CHALLENGE 1
#define GPEVENT_SPECIAL 2
typedef enum
{
GPEVENT_NONE = 0,
GPEVENT_BONUS,
GPEVENT_SPECIAL,
} gpEvent_e;
extern struct grandprixinfo
{
boolean gp; ///< If true, then we are in a Grand Prix.
UINT8 roundnum; ///< Round number. If 0, this is a single session from the warp command.
cupheader_t *cup; ///< Which cup are we playing?
UINT8 gamespeed; ///< Copy of gamespeed, just to make sure you can't cheat it with cvars
boolean encore; ///< Ditto, but for encore mode

View file

@ -32,6 +32,7 @@
#include "doomstat.h"
#include "d_clisrv.h"
#include "g_game.h"
#include "g_input.h"
#include "p_local.h"
#include "z_zone.h"
#include "m_cond.h"
@ -2682,7 +2683,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 19
#define BASEMODS 21
static void K_DrawServerMods(INT32 x, INT32 y)
{
UINT8 i, j;
@ -2709,7 +2710,9 @@ static void K_DrawServerMods(INT32 x, INT32 y)
{"Bump Spark", 0, &cv_kartbumpspark, -1, true},
{"Bump Drift", 0, NULL, K_GetBumpSpark() > 0, true},
{"Bump Spark", 0, NULL, K_GetBumpSpark() > BUMPSPARK_NOCHARGE, true},
{"Bump Spring", 0, &cv_kartbumpspring, -1, true}
{"Bump Spring", 0, &cv_kartbumpspring, -1, true},
{"Keep Stuff", 0, NULL, K_KeepStuffActive() > 0, true},
{"No BananaDrag", 0, NULL, K_TrailSlowActive() < 1, true},
//TODO: separate drawer that enumerates item changes?
};
@ -5042,6 +5045,12 @@ static void K_drawKartMinimap(void)
if (cv_kartdebugwaypoints.value != 0)
{
if (!(gametypes[gametype]->rules & GTR_CIRCUIT))
return;
if (waypointcap == NULL)
return;
size_t idx;
for (idx = 0; idx < K_GetNumWaypoints(); ++idx)
@ -5558,7 +5567,6 @@ static void K_drawInput(void)
patch_t *shadowPic = kp_inputwheel_shadow;
INT16 turning = encoremode ? -stplyr->cmd.turning : stplyr->cmd.turning;
SINT8 tilt = encoremode ? -stplyr->cmd.tilt : stplyr->cmd.tilt;
angle_t rotate = FixedAngle(60 * FixedDiv(abs(turning), 1024) * intsign(turning));
UINT8 *colormap;
@ -5577,9 +5585,13 @@ static void K_drawInput(void)
// a la GT7
if (stplyr->cmd.flags & TICCMD_USINGTILT)
{
rotate = FixedAngle(60 * ((tilt < 0) ? FixedDiv(-tilt, -(50*INT8_MIN/100)) : FixedDiv(tilt, (50*INT8_MAX/100))));
x += 17*FINESINE(rotate>>ANGLETOFINESHIFT) * intsign(tilt);
y -= 17*FINECOSINE(rotate>>ANGLETOFINESHIFT);
fixed_t tilt = G_GetGamepadGravity(stplyrnum).x;
if (demo.playback || !P_IsMachineLocalPlayer(stplyr))
tilt = -1;
else
rotate = FixedAngle(120 * abs(tilt));
x += 17*FSIN(rotate) * intsign(tilt);
y -= 17*FCOS(rotate);
splitflags |= (((leveltime % 3 == 0) && (stplyr->cmd.flags & TICCMD_EXCESSTILT)) ? V_ADD|V_20TRANS : 0);
if (!K_GetHudColor())
@ -6107,6 +6119,24 @@ static void K_DrawWaypointDebugger(void)
if (stplyr->bigwaypointgap)
V_DrawString(8, 140, 0, va("Auto Respawn Timer: %d", stplyr->bigwaypointgap));
if (stplyr->currentwaypoint && (stplyr->currentwaypoint->mobj != NULL) && K_SafeRespawnPosition(stplyr->currentwaypoint->mobj))
{
V_DrawString(8, 120, 0, va("Waypoint %d (Current) Safe: True", K_GetWaypointID(stplyr->currentwaypoint)));
}
else
{
V_DrawString(8, 120, 0, va("Waypoint %d (Current) Safe: False", K_GetWaypointID(stplyr->currentwaypoint)));
}
if (stplyr->nextwaypoint && (stplyr->nextwaypoint->mobj != NULL) && K_SafeRespawnPosition(stplyr->nextwaypoint->mobj))
{
V_DrawString(8, 130, 0, va("Waypoint %d (Next) Safe: True", K_GetWaypointID(stplyr->nextwaypoint)));
}
else
{
V_DrawString(8, 130, 0, va("Waypoint %d (Next) Safe: False", K_GetWaypointID(stplyr->nextwaypoint)));
}
V_DrawString(8, 150, 0, va("Current Waypoint ID: %d", K_GetWaypointID(stplyr->currentwaypoint)));
V_DrawString(8, 160, 0, va("Next Waypoint ID: %d", K_GetWaypointID(stplyr->nextwaypoint)));
V_DrawString(8, 170, 0, va("Finishline Distance: %u (WP %u)", stplyr->distancetofinish,
@ -6148,6 +6178,8 @@ void K_getSlipstreamDrawinfo(drawinfo_t *out)
if (r_splitscreen > 0)
splitflags |= V_30TRANS;
else
splitflags |= V_SNAPTOBOTTOM;
}
else // now we're having a fun game.
{
@ -6405,7 +6437,7 @@ void K_drawKartHUD(void)
else
{
INT32 karlen = strlen(countstr)*6; // half of 12
V_DrawKartString((BASEVIDWIDTH/2)-karlen, LAPS_Y+3, V_SPLITSCREEN, countstr);
V_DrawKartString((BASEVIDWIDTH/2)-karlen, LAPS_Y+3, V_SNAPTOBOTTOM, countstr);
}
}

View file

@ -1627,7 +1627,7 @@ INT32 KO_SPBRaceOdds(INT32 odds, const kartroulette_t *roulette, const kartresul
#define NEIGHBOR_IFRAMES (TICRATE / 2)
#define BASE_IFRAMES (2 * TICRATE)
static void K_DoGrowShrink(player_t *player, boolean shrinking)
void K_DoGrowShrink(player_t *player, boolean shrinking)
{
player->mo->scalespeed = mapobjectscale/TICRATE;
player->mo->destscale = FixedMul(mapobjectscale, (shrinking) ? SHRINK_SCALE : GROW_SCALE);
@ -1772,7 +1772,16 @@ static void K_DoHyudoroSteal(player_t *player)
&& (players[i].itemtype
&& players[i].itemamount
&& !(players[i].itemflags & IF_ITEMOUT)
&& !players[i].itemblink))
&& !players[i].itemblink
//todo: make this more modular for hold-button items (these should never be stolen when being used)
&& !(
players[i].flametimer +
players[i].bubblecool +
players[i].bubbleblowup +
players[i].bubblebuffer +
players[i].attractioncharge
)
))
{
kartitemflags_e flags = K_GetItemFlags(players[i].itemtype);
@ -1843,6 +1852,7 @@ static void K_DoHyudoroSteal(player_t *player)
players[stealplayer].itemtype = KITEM_NONE;
players[stealplayer].itemamount = 0;
K_DisableSeekingReticule(&players[stealplayer]);
K_UnsetItemOut(&players[stealplayer]);
if (P_IsDisplayPlayer(&players[stealplayer]) && !r_splitscreen)
@ -1912,8 +1922,13 @@ void K_DoAttractionShield(player_t *player, boolean hipower)
fixed_t sy;
angle_t an;
if (S_SoundPlaying(player->mo, sfx_vwre))
{
S_StopSoundByID(player->mo, sfx_vwre);
}
S_StartSound(player->mo, sfx_zio3);
K_AttractionShieldAttack(player->mo, (cv_kartthunder_radius.value + THUNDERSPRITE) * FRACUNIT);
K_AttractionShieldAttack(player->mo, (cv_kartthunder_radius.value + THUNDERSPRITE) * FRACUNIT, hipower);
// spawn vertical bolt
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THOK);
@ -1921,12 +1936,16 @@ void K_DoAttractionShield(player_t *player, boolean hipower)
P_SetMobjState(mo, S_LZIO11);
mo->color = SKINCOLOR_TEAL;
mo->scale = player->mo->scale*3 + (player->mo->scale/2);
mo->color = SKINCOLOR_YELLOW;
mo->colorized = true;
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THOK);
P_SetTarget(&mo->target, player->mo);
P_SetMobjState(mo, S_LZIO21);
mo->color = SKINCOLOR_CYAN;
mo->scale = player->mo->scale*3 + (player->mo->scale/2);
mo->color = SKINCOLOR_YELLOW;
mo->colorized = true;
// spawn the radius thing:
an = ANGLE_22h;
@ -1940,6 +1959,8 @@ void K_DoAttractionShield(player_t *player, boolean hipower)
mo->scale = player->mo->scale*3;
P_SetTarget(&mo->target, player->mo);
P_SetMobjState(mo, S_KSPARK1);
mo->color = SKINCOLOR_YELLOW;
mo->colorized = true;
}
}
@ -2080,16 +2101,7 @@ void K_PlayerItemThink(player_t *player, boolean onground)
for (moloop = 0; moloop < 2; moloop++)
{
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ROCKETSNEAKER);
K_MatchGenericExtraFlags(mo, player->mo);
mo->flags |= MF_NOCLIPTHING;
mo->angle = player->mo->angle;
mo->threshold = 10;
mo->movecount = moloop%2;
mo->movedir = mo->lastlook = moloop+1;
P_SetTarget(&mo->target, player->mo);
P_SetTarget(&mo->hprev, prev);
P_SetTarget(&prev->hnext, mo);
mo = K_SpawnEquippedItem(player, KITEMEQUIP_ROCKETS, MT_ROCKETSNEAKER, moloop, prev);
prev = mo;
}
K_BotResetItemConfirm(player, false);
@ -2120,19 +2132,12 @@ void K_PlayerItemThink(player_t *player, boolean onground)
for (moloop = 0; moloop < player->itemamount; moloop++)
{
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BANANA_SHIELD);
mo = K_SpawnEquippedItem(player, KITEMEQUIP_TRAIL, MT_BANANA_SHIELD, moloop, prev);
if (!mo)
{
player->itemamount = moloop;
break;
}
mo->flags |= MF_NOCLIPTHING;
mo->threshold = 10;
mo->movecount = player->itemamount;
mo->movedir = moloop+1;
P_SetTarget(&mo->target, player->mo);
P_SetTarget(&mo->hprev, prev);
P_SetTarget(&prev->hnext, mo);
prev = mo;
}
K_BotResetItemConfirm(player, false);
@ -2166,21 +2171,12 @@ void K_PlayerItemThink(player_t *player, boolean onground)
for (moloop = 0; moloop < player->itemamount; moloop++)
{
newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->itemamount) * moloop) << FRACBITS) + ANGLE_90;
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMINE_SHIELD);
mo = K_SpawnEquippedItem(player, KITEMEQUIP_ORBIT, MT_EGGMINE_SHIELD, moloop, prev);
if (!mo)
{
player->itemamount = moloop;
break;
}
mo->flags |= MF_NOCLIPTHING;
mo->angle = newangle;
mo->movecount = player->itemamount;
mo->movedir = mo->lastlook = moloop+1;
P_SetTarget(&mo->target, player->mo);
P_SetTarget(&mo->hprev, prev);
P_SetTarget(&prev->hnext, mo);
prev = mo;
}
K_BotResetItemConfirm(player, false);
@ -2225,16 +2221,10 @@ void K_PlayerItemThink(player_t *player, boolean onground)
player->itemamount--;
K_SetItemOut(player, KITEM_EGGMAN, IF_EGGMANOUT);
S_StartSound(player->mo, sfx_s254);
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMANITEM_SHIELD);
mo = K_SpawnEquippedItem(player, KITEMEQUIP_TRAIL, MT_EGGMANITEM_SHIELD, 0, player->mo);
if (mo)
{
K_FlipFromObject(mo, player->mo);
mo->flags |= MF_NOCLIPTHING;
mo->threshold = 10;
mo->movecount = 1;
mo->movedir = 1;
P_SetTarget(&mo->target, player->mo);
P_SetTarget(&player->mo->hnext, mo);
}
K_BotResetItemConfirm(player, false);
}
@ -2254,22 +2244,13 @@ void K_PlayerItemThink(player_t *player, boolean onground)
for (moloop = 0; moloop < player->itemamount; moloop++)
{
newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->itemamount) * moloop) << FRACBITS) + ANGLE_90;
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ORBINAUT_SHIELD);
mo = K_SpawnEquippedItem(player, KITEMEQUIP_ORBIT, MT_ORBINAUT_SHIELD, moloop, prev);
if (!mo)
{
player->itemamount = moloop;
break;
}
mo->flags |= MF_NOCLIPTHING;
mo->angle = newangle;
mo->threshold = 10;
mo->movecount = player->itemamount;
mo->movedir = mo->lastlook = moloop+1;
mo->color = player->skincolor;
P_SetTarget(&mo->target, player->mo);
P_SetTarget(&mo->hprev, prev);
P_SetTarget(&prev->hnext, mo);
prev = mo;
}
K_BotResetItemConfirm(player, false);
@ -2294,24 +2275,16 @@ void K_PlayerItemThink(player_t *player, boolean onground)
//K_PlayAttackTaunt(player->mo);
K_SetItemOut(player, KITEM_JAWZ, IF_ITEMOUT|IF_SEEKING);
S_StartSound(player->mo, sfx_s3k3a);
K_EnableSeekingReticule(player, false);
for (moloop = 0; moloop < player->itemamount; moloop++)
{
newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->itemamount) * moloop) << FRACBITS) + ANGLE_90;
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_JAWZ_SHIELD);
mo = K_SpawnEquippedItem(player, KITEMEQUIP_ORBIT, MT_JAWZ_SHIELD, moloop, prev);
if (!mo)
{
player->itemamount = moloop;
break;
}
mo->flags |= MF_NOCLIPTHING;
mo->angle = newangle;
mo->threshold = 10;
mo->movecount = player->itemamount;
mo->movedir = mo->lastlook = moloop+1;
P_SetTarget(&mo->target, player->mo);
P_SetTarget(&mo->hprev, prev);
P_SetTarget(&prev->hnext, mo);
prev = mo;
}
K_BotResetItemConfirm(player, false);
@ -2329,7 +2302,7 @@ void K_PlayerItemThink(player_t *player, boolean onground)
if (player->itemamount <= 0)
{
player->itemflags &= ~IF_SEEKING;
K_DisableSeekingReticule(player);
}
}
break;
@ -2339,16 +2312,7 @@ void K_PlayerItemThink(player_t *player, boolean onground)
mobj_t *mo;
K_SetItemOut(player, KITEM_MINE, IF_ITEMOUT);
S_StartSound(player->mo, sfx_s254);
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SSMINE_SHIELD);
if (mo)
{
mo->flags |= MF_NOCLIPTHING;
mo->threshold = 10;
mo->movecount = 1;
mo->movedir = 1;
P_SetTarget(&mo->target, player->mo);
P_SetTarget(&player->mo->hnext, mo);
}
mo = K_SpawnEquippedItem(player, KITEMEQUIP_TRAIL, MT_SSMINE_SHIELD, 0, player->mo);
K_BotResetItemConfirm(player, false);
}
else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT))
@ -2436,28 +2400,25 @@ void K_PlayerItemThink(player_t *player, boolean onground)
}
break;
case KITEM_THUNDERSHIELD:
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);
}
if (K_IsKartItemAlternate(KITEM_THUNDERSHIELD))
{
if (K_GetShieldFromPlayer(player) != KSHIELD_ATTRACTION)
{
mobj_t *shield = K_SpawnEquippedItem(player, KITEMEQUIP_SHIELD, MT_ATTRACTIONSHIELD, 0, NULL);
S_StartSound(player->mo, sfx_attrsg);
}
if (!HOLDING_ITEM && NO_HYUDORO)
{
if (buttons & BT_ATTACK)
if (buttons & BT_ATTACK &&
((player->itemflags & IF_HOLDREADY) || player->attractioncharge > 0))
{
fixed_t effectscale = 75*player->mo->scale/100;
if (player->itemflags & IF_HOLDREADY)
if (player->attractioncharge == 0)
{
S_StartSound(player->mo, sfx_vwre);
}
player->itemflags &= ~IF_HOLDREADY;
if (player->attractioncharge >= ATTRACTIONCHARGETIME)
{
@ -2470,16 +2431,29 @@ void K_PlayerItemThink(player_t *player, boolean onground)
{
S_StopSoundByID(player->mo, sfx_vwre);
}
player->itemflags |= (IF_SEEKING|IF_PASSIVESEEKING);
K_EnableSeekingReticule(player, false);
player->bananadrag += 4;
}
else
{
player->itemflags |= IF_SEEKING;
effectscale = Easing_Linear(CLAMP(FixedDiv(player->attractioncharge, ATTRACTIONCHARGETIME), 0, FRACUNIT),
player->mo->scale/4,
player->mo->scale/2
);
K_EnableSeekingReticule(player, false);
}
// stolen from machine water breathing
if (P_RandomChance(FRACUNIT/5))
{
fixed_t r = player->mo->radius>>FRACBITS;
fixed_t x = player->mo->x + (P_RandomRange(r, -r)<<FRACBITS);
fixed_t y = player->mo->y + (P_RandomRange(r, -r)<<FRACBITS);
fixed_t z = player->mo->z + (P_RandomKey(player->mo->height>>FRACBITS)<<FRACBITS);
mobj_t *spark = P_SpawnMobj(x, y, z, MT_WATERZAP);
S_StartSound(spark, sfx_beelec);
spark->color = SKINCOLOR_YELLOW;
spark->colorized = true;
}
if (player->attractioncharge % 8 == 0)
@ -2489,6 +2463,8 @@ void K_PlayerItemThink(player_t *player, boolean onground)
mo->fuse = P_RandomRange(20, 50);
P_SetScale(mo, effectscale);
mo->destscale = mo->scale/2;
mo->color = SKINCOLOR_YELLOW;
mo->colorized = true;
P_SetTarget(&mo->target, player->mo);
P_SetMobjState(mo, S_KLIT1);
@ -2535,15 +2511,29 @@ void K_PlayerItemThink(player_t *player, boolean onground)
K_BotResetItemConfirm(player, false);
}
player->itemflags |= (IF_SEEKING|IF_PASSIVESEEKING);
K_EnableSeekingReticule(player, true);
}
player->itemflags |= IF_HOLDREADY;
player->attractioncharge = 0;
}
if (buttons & BT_ATTACK || player->attractioncharge > 0)
{
player->itemflags &= ~IF_HOLDREADY;
}
else
{
player->itemflags |= IF_HOLDREADY;
}
}
}
else
{
if (K_GetShieldFromPlayer(player) != KSHIELD_THUNDER)
{
mobj_t *shield = K_SpawnEquippedItem(player, KITEMEQUIP_SHIELD, MT_THUNDERSHIELD, 0, NULL);
S_StartSound(player->mo, sfx_s3k41);
}
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
K_DoThunderShield(player);
@ -2564,13 +2554,12 @@ void K_PlayerItemThink(player_t *player, boolean onground)
case KITEM_BUBBLESHIELD:
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);
mobj_t *shield = K_SpawnEquippedItem(player, KITEMEQUIP_SHIELD, MT_BUBBLESHIELD, 0, NULL);
S_StartSound(player->mo, sfx_s3k3f);
if (player->bubblehealth <= 0 || player->bubblehealth > MAXBUBBLEHEALTH)
player->bubblehealth = MAXBUBBLEHEALTH;
// bit of mercy so bubble doesn't get instantly killed on creation
player->bubblebuffer = TICRATE/2;
}
if (!HOLDING_ITEM && NO_HYUDORO)
@ -2651,10 +2640,7 @@ void K_PlayerItemThink(player_t *player, boolean onground)
player->itemamount--;
player->flametimer = flametime;
player->flamedash = 0;
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);
mobj_t *shield = K_SpawnEquippedItem(player, KITEMEQUIP_SHIELD, MT_FLAMESHIELD, 0, NULL);
S_StartSound(player->mo, sfx_s3k3e);
}
break;
@ -2691,16 +2677,7 @@ void K_PlayerItemThink(player_t *player, boolean onground)
mobj_t *mo;
K_SetItemOut(player, KITEM_KITCHENSINK, IF_ITEMOUT);
S_StartSound(player->mo, sfx_s254);
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SINK_SHIELD);
if (mo)
{
mo->flags |= MF_NOCLIPTHING;
mo->threshold = 10;
mo->movecount = 1;
mo->movedir = 1;
P_SetTarget(&mo->target, player->mo);
P_SetTarget(&player->mo->hnext, mo);
}
mo = K_SpawnEquippedItem(player, KITEMEQUIP_TRAIL, MT_SINK_SHIELD, 0, player->mo);
K_BotResetItemConfirm(player, false);
// Woah this could be big, lets get the inside scoop...
@ -2823,6 +2800,20 @@ void K_DoEggMineStrip(mobj_t *tmo, mobj_t *inflictor, mobj_t *source)
}
}
void K_EnableSeekingReticule(player_t *player, boolean passive)
{
player->itemflags |= IF_SEEKING;
if (passive)
{
player->itemflags |= IF_PASSIVESEEKING;
}
}
void K_DisableSeekingReticule(player_t *player)
{
player->itemflags &= ~(IF_SEEKING|IF_PASSIVESEEKING);
}
void K_KartSeekingReticule(player_t *player)
{
// seeking item reticule
@ -2832,8 +2823,9 @@ void K_KartSeekingReticule(player_t *player)
player_t *targ;
mobj_t *ret;
if ((player->itemtargetdelay && playeringame[lasttarg] && !players[lasttarg].spectator)
|| (player->itemflags & IF_PASSIVESEEKING))
if (lasttarg >= 0 && lasttarg < MAXPLAYERS &&
((player->itemtargetdelay && playeringame[lasttarg] && !players[lasttarg].spectator)
|| (player->itemflags & IF_PASSIVESEEKING)))
{
targ = &players[lasttarg];
player->itemtargetdelay--;
@ -2970,4 +2962,56 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source)
}
return wtarg;
}
}
// after using this you must handle setting any additional values on the mobj (like skincolour)
mobj_t *K_SpawnEquippedItem(player_t *player, kartitemequip_e equipstyle, mobjtype_t type, INT32 moloop, mobj_t *prev)
{
mobj_t *mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, type);
angle_t newangle;
if (!mo)
{
return NULL;
}
mo->flags |= MF_NOCLIPTHING;
mo->threshold = 10;
switch (equipstyle)
{
case KITEMEQUIP_ORBIT: // Kart orbit items
K_MatchGenericExtraFlags(mo, player->mo);
newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->itemamount) * moloop) << FRACBITS) + ANGLE_90;
mo->angle = newangle;
mo->movecount = player->itemamount;
mo->movedir = mo->lastlook = moloop+1;
break;
case KITEMEQUIP_TRAIL: // Kart trailing items
mo->movecount = player->itemamount;
mo->movedir = moloop+1;
break;
case KITEMEQUIP_ROCKETS: // Rocket Sneaker et autres side-by-side style items
K_MatchGenericExtraFlags(mo, player->mo);
mo->angle = player->mo->angle;
mo->movecount = moloop%2;
mo->movedir = mo->lastlook = moloop+1;
break;
case KITEMEQUIP_SHIELD: // Force Field Shields
P_SetScale(mo, (mo->destscale = (5*mo->destscale)>>2));
P_SetTarget(&player->shieldtracer, mo);
break;
default:
break;
}
P_SetTarget(&mo->target, player->mo);
if (prev != NULL)
{
if (equipstyle != KITEMEQUIP_SHIELD)
{
P_SetTarget(&mo->hprev, prev);
}
P_SetTarget(&prev->hnext, mo);
}
return mo;
}

View file

@ -195,6 +195,8 @@ patch_t *K_GetCachedItemPatchEx(kartitemtype_e type, boolean tiny, UINT8 amount,
void K_SetItemOut(player_t *player, kartitemtype_e itemtype, itemflags_t flags);
void K_UnsetItemOut(player_t *player);
mobj_t *K_SpawnEquippedItem(player_t *player, kartitemequip_e equipstyle, mobjtype_t type, INT32 moloop, mobj_t *prev);
void K_AwardPlayerItem(player_t *player, kartitemtype_e type, UINT8 amount, kartitemblink_e blink);
void K_UpdateMobjItemOverlay(mobj_t *part, kartitemtype_e itemType, UINT8 itemCount);
void K_UpdateItemCooldown(void);
@ -228,6 +230,8 @@ void K_AltShrinkPityIncrease(player_t *player);
void K_SpawnEggMineBumpEffect(mobj_t *mo);
void K_DoEggMineStrip(mobj_t *tmo, mobj_t *inflictor, mobj_t *source);
void K_EnableSeekingReticule(player_t *player, boolean passive);
void K_DisableSeekingReticule(player_t *player);
void K_KartSeekingReticule(player_t *player);
player_t *K_FindJawzTarget(mobj_t *actor, player_t *source);
@ -239,10 +243,13 @@ extern consvar_t cv_karteggmine_slotbrick;
extern consvar_t cv_kartthunder_radius;
#define BUBBLEBOOSTTIME (7 * sneakertime / 10)
#define ATTRACTIONCHARGETIME ((92*TICRATE)/60)
#define ATTRACTIONATTACKTIME_FULL (TICRATE)
#define ATTRACTIONATTACKTIME_MAX (TICRATE/2)
#define ATTRACTIONATTACKTIME_MIN (TICRATE/3)
#define ATTRACTIONATTACKTIME_MAX (3*TICRATE/4)
#define ATTRACTIONATTACKTIME_MIN (TICRATE/2)
void K_DoGrowShrink(player_t *player, boolean shrinking);
#ifdef __cplusplus
} // extern "C"

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