/* * ORXONOX - the hottest 3D action shooter ever to exist * > www.orxonox.net < * * * License notice: * * 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 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Author: * Fabian 'x3n' Landau * Co-authors: * Dominik Solenicki * */ #include "DivisionController.h" #include "infos/PlayerInfo.h" namespace orxonox { RegisterClass(DivisionController); //Leaders share the fact that they have Wingmans DivisionController::DivisionController(Context* context) : LeaderController(context) { RegisterObject(DivisionController); this->setFormationMode(FormationMode::DIAMOND); this->target_ = 0; this->myFollower_ = 0; this->myWingman_ = 0; this->actionTimer_.setTimer(ACTION_INTERVAL, true, createExecutor(createFunctor(&DivisionController::action, this))); this->rank_ = Rank::DIVISIONLEADER; } DivisionController::~DivisionController() { } void DivisionController::XMLPort(Element& xmlelement, XMLPort::Mode mode) { SUPER(DivisionController, XMLPort, xmlelement, mode); //XMLPortParam(DivisionController, "target_", setTarget, getTarget, xmlelement, mode).defaultValues(100.0f); } void DivisionController::tick(float dt) { if (!this->isActive()) return; SUPER(DivisionController, tick, dt); } void DivisionController::action() { /* if (this->target_) { if (CommonController::distance (this->getControllableEntity(), newTarget) < CommonController::distance (this->getControllableEntity(), target_)) { Actionpoint* ap = new Actionpoint(this->getContext()); ap->setPosition (0, 0, 0); ap->setActionXML ("FIGHT"); //ap->setEnemyXML(CommonController::getName(newTarget)); this->addActionpoint (ap); } }*/ //----Whatever ship is doing, if there are targets close to it and its own target is far away, fight them---- //analog to attack move if (this->action_ != Action::FIGHT && this->action_ != Action::FIGHTALL) { if ( (this->target_ && CommonController::distance (this->getControllableEntity(), this->target_) > this->attackRange_) || !this->target_ ) { Pawn* newTarget = this->closestTarget(); if ( newTarget && CommonController::distance (this->getControllableEntity(), static_cast(newTarget)) <= this->attackRange_ ) { // this->backupAction(); // this->setAction (Action::FIGHT, newTarget); Point p = { Action::FIGHT, CommonController::getName(newTarget), Vector3::ZERO }; this->parsedActionpoints_.push_back(p); this->executeActionpoint(); } } } //action is NONE whenever ships finishes current action, //if it was fighting before because enemies were close, resume what it was doing //otherwise try to execute next action if (this->action_ == Action::NONE) { this->executeActionpoint(); } //this->action_ is what I am actually executing, this->target_ is what I am //actually attacking, etc. //after action is finished, .pop_back() is to be called. if (this->action_ == Action::FIGHT || this->action_ == Action::FIGHTALL) { if (!this->hasTarget()) { //----find a target---- ControllableEntity* newTarget = this->closestTarget(); if (this->action_ == Action::FIGHT) { if (newTarget && CommonController::distance (this->getControllableEntity(), newTarget) < this->attackRange_) { this->setAction (Action::FIGHT, newTarget); } else { this->nextActionpoint(); return; } } else if (this->action_ == Action::FIGHTALL) { if (newTarget && newTarget->getController()) { this->setAction (Action::FIGHTALL, newTarget); } else { this->nextActionpoint(); return; } } } else if (this->hasTarget()) { //----fly in formation if far enough---- Vector3 diffVector = this->positionOfTarget_ - this->getControllableEntity()->getWorldPosition(); if (diffVector.length() > this->attackRange_) { if (this->action_ == Action::FIGHT) { this->nextActionpoint(); return; } else { this->setTargetPositionOfWingman(); this->setTargetPositionOfFollower(); } } else { //----wingmans shall support the fire of their leaders---- if (this->myWingman_) { this->myWingman_->setAction (this->action_, this->target_); } if (this->myFollower_) { this->myFollower_->setAction (this->action_); } } } if (this->hasTarget()) { //----choose where to go---- this->maneuver(); //----fire if you can---- this->bShooting_ = this->canFire(); } } else if (this->action_ == Action::FLY) { if (this->squaredDistanceToTarget() <= this->squaredaccuracy_) { orxout(internal_error) << "arrived"; this->nextActionpoint(); return; } this->setTargetPositionOfWingman(); this->setTargetPositionOfFollower(); } else if (this->action_ == Action::PROTECT) { if (!this->getProtect()) { this->nextActionpoint(); return; } /* if (this->myWingman_) this->myWingman_->setAction (Action::PROTECT, this->getProtect()); if (this->myFollower_) this->myFollower_->setAction (Action::PROTECT, this->getProtect()); */ Vector3* targetRelativePosition; targetRelativePosition = new Vector3 (0, 0, 500); Vector3 targetAbsolutePosition = ((this->getProtect()->getWorldPosition()) + (this->getProtect()->getWorldOrientation()* (*targetRelativePosition))); this->setTargetPosition(targetAbsolutePosition); this->setTargetPositionOfWingman(); this->setTargetPositionOfFollower(); } else if (this->action_ == Action::ATTACK) { if (!this->hasTarget()) { this->nextActionpoint(); return; } //----fly in formation if far enough---- Vector3 diffVector = this->positionOfTarget_ - this->getControllableEntity()->getWorldPosition(); if (diffVector.length() > this->attackRange_) { this->setTargetPositionOfWingman(); this->setTargetPositionOfFollower(); } else { //----wingmans shall support the fire of their leaders---- if (this->myWingman_) { this->myWingman_->setAction (this->action_, this->target_); } if (this->myFollower_) { this->myFollower_->setAction (this->action_); } } //----choose where to go---- this->maneuver(); //----fire if you can---- this->bShooting_ = this->canFire(); } } void DivisionController::setTargetPositionOfWingman() { if (!this->myWingman_) return; Vector3* targetRelativePositionOfWingman; switch (this->formationMode_){ case FormationMode::WALL: { targetRelativePositionOfWingman = new Vector3 (400, 0, 0); break; } case FormationMode::FINGER4: { targetRelativePositionOfWingman = new Vector3 (400, 0, 200); break; } case FormationMode::DIAMOND: { targetRelativePositionOfWingman = new Vector3 (400, 0, 200); break; } } Quaternion orient = this->getControllableEntity()->getWorldOrientation(); Vector3 targetAbsolutePositionOfWingman = ((this->getControllableEntity()->getWorldPosition()) + (this->getControllableEntity()->getWorldOrientation()* (*targetRelativePositionOfWingman))); myWingman_->setAction( Action::FLY, targetAbsolutePositionOfWingman, orient); } void DivisionController::setTargetPositionOfFollower() { if (!this->myFollower_) return; this->myFollower_->setFormationMode(this->formationMode_); Vector3* targetRelativePositionOfFollower; switch (this->formationMode_){ case FormationMode::WALL: { targetRelativePositionOfFollower = new Vector3 (-400, 0, 0); break; } case FormationMode::FINGER4: { targetRelativePositionOfFollower = new Vector3 (-400, 0, 200); break; } case FormationMode::DIAMOND: { targetRelativePositionOfFollower = new Vector3 (-400, 0, 200); break; } } Quaternion orient = this->getControllableEntity()->getWorldOrientation(); Vector3 targetAbsolutePositionOfFollower = ((this->getControllableEntity()->getWorldPosition()) + (this->getControllableEntity()->getWorldOrientation()* (*targetRelativePositionOfFollower))); myFollower_->setAction ( Action::FLY, targetAbsolutePositionOfFollower, orient ); } bool DivisionController::setWingman(CommonController* cwingman) { WeakPtr wingman = orxonox_cast(cwingman); if (!this->myWingman_) { this->myWingman_ = wingman; return true; } else { return false; } } bool DivisionController::setFollower(LeaderController* myFollower) { if (!this->myFollower_) { this->myFollower_ = myFollower; return true; } else { return false; } } bool DivisionController::hasWingman() { if (this->myWingman_) return true; else return false; } bool DivisionController::hasFollower() { if (this->myFollower_) return true; else return false; } }