FS2_Open
Open source remastering of the Freespace 2 engine
scripting.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdarg.h>
3 
4 #include "bmpman/bmpman.h"
6 #include "freespace2/freespace.h"
9 #include "globalincs/version.h"
10 #include "hud/hud.h"
11 #include "io/key.h"
13 #include "parse/parselo.h"
14 #include "parse/scripting.h"
15 #include "ship/ship.h"
16 #include "weapon/beam.h"
17 #include "weapon/weapon.h"
18 
19 //tehe. Declare the main event
20 script_state Script_system("FS2_Open Scripting");
21 bool Output_scripting_meta = false;
22 
23 //*************************Scripting hook globals*************************
29 
31 {
32  {"State", CHC_STATE, 0},
33  {"Campaign", CHC_CAMPAIGN, 0},
34  {"Mission", CHC_MISSION, 0},
35  {"Object Type", CHC_OBJECTTYPE, 0},
36  {"Ship", CHC_SHIP, 0},
37  {"Ship class", CHC_SHIPCLASS, 0},
38  {"Ship type", CHC_SHIPTYPE, 0},
39  {"Weapon class",CHC_WEAPONCLASS, 0},
40  {"KeyPress", CHC_KEYPRESS, 0},
41  {"Action", CHC_ACTION, 0},
42  {"Version", CHC_VERSION, 0},
43  {"Application", CHC_APPLICATION, 0}
44 };
45 
47 
49 {
50  {"On Game Init", CHA_GAMEINIT, 0},
51  {"On Splash Screen", CHA_SPLASHSCREEN, 0},
52  {"On State Start", CHA_ONSTATESTART, 0},
53  {"On Frame", CHA_ONFRAME, 0},
54  {"On Action", CHA_ONACTION, 0},
55  {"On Action Stopped", CHA_ONACTIONSTOPPED,0},
56  {"On Key Pressed", CHA_KEYPRESSED, 0},
57  {"On Key Released", CHA_KEYRELEASED, 0},
58  {"On Mouse Moved", CHA_MOUSEMOVED, 0},
59  {"On Mouse Pressed", CHA_MOUSEPRESSED, 0},
60  {"On Mouse Released", CHA_MOUSERELEASED, 0},
61  {"On State End", CHA_ONSTATEEND, 0},
62  {"On Mission Start", CHA_MISSIONSTART, 0},
63  {"On HUD Draw", CHA_HUDDRAW, 0},
64  {"On Ship Collision", CHA_COLLIDESHIP, 0},
65  {"On Weapon Collision", CHA_COLLIDEWEAPON, 0},
66  {"On Debris Collision", CHA_COLLIDEDEBRIS, 0},
67  {"On Asteroid Collision", CHA_COLLIDEASTEROID,0},
68  {"On Object Render", CHA_OBJECTRENDER, 0},
69  {"On Warp In", CHA_WARPIN, 0},
70  {"On Warp Out", CHA_WARPOUT, 0},
71  {"On Death", CHA_DEATH, 0},
72  {"On Mission End", CHA_MISSIONEND, 0},
73  {"On Weapon Delete", CHA_ONWEAPONDELETE, 0},
74  {"On Weapon Equipped", CHA_ONWPEQUIPPED, 0},
75  {"On Weapon Fired", CHA_ONWPFIRED, 0},
76  {"On Weapon Selected", CHA_ONWPSELECTED, 0},
77  {"On Weapon Deselected", CHA_ONWPDESELECTED, 0},
78  {"On Gameplay Start", CHA_GAMEPLAYSTART, 0},
79  {"On Turret Fired", CHA_ONTURRETFIRED, 0},
80  {"On Primary Fire", CHA_PRIMARYFIRE, 0},
81  {"On Secondary Fire", CHA_SECONDARYFIRE, 0},
82  {"On Ship Arrive", CHA_ONSHIPARRIVE, 0},
83  {"On Beam Collision", CHA_COLLIDEBEAM, 0},
84  {"On Message Received", CHA_MSGRECEIVED, 0},
85  {"On HUD Message Received", CHA_HUDMSGRECEIVED, 0},
86  { "On Afterburner Engage", CHA_AFTERBURNSTART, 0 },
87  { "On Afterburner Stop", CHA_AFTERBURNEND, 0 },
88  { "On Beam Fire", CHA_BEAMFIRE, 0 }
89 };
90 
93 
94 //*************************Scripting init and handling*************************
95 
96 // the prototype for this is in pstypes.h, below the script_hook struct
98 {
99  hook->o_language = 0;
100  hook->h_language = 0;
101 
102  hook->o_index = -1;
103  hook->h_index = -1;
104 }
105 
106 // ditto
108 {
109  return hook->h_index >= 0;
110 }
111 
112 void script_parse_table(const char *filename)
113 {
115 
116  try
117  {
118  read_file_text(filename, CF_TYPE_TABLES);
119  reset_parse();
120 
121  if (optional_string("#Global Hooks"))
122  {
123  //int num = 42;
124  //Script_system.SetHookVar("Version", 'i', &num);
125  if (optional_string("$Global:")) {
126  st->ParseChunk(&Script_globalhook, "Global");
127  }
128 
129  if (optional_string("$Splash:")) {
130  st->ParseChunk(&Script_splashhook, "Splash");
131  }
132 
133  if (optional_string("$GameInit:")) {
134  st->ParseChunk(&Script_gameinithook, "GameInit");
135  }
136 
137  if (optional_string("$Simulation:")) {
138  st->ParseChunk(&Script_simulationhook, "Simulation");
139  }
140 
141  if (optional_string("$HUD:")) {
142  st->ParseChunk(&Script_hudhook, "HUD");
143  }
144 
145  required_string("#End");
146  }
147  /*
148  if(optional_string("#State Hooks"))
149  {
150  while(optional_string("$State:")) {
151  char buf[NAME_LENGTH];
152  int idx;
153  stuff_string(buf, F_NAME, sizeof(buf));
154 
155  idx = gameseq_get_state_idx(buf);
156 
157  if(optional_string("$Hook:"))
158  {
159  if(idx > -1) {
160  GS_state_hooks[idx] = st->ParseChunk(buf);
161  } else {
162  st->ParseChunk(buf);
163  }
164  }
165  }
166  required_string("#End");
167  }
168  */
169  if (optional_string("#Conditional Hooks"))
170  {
171  while (st->ParseCondition(filename));
172  required_string("#End");
173  }
174 
175  // add tbl/tbm to multiplayer validation list
176  extern void fs2netd_add_table_validation(const char *tblname);
178  }
179  catch (const parse::ParseException& e)
180  {
181  mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
182  return;
183  }
184 }
185 
186 //Initializes the (global) scripting system, as well as any subsystems.
187 //script_close is handled by destructors
189 {
190  mprintf(("SCRIPTING: Beginning initialization sequence...\n"));
191 
192  // first things first: init all script hooks, since they are PODs now, not classes...
193  script_hook_init(&Script_splashhook);
194  script_hook_init(&Script_simulationhook);
195  script_hook_init(&Script_hudhook);
196  script_hook_init(&Script_globalhook);
197  script_hook_init(&Script_gameinithook);
198 
199  mprintf(("SCRIPTING: Beginning Lua initialization...\n"));
201 
203  {
204  mprintf(("SCRIPTING: Outputting scripting metadata...\n"));
205  Script_system.OutputMeta("scripting.html");
206  }
207  mprintf(("SCRIPTING: Beginning main hook parse sequence....\n"));
208  script_parse_table("scripting.tbl");
210  mprintf(("SCRIPTING: Inititialization complete.\n"));
211 }
212 /*
213 //WMC - Doesn't work as debug console interferes with any non-alphabetic chars.
214 DCF(script, "Evaluates a line of scripting")
215 {
216  if(Dc_command)
217  {
218  dc_get_arg(ARG_STRING);
219  Script_system.EvalString(Dc_arg);
220  }
221 
222  if(Dc_help)
223  {
224  dc_printf("Usage: script <script\n");
225  dc_printf("<script> -- Scripting to evaluate.\n");
226  }
227 }
228 */
229 
230 //*************************CLASS: ConditionedScript*************************
231 extern char Game_current_mission_filename[];
233 {
234  for(int i = 0; i < MAX_HOOK_CONDITIONS; i++)
235  {
236  if(Conditions[i].condition_type == CHC_NONE)
237  {
238  Conditions[i] = *sc;
239  return true;
240  }
241  }
242 
243  return false;
244 }
245 
247 {
248  if(!script_hook_valid(&sa->hook))
249  return false;
250 
251  Actions.push_back(*sa);
252 
253  return true;
254 }
255 
256 bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
257 {
258  uint i;
259 
260  //Return false if any conditions are not met
261  script_condition *scp;
262  ship_info *sip;
263  for(i = 0; i < MAX_HOOK_CONDITIONS; i++)
264  {
265  scp = &Conditions[i];
266  switch(scp->condition_type)
267  {
268  case CHC_STATE:
269  if(gameseq_get_depth() < 0)
270  return false;
272  return false;
273  break;
274  case CHC_SHIPTYPE:
275  if(objp == NULL || objp->type != OBJ_SHIP)
276  return false;
277  sip = &Ship_info[Ships[objp->instance].ship_info_index];
278  if(sip->class_type < 0)
279  return false;
280  if(stricmp(Ship_types[sip->class_type].name, scp->data.name))
281  return false;
282  case CHC_SHIPCLASS:
283  if(objp == NULL || objp->type != OBJ_SHIP)
284  return false;
285  if(stricmp(Ship_info[Ships[objp->instance].ship_info_index].name, scp->data.name))
286  return false;
287  break;
288  case CHC_SHIP:
289  if(objp == NULL || objp->type != OBJ_SHIP)
290  return false;
291  if(stricmp(Ships[objp->instance].ship_name, scp->data.name))
292  return false;
293  break;
294  case CHC_MISSION:
295  {
296  //WMC - Get mission filename with Mission_filename
297  //I don't use Game_current_mission_filename, because
298  //Mission_filename is valid in both fs2_open and FRED
299  size_t len = strlen(Mission_filename);
300  if(!len)
301  return false;
302  if(len > 4 && !stricmp(&Mission_filename[len-4], ".fs2"))
303  len -= 4;
304  if(strnicmp(scp->data.name, Mission_filename, len))
305  return false;
306  break;
307  }
308  case CHC_CAMPAIGN:
309  {
310  size_t len = strlen(Campaign.filename);
311  if(!len)
312  return false;
313  if(len > 4 && !stricmp(&Mission_filename[len-4], ".fc2"))
314  len -= 4;
315  if(strnicmp(scp->data.name, Mission_filename, len))
316  return false;
317  break;
318  }
319  case CHC_WEAPONCLASS:
320  {
321  if (action == CHA_COLLIDEWEAPON) {
322  if (stricmp(Weapon_info[more_data].name, scp->data.name) != 0)
323  return false;
324  } else if (!(action == CHA_ONWPSELECTED || action == CHA_ONWPDESELECTED || action == CHA_ONWPEQUIPPED || action == CHA_ONWPFIRED || action == CHA_ONTURRETFIRED )) {
325  if(objp == NULL || (objp->type != OBJ_WEAPON && objp->type != OBJ_BEAM))
326  return false;
327  else if (( objp->type == OBJ_WEAPON) && (stricmp(Weapon_info[Weapons[objp->instance].weapon_info_index].name, scp->data.name) != 0 ))
328  return false;
329  else if (( objp->type == OBJ_BEAM) && (stricmp(Weapon_info[Beams[objp->instance].weapon_info_index].name, scp->data.name) != 0 ))
330  return false;
331  } else if(objp == NULL || objp->type != OBJ_SHIP) {
332  return false;
333  } else {
334 
335  // Okay, if we're still here, then objp is both valid and a ship
336  ship* shipp = &Ships[objp->instance];
337  bool primary = false, secondary = false, prev_primary = false, prev_secondary = false;
338  switch (action) {
339  case CHA_ONWPSELECTED:
342 
343  if (!(primary || secondary))
344  return false;
345 
347  return false;
348 
349  break;
350  case CHA_ONWPDESELECTED:
352  prev_primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.previous_primary_bank]].name, scp->data.name) == 0;
354  prev_secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.previous_secondary_bank]].name, scp->data.name) == 0;
355 
356  if ((shipp->flags & SF_PRIMARY_LINKED) && prev_primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.previous_primary_bank]].wi_flags3 & WIF3_NOLINK))
357  return true;
358 
359  if ( !prev_secondary && ! secondary && !prev_primary && !primary )
360  return false;
361 
362  if ( (!prev_secondary && !secondary) && (prev_primary && primary) )
363  return false;
364 
365  if ( (!prev_secondary && !secondary) && (!prev_primary && primary) )
366  return false;
367 
368  if ( (!prev_primary && !primary) && (prev_secondary && secondary) )
369  return false;
370 
371  if ( (!prev_primary && !primary) && (!prev_secondary && secondary) )
372  return false;
373 
374  break;
375  case CHA_ONWPEQUIPPED: {
376  bool equipped = false;
377  for(int j = 0; j < MAX_SHIP_PRIMARY_BANKS; j++) {
378  if (!equipped && (shipp->weapons.primary_bank_weapons[j] >= 0) && (shipp->weapons.primary_bank_weapons[j] < MAX_WEAPON_TYPES) ) {
379  if ( !stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[j]].name, scp->data.name) ) {
380  equipped = true;
381  break;
382  }
383  }
384  }
385 
386  if (!equipped) {
387  for(int j = 0; j < MAX_SHIP_SECONDARY_BANKS; j++) {
388  if (!equipped && (shipp->weapons.secondary_bank_weapons[j] >= 0) && (shipp->weapons.secondary_bank_weapons[j] < MAX_WEAPON_TYPES) ) {
389  if ( !stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[j]].name, scp->data.name) ) {
390  equipped = true;
391  break;
392  }
393  }
394  }
395  }
396 
397  if (!equipped)
398  return false;
399 
400  break;
401  }
402  case CHA_ONWPFIRED: {
403  if (more_data == 1) {
405  secondary = false;
406  } else {
407  primary = false;
409  }
410 
411  if ((shipp->flags & SF_PRIMARY_LINKED) && primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags3 & WIF3_NOLINK))
412  return false;
413 
414  return more_data == 1 ? primary : secondary;
415 
416  break;
417  }
418  case CHA_ONTURRETFIRED: {
420  return false;
421  break;
422  }
423  case CHA_PRIMARYFIRE: {
425  return false;
426  break;
427  }
428  case CHA_SECONDARYFIRE: {
430  return false;
431  break;
432  }
433  case CHA_BEAMFIRE: {
434  if (!(stricmp(Weapon_info[more_data].name, scp->data.name) == 0))
435  return false;
436  break;
437  }
438 
439  }
440  } // case CHC_WEAPONCLASS
441  break;
442  }
443  case CHC_OBJECTTYPE:
444  if(objp == NULL)
445  return false;
446  if(stricmp(Object_type_names[objp->type], scp->data.name))
447  return false;
448  break;
449  case CHC_KEYPRESS:
450  {
451  extern int Current_key_down;
452  if(gameseq_get_depth() < 0)
453  return false;
454  if(Current_key_down == 0)
455  return false;
456  //WMC - could be more efficient, but whatever.
457  if(stricmp(textify_scancode(Current_key_down), scp->data.name))
458  return false;
459  break;
460  }
461  case CHC_ACTION:
462  {
463  if(gameseq_get_depth() < 0)
464  return false;
465 
466  int action_index = more_data;
467 
468  if (action_index <= 0 || stricmp(scp->data.name, Control_config[action_index].text))
469  return false;
470  break;
471  }
472  case CHC_VERSION:
473  {
474  // Goober5000: I'm going to assume scripting doesn't care about SVN revision
475  char buf[32];
477  if(stricmp(buf, scp->data.name))
478  {
479  //In case some people are lazy and say "3.7" instead of "3.7.0" or something
480  if(FS_VERSION_BUILD == 0)
481  {
482  sprintf(buf, "%i.%i", FS_VERSION_MAJOR, FS_VERSION_MINOR);
483  if(stricmp(buf, scp->data.name))
484  return false;
485  }
486  else
487  {
488  return false;
489  }
490  }
491  break;
492  }
493  case CHC_APPLICATION:
494  {
495  if(Fred_running)
496  {
497  if(stricmp("FRED2_Open", scp->data.name) && stricmp("FRED2Open", scp->data.name) && stricmp("FRED 2", scp->data.name) && stricmp("FRED", scp->data.name))
498  return false;
499  }
500  else
501  {
502  if(stricmp("FS2_Open", scp->data.name) && stricmp("FS2Open", scp->data.name) && stricmp("Freespace 2", scp->data.name) && stricmp("Freespace", scp->data.name))
503  return false;
504  }
505  }
506  default:
507  break;
508  }
509  }
510 
511  return true;
512 }
513 
514 bool ConditionedHook::Run(script_state *sys, int action, char format, void *data)
515 {
516  Assert(sys != NULL);
517 
518  //Do the actions
519  for(SCP_vector<script_action>::iterator sap = Actions.begin(); sap != Actions.end(); ++sap)
520  {
521  if(sap->action_type == action)
522  sys->RunBytecode(sap->hook, format, data);
523  }
524 
525  return true;
526 }
527 
529 {
530  Assert(sys != NULL);
531  //bool b = false;
532 
533  //Do the actions
534  for(SCP_vector<script_action>::iterator sap = Actions.begin(); sap != Actions.end(); ++sap)
535  {
536  if(sap->action_type == action)
537  {
538  if(sys->IsOverride(sap->hook))
539  return true;
540  }
541  }
542 
543  return false;
544 }
545 
546 //*************************CLASS: script_state*************************
547 //Most of the icky stuff is here. Lots of #ifdefs
548 
549 //WMC - defined in parse/lua.h
550 int ade_set_object_with_breed(lua_State *L, int obj_idx);
552 {
553  SetHookObjects(1, name, objp);
554 }
555 
557 {
558  va_list vl;
559  va_start(vl, num);
560  if(this->OpenHookVarTable())
561  {
562  int amt_ldx = lua_gettop(LuaState);
563  for(int i = 0; i < num; i++)
564  {
565  char *name = va_arg(vl, char*);
566  object *objp = va_arg(vl, object*);
567 
568  ade_set_object_with_breed(LuaState, OBJ_INDEX(objp));
569  int data_ldx = lua_gettop(LuaState);
570 
571  lua_pushstring(LuaState, name);
572  lua_pushvalue(LuaState, data_ldx);
573  lua_rawset(LuaState, amt_ldx);
574 
575  lua_pop(LuaState, 1); //data_ldx
576  }
577  this->CloseHookVarTable();
578  }
579  else
580  {
581  LuaError(LuaState, "Could not get HookVariable library to add hook variables - get a coder");
582  }
583  va_end(vl);
584 }
585 
586 //This pair of abstraction functions handles
587 //getting the table of ade member functions
588 //for the hook library.
589 //Call CloseHookVarTable() only if OpenHookVarTable()
590 //returns true. (see below)
591 static int ohvt_poststack = 0; //Items on the stack prior to OHVT
592 static int ohvt_isopen = 0; //Items OHVT puts on the stack
593 bool script_state::OpenHookVarTable()
594 {
595  if(ohvt_isopen)
596  Error(LOCATION, "OpenHookVarTable was called twice with no call to CloseHookVarTable - missing call ahoy!");
597 
598  lua_pushstring(LuaState, "hv");
599  lua_gettable(LuaState, LUA_GLOBALSINDEX);
600  int sv_ldx = lua_gettop(LuaState);
601  if(lua_isuserdata(LuaState, sv_ldx))
602  {
603  //Get ScriptVar metatable
604  lua_getmetatable(LuaState, sv_ldx);
605  int mtb_ldx = lua_gettop(LuaState);
606  if(lua_istable(LuaState, mtb_ldx))
607  {
608  //Get ScriptVar/metatable/__ademembers
609  lua_pushstring(LuaState, "__ademembers");
610  lua_rawget(LuaState, mtb_ldx);
611  int amt_ldx = lua_gettop(LuaState);
612  if(lua_istable(LuaState, amt_ldx))
613  {
614  ohvt_isopen = 3;
615  ohvt_poststack = amt_ldx;
616  return true;
617  }
618  lua_pop(LuaState, 1); //amt
619  }
620  lua_pop(LuaState, 1); //metatable
621  }
622  lua_pop(LuaState, 1); //Library
623 
624  return false;
625 }
626 
627 //Call when you are done with CloseHookVarTable,
628 //and you have removed all other objects 'above'
629 //the stack objects generated by the call to OpenHookVarTable.
630 bool script_state::CloseHookVarTable()
631 {
632  if(!ohvt_isopen)
633  {
634  Error(LOCATION, "CloseHookVarTable was called with no associated call to OpenHookVarTable");
635  }
636  int top_ldx = lua_gettop(LuaState);
637  if(top_ldx >= ohvt_poststack)
638  {
639  lua_pop(LuaState, ohvt_isopen);
640  ohvt_isopen = 0;
641  return true;
642  }
643  else
644  {
645  Error(LOCATION, "CloseHookVarTable() was called with too few objects on the stack; get a coder. (Stack: %d OHVT post: %d OHVT num: %d", top_ldx, ohvt_poststack, ohvt_isopen);
646  return false;
647  }
648 }
649 
650 void script_state::SetHookVar(char *name, char format, void *data)
651 {
652  if(format == '\0')
653  return;
654 
655  if(LuaState != NULL)
656  {
657  char fmt[2] = {format, '\0'};
658  int data_ldx = 0;
659  if(data == NULL)
660  data_ldx = lua_gettop(LuaState);
661 
662  if(data_ldx < 1 && data == NULL)
663  return;
664 
665  //Get ScriptVar table
666  if(this->OpenHookVarTable())
667  {
668  int amt_ldx = lua_gettop(LuaState);
669  lua_pushstring(LuaState, name);
670  //ERRORS? LOOK HERE!!!
671  //--------------------
672  //WMC - Now THIS has to be the nastiest hack I've made
673  //Basically, I tell it to copy over enough stack
674  //for a ade_odata object. If you pass
675  //_anything_ larger as a stack object, this will not work.
676  //You'll get memory corruption
677  if(data == NULL)
678  {
679  lua_pushvalue(LuaState, data_ldx);
680  }
681  else
682  {
683  if(format == 's')
684  ade_set_args(LuaState, fmt, data);
685  else if (format == 'i')
686  ade_set_args(LuaState, fmt, *(int*)data);
687  else
688  ade_set_args(LuaState, fmt, *(ade_odata*)data);
689  }
690  //--------------------
691  //WMC - This was a separate function
692  //lua_set_arg(LuaState, format, data);
693  //WMC - switch to the lua library
694  //lua_setglobal(LuaState, name);
695  lua_rawset(LuaState, amt_ldx);
696 
697  if(data_ldx)
698  lua_pop(LuaState, 1);
699  //Close hook var table
700  this->CloseHookVarTable();
701  }
702  else
703  {
704  LuaError(LuaState, "Could not get HookVariable library to set hook variable '%s'", name);
705  if(data_ldx)
706  lua_pop(LuaState, 1);
707  }
708  }
709 }
710 
711 //WMC - data can be NULL, if we just want to know if it exists
712 bool script_state::GetHookVar(char *name, char format, void *data)
713 {
714  bool got_global = false;
715  if(LuaState != NULL)
716  {
717  //Construct format string
718  char fmt[3] = {'|', format, '\0'};
719 
720  //WMC - Quick and clean. :)
721  //WMC - *sigh* nostalgia
722  //Get ScriptVar table
723  if(this->OpenHookVarTable())
724  {
725  int amt_ldx = lua_gettop(LuaState);
726 
727  lua_pushstring(LuaState, name);
728  lua_rawget(LuaState, amt_ldx);
729  if(!lua_isnil(LuaState, -1))
730  {
731  if(data != NULL) {
732  ade_get_args(LuaState, fmt, data);
733  }
734  got_global = true;
735  }
736  lua_pop(LuaState, 1); //Remove data
737 
738  this->CloseHookVarTable();
739  }
740  else
741  {
742  LuaError(LuaState, "Could not get HookVariable library to get hook variable '%s'", name);
743  }
744  }
745 
746  return got_global;
747 }
748 
750 {
751  this->RemHookVars(1, name);
752 }
753 
754 void script_state::RemHookVars(unsigned int num, ...)
755 {
756  if(LuaState != NULL)
757  {
758  //WMC - Quick and clean. :)
759  //WMC - *sigh* nostalgia
760  //Get ScriptVar table
761  if(this->OpenHookVarTable())
762  {
763  int amt_ldx = lua_gettop(LuaState);
764  va_list vl;
765  va_start(vl, num);
766  for(unsigned int i = 0; i < num; i++)
767  {
768  char *name = va_arg(vl, char*);
769  lua_pushstring(LuaState, name);
770  lua_pushnil(LuaState);
771  lua_rawset(LuaState, amt_ldx);
772  }
773  va_end(vl);
774 
775  this->CloseHookVarTable();
776  }
777  else
778  {
779  LuaError(LuaState, "Could not get HookVariable library to remove hook variables - get a coder");
780  }
781  }
782 }
783 
784 //WMC - data can be NULL, if we just want to know if it exists
785 bool script_state::GetGlobal(char *name, char format, void *data)
786 {
787  bool got_global = false;
788  if(LuaState != NULL)
789  {
790  //Construct format string
791  char fmt[3] = {'|', format, '\0'};
792 
793  lua_getglobal(LuaState, name);
794  //Does global exist?
795  if(!lua_isnil(LuaState, -1))
796  {
797  if(data != NULL) {
798  ade_get_args(LuaState, fmt, data);
799  }
800  got_global = true;
801  }
802  lua_pop(LuaState, 1); //Remove data
803  }
804 
805  return got_global;
806 }
807 
809 {
810  if(LuaState != NULL)
811  {
812  //WMC - Quick and clean. :)
813  lua_pushnil(LuaState);
814  lua_setglobal(LuaState, name);
815  }
816 }
817 
819 {
820  for(int i = 0; i < (int)ScriptImages.size(); i++)
821  {
822  if(!stricmp(name, ScriptImages[i].fname))
823  return ScriptImages[i].handle;
824  }
825 
826  image_desc id;
827  int idx = bm_load(name);
828 
829  if(idx > -1) {
830  id.handle = idx;
831  strcpy_s(id.fname, name);
832  ScriptImages.push_back(id);
833  }
834 
835  return idx;
836 }
837 
839 {
840  for(int i = 0; i < (int)ScriptImages.size(); i++)
841  {
842  bm_release(ScriptImages[i].handle);
843  }
844 
845  ScriptImages.clear();
846 }
847 
848 int script_state::RunBytecodeSub(int in_lang, int in_idx, char format, void *data)
849 {
850  if(in_idx >= 0)
851  {
852  // if this is the hook for the hud, and the hud is disabled or we are in freelook mode, then don't run the script
853  // (admittedly this is wrong, but I'm not sure where else to put this check and have it work properly. hopefully
854  // WMCoolmon can get some time to come back over this and fix the issues, or just make it better period. - taylor)
855  //WMC - Barf barf icky hack. Maybe later.
856  if (in_idx == Script_hudhook.h_index) {
857  if ( (Viewer_mode & VM_FREECAMERA) || hud_disabled() ) {
858  return 1;
859  }
860  }
861 
862  if(in_lang == SC_LUA)
863  {
864  lua_pushcfunction(GetLuaSession(), ade_friendly_error);
865  int err_ldx = lua_gettop(GetLuaSession());
866  if(!lua_iscfunction(GetLuaSession(), err_ldx))
867  {
868  lua_pop(GetLuaSession(), 1);
869  return 0;
870  }
871 
872  int args_start = lua_gettop(LuaState);
873 
874  lua_getref(GetLuaSession(), in_idx);
875  int hook_ldx = lua_gettop(GetLuaSession());
876 
877  if(lua_isfunction(GetLuaSession(), hook_ldx))
878  {
879  if(lua_pcall(GetLuaSession(), 0, format!='\0' ? 1 : 0, err_ldx) != 0)
880  {
881  //WMC - Pop all extra stuff from ze stack.
882  args_start = lua_gettop(GetLuaSession()) - args_start;
883  for(; args_start > 0; args_start--) lua_pop(GetLuaSession(), 1);
884 
885  lua_pop(GetLuaSession(), 1);
886  return 0;
887  }
888 
889  //WMC - Just allow one argument for now.
890  if(data != NULL)
891  {
892  char fmt[2] = {format, '\0'};
893  Ade_get_args_skip = args_start;
894  Ade_get_args_lfunction = true;
895  ade_get_args(LuaState, fmt, data);
896  Ade_get_args_skip = 0;
897  Ade_get_args_lfunction = false;
898  }
899 
900  //WMC - Pop anything leftover from the function from the stack
901  args_start = lua_gettop(GetLuaSession()) - args_start;
902  for(; args_start > 0; args_start--) lua_pop(GetLuaSession(), 1);
903  }
904  else
905  {
906  lua_pop(GetLuaSession(), 1); //"hook"
907  LuaError(GetLuaSession(),"RunBytecodeSub tried to call a non-function value!");
908  }
909  lua_pop(GetLuaSession(), 1); //err
910 
911  }
912  }
913 
914  return 1;
915 }
916 
917 //returns 0 on failure (Parse error), 1 on success
918 int script_state::RunBytecode(script_hook &hd, char format, void *data)
919 {
920  RunBytecodeSub(hd.h_language, hd.h_index, format, data);
921  return 1;
922 }
923 
924 int script_state::RunCondition(int action, char format, void *data, object *objp, int more_data)
925 {
926  int num = 0;
927  for(SCP_vector<ConditionedHook>::iterator chp = ConditionalHooks.begin(); chp != ConditionalHooks.end(); ++chp)
928  {
929  if(chp->ConditionsValid(action, objp, more_data))
930  {
931  chp->Run(this, action, format, data);
932  num++;
933  }
934  }
935  return num;
936 }
937 
938 bool script_state::IsConditionOverride(int action, object *objp)
939 {
940  //bool b = false;
941  for(SCP_vector<ConditionedHook>::iterator chp = ConditionalHooks.begin(); chp != ConditionalHooks.end(); ++chp)
942  {
943  if(chp->ConditionsValid(action, objp))
944  {
945  if(chp->IsOverride(this, action))
946  return true;
947  }
948  }
949  return false;
950 }
951 
953 {
954  EndLuaFrame();
955 }
956 
957 void script_state::Clear()
958 {
959  StateName[0] = '\0';
960  Langs = 0;
961 
962  //Don't close this yet
963  LuaState = NULL;
964  LuaLibs = NULL;
965 }
966 
968 {
969  strncpy(StateName, name, sizeof(StateName)-1);
970 
971  Langs = 0;
972 
973  LuaState = NULL;
974  LuaLibs = NULL;
975 }
976 
978 {
979  Error(LOCATION, "SESSION COPY ATTEMPTED");
980 
981  return *this;
982 }
983 
985 {
986  if(LuaState != NULL) {
987  lua_close(LuaState);
988  }
989 
990  Clear();
991 }
992 
993 void script_state::SetLuaSession(lua_State *L)
994 {
995  if(LuaState != NULL)
996  {
997  lua_close(LuaState);
998  }
999  LuaState = L;
1000  if(LuaState != NULL) {
1001  Langs |= SC_LUA;
1002  }
1003  else if(Langs & SC_LUA) {
1004  Langs &= ~SC_LUA;
1005  }
1006 }
1007 
1009 {
1010  FILE *fp = fopen(filename,"w");
1011  int i;
1012 
1013  if(fp == NULL)
1014  {
1015  return 0;
1016  }
1017 
1018  if (FS_VERSION_BUILD == 0 && FS_VERSION_REVIS == 0) //-V547
1019  {
1020  fprintf(fp, "<html>\n<head>\n\t<title>Script Output - FSO v%i.%i (%s)</title>\n</head>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, StateName);
1021  fputs("<body>", fp);
1022  fprintf(fp,"\t<h1>Script Output - FSO v%i.%i (%s)</h1>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, StateName);
1023  }
1024  else if (FS_VERSION_REVIS == 0)
1025  {
1026  fprintf(fp, "<html>\n<head>\n\t<title>Script Output - FSO v%i.%i.%i (%s)</title>\n</head>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD, StateName);
1027  fputs("<body>", fp);
1028  fprintf(fp,"\t<h1>Script Output - FSO v%i.%i.%i (%s)</h1>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD, StateName);
1029  }
1030  else
1031  {
1032  fprintf(fp, "<html>\n<head>\n\t<title>Script Output - FSO v%i.%i.%i.%i (%s)</title>\n</head>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD, FS_VERSION_REVIS, StateName);
1033  fputs("<body>", fp);
1034  fprintf(fp,"\t<h1>Script Output - FSO v%i.%i.%i.%i (%s)</h1>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD, FS_VERSION_REVIS, StateName);
1035  }
1036 
1037  //Scripting languages links
1038  fputs("<dl>", fp);
1039 
1040  //***Hooks
1041  fputs("<dt><h2>Conditional Hooks</h2></dt>", fp);
1042  fputs("<dd><dl>", fp);
1043 
1044  //Conditions
1045  fputs("<dt><b>Conditions</b></dt>", fp);
1046  for(i = 0; i < Num_script_conditions; i++)
1047  {
1048  fprintf(fp, "<dd>%s</dd>", Script_conditions[i].name);
1049  }
1050 
1051  //Actions
1052  fputs("<dt><b>Actions</b></dt>", fp);
1053  for(i = 0; i < Num_script_actions; i++)
1054  {
1055  fprintf(fp, "<dd>%s</dd>", Script_actions[i].name);
1056  }
1057 
1058  fputs("</dl></dd><br />", fp);
1059 
1060  //***Scripting langs
1061  fputs("<dt><h2>Scripting languages</h2></dt>", fp);
1062  if(Langs & SC_LUA) {
1063  fputs("<dd><a href=\"#Lua\">Lua</a></dd>", fp);
1064  }
1065  fputs("</dl>", fp);
1066 
1067  //Languages
1068  fputs("<dl>", fp);
1069  if(Langs & SC_LUA) {
1070  fputs("<dt><H2><a name=\"#Lua\">Lua</a></H2></dt>", fp);
1071 
1072  fputs("<dd>", fp);
1073  OutputLuaMeta(fp);
1074  fputs("</dd>", fp);
1075  }
1076  fputs("</dl></body></html>", fp);
1077 
1078  fclose(fp);
1079 
1080  return 1;
1081 }
1082 
1083 bool script_state::EvalString(const char *string, const char *format, void *rtn, const char *debug_str)
1084 {
1085  char lastchar = string[strlen(string)-1];
1086 
1087  if(string[0] == '{')
1088  {
1089  return false;
1090  }
1091 
1092  if(string[0] == '[' && lastchar != ']')
1093  {
1094  return false;
1095  }
1096 
1097  size_t s_bufSize = strlen(string) + 8;
1098  char *s = new char[ s_bufSize ];
1099  if(string[0] != '[')
1100  {
1101  if(rtn != NULL)
1102  {
1103  strcpy_s(s, s_bufSize, "return ");
1104  strcat_s(s, s_bufSize, string);
1105  }
1106  else
1107  {
1108  strcpy_s(s, s_bufSize, string);
1109  }
1110  }
1111  else
1112  {
1113  strcpy_s(s, s_bufSize, string+1);
1114  s[strlen(s)-1] = '\0';
1115  }
1116 
1117  //WMC - So we can pop everything we put on the stack
1118  int stack_start = lua_gettop(LuaState);
1119 
1120  //WMC - Push error handling function
1121  lua_pushcfunction(LuaState, ade_friendly_error);
1122  //Parse string
1123  int rval = luaL_loadbuffer(LuaState, s, strlen(s), debug_str);
1124  //We don't need s anymore.
1125  delete[] s;
1126  //Call function
1127  if(!rval)
1128  {
1129  if(lua_pcall(LuaState, 0, LUA_MULTRET, -2))
1130  {
1131  return false;
1132  }
1133  int stack_curr = lua_gettop(LuaState);
1134 
1135  //Only get args if we can put them someplace
1136  //WMC - We must have more than one more arg on the stack than stack_start:
1137  //(stack_start)
1138  //ade_friendly_error
1139  //(additional return values)
1140  if(rtn != NULL && stack_curr > (stack_start+1))
1141  {
1142  Ade_get_args_skip = stack_start+1;
1143  Ade_get_args_lfunction = true;
1144  ade_get_args(LuaState, format, rtn);
1145  Ade_get_args_skip = 0;
1146  Ade_get_args_lfunction = false;
1147  }
1148 
1149  //WMC - Pop anything leftover from the function from the stack
1150  stack_curr = lua_gettop(LuaState) - stack_start;
1151  for(; stack_curr > 0; stack_curr--) lua_pop(LuaState, 1);
1152  }
1153  else
1154  {
1155  //Or return error
1156  if(lua_isstring(GetLuaSession(), -1))
1158  else
1159  LuaError(GetLuaSession(), "Error parsing %s", debug_str);
1160  }
1161 
1162  return true;
1163 }
1164 
1165 void script_state::ParseChunkSub(int *out_lang, int *out_index, char* debug_str)
1166 {
1167  Assert(out_lang != NULL);
1168  Assert(out_index != NULL);
1169  Assert(debug_str != NULL);
1170 
1171  if(check_for_string("[["))
1172  {
1173  //Lua from file
1174 
1175  //Lua
1176  *out_lang = SC_LUA;
1177 
1178  char *filename = alloc_block("[[", "]]");
1179 
1180  //Load from file
1181  CFILE *cfp = cfopen(filename, "rb", CFILE_NORMAL, CF_TYPE_SCRIPTS );
1182  if(cfp == NULL)
1183  {
1184  Warning(LOCATION, "Could not load lua script file '%s'", filename);
1185  }
1186  else
1187  {
1188  int len = cfilelength(cfp);
1189 
1190  char *raw_lua = (char*)vm_malloc(len+1);
1191  raw_lua[len] = '\0';
1192 
1193  cfread(raw_lua, len, 1, cfp);
1194  cfclose(cfp);
1195 
1196  //WMC - use filename instead of debug_str so that the filename
1197  //gets passed.
1198  if(!luaL_loadbuffer(GetLuaSession(), raw_lua, len, filename))
1199  {
1200  //Stick it in the registry
1201  *out_index = luaL_ref(GetLuaSession(), LUA_REGISTRYINDEX);
1202  }
1203  else
1204  {
1205  if(lua_isstring(GetLuaSession(), -1))
1207  else
1208  LuaError(GetLuaSession(), "Error parsing %s", filename);
1209  *out_index = -1;
1210  }
1211  vm_free(raw_lua);
1212  }
1213  //dealloc
1214  //WMC - For some reason these cause crashes
1215  vm_free(filename);
1216  }
1217  else if(check_for_string("["))
1218  {
1219  //Lua string
1220 
1221  //Assume Lua
1222  *out_lang = SC_LUA;
1223 
1224  //Allocate raw script
1225  char* raw_lua = alloc_block("[", "]", 1);
1226  //WMC - minor hack to make sure that the last line gets
1227  //executed properly. In testing, I couldn't reproduce Nuke's
1228  //crash, so this is here just to be on the safe side.
1229  strcat(raw_lua, "\n");
1230 
1231  char *tmp_ptr = raw_lua;
1232 
1233  //Load it into a buffer & parse it
1234  //WMC - This is causing an access violation error. Sigh.
1235  if(!luaL_loadbuffer(GetLuaSession(), tmp_ptr, strlen(tmp_ptr), debug_str))
1236  {
1237  //Stick it in the registry
1238  *out_index = luaL_ref(GetLuaSession(), LUA_REGISTRYINDEX);
1239  }
1240  else
1241  {
1242  if(lua_isstring(GetLuaSession(), -1))
1244  else
1245  LuaError(GetLuaSession(), "Error parsing %s", debug_str);
1246  *out_index = -1;
1247  }
1248 
1249  //free the mem
1250  //WMC - This makes debug go wonky.
1251  vm_free(raw_lua);
1252  }
1253  else
1254  {
1255  char buf[PARSE_BUF_SIZE];
1256 
1257  //Assume lua
1258  *out_lang = SC_LUA;
1259 
1260  strcpy_s(buf, "return ");
1261 
1262  //Stuff it
1263  stuff_string(buf+strlen(buf), F_RAW, sizeof(buf) - strlen(buf));
1264 
1265  //Add ending
1266  strcat_s(buf, "\n");
1267 
1268  int len = strlen(buf);
1269 
1270  //Load it into a buffer & parse it
1271  if(!luaL_loadbuffer(GetLuaSession(), buf, len, debug_str))
1272  {
1273  //Stick it in the registry
1274  *out_index = luaL_ref(GetLuaSession(), LUA_REGISTRYINDEX);
1275  }
1276  else
1277  {
1278  if(lua_isstring(GetLuaSession(), -1))
1280  else
1281  LuaError(GetLuaSession(), "Error parsing %s", debug_str);
1282  *out_index = -1;
1283  }
1284  }
1285 }
1286 
1287 void script_state::ParseChunk(script_hook *dest, char *debug_str)
1288 {
1289  static int total_parse_calls = 0;
1290  char debug_buf[128];
1291 
1292  total_parse_calls++;
1293 
1294  //DANGER! This code means the debug_str must be used only before parsing
1295  if(debug_str == NULL)
1296  {
1297  debug_str = debug_buf;
1298  sprintf(debug_str, "script_parse() count %d", total_parse_calls);
1299  }
1300 
1301  ParseChunkSub(&dest->h_language, &dest->h_index, debug_str);
1302 
1303  if(optional_string("+Override:"))
1304  {
1305  size_t bufSize = strlen(debug_str) + 10;
1306  char *debug_str_over = (char*)vm_malloc(bufSize);
1307  strcpy_s(debug_str_over, bufSize, debug_str);
1308  strcat_s(debug_str_over, bufSize, " override");
1309  ParseChunkSub(&dest->o_language, &dest->o_index, debug_str_over);
1310  vm_free(debug_str_over);
1311  }
1312 }
1313 
1315 {
1316  char buf[NAME_LENGTH];
1317  for(int i = 0; i < Num_script_conditions; i++)
1318  {
1319  sprintf(buf, "$%s:", Script_conditions[i].name);
1320  if(optional_string(buf))
1321  return Script_conditions[i].def;
1322  }
1323 
1324  return CHC_NONE;
1325 }
1327 {
1328  char buf[NAME_LENGTH];
1329  for(int i = 0; i < Num_script_actions; i++)
1330  {
1331  sprintf(buf, "$%s:", Script_actions[i].name);
1332  if(optional_string(buf))
1333  return &Script_actions[i];
1334  }
1335 
1336  return NULL;
1337 }
1338 bool script_state::ParseCondition(const char *filename)
1339 {
1340  ConditionedHook *chp = NULL;
1341  int condition;
1342 
1343  for(condition = script_parse_condition(); condition != CHC_NONE; condition = script_parse_condition())
1344  {
1345  script_condition sct;
1346  sct.condition_type = condition;
1347 
1348  switch(condition)
1349  {
1350  case CHC_STATE:
1351  case CHC_SHIPCLASS:
1352  case CHC_SHIPTYPE:
1353  case CHC_SHIP:
1354  case CHC_MISSION:
1355  case CHC_CAMPAIGN:
1356  case CHC_WEAPONCLASS:
1357  case CHC_OBJECTTYPE:
1358  case CHC_VERSION:
1359  case CHC_APPLICATION:
1360  default:
1362  break;
1363  }
1364 
1365  if(chp == NULL)
1366  {
1367  ConditionalHooks.push_back(ConditionedHook());
1368  chp = &ConditionalHooks[ConditionalHooks.size()-1];
1369  }
1370 
1371  if(!chp->AddCondition(&sct))
1372  {
1373  Warning(LOCATION, "Could not add condition to conditional hook in file '%s'; you may have more than %d", filename, MAX_HOOK_CONDITIONS);
1374  }
1375  }
1376 
1377  if(chp == NULL)
1378  {
1379  return false;
1380  }
1381 
1382  flag_def_list *action;
1383  bool actions_added = false;
1384  for(action = script_parse_action(); action != NULL; action = script_parse_action())
1385  {
1386  script_action sat;
1387  sat.action_type = action->def;
1388 
1389  //WMC - build error string
1390  char *buf = (char *)vm_malloc(strlen(filename) + strlen(action->name) + 4);
1391  sprintf(buf, "%s - %s", filename, action->name);
1392 
1393  ParseChunk(&sat.hook, buf);
1394 
1395  //Free error string
1396  vm_free(buf);
1397 
1398  //Add the action
1399  if(chp->AddAction(&sat))
1400  actions_added = true;
1401  }
1402 
1403  if(!actions_added)
1404  {
1405  Warning(LOCATION, "No actions specified for conditional hook in file '%s'", filename);
1406  ConditionalHooks.pop_back();
1407  return false;
1408  }
1409 
1410  return true;
1411 }
1412 
1413 //*************************CLASS: script_state*************************
1415 {
1416  if(hd.h_index < 0)
1417  return false;
1418 
1419  bool b=false;
1420  RunBytecodeSub(hd.o_language, hd.o_index, 'b', &b);
1421 
1422  return b;
1423 }
1424 
1426 {
1427  // nothing to do here
1428  if (scripting_state_inited)
1429  return;
1430 
1431  gr_set_clear_color(0, 0, 0);
1432 
1433  scripting_state_inited = 1;
1434 }
1435 
1437 {
1438  if (!scripting_state_inited)
1439  return;
1440 
1441  game_flush();
1442 
1443  scripting_state_inited = 0;
1444 }
1445 
1446 void scripting_state_do_frame(float frametime)
1447 {
1448  // just incase something is wrong
1449  if (!scripting_state_inited)
1450  return;
1451 
1452  gr_reset_clip();
1453  gr_clear();
1454  gr_flip();
1455 
1456  // process keys
1457  int k = game_check_key() & ~KEY_DEBUGGED;
1458 
1459  switch (k)
1460  {
1461  case KEY_ESC:
1463  return;
1464  }
1465 }
void game_flush()
Definition: fredstubs.cpp:83
GLenum GLsizei GLenum format
Definition: Gl.h:1509
bool IsOverride(class script_state *sys, int action)
Definition: scripting.cpp:528
bool AddAction(script_action *sa)
Definition: scripting.cpp:246
bool ParseCondition(const char *filename="<Unknown>")
Definition: scripting.cpp:1338
#define CHA_MOUSEPRESSED
Definition: scripting.h:58
bool AddCondition(script_condition *sc)
Definition: scripting.cpp:232
script_hook Script_hudhook
Definition: scripting.cpp:26
#define CFILE_NORMAL
Definition: cfile.h:89
int i
Definition: multi_pxo.cpp:466
char name[CONDITION_LENGTH]
Definition: scripting.h:94
#define vm_free(ptr)
Definition: pstypes.h:548
#define PARSE_BUF_SIZE
Definition: parselo.h:47
#define gr_clear
Definition: 2d.h:749
weapon Weapons[MAX_WEAPONS]
Definition: weapons.cpp:78
int primary_bank_weapons[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:103
GLuint GLsizei bufSize
Definition: Glext.h:5617
#define MAX_SHIP_PRIMARY_BANKS
Definition: globals.h:62
int previous_primary_bank
Definition: ship.h:110
#define CHA_ONSTATEEND
Definition: scripting.h:63
bool GetGlobal(char *name, char format='\0', void *data=NULL)
Definition: scripting.cpp:785
char name[NAME_LENGTH]
Definition: weapon.h:322
int check_for_string(const char *pstr)
Definition: parselo.cpp:517
void gr_flip()
Definition: 2d.cpp:2113
#define CHA_ONACTIONSTOPPED
Definition: scripting.h:76
bool GetHookVar(char *name, char format='\0', void *data=NULL)
Definition: scripting.cpp:712
void fs2netd_add_table_validation(const char *tblname)
#define MAX_HOOK_CONDITIONS
Definition: scripting.h:24
#define CHC_WEAPONCLASS
Definition: scripting.h:34
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
ship_weapon weapons
Definition: ship.h:658
void RemHookVar(char *name)
Definition: scripting.cpp:749
int cfread(void *buf, int elsize, int nelem, CFILE *fp)
int Fred_running
Definition: fred.cpp:44
GLenum condition
Definition: Glext.h:8726
#define CHA_AFTERBURNEND
Definition: scripting.h:80
script_hook Script_simulationhook
Definition: scripting.cpp:25
#define CHA_ONSTATESTART
Definition: scripting.h:62
char * Object_type_names[MAX_OBJECT_TYPES]
Definition: object.cpp:76
script_hook Script_gameinithook
Definition: scripting.cpp:28
int class_type
Definition: ship.h:1167
int gameseq_get_state(void)
Definition: fredstubs.cpp:60
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
Assert(pm!=NULL)
#define gr_set_clear_color
Definition: 2d.h:850
union script_condition::@261 data
#define mprintf(args)
Definition: pstypes.h:238
void scripting_state_close()
Definition: scripting.cpp:1436
#define SC_LUA
Definition: scripting.h:11
#define FS_VERSION_MAJOR
Definition: version.h:37
Definition: cfile.h:28
int current_primary_bank
Definition: ship.h:106
#define CHA_WARPIN
Definition: scripting.h:44
#define CHA_AFTERBURNSTART
Definition: scripting.h:79
uint flags
Definition: ship.h:644
char Game_current_mission_filename[]
Definition: fredstubs.cpp:26
object * objp
Definition: lua.cpp:3105
int current_secondary_bank
Definition: ship.h:107
#define CHA_ONTURRETFIRED
Definition: scripting.h:70
#define CHA_MISSIONEND
Definition: scripting.h:56
#define CHA_KEYRELEASED
Definition: scripting.h:61
char * textify_scancode(int code)
GLuint in
Definition: Glext.h:9087
ship * shipp
Definition: lua.cpp:9162
void EndFrame()
Definition: scripting.cpp:952
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
script_state & operator=(script_state &in)
Definition: scripting.cpp:977
int bm_release(int handle, int clear_render_targets)
Frees both a bitmap's data and it's associated slot.
Definition: bmpman.cpp:2603
void ParseChunk(script_hook *dest, char *debug_str=NULL)
Definition: scripting.cpp:1287
script_state Script_system("FS2_Open Scripting")
ship_subsys * last_fired_turret
Definition: ship.h:772
int scripting_state_inited
Definition: scripting.cpp:92
config_item Control_config[]
Stores the keyboard configuration.
#define CHC_SHIP
Definition: scripting.h:29
#define CHA_WARPOUT
Definition: scripting.h:43
void script_hook_init(script_hook *hook)
Definition: scripting.cpp:97
int weapon_info_index
Definition: weapon.h:164
script_hook Script_splashhook
Definition: scripting.cpp:24
int weapon_info_index
Definition: beam.h:117
#define VM_FREECAMERA
Definition: systemvars.h:44
#define CHA_ONWPDESELECTED
Definition: scripting.h:68
char * GS_state_text[]
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define MAX_SHIP_SECONDARY_BANKS
Definition: globals.h:63
#define gr_reset_clip
Definition: 2d.h:745
int instance
Definition: object.h:150
int previous_secondary_bank
Definition: ship.h:111
void scripting_state_init()
Definition: scripting.cpp:1425
#define CHA_PRIMARYFIRE
Definition: scripting.h:71
ade_get_args(L,"|i",&depth)
#define CHA_ONFRAME
Definition: scripting.h:46
unsigned int uint
Definition: pstypes.h:64
int Ade_get_args_skip
Definition: lua.cpp:16097
#define cfopen(...)
Definition: cfile.h:134
int o_index
Definition: pstypes.h:597
#define CHA_COLLIDEDEBRIS
Definition: scripting.h:49
int ade_set_object_with_breed(lua_State *L, int obj_idx)
Definition: lua.cpp:15770
char * filename
#define strnicmp(s1, s2, n)
Definition: config.h:272
#define CHA_SPLASHSCREEN
Definition: scripting.h:53
#define CHA_KEYPRESSED
Definition: scripting.h:60
#define CHA_GAMEINIT
Definition: scripting.h:54
int o_language
Definition: pstypes.h:596
#define OBJ_WEAPON
Definition: object.h:33
void stuff_string(char *outstr, int type, int len, char *terminators)
Definition: parselo.cpp:1189
#define MAX_WEAPON_TYPES
Definition: globals.h:73
#define CF_TYPE_TABLES
Definition: cfile.h:50
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
#define CHA_GAMEPLAYSTART
Definition: scripting.h:69
void script_parse_table(const char *filename)
Definition: scripting.cpp:112
Definition: lua.h:38
#define CONDITION_LENGTH
Definition: globals.h:25
int required_string(const char *pstr)
Definition: parselo.cpp:468
#define SF_PRIMARY_LINKED
Definition: ship.h:458
#define FS_VERSION_MINOR
Definition: version.h:38
int secondary_bank_weapons[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:104
#define CHA_ONWPFIRED
Definition: scripting.h:66
int ade_friendly_error(lua_State *L)
Definition: lua.cpp:16392
GLdouble s
Definition: Glext.h:5321
int optional_string(const char *pstr)
Definition: parselo.cpp:539
Definition: ship.h:534
int wi_flags3
Definition: weapon.h:386
GLenum GLuint id
Definition: Glext.h:5156
cfp
Definition: cfile.cpp:1061
#define CHC_SHIPCLASS
Definition: scripting.h:30
char Mission_filename[80]
#define CHA_HUDMSGRECEIVED
Definition: scripting.h:78
void read_file_text(const char *filename, int mode, char *processed_text, char *raw_text)
Definition: parselo.cpp:1995
void SetHookObject(char *name, object *objp)
Definition: scripting.cpp:551
#define CHC_APPLICATION
Definition: scripting.h:39
int idx
Definition: multiui.cpp:761
cfbp fp
Definition: cfile.cpp:1065
#define CHA_COLLIDEASTEROID
Definition: scripting.h:50
beam Beams[MAX_BEAMS]
Definition: beam.cpp:60
void scripting_state_do_frame(float frametime)
Definition: scripting.cpp:1446
bool script_hook_valid(script_hook *hook)
Definition: scripting.cpp:107
#define CHC_KEYPRESS
Definition: scripting.h:36
int hud_disabled()
Checks if HUD disabled.
Definition: hud.cpp:1306
#define CHA_BEAMFIRE
Definition: scripting.h:81
#define OBJ_INDEX(objp)
Definition: object.h:235
#define CHA_COLLIDEWEAPON
Definition: scripting.h:48
int CreateLuaState()
Definition: lua.cpp:15872
#define NOX(s)
Definition: pstypes.h:473
#define OBJ_SHIP
Definition: object.h:32
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
int script_parse_condition()
Definition: scripting.cpp:1314
#define vm_malloc(size)
Definition: pstypes.h:547
void reset_parse(char *text)
Definition: parselo.cpp:3305
GLuint const GLchar * name
Definition: Glext.h:5608
int RunCondition(int condition, char format='\0', void *data=NULL, class object *objp=NULL, int more_data=0)
Definition: scripting.cpp:924
script_state(char *name)
Definition: scripting.cpp:967
#define CHA_ONWPEQUIPPED
Definition: scripting.h:65
void SetHookObjects(int num,...)
Definition: scripting.cpp:556
int RunBytecode(script_hook &hd, char format='\0', void *data=NULL)
Definition: scripting.cpp:918
char * name
Definition: pstypes.h:206
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
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
GLuint GLuint num
Definition: Glext.h:9089
int LoadBm(char *name)
Definition: scripting.cpp:818
campaign Campaign
#define CHC_SHIPTYPE
Definition: scripting.h:31
#define strcat_s(...)
Definition: safe_strings.h:68
#define FS_VERSION_REVIS
Definition: version.h:40
bool ConditionsValid(int action, class object *objp=NULL, int more_data=0)
Definition: scripting.cpp:256
#define KEY_ESC
Definition: key.h:124
#define NAME_LENGTH
Definition: globals.h:15
flag_def_list Script_conditions[]
Definition: scripting.cpp:30
bool Run(class script_state *sys, int action, char format='\0', void *data=NULL)
Definition: scripting.cpp:514
flag_def_list Script_actions[]
Definition: scripting.cpp:48
int h_language
Definition: pstypes.h:599
#define CHC_MISSION
Definition: scripting.h:28
#define CHC_NONE
Definition: scripting.h:27
int game_check_key()
Definition: fredstubs.cpp:65
lua_State * GetLuaSession()
Definition: scripting.h:174
#define CHA_MSGRECEIVED
Definition: scripting.h:77
#define CHA_HUDDRAW
Definition: scripting.h:51
int Num_script_conditions
Definition: scripting.cpp:46
void RemHookVars(unsigned int num,...)
Definition: scripting.cpp:754
char * text
describes the action in the config screen
int ship_info_index
Definition: ship.h:539
#define KEY_DEBUGGED
Definition: key.h:65
int Num_script_actions
Definition: scripting.cpp:91
#define CHA_OBJECTRENDER
Definition: scripting.h:52
#define F_NAME
Definition: parselo.h:34
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
#define LOCATION
Definition: pstypes.h:245
bool Output_scripting_meta
Definition: scripting.cpp:21
GLenum GLsizei GLenum GLenum const GLvoid * data
Definition: Gl.h:1509
int Viewer_mode
Definition: systemvars.cpp:28
#define CHA_SECONDARYFIRE
Definition: scripting.h:72
script_hook Script_globalhook
Definition: scripting.cpp:27
void SetHookVar(char *name, char format, void *data=NULL)
Definition: scripting.cpp:650
#define CHA_ONACTION
Definition: scripting.h:75
bool EvalString(const char *string, const char *format=NULL, void *rtn=NULL, const char *debug_str=NULL)
Definition: scripting.cpp:1083
int h_index
Definition: pstypes.h:600
#define CHC_STATE
Definition: scripting.h:32
#define CHA_ONWPSELECTED
Definition: scripting.h:67
script_hook hook
Definition: scripting.h:108
int parse_modular_table(const char *name_check, void(*parse_callback)(const char *filename), int path_type, int sort_type)
Definition: parselo.cpp:4205
#define CHA_MISSIONSTART
Definition: scripting.h:55
GLenum GLsizei len
Definition: Glext.h:6283
#define FS_VERSION_BUILD
Definition: version.h:39
char filename[MAX_FILENAME_LEN]
#define CHA_ONWEAPONDELETE
Definition: scripting.h:64
bool Ade_get_args_lfunction
Definition: lua.cpp:16098
#define CF_TYPE_SCRIPTS
Definition: cfile.h:79
#define CHC_OBJECTTYPE
Definition: scripting.h:35
#define CHA_MOUSERELEASED
Definition: scripting.h:59
void UnloadImages()
Definition: scripting.cpp:838
#define OBJ_BEAM
Definition: object.h:46
#define WIF3_NOLINK
Definition: weapon.h:117
#define CHA_COLLIDESHIP
Definition: scripting.h:47
void RemGlobal(char *name)
Definition: scripting.cpp:808
#define CHC_VERSION
Definition: scripting.h:38
int cfclose(CFILE *cfile)
Definition: cfile.cpp:895
int OutputMeta(char *filename)
Definition: scripting.cpp:1008
char type
Definition: object.h:146
void _cdecl void LuaError(struct lua_State *L, SCP_FORMAT_STRING const char *format=NULL,...) SCP_FORMAT_STRING_ARGS(2
bool IsConditionOverride(int action, object *objp=NULL)
Definition: scripting.cpp:938
#define CHC_CAMPAIGN
Definition: scripting.h:33
void gameseq_post_event(int event)
#define CHC_ACTION
Definition: scripting.h:37
#define stricmp(s1, s2)
Definition: config.h:271
int gameseq_get_depth()
char * alloc_block(char *startstr, char *endstr, int extra_chars)
Definition: parselo.cpp:1014
int Current_key_down
Definition: key.cpp:423
int cfilelength(CFILE *cfile)
Definition: cfile.cpp:1393
void script_init()
Definition: scripting.cpp:188
return ade_set_args(L,"f",*val)
flag_def_list * script_parse_action()
Definition: scripting.cpp:1326
SCP_vector< ship_type_info > Ship_types
Definition: ship.cpp:168
#define CHA_ONSHIPARRIVE
Definition: scripting.h:73
int last_fired_weapon_info_index
Definition: ship.h:346
#define CHA_COLLIDEBEAM
Definition: scripting.h:74
#define F_RAW
Definition: parselo.h:44
#define CHA_MOUSEMOVED
Definition: scripting.h:57
bool IsOverride(script_hook &hd)
Definition: scripting.cpp:1414
#define strcpy_s(...)
Definition: safe_strings.h:67
#define CHA_DEATH
Definition: scripting.h:45