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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
global function GamemodeGG_Init
void function GamemodeGG_Init()
{
SetSpawnpointGamemodeOverride( FFA )
SetShouldUseRoundWinningKillReplay( true )
ClassicMP_ForceDisableEpilogue( true )
SetLoadoutGracePeriodEnabled( false ) // prevent modifying loadouts with grace period
SetWeaponDropsEnabled( false )
Riff_ForceTitanAvailability( eTitanAvailability.Never )
Riff_ForceBoostAvailability( eBoostAvailability.Disabled )
AddCallback_OnPlayerRespawned( OnPlayerRespawned )
AddCallback_OnPlayerKilled( OnPlayerKilled )
AddCallback_OnClientDisconnected( OnPlayerDisconnected )
AddCallback_GameStateEnter( eGameState.WinnerDetermined, OnWinnerDetermined )
AddCallback_GGEarnMeterFull( OnGGEarnMeterFilled )
}
void function OnPlayerDisconnected(entity player)
{
// resetting a player's score when they leave prevents a new player to join the leaver's team and having the previous player's points
AddTeamScore( player.GetTeam(), -GameRules_GetTeamScore( player.GetTeam() ) )
}
void function OnPlayerRespawned( entity player )
{
UpdateLoadout( player )
thread OnPlayerRespawned_Threaded( player )
}
void function OnPlayerRespawned_Threaded( entity player )
{
// bit of a hack, need to rework earnmeter code to have better support for completely disabling it
// rn though this just waits for earnmeter code to set the mode before we set it back
WaitFrame()
if ( IsValid( player ) )
PlayerEarnMeter_SetMode( player, eEarnMeterMode.DISABLED )
}
void function OnPlayerKilled( entity victim, entity attacker, var damageInfo )
{
if ( !victim.IsPlayer() || !attacker.IsPlayer() || GetGameState() != eGameState.Playing )
return
if ( attacker == victim ) // suicide
{
string message = victim.GetPlayerName() + " committed suicide."
foreach ( entity player in GetPlayerArray() )
SendHudMessage( player, message, -1, 0.4, 255, 0, 0, 0, 0, 3, 0.15 )
DeRank( victim )
}
else
{
if ( DamageInfo_GetDamageSourceIdentifier( damageInfo ) != eDamageSourceId.melee_pilot_emptyhanded )
{
float percentageReward = GetCurrentPlaylistVarFloat( "gg_kill_reward", 1.0 )
string scoreEvent = "KillPilot"
if ( DamageInfo_GetDamageSourceIdentifier( damageInfo ) == eDamageSourceId.human_execution )
{
string message = victim.GetPlayerName() + " got executed."
foreach ( entity player in GetPlayerArray() )
SendHudMessage( player, message, -1, 0.4, 255, 0, 0, 0, 0, 3, 0.15 )
DeRank( victim )
percentageReward = GetCurrentPlaylistVarFloat( "gg_execution_reward", 1.0 )
scoreEvent = "Execution"
}
Reward( attacker, victim, scoreEvent, percentageReward )
}
}
table<int, bool> alreadyAssisted
foreach( DamageHistoryStruct attackerInfo in victim.e.recentDamageHistory )
{
if ( !IsValid( attackerInfo.attacker ) || !attackerInfo.attacker.IsPlayer() || attackerInfo.attacker == victim )
continue
if ( attackerInfo.attacker != attacker && !( attackerInfo.attacker.GetEncodedEHandle() in alreadyAssisted ) )
{
if ( attackerInfo.damageSourceId != eDamageSourceId.melee_pilot_emptyhanded ) {
alreadyAssisted[attackerInfo.attacker.GetEncodedEHandle()] <- true
Reward( attackerInfo.attacker, victim, "PilotAssist", GetCurrentPlaylistVarFloat( "gg_assist_reward", 0.0 ) )
}
}
}
}
void function Reward( entity player, entity victim, string scoreEvent, float percentageReward )
{
percentageReward = clamp(percentageReward, 0.0, 1.0)
Sv_GGEarnMeter_AddPercentage( player, percentageReward )
Remote_CallFunction_NonReplay( player, "ServerCallback_ScoreEvent", GetScoreEvent(scoreEvent).eventId, 0, eEventDisplayType.MEDAL, victim.GetEncodedEHandle(), 0.0, percentageReward)
}
void function DeRank( entity player )
{
Sv_GGEarnMeter_SetPercentage( player, 0.0 )
if ( GameRules_GetTeamScore( player.GetTeam() ) != 0 )
{
AddTeamScore( player.GetTeam(), -1 ) // get absolutely fucking destroyed lol
player.AddToPlayerGameStat( PGS_ASSAULT_SCORE, -1 )
UpdateLoadout( player )
}
}
bool function OnGGEarnMeterFilled( entity player )
{
AddTeamScore( player.GetTeam(), 1 )
player.AddToPlayerGameStat( PGS_ASSAULT_SCORE, 1 )
UpdateLoadout( player )
int currentScore = GameRules_GetTeamScore( player.GetTeam() )
int maxScore = GetGunGameWeapons().len()
return currentScore >= maxScore
}
void function UpdateLoadout( entity player )
{
// todo: honestly, this should be reworked to use PilotLoadoutDefs instead of directly modifying weapons and shit
int currentWeaponIndex = GameRules_GetTeamScore( player.GetTeam() )
array<GunGameWeapon> weapons = GetGunGameWeapons()
if ( currentWeaponIndex >= weapons.len() )
currentWeaponIndex = weapons.len() - 1
if ( currentWeaponIndex > weapons.len() - 3 ) // play end of game music for special or last few weapons
PlayMusicToAll( eMusicPieceID.LEVEL_LAST_MINUTE ) // this *shouldn't* overlap if done multiple times
GunGameWeapon weapon = weapons[ currentWeaponIndex ]
foreach ( entity weapon in player.GetMainWeapons() )
player.TakeWeaponNow( weapon.GetWeaponClassName() )
foreach ( entity weapon in player.GetOffhandWeapons() )
player.TakeWeaponNow( weapon.GetWeaponClassName() )
if ( weapon.offhandSlot != -1 )
{
player.GiveOffhandWeapon( weapon.weapon, weapon.offhandSlot, weapon.mods )
player.GiveOffhandWeapon( "melee_pilot_emptyhanded", OFFHAND_MELEE, [ "allow_as_primary" ] )
player.SetActiveWeaponByName( "melee_pilot_emptyhanded" ) // Let the player use the melee in the primary slot, and then force equip it. Effectively gives them an empty hand.
}
else
{
player.GiveWeapon( weapon.weapon, weapon.mods )
player.GiveOffhandWeapon( "melee_pilot_emptyhanded", OFFHAND_MELEE )
}
}
void function OnWinnerDetermined()
{
SetRespawnsEnabled( false )
SetKillcamsEnabled( false )
}
|