/* 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: * remartin * Co-authors: * ... * */ /* @file @author remartin @brief An asteroid which can be destroyed. Some smaller asteroids are created and a pickup spawns. HANDBUCH: o Die Collision Shape kann nur im Konstruktor hinzugefügt werden. Die XML-Argumente werden aber erst nach dem Konstruktor gesetzt. Darum wird hier beim ersten Aufruf der tick()-Methode via putStuff() ein komplett neuer Asteroid generiert und der alte zerstört. o im Level-File includes/pickups.oxi importieren. OFFEN/Weiterentwicklung: o @TODO Add resource pickups. --> data_extern/images/effects: PNG's für die Pickups --> https://www.orxonox.net/jenkins/view/Management/job/orxonox_doxygen_trunk/javadoc/group___pickup.html o Density doesn't add up to 1... o Does collision damage work properly o Add sound effect (crunching etc. ) (No sound in space...) o Explosion parts ANDERORTS VERÄNDERTE SACHEN: Pickup-Zeug: o PickupSpawner.h: Zugriffsrechte setPickupTemplateName() und setMaxSpawnedItems() o PickupSpawner.h: In Tick() zwei Testbedingungen eingefügt. o Pawn.h: Attribut acceptsPickups_ inklusive get/set. ERLEGTE FEHLER: o Grössenabhängige Collision Shape -> putStuff-Methode, Werte noch nicht durchgesickert. o setHealth: maxHealth() des pawns setzen! o Asteroiden fressen Pickups: Argument in Pawn, Test darauf in Tick() von PickupSpawner. o i++ einfach ganz verhindern, ++i stattdessen. o Velocity didn-t get passed properly through the 2nd constructor. Used get/set instead. o Rand() geht bis zu riesigen Nummern! rnd() ist zwischen 0 und 1 NOTIZEN: o SUPER o Warnungsverhinderung anderswo: (void)pickedUp; // To avoid compiler warning. o friend class Pickupable; */ #include "AsteroidMinable.h" #include #include "core/CoreIncludes.h" #include "core/GameMode.h" #include "core/XMLPort.h" #include "util/Convert.h" #include "util/Math.h" #include "pickup/PickupSpawner.h" #include "pickup/Pickup.h" #include "objects/collisionshapes/SphereCollisionShape.h" #include "graphics/Model.h" namespace orxonox{ RegisterClass(AsteroidMinable); // @brief Standard constructor AsteroidMinable::AsteroidMinable(Context* context) : Pawn(context){ RegisterObject(AsteroidMinable); // Default Values: this->size = 1; this->dropStuff = true; this->generateSmaller = true; this->acceptsPickups_ = false; this->setCollisionType(WorldEntity::CollisionType::Dynamic); this->enableCollisionCallback(); // Old from Pawn this->registerVariables(); this->initialised = false; } AsteroidMinable::~AsteroidMinable(){ } void AsteroidMinable::setSize(float s) { this->size = s; this->health_ = 15*size; this->maxHealth_ = this->health_; } // @brief Helper method. void AsteroidMinable::putStuff(){ // The radar is able to detect whether an asteroid contains resources.... if(dropStuff){ this->setRadarObjectColour(ColourValue(1.0f, 1.0f, 0.0f, 1.0f)); this->setRadarObjectShape(RadarViewable::Shape::Dot); }else{ // Somehow remove from radar? (all pawns get registered automatically... ) this->setRadarObjectColour(ColourValue(0.663f, 0.663f, 0.663f, 1.0f)); this->setRadarObjectShape(RadarViewable::Shape::Dot); } // Add Model, random one of the 6 shapes Model* hull = new Model(this->getContext()); hull->setMeshSource("ast" + multi_cast(1 + (int)rnd(0, 6)) + ".mesh"); hull->setScale(this->size); this->attach(hull); // Collision shape SphereCollisionShape* cs = new SphereCollisionShape(this->getContext()); cs->setRadius((this->size)*2); //OFFEN: Feinabstimmung der Radien. this->attachCollisionShape(cs); this->initialised=true; } void AsteroidMinable::XMLPort(Element& xmlelement, XMLPort::Mode mode){ SUPER(AsteroidMinable, XMLPort, xmlelement, mode); XMLPortParam(AsteroidMinable, "size", setSize, getSize, xmlelement, mode); XMLPortParam(AsteroidMinable, "generateSmaller", setShattering, doesShatter, xmlelement, mode); XMLPortParam(AsteroidMinable, "dropStuff", setDropStuff, doesDropStuff, xmlelement, mode); } void AsteroidMinable::registerVariables(){ registerVariable(this->size, VariableDirection::ToClient); registerVariable(this->generateSmaller, VariableDirection::ToClient); registerVariable(this->dropStuff, VariableDirection::ToClient); registerVariable(this->initialised, VariableDirection::ToClient); } void AsteroidMinable::tick(float dt){ if(!(this->initialised)){this->putStuff();} if(this->health_ <=0){this->death();} } void AsteroidMinable::death(){ // @brief Überschreibt die Methode in Pawn // just copied that from somewhere else. this->bAlive_ = false; this->destroyLater(); this->setDestroyWhenPlayerLeft(false); // pawn -> addExplosionPart // this->goWithStyle(); // Pickups which can be harvested. It's munition at the moment, could be changed/extended. if(dropStuff){ PickupSpawner* thingy = new PickupSpawner(this->getContext()); std::string tname; if(this->size <= 5){ tname = "smallmunitionpickup"; }else if(this->size <= 20){ tname = "mediummunitionpickup"; }else{ tname = "hugemunitionpickup"; } thingy->setPickupTemplateName(tname); thingy->setPosition(this->getPosition()); thingy->setMaxSpawnedItems(1); // Would be default anyways thingy->setRespawnTime(0.2f); } // Smaller Parts = 'Children' if(this->generateSmaller){this->spawnChildren();} } // @brief If the option generateSmaller is enabled, individual fragments are added with this method. void AsteroidMinable::spawnChildren(){ if (this->size <=1){return;} // Absicherung trivialer Fall float massRem = (this->size-1); //some mass is lost int num = (int)roundf(rnd(massRem-1)) + 1; // random number of children, at least one if(num > 10){num = 10;} // no max function in C? std::vector masses(num); // Masses of the asteroids // orxout() << "SpawnChildren(): Passed basic stuff. num = " << num << "; massRem(total) = "<< massRem << endl; massRem = massRem-num; // mass must be at least one, add later. // Randomnised spawning points for the new asteroids std::vector phi(num); std::vector theta(num); // Discusting C stuff -> use that to initialise dynamic array values to 0. for(int twat = 0; twat0){ int c = (int)massRem; std::vector probDensity(c); int a = (int)roundf(massRem/num); int b = c-a; int z = 0; float dProbA = 1.0f/(a*a + 3.0f*a + 2.0f); // one 'probability unit' for discrete ramp function. Gauss stuff. for(z = 0; zprobSum && result 1){// not required if there-s just one child float r = masses[fisch]/rScaling; pos = Vector3(r*sin(theta[fisch])*cos(phi[fisch]), r*sin(theta[fisch])*sin(phi[fisch]), r*cos(theta[fisch])); // convert spheric coordinates to vector } AsteroidMinable* child = new AsteroidMinable(this->getContext()); child->setSize(masses[fisch]); child->setPosition(this->getPosition() + pos); child->setVelocity(this->getVelocity()); child->setDropStuff(this->dropStuff); } // orxout() << "Leaving spawnChildren() method. " << endl; } // @brief overloading that to prevent asteroids from taking damage from each other (domino effect etc. ) void AsteroidMinable::hit(Pawn* originator, const Vector3& force, const btCollisionShape* cs, float damage, float healthdamage, float shielddamage){ // orxout() << "AsteroidMining::Hit(Variante 1) Dings aufgerufen. " << endl; if(orxonox_cast(originator) || orxonox_cast(originator)){return;} this->damage(damage, healthdamage, shielddamage, originator, cs); this->setVelocity(this->getVelocity() + force); // if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator))// && (!this->getController() || !this->getController()->getGodMode()) ) // { // this->damage(damage, healthdamage, shielddamage, originator, cs); // this->setVelocity(this->getVelocity() + force); // } } // @brief overloading that to prevent asteroids from taking damage from each other (domino effect etc. ) void AsteroidMinable::hit(Pawn* originator, btManifoldPoint& contactpoint, const btCollisionShape* cs, float damage, float healthdamage, float shielddamage){ //orxout() << "AsteroidMining::Hit(Variante 2) Dings aufgerufen. " << endl; if(orxonox_cast(originator) || orxonox_cast(originator)){return;} this->damage(damage, healthdamage, shielddamage, originator, cs); // if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator))// && (!this->getController() || !this->getController()->getGodMode()) ) // { // this->damage(damage, healthdamage, shielddamage, originator, cs); // //if ( this->getController() ) // // this->getController()->hit(originator, contactpoint, damage); // changed to damage, why shielddamage? // } } }