Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10502 was 10502, checked in by meggiman, 9 years ago

Bugfix: Game crashed if a pawn was directly hit by the bomb. Changed Radar Color to red.

File size: 6.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.