aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/mod/scripts/vscripts/weapons/_cloaker.gnut
blob: b4045f3eda6b53bab1fc7e3afc78429a7d7dd932 (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
untyped

global function CloakerThink
global function CloakerShouldCloakGuy

global function CloakerCloaksGuy
global function CloakerDeCloaksGuy

function CloakerThink( entity cloaker, float radius, array<string> ents = [ "any" ], vector offset = Vector(0,0,0), var shouldCloakGuyFunc = null, float waitTime = 0.25 )
{
	OnThreadEnd(
		function() : ( cloaker )
		{
			local cloakList = clone cloaker.s.cloakList
			foreach ( entity guy, value in cloakList )
			{
				if ( !IsAlive( guy ) )
					continue

				CloakerDeCloaksGuy( guy )
			}
		}
	)

	cloaker.s.cloakList <- {}
	cloaker.s.decloakList <- {}

	while( 1 )
	{
		vector origin = cloaker.GetOrigin() + offset
		array<entity> guys

		foreach ( entType in ents )
		{
			switch ( entType )
			{
				case "player":
				case "players":
					guys.extend( GetPlayerArrayEx( "any", cloaker.GetTeam(), TEAM_ANY, origin, radius ) )
					break;
				default:
					guys.extend( GetNPCArrayEx( entType, cloaker.GetTeam(), TEAM_ANY, origin, radius ) )
					break
			}
		}
		int index = 0

		float startTime = Time()

		table cloakList = expect table( cloaker.s.cloakList )
		cloaker.s.decloakList = clone cloakList

		foreach ( guy in guys )
		{
			//only do 5 distanceSqr / cansee checks per frame
			if ( index++ > 5 )
			{
				wait 0.1
				index = 0
				origin = cloaker.GetOrigin() + offset
			}

			bool shouldCloakGuy = CloakerShouldCloakGuy( cloaker, guy )

			if ( shouldCloakGuy )
				shouldCloakGuy = expect bool( shouldCloakGuyFunc( cloaker, guy ) )

			if ( shouldCloakGuy )
			{
				if ( guy in cloaker.s.decloakList )
					delete cloaker.s.decloakList[ guy ]

				if ( IsCloaked( guy ) )
					continue

				cloakList[ guy ] <- true
				CloakerCloaksGuy( guy )
			}
		}

		foreach ( entity guy, value in cloaker.s.decloakList )
		{
			// any guys still in the decloakList shouldn't be decloaked ... if alive.
			Assert( guy in cloakList )
			delete cloakList[ guy ]

			if ( IsAlive( guy ) )
				CloakerDeCloaksGuy( guy )
		}

		float endTime = Time()
		float elapsedTime = endTime - startTime
		if ( elapsedTime < waitTime )
			wait waitTime - elapsedTime
	}
}

void function CloakerCloaksGuy( guy )
{
	if( guy.IsNPC() )
		guy.SetCanCloak(true) // if you don't want to cloak specific targets, it should be handled by shouldCloakGuyFunc in CloakerThink
	guy.SetCloakDuration( 2.0, -1, 0 )
	EmitSoundOnEntity( guy, CLOAKED_DRONE_CLOAK_START_SFX )
	EmitSoundOnEntity( guy, CLOAKED_DRONE_CLOAK_LOOP_SFX )
	guy.Minimap_Hide( TEAM_IMC, null )
	guy.Minimap_Hide( TEAM_MILITIA, null )
}

void function CloakerDeCloaksGuy( guy )
{
	guy.SetCloakDuration( 0, 0, 1.5 )
	StopSoundOnEntity( guy, CLOAKED_DRONE_CLOAK_LOOP_SFX )
	guy.Minimap_AlwaysShow( TEAM_IMC, null )
	guy.Minimap_AlwaysShow( TEAM_MILITIA, null )
	if( guy.IsNPC() )
		guy.SetCanCloak(false)
}

bool function CloakerShouldCloakGuy( entity cloaker, entity guy )
{
	if ( !IsAlive( guy ) )
		return false

	return true
}