/* * 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 "WingmanController.h" namespace orxonox { RegisterClass(WingmanController); //CommonController contains all common functionality of AI Controllers WingmanController::WingmanController(Context* context) : CommonController(context) { RegisterObject(WingmanController); this->actionTimer_.setTimer(ACTION_INTERVAL, true, createExecutor(createFunctor(&WingmanController::action, this))); this->myLeader_ = 0; this->rank_ = Rank::WINGMAN; } WingmanController::~WingmanController() { } void WingmanController::XMLPort(Element& xmlelement, XMLPort::Mode mode) { SUPER(WingmanController, XMLPort, xmlelement, mode); //XMLPortParam(SectionController, "target_", setTarget, getTarget, xmlelement, mode).defaultValues(100.0f); } //----in tick, move (or look) and shoot---- void WingmanController::tick(float dt) { if (!this->isActive()) return; if (this->bHasTargetPosition_) { this->moveToTargetPosition(dt); } else if (this->bLookAtTarget_) { this->lookAtTarget(dt); } if (bShooting_) { this->doFire(); } SUPER(WingmanController, tick, dt); } //----action for hard calculations---- void WingmanController::action() { //----If no leader, find one---- if (!this->myLeader_) { CommonController* newLeader = findNewLeader(); this->myLeader_ = newLeader; if (newLeader) { //orxout(internal_error) << "new Leader set" << endl; } //----If no leader found, attack someone---- //----TODO: find closest enemy---- else { if ( !this->hasTarget() || this->action_ != Action::FIGHT ) { for (ObjectList::iterator itP = ObjectList::begin(); itP; ++itP) { if ( CommonController::sameTeam (this->getControllableEntity(), static_cast(*itP)) ) continue; this->setAction(Action::FIGHT, (*itP)); break; } } } } //----If have leader, he will deal with logic---- else { } //----action was set to fight---- if (this->action_ == Action::FIGHT) { //----choose where to go---- this->maneuver(); //----fire if you can---- this->bShooting_ = this->canFire(); } //----action was set to fly, leader handles the logic---- else if (this->action_ == Action::FLY) { } //----TODO: implement protect---- else if (this->action_ == Action::PROTECT) { } } //----POST: closest leader that is ready to take a new wingman is returned---- CommonController* WingmanController::findNewLeader() { if (!this->getControllableEntity()) return 0; //----vars for finding the closest leader---- CommonController* closestLeader = 0; float minDistance = std::numeric_limits::infinity(); for (ObjectList::iterator it = ObjectList::begin(); it; ++it) { //----0ptr or not a leader or dead?---- if (!it || (it->getRank() != Rank::SECTIONLEADER && it->getRank() != Rank::DIVISIONLEADER) || !(it->getControllableEntity())) continue; //----same team?---- if ( !CommonController::sameTeam (this->getControllableEntity(), (it)->getControllableEntity()) ) continue; //----check distance---- float distance = CommonController::distance (it->getControllableEntity(), this->getControllableEntity()); if (distance < minDistance && !(it->hasWingman())) { closestLeader = *it; minDistance = distance; } } if (closestLeader) { //----Racing conditions---- if (closestLeader->setWingman(this)) return closestLeader; } return 0; } }