aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/scripts/vscripts/mp/player_cloak.nut
blob: 8ef7dcd9360aa0d578a47aabfb27f124a419d527 (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
untyped //TODO: get rid of player.s.cloakedShotsAllowed. (Referenced in base_gametype_sp, so remove for R5)

global function PlayerCloak_Init

global const CLOAK_FADE_IN = 1.0
global const CLOAK_FADE_OUT = 1.0

global function EnableCloak
global function DisableCloak
global function EnableCloakForever
global function DisableCloakForever

//=========================================================
//	player_cloak
//
//=========================================================

void function PlayerCloak_Init()
{
	RegisterSignal( "OnStartCloak" )
	RegisterSignal( "KillHandleCloakEnd" ) //Somewhat awkward, mainly to smooth out weird interactions with cloak ability and cloak execution

	AddCallback_OnPlayerKilled( AbilityCloak_OnDeath )
	AddSpawnCallback( "npc_titan", SetCannotCloak )
}

void function SetCannotCloak( entity ent )
{
	ent.SetCanCloak( false )
}

void function PlayCloakSounds( entity player )
{
	EmitSoundOnEntityOnlyToPlayer( player, player, "cloak_on_1P" )
	EmitSoundOnEntityExceptToPlayer( player, player, "cloak_on_3P" )

	EmitSoundOnEntityOnlyToPlayer( player, player, "cloak_sustain_loop_1P" )
	EmitSoundOnEntityExceptToPlayer( player, player, "cloak_sustain_loop_3P" )
}

void function EnableCloak( entity player, float duration, float fadeIn = CLOAK_FADE_IN )
{
	if ( player.cloakedForever )
		return

	thread AICalloutCloak( player )

	PlayCloakSounds( player )

	float cloakDuration = duration - fadeIn

	Assert( cloakDuration > 0.0, "Not valid cloak duration. Check that duration is larger than the fadeinTime. When this is not true it will cause the player to be cloaked forever. If you want to do that use EnableCloakForever instead" )

	player.SetCloakDuration( fadeIn, cloakDuration, CLOAK_FADE_OUT )

	player.s.cloakedShotsAllowed = 0

	Battery_StopFXAndHideIconForPlayer( player )

	thread HandleCloakEnd( player )
}

void function AICalloutCloak( entity player )
{
	player.EndSignal( "OnDeath" )

	wait CLOAK_FADE_IN //Give it a beat after cloak has finishing cloaking in

	array<entity> nearbySoldiers = GetNPCArrayEx( "npc_soldier", TEAM_ANY, player.GetTeam(), player.GetOrigin(), 1000  )  //-1 for distance parameter means all spectres in map
	foreach ( entity grunt in nearbySoldiers )
	{
		if ( !IsAlive( grunt ) )
			continue

		if ( grunt.GetEnemy() == player )
		{
			ScriptDialog_PilotCloaked( grunt, player )
			return //Only need one guy to say this instead of multiple guys
		}
	}
}

void function EnableCloakForever( entity player )
{
	player.SetCloakDuration( CLOAK_FADE_IN, -1, CLOAK_FADE_OUT )

	player.cloakedForever = true

	thread HandleCloakEnd( player )
	PlayCloakSounds( player )
}


void function DisableCloak( entity player, float fadeOut = CLOAK_FADE_OUT )
{
	StopSoundOnEntity( player, "cloak_sustain_loop_1P" )
	StopSoundOnEntity( player, "cloak_sustain_loop_3P" )

	bool wasCloaked = player.IsCloaked( CLOAK_INCLUDE_FADE_IN_TIME )

	if ( fadeOut < CLOAK_FADE_OUT && wasCloaked )
	{
		EmitSoundOnEntityOnlyToPlayer( player, player, "cloak_interruptend_1P" )
		EmitSoundOnEntityExceptToPlayer( player, player, "cloak_interruptend_3P" )

		StopSoundOnEntity( player, "cloak_warningtoend_1P" )
		StopSoundOnEntity( player, "cloak_warningtoend_3P" )
	}

	player.SetCloakDuration( 0, 0, fadeOut )
}

void function DisableCloakForever( entity player, float fadeOut = CLOAK_FADE_OUT )
{
	DisableCloak( player, fadeOut )
	player.cloakedForever = false
}


void function HandleCloakEnd( entity player )
{
	player.EndSignal( "OnDeath" )
	player.EndSignal( "OnEMPPilotHit" )
	player.EndSignal( "OnChangedPlayerClass" )
	player.Signal( "OnStartCloak" )
	player.EndSignal( "OnStartCloak" )
	player.EndSignal( "KillHandleCloakEnd" ) //Calling DisableCloak() after EnableCloak() doesn't kill this thread by design (to allow attacking through cloak etc), so this signal is for when you want to kill this thread

	float duration = player.GetCloakEndTime() - Time()

	OnThreadEnd(
		function() : ( player )
		{
			if ( !IsValid( player ) )
				return

			if ( PlayerHasBattery( player ) )
				Battery_StartFX( GetBatteryOnBack( player ) )

			StopSoundOnEntity( player, "cloak_sustain_loop_1P" )
			StopSoundOnEntity( player, "cloak_sustain_loop_3P" )
			if ( !IsCloaked( player ) )
				return

			if ( !IsAlive( player ) || !player.IsHuman() )
			{
				DisableCloak( player )
				return
			}

			float duration = player.GetCloakEndTime() - Time()
			if ( duration <= 0 )
			{
				DisableCloak( player )
			}
		}
	)

	float soundBufferTime = 3.45

	if ( duration > soundBufferTime )
	{
		wait ( duration - soundBufferTime )
		if ( !IsCloaked( player ) )
			return
		EmitSoundOnEntityOnlyToPlayer( player, player, "cloak_warningtoend_1P" )
		EmitSoundOnEntityExceptToPlayer( player, player, "cloak_warningtoend_3P" )

		wait soundBufferTime
	}
	else
	{
		wait duration
	}
}


void function AbilityCloak_OnDeath( entity player, entity attacker, var damageInfo )
{
	if ( !IsCloaked( player ) )
		return

	DisableCloak( player, 0 )
}