ShooterCore Game Logic Dissection
ShooterCore defines a lot more functionality than it shows off. In addition to the one map it provides, it is also used by ShooterMaps to showcase more maps and experiences.
In this high level game logic dissection we’ll take a look at what makes the game do what it does. This isn’t going to get into details of animation, menus, music or other aspects of the game. This is purely focused on the logic.
Experience: B_ShooterGame_Elimination
The L_ShooterGym map activates the B_ShooterGame_Elimination experience.
- Activate
ShooterCoreGameFeature Plugin- Mainly useful when other plugins want to use this experience
Pawn Data: HeroData_ShooterGame
- Pawn Class:
B_Hero_ShooterMannequin- Very important class that warrants its own dissection
- Tag Relationships:
TagRelationships_ShooterHero- This config helps determine which abilities can be used and when
- Input Config:
InputData_Hero - Camera Mode:
CM_ThirdPerson
Pawn Ability Set: AbilitySet_ShooterHero
Adds default ShooterCore hero abilities to the pawn, maps which abilities should activate for which input tags.
- Abilities:
GA_Hero_Jump,GA_Hero_Death,GA_Hero_Dash,GA_Emote,GA_QuickbarSlots,GA_ADS,GA_Grenade,GA_DropWeapon,GA_Melee,GA_SpawnEffect,LyraGameplayAbility_Reset - Effects:
GS_IsPlayer(setsLyra.Playertag)
Action Set: LAS_ShooterGame_SharedInput
Adds input bindings and key mappings pertinent to ShooterCore (e.g. show leaderboard, throw grenade, melee attack, etc)
- Input Mapping:
IMC_ShooterGame_KBM - Input Config:
InputData_ShooterGame_Addons
Action Set: LAS_ShooterGame_StandardComponents
LyraPlayerController injections:
| Component | Parent Class | Tick Group | Scope |
|---|---|---|---|
B_NiagaraNumberPopComponent |
ULyraNumberPopComponent_NiagaraText |
During Physics |
Client |
NameplateManagerComponent |
UControllerComponent |
During Physics |
Client |
Controller injections: (Player + AI both)
| Component | Parent Class | Tick Group | Scope |
|---|---|---|---|
B_QuickBarComponent |
ULyraQuickBarComponent |
During Physics |
Client + Server |
B_Hero_ShooterMannequin injections:
| Component | Parent Class | Tick Group | Scope |
|---|---|---|---|
NameplateSource |
ULyraQuickBarComponent |
During Physics |
Client |
Action Set: LAS_ShooterGame_StandardHUD
- Layout:
W_ShooterHUDLayout - Widgets:
| Slot ID | Widget | Note |
|---|---|---|
HUD.Slot.EliminationFeed |
W_EliminationFeed |
|
HUD.Slot.Equipment |
W_QuickBar |
|
HUD.Slot.TopAccolades |
W_AccoladeHostWidget |
|
HUD.Slot.Reticle |
W_WeaponReticleHost |
|
HUD.Slot.PerfStats.Graph |
W_PerfStatContainer_GraphOnly |
|
HUD.Slot.PerfStats.Text |
W_PerfStatContainer_TextOnly |
|
HUD.Slot.LeftSideTouchInputs |
W_OnScreenJoystick_Left |
|
HUD.Slot.RightSideTouchInputs |
W_OnScreenJoystick_Right |
|
HUD.Slot.RightSideTouchInputs |
W_FireButton |
|
HUD.Slot.RightSideTouchRegion |
W_TouchRegion_Right |
|
HUD.Slot.LeftSideTouchRegion |
W_TouchRegion_Left |
Action Set: EAS_BasicShooterAccolades
Interestingly this is the only place where injections are made to base Engine code rather than to ModularGameplayActors-derived classes.
This action set is also the only one with an EAS_ prefix rather than LAS_ which I imagine is intended to illustrate that this is intentionally referring to GameStateBase rather than LyraGameStateBase for these particular injections.
GameStateBase injections:
| Component | Parent Class | Tick Group | Scope |
|---|---|---|---|
B_ElimChainProcessor |
UElimChainProcessor < UGameplayMessageProcessor |
During Physics |
Server only |
B_ElimStreakProcessor |
UElimStreakProcessor < UGameplayMessageProcessor |
During Physics |
Server only |
AssistProcessor (C++) |
UGameplayMessageProcessor |
During Physics |
Server only |
B_AccoladeRelay |
UGameplayMessageProcessor |
During Physics |
Client + Server |
Experience Ability Sets
LyraPlayerState injections:
| Component | Parent Class |
|---|---|
AbilitySet_Elimination |
ULyraAbilitySet |
Ability Set: AbilitySet_Elimination
| Ability | Input Tag |
|---|---|
GA_ShowLeaderboard_TDM |
InputTag.Ability.ShowLeaderboard |
GA_AutoRespawn |
Experience Component Injection
LyraGameState injections:
| Component | Parent Class | Tick Group | Scope |
|---|---|---|---|
B_TeamDeathMatchScoring |
B_ShooterGameScoringBase |
During Physics |
Client + Server |
B_MusicManagerComponent_Elimination |
B_MusicManagerComponentBase |
During Physics |
Client |
B_ShooterBotSpawner |
ULyraBotCreationComponent |
During Physics |
Server |
B_TeamSetup_TwoTeams |
ULyraTeamCreationComponent |
During Physics |
Server |
B_TeamSpawningRules |
UTDM_PlayerSpawningManagmentComponent |
Pre Physics |
Server |
Controller injections: (Player + AI both)
| Component | Parent Class | Tick Group | Scope |
|---|---|---|---|
B_PickRandomCharacter |
ULyraControllerComponent_CharacterParts |
During Physics |
Server |
Experience Widgets
| Slot ID | Widget |
|---|---|
HUD.Slot.TeamScore |
W_ScoreWidget_Elimination |
Game Logic
Logic from LyraGameState injections
B_TeamSetup_TwoTeams logic
- Teams to Create:
- 1 =
TeamDA_Red - 2 =
TeamDA_Blue
- 1 =
B_TeamSpawningRules logic
- Try to find
ALyraPlayerStartfarthest from enemy teams
B_ShooterBotSpawner logic
- Num Bots to Create:
3 - Assign random bot names
- Bot Controller Class:
B_AI_Controller_LyraShooter<ULyraPlayerBotController
B_AI_Controller_LyraShooter logic
- BeginPlay:
Wait for Experience Ready, then:Run Behavior Tree=BT_Lyra_Shooter_Bot
- Register
OnDeathStartedcustom event on pawn’sLyra Health Component.OnDeathStartedevent
OnPossessevent:- Start
BrainComponentlogic - Set
AIPerceptionteam ID
- Start
OnUnPossessevent:- Call
OnDeathStartedcustom event
- Call
OnDeathStartedcustom event:- Clear blackboard
- Stop
BrainComponentlogic
B_TeamDeathMatchScoring logic
Wait for Experience Ready, then:- Start
Phase_Warmupgame phase- Attach
GameStartedcustom event to end ofPhase_Warmupgame phase
- Attach
- Start
GameStartedcustom event- Set game state like max # kills to win, max time to end game
- Start timer to tick game clock every second
- Calls
CountDowncustom event each second
- Calls
- If lots of players then enable data layer with extra spawn points
- Reset all players
- Reset all other misc actors
CountDowncustom event- update game clock
- when out of time, call
HandleVictoryfunction
OnEliminationScoredfunction- Base class calls this each time someone is killed
- Child class calls
HandleVictoryif one team reaches the winning threshold
HandleVictoryfunction- Send
GameplayCue.ShooterGame.UserMessage.MatchDecidedcue - Start
Phase_Post_Gamegame phase
- Send
- (via base class)
- Listen for Gameplay Cues, update score
Lyra.Elimination.MessageLyra.Assist.Message
- Listen for Gameplay Cues, update score
B_MusicManagerComponent_Elimination logic
- Set Is Menu = False
- Begin Play:
- Set
mx_Systemas Game State Music System - Listen for
Lyra.Elimination.Messagecues, callReceive Player Deathfunction - Listen for
Lyra.Damage.Taken.Messagecues, if local player then callReceive Weapon Firefunction
- Set
- Every Tick:
- Set
LookDiraudio controller parameter - Set
Alpha Mvmtaudio parameter based on current move speed - Set
Intensityaudio parameter
- Set
Receive Player Deathfunction sets max alpha 1.0Receive Weapon Firefunction sets alpha based on weapon fire strength
Logic from LyraPlayerController injections
B_NiagaraNumberPopComponent logic
Base class ULyraNumberPopComponent
- When damage is done/taken, briefly display a damage number
NameplateManagerComponent logic
- Keep track of all actors needing nameplates
- Use
W_NameplateUI widget
Logic from Controller injections
B_PickRandomCharacter Logic
This component is injected into all Controllers for both Players and AI.
BeginPlayevent:AddCharacterPartrandomly choose eitherB_MannyorB_Quinnbody parts- Minor bug:
Does NOT call Parent BeginPlay - Seems like it will only be problematic if/when you allow users to change which pawns they possess
B_QuickBarComponent logic
Base class ULyraQuickBarComponent
- Manage the 3 quick bar slots
- which equipment is in which slot
- Allow swapping which equipment is active
Logic from B_Hero_ShooterMannequin injections
NameplateSource logic
- Begin Play:
- Broadcast to other players that self should have a nameplate
- Register for
Gameplay.Message.Nameplate.Discovergameplay cues- When receiving one, respond and register self
- End Play:
- Broadcast to other players to remove self as a nameplate object
Logic from GameStateBase injections
B_ElimChainProcessor logic
Base class UElimChainProcessor
- Keep track of how many players were eliminated since we last died.
B_ElimStreakProcessor logic
Base class UElimStreakProcessor
- Keep track of long streaks of kills (5, 10, 15, 20).
AssistProcessor logic
- Keep track of number of kill assists this player has.
B_AccoladeRelay logic
- Listen for
Lyra.ShooterGame.Accoladegameplay cues - Do stuff RE accolades