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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
untyped
global function GamemodeLts_Init
struct {
entity lastDamageInfoVictim
entity lastDamageInfoAttacker
int lastDamageInfoMethodOfDeath
float lastDamageInfoTime
bool shouldDoHighlights
table< entity, int > pilotstreak
} file
void function GamemodeLts_Init()
{
// gamemode settings
SetShouldUsePickLoadoutScreen( true )
SetSwitchSidesBased( true )
SetRoundBased( true )
SetRespawnsEnabled( false )
Riff_ForceSetEliminationMode( eEliminationMode.PilotsTitans )
Riff_ForceSetSpawnAsTitan( eSpawnAsTitan.Always )
SetShouldUseRoundWinningKillReplay( true )
SetRoundWinningKillReplayKillClasses( true, true ) // both titan and pilot kills are tracked
ScoreEvent_SetupEarnMeterValuesForTitanModes()
SetLoadoutGracePeriodEnabled( false )
FlagSet( "ForceStartSpawn" )
AddCallback_OnPilotBecomesTitan( RefreshThirtySecondWallhackHighlight )
AddCallback_OnTitanBecomesPilot( RefreshThirtySecondWallhackHighlight )
SetTimeoutWinnerDecisionFunc( CheckTitanHealthForDraw )
TrackTitanDamageInPlayerGameStat( PGS_ASSAULT_SCORE )
ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() )
ClassicMP_ForceDisableEpilogue( true )
AddCallback_GameStateEnter( eGameState.Playing, WaitForThirtySecondsLeft )
AddCallback_OnClientConnected( SetupPlayerLTSChallenges ) //Just to make up the Match Goals tracking
AddCallback_OnClientDisconnected( RemovePlayerLTSChallenges ) //Safety removal of data to prevent crashes
AddCallback_OnPlayerKilled( LTSChallengeForPlayerKilled )
}
void function SetupPlayerLTSChallenges( entity player )
{
file.pilotstreak[ player ] <- 0
}
void function RemovePlayerLTSChallenges( entity player )
{
if( player in file.pilotstreak )
delete file.pilotstreak[ player ]
}
void function LTSChallengeForPlayerKilled( entity victim, entity attacker, var damageInfo )
{
if ( victim == attacker || !attacker.IsPlayer() || GetGameState() != eGameState.Playing )
return
if ( victim.IsPlayer() && attacker in file.pilotstreak )
{
file.pilotstreak[attacker]++
if( file.pilotstreak[attacker] >= 2 && !HasPlayerCompletedMeritScore( attacker ) )
{
AddPlayerScore( attacker, "ChallengeLTS" )
SetPlayerChallengeMeritScore( attacker )
}
}
}
void function WaitForThirtySecondsLeft()
{
thread WaitForThirtySecondsLeftThreaded()
}
void function WaitForThirtySecondsLeftThreaded()
{
svGlobal.levelEnt.EndSignal( "RoundEnd" ) // end this on round end
float endTime = expect float ( GetServerVar( "roundEndTime" ) )
// wait until 30sec left
wait ( endTime - 30 ) - Time()
PlayMusicToAll( eMusicPieceID.LEVEL_LAST_MINUTE )
foreach ( entity player in GetPlayerArray() )
{
// warn there's 30 seconds left
Remote_CallFunction_NonReplay( player, "ServerCallback_LTSThirtySecondWarning" )
// do initial highlight
RefreshThirtySecondWallhackHighlight( player, null )
}
}
void function RefreshThirtySecondWallhackHighlight( entity player, entity titan )
{
if ( TimeSpentInCurrentState() < expect float ( GetServerVar( "roundEndTime" ) ) - 30.0 )
return
Highlight_SetEnemyHighlight( player, "enemy_sonar" ) // i think this needs a different effect, this works for now tho
if ( player.GetPetTitan() != null )
Highlight_SetEnemyHighlight( player.GetPetTitan(), "enemy_sonar" )
}
int function CheckTitanHealthForDraw()
{
int militiaTitans
int imcTitans
float militiaHealth
float imcHealth
foreach ( entity titan in GetTitanArray() )
{
if ( titan.GetTeam() == TEAM_MILITIA )
{
// doomed is counted as 0 health
militiaHealth += titan.GetTitanSoul().IsDoomed() ? 0.0 : GetHealthFrac( titan )
militiaTitans++
}
else
{
// doomed is counted as 0 health in this
imcHealth += titan.GetTitanSoul().IsDoomed() ? 0.0 : GetHealthFrac( titan )
imcTitans++
}
}
// note: due to how stuff is set up rn, there's actually no way to do win/loss reasons outside of a SetWinner call, i.e. not in timeout winner decision
// as soon as there is, strings in question are "#GAMEMODE_TITAN_TITAN_ADVANTAGE" and "#GAMEMODE_TITAN_TITAN_DISADVANTAGE"
if ( militiaTitans != imcTitans )
return militiaTitans > imcTitans ? TEAM_MILITIA : TEAM_IMC
else if ( militiaHealth != imcHealth )
return militiaHealth > imcHealth ? TEAM_MILITIA : TEAM_IMC
return TEAM_UNASSIGNED
}
|