FS2_Open
Open source remastering of the Freespace 2 engine
lua.cpp
Go to the documentation of this file.
1 #include "ai/ai.h"
2 #include "ai/aigoals.h"
3 #include "asteroid/asteroid.h"
4 #include "camera/camera.h"
5 #include "cfile/cfilesystem.h"
6 #include "cmdline/cmdline.h"
7 #include "cutscene/movie.h"
8 #include "debris/debris.h"
10 #include "freespace2/freespace.h"
12 #include "globalincs/linklist.h"
13 #include "graphics/2d.h"
14 #include "graphics/font.h"
16 #include "hud/hudbrackets.h"
17 #include "hud/hudconfig.h"
18 #include "hud/hudescort.h"
19 #include "hud/hudets.h"
20 #include "hud/hudgauges.h"
21 #include "hud/hudshield.h"
22 #include "iff_defs/iff_defs.h"
23 #include "io/joy.h"
24 #include "io/key.h"
25 #include "io/mouse.h"
26 #include "io/timer.h"
27 #include "jumpnode/jumpnode.h"
28 #include "lighting/lighting.h"
29 #include "menuui/credits.h"
31 #include "mission/missiongoals.h"
32 #include "mission/missionload.h"
33 #include "mission/missionlog.h"
34 #include "mission/missionmessage.h"
36 #include "missionui/missionbrief.h"
37 #include "model/model.h"
38 #include "network/multi.h"
39 #include "network/multimsgs.h"
40 #include "object/objectshield.h"
41 #include "object/waypoint.h"
42 #include "parse/lua.h"
43 #include "parse/parselo.h"
44 #include "parse/scripting.h"
45 #include "particle/particle.h"
46 #include "playerman/player.h"
47 #include "render/3d.h"
48 #include "render/3dinternal.h"
49 #include "ship/ship.h"
50 #include "ship/shipfx.h"
51 #include "ship/shiphit.h"
52 #include "sound/audiostr.h"
53 #include "sound/ds.h"
54 #include "weapon/beam.h"
55 #include "weapon/weapon.h"
56 
57 #define BMPMAN_INTERNAL
58 #include "bmpman/bm_internal.h"
59 
60 //*************************Lua globals*************************
62 
63 //*************************Lua classes************************
64 
65 //Library class
66 //This is what you define a variable of to make new libraries
67 class ade_lib : public ade_lib_handle {
68 public:
69  ade_lib(char *in_name, ade_lib_handle *parent=NULL, char *in_shortname=NULL, char *in_desc=NULL) {
70  ade_table_entry ate;
71 
72  ate.Name = in_name;
73  ate.ShortName = in_shortname;
74  ate.Instanced = true;
75 
76  //WMC - Here's a little hack.
77  //Lua did not work with __len on standard table objects.
78  //So instead, all FS2 libraries are now userdata.
79  //This means that no new functions can be added from
80  //within the scripting environment, but I don't think
81  //there will be any catastrophic consequences.
82  ate.Type = 'o';
83  ate.Value.Object.idx = Ade_table_entries.size();
84  ate.Value.Object.sig = NULL;
85  ate.Value.Object.buf = &Num_reinforcements; //WMC - I just chose Num_ship_classes randomly. MageKing17 - changed to Num_reinforcements, likewise at random, due to the removal of Num_ship_classes
86  ate.Value.Object.size = sizeof(Num_reinforcements);
87  ate.Description = in_desc;
88 
89  if(parent != NULL)
90  Ade_table_entries[parent->GetIdx()].AddSubentry(ate);
91  else
92  Ade_table_entries.push_back(ate);
93  LibIdx = Ade_table_entries.size()-1;
94  }
95 
96  char *GetName();
97 };
98 
100 {
101  if(GetIdx() == UINT_MAX)
102  return "<Invalid>";
103 
104  return Ade_table_entries[GetIdx()].GetName();
105 }
106 
107 //Function helper class
108 //Lets us add functions via its constructor
109 class ade_func : public ade_lib_handle {
110 public:
111  ade_func(char *name, lua_CFunction func, ade_lib_handle &parent, char *args=NULL, char *desc=NULL, char *ret_type=NULL, char*ret_desc=NULL) {
112  ade_table_entry ate;
113 
114  ate.Name = name;
115  ate.Instanced = true;
116  ate.Type = 'u';
117  ate.Value.Function = func;
118  ate.Arguments = args;
119  ate.Description = desc;
120  ate.ReturnType = ret_type;
121  ate.ReturnDescription = ret_desc;
122 
123  Ade_table_entries[parent.GetIdx()].AddSubentry(ate);
124  LibIdx = Ade_table_entries.size()-1;
125  }
126 };
127 
128 class ade_virtvar : public ade_lib_handle {
129 public:
130  ade_virtvar(char *name, lua_CFunction func, ade_lib_handle &parent, char *args=NULL, char *desc=NULL, char *ret_type=NULL, char*ret_desc=NULL) {
131  ade_table_entry ate;
132 
133  ate.Name = name;
134  ate.Instanced = true;
135  ate.Type = 'v';
136  ate.Value.Function = func;
137  ate.Arguments = args;
138  ate.Description = desc;
139  ate.ReturnType = ret_type;
140  ate.ReturnDescription = ret_desc;
141 
142  Ade_table_entries[parent.GetIdx()].AddSubentry(ate);
143  LibIdx = Ade_table_entries.size()-1;
144  }
145 };
146 
147 class ade_indexer : public ade_lib_handle {
148 public:
149  ade_indexer(lua_CFunction func, ade_lib_handle &parent, char *args=NULL, char *desc=NULL, char *ret_type=NULL, char*ret_desc=NULL) {
150  //Add function for meta
151  ade_table_entry ate;
152 
153  ate.Name = "__indexer";
154  ate.Instanced = true;
155  ate.Type = 'u';
156  ate.Value.Function = func;
157  ate.Arguments = args;
158  ate.Description = desc;
159  ate.ReturnType = ret_type;
160  ate.ReturnDescription = ret_desc;
161 
162  Ade_table_entries[parent.GetIdx()].AddSubentry(ate);
163  LibIdx = Ade_table_entries.size()-1;
164  }
165 };
166 
167 //Struct for converting one string for another. whee!
168 struct string_conv {
169  char *src;
170  char *dest;
171 };
172 
173 //*************************Lua operators*************************
174 //These are the various types of operators you can
175 //set in Lua. Use these as function name to activate.
176 //
177 //Format string should be "*o" or "o*", where "*" is the type of
178 //variable you want to deal with.
179 //The order varies with order of variables
181  {"__add", "+"}, //var + obj
182  {"__sub", "-"}, //var - obj
183  {"__mul", "*"}, //var * obj
184  {"__div", "/"}, //var / obj
185  {"__mod", "%"}, //var % obj
186  {"__pow", "^"}, //var ^ obj
187  {"__unm", "~"}, //var ~ obj
188  {"__concat", ".."}, //var .. obj
189  {"__len", "#"}, //#var
190  {"__eq", "=="}, //var == obj
191  {"__lt", "<"}, //var < obj
192  {"__le", "<="}, //var <= obj
193  {"__newindex", "="}, //var = obj
194  {"__call", ""}, //*shrug*
195  {"__gc", "__gc"}, //Lua's equivelant of a destructor
196  //WMC - Used with tostring() lua operator.
197  {"__tostring", "(string)"}, //tostring(var)
198  //WMC - This is NOT a Lua type, but for the LUA_INDEXER define
199  {"__indexer", "[]"}, //obj[var]
200 };
201 
203 
204 int ade_get_operator(char *tablename)
205 {
206  for(int i = 0; i < ade_Num_operators; i++)
207  {
208  if(!strcmp(tablename, ade_Operators[i].src))
209  return i;
210  }
211 
212  return -1;
213 }
214 
215 const size_t INVALID_ID = (size_t) -1; // Use -1 to get highest possible unsigned number
216 
217 //*************************Lua helpers*************************
218 //Function macro
219 //This is what you call to make new functions
220 #define ADE_FUNC(name, parent, args, desc, ret_type, ret_desc) \
221  static int parent##_##name##_f(lua_State *L); \
222  ade_func parent##_##name(#name, parent##_##name##_f, parent, args, desc, ret_type, ret_desc); \
223  static int parent##_##name##_f(lua_State *L)
224 
225 //Use this to handle forms of type vec.x and vec['x']. Basically an indexer for a specific variable.
226 //Format string should be "o*%", where * is indexing value, and % is the value to set to when LUA_SETTTING_VAR is set
227 #define ADE_VIRTVAR(name, parent, args, desc, ret_type, ret_desc) \
228  static int parent##_##name##_f(lua_State *L); \
229  ade_virtvar parent##_##name(#name, parent##_##name##_f, parent, args, desc, ret_type, ret_desc); \
230  static int parent##_##name##_f(lua_State *L)
231 
232 //Use this with objects to deal with forms such as vec.x, vec['x'], vec[0]
233 //Format string should be "o*%", where * is indexing value, and % is the value to set to when LUA_SETTTING_VAR is set
234 #define ADE_INDEXER(parent, args, desc, ret_type, ret_desc) \
235  static int parent##___indexer_f(lua_State *L); \
236  ade_indexer parent##___indexer(parent##___indexer_f, parent, args, desc, ret_type, ret_desc); \
237  static int parent##___indexer_f(lua_State *L)
238 
239 //Checks to determine whether ADE_VIRTVAR or LUA_INDEXER should set the variable
240 #define ADE_FUNCNAME_UPVALUE_INDEX 1
241 #define ADE_SETTING_UPVALUE_INDEX 2
242 #define ADE_SETTING_VAR lua_toboolean(L,lua_upvalueindex(ADE_SETTING_UPVALUE_INDEX))
243 
244 //*************************Lua return values*************************
245 #define ADE_RETURN_NIL 0
246 #define ADE_RETURN_TRUE ade_set_args(L, "b", true)
247 #define ADE_RETURN_FALSE ade_set_args(L, "b", false)
248 #define ade_set_error ade_set_args
249 
250 //*************************Begin non-lowlevel stuff*************************
251 //*************************Helper function declarations*********************
252 //WMC - Sets object handle with proper type
253 int ade_set_object_with_breed(lua_State *L, int obj_idx);
254 
255 //**********Handles
256 /*ade_obj<int> l_Camera("camera", "Camera handle");
257 ade_obj<int> l_Cmission("cmission", "Campaign mission handle"); //WMC - We can get away with a pointer right now, but if it ever goes dynamic, it'd be a prob
258 ade_obj<enum_h> l_Enum("enumeration", "Enumeration object");
259 ade_obj<int> l_Event("event", "Mission event handle");
260 ade_obj<int> l_Font("font", "font handle");
261 ade_obj<matrix_h> l_Matrix("orientation", "Orientation matrix object");
262 ade_obj<int> l_Model("model", "3D Model (POF) handle");
263 ade_obj<object_h> l_Object("object", "Object handle");
264 ade_obj<physics_info_h> l_Physics("physics", "Physics handle");
265 ade_obj<int> l_Player("player", "Player handle");
266 ade_obj<object_h> l_Shields("shields", "Shields handle");
267 ade_obj<object_h> l_Ship("ship", "Ship handle", &l_Object);
268 ade_obj<int> l_Shipclass("shipclass", "Ship class handle");
269 ade_obj<object_h> l_ShipTextures("shiptextures", "Ship textures handle");
270 ade_obj<int> l_Shiptype("shiptype", "Ship type handle");
271 ade_obj<int> l_Species("species", "Species handle");
272 ade_obj<ship_subsys_h> l_Subsystem("subsystem", "Ship subsystem handle");
273 ade_obj<int> l_Team("team", "Team handle");
274 ade_obj<int> l_Texture("texture", "Texture handle");
275 ade_obj<int> l_Wing("wing", "Wing handle");
276 ade_obj<vec3d> l_Vector("vector", "Vector object");
277 ade_obj<object_h> l_Weapon("weapon", "Weapon handle", &l_Object);
278 ade_obj<ship_bank_h> l_WeaponBank("weaponbank", "Ship/subystem weapons bank handle");
279 ade_obj<ship_banktype_h> l_WeaponBankType("weaponbanktype", "Ship/subsystem weapons bank type handle");
280 ade_obj<int> l_Weaponclass("weaponclass", "Weapon class handle");
281 */
282 //###########################################################
283 //########################<IMPORTANT>########################
284 //###########################################################
285 //If you are a coder who wants to add libraries, functions,
286 //or objects to Lua, then you want to be below this point.
287 //###########################################################
288 //########################</IMPORTANT>#######################
289 //###########################################################
290 
291 //**********OBJECT: orientation matrix
292 //WMC - So matrix can use vector, I define it up here.
293 ade_obj<vec3d> l_Vector("vector", "Vector object");
294 //WMC - Due to the exorbitant times required to store matrix data,
295 //I initially store the matrix in this struct.
296 #define MH_FINE 0
297 #define MH_MATRIX_OUTOFDATE 1
298 #define MH_ANGLES_OUTOFDATE 2
299 struct matrix_h {
300 private:
301  int status;
302 
303  matrix mtx;
304  angles ang;
305 
306  //WMC - Call these to make sure what you want
307  //is up to date
308  void ValidateAngles() {
309  if(status == MH_ANGLES_OUTOFDATE) {
310  vm_extract_angles_matrix(&ang, &mtx);
311  status = MH_FINE;
312  }
313  }
314 
315  void ValidateMatrix() {
316  if(status == MH_MATRIX_OUTOFDATE) {
317  vm_angles_2_matrix(&mtx, &ang);
318  status = MH_FINE;
319  }
320  }
321 public:
323  matrix_h(matrix *in){mtx = *in; status = MH_ANGLES_OUTOFDATE;}
324  matrix_h(angles *in){ang = *in; status = MH_MATRIX_OUTOFDATE;}
325 
327  {
328  this->ValidateAngles();
329  return &ang;
330  }
331 
333  {
334  this->ValidateMatrix();
335  return &mtx;
336  }
337 
338  void SetStatus(int n_status)
339  {
340  status = n_status;
341  }
342 
343  //LOOK LOOK LOOK LOOK LOOK LOOK
344  //IMPORTANT!!!:
345  //LOOK LOOK LOOK LOOK LOOK LOOK
346  //Don't forget to set status appropriately when you change ang or mtx.
347 };
348 ade_obj<matrix_h> l_Matrix("orientation", "Orientation matrix object");
349 
350 ADE_INDEXER(l_Matrix, "p,b,h or 1-9", "Orientation component - pitch, bank, heading, or index into 3x3 matrix (1-9)", "number", "Number at the specified index, or 0 if index is invalid.")
351 {
352  matrix_h *mh;
353  char *s = NULL;
354  float newval = 0.0f;
355  int numargs = ade_get_args(L, "os|f", l_Matrix.GetPtr(&mh), &s, &newval);
356 
357  if(!numargs || s[1] != '\0')
358  return ade_set_error(L, "f", 0.0f);
359 
360  int idx=0;
361  if(s[0]=='p')
362  idx = -1;
363  else if(s[0]=='b')
364  idx = -2;
365  else if(s[0]=='h')
366  idx = -3;
367  else if(atoi(s))
368  idx = atoi(s);
369 
370  if(idx < -3 || idx==0 || idx > 9)
371  return ade_set_error(L, "f", 0.0f);
372 
373  //Handle out of date stuff.
374  float *val = NULL;
375  if(idx < 0)
376  {
377  angles *ang = mh->GetAngles();
378 
379  if(idx == -1)
380  val = &ang->p;
381  if(idx == -2)
382  val = &ang->b;
383  if(idx == -3)
384  val = &ang->h;
385  }
386  else
387  {
388  idx--; //Lua->FS2
389  val = &mh->GetMatrix()->a1d[idx];
390  }
391 
392  if(ADE_SETTING_VAR && *val != newval)
393  {
394  //WMC - I figure this is quicker
395  //than just assuming matrix or angles is diff
396  //and recalculating every time.
397 
398  if(idx < 0)
400  else
402 
403  //Might as well put this here
404  *val = newval;
405  }
406 
407  return ade_set_args(L, "f", *val);
408 }
409 
410 ADE_FUNC(__mul, l_Matrix, "orientation", "Multiplies two matrix objects)", "orientation", "matrix, or empty matrix if unsuccessful")
411 {
412  matrix_h *mha=NULL, *mhb=NULL;
413  if(!ade_get_args(L, "oo", l_Matrix.GetPtr(&mha), l_Matrix.GetPtr(&mhb)))
414  return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
415 
416  matrix mr;
417 
418  vm_matrix_x_matrix(&mr, mha->GetMatrix(), mhb->GetMatrix());
419 
420  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&mr)));
421 }
422 
423 ADE_FUNC(__tostring, l_Matrix, NULL, "Converts a matrix to a string with format \"[r1c1 r2c1 r3c1 | r1c2 r2c2 r3c2| r1c3 r2c3 r3c3]\"", "string", "Formatted string or \"<NULL\"")
424 {
425  matrix_h *mh;
426  if(!ade_get_args(L, "o", l_Matrix.GetPtr(&mh)))
427  return ade_set_error(L, "s", "<NULL>");
428 
429  char buf[128];
430  float *a = &mh->GetMatrix()->a1d[0];
431  sprintf(buf, "[%f %f %f | %f %f %f | %f %f %f]", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
432 
433  return ade_set_args(L, "s", buf);
434 }
435 
436 ADE_FUNC(getInterpolated, l_Matrix, "orientation Final, number Factor", "Returns orientation that has been interpolated to Final by Factor (0.0-1.0)", "orientation", "Interpolated orientation, or null orientation on failure")
437 {
438  matrix_h *oriA = NULL;
439  matrix_h *oriB = NULL;
440  float factor = 0.0f;
441  if(!ade_get_args(L, "oof", l_Matrix.GetPtr(&oriA), l_Matrix.GetPtr(&oriB), &factor))
442  return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
443 
444  matrix *A = oriA->GetMatrix();
445  matrix *B = oriB->GetMatrix();
447 
448  //matrix subtraction & scaling
449  for(int i = 0; i < 9; i++)
450  {
451  final.a1d[i] = A->a1d[i] + (B->a1d[i] - A->a1d[i])*factor;
452  }
453 
454  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&final)));
455 }
456 
457 ADE_FUNC(getTranspose, l_Matrix, NULL, "Returns a transpose version of the specified orientation", "orientation", "Transpose matrix, or null orientation on failure")
458 {
459  matrix_h *mh = NULL;
460  if(!ade_get_args(L, "o", l_Matrix.GetPtr(&mh)))
461  return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
462 
463  matrix final = *mh->GetMatrix();
464  vm_transpose(&final);
465 
466  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&final)));
467 }
468 
469 
470 ADE_FUNC(rotateVector, l_Matrix, "vector Input", "Returns rotated version of given vector", "vector", "Rotated vector, or empty vector on error")
471 {
472  matrix_h *mh;
473  vec3d *v3;
474  if(!ade_get_args(L, "oo", l_Matrix.GetPtr(&mh), l_Vector.GetPtr(&v3)))
475  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
476 
477  vec3d v3r;
478  vm_vec_rotate(&v3r, v3, mh->GetMatrix());
479 
480  return ade_set_args(L, "o", l_Vector.Set(v3r));
481 }
482 
483 ADE_FUNC(unrotateVector, l_Matrix, "vector Input", "Returns unrotated version of given vector", "vector", "Unrotated vector, or empty vector on error")
484 {
485  matrix_h *mh;
486  vec3d *v3;
487  if(!ade_get_args(L, "oo", l_Matrix.GetPtr(&mh), l_Vector.GetPtr(&v3)))
488  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
489 
490  vec3d v3r;
491  vm_vec_unrotate(&v3r, v3, mh->GetMatrix());
492 
493  return ade_set_args(L, "o", l_Vector.Set(v3r));
494 }
495 
496 ADE_FUNC(getUvec, l_Matrix, NULL, "Returns the vector that points up (0,1,0 unrotated by this matrix)", "vector", "Vector or null vector on error")
497 {
498  matrix_h *mh = NULL;
499  if(!ade_get_args(L, "o", l_Matrix.GetPtr(&mh)))
500  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
501 
502  return ade_set_args(L, "o", l_Vector.Set(mh->GetMatrix()->vec.uvec));
503 }
504 
505 ADE_FUNC(getFvec, l_Matrix, NULL, "Returns the vector that points to the front (0,0,1 unrotated by this matrix)", "vector", "Vector or null vector on error")
506 {
507  matrix_h *mh = NULL;
508  if(!ade_get_args(L, "o", l_Matrix.GetPtr(&mh)))
509  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
510 
511  return ade_set_args(L, "o", l_Vector.Set(mh->GetMatrix()->vec.fvec));
512 }
513 
514 ADE_FUNC(getRvec, l_Matrix, NULL, "Returns the vector that points to the right (1,0,0 unrotated by this matrix)", "vector", "Vector or null vector on error")
515 {
516  matrix_h *mh = NULL;
517  if(!ade_get_args(L, "o", l_Matrix.GetPtr(&mh)))
518  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
519 
520  return ade_set_args(L, "o", l_Vector.Set(mh->GetMatrix()->vec.rvec));
521 }
522 
523 //**********OBJECT: constant class
524 //WMC NOTE -
525 //While you can have enumeration indexes in any order, make sure
526 //that any new enumerations have indexes of NEXT INDEX (see below)
527 //or after. Don't forget to increment NEXT INDEX after you're done.
528 //=====================================
529 static const int ENUM_NEXT_INDEX = 74; // <<<<<<<<<<<<<<<<<<<<<<
530 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
531 static flag_def_list Enumerations[] = {
532  #define LE_ALPHABLEND_FILTER 14
533  { "ALPHABLEND_FILTER", LE_ALPHABLEND_FILTER, 0},
534 
535  #define LE_ALPHABLEND_NONE 27
536  { "ALPHABLEND_NONE", LE_ALPHABLEND_NONE, 0},
537 
538  #define LE_CFILE_TYPE_NORMAL 20
539  { "CFILE_TYPE_NORMAL", LE_CFILE_TYPE_NORMAL, 0},
540 
541  #define LE_CFILE_TYPE_MEMORY_MAPPED 21
542  { "CFILE_TYPE_MEMORY_MAPPED", LE_CFILE_TYPE_MEMORY_MAPPED, 0},
543 
544  #define LE_MOUSE_LEFT_BUTTON 1
545  { "MOUSE_LEFT_BUTTON", LE_MOUSE_LEFT_BUTTON, 0},
546 
547  #define LE_MOUSE_RIGHT_BUTTON 2
548  { "MOUSE_RIGHT_BUTTON", LE_MOUSE_RIGHT_BUTTON, 0},
549 
550  #define LE_MOUSE_MIDDLE_BUTTON 3
551  { "MOUSE_MIDDLE_BUTTON", LE_MOUSE_MIDDLE_BUTTON, 0},
552 
553  #define LE_ORDER_ATTACK 28
554  { "ORDER_ATTACK", LE_ORDER_ATTACK, 0},
555 
556  #define LE_ORDER_ATTACK_ANY 29
557  { "ORDER_ATTACK_ANY", LE_ORDER_ATTACK_ANY, 0},
558 
559  #define LE_ORDER_DEPART 30
560  { "ORDER_DEPART", LE_ORDER_DEPART, 0},
561 
562  #define LE_ORDER_DISABLE 31
563  { "ORDER_DISABLE", LE_ORDER_DISABLE, 0},
564 
565  #define LE_ORDER_DISARM 32
566  { "ORDER_DISARM", LE_ORDER_DISARM, 0},
567 
568  #define LE_ORDER_DOCK 33
569  { "ORDER_DOCK", LE_ORDER_DOCK, 0},
570 
571  #define LE_ORDER_EVADE 34
572  { "ORDER_EVADE", LE_ORDER_EVADE, 0},
573 
574  #define LE_ORDER_FLY_TO 35
575  { "ORDER_FLY_TO", LE_ORDER_FLY_TO, 0},
576 
577  #define LE_ORDER_FORM_ON_WING 36
578  { "ORDER_FORM_ON_WING", LE_ORDER_FORM_ON_WING, 0},
579 
580  #define LE_ORDER_GUARD 37
581  { "ORDER_GUARD", LE_ORDER_GUARD, 0},
582 
583  #define LE_ORDER_IGNORE 38
584  { "ORDER_IGNORE_SHIP", LE_ORDER_IGNORE, 0},
585 
586  #define LE_ORDER_KEEP_SAFE_DISTANCE 39
587  { "ORDER_KEEP_SAFE_DISTANCE", LE_ORDER_KEEP_SAFE_DISTANCE, 0},
588 
589  #define LE_ORDER_PLAY_DEAD 40
590  { "ORDER_PLAY_DEAD", LE_ORDER_PLAY_DEAD, 0},
591 
592  #define LE_ORDER_REARM 41
593  { "ORDER_REARM", LE_ORDER_REARM, 0},
594 
595  #define LE_ORDER_STAY_NEAR 42
596  { "ORDER_STAY_NEAR", LE_ORDER_STAY_NEAR, 0},
597 
598  #define LE_ORDER_STAY_STILL 43
599  { "ORDER_STAY_STILL", LE_ORDER_STAY_STILL, 0},
600 
601  #define LE_ORDER_UNDOCK 44
602  { "ORDER_UNDOCK", LE_ORDER_UNDOCK, 0},
603 
604  #define LE_ORDER_WAYPOINTS 45
605  { "ORDER_WAYPOINTS", LE_ORDER_WAYPOINTS, 0},
606 
607  #define LE_ORDER_WAYPOINTS_ONCE 46
608  { "ORDER_WAYPOINTS_ONCE", LE_ORDER_WAYPOINTS_ONCE, 0},
609 
610  #define LE_ORDER_ATTACK_WING 69
611  { "ORDER_ATTACK_WING", LE_ORDER_ATTACK_WING, 0},
612 
613  #define LE_ORDER_GUARD_WING 70
614  { "ORDER_GUARD_WING", LE_ORDER_GUARD_WING, 0},
615 
616  #define LE_PARTICLE_DEBUG 4
617  { "PARTICLE_DEBUG", LE_PARTICLE_DEBUG, 0},
618 
619  #define LE_PARTICLE_BITMAP 5
620  { "PARTICLE_BITMAP", LE_PARTICLE_BITMAP, 0},
621 
622  #define LE_PARTICLE_FIRE 6
623  { "PARTICLE_FIRE", LE_PARTICLE_FIRE, 0},
624 
625  #define LE_PARTICLE_SMOKE 7
626  { "PARTICLE_SMOKE", LE_PARTICLE_SMOKE, 0},
627 
628  #define LE_PARTICLE_SMOKE2 8
629  { "PARTICLE_SMOKE2", LE_PARTICLE_SMOKE2, 0},
630 
631  #define LE_PARTICLE_PERSISTENT_BITMAP 9
632  { "PARTICLE_PERSISTENT_BITMAP", LE_PARTICLE_PERSISTENT_BITMAP, 0},
633 
634  #define LE_SEXPVAR_CAMPAIGN_PERSISTENT 22
635  { "SEXPVAR_CAMPAIGN_PERSISTENT", LE_SEXPVAR_CAMPAIGN_PERSISTENT, 0},
636 
637  #define LE_SEXPVAR_NOT_PERSISTENT 23
638  { "SEXPVAR_NOT_PERSISTENT", LE_SEXPVAR_NOT_PERSISTENT, 0},
639 
640  #define LE_SEXPVAR_PLAYER_PERSISTENT 24
641  { "SEXPVAR_PLAYER_PERSISTENT", LE_SEXPVAR_PLAYER_PERSISTENT, 0},
642 
643  #define LE_SEXPVAR_TYPE_NUMBER 25
644  { "SEXPVAR_TYPE_NUMBER", LE_SEXPVAR_TYPE_NUMBER, 0},
645 
646  #define LE_SEXPVAR_TYPE_STRING 26
647  { "SEXPVAR_TYPE_STRING", LE_SEXPVAR_TYPE_STRING, 0},
648 
649  #define LE_TEXTURE_STATIC 10
650  { "TEXTURE_STATIC", LE_TEXTURE_STATIC, 0},
651 
652  #define LE_TEXTURE_DYNAMIC 11
653  { "TEXTURE_DYNAMIC", LE_TEXTURE_DYNAMIC, 0},
654 
655  #define LE_LOCK 12
656  { "LOCK", LE_LOCK, 0},
657 
658  #define LE_UNLOCK 13
659  { "UNLOCK", LE_UNLOCK, 0},
660 
661  #define LE_NONE 15
662  { "NONE", LE_NONE, 0},
663 
664  #define LE_SHIELD_FRONT 16
665  { "SHIELD_FRONT", LE_SHIELD_FRONT, 0},
666 
667  #define LE_SHIELD_LEFT 17
668  { "SHIELD_LEFT", LE_SHIELD_LEFT, 0},
669 
670  #define LE_SHIELD_RIGHT 18
671  { "SHIELD_RIGHT", LE_SHIELD_RIGHT, 0},
672 
673  #define LE_SHIELD_BACK 19
674  { "SHIELD_BACK", LE_SHIELD_BACK, 0},
675 
676  #define LE_MISSION_REPEAT 47
677  { "MISSION_REPEAT", LE_MISSION_REPEAT, 0},
678 
679  #define LE_NORMAL_CONTROLS 48
680  { "NORMAL_CONTROLS", LE_NORMAL_CONTROLS, 0},
681 
682  #define LE_LUA_STEERING_CONTROLS 49
683  { "LUA_STEERING_CONTROLS", LE_LUA_STEERING_CONTROLS, 0},
684 
685  #define LE_LUA_FULL_CONTROLS 50
686  { "LUA_FULL_CONTROLS", LE_LUA_FULL_CONTROLS, 0},
687 
688  #define LE_NORMAL_BUTTON_CONTROLS 51
689  { "NORMAL_BUTTON_CONTROLS", LE_NORMAL_BUTTON_CONTROLS, 0},
690 
691  #define LE_LUA_ADDITIVE_BUTTON_CONTROL 52
692  { "LUA_ADDITIVE_BUTTON_CONTROL", LE_LUA_ADDITIVE_BUTTON_CONTROL, 0},
693 
694  #define LE_LUA_OVERRIDE_BUTTON_CONTROL 53
695  { "LUA_OVERRIDE_BUTTON_CONTROL", LE_LUA_OVERRIDE_BUTTON_CONTROL, 0},
696 
697  #define LE_VM_INTERNAL 54
698  { "VM_INTERNAL", LE_VM_INTERNAL, 0},
699 
700  #define LE_VM_EXTERNAL 55
701  { "VM_EXTERNAL", LE_VM_EXTERNAL, 0},
702 
703  #define LE_VM_TRACK 56
704  { "VM_TRACK", LE_VM_TRACK, 0},
705 
706  #define LE_VM_DEAD_VIEW 57
707  { "VM_DEAD_VIEW", LE_VM_DEAD_VIEW, 0},
708 
709  #define LE_VM_CHASE 58
710  { "VM_CHASE", LE_VM_CHASE, 0},
711 
712  #define LE_VM_OTHER_SHIP 59
713  { "VM_OTHER_SHIP", LE_VM_OTHER_SHIP, 0},
714 
715  #define LE_VM_EXTERNAL_CAMERA_LOCKED 60
716  { "VM_EXTERNAL_CAMERA_LOCKED", LE_VM_EXTERNAL_CAMERA_LOCKED, 0},
717 
718  #define LE_VM_WARP_CHASE 61
719  { "VM_WARP_CHASE", LE_VM_WARP_CHASE, 0},
720 
721  #define LE_VM_PADLOCK_UP 62
722  { "VM_PADLOCK_UP", LE_VM_PADLOCK_UP, 0},
723 
724  #define LE_VM_PADLOCK_REAR 63
725  { "VM_PADLOCK_REAR", LE_VM_PADLOCK_REAR, 0},
726 
727  #define LE_VM_PADLOCK_LEFT 64
728  { "VM_PADLOCK_LEFT", LE_VM_PADLOCK_LEFT, 0},
729 
730  #define LE_VM_PADLOCK_RIGHT 65
731  { "VM_PADLOCK_RIGHT", LE_VM_PADLOCK_RIGHT, 0},
732 
733  #define LE_VM_WARPIN_ANCHOR 66
734  { "VM_WARPIN_ANCHOR", LE_VM_WARPIN_ANCHOR, 0},
735 
736  #define LE_VM_TOPDOWN 67
737  { "VM_TOPDOWN", LE_VM_TOPDOWN, 0},
738 
739  #define LE_VM_FREECAMERA 68
740  { "VM_FREECAMERA", LE_VM_FREECAMERA, 0},
741 
742  #define LE_MESSAGE_PRIORITY_LOW 71
743  { "MESSAGE_PRIORITY_LOW", LE_MESSAGE_PRIORITY_LOW, 0},
744 
745  #define LE_MESSAGE_PRIORITY_NORMAL 72
746  { "MESSAGE_PRIORITY_NORMAL", LE_MESSAGE_PRIORITY_NORMAL, 0},
747 
748  #define LE_MESSAGE_PRIORITY_HIGH 73
749  { "MESSAGE_PRIORITY_HIGH", LE_MESSAGE_PRIORITY_HIGH, 0},
750 };
751 
752 //DO NOT FORGET to increment NEXT INDEX: !!!!!!!!!!!!!
753 
754 static uint Num_enumerations = sizeof(Enumerations) / sizeof(flag_def_list);
755 
757  { "TARGET_NEXT", TARGET_NEXT, 0 },
758  { "TARGET_PREV", TARGET_PREV, 0 },
759  { "TARGET_NEXT_CLOSEST_HOSTILE", TARGET_NEXT_CLOSEST_HOSTILE, 0 },
760  { "TARGET_PREV_CLOSEST_HOSTILE", TARGET_PREV_CLOSEST_HOSTILE, 0 },
761  { "TOGGLE_AUTO_TARGETING", TOGGLE_AUTO_TARGETING, 0 },
762  { "TARGET_NEXT_CLOSEST_FRIENDLY", TARGET_NEXT_CLOSEST_FRIENDLY, 0 },
763  { "TARGET_PREV_CLOSEST_FRIENDLY", TARGET_PREV_CLOSEST_FRIENDLY, 0 },
764  { "TARGET_SHIP_IN_RETICLE", TARGET_SHIP_IN_RETICLE, 0 },
765  { "TARGET_CLOSEST_SHIP_ATTACKING_TARGET", TARGET_CLOSEST_SHIP_ATTACKING_TARGET, 0 },
766  { "TARGET_LAST_TRANMISSION_SENDER", TARGET_LAST_TRANMISSION_SENDER, 0 },
767  { "STOP_TARGETING_SHIP", STOP_TARGETING_SHIP, 0 },
768  { "TARGET_SUBOBJECT_IN_RETICLE", TARGET_SUBOBJECT_IN_RETICLE, 0 },
769  { "TARGET_NEXT_SUBOBJECT", TARGET_NEXT_SUBOBJECT, 0 },
770  { "TARGET_PREV_SUBOBJECT", TARGET_PREV_SUBOBJECT, 0 },
771  { "STOP_TARGETING_SUBSYSTEM", STOP_TARGETING_SUBSYSTEM, 0 },
772  { "MATCH_TARGET_SPEED", MATCH_TARGET_SPEED, 0 },
773  { "TOGGLE_AUTO_MATCH_TARGET_SPEED", TOGGLE_AUTO_MATCH_TARGET_SPEED, 0 },
774  { "FIRE_PRIMARY", FIRE_PRIMARY, 0 },
775  { "FIRE_SECONDARY", FIRE_SECONDARY, 0 },
776  { "CYCLE_NEXT_PRIMARY", CYCLE_NEXT_PRIMARY, 0 },
777  { "CYCLE_PREV_PRIMARY", CYCLE_PREV_PRIMARY, 0 },
778  { "CYCLE_SECONDARY", CYCLE_SECONDARY, 0 },
779  { "CYCLE_NUM_MISSLES", CYCLE_NUM_MISSLES, 0 },
780  { "LAUNCH_COUNTERMEASURE", LAUNCH_COUNTERMEASURE, 0 },
781  { "FORWARD_THRUST", FORWARD_THRUST, 0 },
782  { "REVERSE_THRUST", REVERSE_THRUST, 0 },
783  { "BANK_LEFT", BANK_LEFT, 0 },
784  { "BANK_RIGHT", BANK_RIGHT, 0 },
785  { "PITCH_FORWARD", PITCH_FORWARD, 0 },
786  { "PITCH_BACK", PITCH_BACK, 0 },
787  { "YAW_LEFT", YAW_LEFT, 0 },
788  { "YAW_RIGHT", YAW_RIGHT, 0 },
789  { "ZERO_THROTTLE", ZERO_THROTTLE, 1 },
790  { "MAX_THROTTLE", MAX_THROTTLE, 1 },
791  { "ONE_THIRD_THROTTLE", ONE_THIRD_THROTTLE, 1 },
792  { "TWO_THIRDS_THROTTLE", TWO_THIRDS_THROTTLE, 1 },
793  { "PLUS_5_PERCENT_THROTTLE", PLUS_5_PERCENT_THROTTLE, 1 },
794  { "MINUS_5_PERCENT_THROTTLE", MINUS_5_PERCENT_THROTTLE, 1 },
795  { "ATTACK_MESSAGE", ATTACK_MESSAGE, 1 },
796  { "DISARM_MESSAGE", DISARM_MESSAGE, 1 },
797  { "DISABLE_MESSAGE", DISABLE_MESSAGE, 1 },
798  { "ATTACK_SUBSYSTEM_MESSAGE", ATTACK_SUBSYSTEM_MESSAGE, 1 },
799  { "CAPTURE_MESSAGE", CAPTURE_MESSAGE, 1 },
800  { "ENGAGE_MESSAGE", ENGAGE_MESSAGE, 1 },
801  { "FORM_MESSAGE", FORM_MESSAGE, 1 },
802  { "IGNORE_MESSAGE", IGNORE_MESSAGE, 1 },
803  { "PROTECT_MESSAGE", PROTECT_MESSAGE, 1 },
804  { "COVER_MESSAGE", COVER_MESSAGE, 1 },
805  { "WARP_MESSAGE", WARP_MESSAGE, 1 },
806  { "REARM_MESSAGE", REARM_MESSAGE, 1 },
807  { "TARGET_CLOSEST_SHIP_ATTACKING_SELF", TARGET_CLOSEST_SHIP_ATTACKING_SELF, 1 },
808  { "VIEW_CHASE", VIEW_CHASE, 1 },
809  { "VIEW_EXTERNAL", VIEW_EXTERNAL, 1 },
810  { "VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK", VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK, 1 },
811  { "VIEW_SLEW", VIEW_SLEW, 1 },
812  { "VIEW_OTHER_SHIP", VIEW_OTHER_SHIP, 1 },
813  { "VIEW_DIST_INCREASE", VIEW_DIST_INCREASE, 1 },
814  { "VIEW_DIST_DECREASE", VIEW_DIST_DECREASE, 1 },
815  { "VIEW_CENTER", VIEW_CENTER, 1 },
816  { "PADLOCK_UP", PADLOCK_UP, 1 },
817  { "PADLOCK_DOWN", PADLOCK_DOWN, 1 },
818  { "PADLOCK_LEFT", PADLOCK_LEFT, 1 },
819  { "PADLOCK_RIGHT", PADLOCK_RIGHT, 1 },
820  { "RADAR_RANGE_CYCLE", RADAR_RANGE_CYCLE, 1 },
821  { "SQUADMSG_MENU", SQUADMSG_MENU, 2 },
822  { "SHOW_GOALS", SHOW_GOALS, 2 },
823  { "END_MISSION", END_MISSION, 2 },
824  { "TARGET_TARGETS_TARGET", TARGET_TARGETS_TARGET, 2 },
825  { "AFTERBURNER", AFTERBURNER, 2 },
826  { "INCREASE_WEAPON", INCREASE_WEAPON, 2 },
827  { "DECREASE_WEAPON", DECREASE_WEAPON, 2 },
828  { "INCREASE_SHIELD", INCREASE_SHIELD, 2 },
829  { "DECREASE_SHIELD", DECREASE_SHIELD, 2 },
830  { "INCREASE_ENGINE", INCREASE_ENGINE, 2 },
831  { "DECREASE_ENGINE", DECREASE_ENGINE, 2 },
832  { "ETS_EQUALIZE", ETS_EQUALIZE, 2 },
833  { "SHIELD_EQUALIZE", SHIELD_EQUALIZE, 2 },
834  { "SHIELD_XFER_TOP", SHIELD_XFER_TOP, 2 },
835  { "SHIELD_XFER_BOTTOM", SHIELD_XFER_BOTTOM, 2 },
836  { "SHIELD_XFER_LEFT", SHIELD_XFER_LEFT, 2 },
837  { "SHIELD_XFER_RIGHT", SHIELD_XFER_RIGHT, 2 },
838  { "XFER_SHIELD", XFER_SHIELD, 2 },
839  { "XFER_LASER", XFER_LASER, 2 },
840  { "GLIDE_WHEN_PRESSED", GLIDE_WHEN_PRESSED, 2 },
841  { "BANK_WHEN_PRESSED", BANK_WHEN_PRESSED, 2 },
842  { "SHOW_NAVMAP", SHOW_NAVMAP, 2 },
843  { "ADD_REMOVE_ESCORT", ADD_REMOVE_ESCORT, 2 },
844  { "ESCORT_CLEAR", ESCORT_CLEAR, 2 },
845  { "TARGET_NEXT_ESCORT_SHIP", TARGET_NEXT_ESCORT_SHIP, 2 },
846  { "TARGET_CLOSEST_REPAIR_SHIP", TARGET_CLOSEST_REPAIR_SHIP, 2 },
847  { "TARGET_NEXT_UNINSPECTED_CARGO", TARGET_NEXT_UNINSPECTED_CARGO, 2 },
848  { "TARGET_PREV_UNINSPECTED_CARGO", TARGET_PREV_UNINSPECTED_CARGO, 2 },
849  { "TARGET_NEWEST_SHIP", TARGET_NEWEST_SHIP, 2 },
850  { "TARGET_NEXT_LIVE_TURRET", TARGET_NEXT_LIVE_TURRET, 2 },
851  { "TARGET_PREV_LIVE_TURRET", TARGET_PREV_LIVE_TURRET, 2 },
852  { "TARGET_NEXT_BOMB", TARGET_NEXT_BOMB, 2 },
853  { "TARGET_PREV_BOMB", TARGET_PREV_BOMB, 3 },
854  { "MULTI_MESSAGE_ALL", MULTI_MESSAGE_ALL, 3 },
855  { "MULTI_MESSAGE_FRIENDLY", MULTI_MESSAGE_FRIENDLY, 3 },
856  { "MULTI_MESSAGE_HOSTILE", MULTI_MESSAGE_HOSTILE, 3 },
857  { "MULTI_MESSAGE_TARGET", MULTI_MESSAGE_TARGET, 3 },
858  { "MULTI_OBSERVER_ZOOM_TO", MULTI_OBSERVER_ZOOM_TO, 3 },
859  { "TIME_SPEED_UP", TIME_SPEED_UP, 3 },
860  { "TIME_SLOW_DOWN", TIME_SLOW_DOWN, 3 },
861  { "TOGGLE_HUD_CONTRAST", TOGGLE_HUD_CONTRAST, 3 },
862  { "MULTI_TOGGLE_NETINFO", MULTI_TOGGLE_NETINFO, 3 },
863  { "MULTI_SELF_DESTRUCT", MULTI_SELF_DESTRUCT, 3 },
864  { "TOGGLE_HUD", TOGGLE_HUD, 3 },
865  { "RIGHT_SLIDE_THRUST", RIGHT_SLIDE_THRUST, 3 },
866  { "LEFT_SLIDE_THRUST", LEFT_SLIDE_THRUST, 3 },
867  { "UP_SLIDE_THRUST", UP_SLIDE_THRUST, 3 },
868  { "DOWN_SLIDE_THRUST", DOWN_SLIDE_THRUST, 3 },
869  { "HUD_TARGETBOX_TOGGLE_WIREFRAME", HUD_TARGETBOX_TOGGLE_WIREFRAME, 3 },
870  { "VIEW_TOPDOWN", VIEW_TOPDOWN, 3 },
871  { "VIEW_TRACK_TARGET", VIEW_TRACK_TARGET, 3 },
872  { "AUTO_PILOT_TOGGLE", AUTO_PILOT_TOGGLE, 3 },
873  { "NAV_CYCLE", NAV_CYCLE, 3 },
874  { "TOGGLE_GLIDING", TOGGLE_GLIDING, 3 },
875 };
876 
878 
879 struct enum_h {
880  int index;
882 
883  enum_h(){index=-1; is_constant=false;}
884  enum_h(int n_index){index=n_index; is_constant=false;}
885 
886  bool IsValid(){return (index > -1 && index < ENUM_NEXT_INDEX);}
887 };
888 ade_obj<enum_h> l_Enum("enumeration", "Enumeration object");
889 
890 ADE_FUNC(__newindex, l_Enum, "enumeration", "Sets enumeration to specified value (if it is not a global", "enumeration", "enumeration")
891 {
892  enum_h *e1=NULL, *e2=NULL;
893  if(!ade_get_args(L, "oo", l_Enum.GetPtr(&e1), l_Enum.GetPtr(&e2)))
894  return ade_set_error(L, "o", l_Enum.Set(enum_h()));
895 
896  if(!e1->is_constant)
897  e1->index = e2->index;
898 
899  return ade_set_args(L, "o", l_Enum.Set(*e1));
900 }
901 
902 ADE_FUNC(__tostring, l_Enum, NULL, "Returns enumeration name", "string", "Enumeration name, or \"<INVALID>\" if invalid")
903 {
904  enum_h *e = NULL;
905  if(!ade_get_args(L, "o", l_Enum.GetPtr(&e)))
906  return ade_set_args(L, "s", "<INVALID>");
907 
908  if(e->index < 1 || e->index >= ENUM_NEXT_INDEX)
909  return ade_set_args(L, "s", "<INVALID>");
910 
911  uint i;
912  for(i = 0; i < Num_enumerations; i++)
913  {
914  if(Enumerations[i].def == e->index)
915  return ade_set_args(L, "s", Enumerations[i].name);
916  }
917 
918  return ade_set_args(L, "s", "<INVALID>");
919 }
920 
921 ADE_FUNC(__eq, l_Enum, "enumeration", "Compares the two enumerations for equality", "boolean", "true if equal, false otherwise")
922 {
923  enum_h *e1 = NULL;
924  enum_h *e2 = NULL;
925 
926  if(!ade_get_args(L, "oo", l_Enum.GetPtr(&e1), l_Enum.GetPtr(&e2)))
927  return ade_set_error(L, "o", l_Enum.Set(enum_h()));
928 
929  if (e1 == NULL || e2 == NULL)
930  return ADE_RETURN_FALSE;
931 
932  return ade_set_args(L, "b", e1->index == e2->index);
933 }
934 
935 //**********HANDLE: event
936 ade_obj<int> l_Event("event", "Mission event handle");
937 
938 ADE_VIRTVAR(Name, l_Event, "string", "Mission event name", "string", NULL)
939 {
940  int idx;
941  char *s = NULL;
942  if(!ade_get_args(L, "o|s", l_Event.Get(&idx), &s))
943  return ade_set_error(L, "s", "");
944 
945  if(idx < 0 || idx >= Num_mission_events)
946  return ade_set_error(L, "s", "");
947 
949 
950  if(ADE_SETTING_VAR) {
951  strncpy(mep->name, s, sizeof(mep->name) - sizeof(char));
952  }
953 
954  return ade_set_args(L, "s", mep->name);
955 }
956 
957 ADE_VIRTVAR(DirectiveText, l_Event, "string", "Directive text", "string", NULL)
958 {
959  int idx;
960  char *s = NULL;
961  if(!ade_get_args(L, "o|s", l_Event.Get(&idx), &s))
962  return ade_set_error(L, "s", "");
963 
964  if(idx < 0 || idx >= Num_mission_events)
965  return ade_set_error(L, "s", "");
966 
968 
969  if(ADE_SETTING_VAR && s != NULL) {
970  if(mep->objective_text != NULL)
971  vm_free(mep->objective_text);
972 
973  mep->objective_text = vm_strdup(s);
974  }
975 
976  if(mep->objective_text != NULL)
977  return ade_set_args(L, "s", mep->objective_text);
978  else
979  return ade_set_args(L, "s", "");
980 }
981 
982 ADE_VIRTVAR(DirectiveKeypressText, l_Event, "string", "Raw directive keypress text, as seen in FRED.", "string", NULL)
983 {
984  int idx;
985  char *s = NULL;
986  if(!ade_get_args(L, "o|s", l_Event.Get(&idx), &s))
987  return ade_set_error(L, "s", "");
988 
989  if(idx < 0 || idx >= Num_mission_events)
990  return ade_set_error(L, "s", "");
991 
993 
994  if(ADE_SETTING_VAR && s != NULL) {
995  if(mep->objective_text != NULL)
997 
998  mep->objective_key_text = vm_strdup(s);
999  }
1000 
1001  if(mep->objective_key_text != NULL)
1002  return ade_set_args(L, "s", mep->objective_key_text);
1003  else
1004  return ade_set_args(L, "s", "");
1005 }
1006 
1007 ADE_VIRTVAR(Interval, l_Event, "number", "Time for event to repeat (in seconds)", "number", "Repeat time, or 0 if invalid handle")
1008 {
1009  int idx;
1010  int newinterval = 0;
1011  if(!ade_get_args(L, "o|i", l_Event.Get(&idx), &newinterval))
1012  return ade_set_error(L, "i", 0);
1013 
1014  if(idx < 0 || idx >= Num_mission_events)
1015  return ade_set_error(L, "i", 0);
1016 
1018 
1020  mep->interval = newinterval;
1021  }
1022 
1023  return ade_set_args(L, "i", mep->interval);
1024 }
1025 
1026 ADE_VIRTVAR(ObjectCount, l_Event, "number", "Number of objects left for event", "number", "Repeat count, or 0 if invalid handle")
1027 {
1028  int idx;
1029  int newobject = 0;
1030  if(!ade_get_args(L, "o|i", l_Event.Get(&idx), &newobject))
1031  return ade_set_error(L, "i", 0);
1032 
1033  if(idx < 0 || idx >= Num_mission_events)
1034  return ade_set_error(L, "i", 0);
1035 
1036  mission_event *mep = &Mission_events[idx];
1037 
1038  if(ADE_SETTING_VAR) {
1039  mep->count = newobject;
1040  }
1041 
1042  return ade_set_args(L, "i", mep->count);
1043 }
1044 
1045 ADE_VIRTVAR(RepeatCount, l_Event, "number", "Event repeat count", "number", "Repeat count, or 0 if invalid handle")
1046 {
1047  int idx;
1048  int newrepeat = 0;
1049  if(!ade_get_args(L, "o|i", l_Event.Get(&idx), &newrepeat))
1050  return ade_set_error(L, "i", 0);
1051 
1052  if(idx < 0 || idx >= Num_mission_events)
1053  return ade_set_error(L, "i", 0);
1054 
1055  mission_event *mep = &Mission_events[idx];
1056 
1057  if(ADE_SETTING_VAR) {
1058  mep->repeat_count = newrepeat;
1059  }
1060 
1061  return ade_set_args(L, "i", mep->repeat_count);
1062 }
1063 
1064 ADE_VIRTVAR(Score, l_Event, "number", "Event score", "number", "Event score, or 0 if invalid handle")
1065 {
1066  int idx;
1067  int newscore = 0;
1068  if(!ade_get_args(L, "o|i", l_Event.Get(&idx), &newscore))
1069  return ade_set_error(L, "i", 0);
1070 
1071  if(idx < 0 || idx >= Num_mission_events)
1072  return ade_set_error(L, "i", 0);
1073 
1074  mission_event *mep = &Mission_events[idx];
1075 
1076  if(ADE_SETTING_VAR) {
1077  mep->score = newscore;
1078  }
1079 
1080  return ade_set_args(L, "i", mep->score);
1081 }
1082 
1083 ADE_FUNC(isValid, l_Event, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
1084 {
1085  int idx;
1086  if(!ade_get_args(L, "o", l_Event.Get(&idx)))
1087  return ADE_RETURN_NIL;
1088 
1089  if(idx < 0 || idx >= Num_mission_events)
1090  return ADE_RETURN_FALSE;
1091 
1092  return ADE_RETURN_TRUE;
1093 }
1094 
1095 //**********HANDLE: File
1096 
1097 ade_obj<CFILE*> l_File("file", "File handle");
1098 
1099 ADE_FUNC(isValid, l_File, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
1100 {
1101  CFILE *cfp = NULL;
1102  if(!ade_get_args(L, "o", l_File.Get(&cfp)))
1103  return ADE_RETURN_NIL;
1104 
1105  if(!cf_is_valid(cfp))
1106  return ADE_RETURN_FALSE;
1107 
1108  return ADE_RETURN_TRUE;
1109 }
1110 
1111 ADE_FUNC(close, l_File, NULL, "Instantly closes file and invalidates all file handles", NULL, NULL)
1112 {
1113  CFILE *cfp;
1114  if(!ade_get_args(L, "o", l_File.Get(&cfp)))
1115  return ADE_RETURN_FALSE;
1116 
1117  if(!cf_is_valid(cfp))
1118  return ADE_RETURN_FALSE;
1119 
1120  int rval = cfclose(cfp);
1121  if(rval != 0)
1122  {
1123  LuaError(L, "Attempt to close file resulted in error %d", rval);
1124  return ADE_RETURN_FALSE;
1125  }
1126  return ADE_RETURN_TRUE;
1127 }
1128 
1129 ADE_FUNC(flush, l_File, NULL, "Flushes file buffer to disk.", "boolean", "True for success, false on failure")
1130 {
1131  CFILE *cfp = NULL;
1132  if(!ade_get_args(L, "o", l_File.Get(&cfp)))
1133  return ADE_RETURN_FALSE;
1134 
1135  if(!cf_is_valid(cfp))
1136  return ADE_RETURN_FALSE;
1137 
1138  //WMC - this looks reversed, yes, it's right. Look at cflush.
1139  int cf_result = cflush(cfp);
1140  return ade_set_args(L, "b", cf_result ? false : true);
1141 }
1142 
1143 ADE_FUNC(getPath, l_File, NULL, "Determines path of the given file", "string", "Path string of the file handle, or an empty string if it doesn't have one, or the handle is invalid")
1144 {
1145  CFILE *cfp = NULL;
1146  if(!ade_get_args(L, "o", l_File.Get(&cfp)))
1147  return ade_set_error(L, "s", "");
1148 
1149  if(!cf_is_valid(cfp))
1150  return ade_set_error(L, "s", "");
1151 
1152  int id = cf_get_dir_type(cfp);
1153  if(Pathtypes[id].path != NULL)
1154  return ade_set_args(L, "s", Pathtypes[id].path);
1155  else
1156  return ade_set_args(L, "s", "");
1157 }
1158 
1159 extern int cfread_lua_number(double *buf, CFILE *cfile);
1160 ADE_FUNC(read, l_File, "number or string, ...",
1161  "Reads part of or all of a file, depending on arguments passed. Based on basic Lua file:read function."
1162  "Returns nil when the end of the file is reached."
1163  "<br><ul><li>\"*n\" - Reads a number.</li>"
1164  "<li>\"*a\" - Reads the rest of the file and returns it as a string.</li>"
1165  "<li>\"*l\" - Reads a line. Skips the end of line markers.</li>"
1166  "<li>(number) - Reads given number of characters, then returns them as a string.</li></ul>",
1167  "number or string, ...",
1168  "Requested data, or nil if the function fails")
1169 {
1170  CFILE *cfp = NULL;
1171  if(!ade_get_args(L, "o", l_File.Get(&cfp)))
1172  return ADE_RETURN_NIL;
1173 
1174  if(!cf_is_valid(cfp))
1175  return ADE_RETURN_NIL;
1176 
1177  int i;
1178  int num_returned = 0;
1179  int type = LUA_TNONE;
1180 
1181  //WMC - Since we push stuff onto the stack, we must get
1182  //the original arguments NOW.
1183  int lastarg = lua_gettop(L);
1184  for(i = 2; i <= lastarg; i++)
1185  {
1186  type = lua_type(L, i);
1187  char *fmt = NULL;
1188  //int num = 0;
1189  if(type == LUA_TSTRING)
1190  {
1191  fmt = (char*)lua_tostring(L, i);
1192  if(!stricmp(fmt, "*n"))
1193  {
1194  double d = 0.0f;
1195  if(cfread_lua_number(&d, cfp) == EOF)
1196  return ADE_RETURN_NIL;
1197 
1198  lua_pushnumber(L, d);
1199  num_returned++;
1200  }
1201  else if(!stricmp(fmt, "*a"))
1202  {
1203  int tell_res = cftell(cfp);
1204  if(tell_res < 0)
1205  {
1206  Error(LOCATION, "Critical error reading Lua file; could not cftell.");
1207  }
1208  int read_len = cfilelength(cfp) - tell_res;
1209 
1210  char *buf = (char *)vm_malloc(read_len + 1);
1211  int final_len = cfread(buf, 1, read_len, cfp);
1212  buf[final_len] = '\0';
1213 
1214  lua_pushstring(L, buf);
1215  vm_free(buf);
1216  num_returned++;
1217  }
1218  else if(!stricmp(fmt, "*l"))
1219  {
1220  char buf[10240];
1221  size_t idx;
1222  if(cfgets(buf, (int)(sizeof(buf)/sizeof(char)), cfp) == NULL)
1223  {
1224  lua_pushnil(L);
1225  }
1226  else
1227  {
1228  // Strip all newlines so this works like the Lua original
1229  // http://www.lua.org/source/5.1/liolib.c.html#g_read
1230  // Note: we also strip carriage return in WMC's implementation
1231  for (idx = 0; idx < strlen(buf); idx++)
1232  {
1233  if ( buf[idx] == '\n' || buf[idx] == '\r' )
1234  buf[idx] = '\0';
1235  }
1236 
1237  lua_pushstring(L, buf);
1238  }
1239  num_returned++;
1240  }
1241  }
1242  if(type == LUA_TNUMBER || (type == LUA_TSTRING && strpbrk(fmt, "1234567890")))
1243  {
1244  int num = 0;
1245  if(type == LUA_TSTRING)
1246  num = atoi(fmt);
1247  else
1248  num = fl2i(lua_tonumber(L, i));
1249 
1250  if(num < 1)
1251  {
1252  if(cfeof(cfp))
1253  lua_pushstring(L, "");
1254  else
1255  lua_pushnil(L);
1256  }
1257 
1258  char *buf = (char*)vm_malloc(num+1);
1259  int total_read = cfread(buf, 1, num, cfp);
1260  if(total_read)
1261  {
1262  buf[total_read] = '\0';
1263  lua_pushstring(L, buf);
1264  }
1265  else
1266  {
1267  lua_pushnil(L);
1268  }
1269  vm_free(buf);
1270  num_returned++;
1271  }
1272  if(type != LUA_TNUMBER && type != LUA_TSTRING)
1273  LuaError(L, "Invalid argument passed to file:read");
1274  }
1275 
1276  return num_returned;
1277 }
1278 
1279 ADE_FUNC(seek, l_File, "[string Whence=\"cur\", number Offset=0]",
1280  "Changes position of file, or gets location."
1281  "Whence can be:"
1282  "<li>\"set\" - File start.</li>"
1283  "<li>\"cur\" - Current position in file.</li>"
1284  "<li>\"end\" - File end.</li></ul>",
1285  "number",
1286  "new offset, or false or nil on failure")
1287 {
1288  char *w = NULL;
1289  int o = 0;
1290 
1291  CFILE *cfp = NULL;
1292  if(!ade_get_args(L, "o|si", l_File.Get(&cfp), &w, &o))
1293  return ADE_RETURN_NIL;
1294 
1295  if(!cf_is_valid(cfp))
1296  return ADE_RETURN_NIL;
1297 
1298  if(!(w == NULL || (!stricmp(w, "cur") && o != 0)))
1299  {
1300  int seek_type = CF_SEEK_CUR;
1301  if(!stricmp(w, "set"))
1302  seek_type = CF_SEEK_SET;
1303  else if(!stricmp(w, "cur"))
1304  seek_type = CF_SEEK_CUR;
1305  else if(!stricmp(w, "end"))
1306  seek_type = CF_SEEK_END;
1307  else
1308  LuaError(L, "Invalid where argument passed to seek() - '%s'", w);
1309 
1310  if(cfseek(cfp, o, seek_type))
1311  return ADE_RETURN_FALSE;
1312  }
1313 
1314  int res = cftell(cfp);
1315  if(res >= 0)
1316  return ade_set_args(L, "i", res);
1317  else
1318  return ADE_RETURN_FALSE;
1319 }
1320 
1321 ADE_FUNC(write, l_File, "string or number, ...",
1322  "Writes a series of Lua strings or numbers to the current file.", "number", "Number of items successfully written.")
1323 {
1324  CFILE *cfp = NULL;
1325  if(!ade_get_args(L, "o", l_File.Get(&cfp)))
1326  return ade_set_error(L, "i", 0);
1327 
1328  if(!cf_is_valid(cfp))
1329  return ade_set_error(L, "i", 0);
1330 
1331  int l_pos = 2;
1332  int type = LUA_TNONE;
1333 
1334  int num_successful = 0;
1335  while((type = lua_type(L, l_pos)) != LUA_TNONE)
1336  {
1337  if(type == LUA_TSTRING)
1338  {
1339  char *s = (char*)lua_tostring(L, l_pos);
1340  if(cfwrite(s, sizeof(char), strlen(s), cfp))
1341  num_successful++;
1342  }
1343  else if(type == LUA_TNUMBER)
1344  {
1345  double d = lua_tonumber(L, l_pos);
1346  char buf[32]= {0};
1347  sprintf(buf, LUA_NUMBER_FMT, d);
1348  if(cfwrite(buf, sizeof(char), strlen(buf), cfp))
1349  num_successful++;
1350  }
1351 
1352  l_pos++;
1353  }
1354 
1355  return ade_set_args(L, "i", num_successful);
1356 }
1357 
1358 //**********HANDLE: Font
1359 ade_obj<int> l_Font("font", "font handle");
1360 
1361 ADE_FUNC(__tostring, l_Font, NULL, "Filename of font", "string", "Font filename, or an empty string if the handle is invalid")
1362 {
1363  int font_num = -1;
1364  if(!ade_get_args(L, "o", l_Font.Get(&font_num)))
1365  return ade_set_error(L, "s", "");
1366 
1367  if(font_num < 0 || font_num >= Num_fonts)
1368  return ade_set_error(L, "s", "");
1369 
1370  return ade_set_args(L, "s", Fonts[font_num].filename);
1371 }
1372 
1373 ADE_VIRTVAR(Filename, l_Font, "string", "Filename of font (including extension)", "string", NULL)
1374 {
1375  int font_num = -1;
1376  char *newname = NULL;
1377  if(!ade_get_args(L, "o|s", l_Font.Get(&font_num), &newname))
1378  return ade_set_error(L, "s", "");
1379 
1380  if(font_num < 0 || font_num >= Num_fonts)
1381  return ade_set_error(L, "s", "");
1382 
1383  if(ADE_SETTING_VAR) {
1384  strncpy(Fonts[font_num].filename, newname, sizeof(Fonts[font_num].filename)-1);
1385  }
1386 
1387  return ade_set_args(L, "s", Fonts[font_num].filename);
1388 }
1389 
1390 ADE_VIRTVAR(Height, l_Font, "number", "Height of font (in pixels)", "number", "Font height, or 0 if the handle is invalid")
1391 {
1392  int font_num = -1;
1393  int newheight = -1;
1394  if(!ade_get_args(L, "o|i", l_Font.Get(&font_num), &newheight))
1395  return ade_set_error(L, "i", 0);
1396 
1397  if(font_num < 0 || font_num >= Num_fonts)
1398  return ade_set_error(L, "i", 0);
1399 
1400  if(ADE_SETTING_VAR && newheight > 0) {
1401  Fonts[font_num].h = newheight;
1402  }
1403 
1404  return ade_set_args(L, "i", Fonts[font_num].h);
1405 }
1406 
1407 ADE_FUNC(isValid, l_Font, NULL, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid")
1408 {
1409  int font_num;
1410  if(!ade_get_args(L, "o", l_Font.Get(&font_num)))
1411  return ADE_RETURN_NIL;
1412 
1413  if(font_num < 0 || font_num >= Num_fonts)
1414  return ADE_RETURN_FALSE;
1415  else
1416  return ADE_RETURN_TRUE;
1417 }
1418 
1419 //**********HANDLE: gameevent
1421 {
1422 private:
1423  int edx;
1424 public:
1425  gameevent_h(){edx=-1;}
1426  gameevent_h(int n_event){edx=n_event;}
1427 
1428  bool IsValid(){return (edx > -1 && edx < Num_gs_event_text);}
1429 
1430  int Get(){return edx;}
1431 };
1432 
1433 ade_obj<gameevent_h> l_GameEvent("gameevent", "Game event");
1434 
1435 ADE_FUNC(__tostring, l_GameEvent, NULL, "Game event name", "string", "Game event name, or empty string if handle is invalid")
1436 {
1437  gameevent_h *gh = NULL;
1438  if(!ade_get_args(L, "o", l_GameEvent.GetPtr(&gh)))
1439  return ade_set_error(L, "s", "");
1440 
1441  if(!gh->IsValid())
1442  return ade_set_error(L, "s", "");
1443 
1444  return ade_set_args(L, "s", GS_event_text[gh->Get()]);
1445 }
1446 
1447 ADE_VIRTVAR(Name, l_GameEvent, "string", "Game event name", "string", "Game event name, or empty string if handle is invalid")
1448 {
1449  gameevent_h *gh = NULL;
1450  char *n_name = NULL;
1451  if(!ade_get_args(L, "o|s", l_GameEvent.GetPtr(&gh), &n_name))
1452  return ade_set_error(L, "s", "");
1453 
1454  if(!gh->IsValid())
1455  return ade_set_error(L, "s", "");
1456 
1457  int edx = gh->Get();
1458 
1459  if(ADE_SETTING_VAR)
1460  {
1461  Error(LOCATION, "Can't set game event names at this time");
1462  }
1463 
1464  return ade_set_args(L, "s", GS_event_text[edx]);
1465 }
1466 
1467 //**********HANDLE: gamestate
1469 {
1470 private:
1471  int sdx;
1472 public:
1473  gamestate_h(){sdx=-1;}
1474  gamestate_h(int n_state){sdx=n_state;}
1475 
1476  bool IsValid(){return (sdx > -1 && sdx < Num_gs_state_text);}
1477 
1478  int Get(){return sdx;}
1479 };
1480 
1481 ade_obj<gamestate_h> l_GameState("gamestate", "Game state");
1482 
1483 ADE_FUNC(__tostring, l_GameState, NULL, "Game state name", "string", "Game state name, or empty string if handle is invalid")
1484 {
1485  gamestate_h *gh = NULL;
1486  if(!ade_get_args(L, "o", l_GameState.GetPtr(&gh)))
1487  return ade_set_error(L, "s", "");
1488 
1489  if(!gh->IsValid())
1490  return ade_set_error(L, "s", "");
1491 
1492  return ade_set_args(L, "s", GS_state_text[gh->Get()]);
1493 }
1494 
1495 ADE_VIRTVAR(Name, l_GameState,"string", "Game state name", "string", "Game state name, or empty string if handle is invalid")
1496 {
1497  gamestate_h *gh = NULL;
1498  char *n_name = NULL;
1499  if(!ade_get_args(L, "o|s", l_GameState.GetPtr(&gh), &n_name))
1500  return ade_set_error(L, "s", "");
1501 
1502  if(!gh->IsValid())
1503  return ade_set_error(L, "s", "");
1504 
1505  int sdx = gh->Get();
1506 
1507  if(ADE_SETTING_VAR)
1508  {
1509  Error(LOCATION, "Can't set game state names at this time");
1510  }
1511 
1512  return ade_set_args(L, "s", GS_state_text[sdx]);
1513 }
1514 
1515 //**********HANDLE: HUD Gauge
1516 ade_obj<HudGauge> l_HudGauge("HudGauge", "HUD Gauge handle");
1517 
1518 ADE_VIRTVAR(Name, l_HudGauge, "string", "Custom HUD Gauge name", "string", "Custom HUD Gauge name, or nil if handle is invalid")
1519 {
1520  HudGauge* gauge;
1521 
1522  if (!ade_get_args(L, "o", l_HudGauge.GetPtr(&gauge)))
1523  return ADE_RETURN_NIL;
1524 
1525  if (gauge->getObjectType() != HUD_OBJECT_CUSTOM)
1526  return ADE_RETURN_NIL;
1527 
1528  return ade_set_args(L, "s", gauge->getCustomGaugeName());
1529 }
1530 
1531 ADE_VIRTVAR(Text, l_HudGauge, "string", "Custom HUD Gauge text", "string", "Custom HUD Gauge text, or nil if handle is invalid")
1532 {
1533  HudGauge* gauge;
1534  char* text = NULL;
1535 
1536  if (!ade_get_args(L, "o|s", l_HudGauge.GetPtr(&gauge), text))
1537  return ADE_RETURN_NIL;
1538 
1539  if (gauge->getObjectType() != HUD_OBJECT_CUSTOM)
1540  return ADE_RETURN_NIL;
1541 
1542  if (ADE_SETTING_VAR && text != NULL)
1543  {
1544  gauge->updateCustomGaugeText(text);
1545  }
1546 
1547  return ade_set_args(L, "s", gauge->getCustomGaugeText());
1548 }
1549 
1550 //**********HANDLE: Eyepoint
1551 struct eye_h
1552 {
1553  int model;
1554  int eye_idx;
1555 
1556  eye_h(){model=-1;eye_idx=-1;}
1557  eye_h(int n_m, int n_e){model=n_m; eye_idx=n_e;}
1558  bool IsValid(){
1559  polymodel *pm = NULL;
1560  return (model > -1
1561  && (pm = model_get(model)) != NULL
1562  && eye_idx > -1
1563  && eye_idx < pm->n_view_positions);
1564  }
1565 };
1566 ade_obj<eye_h> l_Eyepoint("eyepoint", "Eyepoint handle");
1567 
1568 ADE_VIRTVAR(Normal, l_Eyepoint, "vector", "Eyepoint normal", "vector", "Eyepoint normal, or null vector if handle is invalid")
1569 {
1570  eye_h *eh;
1571  vec3d *v;
1572  if(!ade_get_args(L, "o|o", l_Eyepoint.GetPtr(&eh), l_Vector.GetPtr(&v)))
1573  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
1574 
1575  if(!eh->IsValid())
1576  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
1577 
1578  polymodel *pm = model_get(eh->model);
1579 
1580  if(ADE_SETTING_VAR && v != NULL)
1581  {
1582  pm->view_positions[eh->eye_idx].norm = *v;
1583  }
1584 
1585  return ade_set_args(L, "o", l_Vector.Set(pm->view_positions[eh->eye_idx].norm));
1586 }
1587 
1588 ADE_VIRTVAR(Position, l_Eyepoint, "vector", "Eyepoint location (Local vector)", "vector", "Eyepoint location, or null vector if handle is invalid")
1590  eye_h *eh;
1591  vec3d *v;
1592  if(!ade_get_args(L, "o|o", l_Eyepoint.GetPtr(&eh), l_Vector.GetPtr(&v)))
1593  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
1594 
1595  if(!eh->IsValid())
1596  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
1597 
1599 
1600  if(ADE_SETTING_VAR && v != NULL)
1601  {
1602  pm->view_positions[eh->eye_idx].pnt = *v;
1603  }
1604 
1605  return ade_set_args(L, "o", l_Vector.Set(pm->view_positions[eh->eye_idx].pnt));
1606 }
1607 
1608 ADE_FUNC(IsValid, l_Eyepoint, NULL, "Detect whether this handle is valid", "boolean", "true if valid false otherwise")
1609 {
1610  eye_h *eh = NULL;
1611  if (!ade_get_args(L, "o", l_Eyepoint.GetPtr(&eh)))
1612  {
1613  return ADE_RETURN_FALSE;
1614  }
1615 
1616  return ade_set_args(L, "b", eh->IsValid());
1617 }
1618 
1619 //**********HANDLE: model
1620 class model_h
1621 {
1622 protected:
1623  int mid;
1625 
1626 public:
1628  if(!this->IsValid())
1629  return NULL;
1630 
1631  return model;
1632  }
1633 
1634  int GetID(){
1635  if(!this->IsValid())
1636  return -1;
1637 
1638  return mid;
1639  }
1640 
1641  bool IsValid(){
1642  return (model != NULL && mid > -1 && model_get(mid) == model);
1643  }
1644 
1645  model_h(int n_modelnum) {
1646  mid = n_modelnum;
1647  if(mid > 0)
1648  model = model_get(mid);
1649  else
1650  model = NULL;
1651  }
1652  model_h(polymodel *n_model) {
1653  model = n_model;
1654  if(n_model != NULL)
1655  mid = n_model->id;
1656  else
1657  mid = -1;
1658  }
1660  mid=-1;
1661  model = NULL;
1662  }
1663 };
1664 
1665 class modeltextures_h : public model_h
1666 {
1667 public:
1670 };
1671 ade_obj<model_h> l_Model("model", "3D Model (POF) handle");
1672 
1673 ade_obj<modeltextures_h> l_ModelTextures("modeltextures_h", "Array of materials");
1674 
1675 class eyepoints_h : public model_h
1676 {
1677 public:
1680 };
1681 
1682 ade_obj<eyepoints_h> l_Eyepoints("eyepoints", "Array of model eye points");
1683 
1684 // Thrusters:
1685 class thrusters_h : public model_h
1686 {
1687  public:
1690 };
1691 
1692 ade_obj<thrusters_h> l_Thrusters("thrusters", "The thrusters of a model");
1693 
1694 // Thrusterbank:
1696 {
1698 
1700  {
1701  bank = NULL;
1702  }
1703 
1705  {
1706  bank = ba;
1707  }
1708 
1710  {
1711  if (!isValid())
1712  return NULL;
1713 
1714  return bank;
1715  }
1716 
1717  bool isValid()
1718  {
1719  return bank != NULL;
1720  }
1721 };
1722 
1723 ade_obj<thrusterbank_h> l_Thrusterbank("thrusterbank", "A model thrusterbank");
1724 
1725 // Glowpoint:
1727 {
1729 
1731  {
1732  }
1733 
1735  {
1736  point = np;
1737  }
1738 
1740  {
1741  if (!isValid())
1742  return NULL;
1743 
1744  return point;
1745  }
1746 
1747  bool isValid()
1748  {
1749  return point != NULL;
1750  }
1751 
1752 };
1753 
1754 ade_obj<glowpoint_h> l_Glowpoint("glowpoint", "A model glowpoint");
1755 
1756 // Glowbanks:
1757 class dockingbays_h : public model_h
1758 {
1759  public:
1762 };
1763 ade_obj<dockingbays_h> l_Dockingbays("dockingbays", "The docking bays of a model");
1764 
1765 ADE_VIRTVAR(Textures, l_Model, "modeltextures_h", "Model textures", "modeltextures_h", "Model textures, or an invalid modeltextures handle if the model handle is invalid")
1766 {
1767  model_h *mdl = NULL;
1768  modeltextures_h *oth = NULL;
1769  if(!ade_get_args(L, "o|o", l_Model.GetPtr(&mdl), l_ModelTextures.GetPtr(&oth)))
1770  return ade_set_error(L, "o", l_ModelTextures.Set(modeltextures_h()));
1771 
1772  polymodel *pm = mdl->Get();
1773  if(pm == NULL)
1774  return ade_set_error(L, "o", l_ModelTextures.Set(modeltextures_h()));
1775 
1776  if(ADE_SETTING_VAR && oth && oth->IsValid()) {
1777  //WMC TODO: Copy code
1778  LuaError(L, "Attempt to use Incomplete Feature: Modeltextures copy");
1779  }
1780 
1781  return ade_set_args(L, "o", l_ModelTextures.Set(modeltextures_h(pm)));
1782 }
1783 
1784 ADE_VIRTVAR(Thrusters, l_Model, "thrusters", "Model thrusters", "thrusters", "Thrusters of the model or invalid handle")
1785 {
1786  model_h *mdl = NULL;
1787  thrusters_h *oth = NULL;
1788  if(!ade_get_args(L, "o|o", l_Model.GetPtr(&mdl), l_Thrusters.GetPtr(&oth)))
1789  return ade_set_error(L, "o", l_Thrusters.Set(thrusters_h()));
1790 
1791  polymodel *pm = mdl->Get();
1792  if(pm == NULL)
1793  return ade_set_error(L, "o", l_Thrusters.Set(thrusters_h()));
1794 
1795  if(ADE_SETTING_VAR && oth && oth->IsValid()) {
1796  LuaError(L, "Attempt to use Incomplete Feature: Thrusters copy");
1797  }
1798 
1799  return ade_set_args(L, "o", l_Thrusters.Set(thrusters_h(pm)));
1800 }
1801 
1802 ADE_VIRTVAR(Eyepoints, l_Model, "eyepoints", "Model eyepoints", "eyepoints", "Array of eyepoints or invalid handle on error")
1803 {
1804  model_h *mdl = NULL;
1805  eyepoints_h *eph = NULL;
1806  if(!ade_get_args(L, "o|o", l_Model.GetPtr(&mdl), l_Eyepoints.GetPtr(&eph)))
1807  return ade_set_error(L, "o", l_Eyepoints.Set(eyepoints_h()));
1808 
1809  polymodel *pm = mdl->Get();
1810  if(pm == NULL)
1811  return ade_set_error(L, "o", l_Eyepoints.Set(eyepoints_h()));
1812 
1813  if(ADE_SETTING_VAR && eph && eph->IsValid()) {
1814  LuaError(L, "Attempt to use Incomplete Feature: Eyepoints copy");
1815  }
1816 
1817  return ade_set_args(L, "o", l_Eyepoints.Set(eyepoints_h(pm)));
1818 }
1819 
1820 ADE_VIRTVAR(Dockingbays, l_Model, "dockingbays", "Docking bays handle of model", "dockingbays", "Array of docking bays on this model, or invalid handle on error")
1821 {
1822  model_h *mdl = NULL;
1823  dockingbays_h *dbh = NULL;
1824  if(!ade_get_args(L, "o|o", l_Model.GetPtr(&mdl), l_Dockingbays.GetPtr(&dbh)))
1825  return ade_set_error(L, "o", l_Dockingbays.Set(dockingbays_h()));
1826 
1827  polymodel *pm = mdl->Get();
1828  if(pm == NULL)
1829  return ade_set_error(L, "o", l_Dockingbays.Set(dockingbays_h()));
1830 
1831  if(ADE_SETTING_VAR && dbh && dbh->IsValid()) {
1832  LuaError(L, "Attempt to use Incomplete Feature: Docking bays copy");
1833  }
1834 
1835  return ade_set_args(L, "o", l_Dockingbays.Set(dockingbays_h(pm)));
1836 }
1837 
1838 extern void model_calc_bound_box( vec3d *box, vec3d *big_mn, vec3d *big_mx);
1839 
1840 ADE_VIRTVAR(BoundingBoxMax, l_Model, "vector", "Model bounding box maximum", "vector", "Model bounding box, or an empty vector if the handle is invalid")
1841 {
1842  model_h *mdl = NULL;
1843  vec3d *v = NULL;
1844  if(!ade_get_args(L, "o|o", l_Model.GetPtr(&mdl), l_Vector.GetPtr(&v)))
1845  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
1846 
1847  polymodel *pm = mdl->Get();
1848 
1849  if(pm == NULL)
1850  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
1851 
1852  if(ADE_SETTING_VAR && v != NULL) {
1853  pm->maxs = *v;
1854 
1855  //Recalculate this, so it stays valid
1856  model_calc_bound_box(pm->bounding_box, &pm->mins, &pm->maxs);
1857  }
1858 
1859  return ade_set_args(L, "o", l_Vector.Set(pm->maxs));
1860 }
1861 
1862 ADE_VIRTVAR(BoundingBoxMin, l_Model, "vector", "Model bounding box minimum", "vector", "Model bounding box, or an empty vector if the handle is invalid")
1863 {
1864  model_h *mdl = NULL;
1865  vec3d *v = NULL;
1866  if(!ade_get_args(L, "o|o", l_Model.GetPtr(&mdl), l_Vector.GetPtr(&v)))
1867  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
1868 
1869  polymodel *pm = mdl->Get();
1870 
1871  if(pm == NULL)
1872  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
1873 
1874  if(ADE_SETTING_VAR && v != NULL) {
1875  pm->mins = *v;
1876 
1877  //Recalculate this, so it stays valid
1878  model_calc_bound_box(pm->bounding_box, &pm->mins, &pm->maxs);
1879  }
1880 
1881  return ade_set_args(L, "o", l_Vector.Set(pm->mins));
1882 }
1883 
1884 ADE_VIRTVAR(Filename, l_Model, "string", "Model filename", "string", "Model filename, or an empty string if the handle is invalid")
1885 {
1886  model_h *mdl = NULL;
1887  char *s = NULL;
1888  if(!ade_get_args(L, "o|s", l_Model.GetPtr(&mdl), &s))
1889  return ade_set_error(L, "s", "");
1890 
1891  polymodel *pm = mdl->Get();
1892 
1893  if(pm == NULL)
1894  return ade_set_error(L, "s", "");
1895 
1896  if(ADE_SETTING_VAR) {
1897  strncpy(pm->filename, s, sizeof(pm->filename) - sizeof(char));
1898  }
1899 
1900  return ade_set_args(L, "s", pm->filename);
1901 }
1902 
1903 ADE_VIRTVAR(Mass, l_Model, "number", "Model mass", "number", "Model mass, or 0 if the model handle is invalid")
1904 {
1905  model_h *mdl = NULL;
1906  float nm = 0.0f;
1907  if(!ade_get_args(L, "o|f", l_Model.GetPtr(&mdl), &nm))
1908  return ade_set_error(L, "f", 0.0f);
1909 
1910  polymodel *pm = mdl->Get();
1911 
1912  if(pm == NULL)
1913  return ade_set_error(L, "f", 0.0f);
1914 
1915  if(ADE_SETTING_VAR) {
1916  pm->mass = nm;
1917  }
1918 
1919  return ade_set_args(L, "f", pm->mass);
1920 }
1921 
1922 ADE_VIRTVAR(MomentOfInertia, l_Model, "orientation", "Model moment of inertia", "orientation", "Moment of Inertia matrix or identity matrix if invalid" )
1923 {
1924  model_h *mdl = NULL;
1925  matrix_h *mh = NULL;
1926  if(!ade_get_args(L, "o|o", l_Model.GetPtr(&mdl), l_Matrix.GetPtr(&mh)))
1927  return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
1928 
1929  polymodel *pm = mdl->Get();
1930 
1931  if(pm == NULL)
1932  return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
1933 
1934  if(ADE_SETTING_VAR && mh != NULL) {
1935  matrix *mtx = mh->GetMatrix();
1936  memcpy(&pm->moment_of_inertia, mtx, sizeof(*mtx));
1937  }
1938 
1939  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&pm->moment_of_inertia)));
1940 }
1941 
1942 ADE_VIRTVAR(Radius, l_Model, "number", "Model radius (Used for collision & culling detection)", "number", "Model Radius or 0 if invalid")
1943 {
1944  model_h *mdl = NULL;
1945  float nr = 0.0f;
1946  if(!ade_get_args(L, "o|f", l_Model.GetPtr(&mdl), &nr))
1947  return ade_set_error(L, "f", 0.0f);
1948 
1949  polymodel *pm = mdl->Get();
1950 
1951  if(pm == NULL)
1952  return ade_set_error(L, "f", 0.0f);
1953 
1954  if(ADE_SETTING_VAR) {
1955  pm->rad = nr;
1956  }
1957 
1958  return ade_set_args(L, "f", pm->rad);
1959 }
1960 
1961 ADE_FUNC(isValid, l_Model, NULL, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid")
1962 {
1963  model_h *mdl;
1964  if(!ade_get_args(L, "o", l_Model.GetPtr(&mdl)))
1965  return ADE_RETURN_NIL;
1966 
1967  return mdl->IsValid();
1968 }
1969 
1970 //**********HANDLE: eyepoints
1971 ADE_FUNC(__len, l_Eyepoints, NULL, "Gets the number of eyepoints on this model", "number", "Number of eyepoints on this model or 0 on error")
1972 {
1973  eyepoints_h *eph = NULL;
1974  if (!ade_get_args(L, "o", l_Eyepoints.GetPtr(&eph)))
1975  {
1976  return ade_set_error(L, "i", 0);
1977  }
1978 
1979  if (!eph->IsValid())
1980  {
1981  return ade_set_error(L, "i", 0);
1982  }
1983 
1984  polymodel *pm = eph->Get();
1985 
1986  if (pm == NULL)
1987  {
1988  return ade_set_error(L, "i", 0);
1989  }
1990 
1991  return ade_set_args(L, "i", pm->n_view_positions);
1992 }
1993 
1994 ADE_INDEXER(l_Eyepoints, "eyepoint", "Gets en eyepoint handle", "eyepoint", "eye handle or invalid handle on error")
1995 {
1996  eyepoints_h *eph = NULL;
1997  int index = -1;
1998  eye_h *eh = NULL;
1999 
2000  if (!ade_get_args(L, "oi|o", l_Eyepoints.GetPtr(&eph), &index, l_Eyepoint.GetPtr(&eh)))
2001  {
2002  return ade_set_error(L, "o", l_Eyepoint.Set(eye_h()));
2003  }
2004 
2005  if (!eph->IsValid())
2006  {
2007  return ade_set_error(L, "o", l_Eyepoint.Set(eye_h()));
2008  }
2009 
2010  polymodel *pm = eph->Get();
2011 
2012  if (pm == NULL)
2013  {
2014  return ade_set_error(L, "o", l_Eyepoint.Set(eye_h()));
2015  }
2016 
2017  index--; // Lua -> FS2
2018 
2020  {
2021  return ade_set_error(L, "o", l_Eyepoint.Set(eye_h()));
2022  }
2023 
2024  if (ADE_SETTING_VAR && eh && eh->IsValid())
2025  {
2026  LuaError(L, "Attempted to use incomplete feature: Eyepoint copy");
2027  }
2028 
2029  return ade_set_args(L, "o", l_Eyepoint.Set(eye_h(eph->GetID(), index)));
2030 }
2031 
2032 ADE_FUNC(isValid, l_Eyepoints, NULL, "Detects whether handle is valid or not", "boolean", "true if valid false otherwise")
2033 {
2034  eyepoints_h *eph;
2035  if(!ade_get_args(L, "o", l_Eyepoints.GetPtr(&eph)))
2036  return ADE_RETURN_FALSE;
2037 
2038  return ade_set_args(L, "b", eph->IsValid());
2039 }
2040 
2041 //**********HANDLE: thrusters
2042 ADE_FUNC(__len, l_Thrusters, NULL, "Number of thruster banks on the model", "number", "Number of thrusterbanks")
2043 {
2044  thrusters_h *trh;
2045  if(!ade_get_args(L, "o", l_Thrusters.GetPtr(&trh)))
2046  return ade_set_error(L, "i", -1);
2047 
2048  if(!trh->IsValid())
2049  return ade_set_error(L, "i", -1);
2050 
2051  polymodel *pm = trh->Get();
2052 
2053  if(pm == NULL)
2054  return ade_set_error(L, "i", -1);
2055 
2056  return ade_set_args(L, "i", pm->n_thrusters);
2057 }
2058 
2059 ADE_INDEXER(l_Thrusters, "number Index", "Array of all thrusterbanks on this thruster", "thrusterbank", "Handle to the thrusterbank or invalid handle if index is invalid")
2060 {
2061  thrusters_h *trh = NULL;
2062  char *s = NULL;
2063  thrusterbank_h newThr;
2064 
2065  if (!ade_get_args(L, "os|o", l_Thrusters.GetPtr(&trh), &s, l_Thrusterbank.Get(&newThr)))
2066  return ade_set_error(L, "o", l_Thrusterbank.Set(thrusterbank_h()));
2067 
2068  polymodel *pm = trh->Get();
2069 
2070  if (!trh->IsValid() || s == NULL || pm == NULL)
2071  return ade_set_error(L, "o", l_Thrusterbank.Set(thrusterbank_h()));
2072 
2073  //Determine index
2074  int idx = atoi(s) - 1; //Lua->FS2
2075 
2076  if (idx < 0 || idx >= pm->n_thrusters)
2077  return ade_set_error(L, "o", l_Thrusterbank.Set(thrusterbank_h()));
2078 
2079  thruster_bank* bank = &pm->thrusters[idx];
2080 
2081  if (ADE_SETTING_VAR && trh != NULL)
2082  {
2083  if (newThr.isValid())
2084  {
2085  pm->thrusters[idx] = *(newThr.Get());
2086  }
2087  }
2088 
2089  return ade_set_args(L, "o", l_Thrusterbank.Set(bank));
2090 }
2091 
2092 ADE_FUNC(isValid, l_Thrusters, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
2093 {
2094  thrusters_h *trh;
2095  if(!ade_get_args(L, "o", l_Thrusters.GetPtr(&trh)))
2096  return ADE_RETURN_NIL;
2097 
2098  return ade_set_args(L, "b", trh->IsValid());
2099 }
2100 
2101 //**********HANDLE: thrusterbank
2102 ADE_FUNC(__len, l_Thrusterbank, NULL, "Number of thrusters on this thrusterbank", "number", "Number of thrusters on this bank or 0 if handle is invalid")
2103 {
2104  thrusterbank_h *tbh = NULL;
2105  if(!ade_get_args(L, "o", l_Thrusterbank.GetPtr(&tbh)))
2106  return ade_set_error(L, "i", -1);
2107 
2108  if(!tbh->isValid())
2109  return ade_set_error(L, "i", -1);
2110 
2111  thruster_bank* bank = tbh->Get();
2112 
2113  return ade_set_args(L, "i", bank->num_points);
2114 }
2115 
2116 ADE_INDEXER(l_Thrusterbank, "number Index", "Array of glowpoint", "glowpoint", "Glowpoint, or invalid glowpoint handle on failure")
2117 {
2118  thrusterbank_h *tbh = NULL;
2119  char *s = NULL;
2120  glowpoint_h *glh = NULL;
2121 
2122  if (!ade_get_args(L, "os|o", l_Thrusterbank.GetPtr(&tbh), &s, l_Glowpoint.GetPtr(&glh)))
2123  return ade_set_error(L, "o", l_Glowpoint.Set(glowpoint_h()));
2124 
2125  if (!tbh->isValid() || s==NULL)
2126  return ade_set_error(L, "o", l_Glowpoint.Set(glowpoint_h()));
2127 
2128  thruster_bank* bank = tbh->Get();
2129 
2130  //Determine index
2131  int idx = atoi(s) - 1; //Lua->FS2
2132 
2133  if (idx < 0 || idx >= bank->num_points)
2134  return ade_set_error(L, "o", l_Glowpoint.Set(glowpoint_h()));
2135 
2136  glow_point* glp = &bank->points[idx];
2137 
2138  if (ADE_SETTING_VAR && glh != NULL)
2139  {
2140  if (glh->isValid())
2141  {
2142  bank->points[idx] = *(glh->Get());
2143  }
2144  }
2145 
2146  return ade_set_args(L, "o", l_Glowpoint.Set(glp));
2147 }
2148 
2149 ADE_FUNC(isValid, l_Thrusterbank, NULL, "Detectes if this handle is valid", "boolean", "true if this handle is valid, false otherwise")
2150 {
2151  thrusterbank_h* trh;
2152  if(!ade_get_args(L, "o", l_Thrusterbank.GetPtr(&trh)))
2153  return ADE_RETURN_FALSE;
2154 
2155  if (!trh->isValid())
2156  return ADE_RETURN_FALSE;
2157 
2158  return ade_set_args(L, "b", trh->isValid());
2159 }
2160 
2161 //**********HANDLE: glowpoint
2162 ADE_VIRTVAR(Position, l_Glowpoint, NULL, "The (local) vector to the position of the glowpoint", "vector", "The local vector to the glowpoint or nil invalid")
2164  glowpoint_h *glh = NULL;
2165  vec3d newVec;
2166 
2167  if(!ade_get_args(L, "o|o", l_Glowpoint.GetPtr(&glh), l_Vector.Get(&newVec)))
2168  return ADE_RETURN_NIL;
2169 
2170  if (!glh->isValid())
2171  return ADE_RETURN_NIL;
2172 
2173  vec3d vec = glh->point->pnt;
2174 
2175  if (ADE_SETTING_VAR)
2176  {
2177  glh->point->pnt = newVec;
2178  }
2179 
2180  return ade_set_args(L, "o", l_Vector.Set(vec));
2181 }
2182 
2183 ADE_VIRTVAR(Radius, l_Glowpoint, NULL, "The radius of the glowpoint", "number", "The radius of the glowpoint or -1 of invalid")
2184 {
2185  glowpoint_h* glh = NULL;
2186  float newVal;
2187 
2188  if(!ade_get_args(L, "o|f", l_Glowpoint.GetPtr(&glh), &newVal))
2189  return ade_set_error(L, "f", -1.0f);
2190 
2191  if (!glh->isValid())
2192  return ade_set_error(L, "f", -1.0f);
2193 
2194  float radius = glh->point->radius;
2195 
2196  if (ADE_SETTING_VAR)
2197  {
2198  glh->point->radius = newVal;
2199  }
2200 
2201  return ade_set_args(L, "f", radius);
2202 }
2203 
2204 ADE_FUNC(isValid, l_Glowpoint, NULL, "Returns wether this handle is valid or not", "boolean", "True if handle is valid, false otherwise")
2205 {
2206  glowpoint_h glh = NULL;
2207 
2208  if(!ade_get_args(L, "o", l_Glowpoint.Get(&glh)))
2209  return ADE_RETURN_FALSE;
2210 
2211  return ade_set_args(L, "b", glh.isValid());
2212 }
2213 
2214 class dockingbay_h : public model_h
2215 {
2216 private:
2217  int dock_id;
2218 
2219 public:
2220  dockingbay_h(polymodel *pm, int dock_idx) : model_h(pm), dock_id(dock_idx) {}
2221  dockingbay_h() : model_h(), dock_id(-1){}
2222 
2223  bool IsValid()
2224  {
2225  if (!model_h::IsValid())
2226  {
2227  return false;
2228  }
2229  else
2230  {
2231  return dock_id >= 0 && dock_id < this->Get()->n_docks;
2232  }
2233  }
2234 
2236  {
2237  if (!this->IsValid())
2238  {
2239  return NULL;
2240  }
2241 
2242  return &this->Get()->docking_bays[dock_id];
2243  }
2244 };
2245 ade_obj<dockingbay_h> l_Dockingbay("dockingbay", "Handle to a model docking bay");
2246 
2247 //**********HANDLE: dockingbays
2248 ADE_INDEXER(l_Dockingbays, "dockingbay", "Gets a dockingbay handle from this model. If a string is given then a dockingbay with that name is searched.", "dockingbay", "Handle or invalid handle on error")
2249 {
2250  dockingbays_h *dbhp = NULL;
2251  int index = -1;
2252  dockingbay_h *newVal = NULL;
2253 
2254  if (lua_isnumber(L, 2))
2255  {
2256  if (!ade_get_args(L, "oi|o", l_Dockingbays.GetPtr(&dbhp), &index, l_Dockingbay.GetPtr(&newVal)))
2257  return ade_set_error(L, "o", l_Dockingbay.Set(dockingbay_h()));
2258 
2259  if (!dbhp->IsValid())
2260  return ade_set_error(L, "o", l_Dockingbay.Set(dockingbay_h()));
2261 
2262  index--; // Lua --> C/C++
2263  }
2264  else
2265  {
2266  char* name = NULL;
2267 
2268  if (!ade_get_args(L, "os|o", l_Dockingbays.GetPtr(&dbhp), &name, l_Dockingbay.GetPtr(&newVal)))
2269  {
2270  return ade_set_error(L, "o", l_Dockingbay.Set(dockingbay_h()));
2271  }
2272 
2273  if (!dbhp->IsValid() && name != NULL)
2274  return ade_set_error(L, "o", l_Dockingbay.Set(dockingbay_h()));
2275 
2276  index = model_find_dock_name_index(dbhp->GetID(), name);
2277  }
2278 
2279  polymodel *pm = dbhp->Get();
2280 
2281  if (index < 0 || index >= pm->n_docks)
2282  {
2283  return ade_set_error(L, "o", l_Dockingbay.Set(dockingbay_h()));
2284  }
2285 
2286  return ade_set_args(L, "o", l_Dockingbay.Set(dockingbay_h(pm, index)));
2287 }
2288 
2289 ADE_FUNC(__len, l_Dockingbays, NULL, "Retrieves the number of dockingbays on this model", "number", "number of docking bays or 0 on error")
2290 {
2291  dockingbays_h *dbhp = NULL;
2292 
2293  if (!ade_get_args(L, "o", l_Dockingbays.GetPtr(&dbhp)))
2294  return ade_set_error(L, "i", 0);
2295 
2296  if (!dbhp->IsValid())
2297  return ade_set_error(L, "i", 0);
2298 
2299  return ade_set_args(L, "i", dbhp->Get()->n_docks);
2300 }
2301 
2302 //**********HANDLE: dockingbay
2303 ADE_FUNC(__len, l_Dockingbay, NULL, "Gets the number of docking points in this bay", "number", "The number of docking points or 0 on error")
2304 {
2305  dockingbay_h* dbh = NULL;
2306 
2307  if (!ade_get_args(L, "o", l_Dockingbay.GetPtr(&dbh)))
2308  {
2309  return ade_set_error(L, "i", 0);
2310  }
2311 
2312  if (dbh == NULL || !dbh->IsValid())
2313  {
2314  return ade_set_error(L, "i", 0);
2315  }
2316 
2317  return ade_set_args(L, "i", dbh->getDockingBay()->num_slots);
2318 }
2319 
2320 ADE_FUNC(getName, l_Dockingbay, NULL, "Gets the name of this docking bay", "string", "The name or an empty string on error")
2321 {
2322  dockingbay_h* dbh = NULL;
2323  if (!ade_get_args(L, "o", l_Dockingbay.GetPtr(&dbh)))
2324  {
2325  return ade_set_error(L, "s", "");
2326  }
2327 
2328  if (dbh == NULL || !dbh->IsValid())
2329  {
2330  return ade_set_error(L, "s", "");
2331  }
2332 
2333  dock_bay* dbp = dbh->getDockingBay();
2334 
2335  return ade_set_args(L, "s", dbp->name);
2336 }
2337 
2338 ADE_FUNC(getPoint, l_Dockingbay, "number index", "Gets the location of a docking point in this bay", "vector", "The local location or null vector on error")
2339 {
2340  dockingbay_h* dbh = NULL;
2341  int index = -1;
2342 
2343  if (!ade_get_args(L, "oi", l_Dockingbay.GetPtr(&dbh), &index))
2344  {
2345  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2346  }
2347 
2348  index--; // Lua --> C/C++
2349 
2350  if (dbh == NULL || !dbh->IsValid())
2351  {
2352  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2353  }
2354 
2355  dock_bay* dbp = dbh->getDockingBay();
2356 
2358  {
2359  LuaError(L, "Invalid dock bay index %d!", (index + 1));
2360  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2361  }
2362 
2363  return ade_set_args(L, "o", l_Vector.Set(dbp->pnt[index]));
2364 }
2365 
2366 ADE_FUNC(getNormal, l_Dockingbay, "number index", "Gets the normal of a docking point in this bay", "vector", "The normal vector or null vector on error")
2367 {
2368  dockingbay_h* dbh = NULL;
2369  int index = -1;
2370 
2371  if (!ade_get_args(L, "oi", l_Dockingbay.GetPtr(&dbh), &index))
2372  {
2373  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2374  }
2375 
2376  index--; // Lua --> C/C++
2377 
2378  if (dbh == NULL || !dbh->IsValid())
2379  {
2380  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2381  }
2382 
2383  dock_bay* dbp = dbh->getDockingBay();
2384 
2386  {
2387  LuaError(L, "Invalid dock bay index %d!", (index + 1));
2388  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2389  }
2390 
2391  return ade_set_args(L, "o", l_Vector.Set(dbp->norm[index]));
2392 }
2393 
2394 ADE_FUNC(computeDocker, l_Dockingbay, "dockingbay", "Computes the final position and orientation of a docker bay that docks with this bay.", "vector, orientation", "The local location and orientation of the docker vessel in the reference to the vessel of the docking bay handle, or a nil value on error")
2395 {
2396  dockingbay_h *dockee_bay_h = NULL, *docker_bay_h = NULL;
2397  vec3d final_pos;
2398  matrix final_orient;
2399 
2400  if (!ade_get_args(L, "oo", l_Dockingbay.GetPtr(&dockee_bay_h), l_Dockingbay.GetPtr(&docker_bay_h)))
2401  {
2402  return ADE_RETURN_NIL;
2403  }
2404 
2405  if (!dockee_bay_h->IsValid() || !docker_bay_h->IsValid())
2406  {
2407  return ADE_RETURN_NIL;
2408  }
2409 
2410  dock_bay* dockee_bay = dockee_bay_h->getDockingBay();
2411  dock_bay* docker_bay = docker_bay_h->getDockingBay();
2412 
2413  // Mostly the same as aicode.cpp: dock_orient_and_approach
2414  vec3d dockee_dock_pos, docker_dock_pos_local, docker_dock_pos;
2415  vec3d dock_up_dir;
2416 
2417  // Get the center between the two docking points
2418  vm_vec_avg(&dockee_dock_pos, &dockee_bay->pnt[0], &dockee_bay->pnt[1]);
2419  vm_vec_avg(&docker_dock_pos_local, &docker_bay->pnt[0], &docker_bay->pnt[1]);
2420 
2421  // Get the up-vector of the docking bay
2422  vm_vec_sub(&dock_up_dir, &dockee_bay->pnt[1], &dockee_bay->pnt[0]);
2423 
2424  // Compute the orientation
2425  vm_vector_2_matrix(&final_orient, &dockee_bay->norm[0], &dock_up_dir, NULL);
2426 
2427  // Rotate the docker position into the right orientation
2428  vm_vec_unrotate(&docker_dock_pos, &docker_dock_pos_local, &final_orient);
2429 
2430  // The docker vector points into the wrong direction, we need to scale it appropriately
2431  vm_vec_scale(&docker_dock_pos, -1.0f);
2432 
2433  // Now get the position of the other vessel
2434  vm_vec_add(&final_pos, &dockee_dock_pos, &docker_dock_pos);
2435 
2436  return ade_set_args(L, "oo", l_Vector.Set(final_pos),l_Matrix.Set(matrix_h(&final_orient)));
2437 }
2438 
2439 ADE_FUNC(isValid, l_Dockingbay, NULL, "Detects whether is valid or not", "number", "<i>true</i> if valid, <i>false</i> otherwise")
2440 {
2441  dockingbay_h* dbh = NULL;
2442 
2443  if (!ade_get_args(L, "o", l_Dockingbay.GetPtr(&dbh)))
2444  {
2445  return ade_set_error(L, "i", 0);
2446  }
2447 
2448  if (dbh == NULL)
2449  {
2450  return ADE_RETURN_FALSE;
2451  }
2452 
2453  return ade_set_args(L, "b", dbh->IsValid());
2454 }
2455 
2456 //**********HANDLE: physics
2458 {
2461 
2463  objh = object_h();
2464  pi = NULL;
2465  }
2466 
2468  objh = object_h(objp);
2469  pi = &objp->phys_info;
2470  }
2471 
2473  pi = in_pi;
2474  }
2475 
2476  bool IsValid(){if(objh.objp != NULL) return objh.IsValid(); else return (pi != NULL);}
2477 };
2478 
2479 ade_obj<physics_info_h> l_Physics("physics", "Physics handle");
2480 
2481 ADE_VIRTVAR(AfterburnerAccelerationTime, l_Physics, "number", "Afterburner acceleration time", "number", "Afterburner acceleration time, or 0 if handle is invalid")
2482 {
2483  physics_info_h *pih;
2484  float f = 0.0f;
2485  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2486  return ade_set_error(L, "f", 0.0f);
2487 
2488  if(!pih->IsValid())
2489  return ade_set_error(L, "f", 0.0f);
2490 
2491  if(ADE_SETTING_VAR) {
2493  }
2494 
2496 }
2497 
2498 ADE_VIRTVAR(AfterburnerVelocityMax, l_Physics, "vector", "Afterburner max velocity (Local vector)", "vector", "Afterburner max velocity, or null vector if handle is invalid")
2499 {
2500  physics_info_h *pih;
2501  vec3d *v3=NULL;
2502  if(!ade_get_args(L, "o|o", l_Physics.GetPtr(&pih), l_Vector.GetPtr(&v3)))
2503  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2504 
2505  if(!pih->IsValid())
2506  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2507 
2508  if(ADE_SETTING_VAR && v3 != NULL) {
2509  pih->pi->afterburner_max_vel = *v3;
2510  }
2511 
2512  return ade_set_args(L, "o", l_Vector.Set(pih->pi->afterburner_max_vel));
2513 }
2514 
2515 ADE_VIRTVAR(BankingConstant, l_Physics, "number", "Banking constant", "number", "Banking constant, or 0 if handle is invalid")
2516 {
2517  physics_info_h *pih;
2518  float f = 0.0f;
2519  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2520  return ade_set_error(L, "f", 0.0f);
2521 
2522  if(!pih->IsValid())
2523  return ade_set_error(L, "f", 0.0f);
2524 
2525  if(ADE_SETTING_VAR) {
2526  pih->pi->delta_bank_const = f;
2527  }
2528 
2529  return ade_set_args(L, "f", pih->pi->delta_bank_const);
2530 }
2531 
2532 ADE_VIRTVAR(ForwardAccelerationTime, l_Physics, "number", "Forward acceleration time", "number", "Forward acceleration time, or 0 if handle is invalid")
2533 {
2534  physics_info_h *pih;
2535  float f = 0.0f;
2536  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2537  return ade_set_error(L, "f", 0.0f);
2538 
2539  if(!pih->IsValid())
2540  return ade_set_error(L, "f", 0.0f);
2541 
2542  if(ADE_SETTING_VAR) {
2543  pih->pi->forward_accel_time_const = f;
2544  }
2545 
2546  return ade_set_args(L, "f", pih->pi->forward_accel_time_const);
2547 }
2548 
2549 ADE_VIRTVAR(ForwardDecelerationTime, l_Physics, "number", "Forward deceleration time", "number", "Forward decleration time, or 0 if handle is invalid")
2550 {
2551  physics_info_h *pih;
2552  float f = 0.0f;
2553  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2554  return ade_set_error(L, "f", 0.0f);
2555 
2556  if(!pih->IsValid())
2557  return ade_set_error(L, "f", 0.0f);
2558 
2559  if(ADE_SETTING_VAR) {
2560  pih->pi->forward_decel_time_const = f;
2561  }
2562 
2563  return ade_set_args(L, "f", pih->pi->forward_decel_time_const);
2564 }
2565 
2566 ADE_VIRTVAR(ForwardThrust, l_Physics, "number", "Forward thrust amount (0-1), used primarily for thruster graphics", "number", "Forward thrust, or 0 if handle is invalid")
2567 {
2568  physics_info_h *pih;
2569  float f = 0.0f;
2570  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2571  return ade_set_error(L, "f", 0.0f);
2572 
2573  if(!pih->IsValid())
2574  return ade_set_error(L, "f", 0.0f);
2575 
2576  if(ADE_SETTING_VAR) {
2577  pih->pi->forward_thrust = f;
2578  }
2579 
2580  return ade_set_args(L, "f", pih->pi->forward_thrust);
2581 }
2582 
2583 ADE_VIRTVAR(Mass, l_Physics, "number", "Object mass", "number", "Object mass, or 0 if handle is invalid")
2584 {
2585  physics_info_h *pih;
2586  float f = 0.0f;
2587  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2588  return ade_set_error(L, "f", 0.0f);
2589 
2590  if(!pih->IsValid())
2591  return ade_set_error(L, "f", 0.0f);
2592 
2593  if(ADE_SETTING_VAR) {
2594  pih->pi->mass = f;
2595  }
2596 
2597  return ade_set_args(L, "f", pih->pi->mass);
2598 }
2599 
2600 ADE_VIRTVAR(RotationalVelocity, l_Physics, "vector", "Rotational velocity (Local vector)", "vector", "Rotational velocity, or null vector if handle is invalid")
2601 {
2602  physics_info_h *pih;
2603  vec3d *v3=NULL;
2604  if(!ade_get_args(L, "o|o", l_Physics.GetPtr(&pih), l_Vector.GetPtr(&v3)))
2605  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2606 
2607  if(!pih->IsValid())
2608  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2609 
2610  if(ADE_SETTING_VAR && v3 != NULL) {
2611  pih->pi->rotvel = *v3;
2612  }
2613 
2614  return ade_set_args(L, "o", l_Vector.Set(pih->pi->rotvel));
2615 }
2616 
2617 ADE_VIRTVAR(RotationalVelocityDamping, l_Physics, "number", "Rotational damping, ie derivative of rotational speed", "number", "Rotational damping, or 0 if handle is invalid")
2618 {
2619  physics_info_h *pih;
2620  float f = 0.0f;
2621  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2622  return ade_set_error(L, "f", 0.0f);
2623 
2624  if(!pih->IsValid())
2625  return ade_set_error(L, "f", 0.0f);
2626 
2627  if(ADE_SETTING_VAR) {
2628  pih->pi->rotdamp = f;
2629  }
2630 
2631  return ade_set_args(L, "f", pih->pi->rotdamp);
2632 }
2633 
2634 ADE_VIRTVAR(RotationalVelocityDesired, l_Physics, "vector", "Desired rotational velocity", "vector", "Desired rotational velocity, or null vector if handle is invalid")
2635 {
2636  physics_info_h *pih;
2637  vec3d *v3=NULL;
2638  if(!ade_get_args(L, "o|o", l_Physics.GetPtr(&pih), l_Vector.GetPtr(&v3)))
2639  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2640 
2641  if(!pih->IsValid())
2642  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2643 
2644  if(ADE_SETTING_VAR && v3 != NULL) {
2645  pih->pi->desired_rotvel = *v3;
2646  }
2647 
2648  return ade_set_args(L, "o", l_Vector.Set(pih->pi->desired_rotvel));
2649 }
2650 
2651 ADE_VIRTVAR(RotationalVelocityMax, l_Physics, "vector", "Maximum rotational velocity (Local vector)", "vector", "Maximum rotational velocity, or null vector if handle is invalid")
2652 {
2653  physics_info_h *pih;
2654  vec3d *v3=NULL;
2655  if(!ade_get_args(L, "o|o", l_Physics.GetPtr(&pih), l_Vector.GetPtr(&v3)))
2656  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2657 
2658  if(!pih->IsValid())
2659  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2660 
2661  if(ADE_SETTING_VAR && v3 != NULL) {
2662  pih->pi->max_rotvel = *v3;
2663  }
2664 
2665  return ade_set_args(L, "o", l_Vector.Set(pih->pi->max_rotvel));
2666 }
2667 
2668 ADE_VIRTVAR(ShockwaveShakeAmplitude, l_Physics, "number", "How much shaking from shockwaves is applied to object", "number", "Shockwave shake amplitude, or 0 if handle is invalid")
2669 {
2670  physics_info_h *pih;
2671  float f = 0.0f;
2672  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2673  return ade_set_error(L, "f", 0.0f);
2674 
2675  if(!pih->IsValid())
2676  return ade_set_error(L, "f", 0.0f);
2677 
2678  if(ADE_SETTING_VAR) {
2679  pih->pi->shockwave_shake_amp = f;
2680  }
2681 
2682  return ade_set_args(L, "f", pih->pi->shockwave_shake_amp);
2683 }
2684 
2685 ADE_VIRTVAR(SideThrust, l_Physics, "number", "Side thrust amount (0-1), used primarily for thruster graphics", "number", "Side thrust amount, or 0 if handle is invalid")
2686 {
2687  physics_info_h *pih;
2688  float f = 0.0f;
2689  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2690  return ade_set_error(L, "f", 0.0f);
2691 
2692  if(!pih->IsValid())
2693  return ade_set_error(L, "f", 0.0f);
2694 
2695  if(ADE_SETTING_VAR) {
2696  pih->pi->side_thrust = f;
2697  }
2698 
2699  return ade_set_args(L, "f", pih->pi->side_thrust);
2700 }
2701 
2702 ADE_VIRTVAR(SlideAccelerationTime, l_Physics, "number", "Time to accelerate to maximum slide velocity", "number", "Sliding acceleration time, or 0 if handle is invalid")
2703 {
2704  physics_info_h *pih;
2705  float f = 0.0f;
2706  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2707  return ade_set_error(L, "f", 0.0f);
2708 
2709  if(!pih->IsValid())
2710  return ade_set_error(L, "f", 0.0f);
2711 
2712  if(ADE_SETTING_VAR) {
2713  pih->pi->slide_accel_time_const = f;
2714  }
2715 
2716  return ade_set_args(L, "f", pih->pi->slide_accel_time_const);
2717 }
2718 
2719 ADE_VIRTVAR(SlideDecelerationTime, l_Physics, "number", "Time to decelerate from maximum slide speed", "number", "Sliding deceleration time, or 0 if handle is invalid")
2720 {
2721  physics_info_h *pih;
2722  float f = 0.0f;
2723  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2724  return ade_set_error(L, "f", 0.0f);
2725 
2726  if(!pih->IsValid())
2727  return ade_set_error(L, "f", 0.0f);
2728 
2729  if(ADE_SETTING_VAR) {
2730  pih->pi->slide_decel_time_const = f;
2731  }
2732 
2733  return ade_set_args(L, "f", pih->pi->slide_decel_time_const);
2734 }
2735 
2736 ADE_VIRTVAR(Velocity, l_Physics, "vector", "Object world velocity (World vector)", "vector", "Object velocity, or null vector if handle is invalid")
2737 {
2738  physics_info_h *pih;
2739  vec3d *v3=NULL;
2740  if(!ade_get_args(L, "o|o", l_Physics.GetPtr(&pih), l_Vector.GetPtr(&v3)))
2741  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2742 
2743  if(!pih->IsValid())
2744  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2745 
2746  if(ADE_SETTING_VAR && v3 != NULL) {
2747  pih->pi->vel = *v3;
2748  }
2749 
2750  return ade_set_args(L, "o", l_Vector.Set(pih->pi->vel));
2751 }
2752 
2753 ADE_VIRTVAR(VelocityDesired, l_Physics, "vector", "Desired velocity (World vector)", "vector", "Desired velocity, or null vector if handle is invalid")
2754 {
2755  physics_info_h *pih;
2756  vec3d *v3=NULL;
2757  if(!ade_get_args(L, "o|o", l_Physics.GetPtr(&pih), l_Vector.GetPtr(&v3)))
2758  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2759 
2760  if(!pih->IsValid())
2761  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2762 
2763  if(ADE_SETTING_VAR && v3 != NULL) {
2764  pih->pi->desired_vel = *v3;
2765  }
2766 
2767  return ade_set_args(L, "o", l_Vector.Set(pih->pi->desired_vel));
2768 }
2769 
2770 ADE_VIRTVAR(VelocityMax, l_Physics, "vector", "Object max local velocity (Local vector)", "vector", "Maximum velocity, or null vector if handle is invalid")
2771 {
2772  physics_info_h *pih;
2773  vec3d *v3=NULL;
2774  if(!ade_get_args(L, "o|o", l_Physics.GetPtr(&pih), l_Vector.GetPtr(&v3)))
2775  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2776 
2777  if(!pih->IsValid())
2778  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
2779 
2780  if(ADE_SETTING_VAR && v3 != NULL) {
2781  pih->pi->max_vel = *v3;
2782  }
2783 
2784  return ade_set_args(L, "o", l_Vector.Set(pih->pi->max_vel));
2785 }
2786 
2787 ADE_VIRTVAR(VerticalThrust, l_Physics, "number", "Vertical thrust amount (0-1), used primarily for thruster graphics", "number", "Vertical thrust amount, or 0 if handle is invalid")
2788 {
2789  physics_info_h *pih;
2790  float f = 0.0f;
2791  if(!ade_get_args(L, "o|f", l_Physics.GetPtr(&pih), &f))
2792  return ade_set_error(L, "f", 0.0f);
2793 
2794  if(!pih->IsValid())
2795  return ade_set_error(L, "f", 0.0f);
2796 
2797  if(ADE_SETTING_VAR) {
2798  pih->pi->vert_thrust = f;
2799  }
2800 
2801  return ade_set_args(L, "f", pih->pi->vert_thrust);
2802 }
2803 
2804 ADE_VIRTVAR(AfterburnerActive, l_Physics, "boolean", "Specifies if the afterburner is active or not", "boolean", "true if afterburner is active false otherwise")
2805 {
2806  physics_info_h *pih;
2807  bool set = false;
2808 
2809  if(!ade_get_args(L, "o|b", l_Physics.GetPtr(&pih), &set))
2810  return ade_set_error(L, "b", false);
2811 
2812  if(!pih->IsValid())
2813  return ade_set_error(L, "b", false);
2814 
2815  if (ADE_SETTING_VAR)
2816  {
2817  if(set)
2818  pih->pi->flags |= PF_AFTERBURNER_ON;
2819  else
2820  pih->pi->flags &= ~PF_AFTERBURNER_ON;
2821  }
2822 
2823  if (pih->pi->flags & PF_AFTERBURNER_ON)
2824  return ade_set_args(L, "b", true);
2825  else
2826  return ade_set_args(L, "b", false);
2827 }
2828 
2829 ADE_FUNC(isValid, l_Physics, NULL, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid")
2830 {
2831  physics_info_h *pih;
2832  if(!ade_get_args(L, "o", l_Physics.GetPtr(&pih)))
2833  return ADE_RETURN_NIL;
2834 
2835  return ade_set_args(L, "b", pih->IsValid());
2836 }
2837 
2838 ADE_FUNC(getSpeed, l_Physics, NULL, "Gets total speed as of last frame", "number", "Total speed, or 0 if handle is invalid")
2839 {
2840  physics_info_h *pih;
2841  if(!ade_get_args(L, "o", l_Physics.GetPtr(&pih)))
2842  return ade_set_error(L, "f", 0.0f);
2843 
2844  if(!pih->IsValid())
2845  return ade_set_error(L, "f", 0.0f);
2846 
2847  return ade_set_args(L, "f", pih->pi->speed);
2848 }
2849 
2850 ADE_FUNC(getForwardSpeed, l_Physics, NULL, "Gets total speed in the ship's 'forward' direction as of last frame", "number", "Total forward speed, or 0 if handle is invalid")
2851 {
2852  physics_info_h *pih;
2853  if(!ade_get_args(L, "o", l_Physics.GetPtr(&pih)))
2854  return ade_set_error(L, "f", 0.0f);
2855 
2856  if(!pih->IsValid())
2857  return ade_set_error(L, "f", 0.0f);
2858 
2859  return ade_set_args(L, "f", pih->pi->fspeed);
2860 }
2861 
2862 // Nuke's afterburner function
2863 ADE_FUNC(isAfterburnerActive, l_Physics, NULL, "True if Afterburners are on, false or nil if not", "boolean", "Detects whether afterburner is active")
2864 {
2865  physics_info_h *pih;
2866  if(!ade_get_args(L, "o", l_Physics.GetPtr(&pih)))
2867  return ADE_RETURN_NIL;
2868 
2869  if(!pih->IsValid())
2870  return ade_set_error(L, "b", false);
2871 
2872  if (pih->pi->flags & PF_AFTERBURNER_ON)
2873  return ade_set_args(L, "b", true);
2874  else
2875  return ade_set_args(L, "b", false);
2876 }
2877 
2878 //nukes glide function
2879 ADE_FUNC(isGliding, l_Physics, NULL, "True if glide mode is on, false or nil if not", "boolean", "Detects if ship is gliding")
2880 {
2881  physics_info_h *pih;
2882  if(!ade_get_args(L, "o", l_Physics.GetPtr(&pih)))
2883  return ADE_RETURN_NIL;
2884 
2885  if(!pih->IsValid())
2886  return ade_set_error(L, "b", false);
2887 
2888  if (pih->pi->flags & (PF_GLIDING|PF_FORCE_GLIDE))
2889  return ade_set_args(L, "b", true);
2890  else
2891  return ade_set_args(L, "b", false);
2892 }
2893 
2894 ADE_FUNC(applyWhack, l_Physics, "vector Impulse, [ vector Position]", "Applies a whack to an object at a position (a local vector) based on impulse supplied (a world vector). If no position is supplied, an empty vector is used.", "boolean", "true if it succeeded, false otherwise")
2895  {
2896  object_h objh;
2897  physics_info_h *pih;
2898  vec3d *impulse;
2900 
2901  if (!ade_get_args(L, "oo|o", l_Physics.GetPtr(&pih), l_Vector.GetPtr(&impulse), l_Vector.GetPtr(&offset)))
2902  return ADE_RETURN_NIL;
2903 
2904  objh = pih->objh;
2905 
2906  physics_apply_whack(impulse, offset, pih->pi, &objh.objp->orient, pih->pi->mass);
2907 
2908  return ADE_RETURN_TRUE;
2909 
2910 }
2911 
2912 
2913 //**********HANDLE: sexpvariable
2915 {
2916  int idx;
2918 
2919  sexpvar_h(){idx=-1;variable_name[0]='\0';}
2920  sexpvar_h(int n_idx){idx = n_idx; strcpy_s(variable_name, Sexp_variables[n_idx].variable_name);}
2921  bool IsValid(){
2922  return (idx > -1
2923  && idx < MAX_SEXP_VARIABLES
2925  && !strcmp(Sexp_variables[idx].variable_name, variable_name));}
2926 };
2927 
2928 ade_obj<sexpvar_h> l_SEXPVariable("sexpvariable", "SEXP Variable handle");
2929 
2930 ADE_VIRTVAR(Persistence, l_SEXPVariable, "enumeration", "SEXP Variable persistance, uses SEXPVAR_*_PERSISTENT enumerations", "enumeration", "SEXPVAR_*_PERSISTENT enumeration, or invalid numeration if handle is invalid")
2931 {
2932  sexpvar_h *svh = NULL;
2933  enum_h *type = NULL;
2934  if(!ade_get_args(L, "o|o", l_SEXPVariable.GetPtr(&svh), l_Enum.GetPtr(&type)))
2935  return ade_set_error(L, "o", l_Enum.Set(enum_h()));
2936 
2937  if(!svh->IsValid())
2938  return ade_set_error(L, "o", l_Enum.Set(enum_h()));
2939 
2940  sexp_variable *sv = &Sexp_variables[svh->idx];
2941 
2942  if(ADE_SETTING_VAR && type != NULL)
2943  {
2944  if(type->index == LE_SEXPVAR_PLAYER_PERSISTENT)
2945  {
2948  }
2949  else if(type->index == LE_SEXPVAR_CAMPAIGN_PERSISTENT)
2950  {
2953  }
2954  else if(type->index == LE_SEXPVAR_NOT_PERSISTENT)
2955  {
2958  }
2959  }
2960 
2961  enum_h ren;
2966  else
2968 
2969  return ade_set_args(L, "o", l_Enum.Set(ren));
2970 }
2971 
2972 ADE_VIRTVAR(Type, l_SEXPVariable, "enumeration", "SEXP Variable type, uses SEXPVAR_TYPE_* enumerations", "enumeration", "SEXPVAR_TYPE_* enumeration, or invalid numeration if handle is invalid")
2973 {
2974  sexpvar_h *svh = NULL;
2975  enum_h *type = NULL;
2976  if(!ade_get_args(L, "o|o", l_SEXPVariable.GetPtr(&svh), l_Enum.GetPtr(&type)))
2977  return ade_set_error(L, "o", l_Enum.Set(enum_h()));
2978 
2979  if(!svh->IsValid())
2980  return ade_set_error(L, "o", l_Enum.Set(enum_h()));
2981 
2982  sexp_variable *sv = &Sexp_variables[svh->idx];
2983 
2984  if(ADE_SETTING_VAR && type != NULL)
2985  {
2986  if(type->index == LE_SEXPVAR_TYPE_NUMBER)
2987  {
2988  sv->type &= ~(SEXP_VARIABLE_NUMBER);
2989  sv->type |= SEXP_VARIABLE_STRING;
2990  }
2991  else if(type->index == LE_SEXPVAR_TYPE_STRING)
2992  {
2993  sv->type |= SEXP_VARIABLE_NUMBER;
2994  sv->type &= ~(SEXP_VARIABLE_STRING);
2995  }
2996  }
2997 
2998  enum_h ren;
2999  if(sv->type & SEXP_VARIABLE_NUMBER)
3001  else if(sv->type & SEXP_VARIABLE_STRING)
3003 
3004  return ade_set_args(L, "o", l_Enum.Set(ren));
3005 }
3006 
3007 ADE_VIRTVAR(Value, l_SEXPVariable, "number/string", "SEXP variable value", "string", "SEXP variable contents, or nil if the variable is of an invalid type or the handle is invalid")
3008 {
3009  sexpvar_h *svh = NULL;
3010  char *newvalue = NULL;
3011  char number_as_str[TOKEN_LENGTH];
3012 
3013  if(lua_type(L, 2) == LUA_TNUMBER)
3014  {
3015  int newnumber = 0;
3016  if(!ade_get_args(L, "o|i", l_SEXPVariable.GetPtr(&svh), &newnumber))
3017  return ADE_RETURN_NIL;
3018 
3019  sprintf(number_as_str, "%d", newnumber);
3020  newvalue = number_as_str;
3021  }
3022  else
3023  {
3024  if(!ade_get_args(L, "o|s", l_SEXPVariable.GetPtr(&svh), &newvalue))
3025  return ADE_RETURN_NIL;
3026  }
3027 
3028  if(!svh->IsValid())
3029  return ADE_RETURN_NIL;
3030 
3031  sexp_variable *sv = &Sexp_variables[svh->idx];
3032 
3033  if(ADE_SETTING_VAR && newvalue)
3034  {
3035  sexp_modify_variable(newvalue, svh->idx, false);
3036  }
3037 
3038  if(sv->type & SEXP_VARIABLE_NUMBER)
3039  return ade_set_args(L, "i", atoi(sv->text));
3040  else if(sv->type & SEXP_VARIABLE_STRING)
3041  return ade_set_args(L, "s", sv->text);
3042  else
3043  return ADE_RETURN_NIL;
3044 }
3045 
3046 ADE_FUNC(__tostring, l_SEXPVariable, NULL, "Returns SEXP name", "string", "SEXP name, or empty string if handle is invalid")
3047 {
3048  sexpvar_h *svh = NULL;
3049  if(!ade_get_args(L, "o", l_SEXPVariable.GetPtr(&svh)))
3050  return ade_set_error(L, "s", "");
3051 
3052  if(!svh->IsValid())
3053  return ade_set_error(L, "s", "");
3054 
3055  return ade_set_args(L, "s", Sexp_variables[svh->idx].variable_name);
3056 }
3057 
3058 ADE_FUNC(isValid, l_SEXPVariable, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
3059 {
3060  sexpvar_h *svh = NULL;
3061  if(!ade_get_args(L, "o", l_SEXPVariable.GetPtr(&svh)))
3062  return ADE_RETURN_NIL;
3063 
3064  if(!svh->IsValid())
3065  return ADE_RETURN_FALSE;
3066 
3067  return ADE_RETURN_TRUE;
3068 }
3069 
3070 ADE_FUNC(delete, l_SEXPVariable, NULL, "Deletes a SEXP Variable", "boolean", "True if successful, false if the handle is invalid")
3071 {
3072  sexpvar_h *svh = NULL;
3073  if(!ade_get_args(L, "o", l_SEXPVariable.GetPtr(&svh)))
3074  return ade_set_error(L, "b", false);
3075 
3076  if(!svh->IsValid())
3077  return ade_set_error(L, "b", false);
3078 
3079  sexp_variable_delete(svh->idx);
3080 
3081  return ADE_RETURN_TRUE;
3082 }
3083 
3084 //**********HANDLE: Shields
3085 ade_obj<object_h> l_Shields("shields", "Shields handle");
3086 
3087 ADE_FUNC(__len, l_Shields, NULL, "Number of shield segments", "number", "Number of shield segments or 0 if handle is invalid")
3088 {
3089  object_h *objh;
3090 
3091  if(!ade_get_args(L, "o", l_Shields.GetPtr(&objh)))
3092  return ade_set_error(L, "i", -1);
3093 
3094  if(!objh->IsValid())
3095  return ade_set_error(L, "i", -1);
3096 
3097  return ade_set_args(L, "i", objh->objp->n_quadrants);
3098 }
3099 
3100 ADE_INDEXER(l_Shields, "enumeration/number", "Gets or sets shield segment strength. Use \"SHIELD_*\" enumerations (for standard 4-quadrant shields) or index of a specific segment, or NONE for the entire shield", "number", "Segment/shield strength, or 0 if handle is invalid")
3101 {
3102  object_h *objh;
3103  float nval = -1.0f;
3104 
3105  object *objp = NULL;
3106  int qdx = -1;
3107 
3108  if(lua_isstring(L, 2))
3109  {
3110  char *qd = NULL;
3111  if(!ade_get_args(L, "os|f", l_Shields.GetPtr(&objh), &qd, &nval))
3112  return ade_set_error(L, "f", 0.0f);
3113 
3114  if(!objh->IsValid())
3115  return ade_set_error(L, "f", 0.0f);
3116 
3117  objp = objh->objp;
3118 
3119  //Which quadrant?
3120  int qdi;
3121  if(qd == NULL)
3122  qdx = -1;
3123  else if((qdi = atoi(qd)) > 0 && qdi <= objp->n_quadrants)
3124  qdx = qdi-1; //LUA->FS2
3125  else
3126  return ade_set_error(L, "f", 0.0f);
3127  } else {
3128  enum_h *qd = NULL;
3129  if(!ade_get_args(L, "oo|f", l_Shields.GetPtr(&objh), l_Enum.GetPtr(&qd), &nval))
3130  return 0;
3131 
3132  if(!objh->IsValid())
3133  return ade_set_error(L, "f", 0.0f);
3134 
3135  objp = objh->objp;
3136 
3137  switch(qd->index)
3138  {
3139  case LE_NONE:
3140  qdx = -1;
3141  break;
3142  case LE_SHIELD_FRONT:
3143  qdx = FRONT_QUAD;
3144  break;
3145  case LE_SHIELD_LEFT:
3146  qdx = LEFT_QUAD;
3147  break;
3148  case LE_SHIELD_RIGHT:
3149  qdx = RIGHT_QUAD;
3150  break;
3151  case LE_SHIELD_BACK:
3152  qdx = REAR_QUAD;
3153  break;
3154  default:
3155  return ade_set_error(L, "f", 0.0f);
3156  }
3157  }
3158 
3159  //Set/get all quadrants
3160  if(qdx == -1) {
3161  if(ADE_SETTING_VAR && nval >= 0.0f)
3162  shield_set_strength(objp, nval);
3163 
3164  return ade_set_args(L, "f", shield_get_strength(objp));
3165  }
3166 
3167  //Set one quadrant?
3168  if(ADE_SETTING_VAR && nval >= 0.0f)
3169  shield_set_quad(objp, qdx, nval);
3170 
3171  //Get one quadrant
3172  return ade_set_args(L, "f", shield_get_quad(objp, qdx));
3173 }
3174 
3175 //WMC - Not sure if I want this to be a variable. It'd make more sense
3176 //as a function, since it modifies all quadrant variables
3177 //WMC - Ehh, screw it.
3178 ADE_VIRTVAR(CombinedLeft, l_Shields, "number", "Total shield hitpoints left (for all segments combined)", "number", "Combined shield strength, or 0 if handle is invalid")
3179 {
3180  object_h *objh;
3181  float nval = -1.0f;
3182  if(!ade_get_args(L, "o|f", l_Shields.GetPtr(&objh), &nval))
3183  return ade_set_error(L, "f", 0.0f);
3184 
3185  if(!objh->IsValid())
3186  return ade_set_error(L, "f", 0.0f);
3187 
3188  if(ADE_SETTING_VAR && nval >= 0.0f) {
3189  shield_set_strength(objh->objp, nval);
3190  }
3191 
3192  return ade_set_args(L, "f", shield_get_strength(objh->objp));
3193 }
3194 
3195 ADE_VIRTVAR(CombinedMax, l_Shields, "number", "Maximum shield hitpoints (for all segments combined)", "number", "Combined maximum shield strength, or 0 if handle is invalid")
3196 {
3197  object_h *objh;
3198  float nval = -1.0f;
3199  if(!ade_get_args(L, "o|f", l_Shields.GetPtr(&objh), &nval))
3200  return 0;
3201 
3202  if(!objh->IsValid())
3203  return ade_set_error(L, "f", 0.0f);
3204 
3205  if(ADE_SETTING_VAR && nval >= 0.0f) {
3206  shield_set_max_strength(objh->objp, nval);
3207  }
3208 
3209  return ade_set_args(L, "f", shield_get_max_strength(objh->objp));
3210 }
3211 
3212 ADE_FUNC(isValid, l_Shields, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
3213 {
3214  object_h *oh;
3215  if(!ade_get_args(L, "o", l_Shields.GetPtr(&oh)))
3216  return ADE_RETURN_NIL;
3217 
3218  return ade_set_args(L, "b", oh->IsValid());
3219 }
3220 
3221 //**********HANDLE: Shiptype
3222 ade_obj<int> l_Shiptype("shiptype", "Ship type handle");
3223 extern int Species_initted;
3224 
3225 ADE_VIRTVAR(Name, l_Shiptype, "string", "Ship type name", "string", "Ship type name, or empty string if handle is invalid")
3226 {
3227  if(!Species_initted)
3228  return ade_set_error(L, "s", "");
3229 
3230  char *s = NULL;
3231  int idx;
3232  if(!ade_get_args(L, "o|s", l_Shiptype.Get(&idx), &s))
3233  return ade_set_error(L, "s", "");
3234 
3235  if(idx < 0 || idx >= (int)Ship_types.size())
3236  return ade_set_error(L, "s", "");
3237 
3238  if(ADE_SETTING_VAR && s != NULL) {
3239  strncpy(Ship_types[idx].name, s, sizeof(Ship_types[idx].name)-1);
3240  }
3241 
3242  return ade_set_args(L, "s", Ship_types[idx].name);
3243 }
3244 
3245 ADE_FUNC(isValid, l_Shiptype, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
3246 {
3247  int idx;
3248  if(!ade_get_args(L, "o", l_Shiptype.Get(&idx)))
3249  return ADE_RETURN_NIL;
3250 
3251  if(idx < 0 || idx >= (int)Ship_types.size())
3252  return ADE_RETURN_FALSE;
3253 
3254  return ADE_RETURN_TRUE;
3255 }
3256 
3257 //**********HANDLE: Species
3258 ade_obj<int> l_Species("species", "Species handle");
3259 extern int Species_initted;
3260 
3261 ADE_VIRTVAR(Name, l_Species, "string", "Species name", "string", "Species name, or empty string if handle is invalid")
3262 {
3263  if(!Species_initted)
3264  return ade_set_error(L, "s", "");
3265 
3266  char *s = NULL;
3267  int idx;
3268  if(!ade_get_args(L, "o|s", l_Species.Get(&idx), &s))
3269  return ade_set_error(L, "s", "");
3270 
3271  if(idx < 0 || idx >= (int)Species_info.size())
3272  return ade_set_error(L, "s", "");
3273 
3274  if(ADE_SETTING_VAR && s != NULL) {
3275  strncpy(Species_info[idx].species_name, s, sizeof(Species_info[idx].species_name)-1);
3276  }
3277 
3278  return ade_set_args(L, "s", Species_info[idx].species_name);
3279 }
3280 
3281 ADE_FUNC(isValid, l_Species, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
3282 {
3283  int idx;
3284  if(!ade_get_args(L, "o", l_Species.Get(&idx)))
3285  return ADE_RETURN_NIL;
3286 
3287  if(idx < 0 || idx >= (int)Species_info.size())
3288  return ADE_RETURN_FALSE;
3289 
3290  return ADE_RETURN_TRUE;
3291 }
3292 
3293 //**********HANDLE: Team
3294 ade_obj<int> l_Team("team", "Team handle");
3295 
3296 ADE_FUNC(__eq, l_Team, "team, team", "Checks whether two teams are the same team", "boolean", "true if equal")
3297 {
3298  int t1, t2;
3299  if(!ade_get_args(L, "oo", l_Team.Get(&t1), l_Team.Get(&t2)))
3300  return ADE_RETURN_FALSE;
3301 
3302  return ade_set_args(L, "b", (t1 == t2));
3303 }
3304 
3305 ADE_VIRTVAR(Name, l_Team, "string", "Team name", "string", "Team name, or empty string if handle is invalid")
3306 {
3307  int tdx=-1;
3308  char *s=NULL;
3309  if(!ade_get_args(L, "o|s", l_Team.Get(&tdx), &s))
3310  return ade_set_error(L, "s", "");
3311 
3312  if(tdx < 0 || tdx > Num_iffs)
3313  return ade_set_error(L, "s", "");
3314 
3315  if(ADE_SETTING_VAR && s != NULL) {
3316  strncpy(Iff_info[tdx].iff_name, s, NAME_LENGTH-1);
3317  }
3318 
3319  return ade_set_args(L, "s", Iff_info[tdx].iff_name);
3320 }
3321 
3322 ADE_FUNC(getColor, l_Team, NULL, "Gets the IFF color of the specified Team", "number, number, number", "rgb color for the specified team or nil if invalid") {
3323  int idx;
3324  int r,g,b;
3325  if(!ade_get_args(L, "o", l_Team.Get(&idx)))
3326  return ADE_RETURN_NIL;
3327 
3328  if(idx < 0 || idx >= Num_iffs)
3329  return ADE_RETURN_NIL;
3330 
3331  color* col = iff_get_color_by_team(idx, 0, 0);
3332 
3333  r = col->red;
3334  g = col->green;
3335  b = col->blue;
3336 
3337  return ade_set_args(L, "iii", r, g, b);
3338 }
3339 
3340 ADE_FUNC(isValid, l_Team, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
3341 {
3342  int idx;
3343  if(!ade_get_args(L, "o", l_Team.Get(&idx)))
3344  return ADE_RETURN_NIL;
3345 
3346  if(idx < 0 || idx >= Num_iffs)
3347  return ADE_RETURN_FALSE;
3348 
3349  return ADE_RETURN_TRUE;
3350 }
3351 
3352 //**********HANDLE: Texture
3353 ade_obj<int> l_Texture("texture", "Texture handle");
3354 //WMC - int should NEVER EVER be an invalid handle. Return Nil instead. Nil FTW.
3355 
3356 static float lua_Opacity = 1.0f;
3357 static int lua_Opacity_type = GR_ALPHABLEND_NONE;
3358 
3359 ADE_FUNC(__gc, l_Texture, NULL, "Auto-deletes texture", NULL, NULL)
3360 {
3361  int idx;
3362 
3363  if(!ade_get_args(L, "o", l_Texture.Get(&idx)))
3364  return ADE_RETURN_NIL;
3365 
3366  // Note: due to some unknown reason, in some circumstances this function
3367  // might get called even for handles to bitmaps which are actually still in
3368  // use, and in order to prevent that we want to double-check the load count
3369  // here before unloading the bitmap. -zookeeper
3370  if(idx > -1 && bm_is_valid(idx) && bm_bitmaps[bm_get_cache_slot(idx, 0)].load_count < 1)
3371  bm_release(idx);
3372 
3373  return ADE_RETURN_NIL;
3374 }
3375 
3376 ADE_FUNC(__eq, l_Texture, "texture, texture", "Checks if two texture handles refer to the same texture", "boolean", "True if textures are equal")
3377 {
3378  int idx,idx2;
3379 
3380  if(!ade_get_args(L, "oo", l_Texture.Get(&idx), l_Texture.Get(&idx2)))
3381  return ADE_RETURN_NIL;
3382 
3383  if(idx == idx2)
3384  return ADE_RETURN_TRUE;
3385 
3386  return ADE_RETURN_FALSE;
3387 }
3388 
3390  "Returns texture handle to specified frame number in current texture's animation."
3391  "This means that [1] will always return the first frame in an animation, no matter what frame an animation is."
3392  "You cannot change a texture animation frame.",
3393  "texture",
3394  "Texture handle, or invalid texture handle if index is invalid")
3395 {
3396  int idx;
3397  int frame=-1;
3398  int newframe=-1; //WMC - Ignore for now
3399  if(!ade_get_args(L, "oi|i", l_Texture.Get(&idx), &frame, &newframe))
3400  return ade_set_error(L, "o", l_Texture.Set(-1));
3401 
3402  if(frame < 1)
3403  return ade_set_error(L, "o", l_Texture.Set(-1));
3404 
3405  //Get me some info
3406  int num=-1;
3407  int first=-1;
3408  first = bm_get_info(idx, NULL, NULL, NULL, &num);
3409 
3410  //Check it's a valid one
3411  if(first < 0 || frame > num)
3412  return ade_set_error(L, "o", l_Texture.Set(-1));
3413 
3414  frame--; //Lua->FS2
3415 
3416  //Get actual texture handle
3417  frame = first + frame;
3418 
3419  return ade_set_args(L, "o", l_Texture.Set(frame));
3420 }
3421 
3422 ADE_FUNC(isValid, l_Texture, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
3423 {
3424  int idx;
3425  if(!ade_get_args(L, "o", l_Texture.Get(&idx)))
3426  return ADE_RETURN_NIL;
3427 
3428  return ade_set_args(L, "b", bm_is_valid(idx));
3429 }
3430 
3431 ADE_FUNC(unload, l_Texture, NULL, "Unloads a texture from memory", NULL, NULL)
3432 {
3433  int *idx;
3434 
3435  if(!ade_get_args(L, "o", l_Texture.GetPtr(&idx)))
3436  return ADE_RETURN_NIL;
3437 
3438  if(!bm_is_valid(*idx))
3439  return ADE_RETURN_NIL;
3440 
3441  bm_release(*idx);
3442 
3443  //WMC - invalidate this handle
3444  *idx = -1;
3445 
3446  return ADE_RETURN_NIL;
3447 }
3448 
3449 ADE_FUNC(getFilename, l_Texture, NULL, "Returns filename for texture", "string", "Filename, or empty string if handle is invalid")
3450 {
3451  int idx;
3452  if(!ade_get_args(L, "o", l_Texture.Get(&idx)))
3453  return ade_set_error(L, "s", "");
3454 
3455  if(!bm_is_valid(idx))
3456  return ade_set_error(L, "s", "");
3457 
3458  return ade_set_args(L, "s", bm_get_filename(idx));
3459 }
3460 
3461 ADE_FUNC(getWidth, l_Texture, NULL, "Gets texture width", "number", "Texture width, or 0 if handle is invalid")
3462 {
3463  int idx;
3464  if(!ade_get_args(L, "o", l_Texture.Get(&idx)))
3465  return ade_set_error(L, "i", 0);
3466 
3467  if(!bm_is_valid(idx))
3468  return ade_set_error(L, "i", 0);
3469 
3470  int w = -1;
3471 
3472  if(bm_get_info(idx, &w) < 0)
3473  return ade_set_error(L, "i", 0);
3474 
3475  return ade_set_args(L, "i", w);
3476 }
3477 
3478 ADE_FUNC(getHeight, l_Texture, NULL, "Gets texture height", "number", "Texture height, or 0 if handle is invalid")
3479 {
3480  int idx;
3481  if(!ade_get_args(L, "o", l_Texture.Get(&idx)))
3482  return ade_set_error(L, "i", 0);
3483 
3484  if(!bm_is_valid(idx))
3485  return ade_set_error(L, "i", 0);
3486 
3487  int h=-1;
3488 
3489  if(bm_get_info(idx, NULL, &h) < 0)
3490  return ade_set_error(L, "i", 0);
3491 
3492  return ade_set_args(L, "i", h);
3493 }
3494 
3495 ADE_FUNC(getFPS, l_Texture, NULL,"Gets frames-per-second of texture", "number", "Texture FPS, or 0 if handle is invalid")
3496 {
3497  int idx;
3498  if(!ade_get_args(L, "o", l_Texture.Get(&idx)))
3499  return ade_set_error(L, "i", 0);
3500 
3501  if(!bm_is_valid(idx))
3502  return ade_set_error(L, "i", 0);
3503 
3504  int fps=-1;
3505 
3506  if(bm_get_info(idx, NULL, NULL, NULL, NULL, &fps) < 0)
3507  return ade_set_error(L, "i", 0);
3508 
3509  return ade_set_args(L, "i", fps);
3510 }
3511 
3512 ADE_FUNC(getFramesLeft, l_Texture, NULL, "Gets number of frames left, from handle's position in animation", "number", "Frames left, or 0 if handle is invalid")
3513 {
3514  int idx;
3515  if(!ade_get_args(L, "o", l_Texture.Get(&idx)))
3516  return ADE_RETURN_NIL;
3517 
3518  if(!bm_is_valid(idx))
3519  return ADE_RETURN_NIL;
3520 
3521  int num=-1;
3522 
3523  if(bm_get_info(idx, NULL, NULL, NULL, &num) < 0)
3524  return ade_set_error(L, "i", 0);
3525 
3526  return ade_set_args(L, "i", num);
3527 }
3528 
3529 //**********OBJECT: vector
3530 //WMC - see matrix for ade_obj def
3531 
3532 ADE_INDEXER(l_Vector, "x,y,z or 1-3", "Vector component", "number", "Value at index, or 0 if vector handle is invalid")
3533 {
3534  vec3d *v3;
3535  char *s = NULL;
3536  float newval = 0.0f;
3537  int numargs = ade_get_args(L, "os|f", l_Vector.GetPtr(&v3), &s, &newval);
3538 
3539  if(!numargs || s[1] != '\0')
3540  return ade_set_error(L, "f", 0.0f);
3541 
3542  int idx=-1;
3543  if(s[0]=='x' || s[0] == '1')
3544  idx = 0;
3545  else if(s[0]=='y' || s[0] == '2')
3546  idx = 1;
3547  else if(s[0]=='z' || s[0] == '3')
3548  idx = 2;
3549 
3550  if(idx < 0 || idx > 3)
3551  return ade_set_error(L, "f", 0.0f);
3552 
3553  if(ADE_SETTING_VAR) {
3554  v3->a1d[idx] = newval;
3555  }
3556 
3557  return ade_set_args(L, "f", v3->a1d[idx]);
3558 }
3559 
3560 ADE_FUNC(__add, l_Vector, "number/vector", "Adds vector by another vector, or adds all axes by value", "vector", "Final vector, or null vector if error occurs")
3561 {
3562  vec3d v3 = vmd_zero_vector;
3563  if(lua_isnumber(L, 1) || lua_isnumber(L, 2))
3564  {
3565  float f;
3566  if((lua_isnumber(L, 1) && ade_get_args(L, "fo", &f, l_Vector.Get(&v3)))
3567  || (lua_isnumber(L, 2) && ade_get_args(L, "of", l_Vector.Get(&v3), &f)))
3568  {
3569  v3.xyz.x += f;
3570  v3.xyz.y += f;
3571  v3.xyz.z += f;
3572  }
3573  }
3574  else
3575  {
3576  vec3d v3b;
3577  //WMC - doesn't really matter which is which
3578  if(ade_get_args(L, "oo", l_Vector.Get(&v3), l_Vector.Get(&v3b)))
3579  {
3580  vm_vec_add2(&v3, &v3b);
3581  }
3582  }
3583  return ade_set_args(L, "o", l_Vector.Set(v3));
3584 }
3585 
3586 ADE_FUNC(__sub, l_Vector, "number/vector", "Subtracts vector from another vector, or subtracts all axes by value", "vector", "Final vector, or null vector if error occurs")
3587 {
3588  vec3d v3 = vmd_zero_vector;
3589  if(lua_isnumber(L, 1) || lua_isnumber(L, 2))
3590  {
3591  float f;
3592  if((lua_isnumber(L, 1) && ade_get_args(L, "fo", &f, l_Vector.Get(&v3)))
3593  || (lua_isnumber(L, 2) && ade_get_args(L, "of", l_Vector.Get(&v3), &f)))
3594  {
3595  v3.xyz.x += f;
3596  v3.xyz.y += f;
3597  v3.xyz.z += f;
3598  }
3599  }
3600  else
3601  {
3602  vec3d v3b;
3603  //WMC - doesn't really matter which is which
3604  if(ade_get_args(L, "oo", l_Vector.Get(&v3), l_Vector.Get(&v3b)))
3605  {
3606  vm_vec_sub2(&v3, &v3b);
3607  }
3608  }
3609 
3610  return ade_set_args(L, "o", l_Vector.Set(v3));
3611 }
3612 
3613 ADE_FUNC(__mul, l_Vector, "number/vector", "Scales vector object (Multiplies all axes by number), or multiplies each axes by the other vector's axes.", "vector", "Final vector, or null vector if error occurs")
3614 {
3615  vec3d v3 = vmd_zero_vector;
3616  if(lua_isnumber(L, 1) || lua_isnumber(L, 2))
3617  {
3618  float f;
3619  if((lua_isnumber(L, 1) && ade_get_args(L, "fo", &f, l_Vector.Get(&v3)))
3620  || (lua_isnumber(L, 2) && ade_get_args(L, "of", l_Vector.Get(&v3), &f)))
3621  {
3622  vm_vec_scale(&v3, f);
3623  }
3624  }
3625  else
3626  {
3627  vec3d *v1 = NULL;
3628  vec3d *v2 = NULL;
3629  if(!ade_get_args(L, "oo", l_Vector.GetPtr(&v1), l_Vector.GetPtr(&v2)))
3630  return ade_set_args(L, "o", l_Vector.Set(vmd_zero_vector));
3631 
3632  v3.xyz.x = v1->xyz.x * v2->xyz.x;
3633  v3.xyz.y = v1->xyz.y * v2->xyz.y;
3634  v3.xyz.z = v1->xyz.z * v2->xyz.z;
3635  }
3636 
3637  return ade_set_args(L, "o", l_Vector.Set(v3));
3638 }
3639 
3640 ADE_FUNC(__div, l_Vector, "number/vector", "Scales vector object (Divide all axes by number), or divides each axes by the dividing vector's axes.", "vector", "Final vector, or null vector if error occurs")
3641 {
3642  vec3d v3 = vmd_zero_vector;
3643  if(lua_isnumber(L, 1) || lua_isnumber(L, 2))
3644  {
3645  float f;
3646  if((lua_isnumber(L, 1) && ade_get_args(L, "fo", &f, l_Vector.Get(&v3)))
3647  || (lua_isnumber(L, 2) && ade_get_args(L, "of", l_Vector.Get(&v3), &f)))
3648  {
3649  vm_vec_scale(&v3, 1.0f/f);
3650  }
3651  }
3652  else
3653  {
3654  vec3d *v1 = NULL;
3655  vec3d *v2 = NULL;
3656  if(!ade_get_args(L, "oo", l_Vector.GetPtr(&v1), l_Vector.GetPtr(&v2)))
3657  return ade_set_args(L, "o", l_Vector.Set(vmd_zero_vector));
3658 
3659  v3.xyz.x = v1->xyz.x / v2->xyz.x;
3660  v3.xyz.y = v1->xyz.y / v2->xyz.y;
3661  v3.xyz.z = v1->xyz.z / v2->xyz.z;
3662  }
3663 
3664  return ade_set_args(L, "o", l_Vector.Set(v3));
3665 }
3666 
3667 
3668 ADE_FUNC(__tostring, l_Vector, NULL, "Converts a vector to string with format \"(x,y,z)\"", "string", "Vector as string, or empty string if handle is invalid")
3669 {
3670  vec3d *v3;
3671  if(!ade_get_args(L, "o", l_Vector.GetPtr(&v3)))
3672  return ade_set_error(L, "s", "");
3673 
3674  char buf[128];
3675  sprintf(buf, "(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z);
3676 
3677  return ade_set_args(L, "s", buf);
3678 }
3679 
3680 ADE_FUNC(getOrientation, l_Vector, NULL,
3681  "Returns orientation object representing the direction of the vector. Does not require vector to be normalized.",
3682  "orientation",
3683  "Orientation object, or null orientation object if handle is invalid")
3684 {
3685  vec3d v3;
3686  if(!ade_get_args(L, "o", l_Vector.Get(&v3)))
3687  return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
3688 
3690 
3691  vm_vec_normalize_safe(&v3);
3692  vm_vector_2_matrix_norm(&mt, &v3);
3693  matrix_h mh(&mt);
3694 
3695  return ade_set_args(L, "o", l_Matrix.Set(mh));
3696 }
3697 
3698 ADE_FUNC(getMagnitude, l_Vector, NULL, "Returns the magnitude of a vector (Total regardless of direction)", "number", "Magnitude of vector, or 0 if handle is invalid")
3699 {
3700  vec3d *v3;
3701  if(!ade_get_args(L, "o", l_Vector.GetPtr(&v3)))
3702  return ade_set_error(L, "f", 0.0f);
3703 
3704  return ade_set_args(L, "f", vm_vec_mag(v3));
3705 }
3706 
3707 ADE_FUNC(getDistance, l_Vector, "Vector", "Distance", "number", "Returns distance from another vector")
3708 {
3709  vec3d *v3a, *v3b;
3710  if(!ade_get_args(L, "oo", l_Vector.GetPtr(&v3a), l_Vector.GetPtr(&v3b)))
3711  return ade_set_error(L, "f", 0.0f);
3712 
3713  return ade_set_args(L, "f",vm_vec_dist(v3a, v3b));
3714 }
3715 
3716 ADE_FUNC(getDotProduct, l_Vector, "vector OtherVector", "Returns dot product of vector object with vector argument", "number", "Dot product, or 0 if a handle is invalid")
3717 {
3718  vec3d *v3a, *v3b;
3719  if(!ade_get_args(L, "oo", l_Vector.GetPtr(&v3a), l_Vector.GetPtr(&v3b)))
3720  return ade_set_error(L, "f", 0.0f);
3721 
3722  return ade_set_args(L, "f", vm_vec_dot(v3a, v3b));
3723 }
3724 
3725 ADE_FUNC(getCrossProduct, l_Vector, "vector OtherVector", "Returns cross product of vector object with vector argument", "vector", "Cross product, or null vector if a handle is invalid")
3726 {
3727  vec3d *v3a, *v3b;
3728  if(!ade_get_args(L, "oo", l_Vector.GetPtr(&v3a), l_Vector.GetPtr(&v3b)))
3729  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
3730 
3731  vec3d v3r;
3732  vm_vec_cross(&v3r, v3a, v3b);
3733 
3734  return ade_set_args(L, "o",l_Vector.Set(v3r));
3735 }
3736 
3737 ADE_FUNC(getScreenCoords, l_Vector, NULL, "Gets screen cordinates of a world vector", "number,number", "X (number), Y (number), or false if off-screen")
3738 {
3739  vec3d v3;
3740  if(!ade_get_args(L, "o", l_Vector.Get(&v3)))
3741  return ADE_RETURN_NIL;
3742 
3743  vertex vtx;
3744  bool do_g3 = G3_count < 1;
3745  if(do_g3)
3746  g3_start_frame(1);
3747 
3748  g3_rotate_vertex(&vtx,&v3);
3749  g3_project_vertex(&vtx);
3750 
3751  if(do_g3)
3752  g3_end_frame();
3753 
3754  if(vtx.flags & PF_OVERFLOW)
3755  return ADE_RETURN_FALSE;
3756 
3757  return ade_set_args(L, "ff", vtx.screen.xyw.x, vtx.screen.xyw.y);
3758 }
3759 
3760 ADE_FUNC(getNormalized, l_Vector, NULL, "Returns a normalized version of the vector", "vector", "Normalized Vector, or NIL if invalid")
3761 {
3762  vec3d v3;
3763  if(!ade_get_args(L, "o", l_Vector.Get(&v3)))
3764  return ADE_RETURN_NIL;
3765 
3766  vm_vec_normalize(&v3);
3767 
3768  return ade_set_args(L, "o", l_Vector.Set(v3));
3769 }
3770 
3771 //**********HANDLE: material
3772 static const int THT_INDEPENDENT = 0;
3773 static const int THT_OBJECT = 1;
3774 static const int THT_MODEL = 2;
3776 {
3777 protected:
3778  int type;
3781 
3782  texture_map *tmap; //Pointer to subsystem, or NULL for the hull
3783 
3784 public:
3786  type = THT_INDEPENDENT;
3787  tmap = NULL;
3788  }
3789 
3790  texture_map_h(object *objp, texture_map *n_tmap = NULL) {
3791  type = THT_OBJECT;
3792  obj = object_h(objp);
3793  tmap = n_tmap;
3794  }
3795 
3796  texture_map_h(int modelnum, texture_map *n_tmap = NULL) {
3797  type = THT_MODEL;
3798  mdl = model_h(modelnum);
3799  tmap = n_tmap;
3800  }
3801 
3802  texture_map_h(polymodel *n_model, texture_map *n_tmap = NULL) {
3803  type = THT_MODEL;
3804  mdl = model_h(n_model);
3805  tmap = n_tmap;
3806  }
3807 
3809  {
3810  if(!this->IsValid())
3811  return NULL;
3812 
3813  return tmap;
3814  }
3815 
3816  int GetSize()
3817  {
3818  if(!this->IsValid())
3819  return 0;
3820 
3821  switch(type)
3822  {
3823  case THT_MODEL:
3824  return mdl.Get()->n_textures;
3825  case THT_OBJECT:
3826  return 0; //Can't do this right now.
3827  default:
3828  return 0;
3829  }
3830  }
3831 
3832  bool IsValid() {
3833  if(tmap == NULL)
3834  return false;
3835 
3836  switch(type)
3837  {
3838  case THT_INDEPENDENT:
3839  return true;
3840  case THT_OBJECT:
3841  return obj.IsValid();
3842  case THT_MODEL:
3843  return mdl.IsValid();
3844  default:
3845  Error(LOCATION, "Bad type in texture_map_h; debug this.");
3846  return false;
3847  }
3848  }
3849 };
3850 ade_obj<texture_map_h> l_TextureMap("material", "Texture map, including diffuse, glow, and specular textures");
3851 
3852 ADE_VIRTVAR(BaseMap, l_TextureMap, "texture", "Base texture", "texture", "Base texture, or invalid texture handle if material handle is invalid")
3853 {
3854  texture_map_h *tmh = NULL;
3855  int new_tex = -1;
3856  if(!ade_get_args(L, "o|o", l_TextureMap.GetPtr(&tmh), l_Texture.Get(&new_tex)))
3857  return ade_set_error(L, "o", l_Texture.Set(-1));
3858 
3859  texture_map *tmap = tmh->Get();
3860  if(tmap == NULL)
3861  return ade_set_error(L, "o", l_Texture.Set(-1));
3862 
3863  if(ADE_SETTING_VAR && new_tex > -1) {
3864  tmap->textures[TM_BASE_TYPE].SetTexture(new_tex);
3865  }
3866 
3867  return ade_set_args(L, "o", l_Texture.Set(tmap->textures[TM_BASE_TYPE].GetTexture()));
3868 }
3869 
3870 ADE_VIRTVAR(GlowMap, l_TextureMap, "texture", "Glow texture", "texture", "Glow texture, or invalid texture handle if material handle is invalid")
3871 {
3872  texture_map_h *tmh = NULL;
3873  int new_tex = -1;
3874  if(!ade_get_args(L, "o|o", l_TextureMap.GetPtr(&tmh), l_Texture.Get(&new_tex)))
3875  return ade_set_error(L, "o", l_Texture.Set(-1));
3876 
3877  texture_map *tmap = tmh->Get();
3878  if(tmap == NULL)
3879  return ade_set_error(L, "o", l_Texture.Set(-1));
3880 
3881  if(ADE_SETTING_VAR && new_tex > -1) {
3882  tmap->textures[TM_GLOW_TYPE].SetTexture(new_tex);
3883  }
3884 
3885  return ade_set_args(L, "o", l_Texture.Set(tmap->textures[TM_GLOW_TYPE].GetTexture()));
3886 }
3887 
3888 ADE_VIRTVAR(SpecularMap, l_TextureMap, "texture", "Specular texture", "texture", "Texture handle, or invalid texture handle if material handle is invalid")
3889 {
3890  texture_map_h *tmh = NULL;
3891  int new_tex = -1;
3892  if(!ade_get_args(L, "o|o", l_TextureMap.GetPtr(&tmh), l_Texture.Get(&new_tex)))
3893  return ade_set_error(L, "o", l_Texture.Set(-1));
3894 
3895  texture_map *tmap = tmh->Get();
3896  if(tmap == NULL)
3897  return ade_set_error(L, "o", l_Texture.Set(-1));
3898 
3899  if(ADE_SETTING_VAR && new_tex > -1) {
3900  tmap->textures[TM_SPECULAR_TYPE].SetTexture(new_tex);
3901  }
3902 
3903  return ade_set_args(L, "o", l_Texture.Set(tmap->textures[TM_SPECULAR_TYPE].GetTexture()));
3904 }
3905 
3906 //**********HANDLE: Weaponclass
3907 ade_obj<int> l_Weaponclass("weaponclass", "Weapon class handle");
3908 
3909 ADE_FUNC(__tostring, l_Weaponclass, NULL, "Weapon class name", "string", "Weapon class name, or an empty string if handle is invalid")
3910 {
3911  int idx;
3912  char *s = NULL;
3913  if(!ade_get_args(L, "o|s", l_Weaponclass.Get(&idx), &s))
3914  return ade_set_error(L, "s", "");
3915 
3916  if(idx < 0 || idx >= Num_weapon_types)
3917  return ade_set_error(L, "s", "");
3918 
3919  return ade_set_args(L, "s", Weapon_info[idx].name);
3920 }
3921 
3922 ADE_FUNC(__eq, l_Weaponclass, "weaponclass, weaponclass", "Checks if the two classes are equal", "boolean", "true if equal false otherwise")
3923 {
3924  int idx1,idx2;
3925  if(!ade_get_args(L, "oo", l_Weaponclass.Get(&idx1), l_Weaponclass.Get(&idx2)))
3926  return ade_set_error(L, "b", false);
3927 
3928  if(idx1 < 0 || idx1 >= Num_weapon_types)
3929  return ade_set_error(L, "b", false);
3930 
3931  if(idx2 < 0 || idx2 >= Num_weapon_types)
3932  return ade_set_error(L, "b", false);
3933 
3934  return ade_set_args(L, "b", idx1 == idx2);
3935 }
3936 
3937 ADE_VIRTVAR(Name, l_Weaponclass, "string", "Weapon class name", "string", "Weapon class name, or empty string if handle is invalid")
3938 
3939 {
3940  int idx;
3941  char *s = NULL;
3942  if(!ade_get_args(L, "o|s", l_Weaponclass.Get(&idx), &s))
3943  return ade_set_error(L, "s", "");
3944 
3945  if(idx < 0 || idx >= Num_weapon_types)
3946  return ade_set_error(L, "s", "");
3947 
3948  if(ADE_SETTING_VAR && s != NULL) {
3949  strncpy(Weapon_info[idx].name, s, sizeof(Weapon_info[idx].name)-1);
3950  }
3951 
3952  return ade_set_args(L, "s", Weapon_info[idx].name);
3953 }
3954 
3955 ADE_VIRTVAR(Title, l_Weaponclass, "string", "Weapon class title", "string", "Weapon class title, or empty string if handle is invalid")
3956 {
3957  int idx;
3958  char *s = NULL;
3959  if(!ade_get_args(L, "o|s", l_Weaponclass.Get(&idx), &s))
3960  return ade_set_error(L, "s", "");
3961 
3962  if(idx < 0 || idx >= Num_weapon_types)
3963  return ade_set_error(L, "s", "");
3964 
3965  if(ADE_SETTING_VAR && s != NULL) {
3966  strncpy(Weapon_info[idx].title, s, sizeof(Weapon_info[idx].title)-1);
3967  }
3968 
3969  return ade_set_args(L, "s", Weapon_info[idx].title);
3970 }
3971 
3972 ADE_VIRTVAR(Description, l_Weaponclass, "string", "Weapon class description string", "string", "Description string, or empty string if handle is invalid")
3973 {
3974  int idx;
3975  char *s = NULL;
3976  if(!ade_get_args(L, "o|s", l_Weaponclass.Get(&idx), &s))
3977  return ade_set_error(L, "s", "");
3978 
3979  if(idx < 0 || idx >= Num_weapon_types)
3980  return ade_set_error(L, "s", "");
3981 
3982  weapon_info *wip = &Weapon_info[idx];
3983 
3984  if(ADE_SETTING_VAR) {
3985  vm_free(wip->desc);
3986  if(s != NULL) {
3987  wip->desc = (char*)vm_malloc(strlen(s)+1);
3988  strcpy(wip->desc, s);
3989  } else {
3990  wip->desc = NULL;
3991  }
3992  }
3993 
3994  if(wip->desc != NULL)
3995  return ade_set_args(L, "s", wip->desc);
3996  else
3997  return ade_set_args(L, "s", "");
3998 }
3999 
4000 ADE_VIRTVAR(TechTitle, l_Weaponclass, "string", "Weapon class tech title", "string", "Tech title, or empty string if handle is invalid")
4001 {
4002  int idx;
4003  char *s = NULL;
4004  if(!ade_get_args(L, "o|s", l_Weaponclass.Get(&idx), &s))
4005  return ade_set_error(L, "s", "");
4006 
4007  if(idx < 0 || idx >= Num_weapon_types)
4008  return ade_set_error(L, "s", "");
4009 
4010  if(ADE_SETTING_VAR && s != NULL) {
4011  strncpy(Weapon_info[idx].tech_title, s, sizeof(Weapon_info[idx].tech_title)-1);
4012  }
4013 
4014  return ade_set_args(L, "s", Weapon_info[idx].tech_title);
4015 }
4016 
4017 ADE_VIRTVAR(TechAnimationFilename, l_Weaponclass, "string", "Weapon class animation filename", "string", "Filename, or empty string if handle is invalid")
4018 {
4019  int idx;
4020  char *s = NULL;
4021  if(!ade_get_args(L, "o|s", l_Weaponclass.Get(&idx), &s))
4022  return ade_set_error(L, "s", "");
4023 
4024  if(idx < 0 || idx >= Num_weapon_types)
4025  return ade_set_error(L, "s", "");
4026 
4027  if(ADE_SETTING_VAR && s != NULL) {
4028  strncpy(Weapon_info[idx].tech_anim_filename, s, sizeof(Weapon_info[idx].tech_anim_filename)-1);
4029  }
4030 
4031  return ade_set_args(L, "s", Weapon_info[idx].tech_anim_filename);
4032 }
4033 
4034 ADE_VIRTVAR(TechDescription, l_Weaponclass, "string", "Weapon class tech description string", "string", "Description string, or empty string if handle is invalid")
4035 {
4036  int idx;
4037  char *s = NULL;
4038  if(!ade_get_args(L, "o|s", l_Weaponclass.Get(&idx), &s))
4039  return ade_set_error(L, "s", "");
4040 
4041  if(idx < 0 || idx >= Num_weapon_types)
4042  return ade_set_error(L, "s", "");
4043 
4044  weapon_info *wip = &Weapon_info[idx];
4045 
4046  if(ADE_SETTING_VAR) {
4047  vm_free(wip->tech_desc);
4048  if(s != NULL) {
4049  wip->tech_desc = (char*)vm_malloc(strlen(s)+1);
4050  strcpy(wip->tech_desc, s);
4051  } else {
4052  wip->tech_desc = NULL;
4053  }
4054  }
4055 
4056  if(wip->tech_desc != NULL)
4057  return ade_set_args(L, "s", wip->tech_desc);
4058  else
4059  return ade_set_args(L, "s", "");
4060 }
4061 
4062 ADE_VIRTVAR(Model, l_Weaponclass, "model", "Model", "model", "Weapon class model, or invalid model handle if weaponclass handle is invalid")
4063 {
4064  int weapon_info_idx=-1;
4065  model_h *mdl = NULL;
4066  if(!ade_get_args(L, "o|o", l_Weaponclass.Get(&weapon_info_idx), l_Model.GetPtr(&mdl)))
4067  return ade_set_error(L, "o", l_Model.Set(-1));
4068 
4069  if(weapon_info_idx < 0 || weapon_info_idx >= Num_weapon_types)
4070  return ade_set_error(L, "o", l_Model.Set(-1));
4071 
4072  weapon_info *wip = &Weapon_info[weapon_info_idx];
4073 
4074  int mid = (mdl ? mdl->GetID() : -1);
4075 
4076  if(ADE_SETTING_VAR && mid > -1) {
4077  wip->model_num = mid;
4078  }
4079 
4080  return ade_set_args(L, "o", l_Model.Set(model_h(wip->model_num)));
4081 }
4082 
4083 ADE_VIRTVAR(ArmorFactor, l_Weaponclass, "number", "Amount of weapon damage applied to ship hull (0-1.0)", "number", "Armor factor, or empty string if handle is invalid")
4084 {
4085  int idx;
4086  float f = 0.0f;
4087  if(!ade_get_args(L, "o|f", l_Weaponclass.Get(&idx), &f))
4088  return ade_set_error(L, "f", 0.0f);
4089 
4090  if(idx < 0 || idx >= Num_weapon_types)
4091  return ade_set_error(L, "f", 0.0f);
4092 
4093  if(ADE_SETTING_VAR) {
4095  }
4096 
4097  return ade_set_args(L, "f", Weapon_info[idx].armor_factor);
4098 }
4099 
4100 ADE_VIRTVAR(Damage, l_Weaponclass, "number", "Amount of damage that weapon deals", "number", "Damage amount, or 0 if handle is invalid")
4101 {
4102  int idx;
4103  float f = 0.0f;
4104  if(!ade_get_args(L, "o|f", l_Weaponclass.Get(&idx), &f))
4105  return ade_set_error(L, "f", 0.0f);
4106 
4107  if(idx < 0 || idx >= Num_weapon_types)
4108  return ade_set_error(L, "f", 0.0f);
4109 
4110  if(ADE_SETTING_VAR) {
4111  Weapon_info[idx].damage = f;
4112  }
4113 
4114  return ade_set_args(L, "f", Weapon_info[idx].damage);
4115 }
4116 
4117 ADE_VIRTVAR(FireWait, l_Weaponclass, "number", "Weapon fire wait (cooldown time) in seconds", "number", "Fire wait time, or 0 if handle is invalid")
4118 {
4119  int idx;
4120  float f = 0.0f;
4121  if(!ade_get_args(L, "o|f", l_Weaponclass.Get(&idx), &f))
4122  return ade_set_error(L, "f", 0.0f);
4123 
4124  if(idx < 0 || idx >= Num_weapon_types)
4125  return ade_set_error(L, "f", 0.0f);
4126 
4127  if(ADE_SETTING_VAR) {
4129  }
4130 
4131  return ade_set_args(L, "f", Weapon_info[idx].fire_wait);
4132 }
4133 
4134 ADE_VIRTVAR(FreeFlightTime, l_Weaponclass, "number", "The time the weapon will fly before turing onto its target", "number", "Free flight time or emty string if invalid")
4135 {
4136  int idx;
4137  float f = 0.0f;
4138  if(!ade_get_args(L, "o|f", l_Weaponclass.Get(&idx), &f))
4139  return ade_set_error(L, "f", 0.0f);
4140 
4141  if(idx < 0 || idx >= Num_weapon_types)
4142  return ade_set_error(L, "f", 0.0f);
4143 
4144  if(ADE_SETTING_VAR) {
4146  }
4147 
4148  return ade_set_args(L, "f", Weapon_info[idx].free_flight_time);
4149 }
4150 
4151 ADE_VIRTVAR(LifeMax, l_Weaponclass, "number", "Life of weapon in seconds", "number", "Life of weapon, or 0 if handle is invalid")
4152 {
4153  int idx;
4154  float f = 0.0f;
4155  if(!ade_get_args(L, "o|f", l_Weaponclass.Get(&idx), &f))
4156  return ade_set_error(L, "f", 0.0f);
4157 
4158  if(idx < 0 || idx >= Num_weapon_types)
4159  return ade_set_error(L, "f", 0.0f);
4160 
4161  if(ADE_SETTING_VAR) {
4163  }
4164 
4165  return ade_set_args(L, "f", Weapon_info[idx].lifetime);
4166 }
4167 
4168 ADE_VIRTVAR(Range, l_Weaponclass, "number", "Range of weapon in meters", "number", "Weapon Range, or 0 if handle is invalid")
4169 {
4170  int idx;
4171  float f = 0.0f;
4172  if(!ade_get_args(L, "o|f", l_Weaponclass.Get(&idx), &f))
4173  return ade_set_error(L, "f", 0.0f);
4174 
4175  if(idx < 0 || idx >= Num_weapon_types)
4176  return ade_set_error(L, "f", 0.0f);
4177 
4178  if(ADE_SETTING_VAR) {
4180  }
4181 
4182  return ade_set_args(L, "f", Weapon_info[idx].weapon_range);
4183 }
4184 
4185 ADE_VIRTVAR(Mass, l_Weaponclass, "number", "Weapon mass", "number", "Weapon mass, or 0 if handle is invalid")
4186 {
4187  int idx;
4188  float f = 0.0f;
4189  if(!ade_get_args(L, "o|f", l_Weaponclass.Get(&idx), &f))
4190  return ade_set_error(L, "f", 0.0f);
4191 
4192  if(idx < 0 || idx >= Num_weapon_types)
4193  return ade_set_error(L, "f", 0.0f);
4194 
4195  if(ADE_SETTING_VAR) {
4196  Weapon_info[idx].mass = f;
4197  }
4198 
4199  return ade_set_args(L, "f", Weapon_info[idx].mass);
4200 }
4201 
4202 ADE_VIRTVAR(ShieldFactor, l_Weaponclass, "number", "Amount of weapon damage applied to ship shields (0-1.0)", "number", "Shield damage factor, or 0 if handle is invalid")
4203 {
4204  int idx;
4205  float f = 0.0f;
4206  if(!ade_get_args(L, "o|f", l_Weaponclass.Get(&idx), &f))
4207  return ade_set_error(L, "f", 0.0f);
4208 
4209  if(idx < 0 || idx >= Num_weapon_types)
4210  return ade_set_error(L, "f", 0.0f);
4211 
4212  if(ADE_SETTING_VAR) {
4214  }
4215 
4216  return ade_set_args(L, "f", Weapon_info[idx].shield_factor);
4217 }
4218 
4219 ADE_VIRTVAR(SubsystemFactor, l_Weaponclass, "number", "Amount of weapon damage applied to ship subsystems (0-1.0)", "number", "Subsystem damage factor, or 0 if handle is invalid")
4220 {
4221  int idx;
4222  float f = 0.0f;
4223  if(!ade_get_args(L, "o|f", l_Weaponclass.Get(&idx), &f))
4224  return ade_set_error(L, "f", 0.0f);
4225 
4226  if(idx < 0 || idx >= Num_weapon_types)
4227  return ade_set_error(L, "f", 0.0f);
4228 
4229  if(ADE_SETTING_VAR) {
4231  }
4232 
4233  return ade_set_args(L, "f", Weapon_info[idx].subsystem_factor);
4234 }
4235 
4236 ADE_VIRTVAR(TargetLOD, l_Weaponclass, "number", "LOD used for weapon model in the targeting computer", "number", "LOD number, or 0 if handle is invalid")
4237 {
4238  int idx;
4239  int lod = 0;
4240  if(!ade_get_args(L, "o|i", l_Weaponclass.Get(&idx), &lod))
4241  return ade_set_error(L, "i", 0);
4242 
4243  if(idx < 0 || idx >= Num_weapon_types)
4244  return ade_set_error(L, "i", 0);
4245 
4246  if(ADE_SETTING_VAR) {
4248  }
4249 
4250  return ade_set_args(L, "i", Weapon_info[idx].hud_target_lod);
4251 }
4252 
4253 ADE_VIRTVAR(Speed, l_Weaponclass, "number", "Weapon max speed, aka $Velocity in weapons.tbl", "number", "Weapon speed, or 0 if handle is invalid")
4254 {
4255  int idx;
4256  float spd = 0.0f;
4257  if(!ade_get_args(L, "o|f", l_Weaponclass.Get(&idx), &spd))
4258  return ade_set_error(L, "f", 0.0f);
4259 
4260  if(idx < 0 || idx >= Num_weapon_types)
4261  return ade_set_error(L, "f", 0.0f);
4262 
4263  if(ADE_SETTING_VAR) {
4264  Weapon_info[idx].max_speed = spd;
4265  }
4266 
4267  return ade_set_args(L, "f", Weapon_info[idx].max_speed);
4268 }
4269 
4270 ADE_VIRTVAR(Bomb, l_Weaponclass, "boolean", "Is weapon class flagged as bomb", "boolean", "New flag")
4271 {
4272  int idx;
4273  bool newVal = false;
4274  if(!ade_get_args(L, "o|b", l_Weaponclass.Get(&idx), &newVal))
4275  return ADE_RETURN_FALSE;
4276 
4277  if(idx < 0 || idx >= Num_weapon_types)
4278  return ADE_RETURN_FALSE;
4279 
4280  weapon_info *info = &Weapon_info[idx];
4281 
4282  if(ADE_SETTING_VAR)
4283  {
4284  if(newVal)
4285  {
4286  info->wi_flags |= WIF_BOMB;
4287  }
4288  else
4289  {
4290  info->wi_flags &= ~WIF_BOMB;
4291  }
4292  }
4293 
4294 
4295  if (info->wi_flags & WIF_BOMB)
4296  return ADE_RETURN_TRUE;
4297  else
4298  return ADE_RETURN_FALSE;
4299 }
4300 
4301 ADE_VIRTVAR(CargoSize, l_Weaponclass, "number", "The cargo size of this weapon class", "number", "The new cargo size or -1 on error")
4302 {
4303  int idx;
4304  float newVal = -1.0f;
4305  if(!ade_get_args(L, "o|f", l_Weaponclass.Get(&idx), &newVal))
4306  return ade_set_args(L, "f", -1.0f);
4307 
4308  if(idx < 0 || idx >= Num_weapon_types)
4309  return ade_set_args(L, "f", -1.0f);
4310 
4311  weapon_info *info = &Weapon_info[idx];
4312 
4313  if(ADE_SETTING_VAR)
4314  {
4315  if(newVal > 0)
4316  {
4317  info->cargo_size = newVal;
4318  }
4319  else
4320  {
4321  LuaError(L, "Cargo size must be bigger than zero, got %f!", newVal);
4322  }
4323  }
4324 
4325  return ade_set_args(L, "f", info->cargo_size);
4326 }
4327 
4328 ADE_FUNC(isValid, l_Weaponclass, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
4329 {
4330  int idx;
4331  if(!ade_get_args(L, "o", l_Weaponclass.Get(&idx)))
4332  return ADE_RETURN_NIL;
4333 
4334  if(idx < 0 || idx >= Num_weapon_types)
4335  return ADE_RETURN_FALSE;
4336 
4337  return ADE_RETURN_TRUE;
4338 }
4339 
4340 ADE_FUNC(getWeaponClassIndex, l_Weaponclass, NULL, "Gets the index value of the weapon class", "number", "index value of the weapon class")
4341 {
4342  int idx;
4343  if(!ade_get_args(L, "o", l_Weaponclass.Get(&idx)))
4344  return ade_set_args(L, "i", -1);
4345 
4346  if(idx < 0 || idx >= Num_weapon_types)
4347  return ade_set_args(L, "i", -1);
4348 
4349  return ade_set_args(L, "i", idx + 1);
4350 }
4351 
4352 ADE_FUNC(isLaser, l_Weaponclass, NULL, "Return true if the weapon is a primary weapon (this includes Beams). This function is deprecated, use isPrimary instead.", "boolean", "true if the weapon is a primary, false otherwise")
4353 {
4354  int idx;
4355  if(!ade_get_args(L, "o", l_Weaponclass.Get(&idx)))
4356  return ADE_RETURN_NIL;
4357 
4358  if(idx < 0 || idx >= Num_weapon_types)
4359  return ADE_RETURN_FALSE;
4360 
4361  if (Weapon_info[idx].subtype == WP_LASER)
4362  return ADE_RETURN_TRUE;
4363  else
4365 }
4366 
4367 ADE_FUNC(isMissile, l_Weaponclass, NULL, "Return true if the weapon is a secondary weapon. This function is deprecated, use isSecondary instead.", "boolean", "true if the weapon is a secondary, false otherwise")
4368 {
4369  int idx;
4370  if(!ade_get_args(L, "o", l_Weaponclass.Get(&idx)))
4371  return ADE_RETURN_NIL;
4372 
4373  if(idx < 0 || idx >= Num_weapon_types)
4374  return ADE_RETURN_FALSE;
4375 
4376  if (Weapon_info[idx].subtype == WP_MISSILE)
4377  return ADE_RETURN_TRUE;
4378  else
4379  return ADE_RETURN_FALSE;
4380 }
4381 
4382 ADE_FUNC(isPrimary, l_Weaponclass, NULL, "Return true if the weapon is a primary weapon (this includes Beams)", "boolean", "true if the weapon is a primary, false otherwise")
4383 {
4384  int idx;
4385  if(!ade_get_args(L, "o", l_Weaponclass.Get(&idx)))
4386  return ADE_RETURN_NIL;
4387 
4388  if(idx < 0 || idx >= Num_weapon_types)
4389  return ADE_RETURN_FALSE;
4390 
4391  if (Weapon_info[idx].subtype == WP_LASER)
4392  return ADE_RETURN_TRUE;
4393  else
4394  return ADE_RETURN_FALSE;
4395 }
4396 
4397 ADE_FUNC(isSecondary, l_Weaponclass, NULL, "Return true if the weapon is a secondary weapon", "boolean", "true if the weapon is a secondary, false otherwise")
4398 {
4399  int idx;
4400  if(!ade_get_args(L, "o", l_Weaponclass.Get(&idx)))
4401  return ADE_RETURN_NIL;
4402 
4403  if(idx < 0 || idx >= Num_weapon_types)
4404  return ADE_RETURN_FALSE;
4405 
4406  if (Weapon_info[idx].subtype == WP_MISSILE)
4407  return ADE_RETURN_TRUE;
4408  else
4409  return ADE_RETURN_FALSE;
4410 }
4411 
4412 ADE_FUNC(isBeam, l_Weaponclass, NULL, "Return true if the weapon is a beam", "boolean", "true if the weapon is a beam, false otherwise")
4413 {
4414  int idx;
4415  if(!ade_get_args(L, "o", l_Weaponclass.Get(&idx)))
4416  return ADE_RETURN_NIL;
4417 
4418  if(idx < 0 || idx >= Num_weapon_types)
4419  return ADE_RETURN_FALSE;
4420 
4421  if (Weapon_info[idx].wi_flags & WIF_BEAM || Weapon_info[idx].subtype == WP_BEAM)
4422  return ADE_RETURN_TRUE;
4423  else
4424  return ADE_RETURN_FALSE;
4425 }
4426 
4428 {
4429 protected:
4431 public:
4432  mc_info_h(mc_info* val) : info(val) {}
4433 
4434  mc_info_h() : info(NULL) {}
4435 
4437  {
4438  return info;
4439  }
4440 
4441  void deleteInfo()
4442  {
4443  if (!this->IsValid())
4444  return;
4445 
4446  delete info;
4447 
4448  info = NULL;
4449  }
4450 
4451  bool IsValid()
4452  {
4453  return info != NULL;
4454  }
4455 };
4456 
4457 //**********HANDLE: Collision info
4458 ade_obj<mc_info_h> l_ColInfo("collision info", "Information about a collision");
4459 
4460 ADE_FUNC(__gc, l_ColInfo, NULL, "Removes the allocated reference of this handle", NULL, NULL)
4461 {
4462  mc_info_h* info;
4463 
4464  if(!ade_get_args(L, "o", l_ColInfo.GetPtr(&info)))
4465  return ADE_RETURN_NIL;
4466 
4467  if (info->IsValid())
4468  info->deleteInfo();
4469 
4470  return ADE_RETURN_NIL;
4471 }
4472 
4473 ADE_VIRTVAR(Model, l_ColInfo, "model", "The model this collision info is about", "model", "The model")
4474 {
4475  mc_info_h* info;
4476  model_h * mh = nullptr;
4477 
4478  if(!ade_get_args(L, "o|o", l_ColInfo.GetPtr(&info), l_Model.GetPtr(&mh)))
4479  return ade_set_error(L, "o", l_Model.Set(model_h()));
4480 
4481  if (!info->IsValid())
4482  return ade_set_error(L, "o", l_Model.Set(model_h()));
4483 
4484  mc_info *collide = info->Get();
4485 
4486  int modelNum = collide->model_num;
4487 
4488  if (ADE_SETTING_VAR && mh)
4489  {
4490  if (mh->IsValid())
4491  {
4492  collide->model_num = mh->GetID();
4493  }
4494  }
4495 
4496  return ade_set_args(L, "o", l_Model.Set(model_h(modelNum)));
4497 }
4498 
4499 ADE_FUNC(getCollisionDistance, l_ColInfo, NULL, "The distance to the closest collision point", "number", "distance or -1 on error")
4500 {
4501  mc_info_h* info;
4502 
4503  if(!ade_get_args(L, "o", l_ColInfo.GetPtr(&info)))
4504  return ade_set_error(L, "f", -1.0f);
4505 
4506  if (!info->IsValid())
4507  return ade_set_error(L, "f", -1.0f);
4508 
4509  mc_info *collide = info->Get();
4510 
4511  if (collide->num_hits <= 0)
4512  {
4513  return ade_set_args(L, "f", -1.0f);;
4514  }
4515  else
4516  {
4517  return ade_set_args(L, "f", collide->hit_dist);
4518  }
4519 }
4520 
4521 ADE_FUNC(getCollisionPoint, l_ColInfo, "[boolean local]", "The collision point of this information (local to the object if boolean is set to <i>true</i>)", "vector", "The collision point or nil of none")
4522 {
4523  mc_info_h* info;
4524  bool local = false;
4525 
4526  if(!ade_get_args(L, "o|b", l_ColInfo.GetPtr(&info), &local))
4527  return ADE_RETURN_NIL;
4528 
4529  if (!info->IsValid())
4530  return ADE_RETURN_NIL;
4531 
4532  mc_info *collide = info->Get();
4533 
4534  if (collide->num_hits <= 0)
4535  {
4536  return ADE_RETURN_NIL;
4537  }
4538  else
4539  {
4540  if (local)
4541  return ade_set_args(L, "o", l_Vector.Set(collide->hit_point));
4542  else
4543  return ade_set_args(L, "o", l_Vector.Set(collide->hit_point_world));
4544  }
4545 }
4546 
4547 ADE_FUNC(getCollisionNormal, l_ColInfo, "[boolean local]", "The collision normal of this information (local to object if boolean is set to <i>true</i>)", "vector", "The collision normal or nil of none")
4548 {
4549  mc_info_h* info;
4550  bool local = false;
4551 
4552  if(!ade_get_args(L, "o|b", l_ColInfo.GetPtr(&info), &local))
4553  return ADE_RETURN_NIL;
4554 
4555  if (!info->IsValid())
4556  return ADE_RETURN_NIL;
4557 
4558  mc_info *collide = info->Get();
4559 
4560  if (collide->num_hits <= 0)
4561  {
4562  return ADE_RETURN_NIL;
4563  }
4564  else
4565  {
4566  if (!local)
4567  {
4568  vec3d normal;
4569 
4570  vm_vec_unrotate(&normal, &collide->hit_normal, collide->orient);
4571 
4572  return ade_set_args(L, "o", l_Vector.Set(normal));
4573  }
4574  else
4575  {
4576  return ade_set_args(L, "o", l_Vector.Set(collide->hit_normal));
4577  }
4578  }
4579 }
4580 
4581 ADE_FUNC(isValid, l_ColInfo, NULL, "Detects if this handle is valid", "boolean", "true if valid false otherwise")
4582 {
4583  mc_info_h* info;
4584 
4585  if(!ade_get_args(L, "o", l_ColInfo.GetPtr(&info)))
4586  return ADE_RETURN_NIL;
4587 
4588  if (info->IsValid())
4589  return ADE_RETURN_TRUE;
4590  else
4591  return ADE_RETURN_FALSE;
4592 }
4593 
4594 //**********HANDLE: modeltextures
4595 ADE_FUNC(__len, l_ModelTextures, NULL, "Number of textures on model", "number", "Number of model textures")
4596 {
4597  modeltextures_h *mth;
4598  if(!ade_get_args(L, "o", l_ModelTextures.GetPtr(&mth)))
4599  return ade_set_error(L, "i", 0);
4600 
4601  if(!mth->IsValid())
4602  return ade_set_error(L, "i", 0);
4603 
4604  polymodel *pm = mth->Get();
4605 
4606  if(pm == NULL)
4607  return ade_set_error(L, "i", 0);
4608 
4609  return ade_set_args(L, "i", TM_NUM_TYPES*pm->n_textures);
4610 }
4611 
4612 ADE_INDEXER(l_ModelTextures, "texture", "number Index/string TextureName", "texture", "Model textures, or invalid modeltextures handle if model handle is invalid")
4613 {
4614  modeltextures_h *mth = NULL;
4615  int new_tex = -1;
4616  char *s = NULL;
4617 
4618  if (!ade_get_args(L, "os|o", l_ModelTextures.GetPtr(&mth), &s, l_Texture.Get(&new_tex)))
4619  return ade_set_error(L, "o", l_Texture.Set(-1));
4620 
4621  polymodel *pm = mth->Get();
4622 
4623  if (!mth->IsValid() || s == NULL || pm == NULL)
4624  return ade_set_error(L, "o", l_Texture.Set(-1));
4625 
4626  texture_info *tinfo = NULL;
4627  texture_map *tmap = NULL;
4628 
4629  if(strspn(s, "0123456789") == strlen(s))
4630  {
4631  int num_textures = TM_NUM_TYPES*pm->n_textures;
4632  int idx = atoi(s) - 1; //Lua->FS2
4633 
4634  if (idx < 0 || idx >= num_textures)
4635  return ade_set_error(L, "o", l_Texture.Set(-1));
4636 
4637  tmap = &pm->maps[idx / TM_NUM_TYPES];
4638  tinfo = &tmap->textures[idx % TM_NUM_TYPES];
4639  }
4640 
4641  if(tinfo == NULL)
4642  {
4643  for (int i = 0; i < pm->n_textures; i++)
4644  {
4645  tmap = &pm->maps[i];
4646 
4647  int tnum = tmap->FindTexture(s);
4648  if(tnum > -1)
4649  tinfo = &tmap->textures[tnum];
4650  }
4651  }
4652 
4653  if(tinfo == NULL)
4654  return ade_set_error(L, "o", l_Texture.Set(-1));
4655 
4656  if (ADE_SETTING_VAR) {
4657  tinfo->SetTexture(new_tex);
4658  }
4659 
4660  return ade_set_args(L, "o", l_Texture.Set(tinfo->GetTexture()));
4661 }
4662 
4663 ADE_FUNC(isValid, l_ModelTextures, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
4664 {
4665  modeltextures_h *mth;
4666  if(!ade_get_args(L, "o", l_ModelTextures.GetPtr(&mth)))
4667  return ADE_RETURN_NIL;
4668 
4669  return ade_set_args(L, "b", mth->IsValid());
4670 }
4671 
4672 //**********HANDLE: Object
4673 ade_obj<object_h> l_Object("object", "Object handle");
4674 //Helper function
4675 //Returns 1 if object sig stored in idx exists, and stores Objects[] index in idx
4676 //Returns 0 if object sig does not exist, and does not change idx
4677 
4678 ADE_FUNC(__eq, l_Object, "object, object", "Checks whether two object handles are for the same object", "boolean", "True if equal, false if not or a handle is invalid")
4679 {
4680  object_h *o1, *o2;
4681  if(!ade_get_args(L, "oo", l_Object.GetPtr(&o1), l_Object.GetPtr(&o2)))
4682  return ADE_RETURN_FALSE;
4683 
4684  if(!o1->IsValid() || !o2->IsValid())
4685  return ADE_RETURN_FALSE;
4686 
4687  return ade_set_args(L, "b", o1->sig == o2->sig);
4688 }
4689 
4690 ADE_FUNC(__tostring, l_Object, NULL, "Returns name of object (if any)", "string", "Object name, or empty string if handle is invalid")
4691 {
4692  object_h *objh;
4693  if(!ade_get_args(L, "o", l_Object.GetPtr(&objh)))
4694  return ade_set_error(L, "s", "");
4695 
4696  if(!objh->IsValid())
4697  return ade_set_error(L, "s", "");
4698 
4699  char buf[512];
4700 
4701  switch(objh->objp->type)
4702  {
4703  case OBJ_SHIP:
4704  sprintf(buf, "%s", Ships[objh->objp->instance].ship_name);
4705  break;
4706  case OBJ_WEAPON:
4707  sprintf(buf, "%s projectile", Weapon_info[Weapons[objh->objp->instance].weapon_info_index].name);
4708  break;
4709  default:
4710  sprintf(buf, "Object %td [%d]", OBJ_INDEX(objh->objp), objh->sig);
4711  }
4712 
4713  return ade_set_args(L, "s", buf);
4714 }
4715 
4716 ADE_VIRTVAR(Parent, l_Object, "object", "Parent of the object. Value may also be a deriviative of the 'object' class, such as 'ship'.", "object", "Parent handle, or invalid handle if object is invalid")
4717 {
4718  object_h *objh;
4719  object_h *newparenth = NULL;
4720  if(!ade_get_args(L, "o|o", l_Object.GetPtr(&objh), l_Object.GetPtr(&newparenth)))
4721  return ade_set_error(L, "o", l_Object.Set(object_h()));
4722 
4723  if(!objh->IsValid())
4724  return ade_set_error(L, "o", l_Object.Set(object_h()));
4725 
4726  if(ADE_SETTING_VAR)
4727  {
4728  if(newparenth != NULL && newparenth->IsValid())
4729  {
4730  objh->objp->parent = OBJ_INDEX(newparenth->objp);
4731  objh->objp->parent_sig = newparenth->sig;
4732  objh->objp->parent_type = newparenth->objp->type;
4733  }
4734  else
4735  {
4736  objh->objp->parent = -1;
4737  objh->objp->parent_sig = 0;
4738  objh->objp->parent_type = OBJ_NONE;
4739  }
4740  }
4741 
4742  if(objh->objp->parent > -1)
4743  return ade_set_object_with_breed(L, objh->objp->parent);
4744  else
4745  return ade_set_args(L, "o", l_Object.Set(object_h()));
4746 }
4747 
4748 ADE_VIRTVAR(Position, l_Object, "vector", "Object world position (World vector)", "vector", "World position, or null vector if handle is invalid")
4749 {
4750  object_h *objh;
4751  vec3d *v3=NULL;
4752  if(!ade_get_args(L, "o|o", l_Object.GetPtr(&objh), l_Vector.GetPtr(&v3)))
4753  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
4754 
4755  if(!objh->IsValid())
4756  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
4757 
4758  if(ADE_SETTING_VAR && v3 != NULL) {
4759  objh->objp->pos = *v3;
4760  if (objh->objp->type == OBJ_WAYPOINT) {
4762  wpt->set_pos(v3);
4763  }
4764  }
4765 
4766  return ade_set_args(L, "o", l_Vector.Set(objh->objp->pos));
4767 }
4768 
4769 ADE_VIRTVAR(LastPosition, l_Object, "vector", "Object world position as of last frame (World vector)", "vector", "World position, or null vector if handle is invalid")
4770 {
4771  object_h *objh;
4772  vec3d *v3=NULL;
4773  if(!ade_get_args(L, "o|o", l_Object.GetPtr(&objh), l_Vector.GetPtr(&v3)))
4774  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
4775 
4776  if(!objh->IsValid())
4777  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
4778 
4779  if(ADE_SETTING_VAR && v3 != NULL) {
4780  objh->objp->last_pos = *v3;
4781  }
4782 
4783  return ade_set_args(L, "o", l_Vector.Set(objh->objp->last_pos));
4784 }
4785 
4786 ADE_VIRTVAR(Orientation, l_Object, "orientation", "Object world orientation (World orientation)", "orientation", "Orientation, or null orientation if handle is invalid")
4787 {
4788  object_h *objh;
4789  matrix_h *mh=NULL;
4790  if(!ade_get_args(L, "o|o", l_Object.GetPtr(&objh), l_Matrix.GetPtr(&mh)))
4791  return ade_set_error(L, "o", l_Matrix.Set(matrix_h(&vmd_identity_matrix)));
4792 
4793  if(!objh->IsValid())
4794  return ade_set_error(L, "o", l_Matrix.Set(matrix_h(&vmd_identity_matrix)));
4795 
4796  if(ADE_SETTING_VAR && mh != NULL) {
4797  objh->objp->orient = *mh->GetMatrix();
4798  }
4799 
4800  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&objh->objp->orient)));
4801 }
4802 
4803 ADE_VIRTVAR(LastOrientation, l_Object, "orientation", "Object world orientation as of last frame (World orientation)", "orientation", "Orientation, or null orientation if handle is invalid")
4804 {
4805  object_h *objh;
4806  matrix_h *mh=NULL;
4807  if(!ade_get_args(L, "o|o", l_Object.GetPtr(&objh), l_Matrix.GetPtr(&mh)))
4808  return ade_set_error(L, "o", l_Matrix.Set(matrix_h(&vmd_identity_matrix)));
4809 
4810  if(!objh->IsValid())
4811  return ade_set_error(L, "o", l_Matrix.Set(matrix_h(&vmd_identity_matrix)));
4812 
4813  if(ADE_SETTING_VAR && mh != NULL) {
4814  objh->objp->last_orient = *mh->GetMatrix();
4815  }
4816 
4817  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&objh->objp->last_orient)));
4818 }
4819 
4820 ADE_VIRTVAR(Physics, l_Object, "physics", "Physics data used to move ship between frames", "physics", "Physics data, or invalid physics handle if object handle is invalid")
4821 {
4822  object_h *objh;
4823  physics_info_h *pih = nullptr;
4824  if(!ade_get_args(L, "o|o", l_Object.GetPtr(&objh), l_Physics.GetPtr(&pih)))
4825  return ade_set_error(L, "o", l_Physics.Set(physics_info_h()));
4826 
4827  if(!objh->IsValid())
4828  return ade_set_error(L, "o", l_Physics.Set(physics_info_h()));
4829 
4830  if(ADE_SETTING_VAR && pih && pih->IsValid()) {
4831  objh->objp->phys_info = *pih->pi;
4832  }
4833 
4834  return ade_set_args(L, "o", l_Physics.Set(physics_info_h(objh->objp)));
4835 }
4836 
4837 ADE_VIRTVAR(HitpointsLeft, l_Object, "number", "Hitpoints an object has left", "number", "Hitpoints left, or 0 if handle is invalid")
4838 {
4839  object_h *objh = NULL;
4840  float f = -1.0f;
4841  if(!ade_get_args(L, "o|f", l_Object.GetPtr(&objh), &f))
4842  return ade_set_error(L, "f", 0.0f);
4843 
4844  if(!objh->IsValid())
4845  return ade_set_error(L, "f", 0.0f);
4846 
4847  //Set hull strength.
4848  if(ADE_SETTING_VAR) {
4849  objh->objp->hull_strength = f;
4850  }
4851 
4852  return ade_set_args(L, "f", objh->objp->hull_strength);
4853 }
4854 
4855 ADE_VIRTVAR(Shields, l_Object, "shields", "Shields", "shields", "Shields handle, or invalid shields handle if object handle is invalid")
4856 {
4857  object_h *objh;
4858  object_h *sobjh = nullptr;
4859  if(!ade_get_args(L, "o|o", l_Object.GetPtr(&objh), l_Shields.GetPtr(&sobjh)))
4860  return ade_set_error(L, "o", l_Shields.Set(object_h()));
4861 
4862  if(!objh->IsValid())
4863  return ade_set_error(L, "o", l_Shields.Set(object_h()));
4864 
4865  //WMC - copy shields
4866  if(ADE_SETTING_VAR && sobjh && sobjh->IsValid())
4867  {
4868  for(int i = 0; i < objh->objp->n_quadrants; i++)
4869  shield_set_quad(objh->objp, i, shield_get_quad(sobjh->objp, i));
4870  }
4871 
4872  return ade_set_args(L, "o", l_Shields.Set(object_h(objh->objp)));
4873 }
4874 
4875 ADE_FUNC(getSignature, l_Object, NULL, "Gets the object's unique signature", "number", "Returns the object's unique numeric signature, or -1 if invalid. Useful for creating a metadata system")
4876 {
4877  object_h *oh;
4878  if(!ade_get_args(L, "o", l_Object.GetPtr(&oh)))
4879  return ade_set_error(L, "i", -1);
4880 
4881  if(!oh->IsValid())
4882  return ade_set_error(L, "i", -1);
4883 
4884  // this shouldn't be possible, added here to trap the offending object
4885  Assert(oh->sig > 0);
4886 
4887  return ade_set_args(L, "i", oh->sig);
4888 }
4889 
4890 ADE_FUNC(isValid, l_Object, NULL, "Detects whether handle is valid", "boolean", "true if handle is valid, false if handle is invalid, nil if a syntax/type error occurs")
4891 {
4892  object_h *oh;
4893  if(!ade_get_args(L, "o", l_Object.GetPtr(&oh)))
4894  return ADE_RETURN_FALSE;
4895 
4896  return ade_set_args(L, "b", oh->IsValid());
4897 }
4898 
4899 ADE_FUNC(getBreedName, l_Object, NULL, "Gets object type", "string", "Object type name, or empty string if handle is invalid")
4900 {
4901  object_h *objh;
4902  if(!ade_get_args(L, "o", l_Object.GetPtr(&objh)))
4903  return ade_set_error(L, "s", "");
4904 
4905  if(!objh->IsValid())
4906  return ade_set_error(L, "s", "");
4907 
4908  return ade_set_args(L, "s", Object_type_names[objh->objp->type]);
4909 }
4910 
4911 ADE_VIRTVAR(CollisionGroups, l_Object, "number", "Collision group data", "number", "Current collision group signature. NOTE: This is a bitfield, NOT a normal number.")
4912 {
4913  object_h *objh = NULL;
4914  int id = 0;
4915  if(!ade_get_args(L, "o|i", l_Object.GetPtr(&objh), &id))
4916  return ade_set_error(L, "i", 0);
4917 
4918  if(!objh->IsValid())
4919  return ade_set_error(L, "i", 0);
4920 
4921  //Set collision group data
4922  if(ADE_SETTING_VAR) {
4923  objh->objp->collision_group_id = id;
4924  }
4925 
4926  return ade_set_args(L, "i", objh->objp->collision_group_id);
4927 }
4928 
4929 ADE_FUNC(getfvec, l_Object, "[boolean normalize]", "Returns the objects' current fvec.", "vector", "Objects' forward vector, or nil if invalid. If called with a true argument, vector will be normalized.")
4930 {
4931  object_h *objh = NULL;
4932  object *obj = NULL;
4933  bool normalize = false;
4934 
4935  if (!ade_get_args(L, "o|b", l_Object.GetPtr(&objh), &normalize)) {
4936  return ADE_RETURN_NIL;
4937  }
4938 
4939  if(!objh->IsValid())
4940  return ADE_RETURN_NIL;
4941 
4942  obj = objh->objp;
4943  vec3d v1 = obj->orient.vec.fvec;
4944  if (normalize)
4945  vm_vec_normalize(&v1);
4946 
4947  return ade_set_args(L, "o", l_Vector.Set(v1));
4948 }
4949 
4950 ADE_FUNC(getuvec, l_Object, "[boolean normalize]", "Returns the objects' current uvec.", "vector", "Objects' up vector, or nil if invalid. If called with a true argument, vector will be normalized.")
4951 {
4952  object_h *objh = NULL;
4953  object *obj = NULL;
4954  bool normalize = false;
4955 
4956  if (!ade_get_args(L, "o|b", l_Object.GetPtr(&objh), &normalize)) {
4957  return ADE_RETURN_NIL;
4958  }
4959 
4960  if(!objh->IsValid())
4961  return ADE_RETURN_NIL;
4962 
4963  obj = objh->objp;
4964  vec3d v1 = obj->orient.vec.uvec;
4965  if (normalize)
4966  vm_vec_normalize(&v1);
4967 
4968  return ade_set_args(L, "o", l_Vector.Set(v1));
4969 }
4970 
4971 ADE_FUNC(getrvec, l_Object, "[boolean normalize]", "Returns the objects' current rvec.", "vector", "Objects' rvec, or nil if invalid. If called with a true argument, vector will be normalized.")
4972 {
4973  object_h *objh = NULL;
4974  object *obj = NULL;
4975  bool normalize = false;
4976 
4977  if (!ade_get_args(L, "o|b", l_Object.GetPtr(&objh), &normalize)) {
4978  return ADE_RETURN_NIL;
4979  }
4980 
4981  if(!objh->IsValid())
4982  return ADE_RETURN_NIL;
4983 
4984  obj = objh->objp;
4985  vec3d v1 = obj->orient.vec.rvec;
4986  if (normalize)
4987  vm_vec_normalize(&v1);
4988 
4989  return ade_set_args(L, "o", l_Vector.Set(v1));
4990 }
4991 
4992 ADE_FUNC(checkRayCollision, l_Object, "vector Start Point, vector End Point, [boolean Local]", "Checks the collisions between the polygons of the current object and a ray", "vector, collision info", "World collision point (local if boolean is set to true) and the specific collsision info, nil if no collisions")
4993 {
4994  object_h *objh = NULL;
4995  object *obj = NULL;
4996  int model_num = -1, model_instance_num = -1, temp = 0;
4998  bool local = false;
4999  if(!ade_get_args(L, "ooo|b", l_Object.GetPtr(&objh), l_Vector.GetPtr(&v3a), l_Vector.GetPtr(&v3b), &local))
5000  return ADE_RETURN_NIL;
5001 
5002  if(!objh->IsValid())
5003  return ADE_RETURN_NIL;
5004 
5005  obj = objh->objp;
5006  int flags = 0;
5007  int submodel = -1;
5008 
5009  switch(obj->type) {
5010  case OBJ_SHIP:
5011  model_num = Ship_info[Ships[obj->instance].ship_info_index].model_num;
5012  flags = (MC_CHECK_MODEL | MC_CHECK_RAY);
5013  break;
5014  case OBJ_WEAPON:
5016  flags = (MC_CHECK_MODEL | MC_CHECK_RAY);
5017  break;
5018  case OBJ_DEBRIS:
5019  model_num = Debris[obj->instance].model_num;
5020  flags = (MC_CHECK_MODEL | MC_CHECK_RAY | MC_SUBMODEL);
5021  submodel = Debris[obj->instance].submodel_num;
5022  break;
5023  case OBJ_ASTEROID:
5025  model_num = Asteroid_info[Asteroids[obj->instance].asteroid_type].model_num[temp];
5026  flags = (MC_CHECK_MODEL | MC_CHECK_RAY);
5027  break;
5028  default:
5029  return ADE_RETURN_NIL;
5030  }
5031 
5032  if (model_num < 0)
5033  return ADE_RETURN_NIL;
5034 
5035  if (obj->type == OBJ_SHIP) {
5037  } else if (obj->type == OBJ_WEAPON) {
5039  } else if (obj->type == OBJ_ASTEROID) {
5041  }
5042 
5044  mc_info_init(&hull_check);
5045 
5046  hull_check.model_num = model_num;
5048  hull_check.submodel_num = submodel;
5049  hull_check.orient = &obj->orient;
5050  hull_check.pos = &obj->pos;
5051  hull_check.p0 = v3a;
5052  hull_check.p1 = v3b;
5053  hull_check.flags = flags;
5054 
5055  if ( !model_collide(&hull_check) ) {
5056  return ADE_RETURN_NIL;
5057  }
5058 
5059  if (local)
5060  return ade_set_args(L, "oo", l_Vector.Set(hull_check.hit_point), l_ColInfo.Set(mc_info_h(new mc_info(hull_check))));
5061  else
5062  return ade_set_args(L, "oo", l_Vector.Set(hull_check.hit_point_world), l_ColInfo.Set(mc_info_h(new mc_info(hull_check))));
5063 }
5064 
5065 //**********HANDLE: Asteroid
5066 ade_obj<object_h> l_Asteroid("asteroid", "Asteroid handle", &l_Object);
5067 
5068 ADE_VIRTVAR(Target, l_Asteroid, "object", "Asteroid target object; may be object derivative, such as ship.", "object", "Target object, or invalid handle if asteroid handle is invalid")
5069 {
5070  object_h *oh = NULL;
5071  object_h *th = NULL;
5072  if(!ade_get_args(L, "o|o", l_Asteroid.GetPtr(&oh), l_Object.GetPtr(&th)))
5073  return ade_set_error(L, "o", l_Object.Set(object_h()));
5074 
5075  if(!oh->IsValid())
5076  return ade_set_error(L, "o", l_Object.Set(object_h()));
5077 
5078  asteroid *asp = &Asteroids[oh->objp->instance];
5079 
5080  if(ADE_SETTING_VAR && th != NULL) {
5081  if(th->IsValid())
5082  asp->target_objnum = OBJ_INDEX(th->objp);
5083  else
5084  asp->target_objnum = -1;
5085  }
5086 
5087  if(asp->target_objnum > 0 && asp->target_objnum < MAX_OBJECTS)
5088  return ade_set_object_with_breed(L, asp->target_objnum);
5089  else
5090  return ade_set_error(L, "o", l_Object.Set(object_h()));
5091 
5092 }
5093 
5094 ADE_FUNC(kill, l_Asteroid, "[ship killer=nil, wvector hitpos=nil]", "Kills the asteroid. Set \"killer\" to designate a specific ship as having been the killer, and \"hitpos\" to specify the world position of the hit location; if nil, the asteroid center is used.", "boolean", "True if successful, false or nil otherwise")
5095 {
5096  object_h *victim,*killer=NULL;
5097  vec3d *hitpos=NULL;
5098  if(!ade_get_args(L, "o|oo", l_Asteroid.GetPtr(&victim), l_Ship.GetPtr(&killer), l_Vector.GetPtr(&hitpos)))
5099  return ADE_RETURN_NIL;
5100 
5101  if(!victim->IsValid())
5102  return ADE_RETURN_NIL;
5103 
5104  if(killer != NULL && !killer->IsValid())
5105  return ADE_RETURN_NIL;
5106 
5107  if (!hitpos)
5108  hitpos = &victim->objp->pos;
5109 
5110  if (killer)
5111  asteroid_hit(victim->objp, killer->objp, hitpos, victim->objp->hull_strength + 1);
5112  else
5113  asteroid_hit(victim->objp, NULL, hitpos, victim->objp->hull_strength + 1);
5114 
5115  return ADE_RETURN_TRUE;
5116 }
5117 
5118 //**********HANDLE: Cockpit Display info
5120 {
5121 private:
5122  ship_info *m_sip;
5123  size_t m_display_num;
5124 
5125 public:
5126  cockpit_disp_info_h() : m_sip( NULL ), m_display_num( INVALID_ID ) {}
5127  cockpit_disp_info_h(ship_info *sip, size_t display_num)
5128  {
5129  this->m_sip = sip;
5130  this->m_display_num = display_num;
5131  }
5132 
5134  {
5135  if (!this->isValid())
5136  return NULL;
5137 
5138  return &m_sip->displays[m_display_num];
5139  }
5140 
5141  bool isValid()
5142  {
5143  if (m_sip == NULL)
5144  {
5145  return false;
5146  }
5147 
5148  if (m_display_num == INVALID_ID)
5149  {
5150  return false;
5151  }
5152 
5153  if ( m_display_num >= m_sip->displays.size())
5154  {
5155  return false;
5156  }
5157 
5158  if (!m_sip->hud_enabled)
5159  {
5160  return false;
5161  }
5162 
5163  return true;
5164  }
5165 };
5166 
5167 ade_obj<cockpit_disp_info_h> l_DisplayInfo("display info", "Ship cockpit display information handle");
5168 
5169 ADE_FUNC(getName, l_DisplayInfo, NULL, "Gets the name of this cockpit display as defined in ships.tbl", "string", "Name string or empty string on error")
5170 {
5171  cockpit_disp_info_h *cdh = NULL;
5172 
5173  if (!ade_get_args(L, "o", l_DisplayInfo.GetPtr(&cdh)))
5174  return ade_set_error(L, "s", "");
5175 
5176  if (!cdh->isValid())
5177  return ade_set_error(L, "s", "");
5178 
5179  cockpit_display_info *cdi = cdh->Get();
5180 
5181  if (cdi == NULL)
5182  return ade_set_error(L, "s", "");
5183 
5184  return ade_set_args(L, "s", cdi->name);
5185 }
5186 
5187 ADE_FUNC(getFileName, l_DisplayInfo, NULL, "Gets the file name of the target texture of this cockpit display", "string", "Texture name string or empty string on error")
5188 {
5189  cockpit_disp_info_h *cdh = NULL;
5190 
5191  if (!ade_get_args(L, "o", l_DisplayInfo.GetPtr(&cdh)))
5192  return ade_set_error(L, "s", "");
5193 
5194  if (!cdh->isValid())
5195  return ade_set_error(L, "s", "");
5196 
5197  cockpit_display_info *cdi = cdh->Get();
5198 
5199  if (cdi == NULL)
5200  return ade_set_error(L, "s", "");
5201 
5202  return ade_set_args(L, "s", cdi->filename);
5203 }
5204 
5205 ADE_FUNC(getForegroundFileName, l_DisplayInfo, NULL, "Gets the file name of the foreground texture of this cockpit display", "string", "Foreground texture name string or nil if texture is not set or on error")
5206 {
5207  cockpit_disp_info_h *cdh = NULL;
5208 
5209  if (!ade_get_args(L, "o", l_DisplayInfo.GetPtr(&cdh)))
5210  return ADE_RETURN_NIL;
5211 
5212  if (!cdh->isValid())
5213  return ADE_RETURN_NIL;
5214 
5215  cockpit_display_info *cdi = cdh->Get();
5216 
5217  if (cdi == NULL)
5218  return ADE_RETURN_NIL;
5219 
5220  if (cdi->fg_filename[0] == 0)
5221  return ADE_RETURN_NIL;
5222 
5223  return ade_set_args(L, "s", cdi->fg_filename);
5224 }
5225 
5226 ADE_FUNC(getBackgroundFileName, l_DisplayInfo, NULL, "Gets the file name of the background texture of this cockpit display", "string", "Background texture name string or nil if texture is not set or on error")
5227 {
5228  cockpit_disp_info_h *cdh = NULL;
5229 
5230  if (!ade_get_args(L, "o", l_DisplayInfo.GetPtr(&cdh)))
5231  return ADE_RETURN_NIL;
5232 
5233  if (!cdh->isValid())
5234  return ADE_RETURN_NIL;
5235 
5236  cockpit_display_info *cdi = cdh->Get();
5237 
5238  if (cdi == NULL)
5239  return ADE_RETURN_NIL;
5240 
5241  if (cdi->bg_filename[0] == 0)
5242  return ADE_RETURN_NIL;
5243 
5244  return ade_set_args(L, "s", cdi->bg_filename);
5245 }
5246 
5247 ADE_FUNC(getSize, l_DisplayInfo, NULL, "Gets the size of this cockpit display", "number, number", "Width and height of the display or -1, -1 on error")
5248 {
5249  cockpit_disp_info_h *cdh = NULL;
5250 
5251  if (!ade_get_args(L, "o", l_DisplayInfo.GetPtr(&cdh)))
5252  return ade_set_error(L, "ii", -1, -1);
5253 
5254  if (!cdh->isValid())
5255  return ade_set_error(L, "ii", -1, -1);
5256 
5257  cockpit_display_info *cdi = cdh->Get();
5258 
5259  if (cdi == NULL)
5260  return ade_set_error(L, "ii", -1, -1);
5261 
5262  return ade_set_args(L, "ii", cdi->size[0], cdi->size[1]);
5263 }
5264 
5265 ADE_FUNC(getOffset, l_DisplayInfo, NULL, "Gets the offset of this cockpit display", "number, number", "x and y offset of the display or -1, -1 on error")
5266 {
5267  cockpit_disp_info_h *cdh = NULL;
5268 
5269  if (!ade_get_args(L, "o", l_DisplayInfo.GetPtr(&cdh)))
5270  return ade_set_error(L, "ii", -1, -1);
5271 
5272  if (!cdh->isValid())
5273  return ade_set_error(L, "ii", -1, -1);
5274 
5275  cockpit_display_info *cdi = cdh->Get();
5276 
5277  if (cdi == NULL)
5278  return ade_set_error(L, "ii", -1, -1);
5279 
5280  return ade_set_args(L, "ii", cdi->offset[0], cdi->offset[1]);
5281 }
5282 
5283 ADE_FUNC(isValid, l_DisplayInfo, NULL, "Detects whether this handle is valid", "boolean", "true if valid false otherwise")
5284 {
5285  cockpit_disp_info_h *cdh = NULL;
5286 
5287  if (!ade_get_args(L, "o", l_DisplayInfo.GetPtr(&cdh)))
5288  return ADE_RETURN_FALSE;
5289 
5290  return ade_set_args(L, "b", cdh->isValid());
5291 }
5292 
5293 //**********HANDLE: Cockpit Display
5295 {
5296 private:
5297  int obj_num;
5298  object *m_objp;
5299  size_t m_display_num;
5300 
5301 public:
5302  cockpit_display_h() : obj_num( -1 ), m_objp( NULL ), m_display_num( INVALID_ID ) {}
5303  cockpit_display_h(object *objp, size_t display_num)
5304  {
5305  this->obj_num = OBJ_INDEX(objp);
5306  this->m_objp = objp;
5307 
5308  this->m_display_num = display_num;
5309  }
5310 
5312  {
5313  if (!isValid())
5314  {
5315  return NULL;
5316  }
5317 
5318  return &Player_displays[m_display_num];
5319  }
5320 
5321  size_t GetId()
5322  {
5323  if (!isValid())
5324  {
5325  return INVALID_ID;
5326  }
5327 
5328  return m_display_num;
5329  }
5330 
5331  bool isValid()
5332  {
5333  if (obj_num < 0 || obj_num > MAX_OBJECTS)
5334  {
5335  return false;
5336  }
5337 
5338  if (m_objp == NULL || OBJ_INDEX(m_objp) != obj_num)
5339  {
5340  return false;
5341  }
5342 
5343  // Only player has cockpit displays
5344  if (m_objp != Player_obj)
5345  {
5346  return false;
5347  }
5348 
5349  if (m_display_num == INVALID_ID)
5350  {
5351  return false;
5352  }
5353 
5354  if (m_display_num >= Player_displays.size())
5355  {
5356  return false; }
5357 
5358  return true;
5359  }
5360 };
5361 ade_obj<cockpit_display_h> l_CockpitDisplay("display", "Cockpit display handle");
5362 
5363 ADE_FUNC(startRendering, l_CockpitDisplay, "[boolean setClip = true]", "Starts rendering to this cockpit display. That means if you get a valid texture handle from this function then the rendering system is ready to do a render to texture. If setClip is true then the clipping region will be set to the region of the cockpit display.<br><b>Important:</b> You have to call stopRendering after you're done or this render target will never be released!", "texture", "texture handle that is being drawn to or invalid handle on error")
5364 {
5365  cockpit_display_h *cdh = NULL;
5366  bool setClip = true;
5367 
5368  if (!ade_get_args(L, "o|b", l_CockpitDisplay.GetPtr(&cdh), &setClip))
5369  return ade_set_error(L, "o", l_Texture.Set(-1));
5370 
5371  if (!cdh->isValid())
5372  return ade_set_error(L, "o", l_Texture.Set(-1));
5373 
5374  int bm_handle = ship_start_render_cockpit_display(cdh->GetId());
5375 
5376  if (bm_is_valid(bm_handle) && setClip)
5377  {
5378  cockpit_display *cd = cdh->Get();
5379  gr_set_clip(cd->offset[0], cd->offset[1], cd->size[0], cd->size[1], GR_RESIZE_NONE);
5380  }
5381 
5382  return ade_set_args(L, "o", l_Texture.Set(bm_handle));
5383 }
5384 
5385 ADE_FUNC(stopRendering, l_CockpitDisplay, NULL, "Stops rendering to this cockpit display", "boolean", "true if successfull, false otherwise")
5386 {
5387  cockpit_display_h *cdh = NULL;
5388 
5389  if (!ade_get_args(L, "o", l_CockpitDisplay.GetPtr(&cdh)))
5390  return ADE_RETURN_FALSE;
5391 
5392  if (!cdh->isValid())
5393  return ADE_RETURN_FALSE;
5394 
5396  gr_reset_clip();
5397 
5398  return ADE_RETURN_TRUE;
5399 }
5400 
5401 ADE_FUNC(getBackgroundTexture, l_CockpitDisplay, NULL, "Gets the background texture handle of this cockpit display", "texture", "texture handle or invalid handle if no background texture or an error happened")
5402 {
5403  cockpit_display_h *cdh = NULL;
5404 
5405  if (!ade_get_args(L, "o", l_CockpitDisplay.GetPtr(&cdh)))
5406  return ade_set_error(L, "o", l_Texture.Set(-1));
5407 
5408  if (!cdh->isValid())
5409  return ade_set_error(L, "o", l_Texture.Set(-1));
5410 
5411  cockpit_display *cd = cdh->Get();
5412 
5413  if (cd == NULL)
5414  return ade_set_error(L, "o", l_Texture.Set(-1));
5415 
5416  return ade_set_args(L, "o", l_Texture.Set(cd->background));
5417 }
5418 
5419 ADE_FUNC(getForegroundTexture, l_CockpitDisplay, NULL, "Gets the foreground texture handle of this cockpit display<br>"
5420  "<b>Important:</b> If you want to do render to texture then you have to use startRendering/stopRendering", "texture", "texture handle or invalid handle if no foreground texture or an error happened")
5421 {
5422  cockpit_display_h *cdh = NULL;
5423 
5424  if (!ade_get_args(L, "o", l_CockpitDisplay.GetPtr(&cdh)))
5425  return ade_set_error(L, "o", l_Texture.Set(-1));
5426 
5427  if (!cdh->isValid())
5428  return ade_set_error(L, "o", l_Texture.Set(-1));
5429 
5430  cockpit_display *cd = cdh->Get();
5431 
5432  if (cd == NULL)
5433  return ade_set_error(L, "o", l_Texture.Set(-1));
5434 
5435  return ade_set_args(L, "o", l_Texture.Set(cd->foreground));
5436 }
5437 
5438 ADE_FUNC(getSize, l_CockpitDisplay, NULL, "Gets the size of this cockpit display", "number, number", "Width and height of the display or -1, -1 on error")
5439 {
5440  cockpit_display_h *cdh = NULL;
5441 
5442  if (!ade_get_args(L, "o", l_CockpitDisplay.GetPtr(&cdh)))
5443  return ade_set_error(L, "ii", -1, -1);
5444 
5445  if (!cdh->isValid())
5446  return ade_set_error(L, "ii", -1, -1);
5447 
5448  cockpit_display *cd = cdh->Get();
5449 
5450  if (cd == NULL)
5451  return ade_set_error(L, "ii", -1, -1);
5452 
5453  return ade_set_args(L, "ii", cd->size[0], cd->size[1]);
5454 }
5455 
5456 ADE_FUNC(getOffset, l_CockpitDisplay, NULL, "Gets the offset of this cockpit display", "number, number", "x and y offset of the display or -1, -1 on error")
5457 {
5458  cockpit_display_h *cdh = NULL;
5459 
5460  if (!ade_get_args(L, "o", l_CockpitDisplay.GetPtr(&cdh)))
5461  return ade_set_error(L, "ii", -1, -1);
5462 
5463  if (!cdh->isValid())
5464  return ade_set_error(L, "ii", -1, -1);
5465 
5466  cockpit_display *cd = cdh->Get();
5467 
5468  if (cd == NULL)
5469  return ade_set_error(L, "ii", -1, -1);
5470 
5471  return ade_set_args(L, "ii", cd->offset[0], cd->offset[1]);
5472 }
5473 
5474 ADE_FUNC(isValid, l_CockpitDisplay, NULL, "Detects whether this handle is valid or not", "boolean", "true if valid, false otherwise")
5475 {
5476  cockpit_display_h *cdh = NULL;
5477 
5478  if (!ade_get_args(L, "o", l_CockpitDisplay.GetPtr(&cdh)))
5479  return ADE_RETURN_FALSE;
5480 
5481  return ade_set_args(L, "b", cdh->isValid());
5482 }
5483 
5484 //**********HANDLE: CockpitDisplayArray
5486 {
5487 private:
5488  int m_ship_info_idx;
5489 public:
5490  cockpit_displays_info_h() : m_ship_info_idx( -1 ) {}
5491  cockpit_displays_info_h(int ship_info_idx)
5492  {
5493  this->m_ship_info_idx = ship_info_idx;
5494  }
5495 
5497  {
5498  if (!isValid())
5499  return NULL;
5500 
5501  return &Ship_info[m_ship_info_idx];
5502  }
5503 
5504  bool isValid()
5505  {
5506  if (m_ship_info_idx < 0 || m_ship_info_idx >= static_cast<int>(Ship_info.size()))
5507  {
5508  return false;
5509  }
5510 
5511  if (!Ship_info[m_ship_info_idx].hud_enabled)
5512  {
5513  return false;
5514  }
5515 
5516  return true;
5517  }
5518 };
5519 ade_obj<cockpit_displays_info_h> l_CockpitDisplayInfos("cockpitdisplays", "Array of cockpit display information");
5520 
5521 ADE_FUNC(__len, l_CockpitDisplayInfos, NULL, "Number of cockpit displays for this ship class", "number", "number of cockpit displays or -1 on error")
5522 {
5523  cockpit_displays_info_h *cdih = NULL;
5524  if (!ade_get_args(L, "o", l_CockpitDisplayInfos.GetPtr(&cdih)))
5525  return ade_set_error(L, "i", -1);
5526 
5527  if (!cdih->isValid())
5528  return ade_set_error(L, "i", -1);
5529 
5530  return ade_set_args(L, "i", (int) cdih->Get()->displays.size());
5531 }
5532 
5533 ADE_INDEXER(l_CockpitDisplayInfos, "number/string", "Returns the handle at the requested index or the handle with the specified name", "display info", "display handle or invalid handle on error")
5534 {
5535  if (lua_isnumber(L, 2))
5536  {
5537  cockpit_displays_info_h *cdih = NULL;
5538  int index = -1;
5539 
5540  if (!ade_get_args(L, "oi", l_CockpitDisplayInfos.GetPtr(&cdih), &index))
5541  {
5542  return ade_set_error(L, "o", l_DisplayInfo.Set(cockpit_disp_info_h()));
5543  }
5544 
5545  if (index < 0)
5546  {
5547  return ade_set_error(L, "o", l_DisplayInfo.Set(cockpit_disp_info_h()));
5548  }
5549 
5550  index--; // Lua -> C/C++
5551 
5552  return ade_set_args(L, "o", l_DisplayInfo.Set(cockpit_disp_info_h(cdih->Get(), index)));
5553  }
5554  else
5555  {
5556  cockpit_displays_info_h *cdih = NULL;
5557  char *name = NULL;
5558 
5559  if (!ade_get_args(L, "os", l_CockpitDisplayInfos.GetPtr(&cdih), &name))
5560  {
5561  return ade_set_error(L, "o", l_DisplayInfo.Set(cockpit_disp_info_h()));
5562  }
5563 
5564  if (!cdih->isValid())
5565  {
5566  return ade_set_error(L, "o", l_DisplayInfo.Set(cockpit_disp_info_h()));
5567  }
5568 
5569  if (name == NULL)
5570  {
5571  return ade_set_error(L, "o", l_DisplayInfo.Set(cockpit_disp_info_h()));
5572  }
5573 
5574  ship_info *sip = cdih->Get();
5575 
5576  if (!sip->hud_enabled)
5577  {
5578  return ade_set_error(L, "o", l_DisplayInfo.Set(cockpit_disp_info_h()));
5579  }
5580 
5581  size_t index = 0;
5582 
5583  for (SCP_vector<cockpit_display_info>::iterator iter = sip->displays.begin(); iter != sip->displays.end(); ++iter)
5584  {
5585  if (!strcmp(name, iter->name))
5586  {
5587  break;
5588  }
5589  else
5590  {
5591  index++;
5592  }
5593  }
5594 
5595  if (index == sip->displays.size())
5596  {
5597  LuaError(L, "Couldn't find cockpit display info with name \"%s\"", name);
5598  return ade_set_error(L, "o", l_DisplayInfo.Set(cockpit_disp_info_h()));
5599  }
5600 
5601  return ade_set_args(L, "o", l_DisplayInfo.Set(cockpit_disp_info_h(cdih->Get(), index)));
5602  }
5603 }
5604 
5605 ADE_FUNC(isValid, l_CockpitDisplayInfos, NULL, "Detects whether this handle is valid", "boolean", "true if valid, false otehrwise")
5606 {
5607  cockpit_displays_info_h *cdih = NULL;
5608  if (!ade_get_args(L, "o", l_CockpitDisplayInfos.GetPtr(&cdih)))
5609  return ADE_RETURN_FALSE;
5610 
5611  return ade_set_args(L, "b", cdih->isValid());
5612 }
5613 
5614 //**********HANDLE: Shipclass
5615 ade_obj<int> l_Shipclass("shipclass", "Ship class handle");
5616 
5617 ADE_FUNC(__tostring, l_Shipclass, NULL, "Ship class name", "string", "Ship class name, or an empty string if handle is invalid")
5618 {
5619  int idx;
5620  char *s = NULL;
5621  if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
5622  return ade_set_error(L, "s", "");
5623 
5624  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5625  return ade_set_error(L, "s", "");
5626 
5627  return ade_set_args(L, "s", Ship_info[idx].name);
5628 }
5629 
5630 ADE_FUNC(__eq, l_Shipclass, "shipclass, shipclass", "Checks if the two classes are equal", "boolean", "true if equal false otherwise")
5631 {
5632  int idx1,idx2;
5633  if(!ade_get_args(L, "oo", l_Shipclass.Get(&idx1), l_Shipclass.Get(&idx2)))
5634  return ade_set_error(L, "b", false);
5635 
5636  if(idx1 < 0 || idx1 >= static_cast<int>(Ship_info.size()))
5637  return ade_set_error(L, "b", false);
5638 
5639  if(idx2 < 0 || idx2 >= static_cast<int>(Ship_info.size()))
5640  return ade_set_error(L, "b", false);
5641 
5642  return ade_set_args(L, "b", idx1 == idx2);
5643 }
5644 
5645 ADE_VIRTVAR(Name, l_Shipclass, "string", "Ship class name", "string", "Ship class name, or an empty string if handle is invalid")
5646 {
5647  int idx;
5648  char *s = NULL;
5649  if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
5650  return ade_set_error(L, "s", "");
5651 
5652  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5653  return ade_set_error(L, "s", "");
5654 
5655  if(ADE_SETTING_VAR && s != NULL) {
5656  strncpy(Ship_info[idx].name, s, sizeof(Ship_info[idx].name)-1);
5657  }
5658 
5659  return ade_set_args(L, "s", Ship_info[idx].name);
5660 }
5661 
5662 ADE_VIRTVAR(ShortName, l_Shipclass, "string", "Ship class short name", "string", "Ship short name, or empty string if handle is invalid")
5663 {
5664  int idx;
5665  char *s = NULL;
5666  if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
5667  return ade_set_error(L, "s", "");
5668 
5669  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5670  return ade_set_error(L, "s", "");
5671 
5672  if(ADE_SETTING_VAR && s != NULL) {
5673  strncpy(Ship_info[idx].short_name, s, sizeof(Ship_info[idx].short_name)-1);
5674  }
5675 
5676  return ade_set_args(L, "s", Ship_info[idx].short_name);
5677 }
5678 
5679 ADE_VIRTVAR(TypeString, l_Shipclass, "string", "Ship class type string", "string", "Type string, or empty string if handle is invalid")
5680 {
5681  int idx;
5682  char *s = NULL;
5683  if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
5684  return ade_set_error(L, "s", "");
5685 
5686  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5687  return ade_set_error(L, "s", "");
5688 
5689  ship_info *sip = &Ship_info[idx];
5690 
5691  if(ADE_SETTING_VAR) {
5692  vm_free(sip->type_str);
5693  if(s != NULL) {
5694  sip->type_str = (char*)vm_malloc(strlen(s)+1);
5695  strcpy(sip->type_str, s);
5696  } else {
5697  sip->type_str = NULL;
5698  }
5699  }
5700 
5701  if(sip->type_str != NULL)
5702  return ade_set_args(L, "s", sip->type_str);
5703  else
5704  return ade_set_args(L, "s", "");
5705 }
5706 
5707 ADE_VIRTVAR(ManeuverabilityString, l_Shipclass, "string", "Ship class maneuverability string", "string", "Maneuverability string, or empty string if handle is invalid")
5708 {
5709  int idx;
5710  char *s = NULL;
5711  if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
5712  return ade_set_error(L, "s", "");
5713 
5714  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5715  return ade_set_error(L, "s", "");
5716 
5717  ship_info *sip = &Ship_info[idx];
5718 
5719  if(ADE_SETTING_VAR) {
5721  if(s != NULL) {
5722  sip->maneuverability_str = (char*)vm_malloc(strlen(s)+1);
5723  strcpy(sip->maneuverability_str, s);
5724  } else {
5725  sip->maneuverability_str = NULL;
5726  }
5727  }
5728 
5729  if(sip->maneuverability_str != NULL)
5730  return ade_set_args(L, "s", sip->maneuverability_str);
5731  else
5732  return ade_set_args(L, "s", "");
5733 }
5734 
5735 ADE_VIRTVAR(ArmorString, l_Shipclass, "string", "Ship class armor string", "string", "Armor string, or empty string if handle is invalid")
5736 {
5737  int idx;
5738  char *s = NULL;
5739  if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
5740  return ade_set_error(L, "s", "");
5741 
5742  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5743  return ade_set_error(L, "s", "");
5744 
5745  ship_info *sip = &Ship_info[idx];
5746 
5747  if(ADE_SETTING_VAR) {
5748  vm_free(sip->armor_str);
5749  if(s != NULL) {
5750  sip->armor_str = (char*)vm_malloc(strlen(s)+1);
5751  strcpy(sip->armor_str, s);
5752  } else {
5753  sip->armor_str = NULL;
5754  }
5755  }
5756 
5757  if(sip->armor_str != NULL)
5758  return ade_set_args(L, "s", sip->armor_str);
5759  else
5760  return ade_set_args(L, "s", "");
5761 }
5762 
5763 ADE_VIRTVAR(ManufacturerString, l_Shipclass, "string", "Ship class manufacturer", "string", "Manufacturer, or empty string if handle is invalid")
5764 {
5765  int idx;
5766  char *s = NULL;
5767  if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
5768  return ade_set_error(L, "s", "");
5769 
5770  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5771  return ade_set_error(L, "s", "");
5772 
5773  ship_info *sip = &Ship_info[idx];
5774 
5775  if(ADE_SETTING_VAR) {
5776  vm_free(sip->manufacturer_str);
5777  if(s != NULL) {
5778  sip->manufacturer_str = (char*)vm_malloc(strlen(s)+1);
5779  strcpy(sip->manufacturer_str, s);
5780  } else {
5781  sip->manufacturer_str = NULL;
5782  }
5783  }
5784 
5785  if(sip->manufacturer_str != NULL)
5786  return ade_set_args(L, "s", sip->manufacturer_str);
5787  else
5788  return ade_set_args(L, "s", "");
5789 }
5790 
5791 
5792 ADE_VIRTVAR(Description, l_Shipclass, "string", "Ship class description", "string", "Description, or empty string if handle is invalid")
5793 {
5794  int idx;
5795  char *s = NULL;
5796  if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
5797  return ade_set_error(L, "s", "");
5798 
5799  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5800  return ade_set_error(L, "s", "");
5801 
5802  ship_info *sip = &Ship_info[idx];
5803 
5804  if(ADE_SETTING_VAR) {
5805  vm_free(sip->desc);
5806  if(s != NULL) {
5807  sip->desc = (char*)vm_malloc(strlen(s)+1);
5808  strcpy(sip->desc, s);
5809  } else {
5810  sip->desc = NULL;
5811  }
5812  }
5813 
5814  if(sip->desc != NULL)
5815  return ade_set_args(L, "s", sip->desc);
5816  else
5817  return ade_set_args(L, "s", "");
5818 }
5819 
5820 ADE_VIRTVAR(TechDescription, l_Shipclass, "string", "Ship class tech description", "string", "Tech description, or empty string if handle is invalid")
5821 {
5822  int idx;
5823  char *s = NULL;
5824  if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
5825  return ade_set_error(L, "s", "");
5826 
5827  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5828  return ade_set_error(L, "s", "");
5829 
5830  ship_info *sip = &Ship_info[idx];
5831 
5832  if(ADE_SETTING_VAR) {
5833  vm_free(sip->tech_desc);
5834  if(s != NULL) {
5835  sip->tech_desc = (char*)vm_malloc(strlen(s)+1);
5836  strcpy(sip->tech_desc, s);
5837  } else {
5838  sip->tech_desc = NULL;
5839  }
5840  }
5841 
5842  if(sip->tech_desc != NULL)
5843  return ade_set_args(L, "s", sip->tech_desc);
5844  else
5845  return ade_set_args(L, "s", "");
5846 }
5847 
5848 ADE_VIRTVAR(AfterburnerFuelMax, l_Shipclass, "number", "Afterburner fuel capacity", "number", "Afterburner capacity, or 0 if handle is invalid")
5849 {
5850  int idx;
5851  float fuel = -1.0f;
5852  if(!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &fuel))
5853  return ade_set_error(L, "f", 0.0f);
5854 
5855  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5856  return ade_set_error(L, "f", 0.0f);
5857 
5858  if(ADE_SETTING_VAR && fuel >= 0.0f)
5859  Ship_info[idx].afterburner_fuel_capacity = fuel;
5860 
5861  return ade_set_args(L, "f", Ship_info[idx].afterburner_fuel_capacity);
5862 }
5863 
5864 ADE_VIRTVAR(CountermeasuresMax, l_Shipclass, "number", "Maximum number of countermeasures the ship can carry", "number", "Countermeasure capacity, or 0 if handle is invalid")
5865 {
5866  int idx;
5867  int i = -1;
5868  if(!ade_get_args(L, "o|i", l_Shipclass.Get(&idx), &i))
5869  return ade_set_error(L, "i", 0);
5870 
5871  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5872  return ade_set_error(L, "i", 0);
5873 
5874  if(ADE_SETTING_VAR && i > -1) {
5875  Ship_info[idx].cmeasure_max = i;
5876  }
5877 
5878  return ade_set_args(L, "i", Ship_info[idx].cmeasure_max);
5879 }
5880 
5881 ADE_VIRTVAR(Model, l_Shipclass, "model", "Model", "model", "Ship class model, or invalid model handle if shipclass handle is invalid")
5882 {
5883  int ship_info_idx=-1;
5884  model_h *mdl = NULL;
5885  if(!ade_get_args(L, "o|o", l_Shipclass.Get(&ship_info_idx), l_Model.GetPtr(&mdl)))
5886  return ade_set_error(L, "o", l_Model.Set(-1));
5887 
5888  if(ship_info_idx < 0 || ship_info_idx >= static_cast<int>(Ship_info.size()))
5889  return ade_set_error(L, "o", l_Model.Set(-1));
5890 
5891  ship_info *sip = &Ship_info[ship_info_idx];
5892 
5893  int mid = (mdl ? mdl->GetID() : -1);
5894 
5895  if(ADE_SETTING_VAR && mid > -1) {
5896  sip->model_num = mid;
5897  }
5898 
5899  return ade_set_args(L, "o", l_Model.Set(model_h(sip->model_num)));
5900 }
5901 
5902 ADE_VIRTVAR(CockpitModel, l_Shipclass, "model", "Model used for first-person cockpit", "model", "Cockpit model")
5903 {
5904  int ship_info_idx=-1;
5905  model_h *mdl = NULL;
5906  if(!ade_get_args(L, "o|o", l_Shipclass.Get(&ship_info_idx), l_Model.GetPtr(&mdl)))
5907  return ade_set_error(L, "o", l_Model.Set(model_h()));
5908 
5909  if(ship_info_idx < 0 || ship_info_idx >= static_cast<int>(Ship_info.size()))
5910  return ade_set_error(L, "o", l_Model.Set(model_h()));
5911 
5912  ship_info *sip = &Ship_info[ship_info_idx];
5913 
5914  int mid = (mdl ? mdl->GetID() : -1);
5915 
5916  if(ADE_SETTING_VAR) {
5917  sip->cockpit_model_num = mid;
5918  }
5919 
5920  return ade_set_args(L, "o", l_Model.Set(model_h(sip->cockpit_model_num)));
5921 }
5922 
5923 ADE_VIRTVAR(CockpitDisplays, l_Shipclass, "cockpitdisplays", "Gets the cockpit display information array of this ship class", "cockpitdisplays", "Array handle containing the information or invalid handle on error")
5924 {
5925  int ship_info_idx=-1;
5926  cockpit_displays_info_h *cdih = NULL;
5927  if(!ade_get_args(L, "o|o", l_Shipclass.Get(&ship_info_idx), l_CockpitDisplayInfos.GetPtr(&cdih)))
5929 
5930  if(ship_info_idx < 0 || ship_info_idx >= static_cast<int>(Ship_info.size()))
5932 
5933  if(ADE_SETTING_VAR) {
5934  LuaError(L, "Attempted to use incomplete feature: Cockpit display information copy");
5935  }
5936 
5937  return ade_set_args(L, "o", l_CockpitDisplayInfos.Set(cockpit_displays_info_h(ship_info_idx)));
5938 }
5939 
5940 ADE_VIRTVAR(HitpointsMax, l_Shipclass, "number", "Ship class hitpoints", "number", "Hitpoints, or 0 if handle is invalid")
5941 {
5942  int idx;
5943  float f = -1.0f;
5944  if(!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &f))
5945  return ade_set_error(L, "f", 0.0f);
5946 
5947  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5948  return ade_set_error(L, "f", 0.0f);
5949 
5950  if(ADE_SETTING_VAR && f >= 0.0f) {
5951  Ship_info[idx].max_hull_strength = f;
5952  }
5953 
5954  return ade_set_args(L, "f", Ship_info[idx].max_hull_strength);
5955 }
5956 
5957 ADE_VIRTVAR(Species, l_Shipclass, "Species", "Ship class species", "species", "Ship class species, or invalid species handle if shipclass handle is invalid")
5958 {
5959  int idx;
5960  int sidx = -1;
5961  if(!ade_get_args(L, "o|o", l_Shipclass.Get(&idx), l_Species.Get(&sidx)))
5962  return ade_set_error(L, "o", l_Species.Set(-1));
5963 
5964  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5965  return ade_set_error(L, "o", l_Species.Set(-1));
5966 
5967  if(ADE_SETTING_VAR && sidx > -1 && sidx < (int)Species_info.size()) {
5968  Ship_info[idx].species = sidx;
5969  }
5970 
5971  return ade_set_args(L, "o", l_Species.Set(Ship_info[idx].species));
5972 }
5973 
5974 ADE_VIRTVAR(Type, l_Shipclass, "shiptype", "Ship class type", "shiptype", "Ship type, or invalid handle if shipclass handle is invalid")
5975 {
5976  int idx;
5977  int sidx = -1;
5978  if(!ade_get_args(L, "o|o", l_Shipclass.Get(&idx), l_Shiptype.Get(&sidx)))
5979  return ade_set_error(L, "o", l_Shiptype.Set(-1));
5980 
5981  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5982  return ade_set_error(L, "o", l_Shiptype.Set(-1));
5983 
5984  if(ADE_SETTING_VAR && sidx > -1 && sidx < (int)Ship_types.size()) {
5985  Ship_info[idx].class_type = sidx;
5986  }
5987 
5988  return ade_set_args(L, "o", l_Shiptype.Set(Ship_info[idx].class_type));
5989 }
5990 
5991 ADE_VIRTVAR(AltName, l_Shipclass, "string", "Alternate name for ship class", "string", "Alternate string or empty string if handle is invalid")
5992 {
5993  char* newName = NULL;
5994  int idx;
5995  if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &newName))
5996  return ade_set_error(L, "s", "");
5997 
5998  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
5999  return ade_set_error(L, "s", "");
6000 
6001  if(ADE_SETTING_VAR && newName != NULL) {
6002  if (strlen(newName) >= NAME_LENGTH)
6003  {
6004  LuaError(L, "Cannot set alternate name value to '%s' because it is too long, maximum length is %d!", newName, NAME_LENGTH - 1);
6005  return ade_set_error(L, "s", "");
6006  }
6007 
6008  strcpy_s(Ship_info[idx].alt_name, newName);
6009  }
6010 
6011  return ade_set_args(L, "s", Ship_info[idx].alt_name);
6012 }
6013 
6014 ADE_FUNC(isValid, l_Shipclass, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
6015 {
6016  int idx;
6017  if(!ade_get_args(L, "o", l_Shipclass.Get(&idx)))
6018  return ADE_RETURN_NIL;
6019 
6020  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
6021  return ADE_RETURN_FALSE;
6022 
6023  return ADE_RETURN_TRUE;
6024 }
6025 
6026 ADE_FUNC(isInTechroom, l_Shipclass, NULL, "Gets whether or not the ship class is available in the techroom", "boolean", "Whether ship has been revealed in the techroom, false if handle is invalid")
6027 {
6028  int idx;
6029  if(!ade_get_args(L, "o", l_Shipclass.Get(&idx)))
6030  return ade_set_error(L, "b", false);
6031 
6032  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
6033  return ade_set_error(L, "b", false);
6034 
6035  bool b = false;
6036  if(Player != NULL && (Player->flags & PLAYER_FLAGS_IS_MULTI) && (Ship_info[idx].flags & SIF_IN_TECH_DATABASE_M)) {
6037  b = true;
6038  } else if(Ship_info[idx].flags & SIF_IN_TECH_DATABASE) {
6039  b = true;
6040  }
6041 
6042  return ade_set_args(L, "b", b);
6043 }
6044 
6045 ADE_FUNC(renderTechModel, l_Shipclass, "X1, Y1, X2, Y2, [Rotation %=0, Pitch %=0, Bank %=40, number Zoom=1.3]", "Draws ship model as if in techroom", "boolean", "Whether ship was rendered")
6046 {
6047  int x1,y1,x2,y2;
6048  angles rot_angles = {0.0f, 0.0f, 40.0f};
6049  int idx;
6050  float zoom = 1.3f;
6051  if(!ade_get_args(L, "oiiii|ffff", l_Shipclass.Get(&idx), &x1, &y1, &x2, &y2, &rot_angles.h, &rot_angles.p, &rot_angles.b, &zoom))
6052  return ade_set_error(L, "b", false);
6053 
6054  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
6055  return ade_set_args(L, "b", false);
6056 
6057  if(x2 < x1 || y2 < y1)
6058  return ade_set_args(L, "b", false);
6059 
6060  CLAMP(rot_angles.p, 0.0f, 100.0f);
6061  CLAMP(rot_angles.b, 0.0f, 100.0f);
6062  CLAMP(rot_angles.h, 0.0f, 100.0f);
6063 
6064  ship_info *sip = &Ship_info[idx];
6065  model_render_params render_info;
6066 
6067  if (sip->uses_team_colors) {
6068  render_info.set_team_color(sip->default_team_name, "none", 0, 0);
6069  }
6070 
6071  //Make sure model is loaded
6072  sip->model_num = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0], 0);
6073 
6074  if(sip->model_num < 0)
6075  return ade_set_args(L, "b", false);
6076 
6077  //Handle angles
6079  angles view_angles = {-0.6f, 0.0f, 0.0f};
6080  vm_angles_2_matrix(&orient, &view_angles);
6081 
6082  rot_angles.p = (rot_angles.p*0.01f) * PI2;
6083  rot_angles.b = (rot_angles.b*0.01f) * PI2;
6084  rot_angles.h = (rot_angles.h*0.01f) * PI2;
6085  vm_rotate_matrix_by_angles(&orient, &rot_angles);
6086 
6087  //Clip
6088  gr_set_clip(x1,y1,x2-x1,y2-y1,GR_RESIZE_NONE);
6089 
6090  //Handle 3D init stuff
6091  g3_start_frame(1);
6093 
6096 
6097  //Handle light
6098  light_reset();
6099  vec3d light_dir = vmd_zero_vector;
6100  light_dir.xyz.y = 1.0f;
6101  light_add_directional(&light_dir, 0.65f, 1.0f, 1.0f, 1.0f);
6102  light_rotate_all();
6103 
6104  //Draw the ship!!
6106  render_info.set_detail_level_lock(0);
6107 
6108  uint render_flags = MR_AUTOCENTER | MR_NO_FOGGING;
6109 
6110  if(sip->flags2 & SIF2_NO_LIGHTING)
6111  render_flags |= MR_NO_LIGHTING;
6112 
6113  render_info.set_flags(render_flags);
6114 
6115  model_render_immediate(&render_info, sip->model_num, &orient, &vmd_zero_vector);
6116 
6117  //OK we're done
6120 
6121  //Bye!!
6122  g3_end_frame();
6123  gr_reset_clip();
6124 
6125  return ade_set_args(L, "b", true);
6126 }
6127 
6128 // Nuke's alternate tech model rendering function
6129 ADE_FUNC(renderTechModel2, l_Shipclass, "X1, Y1, X2, Y2, [orientation Orientation=nil, number Zoom=1.3]", "Draws ship model as if in techroom", "boolean", "Whether ship was rendered")
6130 {
6131  int x1,y1,x2,y2;
6132  int idx;
6133  float zoom = 1.3f;
6134  matrix_h *mh = NULL;
6135  if(!ade_get_args(L, "oiiiio|f", l_Shipclass.Get(&idx), &x1, &y1, &x2, &y2, l_Matrix.GetPtr(&mh), &zoom))
6136  return ade_set_error(L, "b", false);
6137 
6138  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
6139  return ade_set_args(L, "b", false);
6140 
6141  if(x2 < x1 || y2 < y1)
6142  return ade_set_args(L, "b", false);
6143 
6144  ship_info *sip = &Ship_info[idx];
6145  model_render_params render_info;
6146 
6147  if (sip->uses_team_colors) {
6148  render_info.set_team_color(sip->default_team_name, "none", 0, 0);
6149  }
6150 
6151  //Make sure model is loaded
6152  sip->model_num = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0], 0);
6153 
6154  if(sip->model_num < 0)
6155  return ade_set_args(L, "b", false);
6156 
6157  //Handle angles
6158  matrix *orient = mh->GetMatrix();
6159 
6160  //Clip
6161  gr_set_clip(x1,y1,x2-x1,y2-y1,GR_RESIZE_NONE);
6162 
6163  //Handle 3D init stuff
6164  g3_start_frame(1);
6166 
6169 
6170  //Handle light
6171  light_reset();
6172  vec3d light_dir = vmd_zero_vector;
6173  light_dir.xyz.y = 1.0f;
6174  light_add_directional(&light_dir, 0.65f, 1.0f, 1.0f, 1.0f);
6175  light_rotate_all();
6176 
6177  //Draw the ship!!
6179  render_info.set_detail_level_lock(0);
6180 
6181  uint render_flags = MR_AUTOCENTER | MR_NO_FOGGING;
6182 
6183  if(sip->flags2 & SIF2_NO_LIGHTING)
6184  render_flags |= MR_NO_LIGHTING;
6185 
6186  render_info.set_flags(render_flags);
6187 
6188  model_render_immediate(&render_info, sip->model_num, orient, &vmd_zero_vector);
6189 
6190  //OK we're done
6193 
6194  //Bye!!
6195  g3_end_frame();
6196  gr_reset_clip();
6197 
6198  return ade_set_args(L, "b", true);
6199 }
6200 
6201 ADE_FUNC(isModelLoaded, l_Shipclass, "[boolean Load = false]", "Checks if the model used for this shipclass is loaded or not and optionally loads the model, which might be a slow operation.", "boolean", "If the model is loaded or not")
6202 {
6203  int idx;
6204  bool load_check = false;
6205  if(!ade_get_args(L, "o|b", l_Shipclass.Get(&idx), &load_check))
6206  return ADE_RETURN_FALSE;
6207 
6208  ship_info *sip = &Ship_info[idx];
6209 
6210  if (sip == NULL)
6211  return ADE_RETURN_FALSE;
6212 
6213  if(load_check){
6214  sip->model_num = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
6215  }
6216 
6217  if (sip->model_num > -1)
6218  return ADE_RETURN_TRUE;
6219  else
6220  return ADE_RETURN_FALSE;
6221 }
6222 
6223 ADE_FUNC(getShipClassIndex, l_Shipclass, NULL, "Gets the index valus of the ship class", "number", "index value of the ship class")
6224 {
6225  int idx;
6226  if(!ade_get_args(L, "o", l_Shipclass.Get(&idx)))
6227  return ade_set_args(L, "i", -1);
6228 
6229  if(idx < 0 || idx >= static_cast<int>(Ship_info.size()))
6230  return ade_set_args(L, "i", -1);
6231 
6232  return ade_set_args(L, "i", idx + 1); // Lua is 1-based
6233 }
6234 
6235 //**********HANDLE: Debris
6236 ade_obj<object_h> l_Debris("debris", "Debris handle", &l_Object);
6237 
6238 ADE_VIRTVAR(IsHull, l_Debris, "boolean", "Whether or not debris is a piece of hull", "boolean", "Whether debris is a hull fragment, or false if handle is invalid")
6239 {
6240  object_h *oh;
6241  bool b=false;
6242  if(!ade_get_args(L, "o|b", l_Debris.GetPtr(&oh), &b))
6243  return ade_set_error(L, "b", false);
6244 
6245  if(!oh->IsValid())
6246  return ade_set_error(L, "b", false);
6247 
6248  debris *db = &Debris[oh->objp->instance];
6249 
6250  if(ADE_SETTING_VAR) {
6251  db->is_hull = b ? 1 : 0;
6252  }
6253 
6254  return ade_set_args(L, "b", db->is_hull ? true : false);
6255 
6256 }
6257 
6258 ADE_VIRTVAR(OriginClass, l_Debris, "shipclass", "The shipclass of the ship this debris originates from", "shipclass", "The shipclass of the ship that created this debris")
6259 {
6260  object_h *oh;
6261  int shipIdx = -1;
6262  if(!ade_get_args(L, "o|o", l_Debris.GetPtr(&oh), &shipIdx))
6263  return ade_set_error(L, "o", l_Shipclass.Set(-1));
6264 
6265  if(!oh->IsValid())
6266  return ade_set_error(L, "o", l_Shipclass.Set(-1));
6267 
6268  debris *db = &Debris[oh->objp->instance];
6269 
6270  if(ADE_SETTING_VAR) {
6271  if (shipIdx >= 0 && shipIdx < static_cast<int>(Ship_info.size()))
6272  db->ship_info_index = shipIdx;
6273  }
6274 
6275  return ade_set_error(L, "o", l_Shipclass.Set(db->ship_info_index));
6276 }
6277 
6278 ADE_FUNC(getDebrisRadius, l_Debris, NULL, "The radius of this debris piece", "number", "The radius of this debris piece or -1 if invalid")
6279 {
6280  object_h *oh;
6281  if(!ade_get_args(L, "o", l_Debris.GetPtr(&oh)))
6282  return ade_set_error(L, "f", -1.0f);
6283 
6284  if(!oh->IsValid())
6285  return ade_set_error(L, "f", -1.0f);
6286 
6287  debris *db = &Debris[oh->objp->instance];
6288 
6289  polymodel *pm = model_get(db->model_num);
6290 
6291  if (pm == NULL)
6292  return ade_set_error(L, "f", -1.0f);
6293 
6294  if (db->submodel_num < 0 || pm->n_models <= db->submodel_num)
6295  return ade_set_error(L, "f", -1.0f);
6296 
6297  return ade_set_error(L, "f", pm->submodel[db->submodel_num].rad);
6298 }
6299 
6300 ADE_FUNC(isValid, l_Debris, NULL, "Return if this debris handle is valid", "boolean", "true if valid false otherwise")
6301 {
6302  object_h *oh;
6303  if(!ade_get_args(L, "o", l_Debris.GetPtr(&oh)))
6304  return ADE_RETURN_FALSE;
6305 
6306  return ade_set_args(L, "b", oh != NULL && oh->IsValid());
6307 }
6308 
6309 //**********HANDLE: Waypoint
6310 ade_obj<object_h> l_Waypoint("waypoint", "waypoint handle", &l_Object);
6311 
6312 //**********HANDLE: WaypointList
6314 {
6317  waypointlist_h(){wlp=NULL;name[0]='\0';}
6319  wlp = n_wlp;
6320  if(n_wlp != NULL)
6321  strcpy_s(name, wlp->get_name());
6322  }
6323  waypointlist_h(char wlname[NAME_LENGTH]) {
6324  wlp = NULL;
6325  if ( wlname != NULL ) {
6326  strcpy_s(name, wlname);
6327  wlp = find_matching_waypoint_list(wlname);
6328  }
6329  }
6330  bool IsValid() {
6331  return (wlp != NULL && !strcmp(wlp->get_name(), name));
6332  }
6333 };
6334 
6335 ade_obj<waypointlist_h> l_WaypointList("waypointlist", "waypointlist handle");
6336 
6337 ADE_INDEXER(l_WaypointList, "number Index", "Array of waypoints that are part of the waypoint list", "waypoint", "Waypoint, or invalid handle if the index or waypointlist handle is invalid")
6338 {
6339  int idx = -1;
6340  waypointlist_h* wlh = NULL;
6341  char wpname[128];
6342  if( !ade_get_args(L, "oi", l_WaypointList.GetPtr( &wlh ), &idx))
6343  return ade_set_error( L, "o", l_Waypoint.Set( object_h() ) );
6344 
6345  if(!wlh->IsValid())
6346  return ade_set_error( L, "o", l_Waypoint.Set( object_h() ) );
6347 
6348  //Lua-->FS2
6349  idx--;
6350 
6351  //Get waypoint name
6352  sprintf(wpname, "%s:%d", wlh->wlp->get_name(), calc_waypoint_index(idx) + 1);
6353  waypoint *wpt = find_matching_waypoint( wpname );
6354  if( (idx >= 0) && ((uint) idx < wlh->wlp->get_waypoints().size()) && (wpt != NULL) && (wpt->get_objnum() >= 0) ) {
6355  return ade_set_args( L, "o", l_Waypoint.Set( object_h( &Objects[wpt->get_objnum()] ), Objects[wpt->get_objnum()].signature ) );
6356  }
6357 
6358  return ade_set_error(L, "o", l_Waypoint.Set( object_h() ) );
6359 }
6360 
6362  NULL,
6363  "Number of waypoints in the list. "
6364  "Note that the value returned cannot be relied on for more than one frame.",
6365  "number",
6366  "Number of waypoints in the list, or 0 if handle is invalid")
6367 {
6368  waypointlist_h* wlh = NULL;
6369  if ( !ade_get_args(L, "o", l_WaypointList.GetPtr(&wlh)) ) {
6370  return ade_set_error( L, "o", l_Waypoint.Set( object_h() ) );
6371  }
6372  return ade_set_args(L, "i", wlh->wlp->get_waypoints().size());
6373 }
6374 
6375 ADE_VIRTVAR(Name, l_WaypointList, "string", "Name of WaypointList", "string", "Waypointlist name, or empty string if handle is invalid")
6376 {
6377  waypointlist_h* wlh = NULL;
6378  char *s = NULL;
6379  if ( !ade_get_args(L, "o|s", l_WaypointList.GetPtr(&wlh), &s) ) {
6380  return ade_set_error(L, "s", "");
6381  }
6382 
6383  if(ADE_SETTING_VAR && s != NULL) {
6384  wlh->wlp->set_name(s);
6385  strcpy_s(wlh->name,s);
6386  }
6387 
6388  return ade_set_args( L, "s", wlh->name);
6389 }
6390 
6391 ADE_FUNC(isValid, l_WaypointList, NULL, "Return if this waypointlist handle is valid", "boolean", "true if valid false otherwise")
6392 {
6393  waypointlist_h* wlh = NULL;
6394  if ( !ade_get_args(L, "o", l_WaypointList.GetPtr(&wlh)) ) {
6395  return ADE_RETURN_FALSE;
6396  }
6397  return ade_set_args(L, "b", wlh != NULL && wlh->IsValid());
6398 }
6399 
6400 //WMC - Waypoints are messed. Gonna leave this for later.
6401 /*
6402 ade_lib l_WaypointList_Waypoints("Waypoints", &l_Waypoint, NULL, NULL);
6403 
6404 ADE_INDEXER(l_WaypointList_Waypoints, "waypoint index", "waypoint", "Gets waypoint handle")
6405 {
6406  waypoint_list *wlp = NULL;
6407  int idx;
6408  if(!ade_get_args(L, "o|i", &idx))
6409  return ade_set_error(L, "o", l_Waypoint.Set(object_h()));
6410 
6411  //Remember, Lua indices start at 0.
6412  int count=0;
6413 
6414  object *ptr = GET_FIRST(&obj_used_list);
6415  while (ptr != END_OF_LIST(&obj_used_list))
6416  {
6417  if (ptr->type == OBJ_WAYPOINT)
6418  count++;
6419 
6420  if(count == idx) {
6421  return ade_set_args(L, "o", l_Waypoint.Set(object_h(ptr)));
6422  }
6423 
6424  ptr = GET_NEXT(ptr);
6425  }
6426 
6427  return ade_set_error(L, "o", l_Weapon.Set(object_h()));
6428 }
6429 
6430 ADE_FUNC(__len, l_WaypointList_Waypoints, NULL, "Number of waypoints in the mission",
6431  "Gets number of waypoints in mission. Note that this is only accurate for one frame.")
6432 {
6433  int count=0;
6434  for(int i = 0; i < MAX_OBJECTS; i++)
6435  {
6436  if (Objects[i].type == OBJ_WAYPOINT)
6437  count++;
6438  }
6439 
6440  return ade_set_args(L, "i", count);
6441 }*/
6442 
6443 ADE_FUNC(getList, l_Waypoint, NULL, "Returns the waypoint list", "waypointlist", "waypointlist handle or invalid handle if waypoint was invalid")
6444 {
6445  object_h *oh = NULL;
6446  waypointlist_h wpl;
6447  waypoint_list *wp_list = NULL;
6448  if(!ade_get_args(L, "o", l_Waypoint.GetPtr(&oh)))
6449  return ade_set_error(L, "o", l_WaypointList.Set(waypointlist_h()));
6450 
6451  if(oh->IsValid() && oh->objp->type == OBJ_WAYPOINT) {
6453  if(wp_list != NULL)
6454  wpl = waypointlist_h(wp_list);
6455  }
6456 
6457  if (wpl.IsValid()) {
6458  return ade_set_args(L, "o", l_WaypointList.Set(wpl));
6459  }
6460 
6461  return ade_set_error(L, "o", l_WaypointList.Set(waypointlist_h()));
6462 }
6463 
6464 //**********HANDLE: Weaponbank
6465 #define SWH_NONE 0
6466 #define SWH_PRIMARY 1
6467 #define SWH_SECONDARY 2
6468 #define SWH_TERTIARY 3
6469 
6470 struct ship_banktype_h : public object_h
6471 {
6472  int type;
6474 
6476  sw = NULL;
6477  type = SWH_NONE;
6478  }
6479  ship_banktype_h(object *objp_in, ship_weapon *wpn, int in_type) : object_h(objp_in) {
6480  sw = wpn;
6481  type = in_type;
6482  }
6483 
6484  bool IsValid()
6485  {
6486  return object_h::IsValid() && sw != NULL && (type == SWH_PRIMARY || type == SWH_SECONDARY || type == SWH_TERTIARY);
6487  }
6488 };
6490 {
6491  int bank;
6492 
6494  bank = -1;
6495  }
6496  ship_bank_h(object *objp_in, ship_weapon *wpn, int in_type, int in_bank) : ship_banktype_h(objp_in, wpn, in_type) {
6497  bank = in_bank;
6498  }
6499 
6500  bool IsValid()
6501  {
6503  return false;
6504 
6505  if(bank < 0)
6506  return false;
6507 
6508  if(type == SWH_PRIMARY && bank >= sw->num_primary_banks)
6509  return false;
6510  if(type == SWH_SECONDARY && bank >= sw->num_secondary_banks)
6511  return false;
6512  if(type == SWH_TERTIARY && bank >= sw->num_tertiary_banks)
6513  return false;
6514 
6515  return true;
6516  }
6517 };
6518 
6519 //**********HANDLE: Ship bank
6520 ade_obj<ship_bank_h> l_WeaponBank("weaponbank", "Ship/subystem weapons bank handle");
6521 
6522 ADE_VIRTVAR(WeaponClass, l_WeaponBank, "weaponclass", "Class of weapon mounted in the bank", "weaponclass", "Weapon class, or an invalid weaponclass handle if bank handle is invalid")
6523 {
6524  ship_bank_h *bh = NULL;
6525  int weaponclass=-1;
6526  if(!ade_get_args(L, "o|o", l_WeaponBank.GetPtr(&bh), l_Weaponclass.Get(&weaponclass)))
6527  return ade_set_error(L, "o", l_Weaponclass.Set(-1));
6528 
6529  if(!bh->IsValid())
6530  return ade_set_error(L, "o", l_Weaponclass.Set(-1));
6531 
6532  switch(bh->type)
6533  {
6534  case SWH_PRIMARY:
6535  if(ADE_SETTING_VAR && weaponclass > -1) {
6536  bh->sw->primary_bank_weapons[bh->bank] = weaponclass;
6537  }
6538 
6539  return ade_set_args(L, "o", l_Weaponclass.Set(bh->sw->primary_bank_weapons[bh->bank]));
6540  case SWH_SECONDARY:
6541  if(ADE_SETTING_VAR && weaponclass > -1) {
6542  bh->sw->secondary_bank_weapons[bh->bank] = weaponclass;
6543  }
6544 
6545  return ade_set_args(L, "o", l_Weaponclass.Set(bh->sw->secondary_bank_weapons[bh->bank]));
6546  case SWH_TERTIARY:
6547  if(ADE_SETTING_VAR && weaponclass > -1) {
6548  //bh->sw->tertiary_bank_weapons[bh->bank] = weaponclass;
6549  }
6550 
6551  // return ade_set_args(L, "o", l_Weaponclass.Set(bh->sw->tertiary_bank_weapons[bh->bank]));
6552  // Error(LOCATION, "Tertiary bank support is still in progress");
6553  // WMC: TODO
6554  return ADE_RETURN_FALSE;
6555  }
6556 
6557  return ade_set_error(L, "o", l_Weaponclass.Set(-1));
6558 }
6559 
6560 ADE_VIRTVAR(AmmoLeft, l_WeaponBank, "number", "Ammo left for the current bank", "number", "Ammo left, or 0 if handle is invalid")
6561 {
6562  ship_bank_h *bh = NULL;
6563  int ammo;
6564  if(!ade_get_args(L, "o|i", l_WeaponBank.GetPtr(&bh), &ammo))
6565  return ade_set_error(L, "i", 0);
6566 
6567  if(!bh->IsValid())
6568  return ade_set_error(L, "i", 0);
6569 
6570  switch(bh->type)
6571  {
6572  case SWH_PRIMARY:
6573  if(ADE_SETTING_VAR && ammo > -1) {
6574  bh->sw->primary_bank_ammo[bh->bank] = ammo;
6575  }
6576 
6577  return ade_set_args(L, "i", bh->sw->primary_bank_ammo[bh->bank]);
6578  case SWH_SECONDARY:
6579  if(ADE_SETTING_VAR && ammo > -1) {
6580  bh->sw->secondary_bank_ammo[bh->bank] = ammo;
6581  }
6582 
6583  return ade_set_args(L, "i", bh->sw->secondary_bank_ammo[bh->bank]);
6584  case SWH_TERTIARY:
6585  if(ADE_SETTING_VAR && ammo > -1) {
6586  bh->sw->tertiary_bank_ammo = ammo;
6587  }
6588  return ade_set_args(L, "i", bh->sw->tertiary_bank_ammo);
6589  }
6590 
6591  return ade_set_error(L, "i", 0);
6592 }
6593 
6594 ADE_VIRTVAR(AmmoMax, l_WeaponBank, "number", "Maximum ammo for the current bank<br>"
6595  "<b>Note:</b> Setting this value actually sets the <i>capacity</i> of the weapon bank. To set the actual maximum ammunition use <tt>AmmoMax = <amount> * class.CargoSize</tt>", "number", "Ammo capacity, or 0 if handle is invalid")
6596 {
6597  ship_bank_h *bh = NULL;
6598  int ammomax;
6599  if(!ade_get_args(L, "o|i", l_WeaponBank.GetPtr(&bh), &ammomax))
6600  return ade_set_error(L, "i", 0);
6601 
6602  if(!bh->IsValid())
6603  return ade_set_error(L, "i", 0);
6604 
6605  switch(bh->type)
6606  {
6607  case SWH_PRIMARY:
6608  {
6609  if(ADE_SETTING_VAR && ammomax > -1) {
6610  bh->sw->primary_bank_capacity[bh->bank] = ammomax;
6611  }
6612 
6613  int weapon_class = bh->sw->primary_bank_weapons[bh->bank];
6614 
6615  Assert(bh->objp->type == OBJ_SHIP);
6616 
6617  return ade_set_args(L, "i", get_max_ammo_count_for_primary_bank(Ships[bh->objp->instance].ship_info_index, bh->bank, weapon_class));
6618  }
6619  case SWH_SECONDARY:
6620  {
6621  if(ADE_SETTING_VAR && ammomax > -1) {
6622  bh->sw->secondary_bank_capacity[bh->bank] = ammomax;
6623  }
6624 
6625  int weapon_class = bh->sw->secondary_bank_weapons[bh->bank];
6626 
6627  Assert(bh->objp->type == OBJ_SHIP);
6628 
6629  return ade_set_args(L, "i", get_max_ammo_count_for_bank(Ships[bh->objp->instance].ship_info_index, bh->bank, weapon_class));
6630  }
6631  case SWH_TERTIARY:
6632  if(ADE_SETTING_VAR && ammomax > -1) {
6633  bh->sw->tertiary_bank_capacity = ammomax;
6634  }
6635 
6636  return ade_set_args(L, "i", bh->sw->tertiary_bank_capacity);
6637  }
6638 
6639  return ade_set_error(L, "i", 0);
6640 }
6641 
6642 ADE_VIRTVAR(Armed, l_WeaponBank, "boolean", "Weapon armed status. Does not take linking into account.", "boolean", "True if armed, false if unarmed or handle is invalid")
6643 {
6644  ship_bank_h *bh = NULL;
6645  bool armthis=false;
6646  if(!ade_get_args(L, "o|b", l_WeaponBank.GetPtr(&bh), &armthis))
6647  return ade_set_error(L, "b", false);
6648 
6649  if(!bh->IsValid())
6650  return ade_set_error(L, "b", false);
6651 
6652  int new_armed_bank = -1;
6653  if(armthis)
6654  new_armed_bank = bh->bank;
6655 
6656  switch(bh->type)
6657  {
6658  case SWH_PRIMARY:
6659  if(ADE_SETTING_VAR) {
6660  bh->sw->current_primary_bank = new_armed_bank;
6661  }
6662  return ade_set_args(L, "b", bh->sw->current_primary_bank == bh->bank);
6663  case SWH_SECONDARY:
6664  if(ADE_SETTING_VAR) {
6665  bh->sw->current_secondary_bank = new_armed_bank;
6666  }
6667  return ade_set_args(L, "b", bh->sw->current_secondary_bank == bh->bank);
6668  case SWH_TERTIARY:
6669  if(ADE_SETTING_VAR) {
6670  bh->sw->current_tertiary_bank = new_armed_bank;
6671  }
6672  return ade_set_args(L, "b", bh->sw->current_tertiary_bank == bh->bank);
6673  }
6674 
6675  return ade_set_error(L, "b", false);
6676 }
6677 
6678 ADE_VIRTVAR(Capacity, l_WeaponBank, "number", "The actual capacity of a weapon bank as specified in the table", "number", "The capacity or -1 if handle is invalid")
6679 {
6680  ship_bank_h *bh = NULL;
6681  int newCapacity = -1;
6682  if(!ade_get_args(L, "o|i", l_WeaponBank.GetPtr(&bh), &newCapacity))
6683  return ade_set_error(L, "i", -1);
6684 
6685  if(!bh->IsValid())
6686  return ade_set_error(L, "i", -1);
6687 
6688  switch(bh->type)
6689  {
6690  case SWH_PRIMARY:
6691  if(ADE_SETTING_VAR && newCapacity > 0) {
6692  bh->sw->primary_bank_capacity[bh->bank] = newCapacity;
6693  }
6694  return ade_set_args(L, "i", bh->sw->primary_bank_capacity[bh->bank]);
6695  case SWH_SECONDARY:
6696  if(ADE_SETTING_VAR && newCapacity > 0) {
6697  bh->sw->secondary_bank_capacity[bh->bank] = newCapacity;
6698  }
6699  return ade_set_args(L, "i", bh->sw->secondary_bank_capacity[bh->bank]);
6700  case SWH_TERTIARY:
6701  if(ADE_SETTING_VAR && newCapacity > 0) {
6702  bh->sw->tertiary_bank_capacity = newCapacity;
6703  }
6704  return ade_set_args(L, "i", bh->sw->tertiary_bank_capacity);
6705  }
6706 
6707  return ade_set_error(L, "i", -1);
6708 }
6709 
6710 ADE_FUNC(isValid, l_WeaponBank, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
6711 {
6712  ship_bank_h *bh;
6713  if(!ade_get_args(L, "o", l_WeaponBank.GetPtr(&bh)))
6714  return ADE_RETURN_NIL;
6715 
6716  return ade_set_args(L, "b", bh->IsValid());
6717 }
6718 
6719 //**********HANDLE: Weaponbanktype
6720 ade_obj<ship_banktype_h> l_WeaponBankType("weaponbanktype", "Ship/subsystem weapons bank type handle");
6721 
6722 ADE_INDEXER(l_WeaponBankType, "number Index", "Array of weapon banks", "weaponbank", "Weapon bank, or invalid handle on failure")
6723 {
6724  ship_banktype_h *sb=NULL;
6725  int idx = -1;
6726  ship_bank_h *newbank = nullptr;
6727  if(!ade_get_args(L, "oi|o", l_WeaponBankType.GetPtr(&sb), &idx, l_WeaponBank.GetPtr(&newbank)))
6728  return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h()));
6729 
6730  if(!sb->IsValid())
6731  return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h()));
6732 
6733  switch(sb->type)
6734  {
6735  case SWH_PRIMARY:
6736  if(idx < 1 || idx > sb->sw->num_primary_banks)
6737  return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h()));
6738 
6739  idx--; //Lua->FS2
6740 
6741  if(ADE_SETTING_VAR && newbank && newbank->IsValid()) {
6744  sb->sw->primary_bank_ammo[idx] = newbank->sw->primary_bank_ammo[idx];
6748  }
6749  break;
6750  case SWH_SECONDARY:
6751  if(idx < 1 || idx > sb->sw->num_secondary_banks)
6752  return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h()));
6753 
6754  idx--; //Lua->FS2
6755 
6756  if(ADE_SETTING_VAR && newbank && newbank->IsValid()) {
6759  sb->sw->primary_bank_ammo[idx] = newbank->sw->primary_bank_ammo[idx];
6762  }
6763  break;
6764  case SWH_TERTIARY:
6765  if(idx < 1 || idx > sb->sw->num_tertiary_banks)
6766  return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h()));
6767 
6768  idx--; //Lua->FS2
6769 
6770  if(ADE_SETTING_VAR && newbank && newbank->IsValid()) {
6771  Error(LOCATION, "Tertiary bank support is still in progress");
6772  //WMC: TODO
6773  }
6774  break;
6775  default:
6776  return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h())); //Invalid type
6777  }
6778 
6779  return ade_set_args(L, "o", l_WeaponBank.Set(ship_bank_h(sb->objp, sb->sw, sb->type, idx)));
6780 }
6781 
6782 ADE_VIRTVAR(Linked, l_WeaponBankType, "boolean", "Whether bank is in linked or unlinked fire mode (Primary-only)", "boolean", "Link status, or false if handle is invalid")
6783 {
6784  ship_banktype_h *bh;
6785  bool newlink = false;
6786  int numargs = ade_get_args(L, "o|b", l_WeaponBankType.GetPtr(&bh), &newlink);
6787 
6788  if(!numargs)
6789  return ade_set_error(L, "b", false);
6790 
6791  if(!bh->IsValid())
6792  return ade_set_error(L, "b", false);
6793 
6794  switch(bh->type)
6795  {
6796  case SWH_PRIMARY:
6797  if(ADE_SETTING_VAR && numargs > 1) {
6798  if(newlink)
6800  else
6802  }
6803 
6804  return ade_set_args(L, "b", (Ships[bh->objp->instance].flags & SF_PRIMARY_LINKED) > 0);
6805 
6806  case SWH_SECONDARY:
6807  case SWH_TERTIARY:
6808  return ADE_RETURN_FALSE;
6809  }
6810 
6811  return ade_set_error(L, "b", false);
6812 }
6813 
6814 ADE_VIRTVAR(DualFire, l_WeaponBankType, "boolean", "Whether bank is in dual fire mode (Secondary-only)", "boolean", "Dual fire status, or false if handle is invalid")
6815 {
6816  ship_banktype_h *bh;
6817  bool newfire = false;
6818  int numargs = ade_get_args(L, "o|b", l_WeaponBankType.GetPtr(&bh), &newfire);
6819 
6820  if(!numargs)
6821  return ade_set_error(L, "b", false);
6822 
6823  if(!bh->IsValid())
6824  return ade_set_error(L, "b", false);
6825 
6826  switch(bh->type)
6827  {
6828  case SWH_SECONDARY:
6829  if(ADE_SETTING_VAR && numargs > 1) {
6830  if(newfire)
6832  else
6834  }
6835 
6836  return ade_set_args(L, "b", (Ships[bh->objp->instance].flags & SF_SECONDARY_DUAL_FIRE) > 0);
6837 
6838  case SWH_PRIMARY:
6839  case SWH_TERTIARY:
6840  return ADE_RETURN_FALSE;
6841  }
6842 
6843  return ade_set_error(L, "b", false);
6844 }
6845 
6846 ADE_FUNC(isValid, l_WeaponBankType, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
6847 {
6848  ship_banktype_h *sb;
6849  if(!ade_get_args(L, "o", l_WeaponBankType.GetPtr(&sb)))
6850  return ADE_RETURN_NIL;
6851 
6852  return ade_set_args(L, "b", sb->IsValid());
6853 }
6854 
6855 ADE_FUNC(__len, l_WeaponBankType, NULL, "Number of weapons in the mounted bank", "number", "Number of bank weapons, or 0 if handle is invalid")
6856 {
6857  ship_banktype_h *sb=NULL;
6858  if(!ade_get_args(L, "o", l_WeaponBankType.GetPtr(&sb)))
6859  return ade_set_error(L, "i", 0);
6860 
6861  if(!sb->IsValid())
6862  return ade_set_error(L, "i", 0);
6863 
6864  switch(sb->type)
6865  {
6866  case SWH_PRIMARY:
6867  return ade_set_args(L, "i", sb->sw->num_primary_banks);
6868  case SWH_SECONDARY:
6869  return ade_set_args(L, "i", sb->sw->num_secondary_banks);
6870  case SWH_TERTIARY:
6871  return ade_set_args(L, "i", sb->sw->num_tertiary_banks);
6872  default:
6873  return ade_set_error(L, "i", 0); //Invalid type
6874  }
6875 }
6876 
6877 //**********HANDLE: Subsystem
6878 struct ship_subsys_h : public object_h
6879 {
6880  ship_subsys *ss; //Pointer to subsystem, or NULL for the hull
6881 
6882  bool IsValid(){return object_h::IsValid() && objp->type == OBJ_SHIP && ss != NULL;}
6884  ss = NULL;
6885  }
6886  ship_subsys_h(object *objp_in, ship_subsys *sub) : object_h(objp_in) {
6887  ss = sub;
6888  }
6889 };
6890 ade_obj<ship_subsys_h> l_Subsystem("subsystem", "Ship subsystem handle");
6891 
6892 ADE_FUNC(__tostring, l_Subsystem, NULL, "Returns name of subsystem", "string", "Subsystem name, or empty string if handle is invalid")
6893 {
6894  ship_subsys_h *sso;
6895  if(!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso)))
6896  return ade_set_error(L, "s", "");
6897 
6898  if(!sso->IsValid())
6899  return ade_set_error(L, "s", "");
6900 
6901  return ade_set_args(L, "s", ship_subsys_get_name(sso->ss));
6902 }
6903 
6904 ADE_VIRTVAR(ArmorClass, l_Subsystem, "string", "Current Armor class", "string", "Armor class name, or empty string if none is set")
6905 {
6906  ship_subsys_h *sso;
6907  char *s = NULL;
6908  char *name = NULL;
6909 
6910  if(!ade_get_args(L, "o|s", l_Subsystem.GetPtr(&sso), &s))
6911  return ade_set_error(L, "s", "");
6912 
6913  if(!sso->IsValid())
6914  return ade_set_error(L, "s", "");
6915 
6916  ship_subsys *ssys = sso->ss;
6917 
6918  int atindex = -1;
6919  if (ADE_SETTING_VAR && s != NULL) {
6920  atindex = armor_type_get_idx(s);
6921  ssys->armor_type_idx = atindex;
6922  }
6923 
6924  if (atindex != -1)
6925  name = Armor_types[atindex].GetNamePtr();
6926  else
6927  name = "";
6928 
6929  return ade_set_args(L, "s", name);
6930 }
6931 
6932 ADE_VIRTVAR(AWACSIntensity, l_Subsystem, "number", "Subsystem AWACS intensity", "number", "AWACS intensity, or 0 if handle is invalid")
6933 {
6934  ship_subsys_h *sso;
6935  float f = -1.0f;
6936  if(!ade_get_args(L, "o|f", l_Subsystem.GetPtr(&sso), &f))
6937  return ade_set_error(L, "f", 0.0f);
6938 
6939  if(!sso->IsValid())
6940  return ade_set_error(L, "f", 0.0f);
6941 
6942  if(ADE_SETTING_VAR && f >= 0.0f)
6943  sso->ss->awacs_intensity = f;
6944 
6945  return ade_set_args(L, "f", sso->ss->awacs_intensity);
6946 }
6947 
6948 ADE_VIRTVAR(AWACSRadius, l_Subsystem, "number", "Subsystem AWACS radius", "number", "AWACS radius, or 0 if handle is invalid")
6949 {
6950  ship_subsys_h *sso;
6951  float f = -1.0f;
6952  if(!ade_get_args(L, "o|f", l_Subsystem.GetPtr(&sso), &f))
6953  return ade_set_error(L, "f", 0.0f);
6954 
6955  if(!sso->IsValid())
6956  return ade_set_error(L, "f", 0.0f);
6957 
6958  if(ADE_SETTING_VAR && f >= 0.0f)
6959  sso->ss->awacs_radius = f;
6960 
6961  return ade_set_args(L, "f", sso->ss->awacs_radius);
6962 }
6963 
6964 ADE_VIRTVAR(Orientation, l_Subsystem, "orientation", "Orientation of subobject or turret base", "orientation", "Subsystem orientation, or null orientation if handle is invalid")
6965 {
6966  ship_subsys_h *sso;
6967  matrix_h *mh = nullptr;
6968  if(!ade_get_args(L, "o|o", l_Subsystem.GetPtr(&sso), l_Matrix.GetPtr(&mh)))
6969  return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
6970 
6971  if(!sso->IsValid())
6972  return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
6973 
6974  if(ADE_SETTING_VAR && mh)
6975  {
6976  sso->ss->submodel_info_1.angs = *mh->GetAngles();
6977  }
6978 
6979  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&sso->ss->submodel_info_1.angs)));
6980 }
6981 
6982 ADE_VIRTVAR(GunOrientation, l_Subsystem, "orientation", "Orientation of turret gun", "orientation", "Gun orientation, or null orientation if handle is invalid")
6983 {
6984  ship_subsys_h *sso;
6985  matrix_h *mh = nullptr;
6986  if(!ade_get_args(L, "o|o", l_Subsystem.GetPtr(&sso), l_Matrix.GetPtr(&mh)))
6987  return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
6988 
6989  if(!sso->IsValid())
6990  return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
6991 
6992  if(ADE_SETTING_VAR && mh)
6993  {
6994  sso->ss->submodel_info_2.angs = *mh->GetAngles();
6995  }
6996 
6997  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&sso->ss->submodel_info_2.angs)));
6998 }
6999 
7000 ADE_VIRTVAR(HitpointsLeft, l_Subsystem, "number", "Subsystem hitpoints left", "number", "Hitpoints left, or 0 if handle is invalid. Setting a value of 0 will disable it - set a value of -1 or lower to actually blow it up.")
7001 {
7002  ship_subsys_h *sso;
7003  float f = -1.0f;
7004  if(!ade_get_args(L, "o|f", l_Subsystem.GetPtr(&sso), &f))
7005  return ade_set_error(L, "f", 0.0f);
7006 
7007  if(!sso->IsValid())
7008  return ade_set_error(L, "f", 0.0f);
7009 
7010  if(ADE_SETTING_VAR)
7011  {
7012  //Only go down to 0 hits
7013  sso->ss->current_hits = MAX(0.0f, f);
7014 
7015  ship *shipp = &Ships[sso->objp->instance];
7016  if (f <= -1.0f && sso->ss->current_hits <= 0.0f) {
7017  do_subobj_destroyed_stuff(shipp, sso->ss, NULL);
7018  }
7020  }
7021 
7022  return ade_set_args(L, "f", sso->ss->current_hits);
7023 }
7024 
7025 ADE_VIRTVAR(HitpointsMax, l_Subsystem, "number", "Subsystem hitpoints max", "number", "Max hitpoints, or 0 if handle is invalid")
7026 {
7027  ship_subsys_h *sso;
7028  float f = -1.0f;
7029  if(!ade_get_args(L, "o|f", l_Subsystem.GetPtr(&sso), &f))
7030  return ade_set_error(L, "f", 0.0f);
7031 
7032  if(!sso->IsValid())
7033  return ade_set_error(L, "f", 0.0f);
7034 
7035  if(ADE_SETTING_VAR)
7036  {
7037  sso->ss->max_hits = MIN(0.0f, f);
7038 
7040  }
7041 
7042  return ade_set_args(L, "f", sso->ss->max_hits);
7043 }
7044 
7045 ADE_VIRTVAR(Position, l_Subsystem, "vector", "Subsystem position with regards to main ship (Local Vector)", "vector", "Subsystem position, or null vector if subsystem handle is invalid")
7046 {
7047  ship_subsys_h *sso;
7048  vec3d *v = NULL;
7049  if(!ade_get_args(L, "o|o", l_Subsystem.GetPtr(&sso), l_Vector.GetPtr(&v)))
7050  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
7051 
7052  if(!sso->IsValid())
7053  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
7054 
7055  if(ADE_SETTING_VAR && v != NULL)
7056  {
7057  sso->ss->system_info->pnt = *v;
7058  }
7059 
7060  return ade_set_args(L, "o", l_Vector.Set(sso->ss->system_info->pnt));
7061 }
7062 
7063 ADE_VIRTVAR(GunPosition, l_Subsystem, "vector", "Subsystem gun position with regards to main ship (Local vector)", "vector", "Gun position, or null vector if subsystem handle is invalid")
7064 {
7065  ship_subsys_h *sso;
7066  vec3d *v = NULL;
7067  if(!ade_get_args(L, "o|o", l_Subsystem.GetPtr(&sso), l_Vector.GetPtr(&v)))
7068  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
7069 
7070  if(!sso->IsValid())
7071  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
7072 
7073  polymodel *pm = model_get(Ship_info[Ships[sso->objp->instance].ship_info_index].model_num);
7074  Assert(pm != NULL);
7075 
7076  if(sso->ss->system_info->turret_gun_sobj < 0)
7077  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
7078 
7080 
7081  if(ADE_SETTING_VAR && v != NULL)
7082  sm->offset = *v;
7083 
7084  return ade_set_args(L, "o", l_Vector.Set(sm->offset));
7085 }
7086 
7087 ADE_VIRTVAR(Name, l_Subsystem, "string", "Subsystem name", "string", "Subsystem name, or an empty string if handle is invalid")
7088 {
7089  ship_subsys_h *sso;
7090  char *s = NULL;
7091  if(!ade_get_args(L, "o|s", l_Subsystem.GetPtr(&sso), &s))
7092  return ade_set_error(L, "s", "");
7093 
7094  if(!sso->IsValid())
7095  return ade_set_error(L, "s", "");
7096 
7097  if(ADE_SETTING_VAR && s != NULL && strlen(s))
7098  {
7099  ship_subsys_set_name(sso->ss, s);
7100  }
7101 
7102  return ade_set_args(L, "s", ship_subsys_get_name(sso->ss));
7103 }
7104 
7105 ADE_FUNC(getModelName, l_Subsystem, NULL, "Returns the original name of the subsystem in the model file", "string", "name or empty string on error")
7106 {
7107  ship_subsys_h *sso;
7108  if(!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso)))
7109  return ade_set_error(L, "s", "");
7110 
7111  if(!sso->IsValid())
7112  return ade_set_error(L, "s", "");
7113 
7114  return ade_set_args(L, "s", sso->ss->system_info->subobj_name);
7115 }
7116 
7117 ADE_VIRTVAR(PrimaryBanks, l_Subsystem, "weaponbanktype", "Array of primary weapon banks", "weaponbanktype", "Primary banks, or invalid weaponbanktype handle if subsystem handle is invalid")
7118 {
7119  ship_subsys_h *sso, *sso2 = nullptr;
7120  if(!ade_get_args(L, "o|o", l_Subsystem.GetPtr(&sso), l_Subsystem.GetPtr(&sso2)))
7121  return ade_set_error(L, "o", l_WeaponBankType.Set(ship_banktype_h()));
7122 
7123  if(!sso->IsValid())
7124  return ade_set_error(L, "o", l_WeaponBankType.Set(ship_banktype_h()));
7125 
7126  ship_weapon *dst = &sso->ss->weapons;
7127 
7128  if(ADE_SETTING_VAR && sso2 && sso2->IsValid()) {
7129  ship_weapon *src = &sso2->ss->weapons;
7130 
7133 
7137  memcpy(dst->primary_bank_ammo, src->primary_bank_ammo, sizeof(dst->primary_bank_ammo));
7138  memcpy(dst->primary_bank_capacity, src->primary_bank_capacity, sizeof(dst->primary_bank_capacity));
7141  memcpy(dst->primary_bank_weapons, src->primary_bank_weapons, sizeof(dst->primary_bank_weapons));
7142  }
7143 
7144  return ade_set_args(L, "o", l_WeaponBankType.Set(ship_banktype_h(sso->objp, dst, SWH_PRIMARY)));
7145 }
7146 
7147 ADE_VIRTVAR(SecondaryBanks, l_Subsystem, "weaponbanktype", "Array of secondary weapon banks", "weaponbanktype", "Secondary banks, or invalid weaponbanktype handle if subsystem handle is invalid")
7148 {
7149  ship_subsys_h *sso, *sso2 = nullptr;
7150  if(!ade_get_args(L, "o|o", l_Subsystem.GetPtr(&sso), l_Subsystem.GetPtr(&sso2)))
7151  return ade_set_error(L, "o", l_WeaponBankType.Set(ship_banktype_h()));
7152 
7153  if(!sso->IsValid())
7154  return ade_set_error(L, "o", l_WeaponBankType.Set(ship_banktype_h()));
7155 
7156  ship_weapon *dst = &sso->ss->weapons;
7157 
7158  if(ADE_SETTING_VAR && sso2 && sso2->IsValid()) {
7159  ship_weapon *src = &sso2->ss->weapons;
7160 
7163 
7167  memcpy(dst->secondary_bank_ammo, src->secondary_bank_ammo, sizeof(dst->secondary_bank_ammo));
7171  memcpy(dst->secondary_bank_weapons, src->secondary_bank_weapons, sizeof(dst->secondary_bank_weapons));
7172  memcpy(dst->secondary_next_slot, src->secondary_next_slot, sizeof(dst->secondary_next_slot));
7173  }
7174 
7175  return ade_set_args(L, "o", l_WeaponBankType.Set(ship_banktype_h(sso->objp, dst, SWH_SECONDARY)));
7176 }
7177 
7178 
7179 ADE_VIRTVAR(Target, l_Subsystem, "object", "Object targeted by this subsystem. If used to set a new target, AI targeting will be switched off.", "object", "Targeted object, or invalid object handle if subsystem handle is invalid")
7180 {
7181  ship_subsys_h *sso;
7182  object_h *objh = nullptr;
7183  if(!ade_get_args(L, "o|o", l_Subsystem.GetPtr(&sso), l_Object.GetPtr(&objh)))
7184  return ade_set_error(L, "o", l_Object.Set(object_h()));
7185 
7186  if(!sso->IsValid())
7187  return ade_set_error(L, "o", l_Object.Set(object_h()));
7188 
7189  ship_subsys *ss = sso->ss;
7190 
7191  if(ADE_SETTING_VAR && objh && objh->IsValid())
7192  {
7193  ss->turret_enemy_objnum = OBJ_INDEX(objh->objp);
7194  ss->turret_enemy_sig = objh->sig;
7195  ss->targeted_subsys = NULL;
7196  ss->scripting_target_override = true;
7197  }
7198 
7200 }
7201 
7202 ADE_VIRTVAR(TurretResets, l_Subsystem, "boolean", "Specifies wether this turrets resets after a certain time of inactivity", "boolean", "true if turret resets, false otherwise")
7203 {
7204  ship_subsys_h *sso;
7205  bool newVal = false;
7206  if (!ade_get_args(L, "o|b", l_Subsystem.GetPtr(&sso), &newVal))
7207  return ADE_RETURN_FALSE;
7208 
7209  if (!sso->IsValid())
7210  return ADE_RETURN_FALSE;
7211 
7212  if(ADE_SETTING_VAR)
7213  {
7214  if(newVal)
7215  {
7217  }
7218  else
7219  {
7221  }
7222  }
7223 
7225  return ADE_RETURN_TRUE;
7226  else
7227  return ADE_RETURN_FALSE;
7228 }
7229 
7230 ADE_VIRTVAR(TurretResetDelay, l_Subsystem, "number", "The time (in milliseconds) after that the turret resets itself", "number", "Reset delay")
7231 {
7232  ship_subsys_h *sso;
7233  int newVal = -1;
7234  if (!ade_get_args(L, "o|i", l_Subsystem.GetPtr(&sso), &newVal))
7235  return ade_set_error(L, "i", -1);
7236 
7237  if (!sso->IsValid())
7238  return ade_set_error(L, "i", -1);
7239 
7241  return ade_set_error(L, "i", -1);
7242 
7243  if(ADE_SETTING_VAR)
7244  {
7246  sso->ss->system_info->turret_reset_delay = newVal;
7247  }
7248 
7249  return ade_set_args(L, "i", sso->ss->system_info->turret_reset_delay);
7250 }
7251 
7252 ADE_VIRTVAR(TurnRate, l_Subsystem, "number", "The turn rate", "number", "Turnrate or -1 on error")
7253 {
7254  ship_subsys_h *sso;
7255  float newVal = -1.0f;
7256  if (!ade_get_args(L, "o|f", l_Subsystem.GetPtr(&sso), &newVal))
7257  return ade_set_error(L, "f", -1.0f);
7258 
7259  if (!sso->IsValid())
7260  return ade_set_error(L, "f", -1.0f);
7261 
7262  if(ADE_SETTING_VAR)
7263  {
7265  }
7266 
7267  return ade_set_args(L, "f", sso->ss->system_info->turret_turning_rate);
7268 }
7269 
7270 ADE_VIRTVAR(Targetable, l_Subsystem, "boolean", "Targetability of this subsystem", "boolean", "true if targetable, false otherwise or on error")
7271 {
7272  ship_subsys_h *sso;
7273  bool newVal = false;
7274  if (!ade_get_args(L, "o|b", l_Subsystem.GetPtr(&sso), &newVal))
7275  return ade_set_error(L, "b", false);
7276 
7277  if (!sso->IsValid())
7278  return ade_set_error(L, "b", false);
7279 
7280  if(ADE_SETTING_VAR)
7281  {
7282  if (!newVal)
7283  sso->ss->flags &= ~SSF_UNTARGETABLE;
7284  else
7285  sso->ss->flags |= SSF_UNTARGETABLE;
7286  }
7287 
7288  return ade_set_args(L, "b", !(sso->ss->flags & SSF_UNTARGETABLE));
7289 }
7290 
7291 ADE_VIRTVAR(Radius, l_Subsystem, "number", "The radius of this subsystem", "number", "The radius or 0 on error")
7292 {
7293  ship_subsys_h *sso;
7294  if (!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso)))
7295  return ade_set_error(L, "f", 0.0f);
7296 
7297  if (!sso->IsValid())
7298  return ade_set_error(L, "f", 0.0f);
7299 
7300  if(ADE_SETTING_VAR)
7301  {
7302  LuaError(L, "Setting radius for subsystems is not allowed!");
7303  }
7304 
7305  return ade_set_args(L, "f", sso->ss->system_info->radius);
7306 }
7307 
7308 ADE_VIRTVAR(TurretLocked, l_Subsystem, "boolean", "Whether the turret is locked. Setting to true locks the turret, setting to false frees it.", "boolean", "True if turret is locked, false otherwise")
7309 {
7310  ship_subsys_h *sso;
7311  bool newVal = false;
7312  if (!ade_get_args(L, "o|b", l_Subsystem.GetPtr(&sso), &newVal))
7313  return ade_set_error(L, "b", false);
7314 
7315  if (!sso->IsValid())
7316  return ade_set_error(L, "b", false);
7317 
7318  if(ADE_SETTING_VAR)
7319  {
7320  if (newVal) {
7322  } else {
7323  sso->ss->weapons.flags &= (~SW_FLAG_TURRET_LOCK);
7324  }
7325  }
7326 
7327  return ade_set_args(L, "b", (sso->ss->weapons.flags & SW_FLAG_TURRET_LOCK));
7328 }
7329 
7330 ADE_VIRTVAR(NextFireTimestamp, l_Subsystem, "number", "The next time the turret may attempt to fire", "number", "Mission time (seconds) or -1 on error")
7331 {
7332  ship_subsys_h *sso;
7333  float newVal = -1.0f;
7334  if (!ade_get_args(L, "o|f", l_Subsystem.GetPtr(&sso), &newVal))
7335  return ade_set_error(L, "f", -1.0f);
7336 
7337  if (!sso->IsValid())
7338  return ade_set_error(L, "f", -1.0f);
7339 
7340  if(ADE_SETTING_VAR)
7341  {
7342  sso->ss->turret_next_fire_stamp = (int)(newVal * 1000);
7343  }
7344 
7345  return ade_set_args(L, "f", sso->ss->turret_next_fire_stamp / 1000.0f);
7346 }
7347 
7348 ADE_FUNC(targetingOverride, l_Subsystem, "boolean", "If set to true, AI targeting for this turret is switched off. If set to false, the AI will take over again.", "boolean", "Returns true if successful, false otherwise")
7349 {
7350  bool targetOverride = false;
7351  ship_subsys_h *sso;
7352  if(!ade_get_args(L, "ob", l_Subsystem.GetPtr(&sso), &targetOverride))
7353  return ADE_RETURN_FALSE;
7354 
7355  if(!sso->IsValid())
7356  return ADE_RETURN_FALSE;
7357 
7358  ship_subsys *ss = sso->ss;
7359 
7360  ss->scripting_target_override = targetOverride;
7361  return ADE_RETURN_TRUE;
7362 }
7363 
7364 ADE_FUNC(hasFired, l_Subsystem, NULL, "Determine if a subsystem has fired", "boolean", "true if if fired, false if not fired, or nil if invalid. resets fired flag when called.")
7365 {
7366  ship_subsys_h *sso;
7367  if(!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso)))
7368  return ADE_RETURN_NIL;
7369 
7370  if(!sso->IsValid())
7371  return ADE_RETURN_NIL;
7372 
7373  if(sso->ss->flags & SSF_HAS_FIRED){
7374  sso->ss->flags &= ~SSF_HAS_FIRED;
7375  return ADE_RETURN_TRUE;}
7376  else
7377  return ADE_RETURN_FALSE;
7378 }
7379 
7380 ADE_FUNC(isTurret, l_Subsystem, NULL, "Determines if this subsystem is a turret", "boolean", "true if subsystem is turret, false otherwise or nil on error")
7381 {
7382  ship_subsys_h *sso;
7383  if(!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso)))
7384  return ADE_RETURN_NIL;
7385 
7386  if (!sso->IsValid())
7387  return ADE_RETURN_NIL;
7388 
7389  return ade_set_args(L, "b", sso->ss->system_info->type == SUBSYSTEM_TURRET);
7390 }
7391 
7392 ADE_FUNC(isTargetInFOV, l_Subsystem, "object Target", "Determines if the object is in the turrets FOV", "boolean", "true if in FOV, false if not, nil on error or if subsystem is not a turret ")
7393 {
7394  ship_subsys_h *sso;
7395  object_h *newh = nullptr;
7396  if(!ade_get_args(L, "o|o", l_Subsystem.GetPtr(&sso), l_Object.GetPtr(&newh)))
7397  return ADE_RETURN_NIL;
7398 
7399  if (!sso->IsValid() || !newh || !newh->IsValid() || !(sso->ss->system_info->type == SUBSYSTEM_TURRET))
7400  return ADE_RETURN_NIL;
7401 
7402  vec3d tpos,tvec;
7403  ship_get_global_turret_info(sso->objp, sso->ss->system_info, &tpos, &tvec);
7404 
7405  int in_fov = object_in_turret_fov(newh->objp,sso->ss,&tvec,&tpos,vm_vec_dist(&newh->objp->pos,&tpos));
7406 
7407  if (in_fov)
7408  return ADE_RETURN_TRUE;
7409  else
7410  return ADE_RETURN_FALSE;
7411 }
7412 
7413 bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, vec3d *turret_pos, vec3d *turret_fvec, vec3d *predicted_pos = NULL, float flak_range_override = 100.0f);
7414 ADE_FUNC(fireWeapon, l_Subsystem, "[Turret weapon index = 1, Flak range = 100]", "Fires weapon on turret", NULL, NULL)
7415 {
7416  ship_subsys_h *sso;
7417  int wnum = 1;
7418  float flak_range = 100.0f;
7419  if(!ade_get_args(L, "o|if", l_Subsystem.GetPtr(&sso), &wnum, &flak_range))
7420  return ADE_RETURN_NIL;
7421 
7422  if(!sso->IsValid())
7423  return ADE_RETURN_NIL;
7424 
7425  if (sso->ss->current_hits <= 0)
7426  {
7427  return ADE_RETURN_FALSE;
7428  }
7429 
7430  wnum--; //Lua->FS2
7431 
7432  //Get default turret info
7433  vec3d gpos, gvec;
7434 
7435  ship_get_global_turret_gun_info(sso->objp, sso->ss, &gpos, &gvec, 1, NULL);
7436 
7437  bool rtn = turret_fire_weapon(wnum, sso->ss, OBJ_INDEX(sso->objp), &gpos, &gvec, NULL, flak_range);
7438 
7439  sso->ss->turret_next_fire_pos++;
7440 
7441  return ade_set_args(L, "b", rtn);
7442 }
7443 
7444 ADE_FUNC(rotateTurret, l_Subsystem, "vector Pos[, boolean reset=false", "Rotates the turret to face Pos or resets the turret to its original state", "boolean", "true on success false otherwise")
7445 {
7446  ship_subsys_h *sso;
7448  bool reset = false;
7449  if (!ade_get_args(L, "oo|b", l_Subsystem.GetPtr(&sso), l_Vector.Get(&pos), &reset))
7450  return ADE_RETURN_NIL;
7451 
7452  //Get default turret info
7453  vec3d gpos, gvec;
7454  model_subsystem *tp = sso->ss->system_info;
7455  object *objp = sso->objp;
7456 
7457  //Rotate turret position with ship
7458  vm_vec_unrotate(&gpos, &tp->pnt, &sso->objp->orient);
7459 
7460  //Add turret position to appropriate world space
7461  vm_vec_add2(&gpos, &sso->objp->pos);
7462 
7463  // Find direction of turret
7465 
7466  int ret_val = model_rotate_gun(Ship_info[(&Ships[sso->objp->instance])->ship_info_index].model_num, tp, &Objects[sso->objp->instance].orient, &sso->ss->submodel_info_1.angs, &sso->ss->submodel_info_2.angs, &Objects[sso->objp->instance].pos, &pos, (&Ships[sso->objp->instance])->objnum, reset);
7467 
7468  if (ret_val)
7469  return ADE_RETURN_TRUE;
7470  else
7471  return ADE_RETURN_FALSE;
7472 }
7473 
7474 ADE_FUNC(getTurretHeading, l_Subsystem, NULL, "Returns the turrets forward vector", "vector", "Returns a normalized version of the forward vector or null vector on error")
7475 {
7476  ship_subsys_h *sso;
7477  if(!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso)))
7478  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
7479 
7480  if(!sso->IsValid())
7481  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
7482 
7483  vec3d gvec;
7484  object *objp = sso->objp;
7485 
7487 
7488  vec3d out;
7489  vm_vec_rotate(&out, &gvec, &sso->objp->orient);
7490 
7491  return ade_set_args(L, "o", l_Vector.Set(out));
7492 }
7493 
7494 ADE_FUNC(getFOVs, l_Subsystem, NULL, "Returns current turrets FOVs", "number, number, number", "Standard FOV, maximum barrel elevation, turret base fov.")
7495 {
7496  ship_subsys_h *sso;
7497  float fov, fov_e, fov_y;
7498  if(!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso)))
7499  return ADE_RETURN_NIL;
7500 
7501  if(!sso->IsValid())
7502  return ADE_RETURN_NIL;
7503 
7504  model_subsystem *tp = sso->ss->system_info;
7505 
7506  fov = tp->turret_fov;
7507  fov_e = tp->turret_max_fov;
7508  fov_y = tp->turret_y_fov;
7509 
7510  return ade_set_args(L, "fff", fov, fov_e, fov_y);
7511 }
7512 
7513 ADE_FUNC(getNextFiringPosition, l_Subsystem, NULL, "Retrieves the next position and firing normal this turret will fire from. This function returns a world position", "vector, vector", "vector or null vector on error")
7514 {
7515  ship_subsys_h *sso;
7516  if(!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso)))
7517  return ade_set_error(L, "oo", l_Vector.Set(vmd_zero_vector), l_Vector.Set(vmd_zero_vector));
7518 
7519  if(!sso->IsValid())
7520  return ade_set_error(L, "oo", l_Vector.Set(vmd_zero_vector), l_Vector.Set(vmd_zero_vector));
7521 
7522  vec3d gpos, gvec;
7523 
7524  ship_get_global_turret_gun_info(sso->objp, sso->ss, &gpos, &gvec, 1, NULL);
7525 
7526  return ade_set_args(L, "oo", l_Vector.Set(gpos), l_Vector.Set(gvec));
7527 }
7528 
7529 ADE_FUNC(getTurretMatrix, l_Subsystem, NULL, "Returns current subsystems turret matrix", "matrix", "Turret matrix.")
7530 {
7531  ship_subsys_h *sso;
7532  matrix m;
7533  if(!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso)))
7534  return ADE_RETURN_NIL;
7535 
7536  if(!sso->IsValid())
7537  return ADE_RETURN_NIL;
7538 
7539  model_subsystem *tp = sso->ss->system_info;
7540 
7541  m = tp->turret_matrix;
7542 
7543  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&m)));
7544 }
7545 
7546 ADE_FUNC(getParent, l_Subsystem, NULL, "The object parent of this subsystem, is of type ship", "object", "object handle or invalid handle on error")
7547 {
7548  ship_subsys_h *sso = NULL;
7549  object_h *objhp = NULL;
7550  if(!ade_get_args(L, "o|o", l_Subsystem.GetPtr(&sso), l_Ship.GetPtr(&objhp)))
7551  return ade_set_error(L, "o", l_Object.Set(object_h()));
7552 
7553  if(!sso->IsValid())
7554  return ade_set_error(L, "o", l_Object.Set(object_h()));
7555 
7556  return ade_set_args(L, "o", l_Object.Set(object_h(sso->objp)));
7557 }
7558 
7559 ADE_FUNC(isValid, l_Subsystem, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
7560 {
7561  ship_subsys_h *sso;
7562  if(!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso)))
7563  return ADE_RETURN_NIL;
7564 
7565  return ade_set_args(L, "b", sso->IsValid());
7566 }
7567 
7568 //**********HANDLE: order
7569 struct order_h
7570 {
7572  int odx;
7573  int sig;
7575 
7577  objh = object_h();
7578  odx = -1;
7579  sig = -1;
7580  aigp = NULL;
7581  }
7582 
7583  order_h(object *objp, int n_odx)
7584  {
7585  objh = object_h(objp);
7586  if(objh.IsValid() && objh.objp->type == OBJ_SHIP && n_odx > -1 && n_odx < MAX_AI_GOALS)
7587  {
7588  odx = n_odx;
7590  aigp = &Ai_info[Ships[objh.objp->instance].ai_index].goals[odx];
7591  }
7592  else
7593  {
7594  odx = -1;
7595  sig = -1;
7596  aigp = NULL;
7597  }
7598  }
7599 
7600  bool IsValid()
7601  {
7602  if (objh.objp == NULL || aigp == NULL)
7603  return false;
7604 
7605  return objh.IsValid() && objh.objp->type == OBJ_SHIP && odx > -1 && odx < MAX_AI_GOALS && sig == Ai_info[Ships[objh.objp->instance].ai_index].goals[odx].signature;
7606  }
7607 };
7608 
7609 ade_obj<order_h> l_Order("order", "order handle");
7610 
7611 ADE_VIRTVAR(Priority, l_Order, "number", "Priority of the given order", "number", "Order priority or 0 if invalid")
7612 {
7613  order_h *ohp = NULL;
7614  int priority = 1;
7615 
7616  if(!ade_get_args(L, "o|i", l_Order.GetPtr(&ohp), &priority))
7617  return ade_set_error(L, "i", 0);
7618 
7619  if(!ohp->IsValid())
7620  return ade_set_error(L, "i", 0);
7621 
7622  if(ADE_SETTING_VAR) {
7623  ohp->aigp->priority = priority;
7624  }
7625 
7626  return ade_set_args(L, "i", ohp->aigp->priority);
7627 }
7628 
7629 ADE_FUNC(remove, l_Order, NULL, "Removes the given order from the ship's priority queue.", "boolean", "True if order was successfully removed, otherwise false or nil.")
7630 {
7631  order_h *ohp = NULL;
7632  if(!ade_get_args(L, "o", l_Order.GetPtr(&ohp)))
7633  return ADE_RETURN_NIL;
7634 
7635  if(!ohp->IsValid())
7636  return ADE_RETURN_FALSE;
7637 
7638  ai_info *aip = &Ai_info[Ships[ohp->objh.objp->instance].ai_index];
7639 
7640  ai_remove_ship_goal(aip, ohp->odx);
7641 
7642  return ADE_RETURN_TRUE;
7643 }
7644 
7645 ADE_FUNC(getType, l_Order, NULL, "Gets the type of the order.", "enumeration", "The type of the order as one of the ORDER_* enumerations.")
7646 {
7647  order_h *ohp = NULL;
7648  int eh_idx = -1;
7649  if(!ade_get_args(L, "o", l_Order.GetPtr(&ohp)))
7650  return ade_set_error(L, "o", l_Enum.Set(enum_h()));
7651 
7652  if(!ohp->IsValid())
7653  return ade_set_error(L, "o", l_Enum.Set(enum_h()));
7654 
7655  switch(ohp->aigp->ai_mode){
7657  case AI_GOAL_CHASE_WEAPON:
7658  case AI_GOAL_CHASE:
7659  eh_idx = LE_ORDER_ATTACK;
7660  break;
7661  case AI_GOAL_DOCK:
7662  eh_idx = LE_ORDER_DOCK;
7663  break;
7664  case AI_GOAL_WAYPOINTS:
7665  eh_idx = LE_ORDER_WAYPOINTS;
7666  break;
7668  eh_idx = LE_ORDER_WAYPOINTS_ONCE;
7669  break;
7670  case AI_GOAL_WARP:
7671  eh_idx = LE_ORDER_DEPART;
7672  break;
7673  case AI_GOAL_FORM_ON_WING:
7674  eh_idx = LE_ORDER_FORM_ON_WING;
7675  break;
7676  case AI_GOAL_UNDOCK:
7677  eh_idx = LE_ORDER_UNDOCK;
7678  break;
7679  case AI_GOAL_GUARD:
7680  eh_idx = LE_ORDER_GUARD;
7681  break;
7682  case AI_GOAL_DISABLE_SHIP:
7683  eh_idx = LE_ORDER_DISABLE;
7684  break;
7685  case AI_GOAL_DISARM_SHIP:
7686  eh_idx = LE_ORDER_DISARM;
7687  break;
7688  case AI_GOAL_CHASE_ANY:
7689  eh_idx = LE_ORDER_ATTACK_ANY;
7690  break;
7691  case AI_GOAL_IGNORE_NEW:
7692  case AI_GOAL_IGNORE:
7693  eh_idx = LE_ORDER_IGNORE;
7694  break;
7695  case AI_GOAL_EVADE_SHIP:
7696  eh_idx = LE_ORDER_EVADE;
7697  break;
7699  eh_idx = LE_ORDER_STAY_NEAR;
7700  break;
7702  eh_idx = LE_ORDER_KEEP_SAFE_DISTANCE;
7703  break;
7704  case AI_GOAL_REARM_REPAIR:
7705  eh_idx = LE_ORDER_REARM;
7706  break;
7707  case AI_GOAL_STAY_STILL:
7708  eh_idx = LE_ORDER_STAY_STILL;
7709  break;
7710  case AI_GOAL_PLAY_DEAD:
7711  eh_idx = LE_ORDER_PLAY_DEAD;
7712  break;
7713  case AI_GOAL_FLY_TO_SHIP:
7714  eh_idx = LE_ORDER_FLY_TO;
7715  break;
7716  case AI_GOAL_CHASE_WING:
7717  eh_idx = LE_ORDER_ATTACK_WING;
7718  break;
7719  case AI_GOAL_GUARD_WING:
7720  eh_idx = LE_ORDER_GUARD_WING;
7721  break;
7722  }
7723 
7724  return ade_set_args(L, "o", l_Enum.Set(eh_idx));
7725 }
7726 
7727 ADE_VIRTVAR(Target, l_Order, "object", "Target of the order. Value may also be a deriviative of the 'object' class, such as 'ship'.", "object", "Target object or invalid object handle if order handle is invalid or order requires no target.")
7728 {
7729  order_h *ohp = NULL;
7730  object_h *newh = NULL;
7731  ai_info *aip = NULL;
7732  waypoint_list *wpl = NULL;
7733  int shipnum = -1, objnum = -1;
7734  if(!ade_get_args(L, "o|o", l_Order.GetPtr(&ohp), l_Object.GetPtr(&newh)))
7735  return ade_set_error(L, "o", l_Object.Set(object_h()));
7736 
7737  if(!ohp->IsValid())
7738  return ade_set_error(L, "o", l_Object.Set(object_h()));
7739 
7740  aip = &Ai_info[Ships[ohp->objh.objp->instance].ai_index];
7741 
7742  if(ADE_SETTING_VAR){
7743  if(newh && newh->IsValid()){
7744  switch(ohp->aigp->ai_mode){
7746  case AI_GOAL_CHASE:
7747  case AI_GOAL_FORM_ON_WING:
7748  case AI_GOAL_GUARD:
7749  case AI_GOAL_DISABLE_SHIP:
7750  case AI_GOAL_DISARM_SHIP:
7751  case AI_GOAL_IGNORE_NEW:
7752  case AI_GOAL_IGNORE:
7753  case AI_GOAL_EVADE_SHIP:
7756  case AI_GOAL_FLY_TO_SHIP:
7757  case AI_GOAL_STAY_STILL:
7758  if ((newh->objp->type == OBJ_SHIP) && !stricmp(Ships[newh->objp->instance].ship_name, ohp->aigp->target_name)){
7759  ohp->aigp->target_name = Ships[newh->objp->instance].ship_name;
7760  ohp->aigp->time = Missiontime;
7761  if(ohp->odx == 0) {
7763  set_target_objnum(aip, OBJ_INDEX(newh->objp));
7764  }
7765  }
7766  break;
7767  case AI_GOAL_CHASE_WEAPON:
7768  if ((newh->objp->type == OBJ_WEAPON) && (ohp->aigp->target_signature != newh->sig)){
7769  ohp->aigp->target_instance = newh->objp->instance;
7770  ohp->aigp->target_signature = Weapons[newh->objp->instance].objnum;
7771  ohp->aigp->time = Missiontime;
7772  if(ohp->odx == 0) {
7774  set_target_objnum(aip, OBJ_INDEX(newh->objp));
7775  }
7776  }
7777  break;
7778  case AI_GOAL_WAYPOINTS:
7780  if (newh->objp->type == OBJ_WAYPOINT){
7782  if (!stricmp(wpl->get_name(),ohp->aigp->target_name)){
7783  ohp->aigp->target_name = wpl->get_name();
7784  ohp->aigp->time = Missiontime;
7785  if(ohp->odx == 0) {
7786  int flags = 0;
7787  if ( ohp->aigp->ai_mode == AI_GOAL_WAYPOINTS)
7788  flags |= WPF_REPEAT;
7789  ai_start_waypoints(ohp->objh.objp, wpl, flags);
7790  }
7791  }
7792  }
7793  break;
7794  case AI_GOAL_CHASE_WING:
7795  if((newh->objp->type == OBJ_SHIP) && !stricmp(Ships[newh->objp->instance].ship_name, ohp->aigp->target_name)){
7796  ship *shipp = &Ships[newh->objp->instance];
7797  if (shipp->wingnum != -1){
7798  ohp->aigp->target_name = Wings[shipp->wingnum].name;
7799  if(ohp->odx == 0) {
7801  ai_attack_wing(ohp->objh.objp,shipp->wingnum);
7802  }
7803  }
7804  }
7805  break;
7806  case AI_GOAL_GUARD_WING:
7807  if((newh->objp->type == OBJ_SHIP) && !stricmp(Ships[newh->objp->instance].ship_name, ohp->aigp->target_name)){
7808  ship *shipp = &Ships[newh->objp->instance];
7809  if (shipp->wingnum != -1){
7810  ohp->aigp->target_name = Wings[shipp->wingnum].name;
7811  if(ohp->odx == 0) {
7813  ai_set_guard_wing(ohp->objh.objp,shipp->wingnum);
7814  }
7815  }
7816  }
7817  break;
7818  }
7819  }
7820  }
7821 
7822  switch(ohp->aigp->ai_mode){
7824  case AI_GOAL_CHASE:
7825  case AI_GOAL_DOCK:
7826  case AI_GOAL_FORM_ON_WING:
7827  case AI_GOAL_GUARD:
7828  case AI_GOAL_DISABLE_SHIP:
7829  case AI_GOAL_DISARM_SHIP:
7830  case AI_GOAL_IGNORE_NEW:
7831  case AI_GOAL_IGNORE:
7832  case AI_GOAL_EVADE_SHIP:
7835  case AI_GOAL_REARM_REPAIR:
7836  case AI_GOAL_FLY_TO_SHIP:
7837  case AI_GOAL_UNDOCK:
7838  shipnum = ship_name_lookup(ohp->aigp->target_name);
7839  objnum = Ships[shipnum].objnum;
7840  break;
7841  case AI_GOAL_CHASE_WEAPON:
7842  objnum = Weapons[ohp->aigp->target_instance].objnum;
7843  break;
7844  case AI_GOAL_WAYPOINTS:
7847  if(ohp->odx == 0) {
7848  objnum = aip->wp_list->get_waypoints()[aip->wp_index].get_objnum();
7849  } else {
7850  objnum = wpl->get_waypoints().front().get_objnum();
7851  }
7852  break;
7853  case AI_GOAL_STAY_STILL:
7854  shipnum = ship_name_lookup(ohp->aigp->target_name);
7855  if (shipnum != -1){
7856  objnum = Ships[shipnum].objnum;
7857  break;
7858  }
7859  case AI_GOAL_CHASE_WING:
7860  case AI_GOAL_GUARD_WING:
7861  int wingnum = wing_name_lookup(ohp->aigp->target_name);
7862  if (Wings[wingnum].current_count > 0){
7863  shipnum = Wings[wingnum].ship_index[0];
7864  objnum = Ships[shipnum].objnum;
7865  }
7866  break;
7867  }
7868 
7869  return ade_set_object_with_breed(L, objnum);
7870 }
7871 
7872 
7873 ADE_VIRTVAR(TargetSubsystem, l_Order, "subsystem", "Target subsystem of the order.", "subsystem", "Target subsystem, or invalid subsystem handle if order handle is invalid or order requires no subsystem target.")
7874 {
7875  order_h *ohp = NULL;
7876  ship_subsys_h *newh = NULL;
7877  ai_info *aip = NULL;
7878  object *objp = NULL;
7879  if(!ade_get_args(L, "o|o", l_Order.GetPtr(&ohp), l_Subsystem.GetPtr(&newh)))
7880  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
7881 
7882  if(!ohp->IsValid())
7883  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
7884 
7885  aip = &Ai_info[Ships[ohp->objh.objp->instance].ai_index];
7886 
7887  if(ADE_SETTING_VAR)
7888  {
7889  if(newh && newh->IsValid() && (ohp->aigp->ai_mode == AI_GOAL_DESTROY_SUBSYSTEM))
7890  {
7891  objp = &Objects[newh->ss->parent_objnum];
7892  if(!stricmp(Ships[objp->instance].ship_name, ohp->aigp->target_name)) {
7893  ohp->aigp->target_name = Ships[objp->instance].ship_name;
7894  ohp->aigp->time = Missiontime;
7895  if(ohp->odx == 0) {
7897  set_target_objnum(aip, OBJ_INDEX(objp));
7898  }
7899  }
7900  ohp->aigp->ai_submode = ship_get_subsys_index( &Ships[objp->instance], newh->ss->system_info->subobj_name );
7901  if(ohp->odx == 0) {
7902  set_targeted_subsys(aip, newh->ss, OBJ_INDEX(objp));
7903  }
7904  if (aip == Player_ai) {
7905  Ships[newh->ss->parent_objnum].last_targeted_subobject[Player_num] = newh->ss;
7906  }
7907  }
7908  }
7909 
7910  if(ohp->aigp->ai_mode == AI_GOAL_DESTROY_SUBSYSTEM){
7912  } else {
7913  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
7914  }
7915 }
7916 
7917 ADE_FUNC(isValid, l_Order, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
7918 {
7919  order_h *ohp = NULL;
7920  if(!ade_get_args(L, "o", l_Order.GetPtr(&ohp)))
7921  return ADE_RETURN_NIL;
7922 
7923  return ade_set_args(L, "b", ohp->IsValid());
7924 }
7925 
7926 //**********HANDLE: shiporders
7927 ade_obj<object_h> l_ShipOrders("shiporders", "Ship orders");
7928 
7929 ADE_FUNC(__len, l_ShipOrders, NULL, "Number of ship orders", "number", "Number of ship orders, or 0 if handle is invalid")
7930 {
7931  object_h *objh = NULL;
7932  if(!ade_get_args(L, "o", l_ShipOrders.GetPtr(&objh)))
7933  return ade_set_error(L, "i", 0);
7934 
7935  if(!objh->IsValid() || objh->objp->type != OBJ_SHIP || Ships[objh->objp->instance].ai_index < 0)
7936  return ade_set_error(L, "i", 0);
7937 
7938  return ade_set_args(L, "i", ai_goal_num(&Ai_info[Ships[objh->objp->instance].ai_index].goals[0]));
7939 }
7940 
7941 ADE_INDEXER(l_ShipOrders, "number Index", "Array of ship orders", "order", "Order, or invalid order handle on failure")
7942 {
7943  object_h *objh = NULL;
7944  int i;
7945 
7946  if (!ade_get_args(L, "oi", l_ShipOrders.GetPtr(&objh), &i))
7947  return ade_set_error(L, "o", l_Order.Set(order_h()));
7948 
7949  i--; //Lua->FS2
7950 
7951  if (!objh->IsValid() || i < 0 || i >= MAX_AI_GOALS)
7952  return ade_set_error(L, "o", l_Order.Set(order_h()));
7953 
7954  ai_info *aip = &Ai_info[Ships[objh->objp->instance].ai_index];
7955 
7956  if (aip->goals[i].ai_mode != AI_GOAL_NONE)
7957  return ade_set_args(L, "o", l_Order.Set(order_h(objh->objp, i)));
7958  else
7959  return ade_set_args(L, "o", l_Order.Set(order_h()));
7960 }
7961 
7962 ADE_FUNC(isValid, l_ShipOrders, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
7963 {
7964  object_h *oh;
7965  if(!ade_get_args(L, "o", l_ShipOrders.GetPtr(&oh)))
7966  return ADE_RETURN_NIL;
7967 
7968  return ade_set_args(L, "b", oh->IsValid());
7969 }
7970 
7971 
7972 
7973 //**********HANDLE: shiptextures
7974 ade_obj<object_h> l_ShipTextures("shiptextures", "Ship textures handle");
7975 
7976 ADE_FUNC(__len, l_ShipTextures, NULL, "Number of textures on ship", "number", "Number of textures on ship, or 0 if handle is invalid")
7977 {
7978  object_h *objh;
7979  if(!ade_get_args(L, "o", l_ShipTextures.GetPtr(&objh)))
7980  return ade_set_error(L, "i", 0);
7981 
7982  if(!objh->IsValid())
7983  return ade_set_error(L, "i", 0);
7984 
7985  polymodel *pm = model_get(Ship_info[Ships[objh->objp->instance].ship_info_index].model_num);
7986 
7987  if(pm == NULL)
7988  return ade_set_error(L, "i", 0);
7989 
7990  return ade_set_args(L, "i", pm->n_textures*TM_NUM_TYPES);
7991 }
7992 
7993 ADE_INDEXER(l_ShipTextures, "number Index/string TextureFilename", "Array of ship textures", "texture", "Texture, or invalid texture handle on failure")
7994 {
7995  object_h *oh;
7996  char *s;
7997  int tdx=-1;
7998  if (!ade_get_args(L, "os|o", l_ShipTextures.GetPtr(&oh), &s, l_Texture.Get(&tdx)))
7999  return ade_set_error(L, "o", l_Texture.Set(-1));
8000 
8001  if (!oh->IsValid() || s==NULL)
8002  return ade_set_error(L, "o", l_Texture.Set(-1));
8003 
8004  ship *shipp = &Ships[oh->objp->instance];
8005  polymodel *pm = model_get(Ship_info[shipp->ship_info_index].model_num);
8006  int final_index = -1;
8007  int i;
8008 
8009  char fname[MAX_FILENAME_LEN];
8010  if (shipp->ship_replacement_textures != NULL)
8011  {
8012  for(i = 0; i < MAX_REPLACEMENT_TEXTURES; i++)
8013  {
8014  bm_get_filename(shipp->ship_replacement_textures[i], fname);
8015 
8016  if(!strextcmp(fname, s)) {
8017  final_index = i;
8018  break;
8019  }
8020  }
8021  }
8022 
8023  if(final_index < 0)
8024  {
8025  for (i = 0; i < pm->n_textures; i++)
8026  {
8027  int tm_num = pm->maps[i].FindTexture(s);
8028  if(tm_num > -1)
8029  {
8030  final_index = i*TM_NUM_TYPES+tm_num;
8031  break;
8032  }
8033  }
8034  }
8035 
8036  if (final_index < 0)
8037  {
8038  final_index = atoi(s) - 1; //Lua->FS2
8039 
8040  if (final_index < 0 || final_index >= MAX_REPLACEMENT_TEXTURES)
8041  return ade_set_error(L, "o", l_Texture.Set(-1));
8042  }
8043 
8044  if (ADE_SETTING_VAR) {
8045  if (shipp->ship_replacement_textures == NULL) {
8046  shipp->ship_replacement_textures = (int *) vm_malloc(MAX_REPLACEMENT_TEXTURES * sizeof(int));
8047 
8048  for (i = 0; i < MAX_REPLACEMENT_TEXTURES; i++)
8049  shipp->ship_replacement_textures[i] = -1;
8050  }
8051 
8052  if(bm_is_valid(tdx))
8053  shipp->ship_replacement_textures[final_index] = tdx;
8054  else
8055  shipp->ship_replacement_textures[final_index] = -1;
8056  }
8057 
8058  if (shipp->ship_replacement_textures != NULL && shipp->ship_replacement_textures[final_index] >= 0)
8059  return ade_set_args(L, "o", l_Texture.Set(shipp->ship_replacement_textures[final_index]));
8060  else
8061  return ade_set_args(L, "o", l_Texture.Set(pm->maps[final_index / TM_NUM_TYPES].textures[final_index % TM_NUM_TYPES].GetTexture()));
8062 }
8063 
8064 ADE_FUNC(isValid, l_ShipTextures, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
8065 {
8066  object_h *oh;
8067  if(!ade_get_args(L, "o", l_ShipTextures.GetPtr(&oh)))
8068  return ADE_RETURN_NIL;
8069 
8070  return ade_set_args(L, "b", oh->IsValid());
8071 }
8072 
8073 //**********HANDLE: CockpitDisplayArray
8075 {
8076 private:
8077  object *m_objp;
8078 public:
8079  cockpit_displays_h() : m_objp( NULL ) {}
8080  cockpit_displays_h(object *objp)
8081  {
8082  this->m_objp = objp;
8083  }
8084 
8085  bool isValid()
8086  {
8087  if (m_objp == NULL)
8088  {
8089  return false;
8090  }
8091 
8092  if (m_objp != Player_obj)
8093  {
8094  return false;
8095  }
8096 
8097  if ( Ship_info[Player_ship->ship_info_index].cockpit_model_num < 0 ) {
8098  return false;
8099  }
8100 
8101  if ( Player_cockpit_textures == NULL ) {
8102  return false;
8103  }
8104 
8105  return true;
8106  }
8107 };
8108 ade_obj<cockpit_displays_h> l_CockpitDisplays("displays", "Player cockpit displays array handle");
8109 
8110 ADE_FUNC(__len, l_CockpitDisplays, NULL, "Gets the number of cockpit displays for the player ship", "number", "number of displays or -1 on error")
8111 {
8112  cockpit_displays_h *cdh = NULL;
8113  if(!ade_get_args(L, "o", l_CockpitDisplays.GetPtr(&cdh)))
8114  return ade_set_error(L, "i", -1);
8115 
8116  if (!cdh->isValid())
8117  return ade_set_error(L, "i", -1);
8118 
8119  return ade_set_args(L, "i", (int) Player_displays.size());
8120 }
8121 
8122 ADE_INDEXER(l_CockpitDisplays, "number/string", "Gets a cockpit display from the present player displays by either the index or the name of the display", "display", "Display handle or invalid handle on error")
8123 {
8124  if (lua_isnumber(L, 2))
8125  {
8126  cockpit_displays_h *cdh = NULL;
8127  int index = -1;
8128 
8129  if (!ade_get_args(L, "oi", l_CockpitDisplays.GetPtr(&cdh), &index))
8130  {
8131  return ade_set_error(L, "o", l_CockpitDisplay.Set(cockpit_display_h()));
8132  }
8133 
8134  if (index < 0)
8135  {
8136  return ade_set_error(L, "o", l_CockpitDisplay.Set(cockpit_display_h()));
8137  }
8138 
8139  index--; // Lua -> C/C++
8140 
8141  return ade_set_args(L, "o", l_CockpitDisplay.Set(cockpit_display_h(Player_obj, index)));
8142  }
8143  else
8144  {
8145  cockpit_displays_h *cdh = NULL;
8146  char *name = NULL;
8147 
8148  if (!ade_get_args(L, "os", l_CockpitDisplays.GetPtr(&cdh), &name))
8149  {
8150  return ade_set_error(L, "o", l_CockpitDisplay.Set(cockpit_display_h()));
8151  }
8152 
8153  if (!cdh->isValid())
8154  {
8155  return ade_set_error(L, "o", l_CockpitDisplay.Set(cockpit_display_h()));
8156  }
8157 
8158  if (name == NULL)
8159  {
8160  return ade_set_error(L, "o", l_CockpitDisplay.Set(cockpit_display_h()));
8161  }
8162 
8163  size_t index = 0;
8164 
8165  for (SCP_vector<cockpit_display>::iterator iter = Player_displays.begin(); iter != Player_displays.end(); ++iter)
8166  {
8167  if (!strcmp(name, iter->name))
8168  {
8169  break;
8170  }
8171  else
8172  {
8173  index++;
8174  }
8175  }
8176 
8177  if (index == Player_displays.size())
8178  {
8179  LuaError(L, "Couldn't find cockpit display info with name \"%s\"", name);
8180  return ade_set_error(L, "o", l_CockpitDisplay.Set(cockpit_display_h()));
8181  }
8182 
8183  return ade_set_args(L, "o", l_CockpitDisplay.Set(cockpit_display_h(Player_obj, index)));
8184  }
8185 }
8186 
8187 ADE_FUNC(isValid, l_CockpitDisplays, NULL, "Detects whether this handle is valid or not", "boolean", "true if valid, false otherwise")
8188 {
8189  cockpit_displays_h *cdh = NULL;
8190  if(!ade_get_args(L, "o", l_CockpitDisplays.GetPtr(&cdh)))
8191  return ADE_RETURN_FALSE;
8192 
8193  return ade_set_args(L, "b", cdh->isValid());
8194 }
8195 
8196 //**********HANDLE: SoundEntry
8198 {
8199  int idx;
8200 
8202  {
8203  idx = -1;
8204  }
8205 
8206  sound_entry_h(int n_idx)
8207  {
8208  idx = n_idx;
8209  }
8210 
8212  {
8213  if (!this->IsValid())
8214  return NULL;
8215 
8216  return &Snds[idx];
8217  }
8218 
8219  bool IsValid()
8220  {
8221  if (idx < 0 || idx >= (int) Snds.size())
8222  return false;
8223 
8224  return true;
8225  }
8226 
8227  int getId()
8228  {
8229  if (!IsValid())
8230  return -1;
8231 
8232  game_snd *snd = Get();
8233 
8234  if (snd == NULL)
8235  return -1;
8236 
8237  return snd->id;
8238  }
8239 
8240 };
8241 
8242 //**********HANDLE: SoundEntry
8243 ade_obj<sound_entry_h> l_SoundEntry("soundentry", "sounds.tbl table entry handle");
8244 
8245 ADE_VIRTVAR(DefaultVolume, l_SoundEntry, "number", "The default volume of this game sound", "number", "Volume in the range from 1 to 0 or -1 on error")
8246 {
8247  sound_entry_h *seh = NULL;
8248  float newVal = -1.0f;
8249 
8250  if (!ade_get_args(L, "o|f", l_SoundEntry.GetPtr(&seh), &newVal))
8251  return ade_set_error(L, "f", -1.0f);
8252 
8253  if (seh == NULL || !seh->IsValid())
8254  return ade_set_error(L, "f", -1.0f);
8255 
8256  if (ADE_SETTING_VAR)
8257  {
8258  if (seh->Get() != NULL)
8259  {
8260  CAP(newVal, 0.0f, 1.0f);
8261 
8262  seh->Get()->default_volume = newVal;
8263  }
8264  }
8265 
8266  return ade_set_args(L, "f", seh->Get()->default_volume);
8267 }
8268 
8269 ADE_FUNC(getFilename, l_SoundEntry, NULL, "Returns the filename of this sound", "string", "filename or empty string on error")
8270 {
8271  sound_entry_h *seh = NULL;
8272 
8273  if (!ade_get_args(L, "o", l_SoundEntry.GetPtr(&seh)))
8274  return ade_set_error(L, "s", "");
8275 
8276  if (seh == NULL || !seh->IsValid())
8277  return ade_set_error(L, "s", "");
8278 
8279  return ade_set_args(L, "s", seh->Get()->filename);
8280 }
8281 
8282 ADE_FUNC(getDuration, l_SoundEntry, NULL, "Gives the length of the sound in seconds.", "number", "the length, or -1 on error")
8283 {
8284  sound_entry_h *seh = NULL;
8285 
8286  if (!ade_get_args(L, "o", l_SoundEntry.GetPtr(&seh)))
8287  return ade_set_error(L, "f", -1.0f);
8288 
8289  if (seh == NULL || !seh->IsValid())
8290  return ade_set_error(L, "f", -1.0f);
8291 
8292  return ade_set_args(L, "f", (i2fl(snd_get_duration(seh->getId())) / 1000.0f));
8293 }
8294 
8295 ADE_FUNC(get3DValues, l_SoundEntry, "vector Postion[, number radius=0.0]", "Computes the volume and the panning of the sound when it would be played from the specified position.<br>"
8296  "If range is given then the volume will diminish when the listener is withing that distance to the source.<br>"
8297  "The position of the listener is always the the current viewing position.", "number, number", "The volume and the panning, in that sequence, or both -1 on error")
8298 {
8299  sound_entry_h *seh = NULL;
8300  vec3d *sourcePos = NULL;
8301  float radius = 0.0f;
8302 
8303  float vol = 0.0f;
8304  float pan = 0.0f;
8305 
8306  if (!ade_get_args(L, "oo|f", l_SoundEntry.GetPtr(&seh), l_Vector.GetPtr(&sourcePos), &radius))
8307  return ade_set_error(L, "ff", -1.0f, -1.0f);
8308 
8309  if (seh == NULL || !seh->IsValid())
8310  return ade_set_error(L, "ff", -1.0f, -1.0f);
8311 
8312  int result = snd_get_3d_vol_and_pan(seh->Get(), sourcePos, &vol, &pan, radius);
8313 
8314  if (result < 0)
8315  {
8316  return ade_set_args(L, "ff", -1.0f, -1.0f);
8317  }
8318  else
8319  {
8320  return ade_set_args(L, "ff", vol, pan);
8321  }
8322 }
8323 
8324 ADE_FUNC(isValid, l_SoundEntry, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
8325 {
8326  sound_entry_h *seh;
8327  if(!ade_get_args(L, "o", l_SoundEntry.GetPtr(&seh)))
8328  return ADE_RETURN_NIL;
8329 
8330  return ade_set_args(L, "b", seh->IsValid());
8331 }
8332 
8333 //**********HANDLE: Sound
8334 struct sound_h : public sound_entry_h
8335 {
8336  int sig;
8337 
8339  {
8340  sig=-1;
8341  }
8342 
8343  sound_h(int n_gs_idx, int n_sig) : sound_entry_h(n_gs_idx)
8344  {
8345  sig=n_sig;
8346  }
8347 
8349  {
8350  if (!IsValid())
8351  return -1;
8352 
8353  return sig;
8354  }
8355 
8357  {
8358  if(sig < 0 || ds_get_channel(sig) < 0)
8359  return false;
8360 
8361  return true;
8362  }
8363 
8364  bool IsValid()
8365  {
8366  if(!sound_entry_h::IsValid())
8367  return false;
8368 
8369  if(sig < 0 || ds_get_channel(sig) < 0)
8370  return false;
8371 
8372  return true;
8373  }
8374 };
8375 
8376 ade_obj<sound_h> l_Sound("sound", "sound instance handle");
8377 
8378 ADE_VIRTVAR(Pitch, l_Sound, "number", "Pitch of sound, from 100 to 100000", "number", "Pitch, or 0 if handle is invalid")
8379 {
8380  sound_h *sh;
8381  int newpitch = 100;
8382  if(!ade_get_args(L, "o|i", l_Sound.GetPtr(&sh), &newpitch))
8383  return ade_set_error(L, "f", 0.0f);
8384 
8385  if (!sh->IsSoundValid())
8386  return ade_set_error(L, "f", 0.0f);
8387 
8388  if(ADE_SETTING_VAR)
8389  {
8390  if(newpitch < 100)
8391  newpitch = 100;
8392  if(newpitch > 100000)
8393  newpitch = 100000;
8394 
8395  snd_set_pitch(sh->sig, newpitch);
8396  }
8397 
8398  return ade_set_args(L, "f", snd_get_pitch(sh->sig));
8399 }
8400 
8401 ADE_FUNC(getRemainingTime, l_Sound, NULL, "The remaining time of this sound handle", "number", "Remaining time, or -1 on error")
8402 {
8403  sound_h *sh;
8404  if(!ade_get_args(L, "o", l_Sound.GetPtr(&sh)))
8405  return ade_set_error(L, "f", -1.0f);
8406 
8407  if (!sh->IsSoundValid())
8408  return ade_set_error(L, "f", -1.0f);
8409 
8410  int remaining = snd_time_remaining(sh->getSignature());
8411 
8412  return ade_set_args(L, "f", i2fl(remaining) / 1000.0f);
8413 }
8414 
8415 ADE_FUNC(setVolume, l_Sound, "number", "Sets the volume of this sound instance", "boolean", "true if succeeded, false otherwise")
8416 {
8417  sound_h *sh;
8418  float newVol = -1.0f;
8419  if(!ade_get_args(L, "of", l_Sound.GetPtr(&sh), &newVol))
8420  return ADE_RETURN_FALSE;
8421 
8422  if (!sh->IsSoundValid())
8423  return ADE_RETURN_FALSE;
8424 
8425  CAP(newVol, 0.0f, 1.0f);
8426 
8427  snd_set_volume(sh->getSignature(), newVol);
8428 
8429  return ADE_RETURN_TRUE;
8430 }
8431 
8432 ADE_FUNC(setPanning, l_Sound, "number", "Sets the panning of this sound. Argument ranges from -1 for left to 1 for right", "boolean", "true if succeeded, false otherwise")
8433 {
8434  sound_h *sh;
8435  float newPan = -1.0f;
8436  if(!ade_get_args(L, "of", l_Sound.GetPtr(&sh), &newPan))
8437  return ADE_RETURN_FALSE;
8438 
8439  if (!sh->IsSoundValid())
8440  return ADE_RETURN_FALSE;
8441 
8442  CAP(newPan, -1.0f, 1.0f);
8443 
8444  snd_set_pan(sh->getSignature(), newPan);
8445 
8446  return ADE_RETURN_TRUE;
8447 }
8448 
8449 
8450 ADE_FUNC(setPosition, l_Sound, "number[,boolean = true]",
8451  "Sets the absolute position of the sound. If boolean argument is true then the value is given as a percentage<br>"
8452  "This operation fails if there is no backing soundentry!",
8453  "boolean", "true if successfull, false otherwise")
8454 {
8455  sound_h *sh;
8456  float val = -1.0f;
8457  bool percent = true;
8458  if(!ade_get_args(L, "of|b", l_Sound.GetPtr(&sh), &val, &percent))
8459  return ADE_RETURN_FALSE;
8460 
8461  if (!sh->IsValid())
8462  return ADE_RETURN_FALSE;
8463 
8464  if (val <= 0.0f)
8465  return ADE_RETURN_FALSE;
8466 
8467  snd_set_pos(sh->getSignature(), sh->Get(), val, percent);
8468 
8469  return ADE_RETURN_TRUE;
8470 }
8471 
8472 ADE_FUNC(rewind, l_Sound, "number", "Rewinds the sound by the given number of seconds<br>"
8473  "This operation fails if there is no backing soundentry!", "boolean", "true if succeeded, false otherwise")
8474 {
8475  sound_h *sh;
8476  float val = -1.0f;
8477  if(!ade_get_args(L, "of", l_Sound.GetPtr(&sh), &val))
8478  return ADE_RETURN_FALSE;
8479 
8480  if (!sh->IsValid())
8481  return ADE_RETURN_FALSE;
8482 
8483  if (val <= 0.0f)
8484  return ADE_RETURN_FALSE;
8485 
8486  snd_rewind(sh->getSignature(), sh->Get(), val);
8487 
8488  return ADE_RETURN_TRUE;
8489 }
8490 
8491 ADE_FUNC(skip, l_Sound, "number", "Skips the given number of seconds of the sound<br>"
8492  "This operation fails if there is no backing soundentry!", "boolean", "true if succeeded, false otherwise")
8493 {
8494  sound_h *sh;
8495  float val = -1.0f;
8496  if(!ade_get_args(L, "of", l_Sound.GetPtr(&sh), &val))
8497  return ADE_RETURN_FALSE;
8498 
8499  if (!sh->IsValid())
8500  return ADE_RETURN_FALSE;
8501 
8502  if (val <= 0.0f)
8503  return ADE_RETURN_FALSE;
8504 
8505  snd_ffwd(sh->getSignature(), sh->Get(), val);
8506 
8507  return ADE_RETURN_TRUE;
8508 }
8509 
8510 ADE_FUNC(isPlaying, l_Sound, NULL, "Specifies if this handle is currently playing", "boolean", "true if playing, false if otherwise")
8511 {
8512  sound_h *sh;
8513  if(!ade_get_args(L, "o", l_Sound.GetPtr(&sh)))
8514  return ade_set_error(L, "b", false);
8515 
8516  if (!sh->IsSoundValid())
8517  return ade_set_error(L, "b", false);
8518 
8519  return ade_set_args(L, "b", snd_is_playing(sh->getSignature()) == 1);
8520 }
8521 
8522 ADE_FUNC(stop, l_Sound, NULL, "Stops the sound of this handle", "boolean", "true if succeeded, false otherwise")
8523 {
8524  sound_h *sh;
8525  if(!ade_get_args(L, "o", l_Sound.GetPtr(&sh)))
8526  return ade_set_error(L, "b", false);
8527 
8528  if (!sh->IsSoundValid())
8529  return ade_set_error(L, "b", false);
8530 
8531  snd_stop(sh->getSignature());
8532 
8533  return ADE_RETURN_TRUE;
8534 }
8535 
8536 ADE_FUNC(isValid, l_Sound, NULL, "Detects whether the whole handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
8537 {
8538  sound_h *sh;
8539  if(!ade_get_args(L, "o", l_Sound.GetPtr(&sh)))
8540  return ADE_RETURN_NIL;
8541 
8542  return ade_set_args(L, "b", sh->IsValid());
8543 }
8544 
8545 ADE_FUNC(isSoundValid, l_Sound, NULL, "Checks if only the sound is valid, should be used for non soundentry sounds",
8546  "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
8547 {
8548  sound_h *sh;
8549  if(!ade_get_args(L, "o", l_Sound.GetPtr(&sh)))
8550  return ADE_RETURN_NIL;
8551 
8552  return ade_set_args(L, "b", sh->IsSoundValid());
8553 }
8554 
8555 ade_obj<sound_h> l_Sound3D("3Dsound", "3D sound instance handle", &l_Sound);
8556 
8557 ADE_FUNC(updatePosition, l_Sound3D, "vector Position[, number radius = 0.0]", "Updates the given 3D sound with the specified position and an optional range value", "boolean", "true if succeesed, false otherwise")
8558 {
8559  sound_h *sh;
8560  vec3d *newPos = NULL;
8561  float radius = 0.0f;
8562 
8563  if(!ade_get_args(L, "oo|f", l_Sound.GetPtr(&sh), l_Vector.GetPtr(&newPos), &radius))
8564  return ade_set_error(L, "b", false);
8565 
8566  if (!sh->IsValid() || newPos == NULL)
8567  return ade_set_error(L, "b", false);
8568 
8569  snd_update_3d_pos(sh->getSignature(), sh->Get(), newPos, radius);
8570 
8571  return ADE_RETURN_TRUE;
8572 }
8573 
8574 //**********HANDLE: Soundfile
8575 ade_obj<int> l_Soundfile("soundfile", "Handle to a sound file");
8576 
8577 ADE_VIRTVAR(Duration, l_Soundfile, "number", "The duration of the sound file, in seconds", "number", "The duration or -1 on error")
8578 {
8579  int snd_idx = -1;
8580 
8581  if (!ade_get_args(L, "o", l_Soundfile.Get(&snd_idx)))
8582  return ade_set_error(L, "f", -1.0f);
8583 
8584  if (snd_idx < 0)
8585  return ade_set_error(L, "f", -1.0f);
8586 
8587  int duration = snd_get_duration(snd_idx);
8588 
8589  return ade_set_args(L, "f", i2fl(duration) / 1000.0f);
8590 }
8591 
8592 ADE_VIRTVAR(Filename, l_Soundfile, "string", "The filename of the file", "string", "The file name or empty string on error")
8593 {
8594  int snd_idx = -1;
8595 
8596  if (!ade_get_args(L, "o", l_Soundfile.Get(&snd_idx)))
8597  return ade_set_error(L, "s", "");
8598 
8599  if (snd_idx < 0)
8600  return ade_set_error(L, "s", "");
8601 
8602  const char* filename = snd_get_filename(snd_idx);
8603 
8604  return ade_set_args(L, "s", filename);
8605 }
8606 
8607 
8608 ADE_FUNC(play, l_Soundfile, "[number volume = 1.0[, number panning = 0.0]]", "Plays the sound", "sound", "A sound handle or invalid handle on error")
8609 {
8610  int snd_idx = -1;
8611  float volume = 1.0f;
8612  float panning = 0.0f;
8613 
8614  if (!ade_get_args(L, "o|ff", l_Soundfile.Get(&snd_idx)))
8615  return ade_set_error(L, "o", l_Sound.Set(sound_h()));
8616 
8617  if (snd_idx < 0)
8618  return ade_set_error(L, "o", l_Sound.Set(sound_h()));
8619 
8620  if (volume < 0.0f)
8621  {
8622  LuaError(L, "Invalid volume value of %f specified!", volume);
8623  return ade_set_error(L, "o", l_Sound.Set(sound_h()));
8624  }
8625 
8626  int handle = snd_play_raw(snd_idx, panning, volume);
8627 
8628  return ade_set_args(L, "o", l_Sound.Set(sound_h(-1, handle)));
8629 }
8630 
8631 ADE_FUNC(isValid, l_Soundfile, NULL, "Checks if the soundfile handle is valid", "boolean", "true if valid, false otherwise")
8632 {
8633  int idx = -1;
8634  if (!ade_get_args(L, "o", l_Soundfile.Get(&idx)))
8635  return ADE_RETURN_FALSE;
8636 
8637  return ade_set_args(L, "b", idx >= 0);
8638 }
8639 
8640 //**********HANDLE: Persona
8641 ade_obj<int> l_Persona("persona", "Persona handle");
8642 
8643 ADE_VIRTVAR(Name, l_Persona, "string", "The name of the persona", "string", "The name or empty string on error")
8644 {
8645  int idx = -1;
8646 
8647  if (!ade_get_args(L, "o", l_Persona.Get(&idx)))
8648  return ade_set_error(L, "s", "");
8649 
8650  if (Personas == NULL)
8651  return ade_set_error(L, "s", "");
8652 
8653  if (idx < 0 || idx >= Num_personas)
8654  return ade_set_error(L, "s", "");
8655 
8656  return ade_set_args(L, "s", Personas[idx].name);
8657 }
8658 
8659 ADE_FUNC(isValid, l_Persona, NULL, "Detect if the handle is valid", "boolean", "true if valid, false otherwise")
8660 {
8661  int idx = -1;
8662 
8663  if (!ade_get_args(L, "o", l_Persona.Get(&idx)))
8664  return ADE_RETURN_FALSE;
8665 
8666  return ade_set_args(L, "b", idx >= 0 && idx < Num_personas);
8667 }
8668 
8669 //**********HANDLE: Message
8670 ade_obj<int> l_Message("message", "Handle to a mission message");
8671 
8672 ADE_VIRTVAR(Name, l_Message, "string", "The name of the message as specified in the mission file", "string", "The name or an empty string if handle is invalid")
8673 {
8674  int idx = -1;
8675  if (!ade_get_args(L, "o", l_Message.Get(&idx)))
8676  return ade_set_error(L, "s", "");
8677 
8678  if (idx < 0 && idx >= (int) Messages.size())
8679  return ade_set_error(L, "s", "");
8680 
8681  return ade_set_args(L, "s", Messages[idx].name);
8682 }
8683 
8684 ADE_VIRTVAR(Message, l_Message, "string", "The unaltered text of the message, see getMessage() for options to replace variables<br>"
8685  "<b>NOTE:</b> Changing the text will also change the text for messages not yet played but already in the message queue!",
8686  "string", "The message or an empty string if handle is invalid")
8687 {
8688  int idx = -1;
8689  char* newText = NULL;
8690  if (!ade_get_args(L, "o|s", l_Message.Get(&idx), &newText))
8691  return ade_set_error(L, "s", "");
8692 
8693  if (idx < 0 && idx >= (int) Messages.size())
8694  return ade_set_error(L, "s", "");
8695 
8696  if (ADE_SETTING_VAR && newText != NULL)
8697  {
8698  if (strlen(newText) > MESSAGE_LENGTH)
8699  LuaError(L, "New message text is too long, maximum is %d!", MESSAGE_LENGTH);
8700  else
8701  strcpy_s(Messages[idx].message, newText);
8702  }
8703 
8704  return ade_set_args(L, "s", Messages[idx].message);
8705 }
8706 
8707 // from mission/missionmessage.cpp
8708 extern int add_wave( const char *wave_name );
8709 ADE_VIRTVAR(VoiceFile, l_Message, "soundfile", "The voice file of the message", "soundfile", "The voice file handle or invalid handle when not present")
8710 {
8711  int idx = -1;
8712  int sndIdx = -1;
8713 
8714  if (!ade_get_args(L, "o|o", l_Message.Get(&idx), l_Soundfile.Get(&sndIdx)))
8715  return ade_set_error(L, "o", l_Soundfile.Set(-1));
8716 
8717  if (idx < 0 && idx >= (int) Messages.size())
8718  return ade_set_error(L, "o", l_Soundfile.Set(-1));
8719 
8720  MissionMessage* msg = &Messages[idx];
8721 
8722  if (ADE_SETTING_VAR)
8723  {
8724  if (sndIdx >= 0)
8725  {
8726  const char* newFilename = snd_get_filename(sndIdx);
8727 
8728  msg->wave_info.index = add_wave(newFilename);
8729  }
8730  else
8731  {
8732  msg->wave_info.index = -1;
8733  }
8734  }
8735 
8736  if (msg->wave_info.index < 0)
8737  {
8738  return ade_set_args(L, "o", l_Soundfile.Set(-1));
8739  }
8740  else
8741  {
8742  int index = msg->wave_info.index;
8743  // Load the sound before using it
8744  message_load_wave(index, Message_waves[index].name);
8745 
8746  return ade_set_args(L, "o", l_Soundfile.Set(Message_waves[index].num));
8747  }
8748 }
8749 
8750 ADE_VIRTVAR(Persona, l_Message, "persona", "The persona of the message", "persona", "The persona handle or invalid handle if not present")
8751 {
8752  int idx = -1;
8753  int newPersona = -1;
8754 
8755  if (!ade_get_args(L, "o|o", l_Message.Get(&idx), l_Persona.Get(&newPersona)))
8756  return ade_set_error(L, "o", l_Soundfile.Set(-1));
8757 
8758  if (idx < 0 && idx >= (int) Messages.size())
8759  return ade_set_error(L, "o", l_Soundfile.Set(-1));
8760 
8761  if (ADE_SETTING_VAR && newPersona >= 0 && newPersona < Num_personas)
8762  {
8763  Messages[idx].persona_index = newPersona;
8764  }
8765 
8766  return ade_set_args(L, "o", l_Persona.Set(Messages[idx].persona_index));
8767 }
8768 
8769 ADE_FUNC(getMessage, l_Message, "[boolean replaceVars = true]", "Gets the text of the message and optionally replaces SEXP variables with their respective values.", "string", "The message or an empty string if handle is invalid")
8770 {
8771  int idx = -1;
8772  bool replace = true;
8773  if (!ade_get_args(L, "o|b", l_Message.Get(&idx), &replace))
8774  return ade_set_error(L, "s", "");
8775 
8776  if (idx < 0 && idx >= (int) Messages.size())
8777  return ade_set_error(L, "s", "");
8778 
8779  if (!replace)
8780  return ade_set_args(L, "s", Messages[idx].message);
8781  else
8782  {
8783  char temp_buf[MESSAGE_LENGTH];
8784  strcpy_s(temp_buf, Messages[idx].message);
8785 
8787 
8788  return ade_set_args(L, "s", temp_buf);
8789  }
8790 }
8791 
8792 ADE_FUNC(isValid, l_Message, NULL, "Checks if the message handle is valid", "boolean", "true if valid, false otherwise")
8793 {
8794  int idx = -1;
8795  if (!ade_get_args(L, "o", l_Message.Get(&idx)))
8796  return ADE_RETURN_FALSE;
8797 
8798  return ade_set_args(L, "b", idx >= 0 && idx < (int) Messages.size());
8799 }
8800 
8801 //**********HANDLE: Wing
8802 ade_obj<int> l_Wing("wing", "Wing handle");
8803 
8804 ADE_INDEXER(l_Wing, "number Index", "Array of ships in the wing", "ship", "Ship handle, or invalid ship handle if index is invalid or wing handle is invalid")
8805 {
8806  int wdx;
8807  int sdx;
8808  object_h *ndx=NULL;
8809  if(!ade_get_args(L, "oi|o", l_Wing.Get(&wdx), &sdx, l_Ship.GetPtr(&ndx)))
8810  return ade_set_error(L, "o", l_Ship.Set(object_h()));
8811 
8812  if(wdx < 0 || wdx >= Num_wings || sdx < 1 || sdx > Wings[wdx].current_count) {
8813  return ade_set_error(L, "o", l_Ship.Set(object_h()));
8814  }
8815 
8816  //Lua-->FS2
8817  sdx--;
8818 
8819  if(ADE_SETTING_VAR && ndx != NULL && ndx->IsValid()) {
8820  Wings[wdx].ship_index[sdx] = ndx->objp->instance;
8821  }
8822 
8823  return ade_set_args(L, "o", l_Ship.Set(object_h(&Objects[Ships[Wings[wdx].ship_index[sdx]].objnum])));
8824 }
8825 
8826 ADE_FUNC(__len, l_Wing, NULL, "Gets the number of ships in the wing", "number", "Number of ships in wing, or 0 if invalid handle")
8827 {
8828  int wdx;
8829  if(!ade_get_args(L, "o", l_Wing.Get(&wdx)) || wdx < 0 || wdx >= Num_wings)
8830  return ade_set_error(L, "i", 0);
8831 
8832  return ade_set_args(L, "i", Wings[wdx].current_count);
8833 }
8834 
8835 ADE_VIRTVAR(Name, l_Wing, "string", "Name of Wing", "string", "Wing name, or empty string if handle is invalid")
8836 {
8837  int wdx;
8838  char *s = NULL;
8839  if ( !ade_get_args(L, "o|s", l_Wing.Get(&wdx), &s) || wdx < 0 || wdx >= Num_wings )
8840  return ade_set_error(L, "s", "");
8841 
8842  if(ADE_SETTING_VAR && s != NULL) {
8843  strncpy(Wings[wdx].name, s, sizeof(Wings[wdx].name)-1);
8844  }
8845 
8846  return ade_set_args(L, "s", Wings[wdx].name);
8847 }
8848 
8849 ADE_FUNC(isValid, l_Wing, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
8850 {
8851  int idx;
8852  if(!ade_get_args(L, "o", l_Wing.Get(&idx)))
8853  return ADE_RETURN_NIL;
8854 
8855  if (idx < 0 || idx >= Num_wings)
8856  return ADE_RETURN_FALSE;
8857 
8858  return ADE_RETURN_TRUE;
8859 }
8860 
8861 //**********HANDLE: Ship
8862 ade_obj<object_h> l_Ship("ship", "Ship handle", &l_Object);
8863 
8864 ADE_INDEXER(l_Ship, "string Name/number Index", "Array of ship subsystems", "subsystem", "Subsystem handle, or invalid subsystem handle if index or ship handle is invalid")
8865 {
8866  object_h *objh;
8867  char *s = NULL;
8868  ship_subsys_h *sub = nullptr;
8869  if(!ade_get_args(L, "o|so", l_Ship.GetPtr(&objh), &s, l_Subsystem.GetPtr(&sub)))
8870  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
8871 
8872  if(!objh->IsValid())
8873  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
8874 
8875  ship *shipp = &Ships[objh->objp->instance];
8876  ship_subsys *ss = ship_get_subsys(shipp, s);
8877 
8878  if(ss == NULL)
8879  {
8880  int idx = atoi(s);
8881  if(idx > 0 && idx <= ship_get_num_subsys(shipp))
8882  {
8883  idx--; //Lua->FS2
8884  ss = ship_get_indexed_subsys(shipp, idx);
8885  }
8886  }
8887 
8888  if(ss == NULL)
8889  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
8890 
8891  return ade_set_args(L, "o", l_Subsystem.Set(ship_subsys_h(objh->objp, ss)));
8892 }
8893 
8894 ADE_FUNC(__len, l_Ship, NULL, "Number of subsystems on ship", "number", "Subsystem number, or 0 if handle is invalid")
8895 {
8896  object_h *objh;
8897  if(!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
8898  return ade_set_error(L, "i", 0);
8899 
8900  if(!objh->IsValid())
8901  return ade_set_error(L, "i", 0);
8902 
8903  return ade_set_args(L, "i", ship_get_num_subsys(&Ships[objh->objp->instance]));
8904 }
8905 
8906 ADE_VIRTVAR(ShieldArmorClass, l_Ship, "string", "Current Armor class of the ships' shield", "string", "Armor class name, or empty string if none is set")
8907 {
8908  object_h *objh;
8909  char *s = NULL;
8910  char *name = NULL;
8911 
8912  if(!ade_get_args(L, "o|s", l_Ship.GetPtr(&objh), &s))
8913  return ade_set_error(L, "s", "");
8914 
8915  if(!objh->IsValid())
8916  return ade_set_error(L, "s", "");
8917 
8918  ship *shipp = &Ships[objh->objp->instance];
8919  int atindex = -1;
8920  if (ADE_SETTING_VAR && s != NULL) {
8921  atindex = armor_type_get_idx(s);
8922  shipp->shield_armor_type_idx = atindex;
8923  }
8924 
8925  if (atindex != -1)
8926  name = Armor_types[atindex].GetNamePtr();
8927  else
8928  name = "";
8929 
8930  return ade_set_args(L, "s", name);
8931 }
8932 
8933 ADE_VIRTVAR(ArmorClass, l_Ship, "string", "Current Armor class", "string", "Armor class name, or empty string if none is set")
8934 {
8935  object_h *objh;
8936  char *s = NULL;
8937  char *name = NULL;
8938 
8939  if(!ade_get_args(L, "o|s", l_Ship.GetPtr(&objh), &s))
8940  return ade_set_error(L, "s", "");
8941 
8942  if(!objh->IsValid())
8943  return ade_set_error(L, "s", "");
8944 
8945  ship *shipp = &Ships[objh->objp->instance];
8946  int atindex = -1;
8947  if (ADE_SETTING_VAR && s != NULL) {
8948  atindex = armor_type_get_idx(s);
8949  shipp->armor_type_idx = atindex;
8950  }
8951 
8952  if (atindex != -1)
8953  name = Armor_types[atindex].GetNamePtr();
8954  else
8955  name = "";
8956 
8957  return ade_set_args(L, "s", name);
8958 }
8959 
8960 ADE_VIRTVAR(Name, l_Ship, "string", "Ship name", "string", "Ship name, or empty string if handle is invalid")
8961 {
8962  object_h *objh;
8963  char *s = NULL;
8964  if(!ade_get_args(L, "o|s", l_Ship.GetPtr(&objh), &s))
8965  return ade_set_error(L, "s", "");
8966 
8967  if(!objh->IsValid())
8968  return ade_set_error(L, "s", "");
8969 
8970  ship *shipp = &Ships[objh->objp->instance];
8971 
8972  if(ADE_SETTING_VAR && s != NULL) {
8973  strncpy(shipp->ship_name, s, sizeof(shipp->ship_name)-1);
8974  }
8975 
8976  return ade_set_args(L, "s", shipp->ship_name);
8977 }
8978 
8979 ADE_VIRTVAR(AfterburnerFuelLeft, l_Ship, "number", "Afterburner fuel left", "number", "Afterburner fuel left, or 0 if handle is invalid")
8980 {
8981  object_h *objh;
8982  float fuel = -1.0f;
8983  if(!ade_get_args(L, "o|f", l_Ship.GetPtr(&objh), &fuel))
8984  return ade_set_error(L, "f", 0.0f);
8985 
8986  if(!objh->IsValid())
8987  return ade_set_error(L, "f", 0.0f);
8988 
8989  ship *shipp = &Ships[objh->objp->instance];
8990 
8991  if(ADE_SETTING_VAR && fuel >= 0.0f)
8992  shipp->afterburner_fuel = fuel;
8993 
8994  return ade_set_args(L, "f", shipp->afterburner_fuel);
8995 }
8996 
8997 ADE_VIRTVAR(AfterburnerFuelMax, l_Ship, "number", "Afterburner fuel capacity", "number", "Afterburner fuel capacity, or 0 if handle is invalid")
8998 {
8999  object_h *objh;
9000  float fuel = -1.0f;
9001  if(!ade_get_args(L, "o|f", l_Ship.GetPtr(&objh), &fuel))
9002  return ade_set_error(L, "f", 0.0f);
9003 
9004  if(!objh->IsValid())
9005  return ade_set_error(L, "f", 0.0f);
9006 
9008 
9009  if(ADE_SETTING_VAR && fuel >= 0.0f)
9010  sip->afterburner_fuel_capacity = fuel;
9011 
9012  return ade_set_args(L, "f", sip->afterburner_fuel_capacity);
9013 }
9014 
9015 ADE_VIRTVAR(Class, l_Ship, "shipclass", "Ship class", "shipclass", "Ship class, or invalid shipclass handle if ship handle is invalid")
9016 {
9017  object_h *objh;
9018  int idx=-1;
9019  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&objh), l_Shipclass.Get(&idx)))
9020  return ade_set_error(L, "o", l_Shipclass.Set(-1));
9021 
9022  if(!objh->IsValid())
9023  return ade_set_error(L, "o", l_Shipclass.Set(-1));
9024 
9025  ship *shipp = &Ships[objh->objp->instance];
9026 
9027  if(ADE_SETTING_VAR && idx > -1) {
9028  change_ship_type(objh->objp->instance, idx, 1);
9029  if (shipp == Player_ship) {
9030  set_current_hud();
9031  }
9032  }
9033 
9034  if(shipp->ship_info_index < 0)
9035  return ade_set_error(L, "o", l_Shipclass.Set(-1));
9036 
9037  return ade_set_args(L, "o", l_Shipclass.Set(shipp->ship_info_index));
9038 }
9039 
9040 ADE_VIRTVAR(CountermeasuresLeft, l_Ship, "number", "Number of countermeasures left", "number", "Countermeasures left, or 0 if ship handle is invalid")
9041 {
9042  object_h *objh;
9043  int newcm = -1;
9044  if(!ade_get_args(L, "o|i", l_Ship.GetPtr(&objh), &newcm))
9045  return ade_set_error(L, "i", 0);
9046 
9047  if(!objh->IsValid())
9048  return ade_set_error(L, "i", 0);
9049 
9050  ship *shipp = &Ships[objh->objp->instance];
9051 
9052  if(ADE_SETTING_VAR && newcm > -1)
9053  shipp->cmeasure_count = newcm;
9054 
9055  return ade_set_args(L, "i", shipp->cmeasure_count);
9056 }
9057 
9058 ADE_VIRTVAR(CockpitDisplays, l_Ship, "displays", "An array of the cockpit displays on this ship.<br>NOTE: Only the ship of the player has these", "displays", "displays handle or invalid handle on error")
9059 {
9060  object_h *objh;
9061  cockpit_displays_h *cdh = NULL;
9062  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&objh), l_CockpitDisplays.GetPtr(&cdh)))
9063  return ade_set_error(L, "o", l_CockpitDisplays.Set(cockpit_displays_h()));
9064 
9065  if(!objh->IsValid())
9066  return ade_set_error(L, "o", l_CockpitDisplays.Set(cockpit_displays_h()));
9067 
9068  if(ADE_SETTING_VAR)
9069  {
9070  LuaError(L, "Attempted to use incomplete feature: Cockpit displays copy");
9071  }
9072 
9073  return ade_set_args(L, "o", l_CockpitDisplays.Set(cockpit_displays_h(objh->objp)));
9074 }
9075 
9076 ADE_VIRTVAR(CountermeasureClass, l_Ship, "weaponclass", "Weapon class mounted on this ship's countermeasure point", "weaponclass", "Countermeasure hardpoint weapon class, or invalid weaponclass handle if no countermeasure class or ship handle is invalid")
9077 {
9078  object_h *objh;
9079  int newcm = -1;
9080  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&objh), l_Weaponclass.Get(&newcm)))
9081  return ade_set_error(L, "o", l_Weaponclass.Set(-1));;
9082 
9083  if(!objh->IsValid())
9084  return ade_set_error(L, "o", l_Weaponclass.Set(-1));;
9085 
9086  ship *shipp = &Ships[objh->objp->instance];
9087 
9088  if(ADE_SETTING_VAR) {
9089  shipp->current_cmeasure = newcm;
9090  }
9091 
9092  if(shipp->current_cmeasure > -1)
9093  return ade_set_args(L, "o", l_Weaponclass.Set(shipp->current_cmeasure));
9094  else
9095  return ade_set_error(L, "o", l_Weaponclass.Set(-1));;
9096 }
9097 
9098 ADE_VIRTVAR(HitpointsMax, l_Ship, "number", "Total hitpoints", "number", "Ship maximum hitpoints, or 0 if handle is invalid")
9099 {
9100  object_h *objh;
9101  float newhits = -1;
9102  if(!ade_get_args(L, "o|f", l_Ship.GetPtr(&objh), &newhits))
9103  return ade_set_error(L, "f", 0.0f);
9104 
9105  if(!objh->IsValid())
9106  return ade_set_error(L, "f", 0.0f);
9107 
9108  ship *shipp = &Ships[objh->objp->instance];
9109 
9110  if(ADE_SETTING_VAR && newhits > -1)
9111  shipp->ship_max_hull_strength = newhits;
9112 
9113  return ade_set_args(L, "f", shipp->ship_max_hull_strength);
9114 }
9115 
9116 ADE_VIRTVAR(WeaponEnergyLeft, l_Ship, "number", "Current weapon energy reserves", "number", "Ship current weapon energy reserve level, or 0 if invalid")
9117 {
9118  object_h *objh;
9119  float neweng = -1;
9120  if(!ade_get_args(L, "o|f", l_Ship.GetPtr(&objh), &neweng))
9121  return ade_set_error(L, "f", 0.0f);
9122 
9123  if(!objh->IsValid())
9124  return ade_set_error(L, "f", 0.0f);
9125 
9126  ship *shipp = &Ships[objh->objp->instance];
9127 
9128  if(ADE_SETTING_VAR && neweng > -1)
9129  shipp->weapon_energy = neweng;
9130 
9131  return ade_set_args(L, "f", shipp->weapon_energy);
9132 }
9133 
9134 ADE_VIRTVAR(WeaponEnergyMax, l_Ship, "number", "Maximum weapon energy", "number", "Ship maximum weapon energy reserve level, or 0 if invalid")
9135 {
9136  object_h *objh;
9137  float neweng = -1;
9138  if(!ade_get_args(L, "o|f", l_Ship.GetPtr(&objh), &neweng))
9139  return ade_set_error(L, "f", 0.0f);
9140 
9141  if(!objh->IsValid())
9142  return ade_set_error(L, "f", 0.0f);
9143 
9145 
9146  if(ADE_SETTING_VAR && neweng > -1)
9147  sip->max_weapon_reserve = neweng;
9148 
9149  return ade_set_args(L, "f", sip->max_weapon_reserve);
9150 }
9151 
9152 ADE_VIRTVAR(AutoaimFOV, l_Ship, "number", "FOV of ship's autoaim, if any", "number", "FOV (in degrees), or 0 if ship uses no autoaim or if handle is invalid")
9153 {
9154  object_h *objh;
9155  float fov = -1;
9156  if(!ade_get_args(L, "o|f", l_Ship.GetPtr(&objh), &fov))
9157  return ade_set_error(L, "f", 0.0f);
9158 
9159  if(!objh->IsValid())
9160  return ade_set_error(L, "f", 0.0f);
9161 
9163 
9164  if(ADE_SETTING_VAR && fov >= 0.0f) {
9165  if (fov > 180.0)
9166  fov = 180.0;
9167 
9168  shipp->autoaim_fov = fov * PI / 180.0f;
9169  }
9170 
9171  return ade_set_args(L, "f", shipp->autoaim_fov * 180.0f / PI);
9172 }
9173 
9174 ADE_VIRTVAR(PrimaryTriggerDown, l_Ship, "boolean", "Determines if primary trigger is pressed or not", "boolean", "True if pressed, false if not, nil if ship handle is invalid")
9175 {
9176  object_h *objh;
9177  bool trig = false;
9178  if(!ade_get_args(L, "o|b", l_Ship.GetPtr(&objh), &trig))
9179  return ADE_RETURN_NIL;
9180 
9181  if(!objh->IsValid())
9182  return ADE_RETURN_NIL;
9183 
9184  ship *shipp = &Ships[objh->objp->instance];
9185 
9186  if(ADE_SETTING_VAR)
9187  {
9188  if(trig)
9189  shipp->flags |= SF_TRIGGER_DOWN;
9190  else
9191  shipp->flags &= ~SF_TRIGGER_DOWN;
9192  }
9193 
9194  if (shipp->flags & SF_TRIGGER_DOWN)
9195  return ADE_RETURN_TRUE;
9196  else
9197  return ADE_RETURN_FALSE;
9198 }
9199 
9200 
9201 ADE_VIRTVAR(PrimaryBanks, l_Ship, "weaponbanktype", "Array of primary weapon banks", "weaponbanktype", "Primary weapon banks, or invalid weaponbanktype handle if ship handle is invalid")
9202 {
9203  object_h *objh;
9204  ship_banktype_h *swh = nullptr;
9205  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&objh), l_WeaponBankType.GetPtr(&swh)))
9206  return ade_set_error(L, "o", l_WeaponBankType.Set(ship_banktype_h()));
9207 
9208  if(!objh->IsValid())
9209  return ade_set_error(L, "o", l_WeaponBankType.Set(ship_banktype_h()));
9210 
9211  ship_weapon *dst = &Ships[objh->objp->instance].weapons;
9212 
9213  if(ADE_SETTING_VAR && swh && swh->IsValid()) {
9215 
9218 
9222  memcpy(dst->primary_bank_ammo, src->primary_bank_ammo, sizeof(dst->primary_bank_ammo));
9223  memcpy(dst->primary_bank_capacity, src->primary_bank_capacity, sizeof(dst->primary_bank_capacity));
9226  memcpy(dst->primary_bank_weapons, src->primary_bank_weapons, sizeof(dst->primary_bank_weapons));
9227  }
9228 
9229  return ade_set_args(L, "o", l_WeaponBankType.Set(ship_banktype_h(objh->objp, dst, SWH_PRIMARY)));
9230 }
9231 
9232 ADE_VIRTVAR(SecondaryBanks, l_Ship, "weaponbanktype", "Array of secondary weapon banks", "weaponbanktype", "Secondary weapon banks, or invalid weaponbanktype handle if ship handle is invalid")
9233 {
9234  object_h *objh;
9235  ship_banktype_h *swh = nullptr;
9236  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&objh), l_WeaponBankType.GetPtr(&swh)))
9237  return ade_set_error(L, "o", l_WeaponBankType.Set(ship_banktype_h()));
9238 
9239  if(!objh->IsValid())
9240  return ade_set_error(L, "o", l_WeaponBankType.Set(ship_banktype_h()));
9241 
9242  ship_weapon *dst = &Ships[objh->objp->instance].weapons;
9243 
9244  if(ADE_SETTING_VAR && swh && swh->IsValid()) {
9246 
9249 
9253  memcpy(dst->secondary_bank_ammo, src->secondary_bank_ammo, sizeof(dst->secondary_bank_ammo));
9257  memcpy(dst->secondary_bank_weapons, src->secondary_bank_weapons, sizeof(dst->secondary_bank_weapons));
9258  memcpy(dst->secondary_next_slot, src->secondary_next_slot, sizeof(dst->secondary_next_slot));
9259  }
9260 
9261  return ade_set_args(L, "o", l_WeaponBankType.Set(ship_banktype_h(objh->objp, dst, SWH_SECONDARY)));
9262 }
9263 
9264 ADE_VIRTVAR(TertiaryBanks, l_Ship, "weaponbanktype", "Array of tertiary weapon banks", "weaponbanktype", "Tertiary weapon banks, or invalid weaponbanktype handle if ship handle is invalid")
9265 {
9266  object_h *objh;
9267  ship_banktype_h *swh = nullptr;
9268  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&objh), l_WeaponBankType.GetPtr(&swh)))
9269  return ade_set_error(L, "o", l_WeaponBankType.Set(ship_banktype_h()));
9270 
9271  if(!objh->IsValid())
9272  return ade_set_error(L, "o", l_WeaponBankType.Set(ship_banktype_h()));
9273 
9274  ship_weapon *dst = &Ships[objh->objp->instance].weapons;
9275 
9276  if(ADE_SETTING_VAR && swh && swh->IsValid()) {
9278 
9281 
9287  }
9288 
9289  return ade_set_args(L, "o", l_WeaponBankType.Set(ship_banktype_h(objh->objp, dst, SWH_TERTIARY)));
9290 }
9291 
9292 ADE_VIRTVAR(Target, l_Ship, "object", "Target of ship. Value may also be a deriviative of the 'object' class, such as 'ship'.", "object", "Target object, or invalid object handle if no target or ship handle is invalid")
9293 {
9294  object_h *objh;
9295  object_h *newh = nullptr;
9296  //WMC - Maybe use two argument return capabilities of Lua to set/return subsystem?
9297  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&objh), l_Object.GetPtr(&newh)))
9298  return ade_set_error(L, "o", l_Object.Set(object_h()));
9299 
9300  if(!objh->IsValid())
9301  return ade_set_error(L, "o", l_Object.Set(object_h()));
9302 
9303  ai_info *aip = NULL;
9304  if(Ships[objh->objp->instance].ai_index > -1)
9305  aip = &Ai_info[Ships[objh->objp->instance].ai_index];
9306  else
9307  return ade_set_error(L, "o", l_Object.Set(object_h()));
9308 
9309  if(ADE_SETTING_VAR && newh)
9310  {
9311  if(aip->target_signature != newh->sig)
9312  {
9313  if(newh->IsValid())
9314  {
9315  aip->target_objnum = OBJ_INDEX(newh->objp);
9316  aip->target_signature = newh->sig;
9317  aip->target_time = 0.0f;
9318 
9319  if (aip == Player_ai)
9320  hud_shield_hit_reset(newh->objp);
9321  }
9322  else
9323  {
9324  aip->target_objnum = -1;
9325  aip->target_signature = 0;
9326  aip->target_time = 0.0f;
9327  }
9328 
9329  set_targeted_subsys(aip, NULL, -1);
9330  }
9331  }
9332 
9333  return ade_set_object_with_breed(L, aip->target_objnum);
9334 }
9335 
9336 ADE_VIRTVAR(TargetSubsystem, l_Ship, "subsystem", "Target subsystem of ship.", "subsystem", "Target subsystem, or invalid subsystem handle if no target or ship handle is invalid")
9337 {
9338  object_h *oh;
9339  ship_subsys_h *newh = nullptr;
9340  //WMC - Maybe use two argument return capabilities of Lua to set/return subsystem?
9341  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&oh), l_Subsystem.GetPtr(&newh)))
9342  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
9343 
9344  if(!oh->IsValid())
9345  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
9346 
9347  ai_info *aip = NULL;
9348  if(Ships[oh->objp->instance].ai_index > -1)
9349  aip = &Ai_info[Ships[oh->objp->instance].ai_index];
9350  else
9351  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
9352 
9353  if(ADE_SETTING_VAR)
9354  {
9355  if(newh && newh->IsValid())
9356  {
9357  if (aip == Player_ai) {
9358  if (aip->target_signature != newh->sig)
9359  hud_shield_hit_reset(newh->objp);
9360 
9361  Ships[newh->ss->parent_objnum].last_targeted_subobject[Player_num] = newh->ss;
9362  }
9363 
9364  aip->target_objnum = OBJ_INDEX(newh->objp);
9365  aip->target_signature = newh->sig;
9366  aip->target_time = 0.0f;
9367  set_targeted_subsys(aip, newh->ss, aip->target_objnum);
9368  }
9369  else
9370  {
9371  aip->target_objnum = -1;
9372  aip->target_signature = 0;
9373  aip->target_time = 0.0f;
9374 
9375  set_targeted_subsys(aip, NULL, -1);
9376  }
9377  }
9378 
9379  return ade_set_args(L, "o", l_Subsystem.Set(ship_subsys_h(&Objects[aip->target_objnum], aip->targeted_subsys)));
9380 }
9381 
9382 ADE_VIRTVAR(Team, l_Ship, "team", "Ship's team", "team", "Ship team, or invalid team handle if ship handle is invalid")
9383 {
9384  object_h *oh=NULL;
9385  int nt=-1;
9386  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&oh), l_Team.Get(&nt)))
9387  return ade_set_error(L, "o", l_Team.Set(-1));
9388 
9389  if(!oh->IsValid())
9390  return ade_set_error(L, "o", l_Team.Set(-1));
9391 
9392  ship *shipp = &Ships[oh->objp->instance];
9393 
9394  if(ADE_SETTING_VAR && nt > -1) {
9395  shipp->team = nt;
9396  }
9397 
9398  return ade_set_args(L, "o", l_Team.Set(shipp->team));
9399 }
9400 
9401 ADE_VIRTVAR(Textures, l_Ship, "shiptextures", "Gets ship textures", "shiptextures", "Ship textures, or invalid shiptextures handle if ship handle is invalid")
9402 {
9403  object_h *sh = nullptr;
9404  object_h *dh;
9405  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&dh), l_Ship.GetPtr(&sh)))
9406  return ade_set_error(L, "o", l_ShipTextures.Set(object_h()));
9407 
9408  if(!dh->IsValid())
9409  return ade_set_error(L, "o", l_ShipTextures.Set(object_h()));
9410 
9411  if(ADE_SETTING_VAR && sh && sh->IsValid()) {
9412  ship *src = &Ships[sh->objp->instance];
9413  ship *dest = &Ships[dh->objp->instance];
9414 
9415  if (src->ship_replacement_textures != NULL)
9416  {
9417  if (dest->ship_replacement_textures == NULL)
9418  dest->ship_replacement_textures = (int *) vm_malloc(MAX_REPLACEMENT_TEXTURES * sizeof(int));
9419 
9421  }
9422  }
9423 
9424  return ade_set_args(L, "o", l_ShipTextures.Set(object_h(dh->objp)));
9425 }
9426 
9427 ADE_VIRTVAR(FlagAffectedByGravity, l_Ship, "boolean", "Checks for the \"affected-by-gravity\" flag", "boolean", "True if flag is set, false if flag is not set and nil on error")
9428 {
9429  object_h *objh=NULL;
9430  bool set = false;
9431 
9432  if (!ade_get_args(L, "o|b", l_Ship.GetPtr(&objh), &set))
9433  return ADE_RETURN_NIL;
9434 
9435  if (!objh->IsValid())
9436  return ADE_RETURN_NIL;
9437 
9438  ship *shipp = &Ships[objh->objp->instance];
9439 
9440  if(ADE_SETTING_VAR)
9441  {
9442  if(set)
9443  shipp->flags2 |= SF2_AFFECTED_BY_GRAVITY;
9444  else
9445  shipp->flags2 &= ~SF2_AFFECTED_BY_GRAVITY;
9446  }
9447 
9448  if (shipp->flags2 & SF2_AFFECTED_BY_GRAVITY)
9449  return ADE_RETURN_TRUE;
9450  else
9451  return ADE_RETURN_FALSE;
9452 }
9453 
9454 extern void ship_reset_disabled_physics(object *objp, int ship_class);
9455 ADE_VIRTVAR(Disabled, l_Ship, "boolean", "The disabled state of this ship", "boolean", "true if ship is diabled, false otherwise")
9456 {
9457  object_h *objh=NULL;
9458  bool set = false;
9459 
9460  if (!ade_get_args(L, "o|b", l_Ship.GetPtr(&objh), &set))
9461  return ADE_RETURN_FALSE;
9462 
9463  if (!objh->IsValid())
9464  return ADE_RETURN_FALSE;
9465 
9466  ship *shipp = &Ships[objh->objp->instance];
9467 
9468  if(ADE_SETTING_VAR)
9469  {
9470  if(set)
9471  {
9473  shipp->flags |= SF_DISABLED;
9474  }
9475  else
9476  {
9477  shipp->flags &= ~SF_DISABLED;
9479  }
9480  }
9481 
9482  if (shipp->flags & SF_DISABLED)
9483  return ADE_RETURN_TRUE;
9484  else
9485  return ADE_RETURN_FALSE;
9486 }
9487 
9488 ADE_VIRTVAR(Stealthed, l_Ship, "boolean", "Stealth status of this ship", "boolean", "true if stealthed, false otherwise or on error")
9489 {
9490  object_h *objh=NULL;
9491  bool stealthed = false;
9492 
9493  if (!ade_get_args(L, "o|b", l_Ship.GetPtr(&objh), &stealthed))
9494  return ADE_RETURN_FALSE;
9495 
9496  if (!objh->IsValid())
9497  return ADE_RETURN_FALSE;
9498 
9499  ship *shipp = &Ships[objh->objp->instance];
9500 
9501  if(ADE_SETTING_VAR)
9502  {
9503  if(stealthed)
9504  {
9505  shipp->flags2 &= ~SF2_STEALTH;
9506  }
9507  else
9508  {
9509  shipp->flags2 |= SF2_STEALTH;
9510  }
9511  }
9512 
9513  if (shipp->flags2 & SF2_STEALTH)
9514  return ADE_RETURN_TRUE;
9515  else
9516  return ADE_RETURN_FALSE;
9517 }
9518 
9519 ADE_VIRTVAR(HiddenFromSensors, l_Ship, "boolean", "Hidden from sensors status of this ship", "boolean", "true if invisible to hidden from sensors, false otherwise or on error")
9520 {
9521  object_h *objh=NULL;
9522  bool hidden = false;
9523 
9524  if (!ade_get_args(L, "o|b", l_Ship.GetPtr(&objh), &hidden))
9525  return ADE_RETURN_FALSE;
9526 
9527  if (!objh->IsValid())
9528  return ADE_RETURN_FALSE;
9529 
9530  ship *shipp = &Ships[objh->objp->instance];
9531 
9532  if(ADE_SETTING_VAR)
9533  {
9534  if(hidden)
9535  {
9536  shipp->flags &= ~SF_HIDDEN_FROM_SENSORS;
9537  }
9538  else
9539  {
9540  shipp->flags |= SF_HIDDEN_FROM_SENSORS;
9541  }
9542  }
9543 
9544  if (shipp->flags & SF_HIDDEN_FROM_SENSORS)
9545  return ADE_RETURN_TRUE;
9546  else
9547  return ADE_RETURN_FALSE;
9548 }
9549 
9550 ADE_VIRTVAR(Gliding, l_Ship, "boolean", "Specifies whether this ship is currently gliding or not.", "boolean", "true if gliding, false otherwise or in case of error")
9551 {
9552  object_h *objh=NULL;
9553  bool gliding = false;
9554 
9555  if (!ade_get_args(L, "o|b", l_Ship.GetPtr(&objh), &gliding))
9556  return ADE_RETURN_FALSE;
9557 
9558  if (!objh->IsValid())
9559  return ADE_RETURN_FALSE;
9560 
9561  ship *shipp = &Ships[objh->objp->instance];
9562 
9563  if(ADE_SETTING_VAR)
9564  {
9565  if (Ship_info[shipp->ship_info_index].can_glide)
9566  {
9567  object_set_gliding(&Objects[shipp->objnum], gliding, true);
9568  }
9569  }
9570 
9571  if (objh->objp->phys_info.flags & PF_GLIDING || objh->objp->phys_info.flags & PF_FORCE_GLIDE)
9572  return ADE_RETURN_TRUE;
9573  else
9574  return ADE_RETURN_FALSE;
9575 }
9576 
9577 ADE_VIRTVAR(EtsEngineIndex, l_Ship, "number", "(not implemented)", "number", "Ships ETS Engine index value, 0 to MAX_ENERGY_INDEX")
9578 {
9579  object_h *objh=NULL;
9580  int ets_idx = 0;
9581 
9582  if (!ade_get_args(L, "o|i", l_Ship.GetPtr(&objh), &ets_idx))
9583  return ade_set_error(L, "i", 0);
9584 
9585  if (!objh->IsValid())
9586  return ade_set_error(L, "i", 0);
9587 
9588  if(ADE_SETTING_VAR)
9589  LuaError(L, "Attempted to set incomplete feature: ETS Engine Index (see EtsSetIndexes)");
9590 
9591  return ade_set_args(L, "i", Ships[objh->objp->instance].engine_recharge_index);
9592 }
9593 
9594 ADE_VIRTVAR(EtsShieldIndex, l_Ship, "number", "(not implemented)", "number", "Ships ETS Shield index value, 0 to MAX_ENERGY_INDEX")
9595 {
9596  object_h *objh=NULL;
9597  int ets_idx = 0;
9598 
9599  if (!ade_get_args(L, "o|i", l_Ship.GetPtr(&objh), &ets_idx))
9600  return ade_set_error(L, "i", 0);
9601 
9602  if (!objh->IsValid())
9603  return ade_set_error(L, "i", 0);
9604 
9605  if(ADE_SETTING_VAR)
9606  LuaError(L, "Attempted to set incomplete feature: ETS Shield Index (see EtsSetIndexes)");
9607 
9608  return ade_set_args(L, "i", Ships[objh->objp->instance].shield_recharge_index);
9609 }
9610 
9611 ADE_VIRTVAR(EtsWeaponIndex, l_Ship, "number", "(not implemented)", "number", "Ships ETS Weapon index value, 0 to MAX_ENERGY_INDEX")
9612 {
9613  object_h *objh=NULL;
9614  int ets_idx = 0;
9615 
9616  if (!ade_get_args(L, "o|i", l_Ship.GetPtr(&objh), &ets_idx))
9617  return ade_set_error(L, "i", 0);
9618 
9619  if (!objh->IsValid())
9620  return ade_set_error(L, "i", 0);
9621 
9622  if(ADE_SETTING_VAR)
9623  LuaError(L, "Attempted to set incomplete feature: ETS Weapon Index (see EtsSetIndexes)");
9624 
9625  return ade_set_args(L, "i", Ships[objh->objp->instance].weapon_recharge_index);
9626 }
9627 
9628 ADE_VIRTVAR(Orders, l_Ship, "shiporders", "Array of ship orders", "shiporders", "Ship orders, or invalid handle if ship handle is invalid")
9629 {
9630  object_h *objh = NULL;
9631  object_h *newh = NULL;
9632  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&objh), l_ShipOrders.GetPtr(&newh)))
9633  return ade_set_error(L, "o", l_ShipOrders.Set(object_h()));
9634 
9635  if(!objh->IsValid())
9636  return ade_set_error(L, "o", l_ShipOrders.Set(object_h()));;
9637 
9638  if(ADE_SETTING_VAR)
9639  {
9640  LuaError(L, "Attempted to use incomplete feature: Ai orders copy. Use giveOrder instead");
9641  }
9642 
9643  return ade_set_args(L, "o", l_ShipOrders.Set(object_h(objh->objp)));
9644 }
9645 
9646 ADE_FUNC(kill, l_Ship, "[object Killer]", "Kills the ship. Set \"Killer\" to the ship you are killing to self-destruct", "boolean", "True if successful, false or nil otherwise")
9647 {
9648  object_h *victim,*killer=NULL;
9649  if(!ade_get_args(L, "o|o", l_Ship.GetPtr(&victim), l_Ship.GetPtr(&killer)))
9650  return ADE_RETURN_NIL;
9651 
9652  if(!victim->IsValid())
9653  return ADE_RETURN_NIL;
9654 
9655  if(!killer || !killer->IsValid())
9656  return ADE_RETURN_NIL;
9657 
9658  //Ripped straight from shiphit.cpp
9659  float percent_killed = -get_hull_pct(victim->objp);
9660  if (percent_killed > 1.0f){
9661  percent_killed = 1.0f;
9662  }
9663 
9664  ship_hit_kill(victim->objp, killer->objp, percent_killed, (victim->sig == killer->sig) ? 1 : 0);
9665 
9666  return ADE_RETURN_TRUE;
9667 }
9668 
9669 ADE_FUNC(addShipEffect, l_Ship, "string name, int duration (in milliseconds)", "Activates an effect for this ship. Effect names are defined in Post_processing.tbl, and need to be implemented in the main shader. This functions analogous to the ship-effect sexp. NOTE: only one effect can be active at any time, adding new effects will override effects already in progress.\n", "boolean", "Returns true if the effect was successfully added, false otherwise") {
9670  object_h *shiph;
9671  char* effect = NULL;
9672  int duration;
9673  int effect_num;
9674 
9675  if (!ade_get_args(L, "o|si", l_Ship.GetPtr(&shiph), &effect, &duration))
9676  return ade_set_error(L, "b", false);
9677 
9678  if (!shiph->IsValid())
9679  return ade_set_error(L, "b", false);
9680 
9681  effect_num = get_effect_from_name(effect);
9682  if (effect_num == -1)
9683  return ade_set_error(L, "b", false);
9684 
9685  ship* shipp = &Ships[shiph->objp->instance];
9686 
9687  shipp->shader_effect_active = true;
9688  shipp->shader_effect_num = effect_num;
9689  shipp->shader_effect_duration = duration;
9691 
9692  return ade_set_args(L, "b", true);
9693 }
9694 
9695 ADE_FUNC(hasShipExploded, l_Ship, NULL, "Checks if the ship explosion event has already happened", "number", "Returns 1 if first explosion timestamp is passed, 2 if second is passed, 0 otherwise")
9696 {
9697  object_h *shiph;
9698  if(!ade_get_args(L, "o", l_Ship.GetPtr(&shiph)))
9699  return ade_set_error(L, "i", 0);
9700 
9701  if(!shiph->IsValid())
9702  return ade_set_error(L, "i", 0);
9703 
9704  ship *shipp = &Ships[shiph->objp->instance];
9705 
9706  if (shipp->flags & SF_DYING) {
9707  if (shipp->final_death_time == 0) {
9708  return ade_set_args(L, "i", 2);
9709  }
9710  if (shipp->pre_death_explosion_happened == 1) {
9711  return ade_set_args(L, "i", 1);
9712  }
9713  return ade_set_args(L, "i", 3);
9714  }
9715 
9716  return ade_set_args(L, "i", 0);
9717 }
9718 
9719 ADE_FUNC(fireCountermeasure, l_Ship, NULL, "Launches a countermeasure from the ship", "boolean", "Whether countermeasure was launched or not")
9720 {
9721  object_h *objh;
9722  if(!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
9723  return ade_set_error(L, "b", false);
9724 
9725  if(!objh->IsValid())
9726  return ade_set_error(L, "b", false);
9727 
9728  return ade_set_args(L, "b", ship_launch_countermeasure(objh->objp));
9729 }
9730 
9731 ADE_FUNC(firePrimary, l_Ship, NULL, "Fires ship primary bank(s)", "number", "Number of primary banks fired")
9732 {
9733  object_h *objh;
9734  if(!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
9735  return ade_set_error(L, "i", 0);
9736 
9737  if(!objh->IsValid())
9738  return ade_set_error(L, "i", 0);
9739 
9740  int i = 0;
9741  i += ship_fire_primary(objh->objp, 0);
9742  i += ship_fire_primary(objh->objp, 1);
9743 
9744  return ade_set_args(L, "i", i);
9745 }
9746 
9747 ADE_FUNC(fireSecondary, l_Ship, NULL, "Fires ship secondary bank(s)", "number", "Number of secondary banks fired")
9748 {
9749  object_h *objh;
9750  if(!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
9751  return ade_set_error(L, "i", 0);
9752 
9753  if(!objh->IsValid())
9754  return ade_set_error(L, "i", 0);
9755 
9756  return ade_set_args(L, "i", ship_fire_secondary(objh->objp, 0));
9757 }
9758 
9759 ADE_FUNC(getAnimationDoneTime, l_Ship, "number Type, number Subtype", "Gets time that animation will be done", "number", "Time (seconds), or 0 if ship handle is invalid")
9760 {
9761  object_h *objh;
9762  char *s = NULL;
9763  int subtype=-1;
9764  if(!ade_get_args(L, "o|si", l_Ship.GetPtr(&objh), &s, &subtype))
9765  return ade_set_error(L, "f", 0.0f);
9766 
9767  if(!objh->IsValid())
9768  return ade_set_error(L, "f", 0.0f);
9769 
9771  if(type < 0)
9772  return ADE_RETURN_FALSE;
9773 
9774  int time_ms = model_anim_get_time_type(&Ships[objh->objp->instance], type, subtype);
9775  float time_s = (float)time_ms / 1000.0f;
9776 
9777  return ade_set_args(L, "f", time_s);
9778 }
9779 
9780 ADE_FUNC(clearOrders, l_Ship, NULL, "Clears a ship's orders list", "boolean", "True if successful, otherwise false or nil")
9781 {
9782  object_h *objh = NULL;
9783  if(!ade_get_args(L, "o", l_Object.GetPtr(&objh)))
9784  return ADE_RETURN_NIL;
9785  if(!objh->IsValid())
9786  return ade_set_error(L, "b", false);
9787 
9788  //The actual clearing of the goals
9790 
9791  return ADE_RETURN_TRUE;
9792 }
9793 
9794 ADE_FUNC(giveOrder, l_Ship, "enumeration Order, [object Target=nil, subsystem TargetSubsystem=nil, number Priority=1.0]", "Uses the goal code to execute orders", "boolean", "True if order was given, otherwise false or nil")
9795 {
9796  object_h *objh = NULL;
9797  enum_h *eh = NULL;
9798  float priority = 1.0f;
9799  object_h *tgh = NULL;
9800  ship_subsys_h *tgsh = NULL;
9801  if(!ade_get_args(L, "oo|oof", l_Object.GetPtr(&objh), l_Enum.GetPtr(&eh), l_Object.GetPtr(&tgh), l_Subsystem.GetPtr(&tgsh), &priority))
9802  return ADE_RETURN_NIL;
9803 
9804  if(!objh->IsValid() || !eh->IsValid())
9805  return ade_set_error(L, "b", false);
9806 
9807  //wtf...
9808  if(priority < 0.0f)
9809  return ade_set_error(L, "b", false);
9810 
9811  if(priority > 1.0f)
9812  priority = 1.0f;
9813 
9814  bool tgh_valid = tgh && tgh->IsValid();
9815  bool tgsh_valid = tgsh && tgsh->IsValid();
9816  int ai_mode = AI_GOAL_NONE;
9817  int ai_submode = -1234567;
9818  char *ai_shipname = NULL;
9819  switch(eh->index)
9820  {
9821  case LE_ORDER_ATTACK:
9822  {
9823  if(tgsh_valid)
9824  {
9825  ai_mode = AI_GOAL_DESTROY_SUBSYSTEM;
9826  ai_shipname = Ships[tgh->objp->instance].ship_name;
9827  ai_submode = ship_get_subsys_index( &Ships[tgsh->objp->instance], tgsh->ss->system_info->subobj_name );
9828  }
9829  else if(tgh_valid && tgh->objp->type == OBJ_WEAPON)
9830  {
9831  ai_mode = AI_GOAL_CHASE_WEAPON;
9832  ai_submode = tgh->objp->instance;
9833  }
9834  else if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9835  {
9836  ai_mode = AI_GOAL_CHASE;
9837  ai_shipname = Ships[tgh->objp->instance].ship_name;
9838  ai_submode = SM_ATTACK;
9839  }
9840  break;
9841  }
9842  case LE_ORDER_DOCK:
9843  {
9844  ai_shipname = Ships[tgh->objp->instance].ship_name;
9845  ai_mode = AI_GOAL_DOCK;
9846  ai_submode = AIS_DOCK_0;
9847  break;
9848  }
9849  case LE_ORDER_WAYPOINTS:
9850  {
9851  if(tgh_valid && tgh->objp->type == OBJ_WAYPOINT)
9852  {
9853  ai_mode = AI_GOAL_WAYPOINTS;
9855  if(wp_list != NULL)
9856  ai_shipname = wp_list->get_name();
9857  }
9858  break;
9859  }
9861  {
9862  if(tgh_valid && tgh->objp->type == OBJ_WAYPOINT)
9863  {
9864  ai_mode = AI_GOAL_WAYPOINTS_ONCE;
9866  if(wp_list != NULL)
9867  ai_shipname = wp_list->get_name();
9868  }
9869  break;
9870  }
9871  case LE_ORDER_DEPART:
9872  {
9873  ai_mode = AI_GOAL_WARP;
9874  ai_submode = -1;
9875  break;
9876  }
9877  case LE_ORDER_FORM_ON_WING:
9878  {
9879  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9880  {
9881  ai_mode = AI_GOAL_FORM_ON_WING;
9882  ai_shipname = Ships[tgh->objp->instance].ship_name;
9883  ai_submode = 0;
9884  }
9885  break;
9886  }
9887  case LE_ORDER_UNDOCK:
9888  {
9889  ai_mode = AI_GOAL_UNDOCK;
9890  ai_submode = AIS_UNDOCK_0;
9891 
9892  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9893  {
9894  ai_shipname = Ships[tgh->objp->instance].ship_name;
9895  }
9896  break;
9897  }
9898  case LE_ORDER_GUARD:
9899  {
9900  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9901  {
9902  ai_mode = AI_GOAL_GUARD;
9903  ai_submode = AIS_GUARD_PATROL;
9904  ai_shipname = Ships[tgh->objp->instance].ship_name;
9905  }
9906  break;
9907  }
9908  case LE_ORDER_DISABLE:
9909  {
9910  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9911  {
9912  ai_mode = AI_GOAL_DISABLE_SHIP;
9913  ai_submode = -SUBSYSTEM_ENGINE;
9914  ai_shipname = Ships[tgh->objp->instance].ship_name;
9915  }
9916  break;
9917  }
9918  case LE_ORDER_DISARM:
9919  {
9920  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9921  {
9922  ai_mode = AI_GOAL_DISARM_SHIP;
9923  ai_submode = -SUBSYSTEM_TURRET;
9924  ai_shipname = Ships[tgh->objp->instance].ship_name;
9925  }
9926  break;
9927  }
9928  case LE_ORDER_ATTACK_ANY:
9929  {
9930  ai_mode = AI_GOAL_CHASE_ANY;
9931  ai_submode = SM_ATTACK;
9932  break;
9933  }
9934  case LE_ORDER_IGNORE:
9935  {
9936  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9937  {
9938  ai_mode = AI_GOAL_IGNORE_NEW;
9939  ai_submode = 0;
9940  ai_shipname = Ships[tgh->objp->instance].ship_name;
9941  }
9942  break;
9943  }
9944  case LE_ORDER_EVADE:
9945  {
9946  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9947  {
9948  ai_mode = AI_GOAL_EVADE_SHIP;
9949  ai_shipname = Ships[tgh->objp->instance].ship_name;
9950  }
9951  break;
9952  }
9953  case LE_ORDER_STAY_NEAR:
9954  {
9955  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9956  {
9957  ai_mode = AI_GOAL_STAY_NEAR_SHIP;
9958  ai_shipname = Ships[tgh->objp->instance].ship_name;
9959  ai_submode = -1;
9960  }
9961  break;
9962  }
9964  {
9965  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9966  {
9967  ai_mode = AI_GOAL_KEEP_SAFE_DISTANCE;
9968  ai_shipname = Ships[tgh->objp->instance].ship_name;
9969  ai_submode = -1;
9970  }
9971  break;
9972  }
9973  case LE_ORDER_REARM:
9974  {
9975  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9976  {
9977  ai_mode = AI_GOAL_REARM_REPAIR;
9978  ai_shipname = Ships[tgh->objp->instance].ship_name;
9979  ai_submode = 0;
9980  }
9981  break;
9982  }
9983  case LE_ORDER_STAY_STILL:
9984  {
9985  ai_mode = AI_GOAL_STAY_STILL;
9986  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
9987  {
9988  ai_shipname = Ships[tgh->objp->instance].ship_name;
9989  }
9990  break;
9991  }
9992  case LE_ORDER_PLAY_DEAD:
9993  {
9994  ai_mode = AI_GOAL_PLAY_DEAD;
9995  break;
9996  }
9997  case LE_ORDER_FLY_TO:
9998  {
9999  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
10000  {
10001  ai_mode = AI_GOAL_FLY_TO_SHIP;
10002  ai_shipname = Ships[tgh->objp->instance].ship_name;
10003  ai_submode = 0;
10004  }
10005  break;
10006  }
10007  case LE_ORDER_ATTACK_WING:
10008  {
10009  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
10010  {
10011  ship *shipp = &Ships[tgh->objp->instance];
10012  if (shipp->wingnum != -1)
10013  {
10014  ai_mode = AI_GOAL_CHASE_WING;
10015  ai_shipname = Wings[shipp->wingnum].name;
10016  ai_submode = SM_ATTACK;
10017  }
10018  }
10019  break;
10020  }
10021  case LE_ORDER_GUARD_WING:
10022  {
10023  if(tgh_valid && tgh->objp->type == OBJ_SHIP)
10024  {
10025  ship *shipp = &Ships[tgh->objp->instance];
10026  if (shipp->wingnum != -1)
10027  {
10028  ai_mode = AI_GOAL_GUARD_WING;
10029  ai_shipname = Wings[shipp->wingnum].name;
10030  ai_submode = AIS_GUARD_STATIC;
10031  }
10032  }
10033 
10034  break;
10035  }
10036  }
10037 
10038  //Nothing got set!
10039  if(ai_mode == AI_GOAL_NONE)
10040  return ade_set_error(L, "b", false);
10041 
10042  //Fire off the goal
10043  ai_add_ship_goal_scripting(ai_mode, ai_submode, (int)(priority*100.0f), ai_shipname, &Ai_info[Ships[objh->objp->instance].ai_index]);
10044 
10045  return ADE_RETURN_TRUE;
10046 }
10047 
10048 ADE_FUNC(doManeuver, l_Ship, "number Duration, number Heading, number Pitch, number Bank, boolean Force Rotation, number Vertical, number Horizontal, number Forward, boolean Force Movement", "Sets ship maneuver over the defined time period", "boolean", "True if maneuver order was given, otherwise false or nil")
10049 {
10050  object_h *objh;
10051  float arr[6];
10052  bool f_rot = false, f_move = false;
10053  int t, i;
10054  if(!ade_get_args(L, "oifffbfffb", l_Ship.GetPtr(&objh), &t, &arr[0], &arr[1], &arr[2], &f_rot, &arr[3], &arr[4], &arr[5], &f_move))
10055  return ADE_RETURN_NIL;
10056 
10057  ship *shipp = &Ships[objh->objp->instance];
10058  ai_info *aip = &Ai_info[shipp->ai_index];
10059  control_info *cip = &aip->ai_override_ci;
10060 
10061  aip->ai_override_timestamp = timestamp(t);
10062  aip->ai_override_flags = 0;
10063 
10064  if (t < 2)
10065  return ADE_RETURN_FALSE;
10066 
10067  for(i = 0; i < 6; i++) {
10068  if((arr[i] < -1.0f) || (arr[i] > 1.0f))
10069  arr[i] = 0;
10070  }
10071 
10072  if(f_rot) {
10073  aip->ai_override_flags |= AIORF_FULL;
10074  cip->heading = arr[0];
10075  cip->pitch = arr[1];
10076  cip->bank = arr[2];
10077  } else {
10078  if (arr[0] != 0) {
10079  cip->heading = arr[0];
10081  }
10082  if (arr[1] != 0) {
10083  cip->pitch = arr[1];
10085  }
10086  if (arr[2] != 0) {
10087  cip->bank = arr[2];
10088  aip->ai_override_flags |= AIORF_ROLL;
10089  }
10090  }
10091  if(f_move) {
10093  cip->vertical = arr[3];
10094  cip->sideways = arr[4];
10095  cip->forward = arr[5];
10096  } else {
10097  if (arr[3] != 0) {
10098  cip->vertical = arr[3];
10099  aip->ai_override_flags |= AIORF_UP;
10100  }
10101  if (arr[4] != 0) {
10102  cip->sideways = arr[4];
10104  }
10105  if (arr[5] != 0) {
10106  cip->forward = arr[5];
10108  }
10109  }
10110  return ADE_RETURN_TRUE;
10111 }
10112 
10113 ADE_FUNC(triggerAnimation, l_Ship, "string Type, [number Subtype, boolean Forwards]",
10114  "Triggers an animation. Type is the string name of the animation type, "
10115  "Subtype is the subtype number, such as weapon bank #, and Forwards is boolean."
10116  "<br><strong>IMPORTANT: Function is in testing and should not be used with official mod releases</strong>",
10117  "boolean",
10118  "True if successful, false or nil otherwise")
10119 {
10120  object_h *objh;
10121  char *s = NULL;
10122  bool b = true;
10123  int subtype=-1;
10124  if(!ade_get_args(L, "o|sib", l_Ship.GetPtr(&objh), &s, &subtype, &b))
10125  return ADE_RETURN_NIL;
10126 
10127  if(!objh->IsValid())
10128  return ADE_RETURN_NIL;
10129 
10130  int type = model_anim_match_type(s);
10131  if(type < 0)
10132  return ADE_RETURN_FALSE;
10133 
10134  int dir = 1;
10135  if(!b)
10136  dir = -1;
10137 
10138  model_anim_start_type(&Ships[objh->objp->instance], type, subtype, dir);
10139 
10140  return ADE_RETURN_TRUE;
10141 }
10142 
10143 ADE_FUNC(warpIn, l_Ship, NULL, "Warps ship in", "boolean", "True if successful, or nil if ship handle is invalid")
10144 {
10145  object_h *objh;
10146  if(!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
10147  return ADE_RETURN_NIL;
10148 
10149  if(!objh->IsValid())
10150  return ADE_RETURN_NIL;
10151 
10152  shipfx_warpin_start(objh->objp);
10153 
10154  return ADE_RETURN_TRUE;
10155 }
10156 
10157 ADE_FUNC(warpOut, l_Ship, NULL, "Warps ship out", "boolean", "True if successful, or nil if ship handle is invalid")
10158 {
10159  object_h *objh;
10160  if(!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
10161  return ADE_RETURN_NIL;
10162 
10163  if(!objh->IsValid())
10164  return ADE_RETURN_NIL;
10165 
10166  shipfx_warpout_start(objh->objp);
10167 
10168  return ADE_RETURN_TRUE;
10169 }
10170 
10171 ADE_FUNC(canWarp, l_Ship, NULL, "Checks whether ship has a working subspace drive and is allowed to use it", "boolean", "True if successful, or nil if ship handle is invalid")
10172 {
10173  object_h *objh;
10174  if(!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
10175  return ADE_RETURN_NIL;
10176 
10177  if(!objh->IsValid())
10178  return ADE_RETURN_NIL;
10179 
10180  ship *shipp = &Ships[objh->objp->instance];
10181  if(shipp->flags & SF2_NO_SUBSPACE_DRIVE){
10182  return ADE_RETURN_FALSE;
10183  }
10184 
10185  return ADE_RETURN_TRUE;
10186 }
10187 
10188 // Aardwolf's function for finding if a ship should be drawn as blue on the radar/minimap
10189 ADE_FUNC(isWarpingIn, l_Ship, NULL, "Checks if ship is warping in", "boolean", "True if the ship is warping in, false or nil otherwise")
10190 {
10191  object_h *objh;
10192  if(!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
10193  return ADE_RETURN_NIL;
10194 
10195  if(!objh->IsValid())
10196  return ADE_RETURN_NIL;
10197 
10198  ship *shipp = &Ships[objh->objp->instance];
10199  if(shipp->flags & SF_ARRIVING_STAGE_1){
10200  return ADE_RETURN_TRUE;
10201  }
10202 
10203  return ADE_RETURN_FALSE;
10204 }
10205 
10206 ADE_FUNC(getEMP, l_Ship, NULL, "Returns the current emp effect strength acting on the object", "number", "Current EMP effect strength or NIL if object is invalid")
10207 {
10208  object_h *objh = NULL;
10209  object *obj = NULL;
10210 
10211  if (!ade_get_args(L, "o", l_Ship.GetPtr(&objh))) {
10212  return ADE_RETURN_NIL;
10213  }
10214 
10215  if(!objh->IsValid())
10216  return ADE_RETURN_NIL;
10217 
10218  obj = objh->objp;
10219 
10220  ship *shipp = &Ships[obj->instance];
10221 
10222  return ade_set_args(L, "f", shipp->emp_intensity);
10223 }
10224 
10225 ADE_FUNC(getTimeUntilExplosion, l_Ship, NULL, "Returns the time in seconds until the ship explodes", "number", "Time until explosion or -1, if invalid handle or ship isn't exploding")
10226 {
10227  object_h *objh = NULL;
10228 
10229  if (!ade_get_args(L, "o", l_Ship.GetPtr(&objh))) {
10230  return ade_set_error(L, "f", -1.0f);
10231  }
10232 
10233  if(!objh->IsValid())
10234  return ade_set_error(L, "f", -1.0f);
10235 
10236  ship *shipp = &Ships[objh->objp->instance];
10237 
10238  if (!timestamp_valid(shipp->final_death_time))
10239  {
10240  return ade_set_args(L, "f", -1.0f);
10241  }
10242 
10243  int time_until = timestamp_until(shipp->final_death_time);
10244 
10245  return ade_set_args(L, "f", (i2fl(time_until) / 1000.0f));
10246 }
10247 
10248 ADE_FUNC(getCallsign, l_Ship, NULL, "Gets the callsign of the ship in the current mission", "string", "The callsign or an empty string if the ship doesn't have a callsign or an error occurs")
10249 {
10250  object_h *objh = NULL;
10251 
10252  if (!ade_get_args(L, "o", l_Ship.GetPtr(&objh))) {
10253  return ade_set_error(L, "s", "");
10254  }
10255 
10256  if(!objh->IsValid())
10257  return ade_set_error(L, "s", "");
10258 
10259  ship *shipp = &Ships[objh->objp->instance];
10260 
10261  if (shipp->callsign_index < 0)
10262  return ade_set_args(L, "s", "");
10263 
10264  char temp_callsign[NAME_LENGTH];
10265 
10266  *temp_callsign = 0;
10267  mission_parse_lookup_callsign_index(shipp->callsign_index, temp_callsign);
10268 
10269  if (*temp_callsign)
10270  return ade_set_args(L, "s", temp_callsign);
10271  else
10272  return ade_set_args(L, "s", "");
10273 }
10274 
10275 ADE_FUNC(getAltClassName, l_Ship, NULL, "Gets the alternate class name of the ship", "string", "The alternate class name or an empty string if the ship doesn't have such a thing or an error occurs")
10276 {
10277  object_h *objh = NULL;
10278 
10279  if (!ade_get_args(L, "o", l_Ship.GetPtr(&objh))) {
10280  return ade_set_error(L, "s", "");
10281  }
10282 
10283  if(!objh->IsValid())
10284  return ade_set_error(L, "s", "");
10285 
10286  ship *shipp = &Ships[objh->objp->instance];
10287 
10288  if (shipp->alt_type_index < 0)
10289  return ade_set_args(L, "s", "");
10290 
10291  char temp[NAME_LENGTH];
10292 
10293  *temp = 0;
10295 
10296  if (*temp)
10297  return ade_set_args(L, "s", temp);
10298  else
10299  return ade_set_args(L, "s", "");
10300 }
10301 
10302 ADE_FUNC(getMaximumSpeed, l_Ship, "[number energy = 0.333]", "Gets the maximum speed of the ship with the given energy on the engines", "number", "The maximum speed or -1 on error")
10303 {
10304  object_h *objh = NULL;
10305  float energy = 0.333f;
10306 
10307  if (!ade_get_args(L, "o|f", l_Ship.GetPtr(&objh), &energy)) {
10308  return ade_set_error(L, "f", -1.0f);
10309  }
10310 
10311  if(!objh->IsValid())
10312  return ade_set_error(L, "f", -1.0f);
10313 
10314  if (energy < 0.0f || energy > 1.0f)
10315  {
10316  LuaError(L, "Invalid energy level %f! Needs to be in [0, 1].", energy);
10317 
10318  return ade_set_args(L, "f", -1.0f);
10319  }
10320  else
10321  {
10322  return ade_set_args(L, "f", ets_get_max_speed(objh->objp, energy));
10323  }
10324 }
10325 
10326 ADE_FUNC(EtsSetIndexes, l_Ship, "number Engine Index, number Shield Index, number Weapon Index",
10327  "Sets ships ETS systems to specified values",
10328  "boolean",
10329  "True if successful, false if target ships ETS was missing, or only has one system")
10330 {
10331  object_h *objh=NULL;
10332  int ets_idx[num_retail_ets_gauges] = {0};
10333 
10334  if (!ade_get_args(L, "oiii", l_Ship.GetPtr(&objh), &ets_idx[ENGINES], &ets_idx[SHIELDS], &ets_idx[WEAPONS]))
10335  return ADE_RETURN_FALSE;
10336 
10337  if (!objh->IsValid())
10338  return ADE_RETURN_FALSE;
10339 
10340  sanity_check_ets_inputs(ets_idx);
10341 
10342  int sindex = objh->objp->instance;
10343  if (validate_ship_ets_indxes(sindex, ets_idx)) {
10344  Ships[sindex].engine_recharge_index = ets_idx[ENGINES];
10345  Ships[sindex].shield_recharge_index = ets_idx[SHIELDS];
10346  Ships[sindex].weapon_recharge_index = ets_idx[WEAPONS];
10347  return ADE_RETURN_TRUE;
10348  } else {
10349  return ADE_RETURN_FALSE;
10350  }
10351 }
10352 
10353 ADE_FUNC(getWing, l_Ship, NULL, "Returns the ship's wing", "wing", "Wing handle, or invalid wing handle if ship is not part of a wing")
10354 {
10355  object_h *objh = NULL;
10356  ship *shipp = NULL;
10357 
10358  if (!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
10359  return ade_set_error(L, "o", l_Wing.Set(-1));
10360 
10361  if(!objh->IsValid())
10362  return ade_set_error(L, "o", l_Wing.Set(-1));
10363 
10364  shipp = &Ships[objh->objp->instance];
10365  return ade_set_args(L, "o", l_Wing.Set(shipp->wingnum));
10366 }
10367 
10368 //**********HANDLE: Weapon
10369 ade_obj<object_h> l_Weapon("weapon", "Weapon handle", &l_Object);
10370 
10371 ADE_VIRTVAR(Class, l_Weapon, "weaponclass", "Weapon's class", "weaponclass", "Weapon class, or invalid weaponclass handle if weapon handle is invalid")
10372 {
10373  object_h *oh=NULL;
10374  int nc=-1;
10375  if(!ade_get_args(L, "o|o", l_Weapon.GetPtr(&oh), l_Weaponclass.Get(&nc)))
10376  return ade_set_error(L, "o", l_Weaponclass.Set(-1));
10377 
10378  if(!oh->IsValid())
10379  return ade_set_error(L, "o", l_Weaponclass.Set(-1));
10380 
10381  weapon *wp = &Weapons[oh->objp->instance];
10382 
10383  if(ADE_SETTING_VAR && nc > -1) {
10384  wp->weapon_info_index = nc;
10385  }
10386 
10387  return ade_set_args(L, "o", l_Weaponclass.Set(wp->weapon_info_index));
10388 }
10389 
10390 ADE_VIRTVAR(DestroyedByWeapon, l_Weapon, "boolean", "Whether weapon was destroyed by another weapon", "boolean", "True if weapon was destroyed by another weapon, false if weapon was destroyed by another object or if weapon handle is invalid")
10391 {
10392  object_h *oh=NULL;
10393  bool b = false;
10394 
10395  int numargs = ade_get_args(L, "o|b", l_Weapon.GetPtr(&oh), &b);
10396 
10397  if(!numargs)
10398  return ade_set_error(L, "b", false);
10399 
10400  if(!oh->IsValid())
10401  return ade_set_error(L, "b", false);
10402 
10403  weapon *wp = &Weapons[oh->objp->instance];
10404 
10405  if(ADE_SETTING_VAR && numargs > 1) {
10406  if(b)
10408  else
10410  }
10411 
10412  return ade_set_args(L, "b", (wp->weapon_flags & WF_DESTROYED_BY_WEAPON) > 0);
10413 }
10414 
10415 ADE_VIRTVAR(LifeLeft, l_Weapon, "number", "Weapon life left (in seconds)", "number", "Life left (seconds) or 0 if weapon handle is invalid")
10416 {
10417  object_h *oh=NULL;
10418  float nll = -1.0f;
10419  if(!ade_get_args(L, "o|f", l_Weapon.GetPtr(&oh), &nll))
10420  return ade_set_error(L, "f", 0.0f);
10421 
10422  if(!oh->IsValid())
10423  return ade_set_error(L, "f", 0.0f);
10424 
10425  weapon *wp = &Weapons[oh->objp->instance];
10426 
10427  if(ADE_SETTING_VAR && nll >= 0.0f) {
10428  wp->lifeleft = nll;
10429  }
10430 
10431  return ade_set_args(L, "f", wp->lifeleft);
10432 }
10433 
10434 ADE_VIRTVAR(FlakDetonationRange, l_Weapon, "number", "Range at which flak will detonate (meters)", "number", "Detonation range (meters) or 0 if weapon handle is invalid")
10435 {
10436  object_h *oh=NULL;
10437  float rng = -1.0f;
10438  if(!ade_get_args(L, "o|f", l_Weapon.GetPtr(&oh), &rng))
10439  return ade_set_error(L, "f", 0.0f);
10440 
10441  if(!oh->IsValid())
10442  return ade_set_error(L, "f", 0.0f);
10443 
10444  weapon *wp = &Weapons[oh->objp->instance];
10445 
10446  if(ADE_SETTING_VAR && rng >= 0.0f) {
10447  wp->det_range = rng;
10448  }
10449 
10450  return ade_set_args(L, "f", wp->det_range);
10451 }
10452 
10453 ADE_VIRTVAR(Target, l_Weapon, "object", "Target of weapon. Value may also be a deriviative of the 'object' class, such as 'ship'.", "object", "Weapon target, or invalid object handle if weapon handle is invalid")
10454 {
10455  object_h *objh;
10456  object_h *newh = nullptr;
10457  if(!ade_get_args(L, "o|o", l_Weapon.GetPtr(&objh), l_Object.GetPtr(&newh)))
10458  return ade_set_error(L, "o", l_Object.Set(object_h()));
10459 
10460  if(!objh->IsValid())
10461  return ade_set_error(L, "o", l_Object.Set(object_h()));
10462 
10463  weapon *wp = NULL;
10464  if(objh->objp->instance > -1)
10465  wp = &Weapons[objh->objp->instance];
10466  else
10467  return ade_set_error(L, "o", l_Object.Set(object_h()));
10468 
10469  if(ADE_SETTING_VAR)
10470  {
10471  if(newh && newh->IsValid())
10472  {
10473  if(wp->target_sig != newh->sig)
10474  {
10475  weapon_set_tracking_info(OBJ_INDEX(objh->objp), objh->objp->parent, OBJ_INDEX(newh->objp), 1);
10476  }
10477  }
10478  else
10479  {
10480  weapon_set_tracking_info(OBJ_INDEX(objh->objp), objh->objp->parent, -1);
10481  }
10482  }
10483 
10484  return ade_set_object_with_breed(L, wp->target_num);
10485 }
10486 
10487 ADE_VIRTVAR(ParentTurret, l_Weapon, "subsystem", "Turret which fired this weapon.", "subsystem", "Turret subsystem handle, or an invalid handle if the weapon not fired from a turret")
10488 {
10489  object_h *objh;
10490  ship_subsys_h *newh = nullptr;
10491  if(!ade_get_args(L, "o|o", l_Weapon.GetPtr(&objh), l_Subsystem.GetPtr(&newh)))
10492  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10493 
10494  if(!objh->IsValid())
10495  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10496 
10497  weapon *wp = NULL;
10498  if(objh->objp->instance > -1)
10499  wp = &Weapons[objh->objp->instance];
10500  else
10501  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10502 
10503  if(ADE_SETTING_VAR)
10504  {
10505  if(newh && newh->IsValid())
10506  {
10507  if(wp->turret_subsys != newh->ss)
10508  {
10509  wp->turret_subsys = newh->ss;
10510  }
10511  }
10512  else
10513  {
10514  wp->turret_subsys = NULL;
10515  }
10516  }
10517 
10518  if(wp->turret_subsys == NULL)
10519  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10520  else
10522 }
10523 
10524 ADE_VIRTVAR(HomingObject, l_Weapon, "object", "Object that weapon will home in on. Value may also be a deriviative of the 'object' class, such as 'ship'", "object", "Object that weapon is homing in on, or an invalid object handle if weapon is not homing or the weapon handle is invalid")
10525 {
10526  object_h *objh;
10527  object_h *newh = nullptr;
10528  if(!ade_get_args(L, "o|o", l_Weapon.GetPtr(&objh), l_Object.GetPtr(&newh)))
10529  return ade_set_error(L, "o", l_Object.Set(object_h()));
10530 
10531  if(!objh->IsValid())
10532  return ade_set_error(L, "o", l_Object.Set(object_h()));
10533 
10534  weapon *wp = NULL;
10535  if(objh->objp->instance > -1)
10536  wp = &Weapons[objh->objp->instance];
10537  else
10538  return ade_set_error(L, "o", l_Object.Set(object_h()));
10539 
10540  if(ADE_SETTING_VAR)
10541  {
10542  if (newh && newh->IsValid())
10543  {
10544  if (wp->target_sig != newh->sig)
10545  {
10546  weapon_set_tracking_info(OBJ_INDEX(objh->objp), objh->objp->parent, OBJ_INDEX(newh->objp), 1);
10547  }
10548  }
10549  else
10550  {
10551  weapon_set_tracking_info(OBJ_INDEX(objh->objp), objh->objp->parent, -1);
10552  }
10553  }
10554 
10555  if(wp->homing_object == &obj_used_list)
10556  return ade_set_args(L, "o", l_Object.Set(object_h()));
10557  else
10559 }
10560 
10561 ADE_VIRTVAR(HomingPosition, l_Weapon, "vector", "Position that weapon will home in on (World vector), setting this without a homing object in place will not have any effect!",
10562  "vector", "Homing point, or null vector if weapon handle is invalid")
10563 {
10564  object_h *objh;
10565  vec3d *v3 = nullptr;
10566  if(!ade_get_args(L, "o|o", l_Weapon.GetPtr(&objh), l_Vector.GetPtr(&v3)))
10567  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
10568 
10569  if(!objh->IsValid())
10570  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
10571 
10572  weapon *wp = NULL;
10573  if(objh->objp->instance > -1)
10574  wp = &Weapons[objh->objp->instance];
10575  else
10576  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
10577 
10578  if(ADE_SETTING_VAR)
10579  {
10580  if(v3)
10581  {
10582  wp->homing_pos = *v3;
10583  }
10584  else
10585  {
10587  }
10588  }
10589 
10590  return ade_set_args(L, "o", l_Vector.Set(wp->homing_pos));
10591 }
10592 
10593 ADE_VIRTVAR(HomingSubsystem, l_Weapon, "subsystem", "Subsystem that weapon will home in on.", "subsystem", "Homing subsystem, or invalid subsystem handle if weapon is not homing or weapon handle is invalid")
10594 {
10595  object_h *objh;
10596  ship_subsys_h *newh = nullptr;
10597  if(!ade_get_args(L, "o|o", l_Weapon.GetPtr(&objh), l_Subsystem.GetPtr(&newh)))
10598  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10599 
10600  if(!objh->IsValid())
10601  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10602 
10603  weapon *wp = NULL;
10604  if(objh->objp->instance > -1)
10605  wp = &Weapons[objh->objp->instance];
10606  else
10607  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10608 
10609  if(ADE_SETTING_VAR)
10610  {
10611  if(newh && newh->IsValid())
10612  {
10613  if(wp->target_sig != newh->sig)
10614  {
10615  wp->homing_object = newh->objp;
10616  wp->homing_subsys = newh->ss;
10618  }
10619  }
10620  else
10621  {
10624  wp->homing_subsys = NULL;
10625  }
10626  }
10627 
10628  return ade_set_args(L, "o", l_Subsystem.Set(ship_subsys_h(wp->homing_object, wp->homing_subsys)));
10629 }
10630 
10631 ADE_VIRTVAR(Team, l_Weapon, "team", "Weapon's team", "team", "Weapon team, or invalid team handle if weapon handle is invalid")
10632 {
10633  object_h *oh=NULL;
10634  int nt=-1;
10635  if(!ade_get_args(L, "o|o", l_Weapon.GetPtr(&oh), l_Team.Get(&nt)))
10636  return ade_set_error(L, "o", l_Team.Set(-1));
10637 
10638  if(!oh->IsValid())
10639  return ade_set_error(L, "o", l_Team.Set(-1));
10640 
10641  weapon *wp = &Weapons[oh->objp->instance];
10642 
10643  if(ADE_SETTING_VAR && nt > -1 && nt < Num_teams) {
10644  wp->team = nt;
10645  }
10646 
10647  return ade_set_args(L, "o", l_Team.Set(wp->team));
10648 }
10649 
10650 ADE_FUNC(isArmed, l_Weapon, "[boolean Hit target]", "Checks if the weapon is armed.", "boolean", "boolean value of the weapon arming status")
10651 {
10652  object_h *oh = NULL;
10653  bool hit_target = false;
10654  if(!ade_get_args(L, "o|b", l_Weapon.GetPtr(&oh), &hit_target))
10655  return ADE_RETURN_FALSE;
10656 
10657  if(!oh->IsValid())
10658  return ADE_RETURN_FALSE;
10659 
10660  weapon *wp = &Weapons[oh->objp->instance];
10661 
10662  if(weapon_armed(wp, hit_target))
10663  return ADE_RETURN_TRUE;
10664 
10665  return ADE_RETURN_FALSE;
10666 }
10667 
10668 ADE_FUNC(getCollisionInformation, l_Weapon, NULL, "Returns the collision information for this weapon", "collision info", "The collision information or invalid handle if none")
10669 {
10670  object_h *oh=NULL;
10671  if(!ade_get_args(L, "o", l_Weapon.GetPtr(&oh)))
10672  return ADE_RETURN_NIL;
10673 
10674  if(!oh->IsValid())
10675  return ADE_RETURN_NIL;
10676 
10677  weapon *wp = &Weapons[oh->objp->instance];
10678 
10679  if (wp->collisionOccured)
10680  return ade_set_args(L, "o", l_ColInfo.Set(mc_info_h(new mc_info(wp->collisionInfo))));
10681  else
10682  return ade_set_args(L, "o", l_ColInfo.Set(mc_info_h()));
10683 }
10684 
10685 
10686 //**********HANDLE: Beam
10687 ade_obj<object_h> l_Beam("beam", "Beam handle", &l_Object);
10688 
10689 ADE_VIRTVAR(Class, l_Beam, "weaponclass", "Weapon's class", "weaponclass", "Weapon class, or invalid weaponclass handle if beam handle is invalid")
10690 {
10691  object_h *oh=NULL;
10692  int nc=-1;
10693  if(!ade_get_args(L, "o|o", l_Beam.GetPtr(&oh), l_Weaponclass.Get(&nc)))
10694  return ade_set_error(L, "o", l_Weaponclass.Set(-1));
10695 
10696  if(!oh->IsValid())
10697  return ade_set_error(L, "o", l_Weaponclass.Set(-1));
10698 
10699  beam *bp = &Beams[oh->objp->instance];
10700 
10701  if(ADE_SETTING_VAR && nc > -1) {
10702  bp->weapon_info_index = nc;
10703  }
10704 
10705  return ade_set_args(L, "o", l_Weaponclass.Set(bp->weapon_info_index));
10706 }
10707 
10708 ADE_VIRTVAR(LastShot, l_Beam, "vector", "End point of the beam", "vector", "vector or null vector if beam handle is not valid")
10709 {
10710  object_h *oh=NULL;
10711  vec3d *vec3 = nullptr;
10712  if(!ade_get_args(L, "o|o", l_Beam.GetPtr(&oh), l_Vector.GetPtr(&vec3)))
10713  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
10714 
10715  if(!oh->IsValid())
10716  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
10717 
10718  beam *bp = &Beams[oh->objp->instance];
10719 
10720  if(ADE_SETTING_VAR && vec3) {
10721  bp->last_shot = *vec3;
10722  }
10723 
10724  return ade_set_args(L, "o", l_Vector.Set(bp->last_shot));
10725 }
10726 
10727 ADE_VIRTVAR(LastStart, l_Beam, "vector", "Start point of the beam", "vector", "vector or null vector if beam handle is not valid")
10728 {
10729  object_h *oh=NULL;
10730  vec3d *v3 = nullptr;
10731  if(!ade_get_args(L, "o|o", l_Beam.GetPtr(&oh), l_Vector.GetPtr(&v3)))
10732  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
10733 
10734  if(!oh->IsValid())
10735  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
10736 
10737  beam *bp = &Beams[oh->objp->instance];
10738 
10739  if(ADE_SETTING_VAR && v3) {
10740  bp->last_start = *v3;
10741  }
10742 
10743  return ade_set_args(L, "o", l_Vector.Set(bp->last_start));
10744 }
10745 
10746 ADE_VIRTVAR(Target, l_Beam, "object", "Target of beam. Value may also be a deriviative of the 'object' class, such as 'ship'.", "object", "Beam target, or invalid object handle if beam handle is invalid")
10747 {
10748  object_h *objh;
10749  object_h *newh = nullptr;
10750  if(!ade_get_args(L, "o|o", l_Beam.GetPtr(&objh), l_Object.GetPtr(&newh)))
10751  return ade_set_error(L, "o", l_Object.Set(object_h()));
10752 
10753  if(!objh->IsValid())
10754  return ade_set_error(L, "o", l_Object.Set(object_h()));
10755 
10756  beam *bp = NULL;
10757  if(objh->objp->instance > -1)
10758  bp = &Beams[objh->objp->instance];
10759  else
10760  return ade_set_error(L, "o", l_Object.Set(object_h()));
10761 
10762  if(ADE_SETTING_VAR)
10763  {
10764  if(newh && newh->IsValid())
10765  {
10766  if(bp->target_sig != newh->sig)
10767  {
10768  bp->target = newh->objp;
10769  bp->target_sig = newh->sig;
10770  }
10771  }
10772  else
10773  {
10774  bp->target = NULL;
10775  bp->target_sig = 0;
10776  }
10777  }
10778 
10779  return ade_set_object_with_breed(L, OBJ_INDEX(bp->target));
10780 }
10781 
10782 ADE_VIRTVAR(TargetSubsystem, l_Beam, "subsystem", "Subsystem that beam is targeting.", "subsystem", "Target subsystem, or invalid subsystem handle if beam handle is invalid")
10783 {
10784  object_h *objh;
10785  ship_subsys_h *newh = nullptr;
10786  if(!ade_get_args(L, "o|o", l_Beam.GetPtr(&objh), l_Subsystem.GetPtr(&newh)))
10787  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10788 
10789  if(!objh->IsValid())
10790  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10791 
10792  beam *bp = NULL;
10793  if(objh->objp->instance > -1)
10794  bp = &Beams[objh->objp->instance];
10795  else
10796  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10797 
10798  if(ADE_SETTING_VAR)
10799  {
10800  if(newh && newh->IsValid())
10801  {
10802  if(bp->target_sig != newh->sig)
10803  {
10804  bp->target = newh->objp;
10805  bp->target_subsys = newh->ss;
10806  bp->target_sig = newh->sig;
10807  }
10808  }
10809  else
10810  {
10811  bp->target = NULL;
10812  bp->target_subsys = NULL;
10813  }
10814  }
10815 
10816  return ade_set_args(L, "o", l_Subsystem.Set(ship_subsys_h(bp->target, bp->target_subsys)));
10817 }
10818 
10819 ADE_VIRTVAR(ParentShip, l_Beam, "object", "Parent of the beam.", "object", "Beam parent, or invalid object handle if beam handle is invalid")
10820 {
10821  object_h *objh;
10822  object_h *newh = nullptr;
10823  if(!ade_get_args(L, "o|o", l_Beam.GetPtr(&objh), l_Object.GetPtr(&newh)))
10824  return ade_set_error(L, "o", l_Object.Set(object_h()));
10825 
10826  if(!objh->IsValid())
10827  return ade_set_error(L, "o", l_Object.Set(object_h()));
10828 
10829  beam *bp = NULL;
10830  if(objh->objp->instance > -1)
10831  bp = &Beams[objh->objp->instance];
10832  else
10833  return ade_set_error(L, "o", l_Object.Set(object_h()));
10834 
10835  if(ADE_SETTING_VAR)
10836  {
10837  if(newh && newh->IsValid())
10838  {
10839  if(bp->sig != newh->sig)
10840  {
10841  bp->objp = newh->objp;
10842  bp->sig = newh->sig;
10843  }
10844  }
10845  else
10846  {
10847  bp->objp = NULL;
10848  bp->sig = 0;
10849  }
10850  }
10851 
10852  return ade_set_object_with_breed(L, OBJ_INDEX(bp->objp));
10853 }
10854 
10855 ADE_VIRTVAR(ParentSubsystem, l_Beam, "subsystem", "Subsystem that beam is fired from.", "subsystem", "Parent subsystem, or invalid subsystem handle if beam handle is invalid")
10856 {
10857  object_h *objh;
10858  ship_subsys_h *newh = nullptr;
10859  if(!ade_get_args(L, "o|o", l_Beam.GetPtr(&objh), l_Subsystem.GetPtr(&newh)))
10860  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10861 
10862  if(!objh->IsValid())
10863  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10864 
10865  beam *bp = NULL;
10866  if(objh->objp->instance > -1)
10867  bp = &Beams[objh->objp->instance];
10868  else
10869  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
10870 
10871  if(ADE_SETTING_VAR)
10872  {
10873  if(newh && newh->IsValid())
10874  {
10875  if(bp->sig != newh->sig)
10876  {
10877  bp->objp = newh->objp;
10878  bp->subsys = newh->ss;
10879  }
10880  }
10881  else
10882  {
10883  bp->objp = NULL;
10884  bp->subsys = NULL;
10885  }
10886  }
10887 
10888  return ade_set_args(L, "o", l_Subsystem.Set(ship_subsys_h(bp->objp, bp->subsys)));
10889 }
10890 
10891 ADE_FUNC(getCollisionCount, l_Beam, NULL, "Get the number of collisions in frame.", "number", "Number of beam collisions")
10892 {
10893  object_h *objh;
10894  if(!ade_get_args(L, "o", l_Beam.GetPtr(&objh)))
10895  return ADE_RETURN_NIL;
10896 
10897  beam *bp = NULL;
10898  if(objh->objp->instance > -1)
10899  bp = &Beams[objh->objp->instance];
10900  else
10901  return ADE_RETURN_NIL;
10902 
10903  return ade_set_args(L, "i", bp->f_collision_count);
10904 }
10905 
10906 ADE_FUNC(getCollisionPosition, l_Beam, "number", "Get the position of the defined collision.", "vector", "World vector")
10907 {
10908  object_h *objh;
10909  int idx;
10910  if(!ade_get_args(L, "oi", l_Beam.GetPtr(&objh), &idx))
10911  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
10912 
10913  // convert from Lua to C
10914  idx--;
10915  if ((idx >= MAX_FRAME_COLLISIONS) || (idx < 0))
10916  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
10917 
10918  beam *bp = NULL;
10919  if(objh->objp->instance > -1)
10920  bp = &Beams[objh->objp->instance];
10921  else
10922  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
10923 
10924  // so we have valid beam and valid indexer
10925  return ade_set_args(L, "o", l_Vector.Set(bp->f_collisions[idx].cinfo.hit_point_world));
10926 }
10927 
10928 ADE_FUNC(getCollisionInformation, l_Beam, "number", "Get the collision information of the specified collision", "collision info", "handle to information or invalid handle on error")
10929 {
10930  object_h *objh;
10931  int idx;
10932  if(!ade_get_args(L, "oi", l_Beam.GetPtr(&objh), &idx))
10933  return ade_set_error(L, "o", l_ColInfo.Set(mc_info_h()));
10934 
10935  // convert from Lua to C
10936  idx--;
10937  if ((idx >= MAX_FRAME_COLLISIONS) || (idx < 0))
10938  return ade_set_error(L, "o", l_ColInfo.Set(mc_info_h()));
10939 
10940  beam *bp = NULL;
10941  if(objh->objp->instance > -1)
10942  bp = &Beams[objh->objp->instance];
10943  else
10944  return ade_set_error(L, "o", l_ColInfo.Set(mc_info_h()));
10945 
10946  // so we have valid beam and valid indexer
10947  return ade_set_args(L, "o", l_ColInfo.Set(mc_info_h(new mc_info(bp->f_collisions[idx].cinfo))));
10948 }
10949 
10950 ADE_FUNC(getCollisionObject, l_Beam, "number", "Get the target of the defined collision.", "object", "Object the beam collided with")
10951 {
10952  object_h *objh;
10953  int idx;
10954  if(!ade_get_args(L, "oi", l_Beam.GetPtr(&objh), &idx))
10955  return ade_set_error(L, "o", l_Object.Set(object_h()));
10956 
10957  // convert from Lua to C
10958  idx--;
10959  if ((idx >= MAX_FRAME_COLLISIONS) || (idx < 0))
10960  return ade_set_error(L, "o", l_Object.Set(object_h()));
10961 
10962  beam *bp = NULL;
10963  if(objh->objp->instance > -1)
10964  bp = &Beams[objh->objp->instance];
10965  else
10966  return ade_set_error(L, "o", l_Object.Set(object_h()));
10967 
10968  // so we have valid beam and valid indexer
10969  return ade_set_object_with_breed(L, bp->f_collisions[idx].c_objnum);
10970 }
10971 
10972 ADE_FUNC(isExitCollision, l_Beam, "number", "Checks if the defined collision was exit collision.", "boolean", "True if the collision was exit collision, false if entry, nil otherwise")
10973 {
10974  object_h *objh;
10975  int idx;
10976  if(!ade_get_args(L, "oi", l_Beam.GetPtr(&objh), &idx))
10977  return ADE_RETURN_NIL;
10978 
10979  // convert from Lua to C
10980  idx--;
10981  if ((idx >= MAX_FRAME_COLLISIONS) || (idx < 0))
10982  return ADE_RETURN_NIL;
10983 
10984  beam *bp = NULL;
10985  if(objh->objp->instance > -1)
10986  bp = &Beams[objh->objp->instance];
10987  else
10988  return ADE_RETURN_NIL;
10989 
10990  // so we have valid beam and valid indexer
10991  if (bp->f_collisions[idx].is_exit_collision)
10992  return ADE_RETURN_TRUE;
10993 
10994  return ADE_RETURN_FALSE;
10995 }
10996 
10997 ADE_FUNC(getStartDirectionInfo, l_Beam, NULL, "Gets the start information about the direction. The vector is a normalized vector from LastStart showing the start direction of a slashing beam", "vector", "The start direction or null vector if invalid")
10998 {
10999  object_h *objh;
11000  if(!ade_get_args(L, "o", l_Beam.GetPtr(&objh)))
11001  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11002 
11003  beam *bp = NULL;
11004  if(objh->objp->instance > -1)
11005  bp = &Beams[objh->objp->instance];
11006  else
11007  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11008 
11009  beam_info inf = bp->binfo;
11010 
11011  return ade_set_args(L, "o", l_Vector.Set(inf.dir_a));
11012 }
11013 
11014 ADE_FUNC(getEndDirectionInfo, l_Beam, NULL, "Gets the end information about the direction. The vector is a normalized vector from LastStart showing the end direction of a slashing beam", "vector", "The start direction or null vector if invalid")
11015 {
11016  object_h *objh;
11017  if(!ade_get_args(L, "o", l_Beam.GetPtr(&objh)))
11018  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11019 
11020  beam *bp = NULL;
11021  if(objh->objp->instance > -1)
11022  bp = &Beams[objh->objp->instance];
11023  else
11024  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11025 
11026  beam_info inf = bp->binfo;
11027 
11028  return ade_set_args(L, "o", l_Vector.Set(inf.dir_b));
11029 }
11030 
11031 //**********HANDLE: Player
11032 ade_obj<int> l_Player("player", "Player handle");
11033 
11034 ADE_FUNC(isValid, l_Player, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
11035 {
11036  int idx;
11037  if(!ade_get_args(L, "o", l_Player.Get(&idx)))
11038  return ADE_RETURN_NIL;
11039 
11040  if (idx < 0 || idx >= MAX_PLAYERS)
11041  return ADE_RETURN_FALSE;
11042 
11043  return ADE_RETURN_TRUE;
11044 }
11045 
11046 ADE_FUNC(getName, l_Player, NULL, "Gets current player name", "string", "Player name, or empty string if handle is invalid")
11047 {
11048  int idx;
11049  if(!ade_get_args(L, "o", l_Player.Get(&idx)))
11050  return ade_set_error(L, "s", "");
11051 
11052  if (idx < 0 || idx >= MAX_PLAYERS)
11053  return ade_set_error(L, "s", "");
11054 
11055  return ade_set_args(L, "s", Players[idx].callsign);
11056 }
11057 
11058 ADE_FUNC(getCampaignFilename, l_Player, NULL, "Gets current player campaign filename", "string", "Campaign name, or empty string if handle is invalid")
11059 {
11060  int idx;
11061  if(!ade_get_args(L, "o", l_Player.Get(&idx)))
11062  return ade_set_error(L, "s", "");
11063 
11064  if (idx < 0 || idx >= MAX_PLAYERS)
11065  return ade_set_error(L, "s", "");
11066 
11067  return ade_set_args(L, "s", Players[idx].current_campaign);
11068 }
11069 
11070 ADE_FUNC(getImageFilename, l_Player, NULL, "Gets current player image filename", "string", "Player image filename, or empty string if handle is invalid")
11071 {
11072  int idx;
11073  if(!ade_get_args(L, "o", l_Player.Get(&idx)))
11074  return ade_set_error(L, "s", "");
11075 
11076  if (idx < 0 || idx >= MAX_PLAYERS)
11077  return ade_set_error(L, "s", "");
11078 
11079  return ade_set_args(L, "s", Players[idx].image_filename);
11080 }
11081 
11082 ADE_FUNC(getMainHallName, l_Player, NULL, "Gets player's current main hall name", "string", "Main hall name, or name of first mainhall in campaign if something goes wrong")
11083 {
11084  SCP_string hallname;
11085  // FS2-->Lua
11086  if (Campaign.next_mission == -1) {
11087  hallname = Campaign.missions[0].main_hall;
11088  } else {
11090  }
11091 
11092  return ade_set_args(L, "i", hallname.c_str());
11093 }
11094 
11095 // use getMainHallName if at all possible.
11096 ADE_FUNC(getMainHallIndex, l_Player, NULL, "Gets player's current main hall number", "number", "Main hall index, or index of first mainhall in campaign if something goes wrong")
11097 {
11098  int hallnum = 0;
11099  //FS2-->Lua
11100  if (Campaign.next_mission == -1) {
11102  } else {
11104  }
11105 
11106  return ade_set_args(L, "i", hallnum);
11107 }
11108 
11109 ADE_FUNC(getSquadronName, l_Player, NULL, "Gets current player squad name", "string", "Squadron name, or empty string if handle is invalid")
11110 {
11111  int idx;
11112  if(!ade_get_args(L, "o", l_Player.Get(&idx)))
11113  return ade_set_error(L, "s", "");
11114 
11115  if (idx < 0 || idx >= MAX_PLAYERS)
11116  return ade_set_error(L, "s", "");
11117 
11118  return ade_set_args(L, "s", Players[idx].s_squad_name);
11119 }
11120 
11121 ADE_FUNC(getMultiSquadronName, l_Player, NULL, "Gets current player multi squad name", "string", "Squadron name, or empty string if handle is invalid")
11122 {
11123  int idx;
11124  if(!ade_get_args(L, "o", l_Player.Get(&idx)))
11125  return ade_set_error(L, "s", "");
11126 
11127  if (idx < 0 || idx >= MAX_PLAYERS)
11128  return ade_set_error(L, "s", "");
11129 
11130  return ade_set_args(L, "s", Players[idx].m_squad_name);
11131 }
11132 
11133 //WMC - This isn't working
11134 /*
11135 ADE_FUNC(getSquadronImage, l_Player, NULL, "Squad image (string)", "Gets current player squad image")
11136 {
11137  int idx;
11138  player_helper(L, &idx);
11139 
11140  return ade_set_args(L, "s", Players[idx].squad_filename);
11141 }*/
11142 
11143 //**********HANDLE: Camera
11144 ade_obj<camid> l_Camera("camera", "Camera handle");
11145 
11146 ADE_FUNC(__tostring, l_Camera, NULL, "Camera name", "string", "Camera name, or an empty string if handle is invalid")
11147 {
11148  camid cid;
11149  if(!ade_get_args(L, "o", l_Camera.Get(&cid)))
11150  return ade_set_error(L, "s", "");
11151 
11152  if(!cid.isValid())
11153  return ade_set_error(L, "s", "");
11154 
11155  return ade_set_args(L, "s", cid.getCamera()->get_name());
11156 }
11157 
11158 ADE_FUNC(isValid, l_Camera, NULL, "True if valid, false or nil if not", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
11159 {
11160  camid cid;
11161  if(!ade_get_args(L, "o", l_Camera.Get(&cid)))
11162  return ADE_RETURN_NIL;
11163 
11164  if(!cid.isValid())
11165  return ADE_RETURN_FALSE;
11166 
11167  return ADE_RETURN_TRUE;
11168 }
11169 
11170 ADE_VIRTVAR(Name, l_Camera, "string", "New camera name", "string", "Camera name")
11171 {
11172  camid cid;
11173  char *s = NULL;
11174  if(!ade_get_args(L, "o|s", l_Camera.Get(&cid), &s))
11175  return ade_set_error(L, "s", "");
11176 
11177  if(!cid.isValid())
11178  return ade_set_error(L, "s", "");
11179 
11180  if(ADE_SETTING_VAR && s != NULL) {
11181  cid.getCamera()->set_name(s);
11182  }
11183 
11184  return ade_set_args(L, "s", cid.getCamera()->get_name());
11185 }
11186 
11187 ADE_VIRTVAR(FOV, l_Camera, "number", "New camera FOV (in radians)", "number", "Camera FOV (in radians)")
11188 {
11189  camid cid;
11190  float f = VIEWER_ZOOM_DEFAULT;
11191  if(!ade_get_args(L, "o|f", l_Camera.Get(&cid), &f))
11192  return ade_set_error(L, "f", 0.0f);
11193 
11194  if(!cid.isValid())
11195  return ade_set_error(L, "f", 0.0f);
11196 
11197  if(ADE_SETTING_VAR) {
11198  cid.getCamera()->set_fov(f);
11199  }
11200 
11201  return ade_set_args(L, "f", cid.getCamera()->get_fov());
11202 }
11203 
11204 ADE_VIRTVAR(Orientation, l_Camera, "orientation", "New camera orientation", "orientation", "Camera orientation")
11205 {
11206  camid cid;
11207  matrix_h *mh = NULL;
11208  if(!ade_get_args(L, "o|o", l_Camera.Get(&cid), l_Matrix.GetPtr(&mh)))
11209  return ade_set_error(L, "f", 0.0f);
11210 
11211  if(!cid.isValid())
11212  return ade_set_error(L, "f", 0.0f);
11213 
11214  if(ADE_SETTING_VAR && mh != NULL) {
11215  cid.getCamera()->set_rotation(mh->GetMatrix());
11216  }
11217 
11218  matrix mtx;
11219  cid.getCamera()->get_info(NULL, &mtx);
11220  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&mtx)));
11221 }
11222 
11223 ADE_VIRTVAR(Position, l_Camera, "vector", "New camera position", "vector", "Camera position")
11224 {
11225  camid cid;
11226  vec3d *pos = NULL;
11227  if(!ade_get_args(L, "o|o", l_Camera.Get(&cid), l_Vector.GetPtr(&pos)))
11228  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11229 
11230  if(!cid.isValid())
11231  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11232 
11233  if(ADE_SETTING_VAR && pos) {
11234  cid.getCamera()->set_position(pos);
11235  }
11236 
11237  vec3d v = vmd_zero_vector;
11238  cid.getCamera()->get_info(&v, NULL);
11239  return ade_set_args(L, "o", l_Vector.Set(v));
11240 }
11241 
11242 ADE_VIRTVAR(Self, l_Camera, "object", "New mount object", "object", "Camera object")
11243 {
11244  camid cid;
11245  object_h *oh = NULL;
11246  if(!ade_get_args(L, "o|o", l_Camera.Get(&cid), l_Object.GetPtr(&oh)))
11247  return ade_set_error(L, "o", l_Object.Set(object_h()));
11248 
11249  if(!cid.isValid())
11250  return ade_set_error(L, "o", l_Object.Set(object_h()));
11251 
11252  if(ADE_SETTING_VAR && oh && oh->IsValid()) {
11253  cid.getCamera()->set_object_host(oh->objp);
11254  }
11255 
11256  return ade_set_args(L, "o", l_Object.Set(object_h(cid.getCamera()->get_object_host())));
11257 }
11258 
11259 ADE_VIRTVAR(SelfSubsystem, l_Camera, "subsystem", "New mount object subsystem", "subsystem", "Subsystem that the camera is mounted on")
11260 {
11261  camid cid;
11262  ship_subsys_h *sso = NULL;
11263  if(!ade_get_args(L, "o|o", l_Camera.Get(&cid), l_Subsystem.GetPtr(&sso)))
11264  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11265 
11266  if(!cid.isValid())
11267  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11268 
11269  if(ADE_SETTING_VAR && sso && sso->IsValid()) {
11270  cid.getCamera()->set_object_host(sso->objp, sso->ss->system_info->subobj_num);
11271  }
11272 
11273  object *objp = cid.getCamera()->get_object_host();
11274  if(objp == NULL || objp->type != OBJ_SHIP)
11275  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11276 
11277  int submodel = cid.getCamera()->get_object_host_submodel();
11278  if(submodel < 0)
11279  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11280 
11281  ship *shipp = &Ships[objp->instance];
11282  polymodel *pm = model_get(Ship_info[shipp->ship_info_index].model_num);
11283 
11284  if(pm == NULL)
11285  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11286 
11287  bsp_info *sm = &pm->submodel[submodel];
11288 
11289  ship_subsys *ss = ship_get_subsys(shipp, sm->name);
11290 
11291  if(ss == NULL)
11292  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11293 
11294  return ade_set_args(L, "o", l_Subsystem.Set(ship_subsys_h(objp, ss)));
11295 }
11296 
11297 ADE_VIRTVAR(Target, l_Camera, "object", "New target object", "object", "Camera target object")
11298 {
11299  camid cid;
11300  object_h *oh = NULL;
11301  if(!ade_get_args(L, "o|o", l_Camera.Get(&cid), l_Object.GetPtr(&oh)))
11302  return ade_set_error(L, "o", l_Object.Set(object_h()));
11303 
11304  if(!cid.isValid())
11305  return ade_set_error(L, "o", l_Object.Set(object_h()));
11306 
11307  if(ADE_SETTING_VAR && oh && oh->IsValid()) {
11308  cid.getCamera()->set_object_target(oh->objp);
11309  }
11310 
11311  return ade_set_args(L, "o", l_Object.Set(object_h(cid.getCamera()->get_object_target())));
11312 }
11313 
11314 ADE_VIRTVAR(TargetSubsystem, l_Camera, "subsystem", "New target subsystem", "subsystem", "Subsystem that the camera is pointed at")
11315 {
11316  camid cid;
11317  ship_subsys_h *sso = NULL;
11318  if(!ade_get_args(L, "o|o", l_Camera.Get(&cid), l_Subsystem.GetPtr(&sso)))
11319  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11320 
11321  if(!cid.isValid())
11322  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11323 
11324  if(ADE_SETTING_VAR && sso && sso->IsValid()) {
11326  }
11327 
11328  object *objp = cid.getCamera()->get_object_target();
11329  if(objp == NULL || objp->type != OBJ_SHIP)
11330  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11331 
11332  int submodel = cid.getCamera()->get_object_target_submodel();
11333  if(submodel < 0)
11334  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11335 
11336  ship *shipp = &Ships[objp->instance];
11337  polymodel *pm = model_get(Ship_info[shipp->ship_info_index].model_num);
11338 
11339  if(pm == NULL)
11340  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11341 
11342  bsp_info *sm = &pm->submodel[submodel];
11343 
11344  ship_subsys *ss = ship_get_subsys(shipp, sm->name);
11345 
11346  if(ss == NULL)
11347  return ade_set_error(L, "o", l_Subsystem.Set(ship_subsys_h()));
11348 
11349  return ade_set_args(L, "o", l_Subsystem.Set(ship_subsys_h(objp, ss)));
11350 }
11351 
11352 ADE_FUNC(setFOV, l_Camera, "[number FOV, number Zoom Time, number Zoom Acceleration Time, number Zoom deceleration Time]",
11353  "Sets camera FOV"
11354  "<br>FOV is the final field of view, in radians, of the camera."
11355  "<br>Zoom Time is the total time to take zooming in or out."
11356  "<br>Acceleration Time is the total time it should take the camera to get up to full zoom speed."
11357  "<br>Deceleration Time is the total time it should take the camera to slow down from full zoom speed.",
11358  "boolean", "true if successful, false or nil otherwise")
11359 {
11360  camid cid;
11361  float n_fov = VIEWER_ZOOM_DEFAULT;
11362  float time=0.0f;
11363  float acc_time=0.0f;
11364  float dec_time=0.0f;
11365  if(!ade_get_args(L, "o|ffff", l_Camera.Get(&cid), &n_fov, &time, &acc_time, &dec_time))
11366  return ADE_RETURN_NIL;
11367 
11368  if(!cid.isValid())
11369  return ADE_RETURN_NIL;
11370 
11371  cid.getCamera()->set_fov(n_fov, time, acc_time, dec_time);
11372 
11373  return ADE_RETURN_TRUE;
11374 }
11375 
11376 ADE_FUNC(setOrientation, l_Camera, "[world orientation Orientation, number Rotation Time, number Acceleration Time, number Deceleration time]",
11377  "Sets camera orientation and velocity data."
11378  "<br>Orientation is the final orientation for the camera, after it has finished moving. If not specified, the camera will simply stop at its current orientation."
11379  "<br>Rotation time (seconds) is how long total, including acceleration, the camera should take to rotate. If it is not specified, the camera will jump to the specified orientation."
11380  "<br>Acceleration time (seconds) is how long it should take the camera to get 'up to speed'. If not specified, the camera will instantly start moving."
11381  "<br>Deceleration time (seconds) is how long it should take the camera to slow down. If not specified, the camera will instantly stop moving.",
11382  "boolean", "true if successful, false or nil otherwise")
11383 {
11384  camid cid;
11385  matrix_h *mh=NULL;
11386  float time=0.0f;
11387  float acc_time=0.0f;
11388  float dec_time=0.0f;
11389  if(!ade_get_args(L, "o|offf", l_Camera.Get(&cid), l_Matrix.GetPtr(&mh), &time, &acc_time, &dec_time))
11390  return ADE_RETURN_NIL;
11391 
11392  if(!cid.isValid())
11393  return ADE_RETURN_NIL;
11394 
11395  camera *cam = cid.getCamera();
11396 
11397  if(mh != NULL)
11398  {
11399  cam->set_rotation(mh->GetMatrix(), time, acc_time, dec_time);
11400  }
11401  else
11402  {
11403  cam->set_rotation();
11404  }
11405 
11406  return ADE_RETURN_TRUE;
11407 }
11408 
11409 ADE_FUNC(setPosition, l_Camera, "[wvector Position, number Translation Time, number Acceleration Time, number Deceleration Time]",
11410  "Sets camera position and velocity data."
11411  "<br>Position is the final position for the camera. If not specified, the camera will simply stop at its current position."
11412  "<br>Translation time (seconds) is how long total, including acceleration, the camera should take to move. If it is not specified, the camera will jump to the specified position."
11413  "<br>Acceleration time (seconds) is how long it should take the camera to get 'up to speed'. If not specified, the camera will instantly start moving."
11414  "<br>Deceleration time (seconds) is how long it should take the camera to slow down. If not specified, the camera will instantly stop moving.",
11415  "boolean", "true if successful, false or nil otherwise")
11416 {
11417  camid cid;
11418  vec3d *pos=NULL;
11419  float time=0.0f;
11420  float acc_time=0.0f;
11421  float dec_time=0.0f;
11422  if(!ade_get_args(L, "o|offf", l_Camera.Get(&cid), l_Vector.GetPtr(&pos), &time, &acc_time, &dec_time))
11423  return ADE_RETURN_NIL;
11424 
11425  if(!cid.isValid())
11426  return ADE_RETURN_NIL;
11427 
11428  cid.getCamera()->set_position(pos, time, acc_time, dec_time);
11429 
11430  return ADE_RETURN_TRUE;
11431 }
11432 
11433 //**********HANDLE: Control Info
11434 ade_obj<int> l_Control_Info("control info", "control info handle");
11435 
11436 ADE_VIRTVAR(Pitch, l_Control_Info, "number", "Pitch of the player ship", "number", "Pitch")
11437 {
11438  int idx;
11439  float new_ci = 0.0f;
11440 
11441  if(!ade_get_args(L, "o|f", l_Control_Info.Get(&idx), &new_ci))
11442  return ade_set_error(L, "f", new_ci);
11443 
11444  if(ADE_SETTING_VAR) {
11445  Player->lua_ci.pitch = new_ci;
11446  }
11447 
11448  return ade_set_args(L, "f", Player->lua_ci.pitch);
11449 }
11450 
11451 ADE_VIRTVAR(Heading, l_Control_Info, "number", "Heading of the player ship", "number", "Heading")
11452 {
11453  int idx;
11454  float new_ci = 0.0f;
11455 
11456  if(!ade_get_args(L, "o|f", l_Control_Info.Get(&idx), &new_ci))
11457  return ade_set_error(L, "f", new_ci);
11458 
11459  if(ADE_SETTING_VAR) {
11460  Player->lua_ci.heading = new_ci;
11461  }
11462 
11463  return ade_set_args(L, "f", Player->lua_ci.heading);
11464 }
11465 
11466 ADE_VIRTVAR(Bank, l_Control_Info, "number", "Bank of the player ship", "number", "Bank")
11467 {
11468  int idx;
11469  float new_ci = 0.0f;
11470 
11471  if(!ade_get_args(L, "o|f", l_Control_Info.Get(&idx), &new_ci))
11472  return ade_set_error(L, "f", new_ci);
11473 
11474  if(ADE_SETTING_VAR) {
11475  Player->lua_ci.bank = new_ci;
11476  }
11477 
11478  return ade_set_args(L, "f", Player->lua_ci.bank);
11479 }
11480 
11481 ADE_VIRTVAR(Vertical, l_Control_Info, "number", "Vertical control of the player ship", "number", "Vertical control")
11482 {
11483  int idx;
11484  float new_ci = 0.0f;
11485 
11486  if(!ade_get_args(L, "o|f", l_Control_Info.Get(&idx), &new_ci))
11487  return ade_set_error(L, "f", new_ci);
11488 
11489  if(ADE_SETTING_VAR) {
11490  Player->lua_ci.vertical = new_ci;
11491  }
11492 
11493  return ade_set_args(L, "f", Player->lua_ci.vertical);
11494 }
11495 
11496 ADE_VIRTVAR(Sideways, l_Control_Info, "number", "Sideways control of the player ship", "number", "Sideways control")
11497 {
11498  int idx;
11499  float new_ci = 0.0f;
11500 
11501  if(!ade_get_args(L, "o|f", l_Control_Info.Get(&idx), &new_ci))
11502  return ade_set_error(L, "f", new_ci);
11503 
11504  if(ADE_SETTING_VAR) {
11505  Player->lua_ci.sideways = new_ci;
11506  }
11507 
11508  return ade_set_args(L, "f", Player->lua_ci.sideways);
11509 }
11510 
11511 ADE_VIRTVAR(Forward, l_Control_Info, "number", "Forward control of the player ship", "number", "Forward")
11512 {
11513  int idx;
11514  float new_ci = 0.0f;
11515 
11516  if(!ade_get_args(L, "o|f", l_Control_Info.Get(&idx), &new_ci))
11517  return ade_set_error(L, "f", new_ci);
11518 
11519  if(ADE_SETTING_VAR) {
11520  Player->lua_ci.forward = new_ci;
11521  }
11522 
11523  return ade_set_args(L, "f", Player->lua_ci.forward);
11524 }
11525 
11526 ADE_VIRTVAR(ForwardCruise, l_Control_Info, "number", "Forward control of the player ship", "number", "Forward")
11527 {
11528  int idx;
11529  float new_ci = 0.0f;
11530 
11531  if(!ade_get_args(L, "o|f", l_Control_Info.Get(&idx), &new_ci))
11532  return ade_set_error(L, "f", new_ci);
11533 
11534  if(ADE_SETTING_VAR) {
11535  Player->lua_ci.forward_cruise_percent = new_ci*100.0f;
11536  }
11537 
11538  return ade_set_args(L, "f", Player->lua_ci.forward_cruise_percent*0.01f);
11539 }
11540 
11541 ADE_VIRTVAR(PrimaryCount, l_Control_Info, "number", "Number of primary weapons that will fire", "number", "Number of weapons to fire, or 0 if handle is invalid")
11542 {
11543  int idx;
11544  int new_pri = 0;
11545 
11546  if(!ade_get_args(L, "o|i", l_Control_Info.Get(&idx), &new_pri))
11547  return ade_set_error(L, "i", new_pri);
11548 
11549  if(ADE_SETTING_VAR) {
11550  Player->lua_ci.fire_primary_count = new_pri;
11551  }
11552 
11553  return ade_set_args(L, "i", Player->lua_ci.fire_primary_count);
11554 }
11555 
11556 ADE_VIRTVAR(SecondaryCount, l_Control_Info, "number", "Number of secondary weapons that will fire", "number", "Number of weapons to fire, or 0 if handle is invalid")
11557 {
11558  int idx;
11559  int new_sec = 0;
11560 
11561  if(!ade_get_args(L, "o|i", l_Control_Info.Get(&idx), &new_sec))
11562  return ade_set_error(L, "i", new_sec);
11563 
11564  if(ADE_SETTING_VAR) {
11565  Player->lua_ci.fire_secondary_count = new_sec;
11566  }
11567 
11569 }
11570 
11571 ADE_VIRTVAR(CountermeasureCount, l_Control_Info, "number", "Number of countermeasures that will launch", "number", "Number of countermeasures to launch, or 0 if handle is invalid")
11572 {
11573  int idx;
11574  int new_cm = 0;
11575 
11576  if(!ade_get_args(L, "o|i", l_Control_Info.Get(&idx), &new_cm))
11577  return ade_set_error(L, "i", new_cm);
11578 
11579  if(ADE_SETTING_VAR) {
11581  }
11582 
11584 }
11585 
11586 ADE_FUNC(clearLuaButtonInfo, l_Control_Info, NULL, "Clears the lua button control info", NULL, NULL)
11587 {
11589 
11590  return ADE_RETURN_NIL;
11591 }
11592 
11593 ADE_FUNC(getButtonInfo, l_Control_Info, NULL, "Access the four bitfields containing the button info", "number, number, number,number", "Four bitfields")
11594 {
11595  int i;
11596  int bi_status[4];
11597 
11598  for(i=0;i<4;i++)
11599  bi_status[i] = Player->lua_bi.status[i];
11600 
11601  return ade_set_args(L, "iiii", bi_status[0], bi_status[1], bi_status[2], bi_status[3]);
11602 }
11603 
11604 ADE_FUNC(accessButtonInfo, l_Control_Info, "number, number, number, number", "Access the four bitfields containing the button info", "number, number, number,number", "Four bitfields")
11605 {
11606  int i;
11607  int bi_status[4];
11608 
11609  for(i=0;i<4;i++)
11610  bi_status[i] = 0;
11611 
11612  if(!ade_get_args(L, "|iiii", &bi_status[0], &bi_status[1], &bi_status[2], &bi_status[3]))
11613  return ADE_RETURN_NIL;
11614 
11615  if(ADE_SETTING_VAR) {
11616  for(i=0;i<4;i++)
11617  Player->lua_bi.status[i] = bi_status[i];
11618  }
11619 
11620  for(i=0;i<4;i++)
11621  bi_status[i] = Player->lua_bi.status[i];
11622 
11623  return ade_set_args(L, "iiii", bi_status[0], bi_status[1], bi_status[2], bi_status[3]);
11624 }
11625 
11626 ADE_FUNC(useButtonControl, l_Control_Info, "number, string", "Adds the defined button control to lua button control data, if number is -1 it tries to use the string", NULL, NULL)
11627 {
11628  int index;
11629  char *buf = NULL;
11630 
11631  if(!ade_get_args(L, "i|s", &index, &buf))
11632  return ADE_RETURN_NIL;
11633 
11634  if(index != -1) {
11635  // Process the number
11636  if (index > (4 * 32))
11637  return ADE_RETURN_NIL;
11638 
11639  int a, b;
11640  a = index / 32;
11641  b = index % 32;
11642 
11643  // now add the processed bit
11644  Player->lua_bi.status[a] |= (1<<b);
11645  } else if (buf != NULL) {
11646  int i;
11647  for(i=0; i<num_plr_commands; i++) {
11648  if(!(strcmp(buf, plr_commands[i].name))) {
11649  int a;
11650  a = plr_commands[i].def / 32;
11651  Player->lua_bi.status[plr_commands[i].var] |= (1<<a);
11652  break;
11653  }
11654  }
11655  }
11656 
11657  return ADE_RETURN_NIL;
11658 }
11659 
11660 ADE_FUNC(getButtonControlName, l_Control_Info, "number", "Gives the name of the command corresponding with the given number", "string", "Name of the command")
11661 {
11662  int index;
11663 
11664  if(!ade_get_args(L, "i", &index))
11665  return ade_set_error(L, "s", "");
11666 
11667  if((index < 0) || (index > num_plr_commands))
11668  return ade_set_error(L, "s", "");
11669 
11670  return ade_set_args(L, "s", plr_commands[index].name);
11671 }
11672 
11673 ADE_FUNC(getButtonControlNumber, l_Control_Info, "string", "Gives the number of the command corresponding with the given string", "number", "Number of the command")
11674 {
11675  int i;
11676  char *buf;
11677 
11678  if(!ade_get_args(L, "s", &buf))
11679  return ade_set_error(L, "i", -1);
11680 
11681  for(i = 0; i < num_plr_commands; i++) {
11682  if (!(strcmp(buf, plr_commands[i].name))) {
11683  return ade_set_args(L, "i", plr_commands[i].def);
11684  }
11685  }
11686 
11687  return ade_set_error(L, "i", -1);
11688 }
11689 
11690 ADE_VIRTVAR(AllButtonPolling, l_Control_Info, "boolean", "Toggles the all button polling for lua", "boolean", "If the all button polling is enabled or not")
11691 {
11692  bool p;
11693  int idx;
11694 
11695  if(!ade_get_args(L, "o|b", l_Control_Info.Get(&idx), &p))
11696  return ADE_RETURN_FALSE;
11697 
11698  if (ADE_SETTING_VAR) {
11699  if (p)
11701  else
11703  }
11704 
11706  return ADE_RETURN_TRUE;
11707  else
11708  return ADE_RETURN_FALSE;
11709 }
11710 
11711 ADE_FUNC(pollAllButtons, l_Control_Info, NULL, "Access the four bitfields containing the button info", "number, number, number,number", "Four bitfields")
11712 {
11713  int i;
11714  int bi_status[4];
11715 
11717  return ADE_RETURN_NIL;
11718 
11719  for(i=0;i<4;i++)
11720  bi_status[i] = Player->lua_bi_full.status[i];
11721 
11722  return ade_set_args(L, "iiii", bi_status[0], bi_status[1], bi_status[2], bi_status[3]);
11723 }
11724 
11726 {
11727 protected:
11730 public:
11732  {
11733  part = NULL;
11734  }
11735 
11737  {
11738  this->part = part_p;
11739  if (part_p != NULL)
11740  this->sig = part_p->signature;
11741  }
11742 
11744  {
11745  return this->part;
11746  }
11747 
11748  bool isValid()
11749  {
11750  if (part != NULL && part->signature != 0 && part->signature == this->sig)
11751  return true;
11752  else
11753  return false;
11754  }
11755 
11757  {
11758  }
11759 };
11760 
11761 //**********HANDLE: Particle
11762 ade_obj<particle_h> l_Particle("particle", "Handle to a particle");
11763 
11764 ADE_VIRTVAR(Position, l_Particle, "vector", "The current position of the particle (world vector)", "vector", "The current position")
11765 {
11766  particle_h *ph = NULL;
11767  vec3d newVec = vmd_zero_vector;
11768  if (!ade_get_args(L, "o|o", l_Particle.GetPtr(&ph), l_Vector.Get(&newVec)))
11769  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11770 
11771  if (ph == NULL)
11772  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11773 
11774  if (!ph->isValid())
11775  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11776 
11777  if (ADE_SETTING_VAR)
11778  {
11779  ph->Get()->pos = newVec;
11780  }
11781 
11782  return ade_set_args(L, "o", l_Vector.Set(ph->Get()->pos));
11783 }
11784 
11785 ADE_VIRTVAR(Velocity, l_Particle, "vector", "The current velocity of the particle (world vector)", "vector", "The current velocity")
11786 {
11787  particle_h *ph = NULL;
11788  vec3d newVec = vmd_zero_vector;
11789  if (!ade_get_args(L, "o|o", l_Particle.GetPtr(&ph), l_Vector.Get(&newVec)))
11790  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11791 
11792  if (ph == NULL)
11793  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11794 
11795  if (!ph->isValid())
11796  return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
11797 
11798  if (ADE_SETTING_VAR)
11799  {
11800  ph->Get()->velocity = newVec;
11801  }
11802 
11803  return ade_set_args(L, "o", l_Vector.Set(ph->Get()->velocity));
11804 }
11805 
11806 ADE_VIRTVAR(Age, l_Particle, "number", "The time this particle already lives", "number", "The current age or -1 on error")
11807 {
11808  particle_h *ph = NULL;
11809  float newAge = -1.0f;
11810  if (!ade_get_args(L, "o|f", l_Particle.GetPtr(&ph), &newAge))
11811  return ade_set_error(L, "f", -1.0f);
11812 
11813  if (ph == NULL)
11814  return ade_set_error(L, "f", -1.0f);
11815 
11816  if (!ph->isValid())
11817  return ade_set_error(L, "f", -1.0f);
11818 
11819  if (ADE_SETTING_VAR)
11820  {
11821  if (newAge >= 0)
11822  ph->Get()->age = newAge;
11823  }
11824 
11825  return ade_set_args(L, "f", ph->Get()->age);
11826 }
11827 
11828 ADE_VIRTVAR(MaximumLife, l_Particle, "number", "The time this particle can live", "number", "The maximal life or -1 on error")
11829 {
11830  particle_h *ph = NULL;
11831  float newLife = -1.0f;
11832  if (!ade_get_args(L, "o|f", l_Particle.GetPtr(&ph), &newLife))
11833  return ade_set_error(L, "f", -1.0f);
11834 
11835  if (ph == NULL)
11836  return ade_set_error(L, "f", -1.0f);
11837 
11838  if (!ph->isValid())
11839  return ade_set_error(L, "f", -1.0f);
11840 
11841  if (ADE_SETTING_VAR)
11842  {
11843  if (newLife >= 0)
11844  ph->Get()->max_life = newLife;
11845  }
11846 
11847  return ade_set_args(L, "f", ph->Get()->max_life);
11848 }
11849 
11850 ADE_VIRTVAR(Radius, l_Particle, "number", "The radius of the particle", "number", "The radius or -1 on error")
11851 {
11852  particle_h *ph = NULL;
11853  float newRadius = -1.0f;
11854  if (!ade_get_args(L, "o|f", l_Particle.GetPtr(&ph), &newRadius))
11855  return ade_set_error(L, "f", -1.0f);
11856 
11857  if (ph == NULL)
11858  return ade_set_error(L, "f", -1.0f);
11859 
11860  if (!ph->isValid())
11861  return ade_set_error(L, "f", -1.0f);
11862 
11863  if (ADE_SETTING_VAR)
11864  {
11865  if (newRadius >= 0)
11866  ph->Get()->radius = newRadius;
11867  }
11868 
11869  return ade_set_args(L, "f", ph->Get()->radius);
11870 }
11871 
11872 ADE_VIRTVAR(TracerLength, l_Particle, "number", "The tracer legth of the particle", "number", "The radius or -1 on error")
11873 {
11874  particle_h *ph = NULL;
11875  float newTracer = -1.0f;
11876  if (!ade_get_args(L, "o|f", l_Particle.GetPtr(&ph), &newTracer))
11877  return ade_set_error(L, "f", -1.0f);
11878 
11879  if (ph == NULL)
11880  return ade_set_error(L, "f", -1.0f);
11881 
11882  if (!ph->isValid())
11883  return ade_set_error(L, "f", -1.0f);
11884 
11885  if (ADE_SETTING_VAR)
11886  {
11887  if (newTracer >= 0)
11888  ph->Get()->tracer_length = newTracer;
11889  }
11890 
11891  return ade_set_args(L, "f", ph->Get()->tracer_length);
11892 }
11893 
11894 ADE_VIRTVAR(AttachedObject, l_Particle, "object", "The object this particle is attached to. If valid the position will be relativ to this object and the velocity will be ignored.", "object", "Attached object or invalid object handle on error")
11895 {
11896  particle_h *ph = NULL;
11897  object_h *newObj = nullptr;
11898  if (!ade_get_args(L, "o|o", l_Particle.GetPtr(&ph), l_Object.GetPtr(&newObj)))
11899  return ade_set_error(L, "o", l_Object.Set(object_h()));
11900 
11901  if (ph == NULL)
11902  return ade_set_error(L, "o", l_Object.Set(object_h()));
11903 
11904  if (!ph->isValid())
11905  return ade_set_error(L, "o", l_Object.Set(object_h()));
11906 
11907  if (ADE_SETTING_VAR)
11908  {
11909  if (newObj && newObj->IsValid())
11910  ph->Get()->attached_objnum = newObj->objp->signature;
11911  }
11912 
11913  return ade_set_args(L, "o", l_Object.Set(object_h(&Objects[ph->Get()->attached_objnum])));
11914 }
11915 
11916 ADE_FUNC(isValid, l_Particle, NULL, "Detects whether this handle is valid", "boolean", "true if valid false if not")
11917 {
11918  particle_h *ph = NULL;
11919  if (!ade_get_args(L, "o", l_Particle.GetPtr(&ph)))
11920  return ADE_RETURN_FALSE;
11921 
11922  if (ph == NULL)
11923  return ADE_RETURN_FALSE;
11924 
11925  return ade_set_args(L, "b", ph->isValid());
11926 }
11927 
11928 //**********LIBRARY: Audio
11929 ade_lib l_Audio("Audio", NULL, "ad", "Sound/Music Library");
11930 
11931 ADE_FUNC(getSoundentry, l_Audio, "string/number", "Return a sound entry matching the specified index or name. If you are using a number then the first valid index is 1", "soundentry", "soundentry or invalid handle on error")
11932 {
11933  int index = -1;
11934 
11935  if (lua_isnumber(L, 1))
11936  {
11937  int idx = -1;
11938  if(!ade_get_args(L, "i", &idx))
11939  return ade_set_error(L, "o", l_SoundEntry.Set(sound_entry_h()));
11940 
11941  index = gamesnd_get_by_tbl_index(idx);
11942  }
11943  else
11944  {
11945  char *s = NULL;
11946  if(!ade_get_args(L, "s", &s))
11947  return ade_set_error(L, "o", l_SoundEntry.Set(sound_entry_h()));
11948 
11949  if (s == NULL)
11950  return ade_set_error(L, "o", l_SoundEntry.Set(sound_entry_h()));
11951 
11952  index = gamesnd_get_by_name(s);
11953  }
11954 
11955  if (index < 0)
11956  {
11957  return ade_set_args(L, "o", l_SoundEntry.Set(sound_entry_h()));
11958  }
11959  else
11960  {
11961  return ade_set_args(L, "o", l_SoundEntry.Set(sound_entry_h(index)));
11962  }
11963 }
11964 
11965 ADE_FUNC(loadSoundfile, l_Audio, "string filename", "Loads the specified sound file", "soundfile", "A soundfile handle")
11966 {
11967  char* fileName = NULL;
11968 
11969  if (!ade_get_args(L, "s", &fileName))
11970  return ade_set_error(L, "o", l_Soundfile.Set(-1));
11971 
11972  game_snd tmp_gs;
11973  strcpy_s( tmp_gs.filename, fileName );
11974  int n = snd_load( &tmp_gs, 0 );
11975 
11976  return ade_set_error(L, "o", l_Soundfile.Set(n));
11977 }
11978 
11979 ADE_FUNC(playSound, l_Audio, "soundentry", "Plays the specified sound entry handle", "sound", "A handle to the playing sound")
11980 {
11981  sound_entry_h *seh = NULL;
11982 
11983  if (!ade_get_args(L, "o", l_SoundEntry.GetPtr(&seh)))
11984  return ade_set_error(L, "o", l_Sound.Set(sound_h()));
11985 
11986  if (seh == NULL || !seh->IsValid())
11987  return ade_set_error(L, "o", l_Sound.Set(sound_h()));
11988 
11989  int handle = snd_play(seh->Get());
11990 
11991  if (handle < 0)
11992  {
11993  return ade_set_args(L, "o", l_Sound.Set(sound_h()));
11994  }
11995  else
11996  {
11997  return ade_set_args(L, "o", l_Sound.Set(sound_h(seh->idx, handle)));
11998  }
11999 }
12000 
12001 ADE_FUNC(playLoopingSound, l_Audio, "soundentry", "Plays the specified sound as a looping sound", "sound", "A handle to the playing sound or invalid handle if playback failed")
12002 {
12003  sound_entry_h *seh = NULL;
12004 
12005  if (!ade_get_args(L, "o", l_SoundEntry.GetPtr(&seh)))
12006  return ade_set_error(L, "o", l_Sound.Set(sound_h()));
12007 
12008  if (seh == NULL || !seh->IsValid())
12009  return ade_set_error(L, "o", l_Sound.Set(sound_h()));
12010 
12011  int handle = snd_play_looping(seh->Get());
12012 
12013  if (handle < 0)
12014  {
12015  return ade_set_args(L, "o", l_Sound.Set(sound_h()));
12016  }
12017  else
12018  {
12019  return ade_set_args(L, "o", l_Sound.Set(sound_h(seh->idx, handle)));
12020  }
12021 }
12022 
12023 ADE_FUNC(play3DSound, l_Audio, "soundentry[, vector source[, vector listener]]", "Plays the specified sound entry handle. Source if by default 0, 0, 0 and listener is by default the current viewposition", "3Dsound", "A handle to the playing sound")
12024 {
12025  sound_entry_h *seh = NULL;
12027  vec3d *listener = &View_position;
12028 
12029  if (!ade_get_args(L, "o|oo", l_SoundEntry.GetPtr(&seh), l_Vector.GetPtr(&source), l_Vector.GetPtr(&listener)))
12030  return ade_set_error(L, "o", l_Sound3D.Set(sound_h()));
12031 
12032  if (seh == NULL || !seh->IsValid())
12033  return ade_set_error(L, "o", l_Sound3D.Set(sound_h()));
12034 
12035  int handle = snd_play_3d(seh->Get(), source, listener);
12036 
12037  if (handle < 0)
12038  {
12039  return ade_set_args(L, "o", l_Sound3D.Set(sound_h()));
12040  }
12041  else
12042  {
12043  return ade_set_args(L, "o", l_Sound3D.Set(sound_h(seh->idx, handle)));
12044  }
12045 }
12046 
12047 ADE_FUNC(playGameSound, l_Audio, "Sound index, [Panning (-1.0 left to 1.0 right), Volume %, Priority 0-3, Voice Message?]", "Plays a sound from #Game Sounds in sounds.tbl. A priority of 0 indicates that the song must play; 1-3 will specify the maximum number of that sound that can be played", "boolean", "True if sound was played, false if not (Replaced with a sound instance object in the future)")
12048 {
12049  int idx, gamesnd_idx;
12050  float pan=0.0f;
12051  float vol=100.0f;
12052  int pri=0;
12053  bool voice_msg = false;
12054  if(!ade_get_args(L, "i|ffib", &idx, &pan, &vol, &pri, &voice_msg))
12055  return ADE_RETURN_NIL;
12056 
12057  if(idx < 0)
12058  return ADE_RETURN_FALSE;
12059 
12060  if(pri < 0 || pri > 3)
12061  pri = 0;
12062 
12063  CLAMP(pan, -1.0f, 1.0f);
12064  CLAMP(vol, 0.0f, 100.0f);
12065 
12066  gamesnd_idx = gamesnd_get_by_tbl_index(idx);
12067 
12068  if (gamesnd_idx >= 0) {
12069  int sound_handle = snd_play(&Snds[gamesnd_idx], pan, vol*0.01f, pri, voice_msg);
12070  return ade_set_args(L, "b", sound_handle >= 0);
12071  } else {
12072  LuaError(L, "Invalid sound index %i (Snds[%i]) in playGameSound()", idx, gamesnd_idx);
12073  return ADE_RETURN_FALSE;
12074  }
12075 }
12076 
12077 ADE_FUNC(playInterfaceSound, l_Audio, "Sound index", "Plays a sound from #Interface Sounds in sounds.tbl", "boolean", "True if sound was played, false if not")
12078 {
12079  int idx, gamesnd_idx;
12080  if(!ade_get_args(L, "i", &idx))
12081  return ade_set_error(L, "b", false);
12082 
12083  gamesnd_idx = gamesnd_get_by_iface_tbl_index(idx);
12084 
12085  if (gamesnd_idx >= 0) {
12086  gamesnd_play_iface(gamesnd_idx);
12087  return ade_set_args(L, "b", true);
12088  } else {
12089  LuaError(L, "Invalid sound index %i (Snds[%i]) in playInterfaceSound()", idx, gamesnd_idx);
12090  return ADE_RETURN_FALSE;
12091  }
12092 }
12093 
12094 extern float Master_event_music_volume;
12095 ADE_FUNC(playMusic, l_Audio, "string Filename, [float volume = 1.0, bool looping = true]", "Plays a music file using FS2Open's builtin music system. Volume is currently ignored, uses players music volume setting. Files passed to this function are looped by default.", "number", "Audiohandle of the created audiostream, or -1 on failure")
12096 {
12097  char *s;
12098  float volume = 1.0f;
12099  bool loop = true;
12100  if (!ade_get_args(L, "s|fb", &s, &volume, &loop))
12101  return ade_set_error(L, "i", -1);
12102 
12103  int ah = audiostream_open(s, ASF_MENUMUSIC);
12104  if(ah < 0)
12105  return ade_set_error(L, "i", -1);
12106 
12107  // didn't remove the volume parameter because it'll break the API
12108  volume = Master_event_music_volume;
12109 
12110  audiostream_play(ah, volume, loop ? 1 : 0);
12111  return ade_set_args(L, "i", ah);
12112 }
12113 
12114 ADE_FUNC(stopMusic, l_Audio, "int audiohandle, [bool fade = false], [string 'briefing|credits|mainhall']", "Stops a playing music file, provided audiohandle is valid. If the 3rd arg is set to one of briefing,credits,mainhall then that music will be stopped despite the audiohandle given.", NULL, NULL)
12115 {
12116  int ah;
12117  bool fade = false;
12118  char *music_type = NULL;
12119 
12120  if(!ade_get_args(L, "i|bs", &ah, &fade, &music_type))
12121  return ADE_RETURN_NIL;
12122 
12123  if (ah >= MAX_AUDIO_STREAMS || ah < 0 )
12124  return ADE_RETURN_NIL;
12125 
12126  if (music_type == NULL) {
12127  audiostream_close_file(ah, fade);
12128  } else {
12129  if (!stricmp(music_type, "briefing")) {
12130  briefing_stop_music(fade);
12131  } else if (!stricmp(music_type, "credits")) {
12132  credits_stop_music(fade);
12133  } else if (!stricmp(music_type, "mainhall")) {
12134  main_hall_stop_music(fade);
12135  } else {
12136  LuaError(L, "Invalid music type (%s) passed to stopMusic", music_type);
12137  }
12138  }
12139 
12140  return ADE_RETURN_NIL;
12141 }
12142 
12143 ADE_FUNC(pauseMusic, l_Audio, "int audiohandle, bool pause", "Pauses or unpauses a playing music file, provided audiohandle is valid. The boolean argument should be true to pause and false to unpause. If the audiohandle is -1, *all* audio streams are paused or unpaused.", NULL, NULL)
12144 {
12145  int ah;
12146  bool pause;
12147 
12148  if(!ade_get_args(L, "ib", &ah, &pause))
12149  return ADE_RETURN_NIL;
12150 
12151  if (ah >= 0 && ah < MAX_AUDIO_STREAMS)
12152  {
12153  if (pause)
12154  audiostream_pause(ah, true);
12155  else
12156  audiostream_unpause(ah, true);
12157  }
12158  else if (ah == -1)
12159  {
12160  if (pause)
12161  audiostream_pause_all(true);
12162  else
12164  }
12165 
12166  return ADE_RETURN_NIL;
12167 }
12168 
12169 
12170 //**********LIBRARY: Base
12171 ade_lib l_Base("Base", NULL, "ba", "Base FreeSpace 2 functions");
12172 
12173 ADE_FUNC(print, l_Base, "string Message", "Prints a string", NULL, NULL)
12174 {
12175  mprintf(("%s", lua_tostring(L, -1)));
12176 
12177  return ADE_RETURN_NIL;
12178 }
12179 
12180 ADE_FUNC(warning, l_Base, "string Message", "Displays a FreeSpace warning (debug build-only) message with the string provided", NULL, NULL)
12182  Warning(LOCATION, "%s", lua_tostring(L, -1));
12183 
12184  return ADE_RETURN_NIL;
12185 }
12186 
12187 ADE_FUNC(error, l_Base, "string Message", "Displays a FreeSpace error message with the string provided", NULL, NULL)
12188 {
12189  Error(LOCATION, "%s", lua_tostring(L, -1));
12190 
12191  return ADE_RETURN_NIL;
12192 }
12193 
12194 ADE_FUNC(createOrientation, l_Base, "[p/r1c1, b/r1c2, h/r1c3, r2c1, r2c2, r2c3, r3c1, r3c2, r3c3]", "Given 0, 3, or 9 arguments, creates an orientation object with that orientation.", "orientation", "New orientation object, or null orientation on failure")
12195 {
12196  matrix m;
12197  int numargs = ade_get_args(L, "|fffffffff", &m.a1d[0], &m.a1d[1], &m.a1d[2], &m.a1d[3], &m.a1d[4], &m.a1d[5], &m.a1d[6], &m.a1d[7], &m.a1d[8]);
12198  if(!numargs)
12199  {
12200  return ade_set_args(L, "o", l_Matrix.Set( matrix_h(&vmd_identity_matrix) ));
12201  }
12202  else if(numargs == 3)
12203  {
12204  angles a = {m.a1d[0], m.a1d[1], m.a1d[2]};
12205  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&a)));
12206  }
12207  else if(numargs == 9)
12208  {
12209  return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&m)));
12210  }
12211 
12212  return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
12213 }
12214 
12215 ADE_FUNC(createVector, l_Base, "[x, y, z]", "Creates a vector object", "vector", "Vector object")
12216 {
12217  vec3d v3 = vmd_zero_vector;
12218  ade_get_args(L, "|fff", &v3.xyz.x, &v3.xyz.y, &v3.xyz.z);
12219 
12220  return ade_set_args(L, "o", l_Vector.Set(v3));
12221 }
12222 
12223 ADE_FUNC(getFrametimeOverall, l_Base, NULL, "The overall frame time in seconds since the engine has started", "number", "Overall time (seconds)")
12224 {
12225  return ade_set_args(L, "x", game_get_overall_frametime());
12226 }
12227 
12228 ADE_FUNC(getFrametime, l_Base, "[Do not adjust for time compression (Boolean)]", "Gets how long this frame is calculated to take. Use it to for animations, physics, etc to make incremental changes.", "number", "Frame time (seconds)")
12229 {
12230  bool b=false;
12231  ade_get_args(L, "|b", &b);
12232 
12233  return ade_set_args(L, "f", b ? flRealframetime : flFrametime);
12234 }
12235 
12236 ADE_FUNC(getCurrentGameState, l_Base, "[Depth (number)]", "Gets current FreeSpace state; if a depth is specified, the state at that depth is returned. (IE at the in-game options game, a depth of 1 would give you the game state, while the function defaults to 0, which would be the options screen.", "gamestate", "Current game state at specified depth, or invalid handle if no game state is active yet")
12237 {
12238  int depth = 0;
12239  ade_get_args(L, "|i", &depth);
12240 
12241  if(depth > gameseq_get_depth())
12242  return ade_set_args(L, "o", l_GameState.Set(gamestate_h()));
12243 
12244  return ade_set_args(L, "o", l_GameState.Set(gamestate_h(gameseq_get_state(depth))));
12245 }
12246 
12247 ADE_FUNC(getCurrentMPStatus, l_Base, "NIL", "Gets this computers current MP status", "string", "Current MP status" )
12248 {
12249  if ( MULTIPLAYER_MASTER )
12250  return ade_set_args(L, "s", "MULTIPLAYER_MASTER");
12251 
12252  if ( MULTIPLAYER_HOST )
12253  return ade_set_args(L, "s", "MULTIPLAYER_HOST");
12254 
12255  if ( MULTIPLAYER_CLIENT )
12256  return ade_set_args(L, "s", "MULTIPLAYER_CLIENT");
12257 
12258  if ( MULTIPLAYER_STANDALONE )
12259  return ade_set_args(L, "s", "MULTIPLAYER_STANDALONE");
12260 
12261  return ade_set_args(L, "s", "SINGLEPLAYER");
12262 }
12263 
12264 ADE_FUNC(getCurrentPlayer, l_Base, NULL, "Gets a handle of the currently used player.<br><b>Note:</b> If there is no current player then the first player will be returned, check the game state to make sure you have a valid player handle.", "player", "Player handle")
12265 {
12266  return ade_set_args(L, "o", l_Player.Set(Player_num));
12267 }
12268 
12269 ADE_FUNC(setControlMode, l_Base, "NIL or enumeration LE_*_CONTROL", "Sets the current control mode for the game.", "string", "Current control mode")
12270 {
12271  enum_h *e = NULL;
12272  if (!(ade_get_args(L, "|o", l_Enum.GetPtr(&e)))) {
12274  return ade_set_args(L, "s", "NORMAL");
12275  else if (lua_game_control & LGC_STEERING)
12276  return ade_set_args(L, "s", "STEERING");
12277  else if (lua_game_control & LGC_FULL)
12278  return ade_set_args(L, "s", "FULL");
12279  else
12280  return ade_set_error(L, "s", "");
12281  }
12282 
12283  if (!e) {
12284  return ade_set_error(L, "s", "");
12285  }
12286 
12287  switch (e->index) {
12288  case LE_NORMAL_CONTROLS:
12291  return ade_set_args(L, "s", "NORMAL CONTROLS");
12295  return ade_set_args(L, "s", "LUA STEERING CONTROLS");
12296  case LE_LUA_FULL_CONTROLS:
12299  return ade_set_args(L, "s", "LUA FULL CONTROLS");
12300  default:
12301  return ade_set_error(L, "s", "");
12302  }
12303 }
12304 
12305 ADE_FUNC(setButtonControlMode, l_Base, "NIL or enumeration LE_*_BUTTON_CONTROL", "Sets the current control mode for the game.", "string", "Current control mode")
12306 {
12307  enum_h *e = NULL;
12308  if (!(ade_get_args(L, "|o", l_Enum.GetPtr(&e)))) {
12310  return ade_set_args(L, "s", "NORMAL");
12311  else if (lua_game_control & LGC_B_OVERRIDE)
12312  return ade_set_args(L, "s", "OVERRIDE");
12313  else if (lua_game_control & LGC_B_ADDITIVE)
12314  return ade_set_args(L, "s", "ADDITIVE");
12315  else
12316  return ade_set_error(L, "s", "");
12317  }
12318 
12319  if (!e) {
12320  return ade_set_error(L, "s", "");
12321  }
12322 
12323  switch (e->index) {
12327  return ade_set_args(L, "s", "NORMAL BUTTON CONTROL");
12331  return ade_set_args(L, "s", "LUA OVERRIDE BUTTON CONTROL");
12335  return ade_set_args(L, "s", "LUA ADDITIVE BUTTON CONTROL");
12336  default:
12337  return ade_set_error(L, "s", "");
12338  }
12339 }
12340 
12341 ADE_FUNC(getControlInfo, l_Base, NULL, "Gets the control info handle.", "control info", "control info handle")
12342 {
12343  return ade_set_args(L, "o", l_Control_Info.Set(1));
12344 }
12345 
12346 ADE_FUNC(setTips, l_Base, "True or false", "Sets whether to display tips of the day the next time the current pilot enters the mainhall.", NULL, NULL)
12347 {
12348  if (Player == NULL)
12349  return ADE_RETURN_NIL;
12350 
12351  bool tips = false;
12352 
12353  ade_get_args(L, "b", &tips);
12354 
12355  if (tips)
12356  Player->tips = 1;
12357  else
12358  Player->tips = 0;
12359 
12360  return ADE_RETURN_NIL;
12361 }
12362 
12363 ADE_FUNC(getGameDifficulty, l_Base, NULL, "Returns the difficulty level from 1-5, 1 being the lowest, (Very Easy) and 5 being the highest (Insane)", "integer", "Difficulty level as integer")
12364 {
12365  return ade_set_args(L, "i", Game_skill_level+1);
12366 }
12367 
12368 ADE_FUNC(postGameEvent, l_Base, "gameevent Event", "Sets current game event. Note that you can crash FreeSpace 2 by posting an event at an improper time, so test extensively if you use it.", "boolean", "True if event was posted, false if passed event was invalid")
12369 {
12370  gameevent_h *gh = NULL;
12371  if(!ade_get_args(L, "o", l_GameEvent.GetPtr(&gh)))
12372  return ade_set_error(L, "b", false);
12373 
12374  if(!gh->IsValid())
12375  return ade_set_error(L, "b", false);
12376 
12377  if (Om_tracker_flag)
12380 
12381  gameseq_post_event(gh->Get());
12382 
12383  return ADE_RETURN_TRUE;
12384 }
12385 
12386 //**********SUBLIBRARY: Base/Events
12387 ade_lib l_Base_Events("GameEvents", &l_Base, NULL, "Freespace 2 game events");
12388 
12389 ADE_INDEXER(l_Base_Events, "number Index/string Name", "Array of game events", "gameevent", "Game event, or invalid gameevent handle if index is invalid")
12390 {
12391  char *name;
12392  if(!ade_get_args(L, "*s", &name))
12393  return ade_set_error(L, "o", l_GameEvent.Set(gameevent_h()));
12394 
12395  int idx = gameseq_get_event_idx(name);
12396 
12397  if(idx < 0)
12398  {
12399  idx = atoi(name);
12400 
12401  //Lua-->FS2
12402  idx--;
12403 
12404  if(idx < 0 || idx >= Num_gs_event_text)
12405  return ade_set_error(L, "o", l_GameEvent.Set(gameevent_h()));
12406  }
12407 
12408  return ade_set_args(L, "o", l_GameEvent.Set(gameevent_h(idx)));
12409 }
12410 
12411 ADE_FUNC(__len, l_Base_Events, NULL, "Number of events", "number", "Number of events")
12412 {
12413  return ade_set_args(L, "i", Num_gs_event_text);
12414 }
12415 
12416 //**********SUBLIBRARY: Base/States
12417 ade_lib l_Base_States("GameStates", &l_Base, NULL, "Freespace 2 states");
12418 
12419 ADE_INDEXER(l_Base_States, "number Index/string Name", "Array of game states", "gamestate", "Game state, or invalid gamestate handle if index is invalid")
12420 {
12421  char *name;
12422  if(!ade_get_args(L, "*s", &name))
12423  return ade_set_error(L, "o", l_GameState.Set(gamestate_h()));
12424 
12425  int idx = gameseq_get_state_idx(name);
12426 
12427  if(idx < 0)
12428  {
12429  idx = atoi(name);
12430 
12431  //Lua-->FS2
12432  idx--;
12433 
12434  if(idx < 0 || idx >= Num_gs_state_text)
12435  return ade_set_error(L, "o", l_GameState.Set(gamestate_h()));
12436  }
12437 
12438  return ade_set_args(L, "o", l_GameState.Set(gamestate_h(idx)));
12439 }
12440 
12441 ADE_FUNC(__len, l_Base_States, NULL, "Number of states", "number", "Number of states")
12442 {
12443  return ade_set_args(L, "i", Num_gs_state_text);
12444 }
12445 
12446 //**********LIBRARY: CFILE
12447 //WMC - It's on my to-do list! (Well, if I had one anyway)
12448 //WMC - Did it. I had to invent a to-do list first, though.
12449 //Ironically, I never actually put this on it.
12450 ade_lib l_CFile("CFile", NULL, "cf", "CFile FS2 filesystem access");
12451 
12452 int l_cf_get_path_id(char* n_path)
12453 {
12454  int i;
12455  int path_len = strlen(n_path);
12456 
12457  char *buf = (char*) vm_malloc((path_len+1) * sizeof(char));
12458 
12459  if (!buf)
12460  return CF_TYPE_INVALID;
12461 
12462  strcpy(buf, n_path);
12463 
12464  //Remove trailing slashes; avoid buffer overflow on 1-char strings
12465  i = path_len -1;
12466  while(i >= 0 && (buf[i] == '\\' || buf[i] == '/'))
12467  buf[i--] = '\0';
12468 
12469  //Remove leading slashes
12470  i = 0;
12471  while(i < path_len && (buf[i] == '\\' || buf[i] == '/'))
12472  buf[i++] = '\0';
12473 
12474  //Use official DIR_SEPARATOR_CHAR
12475  for(i = 0; i < path_len; i++)
12476  {
12477  if(buf[i] == '\\' || buf[i] == '/')
12478  buf[i] = DIR_SEPARATOR_CHAR;
12479  }
12480  for(i = 0; i < CF_MAX_PATH_TYPES; i++)
12481  {
12482  if(Pathtypes[i].path != NULL && !stricmp(buf, Pathtypes[i].path)) {
12483  vm_free(buf);
12484  buf = NULL;
12485  return Pathtypes[i].index;
12486  }
12487  }
12488 
12489  vm_free(buf);
12490  buf = NULL;
12491  return CF_TYPE_INVALID;
12492 }
12493 
12494 ADE_FUNC(deleteFile, l_CFile, "string Filename, string Path", "Deletes given file. Path must be specified. Use a slash for the root directory.", "boolean", "True if deleted, false")
12495 {
12496  char *n_filename = NULL;
12497  char *n_path = "";
12498  if(!ade_get_args(L, "ss", &n_filename, &n_path))
12499  return ade_set_error(L, "b", false);
12500 
12501  int path = CF_TYPE_INVALID;
12502  if(n_path != NULL && strlen(n_path))
12503  path = l_cf_get_path_id(n_path);
12504 
12505  if(path == CF_TYPE_INVALID)
12506  return ade_set_error(L, "b", false);
12507 
12508  return ade_set_args(L, "b", cf_delete(n_filename, path) != 0);
12509 }
12510 
12511 ADE_FUNC(fileExists, l_CFile, "string Filename, [string Path = \"\", boolean CheckVPs = false]", "Checks if a file exists. Use a blank string for path for any directory, or a slash for the root directory.", "boolean", "True if file exists, false or nil otherwise")
12512 {
12513  char *n_filename = NULL;
12514  char *n_path = "";
12515  bool check_vps = false;
12516  if(!ade_get_args(L, "s|sb", &n_filename, &n_path, &check_vps))
12517  return ADE_RETURN_NIL;
12518 
12519  int path = CF_TYPE_ANY;
12520  if(n_path != NULL && strlen(n_path))
12521  path = l_cf_get_path_id(n_path);
12522 
12523  if(path == CF_TYPE_INVALID)
12524  return ade_set_error(L, "b", false);
12525 
12526  if(!check_vps)
12527  return ade_set_args(L, "b", cf_exists(n_filename, path) != 0);
12528  else
12529  return ade_set_args(L, "b", cf_exists_full(n_filename, path ) != 0);
12530 }
12531 
12532 ADE_FUNC(openFile, l_CFile, "string Filename, [string Mode=\"r\", string Path = \"\"]",
12533  "Opens a file. 'Mode' uses standard C fopen arguments. Use a blank string for path for any directory, or a slash for the root directory."
12534  "Be EXTREMELY CAREFUL when using this function, as you may PERMANENTLY delete any file by accident",
12535  "file",
12536  "File handle, or invalid file handle if the specified file couldn't be opened")
12537 {
12538  char *n_filename = NULL;
12539  char *n_mode = "r";
12540  char *n_path = "";
12541  if(!ade_get_args(L, "s|ss", &n_filename, &n_mode, &n_path))
12542  return ade_set_error(L, "o", l_File.Set(NULL));
12543 
12544  int type = CFILE_NORMAL;
12545 
12546  int path = CF_TYPE_ANY;
12547  if(n_path != NULL && strlen(n_path))
12548  path = l_cf_get_path_id(n_path);
12549 
12550  if(path == CF_TYPE_INVALID)
12551  return ade_set_error(L, "o", l_File.Set(NULL));
12552 
12553  CFILE *cfp = cfopen(n_filename, n_mode, type, path);
12554 
12555  if(!cf_is_valid(cfp))
12556  return ade_set_error(L, "o", l_File.Set(NULL));
12557 
12558  return ade_set_args(L, "o", l_File.Set(cfp));
12559 }
12560 
12561 ADE_FUNC(openTempFile, l_CFile, NULL, "Opens a temp file that is automatically deleted when closed", "file", "File handle, or invalid file handle if tempfile couldn't be created")
12562 {
12563  return ade_set_args(L, "o", l_File.Set(ctmpfile()));
12564 }
12565 
12566 ADE_FUNC(renameFile, l_CFile, "string CurrentFilename, string NewFilename, string Path", "Renames given file. Path must be specified. Use a slash for the root directory.", "boolean", "True if file was renamed, otherwise false")
12567 {
12568  char *n_filename = NULL;
12569  char *n_new_filename = NULL;
12570  char *n_path = "";
12571  if(!ade_get_args(L, "ss|s", &n_filename, &n_new_filename, &n_path))
12572  return ade_set_error(L, "b", false);
12573 
12574  int path = CF_TYPE_INVALID;
12575  if(n_path != NULL && strlen(n_path))
12576  path = l_cf_get_path_id(n_path);
12577 
12578  if(path == CF_TYPE_INVALID)
12579  return ade_set_error(L, "b", false);
12580 
12581  return ade_set_args(L, "b", cf_rename(n_filename, n_new_filename, path) != 0);
12582 }
12583 
12584 //**********LIBRARY: Controls library
12585 ade_lib l_Mouse("Controls", NULL, "io", "Controls library");
12586 
12587 extern int mouse_inited;
12588 
12589 ADE_FUNC(getMouseX, l_Mouse, NULL, "Gets Mouse X pos", "number", "Mouse x position, or 0 if mouse is not initialized yet")
12590 {
12591  if(!mouse_inited)
12592  return ade_set_error(L, "i", 0);
12593 
12594  int x;
12595 
12596  mouse_get_pos(&x, NULL);
12597 
12598  return ade_set_args(L, "i", x);
12599 }
12600 
12601 ADE_FUNC(getMouseY, l_Mouse, NULL, "Gets Mouse Y pos", "number", "Mouse y position, or 0 if mouse is not initialized yet")
12602 {
12603  if(!mouse_inited)
12604  return ade_set_error(L, "i", 0);
12605 
12606  int y;
12607 
12608  mouse_get_pos(NULL, &y);
12609 
12610  return ade_set_args(L, "i", y);
12611 }
12612 
12613 ADE_FUNC(isMouseButtonDown, l_Mouse, "{MOUSE_*_BUTTON enumeration}, [..., ...]", "Returns whether the specified mouse buttons are up or down", "boolean", "Whether specified mouse buttons are down, or false if mouse is not initialized yet")
12614 {
12615  if(!mouse_inited)
12616  return ade_set_error(L, "b", false);
12617 
12618  enum_h *e[3] = {NULL, NULL, NULL};
12619  ade_get_args(L, "o|oo", l_Enum.GetPtr(&e[0]), l_Enum.GetPtr(&e[1]), l_Enum.GetPtr(&e[2])); //Like a snake!
12620 
12621  bool rtn = false;
12622  int check_flags = 0;
12623 
12624  for(int i = 0; i < 3; i++)
12625  {
12626  if(e[i] == NULL)
12627  break;
12628 
12629  if(e[i]->index == LE_MOUSE_LEFT_BUTTON)
12630  check_flags |= MOUSE_LEFT_BUTTON;
12631  if(e[i]->index == LE_MOUSE_MIDDLE_BUTTON)
12632  check_flags |= MOUSE_MIDDLE_BUTTON;
12633  if(e[i]->index == LE_MOUSE_RIGHT_BUTTON)
12634  check_flags |= MOUSE_RIGHT_BUTTON;
12635  }
12636 
12637  if(mouse_down(check_flags))
12638  rtn = true;
12639 
12640  return ade_set_args(L, "b", rtn);
12641 }
12642 
12643 ADE_FUNC(setCursorImage, l_Mouse, "Image filename, [LOCK or UNLOCK]", "Sets mouse cursor image, and allows you to lock/unlock the image. (A locked cursor may only be changed with the unlock parameter)", NULL, NULL)
12644 {
12645  if(!mouse_inited || !Gr_inited)
12646  return ADE_RETURN_NIL;
12647 
12648  char *s = NULL;
12649  enum_h *u = NULL;
12650  if(!ade_get_args(L, "s|o", &s, l_Enum.GetPtr(&u)))
12651  return ADE_RETURN_NIL;
12652 
12653  int ul = 0;
12654  if(u != NULL)
12655  {
12656  if(u->index == LE_LOCK)
12657  ul = GR_CURSOR_LOCK;
12658  else if(u->index == LE_UNLOCK)
12659  ul = GR_CURSOR_UNLOCK;
12660  }
12661 
12662  gr_set_cursor_bitmap(bm_load(s), ul);
12663 
12664  return ADE_RETURN_NIL;
12665 }
12666 
12667 ADE_FUNC(setCursorHidden, l_Mouse, "True to hide mouse, false to show it", "Shows or hides mouse cursor", NULL, NULL)
12668 {
12669  if(!mouse_inited)
12670  return ADE_RETURN_NIL;
12671 
12672  bool b = false;
12673  ade_get_args(L, "b", &b);
12674 
12675  if(b)
12676  Mouse_hidden = 1;
12677  else
12678  Mouse_hidden = 0;
12679 
12680  return ADE_RETURN_NIL;
12681 }
12682 
12683 ADE_FUNC(forceMousePosition, l_Mouse, "number, number (coordinates)", "function to force mouse position", "boolean", "if the operation succeeded or not")
12684 {
12685  if(!mouse_inited)
12686  return ADE_RETURN_FALSE;
12687 
12688  if(!Gr_inited)
12689  return ADE_RETURN_FALSE;
12690 
12691  int x, y;
12692  if (!(ade_get_args(L, "ii", &x, &y)))
12693  return ADE_RETURN_FALSE;
12694 
12695  if (!((x >= 0) && (x <= gr_screen.max_w)))
12696  return ADE_RETURN_FALSE;
12697 
12698  if (!((y >= 0) && (y <= gr_screen.max_h)))
12699  return ADE_RETURN_FALSE;
12700 
12701  mouse_set_pos(x, y);
12702 
12704 }
12705 
12706 ADE_VIRTVAR(MouseControlStatus, l_Mouse, "boolean", "Gets and sets the retail mouse control status", "boolean", "if the retail mouse is on or off")
12707 {
12708  if(!mouse_inited)
12709  return ADE_RETURN_NIL;
12710 
12711  bool newVal = false;
12712  if (!ade_get_args(L, "*|b", &newVal))
12713  return ADE_RETURN_NIL;
12714 
12715  if (ADE_SETTING_VAR)
12716  {
12717  if (newVal)
12718  {
12719  Use_mouse_to_fly = 1;
12720  }
12721  else
12722  {
12723  Use_mouse_to_fly = 0;
12724  }
12725  }
12726 
12727  if (Use_mouse_to_fly)
12728  return ADE_RETURN_TRUE;
12729  else
12730  return ADE_RETURN_FALSE;
12731 }
12732 
12733 ADE_FUNC(getMouseSensitivity, l_Mouse, NULL, "Gets mouse sensitivity setting", "number", "Mouse sensitivity in range of 0-9")
12734 {
12735  return ade_set_args(L, "i", Mouse_sensitivity);
12736 }
12737 
12738 ADE_FUNC(getJoySensitivity, l_Mouse, NULL, "Gets joystick sensitivity setting", "number", "Joystick sensitivity in range of 0-9")
12739 {
12740  return ade_set_args(L, "i", Joy_sensitivity);
12741 }
12742 
12743 ADE_FUNC(getJoyDeadzone, l_Mouse, NULL, "Gets joystick deadzone setting", "number", "Joystick deadzone in range of 0-9")
12744 {
12745  return ade_set_args(L, "i", Dead_zone_size / 5);
12746 }
12747 
12748 //trackir funcs
12749 ADE_FUNC(updateTrackIR, l_Mouse, NULL, "Updates Tracking Data. Call before using get functions", "boolean", "Checks if trackir is available and updates variables, returns true if successful, otherwise false")
12750 {
12751  if( !gTirDll_TrackIR.Enabled( ) )
12752  return ADE_RETURN_FALSE;
12753 
12754  if (gTirDll_TrackIR.Query( ) == 0)
12755  return ADE_RETURN_FALSE;
12756 
12757  return ade_set_args(L, "b", true);
12758 }
12759 
12760 ADE_FUNC(getTrackIRPitch, l_Mouse, NULL, "Gets pitch axis from last update", "number", "Pitch value -1 to 1, or 0 on failure")
12761 {
12762  if( !gTirDll_TrackIR.Enabled( ) )
12763  return ade_set_error(L, "f", 0.0f);
12764 
12765  return ade_set_args( L, "f", gTirDll_TrackIR.GetPitch( ) );
12766 }
12767 
12768 ADE_FUNC(getTrackIRYaw, l_Mouse, NULL, "Gets yaw axis from last update", "number", "Yaw value -1 to 1, or 0 on failure")
12769 {
12770  if( !gTirDll_TrackIR.Enabled( ) )
12771  return ade_set_error(L, "f", 0.0f);
12772 
12773  return ade_set_args(L, "f", gTirDll_TrackIR.GetYaw());
12774 }
12775 
12776 ADE_FUNC(getTrackIRRoll, l_Mouse, NULL, "Gets roll axis from last update", "number", "Roll value -1 to 1, or 0 on failure")
12777 {
12778  if( !gTirDll_TrackIR.Enabled( ) )
12779  return ade_set_error(L, "f", 0.0f);
12780 
12781  return ade_set_args(L, "f", gTirDll_TrackIR.GetRoll());
12782 }
12783 
12784 ADE_FUNC(getTrackIRX, l_Mouse, NULL, "Gets x position from last update", "number", "X value -1 to 1, or 0 on failure")
12785 {
12786  if( !gTirDll_TrackIR.Enabled( ) )
12787  return ade_set_error(L, "f", 0.0f);
12788 
12789  return ade_set_args(L, "f", gTirDll_TrackIR.GetX());
12790 }
12791 
12792 ADE_FUNC(getTrackIRY, l_Mouse, NULL, "Gets y position from last update", "number", "Y value -1 to 1, or 0 on failure")
12793 {
12794  if( !gTirDll_TrackIR.Enabled( ) )
12795  return ade_set_error(L, "f", 0.0f);
12796 
12797  return ade_set_args(L, "f", gTirDll_TrackIR.GetY());
12798 }
12799 
12800 ADE_FUNC(getTrackIRZ, l_Mouse, NULL, "Gets z position from last update", "number", "Z value -1 to 1, or 0 on failure")
12801 {
12802  if( !gTirDll_TrackIR.Enabled( ) )
12803  return ade_set_error(L, "f", 0.0f);
12804 
12805  return ade_set_args(L, "f", gTirDll_TrackIR.GetZ());
12806 }
12807 
12808 //**********LIBRARY: HUD library
12809 ade_lib l_HUD("HUD", NULL, "hu", "HUD library");
12810 
12811 ADE_VIRTVAR(HUDDrawn, l_HUD, "boolean", "Current HUD draw status", "boolean", "If the HUD is drawn or not")
12812 {
12813  bool to_draw = false;
12814 
12815  if(!ade_get_args(L, "*|b", &to_draw))
12816  return ADE_RETURN_NIL;
12817 
12818  if(ADE_SETTING_VAR)
12819  {
12820  if (to_draw)
12821  HUD_draw = 1;
12822  else
12823  HUD_draw = 0;
12824  }
12825 
12826  if (HUD_draw)
12827  return ADE_RETURN_TRUE;
12828  else
12829  return ADE_RETURN_FALSE;
12830 }
12831 
12832 ADE_VIRTVAR(HUDDisabledExceptMessages, l_HUD, "boolean", "Specifies if only the messages gauges of the hud are drawn", "boolean", "true if only the message gauges are drawn, false otherwise")
12833 {
12834  bool to_draw = false;
12835 
12836  if (!ade_get_args(L, "*|b", &to_draw))
12837  return ADE_RETURN_NIL;
12838 
12839  if (ADE_SETTING_VAR)
12840  {
12841  hud_disable_except_messages(to_draw);
12842  }
12843 
12845  return ADE_RETURN_TRUE;
12846  else
12847  return ADE_RETURN_FALSE;
12848 }
12849 
12850 ADE_FUNC(setHUDGaugeColor, l_HUD, "number (index number of the gauge), [integer red, number green, number blue, number alpha]", "Color used to draw the gauge", "boolean", "If the operation was successful")
12851 {
12852  int idx = -1;
12853  int r = 0;
12854  int g = 0;
12855  int b = 0;
12856  int a = 0;
12857 
12858  if(!ade_get_args(L, "i|iiii", &idx, &r, &g, &b, &a))
12859  return ADE_RETURN_FALSE;
12860 
12861  if ((idx < 0) || (idx >= NUM_HUD_GAUGES))
12862  return ADE_RETURN_FALSE;
12863 
12864  gr_init_alphacolor(&HUD_config.clr[idx], r, g, b, a);
12865 
12866  return ADE_RETURN_TRUE;
12867 }
12868 
12869 ADE_FUNC(getHUDGaugeColor, l_HUD, "number (index number of the gauge)", "Color used to draw the gauge", "number, number, number, number", "Red, green, blue, and alpha of the gauge")
12870 {
12871  int idx = -1;
12872 
12873  if(!ade_get_args(L, "i", &idx))
12874  return ADE_RETURN_NIL;
12875 
12876  if ((idx < 0) || (idx >= NUM_HUD_GAUGES))
12877  return ADE_RETURN_NIL;
12878 
12880 
12881  return ade_set_args(L, "iiii", (int) c.red, (int) c.green, (int) c.blue, (int) c.alpha);
12882 }
12883 
12884 ADE_FUNC(getHUDGaugeHandle, l_HUD, "string Name", "Returns a handle to a specified HUD gauge", "HudGauge", "HUD Gauge handle, or nil if invalid")
12885 {
12886  char* name;
12887  if (!ade_get_args(L, "s", &name))
12888  return ADE_RETURN_NIL;
12889  HudGauge* gauge = NULL;
12890 
12891  gauge = hud_get_gauge(name);
12892 
12893  if (gauge == NULL)
12894  return ADE_RETURN_NIL;
12895  else
12896  return ade_set_args(L, "o", l_HudGauge.Set(*gauge));
12897 }
12898 
12899 //**********LIBRARY: Graphics
12900 ade_lib l_Graphics("Graphics", NULL, "gr", "Graphics Library");
12901 
12902 //****SUBLIBRARY: Graphics/Cameras
12903 ade_lib l_Graphics_Cameras("Cameras", &l_Graphics, NULL, "Cameras");
12904 
12905 ADE_INDEXER(l_Graphics_Cameras, "number Index/string Name", "Gets camera", "camera", "Ship handle, or invalid ship handle if index was invalid")
12906 {
12907  char *s = NULL;
12908  if(!ade_get_args(L, "*s", &s))
12909  return ade_set_error(L, "o", l_Camera.Set(camid()));
12910 
12911  camid cid = cam_lookup(s);
12912  if(!cid.isValid())
12913  {
12914  int cn = atoi(s);
12915  if(cn > 0)
12916  {
12917  //Lua-->FS2
12918  cn--;
12919  cid = cam_get_camera(cn);
12920  }
12921  }
12922 
12923  return ade_set_args(L, "o", l_Camera.Set(cid));
12924 }
12925 
12926 ADE_FUNC(__len, l_Graphics_Cameras, NULL, "Gets number of cameras", "number", "Number of cameras")
12927 {
12928  return ade_set_args(L, "i", (int)cam_get_num());
12929 }
12930 
12931 //****SUBLIBRARY: Graphics/Fonts
12932 ade_lib l_Graphics_Fonts("Fonts", &l_Graphics, NULL, "Font library");
12933 
12934 ADE_FUNC(__len, l_Graphics_Fonts, NULL, "Number of loaded fonts", "number", "Number of loaded fonts")
12935 {
12936  return ade_set_args(L, "i", Num_fonts);
12937 }
12938 
12939 ADE_INDEXER(l_Graphics_Fonts, "number Index/string Filename", "Array of loaded fonts", "font", "Font handle, or invalid font handle if index is invalid")
12940 {
12941  char *s = NULL;
12942 
12943  if(!ade_get_args(L, "*s", &s))
12944  return ade_set_error(L, "o", l_Font.Set(-1));
12945 
12946  int fn = gr_get_fontnum(s);
12947  if(fn < 0)
12948  {
12949  fn = atoi(s);
12950  if(fn < 1 || fn > Num_fonts)
12951  return ade_set_error(L, "o", l_Font.Set(-1));
12952 
12953  //Lua->FS2
12954  fn--;
12955  }
12956 
12957  return ade_set_args(L, "o", l_Font.Set(fn));
12958 }
12959 
12960 ADE_VIRTVAR(CurrentFont, l_Graphics, "font", "Current font", "font", NULL)
12961 {
12962  int newfn = -1;
12963 
12964  if(!ade_get_args(L, "*|o", l_Font.Get(&newfn)))
12965  return ade_set_error(L, "o", l_Font.Set(-1));
12966 
12967  if(ADE_SETTING_VAR && newfn < Num_fonts) {
12968  gr_set_font(newfn);
12969  }
12970 
12971  int fn = gr_get_current_fontnum();
12972 
12973  if(fn < 0 || fn > Num_fonts)
12974  return ade_set_error(L, "o", l_Font.Set(-1));
12975 
12976  return ade_set_args(L, "o", l_Font.Set(fn));
12977 }
12978 
12979 //****SUBLIBRARY: Graphics/PostEffects
12980 ade_lib l_Graphics_Posteffects("PostEffects", &l_Graphics, NULL, "Post processing effects");
12981 
12982 ADE_INDEXER(l_Graphics_Posteffects, "number index", "Gets the name of the specified post processing index", "string", "post processing name or empty string on error")
12983 {
12984  int index = -1;
12985  if(!ade_get_args(L, "*i", &index))
12986  return ade_set_error(L, "s", "");
12987 
12988  index--; // Lua -> C/C++
12989 
12990  if (index < 0)
12991  return ade_set_error(L, "s", "");
12992 
12995  names.push_back(SCP_string("lightshafts"));
12996 
12997  if (index >= (int) names.size())
12998  return ade_set_error(L, "s", "");
12999 
13000  return ade_set_args(L, "s", const_cast<char*>(names[index].c_str()));
13001 }
13002 
13003 ADE_FUNC(__len, l_Graphics_Posteffects, NULL, "Gets the number or available post processing effects", "number", "number of post processing effects or 0 on error")
13004 {
13007 
13008  // Add one for lightshafts
13009  return ade_set_args(L, "i", ((int) names.size()) + 1);
13010 }
13011 
13012 ADE_FUNC(setPostEffect, l_Graphics, "string name, [number value=0]", "Sets the intensity of the specified post processing effect", "boolean", "true when successful, false otherwise")
13013 {
13014  char* name = NULL;
13015  int intensity = 0;
13016 
13017  if (!ade_get_args(L, "s|i", &name, &intensity))
13018  return ADE_RETURN_FALSE;
13019 
13020  if (name == NULL || intensity < 0)
13021  return ADE_RETURN_FALSE;
13022 
13023  gr_post_process_set_effect(name, intensity);
13024 
13025  return ADE_RETURN_TRUE;
13026 }
13027 
13028 ADE_FUNC(resetPostEffects, l_Graphics, NULL, "Resets all post effects to their default values", "boolean", "true if successful, false otherwise")
13029 {
13031 
13032  return ADE_RETURN_TRUE;
13033 }
13034 
13035 ADE_VIRTVAR(CurrentOpacityType, l_Graphics, "enumeration", "Current alpha blending type; uses ALPHABLEND_* enumerations", "enumeration", NULL)
13036 {
13037  enum_h *alphatype = NULL;
13038 
13039  if(!ade_get_args(L, "*|o", l_Enum.GetPtr(&alphatype)))
13040  return ADE_RETURN_NIL;
13041 
13042  if(ADE_SETTING_VAR)
13043  {
13044  if(alphatype != NULL && alphatype->index == LE_ALPHABLEND_FILTER)
13045  lua_Opacity_type = GR_ALPHABLEND_FILTER;
13046  else
13047  lua_Opacity_type = GR_ALPHABLEND_NONE;
13048  }
13049 
13050  int rtn;
13051  switch(lua_Opacity_type)
13052  {
13053  case GR_ALPHABLEND_FILTER:
13054  rtn = LE_ALPHABLEND_FILTER;
13055  break;
13056  default:
13057  rtn = LE_ALPHABLEND_NONE;
13058  }
13059 
13060  return ade_set_args(L, "o", l_Enum.Set(rtn));
13061 }
13062 
13063 ADE_VIRTVAR(CurrentRenderTarget, l_Graphics, "texture", "Current rendering target", "texture", "Current rendering target, or invalid texture handle if screen is render target")
13064 {
13065  int newtx = -1;
13066 
13067  if(ADE_SETTING_VAR && lua_isnil(L, 2))
13068  {
13071  }
13072  else
13073  {
13074 
13075  if(!ade_get_args(L, "*|o", l_Texture.Get(&newtx)))
13076  return ade_set_error(L, "o", l_Texture.Set(-1));
13077 
13078  if(ADE_SETTING_VAR) {
13079  if(newtx > -1 && bm_is_valid(newtx))
13080  bm_set_render_target(newtx, 0);
13081  else
13083  }
13084 
13086  }
13087 }
13088 
13089 ADE_FUNC(clearScreen, l_Graphics, "[integer red, number green, number blue, number alpha]", "Clears the screen to black, or the color specified.", NULL, NULL)
13090 {
13091  int r,g,b,a;
13092  r=g=b=0;
13093  a=255;
13094  ade_get_args(L, "|iiii", &r, &g, &b, &a);
13095 
13096  //WMC - Set to valid values
13097  if(r != 0 || g != 0 || b != 0 || a!= 255)
13098  {
13099  CAP(r,0,255);
13100  CAP(g,0,255);
13101  CAP(b,0,255);
13102  CAP(a,0,255);
13103  gr_set_clear_color(r,g,b);
13105  gr_clear();
13106  gr_set_clear_color(0,0,0);
13107 
13108  return ADE_RETURN_NIL;
13109  }
13110 
13111  gr_clear();
13112  return ADE_RETURN_NIL;
13113 }
13114 
13115 ADE_FUNC(createCamera, l_Graphics,
13116  "string Name, [wvector Position, orientation Orientation]",
13117  "Creates a new camera using the specified position and orientation (World)",
13118  "camera",
13119  "Camera handle, or invalid camera handle if camera couldn't be created")
13120 {
13121  char *s = NULL;
13122  vec3d *v = &vmd_zero_vector;
13123  matrix_h *mh = NULL;
13124  if(!ade_get_args(L, "s|oo", &s, l_Vector.GetPtr(&v), l_Matrix.GetPtr(&mh)))
13125  return ADE_RETURN_NIL;
13126 
13127  matrix *mtx = &vmd_identity_matrix;
13128  if(mh != NULL)
13129  mtx = mh->GetMatrix();
13130  camid cid = cam_create(s, v, mtx);
13131 
13132  //Set position
13133  return ade_set_args(L, "o", l_Camera.Set(cid));
13134 }
13135 
13136 ADE_FUNC(isMenuStretched, l_Graphics, NULL, "Returns whether the standard interface is stretched", "boolean", "True if stretched, false if aspect ratio is maintained")
13137 {
13138  if(!Gr_inited)
13139  return ade_set_error(L, "b", 0);
13140 
13141  return ade_set_args(L, "b", Cmdline_stretch_menu);
13142 }
13143 
13144 ADE_FUNC(getScreenWidth, l_Graphics, NULL, "Gets screen width", "number", "Width in pixels, or 0 if graphics are not initialized yet")
13145 {
13146  if(!Gr_inited)
13147  return ade_set_error(L, "i", 0);
13148 
13149  return ade_set_args(L, "i", gr_screen.max_w);
13150 }
13151 
13152 ADE_FUNC(getScreenHeight, l_Graphics, NULL, "Gets screen height", "number", "Height in pixels, or 0 if graphics are not initialized yet")
13153 {
13154  if(!Gr_inited)
13155  return ade_set_error(L, "i", 0);
13156 
13157  return ade_set_args(L, "i", gr_screen.max_h);
13158 }
13159 
13160 ADE_FUNC(getCenterWidth, l_Graphics, NULL, "Gets width of center monitor (should be used in conjuction with getCenterOffsetX)", "number", "Width of center monitor in pixels, or 0 if graphics are not initialized yet")
13161 {
13162  if(!Gr_inited)
13163  return ade_set_error(L, "i", 0);
13164 
13165  return ade_set_args(L, "i", gr_screen.center_w);
13166 }
13167 
13168 ADE_FUNC(getCenterHeight, l_Graphics, NULL, "Gets height of center monitor (should be used in conjuction with getCenterOffsetY)", "number", "Height of center monitor in pixels, or 0 if graphics are not initialized yet")
13169 {
13170  if(!Gr_inited)
13171  return ade_set_error(L, "i", 0);
13172 
13173  return ade_set_args(L, "i", gr_screen.center_h);
13174 }
13175 
13176 ADE_FUNC(getCenterOffsetX, l_Graphics, NULL, "Gets X offset of center monitor", "number", "X offset of center monitor in pixels")
13177 {
13178  if(!Gr_inited)
13179  return ade_set_error(L, "i", 0);
13180 
13181  return ade_set_args(L, "i", gr_screen.center_offset_x);
13182 }
13183 
13184 ADE_FUNC(getCenterOffsetY, l_Graphics, NULL, "Gets Y offset of center monitor", "number", "Y offset of center monitor in pixels")
13185 {
13186  if(!Gr_inited)
13187  return ade_set_error(L, "i", 0);
13188 
13189  return ade_set_args(L, "i", gr_screen.center_offset_y);
13190 }
13191 
13192 ADE_FUNC(getCurrentCamera, l_Graphics, "[boolean]", "Gets the current camera handle, if argument is <i>true</i> then it will also return the main camera when no custom camera is in use", "camera", "camera handle or invalid handle on error")
13193 {
13194  camid current;
13195 
13196  bool rtnMain = false;
13197 
13198  ade_get_args(L, "|b", &rtnMain);
13199 
13200  if (!rtnMain || Viewer_mode & VM_FREECAMERA)
13201  current = cam_get_current();
13202  else
13203  current = Main_camera;
13204 
13205  return ade_set_args(L, "o", l_Camera.Set(current));
13206 }
13207 
13208 ADE_FUNC(getVectorFromCoords, l_Graphics,
13209  "[number X=center, number Y=center, number Depth, boolean normalize = false]",
13210  "Returns a vector through screen coordinates x and y. "
13211  "If depth is specified, vector is extended to Depth units into space"
13212  "If normalize is true, vector will be normalized.",
13213  "vector",
13214  "Vector, or zero vector on failure")
13215 {
13216  int x = gr_screen.max_w/2;
13217  int y = gr_screen.max_h/2;
13218  float depth = 0.0f;
13219  bool normalize = false;
13220  ade_get_args(L, "|iifb", &x, &y, &depth, &normalize);
13221 
13223 
13224  bool in_frame = g3_in_frame() > 0;
13225  if(!in_frame) {
13226  g3_start_frame(0);
13227 
13228  vec3d cam_pos;
13229  matrix cam_orient;
13230 
13231  camid cid;
13232  if (Viewer_mode & VM_FREECAMERA)
13233  cid = cam_get_current();
13234  else
13235  cid = Main_camera;
13236 
13237  camera *cam = cid.getCamera();
13238 
13239  if (cam != NULL) {
13240  cam->get_info(&cam_pos, &cam_orient);
13241  g3_set_view_matrix(&cam_pos, &cam_orient, View_zoom);
13242  } else {
13244  }
13245 
13248  }
13249 
13250  g3_point_to_vec(&pos, x, y);
13251 
13252  if(!in_frame) {
13255  g3_end_frame();
13256  }
13257 
13258  if(depth)
13259  vm_vec_scale(&pos, depth);
13260 
13261  if (normalize)
13262  vm_vec_normalize_quick(&pos);
13263 
13264  vm_vec_add2(&pos, &View_position);
13265 
13266  return ade_set_args(L, "o", l_Vector.Set(pos));
13267 }
13268 
13269 ADE_FUNC(setTarget, l_Graphics, "[texture Texture]",
13270  "If texture is specified, sets current rendering surface to a texture."
13271  "Otherwise, sets rendering surface back to screen.",
13272  "boolean",
13273  "True if successful, false otherwise")
13274 {
13275  if(!Gr_inited)
13276  return ade_set_error(L, "b", false);
13277 
13278  int idx = -1;
13279  ade_get_args(L, "|o", l_Texture.Get(&idx));
13280 
13281  return ade_set_args(L, "b", bm_set_render_target(idx, 0));
13282 }
13283 
13284 ADE_FUNC(setCamera, l_Graphics, "[camera handle Camera]", "Sets current camera, or resets camera if none specified", "boolean", "true if successful, false or nil otherwise")
13285 {
13286  camid cid;
13287  if(!ade_get_args(L, "|o", l_Camera.Get(&cid)))
13288  {
13289  cam_reset_camera();
13290  return ADE_RETURN_NIL;
13291  }
13292 
13293  if(!cid.isValid())
13294  return ADE_RETURN_NIL;
13295 
13296  cam_set_camera(cid);
13297 
13298  return ADE_RETURN_TRUE;
13299 }
13300 
13301 ADE_FUNC(setColor, l_Graphics, "integer Red, number Green, number Blue, [integer Alpha]", "Sets 2D drawing color; each color number should be from 0 (darkest) to 255 (brightest)", NULL, NULL)
13302 {
13303  if(!Gr_inited)
13304  return ADE_RETURN_NIL;
13305 
13306  int r,g,b,a=255;
13307 
13308  if(!ade_get_args(L, "iii|i", &r, &g, &b, &a))
13309  return ADE_RETURN_NIL;
13310 
13311  color ac;
13312  gr_init_alphacolor(&ac,r,g,b,a);
13313  gr_set_color_fast(&ac);
13314 
13315  return ADE_RETURN_NIL;
13316 }
13317 
13318 ADE_FUNC(setLineWidth, l_Graphics, "[number width=1.0]", "Sets the line width for lines. This call might fail if the specified width is not supported by the graphics implementation. Then the width will be the nearest supported value.", "boolean", "true if succeeded, false otherwise")
13319 {
13320  if(!Gr_inited)
13321  return ADE_RETURN_FALSE;
13322 
13323  float width = 1.0f;
13324 
13325  ade_get_args(L, "|f", &width);
13326 
13327  if (width <= 0.0f)
13328  {
13329  return ADE_RETURN_FALSE;
13330  }
13331 
13332  gr_set_line_width(width);
13333 
13334  return ADE_RETURN_TRUE;
13335 }
13336 
13337 ADE_FUNC(drawCircle, l_Graphics, "number Radius, number X, number Y, [boolean Filled=true]", "Draws a circle", NULL, NULL)
13338 {
13339  if(!Gr_inited)
13340  return ADE_RETURN_NIL;
13341 
13342  int x,y,ra;
13343  bool fill = true;
13344 
13345  if(!ade_get_args(L, "iii|b", &ra,&x,&y,&fill))
13346  return ADE_RETURN_NIL;
13347 
13348  if (fill) {
13349  //WMC - Circle takes...diameter.
13350  gr_circle(x,y, ra*2, GR_RESIZE_NONE);
13351  } else {
13352  gr_unfilled_circle(x,y, ra*2, GR_RESIZE_NONE);
13353  }
13354 
13355  return ADE_RETURN_NIL;
13356 }
13357 
13358 ADE_FUNC(drawArc, l_Graphics, "number Radius, number X, number Y, number StartAngle, number EndAngle, [boolean Filled=true]", "Draws an arc", NULL, NULL)
13359 {
13360  if(!Gr_inited)
13361  return ADE_RETURN_NIL;
13362 
13363  int x,y;
13364  float ra,angle_start,angle_end;
13365  bool fill = true;
13366 
13367  if(!ade_get_args(L, "fiiff|b", &ra,&x,&y,&angle_start,&angle_end,&fill)) {
13368  return ADE_RETURN_NIL;
13369  }
13370 
13371  gr_arc(x,y, ra, angle_start, angle_end, fill, GR_RESIZE_NONE);
13372 
13373  return ADE_RETURN_NIL;
13374 }
13375 
13376 ADE_FUNC(drawCurve, l_Graphics, "number X, number Y, number Radius", "Draws a curve", NULL, NULL)
13377 {
13378  if(!Gr_inited)
13379  return ADE_RETURN_NIL;
13380 
13381  int x,y,ra;
13382 
13383  if(!ade_get_args(L, "iii", &x,&y,&ra))
13384  return ADE_RETURN_NIL;
13385 
13386  //WMC - direction should be settable at a certain point via enumerations.
13387  //Not gonna deal with it now.
13388  gr_curve(x,y,ra,0,GR_RESIZE_FULL);
13389 
13390  return ADE_RETURN_NIL;
13391 }
13392 
13393 ADE_FUNC(drawGradientLine, l_Graphics, "number X1, number Y1, number X2, number Y2", "Draws a line from (x1,y1) to (x2,y2) with the CurrentColor that steadily fades out", NULL, NULL)
13394 {
13395  if(!Gr_inited)
13396  return 0;
13397 
13398  int x1,y1,x2,y2;
13399 
13400  if(!ade_get_args(L, "iiii", &x1, &y1, &x2, &y2))
13401  return ADE_RETURN_NIL;
13402 
13403  gr_gradient(x1,y1,x2,y2,GR_RESIZE_NONE);
13404 
13405  return ADE_RETURN_NIL;
13406 }
13407 
13408 ADE_FUNC(drawLine, l_Graphics, "number X1, number Y1, number X2, number Y2", "Draws a line from (x1,y1) to (x2,y2) with CurrentColor", NULL, NULL)
13409 {
13410  if(!Gr_inited)
13411  return ADE_RETURN_NIL;
13412 
13413  int x1,y1,x2,y2;
13414 
13415  if(!ade_get_args(L, "iiii", &x1, &y1, &x2, &y2))
13416  return ADE_RETURN_NIL;
13417 
13418  gr_line(x1,y1,x2,y2,GR_RESIZE_NONE);
13419 
13420  return ADE_RETURN_NIL;
13421 }
13422 
13423 ADE_FUNC(drawPixel, l_Graphics, "number X, number Y", "Sets pixel to CurrentColor", NULL, NULL)
13424 {
13425  if(!Gr_inited)
13426  return ADE_RETURN_NIL;
13427 
13428  int x,y;
13429 
13430  if(!ade_get_args(L, "ii", &x, &y))
13431  return ADE_RETURN_NIL;
13432 
13433  gr_pixel(x,y,GR_RESIZE_NONE);
13434 
13435  return ADE_RETURN_NIL;
13436 }
13437 
13438 ADE_FUNC(drawPolygon, l_Graphics, "texture Texture, [vector Position={0,0,0}, orientation Orientation=nil, number Width=1.0, number Height=1.0]", "Draws a polygon. May not work properly in hooks other than On Object Render.", NULL, NULL)
13439 {
13440  int tdx = -1;
13442  matrix_h *mh = NULL;
13443  float width = 1.0f;
13444  float height = 1.0f;
13445  if(!ade_get_args(L, "o|ooff", l_Texture.Get(&tdx), l_Vector.Get(&pos), l_Matrix.GetPtr(&mh), &width, &height))
13446  return ADE_RETURN_NIL;
13447 
13448  if(!bm_is_valid(tdx))
13449  return ADE_RETURN_FALSE;
13450 
13451  matrix *orip = &vmd_identity_matrix;
13452  if(mh != NULL)
13453  orip = mh->GetMatrix();
13454 
13455  //Do 3D stuff
13456  bool in_frame = g3_in_frame() > 0;
13457  if(!in_frame)
13458  g3_start_frame(0);
13459 
13460  gr_set_bitmap(tdx, lua_Opacity_type, GR_BITBLT_MODE_NORMAL, lua_Opacity);
13461  g3_draw_polygon(&pos, orip, width, height, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT);
13462 
13463  if(!in_frame)
13464  g3_end_frame();
13465 
13466  return ADE_RETURN_TRUE;
13467 }
13468 
13469 ADE_FUNC(drawRectangle, l_Graphics, "number X1, number Y1, number X2, number Y2, [boolean Filled=true]", "Draws a rectangle with CurrentColor", NULL, NULL)
13470 {
13471  if(!Gr_inited)
13472  return ADE_RETURN_NIL;
13473 
13474  int x1,y1,x2,y2;
13475  bool f=true;
13476 
13477  if(!ade_get_args(L, "iiii|b", &x1, &y1, &x2, &y2, &f))
13478  return ADE_RETURN_NIL;
13479 
13480  if(f)
13481  {
13482  gr_set_bitmap(0); // gr_rect will use the last bitmaps info, so set to zero to flush any previous alpha state
13483  gr_rect(x1, y1, x2-x1, y2-y1, GR_RESIZE_NONE);
13484  }
13485  else
13486  {
13487  gr_line(x1,y1,x2,y1,GR_RESIZE_NONE); //Top
13488  gr_line(x1,y2,x2,y2,GR_RESIZE_NONE); //Bottom
13489  gr_line(x1,y1,x1,y2,GR_RESIZE_NONE); //Left
13490  gr_line(x2,y1,x2,y2,GR_RESIZE_NONE); //Right
13491  }
13492 
13493  return ADE_RETURN_NIL;
13494 }
13495 
13496 ADE_FUNC(drawSphere, l_Graphics, "[number Radius = 1.0, vector Position]", "Draws a sphere with radius Radius at world vector Position. May not work properly in hooks other than On Object Render.", "boolean", "True if successful, false or nil otherwise")
13497 {
13498  float rad = 1.0f;
13500  ade_get_args(L, "|fo", &rad, l_Vector.Get(&pos));
13501 
13502  bool in_frame = g3_in_frame() > 0;
13503  if(!in_frame) {
13504  g3_start_frame(0);
13505 
13506  vec3d cam_pos;
13507  matrix cam_orient;
13508 
13509  camid cid;
13510 
13511  if (Viewer_mode & VM_FREECAMERA)
13512  cid = cam_get_current();
13513  else
13514  cid = Main_camera;
13515 
13516  camera *cam = cid.getCamera();
13517 
13518  if (cam != NULL) {
13519  cam->get_info(&cam_pos, &cam_orient);
13520  g3_set_view_matrix(&cam_pos, &cam_orient, View_zoom);
13521  } else {
13523  }
13524 
13527  }
13528 
13529  vertex vtx;
13530  vtx.world = pos;
13531  g3_rotate_vertex(&vtx, &pos);
13532  g3_draw_sphere(&vtx, rad);
13533 
13534  if(!in_frame) {
13537  g3_end_frame();
13538  }
13539  return ADE_RETURN_TRUE;
13540 }
13541 
13542 // Aardwolf's test code to render a model, supposed to emulate WMC's gr.drawModel function
13543 ADE_FUNC(drawModel, l_Graphics, "model, position, orientation", "Draws the given model with the specified position and orientation - Use with extreme care, may not work properly in all scripting hooks.", "int", "Zero if successful, otherwise an integer error code")
13544 {
13545  model_h *mdl = NULL;
13546  vec3d *v = &vmd_zero_vector;
13547  matrix_h *mh = NULL;
13548  if(!ade_get_args(L, "ooo", l_Model.GetPtr(&mdl), l_Vector.GetPtr(&v), l_Matrix.GetPtr(&mh)))
13549  return ade_set_args(L, "i", 1);
13550 
13551  if(mdl == NULL)
13552  return ade_set_args(L, "i", 2);
13553 
13554  int model_num = mdl->GetID();
13555  if(model_num < 0)
13556  return ade_set_args(L, "i", 3);
13557 
13558  //Handle angles
13559  matrix *orient = mh->GetMatrix();
13560 
13561  //Clip
13563 
13564  //Handle 3D init stuff
13565  g3_start_frame(1);
13566 
13567  vec3d cam_pos;
13568  matrix cam_orient;
13569 
13570  camid cid;
13571  if (Viewer_mode & VM_FREECAMERA)
13572  cid = cam_get_current();
13573  else
13574  cid = Main_camera;
13575 
13576  camera *cam = cid.getCamera();
13577 
13578  if (cam != NULL) {
13579  cam->get_info(&cam_pos, &cam_orient);
13580  g3_set_view_matrix(&cam_pos, &cam_orient, View_zoom);
13581  } else {
13583  }
13584 
13587 
13588  //Draw the ship!!
13589  model_clear_instance(model_num);
13591  model_render_params render_info;
13592 
13593  render_info.set_detail_level_lock(0);
13594 
13595  model_render_immediate(&render_info, model_num, orient, v);
13596 
13597  //OK we're done
13600 
13601  //Bye!!
13602  g3_end_frame();
13603  gr_reset_clip();
13604 
13605  return ade_set_args(L, "i", 0);
13606 }
13607 
13608 // Wanderer
13609 ADE_FUNC(drawModelOOR, l_Graphics, "model Model, vector Position, matrix Orientation, [integer Flags]", "Draws the given model with the specified position and orientation - Use with extreme care, designed to operate properly only in On Object Render hooks.", "int", "Zero if successful, otherwise an integer error code")
13610 {
13611  model_h *mdl = NULL;
13612  vec3d *v = &vmd_zero_vector;
13613  matrix_h *mh = NULL;
13614  int flags = MR_NORMAL;
13615  if(!ade_get_args(L, "ooo|i", l_Model.GetPtr(&mdl), l_Vector.GetPtr(&v), l_Matrix.GetPtr(&mh), &flags))
13616  return ade_set_args(L, "i", 1);
13617 
13618  if(mdl == NULL)
13619  return ade_set_args(L, "i", 2);
13620 
13621  polymodel *pm = mdl->Get();
13622 
13623  if (pm == NULL)
13624  return ade_set_args(L, "i", 3);
13625 
13626  int model_num = pm->id;
13627 
13628  if(model_num < 0)
13629  return ade_set_args(L, "i", 3);
13630 
13631  //Handle angles
13632  matrix *orient = mh->GetMatrix();
13633 
13634  //Draw the ship!!
13635  model_clear_instance(model_num);
13636 
13637  model_render_params render_info;
13638  render_info.set_flags(flags);
13639 
13640  model_render_immediate(&render_info, model_num, orient, v);
13641 
13642  return ade_set_args(L, "i", 0);
13643 }
13644 
13645 // Aardwolf's targeting brackets function
13646 ADE_FUNC(drawTargetingBrackets, l_Graphics, "object Object, [boolean draw=true, int padding=5]",
13647  "Gets the edge positions of targeting brackets for the specified object. The brackets will only be drawn if draw is true or the default value of draw is used. Brackets are drawn with the current color. The brackets will have a padding (distance from the actual bounding box); the default value (used elsewhere in FS2) is 5.",
13648  "number,number,number,number",
13649  "Left, top, right, and bottom positions of the brackets, or nil if invalid")
13650 {
13651  if(!Gr_inited) {
13652  return ADE_RETURN_NIL;
13653  }
13654 
13655  object_h *objh = NULL;
13656  bool draw_box = true;
13657  int padding = 5;
13658 
13659  if( !ade_get_args(L, "o|bi", l_Object.GetPtr(&objh), &draw_box, &padding) ) {
13660  return ADE_RETURN_NIL;
13661  }
13662 
13663  // The following code is mostly copied from
13664  // void hud_show_brackets(object *targetp, vertex *projected_v)
13665  // in hudtarget.cpp
13666 
13667  if( !objh->IsValid()) {
13668  return ADE_RETURN_NIL;
13669  }
13670 
13671  object *targetp = objh->objp;
13672 
13673  int x1,x2,y1,y2;
13674  int bound_rc, pof;
13675  int modelnum;
13676  bool entered_frame = false;
13678 
13679  if ( !(g3_in_frame( ) > 0 ) )
13680  {
13681  g3_start_frame( 0 );
13682  entered_frame = true;
13683  }
13684 
13685 
13686  switch ( targetp->type ) {
13687  case OBJ_SHIP:
13688  modelnum = Ship_info[Ships[targetp->instance].ship_info_index].model_num;
13689  bound_rc = model_find_2d_bound_min( modelnum, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
13690  if ( bound_rc != 0 ) {
13691  if ( entered_frame )
13692  g3_end_frame( );
13693  return ADE_RETURN_NIL;
13694  }
13695  break;
13696  case OBJ_DEBRIS:
13697  modelnum = Debris[targetp->instance].model_num;
13698  bound_rc = submodel_find_2d_bound_min( modelnum, Debris[targetp->instance].submodel_num, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
13699  if ( bound_rc != 0 ) {
13700  if ( entered_frame )
13701  g3_end_frame( );
13702  return ADE_RETURN_NIL;
13703  }
13704  break;
13705  case OBJ_WEAPON:
13707  modelnum = Weapon_info[Weapons[targetp->instance].weapon_info_index].model_num;
13708  bound_rc = model_find_2d_bound_min( modelnum, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
13709  break;
13710  case OBJ_ASTEROID:
13711  pof = Asteroids[targetp->instance].asteroid_subtype;
13712  modelnum = Asteroid_info[Asteroids[targetp->instance].asteroid_type].model_num[pof];
13713  bound_rc = model_find_2d_bound_min( modelnum, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
13714  break;
13715  case OBJ_JUMP_NODE:
13716  for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
13717  if(jnp->GetSCPObject() == targetp)
13718  break;
13719  }
13720 
13721  modelnum = jnp->GetModelNumber();
13722  bound_rc = model_find_2d_bound_min( modelnum, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
13723  break;
13724  default: //Someone passed an invalid pointer.
13725  if ( entered_frame )
13726  g3_end_frame( );
13727  return ADE_RETURN_NIL;
13728  }
13729 
13730  x1 -= padding;
13731  x2 += padding;
13732  y1 -= padding;
13733  y2 += padding;
13734  if ( draw_box ) {
13735  draw_brackets_square(x1, y1, x2, y2, GR_RESIZE_NONE);
13736  }
13737 
13738  if ( entered_frame )
13739  g3_end_frame( );
13740 
13741  return ade_set_args(L, "iiii", x1, y1, x2, y2);
13742 }
13743 
13744 ADE_FUNC(drawSubsystemTargetingBrackets, l_Graphics, "subsystem subsys, [boolean draw=true, boolean setColor=false]",
13745  "Gets the edge position of the targeting brackets drawn for a subsystem as if they were drawn on the HUD. Only actually draws the brackets if <i>draw</i> is true, optionally sets the color the as if it was drawn on the HUD",
13746  "number,number,number,number",
13747  "Left, top, right, and bottom positions of the brackets, or nil if invalid or off-screen")
13748 {
13749  if(!Gr_inited) {
13750  return ADE_RETURN_NIL;
13751  }
13752 
13753  ship_subsys_h *sshp = NULL;
13754  bool draw = true;
13755  bool set_color = false;
13756 
13757  if( !ade_get_args(L, "o|bb", l_Subsystem.GetPtr(&sshp), &draw, &set_color) ) {
13758  return ADE_RETURN_NIL;
13759  }
13760 
13761  if (!sshp->IsValid())
13762  {
13763  return ADE_RETURN_NIL;
13764  }
13765 
13766  bool entered_frame = false;
13767 
13768  if ( !(g3_in_frame( ) > 0 ) )
13769  {
13770  g3_start_frame( 0 );
13771  entered_frame = true;
13772  }
13773 
13774  int coords[4];
13775 
13776  int in_sight = draw_subsys_brackets(sshp->ss, 24, 24, draw, set_color, coords);
13777 
13778  if ( entered_frame )
13779  g3_end_frame( );
13780 
13781  if (in_sight > 0)
13782  {
13783  return ade_set_args(L, "iiii", coords[0], coords[1], coords[2], coords[3]);
13784  }
13785  else
13786  {
13787  return ADE_RETURN_NIL;
13788  }
13789 }
13790 
13791 ADE_FUNC(drawOffscreenIndicator, l_Graphics, "object Object, [boolean draw=true, boolean setColor=false]",
13792  "Draws an off-screen indicator for the given object. The indicator will not be drawn if draw=false, but the coordinates will be returned in either case. The indicator will be drawn using the current color if setColor=true and using the IFF color of the object if setColor=false.",
13793  "number,number",
13794  "Coordinates of the indicator (at the very edge of the screen), or nil if object is on-screen")
13795 {
13796  object_h *objh = NULL;
13797  bool draw = false;
13798  bool setcolor = false;
13799  vec2d outpoint = { -1.0f, -1.0f };
13800 
13801  if(!Gr_inited) {
13802  return ADE_RETURN_NIL;
13803  }
13804 
13805  if( !ade_get_args(L, "o|bb", l_Object.GetPtr(&objh), &draw, &setcolor) ) {
13806  return ADE_RETURN_NIL;
13807  }
13808 
13809  if( !objh->IsValid()) {
13810  return ADE_RETURN_NIL;
13811  }
13812 
13813  object *targetp = objh->objp;
13814  bool in_frame = g3_in_frame() > 0;
13815 
13816  if (!in_frame)
13817  g3_start_frame(0);
13818 
13819  vertex target_point;
13820  g3_rotate_vertex(&target_point, &targetp->pos);
13821  g3_project_vertex(&target_point);
13822 
13823  if (!in_frame)
13824  g3_end_frame();
13825 
13826  if(target_point.codes == 0)
13827  return ADE_RETURN_NIL;
13828 
13830  hud_target_add_display_list(targetp, &target_point, &targetp->pos, 5, NULL, NULL, TARGET_DISPLAY_DIST);
13831 
13832  size_t j, num_gauges;
13833  num_gauges = default_hud_gauges.size();
13834 
13835  for(j = 0; j < num_gauges; j++) {
13836  if (default_hud_gauges[j]->getObjectType() == HUD_OBJECT_OFFSCREEN) {
13837  HudGaugeOffscreen *offscreengauge = static_cast<HudGaugeOffscreen*>(default_hud_gauges[j]);
13838 
13839  offscreengauge->preprocess();
13840  offscreengauge->onFrame(flFrametime);
13841 
13842  if ( !offscreengauge->canRender() ) {
13843  break;
13844  }
13845 
13846  offscreengauge->resetClip();
13847  offscreengauge->setFont();
13848  int dir;
13849  float tri_separation;
13850 
13851  offscreengauge->calculatePosition(&target_point, &targetp->pos, &outpoint, &dir, &tri_separation);
13852 
13853  if (draw) {
13854  float distance = hud_find_target_distance(targetp, Player_obj);
13855 
13856  if (!setcolor)
13857  hud_set_iff_color(targetp, 1);
13858 
13859  offscreengauge->renderOffscreenIndicator(&outpoint, dir, distance, tri_separation, true);
13860  }
13861 
13862  offscreengauge->resize(&outpoint.x, &outpoint.y);
13863 
13864  break;
13865  }
13866  }
13867 
13868  if (outpoint.x >= 0 && outpoint.y >=0)
13869  return ade_set_args(L, "ii", (int)outpoint.x, (int)outpoint.y);
13870  else
13871  return ADE_RETURN_NIL;
13872 }
13873 
13874 #define MAX_TEXT_LINES 256
13875 static char *BooleanValues[] = {"False", "True"};
13876 static const int NextDrawStringPosInitial[] = {0, 0};
13877 static int NextDrawStringPos[] = {NextDrawStringPosInitial[0], NextDrawStringPosInitial[1]};
13878 ADE_FUNC(drawString, l_Graphics, "string Message, [number X1, number Y1, number X2, number Y2]",
13879  "Draws a string. Use x1/y1 to control position, x2/y2 to limit textbox size."
13880  "Text will automatically move onto new lines, if x2/y2 is specified."
13881  "Additionally, calling drawString with only a string argument will automatically"
13882  "draw that string below the previously drawn string (or 0,0 if no strings"
13883  "have been drawn yet",
13884  "number",
13885  "Number of lines drawn, or 0 on failure")
13886 {
13887  if(!Gr_inited)
13888  return ade_set_error(L, "i", 0);
13889 
13890  int x=NextDrawStringPos[0];
13891  int y = NextDrawStringPos[1];
13892 
13893  char *s = "(null)";
13894  int x2=-1,y2=-1;
13895  int num_lines = 0;
13896 
13897  if(lua_isboolean(L, 1))
13898  {
13899  bool b = false;
13900  if(!ade_get_args(L, "b|iiii", &b, &x, &y, &x2, &y2))
13901  return ade_set_error(L, "i", 0);
13902 
13903  if(b)
13904  s = BooleanValues[1];
13905  else
13906  s = BooleanValues[0];
13907  }
13908  else if(lua_isstring(L, 1))
13909  {
13910  if(!ade_get_args(L, "s|iiii", &s, &x, &y, &x2, &y2))
13911  return ade_set_error(L, "i", 0);
13912  }
13913  else
13914  {
13915  ade_get_args(L, "|*iiii", &x, &y, &x2, &y2);
13916  }
13917 
13918  NextDrawStringPos[0] = x;
13919  if(x2 < 0)
13920  {
13921  num_lines = 1;
13922  gr_string(x,y,s,GR_RESIZE_NONE);
13923 
13924  int height = 0;
13925  gr_get_string_size(NULL, &height, s);
13926  NextDrawStringPos[1] = y+height;
13927  }
13928  else
13929  {
13930  int linelengths[MAX_TEXT_LINES];
13931  const char *linestarts[MAX_TEXT_LINES];
13932 
13933  if (y2 >= 0 && y2 < y)
13934  {
13935  // Invalid y2 value
13936  Warning(LOCATION, "Illegal y2 value passed to drawString. Got %d y2 value but %d for y.", y2, y);
13937 
13938  int temp = y;
13939  y = y2;
13940  y2 = temp;
13941  }
13942 
13943  num_lines = split_str(s, x2-x, linelengths, linestarts, MAX_TEXT_LINES);
13944 
13945  //Make sure we don't go over size
13946  int line_ht = gr_get_font_height();
13947  num_lines = MIN(num_lines, (y2 - y) / line_ht);
13948 
13949  int curr_y = y;
13950  for(int i = 0; i < num_lines; i++)
13951  {
13952  //Contrary to WMC's previous comment, let's make a new string each line
13953  int len = linelengths[i];
13954  char *buf = new char[len+1];
13955  strncpy(buf, linestarts[i], len);
13956  buf[len] = '\0';
13957 
13958  //Draw the string
13959  gr_string(x,curr_y,buf,GR_RESIZE_NONE);
13960 
13961  //Free the string we made
13962  delete[] buf;
13963 
13964  //Increment line height
13965  curr_y += line_ht;
13966  }
13967 
13968  if (num_lines <= 0)
13969  {
13970  // If no line was drawn then we need to add one so the next line is
13971  // aligned right
13972  curr_y += line_ht;
13973  }
13974 
13975  NextDrawStringPos[1] = curr_y;
13976  }
13977  return ade_set_error(L, "i", num_lines);
13978 }
13979 
13980 ADE_FUNC(getStringWidth, l_Graphics, "string String", "Gets string width", "number", "String width, or 0 on failure")
13981 {
13982  if(!Gr_inited)
13983  return ade_set_error(L, "i", 0);
13984 
13985  char *s;
13986  if(!ade_get_args(L, "s", &s))
13987  return ade_set_error(L, "i", 0);
13988 
13989  int w;
13990 
13991  gr_get_string_size(&w, NULL, s);
13992 
13993  return ade_set_args(L, "i", w);
13994 }
13995 
13996 ADE_FUNC(createTexture, l_Graphics, "[number Width=512, number Height=512, enumeration Type=TEXTURE_DYNAMIC]",
13997  "Creates a texture for rendering to."
13998  "Types are TEXTURE_STATIC - for infrequent rendering - and TEXTURE_DYNAMIC - for frequent rendering.",
13999  "texture",
14000  "New texture handle, or invalid texture handle if texture couldn't be created")
14001 {
14002  int w=512;
14003  int h=512;
14004  enum_h *e = NULL;
14005 
14006  //GET ARGS
14007  ade_get_args(L, "|iio", &w, &h, l_Enum.GetPtr(&e));
14008 
14010  if(e != NULL)
14011  {
14012  if(e->index == LE_TEXTURE_STATIC)
14014  else if(e->index == LE_TEXTURE_DYNAMIC)
14016  }
14017 
14018  int idx = bm_make_render_target(w, h, t);
14019 
14020  if(idx < 0)
14021  return ade_set_error(L, "o", l_Texture.Set(-1));
14022 
14023  return ade_set_args(L, "o", l_Texture.Set(idx));
14024 }
14025 
14026 ADE_FUNC(loadTexture, l_Graphics, "string Filename, [boolean LoadIfAnimation, boolean NoDropFrames]",
14027  "Gets a handle to a texture. If second argument is set to true, animations will also be loaded."
14028  "If third argument is set to true, every other animation frame will not be loaded if system has less than 48 MB memory."
14029  "<br><strong>IMPORTANT:</strong> Textures will not be unload themselves unless you explicitly tell them to do so."
14030  "When you are done with a texture, call the Unload() function to free up memory.",
14031  "texture",
14032  "Texture handle, or invalid texture handle if texture couldn't be loaded")
14033 {
14034  char *s;
14035  int idx;
14036  bool b=false;
14037  bool d=false;
14038 
14039  if(!ade_get_args(L, "s|bb", &s, &b, &d))
14040  return ade_set_error(L, "o", l_Texture.Set(-1));
14041 
14042  idx = bm_load(s);
14043  if(idx < 0 && b) {
14044  idx = bm_load_animation(s, NULL, NULL, NULL, d ? 1 : 0);
14045  }
14046 
14047  if(idx < 0)
14048  return ade_set_error(L, "o", l_Texture.Set(-1));
14049 
14050  return ade_set_args(L, "o", l_Texture.Set(idx));
14051 }
14052 
14053 ADE_FUNC(drawImage, l_Graphics, "string Filename/texture Texture, [number X1=0, Y1=0, number X2, number Y2, number UVX1 = 0.0, number UVY1 = 0.0, number UVX2=1.0, number UVY2=1.0, number alpha=1.0]",
14054  "Draws an image or texture. Any image extension passed will be ignored."
14055  "The UV variables specify the UV value for each corner of the image. "
14056  "In UV coordinates, (0,0) is the top left of the image; (1,1) is the lower right.",
14057  "boolean",
14058  "Whether image was drawn")
14059 {
14060  if(!Gr_inited)
14061  return ade_set_error(L, "b", false);
14062 
14063  int idx;
14064  int x1 = 0;
14065  int y1 = 0;
14066  int x2=INT_MAX;
14067  int y2=INT_MAX;
14068  float uv_x1=0.0f;
14069  float uv_y1=0.0f;
14070  float uv_x2=1.0f;
14071  float uv_y2=1.0f;
14072  float alpha=1.0f;
14073 
14074  if(lua_isstring(L, 1))
14075  {
14076  char *s = NULL;
14077  if(!ade_get_args(L, "s|iiiifffff", &s,&x1,&y1,&x2,&y2,&uv_x1,&uv_y1,&uv_x2,&uv_y2,&alpha))
14078  return ade_set_error(L, "b", false);
14079 
14080  idx = Script_system.LoadBm(s);
14081 
14082  if(idx < 0)
14083  return ADE_RETURN_FALSE;
14084  }
14085  else
14086  {
14087  if(!ade_get_args(L, "o|iiiifffff", l_Texture.Get(&idx),&x1,&y1,&x2,&y2,&uv_x1,&uv_y1,&uv_x2,&uv_y2,&alpha))
14088  return ade_set_error(L, "b", false);
14089  }
14090 
14091  if(!bm_is_valid(idx))
14092  return ade_set_error(L, "b", false);
14093 
14094  int w, h;
14095  if(bm_get_info(idx, &w, &h) < 0)
14096  return ADE_RETURN_FALSE;
14097 
14098  if(x2!=INT_MAX)
14099  w = x2-x1;
14100 
14101  if(y2!=INT_MAX)
14102  h = y2-y1;
14103 
14104  gr_set_bitmap(idx, lua_Opacity_type, GR_BITBLT_MODE_NORMAL, alpha);
14105  bitmap_rect_list brl = bitmap_rect_list(x1, y1, w, h, uv_x1, uv_y1, uv_x2, uv_y2);
14106  gr_bitmap_list(&brl, 1, GR_RESIZE_NONE);
14107 
14108  return ADE_RETURN_TRUE;
14109 }
14110 
14111 ADE_FUNC(drawMonochromeImage, l_Graphics, "string Filename/texture Texture, number X1, number Y1, [number X2, number Y2, number alpha=1.0]", "Draws a monochrome image using the current color", "boolean", "Whether image was drawn")
14112 {
14113  if(!Gr_inited)
14114  return ade_set_error(L, "b", false);
14115 
14116  int idx;
14117  int x,y;
14118  int x2=INT_MAX;
14119  int y2=INT_MAX;
14120  int sx=0;
14121  int sy=0;
14122  bool m = false;
14123  float alpha=1.0;
14124 
14125  if(lua_isstring(L, 1))
14126  {
14127  char *s = NULL;
14128  if(!ade_get_args(L, "sii|iif", &s,&x,&y,&x2,&y2,&alpha))
14129  return ade_set_error(L, "b", false);
14130 
14131  idx = Script_system.LoadBm(s);
14132 
14133  if(idx < 0)
14134  return ADE_RETURN_FALSE;
14135  }
14136  else
14137  {
14138  if(!ade_get_args(L, "oii|iif", l_Texture.Get(&idx),&x,&y,&x2,&y2,&alpha))
14139  return ade_set_error(L, "b", false);
14140  }
14141 
14142  if(!bm_is_valid(idx))
14143  return ade_set_error(L, "b", false);
14144 
14145  int w, h;
14146  if(bm_get_info(idx, &w, &h) < 0)
14147  return ADE_RETURN_FALSE;
14148 
14149  if(sx < 0)
14150  sx = w + sx;
14151 
14152  if(sy < 0)
14153  sy = h + sy;
14154 
14155  if(x2!=INT_MAX)
14156  w = x2-x;
14157 
14158  if(y2!=INT_MAX)
14159  h = y2-y;
14160 
14161  gr_set_bitmap(idx, lua_Opacity_type, GR_BITBLT_MODE_NORMAL,alpha);
14162  gr_aabitmap_ex(x, y, w, h, sx, sy, GR_RESIZE_NONE, m);
14163 
14164  return ADE_RETURN_TRUE;
14165 }
14166 
14167 ADE_FUNC(getImageWidth, l_Graphics, "string Filename", "Gets image width", "number", "Image width, or 0 if filename is invalid")
14168 {
14169  char *s;
14170  if(!ade_get_args(L, "s", &s))
14171  return ade_set_error(L, "i", 0);
14172 
14173  int w;
14174 
14175  int idx = bm_load(s);
14176 
14177  if(idx < 0)
14178  return ade_set_error(L, "i", 0);
14179 
14180  bm_get_info(idx, &w);
14181  return ade_set_args(L, "i", w);
14182 }
14183 
14184 ADE_FUNC(getImageHeight, l_Graphics, "Image name", "Gets image height", "number", "Image height, or 0 if filename is invalid")
14185 {
14186  char *s;
14187  if(!ade_get_args(L, "s", &s))
14188  return ade_set_error(L, "i", 0);
14189 
14190  int h;
14191 
14192  int idx = bm_load(s);
14193 
14194  if(idx < 0)
14195  return ade_set_error(L, "i", 0);
14196 
14197  bm_get_info(idx, NULL, &h);
14198  return ade_set_args(L, "i", h);
14199 }
14200 
14201 ADE_FUNC(flashScreen, l_Graphics, "number Red, number Green, number Blue", "Flashes the screen", NULL, NULL)
14202 {
14203  if(!Gr_inited)
14204  return ADE_RETURN_NIL;
14205 
14206  int r,g,b;
14207 
14208  if(!ade_get_args(L, "iii", &r, &g, &b))
14209  return ADE_RETURN_NIL;
14210 
14211  gr_flash(r,g,b);
14212 
14213  return ADE_RETURN_NIL;
14214 }
14215 
14216 ADE_FUNC(loadModel, l_Graphics, "string Filename", "Loads the model - will not setup subsystem data, DO NOT USE FOR LOADING SHIP MODELS", "model", "Handle to a model")
14217 {
14218  char *s;
14219  int model_num = -1;
14220 
14221  if(!ade_get_args(L, "s", &s))
14222  return ade_set_error(L, "o", l_Model.Set(-1));
14223 
14224  if (s[0] == '\0')
14225  return ade_set_error(L, "o", l_Model.Set(-1));
14226 
14227  model_num = model_load(s, 0, NULL);
14228 
14229  return ade_set_args(L, "o", l_Model.Set(model_h(model_num)));
14230 }
14231 
14232 ADE_FUNC(hasViewmode, l_Graphics, "enumeration", "Specifies if the current viemode has the specified flag, see VM_* enumeration", "boolean", "true if flag is present, false otherwise")
14233 {
14234  enum_h *type = NULL;
14235 
14236  if (!ade_get_args(L, "o", l_Enum.GetPtr(&type)))
14237  return ade_set_error(L, "b", false);
14238 
14239  if (type == NULL || !type->IsValid())
14240  return ade_set_error(L, "b", false);
14241 
14242  int bit = 0;
14243 
14244  switch(type->index)
14245  {
14246  case LE_VM_INTERNAL:
14247  return ade_set_args(L, "b", Viewer_mode == 0);
14248  break;
14249 
14250  case LE_VM_EXTERNAL:
14251  bit = VM_EXTERNAL;
14252  break;
14253 
14254  case LE_VM_OTHER_SHIP:
14255  bit = VM_OTHER_SHIP;
14256  break;
14257 
14258  case LE_VM_CHASE:
14259  bit = VM_CHASE;
14260  break;
14261 
14262  case LE_VM_DEAD_VIEW:
14263  bit = VM_DEAD_VIEW;
14264  break;
14265 
14268  break;
14269 
14270  case LE_VM_FREECAMERA:
14271  bit = VM_FREECAMERA;
14272  break;
14273 
14274  case LE_VM_PADLOCK_LEFT:
14275  bit = VM_PADLOCK_LEFT;
14276  break;
14277 
14278  case LE_VM_PADLOCK_REAR:
14279  bit = VM_PADLOCK_REAR;
14280  break;
14281 
14282  case LE_VM_PADLOCK_RIGHT:
14283  bit = VM_PADLOCK_RIGHT;
14284  break;
14285 
14286  case LE_VM_PADLOCK_UP:
14287  bit = VM_PADLOCK_UP;
14288  break;
14289 
14290  case LE_VM_TOPDOWN:
14291  bit = VM_TOPDOWN;
14292  break;
14293 
14294  case LE_VM_TRACK:
14295  bit = VM_TRACK;
14296  break;
14297 
14298  case LE_VM_WARP_CHASE:
14299  bit = VM_WARP_CHASE;
14300  break;
14301 
14302  case LE_VM_WARPIN_ANCHOR:
14303  bit = VM_WARPIN_ANCHOR;
14304  break;
14305 
14306  default:
14307  LuaError(L, "Attempted to use hasViewmode with an invalid enumeration! Only VM_* enumerations are allowed!");
14308  return ade_set_error(L, "b", false);
14309  break;
14310  }
14311 
14312  return ade_set_args(L, "b", (Viewer_mode & bit) != 0);
14313 }
14314 
14315 ADE_FUNC(setClip, l_Graphics, "x, y, width, height", "Sets the clipping region to the specified rectangle. Most drawing functions are able to handle the offset.", "boolean", "true if successful, false otherwise")
14316 {
14317  int x, y, width, height;
14318 
14319  if (!ade_get_args(L, "iiii", &x, &y, &width, &height))
14320  return ADE_RETURN_FALSE;
14321 
14322  gr_set_clip(x, y, width, height, GR_RESIZE_NONE);
14323 
14324  return ADE_RETURN_TRUE;
14325 }
14326 
14327 ADE_FUNC(resetClip, l_Graphics, NULL, "Resets the clipping region that might have been set", "boolean", "true if successful, false otherwise")
14328 {
14329  gr_reset_clip();
14330 
14331  return ADE_RETURN_TRUE;
14332 }
14333 
14334 //**********LIBRARY: Scripting Variables
14335 ade_lib l_HookVar("HookVariables", NULL, "hv", "Hook variables repository");
14336 
14337 //WMC: IMPORTANT
14338 //Be very careful when modifying this library, as the Globals[] library does depend
14339 //on the current number of items in the library. If you add _anything_, modify __len.
14340 //Or run changes by me.
14341 
14342 //*****LIBRARY: Scripting Variables
14343 ade_lib l_HookVar_Globals("Globals", &l_HookVar);
14344 
14345 ADE_INDEXER(l_HookVar_Globals, "number Index", "Array of current HookVariable names", "string", "Hookvariable name, or empty string if invalid index specified")
14346 {
14347  int idx;
14348  if(!ade_get_args(L, "*i", &idx))
14349  return ade_set_error(L, "s", "");
14350 
14351  //Get lib
14352  lua_getglobal(L, l_HookVar.GetName());
14353  int lib_ldx = lua_gettop(L);
14354  if(!lua_isuserdata(L, lib_ldx))
14355  {
14356  lua_pop(L, 1);
14357  return ade_set_error(L, "s", "");
14358  }
14359 
14360  //Get metatable
14361  lua_getmetatable(L, lib_ldx);
14362  int mtb_ldx = lua_gettop(L);
14363  if(!lua_istable(L, mtb_ldx))
14364  {
14365  lua_pop(L, 2);
14366  return ade_set_error(L, "s", "");
14367  }
14368 
14369  //Get ade members table
14370  lua_pushstring(L, "__ademembers");
14371  lua_rawget(L, mtb_ldx);
14372  int amt_ldx = lua_gettop(L);
14373  if(!lua_istable(L, amt_ldx))
14374  {
14375  lua_pop(L, 3);
14376  return ade_set_error(L, "s", "");
14377  }
14378 
14379  //List 'em
14380  char *keyname = NULL;
14381  int count = 1;
14382  lua_pushnil(L);
14383  while(lua_next(L, amt_ldx))
14384  {
14385  //Now on stack: Key, value
14386  lua_pushvalue(L, -2);
14387  keyname = (char *)lua_tostring(L, -1);
14388  if(strcmp(keyname, "Globals"))
14389  {
14390  if(count == idx)
14391  {
14392  //lib, mtb, amt, key, value, string go bye-bye
14393  lua_pop(L, 5);
14394  return ade_set_args(L, "s", keyname);
14395  }
14396  count++;
14397  }
14398  lua_pop(L, 2); //Value, string
14399  }
14400 
14401  lua_pop(L, 3); //lib, mtb, amt
14402 
14403  return ade_set_error(L, "s", "");
14404 }
14405 
14406 ADE_FUNC(__len, l_HookVar_Globals, NULL, "Number of HookVariables", "number", "Number of HookVariables")
14407 {
14408  //Get metatable
14409  lua_getglobal(L, l_HookVar.GetName());
14410  int lib_ldx = lua_gettop(L);
14411  if(!lua_isuserdata(L, lib_ldx))
14412  {
14413  lua_pop(L, 1);
14414  return ade_set_error(L, "i", 0);
14415  }
14416 
14417  lua_getmetatable(L, lib_ldx);
14418  int mtb_ldx = lua_gettop(L);
14419  if(!lua_istable(L, mtb_ldx))
14420  {
14421  lua_pop(L, 2);
14422  return ade_set_error(L, "i", 0);
14423  }
14424 
14425  //Get ade members table
14426  lua_pushstring(L, "__ademembers");
14427  lua_rawget(L, mtb_ldx);
14428  int amt_ldx = lua_gettop(L);
14429  if(!lua_istable(L, amt_ldx))
14430  {
14431  lua_pop(L, 3);
14432  return ade_set_error(L, "i", 0);
14433  }
14434 
14435  int total_len = 0;
14436  lua_pushnil(L);
14437  while(lua_next(L, amt_ldx))
14438  {
14439  total_len++;
14440  lua_pop(L, 1); //value
14441  }
14442  int num_sub = Ade_table_entries[l_HookVar.GetIdx()].Num_subentries;
14443 
14444  lua_pop(L, 3);
14445 
14446  //WMC - Return length, minus the 'Globals' library
14447  return ade_set_args(L, "i", total_len - num_sub);
14448 }
14449 
14450 //**********LIBRARY: Mission
14451 ade_lib l_Mission("Mission", NULL, "mn", "Mission library");
14452 
14453 // for use in creating faster metadata systems, use in conjunction with getSignature()
14454 ADE_FUNC(getObjectFromSignature, l_Mission, "number Signature", "Gets a handle of an object from its signature", "object", "Handle of object with signaure, invalid handle if signature is not in use")
14455 {
14456  int sig = -1;
14457  int objnum;
14458  if(!ade_get_args(L, "i", &sig))
14459  return ade_set_error(L, "o", l_Object.Set(object_h()));
14460 
14461  if (sig == -1) {
14462  return ade_set_error(L, "o", l_Object.Set(object_h()));
14463  }
14464 
14465  objnum = obj_get_by_signature(sig);
14466 
14467  return ade_set_object_with_breed(L, objnum);
14468 }
14469 
14470 ADE_FUNC(evaluateSEXP, l_Mission, "string", "Runs the defined SEXP script", "boolean", "if the operation was successful")
14471 {
14472  char *s;
14473  int r_val;
14474 
14475  if(!ade_get_args(L, "s", &s))
14476  return ADE_RETURN_FALSE;
14477 
14478  r_val = run_sexp(s);
14479 
14480  if (r_val == SEXP_TRUE)
14481  return ADE_RETURN_TRUE;
14482  else
14483  return ADE_RETURN_FALSE;
14484 }
14485 
14486 ADE_FUNC(runSEXP, l_Mission, "string", "Runs the defined SEXP script", "boolean", "if the operation was successful")
14487 {
14488  char *s;
14489  int r_val;
14490  char buf[8192];
14491 
14492  if(!ade_get_args(L, "s", &s))
14493  return ADE_RETURN_FALSE;
14494 
14495  while (is_white_space(*s))
14496  s++;
14497  if (*s != '(')
14498  {
14499  static bool Warned_about_runSEXP_parentheses = false;
14500  if (!Warned_about_runSEXP_parentheses)
14501  {
14502  Warned_about_runSEXP_parentheses = true;
14503  Warning(LOCATION, "Invalid SEXP syntax: SEXPs must be surrounded by parentheses. For backwards compatibility, the string has been enclosed in parentheses. This may not be correct in all use cases.");
14504  }
14505  // this is the old sexp handling method, which is incorrect
14506  snprintf(buf, 8191, "( when ( true ) ( %s ) )", s);
14507  }
14508  else
14509  {
14510  // this is correct usage
14511  snprintf(buf, 8191, "( when ( true ) %s )", s);
14512  }
14513 
14514  r_val = run_sexp(buf);
14515 
14516  if (r_val == SEXP_TRUE)
14517  return ADE_RETURN_TRUE;
14518  else
14519  return ADE_RETURN_FALSE;
14520 }
14521 
14522 //****SUBLIBRARY: Mission/Asteroids
14523 ade_lib l_Mission_Asteroids("Asteroids", &l_Mission, NULL, "Asteroids in the mission");
14524 
14525 ADE_INDEXER(l_Mission_Asteroids, "number Index", "Gets asteroid", "asteroid", "Asteroid handle, or invalid handle if invalid index specified")
14526 {
14527  int idx = -1;
14528  if( !ade_get_args(L, "*i", &idx) ) {
14529  return ade_set_error( L, "o", l_Asteroid.Set( object_h() ) );
14530  }
14531  if( idx > -1 && idx < asteroid_count() ) {
14532  idx--; //Convert from Lua to C, as lua indices start from 1, not 0
14533  return ade_set_args( L, "o", l_Asteroid.Set( object_h( &Objects[Asteroids[idx].objnum] ), Objects[Asteroids[idx].objnum].signature ) );
14534  }
14535 
14536  return ade_set_error(L, "o", l_Asteroid.Set( object_h() ) );
14537 }
14538 
14540  "Number of asteroids in mission. Note that the value returned is only good until an asteroid is destroyed, and so cannot be relied on for more than one frame.",
14541  "number",
14542  "Number of asteroids in the mission, or 0 if asteroids are not enabled")
14543 {
14544  if(Asteroids_enabled) {
14545  return ade_set_args(L, "i", asteroid_count());
14546  }
14547  return ade_set_args(L, "i", 0);
14548 }
14549 
14550 //****SUBLIBRARY: Mission/Debris
14551 ade_lib l_Mission_Debris("Debris", &l_Mission, NULL, "debris in the mission");
14552 
14553 ADE_INDEXER(l_Mission_Debris, "number Index", "Array of debris in the current mission", "debris", "Debris handle, or invalid debris handle if index wasn't valid")
14554 {
14555  int idx = -1;
14556  if( !ade_get_args( L, "*i", &idx ) ) {
14557  return ade_set_error(L, "o", l_Debris.Set(object_h()));
14558  }
14559  if( idx > -1 && idx < Num_debris_pieces ) {
14560  idx--; // Lua -> C
14561  if (Debris[idx].objnum == -1) //Somehow accessed an invalid debris piece
14562  return ade_set_error(L, "o", l_Debris.Set(object_h()));
14563  return ade_set_args(L, "o", l_Debris.Set(object_h(&Objects[Debris[idx].objnum]), Objects[Debris[idx].objnum].signature));
14564  }
14565 
14566  return ade_set_error(L, "o", l_Debris.Set(object_h()));
14567 }
14568 
14570  "Number of debris pieces in the mission. "
14571  "Note that the value returned is only good until a piece of debris is destroyed, and so cannot be relied on for more than one frame.",
14572  "number",
14573  "Current number of debris particles")
14574 {
14575  return ade_set_args(L, "i", Num_debris_pieces);
14576 }
14577 
14578 //****SUBLIBRARY: Mission/EscortShips
14579 ade_lib l_Mission_EscortShips("EscortShips", &l_Mission, NULL, NULL);
14580 
14581 ADE_INDEXER(l_Mission_EscortShips, "number Index", "Gets escort ship at specified index on escort list", "ship", "Specified ship, or invalid ship handle if invalid index")
14582 {
14583  int idx;
14584  if(!ade_get_args(L, "*i", &idx))
14585  return ade_set_error(L, "o", l_Ship.Set(object_h()));
14586 
14587  if(idx < 1 || idx > hud_escort_num_ships_on_list())
14588  return ade_set_error(L, "o", l_Ship.Set(object_h()));
14589 
14590  //Lua->FS2
14591  idx--;
14592 
14593  idx = hud_escort_return_objnum(idx);
14594 
14595  if(idx < 0)
14596  return ade_set_error(L, "o", l_Ship.Set(object_h()));
14597 
14598  return ade_set_args(L, "o", l_Ship.Set(object_h(&Objects[idx])));
14599 }
14600 
14601 ADE_FUNC(__len, l_Mission_EscortShips, NULL, "Current number of escort ships", "number", "Current number of escort ships")
14602 {
14603  return ade_set_args(L, "i", hud_escort_num_ships_on_list());
14604 }
14605 
14606 //****SUBLIBRARY: Mission/Events
14607 ade_lib l_Mission_Events("Events", &l_Mission, NULL, "Events");
14608 
14609 ADE_INDEXER(l_Mission_Events, "number Index/string Name", "Indexes events list", "event", "Event handle, or invalid event handle if index was invalid")
14610 {
14611  char *s;
14612  if(!ade_get_args(L, "*s", &s))
14613  return ade_set_error(L, "o", l_Event.Set(-1));
14614 
14615  int i;
14616  for(i = 0; i < Num_mission_events; i++)
14617  {
14618  if(!stricmp(Mission_events[i].name, s))
14619  return ade_set_args(L, "o", l_Event.Set(i));
14620  }
14621 
14622  //Now try as a number
14623  i = atoi(s);
14624  if(i < 1 || i > Num_mission_events)
14625  return ade_set_error(L, "o", l_Event.Set(-1));
14626 
14627  //Lua-->FS2
14628  i--;
14629 
14630  return ade_set_args(L, "o", l_Event.Set(i));
14631 }
14632 
14633 ADE_FUNC(__len, l_Mission_Events, NULL, "Number of events in mission", "number", "Number of events in mission")
14634 {
14635  return ade_set_args(L, "i", Num_mission_events);
14636 }
14637 
14638 //****SUBLIBRARY: Mission/SEXPVariables
14639 ade_lib l_Mission_SEXPVariables("SEXPVariables", &l_Mission, NULL, "SEXP Variables");
14640 
14641 ADE_INDEXER(l_Mission_SEXPVariables, "number Index/string Name", "Array of SEXP variables. Note that you can set a sexp variable using the array, eg \'SEXPVariables[\"newvariable\"] = \"newvalue\"\'", "sexpvariable", "Handle to SEXP variable, or invalid sexpvariable handle if index was invalid")
14642 {
14643  char *name = NULL;
14644  char *newval = NULL;
14645  if(!ade_get_args(L, "*s|s", &name, &newval))
14646  return ade_set_error(L, "o", l_SEXPVariable.Set(sexpvar_h()));
14647 
14648  int idx = get_index_sexp_variable_name(name);
14649  if(idx < 0)
14650  {
14651  idx = atoi(name);
14652 
14653  //Lua-->FS2
14654  idx--;
14655  }
14656 
14657  if(idx < 0 || idx >= MAX_SEXP_VARIABLES)
14658  {
14659  if(ADE_SETTING_VAR && newval != NULL)
14660  {
14661  idx = sexp_add_variable(newval, name, lua_type(L, 2) == LUA_TNUMBER ? SEXP_VARIABLE_NUMBER : SEXP_VARIABLE_STRING);
14662  }
14663 
14664  //We have failed.
14665  if(idx < 0)
14666  {
14667  return ade_set_error(L, "o", l_SEXPVariable.Set(sexpvar_h()));
14668  }
14669  }
14670  else
14671  {
14672  if(ADE_SETTING_VAR && newval != NULL)
14673  {
14674  sexp_modify_variable(newval, idx, false);
14675  }
14676  }
14677 
14678  return ade_set_args(L, "o", l_SEXPVariable.Set(sexpvar_h(idx)));
14679 }
14680 
14681 ADE_FUNC(__len, l_Mission_SEXPVariables, NULL, "Current number of SEXP variables", "number", "Counts number of loaded SEXP Variables. May be slow.")
14682 {
14683  return ade_set_args(L, "i", sexp_variable_count());
14684 }
14685 
14686 //****SUBLIBRARY: Mission/Ships
14687 ade_lib l_Mission_Ships("Ships", &l_Mission, NULL, "Ships in the mission");
14688 
14689 ADE_INDEXER(l_Mission_Ships, "number Index/string Name", "Gets ship", "ship", "Ship handle, or invalid ship handle if index was invalid")
14690 {
14691  char *name;
14692  if(!ade_get_args(L, "*s", &name))
14693  return ade_set_error(L, "o", l_Ship.Set(object_h()));
14694 
14695  int idx = ship_name_lookup(name);
14696 
14697  if(idx > -1)
14698  {
14699  return ade_set_args(L, "o", l_Ship.Set(object_h(&Objects[Ships[idx].objnum]), Objects[Ships[idx].objnum].signature));
14700  }
14701  else
14702  {
14703  idx = atoi(name);
14704  if(idx > 0)
14705  {
14706  int count=1;
14707 
14708  for(int i = 0; i < MAX_SHIPS; i++)
14709  {
14710  if (Ships[i].objnum < 0 || Objects[Ships[i].objnum].type != OBJ_SHIP)
14711  continue;
14712 
14713  if(count == idx) {
14714  return ade_set_args(L, "o", l_Ship.Set(object_h(&Objects[Ships[i].objnum]), Objects[Ships[i].objnum].signature));
14715  }
14716 
14717  count++;
14718  }
14719  }
14720  }
14721 
14722  return ade_set_error(L, "o", l_Ship.Set(object_h()));
14723 }
14724 
14725 extern int ships_inited;
14727  "Number of ships in the mission. "
14728  "This function is somewhat slow, and should be set to a variable for use in looping situations. "
14729  "Note that the value returned is only good until a ship is destroyed, and so cannot be relied on for more than one frame.",
14730  "number",
14731  "Number of ships in the mission, or 0 if ships haven't been initialized yet")
14732 {
14733  if(ships_inited)
14734  return ade_set_args(L, "i", ship_get_num_ships());
14735  else
14736  return ade_set_args(L, "i", 0);
14737 }
14738 
14739 //****SUBLIBRARY: Mission/Waypoints
14740 ade_lib l_Mission_Waypoints("Waypoints", &l_Mission, NULL, NULL);
14741 
14742 ADE_INDEXER(l_Mission_Waypoints, "number Index", "Array of waypoints in the current mission", "waypoint", "Waypoint handle, or invalid waypoint handle if index was invalid")
14743 {
14744  int idx;
14745  if(!ade_get_args(L, "*i", &idx))
14746  return ade_set_error(L, "o", l_Waypoint.Set(object_h()));
14747 
14748  //Remember, Lua indices start at 0.
14749  int count=0;
14750 
14751  object *ptr = GET_FIRST(&obj_used_list);
14752  while (ptr != END_OF_LIST(&obj_used_list))
14753  {
14754  if (ptr->type == OBJ_WAYPOINT)
14755  count++;
14756 
14757  if(count == idx) {
14758  return ade_set_args(L, "o", l_Waypoint.Set(object_h(ptr)));
14759  }
14760 
14761  ptr = GET_NEXT(ptr);
14762  }
14763 
14764  return ade_set_error(L, "o", l_Weapon.Set(object_h()));
14765 }
14766 
14767 ADE_FUNC(__len, l_Mission_Waypoints, NULL, "Gets number of waypoints in mission. Note that this is only accurate for one frame.", "number", "Number of waypoints in the mission")
14768 {
14769  uint count=0;
14770  for(uint i = 0; i < MAX_OBJECTS; i++)
14771  {
14772  if (Objects[i].type == OBJ_WAYPOINT)
14773  count++;
14774  }
14775 
14776  return ade_set_args(L, "i", count);
14777 }
14778 
14779 //****SUBLIBRARY: Mission/WaypointLists
14780 ade_lib l_Mission_WaypointLists("WaypointLists", &l_Mission, NULL, NULL);
14781 
14782 ADE_INDEXER(l_Mission_WaypointLists, "number Index/string WaypointListName", "Array of waypoint lists", "waypointlist", "Gets waypointlist handle")
14783 {
14784  waypointlist_h wpl;
14785  char *name;
14786  if(!ade_get_args(L, "*s", &name))
14787  return ade_set_error(L, "o", l_WaypointList.Set(waypointlist_h()));
14788 
14789  wpl = waypointlist_h(name);
14790 
14791  if (!wpl.IsValid()) {
14792  int idx = atoi(name) - 1;
14794  }
14795 
14796  if (wpl.IsValid()) {
14797  return ade_set_args(L, "o", l_WaypointList.Set(wpl));
14798  }
14799 
14800  return ade_set_error(L, "o", l_WaypointList.Set(waypointlist_h()));
14801 }
14802 
14803 ADE_FUNC(__len, l_Mission_WaypointLists, NULL, "Number of waypoint lists in mission. Note that this is only accurate for one frame.", "number", "Number of waypoint lists in the mission")
14804 {
14805  return ade_set_args(L, "i", Waypoint_lists.size());
14806 }
14807 
14808 //****SUBLIBRARY: Mission/Weapons
14809 ade_lib l_Mission_Weapons("Weapons", &l_Mission, NULL, NULL);
14810 
14811 ADE_INDEXER(l_Mission_Weapons, "number Index", "Gets handle to a weapon object in the mission.", "weapon", "Weapon handle, or invalid weapon handle if index is invalid")
14812 {
14813  int idx;
14814  if(!ade_get_args(L, "*i", &idx))
14815  return ade_set_error(L, "o", l_Weapon.Set(object_h()));
14816 
14817  //Remember, Lua indices start at 0.
14818  int count=1;
14819 
14820  for(int i = 0; i < MAX_WEAPONS; i++)
14821  {
14822  if (Weapons[i].weapon_info_index < 0 || Weapons[i].objnum < 0 || Objects[Weapons[i].objnum].type != OBJ_WEAPON)
14823  continue;
14824 
14825  if(count == idx) {
14826  return ade_set_args(L, "o", l_Weapon.Set(object_h(&Objects[Weapons[i].objnum])));
14827  }
14828 
14829  count++;
14830  }
14831 
14832  return ade_set_error(L, "o", l_Weapon.Set(object_h()));
14833 }
14834 ADE_FUNC(__len, l_Mission_Weapons, NULL, "Number of weapon objects in mission. Note that this is only accurate for one frame.", "number", "Number of weapon objects in mission")
14835 {
14836  return ade_set_args(L, "i", Num_weapons);
14837 }
14838 
14839 //****SUBLIBRARY: Mission/Beams
14840 ade_lib l_Mission_Beams("Beams", &l_Mission, NULL, NULL);
14841 
14842 ADE_INDEXER(l_Mission_Beams, "number Index", "Gets handle to a beam object in the mission.", "beam", "Beam handle, or invalid beam handle if index is invalid")
14843 {
14844  int idx;
14845  if(!ade_get_args(L, "*i", &idx))
14846  return ade_set_error(L, "o", l_Beam.Set(object_h()));
14847 
14848  //Remember, Lua indices start at 0.
14849  int count=1;
14850 
14851  for(int i = 0; i < MAX_BEAMS; i++)
14852  {
14853  if (Beams[i].weapon_info_index < 0 || Beams[i].objnum < 0 || Objects[Beams[i].objnum].type != OBJ_BEAM)
14854  continue;
14855 
14856  if(count == idx) {
14857  return ade_set_args(L, "o", l_Beam.Set(object_h(&Objects[Beams[i].objnum])));
14858  }
14859 
14860  count++;
14861  }
14862 
14863  return ade_set_error(L, "o", l_Beam.Set(object_h()));
14864 }
14865 ADE_FUNC(__len, l_Mission_Beams, NULL, "Number of beam objects in mission. Note that this is only accurate for one frame.", "number", "Number of beam objects in mission")
14866 {
14867  return ade_set_args(L, "i", Beam_count);
14868 }
14869 
14870 //****SUBLIBRARY: Campaign
14871 ade_lib l_Campaign("Campaign", NULL, "ca", "Campaign Library");
14872 
14873 ADE_FUNC(getNextMissionFilename, l_Campaign, NULL, "Gets next mission filename", "string", "Next mission filename, or nil if the next mission is invalid")
14874 {
14876  return ADE_RETURN_NIL;
14877  }
14879 }
14880 
14881 ADE_FUNC(getPrevMissionFilename, l_Campaign, NULL, "Gets previous mission filename", "string", "Previous mission filename, or nil if the previous mission is invalid")
14882 {
14884  return ADE_RETURN_NIL;
14885  }
14887 }
14888 
14889 // DahBlount - This jumps to a mission, the reason it accepts a boolean value is so that players can return to campaign maps
14890 ADE_FUNC(jumpToMission, l_Campaign, "string filename, [boolean hub]", "Jumps to a mission based on the filename. Optionally, the player can be sent to a hub mission without setting missions to skipped.", "boolean", "Jumps to a mission, or returns nil.")
14891 {
14892  char *filename = NULL;;
14893  bool hub = false;
14894  if (!ade_get_args(L, "s|b", &filename, &hub))
14895  return ADE_RETURN_NIL;
14896 
14897  mission_campaign_jump_to_mission(filename, hub);
14898 
14899  return ADE_RETURN_TRUE;
14900 }
14901 
14902 // TODO: add a proper indexer type that returns a handle
14903 // something like ca.Mission[filename/index]
14904 
14905 //****SUBLIBRARY: Mission/Wings
14906 ade_lib l_Mission_Wings("Wings", &l_Mission, NULL, NULL);
14907 
14908 ADE_INDEXER(l_Mission_Wings, "number Index/string WingName", "Wings in the mission", "wing", "Wing handle, or invalid wing handle if index or name was invalid")
14909 {
14910  char *name;
14911  if(!ade_get_args(L, "*s", &name))
14912  return ade_set_error(L, "o", l_Wing.Set(-1));
14913 
14914  //MageKing17 - Make the count-ignoring version of the lookup and leave checking if the wing has any ships to the scripter
14915  int idx = wing_lookup(name);
14916 
14917  if(idx < 0)
14918  {
14919  idx = atoi(name);
14920  if(idx < 1 || idx > Num_wings)
14921  return ade_set_error(L, "o", l_Wing.Set(-1));
14922 
14923  idx--; //Lua->FS2
14924  }
14925 
14926  return ade_set_args(L, "o", l_Wing.Set(idx));
14927 }
14928 
14929 ADE_FUNC(__len, l_Mission_Wings, NULL, "Number of wings in mission", "number", "Number of wings in mission")
14930 {
14931  return ade_set_args(L, "i", Num_wings);
14932 }
14933 
14934 //****SUBLIBRARY: Mission/Teams
14935 ade_lib l_Mission_Teams("Teams", &l_Mission, NULL, NULL);
14936 
14937 ADE_INDEXER(l_Mission_Teams, "number Index/string TeamName", "Teams in the mission", "team", "Team handle or invalid team handle if the requested team could not be found")
14938 {
14939  char *name;
14940  if(!ade_get_args(L, "*s", &name))
14941  return ade_set_error(L, "o", l_Team.Set(-1));
14942 
14943  int idx = iff_lookup(name);
14944 
14945  if(idx < 0)
14946  {
14947  idx = atoi(name);
14948 
14949  idx--; //Lua->FS2
14950  }
14951 
14952  if(idx < 0 || idx >= Num_iffs)
14953  return ade_set_error(L, "o", l_Team.Set(-1));
14954 
14955  return ade_set_args(L, "o", l_Team.Set(idx));
14956 }
14957 
14958 ADE_FUNC(__len, l_Mission_Teams, NULL, "Number of teams in mission", "number", "Number of teams in mission")
14959 {
14960  return ade_set_args(L, "i", Num_iffs);
14961 }
14962 
14963 //****SUBLIBRARY: Mission/Messages
14964 ade_lib l_Mission_Messages("Messages", &l_Mission, NULL, NULL);
14965 
14966 ADE_INDEXER(l_Mission_Messages, "number Index/string messageName", "Messages of the mission", "message", "Message handle or invalid handle on error")
14967 {
14968  int idx = -1;
14969 
14970  if (lua_isnumber(L, 2))
14971  {
14972  if (!ade_get_args(L, "*i", &idx))
14973  return ade_set_args(L, "o", l_Message.Set(-1));
14974 
14975  idx--; // Lua --> FS2
14976 
14977  idx += Num_builtin_messages;
14978  }
14979  else
14980  {
14981  char* name = NULL;
14982 
14983  if (!ade_get_args(L, "*s", &name))
14984  return ade_set_args(L, "o", l_Message.Set(-1));
14985 
14986  if (name == NULL)
14987  return ade_set_args(L, "o", l_Message.Set(-1));
14988 
14989  for (int i = Num_builtin_messages; i < (int) Messages.size(); i++)
14990  {
14991  if (!stricmp(Messages[i].name, name))
14992  {
14993  idx = i;
14994  break;
14995  }
14996  }
14997  }
14998 
14999  if (idx < Num_builtin_messages || idx >= (int) Messages.size())
15000  return ade_set_args(L, "o", l_Message.Set(-1));
15001  else
15002  return ade_set_args(L, "o", l_Message.Set(idx));
15003 }
15004 
15005 ADE_FUNC(__len, l_Mission_Messages, NULL, "Number of messages in the mission", "number", "Number of messages in mission")
15006 {
15007  return ade_set_args(L, "i", (int) Messages.size() - Num_builtin_messages);
15008 }
15009 
15010 //****SUBLIBRARY: Mission/BuiltinMessages
15011 ade_lib l_Mission_BuiltinMessages("BuiltinMessages", &l_Mission, NULL, NULL);
15012 
15013 ADE_INDEXER(l_Mission_BuiltinMessages, "number Index/string messageName", "Built-in messages of the mission", "message", "Message handle or invalid handle on error")
15014 {
15015  int idx = -1;
15016 
15017  if (lua_isnumber(L, 2))
15018  {
15019  if (!ade_get_args(L, "*i", &idx))
15020  return ade_set_args(L, "o", l_Message.Set(-1));
15021 
15022  idx--; // Lua --> FS2
15023  }
15024  else
15025  {
15026  char* name = NULL;
15027 
15028  if (!ade_get_args(L, "*s", &name))
15029  return ade_set_args(L, "o", l_Message.Set(-1));
15030 
15031  if (name == NULL)
15032  return ade_set_args(L, "o", l_Message.Set(-1));
15033 
15034  for (int i = 0; i < Num_builtin_messages; i++)
15035  {
15036  if (!stricmp(Messages[i].name, name))
15037  {
15038  idx = i;
15039  break;
15040  }
15041  }
15042  }
15043 
15044  if (idx < 0 || idx >= Num_builtin_messages)
15045  return ade_set_args(L, "o", l_Message.Set(-1));
15046  else
15047  return ade_set_args(L, "o", l_Message.Set(idx));
15048 }
15049 
15050 ADE_FUNC(__len, l_Mission_BuiltinMessages, NULL, "Number of built-in messages in the mission", "number", "Number of messages in mission")
15051 {
15052  return ade_set_args(L, "i", Num_builtin_messages);
15053 }
15054 
15055 //****SUBLIBRARY: Mission/Personas
15056 ade_lib l_Mission_Personas("Personas", &l_Mission, NULL, NULL);
15057 
15058 ADE_INDEXER(l_Mission_Personas, "number Index/string name", "Personas of the mission", "persona", "Persona handle or invalid handle on error")
15059 {
15060  int idx = -1;
15061 
15062  if (lua_isnumber(L, 2))
15063  {
15064  if (!ade_get_args(L, "*i", &idx))
15065  return ade_set_args(L, "o", l_Persona.Set(-1));
15066 
15067  idx--; // Lua --> FS2
15068  }
15069  else
15070  {
15071  char* name = NULL;
15072 
15073  if (!ade_get_args(L, "*s", &name))
15074  return ade_set_args(L, "o", l_Persona.Set(-1));
15075 
15076  if (name == NULL)
15077  return ade_set_args(L, "o", l_Persona.Set(-1));
15078 
15079  idx = message_persona_name_lookup(name);
15080  }
15081 
15082  if (idx < 0 || idx >= Num_personas)
15083  return ade_set_args(L, "o", l_Persona.Set(-1));
15084  else
15085  return ade_set_args(L, "o", l_Persona.Set(idx));
15086 }
15087 
15088 ADE_FUNC(__len, l_Mission_Personas, NULL, "Number of personas in the mission", "number", "Number of messages in mission")
15089 {
15090  return ade_set_args(L, "i", Num_personas);
15091 }
15092 
15093 ADE_FUNC(addMessage, l_Mission, "string name, string text[, persona persona]", "Adds a message", "message", "The new message or invalid handle on error")
15094 {
15095  char* name = NULL;
15096  char* text = NULL;
15097  int personaIdx = -1;
15098 
15099  if (!ade_get_args(L, "ss|o", &name, &text, l_Persona.Get(&personaIdx)))
15100  return ade_set_error(L, "o", l_Message.Set(-1));
15101 
15102  if (name == NULL || text == NULL)
15103  return ade_set_error(L, "o", l_Message.Set(-1));
15104 
15105  if (personaIdx < 0 || personaIdx >= Num_personas)
15106  personaIdx = -1;
15107 
15108  add_message(name, text, personaIdx, 0);
15109 
15110  return ade_set_error(L, "o", l_Message.Set((int) Messages.size() - 1));
15111 }
15112 
15113 ADE_FUNC(sendMessage, l_Mission, "string sender, message message[, number delay=0.0[, enumeration priority = MESSAGE_PRIORITY_NORMAL[, boolean fromCommand = false]]]",
15114  "Sends a message from the given source (not from a ship!) with the given priority or optionally sends it from the missions command source.<br>"
15115  "If delay is specified the message will be delayed by the specified time in seconds<br>"
15116  "If you pass <i>nil</i> as the sender then the message will not have a sender.",
15117  "boolean", "true if successfull, false otherwise")
15118 {
15119  char* sender = NULL;
15120  int messageIdx = -1;
15121  int priority = MESSAGE_PRIORITY_NORMAL;
15122  bool fromCommand = false;
15123  int messageSource = MESSAGE_SOURCE_SPECIAL;
15124  float delay = 0.0f;
15125 
15126  enum_h* ehp = NULL;
15127 
15128  // if first is nil then use no source
15129  if (lua_isnil(L, 1))
15130  {
15131  if (!ade_get_args(L, "*o|fob", l_Message.Get(&messageIdx), &delay, l_Enum.GetPtr(&ehp), &fromCommand))
15132  return ADE_RETURN_FALSE;
15133 
15134  messageSource = MESSAGE_SOURCE_NONE;
15135  }
15136  else
15137  {
15138  if (!ade_get_args(L, "so|fob", &sender, l_Message.Get(&messageIdx), &delay, l_Enum.GetPtr(&ehp), &fromCommand))
15139  return ADE_RETURN_FALSE;
15140 
15141  if (sender == NULL)
15142  return ADE_RETURN_FALSE;
15143  }
15144 
15145  if (fromCommand)
15146  messageSource = MESSAGE_SOURCE_COMMAND;
15147 
15148  if (messageIdx < 0 || messageIdx >= (int) Messages.size())
15149  return ADE_RETURN_FALSE;
15150 
15151  if (messageIdx < Num_builtin_messages)
15152  {
15153  LuaError(L, "Cannot send built-in messages!");
15154  return ADE_RETURN_FALSE;
15155  }
15156 
15157  if (delay < 0.0f)
15158  {
15159  LuaError(L, "Invalid negative delay of %f!", delay);
15160  return ADE_RETURN_FALSE;
15161  }
15162 
15163  if (ehp != NULL)
15164  {
15165  switch(ehp->index)
15166  {
15168  priority = MESSAGE_PRIORITY_HIGH;
15169  break;
15171  priority = MESSAGE_PRIORITY_NORMAL;
15172  break;
15174  priority = MESSAGE_PRIORITY_LOW;
15175  break;
15176  default:
15177  LuaError(L, "Invalid enumeration used! Must be one of MESSAGE_PRIORITY_*.");
15178  return ADE_RETURN_FALSE;
15179  }
15180  }
15181 
15182  if (messageSource == MESSAGE_SOURCE_NONE)
15183  message_send_unique_to_player(Messages[messageIdx].name, NULL, MESSAGE_SOURCE_NONE, priority, 0, fl2i(delay * 1000.0f));
15184  else
15185  message_send_unique_to_player(Messages[messageIdx].name, (void*) sender, messageSource, priority, 0, fl2i(delay * 1000.0f));
15186 
15187  return ADE_RETURN_TRUE;
15188 }
15189 
15190 ADE_FUNC(sendTrainingMessage, l_Mission, "message message, number time[, number delay=0.0]",
15191  "Sends a training message to the player. <i>time</i> is the amount in seconds to display the message, only whole seconds are used!",
15192  "boolean", "true if successfull, false otherwise")
15193 {
15194  int messageIdx = -1;
15195  float delay = 0.0f;
15196  int time = -1;
15197 
15198  if (!ade_get_args(L, "oi|f", l_Message.Get(&messageIdx), &time, &delay))
15199  return ADE_RETURN_FALSE;
15200 
15201  if (messageIdx < 0 || messageIdx >= (int) Messages.size())
15202  return ADE_RETURN_FALSE;
15203 
15204  if (delay < 0.0f)
15205  {
15206  LuaError(L, "Got invalid delay of %f seconds!", delay);
15207  return ADE_RETURN_FALSE;
15208  }
15209 
15210  if (time < 0)
15211  {
15212  LuaError(L, "Got invalid time of %d seconds!", time);
15213  return ADE_RETURN_FALSE;
15214  }
15215 
15216  message_training_queue(Messages[messageIdx].name, timestamp(fl2i(delay * 1000.0f)), time);
15217 
15218  return ADE_RETURN_TRUE;
15219 }
15220 
15221 ADE_FUNC(createShip, l_Mission, "[string Name, shipclass Class=Shipclass[1], orientation Orientation=null, vector Position={0,0,0}]", "Creates a ship and returns a handle to it using the specified name, class, world orientation, and world position", "ship", "Ship handle, or invalid ship handle if ship couldn't be created")
15222 {
15223  char *name = NULL;
15224  int sclass = -1;
15225  matrix_h *orient = NULL;
15227  ade_get_args(L, "|sooo", &name, l_Shipclass.Get(&sclass), l_Matrix.GetPtr(&orient), l_Vector.Get(&pos));
15228 
15229  matrix *real_orient = &vmd_identity_matrix;
15230  if(orient != NULL)
15231  {
15232  real_orient = orient->GetMatrix();
15233  }
15234 
15235  int obj_idx = ship_create(real_orient, &pos, sclass, name);
15236 
15237  if(obj_idx > -1) {
15238  model_page_in_textures(Ship_info[sclass].model_num, sclass);
15239 
15240  return ade_set_args(L, "o", l_Ship.Set(object_h(&Objects[obj_idx]), Objects[obj_idx].signature));
15241  } else
15242  return ade_set_error(L, "o", l_Ship.Set(object_h()));
15243 }
15244 
15245 ADE_FUNC(createWaypoint, l_Mission, "[vector Position, waypointlist List]",
15246  "Creates a waypoint",
15247  "waypoint",
15248  "Waypoint handle, or invalid waypoint handle if waypoint couldn't be created")
15249 {
15250  vec3d *v3 = NULL;
15251  waypointlist_h *wlh = NULL;
15252  if(!ade_get_args(L, "|oo", l_Vector.GetPtr(&v3), l_WaypointList.GetPtr(&wlh)))
15253  return ade_set_error(L, "o", l_Waypoint.Set(object_h()));
15254 
15255  // determine where we need to create it - it looks like we were given a waypoint list but not a waypoint itself
15256  int waypoint_instance = -1;
15257  if (wlh && wlh->IsValid())
15258  {
15259  int wp_list_index = find_index_of_waypoint_list(wlh->wlp);
15260  int wp_index = (int) wlh->wlp->get_waypoints().size() - 1;
15261  waypoint_instance = calc_waypoint_instance(wp_list_index, wp_index);
15262  }
15263  int obj_idx = waypoint_add(v3 != NULL ? v3 : &vmd_zero_vector, waypoint_instance);
15264 
15265  if(obj_idx >= 0)
15266  return ade_set_args(L, "o", l_Waypoint.Set(object_h(&Objects[obj_idx])));
15267  else
15268  return ade_set_args(L, "o", l_Waypoint.Set(object_h()));
15269 }
15270 
15271 ADE_FUNC(createWeapon, l_Mission, "[weaponclass Class=WeaponClass[1], orientation Orientation=null, world vector Position={0,0,0}, object Parent = nil, number Group = -1",
15272  "Creates a weapon and returns a handle to it. 'Group' is used for lighting grouping purposes;"
15273  " for example, quad lasers would only need to act as one light source.",
15274  "weapon",
15275  "Weapon handle, or invalid weapon handle if weapon couldn't be created.")
15276 {
15277  int wclass = -1;
15278  object_h *parent = NULL;
15279  int group = -1;
15280  matrix_h *orient = NULL;
15282  ade_get_args(L, "|ooooi", l_Weaponclass.Get(&wclass), l_Matrix.GetPtr(&orient), l_Vector.Get(&pos), l_Object.GetPtr(&parent), &group);
15283 
15284  matrix *real_orient = &vmd_identity_matrix;
15285  if(orient != NULL)
15286  {
15287  real_orient = orient->GetMatrix();
15288  }
15289 
15290  int parent_idx = (parent && parent->IsValid()) ? OBJ_INDEX(parent->objp) : -1;
15291 
15292  int obj_idx = weapon_create(&pos, real_orient, wclass, parent_idx, group);
15293 
15294  if(obj_idx > -1)
15295  return ade_set_args(L, "o", l_Weapon.Set(object_h(&Objects[obj_idx]), Objects[obj_idx].signature));
15296  else
15297  return ade_set_error(L, "o", l_Weapon.Set(object_h()));
15298 }
15299 
15300 ADE_FUNC(getMissionFilename, l_Mission, NULL, "Gets mission filename", "string", "Mission filename, or empty string if game is not in a mission")
15301 {
15303 }
15304 
15305 ADE_FUNC(startMission, l_Mission, "[Filename or MISSION_* enumeration, Briefing = true]", "Starts the defined mission", "boolean", "True, or false if the function fails")
15306 {
15307  bool b = true;
15308  char s[MAX_FILENAME_LEN];
15309  char *str = s;
15310 
15311  if(lua_isstring(L, 1))
15312  {
15313  if (!ade_get_args(L, "s|b", &str, &b))
15314  return ade_set_args(L, "b", false);
15315 
15316  } else {
15317  enum_h *e = NULL;
15318 
15319  if (!ade_get_args(L, "o|b", l_Enum.GetPtr(&e), &b))
15320  return ade_set_args(L, "b", false);
15321 
15322  if (e->index == LE_MISSION_REPEAT) {
15323  if (Num_recent_missions > 0) {
15324  strncpy( s, Recent_missions[0], MAX_FILENAME_LEN );
15325  } else {
15326  return ade_set_args(L, "b", false);
15327  }
15328  } else {
15329  return ade_set_args(L, "b", false);
15330  }
15331  }
15332 
15333  // no filename... bail
15334  if (str == NULL)
15335  return ade_set_args(L, "b", false);
15336 
15337  // if mission name has extension... it needs to be removed...
15338  char *file_ext;
15339 
15340  file_ext = strrchr(str, '.');
15341  if (file_ext)
15342  *file_ext = 0;
15343 
15344  // game is in MP mode... or if the file does not exist... bail
15345  if ((Game_mode & GM_MULTIPLAYER) || (cf_exists_full(str, CF_TYPE_MISSIONS) != 0))
15346  return ade_set_args(L, "b", false);
15347 
15348  // mission is already running...
15349  if (Game_mode & GM_IN_MISSION) {
15350  // TO DO... All the things needed if this function is called in any state of the game while mission is running.
15351  // most likely all require 'stricmp(str, Game_current_mission_filename)' to make sure missions arent mixed
15352  // but after that it might be possible to imprement method for jumping directly into already running
15353  // missions.
15354  return ade_set_args(L, "b", false);
15355  // if mission is not running
15356  } else {
15357  // due safety checks of the game_start_mission() function allow only main menu for now.
15360  if (b == true) {
15361  // start mission - go via briefing screen
15363  } else {
15364  // start mission - enter the game directly
15366  }
15367  return ade_set_args(L, "b", true);
15368  }
15369  }
15370  return ade_set_args(L, "b", false);
15371 }
15372 
15373 ADE_FUNC(getMissionTime, l_Mission, NULL, "Game time in seconds since the mission was started; is affected by time compression", "number", "Mission time (seconds), or 0 if game is not in a mission")
15374 {
15375  if(!(Game_mode & GM_IN_MISSION))
15376  return ade_set_error(L, "f", 0.0f);
15377 
15378  return ade_set_args(L, "x", Missiontime);
15379 }
15380 
15381 //WMC - These are in freespace.cpp
15382 ADE_FUNC(loadMission, l_Mission, "Mission name", "Loads a mission", "boolean", "True if mission was loaded, otherwise false")
15383 {
15384  char *s;
15385  if(!ade_get_args(L, "s", &s))
15386  return ade_set_error(L, "b", false);
15387 
15388  // clear post processing settings
15390 
15391  //NOW do the loading stuff
15392  game_stop_time();
15393  get_mission_info(s, &The_mission, false);
15394  game_level_init();
15395 
15396  if(mission_load(s) == -1)
15397  return ADE_RETURN_FALSE;
15398 
15400 
15402 
15403  return ADE_RETURN_TRUE;
15404 }
15405 
15406 ADE_FUNC(unloadMission, l_Mission, NULL, "Stops the current mission and unloads it", NULL, NULL)
15407 {
15408  if(Game_mode & GM_IN_MISSION)
15409  {
15410  game_level_close();
15411  Game_mode &= ~GM_IN_MISSION;
15413  }
15414 
15415  return ADE_RETURN_NIL;
15416 }
15417 
15418 ADE_FUNC(simulateFrame, l_Mission, NULL, "Simulates mission frame", NULL, NULL)
15419 {
15422 
15423  return ADE_RETURN_TRUE;
15424 }
15425 
15426 ADE_FUNC(renderFrame, l_Mission, NULL, "Renders mission frame, but does not move anything", NULL, NULL)
15427 {
15429  game_render_frame( cid );
15431 
15432  return ADE_RETURN_TRUE;
15433 }
15434 
15435 ADE_FUNC(applyShudder, l_Mission, "number time, number intesity", "Applies a shudder effects to the camera. Time is in seconds. Intensity specifies the shudder effect strength, the Maxim has a value of 1440.", "boolean", "true if successfull, false otherwise")
15436 {
15437  float time = -1.0f;
15438  float intensity = -1.0f;
15439 
15440  if (!ade_get_args(L, "ff", &time, &intensity))
15441  return ADE_RETURN_FALSE;
15442 
15443  if (time < 0.0f || intensity < 0.0f)
15444  {
15445  LuaError(L, "Illegal shudder values given. Must be bigger than zero, got time of %f and intensity of %f.", time, intensity);
15446  return ADE_RETURN_FALSE;
15447  }
15448 
15449  int int_time = fl2i(time * 1000.0f);
15450 
15451  game_shudder_apply(int_time, intensity * 0.01f);
15452 
15453  return ADE_RETURN_TRUE;
15454 }
15455 
15456 ADE_FUNC(isInCampaign, l_Mission, NULL, "Get whether or not the current mission being played in a campaign (as opposed to the tech room's simulator)", "boolean", "true if in campaign, false if not")
15457 {
15458  bool b = false;
15459 
15461  b = true;
15462  }
15463 
15464  return ade_set_args(L, "b", b);
15465 }
15466 
15467 //**********LIBRARY: Bitwise Ops
15468 ade_lib l_BitOps("BitOps", NULL, "bit", "Bitwise Operations library");
15469 
15470 ADE_FUNC(AND, l_BitOps, "number, number", "Values for which bitwise boolean AND operation is performed", "number", "Result of the AND operation")
15471 {
15472  int a, b, c;
15473  if(!ade_get_args(L, "ii", &a,&b))
15474  return ade_set_error(L, "i", 0);
15475 
15476  c = (a & b);
15477 
15478  return ade_set_args(L, "i", c);
15479 }
15480 
15481 ADE_FUNC(OR, l_BitOps, "number, number", "Values for which bitwise boolean OR operation is performed", "number", "Result of the OR operation")
15482 {
15483  int a, b, c;
15484  if(!ade_get_args(L, "ii", &a,&b))
15485  return ade_set_error(L, "i", 0);
15486 
15487  c = (a | b);
15488 
15489  return ade_set_args(L, "i", c);
15490 }
15491 
15492 ADE_FUNC(XOR, l_BitOps, "number, number", "Values for which bitwise boolean XOR operation is performed", "number", "Result of the XOR operation")
15493 {
15494  int a, b, c;
15495  if(!ade_get_args(L, "ii", &a,&b))
15496  return ade_set_error(L, "i", 0);
15497 
15498  c = (a ^ b);
15499 
15500  return ade_set_args(L, "i", c);
15501 }
15502 
15503 ADE_FUNC(toggleBit, l_BitOps, "number, number (bit)", "Toggles the value of the set bit in the given number for 32 bit integer", "number", "Result of the operation")
15504 {
15505  int a, b, c;
15506  if(!ade_get_args(L, "ii", &a,&b))
15507  return ade_set_error(L, "i", 0);
15508 
15509  if (!((b >= 0) && (b < 32)))
15510  return ade_set_error(L, "i", 0);
15511 
15512  if(a & (1<<b))
15513  c = (a & !(1<<b)); //-V564
15514  else
15515  c = (a | (1<<b));
15516 
15517  return ade_set_args(L, "i", c);
15518 }
15519 
15520 ADE_FUNC(checkBit, l_BitOps, "number, number (bit)", "Checks the value of the set bit in the given number for 32 bit integer", "boolean", "Was the bit true of false")
15521 {
15522  int a, b;
15523  if(!ade_get_args(L, "ii", &a,&b))
15524  return ade_set_error(L, "i", 0);
15525 
15526  if (!((b >= 0) && (b < 32)))
15527  return ade_set_error(L, "i", 0);
15528 
15529  if(a & (1<<b))
15530  return ADE_RETURN_TRUE;
15531  else
15532  return ADE_RETURN_FALSE;
15533 }
15534 
15535 ADE_FUNC(addBit, l_BitOps, "number, number (bit)", "Performs inclusive or (OR) operation on the set bit of the value", "number", "Result of the operation")
15536 {
15537  int a, b, c;
15538  if(!ade_get_args(L, "ii", &a,&b))
15539  return ade_set_error(L, "i", 0);
15540 
15541  if (!((b >= 0) && (b < 32)))
15542  return ade_set_error(L, "i", 0);
15543 
15544  c = (a | (1<<b));
15545 
15546  return ade_set_args(L, "i", c);
15547 }
15548 
15549 
15550 //**********LIBRARY: Tables
15551 ade_lib l_Tables("Tables", NULL, "tb", "Tables library");
15552 
15553 //*****SUBLIBRARY: Tables/ShipClasses
15554 ade_lib l_Tables_ShipClasses("ShipClasses", &l_Tables, NULL, NULL);
15555 ADE_INDEXER(l_Tables_ShipClasses, "number Index/string Name", "Array of ship classes", "shipclass", "Ship handle, or invalid ship handle if index is invalid")
15556 {
15557  if(!ships_inited)
15558  return ade_set_error(L, "o", l_Shipclass.Set(-1));
15559 
15560  char *name;
15561  if(!ade_get_args(L, "*s", &name))
15562  return ade_set_error(L, "o", l_Shipclass.Set(-1));
15563 
15564  int idx = ship_info_lookup(name);
15565 
15566  if(idx < 0) {
15567  idx = atoi(name);
15568  if(idx < 1 || idx >= static_cast<int>(Ship_info.size()))
15569  return ade_set_error(L, "o", l_Shipclass.Set(-1));
15570 
15571  idx--; //Lua->FS2
15572  }
15573 
15574  return ade_set_args(L, "o", l_Shipclass.Set(idx));
15575 }
15576 
15577 ADE_FUNC(__len, l_Tables_ShipClasses, NULL, "Number of ship classes", "number", "Number of ship classes, or 0 if ship classes haven't been loaded yet")
15578 {
15579  if(!ships_inited)
15580  return ade_set_args(L, "i", 0); //No ships loaded...should be 0
15581 
15582  return ade_set_args(L, "i", Ship_info.size());
15583 }
15584 
15585 //*****SUBLIBRARY: Tables/WeaponClasses
15586 ade_lib l_Tables_WeaponClasses("WeaponClasses", &l_Tables, NULL, NULL);
15587 
15588 extern int Weapons_inited;
15589 
15590 ADE_INDEXER(l_Tables_WeaponClasses, "number Index/string WeaponName", "Array of weapon classes", "weapon", "Weapon class handle, or invalid weaponclass handle if index is invalid")
15591 {
15592  if(!Weapons_inited)
15593  return ade_set_error(L, "o", l_Weaponclass.Set(-1));
15594 
15595  char *name;
15596  if(!ade_get_args(L, "*s", &name))
15597  return 0;
15598 
15599  int idx = weapon_info_lookup(name);
15600 
15601  if(idx < 0) {
15602  idx = atoi(name);
15603 
15604  // atoi is good enough here, 0 is invalid anyway
15605  if (idx > 0)
15606  {
15607  idx--; // Lua --> C/C++
15608  }
15609  else
15610  {
15611  return ade_set_args(L, "o", l_Weaponclass.Set(-1));
15612  }
15613  }
15614 
15615  return ade_set_args(L, "o", l_Weaponclass.Set(idx));
15616 }
15617 
15618 ADE_FUNC(__len, l_Tables_WeaponClasses, NULL, "Number of weapon classes", "number", "Number of weapon classes, or 0 if weapon classes haven't been loaded yet")
15619 {
15620  if(!Weapons_inited)
15621  return ade_set_args(L, "i", 0);
15622 
15623  return ade_set_args(L, "i", Num_weapon_types);
15624 }
15625 
15626 //*************************Testing stuff*************************
15627 //This section is for stuff that's considered experimental.
15628 ade_lib l_Testing("Testing", NULL, "ts", "Experimental or testing stuff");
15629 
15630 ADE_FUNC(avdTest, l_Testing, NULL, "Test the AVD Physics code", NULL, NULL)
15631 {
15632  static bool initialized = false;
15633  static avd_movement avd;
15634 
15635  if(!initialized)
15636  {
15637  avd.setAVD(10.0f, 3.0f, 1.0f, 1.0f, 0.0f);
15638  initialized = true;
15639  }
15640  for(int i = 0; i < 3000; i++)
15641  {
15642  float Pc, Vc;
15643  avd.get((float)i/1000.0f, &Pc, &Vc);
15644  gr_set_color(0, 255, 0);
15645  gr_pixel(i/10, gr_screen.clip_bottom - (int)(Pc*10.0f), GR_RESIZE_NONE);
15646  gr_set_color(255, 0, 0);
15647  gr_pixel(i/10, gr_screen.clip_bottom - (int)(Vc*10.0f), GR_RESIZE_NONE);
15648 
15649  avd.get(&Pc, &Vc);
15650  gr_set_color(255, 255, 255);
15651  gr_pixel((timestamp()%3000)/10, gr_screen.clip_bottom - (int)(Pc*10.0f), GR_RESIZE_NONE);
15652  gr_pixel((timestamp()%3000)/10, gr_screen.clip_bottom - (int)(Vc*10.0f), GR_RESIZE_NONE);
15653  }
15654 
15655  return ADE_RETURN_NIL;
15656 }
15657 
15658 ADE_FUNC(createParticle, l_Testing, "vector Position, vector Velocity, number Lifetime, number Radius, enumeration Type, [number Tracer length=-1, boolean Reverse=false, texture Texture=Nil, object Attached Object=Nil]",
15659  "Creates a particle. Use PARTICLE_* enumerations for type."
15660  "Reverse reverse animation, if one is specified"
15661  "Attached object specifies object that Position will be (and always be) relative to.",
15662  "particle",
15663  "Handle to the created particle")
15664 {
15665  particle_info pi;
15666  pi.type = PARTICLE_DEBUG;
15667  pi.optional_data = -1;
15668  pi.tracer_length = 1.0f;
15669  pi.attached_objnum = -1;
15670  pi.attached_sig = -1;
15671  pi.reverse = 0;
15672 
15673  enum_h *type = NULL;
15674  bool rev=false;
15675  object_h *objh=NULL;
15676  if(!ade_get_args(L, "ooffo|fboo", l_Vector.Get(&pi.pos), l_Vector.Get(&pi.vel), &pi.lifetime, &pi.rad, l_Enum.GetPtr(&type), &pi.tracer_length, &rev, l_Texture.Get((int*)&pi.optional_data), l_Object.GetPtr(&objh)))
15677  return ADE_RETURN_NIL;
15678 
15679  if(type != NULL)
15680  {
15681  switch(type->index)
15682  {
15683  case LE_PARTICLE_DEBUG:
15684  pi.type = PARTICLE_DEBUG;
15685  break;
15686  case LE_PARTICLE_FIRE:
15687  pi.type = PARTICLE_FIRE;
15688  break;
15689  case LE_PARTICLE_SMOKE:
15690  pi.type = PARTICLE_SMOKE;
15691  break;
15692  case LE_PARTICLE_SMOKE2:
15693  pi.type = PARTICLE_SMOKE2;
15694  break;
15695  case LE_PARTICLE_BITMAP:
15696  if (pi.optional_data < 0)
15697  {
15698  LuaError(L, "Invalid texture specified for createParticle()!");
15699  }
15700 
15701  pi.type = PARTICLE_BITMAP;
15702  break;
15703  }
15704  }
15705 
15706  if(rev)
15707  pi.reverse = 0;
15708 
15709  if(objh != NULL && objh->IsValid())
15710  {
15711  pi.attached_objnum = OBJ_INDEX(objh->objp);
15712  pi.attached_sig = objh->objp->signature;
15713  }
15714 
15715  particle *p = particle_create(&pi);
15716 
15717  if (p != NULL)
15718  return ade_set_args(L, "o", l_Particle.Set(particle_h(p)));
15719  else
15720  return ADE_RETURN_NIL;
15721 }
15722 
15723 ADE_FUNC(getStack, l_Testing, NULL, "Generates an ADE stackdump", "string", "Current Lua stack")
15724 {
15725  char buf[10240] = {'\0'};
15726  ade_stackdump(L, buf);
15727  return ade_set_args(L, "s", buf);
15728 }
15729 
15730 ADE_FUNC(isCurrentPlayerMulti, l_Testing, NULL, "Returns whether current player is a multiplayer pilot or not.", "boolean", "Whether current player is a multiplayer pilot or not")
15731 {
15732  if(Player == NULL)
15733  return ade_set_error(L, "b", false);
15734 
15736  return ADE_RETURN_FALSE;
15737 
15738  return ADE_RETURN_TRUE;
15739 }
15740 
15741 // Om_tracker_flag should already be set in FreeSpace.cpp, needed to determine if PXO is enabled from the registry
15742 extern int Om_tracker_flag; // needed for FS2OpenPXO config
15743 
15744 ADE_FUNC(isPXOEnabled, l_Testing, NULL, "Returns whether PXO is currently enabled in the configuration.", "boolean", "Whether PXO is enabled or not")
15745 {
15746  if(!(Om_tracker_flag))
15747  return ADE_RETURN_FALSE;
15748 
15749  return ADE_RETURN_TRUE;
15750 }
15751 
15752 ADE_FUNC(playCutscene, l_Testing, NULL, "Forces a cutscene by the specified filename string to play. Should really only be used in a non-gameplay state (i.e. start of GS_STATE_BRIEFING) otherwise odd side effects may occur. Highly Experimental.", "string", NULL)
15753 {
15754  //This whole thing is a quick hack and can probably be done way better, but is currently functioning fine for my purposes.
15755  char *filename;
15756 
15757  if (!ade_get_args(L, "s", &filename))
15758  return ADE_RETURN_FALSE;
15759 
15760  movie_play(filename);
15761 
15762  return ADE_RETURN_TRUE;
15763 }
15764 
15765 // *************************Helper functions*********************
15766 //WMC - This should be used anywhere that an 'object' is set, so
15767 //that scripters can get access to as much relevant data to that
15768 //object as possible.
15769 //It should also be updated as new types are added to Lua.
15770 int ade_set_object_with_breed(lua_State *L, int obj_idx)
15771 {
15772  if(obj_idx < 0 || obj_idx >= MAX_OBJECTS)
15773  return ade_set_error(L, "o", l_Object.Set(object_h()));
15774 
15775  object *objp = &Objects[obj_idx];
15776 
15777  switch(objp->type)
15778  {
15779  case OBJ_SHIP:
15780  return ade_set_args(L, "o", l_Ship.Set(object_h(objp)));
15781  case OBJ_ASTEROID:
15782  return ade_set_args(L, "o", l_Asteroid.Set(object_h(objp)));
15783  case OBJ_DEBRIS:
15784  return ade_set_args(L, "o", l_Debris.Set(object_h(objp)));
15785  case OBJ_WAYPOINT:
15786  return ade_set_args(L, "o", l_Waypoint.Set(object_h(objp)));
15787  case OBJ_WEAPON:
15788  return ade_set_args(L, "o", l_Weapon.Set(object_h(objp)));
15789  case OBJ_BEAM:
15790  return ade_set_args(L, "o", l_Beam.Set(object_h(objp)));
15791  default:
15792  return ade_set_args(L, "o", l_Object.Set(object_h(objp)));
15793  }
15794 }
15795 
15796 //###########################################################
15797 //########################<IMPORTANT>########################
15798 //###########################################################
15799 //If you are a coder who wants to add libraries, functions,
15800 //or objects to Lua, then you want to be above this point.
15801 //###########################################################
15802 //########################</IMPORTANT>#######################
15803 //###########################################################
15804 
15805 // *************************Housekeeping*************************
15806 //WMC - The miraculous lines of code that make Lua debugging worth something.
15807 lua_Debug Ade_debug_info;
15808 char debug_stack[4][32];
15809 
15810 void ade_debug_call(lua_State *L, lua_Debug *ar)
15811 {
15812  Assert(L != NULL);
15813  Assert(ar != NULL);
15814  lua_getstack(L, 1, ar);
15815  lua_getinfo(L, "nSlu", ar);
15816  memcpy(&Ade_debug_info, ar, sizeof(lua_Debug));
15817 
15818  int n;
15819  for (n = 0; n < 4; n++) {
15820  debug_stack[n][0] = '\0';
15821  }
15822 
15823  for (n = 0; n < 4; n++) {
15824  if (lua_getstack(L,n+1, ar) == 0)
15825  break;
15826  lua_getinfo(L,"n", ar);
15827  if (ar->name == NULL)
15828  break;
15829  strcpy_s(debug_stack[n],ar->name);
15830  }
15831 }
15832 
15833 void ade_debug_ret(lua_State *L, lua_Debug *ar)
15834 {
15835  Assert(L != NULL);
15836  Assert(ar != NULL);
15837  lua_getstack(L, 1, ar);
15838  lua_getinfo(L, "nSlu", ar);
15839  memcpy(&Ade_debug_info, ar, sizeof(lua_Debug));
15840 
15841  int n;
15842  for (n = 0; n < 4; n++) {
15843  debug_stack[n][0] = '\0';
15844  }
15845 
15846  for (n = 0; n < 4; n++) {
15847  if (lua_getstack(L,n+1, ar) == 0)
15848  break;
15849  lua_getinfo(L,"n", ar);
15850  if (ar->name == NULL)
15851  break;
15852  strcpy_s(debug_stack[n],ar->name);
15853  }
15854 }
15855 
15856 //WMC - because the behavior of the return keyword
15857 //was changed, I now have to use this in hooks.
15858 static int ade_return_hack(lua_State *L)
15859 {
15860  int i = 0;
15861  int num = lua_gettop(L);
15862  for(i = 0; i < num; i++)
15863  {
15864  lua_pushvalue(L, i+1);
15865  }
15866 
15867  return num;
15868 }
15869 //Inits LUA
15870 //Note that "libraries" must end with a {NULL, NULL}
15871 //element
15873 {
15874  mprintf(("LUA: Opening LUA state...\n"));
15875  lua_State *L = lua_open();
15876 
15877  if(L == NULL)
15878  {
15879  Warning(LOCATION, "Could not initialize Lua");
15880  return 0;
15881  }
15882 
15883  //*****INITIALIZE AUXILIARY LIBRARIES
15884  mprintf(("LUA: Initializing base Lua libraries...\n"));
15885  luaL_openlibs(L);
15886 
15887  //*****DISABLE DANGEROUS COMMANDS
15888  lua_pushstring(L, "os");
15889  lua_rawget(L, LUA_GLOBALSINDEX);
15890  int os_ldx = lua_gettop(L);
15891  if(lua_istable(L, os_ldx))
15892  {
15893  lua_pushstring(L, "execute");
15894  lua_pushnil(L);
15895  lua_rawset(L, os_ldx);
15896  lua_pushstring(L, "remove");
15897  lua_pushnil(L);
15898  lua_rawset(L, os_ldx);
15899  lua_pushstring(L, "rename");
15900  lua_pushnil(L);
15901  lua_rawset(L, os_ldx);
15902  }
15903  lua_pop(L, 1); //os table
15904 
15905  //*****SET DEBUG HOOKS
15906 #ifndef NDEBUG
15907  lua_sethook(L, ade_debug_ret, LUA_MASKRET, 0);
15908 #endif
15909 
15910  //*****INITIALIZE ADE
15911  uint i;
15912  mprintf(("LUA: Beginning ADE initialization\n"));
15913  for(i = 0; i < Ade_table_entries.size(); i++)
15914  {
15915  //WMC - Do only toplevel table entries, doi
15916  if(Ade_table_entries[i].ParentIdx == UINT_MAX) //WMC - oh hey, we're done with the meaty point in < 10 lines.
15917  Ade_table_entries[i].SetTable(L, LUA_GLOBALSINDEX, LUA_GLOBALSINDEX); //Oh the miracles of OOP.
15918  }
15919 
15920  //*****INITIALIZE RETURN HACK FUNCTION
15921  lua_pushstring(L, "ade_return_hack");
15922  lua_pushboolean(L, 0);
15923  lua_pushcclosure(L, ade_return_hack, 2);
15924  lua_setglobal(L, "ade_return_hack");
15925 
15926  //*****INITIALIZE ENUMERATION CONSTANTS
15927  mprintf(("ADE: Initializing enumeration constants...\n"));
15928  enum_h eh;
15929  for(i = 0; i < Num_enumerations; i++)
15930  {
15931  eh.index = Enumerations[i].def;
15932  eh.is_constant = true;
15933 
15934  ade_set_args(L, "o", l_Enum.Set(eh));
15935  lua_setglobal(L, Enumerations[i].name);
15936  }
15937 
15938  //*****ASSIGN LUA SESSION
15939  mprintf(("ADE: Assigning Lua session...\n"));
15940  SetLuaSession(L);
15941 
15942  return 1;
15943 }
15944 
15945 void script_state::EndLuaFrame()
15946 {
15947  memcpy(NextDrawStringPos, NextDrawStringPosInitial, sizeof(NextDrawStringPos));
15948 }
15949 
15950 //*************************Lua functions*************************
15951 //WMC - Spits out the current Lua stack to "stackdump"
15952 //This includes variable values, but not names
15953 void ade_stackdump(lua_State *L, char *stackdump)
15954 {
15955  char buf[512];
15956  int stacksize = lua_gettop(L);
15957 
15958  //Lua temps
15959  double d;
15960  int b;
15961  char *s;
15962  for(int argnum = 1; argnum <= stacksize; argnum++)
15963  {
15964  int type = lua_type(L, argnum);
15965  sprintf(buf, "\r\n%d: ", argnum);
15966  strcat(stackdump, buf);
15967  switch(type)
15968  {
15969  case LUA_TNIL:
15970  strcat(stackdump, "NIL");
15971  break;
15972  case LUA_TNUMBER:
15973  d = lua_tonumber(L, argnum);
15974  sprintf(buf, "Number [%f]",d);
15975  strcat(stackdump, buf);
15976  break;
15977  case LUA_TBOOLEAN:
15978  b = lua_toboolean(L, argnum);
15979  sprintf(buf, "Boolean [%d]",b);
15980  strcat(stackdump, buf);
15981  break;
15982  case LUA_TSTRING:
15983  s = (char *)lua_tostring(L, argnum);
15984  sprintf(buf, "String [%s]",s);
15985  strcat(stackdump, buf);
15986  break;
15987  case LUA_TTABLE:
15988  {
15989  if(lua_getmetatable(L, argnum))
15990  {
15991  lua_pushstring(L, "__adeid");
15992  lua_rawget(L, -2);
15993  if(lua_isnumber(L, -1))
15994  {
15995  sprintf(buf, "Table [%s]", Ade_table_entries[(uint)lua_tonumber(L, -1)].Name);
15996  strcat(stackdump, buf);
15997  }
15998  else
15999  strcat(stackdump, "non-default Table");
16000  lua_pop(L, 2); //metatable and nil/adeid
16001  }
16002  else
16003  strcat(stackdump, "Table w/ no metatable");
16004 
16005  //Maybe get first key?
16006  char *firstkey = NULL;
16007  lua_pushnil(L);
16008  if(lua_next(L, argnum))
16009  {
16010  firstkey = (char *)lua_tostring(L, -2);
16011  if(firstkey != NULL)
16012  {
16013  strcat(stackdump, ", First key: [");
16014  strcat(stackdump, firstkey);
16015  strcat(stackdump, "]");
16016  }
16017  lua_pop(L, 1); //Key
16018  }
16019  lua_pop(L, 1); //Nil
16020  }
16021  break;
16022  case LUA_TFUNCTION:
16023  strcat(stackdump, "Function");
16024  {
16025  char *upname = (char*)lua_getupvalue(L, argnum, ADE_FUNCNAME_UPVALUE_INDEX);
16026  if(upname != NULL)
16027  {
16028  strcat(stackdump, " ");
16029  strcat(stackdump, lua_tostring(L, -1));
16030  strcat(stackdump, "()");
16031  lua_pop(L, 1);
16032  }
16033  }
16034  break;
16035  case LUA_TUSERDATA:
16036  if(lua_getmetatable(L, argnum))
16037  {
16038  lua_pushstring(L, "__adeid");
16039  lua_rawget(L, -2);
16040  if(lua_isnumber(L, -1))
16041  {
16042  sprintf(buf, "Userdata [%s]", Ade_table_entries[(uint)lua_tonumber(L, -1)].Name);
16043  }
16044  else
16045  sprintf(buf, "non-default Userdata");
16046 
16047  lua_pop(L, 2); //metatable and nil/adeid
16048  }
16049  else
16050  sprintf(buf, "Userdata w/ no metatable");
16051  strcat(stackdump, buf);
16052  break;
16053  case LUA_TTHREAD:
16054  sprintf(buf, "Thread");
16055  strcat(stackdump, buf);
16056  break;
16057  case LUA_TLIGHTUSERDATA:
16058  sprintf(buf, "Light userdata");
16059  strcat(stackdump, buf);
16060  break;
16061  default:
16062  sprintf(buf, "<UNKNOWN>: %s (%f) (%s)", lua_typename(L, type), lua_tonumber(L, argnum), lua_tostring(L, argnum));
16063  strcat(stackdump, buf);
16064  break;
16065  }
16066  }
16067 }
16068 
16069 //WMC - Sometimes this gets out of sync between Lua versions
16070 static const char *Lua_type_names[] = {
16071  "nil",
16072  "boolean",
16073  "light userdata",
16074  "number",
16075  "string",
16076  "table",
16077  "function",
16078  "userdata",
16079  "thread",
16080 };
16081 
16082 static int Lua_type_names_num = sizeof(Lua_type_names)/sizeof(char*);
16083 
16084 //WMC - Gets type of object
16085 const char *ade_get_type_string(lua_State *L, int argnum)
16086 {
16087  int type = lua_type(L, argnum);
16088 
16089  if(type < 0 || type >= Lua_type_names_num)
16090  return "Unknown";
16091 
16092  return Lua_type_names[type];
16093 }
16094 
16095 //WMC - hack to skip X number of arguments on the stack
16096 //Lets me use ade_get_args for global hook return values
16099 
16100 //ade_get_args(state, arguments, variables)
16101 //----------------------------------------------
16102 //based on "Programming in Lua"
16103 //
16104 //Parses arguments from string to variables given
16105 //a '|' divides required and optional arguments.
16106 //Returns 0 if a required argument is invalid,
16107 //or there are too few arguments actually passed
16108 //
16109 //NOTE: This function essentially takes objects
16110 //from the stack in series, so it can easily be used
16111 //to get the return values from a chunk of Lua code
16112 //after it has been executed. See RunByteCode()
16113 int ade_get_args(lua_State *L, const char *fmt, ...)
16114 {
16115  //Check that we have all the arguments that we need
16116  //If we don't, return 0
16117  int needed_args = strlen(fmt);
16118  int total_args = lua_gettop(L) - Ade_get_args_skip;
16119 
16120  if(strchr(fmt, '|') != NULL) {
16121  needed_args = strchr(fmt, '|') - fmt;
16122  }
16123 
16124  char funcname[128] = "\0";
16125 #ifndef NDEBUG
16126  lua_Debug ar;
16127  memset(&ar, 0, sizeof(ar));
16128  if(lua_getstack(L, 0, &ar))
16129  {
16130  lua_getinfo(L, "nl", &ar);
16131  strcpy_s(funcname, "");
16132  if(ar.name != NULL) {
16133  strcat_s(funcname, ar.name);
16134  }
16135  if(ar.currentline > -1) {
16136  char buf[33];
16137  sprintf(buf, "%d", ar.currentline);
16138  strcat_s(funcname, " (Line ");
16139  strcat_s(funcname, buf);
16140  strcat_s(funcname, ")");
16141  }
16142  }
16143 #endif
16144  if(!strlen(funcname)) {
16145  //WMC - This was causing crashes with user-defined functions.
16146  //WMC - Try and get at function name from upvalue
16147  if(!Ade_get_args_lfunction && !lua_isnone(L, lua_upvalueindex(ADE_FUNCNAME_UPVALUE_INDEX)))
16148  {
16149  if(lua_type(L, lua_upvalueindex(ADE_FUNCNAME_UPVALUE_INDEX)) == LUA_TSTRING)
16150  strcpy_s(funcname, lua_tostring(L, lua_upvalueindex(ADE_FUNCNAME_UPVALUE_INDEX)));
16151  }
16152 
16153  //WMC - Totally unknown function
16154  if(!strlen(funcname)) {
16155  strcpy_s(funcname, "<UNKNOWN>");
16156  }
16157  }
16158  if(total_args < needed_args) {
16159  LuaError(L, "Not enough arguments for '%s' - need %d, had %d. If you are using objects or handles, make sure that you are using \":\" to access member functions, rather than \".\"", funcname, needed_args, total_args);
16160  return 0;
16161  }
16162 
16163  //Start throught
16164  va_list vl;
16165  int nargs;
16166  int counted_args = 0;
16167 
16168  //Are we parsing optional args yet?
16169  bool optional_args = false;
16170 
16171  va_start(vl, fmt);
16172  nargs = 1 + Ade_get_args_skip;
16173  total_args += Ade_get_args_skip;
16174  while(*fmt && nargs <= total_args)
16175  {
16176  //Skip functions; I assume these are being used to return args
16177  while(lua_type(L, nargs) == LUA_TFUNCTION && nargs <= total_args)
16178  nargs++;
16179 
16180  if(nargs > total_args)
16181  break;
16182 
16183  switch(*fmt++)
16184  {
16185  case 'b':
16186  if(lua_isboolean(L, nargs)) {
16187  *va_arg(vl, bool*) = lua_toboolean(L, nargs) > 0 ? true : false;
16188  } else {
16189  LuaError(L, "%s: Argument %d is an invalid type '%s'; boolean expected", funcname, nargs, ade_get_type_string(L, nargs));
16190  if(!optional_args) return 0;
16191  }
16192  break;
16193  case 'd':
16194  if(lua_isnumber(L, nargs)) {
16195  *va_arg(vl, double*) = (double)lua_tonumber(L, nargs);
16196  } else {
16197  LuaError(L, "%s: Argument %d is an invalid type '%s'; number expected", funcname, nargs, ade_get_type_string(L, nargs));
16198  if(!optional_args) return 0;
16199  }
16200  break;
16201  case 'f':
16202  if(lua_isnumber(L, nargs)) {
16203  *va_arg(vl, float*) = (float)lua_tonumber(L, nargs);
16204  } else {
16205  LuaError(L, "%s: Argument %d is an invalid type '%s'; number expected", funcname, nargs, ade_get_type_string(L, nargs));
16206  if(!optional_args) return 0;
16207  }
16208  break;
16209  case 'i':
16210  if(lua_isnumber(L, nargs)) {
16211  *va_arg(vl, int*) = (int)lua_tonumber(L, nargs);
16212  } else {
16213  LuaError(L, "%s: Argument %d is an invalid type '%s'; number expected", funcname, nargs, ade_get_type_string(L, nargs));
16214  if(!optional_args) return 0;
16215  }
16216  break;
16217  case 's':
16218  if(lua_isstring(L, nargs)) {
16219  *va_arg(vl, const char **) = lua_tostring(L, nargs);
16220  } else {
16221  LuaError(L, "%s: Argument %d is an invalid type '%s'; string expected", funcname, nargs, ade_get_type_string(L, nargs));
16222  if(!optional_args) return 0;
16223  }
16224  break;
16225  case 'x':
16226  if(lua_isnumber(L, nargs)) {
16227  *va_arg(vl, fix*) = fl2f((float)lua_tonumber(L, nargs));
16228  } else {
16229  LuaError(L, "%s: Argument %d is an invalid type '%s'; number expected", funcname, nargs, ade_get_type_string(L, nargs));
16230  if(!optional_args) return 0;
16231  }
16232  break;
16233  case 'o':
16234  {
16235  ade_odata od = va_arg(vl, ade_odata);
16236  if(lua_isuserdata(L, nargs))
16237  {
16238  //WMC - Get metatable
16239  lua_getmetatable(L, nargs);
16240  int mtb_ldx = lua_gettop(L);
16241  Assert(!lua_isnil(L, -1));
16242 
16243  //Get ID
16244  lua_pushstring(L, "__adeid");
16245  lua_rawget(L, mtb_ldx);
16246 
16247  if(lua_tonumber(L, -1) != od.idx)
16248  {
16249  lua_pushstring(L, "__adederivid");
16250  lua_rawget(L, mtb_ldx);
16251  if((uint)lua_tonumber(L, -1) != od.idx)
16252  {
16253  LuaError(L, "%s: Argument %d is the wrong type of userdata; '%s' given, but '%s' expected", funcname, nargs, Ade_table_entries[(uint)lua_tonumber(L, -2)].Name, Ade_table_entries[od.idx].GetName());
16254  if(!optional_args) return 0;
16255  }
16256  lua_pop(L, 1);
16257  }
16258  lua_pop(L, 2);
16259  if(od.size != ODATA_PTR_SIZE)
16260  {
16261  memcpy(od.buf, lua_touserdata(L, nargs), od.size);
16262  if(od.sig != NULL) {
16263  //WMC - char must be 1
16264  Assert(sizeof(char) == 1);
16265  //WMC - Yuck. Copy sig data.
16266  //Maybe in the future I'll do a packet userdata thing.
16267  (*od.sig) = *(ODATA_SIG_TYPE*)(*(char **)od.buf + od.size);
16268  }
16269  } else {
16270  (*(void**)od.buf) = lua_touserdata(L, nargs);
16271  }
16272  }
16273  else if(lua_isnil(L, nargs) && optional_args)
16274  {
16275  //WMC - Modder has chosen to ignore this argument
16276  }
16277  else
16278  {
16279  LuaError(L, "%s: Argument %d is an invalid type '%s'; type '%s' expected", funcname, nargs, ade_get_type_string(L, nargs), Ade_table_entries[od.idx].GetName());
16280  if(!optional_args) return 0;
16281  }
16282  }
16283  break;
16284  case '|':
16285  nargs--; //cancel out the nargs++ at the end
16286  counted_args--;
16287  optional_args = true;
16288  break;
16289  case '*':
16290  //WMC - Ignore one spot
16291  break;
16292  default:
16293  Error(LOCATION, "%s: Bad character passed to ade_get_args; (%c)", funcname, *(fmt-1));
16294  break;
16295  }
16296  nargs++;
16297  counted_args++;
16298  }
16299  va_end(vl);
16300  return counted_args;
16301 }
16302 
16303 //ade_set_args(state, arguments, variables)
16304 //----------------------------------------------
16305 //based on "Programming in Lua"
16306 //
16307 //Takes variables given and pushes them onto the
16308 //Lua stack. Use it to return variables from a
16309 //Lua scripting function.
16310 //
16311 //NOTE: You can also use this to push arguments
16312 //on to the stack in series. See script_state::SetHookVar
16313 int ade_set_args(lua_State *L, const char *fmt, ...)
16314 {
16315  //Start throught
16316  va_list vl;
16317  int nargs;
16318  int setargs; //args actually set
16319 
16320  va_start(vl, fmt);
16321  nargs = 0;
16322  setargs = 0;
16323  while(*fmt != '\0')
16324  {
16325  switch(*fmt++)
16326  {
16327  case '*':
16328  lua_pushnil(L);
16329  break;
16330  case 'b': //WMC - Bool is actually int for GCC (Why...?)
16331  lua_pushboolean(L, va_arg(vl, int) ? 1 : 0);
16332  break;
16333  case 'd':
16334  lua_pushnumber(L, va_arg(vl, double));
16335  break;
16336  case 'f':
16337  lua_pushnumber(L, va_arg(vl, double));
16338  break;
16339  case 'i':
16340  lua_pushnumber(L, va_arg(vl, int));
16341  break;
16342  case 's':
16343  {
16344  //WMC - Isn't working with HookVar for some strange reason
16345  char *s = va_arg(vl, char*);
16346  lua_pushstring(L, s);
16347  break;
16348  }
16349  case 'x':
16350  lua_pushnumber(L, f2fl(va_arg(vl, fix)));
16351  break;
16352  case 'o':
16353  {
16354  //WMC - char must be 1 byte, foo.
16355  Assert(sizeof(char)==1);
16356  //WMC - step by step
16357  //Copy over objectdata
16358  ade_odata od = (ade_odata) va_arg(vl, ade_odata);
16359 
16360  //Create new LUA object and get handle
16361  char *newod = (char*)lua_newuserdata(L, od.size + sizeof(ODATA_SIG_TYPE));
16362  //Create or get object metatable
16363  luaL_getmetatable(L, Ade_table_entries[od.idx].Name);
16364  //Set the metatable for the object
16365  lua_setmetatable(L, -2);
16366 
16367  //Copy the actual object data to the Lua object
16368  memcpy(newod, od.buf, od.size);
16369 
16370  //Also copy in the unique sig
16371  if(od.sig != NULL)
16372  memcpy(newod + od.size, od.sig, sizeof(ODATA_SIG_TYPE));
16373  else
16374  {
16376  memcpy(newod + od.size, &tempsig, sizeof(ODATA_SIG_TYPE));
16377  }
16378  break;
16379  }
16380  //WMC - Don't forget to update lua_set_arg
16381  default:
16382  Error(LOCATION, "Bad character passed to ade_set_args; (%c)", *(fmt-1));
16383  setargs--;
16384  }
16385  nargs++;
16386  setargs++;
16387  }
16388  va_end(vl);
16389  return setargs;
16390 }
16391 
16392 int ade_friendly_error(lua_State *L)
16393 {
16394  LuaError(L);
16395 
16396  //WMC - According to documentation, this will always be the error
16397  //if error handler is called
16398  return LUA_ERRRUN;
16399 }
16400 
16401 //WMC - Used to get tostring from object, or just return string pointer
16402 //if object is already a string.
16403 char *ade_concat_helper(lua_State *L, int obj_ldx)
16404 {
16405  char *rtn = NULL;
16406 
16407  lua_pushcfunction(L, ade_friendly_error);
16408  int err_ldx = lua_gettop(L);
16409 
16410  if(lua_isstring(L, obj_ldx))
16411  {
16412  rtn = (char*)lua_tostring(L, obj_ldx);
16413  }
16414  else if(lua_isuserdata(L, obj_ldx))
16415  {
16416  if(lua_getmetatable(L, obj_ldx))
16417  {
16418  int mtb_ldx = lua_gettop(L);
16419 
16420  lua_pushstring(L, "__tostring");
16421  lua_rawget(L, mtb_ldx);
16422 
16423  if(lua_iscfunction(L, -1))
16424  {
16425  lua_pushvalue(L, obj_ldx);
16426  if(!lua_pcall(L, 1, 1, err_ldx) && lua_type(L, -1) == LUA_TSTRING)
16427  {
16428  rtn = (char*)lua_tostring(L, -1);
16429  }
16430  }
16431  }
16432  }
16433 
16434  //WMC - Clear out all the extra crap.
16435  lua_pop(L, lua_gettop(L) - err_ldx + 1);
16436 
16437  return rtn;
16438 }
16439 
16440 //1: Userspace variables (ie in object table)
16441 //2: Handle-specific values
16442 //3: Entries in metatable (ie defined by ADE)
16443 //4: Virtual variables
16444 //5: Use the indexer, if possible
16445 //6: Set userspace variable
16446 //7: Set handle-specific variables
16447 //X: Mission failed.
16448 //
16449 //On the stack when this is called:
16450 //Index 1 - Object (Can be anything with Lua 5.1; Number to a library)
16451 //Index 2 - String (ie the key we're trying to access; Object.string, Object:string, Object['string'], etc)
16452 //Index 3 - (Optional) Argument we are trying to set Object.String = Argument
16453 static int ade_index_handler(lua_State *L)
16454 {
16455  Assert(L != NULL);
16456 
16457  const int obj_ldx = 1;
16458  const int key_ldx = 2;
16459  const int arg_ldx = 3;
16460  int last_arg_ldx = lua_gettop(L);
16461  char *type_name = NULL;
16462  uint ade_id = UINT_MAX;
16463  int mtb_ldx = INT_MAX;
16464  ade_table_entry* entry = 0;
16465 
16466  //*****STEP 1: Check for user-defined objects
16467  if(lua_istable(L, obj_ldx) && !ADE_SETTING_VAR)
16468  {
16469  lua_pushvalue(L, key_ldx);
16470  lua_rawget(L, obj_ldx);
16471  if(!lua_isnil(L, -1))
16472  return 1;
16473  else
16474  lua_pop(L, 1); //nil value
16475  }
16476 
16477  //*****STEP 1.5: Set-up metatable
16478  if(lua_getmetatable(L, obj_ldx))
16479  {
16480  mtb_ldx = lua_gettop(L);
16481  lua_pushcfunction(L, ade_friendly_error);
16482  int err_ldx = lua_gettop(L);
16483  int i;
16484 
16485  //*****WMC - go for the type name
16486  lua_pushstring(L, "__adeid");
16487  lua_rawget(L, mtb_ldx);
16488  if(lua_isnumber(L, -1))
16489  {
16490  ade_id = (uint) lua_tonumber(L, -1);
16491  if(ade_id < Ade_table_entries.size())
16492  {
16493  entry = &Ade_table_entries[ade_id];
16494  type_name = entry->Name;
16495  }
16496  }
16497  lua_pop(L, 1);
16498 
16499  //*****STEP 2: Check for handle signature-specific values
16500  if(lua_isuserdata(L, obj_ldx) && ade_id != UINT_MAX && !ADE_SETTING_VAR)
16501  {
16502  //WMC - I assume char is one byte
16503  Assert(sizeof(char) == 1);
16504 
16505  //Get userdata sig
16506  char *ud = (char *)lua_touserdata(L, obj_ldx);
16507  ODATA_SIG_TYPE sig = *(ODATA_SIG_TYPE*)(ud + entry->Value.Object.size);
16508 
16509  //Now use it to index the table with that #
16510  lua_pushnumber(L, sig);
16511  lua_rawget(L, mtb_ldx);
16512  if(lua_istable(L, -1))
16513  {
16514  int hvt_ldx = lua_gettop(L);
16515  lua_pushvalue(L, key_ldx);
16516  lua_rawget(L, hvt_ldx);
16517  if(!lua_isnil(L, -1))
16518  return 1;
16519  else
16520  lua_pop(L, 1); //nil value
16521  }
16522  lua_pop(L, 1); //sig table
16523  }
16524 
16525  //*****STEP 3: Check for __ademember objects (ie defaults)
16526  lua_pushstring(L, "__ademembers");
16527  lua_rawget(L, mtb_ldx);
16528  if(lua_istable(L, -1))
16529  {
16530  int amt_ldx = lua_gettop(L);
16531  lua_pushvalue(L, key_ldx);
16532  lua_rawget(L, amt_ldx);
16533  if(!lua_isnil(L, -1))
16534  return 1;
16535  else
16536  lua_pop(L, 1); //nil value
16537  }
16538  lua_pop(L, 1); //member table
16539 
16540  //*****STEP 4: Check for virtual variables
16541  lua_pushstring(L, "__virtvars");
16542  lua_rawget(L, mtb_ldx);
16543  if(lua_istable(L, -1))
16544  {
16545  //Index virtvar function
16546  int vvt_ldx = lua_gettop(L);
16547  lua_pushvalue(L, key_ldx);
16548  lua_rawget(L, vvt_ldx);
16549  if(lua_isfunction(L, -1))
16550  {
16551  //Set upvalue
16552  lua_pushvalue(L, lua_upvalueindex(ADE_SETTING_UPVALUE_INDEX));
16553  if(lua_setupvalue(L, -2, ADE_SETTING_UPVALUE_INDEX) == NULL)
16554  LuaError(L, "Unable to set upvalue for virtual variable");
16555 
16556  //Set arguments
16557  //WMC - Skip setting the key
16558  lua_pushvalue(L, obj_ldx);
16559  int numargs = 1;
16560  for(i = arg_ldx; i <= last_arg_ldx; i++)
16561  {
16562  lua_pushvalue(L, i);
16563  numargs++;
16564  }
16565 
16566  //Execute function
16567  lua_pcall(L, numargs, LUA_MULTRET, err_ldx);
16568 
16569  return (lua_gettop(L) - vvt_ldx);
16570  }
16571  else
16572  {
16573  lua_pop(L, 1); //non-function value
16574  }
16575  }
16576  lua_pop(L, 1); //virtvar table
16577 
16578  //*****STEP 5: Use the indexer
16579  //NOTE: Requires metatable from step 1.5
16580 
16581  //Get indexer
16582  lua_pushstring(L, "__indexer");
16583  lua_rawget(L, mtb_ldx);
16584  if(lua_isfunction(L, -1))
16585  {
16586  //Function already on stack
16587  //Set upvalue
16588  lua_pushvalue(L, lua_upvalueindex(ADE_SETTING_UPVALUE_INDEX));
16589  if(lua_setupvalue(L, -2, ADE_SETTING_UPVALUE_INDEX) == NULL)
16590  LuaError(L, "Unable to set upvalue for indexer");
16591 
16592  //Set arguments
16593  for(i = 1; i <= last_arg_ldx; i++)
16594  lua_pushvalue(L, i);
16595 
16596  //Execute function
16597  lua_pcall(L, last_arg_ldx, LUA_MULTRET, err_ldx);
16598 
16599  return (lua_gettop(L) - err_ldx);
16600  }
16601  lua_pop(L, 2); //WMC - Don't need __indexer or error handler
16602  }
16603 
16604  //*****STEP 6: Set a new variable or die.
16605  if(ADE_SETTING_VAR && lua_istable(L, obj_ldx))
16606  {
16607  lua_pushvalue(L, key_ldx);
16608  lua_pushvalue(L, arg_ldx);
16609  lua_rawset(L, obj_ldx);
16610 
16611  lua_pushvalue(L, key_ldx);
16612  lua_rawget(L, obj_ldx);
16613  return 1;
16614  }
16615  //*****STEP 7: Set sig thingie
16616  else if(ADE_SETTING_VAR && ade_id != UINT_MAX && mtb_ldx != INT_MAX && lua_isuserdata(L, obj_ldx))
16617  {
16618  //WMC - I assume char is one byte
16619  Assert(sizeof(char) == 1);
16620 
16621  //Get userdata sig
16622  char *ud = (char *)lua_touserdata(L, obj_ldx);
16623  ODATA_SIG_TYPE sig = *(ODATA_SIG_TYPE*)(ud + entry->Value.Object.size);
16624 
16625  //Now use it to index the table with that #
16626  lua_pushnumber(L, sig);
16627  lua_rawget(L, mtb_ldx);
16628 
16629  //Create table, if necessary
16630  if(!lua_istable(L, -1))
16631  {
16632  lua_pop(L, 1);
16633  lua_newtable(L);
16634  lua_pushnumber(L, sig);
16635  lua_pushvalue(L, -2);
16636  lua_rawset(L, mtb_ldx);
16637  }
16638 
16639  //Index the table
16640  if(lua_istable(L, -1))
16641  {
16642  int hvt_ldx = lua_gettop(L);
16643  lua_pushvalue(L, key_ldx);
16644  lua_pushvalue(L, arg_ldx);
16645  lua_rawset(L, hvt_ldx);
16646 
16647  lua_pushvalue(L, key_ldx);
16648  lua_rawget(L, hvt_ldx);
16649  return 1;
16650  }
16651  lua_pop(L, 1); //WMC - maybe-sig-table
16652  }
16653  lua_pop(L, 1); //WMC - metatable
16654 
16655  if(type_name != NULL)
16656  LuaError(L, "Could not find index '%s' in type '%s'", lua_tostring(L, key_ldx), type_name);
16657  else
16658  LuaError(L, "Could not find index '%s'", lua_tostring(L, key_ldx));
16659  return 0;
16660 }
16661 
16662 //Think of n_mtb_ldx as the parent metatable
16663 int ade_table_entry::SetTable(lua_State *L, int p_amt_ldx, int p_mtb_ldx)
16664 {
16665  uint i;
16666  int cleanup_items = 0;
16667  int mtb_ldx = INT_MAX;
16668  int data_ldx = INT_MAX;
16669  int desttable_ldx = INT_MAX;
16670  int amt_ldx = INT_MAX;
16671 
16672  if(Instanced)
16673  {
16674  //Set any actual data
16675  int nset = 0;
16676  switch (Type)
16677  {
16678  //WMC - This hack by taylor is a necessary evil.
16679  //64-bit function pointers do not get passed properly
16680  //when using va_args for some reason.
16681  case 'u':
16682  case 'v':
16683  lua_pushstring(L, "<UNNAMED FUNCTION>");
16684  lua_pushboolean(L, 0);
16685  lua_pushcclosure(L, Value.Function, 2);
16686  nset++;
16687  break;
16688 
16689  default:
16690  char typestr[2] = {Type, '\0'};
16691  nset = ade_set_args(L, typestr, Value);
16692  break;
16693  }
16694 
16695  if (nset)
16696  {
16697  data_ldx = lua_gettop(L);
16698  }
16699  else
16700  {
16701  LuaError(L, "ade_table_entry::SetTable - Could not set data for '%s' (" PTRDIFF_T_ARG ")", GetName(), ADE_INDEX(this));
16702  }
16703 
16704  if(data_ldx != INT_MAX)
16705  {
16706  //WMC - Cannot delete libs and stuff off here.
16707  if(p_amt_ldx != LUA_GLOBALSINDEX)
16708  {
16709  cleanup_items++;
16710  }
16711 
16712  //WMC - Handle virtual variables by getting their table
16713  if(Type == 'v')
16714  {
16715  //Get virtvars table
16716  lua_pushstring(L, "__virtvars");
16717  lua_rawget(L, p_mtb_ldx);
16718  if(lua_istable(L, -1))
16719  {
16720  cleanup_items++;
16721 
16722  //Virtual variables are stored in virtvar table,
16723  //rather than the parent table
16724  desttable_ldx = lua_gettop(L);
16725  }
16726  else
16727  {
16728  lua_pop(L, 1);
16729  }
16730  }
16731  else
16732  {
16733  //WMC - Member objects prefixed with __ are assumed to be metatable objects
16734  if(strnicmp("__", GetName(), 2) && lua_istable(L, p_amt_ldx))
16735  desttable_ldx = p_amt_ldx;
16736  else if(lua_istable(L, p_mtb_ldx))
16737  desttable_ldx = p_mtb_ldx;
16738  }
16739 
16740  if(desttable_ldx != INT_MAX)
16741  {
16742  //If we are setting a function...
16743  if(lua_isfunction(L, data_ldx))
16744  {
16745  //Set the FIRST upvalue to its name,
16746  //so we can always find out what it is for debugging
16747  lua_pushstring(L, GetName());
16748  if(lua_setupvalue(L, data_ldx, 1) == NULL) {
16749  LuaError(L, "ade_table_entry::SetTable - Could not set upvalue for '%s' (" PTRDIFF_T_ARG ")", GetName(), ADE_INDEX(this));
16750  }
16751  }
16752 
16753  //Register name and shortname
16754  if(Name != NULL)
16755  {
16756  lua_pushstring(L, Name);
16757  lua_pushvalue(L, data_ldx);
16758  lua_rawset(L, desttable_ldx);
16759  }
16760  if(ShortName != NULL)
16761  {
16762  lua_pushstring(L, ShortName);
16763  lua_pushvalue(L, data_ldx);
16764  lua_rawset(L, desttable_ldx);
16765  }
16766  }
16767  else
16768  {
16769  LuaError(L, "ade_table_entry::SetTable - Could not instance '%s' (" PTRDIFF_T_ARG ")", GetName(), ADE_INDEX(this));
16770  }
16771  }
16772  }
16773 
16774  //If subentries, create a metatable pointer and set it
16775  if(Num_subentries || (DerivatorIdx != UINT_MAX && Ade_table_entries[DerivatorIdx].Num_subentries))
16776  {
16777  //Create the new metatable
16778  if(!luaL_newmetatable(L, Name))
16779  {
16780  LuaError(L, "ade_table_entry::SetTable - Couldn't create metatable for table entry '%s' - does a Lua object already exist with this name?", Name);
16781  return 0;
16782  }
16783  mtb_ldx = lua_gettop(L);
16784  cleanup_items++;
16785 
16786  //Push a copy of the metatable and set it for this object
16787  //WMC - Make sure it's instanced, too. This helps keep crashes from happening...
16788  if(data_ldx != INT_MAX)
16789  {
16790  lua_pushvalue(L, mtb_ldx);
16791  lua_setmetatable(L, data_ldx);
16792  }
16793 
16794  //***Create index handler entry
16795  lua_pushstring(L, "__index");
16796  lua_pushstring(L, "ade_index_handler(get)"); //upvalue(1) = function name
16797  lua_pushboolean(L, 0); //upvalue(2) = setting true/false
16798  lua_pushcclosure(L, ade_index_handler, 2);
16799  lua_rawset(L, mtb_ldx);
16800 
16801  //***Create newindex handler entry
16802  lua_pushstring(L, "__newindex");
16803  lua_pushstring(L, "ade_index_handler(set)"); //upvalue(1) = function name
16804  lua_pushboolean(L, 1); //upvalue(2) = setting true/false
16805  lua_pushcclosure(L, ade_index_handler, 2);
16806  lua_rawset(L, mtb_ldx);
16807 
16808  //***Create virtvar storage facility
16809  lua_pushstring(L, "__virtvars");
16810  lua_newtable(L);
16811  lua_rawset(L, mtb_ldx);
16812 
16813  //***Create ade members table
16814  lua_createtable(L, 0, Num_subentries);
16815  if(lua_istable(L, -1)) {
16816  //WMC - was lua_gettop(L) - 1 for soem
16817  amt_ldx = lua_gettop(L);
16818  cleanup_items++;
16819 
16820  //Set it
16821  lua_pushstring(L, "__ademembers");
16822  lua_pushvalue(L, amt_ldx); //dup
16823  lua_rawset(L, mtb_ldx);
16824  }
16825 
16826  //***Create ID entries
16827  lua_pushstring(L, "__adeid");
16828  lua_pushnumber(L, ADE_INDEX(this));
16829  lua_rawset(L, mtb_ldx);
16830 
16831  if(DerivatorIdx != UINT_MAX)
16832  {
16833  lua_pushstring(L, "__adederivid");
16834  lua_pushnumber(L, DerivatorIdx);
16835  lua_rawset(L, mtb_ldx);
16836  }
16837  }
16838 
16839  if(amt_ldx != INT_MAX)
16840  {
16841  //Fill out ze metatable
16842  if(DerivatorIdx != UINT_MAX)
16843  {
16844  for(i = 0; i < Ade_table_entries[DerivatorIdx].Num_subentries; i++)
16845  {
16846  Ade_table_entries[Ade_table_entries[DerivatorIdx].Subentries[i]].SetTable(L, amt_ldx, mtb_ldx);
16847  }
16848  }
16849  for(i = 0; i < Num_subentries; i++)
16850  {
16851  Ade_table_entries[Subentries[i]].SetTable(L, amt_ldx, mtb_ldx);
16852  }
16853  }
16854 
16855  //Pop the metatable and data (cleanup)
16856  lua_pop(L, cleanup_items);
16857 
16858  return 1;
16859 }
16860 
16861 void ade_output_type_link(FILE *fp, char *typestr)
16862 {
16863  for(int i = 0; i < Lua_type_names_num; i++)
16864  {
16865  if(!stricmp(Lua_type_names[i], typestr))
16866  {
16867  fputs(typestr, fp);
16868  return;
16869  }
16870  }
16871 
16872  fprintf(fp, "<a href=\"#%s\">%s</a>", typestr, typestr);
16873 }
16874 
16876 {
16877  if(Name == NULL && ShortName == NULL) {
16878  Warning(LOCATION, "Data entry with no name or shortname");
16879  return;
16880  }
16881 
16882  uint i;
16883  bool skip_this = false;
16884 
16885  //WMC - Hack
16886  if(ParentIdx != UINT_MAX)
16887  {
16888  for(i = 0; i < Num_subentries; i++)
16889  {
16890  if(!stricmp(Ade_table_entries[Subentries[i]].Name, "__indexer"))
16891  {
16892  Ade_table_entries[Subentries[i]].OutputMeta(fp);
16893  skip_this = true;
16894  break;
16895  }
16896  }
16897  }
16898 
16899 
16900  //***Begin entry
16901  if(!skip_this)
16902  {
16903  fputs("<dd><dl>", fp);
16904 
16905  switch(Type)
16906  {
16907  case 'o':
16908  {
16909  //***Name (ShortName)
16910  if(ParentIdx == UINT_MAX) {
16911  fprintf(fp, "<dt id=\"%s\">", GetName());
16912  }
16913  if(Name == NULL)
16914  {
16915  if(DerivatorIdx == UINT_MAX)
16916  fprintf(fp, "<h2>%s</h2>\n", ShortName);
16917  else
16918  fprintf(fp, "<h2>%s:<a href=\"#%s\">%s</a></h2>\n", Ade_table_entries[DerivatorIdx].GetName(), Ade_table_entries[DerivatorIdx].GetName(), Ade_table_entries[DerivatorIdx].GetName());
16919  }
16920  else
16921  {
16922  fprintf(fp, "<h2>%s", Name);
16923 
16924  if(ShortName != NULL)
16925  fprintf(fp, " (%s)", ShortName);
16926  if(DerivatorIdx != UINT_MAX)
16927  fprintf(fp, ":<a href=\"#%s\">%s</a>", Ade_table_entries[DerivatorIdx].GetName(), Ade_table_entries[DerivatorIdx].GetName());
16928 
16929  fputs("</h2>\n", fp);
16930  }
16931  fputs("</dt>\n", fp);
16932 
16933  //***Description
16934  if(Description != NULL) {
16935  fprintf(fp, "<dd>%s</dd>\n", this->Description);
16936  }
16937 
16938  //***Type: ReturnType
16939  if(ReturnType != NULL) {
16940  fprintf(fp, "<dd><b>Return Type: </b> %s<br>&nbsp;</dd>\n", ReturnType);
16941  }
16942 
16943  if(ReturnDescription != NULL) {
16944  fprintf(fp, "<dd><b>Return Description: </b> %s<br>&nbsp;</dd>\n", ReturnDescription);
16945  }
16946  }
16947  break;
16948  case 'u':
16949  {
16950  //***Name(ShortName)(Arguments)
16951  fputs("<dt>", fp);
16952  int ao = -1;
16953 
16954  fputs("<i>", fp);
16955  if(ReturnType != NULL)
16957  else
16958  fputs("nil", fp);
16959  fputs(" </i>", fp);
16960  if(Name == NULL) {
16961  fprintf(fp, "<b>%s", ShortName);
16962  }
16963  else
16964  {
16965  ao = ade_get_operator(Name);
16966 
16967  //WMC - Do we have an operator?
16968  if(ao < 0)
16969  {
16970  fprintf(fp, "<b>%s", Name);
16971  if(ShortName != NULL)
16972  {
16973  int ao2 = ade_get_operator(ShortName);
16974  if(ao2 < 0)
16975  fprintf(fp, "(%s)", ShortName);
16976  else
16977  fprintf(fp, "(%s)", ade_Operators[ao2].dest);
16978  }
16979  }
16980  else
16981  {
16982  //WMC - Hack
16983  if(ParentIdx != UINT_MAX && Ade_table_entries[ParentIdx].ParentIdx != UINT_MAX && Ade_table_entries[ParentIdx].Name != NULL && !stricmp(Name, "__indexer"))
16984  {
16985  fprintf(fp, "<b>%s%s", Ade_table_entries[ParentIdx].Name, ade_Operators[ao].dest);
16986  }
16987  else
16988  fprintf(fp, "<b>%s", ade_Operators[ao].dest);
16989  }
16990  }
16991  if(ao < 0)
16992  {
16993  if(Arguments != NULL) {
16994  fprintf(fp, "(</b><i>%s</i><b>)</b>\n", Arguments);
16995  } else {
16996  fprintf(fp, "()</b>\n");
16997  }
16998  }
16999  else
17000  {
17001  fputs("</b>", fp);
17002  if(Arguments != NULL) {
17003  fprintf(fp, " <i>%s</i>\n", Arguments);
17004  }
17005  }
17006  fputs("</dt>\n", fp);
17007 
17008  //***Description
17009  if(Description != NULL) {
17010  fprintf(fp, "<dd>%s</dd>\n", Description);
17011  }
17012 
17013  //***Result: ReturnDescription
17014  if(ReturnDescription != NULL) {
17015  fprintf(fp, "<dd><b>Returns:</b> %s<br>&nbsp;</dd>\n", ReturnDescription);
17016  } else {
17017  fputs("<dd><b>Returns:</b> Nothing<br>&nbsp;</dd>\n", fp);
17018  }
17019  }
17020  break;
17021  default:
17022  Warning(LOCATION, "Unknown type '%c' passed to ade_table_entry::OutputMeta", Type);
17023  case 'b':
17024  case 'd':
17025  case 'f':
17026  case 'i':
17027  case 's':
17028  case 'x':
17029  case 'v':
17030  {
17031  //***Type Name(ShortName)
17032  fputs("<dt>\n", fp);
17033  if(ReturnType != NULL)
17034  {
17035  fputs("<i>", fp);
17037  fputs(" </i>", fp);
17038  }
17039 
17040  if(Name == NULL) {
17041  fprintf(fp, "<b>%s</b>\n", ShortName);
17042  }
17043  else
17044  {
17045  fprintf(fp, "<b>%s", Name);
17046  if(ShortName != NULL)
17047  fputs(ShortName, fp);
17048  fputs("</b>\n", fp);
17049  }
17050  if(Arguments != NULL)
17051  fprintf(fp, " = <i>%s</i>", Arguments);
17052  fputs("</dt>\n", fp);
17053 
17054  //***Description
17055  if(Description != NULL)
17056  fprintf(fp, "<dd>%s</dd>\n", Description);
17057 
17058  //***Also settable with: Arguments
17059  if(ReturnDescription != NULL)
17060  fprintf(fp, "<dd><b>Value:</b> %s</b></dd>\n", ReturnDescription);
17061  }
17062  break;
17063  }
17064  }
17065 
17066  fputs("<dd><dl>\n", fp);
17067  for(i = 0; i < Num_subentries; i++)
17068  {
17069  if(ParentIdx == UINT_MAX
17070  || stricmp(Ade_table_entries[Subentries[i]].Name, "__indexer"))
17071  Ade_table_entries[Subentries[i]].OutputMeta(fp);
17072  }
17073  fputs("</dl></dd>\n", fp);
17074 
17075  if(!skip_this)
17076  fputs("<br></dl></dd>\n", fp);
17077 }
17078 
17080 {
17081  Assert(fp != NULL);
17082  Assert(ate != NULL);
17083 
17084  //WMC - sanity checking
17085  if(ate->Name == NULL && ate->ShortName == NULL) {
17086  Warning(LOCATION, "Found ade_table_entry with no name or shortname");
17087  return;
17088  }
17089 
17090  fputs("<dd>", fp);
17091 
17092  if(ate->Name == NULL)
17093  {
17094  fprintf(fp, "<a href=\"#%s\">%s", ate->ShortName, ate->ShortName);
17095  }
17096  else
17097  {
17098  fprintf(fp, "<a href=\"#%s\">%s", ate->Name, ate->Name);
17099  if(ate->ShortName)
17100  fprintf(fp, " (%s)", ate->ShortName);
17101  }
17102  fputs("</a>", fp);
17103 
17104  if(ate->Description)
17105  fprintf(fp, " - %s\n", ate->Description);
17106 
17107  fputs("</dd>\n", fp);
17108 }
17109 
17110 void script_state::OutputLuaMeta(FILE *fp)
17111 {
17112  uint i;
17113  ade_table_entry *ate;
17114  fputs("<dl>\n", fp);
17115 
17116  //***TOC: Libraries
17117  fputs("<dt><b>Libraries</b></dt>\n", fp);
17118  for(i = 0; i < Ade_table_entries.size(); i++)
17119  {
17120  ate = &Ade_table_entries[i];
17121  if(ate->ParentIdx == UINT_MAX && ate->Type == 'o' && ate->Instanced) {
17122  ade_output_toc(fp, ate);
17123  }
17124  }
17125 
17126  //***TOC: Objects
17127  fputs("<dt><b>Types</b></dt>\n", fp);
17128  for(i = 0; i < Ade_table_entries.size(); i++)
17129  {
17130  ate = &Ade_table_entries[i];
17131  if(ate->ParentIdx == UINT_MAX && ate->Type == 'o' && !ate->Instanced) {
17132  ade_output_toc(fp, ate);
17133  }
17134  }
17135 
17136  //***TOC: Enumerations
17137  fputs("<dt><b><a href=\"#Enumerations\">Enumerations</a></b></dt>", fp);
17138 
17139  //***End TOC
17140  fputs("</dl><br/><br/>", fp);
17141 
17142  //***Everything
17143  fputs("<dl>\n", fp);
17144  for(i = 0; i < Ade_table_entries.size(); i++)
17145  {
17146  ate = &Ade_table_entries[i];
17147  if(ate->ParentIdx == UINT_MAX)
17148  ate->OutputMeta(fp);
17149  }
17150  //***Enumerations
17151  fprintf(fp, "<dt id=\"Enumerations\"><h2>Enumerations</h2></dt>");
17152  for(i = 0; i < Num_enumerations; i++)
17153  {
17154  //WMC - This is in case we ever want to add descriptions to enums.
17155  //fprintf(fp, "<dd><dl><dt><b>%s</b></dt><dd>%s</dd></dl></dd>", Enumerations[i].name, Enumerations[i].desc);
17156 
17157  //WMC - Otherwise, just use this.
17158  fprintf(fp, "<dd><b>%s</b></dd>", Enumerations[i].name);
17159  }
17160  fputs("</dl>\n", fp);
17161 
17162  //***End LUA
17163  fputs("</dl>\n", fp);
17164 }
#define LE_ORDER_EVADE
int Weapons_inited
Definition: weapons.cpp:108
void light_add_directional(const vec3d *dir, float intensity, float r, float g, float b, float spec_r, float spec_g, float spec_b, bool specular)
Definition: lighting.cpp:209
void mc_info_init(mc_info *mc)
Definition: model.h:1138
#define BMP_FLAG_RENDER_TARGET_DYNAMIC
Texture is a dynamic type (animation)
Definition: bmpman.h:67
void gr_rect(int x, int y, int w, int h, int resize_mode)
Definition: 2d.cpp:2068
int fire_countermeasure_count
Definition: physics.h:112
Definition: wmcgui.h:560
bool uses_team_colors
Definition: ship.h:1365
int attached_objnum
Definition: particle.h:89
int target_num
Definition: weapon.h:172
GLuint64EXT * result
Definition: Glext.h:10775
char fg_filename[MAX_FILENAME_LEN]
Definition: ship.h:272
int cf_is_valid(CFILE *cfile)
Definition: cfile.cpp:935
int Joy_sensitivity
Definition: joy-unix.cpp:29
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
int model_collide(mc_info *mc_info_obj)
target your target's target
PITCH_FORWARD.
#define MESSAGE_PRIORITY_NORMAL
size_t wp_index
Definition: ai.h:373
int turret_enemy_sig
Definition: ship.h:338
bool model_anim_start_type(ship_subsys *pss, int animation_type, int subtype, int direction, bool instant)
Definition: modelanim.cpp:566
int flags
Definition: lua.cpp:5006
bsp_info * submodel
Definition: model.h:764
int shader_effect_duration
Definition: ship.h:767
int flags
Definition: ship.h:150
int gr_get_fontnum(const char *filename)
Definition: font.cpp:554
cockpit_disp_info_h(ship_info *sip, size_t display_num)
Definition: lua.cpp:5127
int tertiary_bank_rearm_time
Definition: ship.h:143
int timestamp(int delta_ms)
Definition: timer.cpp:226
model_h mdl
Definition: lua.cpp:3780
camid cam_get_camera(uint idx)
Definition: camera.cpp:944
#define LE_SHIELD_RIGHT
int gr_get_current_fontnum()
Definition: font.cpp:545
wing Wings[MAX_WINGS]
Definition: ship.cpp:128
int offset[2]
Definition: ship.h:262
struct screen3d::@234::@236 xyw
#define MULTIPLAYER_CLIENT
Definition: multi.h:132
ade_lib l_Tables("Tables", NULL,"tb","Tables library")
#define LE_MESSAGE_PRIORITY_HIGH
int ship_info_lookup(const char *token)
Definition: ship.cpp:12772
ade_obj< object_h > l_ShipTextures("shiptextures","Ship textures handle")
#define CFILE_NORMAL
Definition: cfile.h:89
#define LE_PARTICLE_SMOKE
matrix_h()
Definition: lua.cpp:322
#define NET_TCP
Definition: psnet2.h:29
void sexp_modify_variable(int node)
Definition: sexp.cpp:29032
fix Missiontime
Definition: systemvars.cpp:19
bool IsValid()
Definition: lua.cpp:8364
#define vm_free(ptr)
Definition: pstypes.h:548
uint GetIdx()
Definition: lua.h:170
ubyte pre_death_explosion_happened
Definition: ship.h:547
#define AI_GOAL_UNDOCK
Definition: aigoals.h:36
int n_textures
Definition: model.h:761
camid cam_create(char *n_name, vec3d *n_pos, vec3d *n_norm, object *n_object, int n_object_host_submodel)
Definition: camera.cpp:888
float p
Definition: pstypes.h:111
TOGGLE_GLIDING.
int foreground
Definition: ship.h:260
int get_object_host_submodel()
Definition: camera.cpp:266
enum_h(int n_index)
Definition: lua.cpp:884
model_subsystem * system_info
Definition: ship.h:314
ubyte var
Definition: pstypes.h:208
char * tech_desc
Definition: weapon.h:335
#define SEXP_TRUE
Definition: sexp.h:918
#define gr_clear
Definition: 2d.h:749
weapon Weapons[MAX_WEAPONS]
Definition: weapons.cpp:78
#define LE_ORDER_UNDOCK
int primary_bank_weapons[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:103
SCP_vector< ArmorType > Armor_types
Definition: ship.cpp:170
vec3d hit_point
Definition: model.h:1123
float ets_get_max_speed(object *objp, float engine_energy)
Definition: hudets.cpp:147
#define TM_BASE_TYPE
Definition: model.h:657
int cf_get_dir_type(CFILE *cfile)
Definition: cfile.cpp:1100
size_t GetId()
Definition: lua.cpp:5321
#define LE_ORDER_REARM
vec3d turret_norm
Definition: model.h:186
#define MIN(a, b)
Definition: pstypes.h:296
float Proj_fov
Definition: 3dsetup.cpp:31
float tracer_length
Definition: particle.h:88
bool newlink
Definition: lua.cpp:6785
vec3d * pos
Definition: model.h:1113
virtual void onFrame(float frametime)
Definition: hud.cpp:637
float GetRoll()
int sig
Definition: lua.cpp:8336
int cf_delete(const char *filename, int path_type)
Delete the specified file.
Definition: cfile.cpp:483
float max_weapon_reserve
Definition: ship.h:1276
toggle the squadmate messaging menu
#define MESSAGE_SOURCE_NONE
object * objp
Definition: object.h:182
ai_info * Player_ai
Definition: ai.cpp:24
increase energy to engines
int type
Definition: lua.cpp:9770
int team
Definition: ship.h:606
ade_obj< int > l_Persona("persona","Persona handle")
#define ASF_MENUMUSIC
Definition: audiostr.h:20
char * ship_subsys_get_name(ship_subsys *ss)
Definition: ship.cpp:15001
Definition: lua.h:76
int Num_mission_events
int idx
Definition: lua.cpp:2916
int flags
Definition: player.h:104
matrix * vm_matrix_x_matrix(matrix *dest, const matrix *src0, const matrix *src1)
Definition: vecmat.cpp:1006
#define TARGET_DISPLAY_DIST
Definition: hudtarget.h:160
int eye_idx
Definition: lua.cpp:1554
TARGET_NEXT_ESCORT_SHIP.
char * get_name()
Definition: waypoint.cpp:84
char name[NAME_LENGTH]
Definition: weapon.h:322
int get_effect_from_name(char *name)
Definition: sexp.cpp:22454
void mission_log_add_entry(int type, char *pname, char *sname, int info_index)
Definition: missionlog.cpp:184
char text[TOKEN_LENGTH]
Definition: sexp.h:1044
waypoint * find_matching_waypoint(const char *name)
Definition: waypoint.cpp:179
#define MR_NORMAL
Definition: model.h:858
float awacs_intensity
Definition: ship.h:359
vec3d View_position
Definition: 3dsetup.cpp:20
int num_primary_banks
Definition: ship.h:99
object * homing_object
Definition: weapon.h:177
int objnum
Definition: ship.h:537
control_info ai_override_ci
Definition: ai.h:549
model_h(polymodel *n_model)
Definition: lua.cpp:1652
int Game_mode
Definition: systemvars.cpp:24
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
vec3d rotvel
Definition: physics.h:78
message all friendlies
char debug_stack[4][32]
Definition: lua.cpp:15808
void set_object_host(object *objp, int n_object_host_submodel=-1)
Definition: camera.cpp:105
int Mouse_sensitivity
Definition: mouse.cpp:50
uint ParentIdx
Definition: lua.h:83
VIEW_CENTER.
ship_bank_h()
Definition: lua.cpp:6493
char Recent_missions[MAX_RECENT_MISSIONS][MAX_FILENAME_LEN]
Definition: missionload.cpp:34
color * iff_get_color_by_team(int team, int seen_from_team, int is_bright)
Definition: iff_defs.cpp:644
int alt_type_index
Definition: ship.h:556
camid Main_camera
Definition: camera.cpp:25
#define LE_LUA_OVERRIDE_BUTTON_CONTROL
char Game_current_mission_filename[MAX_FILENAME_LEN]
Definition: fredstubs.cpp:26
polymodel * model_get(int model_num)
Definition: modelread.cpp:3134
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
#define MAX_BEAMS
Definition: beam.h:40
mc_info * info
Definition: lua.cpp:4430
bool IsValid()
Definition: lua.cpp:7600
ade_obj< vec3d > l_Vector("vector","Vector object")
float shield_get_strength(object *objp)
ship_weapon weapons
Definition: ship.h:658
int f_collision_count
Definition: beam.h:154
#define AIORF_FORWARD
Definition: ai.h:131
TARGET_LAST_TRANMISSION_SENDER.
mc_info_h(mc_info *val)
Definition: lua.cpp:4432
ship_info * Get()
Definition: lua.cpp:5496
#define MOUSE_LEFT_BUTTON
Definition: mouse.h:43
SCP_vector< game_snd > Snds
Definition: gamesnd.cpp:19
#define SIF_IN_TECH_DATABASE_M
Definition: ship.h:898
float fire_wait
Definition: weapon.h:359
int gamesnd_get_by_tbl_index(int index)
Definition: gamesnd.cpp:368
#define LE_SHIELD_LEFT
float vm_vec_mag(const vec3d *v)
Definition: vecmat.cpp:325
#define gr_end_view_matrix
Definition: 2d.h:896
ade_obj< cockpit_displays_h > l_CockpitDisplays("displays","Player cockpit displays array handle")
VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK.
int cfread(void *buf, int elsize, int nelem, CFILE *fp)
int turret_gun_sobj
Definition: model.h:193
float max_life
Definition: particle.h:81
char parent_type
Definition: object.h:149
#define LE_ORDER_ATTACK_WING
decrease shield recharge rate
submodel_instance_info submodel_info_1
Definition: ship.h:368
ZERO_THROTTLE.
#define AIORF_FULL
Definition: ai.h:124
int snd_load(game_snd *gs, int allow_hardware_load)
Definition: sound.cpp:281
float GetZ()
float flFrametime
Definition: fredstubs.cpp:22
int sexp_add_variable(const char *text, const char *var_name, int type, int index)
Definition: sexp.cpp:28929
ade_obj< cockpit_display_h > l_CockpitDisplay("display","Cockpit display handle")
ade_obj< object_h > l_Weapon("weapon","Weapon handle",&l_Object)
#define LE_LUA_STEERING_CONTROLS
#define SF2_NO_SUBSPACE_DRIVE
Definition: ship.h:487
uint Subentries[256]
Definition: lua.h:117
gr_set_cursor_bitmap(bm_load(s), ul)
void mission_parse_lookup_callsign_index(int index, char *out)
vec3d desired_vel
Definition: physics.h:70
Definition: weapon.h:163
GLuint index
Definition: Glext.h:5608
VIEW_DIST_DECREASE.
void credits_stop_music(bool fade)
Definition: credits.cpp:223
bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, vec3d *turret_pos, vec3d *turret_fvec, vec3d *predicted_pos=NULL, float flak_range_override=100.0f)
Definition: aiturret.cpp:1832
#define SM_ATTACK
Definition: ai.h:247
float afterburner_forward_accel_time_const
Definition: physics.h:60
int calc_waypoint_index(int waypoint_instance)
Definition: waypoint.cpp:131
asteroid Asteroids[MAX_ASTEROIDS]
Definition: asteroid.cpp:63
#define AI_GOAL_CHASE_WING
Definition: aigoals.h:37
#define SWH_PRIMARY
Definition: lua.cpp:6466
ade_lib l_Mission_Beams("Beams",&l_Mission, NULL, NULL)
#define AI_GOAL_DOCK
Definition: aigoals.h:30
ade_lib l_CFile("CFile", NULL,"cf","CFile FS2 filesystem access")
int weapon_create(vec3d *pos, matrix *orient, int weapon_type, int parent_obj, int group_id=-1, int is_locked=0, int is_spawned=0, float fof_cooldown=0.0f, ship_subsys *src_turret=NULL)
Definition: weapons.cpp:5246
#define VM_WARP_CHASE
Definition: systemvars.h:37
physics_info phys_info
Definition: object.h:157
int target_signature
Definition: ai.h:147
int sig
Definition: lua.cpp:7573
matrix * vm_angles_2_matrix(matrix *m, const angles *a)
Definition: vecmat.cpp:752
#define LE_MISSION_REPEAT
#define AI_GOAL_WAYPOINTS
Definition: aigoals.h:31
waypoint_list * wlp
Definition: lua.cpp:6315
int n_view_positions
Definition: model.h:752
#define LE_NORMAL_CONTROLS
#define MAX_SHIPS
Definition: globals.h:37
void vm_rotate_matrix_by_angles(matrix *orient, const angles *tangles)
Definition: vecmat.cpp:1338
__inline void gr_circle(int xc, int yc, int d, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:774
int Om_tracker_flag
int Dead_zone_size
Definition: joy-unix.cpp:27
int odx
Definition: lua.cpp:7572
int model_rotate_gun(int model_num, model_subsystem *turret, matrix *orient, angles *base_angles, angles *gun_angles, vec3d *pos, vec3d *dst, int obj_idx, bool reset=false)
Definition: modelread.cpp:3904
int id
Definition: model.h:732
int hud_escort_num_ships_on_list()
Definition: hudescort.cpp:1026
matrix * vm_vector_2_matrix_norm(matrix *m, const vec3d *fvec, const vec3d *uvec, const vec3d *rvec)
Definition: vecmat.cpp:891
#define LE_TEXTURE_STATIC
dockingbay_h()
Definition: lua.cpp:2221
sexpvar_h(int n_idx)
Definition: lua.cpp:2920
#define AI_GOAL_GUARD
Definition: aigoals.h:38
int fire_secondary_count
Definition: physics.h:111
char * Object_type_names[MAX_OBJECT_TYPES]
Definition: object.cpp:76
void object_set_gliding(object *objp, bool enable, bool force)
Definition: object.cpp:2036
void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, int use_angles, vec3d *targetp)
Definition: aiturret.cpp:1327
int model_num
Definition: ship.h:1189
#define LE_VM_EXTERNAL
#define LE_VM_WARP_CHASE
int r
Definition: lua.cpp:12853
int next_primary_fire_stamp[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:113
int ship_get_num_subsys(ship *shipp)
Definition: ship.cpp:17046
float max_hits
Definition: ship.h:320
#define LE_PARTICLE_BITMAP
polymodel * model
Definition: lua.cpp:1624
RIGHT_SLIDE_THRUST.
int weapon_info_lookup(const char *name=NULL)
Definition: weapons.cpp:467
int mission_load(char *filename_ext)
Definition: missionload.cpp:83
waypoint_list * find_waypoint_list_with_instance(int waypoint_instance, int *waypoint_index)
Definition: waypoint.cpp:254
ade_lib l_Base_States("GameStates",&l_Base, NULL,"Freespace 2 states")
int idx
Definition: lua.cpp:360
int model_instance_num
Definition: ship.h:802
float vm_vec_normalize_quick(vec3d *src)
Definition: vecmat.cpp:529
int next_secondary_fire_stamp[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:115
int gameseq_get_state(void)
Definition: fredstubs.cpp:60
float age
Definition: particle.h:80
void mission_parse_lookup_alt_index(int index, char *out)
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
bool IsValid()
Definition: lua.cpp:2223
#define PF_GLIDING
Definition: physics.h:32
GLenum func
Definition: Glext.h:5605
waypoint_list * wp_list
Definition: ai.h:372
Assert(pm!=NULL)
int target_objnum
Definition: ai.h:339
int cflush(CFILE *cfile)
Definition: cfile.cpp:1895
physics_info_h(object *objp)
Definition: lua.cpp:2467
#define LE_CFILE_TYPE_MEMORY_MAPPED
int fire_primary_count
Definition: physics.h:110
float det_range
Definition: weapon.h:185
int ai_submode
Definition: ai.h:137
wingman message: attack current target
Definition: pstypes.h:88
int Species_initted
Definition: lua.cpp:3259
submodel_instance_info submodel_info_2
Definition: ship.h:369
#define gr_set_clear_color
Definition: 2d.h:850
#define mprintf(args)
Definition: pstypes.h:238
#define FRONT_QUAD
Definition: objectshield.h:16
int ai_index
Definition: ship.h:538
IGNORE_MESSAGE.
ship_weapon weapons
Definition: ship.h:362
#define AIORF_FULL_LAT
Definition: ai.h:128
void gr_init_alphacolor(color *clr, int r, int g, int b, int alpha, int type)
Definition: 2d.cpp:1173
void set_position(vec3d *in_position=NULL, float in_translation_time=0.0f, float in_translation_acceleration_time=0.0f, float in_translation_deceleration_time=0.0f, float in_end_velocity=0.0f)
Definition: camera.cpp:162
GLint GLint GLsizei GLsizei GLsizei depth
Definition: Glext.h:5180
#define SEXP_VARIABLE_SET
Definition: sexp.h:903
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
vec3d norm
Definition: model.h:597
int ship_fire_primary(object *obj, int stream_weapons, int force)
Definition: ship.cpp:10760
GLuint GLuint * names
Definition: Glext.h:11016
int HUD_draw
Definition: hud.cpp:78
#define DIR_SEPARATOR_CHAR
Definition: pstypes.h:43
int Num_gs_state_text
int weapon_recharge_index
Definition: ship.h:638
#define OBJ_ASTEROID
Definition: object.h:44
#define MOUSE_MIDDLE_BUTTON
Definition: mouse.h:45
texture_map_h(polymodel *n_model, texture_map *n_tmap=NULL)
Definition: lua.cpp:3802
target the closest ship attacking current target
YAW_RIGHT.
int target_objnum
Definition: asteroid.h:110
bool isValid()
Definition: lua.cpp:11748
#define AI_GOAL_STAY_NEAR_SHIP
Definition: aigoals.h:47
int getSignature()
Definition: lua.cpp:8348
#define LE_PARTICLE_FIRE
float target_time
Definition: ai.h:350
float turret_max_fov
Definition: model.h:189
#define LE_MESSAGE_PRIORITY_LOW
#define VM_EXTERNAL
Definition: systemvars.h:31
REARM_MESSAGE.
Definition: 2d.h:95
uint sig
Definition: lua.cpp:11729
matrix Eye_matrix
Definition: 3dsetup.cpp:26
float * val
Definition: lua.cpp:374
#define SSF_UNTARGETABLE
Definition: ship.h:280
int run_sexp(const char *sexpression)
Definition: sexp.cpp:25528
#define AI_GOAL_CHASE_ANY
Definition: aigoals.h:41
SCP_vector< ade_table_entry > Ade_table_entries
Definition: lua.cpp:61
toggle auto-match target speed
int bm_get_info(int handle, int *w, int *h, ubyte *flags, int *nframes, int *fps)
Gets info on the bitmap indexed by handle.
Definition: bmpman.cpp:769
void set_flags(uint flags)
void get(float Time, float *Position, float *Velocity)
Definition: physics.cpp:1172
#define MR_NO_LIGHTING
Definition: model.h:867
#define MC_CHECK_RAY
Definition: model.h:1176
__inline void gr_gradient(int x1, int y1, int x2, int y2, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:808
cockpit_displays_h(object *objp)
Definition: lua.cpp:8080
int secondary_bank_start_ammo[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:135
#define VM_TRACK
Definition: systemvars.h:32
int g3_draw_polygon(const vec3d *pos, const matrix *ori, float width, float height, int tmap_flags=TMAP_FLAG_TEXTURED)
Definition: 3ddraw.cpp:310
struct vec3d::@225::@227 xyz
#define LE_ORDER_FLY_TO
ade_obj< int > l_Texture("texture","Texture handle")
vec3d * v3
Definition: lua.cpp:2501
int center_h
Definition: 2d.h:363
float afterburner_fuel
Definition: ship.h:648
#define ODATA_PTR_SIZE
Definition: lua.h:30
#define ADE_INDEX(ate)
Definition: lua.h:72
int ai_goal_num(ai_goal *goals)
Definition: aigoals.cpp:691
#define TMAP_HTL_3D_UNLIT
Definition: tmapper.h:63
bool cam_set_camera(camid cid)
Definition: camera.cpp:980
void model_render_immediate(model_render_params *render_info, int model_num, matrix *orient, vec3d *pos, int render, bool sort)
#define LE_NORMAL_BUTTON_CONTROLS
#define ADE_RETURN_TRUE
Definition: lua.cpp:246
ade_obj< matrix_h > l_Matrix("orientation","Orientation matrix object")
YAW_LEFT.
GLboolean GLuint group
Definition: Glext.h:10591
vec3d max_vel
Definition: physics.h:49
GLclampf f
Definition: Glext.h:7097
BANK_RIGHT.
float y
Definition: pstypes.h:107
#define MAX_OBJECTS
Definition: globals.h:83
#define ADE_FUNCNAME_UPVALUE_INDEX
Definition: lua.cpp:240
ship_subsys * subsys
Definition: beam.h:125
VIEW_TOPDOWN.
int model_find_2d_bound_min(int model_num, matrix *orient, vec3d *pos, int *x1, int *y1, int *x2, int *y2)
Definition: modelread.cpp:3168
int model_num
Definition: debris.h:34
int * Player_cockpit_textures
Definition: ship.cpp:125
int gamesnd_get_by_name(const char *name)
Definition: gamesnd.cpp:301
#define AI_GOAL_WARP
Definition: aigoals.h:33
int Mouse_hidden
Definition: mouse.cpp:52
bitmap_entry bm_bitmaps[MAX_BITMAPS]
Definition: bmpman.cpp:85
int num_tertiary_banks
Definition: ship.h:101
int snd_is_playing(int sig)
Definition: sound.cpp:1047
void calculatePosition(vertex *target_point, vec3d *tpos, vec2d *outcoords, int *dir, float *half_triangle_sep)
Definition: hudtarget.cpp:6295
object * target
Definition: beam.h:120
ship_bank_h(object *objp_in, ship_weapon *wpn, int in_type, int in_bank)
Definition: lua.cpp:6496
#define SF2_AFFECTED_BY_GRAVITY
Definition: ship.h:489
#define AI_GOAL_IGNORE
Definition: aigoals.h:42
Definition: cfile.h:28
ai_info Ai_info[MAX_AI_INFO]
Definition: ai.cpp:23
int center_offset_y
Definition: 2d.h:364
#define LE_VM_PADLOCK_UP
float afterburner_fuel_capacity
Definition: ship.h:1283
vec3d * vm_vec_rotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:933
#define LGC_B_ADDITIVE
Definition: player.h:71
thruster_bank * bank
Definition: lua.cpp:1697
int message_persona_name_lookup(char *name)
#define CF_SEEK_SET
Definition: cfile.h:24
int tertiary_bank_ammo
Definition: ship.h:140
float factor
Definition: lua.cpp:440
object obj_used_list
Definition: object.cpp:53
#define gr_set_line_width
Definition: 2d.h:938
#define f2fl(fx)
Definition: floating.h:37
ship_weapon * sw
Definition: lua.cpp:6473
#define LE_LUA_FULL_CONTROLS
bool is_constant
Definition: lua.cpp:881
enum_h * u
Definition: lua.cpp:12649
PADLOCK_UP.
model_h(int n_modelnum)
Definition: lua.cpp:1645
#define AI_GOAL_DISARM_SHIP
Definition: aigoals.h:40
model_subsystem * subsystems
Definition: ship.h:1271
float nr
Definition: lua.cpp:1945
fix t2
Definition: animplay.cpp:37
float side_thrust
Definition: physics.h:73
int current_primary_bank
Definition: ship.h:106
void set_detail_level_lock(int detail_level_lock)
int target_signature
Definition: ai.h:340
particle_h(particle *part_p)
Definition: lua.cpp:11736
ship_subsys * targeted_subsys
Definition: ai.h:472
#define LE_ORDER_DISABLE
ade_lib l_Mission_Messages("Messages",&l_Mission, NULL, NULL)
int n_quadrants
Definition: object.h:158
int turret_reset_delay
Definition: model.h:227
Definition: lua.cpp:67
sexp_variable Sexp_variables[MAX_SEXP_VARIABLES]
Definition: sexp.cpp:846
int center_w
Definition: 2d.h:363
ade_obj< thrusterbank_h > l_Thrusterbank("thrusterbank","A model thrusterbank")
bool IsValid()
Definition: lua.cpp:1476
#define LE_VM_PADLOCK_RIGHT
float max_speed
Definition: weapon.h:354
VIEW_OTHER_SHIP.
ship_subsys * homing_subsys
Definition: weapon.h:178
GLenum GLuint GLenum GLsizei const GLchar * message
Definition: Glext.h:5156
glow_point * Get()
Definition: lua.cpp:1739
void ship_reset_disabled_physics(object *objp, int ship_class)
Definition: ship.cpp:8974
int mouse_get_pos(int *xpos, int *ypos)
Definition: mouse.cpp:512
Definition: ai.h:329
#define CF_SEEK_CUR
Definition: cfile.h:25
ade_lib l_Mission_EscortShips("EscortShips",&l_Mission, NULL, NULL)
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
float weapon_energy
Definition: ship.h:640
uint flags
Definition: ship.h:644
int ship_fire_secondary(object *obj, int allow_swarm)
Definition: ship.cpp:11799
angles * GetAngles()
Definition: lua.cpp:326
int turret_next_fire_stamp
Definition: ship.h:336
ubyte blue
Definition: 2d.h:102
bool validate_ship_ets_indxes(const int &ship_idx, int(&ets_indexes)[num_retail_ets_gauges])
Definition: hudets.cpp:722
void ai_clear_ship_goals(ai_info *aip)
Definition: aigoals.cpp:251
ade_lib l_Testing("Testing", NULL,"ts","Experimental or testing stuff")
#define SSF_HAS_FIRED
Definition: ship.h:284
int g
Definition: lua.cpp:12854
matrix * B
Definition: lua.cpp:445
float weapon_range
Definition: weapon.h:390
hull_check orient
Definition: lua.cpp:5049
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
#define VM_EXTERNAL_CAMERA_LOCKED
Definition: systemvars.h:36
toggle network info
vec3d pos
Definition: particle.h:78
void set_fov(float in_fov, float in_fov_time=0.0f, float in_fov_acceleration_time=0.0f, float in_deceleration_time=0.0f)
Definition: camera.cpp:87
#define LE_ORDER_ATTACK
int Num_debris_pieces
Definition: debris.cpp:43
#define LGC_STEERING
Definition: player.h:66
target next
ade_obj< ship_subsys_h > l_Subsystem("subsystem","Ship subsystem handle")
object * objp
Definition: lua.cpp:3105
target closest ship that is attacking player
int primary_bank_capacity[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:123
int tertiary_bank_start_ammo
Definition: ship.h:141
float lifeleft
Definition: weapon.h:169
float hit_dist
Definition: model.h:1122
#define PARTICLE_BITMAP
Definition: particle.h:49
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
int current_secondary_bank
Definition: ship.h:107
#define TM_SPECULAR_TYPE
Definition: model.h:659
GLfloat GLfloat GLfloat v2
Definition: Glext.h:5640
int subtype
Definition: weapon.h:326
int get_index_sexp_variable_name(const char *text)
Definition: sexp.cpp:29324
float GetX()
ade_obj< camid > l_Camera("camera","Camera handle")
int a
Definition: lua.cpp:12856
vec3d max_rotvel
Definition: physics.h:52
int size[2]
Definition: ship.h:263
#define ADE_SETTING_UPVALUE_INDEX
Definition: lua.cpp:241
int tertiary_bank_capacity
Definition: ship.h:142
texture_map * tmap
Definition: lua.cpp:3782
char * GS_event_text[]
mc_info * Get()
Definition: lua.cpp:4436
ade_obj< int > l_Team("team","Team handle")
camid game_render_frame_setup()
Definition: fredstubs.cpp:235
color current_clear_color
Definition: 2d.h:398
void snd_update_3d_pos(int soundnum, game_snd *gs, vec3d *new_pos, float radius, float range_factor)
Definition: sound.cpp:693
ade_odata Object
Definition: lua.h:103
ade_lib l_Tables_WeaponClasses("WeaponClasses",&l_Tables, NULL, NULL)
#define AI_GOAL_NONE
Definition: ai.h:194
GLuint in
Definition: Glext.h:9087
ship * shipp
Definition: lua.cpp:9162
int n_thrusters
Definition: model.h:771
vec3d pos
Definition: object.h:152
#define VM_TOPDOWN
Definition: systemvars.h:43
void hud_target_clear_display_list()
Definition: hudtarget.cpp:6221
float emp_intensity
Definition: ship.h:717
float subsystem_factor
Definition: weapon.h:378
b
Definition: lua.cpp:6789
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
#define GR_RESIZE_NONE
Definition: 2d.h:681
bool isValid()
Definition: lua.cpp:5331
vec3d * p0
Definition: model.h:1114
int bm_release(int handle, int clear_render_targets)
Frees both a bitmap's data and it's associated slot.
Definition: bmpman.cpp:2603
ade_obj< sexpvar_h > l_SEXPVariable("sexpvariable","SEXP Variable handle")
void hud_target_add_display_list(object *objp, vertex *target_point, vec3d *target_pos, int correction, color *bracket_clr, char *name, int flags)
Definition: hudtarget.cpp:6195
float awacs_radius
Definition: ship.h:360
void ship_get_global_turret_info(object *objp, model_subsystem *tp, vec3d *gpos, vec3d *gvec)
Definition: aiturret.cpp:1303
SCP_vector< message_extra > Message_waves
void get_post_process_effect_names(SCP_vector< SCP_string > &names)
int mouse_inited
Definition: mouse.cpp:30
SHOW_NAVMAP.
SCP_list< waypoint_list > Waypoint_lists
Definition: waypoint.cpp:9
ade_obj< int > l_Control_Info("control info","control info handle")
physics_info_h()
Definition: lua.cpp:2462
int calc_waypoint_instance(int waypoint_list_index, int waypoint_index)
Definition: waypoint.cpp:111
ade_obj< int > l_Font("font","font handle")
#define BMP_FLAG_RENDER_TARGET_STATIC
Texture is a static type.
Definition: bmpman.h:66
int asteroid_subtype
Definition: asteroid.h:103
int Num_recent_missions
Definition: missionload.cpp:35
script_state Script_system("FS2_Open Scripting")
#define gr_end_proj_matrix
Definition: 2d.h:894
#define TM_NUM_TYPES
Definition: model.h:663
int newinterval
Definition: lua.cpp:1010
void cam_reset_camera()
Definition: camera.cpp:1002
char * name
int signature
Definition: object.h:145
#define LE_VM_TOPDOWN
int subobj_num
Definition: model.h:175
VIEW_EXTERNAL.
char * src
Definition: lua.cpp:169
SCP_list< CJumpNode > Jump_nodes
Definition: jumpnode.cpp:16
void get_info(vec3d *position, matrix *orientation)
Definition: camera.cpp:295
int model_num
Definition: model.h:1110
#define WP_BEAM
Definition: weapon.h:29
GLenum type
Definition: Gl.h:1492
dock_bay * docking_bays
Definition: model.h:774
#define ADE_SETTING_VAR
Definition: lua.cpp:242
char filename[MAX_FILENAME_LEN]
Definition: sound.h:76
model_h()
Definition: lua.cpp:1659
ade_lib l_Mission_Debris("Debris",&l_Mission, NULL,"debris in the mission")
int hud_escort_return_objnum(int index)
Definition: hudescort.cpp:1032
float mass
Definition: model.h:787
int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *keyframe, int can_drop_frames, int dir_type)
Loads a bitmap sequance so we can draw with it.
Definition: bmpman.cpp:1420
#define CLAMP(x, min, max)
Definition: pstypes.h:488
ade_obj< object_h > l_Object
waypoint * find_waypoint_with_objnum(int objnum)
Definition: waypoint.cpp:234
float forward_decel_time_const
Definition: physics.h:62
GLint GLsizei width
Definition: Gl.h:1505
#define AIORF_HEADING
Definition: ai.h:127
target previous
Definition: hud.h:201
char * objective_text
Definition: missiongoals.h:112
match target speed
iff_info Iff_info[MAX_IFFS]
Definition: iff_defs.cpp:20
void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags)
Definition: aicode.cpp:3215
ubyte green
Definition: 2d.h:101
transfer shield energy to right
bool IsValid()
Definition: lua.cpp:3832
int weapon_info_index
Definition: weapon.h:164
void sexp_variable_delete(int index)
Definition: sexp.cpp:29545
float lifetime
Definition: weapon.h:382
void gr_set_color(int r, int g, int b)
Definition: 2d.cpp:1188
int weapon_info_index
Definition: beam.h:117
bool isValid()
Definition: camera.cpp:851
int asteroid_type
Definition: asteroid.h:102
DOWN_SLIDE_THRUST.
SCP_vector< waypoint > & get_waypoints()
Definition: waypoint.cpp:89
cockpit_displays_info_h(int ship_info_idx)
Definition: lua.cpp:5491
int submodel_num
Definition: debris.h:35
stop targeting subsystems on ship
matrix turret_matrix
Definition: model.h:187
SCP_vector< cockpit_display > Player_displays
Definition: ship.cpp:126
#define LGC_NORMAL
Definition: player.h:65
int ship_get_num_ships()
Definition: ship.cpp:522
int bm_is_valid(int handle)
Checks if the bitmap indexed by handle is valid.
Definition: bmpman.cpp:1006
thrusters_h(polymodel *pm)
Definition: lua.cpp:1688
__inline void gr_set_clip(int x, int y, int w, int h, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:741
ade_obj< int > l_Shipclass("shipclass","Ship class handle")
char * Arguments
Definition: lua.h:108
int mouse_down(int btn)
Definition: mouse.cpp:315
vec3d pnt
Definition: model.h:596
#define LGC_FULL
Definition: player.h:67
player Players[MAX_PLAYERS]
message all hostiles
i
Definition: lua.cpp:1012
#define VM_PADLOCK_REAR
Definition: systemvars.h:39
ade_obj< thrusters_h > l_Thrusters("thrusters","The thrusters of a model")
ade_lib l_HookVar_Globals("Globals",&l_HookVar)
int strextcmp(const char *s1, const char *s2)
Definition: parselo.cpp:4013
char * ReturnType
Definition: lua.h:110
#define gr_set_view_matrix
Definition: 2d.h:895
#define SIF2_NO_LIGHTING
Definition: ship.h:932
SCP_vector< MMessage > Messages
void snd_rewind(int snd_handle, game_snd *gs, float seconds)
Definition: sound.cpp:1120
vec3d homing_pos
Definition: weapon.h:179
#define VM_FREECAMERA
Definition: systemvars.h:44
ade_obj< object_h > l_Debris("debris","Debris handle",&l_Object)
int is_hull
Definition: debris.h:37
char * GS_state_text[]
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define OBJ_WAYPOINT
Definition: object.h:36
EModelAnimationPosition secondary_animation_position[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:152
#define AIS_DOCK_0
Definition: ai.h:269
#define gr_reset_clip
Definition: 2d.h:745
bool IsValid()
Definition: lua.cpp:2476
matrix * vm_transpose(matrix *m)
Definition: vecmat.cpp:971
Definition: beam.h:114
#define LE_TEXTURE_DYNAMIC
#define MAX_TEXT_LINES
Definition: lua.cpp:13874
void set_object_target(object *objp, int n_object_target_submodel=-1)
Definition: camera.cpp:135
int instance
Definition: object.h:150
int optional_data
Definition: particle.h:67
bool isValid()
Definition: lua.cpp:8085
SCP_vector< HudGauge * > default_hud_gauges
Definition: hud.cpp:57
polymodel * Get()
Definition: lua.cpp:1627
matrix * vm_vector_2_matrix(matrix *m, const vec3d *fvec, const vec3d *uvec, const vec3d *rvec)
Definition: vecmat.cpp:850
int ok_to_target_timestamp
Definition: ai.h:521
#define PF_OVERFLOW
Definition: 3d.h:22
GLintptr offset
Definition: Glext.h:5497
float delta_bank_const
Definition: physics.h:47
Definition: debris.h:23
#define VM_PADLOCK_RIGHT
Definition: systemvars.h:41
void set_name(const char *name)
Definition: waypoint.cpp:94
void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_objnum, int target_is_locked=0, ship_subsys *target_subsys=NULL)
Definition: weapons.cpp:5093
void vm_vec_add2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:178
float a1d[3]
Definition: pstypes.h:93
#define GR_ALPHABLEND_FILTER
Definition: 2d.h:349
#define VM_DEAD_VIEW
Definition: systemvars.h:33
const float PI2
Definition: pstypes.h:305
char pof_file[MAX_FILENAME_LEN]
Definition: ship.h:1183
matrix_h(matrix *in)
Definition: lua.cpp:323
int shader_effect_start_time
Definition: ship.h:768
int l_cf_get_path_id(char *n_path)
Definition: lua.cpp:12452
vec3d last_pos
Definition: object.h:155
#define LE_VM_PADLOCK_REAR
mc_info collisionInfo
Definition: weapon.h:231
#define gr_set_proj_matrix
Definition: 2d.h:893
float View_zoom
Definition: 3dsetup.cpp:30
#define LE_ALPHABLEND_NONE
char * desc
Definition: weapon.h:325
int weapon_flags
Definition: weapon.h:176
#define MH_FINE
Definition: lua.cpp:296
#define PARTICLE_FIRE
Definition: particle.h:51
sound_entry_h(int n_idx)
Definition: lua.cpp:8206
int Get()
Definition: lua.cpp:1478
ship_subsys * ship_get_indexed_subsys(ship *sp, int index, vec3d *attacker_pos)
Definition: ship.cpp:13340
ade_obj< int > l_Event("event","Mission event handle")
GLdouble GLdouble GLdouble r
Definition: Glext.h:5337
#define LE_MOUSE_RIGHT_BUTTON
ade_get_args(L,"|i",&depth)
float pitch
Definition: physics.h:100
int flags
Definition: ship.h:322
char name[NAME_LENGTH]
Definition: lua.cpp:6316
ship_subsys * turret_subsys
Definition: weapon.h:183
REVERSE_THRUST.
ade_virtvar(char *name, lua_CFunction func, ade_lib_handle &parent, char *args=NULL, char *desc=NULL, char *ret_type=NULL, char *ret_desc=NULL)
Definition: lua.cpp:130
int flags
Definition: model.h:1116
vec3d desired_rotvel
Definition: physics.h:71
int ds_get_channel(int sig)
Definition: ds.cpp:1870
mission_event * mep
Definition: lua.cpp:1017
struct matrix::@228::@230 vec
int qdx
Definition: lua.cpp:3106
#define HUD_OBJECT_CUSTOM
Definition: hudparse.h:67
char * desc
Definition: ship.h:1173
int newheight
Definition: lua.cpp:1393
glowpoint_h(glow_point *np)
Definition: lua.cpp:1734
unsigned int uint
Definition: pstypes.h:64
int Get()
Definition: lua.cpp:1430
int Ade_get_args_skip
Definition: lua.cpp:16097
union ade_table_entry::@260 Value
int Num_weapons
Definition: weapons.cpp:107
float mass
Definition: weapon.h:358
order_h(object *objp, int n_odx)
Definition: lua.cpp:7583
bsp_info * sm
Definition: lua.cpp:7079
ade_obj< gamestate_h > l_GameState("gamestate","Game state")
screen3d screen
Definition: pstypes.h:173
#define LOG_SHIP_DISABLED
Definition: missionlog.h:29
int subtype
Definition: lua.cpp:9763
float ship_max_hull_strength
Definition: ship.h:597
GLboolean GLboolean g
Definition: Glext.h:5781
message targeted ship (if player)
#define LE_VM_WARPIN_ANCHOR
#define cfopen(...)
Definition: cfile.h:134
#define AIORF_ROLL
Definition: ai.h:125
void vm_vec_scale(vec3d *dest, float s)
Definition: vecmat.cpp:248
uint flags
Definition: model.h:169
int timestamp_until(int stamp)
Definition: timer.cpp:242
char * manufacturer_str
Definition: ship.h:1172
const int num_retail_ets_gauges
Definition: hudets.h:40
const char * getCustomGaugeText()
Definition: hud.cpp:394
GLuint coords
Definition: Glext.h:6925
void ship_end_render_cockpit_display(int cockpit_display_num)
Definition: ship.cpp:7539
#define CF_SEEK_END
Definition: cfile.h:26
__inline void gr_arc(int xc, int yc, float r, float angle_start, float angle_end, bool fill, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:784
#define GM_MULTIPLAYER
Definition: systemvars.h:18
int Num_gs_event_text
int g3_draw_sphere(vertex *pnt, float rad)
Definition: 3ddraw.cpp:475
int snd_get_pitch(int sig)
Definition: sound.cpp:992
ade_obj< cockpit_displays_info_h > l_CockpitDisplayInfos("cockpitdisplays","Array of cockpit display information")
float cargo_size
Definition: weapon.h:388
GLenum GLenum dst
Definition: Glext.h:5917
int gameseq_get_state_idx(char *s)
char * newname
Definition: lua.cpp:1376
wingman message: cover me
int team
Definition: weapon.h:167
void ai_attack_wing(object *attacker, int wingnum)
Definition: aicode.cpp:2326
#define MSS_FLAG_TURRET_RESET_IDLE
Definition: model.h:123
float rotdamp
Definition: physics.h:43
int newVal
Definition: lua.cpp:7233
int primary_bank_ammo[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:121
float clip_aspect
Definition: 2d.h:372
char * cfgets(char *buf, int n, CFILE *cfile)
Definition: cfile.cpp:1571
#define SW_FLAG_TURRET_LOCK
Definition: ship.h:95
#define PARTICLE_SMOKE
Definition: particle.h:52
int * ship_replacement_textures
Definition: ship.h:751
#define gr_flash
Definition: 2d.h:813
char name[NAME_LENGTH]
Definition: ship.h:1517
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES]
Definition: cfile.cpp:49
GLboolean GLboolean GLboolean GLboolean a
Definition: Glext.h:5781
int secondary_bank_capacity[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:136
gameevent_h(int n_event)
Definition: lua.cpp:1426
int lua_game_control
int objnum
Definition: weapon.h:165
texture_map_h()
Definition: lua.cpp:3785
float turret_y_fov
Definition: model.h:190
int cf_exists_full(const char *filename, int dir_type)
Definition: cfile.cpp:527
dockingbays_h()
Definition: lua.cpp:1761
vec3d * p1
Definition: model.h:1115
toggle between high and low HUD contrast
__inline void gr_unfilled_circle(int xc, int yc, int d, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:779
int armor_type_get_idx(char *name)
Definition: ship.cpp:18332
int get_max_ammo_count_for_bank(int ship_class, int bank, int ammo_type)
Definition: ship.cpp:16279
ade_lib l_Mission_BuiltinMessages("BuiltinMessages",&l_Mission, NULL, NULL)
char * s
Definition: lua.cpp:353
void g3_set_view_matrix(const vec3d *view_pos, const matrix *view_matrix, float zoom)
Definition: 3dsetup.cpp:152
control_info lua_ci
Definition: player.h:210
float get_hull_pct(object *objp)
Definition: object.cpp:271
increase shield recharge rate
void model_clear_instance(int model_num)
Definition: modelread.cpp:4624
char name[MAX_FILENAME_LEN]
Definition: ship.h:270
#define LE_SHIELD_FRONT
char * filename
float slide_decel_time_const
Definition: physics.h:64
#define strnicmp(s1, s2, n)
Definition: config.h:272
int wingnum
Definition: ship.h:623
ade_obj< int > l_Shiptype("shiptype","Ship type handle")
int id
index into Sounds[], where sound data is stored
Definition: sound.h:82
#define LE_ORDER_GUARD
bool IsValid()
Definition: lua.cpp:1641
float speed
Definition: physics.h:79
ade_lib l_Base_Events("GameEvents",&l_Base, NULL,"Freespace 2 game events")
int hud_target_lod
Definition: weapon.h:332
float free_flight_time
Definition: weapon.h:357
int num_secondary_banks
Definition: ship.h:100
ai_goal goals[MAX_AI_GOALS]
Definition: ai.h:412
#define LE_VM_INTERNAL
#define OBJ_WEAPON
Definition: object.h:33
int snd_play_3d(game_snd *gs, vec3d *source_pos, vec3d *listen_pos, float radius, vec3d *source_vel, int looping, float vol_scale, int priority, vec3d *sound_fvec, float range_factor, int force, bool is_ambient)
Definition: sound.cpp:594
int num_points
Definition: model.h:446
mission_event Mission_events[MAX_MISSION_EVENTS]
texture_map maps[MAX_MODEL_TEXTURES]
Definition: model.h:762
#define LE_SEXPVAR_TYPE_NUMBER
Persona * Personas
void deleteInfo()
Definition: lua.cpp:4441
bool isValid()
Definition: lua.cpp:1747
fix time
Definition: ai.h:140
vec3d vel
Definition: particle.h:63
ade_lib l_Base("Base", NULL,"ba","Base FreeSpace 2 functions")
#define MULTIPLAYER_HOST
Definition: multi.h:131
mc_info hull_check
Definition: lua.cpp:5043
#define WP_LASER
Definition: weapon.h:27
int FindTexture(int bm_handle)
int target_sig
Definition: beam.h:124
float hull_strength
Definition: object.h:160
float Max_draw_distance
Definition: 2d.cpp:85
matrix_h * oriB
Definition: lua.cpp:439
eye_h()
Definition: lua.cpp:1556
ade_obj< int > l_Soundfile("soundfile","Handle to a sound file")
int primary_animation_done_time[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:153
ade_obj< object_h > l_Beam("beam","Beam handle",&l_Object)
Definition: beam.h:43
#define OBJ_DEBRIS
Definition: object.h:37
bool IsValid()
Definition: lua.cpp:886
void game_shudder_apply(int, float)
Definition: fredstubs.cpp:207
void vm_vec_sub2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:187
ade_obj< sound_h > l_Sound3D("3Dsound","3D sound instance handle",&l_Sound)
int parent
Definition: object.h:147
void ship_subsys_set_name(ship_subsys *ss, char *n_name)
Definition: ship.cpp:15017
#define w(p)
Definition: modelsinc.h:68
ade_obj< physics_info_h > l_Physics("physics","Physics handle")
ade_obj< object_h > l_Waypoint("waypoint","waypoint handle",&l_Object)
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
#define LE_SEXPVAR_CAMPAIGN_PERSISTENT
int ai_mode
Definition: ai.h:136
#define ADE_VIRTVAR(name, parent, args, desc, ret_type, ret_desc)
Definition: lua.cpp:227
void set_team_color(team_color &clr)
#define AIORF_SIDEWAYS
Definition: ai.h:130
int n_docks
Definition: model.h:770
#define MC_SUBMODEL
Definition: model.h:1178
ship_subsys * ss
Definition: lua.cpp:6880
float forward
Definition: physics.h:105
SCP_string default_team_name
Definition: ship.h:1366
VIEW_DIST_INCREASE.
int Gr_inited
Definition: 2d.cpp:63
const char * bm_get_filename(int handle)
Gets the filename of the bitmap indexed by handle, which must exist.
Definition: bmpman.cpp:727
#define MAX_AI_GOALS
Definition: ai.h:91
decrease energy to engines
int is_exit_collision
Definition: beam.h:102
int next_tertiary_fire_stamp
Definition: ship.h:117
int tips
Definition: player.h:198
#define LE_UNLOCK
#define SF_HIDDEN_FROM_SENSORS
Definition: ship.h:464
int n_subsystems
Definition: ship.h:1270
ubyte red
Definition: 2d.h:100
sound_h(int n_gs_idx, int n_sig)
Definition: lua.cpp:8343
#define SUBSYSTEM_TURRET
Definition: model.h:54
equalize recharge rates
int object_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, float dist)
Definition: aiturret.cpp:101
int iff_lookup(char *iff_name)
Definition: iff_defs.cpp:540
mc_info * collide
Definition: lua.cpp:4532
#define vm_strdup(ptr)
Definition: pstypes.h:549
#define LE_VM_OTHER_SHIP
int target_instance
Definition: ai.h:146
int priority
Definition: ai.h:141
v3 xyz y
Definition: lua.cpp:3633
ubyte g3_rotate_vertex(vertex *dest, const vec3d *src)
Definition: 3dmath.cpp:97
#define NUM_HUD_GAUGES
Definition: hudgauges.h:16
Definition: lua.h:38
EModelAnimationPosition primary_animation_position[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:151
#define LE_PARTICLE_DEBUG
wingman message: disarm current target
vec3d norm[MAX_DOCK_SLOTS]
Definition: model.h:531
ade_obj< ship_bank_h > l_WeaponBank("weaponbank","Ship/subystem weapons bank handle")
int ship_info_index
Definition: debris.h:29
vec3d * v3b
Definition: lua.cpp:4997
int snd_play(game_snd *gs, float pan, float vol_scale, int priority, bool is_voice_msg)
Definition: sound.cpp:517
ade_lib l_Mission_SEXPVariables("SEXPVariables",&l_Mission, NULL,"SEXP Variables")
TARGET_PREV_LIVE_TURRET.
#define AI_GOAL_STAY_STILL
Definition: aigoals.h:52
char * type_str
Definition: ship.h:1169
button_info lua_bi_full
Definition: player.h:212
int engine_recharge_index
Definition: ship.h:639
#define SF_PRIMARY_LINKED
Definition: ship.h:458
float newval
Definition: lua.cpp:354
AFTERBURNER.
int Num_wings
Definition: ship.cpp:120
#define PF_FORCE_GLIDE
Definition: physics.h:33
fix game_get_overall_frametime()
Definition: fredstubs.cpp:230
virtual void preprocess()
Definition: hud.cpp:632
int secondary_bank_weapons[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:104
bool collisionOccured
Definition: weapon.h:230
int Num_teams
TARGET_PREV_SUBOBJECT.
HudGauge * hud_get_gauge(const char *name)
Definition: hud.cpp:3721
gamestate_h()
Definition: lua.cpp:1473
char * target_name
Definition: ai.h:143
#define gr_curve
Definition: 2d.h:789
int Use_mouse_to_fly
Definition: mouse.cpp:51
bool newfire
Definition: lua.cpp:6817
int ade_friendly_error(lua_State *L)
Definition: lua.cpp:16392
void button_info_clear(button_info *bi)
GLdouble s
Definition: Glext.h:5321
int get_max_ammo_count_for_primary_bank(int ship_class, int bank, int ammo_type)
Definition: ship.cpp:16262
int model_anim_get_time_type(ship_subsys *pss, int animation_type, int subtype)
Definition: modelanim.cpp:740
int cf_rename(const char *old_name, const char *name, int dir_type)
Definition: cfile.cpp:567
texture_map_h(int modelnum, texture_map *n_tmap=NULL)
Definition: lua.cpp:3796
#define LE_VM_EXTERNAL_CAMERA_LOCKED
float vm_vec_dist(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:355
int asteroid_count()
Definition: asteroid.cpp:1473
int split_str(const char *src, int max_pixel_w, int *n_chars, const char **p_str, int max_lines, char ignore_char)
Definition: parselo.cpp:3412
ade_obj< int > l_Species("species","Species handle")
void snd_set_pitch(int sig, int pitch)
Definition: sound.cpp:1021
#define MAX_PLAYERS
Definition: pstypes.h:32
#define LE_SHIELD_BACK
#define PTRDIFF_T_ARG
Definition: clang.h:62
int getObjectType()
Definition: hud.cpp:515
#define AIS_GUARD_PATROL
Definition: ai.h:282
#define LE_ORDER_WAYPOINTS_ONCE
wingman message: form on my wing
int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile)
Definition: cfile.cpp:1414
ade_lib l_Graphics("Graphics", NULL,"gr","Graphics Library")
stop targeting ship
vec3d closeup_pos
Definition: ship.h:1327
int waypoint_add(vec3d *pos, int waypoint_instance)
Definition: waypoint.cpp:401
float shield_get_max_strength(object *objp)
vec3d offset
Definition: model.h:330
eye_h(int n_m, int n_e)
Definition: lua.cpp:1557
int callsign_index
Definition: ship.h:557
angles * vm_extract_angles_matrix(angles *a, const matrix *m)
Definition: vecmat.cpp:1027
float current_hits
Definition: ship.h:319
int flags2
Definition: ship.h:1228
void do_subobj_destroyed_stuff(ship *ship_p, ship_subsys *subsys, vec3d *hitpos, bool no_explosion)
Definition: shiphit.cpp:108
#define RIGHT_QUAD
Definition: objectshield.h:19
lua_Debug Ade_debug_info
Definition: lua.cpp:15807
bool scripting_target_override
Definition: ship.h:345
target next subsystem on current target
object_h objh
Definition: lua.cpp:7571
int armor_type_idx
Definition: ship.h:325
Definition: ship.h:534
cycle number of missiles fired from secondary bank
GLenum GLuint id
Definition: Glext.h:5156
enum_h()
Definition: lua.cpp:883
cfp
Definition: cfile.cpp:1061
VIEW_SLEW.
PADLOCK_RIGHT.
bool IsValid()
Definition: lua.cpp:6484
int model_load(char *filename, int n_subsystems, model_subsystem *subsystems, int ferror=1, int duplicate=0)
Definition: modelread.cpp:2573
#define gr_post_process_set_defaults
Definition: 2d.h:915
#define LE_ORDER_ATTACK_ANY
char filename[MAX_FILENAME_LEN]
Definition: ship.h:271
ADD_REMOVE_ESCORT.
ade_obj< order_h > l_Order("order","order handle")
vec3d pos
Definition: particle.h:62
#define AIORF_UP
Definition: ai.h:129
#define AI_GOAL_EVADE_SHIP
Definition: aigoals.h:44
float time_s
Definition: lua.cpp:9775
ONE_THIRD_THROTTLE.
bool bm_set_render_target(int handle, int face)
(GR function) Calls gr_bm_set_render target for the given bitmap indexed by handle ...
Definition: bmpman.cpp:2810
char bg_filename[MAX_FILENAME_LEN]
Definition: ship.h:273
ade_obj< object_h > l_Ship("ship","Ship handle",&l_Object)
void message_training_queue(char *text, int timestamp, int length)
int psnet_use_protocol(int protocol)
Definition: psnet2.cpp:596
#define LE_ORDER_DISARM
movie_play(filename)
int Asteroids_enabled
Definition: asteroid.cpp:57
void model_page_in_textures(int modelnum, int ship_info_index=-1)
ade_lib l_Mission_Waypoints("Waypoints",&l_Mission, NULL, NULL)
int clip_bottom
Definition: 2d.h:388
float vm_vec_normalize_safe(vec3d *v)
Definition: vecmat.cpp:471
#define MESSAGE_PRIORITY_LOW
int g3_project_vertex(vertex *point)
Definition: 3dmath.cpp:202
void resetClip()
Definition: hud.cpp:978
void shield_set_quad(object *objp, int quadrant_num, float strength)
ade_lib l_Mission_Wings("Wings",&l_Mission, NULL, NULL)
Definition: cfile.h:354
int secondary_bank_ammo[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:134
cfbp fp
Definition: cfile.cpp:1065
GLdouble GLdouble t
Definition: Glext.h:5329
debris Debris[MAX_DEBRIS_PIECES]
Definition: debris.cpp:41
void audiostream_unpause(int i, bool via_sexp_or_script)
Definition: audiostr.cpp:1960
vec3d * v
Definition: lua.cpp:1589
#define SIF_IN_TECH_DATABASE
Definition: ship.h:897
void setAVD(float final_position, float total_movement_time, float starting_accleration_time, float ending_acceleration_time, float final_velocity)
Definition: physics.cpp:1194
void ship_recalc_subsys_strength(ship *shipp)
Definition: ship.cpp:6020
f
Definition: lua.cpp:358
vec3d * vm_vec_unrotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:959
sexpvar_h()
Definition: lua.cpp:2919
void SetStatus(int n_status)
Definition: lua.cpp:338
void game_post_level_init()
Definition: fredstubs.cpp:234
#define AIORF_PITCH
Definition: ai.h:126
int cfread_lua_number(double *buf, CFILE *cfile)
cycle to previous primary weapon
beam Beams[MAX_BEAMS]
Definition: beam.cpp:60
target ship closest to center of reticle
target the closest friendly ship
#define SF_DISABLED
Definition: ship.h:448
#define AI_GOAL_IGNORE_NEW
Definition: aigoals.h:57
void game_render_frame(camid cid)
Definition: fredstubs.cpp:236
#define AI_GOAL_FLY_TO_SHIP
Definition: aigoals.h:56
int get_subsystem_pos(vec3d *pos, object *objp, ship_subsys *subsysp)
Definition: ship.cpp:12975
font Fonts[MAX_FONTS]
Definition: font.cpp:35
camid cam_get_current()
Definition: camera.cpp:952
const char * getCustomGaugeName()
Definition: hud.cpp:389
int type
Definition: sexp.h:1043
int snd_get_duration(int snd_id)
Definition: sound.cpp:1082
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
ade_lib l_Mission_Personas("Personas",&l_Mission, NULL, NULL)
TIME_SLOW_DOWN.
void shipfx_warpin_start(object *objp)
Definition: shipfx.cpp:565
transfer energy to shield from weapons
#define LE_SEXPVAR_PLAYER_PERSISTENT
Definition: lua.cpp:1551
ubyte alpha
Definition: 2d.h:103
long fix
Definition: pstypes.h:54
#define MESSAGE_LENGTH
Definition: globals.h:23
int model_instance_num
Definition: weapon.h:166
PITCH_BACK.
GLclampd n
Definition: Glext.h:7286
char Type
Definition: lua.h:90
particle_h()
Definition: lua.cpp:11731
unsigned char ubyte
Definition: pstypes.h:62
matrix * GetMatrix()
Definition: lua.cpp:332
#define AI_GOAL_PLAY_DEAD
Definition: aigoals.h:53
int get_mission_info(const char *filename, mission *mission_p, bool basic)
cycle to next secondary weapon
vec3d afterburner_max_vel
Definition: physics.h:50
int wi_flags
Definition: weapon.h:384
int sexp_variable_count()
Definition: sexp.cpp:29490
uint flags
Definition: physics.h:37
#define LE_ORDER_DOCK
void game_simulation_frame()
Definition: fredstubs.cpp:237
#define SF_ARRIVING_STAGE_1
Definition: ship.h:451
int ship_create(matrix *orient, vec3d *pos, int ship_type, char *ship_name)
Definition: ship.cpp:9690
particle * part
Definition: lua.cpp:11728
int h
Definition: font.h:43
ade_lib l_Mouse("Controls", NULL,"io","Controls library")
eyepoints_h(polymodel *pm)
Definition: lua.cpp:1678
#define AI_GOAL_WAYPOINTS_ONCE
Definition: aigoals.h:32
void setFont()
Definition: hud.cpp:440
#define MH_ANGLES_OUTOFDATE
Definition: lua.cpp:298
~particle_h()
Definition: lua.cpp:11756
#define LE_MOUSE_LEFT_BUTTON
#define OBJ_INDEX(objp)
Definition: object.h:235
float GetYaw()
PADLOCK_LEFT.
void set_current_hud()
Definition: hudparse.cpp:669
int shield_armor_type_idx
Definition: ship.h:797
float radius
Definition: model.h:442
ship * Player_ship
Definition: ship.cpp:124
vec3d hit_point_world
Definition: model.h:1124
object * objp
Definition: beam.h:119
#define GM_IN_MISSION
Definition: systemvars.h:23
int ai_override_flags
Definition: ai.h:548
int GetSize()
Definition: lua.cpp:3816
int CreateLuaState()
Definition: lua.cpp:15872
dock_bay * getDockingBay()
Definition: lua.cpp:2235
matrix orient
Definition: object.h:153
#define gr_post_process_set_effect
Definition: 2d.h:914
ade_lib l_Graphics_Cameras("Cameras",&l_Graphics, NULL,"Cameras")
int max_w
Definition: 2d.h:360
int cfeof(CFILE *cfile)
target the closest repair ship
int snd_get_3d_vol_and_pan(game_snd *gs, vec3d *pos, float *vol, float *pan, float radius, float range_factor)
Definition: sound.cpp:759
cockpit_display * Get()
Definition: lua.cpp:5311
char * armor_str
Definition: ship.h:1171
texture_map * Get()
Definition: lua.cpp:3808
void briefing_stop_music(bool fade)
ade_obj< glowpoint_h > l_Glowpoint("glowpoint","A model glowpoint")
float rad
Definition: model.h:340
#define LE_VM_PADLOCK_LEFT
#define WIF_BOMB
Definition: weapon.h:63
vec3d vec
Definition: lua.cpp:2173
#define OBJ_SHIP
Definition: object.h:32
#define MULTIPLAYER_STANDALONE
Definition: multi.h:133
mouse_set_pos(x, y)
#define GR_RESIZE_FULL
Definition: 2d.h:682
GLfloat GLfloat v1
Definition: Glext.h:5639
TARGET_NEXT_LIVE_TURRET.
vec3d * v3a
Definition: lua.cpp:4997
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
void OutputMeta(FILE *fp)
Definition: lua.cpp:16875
int target_sig
Definition: weapon.h:173
int ai_override_timestamp
Definition: ai.h:550
float bank
Definition: physics.h:104
#define ADE_RETURN_NIL
Definition: lua.cpp:245
wingman message: engage enemy
dockingbay_h(polymodel *pm, int dock_idx)
Definition: lua.cpp:2220
#define AI_GOAL_GUARD_WING
Definition: aigoals.h:43
matrix_h * mh
Definition: lua.cpp:4789
void * buf
Definition: lua.h:43
thrusterbank_h(thruster_bank *ba)
Definition: lua.cpp:1704
ubyte flags
Definition: pstypes.h:178
GLbitfield flags
Definition: Glext.h:6722
float forward_cruise_percent
Definition: physics.h:106
#define CF_TYPE_INVALID
Definition: cfile.h:44
float tracer_length
Definition: particle.h:70
ade_func(char *name, lua_CFunction func, ade_lib_handle &parent, char *args=NULL, char *desc=NULL, char *ret_type=NULL, char *ret_desc=NULL)
Definition: lua.cpp:111
int Num_weapon_types
Definition: weapons.cpp:105
#define vm_malloc(size)
Definition: pstypes.h:547
void set_rotation(matrix *in_orientation=NULL, float in_rotation_time=0.0f, float in_rotation_acceleration_time=0.0f, float in_rotation_deceleration_time=0.0f)
Definition: camera.cpp:195
void game_level_init()
Definition: fredstubs.cpp:233
int wing_name_lookup(const char *name, int ignore_count)
Definition: ship.cpp:12706
void sanity_check_ets_inputs(int(&ets_indexes)[num_retail_ets_gauges])
Definition: hudets.cpp:681
if i'm an observer, zoom to my targeted object
const char * snd_get_filename(int snd_id)
Definition: sound.cpp:1101
int SetTexture(int n_tex)
GLuint const GLchar * name
Definition: Glext.h:5608
FIRE_SECONDARY.
union MissionMessage::@255 wave_info
#define ADE_RETURN_FALSE
Definition: lua.cpp:247
__inline void gr_line(int x1, int y1, int x2, int y2, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:791
cockpit_display_h(object *objp, size_t display_num)
Definition: lua.cpp:5303
int mid
Definition: lua.cpp:1623
bool IsValid()
Definition: lua.cpp:6500
int Num_builtin_messages
ade_lib l_Campaign("Campaign", NULL,"ca","Campaign Library")
int secondary_bank_rearm_time[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:138
physics_info * pi
Definition: lua.cpp:2460
ade_lib l_Mission_WaypointLists("WaypointLists",&l_Mission, NULL, NULL)
int bank
Definition: lua.cpp:6491
GLuint GLfloat * val
Definition: Glext.h:6741
float x
Definition: pstypes.h:107
int final_death_time
Definition: ship.h:569
ade_obj< waypointlist_h > l_WaypointList("waypointlist","waypointlist handle")
FORWARD_THRUST.
object_h objh
Definition: lua.cpp:2459
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:168
#define SWH_SECONDARY
Definition: lua.cpp:6467
int Num_personas
#define SUBSYSTEM_ENGINE
Definition: model.h:53
vec3d vel
Definition: physics.h:77
float radius
Definition: model.h:179
float fspeed
Definition: physics.h:80
ODATA_SIG_TYPE * sig
Definition: lua.h:42
fix t1
Definition: animplay.cpp:37
transfer energy to weapons from shield
virtual bool canRender()
Definition: hud.cpp:1059
#define TOKEN_LENGTH
Definition: globals.h:41
#define VM_PADLOCK_UP
Definition: systemvars.h:38
Definition: hudets.h:45
int time_ms
Definition: lua.cpp:9774
LEFT_SLIDE_THRUST.
float GetY()
TrackIRDLL gTirDll_TrackIR
int getId()
Definition: lua.cpp:8227
UP_SLIDE_THRUST.
bool sexp_replace_variable_names_with_values(char *text, int max_len)
Definition: sexp.cpp:29395
bool weapon_armed(weapon *wp, bool hit_target)
Definition: weapons.cpp:6208
vec3d Eye_position
Definition: 3dsetup.cpp:27
#define TM_GLOW_TYPE
Definition: model.h:658
int ade_set_object_with_breed(lua_State *L, int obj_idx)
Definition: lua.cpp:15770
#define LE_VM_TRACK
int bm_load(const char *real_filename)
Loads a bitmap so we can draw with it later.
Definition: bmpman.cpp:1119
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
int bm_get_cache_slot(int bitmap_id, int separate_ani_frames)
Definition: bmpman.cpp:669
char * ReturnDescription
Definition: lua.h:111
dockingbays_h(polymodel *pm)
Definition: lua.cpp:1760
SCP_vector< cockpit_display_info > displays
Definition: ship.h:1451
int num_hits
Definition: model.h:1121
int model_find_dock_name_index(int modelnum, char *name)
Definition: modelread.cpp:5055
#define HUD_OBJECT_OFFSCREEN
Definition: hudparse.h:193
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
void model_instance_find_world_dir(vec3d *out_dir, vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient)
Definition: modelread.cpp:4587
float nval
Definition: lua.cpp:3103
int cftell(CFILE *fp)
float turret_turning_rate
Definition: model.h:194
void audiostream_close_file(int i, int fade)
Definition: audiostr.cpp:1772
flag_def_list plr_commands[]
Definition: lua.cpp:756
bool IsValid()
Definition: lua.cpp:4451
o
Definition: lua.cpp:442
wingman message: protect current target
#define MESSAGE_PRIORITY_HIGH
bool add_message(char *name, char *message, int persona_index, int multi_team)
equalize shield energy to all quadrants
int parent_objnum
Definition: ship.h:316
#define MOUSE_RIGHT_BUTTON
Definition: mouse.h:44
#define ODATA_SIG_TYPE
Definition: lua.h:31
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
bool IsValid()
Definition: lua.cpp:2921
TOGGLE_HUD.
void ade_stackdump(lua_State *L, char *stackdump)
Definition: lua.cpp:15953
ade_lib l_Mission_Asteroids("Asteroids",&l_Mission, NULL,"Asteroids in the mission")
GLuint GLuint num
Definition: Glext.h:9089
#define LE_MESSAGE_PRIORITY_NORMAL
TARGET_NEWEST_SHIP.
order_h()
Definition: lua.cpp:7576
#define MAX_REPLACEMENT_TEXTURES
Definition: model.h:690
bool local
Definition: lua.cpp:4524
#define ADE_FUNC(name, parent, args, desc, ret_type, ret_desc)
Definition: lua.cpp:220
sound_h()
Definition: lua.cpp:8338
int LoadBm(char *name)
Definition: scripting.cpp:818
#define AIS_UNDOCK_0
Definition: ai.h:275
ship_subsys * ship_get_subsys(ship *shipp, char *subsys_name)
Definition: ship.cpp:17024
#define LE_SEXPVAR_NOT_PERSISTENT
SCP_string main_hall
int index
Definition: lua.cpp:880
NAV_CYCLE.
waypointlist_h(char wlname[NAME_LENGTH])
Definition: lua.cpp:6323
int attached_sig
Definition: particle.h:72
#define SWH_TERTIARY
Definition: lua.cpp:6468
int ship_launch_countermeasure(object *objp, int rand_val)
Definition: ship.cpp:10421
vec3d pnt
Definition: model.h:178
HUD_TARGETBOX_TOGGLE_WIREFRAME.
#define LE_MOUSE_MIDDLE_BUTTON
void CAP(T &v, T mn, T mx)
Definition: pstypes.h:478
#define LE_PARTICLE_PERSISTENT_BITMAP
int secondary_next_slot[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:137
ade_obj< dockingbays_h > l_Dockingbays("dockingbays","The docking bays of a model")
float turret_fov
Definition: model.h:188
waypoint_list * find_matching_waypoint_list(const char *name)
Definition: waypoint.cpp:164
#define LE_ORDER_GUARD_WING
int turret_next_fire_pos
Definition: ship.h:339
campaign Campaign
GLint GLsizei GLsizei height
Definition: Gl.h:1505
Definition: pstypes.h:606
#define strcat_s(...)
Definition: safe_strings.h:68
void game_level_close()
Definition: fredstubs.cpp:182
int Beam_count
Definition: beam.cpp:63
#define AI_GOAL_KEEP_SAFE_DISTANCE
Definition: aigoals.h:48
#define NAME_LENGTH
Definition: globals.h:15
#define SF_SECONDARY_DUAL_FIRE
Definition: ship.h:459
uint Num_subentries
Definition: lua.h:116
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
char * GetName()
Definition: lua.h:155
thruster_bank * Get()
Definition: lua.cpp:1709
#define LEFT_QUAD
Definition: objectshield.h:18
char * get_name()
Definition: camera.h:71
#define WP_MISSILE
Definition: weapon.h:28
TARGET_PREV_BOMB.
ship_subsys * target_subsys
Definition: beam.h:121
#define AI_GOAL_DISABLE_SHIP
Definition: aigoals.h:39
float rad
Definition: model.h:757
int set_target_objnum(ai_info *aip, int objnum)
Definition: aicode.cpp:1250
int n_models
Definition: model.h:744
struct mc_info mc_info
Definition: pstypes.h:106
int snd_time_remaining(int handle)
Definition: sound.cpp:1291
eyepoints_h()
Definition: lua.cpp:1679
int idx
Definition: lua.cpp:8199
bool hud_enabled
Definition: ship.h:1448
target ships subsystem in reticle
#define VM_PADLOCK_LEFT
Definition: systemvars.h:40
waypoint_list * find_waypoint_list_at_index(int index)
Definition: waypoint.cpp:291
int g3_in_frame()
Definition: 3dsetup.cpp:66
bool IsValid()
Definition: object.h:185
camid cam_lookup(char *name)
Definition: camera.cpp:965
#define fl2i(fl)
Definition: floating.h:33
void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipname, ai_info *aip)
Definition: aigoals.cpp:730
#define LE_PARTICLE_SMOKE2
int submodel
Definition: lua.cpp:5007
ade_obj< int > l_Wing("wing","Wing handle")
void hud_disable_except_messages(int disable)
Definition: hud.cpp:1288
ade_lib l_Graphics_Fonts("Fonts",&l_Graphics, NULL,"Font library")
player * Player
int Num_fonts
Definition: font.cpp:34
void gr_bitmap_list(bitmap_2d_list *list, int n_bm, int resize_mode)
Definition: 2d.cpp:1407
ESCORT_CLEAR.
void audiostream_unpause_all(bool via_sexp_or_script=false)
Definition: audiostr.cpp:1990
int GetID()
Definition: lua.cpp:1634
#define MH_MATRIX_OUTOFDATE
Definition: lua.cpp:297
end the mission
#define MC_CHECK_MODEL
Definition: model.h:1169
PADLOCK_DOWN.
#define LGC_B_NORMAL
Definition: player.h:69
TARGET_NEXT_BOMB.
#define g3_end_frame()
Definition: 3d.h:49
int model_instance_num
Definition: asteroid.h:101
Autopilot key control.
TWO_THIRDS_THROTTLE.
class camera * getCamera()
Definition: camera.cpp:833
screen gr_screen
Definition: 2d.cpp:46
float lifetime
Definition: particle.h:64
mc_info_h()
Definition: lua.cpp:4434
float shield_get_quad(object *objp, int quadrant_num)
float Min_draw_distance
Definition: 2d.cpp:84
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
#define WIF_BEAM
Definition: weapon.h:76
ade_obj< CFILE * > l_File("file","File handle")
ade_lib l_Mission("Mission", NULL,"mn","Mission library")
ade_obj< gameevent_h > l_GameEvent("gameevent","Game event")
float heading
Definition: physics.h:102
#define LE_VM_FREECAMERA
float forward_accel_time_const
Definition: physics.h:59
glow_point * points
Definition: model.h:447
void game_render_post_frame()
Definition: fredstubs.cpp:239
uint cam_get_num()
Definition: camera.cpp:957
FIRE_PRIMARY.
#define MAX_AUDIO_STREAMS
Definition: audiostr.h:26
int snd_play_looping(game_snd *gs, float pan, int start_loop, int stop_loop, float vol_scale, int scriptingUpdateVolume)
Definition: sound.cpp:822
GLint first
Definition: Gl.h:1491
#define SEXP_VARIABLE_CAMPAIGN_PERSISTENT
Definition: sexp.h:886
void mission_campaign_jump_to_mission(char *name, bool no_skip)
ship_subsys * targeted_subsys
Definition: ship.h:344
ade_obj< sound_h > l_Sound("sound","sound instance handle")
waypointlist_h()
Definition: lua.cpp:6317
#define VM_WARPIN_ANCHOR
Definition: systemvars.h:42
#define MAX_FRAME_COLLISIONS
Definition: beam.h:93
char subobj_name[MAX_NAME_LEN]
Definition: model.h:172
int SetTable(lua_State *L, int p_amt_ldx, int p_mtb_ldx)
Definition: lua.cpp:16663
gameevent_h()
Definition: lua.cpp:1425
#define LE_VM_DEAD_VIEW
uint idx
Definition: lua.h:41
CFILE * ctmpfile()
Definition: cfile.cpp:844
void set_name(char *in_name)
Definition: camera.cpp:81
color c
Definition: lua.cpp:12879
int get_object_target_submodel()
Definition: camera.cpp:279
thrusterbank_h()
Definition: lua.cpp:1699
#define LE_ORDER_STAY_NEAR
TIME_SPEED_UP.
void physics_apply_whack(vec3d *impulse, vec3d *pos, physics_info *pi, matrix *orient, float mass)
Definition: physics.cpp:776
GLsizei const GLchar ** path
Definition: Glext.h:6795
bool shader_effect_active
Definition: ship.h:769
int status[NUM_BUTTON_FIELDS]
Definition: keycontrol.h:30
void ship_hit_kill(object *ship_objp, object *other_obj, float percent_killed, int self_destruct)
Definition: shiphit.cpp:1542
int gr_get_font_height()
Definition: font.cpp:187
void snd_ffwd(int snd_handle, game_snd *gs, float seconds)
Definition: sound.cpp:1150
cycle to next primary weapon
#define ODATA_SIG_DEFAULT
Definition: lua.h:32
char variable_name[TOKEN_LENGTH]
Definition: lua.cpp:2917
#define CF_TYPE_MISSIONS
Definition: cfile.h:74
ade_obj< HudGauge > l_HudGauge("HudGauge","HUD Gauge handle")
game_snd * Get()
Definition: lua.cpp:8211
int ship_info_index
Definition: ship.h:539
void light_reset()
Definition: lighting.cpp:150
int center_offset_x
Definition: 2d.h:364
int find_index_of_waypoint_list(waypoint_list *wp_list)
Definition: waypoint.cpp:324
GLfloat GLfloat p
Definition: Glext.h:8373
float slide_accel_time_const
Definition: physics.h:63
#define MULTIPLAYER_MASTER
Definition: multi.h:130
float vertical
Definition: physics.h:101
ade_lib l_Mission_Weapons("Weapons",&l_Mission, NULL, NULL)
vec3d last_shot
Definition: beam.h:142
void message_send_unique_to_player(char *id, void *data, int m_source, int priority, int group, int delay)
void snd_set_volume(int sig, float volume)
Definition: sound.cpp:920
texture_info textures[TM_NUM_TYPES]
Definition: model.h:671
GLenum src
Definition: Glext.h:5917
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
#define LOCATION
Definition: pstypes.h:245
int secondary_animation_done_time[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:154
float shield_factor
Definition: weapon.h:378
int max_h
Definition: 2d.h:360
vec3d * vm_vec_avg(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:217
void ade_debug_ret(lua_State *L, lua_Debug *ar)
Definition: lua.cpp:15833
decrease weapon recharge rate
int submodel_find_2d_bound_min(int model_num, int submodel, matrix *orient, vec3d *pos, int *x1, int *y1, int *x2, int *y2)
Definition: modelread.cpp:3232
void ade_output_toc(FILE *fp, ade_table_entry *ate)
Definition: lua.cpp:17079
void snd_set_pos(int snd_handle, game_snd *gs, float val, int as_pct)
Definition: sound.cpp:1180
ade_lib l_Mission_Ships("Ships",&l_Mission, NULL,"Ships in the mission")
char name[MAX_NAME_LEN]
Definition: model.h:529
#define AI_GOAL_CHASE_WEAPON
Definition: aigoals.h:54
#define LE_ORDER_WAYPOINTS
#define TMAP_FLAG_TEXTURED
Definition: tmapper.h:36
int Viewer_mode
Definition: systemvars.cpp:28
int model_anim_match_type(char *p)
Definition: modelanim.cpp:38
toggle auto-targeting
matrix_h(angles *in)
Definition: lua.cpp:324
Definition: lua.h:177
char buf[128]
Definition: lua.cpp:3672
message all netplayers
__inline void gr_aabitmap_ex(int x, int y, int w, int h, int sx, int sy, int resize_mode=GR_RESIZE_FULL, bool mirror=false)
Definition: 2d.h:755
bool IsValid()
Definition: lua.cpp:1558
int gameseq_get_event_idx(char *s)
SCP_vector< species_info > Species_info
object * get_object_host()
Definition: camera.cpp:258
MINUS_5_PERCENT_THROTTLE.
int num_plr_commands
Definition: lua.cpp:877
void resize(int *x, int *y)
Definition: hud.cpp:1026
const size_t INVALID_ID
Definition: lua.cpp:215
#define SWH_NONE
Definition: lua.cpp:6465
show the mission goals screen
#define PI
Definition: pstypes.h:303
void shipfx_warpout_start(object *objp)
Definition: shipfx.cpp:794
#define MAX_WEAPONS
Definition: globals.h:71
hull_check pos
Definition: lua.cpp:5050
char * maneuverability_str
Definition: ship.h:1170
void audiostream_play(int i, float volume, int looping)
Definition: audiostr.cpp:1803
char * objective_key_text
Definition: missiongoals.h:113
int Game_skill_level
Definition: fredstubs.cpp:170
transfer shield energy to left
float radius
Definition: particle.h:82
const GLfloat * m
Definition: Glext.h:10319
#define LE_ORDER_DEPART
modeltextures_h(polymodel *pm)
Definition: lua.cpp:1668
float Master_event_music_volume
Definition: eventmusic.cpp:40
GLsizei GLsizei GLuint * obj
Definition: Glext.h:5619
int ade_Num_operators
Definition: lua.cpp:202
int load_count
Definition: bm_internal.h:72
float get_fov()
Definition: camera.cpp:284
target the next friendly ship
int model
Definition: lua.cpp:1553
int model_instance_num
Definition: model.h:1109
int armor_type_idx
Definition: ship.h:796
glow_point * point
Definition: lua.cpp:1728
wingman message: capture current target
VIEW_CHASE.
int add_wave(const char *wave_name)
void change_ship_type(int n, int ship_type, int by_sexp)
Definition: ship.cpp:9983
#define AI_GOAL_CHASE
Definition: aigoals.h:29
target the previous closest hostile
void shield_set_max_strength(object *objp, float newmax)
float vm_vec_dot(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:312
float fov
Definition: lua.cpp:9155
cockpit_display_info * Get()
Definition: lua.cpp:5133
ade_lib l_Graphics_Posteffects("PostEffects",&l_Graphics, NULL,"Post processing effects")
void shield_set_strength(object *objp, float strength)
int model_num
Definition: weapon.h:329
#define LE_NONE
float a1d[9]
Definition: pstypes.h:120
void set_pos(vec3d *pos)
Definition: waypoint.cpp:61
bool Instanced
Definition: lua.h:89
TARGET_PREV_UNINSPECTED_CARGO.
beam_collision f_collisions[MAX_FRAME_COLLISIONS]
Definition: beam.h:153
#define i2fl(i)
Definition: floating.h:32
wingman message: disable current target
LAUNCH_COUNTERMEASURE.
void asteroid_hit(object *pasteroid_obj, object *other_obj, vec3d *hitpos, float damage)
Definition: asteroid.cpp:1368
object_h obj
Definition: lua.cpp:3779
#define LE_ORDER_STAY_STILL
char name[NAME_LENGTH]
Definition: missiongoals.h:102
float sideways
Definition: physics.h:103
ade_lib l_Audio("Audio", NULL,"ad","Sound/Music Library")
BANK_LEFT.
ade_obj< particle_h > l_Particle("particle","Handle to a particle")
GLint GLsizei count
Definition: Gl.h:1491
physics_info_h(physics_info *in_pi)
Definition: lua.cpp:2472
#define MAX_CAMPAIGN_MISSIONS
GLsizei GLsizei GLchar * source
Definition: Glext.h:5625
ade_obj< object_h > l_Asteroid("asteroid","Asteroid handle",&l_Object)
#define LGC_B_POLL_ALL
Definition: player.h:73
string_conv ade_Operators[]
Definition: lua.cpp:180
#define GR_BITBLT_MODE_NORMAL
Definition: 2d.h:351
ship_subsys_h()
Definition: lua.cpp:6883
void hud_shield_hit_reset(object *objp, int player)
Definition: hudshield.cpp:497
#define CF_MAX_PATH_TYPES
Definition: cfile.h:82
matrix * A
Definition: lua.cpp:444
lua_CFunction Function
Definition: lua.h:100
ade_obj< model_h > l_Model("model","3D Model (POF) handle")
float shockwave_shake_amp
Definition: physics.h:65
#define ADE_INDEXER(parent, args, desc, ret_type, ret_desc)
Definition: lua.cpp:234
ade_obj< mc_info_h > l_ColInfo("collision info","Information about a collision")
void ai_set_guard_wing(object *objp, int wingnum)
Definition: aicode.cpp:7450
#define LE_CFILE_TYPE_NORMAL
sound_entry_h()
Definition: lua.cpp:8201
eye view_positions[MAX_EYES]
Definition: model.h:753
BANK_WHEN_PRESSED.
#define SEXP_VARIABLE_NUMBER
Definition: sexp.h:873
GLenum GLsizei len
Definition: Glext.h:6283
ade_obj< object_h > l_Shields("shields","Shields handle")
button_info lua_bi
Definition: player.h:211
void ade_debug_call(lua_State *L, lua_Debug *ar)
Definition: lua.cpp:15810
object * Player_obj
Definition: object.cpp:56
ade_obj< eyepoints_h > l_Eyepoints("eyepoints","Array of model eye points")
gamestate_h(int n_state)
Definition: lua.cpp:1474
char * GetName()
Definition: lua.cpp:99
#define WPF_REPEAT
Definition: ai.h:295
self destruct (multiplayer only)
vec3d velocity
Definition: particle.h:79
wingman message: warp out
int Num_reinforcements
Definition: ship.cpp:121
Definition: ai.h:134
uint flags2
Definition: ship.h:645
#define AI_GOAL_REARM_REPAIR
Definition: aigoals.h:49
char variable_name[TOKEN_LENGTH]
Definition: sexp.h:1045
float flRealframetime
Definition: fredstubs.cpp:226
#define SF_DYING
Definition: ship.h:447
ade_obj< object_h > l_ShipOrders("shiporders","Ship orders")
ade_obj< texture_map_h > l_TextureMap("material","Texture map, including diffuse, glow, and specular textures")
vec3d world
Definition: pstypes.h:172
int temp
Definition: lua.cpp:4996
cycle to next radar range
int audiostream_open(const char *filename, int type)
Definition: audiostr.cpp:1713
#define PF_AFTERBURNER_ON
Definition: physics.h:20
uint LibIdx
Definition: lua.h:162
int ships_inited
Definition: ship.cpp:129
ship_subsys_h(object *objp_in, ship_subsys *sub)
Definition: lua.cpp:6886
int ship_index[MAX_SHIPS_PER_WING]
Definition: ship.h:1531
#define LE_ALPHABLEND_FILTER
VIEW_TRACK_TARGET.
polymodel * pm
Definition: lua.cpp:1598
char * dest
Definition: lua.cpp:170
bool Ade_get_args_lfunction
Definition: lua.cpp:16098
const char * ade_get_type_string(lua_State *L, int argnum)
Definition: lua.cpp:16085
vec3d hit_normal
Definition: model.h:1129
ade_lib l_Mission_Events("Events",&l_Mission, NULL,"Events")
thrusters_h()
Definition: lua.cpp:1689
void model_calc_bound_box(vec3d *box, vec3d *big_mn, vec3d *big_mx)
Definition: modelread.cpp:1009
char * Description
Definition: lua.h:109
float rad
Definition: particle.h:65
int primary_bank_rearm_time[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:125
int ade_get_operator(char *tablename)
Definition: lua.cpp:204
int ship_get_subsys_index(ship *sp, char *ss_name, int error_bypass)
Definition: ship.cpp:13421
#define MAX(a, b)
Definition: pstypes.h:299
Definition: camera.h:18
float closeup_zoom
Definition: ship.h:1328
int shader_effect_num
Definition: ship.h:766
#define LE_ORDER_IGNORE
int Num_iffs
Definition: iff_defs.cpp:19
ai_goal * aigp
Definition: lua.cpp:7574
int is_white_space(char ch)
Definition: parselo.cpp:59
#define VM_OTHER_SHIP
Definition: systemvars.h:35
ade_obj< enum_h > l_Enum("enumeration","Enumeration object")
int G3_count
Definition: 3dsetup.cpp:59
#define LE_ORDER_FORM_ON_WING
int size
Definition: lua.h:44
#define LE_LOCK
#define PLAYER_FLAGS_IS_MULTI
Definition: player.h:42
float hud_find_target_distance(object *targetee, object *targeter)
Definition: hudtarget.cpp:2009
int primary_bank_start_ammo[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:122
object * get_object_target()
Definition: camera.cpp:271
void game_update_missiontime()
Definition: fredstubs.cpp:238
gr_init_alphacolor &[idx] HUD_config
Definition: lua.cpp:12864
#define OBJ_NONE
Definition: object.h:31
float mass
Definition: physics.h:39
#define OBJ_BEAM
Definition: object.h:46
glowpoint_h()
Definition: lua.cpp:1730
int ship_name_lookup(const char *name, int inc_players)
Definition: ship.cpp:12900
char * Name
Definition: lua.h:79
ubyte codes
Definition: pstypes.h:177
void audiostream_pause(int i, bool via_sexp_or_script)
Definition: audiostr.cpp:1943
int collision_group_id
Definition: object.h:169
GLboolean reset
Definition: Glext.h:5243
vec3d * vm_vec_cross(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:645
ade_obj< ship_banktype_h > l_WeaponBankType("weaponbanktype","Ship/subsystem weapons bank type handle")
int numargs
Definition: lua.cpp:355
uint DerivatorIdx
Definition: lua.h:84
int obj_get_by_signature(int sig)
Definition: object.cpp:2074
#define GR_ALPHABLEND_NONE
Definition: 2d.h:348
#define SF2_STEALTH
Definition: ship.h:485
particle * particle_create(particle_info *pinfo)
Definition: particle.cpp:105
MAX_THROTTLE.
int current_tertiary_bank
Definition: ship.h:108
#define LE_LUA_ADDITIVE_BUTTON_CONTROL
void snd_stop(int sig)
Definition: sound.cpp:875
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
int draw_subsys_brackets(ship_subsys *subsys, int min_width, int min_height, bool draw, bool set_color, int *draw_coords)
mission The_mission
#define AI_GOAL_DESTROY_SUBSYSTEM
Definition: aigoals.h:34
uint signature
Definition: particle.h:94
#define WF_DESTROYED_BY_WEAPON
Definition: weapon.h:143
matrix last_orient
Definition: object.h:156
ade_obj< sound_entry_h > l_SoundEntry("soundentry","sounds.tbl table entry handle")
void audiostream_pause_all(bool via_sexp_or_script=false)
Definition: audiostr.cpp:1978
vec3d pnt
Definition: model.h:440
#define MESSAGE_SOURCE_SPECIAL
int cfclose(CFILE *cfile)
Definition: cfile.cpp:895
#define LE_ORDER_KEEP_SAFE_DISTANCE
#define VM_CHASE
Definition: systemvars.h:34
#define SF_TRIGGER_DOWN
Definition: ship.h:462
GLint lod
Definition: Glext.h:7352
vec3d last_start
Definition: beam.h:143
wingman message: disable current target
float GetPitch()
float h
Definition: pstypes.h:111
__inline void gr_pixel(int x, int y, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:798
void gr_set_font(int fontnum)
Definition: font.cpp:566
int turret_enemy_objnum
Definition: ship.h:337
#define GR_CURSOR_LOCK
Definition: 2d.h:720
int model_num
Definition: lua.cpp:4996
GLclampf GLclampf GLclampf alpha
Definition: Glext.h:5177
int model_instance_num
Definition: lua.cpp:4996
int submodel_num
Definition: model.h:1111
int bm_make_render_target(int width, int height, int flags)
Creates a render target as close to the desired resolution as possible.
Definition: bmpman.cpp:2267
int current_cmeasure
Definition: ship.h:652
ade_obj< int > l_Message("message","Handle to a mission message")
ade_indexer(lua_CFunction func, ade_lib_handle &parent, char *args=NULL, char *desc=NULL, char *ret_type=NULL, char *ret_desc=NULL)
Definition: lua.cpp:149
int ul
Definition: lua.cpp:12653
int rendering_to_texture
Definition: 2d.h:403
char type
Definition: object.h:146
ade_lib(char *in_name, ade_lib_handle *parent=NULL, char *in_shortname=NULL, char *in_desc=NULL)
Definition: lua.cpp:69
void game_stop_time()
Definition: fredstubs.cpp:189
int background
Definition: ship.h:261
#define MESSAGE_SOURCE_COMMAND
vec3d vmd_zero_vector
Definition: vecmat.cpp:24
#define CF_TYPE_ANY
Definition: cfile.h:42
void main_hall_stop_music(bool fade)
ade_obj< int > l_Player("player","Player handle")
#define PARTICLE_SMOKE2
Definition: particle.h:53
int ship_start_render_cockpit_display(int cockpit_display_num)
Definition: ship.cpp:7494
void ade_output_type_link(FILE *fp, char *typestr)
Definition: lua.cpp:16861
float damage
Definition: weapon.h:363
float default_volume
range: 0.0 -> 1.0
Definition: sound.h:78
int main_hall_get_index(const SCP_string &name_to_find)
void renderOffscreenIndicator(vec2d *coords, int dir, float distance, float half_triangle_sep, bool draw_solid=true)
Definition: hudtarget.cpp:6458
#define LGC_B_OVERRIDE
Definition: player.h:70
int hud_disabled_except_messages()
Like hud_disabled(), except messages are still drawn.
Definition: hud.cpp:1297
bool IsValid()
Definition: lua.cpp:8219
float autoaim_fov
Definition: ship.h:817
char filename[FILESPEC_LENGTH]
Definition: model.h:734
#define wp(p)
Definition: modelsinc.h:69
increase weapon recharge rate
void _cdecl void LuaError(struct lua_State *L, SCP_FORMAT_STRING const char *format=NULL,...) SCP_FORMAT_STRING_ARGS(2
void g3_point_to_vec(vec3d *v, int sx, int sy)
Definition: 3dmath.cpp:231
void draw_brackets_square(int x1, int y1, int x2, int y2, int resize_mode)
Definition: hudbrackets.cpp:49
void updateCustomGaugeText(const char *txt)
Definition: hud.cpp:422
ubyte reverse
Definition: particle.h:73
SCP_vector< asteroid_info > Asteroid_info
Definition: asteroid.cpp:62
int Cmdline_stretch_menu
Definition: cmdline.cpp:382
float armor_factor
Definition: weapon.h:378
ade_obj< modeltextures_h > l_ModelTextures("modeltextures_h","Array of materials")
Definition: lua.cpp:879
int attached_objnum
Definition: particle.h:71
int timer_get_milliseconds()
Definition: timer.cpp:150
void gameseq_post_event(int event)
TARGET_NEXT_UNINSPECTED_CARGO.
v3 xyz x
Definition: lua.cpp:3632
bool IsValid()
Definition: lua.cpp:6330
#define MR_NO_FOGGING
Definition: model.h:884
void hud_set_iff_color(object *objp, int is_bright)
Will set the color to the IFF color based on the team.
Definition: hud.cpp:2950
vec3d pnt[MAX_DOCK_SLOTS]
Definition: model.h:530
int shield_recharge_index
Definition: ship.h:637
matrix * orient
Definition: model.h:1112
#define GM_CAMPAIGN_MODE
Definition: systemvars.h:29
bool IsValid()
Definition: lua.cpp:6882
#define stricmp(s1, s2)
Definition: config.h:271
#define OBJ_JUMP_NODE
Definition: object.h:45
void vm_vec_add(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:159
transfer shield energy to rear
int gameseq_get_depth()
bool IsValid()
Definition: lua.cpp:1428
matrix vmd_identity_matrix
Definition: vecmat.cpp:28
ade_obj< eye_h > l_Eyepoint("eyepoint","Eyepoint handle")
#define timestamp_valid(stamp)
Definition: timer.h:104
bool Enabled()
Definition: trackirpublic.h:60
#define AI_GOAL_FORM_ON_WING
Definition: aigoals.h:35
#define GR_CURSOR_UNLOCK
Definition: 2d.h:721
int wing_lookup(const char *name)
Definition: ship.cpp:12736
multi_global_options Multi_options_g
int cmeasure_count
Definition: ship.h:651
int sig
Definition: beam.h:118
void message_load_wave(int index, const char *filename)
#define LE_SEXPVAR_TYPE_STRING
int parent_sig
Definition: object.h:148
ship_banktype_h(object *objp_in, ship_weapon *wpn, int in_type)
Definition: lua.cpp:6479
int cfilelength(CFILE *cfile)
Definition: cfile.cpp:1393
target the next hostile target
char ship_name[NAME_LENGTH]
Definition: ship.h:604
#define AIS_GUARD_STATIC
Definition: ai.h:285
particle * Get()
Definition: lua.cpp:11743
ship_subsys * set_targeted_subsys(ai_info *aip, ship_subsys *new_subsys, int parent_objnum)
Definition: aicode.cpp:1289
Definition: hudets.h:45
ade_obj< dockingbay_h > l_Dockingbay("dockingbay","Handle to a model docking bay")
return ade_set_args(L,"f",*val)
void light_rotate_all()
Definition: lighting.cpp:585
int signature
Definition: ai.h:135
Definition: lua.cpp:8197
float VIEWER_ZOOM_DEFAULT
Definition: camera.cpp:15
float vert_thrust
Definition: physics.h:74
char * ade_concat_helper(lua_State *L, int obj_ldx)
Definition: lua.cpp:16403
const GLubyte * c
Definition: Glext.h:8376
transfer shield energy to front
#define SEXP_VARIABLE_STRING
Definition: sexp.h:874
int cf_exists(const char *filename, int dir_type)
Definition: cfile.cpp:514
SCP_vector< ship_type_info > Ship_types
Definition: ship.cpp:168
void model_set_detail_level(int n)
texture_map_h(object *objp, texture_map *n_tmap=NULL)
Definition: lua.cpp:3790
cmission missions[MAX_CAMPAIGN_MISSIONS]
int ets_idx
Definition: lua.cpp:9580
#define MAX_SEXP_VARIABLES
Definition: sexp.h:23
#define fl2f(fl)
Definition: floating.h:38
ade_lib l_HUD("HUD", NULL,"hu","HUD library")
Definition: hudets.h:45
ade_lib l_BitOps("BitOps", NULL,"bit","Bitwise Operations library")
bool isValid()
Definition: lua.cpp:1717
float b
Definition: pstypes.h:111
#define LE_ORDER_PLAY_DEAD
int num_slots
Definition: model.h:525
GLuint res
Definition: Glext.h:9084
PLUS_5_PERCENT_THROTTLE.
ade_obj< cockpit_disp_info_h > l_DisplayInfo("display info","Ship cockpit display information handle")
ade_lib l_Tables_ShipClasses("ShipClasses",&l_Tables, NULL, NULL)
waypointlist_h(waypoint_list *n_wlp)
Definition: lua.cpp:6318
float forward_thrust
Definition: physics.h:72
#define g3_start_frame(zbuffer_flag)
Definition: 3d.h:39
GLfloat GLfloat GLfloat GLfloat v3
Definition: Glext.h:5641
void snd_set_pan(int sig, float pan)
Definition: sound.cpp:964
#define ade_set_error
Definition: lua.cpp:248
int sig
Definition: object.h:183
float vm_vec_normalize(vec3d *v)
Definition: vecmat.cpp:460
char * ShortName
Definition: lua.h:80
ade_lib l_Mission_Teams("Teams",&l_Mission, NULL, NULL)
int Player_num
#define PARTICLE_DEBUG
Definition: particle.h:48
vec3d newVec
Definition: lua.cpp:2163
#define strcpy_s(...)
Definition: safe_strings.h:67
Definition: sound.h:72
#define SEXP_VARIABLE_PLAYER_PERSISTENT
Definition: sexp.h:883
ade_lib l_HookVar("HookVariables", NULL,"hv","Hook variables repository")
int snd_play_raw(int soundnum, float pan, float vol_scale, int priority)
Definition: sound.cpp:477
ade_obj< int > l_Weaponclass("weaponclass","Weapon class handle")
void ai_remove_ship_goal(ai_info *aip, int index)
Definition: aigoals.cpp:231
bool IsSoundValid()
Definition: lua.cpp:8356
#define REAR_QUAD
Definition: objectshield.h:17
int cfseek(CFILE *fp, int offset, int where)
int gamesnd_get_by_iface_tbl_index(int index)
Definition: gamesnd.cpp:376
char * tech_desc
Definition: ship.h:1174
#define LE_VM_CHASE
#define MR_AUTOCENTER
Definition: model.h:875