aboutsummaryrefslogtreecommitdiff
path: root/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_arena.gnut
blob: 1765fd9bacf8d380b3b0fb45cee10cd13422f723 (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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
global function GameModeArena_Init

struct {
	bool inBuyPhase

	entity imcBoostStore
	entity militiaBoostStore
	
	entity imcShield
	entity militiaShield
} file

void function GameModeArena_Init()
{
	SetSpawnpointGamemodeOverride( TEAM_DEATHMATCH )

	SetShouldUseRoundWinningKillReplay( true )
	SetRoundBased( true )
	SetRespawnsEnabled( false )
	SetLoadoutGracePeriodEnabled( false ) // prevent modifying loadouts with grace period
	Riff_ForceTitanAvailability( eTitanAvailability.Never )
	Riff_ForceBoostAvailability( eBoostAvailability.Disabled )
	Riff_ForceSetEliminationMode( eEliminationMode.Pilots )

	ClassicMP_SetCustomIntro( GameModeArena_BuyPhaseSetup, 30.0 )
	AddCallback_EntitiesDidLoad( CreateBoostStores )
	AddCallback_OnPlayerRespawned( SetupArenaLoadoutForPlayer )
}

// intro / buy phase

void function GameModeArena_BuyPhaseSetup()
{
	AddCallback_OnClientConnected( SpawnPlayerIntoArenasIntro )
	AddCallback_GameStateEnter( eGameState.Prematch, void function() { thread BuyPhase() } )
}

void function SpawnPlayerIntoArenasIntro( entity player )
{
	if ( GetGameState() == eGameState.Prematch )
		RespawnAsPilot( player )
}

void function CreateBoostStores()
{
	array<entity> startspawns = GetEntArrayByClass_Expensive( "info_spawnpoint_human_start" ) // easier to do this than use a spawn callback imo
	
	vector imcAverageOrigin
	float imcAverageAngle
	int imcNumSpawns
	
	vector militiaAverageOrigin
	float militiaAverageAngle
	int militiaNumSpawns
	
	foreach ( entity startspawn in startspawns )
	{
		if ( !startspawn.HasKey( "gamemode_tdm" ) || startspawn.kv.gamemode_tdm == "0" )
			continue
	
		if ( startspawn.GetTeam() == TEAM_IMC )
		{
			imcAverageOrigin += startspawn.GetOrigin()
			imcAverageAngle += startspawn.GetAngles().y
			imcNumSpawns++
		}
		else
		{
			militiaAverageOrigin += startspawn.GetOrigin()
			militiaAverageAngle += startspawn.GetAngles().y
			militiaNumSpawns++
		}
	}
	
	// create imc boost store 
	vector finalPositionImc = < imcAverageOrigin.x / imcNumSpawns, imcAverageOrigin.y / imcNumSpawns, imcAverageOrigin.z / imcNumSpawns >
	finalPositionImc += ( 200 * AnglesToForward( < 0, imcAverageAngle / imcNumSpawns, 0 > ) )
	CreateBoostStoreLocation( TEAM_IMC, finalPositionImc, < 0, 0, 0 >, true )
	
	vector finalPositionMilitia = < militiaAverageOrigin.x / militiaNumSpawns, militiaAverageOrigin.y / militiaNumSpawns, militiaAverageOrigin.z / militiaNumSpawns >
	finalPositionMilitia += ( 200 * AnglesToForward( < 0, militiaAverageAngle / militiaNumSpawns, 0 > ) )
	CreateBoostStoreLocation( TEAM_MILITIA, finalPositionMilitia, < 0, 0, 0 >, true )
	
	// createbooststorelocation is void so have to do this 
	// also boost store code is just fully fucked lol, teams only get set on open so can't compare teams at this point
	// sorry if someone else makes their own boost stores lol this'll just break
	// if there's some way to get the invisible crates used for boost stores i will be very happy
	
	if ( GetBoostStores().len() != 2 )
		print( "_gamemode_arena.gnut: there are more than 2 boost stores, very bad no good" )
	
	file.imcBoostStore = GetBoostStores()[0]
	file.militiaBoostStore = GetBoostStores()[1]
}

void function BuyPhase()
{
	ClassicMP_OnIntroStarted()

	foreach ( entity player in GetPlayerArray() )
	{
		ScreenFadeFromBlack( player )
		RespawnAsPilot( player )
		
		AddMoneyToPlayer( player, GetCashBoostForRoundCount( GetRoundsPlayed() ) )
	}
	
	SetJoinInProgressBonus( GetCashBoostForRoundCount( GetRoundsPlayed() ) )

	// sort of a hack, set up a new intro here, so dropship intro only ever plays once

	//file.imcShield = CreateBubbleShieldWithSettings( TEAM_IMC, file.imcBoostStore.GetOrigin(), <0,0,0>, null, 15.0 )
	//file.militiaShield = CreateBubbleShieldWithSettings( TEAM_MILITIA, file.militiaBoostStore.GetOrigin(), <0,0,0>, null, 15.0 )
	
	entity imcShield = CreateEntity( "prop_dynamic" )
	imcShield.SetValueForModelKey( $"models/fx/xo_shield.mdl" )
	imcShield.kv.solid = 0
    imcShield.kv.rendercolor = "255 255 255" // white
	imcShield.kv.modelscale = 2.25
	imcShield.SetOrigin( file.imcBoostStore.GetOrigin() )
	DispatchSpawn( imcShield )
		
	entity militiaShield = CreateEntity( "prop_dynamic" )
	militiaShield.SetValueForModelKey( $"models/fx/xo_shield.mdl" )
	militiaShield.kv.solid = 0
    militiaShield.kv.rendercolor = "255 255 255" // white
	militiaShield.kv.modelscale = 2.25
	militiaShield.SetOrigin( file.militiaBoostStore.GetOrigin() )
	DispatchSpawn( militiaShield )
			
	// current problem, there is seemingly no way of getting a shield we can resize which actually resizes the collision
	// could probably just damage players that try to leave lol
	
	OpenBoostStores()
	
	thread DamageLeavingPlayers( imcShield.GetOrigin(), militiaShield.GetOrigin() )
	
	wait 30.0 // intro length
	
	CloseBoostStores()
	imcShield.Destroy()
	militiaShield.Destroy()
	
	foreach ( entity player in GetPlayerArray() )
		if ( player.GetMainWeapons().len() != 3 )
			player.GiveWeapon( "mp_weapon_semipistol" )
	
	ClassicMP_OnIntroFinished()
}

void function DamageLeavingPlayers( vector imcOrigin, vector militiaOrigin )
{
	while ( GetGameState() == eGameState.Prematch )
	{
		wait 0.5
		foreach ( entity player in GetPlayerArray() )
		{
			vector pos = imcOrigin
			if ( player.GetTeam() == TEAM_MILITIA )
				pos = militiaOrigin
			
			if ( Distance( player.GetOrigin(), pos ) > 510.0 ) // roughly the size of the shield
				player.TakeDamage( 25, svGlobal.worldspawn, svGlobal.worldspawn, {} )
		}
	}
}

void function SetupArenaLoadoutForPlayer( entity player )
{
	PilotLoadoutDef playerLoadout = clone GetActivePilotLoadout( player )

	if ( GetGameState() == eGameState.Prematch ) // buy phase
	{
		playerLoadout.primary = ""
		playerLoadout.primaryMods = []
		playerLoadout.secondary = ""
		playerLoadout.secondaryMods = []
		playerLoadout.weapon3 = ""
		playerLoadout.weapon3Mods = []
		playerLoadout.ordnance = ""
		playerLoadout.special = ""
	}
	
	GivePilotLoadout( player, playerLoadout )
}