- Removed all old dev title screen remainders that were interfering with titlemaps.
- F_VersionDrawer displays on all title screen types
- SA2 intro sound only plays whenever there's am actual title card to show (before it checked for not GS_CEREMONY?)
- Removed redundant customversionstring check in menus (F_VersionDrawer already handles customversionstring)
Just in case I don't get to do a major pass on adding a ton of extra unlockable conditions later, this is an easy, quick add featuring a stat gamedata and the statistics menu has been tracking for a while.
Instead of being specific to each level, Spray Cans are stored in a list on gamedata that will be stepped along each Spray Can you collect.
They are only assigned to a level on collection - which prevents you from farming the same easy location for every colour in the game.
In addition, this new system is one step short of dehardcoding them entirely. Now only Spray Cans specifically asked for by the existence of UC_SPRAYCAN will be put in the list, and if a secondary parameter is either "Yes" or "True", it will be put at the head of the list. This could technically support custom skincolours one day, but the author of this commit doesn't care to do the last bit of work necessary to make it happen.
There's a slight extra overhead in that skincolor_t now also holds a `cache_spraycan` (renamed from `cachedcan`, which maps had previously)
Currently, there's no safeguard against grabbing it on a custom course - you'll lose the Spray Can as soon as you load a fresh game again - but I consider that easy to fix (tomorrow) and necessary before merger, because the author of this commit does NOT want complaints on release because we forgot to protect users who keep on losing their skincolors.
Increments gamedata minor version, be aware
- M_AssignSpraycans
- Called in M_FinaliseGameData.
- Attaches a hardcoded set of colours to all race maps in cup order, stopping once we run out.
- The colours are shuffled, with some "freebies" always at the head of the list.
- Integrates partial lists pretty well.
- In DEVELOP builds, I_Errors if it produces corrupted state.
- G_LoadGameData, G_SaveGameData
- Save & Load is implemented for these assignments
Creates a central landing point where gamedata loads/creates can be finalised properly.
In addition, gamedata wipes caused by data erase or custom SOC gamedata can no longer be saved in a partway corrupted state if they were to crash midway through.
The linedef's behaviour was broken horribly by long map names, and it's not worth the effort to fix it for the following reasons.
- It was considered a security vulnerability to have free access to the console when it was written.
- The game literally had a cvar to disable running console scripts. That's "I am willingly distributing ActiveX Word Documents in 2023" levels of foolhardery.
- Anything GOOD it can do, both Lua and ACS can do better.
A much more focused replacement for Hornmod, specc'd out by Tyron and Oni working together and implemented by the author of this commit because it's pretty funny.
- Followers have `hornsound` in their SOC configuration.
- The default sound for all followers without a provided one is sfx_horn00.
- They'll play this sound if you use lookback with one following you, and there's nearby players to get the player looking all the way around.
- Only the players who are successfully considered for lookback will hear it.
- Has a v1-like visual with less randomisation, but still netsynced.
- Also controlled by the cvar `taunthorns`, which, like `tauntvoices`, takes "Tasteful" (default), "Meme", and "Off".
TODO: make the condition for horn a little delayed, so you have to hold lookback for a little bit.
Also makes gamedata save/load a little more forward compatible longterm by making a UINT32 bitfield for various once-event flags, with increased minor version
- Four evaluation modes.
- Perfect
- Currently no visual implementation
- All others have a cool set of visuals
- Multi-stage animation of a glowing threat and a Star that's Sealed
- If they're relevant, show the gems you HAVEN'T grabbed
- Three modes here
- No gems
- For Easy mode, asks you to brave a higher difficulty
- Chaos Emeralds
- Not all 7 chaos emeralds? Push your rank harder!
- Super Emeralds
- Not all 7 super emeralds? Further challenge awaits!
- `useBlackRock` to make evaluation context less specific for custom material is replaced with `useSeal` option
- M_CheckCupEmeralds(difficulty)
- Returns the Emeralds you have for that difficulty
- Obviously returns 0 for Easy
- Makes the method of checking collected Emeralds for cup contexts significantly easier
Hilariously broken due to the evaulation gamestate, but the first piece of the puzzle: gets the player into the Credits gamestate after the conclusion of a Podium, if the GP context's cup has this boolean set.
We're unlikely to utilise this, but permits creators of custom user-created cups to flex their own style without fighting to replace the default Podium.
- Now called "Grand Prix Backup"
- Filename is now `gpringsav.bkp`
- Since available in standard contexts, do a little extra guarding against unsporting behaviour:
- In non-DEVELOP builds, delete Grand Prix Backup when returning to the titlescreen/menus.
- "undo your extra work and make it more generic" - Tyron
- Sprites have directional lighting, like walls
- For normal sprites: contrast is much stronger than walls
- Papersprites look the same as walls
- SpriteBacklight option in level header weakens the contrast for sprites only
- SpriteBacklight subtracts from LightContrast
- E.g. SpriteBacklight = 0 would let it match LightContrast
- E.g. SpriteBacklight = 60 would make the contrast much weaker
- Negative values make the contrast stronger
Made sure there is more than enough headroom for our current purposes.
It should be easy to double again if necessary now that the datatypes have been increased... but that would be obscene at this point
- 1024 Unlockables and 1024 Conditions (these were always tied together in slots)
- 2048 emblems (Medals + nonmedals). If we ship with ~250 maps this permits 8 Medals per map - which is higher than we intend right now but could easily fill out in patches
Only persist the full data while unloaded if player has explicitly achieved something on that level, rather than merely visited (such as in a netgame).
Achieving something counts as:
- Getting a best time
- Getting a best lap time (Race only)
- Getting MV_SPBATTACK (completing an SPB run)
- Completing the level IF the level has LF2_FINISHNEEDED (finish level in GP/MP before you see it in Time Attack)
In the previous entry in the series, due to level header records existing in a NUMMAPS-sized table always saved and loaded in full, Time Attack times persisted even across game loads without the relevant custom levels added.
However, this was changed with the long map name system. Map records were assigned to level headers, which were only created on level load.
This new system brings Ring Racers up to parity (or better, due to the reduced incidence of header conflicts!)
- All levels currently loaded with records attached are written on gamedata save.
- This reduces gamedata size for a player who has not unlocked every level!
- On gamedata load, if a level is not loaded, store those extra records on a linked list.
- On level header creation, check the linked list to see if an associated unloaded mapheader record exists.
- If it does, write the record onto the map structure directly, and delete the "unloaded mapheader" storage struct!
- Then on the NEXT gamedata save, in addition to all loaded mapheaders, it writes the extra records kept in long term storage in exactly the same format.
Preperatory work for the next feature on my agenda.
- No longer independently allocated.
- This was a byproduct of the previous NUMMAPS-based implementation. It's just cleaner to have it live directly on the mapheader_t, no caveats about it.
- Now contains mapvisited bitflag array.
- Now all to-gamedata properties on a mapheader's struct are grouped together.
- I was of two minds about it, but decided that this would have cleaner guarantees for compartmentalisation, saving, and loading.
- They can still be wiped independently (G_ClearRecords for time/lap and M_ClearSecrets for mapvisited).
Foundational assistive work.
Also guarantees a consistent cup name length in memory, as some places read/wrote 15 bytes, and some places read/wrote 16 bytes. We settle on the latter (including null terminator) for the broadest backwards compatibility.
Replaces Flicky List system from 2.2.
Specify a list of comma-seperated Followers.
Not used by any systems in this commit, but important to store the data for later.
- On level load for GT_TUTORIAL:
- Forces to requested skin (or Eggman if not specified).
- Named `relevantskin` and not `tutorialskin` in case it's useful to use the same apparatus later for Adventure.
- Also sets default skincolor and disables follower.
- Replaces `tutorialmode`.
- Forces gamespeed to Easy, with no POSITION.
- Laps are currently disabled as well, but this can be changed if necessary.
- Hides Free Play.
- Does not count as a played round (except for Chao Keys).
`tutorialmap` has also been removed. This will be replaced in a later commit with something that plays nicer with Ring Racers' existing systems.
A little off-piste, but a trivial addition since I'm changing this part of the code.
- Plays in Position outside of Encore
- Shows up first in the Sound Test sequence for that map