1 /*
2 LUA_PLAYER.CPP
3 
4 	Copyright (C) 2008 by Gregory Smith
5 
6 	This program is free software; you can redistribute it and/or modify
7 	it under the terms of the GNU General Public License as published by
8 	the Free Software Foundation; either version 3 of the License, or
9 	(at your option) any later version.
10 
11 	This program is distributed in the hope that it will be useful,
12 	but WITHOUT ANY WARRANTY; without even the implied warranty of
13 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 	GNU General Public License for more details.
15 
16 	This license is contained in the file "COPYING",
17 	which is included with this source code; it is available online at
18 	http://www.gnu.org/licenses/gpl.html
19 
20 	Implements the Lua Player class
21 */
22 
23 #include "ActionQueues.h"
24 #include "alephversion.h"
25 #include "computer_interface.h"
26 #include "Crosshairs.h"
27 #include "fades.h"
28 #include "game_window.h"
29 #include "interface.h"
30 #include "lua_map.h"
31 #include "lua_monsters.h"
32 #include "lua_objects.h"
33 #include "lua_hud_objects.h"
34 #include "lua_player.h"
35 #include "lua_script.h"
36 #include "lua_serialize.h"
37 #include "lua_templates.h"
38 #include "map.h"
39 #include "monsters.h"
40 #include "Music.h"
41 #include "network.h"
42 #include "player.h"
43 #include "projectiles.h"
44 #include "network_games.h"
45 #include "Random.h"
46 #include "screen.h"
47 #include "shell.h"
48 #include "SoundManager.h"
49 #include "ViewControl.h"
50 
51 #include <boost/iostreams/device/array.hpp>
52 #include <boost/iostreams/stream_buffer.hpp>
53 namespace io = boost::iostreams;
54 
55 #define DONT_REPEAT_DEFINITIONS
56 #include "item_definitions.h"
57 #include "projectile_definitions.h"
58 
59 #ifdef HAVE_LUA
60 
61 const float AngleConvert = 360/float(FULL_CIRCLE);
62 
63 char Lua_Action_Flags_Name[] = "action_flags";
64 typedef L_Class<Lua_Action_Flags_Name> Lua_Action_Flags;
65 
66 extern ModifiableActionQueues *GetGameQueue();
67 
68 template<uint32 flag>
Lua_Action_Flags_Get_t(lua_State * L)69 static int Lua_Action_Flags_Get_t(lua_State *L)
70 {
71 	int player_index = Lua_Action_Flags::Index(L, 1);
72 
73 	if (GetGameQueue()->countActionFlags(player_index))
74 	{
75 		uint32 flags = GetGameQueue()->peekActionFlags(player_index, 0);
76 		lua_pushboolean(L, flags & flag);
77 	}
78 	else
79 	{
80 		return luaL_error(L, "action flags are only accessible in idle()");
81 	}
82 
83 	return 1;
84 }
85 
86 template<uint32 flag>
Lua_Action_Flags_Set_t(lua_State * L)87 static int Lua_Action_Flags_Set_t(lua_State *L)
88 {
89 	if (!lua_isboolean(L, 2))
90 		return luaL_error(L, "action flags: incorrect argument type");
91 
92 	int player_index = Lua_Action_Flags::Index(L, 1);
93 	if (GetGameQueue()->countActionFlags(player_index))
94 	{
95 		if (lua_toboolean(L, 2))
96 		{
97 			GetGameQueue()->modifyActionFlags(player_index, flag, flag);
98 		}
99 		else
100 		{
101 			GetGameQueue()->modifyActionFlags(player_index, 0, flag);
102 		}
103 	}
104 	else
105 	{
106 		return luaL_error(L, "action flags are only accessible in idle()");
107 	}
108 
109 	return 0;
110 }
111 
Lua_Action_Flags_Set_Microphone(lua_State * L)112 static int Lua_Action_Flags_Set_Microphone(lua_State *L)
113 {
114 	if (!lua_isboolean(L, 2))
115 		return luaL_error(L, "action flags: incorrect argument type");
116 
117 	if (lua_toboolean(L, 2))
118 		return luaL_error(L, "you can only disable the microphone button flag");
119 
120 	int player_index = Lua_Action_Flags::Index(L, 1);
121 	if (GetGameQueue()->countActionFlags(player_index))
122 	{
123 		GetGameQueue()->modifyActionFlags(player_index, 0, _microphone_button);
124 	}
125 	else
126 	{
127 		return luaL_error(L, "action flags are only accessible in idle()");
128 	}
129 
130 	return 0;
131 }
132 
133 const luaL_Reg Lua_Action_Flags_Get[] = {
134 	{"action_trigger", Lua_Action_Flags_Get_t<_action_trigger_state>},
135 	{"cycle_weapons_backward", Lua_Action_Flags_Get_t<_cycle_weapons_backward>},
136 	{"cycle_weapons_forward", Lua_Action_Flags_Get_t<_cycle_weapons_forward>},
137 	{"left_trigger", Lua_Action_Flags_Get_t<_left_trigger_state>},
138 	{"microphone_button", Lua_Action_Flags_Get_t<_microphone_button>},
139 	{"right_trigger", Lua_Action_Flags_Get_t<_right_trigger_state>},
140 	{"toggle_map", Lua_Action_Flags_Get_t<_toggle_map>},
141 	{0, 0}
142 };
143 
144 const luaL_Reg Lua_Action_Flags_Set[] = {
145 	{"action_trigger", Lua_Action_Flags_Set_t<_action_trigger_state>},
146 	{"cycle_weapons_backward", Lua_Action_Flags_Set_t<_cycle_weapons_backward>},
147 	{"cycle_weapons_forward", Lua_Action_Flags_Set_t<_cycle_weapons_forward>},
148 	{"left_trigger", Lua_Action_Flags_Set_t<_left_trigger_state>},
149 	{"microphone_button", Lua_Action_Flags_Set_Microphone},
150 	{"right_trigger", Lua_Action_Flags_Set_t<_right_trigger_state>},
151 	{"toggle_map", Lua_Action_Flags_Set_t<_toggle_map>},
152 	{0, 0}
153 };
154 
155 extern vector<lua_camera> lua_cameras;
156 
157 char Lua_Camera_Path_Points_Name[] = "camera_path_points";
158 typedef L_Class<Lua_Camera_Path_Points_Name> Lua_Camera_Path_Points;
159 
Lua_Camera_Path_Points_New(lua_State * L)160 int Lua_Camera_Path_Points_New(lua_State *L)
161 {
162 	if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4) || !lua_isnumber(L, 6))
163 		return luaL_error(L, "new: incorrect argument type");
164 
165 	int camera_index = Lua_Camera_Path_Points::Index(L, 1);
166 
167 	int polygon = 0;
168 	if (lua_isnumber(L, 5))
169 	{
170 		polygon = static_cast<int>(lua_tonumber(L, 5));
171 		if (!Lua_Polygon::Valid(polygon))
172 			return luaL_error(L, "new: invalid polygon index");
173 	}
174 	else if (Lua_Polygon::Is(L, 5))
175 	{
176 		polygon = Lua_Polygon::Index(L, 5);
177 	}
178 	else
179 		return luaL_error(L, "new: incorrect argument type");
180 
181 	world_point3d point = {
182 		static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE),
183 		static_cast<world_distance>(lua_tonumber(L, 3) * WORLD_ONE),
184 		static_cast<world_distance>(lua_tonumber(L, 4) * WORLD_ONE)
185 	};
186 
187 	int32 time = static_cast<int32>(lua_tonumber(L, 6));
188 	int point_index = lua_cameras[camera_index].path.path_points.size();
189 	lua_cameras[camera_index].path.path_points.resize(point_index+1);
190 	lua_cameras[camera_index].path.path_points[point_index].polygon = polygon;
191 	lua_cameras[camera_index].path.path_points[point_index].point = point;
192 	lua_cameras[camera_index].path.path_points[point_index].delta_time = time;
193 	return 0;
194 }
195 
196 const luaL_Reg Lua_Camera_Path_Points_Get[] = {
197 	{"new", L_TableFunction<Lua_Camera_Path_Points_New>},
198 	{0, 0}
199 };
200 
201 char Lua_Camera_Path_Angles_Name[] = "camera_path_angles";
202 typedef L_Class<Lua_Camera_Path_Angles_Name> Lua_Camera_Path_Angles;
203 
Lua_Camera_Path_Angles_New(lua_State * L)204 int Lua_Camera_Path_Angles_New(lua_State *L)
205 {
206 	if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4))
207 		return luaL_error(L, "new: incorrect argument type");
208 
209 	int camera_index = Lua_Camera_Path_Angles::Index(L, 1);
210 	short yaw = static_cast<short>(lua_tonumber(L,2));
211 	short pitch = static_cast<short>(lua_tonumber(L,3));
212 	int32 time = static_cast<int32>(lua_tonumber(L,4));
213 	int angle_index = lua_cameras[camera_index].path.path_angles.size();
214 
215 	lua_cameras[camera_index].path.path_angles.resize(angle_index+1);
216 	lua_cameras[camera_index].path.path_angles[angle_index].yaw = static_cast<short>(yaw/AngleConvert);
217 	lua_cameras[camera_index].path.path_angles[angle_index].pitch = static_cast<short>(pitch/AngleConvert);
218 	lua_cameras[camera_index].path.path_angles[angle_index].delta_time = time;
219 	return 0;
220 }
221 
222 const luaL_Reg Lua_Camera_Path_Angles_Get[] = {
223 	{"new", L_TableFunction<Lua_Camera_Path_Angles_New>},
224 	{0, 0}
225 };
226 
227 char Lua_Camera_Name[] = "camera";
228 typedef L_Class<Lua_Camera_Name> Lua_Camera;
229 
230 
Lua_Camera_Activate(lua_State * L)231 int Lua_Camera_Activate(lua_State *L)
232 {
233 	int player_index = -1;
234 	if (lua_isnumber(L, 2))
235 	{
236 		player_index = static_cast<int>(lua_tonumber(L, 2));
237 	}
238 	else if (Lua_Player::Is(L, 2))
239 	{
240 		player_index = Lua_Player::Index(L, 2);
241 	}
242 	else
243 		return luaL_error(L, "activate: incorrect argument type");
244 
245 	if (player_index == local_player_index)
246 	{
247 		int camera_index = Lua_Camera::Index(L, 1);
248 		lua_cameras[camera_index].time_elapsed = 0;
249 		lua_cameras[camera_index].player_active = player_index;
250 		lua_cameras[camera_index].path.current_point_index = 0;
251 		lua_cameras[camera_index].path.current_angle_index = 0;
252 		lua_cameras[camera_index].path.last_point_time = 0;
253 		lua_cameras[camera_index].path.last_angle_time = 0;
254 	}
255 
256 	return 0;
257 }
258 
Lua_Camera_Clear(lua_State * L)259 int Lua_Camera_Clear(lua_State *L)
260 {
261 	int camera_index = Lua_Camera::Index(L, 1);
262 	lua_cameras[camera_index].path.path_points.resize(0);
263 	lua_cameras[camera_index].path.path_angles.resize(0);
264 	return 0;
265 }
266 
Lua_Camera_Deactivate(lua_State * L)267 int Lua_Camera_Deactivate(lua_State *L)
268 {
269 	int camera_index = Lua_Camera::Index(L, 1);
270 	lua_cameras[camera_index].time_elapsed = 0;
271 	lua_cameras[camera_index].player_active = -1;
272 	lua_cameras[camera_index].path.last_point_time = 0;
273 	lua_cameras[camera_index].path.last_angle_time = 0;
274 	return 0;
275 }
276 
Lua_Get_Path_Angles(lua_State * L)277 static int Lua_Get_Path_Angles(lua_State *L)
278 {
279 	Lua_Camera_Path_Angles::Push(L, Lua_Camera::Index(L, 1));
280 	return 1;
281 }
282 
Lua_Get_Path_Points(lua_State * L)283 static int Lua_Get_Path_Points(lua_State *L)
284 {
285 	Lua_Camera_Path_Points::Push(L, Lua_Camera::Index(L, 1));
286 	return 1;
287 }
288 
289 const luaL_Reg Lua_Camera_Get[] = {
290 	{"activate", L_TableFunction<Lua_Camera_Activate>},
291 	{"clear", L_TableFunction<Lua_Camera_Clear>},
292 	{"deactivate", L_TableFunction<Lua_Camera_Deactivate>},
293 	{"path_angles", Lua_Get_Path_Angles},
294 	{"path_points", Lua_Get_Path_Points},
295 	{0, 0}
296 };
297 
Lua_Camera_Valid(int16 index)298 static int Lua_Camera_Valid(int16 index)
299 {
300 	return index >= 0 && index < lua_cameras.size();
301 }
302 
303 char Lua_Cameras_Name[] = "Cameras";
304 typedef L_Container<Lua_Cameras_Name, Lua_Camera> Lua_Cameras;
305 
Lua_Cameras_New(lua_State * L)306 int Lua_Cameras_New(lua_State *L)
307 {
308 	if (lua_cameras.size() == INT16_MAX)
309 	{
310 		return 0;
311 	}
312 
313 	lua_camera camera;
314 	camera.index = lua_cameras.size();
315 	camera.path.index = lua_cameras.size();
316 	camera.path.current_point_index = 0;
317 	camera.path.current_angle_index = 0;
318 	camera.path.last_point_time = 0;
319 	camera.path.last_angle_time = 0;
320 	camera.time_elapsed = 0;
321 	camera.player_active = -1;
322 	lua_cameras.push_back(camera);
323 
324 	Lua_Camera::Push(L, camera.index);
325 
326 	return 1;
327 }
328 
329 const luaL_Reg Lua_Cameras_Methods[] = {
330 	{"new", L_TableFunction<Lua_Cameras_New>},
331 	{0, 0}
332 };
333 
Lua_Cameras_Length()334 static int16 Lua_Cameras_Length() {
335 	return lua_cameras.size();
336 }
337 
338 char Lua_Crosshairs_Name[] = "crosshairs";
339 typedef L_Class<Lua_Crosshairs_Name> Lua_Crosshairs;
340 
Lua_Crosshairs_Get_Active(lua_State * L)341 static int Lua_Crosshairs_Get_Active(lua_State *L)
342 {
343 	int player_index = Lua_Crosshairs::Index(L, 1);
344 	if (player_index == local_player_index)
345 	{
346 		lua_pushboolean(L, Crosshairs_IsActive());
347 		return 1;
348 	}
349 	else
350 	{
351 		return 0;
352 	}
353 }
354 
355 const luaL_Reg Lua_Crosshairs_Get[] = {
356 	{"active", Lua_Crosshairs_Get_Active},
357 	{0, 0}
358 };
359 
Lua_Crosshairs_Set_Active(lua_State * L)360 static int Lua_Crosshairs_Set_Active(lua_State *L)
361 {
362 	int player_index = Lua_Crosshairs::Index(L, 1);
363 	if (player_index == local_player_index)
364 	{
365 		if (!lua_isboolean(L, 2))
366 			return luaL_error(L, "active: incorrect argument type");
367 
368 		Crosshairs_SetActive(lua_toboolean(L, 2));
369 	}
370 
371 	return 0;
372 }
373 
374 const luaL_Reg Lua_Crosshairs_Set[] = {
375 	{"active", Lua_Crosshairs_Set_Active},
376 	{0, 0}
377 };
378 
379 char Lua_OverlayColor_Name[] = "overlay_color";
380 typedef L_Enum<Lua_OverlayColor_Name> Lua_OverlayColor;
381 
382 template<char *name>
383 class PlayerSubtable : public L_Class<name>
384 {
385 public:
386 	int16 m_player_index;
387 
388 	template<typename instance_t = PlayerSubtable /*or a derived class*/>
389 	static instance_t *Push(lua_State *L, int16 player_index, int16 index);
390 
391 	static int16 PlayerIndex(lua_State *L, int index);
392 };
393 
394 template<char *name>
395 template<typename instance_t>
Push(lua_State * L,int16 player_index,int16 index)396 instance_t *PlayerSubtable<name>::Push(lua_State *L, int16 player_index, int16 index)
397 {
398 	instance_t *t = 0;
399 
400 	if (!L_Class<name, int16>::Valid(index) || !Lua_Player::Valid(player_index))
401 	{
402 		lua_pushnil(L);
403 		return 0;
404 	}
405 
406 	t = L_Class<name>::template NewInstance<instance_t>(L, index);
407 	t->m_player_index = player_index;
408 
409 	return t;
410 }
411 
412 template<char *name>
PlayerIndex(lua_State * L,int index)413 int16 PlayerSubtable<name>::PlayerIndex(lua_State *L, int index)
414 {
415 	PlayerSubtable<name> *t = static_cast<PlayerSubtable<name> *>(L_Class<name>::Instance(L, index));
416 	if (!t) luaL_typerror(L, index, name);
417 	return t->m_player_index;
418 }
419 
420 char Lua_Overlay_Name[] = "overlay";
421 typedef PlayerSubtable<Lua_Overlay_Name> Lua_Overlay;
422 
Lua_Overlay_Clear(lua_State * L)423 int Lua_Overlay_Clear(lua_State *L)
424 {
425         int player = Lua_Overlay::PlayerIndex(L, 1);
426 	int index = Lua_Overlay::Index(L, 1);
427 	SetScriptHUDIcon(player, index, 0, 0);
428 	SetScriptHUDText(player, index, 0);
429 
430 	return 0;
431 }
432 
Lua_Overlay_Fill_Icon(lua_State * L)433 int Lua_Overlay_Fill_Icon(lua_State *L)
434 {
435         int player = Lua_Overlay::PlayerIndex(L, 1);
436 	int color = Lua_OverlayColor::ToIndex(L, 2);
437 	SetScriptHUDSquare(player, Lua_Overlay::Index(L, 1), color);
438 
439 	return 0;
440 }
441 
442 const luaL_Reg Lua_Overlay_Get[] = {
443 	{"clear", L_TableFunction<Lua_Overlay_Clear>},
444 	{"fill_icon", L_TableFunction<Lua_Overlay_Fill_Icon>},
445 	{0, 0}
446 };
447 
Lua_Overlay_Set_Icon(lua_State * L)448 static int Lua_Overlay_Set_Icon(lua_State *L)
449 {
450         int player = Lua_Overlay::PlayerIndex(L, 1);
451 	if (lua_isstring(L, 2))
452 	{
453 		SetScriptHUDIcon(player, Lua_Overlay::Index(L, 1), lua_tostring(L, 2), lua_rawlen(L, 2));
454 	}
455 	else
456 	{
457 		SetScriptHUDIcon(player, Lua_Overlay::Index(L, 1), 0, 0);
458 	}
459 
460 	return 0;
461 }
462 
Lua_Overlay_Set_Text(lua_State * L)463 static int Lua_Overlay_Set_Text(lua_State *L)
464 {
465         int player = Lua_Overlay::PlayerIndex(L, 1);
466 	const char *text = 0;
467 	if (lua_isstring(L, 2))
468 		text = lua_tostring(L, 2);
469 
470 	SetScriptHUDText(player, Lua_Overlay::Index(L, 1), text);
471 
472 	return 0;
473 }
474 
Lua_Overlay_Set_Text_Color(lua_State * L)475 static int Lua_Overlay_Set_Text_Color(lua_State *L)
476 {
477         int player = Lua_Overlay::PlayerIndex(L, 1);
478 	int color = Lua_OverlayColor::ToIndex(L, 2);
479 	SetScriptHUDColor(player, Lua_Overlay::Index(L, 1), color);
480 
481 	return 0;
482 }
483 
484 const luaL_Reg Lua_Overlay_Set[] = {
485 	{"color", Lua_Overlay_Set_Text_Color},
486 	{"icon", Lua_Overlay_Set_Icon},
487 	{"text", Lua_Overlay_Set_Text},
488 	{0, 0}
489 };
490 
491 char Lua_Overlays_Name[] = "overlays";
492 typedef L_Class<Lua_Overlays_Name> Lua_Overlays;
493 
Lua_Overlays_Get(lua_State * L)494 static int Lua_Overlays_Get(lua_State *L)
495 {
496 	if (lua_isnumber(L, 2))
497 	{
498 		int player_index = Lua_Overlays::Index(L, 1);
499 		int index = static_cast<int>(lua_tonumber(L, 2));
500 		if (Lua_Overlays::Valid(player_index) && index >= 0 && index < MAXIMUM_NUMBER_OF_SCRIPT_HUD_ELEMENTS)
501 		{
502 			Lua_Overlay::Push(L, player_index, index);
503 		}
504 		else
505 		{
506 			lua_pushnil(L);
507 		}
508 	}
509 	else
510 	{
511 		lua_pushnil(L);
512 	}
513 
514 	return 1;
515 }
516 
Lua_Overlays_Length(lua_State * L)517 static int Lua_Overlays_Length(lua_State *L)
518 {
519 	int player_index = Lua_Overlays::Index(L, 1);
520 	if (Lua_Overlays::Valid(player_index))
521 		lua_pushnumber(L, MAXIMUM_NUMBER_OF_SCRIPT_HUD_ELEMENTS);
522 	else
523 		lua_pushnumber(L, 0);
524 	return 1;
525 }
526 
527 const luaL_Reg Lua_Overlays_Metatable[] = {
528 	{"__index", Lua_Overlays_Get},
529 	{"__len", Lua_Overlays_Length},
530 	{0, 0}
531 };
532 
533 extern bool use_lua_compass[MAXIMUM_NUMBER_OF_NETWORK_PLAYERS];
534 extern world_point2d lua_compass_beacons[MAXIMUM_NUMBER_OF_NETWORK_PLAYERS];
535 extern short lua_compass_states[MAXIMUM_NUMBER_OF_NETWORK_PLAYERS];
536 
537 char Lua_Player_Compass_Name[] = "player_compass";
538 typedef L_Class<Lua_Player_Compass_Name> Lua_Player_Compass;
539 
540 template<short state>
Lua_Player_Compass_All(lua_State * L)541 int Lua_Player_Compass_All(lua_State *L)
542 {
543 	int player_index = Lua_Player_Compass::Index(L, 1);
544 	lua_compass_states[player_index] = state;
545 	return 0;
546 }
547 
Lua_Player_Compass_Get_Lua(lua_State * L)548 static int Lua_Player_Compass_Get_Lua(lua_State *L)
549 {
550 	int player_index = Lua_Player_Compass::Index(L, 1);
551 	lua_pushboolean(L, use_lua_compass[player_index]);
552 	return 1;
553 }
554 
555 template<short state>
Lua_Player_Compass_Get_State(lua_State * L)556 static int Lua_Player_Compass_Get_State(lua_State *L)
557 {
558 	int player_index = Lua_Player_Compass::Index(L, 1);
559 	lua_pushboolean(L, lua_compass_states[player_index] & state);
560 	return 1;
561 }
562 
Lua_Player_Compass_Get_X(lua_State * L)563 static int Lua_Player_Compass_Get_X(lua_State *L)
564 {
565 	int player_index = Lua_Player_Compass::Index(L, 1);
566 	lua_pushnumber(L, static_cast<double>(lua_compass_beacons[player_index].x / WORLD_ONE));
567 	return 1;
568 }
569 
Lua_Player_Compass_Get_Y(lua_State * L)570 static int Lua_Player_Compass_Get_Y(lua_State *L)
571 {
572 	int player_index = Lua_Player_Compass::Index(L, 1);
573 	lua_pushnumber(L, static_cast<double>(lua_compass_beacons[player_index].y / WORLD_ONE));
574 	return 1;
575 }
576 
577 const luaL_Reg Lua_Player_Compass_Get[] = {
578 	{"all_off", L_TableFunction<Lua_Player_Compass_All<_network_compass_all_off> >},
579 	{"all_on", L_TableFunction<Lua_Player_Compass_All<_network_compass_all_on> >},
580 	{"beacon", Lua_Player_Compass_Get_State<_network_compass_use_beacon>},
581 	{"lua", Lua_Player_Compass_Get_Lua},
582 	{"ne", Lua_Player_Compass_Get_State<_network_compass_ne>},
583 	{"northeast", Lua_Player_Compass_Get_State<_network_compass_ne>},
584 	{"northwest", Lua_Player_Compass_Get_State<_network_compass_nw>},
585 	{"nw", Lua_Player_Compass_Get_State<_network_compass_nw>},
586 	{"se", Lua_Player_Compass_Get_State<_network_compass_se>},
587 	{"southeast", Lua_Player_Compass_Get_State<_network_compass_se>},
588 	{"southwest", Lua_Player_Compass_Get_State<_network_compass_sw>},
589 	{"sw", Lua_Player_Compass_Get_State<_network_compass_sw>},
590 	{"x", Lua_Player_Compass_Get_X},
591 	{"y", Lua_Player_Compass_Get_Y},
592 	{0, 0}
593 };
594 
Lua_Player_Compass_Set_Lua(lua_State * L)595 static int Lua_Player_Compass_Set_Lua(lua_State *L)
596 {
597 	if (!lua_isboolean(L, 2))
598 		return luaL_error(L, "lua: incorrect argument type");
599 
600 	int player_index = Lua_Player_Compass::Index(L, 1);
601 	use_lua_compass[player_index] = lua_toboolean(L, 2);
602 	return 0;
603 }
604 
605 template<short state>
Lua_Player_Compass_Set_State(lua_State * L)606 static int Lua_Player_Compass_Set_State(lua_State *L)
607 {
608 	if (!lua_isboolean(L, 2))
609 		return luaL_error(L, "compass: incorrect argument type");
610 
611 	int player_index = Lua_Player_Compass::Index(L, 1);
612 	if (lua_toboolean(L, 2))
613 	{
614 		lua_compass_states[player_index] |= state;
615 	}
616 	else
617 	{
618 		lua_compass_states[player_index] &= ~state;
619 	}
620 
621 	return 0;
622 }
623 
Lua_Player_Compass_Set_X(lua_State * L)624 static int Lua_Player_Compass_Set_X(lua_State *L)
625 {
626 	if (!lua_isnumber(L, 2))
627 		return luaL_error(L, "x: incorrect argument type");
628 
629 	int player_index = Lua_Player_Compass::Index(L, 1);
630 	lua_compass_beacons[player_index].x = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
631 	return 0;
632 }
633 
Lua_Player_Compass_Set_Y(lua_State * L)634 static int Lua_Player_Compass_Set_Y(lua_State *L)
635 {
636 	if (!lua_isnumber(L, 2))
637 		return luaL_error(L, "y: incorrect argument type");
638 
639 	int player_index = Lua_Player_Compass::Index(L, 1);
640 	lua_compass_beacons[player_index].y = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
641 	return 0;
642 }
643 
644 const luaL_Reg Lua_Player_Compass_Set[] = {
645 	{"beacon", Lua_Player_Compass_Set_State<_network_compass_use_beacon>},
646 	{"lua", Lua_Player_Compass_Set_Lua},
647 	{"ne", Lua_Player_Compass_Set_State<_network_compass_ne>},
648 	{"northeast", Lua_Player_Compass_Set_State<_network_compass_ne>},
649 	{"northwest", Lua_Player_Compass_Set_State<_network_compass_nw>},
650 	{"nw", Lua_Player_Compass_Set_State<_network_compass_nw>},
651 	{"se", Lua_Player_Compass_Set_State<_network_compass_se>},
652 	{"southeast", Lua_Player_Compass_Set_State<_network_compass_se>},
653 	{"southwest", Lua_Player_Compass_Set_State<_network_compass_sw>},
654 	{"sw", Lua_Player_Compass_Set_State<_network_compass_sw>},
655 	{"x", Lua_Player_Compass_Set_X},
656 	{"y", Lua_Player_Compass_Set_Y},
657 	{0, 0}
658 };
659 
660 char Lua_Player_Items_Name[] = "player_items";
661 typedef L_Class<Lua_Player_Items_Name> Lua_Player_Items;
662 
Lua_Player_Items_Get(lua_State * L)663 static int Lua_Player_Items_Get(lua_State *L)
664 {
665 	int player_index = Lua_Player_Items::Index(L, 1);
666 	int item_type = Lua_ItemType::ToIndex(L, 2);
667 
668 	player_data *player = get_player_data(player_index);
669 	int item_count = player->items[item_type];
670 	if (item_count == NONE) item_count = 0;
671 	lua_pushnumber(L, item_count);
672 	return 1;
673 }
674 
Lua_Player_Items_Length(lua_State * L)675 static int Lua_Player_Items_Length(lua_State *L)
676 {
677     lua_pushnumber(L, NUMBER_OF_DEFINED_ITEMS);
678     return 1;
679 }
680 
681 extern void destroy_players_ball(short player_index);
682 extern void select_next_best_weapon(short player_index);
683 
Lua_Player_Items_Set(lua_State * L)684 static int Lua_Player_Items_Set(lua_State *L)
685 {
686 	if (!lua_isnumber(L, 3))
687 		return luaL_error(L, "items: incorrect argument type");
688 
689 	int player_index = Lua_Player_Items::Index(L, 1);
690 	player_data *player = get_player_data(player_index);
691 	int item_type = Lua_ItemType::ToIndex(L, 2);
692 	int item_count = player->items[item_type];
693 	item_definition *definition = get_item_definition_external(item_type);
694 	int new_item_count = static_cast<int>(lua_tonumber(L, 3));
695 
696 	bool accounting = L_Get_Proper_Item_Accounting(L);
697 
698 	if (new_item_count < 0)
699 		luaL_error(L, "items: invalid item count");
700 
701 	if (item_count == NONE) item_count = 0;
702 	int real_difference = item_count - new_item_count;
703 	if (new_item_count == 0) new_item_count = NONE;
704 
705 	if (new_item_count < item_count)
706 	{
707 		if (definition->item_kind == _ball)
708 		{
709 			if (find_player_ball_color(player_index) != NONE)
710 				destroy_players_ball(player_index);
711 		}
712 		else
713 		{
714 			player->items[item_type] = new_item_count;
715 			mark_player_inventory_as_dirty(player_index, item_type);
716 			if (definition->item_kind == _weapon && player->items[item_type] == NONE)
717 			{
718 				select_next_best_weapon(player_index);
719 			}
720 
721 			if (accounting)
722 			{
723 				for (int i = 0; i < real_difference; ++i)
724 					object_was_just_destroyed(_object_is_item, item_type);
725 			}
726 		}
727 	}
728 	else if (new_item_count > item_count)
729 	{
730 		while (new_item_count-- > item_count)
731 		{
732 			if (try_and_add_player_item(player_index, item_type))
733 			{
734 				if (accounting)
735 					object_was_just_added(_object_is_item, item_type);
736 			}
737 		}
738 	}
739 
740 	return 0;
741 }
742 
743 const luaL_Reg Lua_Player_Items_Metatable[] = {
744 	{"__index", Lua_Player_Items_Get},
745 	{"__newindex", Lua_Player_Items_Set},
746 	{"__len", Lua_Player_Items_Length},
747 	{0, 0}
748 };
749 
750 char Lua_InternalVelocity_Name[] = "internal_velocity";
751 typedef L_Class<Lua_InternalVelocity_Name> Lua_InternalVelocity;
752 
Lua_InternalVelocity_Get_Forward(lua_State * L)753 static int Lua_InternalVelocity_Get_Forward(lua_State *L)
754 {
755 	int player_index = Lua_InternalVelocity::Index(L, 1);
756 	player_data *player = get_player_data(player_index);
757 	lua_pushnumber(L, (double) player->variables.velocity / FIXED_ONE);
758 	return 1;
759 }
760 
Lua_InternalVelocity_Get_Perpendicular(lua_State * L)761 static int Lua_InternalVelocity_Get_Perpendicular(lua_State *L)
762 {
763 	int player_index = Lua_InternalVelocity::Index(L, 1);
764 	player_data *player = get_player_data(player_index);
765 	lua_pushnumber(L, (double) player->variables.perpendicular_velocity / FIXED_ONE);
766 	return 1;
767 }
768 
769 const luaL_Reg Lua_InternalVelocity_Get[] = {
770 	{"forward", Lua_InternalVelocity_Get_Forward},
771 	{"perpendicular", Lua_InternalVelocity_Get_Perpendicular},
772 	{0, 0}
773 };
774 
775 char Lua_ExternalVelocity_Name[] = "external_velocity";
776 typedef L_Class<Lua_ExternalVelocity_Name> Lua_ExternalVelocity;
777 
Lua_ExternalVelocity_Get_I(lua_State * L)778 static int Lua_ExternalVelocity_Get_I(lua_State *L)
779 {
780 	lua_pushnumber(L, (double) get_player_data(Lua_ExternalVelocity::Index(L, 1))->variables.external_velocity.i / WORLD_ONE);
781 	return 1;
782 }
783 
Lua_ExternalVelocity_Get_J(lua_State * L)784 static int Lua_ExternalVelocity_Get_J(lua_State *L)
785 {
786 	lua_pushnumber(L, (double) get_player_data(Lua_ExternalVelocity::Index(L, 1))->variables.external_velocity.j / WORLD_ONE);
787 	return 1;
788 }
789 
Lua_ExternalVelocity_Get_K(lua_State * L)790 static int Lua_ExternalVelocity_Get_K(lua_State *L)
791 {
792 	lua_pushnumber(L, (double) get_player_data(Lua_ExternalVelocity::Index(L, 1))->variables.external_velocity.k / WORLD_ONE);
793 	return 1;
794 }
795 
796 const luaL_Reg Lua_ExternalVelocity_Get[] = {
797 	{"i", Lua_ExternalVelocity_Get_I},
798 	{"j", Lua_ExternalVelocity_Get_J},
799 	{"k", Lua_ExternalVelocity_Get_K},
800 	{"x", Lua_ExternalVelocity_Get_I},
801 	{"y", Lua_ExternalVelocity_Get_J},
802 	{"z", Lua_ExternalVelocity_Get_K},
803 	{0, 0}
804 };
805 
Lua_ExternalVelocity_Set_I(lua_State * L)806 static int Lua_ExternalVelocity_Set_I(lua_State *L)
807 {
808 	if (!lua_isnumber(L, 2))
809 		return luaL_error(L, "i: incorrect argument type");
810 
811 	int raw_velocity = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
812 	get_player_data(Lua_ExternalVelocity::Index(L, 1))->variables.external_velocity.i = raw_velocity;
813 	return 0;
814 }
815 
Lua_ExternalVelocity_Set_J(lua_State * L)816 static int Lua_ExternalVelocity_Set_J(lua_State *L)
817 {
818 	if (!lua_isnumber(L, 2))
819 		return luaL_error(L, "j: incorrect argument type");
820 
821 	int raw_velocity = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
822 	get_player_data(Lua_ExternalVelocity::Index(L, 1))->variables.external_velocity.j = raw_velocity;
823 	return 0;
824 }
825 
Lua_ExternalVelocity_Set_K(lua_State * L)826 static int Lua_ExternalVelocity_Set_K(lua_State *L)
827 {
828 	if (!lua_isnumber(L, 2))
829 		return luaL_error(L, "k: incorrect argument type");
830 
831 	int raw_velocity = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
832 	get_player_data(Lua_ExternalVelocity::Index(L, 1))->variables.external_velocity.k = raw_velocity;
833 	return 0;
834 }
835 
836 const luaL_Reg Lua_ExternalVelocity_Set[] = {
837 	{"i", Lua_ExternalVelocity_Set_I},
838 	{"j", Lua_ExternalVelocity_Set_J},
839 	{"k", Lua_ExternalVelocity_Set_K},
840 	{"x", Lua_ExternalVelocity_Set_I},
841 	{"y", Lua_ExternalVelocity_Set_J},
842 	{"z", Lua_ExternalVelocity_Set_K},
843 	{0, 0}
844 };
845 
846 char Lua_FadeType_Name[] = "fade_type";
847 typedef L_Enum<Lua_FadeType_Name> Lua_FadeType;
848 
849 char Lua_FadeTypes_Name[] = "FadeTypes";
850 typedef L_EnumContainer<Lua_FadeTypes_Name, Lua_FadeType> Lua_FadeTypes;
851 
852 const int MAX_TEXTURE_PALETTE_SIZE = 256;
853 struct lua_texture {
854     shape_descriptor shape;
855     short type;
856 };
857 typedef struct lua_texture lua_texture;
858 static std::vector<lua_texture> lua_texture_palette;
859 static int lua_texture_palette_selected = -1;
860 
LuaTexturePaletteClear()861 void LuaTexturePaletteClear() {
862 	lua_texture_palette.clear();
863 }
864 
LuaTexturePaletteSize()865 int LuaTexturePaletteSize() {
866 	return lua_texture_palette.size();
867 }
868 
LuaTexturePaletteTexture(size_t index)869 shape_descriptor LuaTexturePaletteTexture(size_t index)
870 {
871 	if (index < lua_texture_palette.size())
872 		return lua_texture_palette[index].shape;
873 	else
874 		return UNONE;
875 }
876 
LuaTexturePaletteTextureType(size_t index)877 short LuaTexturePaletteTextureType(size_t index)
878 {
879 	if (index < lua_texture_palette.size())
880 		return lua_texture_palette[index].type;
881 	else
882 		return 0;
883 }
884 
LuaTexturePaletteSelected()885 int LuaTexturePaletteSelected()
886 {
887 	return lua_texture_palette_selected;
888 }
889 
890 char Lua_Texture_Palette_Slot_Name[] = "texture_palette_slot";
891 typedef PlayerSubtable<Lua_Texture_Palette_Slot_Name> Lua_Texture_Palette_Slot;
892 
Lua_Texture_Palette_Slot_Clear(lua_State * L)893 int Lua_Texture_Palette_Slot_Clear(lua_State *L)
894 {
895 	int player_index = Lua_Texture_Palette_Slot::PlayerIndex(L, 1);
896 	if (player_index != local_player_index)
897 		return 0;
898 
899     lua_texture blank = { UNONE, 0 };
900 	lua_texture_palette[Lua_Texture_Palette_Slot::Index(L, 1)] = blank;
901 	return 0;
902 }
903 
Lua_Texture_Palette_Slot_Get_Collection(lua_State * L)904 static int Lua_Texture_Palette_Slot_Get_Collection(lua_State *L)
905 {
906 	int player_index = Lua_Texture_Palette_Slot::PlayerIndex(L, 1);
907 	if (player_index != local_player_index)
908 		return 0;
909 
910 	int index = Lua_Texture_Palette_Slot::Index(L, 1);
911 	if (lua_texture_palette[index].shape == UNONE)
912 		return 0;
913 
914 	lua_pushnumber(L, GET_COLLECTION(GET_DESCRIPTOR_COLLECTION(lua_texture_palette[index].shape)));
915 	return 1;
916 }
917 
Lua_Texture_Palette_Slot_Get_Texture(lua_State * L)918 static int Lua_Texture_Palette_Slot_Get_Texture(lua_State *L)
919 {
920 	int player_index = Lua_Texture_Palette_Slot::PlayerIndex(L, 1);
921 	if (player_index != local_player_index)
922 		return 0;
923 
924 	int index = Lua_Texture_Palette_Slot::Index(L, 1);
925 	if (lua_texture_palette[index].shape == UNONE)
926 		return 0;
927 
928 	lua_pushnumber(L, GET_DESCRIPTOR_SHAPE(lua_texture_palette[index].shape));
929 	return 1;
930 }
931 
Lua_Texture_Palette_Slot_Get_Type(lua_State * L)932 static int Lua_Texture_Palette_Slot_Get_Type(lua_State *L)
933 {
934 	int player_index = Lua_Texture_Palette_Slot::PlayerIndex(L, 1);
935 	if (player_index != local_player_index)
936 		return 0;
937 
938 	int index = Lua_Texture_Palette_Slot::Index(L, 1);
939 	if (lua_texture_palette[index].shape == UNONE)
940 		return 0;
941 
942 	lua_pushnumber(L, lua_texture_palette[index].type);
943 	return 1;
944 }
945 
946 const luaL_Reg Lua_Texture_Palette_Slot_Get[] = {
947 	{"clear", L_TableFunction<Lua_Texture_Palette_Slot_Clear>},
948 	{"collection", Lua_Texture_Palette_Slot_Get_Collection},
949 	{"texture_index", Lua_Texture_Palette_Slot_Get_Texture},
950     {"type", Lua_Texture_Palette_Slot_Get_Type},
951 	{0, 0}
952 };
953 
Lua_Texture_Palette_Slot_Set_Collection(lua_State * L)954 static int Lua_Texture_Palette_Slot_Set_Collection(lua_State *L)
955 {
956 	int player_index = Lua_Texture_Palette_Slot::PlayerIndex(L, 1);
957 	if (player_index != local_player_index)
958 		return 0;
959 
960 	int16 index = Lua_Texture_Palette_Slot::Index(L, 1);
961 	short collection_index = Lua_Collection::ToIndex(L, 2);
962 
963 	lua_texture_palette[index].shape = BUILD_DESCRIPTOR(collection_index, GET_DESCRIPTOR_SHAPE(lua_texture_palette[index].shape));
964 	return 0;
965 }
966 
Lua_Texture_Palette_Slot_Set_Texture(lua_State * L)967 static int Lua_Texture_Palette_Slot_Set_Texture(lua_State *L)
968 {
969 	int player_index = Lua_Texture_Palette_Slot::PlayerIndex(L, 1);
970 	if (player_index != local_player_index)
971 		return 0;
972 
973 	if (!lua_isnumber(L, 2))
974 		return luaL_error(L, "texture_index: incorrect argument type");
975 
976 	int16 index = Lua_Texture_Palette_Slot::Index(L, 1);
977 	short shape_index = static_cast<short>(lua_tonumber(L, 2));
978 	if (shape_index < 0 || shape_index >= MAXIMUM_SHAPES_PER_COLLECTION)
979 		return luaL_error(L, "texture_index: invalid texture index");
980 
981 	lua_texture_palette[index].shape = BUILD_DESCRIPTOR(GET_DESCRIPTOR_COLLECTION(lua_texture_palette[index].shape), shape_index);
982 	return 0;
983 }
984 
Lua_Texture_Palette_Slot_Set_Type(lua_State * L)985 static int Lua_Texture_Palette_Slot_Set_Type(lua_State *L)
986 {
987 	int player_index = Lua_Texture_Palette_Slot::PlayerIndex(L, 1);
988 	if (player_index != local_player_index)
989 		return 0;
990 
991 	int16 index = Lua_Texture_Palette_Slot::Index(L, 1);
992 	short texture_type = Lua_TextureType::ToIndex(L, 2);
993 
994 	lua_texture_palette[index].type = texture_type;
995 	return 0;
996 }
997 
998 
999 const luaL_Reg Lua_Texture_Palette_Slot_Set[] = {
1000 	{"collection", Lua_Texture_Palette_Slot_Set_Collection},
1001 	{"texture_index", Lua_Texture_Palette_Slot_Set_Texture},
1002     {"type", Lua_Texture_Palette_Slot_Set_Type},
1003 	{0, 0}
1004 };
1005 
1006 char Lua_Texture_Palette_Slots_Name[] = "texture_palette_slots";
1007 typedef L_Class<Lua_Texture_Palette_Slots_Name> Lua_Texture_Palette_Slots;
1008 
Lua_Texture_Palette_Slots_Get(lua_State * L)1009 static int Lua_Texture_Palette_Slots_Get(lua_State *L)
1010 {
1011 	if (lua_isnumber(L, 2))
1012 	{
1013 		int player_index = Lua_Texture_Palette_Slots::Index(L, 1);
1014 		int index = static_cast<int>(lua_tonumber(L, 2));
1015 		if (Lua_Texture_Palette_Slots::Valid(player_index) && index >= 0 && index < lua_texture_palette.size())
1016 		{
1017 			Lua_Texture_Palette_Slot::Push(L, player_index, index);
1018 		}
1019 		else
1020 		{
1021 			lua_pushnil(L);
1022 		}
1023 	}
1024 	else
1025 	{
1026 		lua_pushnil(L);
1027 	}
1028 
1029 	return 1;
1030 }
1031 
Lua_Texture_Palette_Slots_Length(lua_State * L)1032 static int Lua_Texture_Palette_Slots_Length(lua_State *L)
1033 {
1034 	int player_index = Lua_Texture_Palette_Slots::Index(L, 1);
1035 	if (player_index != local_player_index)
1036 		return 0;
1037 
1038 	lua_pushnumber(L, lua_texture_palette.size());
1039 	return 1;
1040 }
1041 
1042 const luaL_Reg Lua_Texture_Palette_Slots_Metatable[] = {
1043 	{"__index", Lua_Texture_Palette_Slots_Get},
1044 	{"__len", Lua_Texture_Palette_Slots_Length},
1045 	{0, 0}
1046 };
1047 
1048 char Lua_Texture_Palette_Name[] = "texture_palette";
1049 typedef L_Class<Lua_Texture_Palette_Name> Lua_Texture_Palette;
1050 
Lua_Texture_Palette_Get_Selected(lua_State * L)1051 static int Lua_Texture_Palette_Get_Selected(lua_State *L)
1052 {
1053 	int player_index = Lua_Texture_Palette::Index(L, 1);
1054 	if (player_index != local_player_index)
1055 		return 0;
1056 
1057 	if (lua_texture_palette_selected == -1)
1058 		return 0;
1059 
1060 	lua_pushnumber(L, lua_texture_palette_selected);
1061 	return 1;
1062 }
1063 
Lua_Texture_Palette_Get_Size(lua_State * L)1064 static int Lua_Texture_Palette_Get_Size(lua_State *L)
1065 {
1066 	int player_index = Lua_Texture_Palette::Index(L, 1);
1067 	if (player_index != local_player_index)
1068 		return 0;
1069 
1070 	lua_pushnumber(L, lua_texture_palette.size());
1071 	return 1;
1072 }
1073 
Lua_Texture_Palette_Get_Slots(lua_State * L)1074 static int Lua_Texture_Palette_Get_Slots(lua_State *L)
1075 {
1076 	Lua_Texture_Palette_Slots::Push(L, Lua_Texture_Palette::Index(L, 1));
1077 	return 1;
1078 }
1079 
1080 const luaL_Reg Lua_Texture_Palette_Get[] = {
1081 	{"highlight", Lua_Texture_Palette_Get_Selected},
1082 	{"size", Lua_Texture_Palette_Get_Size},
1083 	{"slots", Lua_Texture_Palette_Get_Slots},
1084 	{0, 0}
1085 };
1086 
1087 extern void draw_panels();
1088 
Lua_Texture_Palette_Set_Selected(lua_State * L)1089 static int Lua_Texture_Palette_Set_Selected(lua_State *L)
1090 {
1091 	int player_index = Lua_Texture_Palette::Index(L, 1);
1092 	if (player_index != local_player_index)
1093 		return 0;
1094 
1095 	if (lua_isnil(L, 2))
1096 		lua_texture_palette_selected = -1;
1097 	else if (lua_isnumber(L, 2))
1098 	{
1099 		int selected = static_cast<int>(lua_tonumber(L, 2));
1100 		if (selected < -1 || selected > lua_texture_palette.size())
1101 			return luaL_error(L, "highlight: invalid slot");
1102 
1103 		lua_texture_palette_selected = selected;
1104 		draw_panels();
1105 	}
1106 	else
1107 		return luaL_error(L, "highlight: incorrect argument type");
1108 
1109 	return 0;
1110 }
1111 
1112 
Lua_Texture_Palette_Set_Size(lua_State * L)1113 static int Lua_Texture_Palette_Set_Size(lua_State *L)
1114 {
1115 	int player_index = Lua_Texture_Palette::Index(L, 1);
1116 	if (player_index != local_player_index)
1117 		return 0;
1118 
1119 	if (!lua_isnumber(L, 2))
1120 		return luaL_error(L, "size: incorrect argument type");
1121 
1122 	size_t size = static_cast<size_t>(lua_tonumber(L, 2));
1123 	if (size > MAX_TEXTURE_PALETTE_SIZE)
1124 		return luaL_error(L, "size: Its really big");
1125 
1126     lua_texture blank = { UNONE, 0 };
1127 	lua_texture_palette.resize(size, blank);
1128 	if (lua_texture_palette_selected >= lua_texture_palette.size())
1129 		lua_texture_palette_selected = -1;
1130 
1131 	draw_panels();
1132 	return 0;
1133 }
1134 
1135 const luaL_Reg Lua_Texture_Palette_Set[] = {
1136 	{"highlight", Lua_Texture_Palette_Set_Selected},
1137 	{"size", Lua_Texture_Palette_Set_Size},
1138 	{0, 0}
1139 };
1140 
1141 char Lua_WeaponType_Name[] = "weapon_type";
1142 typedef L_Enum<Lua_WeaponType_Name> Lua_WeaponType;
1143 
1144 char Lua_WeaponTypes_Name[] = "WeaponTypes";
1145 typedef L_EnumContainer<Lua_WeaponTypes_Name, Lua_WeaponType> Lua_WeaponTypes;
1146 
1147 char Lua_Player_Weapon_Trigger_Name[] = "player_weapon_trigger";
1148 class Lua_Player_Weapon_Trigger : public PlayerSubtable<Lua_Player_Weapon_Trigger_Name>
1149 {
1150 public:
1151 	int16 m_weapon_index;
1152 
1153 	static Lua_Player_Weapon_Trigger *Push(lua_State *L, int16 player_index, int16 weapon_index, int16 index);
1154 	static int16 WeaponIndex(lua_State *L, int index);
1155 };
1156 
Push(lua_State * L,int16 player_index,int16 weapon_index,int16 index)1157 Lua_Player_Weapon_Trigger *Lua_Player_Weapon_Trigger::Push(lua_State *L, int16 player_index, int16 weapon_index, int16 index)
1158 {
1159 	Lua_Player_Weapon_Trigger *t = PlayerSubtable::Push<Lua_Player_Weapon_Trigger>(L, player_index, index);
1160 	if (t)
1161 	{
1162 		t->m_weapon_index = weapon_index;
1163 	}
1164 
1165 	return t;
1166 }
1167 
WeaponIndex(lua_State * L,int index)1168 int16 Lua_Player_Weapon_Trigger::WeaponIndex(lua_State *L, int index)
1169 {
1170 	Lua_Player_Weapon_Trigger *t = static_cast<Lua_Player_Weapon_Trigger*>(Instance(L, index));
1171 	if (!t) luaL_typerror(L, index, Lua_Player_Weapon_Trigger_Name);
1172 	return t->m_weapon_index;
1173 }
1174 
Lua_Player_Weapon_Trigger_Get_Rounds(lua_State * L)1175 static int Lua_Player_Weapon_Trigger_Get_Rounds(lua_State *L)
1176 {
1177 	short rounds = get_player_weapon_ammo_count(
1178 		Lua_Player_Weapon_Trigger::PlayerIndex(L, 1),
1179 		Lua_Player_Weapon_Trigger::WeaponIndex(L, 1),
1180 		Lua_Player_Weapon_Trigger::Index(L, 1));
1181 	lua_pushnumber(L, rounds);
1182 	return 1;
1183 }
1184 
1185 const luaL_Reg Lua_Player_Weapon_Trigger_Get[] = {
1186 	{"rounds", Lua_Player_Weapon_Trigger_Get_Rounds},
1187 	{0, 0}
1188 };
1189 
1190 char Lua_Player_Weapon_Name[] = "player_weapon";
1191 typedef PlayerSubtable<Lua_Player_Weapon_Name> Lua_Player_Weapon;
1192 
1193 template<int trigger>
get_weapon_trigger(lua_State * L)1194 static int get_weapon_trigger(lua_State *L)
1195 {
1196 	Lua_Player_Weapon_Trigger::Push(L, Lua_Player_Weapon::PlayerIndex(L, 1), Lua_Player_Weapon::Index(L, 1), trigger);
1197 	return 1;
1198 }
1199 
Lua_Player_Weapon_Get_Type(lua_State * L)1200 static int Lua_Player_Weapon_Get_Type(lua_State *L)
1201 {
1202 	Lua_WeaponType::Push(L, Lua_Player_Weapon::Index(L, 1));
1203 	return 1;
1204 }
1205 
1206 extern bool ready_weapon(short player_index, short weapon_index);
1207 
Lua_Player_Weapon_Select(lua_State * L)1208 int Lua_Player_Weapon_Select(lua_State *L)
1209 {
1210 	ready_weapon(Lua_Player_Weapon::PlayerIndex(L, 1), Lua_Player_Weapon::Index(L, 1));
1211 	return 0;
1212 }
1213 
1214 const luaL_Reg Lua_Player_Weapon_Get[] = {
1215 	{"primary", get_weapon_trigger<_primary_weapon>},
1216 	{"secondary", get_weapon_trigger<_secondary_weapon>},
1217 	{"select", L_TableFunction<Lua_Player_Weapon_Select>},
1218 	{"type", Lua_Player_Weapon_Get_Type},
1219 	{0, 0}
1220 };
1221 
1222 extern player_weapon_data *get_player_weapon_data(const short player_index);
1223 extern bool player_has_valid_weapon(short player_index);
1224 
1225 char Lua_Player_Weapons_Name[] = "player_weapons";
1226 typedef L_Class<Lua_Player_Weapons_Name> Lua_Player_Weapons;
1227 
1228 extern bool can_wield_weapons[MAXIMUM_NUMBER_OF_NETWORK_PLAYERS];
1229 
Lua_Player_Weapons_Get(lua_State * L)1230 static int Lua_Player_Weapons_Get(lua_State *L)
1231 {
1232 	int player_index = Lua_Player_Weapons::Index(L, 1);
1233 	bool string_arg = lua_isstring(L, 2) && !lua_isnumber(L, 2);
1234 	if (string_arg && (strcmp(lua_tostring(L, 2), "current") == 0))
1235 	{
1236 	    if (player_has_valid_weapon(player_index))
1237 	    {
1238 	        player_weapon_data *weapon_data = get_player_weapon_data(player_index);
1239 	        Lua_Player_Weapon::Push(L, player_index, weapon_data->current_weapon);
1240 	    }
1241 	    else
1242 	    {
1243 	        lua_pushnil(L);
1244 	    }
1245 	}
1246 	else if (string_arg && (strcmp(lua_tostring(L, 2), "desired") == 0))
1247 	{
1248 	    player_weapon_data *weapon_data = get_player_weapon_data(player_index);
1249 	    if (weapon_data->desired_weapon != NONE)
1250 	    {
1251 	        Lua_Player_Weapon::Push(L, player_index, weapon_data->desired_weapon);
1252 	    }
1253 	    else
1254 	    {
1255 	        lua_pushnil(L);
1256 	    }
1257 	}
1258 	else if (string_arg && (strcmp(lua_tostring(L, 2), "active") == 0))
1259 	{
1260 	    lua_pushboolean(L, can_wield_weapons[player_index]);
1261 	}
1262 	else
1263 	{
1264 		int index = Lua_WeaponType::ToIndex(L, 2);
1265 		Lua_Player_Weapon::Push(L, player_index, index);
1266 	}
1267 
1268 	return 1;
1269 }
1270 
Lua_Player_Weapons_Length(lua_State * L)1271 static int Lua_Player_Weapons_Length(lua_State *L)
1272 {
1273 	lua_pushnumber(L, MAXIMUM_NUMBER_OF_WEAPONS);
1274 	return 1;
1275 }
1276 
Lua_Player_Weapons_Set(lua_State * L)1277 static int Lua_Player_Weapons_Set(lua_State *L)
1278 {
1279 	if (lua_isstring(L, 2) && strcmp(lua_tostring(L, 2), "active") == 0)
1280 	{
1281 		if (!lua_isboolean(L, 3))
1282 			return luaL_error(L, "can_wield: incorrect argument type");
1283 		can_wield_weapons[Lua_Player_Weapons::Index(L, 1)] = lua_toboolean(L, 3);
1284 		return 0;
1285 	}
1286 	else
1287 		return luaL_error(L, "no such index");
1288 }
1289 
1290 const luaL_Reg Lua_Player_Weapons_Metatable[] = {
1291 	{"__index", Lua_Player_Weapons_Get},
1292 	{"__newindex", Lua_Player_Weapons_Set},
1293 	{"__len", Lua_Player_Weapons_Length},
1294 	{0, 0}
1295 };
1296 
1297 char Lua_Player_Kills_Name[] = "player_kills";
1298 typedef L_Class<Lua_Player_Kills_Name> Lua_Player_Kills;
1299 
Lua_Player_Kills_Get(lua_State * L)1300 static int Lua_Player_Kills_Get(lua_State *L)
1301 {
1302 	int player_index = Lua_Player_Kills::Index(L, 1);
1303 	int slain_player_index = Lua_Player::Index(L, 2);
1304 
1305 	player_data *slain_player = get_player_data(slain_player_index);
1306 
1307 	lua_pushnumber(L, slain_player->damage_taken[player_index].kills);
1308 	return 1;
1309 }
1310 
Lua_Player_Kills_Length(lua_State * L)1311 static int Lua_Player_Kills_Length(lua_State *L)
1312 {
1313     lua_pushnumber(L, dynamic_world->player_count);
1314     return 1;
1315 }
1316 
Lua_Player_Kills_Set(lua_State * L)1317 static int Lua_Player_Kills_Set(lua_State *L)
1318 {
1319 	if (!lua_isnumber(L, 3))
1320 		return luaL_error(L, "kills: incorrect argument type");
1321 
1322 	int player_index = Lua_Player_Kills::Index(L, 1);
1323 	int slain_player_index = Lua_Player::Index(L, 2);
1324 	int kills = static_cast<int>(lua_tonumber(L, 3));
1325 
1326 	player_data *player = get_player_data(player_index);
1327 	player_data *slain_player = get_player_data(slain_player_index);
1328 
1329 	int kills_award = kills - slain_player->damage_taken[player_index].kills;
1330 	if (kills_award)
1331 	{
1332 		slain_player->damage_taken[player_index].kills += kills_award;
1333 		team_damage_taken[slain_player->team].kills += kills_award;
1334 
1335 		if (player_index != slain_player_index)
1336 		{
1337 			player->total_damage_given.kills += kills_award;
1338 			team_damage_given[player->team].kills += kills_award;
1339 		}
1340 		if (slain_player->team == player->team)
1341 		{
1342 			team_friendly_fire[slain_player->team].kills += kills_award;
1343 		}
1344 		mark_player_network_stats_as_dirty(current_player_index);
1345 	}
1346 	return 0;
1347 }
1348 
1349 const luaL_Reg Lua_Player_Kills_Metatable[] = {
1350 	{"__index", Lua_Player_Kills_Get},
1351 	{"__newindex", Lua_Player_Kills_Set},
1352 	{"__len", Lua_Player_Kills_Length},
1353 	{0, 0}
1354 };
1355 
1356 char Lua_PlayerColor_Name[] = "player_color";
1357 
1358 char Lua_PlayerColors_Name[] = "PlayerColors";
1359 
1360 char Lua_Player_Name[] = "player";
1361 
1362 // methods
1363 
1364 // accelerate(direction, velocity, vertical_velocity)
Lua_Player_Accelerate(lua_State * L)1365 int Lua_Player_Accelerate(lua_State *L)
1366 {
1367 	if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4))
1368 		return luaL_error(L, "accelerate: incorrect argument type");
1369 
1370 	player_data *player = get_player_data(Lua_Player::Index(L, 1));
1371 	double direction = static_cast<double>(lua_tonumber(L, 2));
1372 	double velocity = static_cast<double>(lua_tonumber(L, 3));
1373 	double vertical_velocity = static_cast<double>(lua_tonumber(L, 4));
1374 
1375 	accelerate_player(player->monster_index, static_cast<int>(vertical_velocity * WORLD_ONE), static_cast<int>(direction/AngleConvert), static_cast<int>(velocity * WORLD_ONE));
1376 	return 0;
1377 }
1378 
Lua_Player_Activate_Terminal(lua_State * L)1379 int Lua_Player_Activate_Terminal(lua_State *L)
1380 {
1381 	int16 text_index = NONE;
1382 	if (lua_isnumber(L, 2))
1383 		text_index = static_cast<int16>(lua_tonumber(L, 2));
1384 	else if (Lua_Terminal::Is(L, 2))
1385 		text_index = Lua_Terminal::Index(L, 2);
1386 	else
1387 		return luaL_error(L, "activate_terminal: invalid terminal index");
1388 
1389 	enter_computer_interface(Lua_Player::Index(L, 1), text_index, calculate_level_completion_state());
1390 	return 0;
1391 }
1392 
Lua_Player_Find_Action_Key_Target(lua_State * L)1393 int Lua_Player_Find_Action_Key_Target(lua_State *L)
1394 {
1395 	short target_type;
1396 	short object_index = find_action_key_target(Lua_Player::Index(L, 1), MAXIMUM_ACTIVATION_RANGE, &target_type, film_profile.find_action_key_target_has_side_effects);
1397 
1398 	if (object_index != NONE)
1399 	{
1400 		switch (target_type)
1401 		{
1402 		case _target_is_platform:
1403 			Lua_Platform::Push(L, object_index);
1404 			break;
1405 
1406 		case _target_is_control_panel:
1407 			Lua_Side::Push(L, object_index);
1408 			break;
1409 
1410 		default:
1411 			lua_pushnil(L);
1412 			break;
1413 		}
1414 	}
1415 	else
1416 	{
1417 		lua_pushnil(L);
1418 	}
1419 
1420 	return 1;
1421 }
1422 
1423 extern projectile_definition *get_projectile_definition(short type);
1424 
Lua_Player_Find_Target(lua_State * L)1425 int Lua_Player_Find_Target(lua_State *L)
1426 {
1427 	// find the origin of projectiles (don't move left/right)
1428 	player_data *player = get_player_data(Lua_Player::Index(L, 1));
1429 	world_point3d origin = player->camera_location;
1430 	world_point3d destination = origin;
1431 
1432 	translate_point3d(&destination, WORLD_ONE, player->facing, player->elevation);
1433 	short old_polygon = get_object_data(player->object_index)->polygon;
1434 	short new_polygon;
1435 	short obstruction_index;
1436 	short line_index;
1437 
1438 	projectile_definition *definition = get_projectile_definition(0);
1439 	bool was_pass_transparent = definition->flags & _usually_pass_transparent_side;
1440 	if (!was_pass_transparent)
1441 		definition->flags |= _usually_pass_transparent_side;
1442 
1443 	// preflight a projectile, 1 WU at a time (because of projectile speed bug)
1444 	uint16 flags = translate_projectile(0, &origin, old_polygon, &destination, &new_polygon, player->monster_index, &obstruction_index, &line_index, true, NONE);
1445 
1446 	while (!(flags & _projectile_hit))
1447 	{
1448 		origin = destination;
1449 		old_polygon = new_polygon;
1450 
1451 		translate_point3d(&destination, WORLD_ONE, player->facing, player->elevation);
1452 		flags = translate_projectile(0, &origin, old_polygon, &destination, &new_polygon, player->monster_index, &obstruction_index, &line_index, true, NONE);
1453 	}
1454 
1455 	if (!was_pass_transparent)
1456 		definition->flags &= ~_usually_pass_transparent_side;
1457 
1458 	if (flags & _projectile_hit_monster)
1459 	{
1460 		object_data *object = get_object_data(obstruction_index);
1461 		Lua_Monster::Push(L, object->permutation);
1462 	}
1463 	else if (flags & _projectile_hit_floor)
1464 	{
1465 		Lua_Polygon_Floor::Push(L, new_polygon);
1466 	}
1467 	else if (flags & _projectile_hit_media)
1468 	{
1469 		Lua_Polygon::Push(L, new_polygon);
1470 	}
1471 	else if (flags & _projectile_hit_scenery)
1472 	{
1473 		Lua_Scenery::Push(L, obstruction_index);
1474 	}
1475 	else if (obstruction_index != NONE)
1476 	{
1477 		Lua_Polygon_Ceiling::Push(L, new_polygon);
1478 	}
1479 	else
1480 	{
1481 		short side_index = find_adjacent_side(new_polygon, line_index);
1482 		Lua_Side::Push(L, side_index);
1483 	}
1484 
1485 	lua_pushnumber(L, (double) destination.x / WORLD_ONE);
1486 	lua_pushnumber(L, (double) destination.y / WORLD_ONE);
1487 	lua_pushnumber(L, (double) destination.z / WORLD_ONE);
1488 	Lua_Polygon::Push(L, new_polygon);
1489 
1490 	return 5;
1491 }
1492 
1493 
Lua_Player_Damage(lua_State * L)1494 int Lua_Player_Damage(lua_State *L)
1495 {
1496 	int args = lua_gettop(L);
1497 	if (!lua_isnumber(L, 2))
1498 		return luaL_error(L, "damage: incorrect argument type");
1499 
1500 	player_data *player = get_player_data(Lua_Player::Index(L, 1));
1501 	if (PLAYER_IS_DEAD(player) || PLAYER_IS_TOTALLY_DEAD(player))
1502 		return 0;
1503 
1504 	damage_definition damage;
1505 	damage.type = _damage_crushing;
1506 	damage.base = static_cast<int>(lua_tonumber(L, 2));
1507 	damage.random = 0;
1508 	damage.scale = FIXED_ONE;
1509 
1510 	if (args > 2)
1511 	{
1512 		damage.type = Lua_DamageType::ToIndex(L, 3);
1513 	}
1514 
1515 	damage_player(player->monster_index, NONE, NONE, &damage, NONE);
1516 	return 0;
1517 }
1518 
Lua_Player_Fade_Screen(lua_State * L)1519 int Lua_Player_Fade_Screen(lua_State *L)
1520 {
1521 	short player_index = Lua_Player::Index(L, 1);
1522 	if (player_index == local_player_index)
1523 	{
1524 		int fade_index = Lua_FadeType::ToIndex(L, 2);
1525 		start_fade(fade_index);
1526 	}
1527 	return 0;
1528 }
1529 
Lua_Player_Play_Sound(lua_State * L)1530 int Lua_Player_Play_Sound(lua_State *L)
1531 {
1532 	int args = lua_gettop(L);
1533 
1534 	int player_index = Lua_Player::Index(L, 1);
1535 	int sound_index = Lua_Sound::ToIndex(L, 2);
1536 	float pitch = 1.0;
1537 	if (args > 2)
1538 	{
1539 		if (lua_isnumber(L, 3))
1540 			pitch = static_cast<float>(lua_tonumber(L, 3));
1541 		else
1542 			return luaL_error(L, "play_sound: incorrect argument type");
1543 	}
1544 
1545 	if (local_player_index != player_index)
1546 		return 0;
1547 
1548 	SoundManager::instance()->PlaySound(sound_index, NULL, NONE, _fixed(FIXED_ONE * pitch));
1549 	return 0;
1550 }
1551 
1552 extern bool mute_lua;
1553 
Lua_Player_Print(lua_State * L)1554 int Lua_Player_Print(lua_State *L)
1555 {
1556 	if (mute_lua) return 0;
1557 
1558 	if (lua_gettop(L) != 2)
1559 		return luaL_error(L, "print: incorrect argument type");
1560 
1561 	int player_index = Lua_Player::Index(L, 1);
1562 	if (player_index == (IsScriptHUDNonlocal() ? current_player_index : local_player_index))
1563 	{
1564 		lua_getglobal(L, "tostring");
1565 		lua_insert(L, -2);
1566 		lua_pcall(L, 1, 1, 0);
1567 		if (lua_tostring(L, -1))
1568 		{
1569 			screen_printf("%s", lua_tostring(L, -1));
1570 		}
1571 		lua_pop(L, 1);
1572 	}
1573 
1574 	return 0;
1575 }
1576 
1577 extern struct physics_constants *get_physics_constants_for_model(short physics_model, uint32 action_flags);
1578 extern void instantiate_physics_variables(struct physics_constants *constants, struct physics_variables *variables, short player_index, bool first_time, bool take_action);
1579 
Lua_Player_Position(lua_State * L)1580 int Lua_Player_Position(lua_State *L)
1581 {
1582 	if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4))
1583 		return luaL_error(L, ("position: incorrect argument type"));
1584 
1585 	int polygon_index = 0;
1586 	if (lua_isnumber(L, 5))
1587 	{
1588 		polygon_index = static_cast<int>(lua_tonumber(L, 5));
1589 		if (!Lua_Polygon::Valid(polygon_index))
1590 			return luaL_error(L, ("position: invalid polygon index"));
1591 	}
1592 	else if (Lua_Polygon::Is(L, 5))
1593 	{
1594 		polygon_index = Lua_Polygon::Index(L, 5);
1595 	}
1596 	else
1597 		return luaL_error(L, ("position: incorrect argument type"));
1598 
1599 	int player_index = Lua_Player::Index(L, 1);
1600 	player_data *player = get_player_data(player_index);
1601 	object_data *object = get_object_data(player->object_index);
1602 
1603 	world_point3d location;
1604 	location.x = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
1605 	location.y = static_cast<int>(lua_tonumber(L, 3) * WORLD_ONE);
1606 	location.z = static_cast<int>(lua_tonumber(L, 4) * WORLD_ONE);
1607 
1608 	translate_map_object(player->object_index, &location, polygon_index);
1609 	player->variables.position.x = WORLD_TO_FIXED(object->location.x);
1610 	player->variables.position.y = WORLD_TO_FIXED(object->location.y);
1611 	player->variables.position.z = WORLD_TO_FIXED(object->location.z);
1612 
1613 	instantiate_physics_variables(get_physics_constants_for_model(static_world->physics_model, 0), &player->variables, player_index, false, false);
1614 	return 0;
1615 }
1616 
Lua_Player_Teleport(lua_State * L)1617 int Lua_Player_Teleport(lua_State *L)
1618 {
1619 	if (!lua_isnumber(L, 2) && !Lua_Polygon::Is(L, 2))
1620 		return luaL_error(L, "teleport(): incorrect argument type");
1621 
1622 	int destination = -1;
1623 	if (lua_isnumber(L, 2))
1624 		destination = static_cast<int>(lua_tonumber(L, 2));
1625 	else
1626 		destination = Lua_Polygon::Index(L, 2);
1627 
1628 	int player_index = Lua_Player::Index(L, 1);
1629 
1630 	player_data *player = get_player_data(player_index);
1631 	monster_data *monster = get_monster_data(player->monster_index);
1632 
1633 	SET_PLAYER_TELEPORTING_STATUS(player, true);
1634 	monster->action = _monster_is_teleporting;
1635 	player->teleporting_phase = 0;
1636 	player->delay_before_teleport = 0;
1637 
1638 	player->teleporting_destination = destination;
1639 	if (local_player_index == player_index)
1640 		start_teleporting_effect(true);
1641 	play_object_sound(player->object_index, Sound_TeleportOut());
1642 	return 0;
1643 }
1644 
Lua_Player_Teleport_To_Level(lua_State * L)1645 int Lua_Player_Teleport_To_Level(lua_State *L)
1646 {
1647 	if (!lua_isnumber(L, 2))
1648 		return luaL_error(L, "teleport_to_level(): incorrect argument type");
1649 
1650 	int level = static_cast<int>(lua_tonumber(L, 2));
1651 	int player_index = Lua_Player::Index(L, 1);
1652 
1653 	player_data *player = get_player_data(player_index);
1654 	monster_data *monster = get_monster_data(player->monster_index);
1655 
1656 	SET_PLAYER_TELEPORTING_STATUS(player, true);
1657 	monster->action = _monster_is_teleporting;
1658 	player->teleporting_phase = 0;
1659 	player->delay_before_teleport = 0;
1660 
1661 	player->teleporting_destination = -level - 1;
1662 	if (View_DoInterlevelTeleportOutEffects()) {
1663 		start_teleporting_effect(true);
1664 		play_object_sound(player->object_index, Sound_TeleportOut());
1665 	}
1666 	return 0;
1667 }
1668 
1669 extern short current_player_index;
1670 
Lua_Player_Get_Viewed_Player(lua_State * L)1671 int Lua_Player_Get_Viewed_Player(lua_State *L)
1672 {
1673 	int player_index = Lua_Player::Index(L, 1);
1674 	if (player_index != local_player_index)
1675 		return 0;
1676 	Lua_Player::Push(L, current_player_index);
1677 	return 1;
1678 }
1679 
Lua_Player_View_Player(lua_State * L)1680 int Lua_Player_View_Player(lua_State *L)
1681 {
1682 	int player_index = Lua_Player::Index(L, 1);
1683 	if (player_index != local_player_index)
1684 		return 0;
1685 
1686 	int view_player_index;
1687 	if (lua_isnumber(L, 2))
1688 	{
1689 		view_player_index = static_cast<int>(lua_tonumber(L, 2));
1690 		if (view_player_index < 0 || view_player_index >= dynamic_world->player_count)
1691 			return luaL_error(L, "view_player(): invalid player index");
1692 	}
1693 	else if (Lua_Player::Is(L, 2))
1694 		view_player_index = Lua_Player::Index(L, 2);
1695 	else
1696 		return luaL_error(L, "view_player(): incorrect argument type");
1697 
1698 	if (view_player_index != current_player_index)
1699 	{
1700 		set_current_player_index(view_player_index);
1701 		update_interface(NONE);
1702 		dirty_terminal_view(player_index);
1703 	}
1704 
1705 	return 0;
1706 
1707 }
1708 
1709 // get accessors
1710 
Lua_Player_Get_Action_Flags(lua_State * L)1711 static int Lua_Player_Get_Action_Flags(lua_State *L)
1712 {
1713 	Lua_Action_Flags::Push(L, Lua_Player::Index(L, 1));
1714 	return 1;
1715 }
1716 
Lua_Player_Get_Color(lua_State * L)1717 static int Lua_Player_Get_Color(lua_State *L)
1718 {
1719 	Lua_PlayerColor::Push(L, get_player_data(Lua_Player::Index(L, 1))->color);
1720 	return 1;
1721 }
1722 
Lua_Player_Get_Compass(lua_State * L)1723 static int Lua_Player_Get_Compass(lua_State *L)
1724 {
1725 	Lua_Player_Compass::Push(L, Lua_Player::Index(L, 1));
1726 	return 1;
1727 }
1728 
Lua_Player_Get_Crosshairs(lua_State * L)1729 static int Lua_Player_Get_Crosshairs(lua_State *L)
1730 {
1731 	Lua_Crosshairs::Push(L, Lua_Player::Index(L, 1));
1732 	return 1;
1733 }
1734 
Lua_Player_Get_Dead(lua_State * L)1735 static int Lua_Player_Get_Dead(lua_State *L)
1736 {
1737 	player_data *player = get_player_data(Lua_Player::Index(L, 1));
1738 	lua_pushboolean(L, (PLAYER_IS_DEAD(player) || PLAYER_IS_TOTALLY_DEAD(player)));
1739 	return 1;
1740 }
1741 
Lua_Player_Get_Deaths(lua_State * L)1742 static int Lua_Player_Get_Deaths(lua_State *L)
1743 {
1744 	player_data *player = get_player_data(Lua_Player::Index(L, 1));
1745 	lua_pushnumber(L, player->monster_damage_taken.kills);
1746 	return 1;
1747 }
1748 
Lua_Player_Get_Energy(lua_State * L)1749 static int Lua_Player_Get_Energy(lua_State *L)
1750 {
1751 	lua_pushnumber(L, get_player_data(Lua_Player::Index(L, 1))->suit_energy);
1752 	return 1;
1753 }
1754 
Lua_Player_Get_Elevation(lua_State * L)1755 static int Lua_Player_Get_Elevation(lua_State *L)
1756 {
1757 	double angle = FIXED_INTEGERAL_PART(get_player_data(Lua_Player::Index(L, 1))->variables.elevation) * AngleConvert;
1758 	lua_pushnumber(L, angle);
1759 	return 1;
1760 }
1761 
Lua_Player_Get_Direction(lua_State * L)1762 static int Lua_Player_Get_Direction(lua_State *L)
1763 {
1764 	double angle = FIXED_INTEGERAL_PART(get_player_data(Lua_Player::Index(L, 1))->variables.direction) * AngleConvert;
1765 	lua_pushnumber(L, angle);
1766 	return 1;
1767 }
1768 
Lua_Player_Get_Head_Direction(lua_State * L)1769 static int Lua_Player_Get_Head_Direction(lua_State *L)
1770 {
1771 	player_data *pdata = get_player_data(Lua_Player::Index(L, 1));
1772 	double angle = FIXED_INTEGERAL_PART(pdata->variables.direction + pdata->variables.head_direction) * AngleConvert;
1773 	if (angle >= 360.0) { angle -= 360.0; }
1774 	if (angle <    0.0) { angle += 360.0; }
1775 	lua_pushnumber(L, angle);
1776 	return 1;
1777 }
1778 
Lua_Player_Get_External_Velocity(lua_State * L)1779 static int Lua_Player_Get_External_Velocity(lua_State *L)
1780 {
1781 	Lua_ExternalVelocity::Push(L, Lua_Player::Index(L, 1));
1782 	return 1;
1783 }
1784 
Lua_Player_Get_Extravision_Duration(lua_State * L)1785 static int Lua_Player_Get_Extravision_Duration(lua_State *L)
1786 {
1787 	lua_pushnumber(L, get_player_data(Lua_Player::Index(L, 1))->extravision_duration);
1788 	return 1;
1789 }
1790 
1791 template<uint16 flag>
Lua_Player_Get_Flag(lua_State * L)1792 static int Lua_Player_Get_Flag(lua_State *L)
1793 {
1794 	player_data *player = get_player_data(Lua_Player::Index(L, 1));
1795 	lua_pushboolean(L, player->variables.flags & flag);
1796 	return 1;
1797 }
1798 
Lua_Player_Get_Infravision_Duration(lua_State * L)1799 static int Lua_Player_Get_Infravision_Duration(lua_State *L)
1800 {
1801 	lua_pushnumber(L, get_player_data(Lua_Player::Index(L, 1))->infravision_duration);
1802 	return 1;
1803 }
1804 
Lua_Player_Get_Internal_Velocity(lua_State * L)1805 static int Lua_Player_Get_Internal_Velocity(lua_State *L)
1806 {
1807 	Lua_InternalVelocity::Push(L, Lua_Player::Index(L, 1));
1808 	return 1;
1809 }
1810 
Lua_Player_Get_Invincibility_Duration(lua_State * L)1811 static int Lua_Player_Get_Invincibility_Duration(lua_State *L)
1812 {
1813 	lua_pushnumber(L, get_player_data(Lua_Player::Index(L, 1))->invincibility_duration);
1814 	return 1;
1815 }
1816 
Lua_Player_Get_Invisibility_Duration(lua_State * L)1817 static int Lua_Player_Get_Invisibility_Duration(lua_State *L)
1818 {
1819 	lua_pushnumber(L, get_player_data(Lua_Player::Index(L, 1))->invisibility_duration);
1820 	return 1;
1821 }
1822 
Lua_Player_Get_Items(lua_State * L)1823 static int Lua_Player_Get_Items(lua_State *L)
1824 {
1825 	Lua_Player_Items::Push(L, Lua_Player::Index(L, 1));
1826 	return 1;
1827 }
1828 
Lua_Player_Get_Kills(lua_State * L)1829 static int Lua_Player_Get_Kills(lua_State *L)
1830 {
1831 	Lua_Player_Kills::Push(L, Lua_Player::Index(L, 1));
1832 	return 1;
1833 }
1834 
Lua_Player_Get_Local(lua_State * L)1835 static int Lua_Player_Get_Local(lua_State *L)
1836 {
1837 	lua_pushboolean(L, Lua_Player::Index(L, 1) == local_player_index);
1838 	return 1;
1839 }
1840 
1841 extern bool MotionSensorActive;
1842 
Lua_Player_Get_Motion_Sensor(lua_State * L)1843 static int Lua_Player_Get_Motion_Sensor(lua_State *L)
1844 {
1845 	short player_index = Lua_Player::Index(L, 1);
1846 	if (player_index == local_player_index)
1847 	{
1848 		lua_pushboolean(L, MotionSensorActive);
1849 		return 1;
1850 	}
1851 	else
1852 	{
1853 		return 0;
1854 	}
1855 }
1856 
Lua_Player_Get_Monster(lua_State * L)1857 static int Lua_Player_Get_Monster(lua_State *L)
1858 {
1859 	Lua_Monster::Push(L, get_player_data(Lua_Player::Index(L, 1))->monster_index);
1860 	return 1;
1861 }
1862 
Lua_Player_Get_Name(lua_State * L)1863 static int Lua_Player_Get_Name(lua_State *L)
1864 {
1865 	lua_pushstring(L, get_player_data(Lua_Player::Index(L, 1))->name);
1866 	return 1;
1867 }
1868 
Lua_Player_Get_Netdead(lua_State * L)1869 static int Lua_Player_Get_Netdead(lua_State *L)
1870 {
1871 	lua_pushboolean(L, get_player_data(Lua_Player::Index(L, 1))->netdead);
1872 	return 1;
1873 }
1874 
Lua_Player_Get_Overlays(lua_State * L)1875 static int Lua_Player_Get_Overlays(lua_State *L)
1876 {
1877 	Lua_Overlays::Push(L, Lua_Player::Index(L, 1));
1878 	return 1;
1879 }
1880 
Lua_Player_Get_Oxygen(lua_State * L)1881 static int Lua_Player_Get_Oxygen(lua_State *L)
1882 {
1883 	lua_pushnumber(L, get_player_data(Lua_Player::Index(L, 1))->suit_oxygen);
1884 	return 1;
1885 }
1886 
Lua_Player_Get_Points(lua_State * L)1887 static int Lua_Player_Get_Points(lua_State *L)
1888 {
1889 	lua_pushnumber(L, get_player_data(Lua_Player::Index(L, 1))->netgame_parameters[0]);
1890 	return 1;
1891 }
1892 
Lua_Player_Get_Polygon(lua_State * L)1893 static int Lua_Player_Get_Polygon(lua_State *L)
1894 {
1895 	Lua_Polygon::Push(L, get_player_data(Lua_Player::Index(L, 1))->supporting_polygon_index);
1896 	return 1;
1897 }
1898 
Lua_Player_Get_Team(lua_State * L)1899 static int Lua_Player_Get_Team(lua_State *L)
1900 {
1901 	Lua_PlayerColor::Push(L, get_player_data(Lua_Player::Index(L, 1))->team);
1902 	return 1;
1903 }
1904 
Lua_Player_Get_Texture_Palette(lua_State * L)1905 static int Lua_Player_Get_Texture_Palette(lua_State *L)
1906 {
1907 	Lua_Texture_Palette::Push(L, Lua_Player::Index(L, 1));
1908 	return 1;
1909 }
1910 
Lua_Player_Get_Weapons(lua_State * L)1911 static int Lua_Player_Get_Weapons(lua_State *L)
1912 {
1913 	Lua_Player_Weapons::Push(L, Lua_Player::Index(L, 1));
1914 	return 1;
1915 }
1916 
Lua_Player_Get_X(lua_State * L)1917 static int Lua_Player_Get_X(lua_State *L)
1918 {
1919 	lua_pushnumber(L, (double) get_player_data(Lua_Player::Index(L, 1))->location.x / WORLD_ONE);
1920 	return 1;
1921 }
1922 
Lua_Player_Get_Y(lua_State * L)1923 static int Lua_Player_Get_Y(lua_State *L)
1924 {
1925 	lua_pushnumber(L, (double) get_player_data(Lua_Player::Index(L, 1))->location.y / WORLD_ONE);
1926 	return 1;
1927 }
1928 
Lua_Player_Get_Z(lua_State * L)1929 static int Lua_Player_Get_Z(lua_State *L)
1930 {
1931 	lua_pushnumber(L, (double) get_player_data(Lua_Player::Index(L, 1))->location.z / WORLD_ONE);
1932 	return 1;
1933 }
1934 
Lua_Player_Get_Zoom(lua_State * L)1935 static int Lua_Player_Get_Zoom(lua_State *L)
1936 {
1937 	short player_index = Lua_Player::Index(L, 1);
1938 	if (player_index == local_player_index)
1939 	{
1940 		lua_pushboolean(L, GetTunnelVision());
1941 		return 1;
1942 	}
1943 	else
1944 	{
1945 		return 0;
1946 	}
1947 }
1948 
1949 const luaL_Reg Lua_Player_Get[] = {
1950 	{"accelerate", L_TableFunction<Lua_Player_Accelerate>},
1951 	{"action_flags", Lua_Player_Get_Action_Flags},
1952 	{"activate_terminal", L_TableFunction<Lua_Player_Activate_Terminal>},
1953 	{"color", Lua_Player_Get_Color},
1954 	{"compass", Lua_Player_Get_Compass},
1955 	{"crosshairs", Lua_Player_Get_Crosshairs},
1956 	{"damage", L_TableFunction<Lua_Player_Damage>},
1957 	{"dead", Lua_Player_Get_Dead},
1958 	{"deaths", Lua_Player_Get_Deaths},
1959 	{"direction", Lua_Player_Get_Direction},
1960 	{"head_direction", Lua_Player_Get_Head_Direction},
1961 	{"disconnected", Lua_Player_Get_Netdead},
1962 	{"energy", Lua_Player_Get_Energy},
1963 	{"elevation", Lua_Player_Get_Elevation},
1964 	{"external_velocity", Lua_Player_Get_External_Velocity},
1965 	{"extravision_duration", Lua_Player_Get_Extravision_Duration},
1966 	{"feet_below_media", Lua_Player_Get_Flag<_FEET_BELOW_MEDIA_BIT>},
1967 	{"fade_screen", L_TableFunction<Lua_Player_Fade_Screen>},
1968 	{"find_action_key_target", L_TableFunction<Lua_Player_Find_Action_Key_Target>},
1969 	{"find_target", L_TableFunction<Lua_Player_Find_Target>},
1970 	{"head_below_media", Lua_Player_Get_Flag<_HEAD_BELOW_MEDIA_BIT>},
1971 	{"infravision_duration", Lua_Player_Get_Infravision_Duration},
1972 	{"internal_velocity", Lua_Player_Get_Internal_Velocity},
1973 	{"invincibility_duration", Lua_Player_Get_Invincibility_Duration},
1974 	{"invisibility_duration", Lua_Player_Get_Invisibility_Duration},
1975 	{"items", Lua_Player_Get_Items},
1976 	{"local_", Lua_Player_Get_Local},
1977 	{"juice", Lua_Player_Get_Energy},
1978 	{"kills", Lua_Player_Get_Kills},
1979 	{"life", Lua_Player_Get_Energy},
1980 	{"monster", Lua_Player_Get_Monster},
1981 	{"motion_sensor_active", Lua_Player_Get_Motion_Sensor},
1982 	{"name", Lua_Player_Get_Name},
1983 	{"overlays", Lua_Player_Get_Overlays},
1984 	{"oxygen", Lua_Player_Get_Oxygen},
1985 	{"pitch", Lua_Player_Get_Elevation},
1986 	{"print", L_TableFunction<Lua_Player_Print>},
1987 	{"play_sound", L_TableFunction<Lua_Player_Play_Sound>},
1988 	{"points", Lua_Player_Get_Points},
1989 	{"polygon", Lua_Player_Get_Polygon},
1990 	{"position", L_TableFunction<Lua_Player_Position>},
1991 	{"team", Lua_Player_Get_Team},
1992 	{"teleport", L_TableFunction<Lua_Player_Teleport>},
1993 	{"teleport_to_level", L_TableFunction<Lua_Player_Teleport_To_Level>},
1994 	{"texture_palette", Lua_Player_Get_Texture_Palette},
1995 	{"view_player", L_TableFunction<Lua_Player_View_Player>},
1996 	{"viewed_player", Lua_Player_Get_Viewed_Player},
1997 	{"weapons", Lua_Player_Get_Weapons},
1998 	{"x", Lua_Player_Get_X},
1999 	{"y", Lua_Player_Get_Y},
2000 	{"yaw", Lua_Player_Get_Direction},
2001 	{"z", Lua_Player_Get_Z},
2002 	{"zoom_active", Lua_Player_Get_Zoom},
2003 	{0, 0}
2004 };
2005 
2006 extern void mark_shield_display_as_dirty();
2007 
Lua_Player_Set_Color(lua_State * L)2008 static int Lua_Player_Set_Color(lua_State *L)
2009 {
2010 	int color = Lua_PlayerColor::ToIndex(L, 2);
2011 	get_player_data(Lua_Player::Index(L, 1))->color = color;
2012 
2013 	return 0;
2014 }
2015 
Lua_Player_Set_Deaths(lua_State * L)2016 static int Lua_Player_Set_Deaths(lua_State *L)
2017 {
2018 	if (!lua_isnumber(L, 2))
2019 		return luaL_error(L, "deaths: incorrect argument type");
2020 
2021 	player_data *player = get_player_data(Lua_Player::Index(L, 1));
2022 	int kills = static_cast<int>(lua_tonumber(L, 2));
2023 	if (player->monster_damage_taken.kills != kills)
2024 	{
2025 		team_monster_damage_taken[player->team].kills += (kills - player->monster_damage_taken.kills);
2026 		player->monster_damage_taken.kills = kills;
2027 		mark_player_network_stats_as_dirty(current_player_index);
2028 	}
2029 
2030 	return 0;
2031 }
2032 
Lua_Player_Set_Direction(lua_State * L)2033 static int Lua_Player_Set_Direction(lua_State *L)
2034 {
2035 	if (!lua_isnumber(L, 2))
2036 		return luaL_error(L, "direction: incorrect argument type");
2037 
2038 	double facing = static_cast<double>(lua_tonumber(L, 2));
2039 	int player_index = Lua_Player::Index(L, 1);
2040 	player_data *player = get_player_data(player_index);
2041 	player->variables.direction = INTEGER_TO_FIXED((int)(facing/AngleConvert));
2042 	instantiate_physics_variables(get_physics_constants_for_model(static_world->physics_model, 0), &player->variables, player_index, false, false);
2043 
2044 	// Lua control locks virtual aim to physical aim
2045 	if (player_index == local_player_index)
2046 		resync_virtual_aim();
2047 
2048 	return 0;
2049 }
2050 
Lua_Player_Set_Head_Direction(lua_State * L)2051 static int Lua_Player_Set_Head_Direction(lua_State *L)
2052 {
2053 	if (!lua_isnumber(L, 2))
2054 		return luaL_error(L, "head_direction: incorrect argument type");
2055 
2056 	double facing = static_cast<double>(lua_tonumber(L, 2));
2057 	int player_index = Lua_Player::Index(L, 1);
2058 	player_data *player = get_player_data(player_index);
2059 	player->variables.head_direction = INTEGER_TO_FIXED((int)(facing/AngleConvert)) - player->variables.direction;
2060 	while (player->variables.head_direction >= INTEGER_TO_FIXED(HALF_CIRCLE)) {
2061 		player->variables.head_direction -= INTEGER_TO_FIXED(FULL_CIRCLE);
2062 	}
2063 	while (player->variables.head_direction < -1*INTEGER_TO_FIXED(HALF_CIRCLE)) {
2064 		player->variables.head_direction += INTEGER_TO_FIXED(FULL_CIRCLE);
2065 	}
2066 	instantiate_physics_variables(get_physics_constants_for_model(static_world->physics_model, 0), &player->variables, player_index, false, false);
2067 
2068 	return 0;
2069 }
2070 
Lua_Player_Set_Elevation(lua_State * L)2071 static int Lua_Player_Set_Elevation(lua_State *L)
2072 {
2073 	if (!lua_isnumber(L, 2))
2074 		return luaL_error(L, "elevation: incorrect argument type");
2075 
2076 	double elevation = static_cast<double>(lua_tonumber(L, 2));
2077 	if (elevation > 180) elevation -= 360.0;
2078 	int player_index = Lua_Player::Index(L, 1);
2079 	player_data *player = get_player_data(player_index);
2080 	player->variables.elevation = INTEGER_TO_FIXED((int)(elevation/AngleConvert));
2081 	instantiate_physics_variables(get_physics_constants_for_model(static_world->physics_model, 0), &player->variables, player_index, false, false);
2082 
2083 	// Lua control locks virtual aim to physical aim
2084 	if (player_index == local_player_index)
2085 		resync_virtual_aim();
2086 
2087 	return 0;
2088 }
2089 
Lua_Player_Set_Infravision_Duration(lua_State * L)2090 static int Lua_Player_Set_Infravision_Duration(lua_State *L)
2091 {
2092 	if (!lua_isnumber(L, 2))
2093 		return luaL_error(L, "extravision: incorrect argument type");
2094 
2095 	player_data *player = get_player_data(Lua_Player::Index(L, 1));
2096 	player->infravision_duration = static_cast<int>(lua_tonumber(L, 2));
2097 	return 0;
2098 }
2099 
Lua_Player_Set_Invincibility_Duration(lua_State * L)2100 static int Lua_Player_Set_Invincibility_Duration(lua_State *L)
2101 {
2102 	if (!lua_isnumber(L, 2))
2103 		return luaL_error(L, "extravision: incorrect argument type");
2104 
2105 	player_data *player = get_player_data(Lua_Player::Index(L, 1));
2106 	player->invincibility_duration = static_cast<int>(lua_tonumber(L, 2));
2107 	return 0;
2108 }
2109 
Lua_Player_Set_Invisibility_Duration(lua_State * L)2110 static int Lua_Player_Set_Invisibility_Duration(lua_State *L)
2111 {
2112 	if (!lua_isnumber(L, 2))
2113 		return luaL_error(L, "extravision: incorrect argument type");
2114 
2115 	player_data *player = get_player_data(Lua_Player::Index(L, 1));
2116 	player->invisibility_duration = static_cast<int>(lua_tonumber(L, 2));
2117 	return 0;
2118 }
2119 
Lua_Player_Set_Energy(lua_State * L)2120 static int Lua_Player_Set_Energy(lua_State *L)
2121 {
2122 	if (!lua_isnumber(L, 2))
2123 		return luaL_error(L, "energy: incorrect argument type");
2124 
2125 	int energy = static_cast<int>(lua_tonumber(L, 2));
2126 	if (energy > 3 * PLAYER_MAXIMUM_SUIT_ENERGY)
2127 		energy = 3 * PLAYER_MAXIMUM_SUIT_ENERGY;
2128 
2129 	get_player_data(Lua_Player::Index(L, 1))->suit_energy = energy;
2130 	mark_shield_display_as_dirty();
2131 
2132 	return 0;
2133 }
2134 
Lua_Player_Set_Extravision_Duration(lua_State * L)2135 static int Lua_Player_Set_Extravision_Duration(lua_State *L)
2136 {
2137 	if (!lua_isnumber(L, 2))
2138 		return luaL_error(L, "extravision: incorrect argument type");
2139 
2140 	int player_index = Lua_Player::Index(L, 1);
2141 	player_data *player = get_player_data(player_index);
2142 	short extravision_duration = static_cast<short>(lua_tonumber(L, 2));
2143 	if ((player_index == local_player_index) && (extravision_duration == 0) != (player->extravision_duration == 0))
2144 	{
2145 		start_extravision_effect(extravision_duration);
2146 	}
2147 	player->extravision_duration = static_cast<int>(lua_tonumber(L, 2));
2148 	return 0;
2149 }
2150 
Lua_Player_Set_Motion_Sensor(lua_State * L)2151 static int Lua_Player_Set_Motion_Sensor(lua_State *L)
2152 {
2153 	short player_index = Lua_Player::Index(L, 1);
2154 	if (player_index == local_player_index)
2155 	{
2156 		if (!lua_isboolean(L, 2))
2157 			return luaL_error(L, "motion_sensor: incorrect argument type");
2158 		bool state = lua_toboolean(L, 2);
2159 		if (MotionSensorActive != state)
2160 		{
2161 			MotionSensorActive = lua_toboolean(L, 2);
2162 			draw_panels();
2163 		}
2164 	}
2165 
2166 	return 0;
2167 }
2168 
Lua_Player_Set_Oxygen(lua_State * L)2169 static int Lua_Player_Set_Oxygen(lua_State *L)
2170 {
2171 	if (!lua_isnumber(L, 2))
2172 		return luaL_error(L, "oxygen: incorrect argument type");
2173 
2174 	int oxygen = static_cast<int>(lua_tonumber(L, 2));
2175 	if (oxygen > PLAYER_MAXIMUM_SUIT_OXYGEN)
2176 		oxygen = PLAYER_MAXIMUM_SUIT_OXYGEN;
2177 
2178 	get_player_data(Lua_Player::Index(L, 1))->suit_oxygen = oxygen;
2179 	mark_shield_display_as_dirty();
2180 
2181 	return 0;
2182 }
2183 
Lua_Player_Set_Points(lua_State * L)2184 static int Lua_Player_Set_Points(lua_State *L)
2185 {
2186 	if (!lua_isnumber(L, 2))
2187 		return luaL_error(L, "points: incorrect argument type");
2188 
2189 	int points = static_cast<int>(lua_tonumber(L, 2));
2190 
2191 	player_data *player = get_player_data(Lua_Player::Index(L, 1));
2192 	if (player->netgame_parameters[0] != points)
2193 	{
2194 #if !defined(DISABLE_NETWORKING)
2195 		team_netgame_parameters[player->team][0] += points - player->netgame_parameters[0];
2196 #endif
2197 		player->netgame_parameters[0] = points;
2198 		mark_player_network_stats_as_dirty(current_player_index);
2199 	}
2200 
2201 	return 0;
2202 }
2203 
Lua_Player_Set_Team(lua_State * L)2204 static int Lua_Player_Set_Team(lua_State *L)
2205 {
2206 	int team = Lua_PlayerColor::ToIndex(L, 2);
2207 	get_player_data(Lua_Player::Index(L, 1))->team = team;
2208 
2209 	return 0;
2210 }
2211 
Lua_Player_Set_Zoom(lua_State * L)2212 static int Lua_Player_Set_Zoom(lua_State *L)
2213 {
2214 	short player_index = Lua_Player::Index(L, 1);
2215 	if (player_index == local_player_index)
2216 	{
2217 		if (!lua_isboolean(L, 2))
2218 			return luaL_error(L, "zoom_active: incorrect argument type");
2219 
2220 		SetTunnelVision(lua_toboolean(L, 2));
2221 	}
2222 
2223 	return 0;
2224 }
2225 
2226 const luaL_Reg Lua_Player_Set[] = {
2227 	{"color", Lua_Player_Set_Color},
2228 	{"deaths", Lua_Player_Set_Deaths},
2229 	{"direction", Lua_Player_Set_Direction},
2230 	{"head_direction", Lua_Player_Set_Head_Direction},
2231 	{"elevation", Lua_Player_Set_Elevation},
2232 	{"energy", Lua_Player_Set_Energy},
2233 	{"extravision_duration", Lua_Player_Set_Extravision_Duration},
2234 	{"infravision_duration", Lua_Player_Set_Infravision_Duration},
2235 	{"invincibility_duration", Lua_Player_Set_Invincibility_Duration},
2236 	{"invisibility_duration", Lua_Player_Set_Invisibility_Duration},
2237 	{"juice", Lua_Player_Set_Energy},
2238 	{"life", Lua_Player_Set_Energy},
2239 	{"motion_sensor_active", Lua_Player_Set_Motion_Sensor},
2240 	{"oxygen", Lua_Player_Set_Oxygen},
2241 	{"pitch", Lua_Player_Set_Elevation},
2242 	{"points", Lua_Player_Set_Points},
2243 	{"team", Lua_Player_Set_Team},
2244 	{"yaw", Lua_Player_Set_Direction},
2245 	{"zoom_active", Lua_Player_Set_Zoom},
2246 	{0, 0}
2247 };
2248 
Lua_Player_Valid(int16 index)2249 bool Lua_Player_Valid(int16 index)
2250 {
2251 	return index >= 0 && index < dynamic_world->player_count;
2252 }
2253 
2254 char Lua_Players_Name[] = "Players";
2255 
Lua_Players_Print(lua_State * L)2256 int Lua_Players_Print(lua_State *L)
2257 {
2258 	if (mute_lua) return 0;
2259 
2260 	if (lua_gettop(L) != 1)
2261 		return luaL_error(L, "print: incorrect argument type");
2262 
2263 	lua_getglobal(L, "tostring");
2264 	lua_insert(L, -2);
2265 	lua_pcall(L, 1, 1, 0);
2266 	if (lua_tostring(L, -1))
2267 	{
2268 		screen_printf("%s", lua_tostring(L, -1));
2269 	}
2270 	lua_pop(L, 1);
2271 
2272 	return 0;
2273 }
2274 
Lua_Players_Get_Local_Player(lua_State * L)2275 int Lua_Players_Get_Local_Player(lua_State *L)
2276 {
2277 	Lua_Player::Push(L, local_player_index);
2278 	return 1;
2279 }
2280 
2281 const luaL_Reg Lua_Players_Get[] = {
2282 	{"local_player", Lua_Players_Get_Local_Player},
2283 	{"print", L_TableFunction<Lua_Players_Print>},
2284 	{0, 0}
2285 };
2286 
Lua_Players_Length()2287 int16 Lua_Players_Length() {
2288 	return dynamic_world->player_count;
2289 }
2290 
2291 char Lua_DifficultyType_Name[] = "difficulty_type";
2292 typedef L_Enum<Lua_DifficultyType_Name> Lua_DifficultyType;
2293 
2294 char Lua_DifficultyTypes_Name[] = "DifficultyTypes";
2295 typedef L_EnumContainer<Lua_DifficultyTypes_Name, Lua_DifficultyType> Lua_DifficultyTypes;
2296 
2297 char Lua_GameType_Name[] = "game_type";
2298 typedef L_Enum<Lua_GameType_Name> Lua_GameType;
2299 
2300 char Lua_GameTypes_Name[] = "GameTypes";
2301 typedef L_EnumContainer<Lua_GameTypes_Name, Lua_GameType> Lua_GameTypes;
2302 
2303 char Lua_Game_Name[] = "Game";
2304 typedef L_Class<Lua_Game_Name> Lua_Game;
2305 
2306 char Lua_ScoringMode_Name[] = "scoring_mode";
2307 typedef L_Enum<Lua_ScoringMode_Name> Lua_ScoringMode;
2308 
2309 char Lua_ScoringModes_Name[] = "ScoringModes";
2310 typedef L_Container<Lua_ScoringModes_Name, Lua_ScoringMode> Lua_ScoringModes;
2311 
Lua_Game_Get_Dead_Players_Drop_Items(lua_State * L)2312 static int Lua_Game_Get_Dead_Players_Drop_Items(lua_State *L)
2313 {
2314 	lua_pushboolean(L, !(GET_GAME_OPTIONS() & _burn_items_on_death));
2315 	return 1;
2316 }
2317 
Lua_Game_Get_Difficulty(lua_State * L)2318 static int Lua_Game_Get_Difficulty(lua_State *L)
2319 {
2320 	Lua_DifficultyType::Push(L, dynamic_world->game_information.difficulty_level);
2321 	return 1;
2322 }
2323 
Lua_Game_Get_Kill_Limit(lua_State * L)2324 static int Lua_Game_Get_Kill_Limit(lua_State *L)
2325 {
2326 	lua_pushnumber(L, dynamic_world->game_information.kill_limit);
2327 	return 1;
2328 }
2329 
Lua_Game_Get_Monsters_Replenish(lua_State * L)2330 static int Lua_Game_Get_Monsters_Replenish(lua_State* L)
2331 {
2332 	lua_pushboolean(L, dynamic_world->game_information.game_options & _monsters_replenish);
2333 	return 1;
2334 }
2335 
Lua_Game_Get_Proper_Item_Accounting(lua_State * L)2336 static int Lua_Game_Get_Proper_Item_Accounting(lua_State* L)
2337 {
2338 	lua_pushboolean(L, L_Get_Proper_Item_Accounting(L));
2339 	return 1;
2340 }
2341 
Lua_Game_Get_Nonlocal_Overlays(lua_State * L)2342 static int Lua_Game_Get_Nonlocal_Overlays(lua_State* L)
2343 {
2344 	lua_pushboolean(L, L_Get_Nonlocal_Overlays(L));
2345 	return 1;
2346 }
2347 
Lua_Game_Get_Time_Remaining(lua_State * L)2348 static int Lua_Game_Get_Time_Remaining(lua_State* L)
2349 {
2350   if(dynamic_world->game_information.game_time_remaining > 999 * 30)
2351     lua_pushnil(L);
2352   else
2353     lua_pushnumber(L, dynamic_world->game_information.game_time_remaining);
2354   return 1;
2355 }
2356 
Lua_Game_Get_Ticks(lua_State * L)2357 static int Lua_Game_Get_Ticks(lua_State *L)
2358 {
2359 	lua_pushnumber(L, dynamic_world->tick_count);
2360 	return 1;
2361 }
2362 
Lua_Game_Get_Type(lua_State * L)2363 static int Lua_Game_Get_Type(lua_State *L)
2364 {
2365 	Lua_GameType::Push(L, GET_GAME_TYPE());
2366 	return 1;
2367 }
2368 
2369 extern int game_end_condition;
2370 extern int game_scoring_mode;
2371 
Lua_Game_Get_Scoring_Mode(lua_State * L)2372 static int Lua_Game_Get_Scoring_Mode(lua_State *L)
2373 {
2374 	Lua_ScoringMode::Push(L, game_scoring_mode);
2375 	return 1;
2376 }
2377 
Lua_Game_Get_Version(lua_State * L)2378 static int Lua_Game_Get_Version(lua_State *L)
2379 {
2380 	lua_pushstring(L, A1_DATE_VERSION);
2381 	return 1;
2382 }
2383 
Lua_Game_Set_View_Player(lua_State * L)2384 static int Lua_Game_Set_View_Player(lua_State *L)
2385 {
2386 
2387 	int view_player_index;
2388 	if (lua_isnumber(L, 2))
2389 	{
2390 		view_player_index = static_cast<int>(lua_tonumber(L, 2));
2391 		if (view_player_index < 0 || view_player_index >= dynamic_world->player_count)
2392 			return luaL_error(L, "view_player: invalid player index");
2393 	}
2394 	else if (Lua_Player::Is(L, 2))
2395 		view_player_index = Lua_Player::Index(L, 2);
2396 	else
2397 		return luaL_error(L, "view_player: incorrect argument type");
2398 
2399 	if (view_player_index != current_player_index)
2400 	{
2401 		set_current_player_index(view_player_index);
2402 		update_interface(NONE);
2403 		dirty_terminal_view(local_player_index);
2404 	}
2405 
2406 	return 0;
2407 
2408 }
2409 
Lua_Game_Set_Proper_Item_Accounting(lua_State * L)2410 static int Lua_Game_Set_Proper_Item_Accounting(lua_State* L)
2411 {
2412 	if (!lua_isboolean(L, 2))
2413 		luaL_error(L, "proper_item_accounting: incorrect argument type");
2414 	L_Set_Proper_Item_Accounting(L, lua_toboolean(L, 2));
2415 	return 0;
2416 }
2417 
Lua_Game_Set_Nonlocal_Overlays(lua_State * L)2418 static int Lua_Game_Set_Nonlocal_Overlays(lua_State* L)
2419 {
2420 	if (!lua_isboolean(L, 2))
2421 		luaL_error(L, "nonlocal_overlays: incorrect argument type");
2422 	L_Set_Nonlocal_Overlays(L, lua_toboolean(L, 2));
2423 	return 0;
2424 }
2425 
Lua_Game_Set_Scoring_Mode(lua_State * L)2426 static int Lua_Game_Set_Scoring_Mode(lua_State *L)
2427 {
2428   int mode = Lua_ScoringMode::ToIndex(L, 2);
2429   game_scoring_mode = mode;
2430   // TODO: set network stats to dirty
2431   return 0;
2432 }
2433 
Lua_Game_Set_Dead_Players_Drop_Items(lua_State * L)2434 static int Lua_Game_Set_Dead_Players_Drop_Items(lua_State* L)
2435 {
2436 	if (!lua_isboolean(L, 2))
2437 		luaL_error(L, "dead_players_drop_items: incorrect argument type");
2438 
2439 	bool dpdi = lua_toboolean(L, 2);
2440 	if (dpdi)
2441 	{
2442 		GET_GAME_OPTIONS() &= ~_burn_items_on_death;
2443 	}
2444 	else
2445 	{
2446 		GET_GAME_OPTIONS() |= _burn_items_on_death;
2447 	}
2448 
2449 	return 0;
2450 }
2451 
Lua_Game_Set_Monsters_Replenish(lua_State * L)2452 static int Lua_Game_Set_Monsters_Replenish(lua_State* L)
2453 {
2454 	if (!lua_isboolean(L, 2))
2455 		luaL_error(L, "monsters_replenish: incorrect argument type");
2456 
2457 	bool replenish = lua_toboolean(L, 2);
2458 	if (replenish)
2459 	{
2460 		dynamic_world->game_information.game_options |= _monsters_replenish;
2461 	}
2462 	else
2463 	{
2464 		dynamic_world->game_information.game_options &= ~_monsters_replenish;
2465 	}
2466 	return 0;
2467 }
2468 
Lua_Game_Set_Over(lua_State * L)2469 static int Lua_Game_Set_Over(lua_State *L)
2470 {
2471   if(lua_isnil(L, 2)) game_end_condition = _game_normal_end_condition;
2472   else game_end_condition = lua_toboolean(L, 2) ? _game_end_now_condition : _game_no_end_condition;
2473   return 0;
2474 }
2475 
2476 extern GM_Random lua_random_generator;
2477 
Lua_Game_Better_Random(lua_State * L)2478 int Lua_Game_Better_Random(lua_State *L)
2479 {
2480 	if (lua_isnumber(L, 1))
2481 	{
2482 		lua_pushnumber(L, lua_random_generator.KISS() % static_cast<uint32>(lua_tonumber(L, 1)));
2483 	}
2484 	else
2485 	{
2486 		lua_pushnumber(L, lua_random_generator.KISS());
2487 	}
2488 	return 1;
2489 }
2490 
Lua_Game_Deserialize(lua_State * L)2491 int Lua_Game_Deserialize(lua_State* L)
2492 {
2493         if (!lua_isstring(L, 1))
2494         {
2495                 lua_pushstring(L, "Game.deserialize: incorrect argument type");
2496                 lua_error(L);
2497         }
2498 
2499         size_t len;
2500         auto s = lua_tolstring(L, 1, &len);
2501 
2502         io::stream_buffer<io::array_source> sb(s, len);
2503 
2504         if (lua_restore(L, &sb))
2505         {
2506                 return 1;
2507         }
2508         else
2509         {
2510                 return 0;
2511         }
2512 }
2513 
Lua_Game_Global_Random(lua_State * L)2514 int Lua_Game_Global_Random(lua_State *L)
2515 {
2516 	if (lua_isnumber(L, 1))
2517 	{
2518 		lua_pushnumber(L, ::global_random() % static_cast<uint16>(lua_tonumber(L, 1)));
2519 	}
2520 	else
2521 	{
2522 		lua_pushnumber(L, ::global_random());
2523 	}
2524 	return 1;
2525 }
2526 
Lua_Game_Local_Random(lua_State * L)2527 int Lua_Game_Local_Random(lua_State *L)
2528 {
2529 	if (lua_isnumber(L, 1))
2530 	{
2531 		lua_pushnumber(L, ::local_random() % static_cast<uint16>(lua_tonumber(L, 1)));
2532 	}
2533 	else
2534 	{
2535 		lua_pushnumber(L, ::local_random());
2536 	}
2537 	return 1;
2538 }
2539 
Lua_Game_Save(lua_State * L)2540 int Lua_Game_Save(lua_State *L)
2541 {
2542 	if (!game_is_networked)
2543 		save_game();
2544 
2545 	return 0;
2546 }
2547 
Lua_Game_Serialize(lua_State * L)2548 int Lua_Game_Serialize(lua_State* L)
2549 {
2550         std::stringbuf sb;
2551         if (lua_save(L, &sb))
2552         {
2553                 lua_pushlstring(L, sb.str().data(), sb.str().size());
2554                 return 1;
2555         }
2556         else
2557         {
2558                 return 0;
2559         }
2560 }
2561 
2562 extern int L_Restore_Passed(lua_State *);
2563 extern int L_Restore_Saved(lua_State *);
2564 
2565 const luaL_Reg Lua_Game_Get[] = {
2566 	{"dead_players_drop_items", Lua_Game_Get_Dead_Players_Drop_Items},
2567         {"deserialize", L_TableFunction<Lua_Game_Deserialize>},
2568 	{"difficulty", Lua_Game_Get_Difficulty},
2569 	{"global_random", L_TableFunction<Lua_Game_Global_Random>},
2570 	{"kill_limit", Lua_Game_Get_Kill_Limit},
2571 	{"time_remaining", Lua_Game_Get_Time_Remaining},
2572 	{"local_random", L_TableFunction<Lua_Game_Local_Random>},
2573 	{"monsters_replenish", Lua_Game_Get_Monsters_Replenish},
2574 	{"proper_item_accounting", Lua_Game_Get_Proper_Item_Accounting},
2575 	{"nonlocal_overlays", Lua_Game_Get_Nonlocal_Overlays},
2576 	{"random", L_TableFunction<Lua_Game_Better_Random>},
2577 	{"restore_passed", L_TableFunction<L_Restore_Passed>},
2578 	{"restore_saved", L_TableFunction<L_Restore_Saved>},
2579 	{"ticks", Lua_Game_Get_Ticks},
2580 	{"type", Lua_Game_Get_Type},
2581 	{"save", L_TableFunction<Lua_Game_Save>},
2582         {"serialize", L_TableFunction<Lua_Game_Serialize>},
2583 	{"scoring_mode", Lua_Game_Get_Scoring_Mode},
2584 	{"version", Lua_Game_Get_Version},
2585 	{0, 0}
2586 };
2587 
2588 const luaL_Reg Lua_Game_Set[] = {
2589 	{"dead_players_drop_items", Lua_Game_Set_Dead_Players_Drop_Items},
2590 	{"monsters_replenish", Lua_Game_Set_Monsters_Replenish},
2591 	{"proper_item_accounting", Lua_Game_Set_Proper_Item_Accounting},
2592 	{"nonlocal_overlays", Lua_Game_Set_Nonlocal_Overlays},
2593 	{"scoring_mode", Lua_Game_Set_Scoring_Mode},
2594 	{"over", Lua_Game_Set_Over},
2595 	{0, 0}
2596 };
2597 
2598 char Lua_Music_Name[] = "Music";
2599 typedef L_Class<Lua_Music_Name> Lua_Music;
2600 
Lua_Music_Clear(lua_State * L)2601 int Lua_Music_Clear(lua_State *L)
2602 {
2603 	Music::instance()->ClearLevelMusic();
2604 	return 0;
2605 }
2606 
Lua_Music_Fade(lua_State * L)2607 int Lua_Music_Fade(lua_State *L)
2608 {
2609 	int duration;
2610 	if (!lua_isnumber(L, 1))
2611 		duration = 1000;
2612 	else
2613 		duration = static_cast<int>(lua_tonumber(L, 1) * 1000);
2614 	Music::instance()->FadeOut(duration);
2615 	Music::instance()->ClearLevelMusic();
2616 	return 0;
2617 }
2618 
Lua_Music_Play(lua_State * L)2619 int Lua_Music_Play(lua_State *L)
2620 {
2621 	bool restart_music;
2622 	restart_music = !Music::instance()->IsLevelMusicActive() && !Music::instance()->Playing();
2623 	for (int n = 1; n <= lua_gettop(L); n++)
2624 	{
2625 		if (!lua_isstring(L, n))
2626 			return luaL_error(L, "play: invalid file specifier");
2627 
2628 		std::string search_path = L_Get_Search_Path(L);
2629 
2630 		FileSpecifier file;
2631 		if (search_path.size())
2632 		{
2633 			if (!file.SetNameWithPath(lua_tostring(L, n), search_path))
2634 				Music::instance()->PushBackLevelMusic(file);
2635 		}
2636 		else
2637 		{
2638 			if (file.SetNameWithPath(lua_tostring(L, n)))
2639 				Music::instance()->PushBackLevelMusic(file);
2640 		}
2641 	}
2642 
2643 	if (restart_music)
2644 		Music::instance()->PreloadLevelMusic();
2645 	return 0;
2646 }
2647 
Lua_Music_Stop(lua_State * L)2648 int Lua_Music_Stop(lua_State *L)
2649 {
2650 	Music::instance()->ClearLevelMusic();
2651 	Music::instance()->StopLevelMusic();
2652 
2653 	return 0;
2654 }
2655 
Lua_Music_Valid(lua_State * L)2656 int Lua_Music_Valid(lua_State* L) {
2657 	int top = lua_gettop(L);
2658 	for(int n = 1; n <= top; n++) {
2659 		if(!lua_isstring(L, n))
2660 			return luaL_error(L, "valid: invalid file specifier");
2661 		FileSpecifier path;
2662 		if(path.SetNameWithPath(lua_tostring(L, n))) {
2663 			StreamDecoder* stream = StreamDecoder::Get(path);
2664 			if(stream) {
2665 				lua_pushboolean(L, true);
2666 				delete stream;
2667 			} else lua_pushboolean(L, false);
2668 		} else lua_pushboolean(L, false);
2669 	}
2670 	return top;
2671 }
2672 
2673 const luaL_Reg Lua_Music_Get[] = {
2674 	{"clear", L_TableFunction<Lua_Music_Clear>},
2675 	{"fade", L_TableFunction<Lua_Music_Fade>},
2676 	{"play", L_TableFunction<Lua_Music_Play>},
2677 	{"stop", L_TableFunction<Lua_Music_Stop>},
2678 	{"valid", L_TableFunction<Lua_Music_Valid>},
2679 	{0, 0}
2680 };
2681 
2682 static void Lua_Player_load_compatibility(lua_State *L);
2683 
Lua_Player_register(lua_State * L)2684 int Lua_Player_register (lua_State *L)
2685 {
2686 	Lua_Action_Flags::Register(L, Lua_Action_Flags_Get, Lua_Action_Flags_Set);
2687 
2688 	Lua_Camera_Path_Angles::Register(L, Lua_Camera_Path_Angles_Get);
2689 	Lua_Camera_Path_Points::Register(L, Lua_Camera_Path_Points_Get);
2690 	Lua_Camera::Register(L, Lua_Camera_Get);
2691 	Lua_Camera::Valid = Lua_Camera_Valid;
2692 
2693 	Lua_Cameras::Register(L, Lua_Cameras_Methods);
2694 	Lua_Cameras::Length = Lua_Cameras_Length;
2695 
2696 	Lua_Crosshairs::Register(L, Lua_Crosshairs_Get, Lua_Crosshairs_Set);
2697 	Lua_Player_Compass::Register(L, Lua_Player_Compass_Get, Lua_Player_Compass_Set);
2698 	Lua_Player_Items::Register(L, 0, 0, Lua_Player_Items_Metatable);
2699 	Lua_Player_Kills::Register(L, 0, 0, Lua_Player_Kills_Metatable);
2700 
2701 	Lua_InternalVelocity::Register(L, Lua_InternalVelocity_Get);
2702 	Lua_ExternalVelocity::Register(L, Lua_ExternalVelocity_Get, Lua_ExternalVelocity_Set);
2703 	Lua_FadeType::Register(L, 0, 0, 0, Lua_FadeType_Mnemonics);
2704 	Lua_FadeType::Valid = Lua_FadeType::ValidRange(NUMBER_OF_FADE_TYPES);
2705 
2706 	Lua_FadeTypes::Register(L);
2707 	Lua_FadeTypes::Length = Lua_FadeTypes::ConstantLength((int16) NUMBER_OF_FADE_TYPES);
2708 
2709 	Lua_Texture_Palette_Slot::Register(L, Lua_Texture_Palette_Slot_Get, Lua_Texture_Palette_Slot_Set);
2710 	Lua_Texture_Palette_Slots::Register(L, 0, 0, Lua_Texture_Palette_Slots_Metatable);
2711 	Lua_Texture_Palette::Register(L, Lua_Texture_Palette_Get, Lua_Texture_Palette_Set);
2712 
2713 	Lua_WeaponType::Register(L, 0, 0, 0, Lua_WeaponType_Mnemonics);
2714 	Lua_WeaponType::Valid = Lua_WeaponType::ValidRange(MAXIMUM_NUMBER_OF_WEAPONS);
2715 
2716 	Lua_WeaponTypes::Register(L);
2717 	Lua_WeaponTypes::Length = Lua_WeaponTypes::ConstantLength((int16) MAXIMUM_NUMBER_OF_WEAPONS);
2718 
2719 	Lua_Player_Weapon::Register(L, Lua_Player_Weapon_Get);
2720 	Lua_Player_Weapon::Valid = Lua_Player_Weapon::ValidRange(MAXIMUM_NUMBER_OF_WEAPONS);
2721 
2722 	Lua_Player_Weapons::Register(L, 0, 0, Lua_Player_Weapons_Metatable);
2723 	Lua_Player_Weapons::Valid = Lua_Player_Valid;
2724 
2725 	Lua_Player_Weapon_Trigger::Register(L, Lua_Player_Weapon_Trigger_Get);
2726 	Lua_Player_Weapon_Trigger::Valid = Lua_Player_Weapon_Trigger::ValidRange((int) _secondary_weapon + 1);
2727 
2728 	Lua_OverlayColor::Register(L, 0, 0, 0, Lua_OverlayColor_Mnemonics);
2729 	Lua_OverlayColor::Valid = Lua_OverlayColor::ValidRange(8);
2730 
2731 	Lua_Overlays::Register(L, 0, 0, Lua_Overlays_Metatable);
2732 	Lua_Overlays::Valid = Lua_Player_Valid;
2733 
2734 	Lua_Overlay::Register(L, Lua_Overlay_Get, Lua_Overlay_Set);
2735 	Lua_Overlay::Valid = Lua_Overlay::ValidRange(MAXIMUM_NUMBER_OF_SCRIPT_HUD_ELEMENTS);
2736 
2737 	Lua_PlayerColor::Register(L, 0, 0, 0, Lua_PlayerColor_Mnemonics);
2738 	Lua_PlayerColor::Valid = Lua_PlayerColor::ValidRange(NUMBER_OF_TEAM_COLORS);
2739 
2740 	Lua_PlayerColors::Register(L);
2741 	Lua_PlayerColors::Length = Lua_PlayerColors::ConstantLength((int16) NUMBER_OF_TEAM_COLORS);
2742 
2743 	Lua_Player::Register(L, Lua_Player_Get, Lua_Player_Set);
2744 	Lua_Player::Valid = Lua_Player_Valid;
2745 
2746 	Lua_Players::Register(L, Lua_Players_Get);
2747 	Lua_Players::Length = Lua_Players_Length;
2748 
2749 	Lua_Game::Register(L, Lua_Game_Get, Lua_Game_Set);
2750 
2751 	Lua_GameType::Register(L, 0, 0, 0, Lua_GameType_Mnemonics);
2752 	Lua_GameType::Valid = Lua_GameType::ValidRange(NUMBER_OF_GAME_TYPES);
2753 
2754 	Lua_GameTypes::Register(L);
2755 	Lua_GameTypes::Length = Lua_GameTypes::ConstantLength(NUMBER_OF_GAME_TYPES);
2756 
2757 	Lua_ScoringMode::Register(L, 0, 0, 0, Lua_ScoringMode_Mnemonics);
2758 	Lua_ScoringMode::Valid = Lua_ScoringMode::ValidRange(NUMBER_OF_GAME_SCORING_MODES);
2759 
2760 	Lua_ScoringModes::Register(L);
2761 	Lua_ScoringModes::Length = Lua_ScoringModes::ConstantLength(NUMBER_OF_GAME_SCORING_MODES);
2762 
2763 	Lua_DifficultyType::Register(L, 0, 0, 0, Lua_DifficultyType_Mnemonics);
2764 	Lua_DifficultyType::Valid = Lua_DifficultyType::ValidRange(NUMBER_OF_GAME_DIFFICULTY_LEVELS);
2765 
2766 	Lua_DifficultyTypes::Register(L);
2767 	Lua_DifficultyTypes::Length = Lua_DifficultyTypes::ConstantLength(NUMBER_OF_GAME_DIFFICULTY_LEVELS);
2768 
2769 	Lua_TextureType::Register(L, 0, 0, 0, Lua_TextureType_Mnemonics);
2770 	Lua_TextureType::Valid = Lua_TextureType::ValidRange(NUMBER_OF_LUA_TEXTURE_TYPES);
2771 
2772 	Lua_TextureTypes::Register(L);
2773 	Lua_TextureTypes::Length = Lua_TextureTypes::ConstantLength(NUMBER_OF_LUA_TEXTURE_TYPES);
2774 
2775 	Lua_Music::Register(L, Lua_Music_Get);
2776 
2777 	// register one Game userdatum globally
2778 	Lua_Game::Push(L, 0);
2779 	lua_setglobal(L, Lua_Game_Name);
2780 
2781 	// register one Music userdatum
2782 	Lua_Music::Push(L, 0);
2783 	lua_setglobal(L, Lua_Music_Name);
2784 
2785 	Lua_Player_load_compatibility(L);
2786 
2787 	return 0;
2788 }
2789 
2790 static const char *compatibility_script = ""
2791 	"function accelerate_player(player, vertical_velocity, direction, velocity) Players[player]:accelerate(direction, velocity, vertical_velocity) end\n"
2792 	"function activate_camera(player, camera) Cameras[camera]:activate(player) end\n"
2793 	"function activate_terminal(player, text) Players[player]:activate_terminal(text) end\n"
2794 	"function add_item(player, item_type) Players[player].items[item_type] = Players[player].items[item_type] + 1 end\n"
2795 	"function add_path_angle(camera, yaw, pitch, time) Cameras[camera].path_angles:new(yaw, pitch, time) end\n"
2796 	"function add_path_point(camera, polygon, x, y, z, time) Cameras[camera].path_points:new(x, y, z, polygon, time) end\n"
2797 	"function award_kills(player, slain_player, amount) if player == -1 then Players[slain_player].deaths = Players[slain_player].deaths + amount else Players[player].kills[slain_player] = Players[player].kills[slain_player] + amount end end\n"
2798 	"function add_to_player_external_velocity(player, x, y, z) Players[player].external_velocity.i = Players[player].external_velocity.i + x Players[player].external_velocity.j = Players[player].external_velocity.j + y Players[player].external_velocity.k = Players[player].external_velocity.k + z end\n"
2799 	"function award_points(player, amount) Players[player].points = Players[player].points + amount end\n"
2800 	"function better_random() return Game.random() end\n"
2801 	"function clear_camera(camera) Cameras[camera]:clear() end\n"
2802 	"function clear_music() Music.clear() end\n"
2803 	"function count_item(player, item_type) return Players[player].items[item_type] end\n"
2804 	"function create_camera() return Cameras.new().index end\n"
2805 	"function crosshairs_active(player) return Players[player].crosshairs.active end\n"
2806 	"function deactivate_camera(camera) Cameras[camera]:deactivate() end\n"
2807 	"function destroy_ball(player) for i in ItemTypes() do if i.ball then Players[player].items[i] = 0 end end end\n"
2808 	"function fade_music(duration) if duration then Music.fade(duration * 60 / 1000) else Music.fade(60 / 1000) end end\n"
2809 	"function get_game_difficulty() return Game.difficulty.index end\n"
2810 	"function get_game_type() return Game.type.index end\n"
2811 	"function get_kills(player, slain_player) if player == -1 then return Players[slain_player].deaths else return Players[player].kills[slain_player] end end\n"
2812 	"function get_kill_limit() return Game.kill_limit end\n"
2813 	"function get_life(player) return Players[player].energy end\n"
2814 	"function get_motion_sensor_state(player) return Players[player].motion_sensor_active end\n"
2815 	"function get_oxygen(player) return Players[player].oxygen end\n"
2816 	"function get_player_angle(player) return Players[player].yaw, Players[player].pitch end\n"
2817 	"function get_player_color(player) return Players[player].color.index end\n"
2818 	"function get_player_external_velocity(player) return Players[player].external_velocity.i * 1024, Players[player].external_velocity.j * 1024, Players[player].external_velocity.k * 1024 end\n"
2819 	"function get_player_internal_velocity(player) return Players[player].internal_velocity.forward * 65536, Players[player].internal_velocity.perpendicular * 65536 end\n"
2820 	"function get_player_name(player) return Players[player].name end\n"
2821 	"function get_player_polygon(player) return Players[player].polygon.index end\n"
2822 	"function get_player_position(player) return Players[player].x, Players[player].y, Players[player].z end\n"
2823 	"function get_player_powerup_duration(player, powerup) if powerup == _powerup_invisibility then return Players[player].invisibility_duration elseif powerup == _powerup_invincibility then return Players[player].invincibility_duration elseif powerup == _powerup_infravision then return Players[player].infravision_duration elseif powerup == _powerup_extravision then return Players[player].extravision_duration end end\n"
2824 	"function get_player_team(player) return Players[player].team.index end\n"
2825 	"function get_player_weapon(player) if Players[player].weapons.current then return Players[player].weapons.current.index else return nil end end\n"
2826 	"function get_points(player) return Players[player].points end\n"
2827 	"function global_random() return Game.global_random() end\n"
2828 	"function inflict_damage(player, amount, type) if (type) then Players[player]:damage(amount, type) else Players[player]:damage(amount) end end\n"
2829 	"function local_player_index() for p in Players() do if p.local_ then return p.index end end end\n"
2830 	"function local_random() return Game.local_random() end\n"
2831 	"function number_of_players() return # Players end\n"
2832 	"function play_music(...) Music.play(...) end\n"
2833 	"function player_is_dead(player) return Players[player].dead end\n"
2834 	"function player_media(player) if Players[player].head_below_media then return Players[player].polygon.media.index else return nil end end\n"
2835 	"function player_to_monster_index(player) return Players[player].monster.index end\n"
2836 	"function play_sound(player, sound, pitch) Players[player]:play_sound(sound, pitch) end\n"
2837 	"function remove_item(player, item_type) if Players[player].items[item_type] > 0 then Players[player].items[item_type] = Players[player].items[item_type] - 1 end end\n"
2838 	"function screen_fade(player, fade) if fade then Players[player]:fade_screen(fade) else for p in Players() do p:fade_screen(player) end end end\n"
2839 	"function screen_print(player, message) if message then if Players[player] then Players[player]:print(message) end else Players.print(player) end end\n"
2840 	"function select_weapon(player, weapon) Players[player].weapons[weapon]:select() end\n"
2841 	"function set_crosshairs_state(player, state) Players[player].crosshairs.active = state end\n"
2842 	"function set_kills(player, slain_player, amount) if player == -1 then Players[slain_player].deaths = amount else Players[player].kills[slain_player] = amount end end\n"
2843 	"function set_life(player, shield) Players[player].energy = shield end\n"
2844 	"function set_lua_compass_beacon(player, x, y) Players[player].compass.x = x Players[player].compass.y = y end\n"
2845 	"function set_lua_compass_state(player, state) if state > 15 then Players[player].compass.beacon = true state = state % 16 else Players[player].compass.beacon = false end if state > 7 then Players[player].compass.se = true state = state - 8 else Players[player].compass.se = false end if state > 3 then Players[player].compass.sw = true state = state - 4 else Players[player].compass.sw = false end if state > 1 then Players[player].compass.ne = true state = state - 2 else Players[player].compass.ne = false end if state == 1 then Players[player].compass.nw = true else Players[player].compass.nw = false end end\n"
2846 	"function set_motion_sensor_state(player, state) Players[player].motion_sensor_active = state end\n"
2847 	"function set_overlay_color(overlay, color) for p in Players() do if p.local_ then p.overlays[overlay].color = color end end end\n"
2848 	"function set_overlay_icon(overlay, icon) for p in Players() do if p.local_ then p.overlays[overlay].icon = icon end end end\n"
2849 	"function set_overlay_icon_by_color(overlay, color) for p in Players() do if p.local_ then p.overlays[overlay]:fill_icon(color) end end end\n"
2850 	"function set_overlay_text(overlay, text) for p in Players() do if p.local_ then p.overlays[overlay].text = text end end end\n"
2851 	"function set_oxygen(player, oxygen) Players[player].oxygen = oxygen end\n"
2852 	"function set_player_angle(player, yaw, pitch) Players[player].yaw = yaw Players[player].pitch = pitch + 360.0 end\n"
2853 	"function set_player_color(player, color) Players[player].color = color end\n"
2854 	"function set_player_external_velocity(player, x, y, z) Players[player].external_velocity.i = x / 1024 Players[player].external_velocity.j = y / 1024 Players[player].external_velocity.k = z / 1024 end\n"
2855 	"function set_player_position(player, x, y, z, polygon) Players[player]:position(x, y, z, polygon) end\n"
2856 	"function set_player_powerup_duration(player, powerup, duration) if powerup == _powerup_invisibility then Players[player].invisibility_duration = duration elseif powerup == _powerup_invincibility then Players[player].invincibility_duration = duration elseif powerup == _powerup_infravision then Players[player].infravision_duration = duration elseif powerup == _powerup_extravision then Players[player].extravision_duration = duration end end\n"
2857 	"function set_player_team(player, team) Players[player].team = team end\n"
2858 	"function set_points(player, amount) Players[player].points = amount end\n"
2859 	"function stop_music() Music.stop() end\n"
2860 	"function set_zoom_state(player, state) Players[player].zoom_active = state end\n"
2861 	"function teleport_player(player, polygon) Players[player]:teleport(polygon) end\n"
2862 	"function teleport_player_to_level(player, level) Players[player]:teleport_to_level(level) end\n"
2863 	"function use_lua_compass(player, state) if state ~= nil then Players[player].compass.lua = state else for p in Players() do p.compass.lua = player end end end\n"
2864 	"function zoom_active(player) return Players[player].zoom_active end\n"
2865 	;
2866 
Lua_Player_load_compatibility(lua_State * L)2867 static void Lua_Player_load_compatibility(lua_State *L)
2868 {
2869 	luaL_loadbuffer(L, compatibility_script, strlen(compatibility_script), "player_compatibility");
2870 	lua_pcall(L, 0, 0, 0);
2871 }
2872 
2873 #endif
2874