/* * 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: * Joel Smely * Co-authors: * ... * */ /** @file SplitGunProjectile.h @brief Implementation of the SplitGunProjectile class. */ #include "SplitGunProjectile.h" #include "core/CoreIncludes.h" #include "core/command/Executor.h" #include "util/Convert.h" #include "util/Math.h" namespace orxonox { RegisterClass(SplitGunProjectile); SplitGunProjectile::SplitGunProjectile(Context* context) : BillboardProjectile(context) { RegisterObject(SplitGunProjectile); this->numberOfSplits_ = 0; this->numberOfChilds_ = 0; this->splitTime_ = 1.0; this->spread_ = 0.2; } void SplitGunProjectile::setNumberOfSplits(int numberOfSplits) { if (numberOfSplits >= 0) { this->numberOfSplits_ = numberOfSplits; } else { this->numberOfSplits_ = 0; } } void SplitGunProjectile::setNumberOfChilds(int numberOfChilds) { if (numberOfChilds >= 0) { this->numberOfChilds_ = numberOfChilds; } else { this->numberOfChilds_ = 0; } } void SplitGunProjectile::setSplitTime(float splitTime) { if (splitTime >= 0) { this->splitTime_ = splitTime; this->textureTimer_.setTimer(this->splitTime_, false, createExecutor(createFunctor(&SplitGunProjectile::split, this))); } else { this->splitTime_ = 0; } } void SplitGunProjectile::setSpread(float spread) { spread_ = spread; } void SplitGunProjectile::split() { if (numberOfSplits_ > 0) { -- numberOfSplits_; // Calculate a normalized vector (velocityOffset) that is perpendicluar to the velocity of this projectile. Since there are infinitly many perpendicular vectors a random one is chosen. Vector3 velocityInitial = this->getVelocity(); Vector3 velocityOffset = velocityInitial.perpendicular(); velocityOffset.normalise(); Degree angle = Degree(rnd(0,360)); velocityOffset = Quaternion(angle, velocityInitial.normalisedCopy()) * velocityOffset; velocityOffset.normalise(); // Create as many childs as defined by numberOfChilds_ for (int i = 0; i < numberOfChilds_; ++i) { // Every child projectile should fly uniform in different directions -> Rotate the velocityOffset in every iteration velocityOffset = Quaternion(Degree(360/numberOfChilds_), velocityInitial.normalisedCopy()) * velocityOffset; velocityOffset.normalise(); SplitGunProjectile* projectile = new SplitGunProjectile(this->getContext()); projectile->setMaterial(this->getMaterial()); projectile->setOrientation(this->getOrientation()); projectile->setPosition(this->getPosition()); projectile->setVelocity(velocityInitial + spread_*velocityOffset*velocityInitial.length()); projectile->setNumberOfSplits(this->numberOfSplits_); projectile->setNumberOfChilds(this->numberOfChilds_); projectile->setSplitTime(this->splitTime_); projectile->setSpread(this->spread_); projectile->setShooter(this->getShooter()); projectile->setDamage(this->getDamage()); projectile->setShieldDamage(this->getShieldDamage()); projectile->setHealthDamage(this->getHealthDamage()); } numberOfSplits_ = 0; } } }