Pol  Revision:cb584c9
syshook.cpp
Go to the documentation of this file.
1 
8 #include "syshook.h"
9 
10 #include <stddef.h>
11 #include <string>
12 
13 #include "../bscript/bobject.h"
14 #include "../clib/cfgelem.h"
15 #include "../clib/cfgfile.h"
16 #include "../clib/fileutil.h"
17 #include "../clib/logfacility.h"
18 #include "../plib/pkg.h"
19 #include "../plib/systemstate.h"
20 #include "globals/uvars.h"
21 #include "scrdef.h"
22 #include "syshookscript.h"
23 
24 namespace Pol
25 {
26 namespace Core
27 {
28 using namespace Bscript;
29 
31  : export_script( shs ), PC( in_PC )
32 {
33 }
35 {
36  export_script = nullptr;
37  PC = 0;
38 }
39 const std::string& ExportedFunction::scriptname() const
40 {
41  return export_script->scriptname();
42 }
43 
45 {
46  return export_script->call( PC, p0 );
47 }
49 {
50  return export_script->call( PC, p0, p1 );
51 }
53 {
54  return export_script->call( PC, p0, p1, p2 );
55 }
57 {
58  return export_script->call( PC, p0, p1, p2, p3 );
59 }
60 
62 {
63  return export_script->call_string( PC, p0, p1 );
64 }
66 {
67  return export_script->call_string( PC, p0, p1, p2 );
68 }
69 
71 {
72  return export_script->call_long( PC, p0 );
73 }
74 
76 {
77  return export_script->call_long( PC, p0, p1 );
78 }
79 
81 {
82  return export_script->call_object( PC, p0, p1 );
83 }
84 
86 {
87  return export_script->call_object( PC, p0, p1, p2 );
88 }
89 
91  : check_skill_hook( nullptr ),
92  open_spellbook_hook( nullptr ),
93  get_book_page_hook( nullptr ),
94  combat_advancement_hook( nullptr ),
95  parry_advancement_hook( nullptr ),
96  attack_hook( nullptr ),
97  pushthrough_hook( nullptr ),
98  speechmul_hook( nullptr ),
99  hitmiss_hook( nullptr ),
100  on_cast_hook( nullptr ),
101  can_decay( nullptr ),
102  ouch_hook( nullptr ),
103  can_die( nullptr ),
104  un_hide( nullptr ),
105  close_customhouse_hook( nullptr ),
106  warmode_change( nullptr ),
107  can_trade( nullptr ),
108  consume_ammunition_hook( nullptr )
109 {
110 }
111 
112 void hook( ExportScript* shs, const std::string& hookname, const std::string& exfuncname )
113 {
114  ExportedFunction** pphook = nullptr;
115  unsigned nargs;
116  if ( hookname == "CheckSkill" )
117  {
118  nargs = 4;
120  }
121  else if ( hookname == "OpenSpellbook" )
122  {
123  nargs = 1;
125  }
126  else if ( hookname == "GetBookPage" )
127  {
128  nargs = 2;
130  }
131  else if ( hookname == "CombatAdvancement" )
132  {
133  nargs = 3;
135  }
136  else if ( hookname == "ParryAdvancement" )
137  {
138  nargs = 4;
140  }
141  else if ( hookname == "Attack" )
142  {
143  nargs = 2;
145  }
146  else if ( hookname == "Pushthrough" )
147  {
148  nargs = 2;
150  }
151  else if ( hookname == "SpeechMul" )
152  {
153  nargs = 3;
155  }
156  else if ( hookname == "HitMiss" )
157  {
158  nargs = 2;
160  }
161  else if ( hookname == "OnCast" )
162  {
163  nargs = 2;
165  }
166  else if ( hookname == "CanDecay" )
167  {
168  nargs = 1;
169  pphook = &gamestate.system_hooks.can_decay;
170  }
171  else if ( hookname == "Ouch" )
172  {
173  nargs = 4;
174  pphook = &gamestate.system_hooks.ouch_hook;
175  }
176  else if ( hookname == "CanDie" )
177  {
178  nargs = 1;
179  pphook = &gamestate.system_hooks.can_die;
180  }
181  else if ( hookname == "UnHide" )
182  {
183  nargs = 1;
184  pphook = &gamestate.system_hooks.un_hide;
185  }
186  else if ( hookname == "CloseCustomHouse" )
187  {
188  nargs = 2;
190  }
191  else if ( hookname == "WarmodeChange" )
192  {
193  nargs = 2;
195  }
196  else if ( hookname == "CanTrade" )
197  {
198  nargs = 3;
199  pphook = &gamestate.system_hooks.can_trade;
200  }
201  else if ( hookname == "ConsumeAmmunition" )
202  {
203  nargs = 2;
205  }
206  else
207  {
208  INFO_PRINT << "Unknown SystemHook " << hookname << "\n";
209  return;
210  }
211 
212  if ( *pphook != nullptr )
213  {
214  INFO_PRINT << "SystemHook " << hookname << " multiply defined\n"
215  << " Already found in: " << gamestate.system_hooks.check_skill_hook->scriptname()
216  << "\n"
217  << " Also defined in: " << shs->scriptname() << "\n";
218  return;
219  }
220 
221  unsigned PC;
222  if ( !shs->FindExportedFunction( exfuncname, nargs, PC ) )
223  {
224  INFO_PRINT << "Exported Function " << exfuncname << " not found in " << shs->scriptname()
225  << "\n";
226  return;
227  }
228 
229  *pphook = new ExportedFunction( shs, PC );
230 }
231 
233 {
234  /*
235  system_hooks.clear();
236  while (!export_scripts.empty())
237  {
238  delete export_scripts.back();
239  export_scripts.pop_back();
240  }
241  */
242  for ( Plib::Packages::const_iterator citr = Plib::systemstate.packages.begin();
243  citr != Plib::systemstate.packages.end(); ++citr )
244  {
245  Plib::Package* pkg = ( *citr );
246  // string fname = pkg->dir() + "syshook.cfg";
247  std::string fname = Plib::GetPackageCfgPath( pkg, "syshook.cfg" );
248  if ( Clib::FileExists( fname.c_str() ) )
249  {
250  Clib::ConfigFile cf( fname.c_str(), "SystemHookScript" );
251  Clib::ConfigElem elem;
252  while ( cf.read( elem ) )
253  {
254  ExportScript* shs = new ExportScript( pkg, elem.rest() );
255  if ( shs->Initialize() )
256  {
257  gamestate.export_scripts.push_back( shs );
258  std::string hookname, exfuncname;
259  while ( elem.remove_first_prop( &hookname, &exfuncname ) )
260  {
261  if ( exfuncname.empty() )
262  exfuncname = hookname;
263  hook( shs, hookname, exfuncname );
264  }
265  }
266  else
267  {
268  delete shs;
269  }
270  }
271  }
272  }
273 }
274 
276 {
277  for ( unsigned i = 0; i < gamestate.export_scripts.size(); ++i )
278  {
280  delete ps;
281  }
282  gamestate.export_scripts.clear();
283  if ( attack_hook != nullptr )
284  delete attack_hook;
285  if ( check_skill_hook != nullptr )
286  delete check_skill_hook;
287  if ( combat_advancement_hook != nullptr )
289  if ( get_book_page_hook != nullptr )
290  delete get_book_page_hook;
291  if ( hitmiss_hook != nullptr )
292  delete hitmiss_hook;
293  if ( open_spellbook_hook != nullptr )
294  delete open_spellbook_hook;
295  if ( parry_advancement_hook != nullptr )
296  delete parry_advancement_hook;
297  if ( pushthrough_hook != nullptr )
298  delete pushthrough_hook;
299  if ( speechmul_hook != nullptr )
300  delete speechmul_hook;
301  if ( on_cast_hook != nullptr )
302  delete on_cast_hook;
303  if ( can_decay != nullptr )
304  delete can_decay;
305  if ( ouch_hook != nullptr )
306  delete ouch_hook;
307  if ( can_die != nullptr )
308  delete can_die;
309  if ( un_hide != nullptr )
310  delete un_hide;
311  if ( close_customhouse_hook != nullptr )
312  delete close_customhouse_hook;
313  if ( warmode_change != nullptr )
314  delete warmode_change;
315  if ( can_trade != nullptr )
316  delete can_trade;
317  if ( consume_ammunition_hook != nullptr )
319 }
320 
322 {
323  for ( unsigned i = 0; i < gamestate.export_scripts.size(); ++i )
324  {
326  if ( ps->scriptname() == sd.name() )
327  return ps;
328  }
329 
330  ExportScript* ps = new ExportScript( sd );
331  if ( ps->Initialize() )
332  {
333  gamestate.export_scripts.push_back( ps );
334  return ps;
335  }
336  else
337  {
338  delete ps;
339  return nullptr;
340  }
341 }
342 
343 // descriptor is script:function (or :pkg:script:function, or ::script:function?)
345  const std::string& descriptor, unsigned nargs,
346  bool complain_if_missing )
347 {
348  // first, split up script and functionname
349  auto colon_pos = descriptor.find_last_of( ':' );
350  if ( colon_pos == std::string::npos )
351  elem.throw_error( "Expected ':' in exported function descriptor (" + descriptor + ")" );
352 
353  std::string scriptname = descriptor.substr( 0, colon_pos );
354  std::string functionname = descriptor.substr( colon_pos + 1, std::string::npos );
355 
356  ScriptDef sd( scriptname, pkg, "" );
357 
358  ExportScript* export_script = FindExportScript( sd );
359  if ( !export_script )
360  {
361  if ( complain_if_missing )
362  elem.throw_error( "Export Script " + sd.name() + " not found" );
363  else
364  return nullptr;
365  }
366 
367  unsigned PC;
368  if ( !export_script->FindExportedFunction( functionname, nargs, PC ) )
369  {
370  if ( complain_if_missing )
371  elem.throw_error( "Exported Function " + functionname + " not found in " +
372  export_script->scriptname() );
373  else
374  return nullptr;
375  }
376 
377  return new ExportedFunction( export_script, PC );
378 }
379 } // namespace Core
380 } // namespace Pol
std::string call_string(unsigned PC, Bscript::BObjectImp *p0, Bscript::BObjectImp *p1)
ExportedFunction * speechmul_hook
Definition: syshook.h:74
const std::string & scriptname() const
SystemState systemstate
Definition: systemstate.cpp:12
bool call(Bscript::BObjectImp *p0)
Definition: syshook.cpp:44
ExportedFunction * close_customhouse_hook
Definition: syshook.h:81
ExportedFunction * open_spellbook_hook
Definition: syshook.h:68
Bscript::BObject call_object(unsigned PC, Bscript::BObjectImp *p0, Bscript::BObjectImp *p1)
ExportedFunction * combat_advancement_hook
Definition: syshook.h:70
SystemHooks system_hooks
Definition: uvars.h:190
ExportedFunction * warmode_change
Definition: syshook.h:82
bool call(unsigned PC, Bscript::BObjectImp *p0)
ExportedFunction * attack_hook
Definition: syshook.h:72
const std::string & scriptname() const
Definition: syshook.cpp:39
ExportedFunction * on_cast_hook
Definition: syshook.h:76
ExportedFunction(ExportScript *, unsigned PC)
Definition: syshook.cpp:30
const std::string & name() const
Definition: scrdef.h:45
POL_NORETURN void throw_error(const std::string &errmsg) const
Definition: cfgfile.cpp:285
ExportScript * export_script
Definition: syshook.h:57
ExportedFunction * can_decay
Definition: syshook.h:77
std::string call_string(Bscript::BObjectImp *p0, Bscript::BObjectImp *p1)
Definition: syshook.cpp:61
bool FindExportedFunction(const std::string &name, unsigned args, unsigned &PC) const
void hook(ExportScript *shs, const std::string &hookname, const std::string &exfuncname)
Definition: syshook.cpp:112
ExportScript * FindExportScript(const ScriptDef &sd)
Definition: syshook.cpp:321
ExportedFunction * ouch_hook
Definition: syshook.h:78
GameState gamestate
Definition: uvars.cpp:74
ExportedFunction * pushthrough_hook
Definition: syshook.h:73
ExportedFunction * can_trade
Definition: syshook.h:83
Bscript::BObject call_object(Bscript::BObjectImp *p0, Bscript::BObjectImp *p1)
Definition: syshook.cpp:80
ExportedFunction * FindExportedFunction(Clib::ConfigElem &elem, const Plib::Package *pkg, const std::string &descriptor, unsigned nargs, bool complain_if_missing)
Definition: syshook.cpp:344
std::string GetPackageCfgPath(const Package *pkg, const std::string &filename)
Definition: pkg.cpp:491
ExportedFunction * can_die
Definition: syshook.h:79
std::vector< ExportScript * > export_scripts
Definition: uvars.h:189
int call_long(Bscript::BObjectImp *p0)
Definition: syshook.cpp:70
ExportedFunction * un_hide
Definition: syshook.h:80
ExportedFunction * get_book_page_hook
Definition: syshook.h:69
bool FileExists(const char *filename)
Definition: fileutil.cpp:118
#define INFO_PRINT
Definition: logfacility.h:223
ExportedFunction * consume_ammunition_hook
Definition: syshook.h:84
Definition: berror.cpp:12
void load_system_hooks()
Definition: syshook.cpp:232
ExportedFunction * parry_advancement_hook
Definition: syshook.h:71
ExportedFunction * check_skill_hook
Definition: syshook.h:67
int call_long(unsigned PC, Bscript::BObjectImp *p0)
ExportedFunction * hitmiss_hook
Definition: syshook.h:75