| 1 | /* | 
|---|
| 2 |    orxonox - the future of 3D-vertical-scrollers | 
|---|
| 3 |  | 
|---|
| 4 |    Copyright (C) 2004-2006 orx | 
|---|
| 5 |  | 
|---|
| 6 |    This program is free software; you can redistribute it and/or modify | 
|---|
| 7 |    it under the terms of the GNU General Public License as published by | 
|---|
| 8 |    the Free Software Foundation; either version 2, or (at your option) | 
|---|
| 9 |    any later version. | 
|---|
| 10 |  | 
|---|
| 11 |    ### File Specific | 
|---|
| 12 |    main-programmer: Marc Schaerrer | 
|---|
| 13 |    co-programmer: | 
|---|
| 14 | */ | 
|---|
| 15 | //#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WEAPON | 
|---|
| 16 |  | 
|---|
| 17 | #include "spike_launcher.h" | 
|---|
| 18 |  | 
|---|
| 19 | #include "weapon_manager.h" | 
|---|
| 20 | #include "world_entities/projectiles/projectile.h" | 
|---|
| 21 | #include "world_entities/projectiles/spike_ball.h" | 
|---|
| 22 |  | 
|---|
| 23 | #include "model.h" | 
|---|
| 24 |  | 
|---|
| 25 | #include "state.h" | 
|---|
| 26 | #include "animation3d.h" | 
|---|
| 27 |  | 
|---|
| 28 | #include <list> | 
|---|
| 29 | #include <iterator> | 
|---|
| 30 | #include "util/state.h" | 
|---|
| 31 |  | 
|---|
| 32 | #include "math/quaternion.h" | 
|---|
| 33 |  | 
|---|
| 34 | #include "util/loading/factory.h" | 
|---|
| 35 |  | 
|---|
| 36 |  | 
|---|
| 37 |  | 
|---|
| 38 | using namespace std; | 
|---|
| 39 |  | 
|---|
| 40 | ObjectListDefinition(SpikeLauncher); | 
|---|
| 41 | CREATE_FACTORY(SpikeLauncher); | 
|---|
| 42 |  | 
|---|
| 43 | /** | 
|---|
| 44 |  *  standard constructor | 
|---|
| 45 |  * | 
|---|
| 46 |  * creates a new SpikeLauncher | 
|---|
| 47 |  */ | 
|---|
| 48 | SpikeLauncher::SpikeLauncher() | 
|---|
| 49 |   : Weapon() | 
|---|
| 50 | { | 
|---|
| 51 |   this->init(); | 
|---|
| 52 | } | 
|---|
| 53 |  | 
|---|
| 54 | /** | 
|---|
| 55 |  * creates a new SpikeLauncher from a TiXmlElement | 
|---|
| 56 |  */ | 
|---|
| 57 | SpikeLauncher::SpikeLauncher(const TiXmlElement* root) | 
|---|
| 58 | { | 
|---|
| 59 |   this->init(); | 
|---|
| 60 |   if (root != NULL) | 
|---|
| 61 |     this->loadParams(root); | 
|---|
| 62 | } | 
|---|
| 63 |  | 
|---|
| 64 | /** | 
|---|
| 65 |  *  standard deconstructor | 
|---|
| 66 | */ | 
|---|
| 67 | SpikeLauncher::~SpikeLauncher () | 
|---|
| 68 | { | 
|---|
| 69 |   delete this->launcher; | 
|---|
| 70 |  | 
|---|
| 71 |   // model will be deleted from WorldEntity-destructor | 
|---|
| 72 | } | 
|---|
| 73 |  | 
|---|
| 74 | void SpikeLauncher::init() | 
|---|
| 75 | { | 
|---|
| 76 |   this->registerObject(this, SpikeLauncher::_objectList); | 
|---|
| 77 |  | 
|---|
| 78 |   Animation3D* animation1 = this->getAnimation(WS_ACTIVATING, this); | 
|---|
| 79 |   Animation3D* animation2 = this->getAnimation(WS_DEACTIVATING, this); | 
|---|
| 80 |  | 
|---|
| 81 |   animation1->addKeyFrame(Vector(0, -.5, 0), Quaternion(), 0.3, ANIM_LINEAR, ANIM_CONSTANT); | 
|---|
| 82 |   animation1->addKeyFrame(Vector(0, 0, 0), Quaternion(), 0.3, ANIM_LINEAR, ANIM_CONSTANT); | 
|---|
| 83 |   animation2->addKeyFrame(Vector(0, 0, 0), Quaternion(), 0.3, ANIM_LINEAR, ANIM_CONSTANT); | 
|---|
| 84 |   animation2->addKeyFrame(Vector(0, -.5, 0), Quaternion(), 0.3, ANIM_LINEAR, ANIM_CONSTANT); | 
|---|
| 85 |  | 
|---|
| 86 |   animation1->setInfinity(ANIM_INF_CONSTANT); | 
|---|
| 87 |   animation2->setInfinity(ANIM_INF_CONSTANT); | 
|---|
| 88 |  | 
|---|
| 89 |   this->setStateDuration(WS_SHOOTING, .6); | 
|---|
| 90 |   this->setStateDuration(WS_RELOADING, 1.0f); | 
|---|
| 91 |   this->setStateDuration(WS_ACTIVATING, .4); | 
|---|
| 92 |   this->setStateDuration(WS_DEACTIVATING, .4); | 
|---|
| 93 |  | 
|---|
| 94 |   this->setEnergyMax(10); | 
|---|
| 95 |   this->increaseEnergy(10); | 
|---|
| 96 |   //this->minCharge = 2; | 
|---|
| 97 |  | 
|---|
| 98 |   this->setCapability(WTYPE_ALLDIRS | WTYPE_TURRET | WTYPE_DIRECTIONAL | WTYPE_LIGHT); | 
|---|
| 99 |   this->setProjectileTypeC("Spike"); | 
|---|
| 100 |  | 
|---|
| 101 | //   this->loadModel("models/guns/turret1.obj", 1.0); | 
|---|
| 102 |   this->size = 2.5; | 
|---|
| 103 |  | 
|---|
| 104 |   this->setEmissionPoint(0.0, 0.0, 0.0); | 
|---|
| 105 |  | 
|---|
| 106 |  | 
|---|
| 107 |   this->spikes = 26; | 
|---|
| 108 |   this->launcher = new Vector [this->spikes]; | 
|---|
| 109 |  | 
|---|
| 110 |   this->getProjectileFactory()->prepare(this->spikes);  //we don't need more... | 
|---|
| 111 |  | 
|---|
| 112 | //   this->setActionSound(WA_SHOOT, "sounds/explosions/explosion_1.wav"); | 
|---|
| 113 | //   this->setActionSound(WA_ACTIVATE, "sounds/voices/rockets.wav"); | 
|---|
| 114 | //   this->setActionSound(WA_RELOAD, "sounds/voices/reload.wav"); | 
|---|
| 115 |  | 
|---|
| 116 | } | 
|---|
| 117 |  | 
|---|
| 118 | void SpikeLauncher::loadParams(const TiXmlElement* root) | 
|---|
| 119 | { | 
|---|
| 120 |   Weapon::loadParams(root); | 
|---|
| 121 | } | 
|---|
| 122 |  | 
|---|
| 123 | void SpikeLauncher::activate() | 
|---|
| 124 | { | 
|---|
| 125 |   this->launcher[0] = Vector(1.0, 0.0, 0.0); | 
|---|
| 126 |   this->launcher[1] = Vector(0.0, 1.0, 0.0); | 
|---|
| 127 |   this->launcher[2] = Vector(0.0, 0.0, 1.0); | 
|---|
| 128 |  | 
|---|
| 129 |   this->launcher[3] = Vector(1.0, 1.0, 0.0); | 
|---|
| 130 |   this->launcher[4] = Vector(0.0, 1.0, 1.0); | 
|---|
| 131 |   this->launcher[5] = Vector(1.0, 0.0, 1.0); | 
|---|
| 132 |   this->launcher[6] = Vector(1.0, -1.0, 0.0); | 
|---|
| 133 |   this->launcher[7] = Vector(0.0, 1.0, -1.0); | 
|---|
| 134 |   this->launcher[8] = Vector(-1.0, 0.0, 1.0); | 
|---|
| 135 |  | 
|---|
| 136 |   this->launcher[9] = Vector(-1.0, 1.0, 1.0); | 
|---|
| 137 |   this->launcher[10] = Vector(1.0, 1.0, 1.0); | 
|---|
| 138 |   this->launcher[11] = Vector(1.0, -1.0, 1.0); | 
|---|
| 139 |   this->launcher[12] = Vector(-1.0, -1.0, 1.0); | 
|---|
| 140 |  | 
|---|
| 141 |   int tmp = this->spikes / 2; | 
|---|
| 142 |   for (int i = 0; i < tmp; i++) | 
|---|
| 143 |   { | 
|---|
| 144 |     this->launcher[i].normalize(); | 
|---|
| 145 |     this->launcher[tmp + i] =  this->launcher[i] * (-1); | 
|---|
| 146 |   } | 
|---|
| 147 | } | 
|---|
| 148 |  | 
|---|
| 149 | void SpikeLauncher::deactivate() | 
|---|
| 150 | { | 
|---|
| 151 | } | 
|---|
| 152 |  | 
|---|
| 153 | void SpikeLauncher::tick(float dt) | 
|---|
| 154 | { | 
|---|
| 155 |   if (!Weapon::tickW(dt)) | 
|---|
| 156 |     return; | 
|---|
| 157 |  | 
|---|
| 158 |   Quaternion quat; | 
|---|
| 159 |   Vector direction; | 
|---|
| 160 |   if (this->getDefaultTarget() == NULL) | 
|---|
| 161 |     direction = this->getAbsCoor(); | 
|---|
| 162 |   else | 
|---|
| 163 |     direction = this->getDefaultTarget()->getAbsCoor() - this->getAbsCoor(); | 
|---|
| 164 |  | 
|---|
| 165 |   direction.normalize(); | 
|---|
| 166 |  | 
|---|
| 167 |   if (likely (this->getParent() != NULL)) | 
|---|
| 168 |     quat = Quaternion(direction, this->getParent()->getAbsDir().apply(Vector(0,1,0))) * Quaternion ( -M_PI_2, Vector(0,1,0)) ; | 
|---|
| 169 |   else | 
|---|
| 170 |     quat = Quaternion(direction, Vector(0,1,0)) * Quaternion ( -M_PI_2, Vector(0,1,0)) ; | 
|---|
| 171 |  | 
|---|
| 172 |   this->setAbsDirSoft(quat, 5); | 
|---|
| 173 | } | 
|---|
| 174 |  | 
|---|
| 175 | void SpikeLauncher::updateFireDir(Vector v, float angle){ | 
|---|
| 176 |  | 
|---|
| 177 |   float** m = new float* [3]; | 
|---|
| 178 |   for( int i = 0; i < 3 ; i++) | 
|---|
| 179 |     m[i] = new float; | 
|---|
| 180 |  | 
|---|
| 181 |   float nx, ny, nz, ca, sa; | 
|---|
| 182 |  | 
|---|
| 183 |   nx = v.x; | 
|---|
| 184 |   ny = v.y; | 
|---|
| 185 |   nz = v.z; | 
|---|
| 186 |  | 
|---|
| 187 |   ca = cos (angle); | 
|---|
| 188 |   sa = sin (angle); | 
|---|
| 189 | // final version below... easier to to cheat with the one above. | 
|---|
| 190 | /* | 
|---|
| 191 |   nx = this->getParent()->getRotationVector().x; | 
|---|
| 192 |   ny = this->getParent()->getRotationVector().y; | 
|---|
| 193 |   nz = this->getParent()->getRotationVector().z; | 
|---|
| 194 |  | 
|---|
| 195 |   ca = cos (this->getParent()->getAngle()); | 
|---|
| 196 |   sa = sin (this->getParent()->getAngle());*/ | 
|---|
| 197 | /* | 
|---|
| 198 |   float * m = new float [9]; | 
|---|
| 199 |   m[0] = 1.0f+(1.0f-ca)*(nx*nx-1.0f); | 
|---|
| 200 |   m[1] = -nz*sa+(1.0f-ca)*nx*ny; | 
|---|
| 201 |   m[2] = ny*sa+(1.0f-ca)*nx*nz; | 
|---|
| 202 |   m[3] = nz*sa+(1.0f-ca)*nx*ny; | 
|---|
| 203 |   m[4] = 1.0f+(1.0f-ca)*(ny*ny-1.0f); | 
|---|
| 204 |   m[5] = -nx*sa+(1.0f-ca)*ny*nz; | 
|---|
| 205 |   m[6] = -ny*sa+(1.0f-ca)*nx*nz; | 
|---|
| 206 |   m[7] = nx*sa+(1.0f-ca)*ny*nz; | 
|---|
| 207 |   m[8] = 1.0f+(1.0f-ca)*(nz*nz-1.0f);*/ | 
|---|
| 208 |  | 
|---|
| 209 |   m[0][0] = nx * nx * (1 - ca) + ca; | 
|---|
| 210 |   m[0][1] = nx * ny * (1 - ca) + nz * sa; | 
|---|
| 211 |   m[0][2] = nx * nz * (1 - ca) - ny * sa; | 
|---|
| 212 |   m[1][0] = nx * nz * (1 - ca) - nz * sa; | 
|---|
| 213 |   m[1][1] = ny * ny * (1 - ca) + ca; | 
|---|
| 214 |   m[1][2] = ny * nz * (1 - ca) + nx * sa; | 
|---|
| 215 |   m[2][0] = nx * nz * (1 - ca) + ny * sa; | 
|---|
| 216 |   m[2][1] = ny * nz * (1 - ca) - nx * sa; | 
|---|
| 217 |   m[2][2] = nz * nz * (1 - ca) + ca; | 
|---|
| 218 |  | 
|---|
| 219 |   float x, y, z; | 
|---|
| 220 |   for (int i = 0; i < this->spikes;i++){ | 
|---|
| 221 |     printf("%i ", i); | 
|---|
| 222 |     x = m[0][0] * this->launcher[i].x + m[0][1] * this->launcher[i].y + m[0][2] * this->launcher[i].z; | 
|---|
| 223 |     y = m[1][0] * this->launcher[i].x + m[1][1] * this->launcher[i].y + m[1][2] * this->launcher[i].z; | 
|---|
| 224 |     z = m[2][0] * this->launcher[i].x + m[2][1] * this->launcher[i].y + m[2][2] * this->launcher[i].z; | 
|---|
| 225 | /* | 
|---|
| 226 |     x = this->launcher[i].x * m[0] + this->launcher[i].y * m[1] + this->launcher[i].z * m[2]; | 
|---|
| 227 |     y = this->launcher[i].x * m[3] + this->launcher[i].y * m[4] + this->launcher[i].z * m[5]; | 
|---|
| 228 |     z = this->launcher[i].x * m[6] + this->launcher[i].y * m[7] + this->launcher[i].z * m[8];*/ | 
|---|
| 229 |     this->launcher[i] = Vector (x, y, z); | 
|---|
| 230 |   } | 
|---|
| 231 |   printf("\n"); | 
|---|
| 232 |  | 
|---|
| 233 |   for( int i = 0; i < 3 ; i++) | 
|---|
| 234 |     delete m[i]; | 
|---|
| 235 |   delete m; | 
|---|
| 236 | } | 
|---|
| 237 |  | 
|---|
| 238 |  | 
|---|
| 239 | void SpikeLauncher::fire() | 
|---|
| 240 | { | 
|---|
| 241 |   updateFireDir(VECTOR_RAND(1), 20); | 
|---|
| 242 |  | 
|---|
| 243 |   Projectile* pj = NULL; | 
|---|
| 244 |   for (int i = 0; i < this->spikes; i++) | 
|---|
| 245 |   { | 
|---|
| 246 |     pj  = this->getProjectile(); | 
|---|
| 247 |     if (pj == NULL) // if true, we do have a problem!! | 
|---|
| 248 |       return; | 
|---|
| 249 |  | 
|---|
| 250 |     pj->setVelocity(this->launcher[i].getNormalized() * 300.0); | 
|---|
| 251 |  | 
|---|
| 252 |     pj->setParent(PNode::getNullParent()); | 
|---|
| 253 |     pj->setAbsCoor(this->getAbsCoor() + this->launcher[i] * this->size); | 
|---|
| 254 |     Quaternion q; | 
|---|
| 255 |     pj->setRelDir(q.lookAt(Vector(), this->launcher[i], VECTOR_RAND(1))); | 
|---|
| 256 |  | 
|---|
| 257 |     pj->activate(); | 
|---|
| 258 |   } | 
|---|
| 259 | } | 
|---|