- M_ProfileControlSaveResponse: Set without stealth (ie, call command which sends XD_WEAPONPREF netxcmd)
- weaponPrefChange (and its splitscreen ilk): Only build/send XD_WEAPONPREF command when Playing()
Two arrows. One above the player, floating. One below the
player, on the ground.
Both arrows use the player's facing angle. Arrows are only
visible to their own player (other players can't see them).
The floating arrow is a papersprite. You can see the arrow
turn with you as you turn your camera.
The grounded arrow is a splat with additive blending. It
tilts to match the slope of the ground you're driving on.
- Got_NameAndColor: Incorporate check for cv_restrictskinchange and FREE PLAY
- CanChangeSkin: Boil away all the useless conditions, combine with CanChangeSkinWhilePlaying
- Doesn't apply on join, intro camera spin turnaround, or outside of GS_LEVEL.
- Extract some of Got_TeamChange's behaviour into a new FinalisePlaystateChange function.
- M_CharacterSelectTick: Initialise Online menu when setting up
- PLAY_MP_OptSelect: Hide entries 0 and 1 instead of removing them, to keep options aligned
- 2p: In 1p position (slides from right)
- 3p/4p: In top-middle of screen (slides from top)
- Uses time from the display with the highest time, which covers exiting, no contest, etc
- Exposes V_ flags in the function signature
Not a currently accessible codepath, but in-advance fix.: P_DoTimeOver sets exitcountdown effectively unconditionally, which means it can only be used in situations where *every* remaining player is about to explode.
- Only exit Capsules/Versus round if number of players with no bumpers is equal to number of players in game.
- Apply Eliminated flags in relevant context, to prevent griefing.
Don't do this because in sdl/i_video.cpp,
S_InitMusicVolume is called to unmute music when the
window is refocused. Because I_StartupGraphics is called
before those cvars are added and it is an error to try to
set a cvar before it is added.
With the old code, if the object at the head of the list
was removed, it would leave the reference behind,
extending the lifetime of the thinker until P_RunKartItems
or P_RunOverlays was run.
This fixes some thinkers never being removed due to having
negative reference counts.
And here's a breakdown of why the old code could produce
negative reference counts:
Consider P_CheckPosition. This function calls P_SetTarget
on tm.thing but does not call P_RestoreTMStruct. This
means that tm.thing will not be NULL the next P_SetTarget
is called on it. What are the implications of this?
Consider the following series of events:
- P_CheckPosition is called, tm.thing != NULL afterward
- Another function saves the tm struct and sets tm.thing to a different mobj
- - the old tm.thing will have its references decremented
- - the new tm.thing will have its references incremented
- This function calls P_RestoreTMStruct
What should happen when P_RestoreTMStruct is called? The
*new* tm.thing should have its references *decremented*
and the *old* tm.thing should its references
*incremented*, of course, for symmetry with P_SetTarget.
The old code correctly decremented new tm.thing's
references but did not increment old tm.thing's
references.