• R/O
  • SSH
  • HTTPS

marathon: Commit


Commit MetaInfo

Revision525 (tree)
Zeit2012-06-02 14:02:35
Autorookawa_mi

Log Message

1.0.2対応
文字コード修正

Ändern Zusammenfassung

Diff

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