/* 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: Patrick Boenzli co-programmer: Silvan Nellen */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY #include "util/loading/factory.h" #include "util/loading/load_param.h" #include "interactive_model.h" #include "gate.h" #include "class_list.h" #include "effects/explosion.h" using namespace std; CREATE_FACTORY(Gate, CL_GATE); #include "script_class.h" CREATE_SCRIPTABLE_CLASS(Gate, CL_GATE, addMethod("hide", ExecutorLua0(&WorldEntity::hide)) ->addMethod("unhide", ExecutorLua0(&WorldEntity::unhide)) ->addMethod("destroy", ExecutorLua0(&Gate::destroy)) ->addMethod("setAbsCoor", ExecutorLua3(&PNode::setAbsCoor)) ->addMethod("getAbsCoorX", ExecutorLua0ret(&PNode::getAbsCoorX)) ->addMethod("getAbsCoorY", ExecutorLua0ret(&PNode::getAbsCoorY)) ->addMethod("getAbsCoorZ", ExecutorLua0ret(&PNode::getAbsCoorZ)) ); //! list of all different animations a std md2model supports sAnim Gate::animationList[3] = { // begin, end, fps, interruptable { 0, 7, 30, 0 }, //!< OPEN { 8, 15, 30, 0 }, //!< CLOSE { 16, 18, 30, 0 } //!< DIE }; Gate::Gate(const TiXmlElement* root) { this->setClassID(CL_GATE, "Gate"); this->scale = 1.0f; this->actionRadius = 1.0; this->destroyed = false; if( root != NULL) this->loadParams(root); this->toList(OM_COMMON); this->bLocked = false; this->bOpen = false; this->loadMD2Texture("maps/wheel.jpg"); this->loadModel("models/creatures/hypergate.md2", this->scale); this->setAnimation(GATE_CLOSE, MD2_ANIM_ONCE); } Gate::~Gate () {} /** * loads the Settings of a MD2Creature from an XML-element. * @param root the XML-element to load the MD2Creature's properties from */ void Gate::loadParams(const TiXmlElement* root) { WorldEntity::loadParams(root); LoadParam(root, "action-radius", this, Gate, setActionRadius) .describe("sets the action radius of the door") .defaultValues(3.0); LoadParam(root, "scale", this, Gate, setScale) .describe("sets the scale of the door") .defaultValues(1.0); } /** * sets the animatin of this entity */ void Gate::setAnimation(int animNum, int playbackMode) { if( likely(this->getModel(0) != NULL)) ((InteractiveModel*)this->getModel(0))->setAnimation(animationList[animNum].firstFrame, animationList[animNum].lastFrame, animationList[animNum].fps, animationList[animNum].bStoppable, playbackMode); } /** * ticks the door * @param time: time since last tick */ void Gate::tick (float time) { if( likely(this->getModel(0) != NULL)) ((InteractiveModel*)this->getModel(0))->tick(time); if( !this->bOpen) { if( this->checkOpen()) { this->open(); } } else { if( !this->checkOpen()) { this->close(); } } } /** * open the door */ void Gate::open() { if( this->bLocked || this->destroyed) return; this->setAnimation(GATE_OPEN, MD2_ANIM_ONCE); this->bOpen = true; } /** * close the door */ void Gate::close() { if( this->destroyed) return; this->setAnimation(GATE_CLOSE, MD2_ANIM_ONCE); this->bOpen = false; } void Gate::destroy() { if( this->destroyed) return; this->setAnimation(GATE_DIE, MD2_ANIM_ONCE); Explosion::explode(this, Vector(this->getScaling()/160,this->getScaling()/160,this->getScaling()/160)); this->destroyed = true; } /** * checks if the door is open */ bool Gate::checkOpen() { std::list::const_iterator it; const std::list* list = ClassList::getList(CL_PLAYABLE); WorldEntity* entity; float distance; if( list == NULL) return false; // for all players for( it = list->begin(); it != list->end(); it++) { entity = dynamic_cast(*it); distance = fabs((this->getAbsCoor() - entity->getAbsCoor()).len()); if( distance < this->actionRadius) return true; } list = ClassList::getList(CL_GENERIC_NPC); if( list == NULL) return false; for( it = list->begin(); it != list->end(); it++) { entity = dynamic_cast(*it); distance = fabs((this->getAbsCoor() - entity->getAbsCoor()).len()); if( distance < this->actionRadius) return true; } return false; }