Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/weaponFS15/src/modules/weapons/projectiles/GravityBombField.cc @ 10604

Last change on this file since 10604 was 10601, checked in by landauf, 9 years ago

cleanup: empty level is empty again & tabs→spaces.

File size: 7.6 KB
Line 
1/*
2 * GravityBombField.cc
3 *
4 *  Created on: Apr 2, 2015
5 *      Author: Manuel Eggimann
6 */
7
8#include "GravityBombField.h"
9#include "graphics/Model.h"
10
11namespace orxonox{
12    RegisterClass(GravityBombField);
13
14    //Change these constants to alter the behaviour of the field.
15   
16    const float GravityBombField::FORCE_FIELD_LIFETIME = 15;
17    const float GravityBombField::FORCE_SPHERE_START_RADIUS = 250;
18    const float GravityBombField::FORCE_SPHERE_START_STRENGTH = -700;
19    const float GravityBombField::PEAK_EXPLOSION_FORCE = 5e4;
20    const float GravityBombField::FORCE_FIELD_EXPLOSION_DAMMAGE = 100;
21    const float GravityBombField::EXPLOSION_DURATION = 1;
22    const float GravityBombField::EXPLOSION_RADIUS = 600;
23    const float GravityBombField::PEAK_ANGULAR_VELOCITY = 20;
24    const float GravityBombField::CENTRE_MODEL_END_SIZE = 1.5;
25
26    GravityBombField::GravityBombField(Context* context) : ForceField(context),RadarViewable(this, static_cast<WorldEntity*>(this))
27    {
28        RegisterObject(GravityBombField);
29        //Initialize variable with their initial values.
30        lifetime_=FORCE_FIELD_LIFETIME;
31        forceStrength_ = FORCE_SPHERE_START_STRENGTH;
32        forceSphereRadius_ = FORCE_SPHERE_START_RADIUS;
33        modelScaling_ = 1;
34        fieldExploded_ = false;
35
36        setVelocity(FORCE_SPHERE_START_STRENGTH);
37        setDiameter(2*FORCE_SPHERE_START_RADIUS);
38        setMode(modeSphere_s);
39        setCollisionResponse(false);
40
41        //Make the Field visible on Radar and minimap.
42        this->setRadarObjectColour(ColourValue(1.0, 0.0, 0.2,1)); // Red
43        this->setRadarObjectShape(RadarViewable::Dot);
44        this->setRadarObjectScale(1.0f);
45       
46
47        //Attach Model
48        Model* model = new Model(this->getContext());
49        model->setMeshSource("GravityBomb.mesh"); //Demo Model from SimpleRocket
50        model->scale(2.5f);
51        bombModel_ = new MovableEntity(context);
52        bombModel_->attach(model);
53        this->attach(bombModel_);
54
55        //Add a Backlight to the centre.
56        centreLight_ = new Backlight(context);
57        centreLight_->setColour(ColourValue(0.2,0.9,0.2,1));
58        centreLight_->setScale(0.3);
59        centreLight_->setTrailMaterial("Trail/backlighttrail");
60        centreLight_->setMaterial("Examples/Flare");
61        centreLight_->setLifetime(20);
62        bombModel_->attach(centreLight_);
63
64        //Let the Bomb Modell in the centre rotate in a random direction.
65        Vector3 randomRotation;
66        srand(time(NULL));
67        randomRotation.x = rand();
68        randomRotation.y = rand();
69        randomRotation.y = rand();
70        randomRotation.normalise();
71        bombModel_->setAngularAcceleration(randomRotation*(PEAK_ANGULAR_VELOCITY/FORCE_FIELD_LIFETIME));
72
73        //Add Collision Shape
74        SphereCollisionShape* collisionShape = new SphereCollisionShape(context);
75        collisionShape->setRadius(10.0);
76        this->attachCollisionShape(collisionShape);
77
78        //Add particle effect to visualize the force field.
79        this->particleSphere_ = new ParticleEmitter(this->getContext());
80        this->attach(this->particleSphere_);
81        particleSphere_->setSource("Orxonox/GravityBombField");
82
83        //Add a sound effect to the field.
84        WorldSound* fieldSound = new WorldSound(context);
85        fieldSound->setSource("sounds/GravityField.ogg");
86        fieldSound->setLooping(true);
87        fieldSound->setVolume(1.0);
88        this->attach(fieldSound);
89        fieldSound->play();
90    }
91
92    GravityBombField::~GravityBombField(){}
93
94   
95    void GravityBombField::tick(float dt)
96    {
97        SUPER(GravityBombField,tick,dt);
98        lifetime_-=dt;
99
100        if(lifetime_ > EXPLOSION_DURATION)//If field is still alive, make it smaller and stronger.
101        {
102            modelScaling_ += ((CENTRE_MODEL_END_SIZE-1) / FORCE_FIELD_LIFETIME)*dt;
103            forceStrength_ *= (1+dt/10);
104            forceSphereRadius_ = FORCE_SPHERE_START_RADIUS*(1-((FORCE_FIELD_LIFETIME-lifetime_)/FORCE_FIELD_LIFETIME)*((FORCE_FIELD_LIFETIME-lifetime_)/FORCE_FIELD_LIFETIME)*((FORCE_FIELD_LIFETIME-lifetime_)/FORCE_FIELD_LIFETIME));
105        }
106        else if(lifetime_ > 0)
107        {
108            if (!fieldExploded_) // Start the field explosion if it has not been started yet.
109            {
110                forceStrength_ = pow((EXPLOSION_DURATION + lifetime_),4)/EXPLOSION_DURATION * PEAK_EXPLOSION_FORCE;
111                fieldExploded_ = true;
112
113                //Add particle effect to visualize explosion
114                explosionCross_ = new ParticleEmitter(this->getContext());
115                explosionCross_->setSource("Orxonox/FieldExplosion");
116                explosionCross_->setOrientation(rand(), rand(), rand(), rand());
117                explosionCross_->setScale(0.7);
118                this->attach(explosionCross_);
119
120                //Add explosion sound effect.
121                explosionSound_ = new WorldSound(getContext());
122                explosionSound_->setSource("sounds/GravityFieldExplosion.ogg");
123                explosionSound_->setVolume(1.0);
124                explosionSound_->play();
125            }
126
127            //Check if any pawn is inside the shockwave and hit it with dammage proportional to the distance between explosion centre and pawn. Make sure, the same pawn is damaged only once.
128            for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it != ObjectList<Pawn>::end(); ++it)
129            {
130                Vector3 distanceVector = it->getWorldPosition()-this->getWorldPosition();
131                 //orxout(debug_output) << "Found Pawn:" << it->getWorldPosition() << endl;
132                if(distanceVector.length()< forceSphereRadius_)
133                {
134                    //orxout(debug_output) << "Force sphere radius is: " << forceSphereRadius_ << " Distance to Pawn is: " << distanceVector.length();
135                    if (std::find(victimsAlreadyDamaged_.begin(),victimsAlreadyDamaged_.end(),*it) == victimsAlreadyDamaged_.end())
136                    {
137                        //orxout(debug_output) << "Found Pawn to damage: " << it->getWorldPosition() << endl;
138                        float damage = FORCE_FIELD_EXPLOSION_DAMMAGE*(1-distanceVector.length()/EXPLOSION_RADIUS);
139                        //orxout(debug_output) << "Damage: " << damage << endl;
140                        it->hit(shooter_, it->getWorldPosition(), NULL, damage, 0,0);
141                        victimsAlreadyDamaged_.push_back(*it);
142                    }
143                }
144            }
145
146            forceSphereRadius_ = EXPLOSION_RADIUS*(1-lifetime_/EXPLOSION_DURATION);
147            explosionCross_->setScale(forceSphereRadius_/FORCE_SPHERE_START_RADIUS);
148        }
149        else if (lifetime_ > -6) //The field has to exist for 6 more seconds for the particles of the particle effect to vanish smoothly.
150        {
151            //Make the bomb model invisible, let the strength of the field be zero and remove all particle emitters so the particle effect will slowly vanish.
152            bombModel_->setVisible(false);
153            this->setRadarVisibility(false);
154            forceStrength_ = 0;
155            forceSphereRadius_ = 0.00001;
156            particleSphere_->getParticleInterface()->removeAllEmitters();
157            explosionCross_->getParticleInterface()->removeAllEmitters();
158        }
159       
160        setDiameter(forceSphereRadius_*2);
161        setVelocity(forceStrength_);
162        if(lifetime_>0) particleSphere_->setScale(forceSphereRadius_/FORCE_SPHERE_START_RADIUS);
163        bombModel_->setScale(modelScaling_);
164
165        if (lifetime_ <= -4)
166        {
167            orxout(debug_output) << "Timeout. Destroying field." << endl;
168            this->destroy();
169        }
170    }
171
172    void GravityBombField::destroy()
173    {
174        ForceField::destroy();
175    }
176
177}
Note: See TracBrowser for help on using the repository browser.