Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/world_entities/playable.cc @ 9173

Last change on this file since 9173 was 9110, checked in by bensch, 18 years ago

orxonox/trunk: merged the Presentation back

File size: 13.0 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 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: Silvan Nellen
13   co-programmer: Benjamin Knecht
14*/
15
16
17#include "playable.h"
18
19#include "key_mapper.h"
20
21#include "player.h"
22#include "state.h"
23#include "camera.h"
24
25#include "util/loading/load_param.h"
26
27#include "power_ups/weapon_power_up.h"
28#include "power_ups/param_power_up.h"
29
30#include "game_rules.h"
31
32#include "dot_emitter.h"
33#include "sprite_particles.h"
34
35#include "shared_network_data.h"
36
37#include "effects/explosion.h"
38#include "kill.cc"
39
40#include "shell_command.h"
41SHELL_COMMAND_STATIC(orxoWeapon, Playable, Playable::addSomeWeapons_CHEAT)
42  ->setAlias("orxoWeapon");
43
44
45Playable::Playable()
46    : weaponMan(this),
47    supportedPlaymodes(Playable::Full3D),
48    playmode(Playable::Full3D)
49{
50  this->setClassID(CL_PLAYABLE, "Playable");
51  PRINTF(4)("PLAYABLE INIT\n");
52
53  this->toList(OM_GROUP_01);
54
55  // the reference to the Current Player is NULL, because we dont have one at the beginning.
56  this->currentPlayer = NULL;
57
58  this->bFire = false;
59  this->oldFlags = 0;
60
61  this->setSynchronized(true);
62
63  this->score = 0;
64  this->collider = NULL;
65  this->enterRadius = 10.0f;
66
67  this->bDead = false;
68
69  //subscribe to collision reaction
70  this->subscribeReaction(CREngine::CR_PHYSICS_GROUND_WALK, CL_BSP_ENTITY);
71
72  registerVar( new SynchronizeableInt( &score, &score, "score" ) );
73  registerVar( new SynchronizeableBool( &bFire, &bFire, "bFire", PERMISSION_OWNER));
74}
75
76
77/**
78 * @brief destroys the Playable
79 */
80Playable::~Playable()
81{
82  // THE DERIVED CLASS MUST UNSUBSCRIBE THE PLAYER THROUGH
83  // this->setPlayer(NULL);
84  // IN ITS DESTRUCTOR.
85
86  assert(this->currentPlayer == NULL);
87}
88
89/**
90 * @brief loads Playable parameters onto the Playable
91 * @param root the XML-root to load from
92 */
93void Playable::loadParams(const TiXmlElement* root)
94{
95  WorldEntity::loadParams(root);
96
97  LoadParam(root, "abs-dir", this, Playable, setPlayDirection);
98  LoadParam(root, "enter-radius", this, Playable, setEnterRadius)
99      .describe("The Distance one can enter the ship from.");
100}
101
102/**
103 * @brief picks up a powerup
104 * @param powerUp the PowerUp that should be picked.
105 * @returns true on success (pickup was picked, false otherwise)
106 *
107 * This function also checks if the Pickup can be picked up by this Playable
108 */
109bool Playable::pickup(PowerUp* powerUp)
110{
111  if(powerUp->isA(CL_WEAPON_POWER_UP))
112  {
113    return dynamic_cast<WeaponPowerUp*>(powerUp)->process(&this->getWeaponManager());
114  }
115  else if(powerUp->isA(CL_PARAM_POWER_UP))
116  {
117    ParamPowerUp* ppu = dynamic_cast<ParamPowerUp*>(powerUp);
118    switch(ppu->getType())
119    {
120      case POWERUP_PARAM_HEALTH:
121        this->increaseHealth(ppu->getValue());
122        return true;
123      case POWERUP_PARAM_MAX_HEALTH:
124        this->increaseHealthMax(ppu->getValue());
125        return true;
126      default:
127        /// EVERYTHING THAT IS NOT HANDLED
128        /// FIXME
129        return false;
130    }
131  }
132  return false;
133}
134
135/**
136 * @brief adds a Weapon to the Playable.
137 * @param weapon the Weapon to add.
138 * @param configID the Configuration ID to add this weapon to.
139 * @param slotID the slotID to add the Weapon to.
140 */
141bool Playable::addWeapon(Weapon* weapon, int configID, int slotID)
142{
143  if(this->weaponMan.addWeapon(weapon, configID, slotID))
144  {
145    this->weaponConfigChanged();
146    return true;
147  }
148  else
149  {
150    if (weapon != NULL)
151      PRINTF(2)("Unable to add Weapon (%s::%s) to %s::%s\n",
152                weapon->getClassName(), weapon->getName(), this->getClassName(), this->getName());
153    else
154      PRINTF(2)("No weapon defined\n");
155    return false;
156
157  }
158}
159
160/**
161 * @brief removes a Weapon.
162 * @param weapon the Weapon to remove.
163 */
164void Playable::removeWeapon(Weapon* weapon)
165{
166  this->weaponMan.removeWeapon(weapon);
167
168  this->weaponConfigChanged();
169}
170
171/**
172 * @brief jumps to the next WeaponConfiguration
173 */
174void Playable::nextWeaponConfig()
175{
176  this->weaponMan.nextWeaponConfig();
177  this->weaponConfigChanged();
178}
179
180/**
181 * @brief moves to the last WeaponConfiguration
182 */
183void Playable::previousWeaponConfig()
184{
185  this->weaponMan.previousWeaponConfig();
186  this->weaponConfigChanged();
187}
188
189/**
190 * @brief tells the Player, that the Weapon-Configuration has changed.
191 *
192 * TODO remove this
193 * This function is needed, so that the WeponManager of this Playable can easily update the HUD
194 */
195void Playable::weaponConfigChanged()
196{
197  if (this->currentPlayer != NULL)
198    this->currentPlayer->weaponConfigChanged();
199}
200
201/**
202 * @brief a Cheat that gives us some Weapons
203 */
204void Playable::addSomeWeapons_CHEAT()
205{
206  if (State::getPlayer() != NULL)
207  {
208    Playable* playable = State::getPlayer()->getPlayable();
209    if (playable != NULL)
210    {
211      PRINTF(2)("ADDING WEAPONS - you cheater\n");
212      playable->addWeapon(Weapon::createWeapon(CL_HYPERBLASTER));
213      playable->addWeapon(Weapon::createWeapon(CL_TURRET));
214      playable->addWeapon(Weapon::createWeapon(CL_AIMING_TURRET));
215      playable->addWeapon(Weapon::createWeapon(CL_CANNON));
216      playable->addWeapon(Weapon::createWeapon(CL_TARGETING_TURRET));
217      PRINTF(2)("ADDING WEAPONS FINISHED\n");
218    }
219  }
220}
221
222/**
223 * @brief subscribe to all events the controllable needs
224 * @param player the player that shall controll this Playable
225 * @returns false on error true otherwise.
226 */
227bool Playable::setPlayer(Player* player)
228{
229  // if we already have a Player inside do nothing
230  if (this->currentPlayer != NULL && player != NULL)
231  {
232    return false;
233  }
234
235  // eject the Player if player == NULL
236  if (this->currentPlayer != NULL && player == NULL)
237  {
238    PRINTF(4)("Player gets ejected\n");
239
240    // unsubscibe all events.
241    std::vector<int>::iterator ev;
242    for (ev = this->events.begin(); ev != events.end(); ev++)
243      player->unsubscribeEvent(ES_GAME, (*ev));
244
245    // leave the entity
246    this->leave();
247
248    // eject the current Player.
249    Player* ejectPlayer = this->currentPlayer;
250    this->currentPlayer = NULL;
251    // eject the Player.
252    ejectPlayer->setPlayable(NULL);
253
254    return true;
255  }
256
257  // get the new Player inside
258  if (this->currentPlayer == NULL && player != NULL)
259  {
260    PRINTF(4)("New Player gets inside\n");
261    this->currentPlayer = player;
262    if (this->currentPlayer->getPlayable() != this)
263      this->currentPlayer->setPlayable(this);
264
265    /*EventHandler*/
266    std::vector<int>::iterator ev;
267    for (ev = this->events.begin(); ev != events.end(); ev++)
268      player->subscribeEvent(ES_GAME, (*ev));
269
270    this->enter();
271    return true;
272  }
273
274  return false;
275}
276
277/**
278 * @brief attaches the current Camera to this Playable
279 *
280 * this function can be derived, so that any Playable can make the attachment differently.
281 */
282void Playable::attachCamera()
283{
284  State::getCameraNode()->setParentSoft(this);
285  State::getCameraTargetNode()->setParentSoft(this);
286
287}
288
289/**
290 * @brief detaches the Camera
291 * @see void Playable::attachCamera()
292 */
293void  Playable::detachCamera()
294{
295}
296
297
298/**
299 * @brief sets the CameraMode.
300 * @param cameraMode: the Mode to switch to.
301 */
302void Playable::setCameraMode(unsigned int cameraMode)
303{
304  State::getCamera()->setViewMode((Camera::ViewMode)cameraMode);
305}
306
307
308/**
309 * @brief sets the Playmode
310 * @param playmode the Playmode
311 * @returns true on success, false otherwise
312 */
313bool Playable::setPlaymode(Playable::Playmode playmode)
314{
315  if (!this->playmodeSupported(playmode))
316    return false;
317  else
318  {
319    this->enterPlaymode(playmode);
320    this->playmode = playmode;
321    return true;
322  }
323}
324
325/**
326 * @brief This function look, that the Playable rotates to the given rotation.
327 * @param angle the Angle around
328 * @param dirX directionX
329 * @param dirY directionY
330 * @param dirZ directionZ
331 * @param speed how fast to turn there.
332 */
333void Playable::setPlayDirection(float angle, float dirX, float dirY, float dirZ, float speed)
334{
335  this->setPlayDirection(Quaternion(angle, Vector(dirX, dirY, dirZ)), speed);
336}
337
338/**
339 * @brief all Playable will enter the Playmode Differently, say here how to do it.
340 * @param playmode the Playmode to enter.
341 *
342 * In this function all the actions that are required to enter the Playmode are described.
343 * e.g: camera, rotation, wait cycle and so on...
344 *
345 * on enter of this function the playmode is still the old playmode.
346 */
347void Playable::enterPlaymode(Playable::Playmode playmode)
348{
349  switch(playmode)
350  {
351    default:
352      this->attachCamera();
353      break;
354    case Playable::Horizontal:
355      this->setCameraMode(Camera::ViewTop);
356      break;
357    case Playable::Vertical:
358      this->setCameraMode(Camera::ViewLeft);
359      break;
360    case Playable::FromBehind:
361      this->setCameraMode(Camera::ViewBehind);
362      break;
363  }
364}
365/**
366 * @brief helps us colliding Playables
367 * @param entity the Entity to collide
368 * @param location where the collision occured.
369 */
370void Playable::collidesWith(WorldEntity* entity, const Vector& location)
371{
372  if (entity == collider)
373    return;
374  collider = entity;
375
376  if ( entity->isA(CL_PROJECTILE) && ( !State::isOnline() || SharedNetworkData::getInstance()->isGameServer() ) )
377  {
378    this->decreaseHealth(entity->getHealth() *(float)rand()/(float)RAND_MAX);
379    // EXTREME HACK
380    if (this->getHealth() <= 0.0f)
381    {
382//       this->destory();
383
384      if( State::getGameRules() != NULL)
385        State::getGameRules()->registerKill(Kill(entity, this));
386    }
387  }
388}
389
390
391void Playable::respawn()
392{
393  PRINTF(0)("Playable respawn\n");
394  // only if this is the spaceship of the player
395  if( this == State::getPlayer()->getPlayable())
396    State::getGameRules()->onPlayerSpawn();
397
398  this->reset();
399  this->bDead = false;
400}
401
402
403
404
405void Playable::destroy()
406{
407  Explosion::explode(dynamic_cast<PNode*>(this), Vector(1.0f, 1.0f, 1.0f));
408
409
410  if( !this->bDead)
411  {
412    PRINTF(0)("Playable dies\n");
413    // only if this is the spaceship of the player
414    if (State::isOnline())
415    {
416      if( this == State::getPlayer()->getPlayable())
417        State::getGameRules()->onPlayerDeath();
418
419      //     this->toList(OM_GROUP_05);
420      //HACK: moves the entity to an unknown place far far away: in the future, GameRules will look for that
421      this->setAbsCoor(-2000.0, -2000.0, -2000.0);
422
423      //explosion hack
424
425    }
426    this->bDead = true;
427  }
428}
429
430
431
432
433
434/**
435 * @brief add an event to the event list of events this Playable can capture
436 * @param eventType the Type of event to add
437 */
438void Playable::registerEvent(int eventType)
439{
440  this->events.push_back(eventType);
441
442  if (this->currentPlayer != NULL)
443    this->currentPlayer->subscribeEvent(ES_GAME, eventType);
444}
445
446/**
447 * @brief remove an event to the event list this Playable can capture.
448 * @param event the event to unregister.
449 */
450void Playable::unregisterEvent(int eventType)
451{
452  std::vector<int>::iterator rmEvent = std::find(this->events.begin(), this->events.end(), eventType);
453  this->events.erase(rmEvent);
454
455  if (this->currentPlayer != NULL)
456    this->currentPlayer->unsubscribeEvent(ES_GAME, eventType);
457}
458
459/**
460 * @brief ticks a Playable
461 * @param dt: the passed time since the last Tick
462 */
463void Playable::tick(float dt)
464{
465  this->weaponMan.tick(dt);
466  if (this->bFire)
467    weaponMan.fire();
468}
469
470
471/**
472 * @brief processes Playable events.
473 * @param event the Captured Event.
474 */
475void Playable::process(const Event &event)
476{
477  if( event.type == KeyMapper::PEV_FIRE1)
478    this->bFire = event.bPressed;
479  else if( event.type == KeyMapper::PEV_NEXT_WEAPON && event.bPressed)
480  {
481    this->nextWeaponConfig();
482  }
483  else if ( event.type == KeyMapper::PEV_PREVIOUS_WEAPON && event.bPressed)
484    this->previousWeaponConfig();
485}
486
487
488
489/**
490 * @brief converts a string into a Playable::Playmode.
491 * @param playmode the string naming the Playable::Playmode to convert.
492 * @returns the Playable::Playmode converted from playmode.
493 */
494Playable::Playmode Playable::stringToPlaymode(const std::string& playmode)
495{
496  if (playmode == Playable::playmodeNames[0])
497    return Playable::Vertical;
498  if (playmode == Playable::playmodeNames[1])
499    return Playable::Horizontal;
500  if (playmode == Playable::playmodeNames[2])
501    return Playable::FromBehind;
502  if (playmode == Playable::playmodeNames[3])
503    return Playable::Full3D;
504  if (playmode == Playable::playmodeNames[4])
505    return Playable::FirstPerson;
506
507  return Playable::Full3D;
508}
509
510
511/**
512 * @brief converts a playmode into a string.
513 * @param playmode the Playable::Playmode to convert.
514 * @returns the String.
515 */
516const std::string& Playable::playmodeToString(Playable::Playmode playmode)
517{
518  switch(playmode)
519  {
520    case Playable::Vertical:
521      return Playable::playmodeNames[0];
522    case Playable::Horizontal:
523      return Playable::playmodeNames[1];
524    case Playable::FromBehind:
525      return Playable::playmodeNames[2];
526    case Playable::Full3D:
527      return Playable::playmodeNames[3];
528    case Playable::FirstPerson:
529      return Playable::playmodeNames[4];
530
531    default:
532      return Playable::playmodeNames[3];
533  }
534}
535
536/**
537 * @brief PlaymodeNames
538 */
539const std::string Playable::playmodeNames[] =
540{
541  "Vertical",
542  "Horizontal",
543  "FromBehind",
544  "Full3D",
545  "FirstPerson"
546};
Note: See TracBrowser for help on using the repository browser.