Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/single_player_map/src/lib/script_engine/script.cc @ 9031

Last change on this file since 9031 was 9031, checked in by snellen, 18 years ago

added some methods to generic npcs scriptable

File size: 9.8 KB
RevLine 
[8711]1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11### File Specific:
12   main-programmer: Silvan Nellen
13   co-programmer: Benjamin Grauer
14*/
15
[8075]16#include "script.h"
[8202]17#include "script_class.h"
18#include "luaincl.h"
[8197]19
[8711]20#include "util/loading/resource_manager.h"
[8202]21
[8193]22#include "loading/load_param.h"
[8197]23#include "parser/tinyxml/tinyxml.h"
[8075]24
[8197]25#include "class_list.h"
[9016]26CREATE_SCRIPTABLE_CLASS(Script, CL_SCRIPT,
[9020]27                    addMethod("addObject", ExecutorLua2<Script,const std::string&, const std::string& >(&Script::addObject))
[9031]28                   // ->addMethod("selectFunction", ExecutorLua2ret<Script, bool, const std::string&, int >(&Script::selectFunction))
[9020]29                    ->addMethod("executeFunction", ExecutorLua0ret<Script,bool >(&Script::executeFunction))
30                     );
[8075]31
[8193]32Script::Script(const TiXmlElement* root)
[8075]33{
[8193]34  this->setClassID(CL_SCRIPT, "Script");
[8231]35
[8075]36  returnCount = argumentCount = 0;
37
38  luaState = lua_open();
39
40  luaopen_base(luaState);
41  luaopen_table(luaState);
42  luaopen_io(luaState);
43  luaopen_string(luaState);
44  luaopen_math(luaState);
45  luaopen_debug(luaState);
[8193]46  if (root != NULL)
47    this->loadParams(root);
[8075]48}
49
50
51Script::~Script()
52{
53  lua_setgcthreshold(luaState, 0);  // collected garbage
54  lua_close(luaState);
55}
56
57
[8193]58void Script::loadParams(const TiXmlElement* root)
59{
[8408]60  //printf("Loading params for %p \n",this);
[8199]61  BaseObject::loadParams(root);
[8231]62
[8197]63  LOAD_PARAM_START_CYCLE(root, object);
[8193]64  {
[8197]65    LoadParam_CYCLE(object, "object", this, Script, addObject)
[8193]66        .describe("The name of an object that is needed by a script");
67  }
[8197]68  LOAD_PARAM_END_CYCLE(object);
[8193]69
70
71  LoadParam(root, "file", this, Script, loadFileNoRet)
72      .describe("the fileName of the script, that should be loaded into this world")
73      .defaultValues("");
74}
75
76
77
78bool Script::loadFile(const std::string& filename)
[8075]79 {
[9003]80   this->setName(filename);
[8711]81   std::string filedest(ResourceManager::getInstance()->getDataDir());
82   filedest += "scripts/" + filename;
83   
[9031]84   this->addThisScript();
85   this->registerStandartClasses();
86   
[8075]87   if(currentFile.length() != 0)
[8131]88   {
[8075]89     printf("Could not load %s because an other file is already loaded: %s\n",filename.c_str(), currentFile.c_str());
[8085]90     return false;
91    }
[8075]92
[8711]93   int error = luaL_loadfile (luaState, filedest.c_str());
[8075]94
95   if(error == 0)
96   {
[8711]97     
[8075]98     error = lua_pcall(luaState, 0, 0, 0);
99
100     if(error == 0)
101     {
102      currentFile = filename;
103      return true;
104     }
105     else
106     {
[8408]107       printf("ERROR while loading file %s: \n",filename.c_str());
108       reportError(error);
[8075]109     }
110
111   }
112   else
113   {
[8408]114     printf("ERROR while loading file %s: \n",filename.c_str());
[8075]115     reportError(error);
116   }
117
118   return false;
119 }
120
[8231]121
[8193]122 void Script::addObject(const std::string& className, const std::string& objectName)
123 {
[9031]124   //printf("Script %s: I am about to add %s of class %s\n",this->getName(),objectName.c_str(),className.c_str());
[8408]125
[8202]126   BaseObject* scriptClass = ClassList::getObject(className, CL_SCRIPT_CLASS);
[8783]127  // printf("The script class for %s is at %p \n",className.c_str(),scriptClass);
[8207]128   WorldObject tmpObj;
[8197]129   if (scriptClass != NULL)
130   {
[8231]131     tmpObj.type = className;
[8206]132     if( !classIsRegistered(className) )
[8207]133     {
[8202]134     static_cast<ScriptClass*>(scriptClass)->registerClass(this);
[8207]135     }
[8231]136
[8197]137     BaseObject* object = ClassList::getObject(objectName, className);
[8783]138    // printf("%s is at %p \n",objectName.c_str(),object);
[8206]139     if (object != NULL && !objectIsAdded(objectName))
[8197]140     {
[8202]141        static_cast<ScriptClass*>(scriptClass)->insertObject(this, object, false);
[8207]142        tmpObj.name = objectName;
143        registeredObjects.push_back(tmpObj);
[8197]144     }
145   }
[8193]146 }
147
[8231]148
149
150
[8075]151 bool Script::executeFile()
152 {
[8231]153   printf("WARNING: script.executeFile is not implemented yet");
154   /*if(currentFile.length() != 0)
[8075]155   {
156    int error = lua_pcall(luaState, 0, 0, 0);
157    if( error == 0)
158      return true;
159     else
160      {
161       reportError(error);
162       return false;
163      }
[8231]164 }*/
[8075]165   return false;
166 }
167
168 bool Script::selectFunction(std::string& functionName, int retCount)
169 {
[8085]170   if(returnCount == 0 && currentFunction.length() == 0) //no return values left on the stack and no other function selected
[8075]171   {
172   lua_pushlstring(luaState, functionName.c_str(), functionName.size() );
173   lua_gettable(luaState, LUA_GLOBALSINDEX);
174
175   if(lua_isfunction( luaState , -1))
176   {
177     returnCount = retCount;
178     argumentCount = 0;
179     currentFunction = functionName;
180     return true;
181   }
182   else
183    return false;
184   }
185   else
[8085]186     printf("There is an other function active ( %s ) or there are unremoved return values on the stack. Please remove them first.\n",currentFunction.c_str());
187   return false;
[8075]188 }
189
190 //return number of returned values
191 bool Script::executeFunction()
192 {
193   if(currentFunction.length() != 0 )
194   {
195    int error = lua_pcall(luaState, argumentCount, returnCount,0);
196    if(error != 0)
197    {
[8408]198     printf("ERROR while executing function %s: \n",currentFunction.c_str());
[8075]199     reportError(error);
[8408]200     //clean up
201     currentFunction.assign("");
202     argumentCount = returnCount = 0;
[8075]203     return false;
204    }
205    else
206    {
207      currentFunction.assign("");//a function gets unusable after beeing called for the first time
208      argumentCount = 0;
209      return true;
210    }
211   }
212   else
213     printf("Error: no function selected.\n");
[8408]214
215   return false;
[8075]216 }
217
218
219 //overload this function to add different types
220 bool Script::pushParam(int param, std::string& toFunction)
221 {
[8711]222   if(currentFunction == toFunction)
[8075]223   {
224     lua_pushnumber(luaState, (lua_Number) param);
225     argumentCount++;
[8711]226     return true;
[8075]227   }
228   else
229   {
230    printf("Couldn't add parameter because the wrong function is selected: %s instead of %s\n", currentFunction.c_str(), toFunction.c_str());
231    return false;
232   }
233
234 }
235
236
237 bool Script::pushParam(float param, std::string& toFunction)
238 {
239   if(currentFunction.compare(toFunction) == 0)
240   {
241     lua_pushnumber(luaState,(lua_Number) param);
242     argumentCount++;
243     return true;
244   }
245   else
246   {
247     printf("Couldn't add parameter because the wrong function is selected: %s instead of %s\n", currentFunction.c_str(), toFunction.c_str());
248     return false;
249   }
250
251 }
252
253 bool Script::pushParam(double param, std::string& toFunction)
254 {
255   if(currentFunction.compare(toFunction) == 0)
256   {
257     lua_pushnumber(luaState,(lua_Number) param);
258     argumentCount++;
259     return true;
260   }
261   else
262   {
263     printf("Couldn't add parameter because the wrong function is selected: %s instead of %s\n", currentFunction.c_str(), toFunction.c_str());
264     return false;
265   }
266
267 }
268
269 int Script::getReturnedInt()
270 {
[8408]271   int returnValue = 0;
[8075]272   if(returnCount > 0)
273   {
[8408]274     if(lua_isnumber(luaState, -1*returnCount))
[8075]275     {
[8408]276       returnValue = (int)lua_tonumber(luaState, -1*returnCount);
277       lua_remove(luaState,-1*returnCount);
[8075]278       returnCount--;
[8408]279       
[8075]280     }
281   }
282   return returnValue;
283 }
284
285
286 bool Script::getReturnedBool()
287 {
[8408]288   bool returnValue = false;
[8075]289   if(returnCount > 0)
290   {
[8408]291     if(lua_isboolean(luaState, -1*returnCount))
[8075]292     {
[8408]293       returnValue = (bool)lua_toboolean(luaState, -1*returnCount);
294       lua_remove(luaState,-1*returnCount);
[8075]295       returnCount--;
296     }
[8711]297     else
298       printf("ERROR: Form %s : trying to retreive non bolean value",this->currentFile.c_str());
[8075]299   }
300   return returnValue;
301 }
302
303float Script::getReturnedFloat()
304 {
[8408]305   float returnValue = 0.0f;
[8075]306   if(returnCount > 0)
307   {
[8408]308     if(lua_isnumber(luaState, -1*returnCount))
[8075]309     {
[8408]310       returnValue = (float)lua_tonumber(luaState, -1*returnCount);
311       lua_remove(luaState,-1*returnCount);
[8075]312       returnCount--;
313     }
314   }
315   return returnValue;
316 }
317
[8131]318 void Script::getReturnedString(std::string& string)
319 {
[8408]320   const char* returnValue = "";
[8131]321   if(returnCount > 0)
322   {
[8408]323     if(lua_isstring(luaState, -1*returnCount))
[8131]324     {
[8408]325       returnValue = lua_tostring(luaState, -1*returnCount);
326       lua_remove(luaState,-1*returnCount);
[8131]327       returnCount--;
328     }
329   }
330  string.assign(returnValue);
331 }
332
[9003]333
334void Script::addThisScript()
335{
336  BaseObject* scriptClass = ClassList::getObject("Script", CL_SCRIPT_CLASS);
337   if (scriptClass != NULL)
338   {
339     static_cast<ScriptClass*>(scriptClass)->registerClass(this);
340     static_cast<ScriptClass*>(scriptClass)->insertObject(this, this,"thisscript", false);
341   }
342}
343
[8075]344 int Script::reportError(int error)
345 {
[8085]346 if(error != 0)
347 {
348  const char *msg = lua_tostring(luaState, -1);
349  if (msg == NULL) msg = "(error with no message)";
350  fprintf(stderr, "ERROR: %s\n", msg);
351  lua_pop(luaState, 1);
[8408]352 }
[8085]353  return error;
[8075]354 }
355
[8711]356 bool Script::registerStandartClasses()
357 {
358   bool success = false;
359   
360   //success = this->registerClass(std::string("Vector"));
[9016]361    success = this->registerClass("ScriptTrigger");
[9031]362
[8711]363   return success;
364 }
365 
366 
367 bool Script::registerClass( const std::string& className)
368 {
369   BaseObject* scriptClass = ClassList::getObject(className, CL_SCRIPT_CLASS);
370   //printf("The script class for %s is at %p \n",className.c_str(),scriptClass);
371   WorldObject tmpObj;
372   if (scriptClass != NULL)
373   {
374     tmpObj.type = className;
375     if( !classIsRegistered(className) )
376     {
377       static_cast<ScriptClass*>(scriptClass)->registerClass(this);
378       tmpObj.name = "";
379       registeredObjects.push_back(tmpObj);
380       return true;
381     }
382   }
383   return false;
384 
385 }
[8231]386
[8206]387 bool Script::classIsRegistered(const std::string& type)
388 {
[8207]389   for(std::list<WorldObject>::const_iterator it = registeredObjects.begin(); it != registeredObjects.end(); it++ )
[8206]390   {
391     if( (*it).type == type)
392     {
393       return true;
394     }
395   }
396   return false;
397 }
[8231]398
399
400
[8206]401 bool Script::objectIsAdded(const std::string& name)
402 {
[8207]403   for(std::list<WorldObject>::const_iterator it = registeredObjects.begin(); it != registeredObjects.end(); it++ )
[8206]404   {
405     if( (*it).name == name)
406     {
407       return true;
408     }
409   }
410   return false;
[8231]411
412
[8206]413 }
Note: See TracBrowser for help on using the repository browser.