Mammoth commit, sorry. I only realised halfway through writing it that SECRET_SKIN was only partially merged.
Ports from 2.2:
- Merge SECRET_SKIN (STJr/SRB2!1474)
- Default skin is now handled by checking all skins for unlock status, and I_Erroring if none are available
- Don't show skin names on game startup, to keep our secrets hidden
- Unlockables now have string variables zallocated.
- For skin names rather than numbers.
- Correctly clean up memory when freeing unlockables and emblems.
Bespoke code:
- For temporary testing. `unlocks.pk3`
- Using this for rapid testing gameboot SOC instead of patch.pk3 because of the intent to turn that into scripts.pk3
- Don't not save gamedata in DEVELOP builds, even if you've used cheats!
- `player->availabilities` is now an array of UINT8
- (MAXSKINS + 7)/8 entries, or 32 bytes.
- Included with XD_ADDPLAYER instead of XD_NAMEANDCOLOR.
- Simplifies a lot of logic with respect to demos, skin changes mid-game, etc.
- Seriously, there's a lot of random places in the code that just iterate over MAXSPLITSCREENPLAYERS and g_localplayers to update availabilities in real time in a way that's not particularly netsafe...
- Lines up with the plan for handling unlocks when returning to menus.
- Was included with XD_ADDBOT, but that actually overruns the netxcmd buffer at first mapload with 7 bots. We might need to consider expanding the size of the netxcmd buffer...
- In demos, can be interpreted as both relative to the original replay and the current skin list depending on boolean context provided to R_SkinUsable.
- Used for SF_IRONMAN (and will crash if all other skins are inaccessible).
- Grand Prix bot randomisation uses the host's unlocks.
- Don't show locked characters on the fancy new character select.
- DXD_JOINDATA for demos
- Replaces the dual-purpose behaviour of DXD_PLAYSTATE
- Contains availabilities
- Handles bot material in a different way
- Forceskin restrictions
- Won't run in demos, because it's assumed recorded DXD_SKIN will handle all the conversions the original match had
- Won't run if K_CanChangeRules says no
- Correctly set `mapvisited` on level visit, even in [fake gasp] MULTIPLAYER/NETGAMES!! 🥹
- Added updating unlockables and extra emblems on `mapvisited` update.
- Currently fails to produce the cecho, but that'll be stripped out entirely in a future commit so I'm not bothered.
Tremendous whoopsie: turns out there's no code that actually saves it outside of netsync. This is now fixed.
Also now allows you to roll Eggman as your first skin, and doesn't cause immediate characterswaps for midgame joiners.
Notable new features:
- Guaranteed native compatibility with SF_IRONMAN even with differing # of skins
- Bots (todo: can still desync midway through round)
Implementation details:
- Demo code (skins):
- Instead of writing a skin name string, and the player's kartspeed, kartweight, and charflags for each player in the initial player-interpreting loop...
- Write a skinlist of EVERY skin's name string, kartspeed, kartweight, and flags next to the file list, to be read into `demo.skinlist`.
- If the skin name isn't loaded, find the skin with (in order)
- SF_IRONMAN if your skin had SF_IRONMAN, since that's more important to signal
- the closest stats otherwise (as per previous implementation)
- Just as tolerant to stats AND the number of base skins changing between versions (the bonuschars aegis situation)
- Not tolerant to restat, but we can add a DXD or EZT later if we want to natively support that kind of mod
- In the initial loop and DXD_SKIN, just write an index that can be used for `demo.skinlist`, and store it in `demo.currentskinid[p]`
- The player's skin is now encoded as EZT_IRONMAN for ghosts (and just in case RNG sync fails for unrelated reasons)
- In the SF_IRONMAN code when demo.playback is true
- everywhere where `skins[player->skin]` is referenced instead uses an index into `demo.skinlist`
- SetRandomFakePlayerSkin uses the `demo.skinlist` to build a table to ensure exact random call parity
- Also means it no longer double rejection-samples.
- `player->fakeskin` and `lastfakeskin` are always == their original recording values, a skin id which can be used into `demo.skinlist`
- Demo code (playstate, initial player setup loop):
- Add bot flag (`DXD_PST_ISBOT`, `DEMO_BOT`)
- Add in-between-level botvars (difficulty, diffincrease, rival)
- Don't rely on `PF_WANTSTOJOIN` to activate
Additional bugfixes:
- Followerskin set to -1 in CL_ClearPlayer so a bad follower isn't recorded on player join without name and color change arriving immediately
- Accomodate new joiners in demo code even if they're not on DXD_PST_SPECTATING for one reason or another
- Demo extra file list saving is now its own function for code cleanliness
- Actually only modify players relevant to the demo at the end of G_DoPlayDemo, not all 16 by supplying and overwriting garbage values (POSSIBLE MEMORY CORRUPTION FIX, mobj_t pointer was previously dereferenced)
- If no clients at server start or after 10 seconds of GS_LEVEL, and no Netxcmd waiting to be digested, halt all SV_MakeTic.
- It's absolutely netsafe to only have enabled on the host's end, the only risk is that a dedicated server might not re-awaken when presented with certain stimuli
- Reduce the joiner grace period for normal ping limit to 10 seconds (from 30)
- Properly account for ignoring all local players when the host is splitscreen
# Conflicts:
# src/d_clisrv.c
Flattened due to changes between the code base including renamed functions.
Also renames CL_LEGACYREQUESTFAILED to the more specific CL_DOWNLOADFAILED.
Originally written by x.organic, flattened rewrite due to massive changes between RR and SRB2Kart codebase
Notable changes:
- p_adding_file has been reworked into partadd_earliestfile to allow for final setup to use
- much like the public version required removing TEXTURE SOCs, this one required removing Flats support from ANIMDEFS
- Make timelimitintics handled a bit more like gamespeed, encore, frantic, etc - update on mapload/starttime, not during gameplay
- Use default setting if can't change rules - this is a surprise tool that will help us later
- Have it properly update when adjusting gametype from the menu
- Cleaned up SV_StartSinglePlayerServer to do this
- Remove CV_SAVE to prevent time limit bruh moments
- Use strlcpy instead of strcpy to prevent footguns
- Use fprintf instead of raw fputs
- Enforce consistent MAX_LOGIP (255) length for each component instead of a combination of magic number 255 and MAXSTRINGLENGTH (32!?) depending on where you look
- Fix fun memory leak in waiting
- Avoid pointless strlens