aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/scripts/vscripts/evac/_evac.gnut
blob: ba473cae9891259912c84cce8ed38507f042d1ee (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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
untyped

global function Evac_Init
global function Evac_AddLocation
global function Evac_SetSpacePosition
global function Evac_SetEnabled
global function Evac_IsEnabled
global function IsEvacDropship
global function EvacMain

const float EVAC_ARRIVAL_TIME = 40.0
const float EVAC_WAIT_TIME = 18.0

struct {
	bool enabled = true

	array<Point> evacPoints
	Point spacePosition
	
	entity evacDropship
	array<entity> evacPlayers
} file

void function Evac_Init()
{
	EvacShared_Init()
	
	AddCallback_GameStateEnter( eGameState.Epilogue, Evac_OnEpilogue )
}

void function Evac_SetEnabled( bool enabled )
{
	file.enabled = enabled
}

bool function Evac_IsEnabled()
{
	return false // shit is busted rn lol
	//return file.enabled && GetClassicMPMode() && !IsRoundBased()
}

void function Evac_AddLocation( vector origin, vector angles )
{
	Point evacPoint
	evacPoint.origin = origin
	evacPoint.angles = angles
	
	file.evacPoints.append( evacPoint )
}

void function Evac_SetSpacePosition( vector origin, vector angles )
{
	file.spacePosition.origin = origin
	file.spacePosition.angles = angles
}

bool function IsEvacDropship( entity ent )
{
	return file.evacDropship == ent && IsValid( file.evacDropship )
}

void function Evac_OnEpilogue()
{
	if ( Evac_IsEnabled() )
		thread EvacMain( GetOtherTeam( GameScore_GetWinningTeam() ) )
}

void function EvacMain( int winningTeam )
{
	if ( file.evacPoints.len() == 0 )
	{
		// automatically add evac locations if they aren't registered yet
		int i = 1
		entity current = null
		while ( true )
		{
			current = GetEnt( "escape_node" + i )
			print( current )
			
			if ( current != null )
				Evac_AddLocation( current.GetOrigin(), current.GetAngles() )
			else
				break
				
			i++
		}
		
		if ( file.evacPoints.len() == 0 )
			unreachable
	}
	
	if ( file.spacePosition.origin == < 0, 0, 0 > )
	{
		// automatically add a space node if not registered yet
		entity defaultSpaceNode = GetEnt( "spaceNode" )
		if ( defaultSpaceNode == null )
			unreachable
		
		Evac_SetSpacePosition( defaultSpaceNode.GetOrigin(), defaultSpaceNode.GetAngles() )
	}
	
	Point evacPoint = file.evacPoints[ RandomInt( file.evacPoints.len() ) ]
	
	// create an entity for the evac point that clients will get
	entity evacPointEntity = CreateEntity( MARKER_ENT_CLASSNAME )
	evacPointEntity.SetOrigin( evacPoint.origin )
	evacPointEntity.kv.spawnflags = SF_INFOTARGET_ALWAYS_TRANSMIT_TO_CLIENT
	DispatchSpawn( evacPointEntity )
	evacPointEntity.DisableHibernation()
			
	// set objectives
	//SetTeamActiveObjective( winningTeam, "EG_DropshipExtract", Time() + EVAC_ARRIVAL_TIME, evacPointEntity )
	//SetTeamActiveObjective( GetOtherTeam( winningTeam ), "EG_StopExtract", Time() + EVAC_ARRIVAL_TIME, evacPointEntity )
		
	// wanted to do this with an actual dropship to calculate embarkStartDelay but spawning it before it should exist ingame is weird
	// could probably do it with a dummy entity but effort
	wait EVAC_ARRIVAL_TIME - 4.33333//embarkStartDelay
		
	// create dropship
	entity dropship = CreateDropship( winningTeam, evacPoint.origin, evacPoint.angles )
	file.evacDropship = dropship 
	
	DispatchSpawn( dropship )
	
	dropship.SetModel( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" ) // gotta do this after dispatch for some reason
	vector startPos = dropship.Anim_GetStartForRefEntity( "cd_dropship_rescue_side_start", evacPointEntity, "origin" ).origin
	dropship.SetOrigin( startPos ) // set origin so the dropship isn't in the map
	dropship.EndSignal( "OnDestroy" )
	
	// calculate time until idle 
	float sequenceDuration = dropship.GetSequenceDuration( "cd_dropship_rescue_side_start" )
	float cycleFrac = dropship.GetScriptedAnimEventCycleFrac( "cd_dropship_rescue_side_start", "ReadyToLoad" )
	float embarkStartDelay = sequenceDuration * cycleFrac
		
	// play anim
	thread PlayAnim( dropship, "cd_dropship_rescue_side_start", evacPointEntity )
	wait embarkStartDelay
	
	print( "evac flyin done! ready to load players" )
	
	// set objectives again
	SetTeamActiveObjective( winningTeam, "EG_DropshipExtract2", Time() + EVAC_WAIT_TIME, evacPointEntity )
	SetTeamActiveObjective( GetOtherTeam( winningTeam ), "EG_StopExtract2", Time() + EVAC_WAIT_TIME, evacPointEntity )
	
	thread EvacShipThink( dropship ) // let people enter it
	
	wait EVAC_WAIT_TIME
	
	// fly away
	thread PlayAnim( dropship, "cd_dropship_rescue_side_end", evacPointEntity )
	
	// set objectives again
	SetTeamActiveObjective( winningTeam, "EG_DropshipExtractDropshipFlyingAway" )
	SetTeamActiveObjective( GetOtherTeam( winningTeam ), "EG_StopExtractDropshipFlyingAway" )
	
	wait dropship.GetSequenceDuration( "cd_dropship_rescue_side_end" ) - WARPINFXTIME
	
	foreach ( entity player in file.evacPlayers  )
	{
		Remote_CallFunction_Replay( player, "ServerCallback_PlayScreenFXWarpJump" )
	}
	
	// todo screen effects and shit
	//WaittillAnimDone( dropship )
	wait WARPINFXTIME
	
	// space
	dropship.SetOrigin( file.spacePosition.origin )
	dropship.SetAngles( file.spacePosition.angles )
	thread PlayAnim( dropship, "ds_space_flyby_dropshipA" )
	
	// display player [Evacuated] in killfeed
	foreach ( entity player in GetPlayerArray() )
	{
		foreach ( entity evacPlayer in file.evacPlayers )
			Remote_CallFunction_NonReplay( player, "ServerCallback_EvacObit", evacPlayer.GetEncodedEHandle() )
	}
	
	foreach ( entity player in file.evacPlayers )
	{
		// set skybox to space for all evac players
		player.SetSkyCamera( GetEnt( "skybox_cam_intro" ) )
		Remote_CallFunction_NonReplay( player, "ServerCallback_DisableHudForEvac" )
	}
	
	wait 5.0
	
	foreach ( entity player in GetPlayerArray() )
		ScreenFadeToBlackForever( player, 2.0 )
		
	wait 2.0
		
	// end game lol
	SetGameState( eGameState.Postmatch )
}

void function EvacShipThink( entity dropship )
{
	dropship.EndSignal( "OnDestroy" )
	
	// this is the easiest way i could figure out to get a bounding box that's parented to the dropship
	entity mover1 = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() )
	mover1.SetParent( dropship )
	mover1.SetLocalOrigin( dropship.GetBoundingMaxs() - < 0, 0, 100> )
	
	entity mover2 = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() )
	mover2.SetParent( dropship )
	mover2.SetLocalOrigin( dropship.GetBoundingMins() - < 0, 0, 100 > )
	
	while ( true )
	{
		foreach ( entity player in GetPlayerArrayOfTeam( dropship.GetTeam() ) )
		{
			if ( file.evacPlayers.contains( player ) || !IsAlive( player ) )
				continue
				
			vector playerPos = player.GetOrigin()

			vector mover1Pos = mover1.GetOrigin()
			vector mover2Pos = mover2.GetOrigin()
			vector maxPos
			maxPos.x = mover1Pos.x > mover2Pos.x ? mover1Pos.x : mover2Pos.x
			maxPos.y = mover1Pos.y > mover2Pos.y ? mover1Pos.y : mover2Pos.y
			maxPos.z = mover1Pos.z > mover2Pos.z ? mover1Pos.z : mover2Pos.z
			
			vector minPos
			minPos.x = mover1Pos.x < mover2Pos.x ? mover1Pos.x : mover2Pos.x
			minPos.y = mover1Pos.y < mover2Pos.y ? mover1Pos.y : mover2Pos.y
			minPos.z = mover1Pos.z < mover2Pos.z ? mover1Pos.z : mover2Pos.z
			
			print( "\n" )
			print( player )
			print( playerPos )
			print( minPos )
			print( maxPos )
			
			if ( playerPos.x > minPos.x && playerPos.y > minPos.y && playerPos.z > minPos.z &&
				 playerPos.x < maxPos.x && playerPos.y < maxPos.y && playerPos.z < maxPos.z )
			{
				print( player + " is evacuating!" )
			
				file.evacPlayers.append( player )
				player.SetParent( dropship )
				
				// super duper temp
				player.SetLocalOrigin( dropship.GetOrigin() - < 0, 10, 80 > )
			}
		}
		
		WaitFrame()
	}
}

/*void function TestEvac()
{
	if ( file.evacShipSpawns.len() == 0 )
		Evac_AddLocation( GetEnt( "escape_node1" ).GetOrigin(), GetEnt( "escape_node1" ).GetAngles() )

	Point shipSpawn = file.evacShipSpawns[ RandomInt( file.evacShipSpawns.len() ) ]
	
	entity dropship = CreateDropship( GetPlayerArray()[0].GetTeam(), shipSpawn.origin, shipSpawn.angles )
	file.evacDropship = dropship	
	DispatchSpawn( dropship )
	
	dropship.SetModel( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" )
	
	print( dropship.GetSequenceDuration( "cd_dropship_rescue_side_start" ) )
	print( dropship.GetScriptedAnimEventCycleFrac( "cd_dropship_rescue_side_start", "ReadyToLoad" ) )
	
	float embarkStart = dropship.GetSequenceDuration( "cd_dropship_rescue_side_start" ) * dropship.GetScriptedAnimEventCycleFrac( "cd_dropship_rescue_side_start", "ReadyToLoad" )
	print( embarkStart )
	
	thread PlayAnim( dropship, "cd_dropship_rescue_side_start" )
	wait embarkStart
	print( "evac start anim done" )
	thread TestEvacThink( dropship )
	SetTeamActiveObjective( GetPlayerArray()[0].GetTeam(), "EG_DropshipExtract2", Time() + 30, dropship )

	thread PlayAnim( dropship, "cd_dropship_rescue_side_idle", GetEnt( "escape_node1" ) )
}

void function TestEvacThink( entity dropship )
{
	dropship.EndSignal( "OnDestroy" )
		
	// these numbers are probably innacurate but there's no real way of getting accurate ones and these are good enough
	entity mover = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() )
	mover.SetParent( dropship )
	mover.SetLocalOrigin( dropship.GetBoundingMaxs() - < 0, 0, 100> )
	
	entity mover2 = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() )
	mover2.SetParent( dropship )
	mover2.SetLocalOrigin( dropship.GetBoundingMins() - < 0, 0, 100> )	
	
	while ( true )
	{
		foreach ( entity player in GetPlayerArrayOfTeam( dropship.GetTeam() ) )
		{
			if ( !IsAlive( player ) )
				continue
		
			vector playerOrigin = player.GetOrigin()
					
			vector dropshipMax = mover.GetOrigin()
			vector dropshipMin = mover2.GetOrigin()
			
			// temp, might be permenant but idk if box triggers are a thing in script
			if ( playerOrigin.x > dropshipMin.x && playerOrigin.y > dropshipMin.y && playerOrigin.z > dropshipMin.z &&
				 playerOrigin.x < dropshipMax.x && playerOrigin.y < dropshipMax.y && playerOrigin.z < dropshipMax.z )
				 player.Die()
		}
		
		WaitFrame()
	}
}*/