summaryrefslogtreecommitdiff
path: root/sourcemod/scripting/include/gamechaos/kreedzclimbing.inc
blob: 0cbb828fff05c3114ed672fa79f4f1843ed264f2 (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
//
// Useful things for making plugins for Kreedz Climbing
//

#if defined _gamechaos_kreedzclimbing_included
	#endinput
#endif
#define _gamechaos_kreedzclimbing_included

#define GC_KREEDZCLIMBING_VERSION 0x01_00_00
#define GC_KREEDZCLIMBING_VERSION_STRING "1.0.0"


#define MAX_COURSE_SIZE   128 // Reasonable maximum characters a course name can have
#define COURSE_CVAR_COUNT 20  // the amount of Course<int> cvars

// Kreedz Climbing Client Commands:
// These may be executed by a player via the console, with / in chat, or via binds.

// specmode          - Cycles spectator mode (F3 by default).
// kz_pause          - Pauses the timer.
// flare             - Fires a flare.
// gototimer | start - Returns to the last pressed start timer.
// spectate | spec   - Enters spectator mode.
// forcespectator    - Becomes a spectator no matter what (force respawns a dead player as well).
// stoptimer         - Instantly stops the player's timer.
// climb | ct        - Respawns at the map spawnpoint.
// InvalidateTimer   - Invalidates the player's timer. An invalid timer can't earn rewards for completing the course. InvalidateTimer 1 displays the message, without the 1 it does not.

// Kreedz Climbing Constants

// Timer state (player->m_Local->Timer_Active)
#define TIMER_STATE_INVISIBLE						0
#define TIMER_STATE_ACTIVE							1
#define TIMER_STATE_INACTIVE						2
#define TIMER_STATE_PAUSED							3

// Timer flags (player_manager->m_iTimerFlags[32])
// These are replicated flags for player's timer (most timer data is local to it's own player).
// Note that these flags are mirrors of data local to the player - they are set to the player's 
// state every frame and cannot be changed.

#define TIMER_FLAG_INVALID							(1 << 0)
#define TIMER_FLAG_ACTIVE							(1 << 1) // We need to broadcast this because Timer_State is local only.
#define TIMER_FLAG_PAUSED							(1 << 2) // A paused timer cannot be active and vice versa.

// Environmental Attributes (player->m_iEnvironmentalAttributes)
#define PLAYER_ENV_ATTRIBUTES_BHOP					(1 << 0)
#define PLAYER_ENV_ATTRIBUTES_SURF					(1 << 1)
#define PLAYER_ENV_ATTRIBUTES_AUTOBHOP				(1 << 2)
#define PLAYER_ENV_ATTRIBUTES_CSGOMOVEMENT			(1 << 3)
#define PLAYER_ENV_ATTRIBUTES_CSGODUCKHULL			(1 << 4)

// Movement restriction flags (player->m_iMovementRestrictions) (new version of Environmental Restrictions below)
#define PLAYER_MOVEMENT_RESTRICTION_NOJUMP			(1 << 0)
#define PLAYER_MOVEMENT_RESTRICTION_NOBHOP			(1 << 1)
#define PLAYER_MOVEMENT_RESTRICTION_NODOUBLEDUCK	(1 << 2)

// OBSOLETE: ONLY IN OLD MAPS: Environmental Restrictions (player->m_iEnvironmentalRestrictions), note not flags, complete integer.
#define PLAYER_ENV_RESTRICTION_NOJUMP				1
#define PLAYER_ENV_RESTRICTION_NOBHOP 				2
#define PLAYER_ENV_RESTRICTION_BOTH 				3

// Cooperative status (player->m_Local.m_multiplayercoursedata.Player1Status, Player2Status etc)
#define COOPERATIVE_STATUS_NONE						0
#define COOPERATIVE_STATUS_WAITING					1
#define COOPERATIVE_STATUS_READY					2
#define COOPERATIVE_STATUS_TIMER_ACTIVE				3
#define COOPERATIVE_STATUS_TIMER_COMPLETE			4
#define COOPERATIVE_STATUS_PLAYER_DISCONNECTED		5 // Player disconnected from server, waiting for them to reconnect.
#define COOPERATIVE_STATUS_TIMER_PAUSED				6

// Kreedz Climbing Button Constants
#define IN_CHECKPOINT	(1 << 25) 
#define IN_TELEPORT		(1 << 26)
#define IN_SPECTATE		(1 << 27)
//#define IN_AVAILABLE		(1 << 28) // Unused
#define IN_HOOK			(1 << 29)

// converts the course id from the obsolete "player_starttimer" event into the course name
stock void GCCourseidToString(int courseid, char[] course, int size)
{
	char szCourseid[16];
	if (courseid < 1 || courseid > COURSE_CVAR_COUNT)
	{
		return;
	}
	FormatEx(szCourseid, sizeof(szCourseid), "Course%i", courseid);
	FindConVar(szCourseid).GetString(course, size);
}

stock void GCGetCurrentMapCourses(ArrayList &array)
{
	if (array == null)
	{
		// 1 for endurance bool
		array = new ArrayList(ByteCountToCells(MAX_COURSE_SIZE) + 1);
	}
	else
	{
		array.Clear();
	}
	
	char course[MAX_COURSE_SIZE];
	
	int ent;
	while((ent = FindEntityByClassname(ent, "func_stoptimer")) != -1) 
	{
		int courseid = GetEntProp(ent, Prop_Data, "CourseID");
		GCCourseidToString(courseid, course, sizeof(course));
		array.PushString(course);
		
		bool endurance = GCIsCourseEndurance(course, ent);
		array.Set(array.Length - 1, endurance, ByteCountToCells(MAX_COURSE_SIZE));
	}
	
	int courseStringtableCount;
	int courseNamesIdx = FindStringTable("CourseNames");
	courseStringtableCount = GetStringTableNumStrings(courseNamesIdx);
	
	for (int i; i < courseStringtableCount; i++)
	{
		ReadStringTable(courseNamesIdx, i, course, sizeof(course));
		array.PushString(course);
		
		bool endurance = GCIsCourseEndurance(course, ent);
		array.Set(array.Length - 1, endurance, ByteCountToCells(MAX_COURSE_SIZE));
	}
}

stock int GCGetTimerState(int client)
{
	return GetEntProp(client, Prop_Send, "Timer_Active");
}

stock void GCSetTimerState(int client, int timerstate)
{
	SetEntProp(client, Prop_Send, "Timer_Active", timerstate);
}

stock int GCGetPlayerEnvAttributes(int client)
{
	return GetEntProp(client, Prop_Send, "m_iEnvironmentalAttributes");
}

stock void GCSetPlayerEnvAttributes(int client, int attributes)
{
	SetEntProp(client, Prop_Send, "m_iEnvironmentalAttributes", attributes);
}

stock int GCGetPlayerMovementRestrictions(int client)
{
	return GetEntProp(client, Prop_Send, "m_iMovementRestrictions");
}

stock void GCSetPlayerMovementRestrictions(int client, int restrictions)
{
	SetEntProp(client, Prop_Send, "m_iMovementRestrictions", restrictions);
}

stock void GCSetActiveCourse(int client, int course)
{
	int ent = FindEntityByClassname(0, "player_manager");
	int courseOffset = FindSendPropInfo("CPlayerResource", "m_iActiveCourse");
	SetEntData(ent, courseOffset + (client * 4), course);
}

stock int GCGetTimerFlags(int client)
{
	int ent = FindEntityByClassname(0, "player_manager");
	int courseOffset = FindSendPropInfo("CPlayerResource", "m_iTimerFlags");
	return GetEntData(ent, courseOffset + (client * 4));
}

stock bool GCInvalidateTimer(int client)
{
	if (~GCGetTimerFlags(client) & TIMER_FLAG_INVALID)
	{
		FakeClientCommand(client, "InvalidateTimer 1");
		return true;
	}
	
	return false;
}

stock bool GCIsCourseEndurance(char[] course, int ent = -1)
{
	if (ent != -1)
	{
		if (IsValidEntity(ent))
		{
			return !!(GetEntProp(ent, Prop_Data, "m_bEnduranceCourse"));
		}
	}
	
	while ((ent = FindEntityByClassname(ent, "point_climbtimer")) != -1)
	{
		if (IsValidEntity(ent))
		{
			char buffer[MAX_COURSE_SIZE];
			GetEntPropString(ent, Prop_Data, "m_strCourseName", buffer, sizeof(buffer));
			
			if (StrEqual(buffer, course))
			{
				return !!(GetEntProp(ent, Prop_Data, "m_bEnduranceCourse"));
			}
		}
	}
	
	while ((ent = FindEntityByClassname(ent, "func_stoptimer")) != -1)
	{
		if (IsValidEntity(ent))
		{
			char buffer[MAX_COURSE_SIZE];
			int courseid = GetEntProp(ent, Prop_Data, "CourseID");
			GCCourseidToString(courseid, buffer, sizeof(buffer));
			
			if (StrEqual(buffer, course))
			{
				return !!(GetEntProp(ent, Prop_Data, "m_bEnduranceCourse"));
			}
		}
	}
	
	return false;
}