/* 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: * Simon Miescher * */ /* * * * An asteroid which can be destroyed. Some smaller asteroids are created and a pickup * spawns. * * * */ /* Veraenderungstagebuch - Dynamische Definition von Argumenten funktioniert nicht (Immer auf default Values gesetzt) ---> Was tut registerVariable? Wann werden die Argumente im XML-File angewendet? (Fall Konstruktor -> Methoden: Beim ersten Tick initialisieren?) ---> Mesh-Teil klappt, Hitbox noch nicht. ---> Maximale Hitpunkte = 200? ---> Meshgroesse passt, aber Hitbox wird iwieso nicht mehr generiert. - Neue Asteroiden generieren -> Absturz - Pickup spawning -> Absturz o hat's mit den Context-Eingenschaften zu tun? Je einen Neuen/Aktuellen besorgen? Nicht Pointer uebergeben? - Manchmal: Absturz bei Zerstoerung eines Asteroiden - Was tut 'Register Variables'? o Error messages: change context::pickups to something else OFFEN: o Add custom pickup 'resources' Erlegt: o Rand() geht bis zu riesigen Nummern! */ #include "../../orxonox/worldentities/pawns/Pawn.h" #include "../../orxonox/worldentities/WorldEntity.h" #include "AsteroidMinable.h" #include #include "core/CoreIncludes.h" #include "core/GameMode.h" #include "core/XMLPort.h" #include "core/EventIncludes.h" #include "network/NetworkFunction.h" // #include "infos/PlayerInfo.h" // #include "controllers/Controller.h" // #include "gametypes/Gametype.h" // #include "graphics/ParticleSpawner.h" // #include "worldentities/ExplosionChunk.h" // #include "worldentities/ExplosionPart.h" // #include "core/object/ObjectListIterator.h" // #include "controllers/FormationController.h" #include "../pickup/items/HealthPickup.h" #include "../pickup/PickupSpawner.h" #include "../pickup/Pickup.h" //#include "../pickup/pickup ..... pickupable #include "../objects/collisionshapes/SphereCollisionShape.h" #include "../../orxonox/graphics/Model.h" namespace orxonox { RegisterClass(AsteroidMinable); AsteroidMinable::AsteroidMinable(Context* context) : Pawn(context) { RegisterObject(AsteroidMinable); // Old stuff from pawn this->setRadarObjectColour(ColourValue(1.0f, 1.0f, 0.0f, 1.0f)); this->setRadarObjectShape(RadarViewable::Shape::Dot); this->setCollisionType(WorldEntity::CollisionType::Dynamic); this->bAlive_ = true; this->bVulnerable_ = true; // Default Values this->generateSmaller = true; //this->size = this->getSize(); // Value doesn-t get accepted. Weird. this->size = 10; this->context = context; this->initialised = false; //this->roll = rand()*5; //etwas Drehung. richtige Variable // DELETE if other stuff works! (wrong size etc.) SphereCollisionShape* cs = new SphereCollisionShape(this->context); cs->setRadius((this->size)*2); //OFFEN: Feinabstimmung der Radien this->attachCollisionShape(cs); // Old from Pawn this->registerVariables(); } AsteroidMinable::~AsteroidMinable() { } void AsteroidMinable::putStuff(){ // Add Model // Model* hull = new Model(this->context); // random one of the 6 shapes char meshThingy[] = ""; sprintf(meshThingy, "ast%.0f.mesh", (round((5*(double)rand()/(double)RAND_MAX))+1)); // sprintf(str, "Value of Pi = %f", M_PI); //char meshThingy[] = "ast5.mesh"; hull->setMeshSource(meshThingy); hull->setScale(this->size); this->attach(hull); //hull->setPosition(this->getPosition()); // Collision shape SphereCollisionShape* cs = new SphereCollisionShape(this->context); cs->setRadius((this->size)*2); //OFFEN: Feinabstimmung der Radien. 2.5 in AsteroidField.lua this->attachCollisionShape(cs); this->initialised=true; } void AsteroidMinable::XMLPort(Element& xmlelement, XMLPort::Mode mode) { SUPER(AsteroidMinable, XMLPort, xmlelement, mode); // XMLPortParam(PickupSpawner, "pickup", setPickupTemplateName, getPickupTemplateName, xmlelement, mode); XMLPortParam(AsteroidMinable, "size", setSize, getSize, xmlelement, mode); } void AsteroidMinable::XMLEventPort(Element& xmlelement, XMLPort::Mode mode) { SUPER(AsteroidMinable, XMLEventPort, xmlelement, mode); XMLPortEventState(AsteroidMinable, BaseObject, "vulnerability", setVulnerable, xmlelement, mode); } void AsteroidMinable::registerVariables() { registerVariable(this->bAlive_, VariableDirection::ToClient); registerVariable(this->bVulnerable_, VariableDirection::ToClient); registerVariable(this->health_, VariableDirection::ToClient); registerVariable(this->maxHealth_, VariableDirection::ToClient); registerVariable(this->size, VariableDirection::ToClient); registerVariable(this->generateSmaller, VariableDirection::ToClient); registerVariable(this->initialised, VariableDirection::ToClient); //registerVariable(this->context, VariableDirection::ToClient); // can't link that since it's a context // float size; // bool generateSmaller; // bool initialised; // Context* context; } void AsteroidMinable::tick(float dt) { // SUPER(Pawn, tick, dt); if(!(this->initialised)){this->putStuff();} if(this->health_ <=0){this->death();} } void AsteroidMinable::setSize(float s){ this->size = s; this->health_ = 5*s;// capped at 200 in pawn or smth? this->setHealth(health_); } float AsteroidMinable::getSize(){ return this->size; } void AsteroidMinable::death() //ueberschreiben { //Spawn Pickup // Create at start already? ( Hidden in CollisionShape) HealthPickup* hP = new HealthPickup(this->context); if(hP == nullptr){ orxout(internal_error, context::pickups) << "Weird, can't create new HealthPickup." << endl; } // hP->setPosition(this->getPosition()); // Does not have a member named 'setPosition' (Inherits from Pickup//BAse Object) // invoke spawnPickup on the pikcup itself? (returns bool, creates the hideous thing) // HealthPickup inherits from Pickup. // createSpawner is protected ->can be used as well in inheriting classes, but not here! // bool unnecessary = hP->createSpawner(); // hP->setPosition(this->getPosition()); //OFFEN: Add custom pickup 'resources' // createPickup is private, hP is of type Pickup! // CreateDroppedPickup returns a PickupSpawner! // PickupSpawner don't have public set methods, just that ugly 'factory method' which returns another PickupSpawner // PickupSpawner* thingy = new PickupSpawner(this->context); // What is Pickupable? says: Interface, no way to set type. Why do I even need the spawner? Trigger Distance? // Plan: Solve the Pickupable mystery, try to adapt the spawner somehow. Ask to modify it if that fails. (Change method types) // PickupSpawner* thingy = (new PickupSpawner(this->context))->createDroppedPickup(this->context, hP, nullptr, 10); // /*static*/ PickupSpawner* PickupSpawner::createDroppedPickup(Context* context, Pickupable* pickup, PickupCarrier* carrier, float triggerDistance) // if(thingy == nullptr){ // orxout(internal_error, context::pickups) << "Weird, can't create new PickupSpawner." << endl; // } // thingy->setPosition(this->getPosition()); // thingy->setMaxSpawnedItems(1);//Default is 1 already, private anyways // // Smaller Parts // if(this->generateSmaller){ // this->spawnChildren(); // } // OFFEN: Sauber kapputten // just copied other stuff: this->setHealth(1); this->bAlive_ = false; this->destroyLater(); this->setDestroyWhenPlayerLeft(false); // pawn -> addExplosionPart // this->goWithStyle(); // if (this->getGametype() && this->getGametype()->allowPawnDeath(this, this->lastHitOriginator_)) // { // // Set bAlive_ to false and wait for destroyLater() to do the destruction // this->bAlive_ = false; // this->destroyLater(); // this->setDestroyWhenPlayerLeft(false); // } } void AsteroidMinable::spawnChildren(){ // Spawn smaller Children int massRem = this->size-1; //some mass is lost int num = round((massRem-1)*(double)rand() / (double)RAND_MAX)+1; // random number of children, at least one massRem = massRem-num; int extra = 0; for(int fisch=num; fisch>=1; fisch++){ // to distribute remaining mass if(fisch==1){ extra = massRem; }else{ extra = round(massRem*(double)rand() / (double)RAND_MAX); massRem = massRem-extra; } //Spawn this child Game crashes! AsteroidMinable* child = new AsteroidMinable(this->context); // if(!(child == nullptr)){//Errorgebastel if(child == nullptr){ orxout(internal_error, context::pickups) << "Weird, can't create new AsteroidMinable." << endl; } child->setSize(extra + 1); //OFFEN:Kollision der Kinder verhindern //Relativ zu Elternteil automatisch? //Typ position:rand()*Vektoriwas? //pawn->getWorldPosition() + Vector3(30,0,-30); child->setPosition(this->getPosition() + Vector3(num*5, 0, 0)); // } // Pawn* pawn = this->carrierToPawnHelper(); // if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed. // this->Pickupable::destroy(); // //Attach to pawn // Drone* drone = new Drone(pawn->getContext()); // this is neccessary because the projectiles fired need a valid creator for the particlespawner (when colliding against something) // drone->addTemplate(this->getDroneTemplate()); } } } /* void DronePickup::changedUsed(void) { SUPER(DronePickup, changedUsed); // If the pickup has transited to used. if(this->isUsed()) { Pawn* pawn = this->carrierToPawnHelper(); if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed. this->Pickupable::destroy(); //Attach to pawn Drone* drone = new Drone(pawn->getContext()); // this is neccessary because the projectiles fired need a valid creator for the particlespawner (when colliding against something) drone->addTemplate(this->getDroneTemplate()); Controller* controller = drone->getController(); DroneController* droneController = orxonox_cast(controller); if(droneController != nullptr) { droneController->setOwner(pawn); } Vector3 spawnPosition = pawn->getWorldPosition() + Vector3(30,0,-30); drone->setPosition(spawnPosition); // The pickup has been used up. this->setUsed(false); } else { // If either the pickup can only be used once or it is continuous and used up, it is destroyed upon setting it to unused. if(this->isOnce() || (this->isContinuous() )) { this->Pickupable::destroy(); } } } */