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
142
143
144
145
146
147
148
149
150
151
152
153
154
|
untyped
global function GamemodeLts_Init
struct {
entity lastDamageInfoVictim
entity lastDamageInfoAttacker
int lastDamageInfoMethodOfDeath
float lastDamageInfoTime
bool shouldDoHighlights
} file
void function GamemodeLts_Init()
{
// gamemode settings
SetShouldUsePickLoadoutScreen( true )
SetRoundBased( true )
SetRespawnsEnabled( false )
Riff_ForceSetEliminationMode( eEliminationMode.PilotsTitans )
SetShouldUseRoundWinningKillReplay( true )
SetRoundWinningKillReplayKillClasses( true, true ) // both titan and pilot kills are tracked
AddDamageCallback( "player", OnPlayerDamaged )
AddDamageCallback( "npc_titan", OnTitanDamaged )
AddCallback_OnPilotBecomesTitan( RefreshThirtySecondWallhackHighlight )
AddCallback_OnTitanBecomesPilot( RefreshThirtySecondWallhackHighlight )
SetTimeoutWinnerDecisionFunc( CheckTitanHealthForDraw )
ClassicMP_SetCustomIntro( GamemodeLTS_Intro, 0.0 ) // dont any sorta
}
// this should also probably be moved into a generic intro rather than being lts-specific
void function GamemodeLTS_Intro()
{
AddCallback_GameStateEnter( eGameState.Prematch, LTSIntroOnPrematchStart )
}
void function LTSIntroOnPrematchStart()
{
ClassicMP_OnIntroStarted()
foreach ( entity player in GetPlayerArray() )
thread LTSIntroSpawnPlayer( player )
wait 2.0 // literally a guess number for how long the drop might take
ClassicMP_OnIntroFinished()
thread GamemodeLTS_PlayingThink()
}
void function LTSIntroSpawnPlayer( entity player )
{
if ( IsAlive( player ) )
{
player.Die()
WaitFrame() // this doesn't work for some reason but the player will die in roundend anyway so not really an issue
}
thread RespawnAsTitan( player, false )
while ( !player.IsTitan() )
WaitFrame()
TryGameModeAnnouncement( player )
}
void function GamemodeLTS_PlayingThink()
{
svGlobal.levelEnt.EndSignal( "RoundEnd" ) // end this on round end
float endTime = expect float ( GetServerVar( "gameEndTime" ) )
// wait until 30sec left
wait endTime - 30 - Time()
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() < 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 in timeout decision funcs
// 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
}
// this should be generic, not restricted to a specific gamemode
void function AddToTitanDamageStat( entity victim, var damageInfo )
{
// todo: this needs to not count selfdamage
entity attacker = DamageInfo_GetAttacker( damageInfo )
float amount = DamageInfo_GetDamage( damageInfo )
if ( attacker.IsPlayer() && attacker != victim )
attacker.AddToPlayerGameStat( PGS_ASSAULT_SCORE, amount ) // titan damage on
}
void function OnPlayerDamaged( entity player, var damageInfo )
{
if ( player.IsTitan() )
AddToTitanDamageStat( player, damageInfo )
}
void function OnTitanDamaged( entity titan, var damageInfo )
{
AddToTitanDamageStat( titan, damageInfo )
}
|