aboutsummaryrefslogtreecommitdiff
path: root/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut
blob: ad46b42e2c4707593adc4e628add36bd1dcc328d (plain)
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 )
}