/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Silvan Nellen co-programmer: ... */ #include "script_trigger.h" #include "script.h" #include "state.h" #include "debug.h" ObjectListDefinition(ScriptTrigger); CREATE_SCRIPTABLE_CLASS(ScriptTrigger, // Coordinates addMethod("setAbsCoor", Executor3(&PNode::setAbsCoor)) ->addMethod("getAbsCoorX", Executor0ret(&PNode::getAbsCoorX)) ->addMethod("getAbsCoorY", Executor0ret(&PNode::getAbsCoorY)) ->addMethod("getAbsCoorZ", Executor0ret(&PNode::getAbsCoorZ)) //Properties ->addMethod("setName", Executor1(&BaseObject::setName)) ->addMethod("setTarget", Executor1(&ScriptTrigger::setTarget)) ->addMethod("setTriggerParent", Executor1(&ScriptTrigger::setTriggerParent)) ->addMethod("setTriggerRemains", Executor1(&ScriptTrigger::setTriggerRemains)) ->addMethod("setActiveOnCreation", Executor1(&ScriptTrigger::setActiveOnCreation)) ->addMethod("setInvert", Executor1(&ScriptTrigger::setInvert)) ->addMethod("setRadius", Executor1(&ScriptTrigger::setRadius)) ->addMethod("setScript", Executor1(&ScriptTrigger::setScript)) ->addMethod("setFunction", Executor1(&ScriptTrigger::setFunction)) ->addMethod("setDebugDraw", Executor1(&ScriptTrigger::setDebugDraw)) ->addMethod("setAddToScript", Executor1(&ScriptTrigger::setAddToScript)) ); /** * Constructs a new ScriptTrigger. * @param root the xml element to load the parameters from. * */ ScriptTrigger::ScriptTrigger(const TiXmlElement* root) { this->registerObject(this, ScriptTrigger::_objectList); this->toList(OM_COMMON); radius = 10; returnCount = 1; scriptFinished = false; doDebugDraw = false; invert = false; scriptCalled = false; scriptIsOk = false; executionStopped = false; // true when something goes wrong and the trigger has to be stopped triggerRemains = true; addToScript = false; this->activeOnCreation = false; target = NULL; if(root != NULL) { loadParams(root); if(addToScript && scriptIsOk) { script->addObject( "ScriptTrigger", this->getName()); } } } /** * Deletes the ScriptTrigger. * */ ScriptTrigger::~ScriptTrigger() { } /** * Reads the values from the tml element and sets them. * @param root the xml element to load the parameters from. * */ void ScriptTrigger::loadParams(const TiXmlElement* root) { WorldEntity ::loadParams(root); LoadParam(root, "file", this, ScriptTrigger, setScript) .describe("the fileName of the script, that should be triggered by this script trigger") .defaultValues(""); LoadParam(root, "function", this, ScriptTrigger, setFunction) .describe("the function of the script, that should be triggered by this script trigger") .defaultValues(""); LoadParam(root, "abs-coor", this, ScriptTrigger, setAbsCoor) .describe("where this script trigger should be located") .defaultValues(""); LoadParam(root, "radius", this, ScriptTrigger, setRadius) .describe("the fileName of the script, that should be triggered by this script trigger") .defaultValues(0); LoadParam(root, "delay", this, ScriptTrigger, setDelay) .describe("the delay after which the funtion sould be triggered") .defaultValues(0); LoadParam(root, "worldentity", this, ScriptTrigger, setTarget) .describe("The name of the target as it is in the *.oxw file") .defaultValues(""); LoadParam(root, "triggerparent", this, ScriptTrigger, setTriggerParent) .describe("The name of the parent as it is in the *.oxw file") .defaultValues(""); LoadParam(root, "invert", this, ScriptTrigger, setInvert) .describe("") .defaultValues(false); LoadParam(root, "triggerRemains", this, ScriptTrigger, setTriggerRemains) .describe("") .defaultValues(true); LoadParam(root, "debugdraw", this, ScriptTrigger, setDebugDraw) .describe("") .defaultValues(false); LoadParam(root, "addtoscript", this, ScriptTrigger, setAddToScript) .describe("True if this scripttrigger should be aviable in the script") .defaultValues(false); } /** * Sets the target(a world entity) of the ScriptTrigger. If the distance between the target and this trigger is smaller than the radius, the script gets triggered. * @param target The worldentity that the script supervises. */ void ScriptTrigger::setTarget(const std::string& target) { WorldEntity* targetEntity = WorldEntity::objectList().getObject(target); if (targetEntity != NULL) { this->setTarget(targetEntity); } else { PRINTF(2)("ERROR SCRTIPTTRIGGER : Target %s for %s::%s does not Exist\n", target.c_str(), this->getClassCName(), this->getCName()); } } /** * Sets the parent of the trigger. * @param parent The parrent. */ void ScriptTrigger::setTriggerParent(const std::string& parent) { WorldEntity* parentEntity = WorldEntity::objectList().getObject(parent); if (parentEntity != NULL) { this->setParent(parentEntity); this->setParentMode(PNODE_MOVEMENT); } else { PRINTF(2)("ERROR SCRTIPTTRIGGER : Parent %s for %s::%s does not Exist\n", parent.c_str(), this->getClassCName(), this->getCName()); } } void ScriptTrigger::tick(float timestep) { if(scriptFinished) return; if(activeOnCreation) { executeAction(timestep); return; } if(triggerRemains && scriptCalled) { executeAction(timestep); return; } if( this->target != NULL) { if( !invert && this->distance(target) < radius) { //printf("Distance is %f \n", this->distance(target)); executeAction(timestep); scriptCalled = true; return; } else if( invert && this->distance(target) > radius) { executeAction(timestep); scriptCalled = true; return; } } } void ScriptTrigger::executeAction(float timestep) { if(executionStopped && scriptIsOk) // If the script has been loaded correctly but something is wrong with the settings of the trigger { PRINT(1)("ERROR SCRTIPTTRIGGER: Something went wrong while executing %s in %s . Execution stopped! \n", functionName.c_str(), script->getFileName().c_str()); return; } if(scriptIsOk) { //testScriptingFramework(); if(!(script->selectFunction(this->functionName,returnCount)) ) { PRINT(1)("ERROR SCRTIPTTRIGGER : Selection of %s in %s failed.\n",functionName.c_str(), script->getFileName().c_str()); executionStopped = true; //Since the triggersettings won't change on runtime, it makes no sense to call the function again. return; } if (! (script->pushParam( timestep, this->functionName)) ) { executionStopped = true; //Since the triggersettings won't change on runtime, it makes no sense to call the function again. return; } if( !(script->executeFunction()) ) { PRINT(1)("ERROR SCRTIPTTRIGGER : Execution of %s in %s failed.\n",functionName.c_str(), script->getFileName().c_str()); executionStopped = true; //Since the triggersettings won't change on runtime, it makes no sense to call the function again. return; } scriptFinished = script->getReturnedBool(); } else printf("ERROR SCRTIPTTRIGGER : Script could not be executed !\n"); } void ScriptTrigger::setScript(const std::string& file) { ScriptManager* scriptManager = State::getScriptManager(); if (scriptManager != NULL) { script = scriptManager->getScriptByFile(file); if(script != NULL) { scriptIsOk = true; } else printf("ERROR SCRTIPTTRIGGER : Could not find the wrapperobject of %s , the script won't be executed ! \n", file.c_str()); } } /* void ScriptTrigger::testScriptingFramework() { std::string file("lunartest2.lua"); //get script Script* script = State::getScriptManager()->getScriptByFile(file); printf("-------------------------- top of the stack:%i\n",lua_gettop(script->getLuaState())); //execute a function printf("----------- main -----------\n"); std::string main("main"); if( script->selectFunction(main,3)) printf("function %s selected\n",main.c_str()); script->pushParam(3.14159,main); printf("-------------------------- top of the stack:%i\n",lua_gettop(script->getLuaState())); script->executeFunction(); int ret = script->getReturnedInt(); printf("main returned %i\n",ret); if(script->getReturnedBool()) printf("main returned true\n"); else printf("main returned false\n"); float retf = script->getReturnedFloat(); printf("main returned %f\n",retf); printf("-------------------------- top of the stack:%i\n",lua_gettop(script->getLuaState())); //execute a 2nd function printf("----------- test -----------\n"); std::string test("test"); if( script->selectFunction(test,0)) printf("function %s selected\n",test.c_str()); script->executeFunction(); //if(argc>1) lua_dofile(script.getLuaState(), argv[1]); printf("-------------------------- top of the stack:%i\n",lua_gettop(script->getLuaState())); }*/