Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: merged the proxy bache back with no conflicts

File size: 12.9 KB
RevLine 
[5838]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:
[5841]12   main-programmer: Silvan Nellen
13   co-programmer: Benjamin Knecht
[5838]14*/
15
[5881]16
[5838]17#include "playable.h"
[5895]18
[7868]19#include "key_mapper.h"
20
[5875]21#include "player.h"
[6241]22#include "state.h"
[7347]23#include "camera.h"
24
[7193]25#include "util/loading/load_param.h"
[5838]26
[6547]27#include "power_ups/weapon_power_up.h"
28#include "power_ups/param_power_up.h"
[5872]29
[7044]30#include "game_rules.h"
[6547]31
[6959]32#include "dot_emitter.h"
33#include "sprite_particles.h"
34
[7121]35#include "shared_network_data.h"
36
[7118]37#include "effects/explosion.h"
[7482]38#include "kill.cc"
[6959]39
[7350]40#include "shell_command.h"
[7356]41SHELL_COMMAND_STATIC(orxoWeapon, Playable, Playable::addSomeWeapons_CHEAT)
42  ->setAlias("orxoWeapon");
[7118]43
[7350]44
[5838]45Playable::Playable()
[7338]46    : weaponMan(this),
47    supportedPlaymodes(Playable::Full3D),
48    playmode(Playable::Full3D)
[5838]49{
[6442]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;
[6695]57
[6804]58  this->bFire = false;
[6868]59  this->oldFlags = 0;
[6804]60
[6695]61  this->setSynchronized(true);
[6959]62
63  this->score = 0;
[7713]64  this->collider = NULL;
[9061]65  this->enterRadius = 10.0f;
[6959]66
[7118]67  this->bDead = false;
[9008]68
[8490]69
[9656]70  this->teamChangeHandler = registerVarId( new SynchronizeableInt( &this->teamId, &this->teamId, "team-id", PERMISSION_MASTER_SERVER ) );
71
72  registerVar( new SynchronizeableInt( &score, &score, "score", PERMISSION_MASTER_SERVER ) );
[7954]73  registerVar( new SynchronizeableBool( &bFire, &bFire, "bFire", PERMISSION_OWNER));
[5838]74}
75
[6695]76
[7346]77/**
78 * @brief destroys the Playable
79 */
[5875]80Playable::~Playable()
[5838]81{
[6986]82  // THE DERIVED CLASS MUST UNSUBSCRIBE THE PLAYER THROUGH
83  // this->setPlayer(NULL);
84  // IN ITS DESTRUCTOR.
[8316]85
[6986]86  assert(this->currentPlayer == NULL);
[5875]87}
88
[7346]89/**
90 * @brief loads Playable parameters onto the Playable
91 * @param root the XML-root to load from
92 */
[7092]93void Playable::loadParams(const TiXmlElement* root)
94{
95  WorldEntity::loadParams(root);
96
[7346]97  LoadParam(root, "abs-dir", this, Playable, setPlayDirection);
[9061]98  LoadParam(root, "enter-radius", this, Playable, setEnterRadius)
99      .describe("The Distance one can enter the ship from.");
[7092]100}
101
[7346]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;
[8316]126      default:
127        /// EVERYTHING THAT IS NOT HANDLED
128        /// FIXME
129        return false;
[7346]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 */
[7350]141bool Playable::addWeapon(Weapon* weapon, int configID, int slotID)
[6443]142{
[9656]143  weapon->setOwner(this->getOwner());
144
145
[7350]146  if(this->weaponMan.addWeapon(weapon, configID, slotID))
147  {
148    this->weaponConfigChanged();
149    return true;
150  }
151  else
152  {
153    if (weapon != NULL)
154      PRINTF(2)("Unable to add Weapon (%s::%s) to %s::%s\n",
[9406]155                weapon->getClassCName(), weapon->getCName(), this->getClassCName(), this->getCName());
[7350]156    else
157      PRINTF(2)("No weapon defined\n");
158    return false;
[6443]159
[7350]160  }
[6443]161}
162
[7346]163/**
164 * @brief removes a Weapon.
165 * @param weapon the Weapon to remove.
166 */
[6443]167void Playable::removeWeapon(Weapon* weapon)
168{
[7337]169  this->weaponMan.removeWeapon(weapon);
[6443]170
[7338]171  this->weaponConfigChanged();
[6443]172}
173
[7346]174/**
175 * @brief jumps to the next WeaponConfiguration
176 */
[6444]177void Playable::nextWeaponConfig()
178{
[7337]179  this->weaponMan.nextWeaponConfig();
[7338]180  this->weaponConfigChanged();
[6444]181}
[6443]182
[7346]183/**
184 * @brief moves to the last WeaponConfiguration
185 */
[6444]186void Playable::previousWeaponConfig()
187{
[7337]188  this->weaponMan.previousWeaponConfig();
[7338]189  this->weaponConfigChanged();
[6444]190}
191
[7346]192/**
193 * @brief tells the Player, that the Weapon-Configuration has changed.
194 *
195 * TODO remove this
196 * This function is needed, so that the WeponManager of this Playable can easily update the HUD
197 */
[6568]198void Playable::weaponConfigChanged()
199{
[6578]200  if (this->currentPlayer != NULL)
201    this->currentPlayer->weaponConfigChanged();
[6568]202}
[6444]203
[7350]204/**
205 * @brief a Cheat that gives us some Weapons
206 */
207void Playable::addSomeWeapons_CHEAT()
208{
[7351]209  if (State::getPlayer() != NULL)
210  {
211    Playable* playable = State::getPlayer()->getPlayable();
212    if (playable != NULL)
213    {
214      PRINTF(2)("ADDING WEAPONS - you cheater\n");
215      playable->addWeapon(Weapon::createWeapon(CL_HYPERBLASTER));
216      playable->addWeapon(Weapon::createWeapon(CL_TURRET));
217      playable->addWeapon(Weapon::createWeapon(CL_AIMING_TURRET));
218      playable->addWeapon(Weapon::createWeapon(CL_CANNON));
219      playable->addWeapon(Weapon::createWeapon(CL_TARGETING_TURRET));
220      PRINTF(2)("ADDING WEAPONS FINISHED\n");
221    }
222  }
[7350]223}
[7346]224
[7173]225/**
[7346]226 * @brief subscribe to all events the controllable needs
227 * @param player the player that shall controll this Playable
228 * @returns false on error true otherwise.
229 */
230bool Playable::setPlayer(Player* player)
231{
232  // if we already have a Player inside do nothing
233  if (this->currentPlayer != NULL && player != NULL)
234  {
235    return false;
236  }
237
238  // eject the Player if player == NULL
239  if (this->currentPlayer != NULL && player == NULL)
240  {
241    PRINTF(4)("Player gets ejected\n");
242
243    // unsubscibe all events.
244    std::vector<int>::iterator ev;
245    for (ev = this->events.begin(); ev != events.end(); ev++)
[7868]246      player->unsubscribeEvent(ES_GAME, (*ev));
[7346]247
248    // leave the entity
249    this->leave();
250
251    // eject the current Player.
252    Player* ejectPlayer = this->currentPlayer;
253    this->currentPlayer = NULL;
254    // eject the Player.
255    ejectPlayer->setPlayable(NULL);
256
257    return true;
258  }
259
260  // get the new Player inside
261  if (this->currentPlayer == NULL && player != NULL)
262  {
263    PRINTF(4)("New Player gets inside\n");
264    this->currentPlayer = player;
265    if (this->currentPlayer->getPlayable() != this)
266      this->currentPlayer->setPlayable(this);
267
268    /*EventHandler*/
269    std::vector<int>::iterator ev;
270    for (ev = this->events.begin(); ev != events.end(); ev++)
[7868]271      player->subscribeEvent(ES_GAME, (*ev));
[7346]272
273    this->enter();
274    return true;
275  }
276
277  return false;
278}
279
[9656]280
[7346]281/**
[9656]282 * @brief sets the TeamID and all the properties needed to be visible on the Playable
283 * @param teamID: the new TeamID of the Entity
284 */
285void Playable::setTeam(int teamID)
286{
287  /// Derive this function to make it look different with differen groups.
288  PRINTF(4)("No special team specific function implemented for %s::%s in Team %d\n", this->getClassCName(), this->getCName(), teamID);
289}
290
291
292/**
[7346]293 * @brief attaches the current Camera to this Playable
294 *
295 * this function can be derived, so that any Playable can make the attachment differently.
296 */
297void Playable::attachCamera()
298{
299  State::getCameraNode()->setParentSoft(this);
300  State::getCameraTargetNode()->setParentSoft(this);
301
302}
303
304/**
305 * @brief detaches the Camera
306 * @see void Playable::attachCamera()
307 */
308void  Playable::detachCamera()
[8147]309{
310}
[7346]311
312
313/**
[7173]314 * @brief sets the CameraMode.
315 * @param cameraMode: the Mode to switch to.
316 */
317void Playable::setCameraMode(unsigned int cameraMode)
[7347]318{
319  State::getCamera()->setViewMode((Camera::ViewMode)cameraMode);
320}
[7338]321
[7346]322
[7338]323/**
324 * @brief sets the Playmode
325 * @param playmode the Playmode
326 * @returns true on success, false otherwise
327 */
[7339]328bool Playable::setPlaymode(Playable::Playmode playmode)
[7173]329{
[7338]330  if (!this->playmodeSupported(playmode))
331    return false;
332  else
[7345]333  {
[7347]334    this->enterPlaymode(playmode);
[7338]335    this->playmode = playmode;
[7345]336    return true;
337  }
[7173]338}
339
[7346]340/**
341 * @brief This function look, that the Playable rotates to the given rotation.
342 * @param angle the Angle around
343 * @param dirX directionX
344 * @param dirY directionY
345 * @param dirZ directionZ
346 * @param speed how fast to turn there.
347 */
348void Playable::setPlayDirection(float angle, float dirX, float dirY, float dirZ, float speed)
349{
350  this->setPlayDirection(Quaternion(angle, Vector(dirX, dirY, dirZ)), speed);
351}
[7173]352
[5872]353/**
[7346]354 * @brief all Playable will enter the Playmode Differently, say here how to do it.
355 * @param playmode the Playmode to enter.
356 *
357 * In this function all the actions that are required to enter the Playmode are described.
358 * e.g: camera, rotation, wait cycle and so on...
[7347]359 *
360 * on enter of this function the playmode is still the old playmode.
[7346]361 */
362void Playable::enterPlaymode(Playable::Playmode playmode)
363{
[7347]364  switch(playmode)
365  {
366    default:
367      this->attachCamera();
368      break;
369    case Playable::Horizontal:
370      this->setCameraMode(Camera::ViewTop);
371      break;
372    case Playable::Vertical:
373      this->setCameraMode(Camera::ViewLeft);
374      break;
375    case Playable::FromBehind:
376      this->setCameraMode(Camera::ViewBehind);
377      break;
378  }
[7346]379}
[7072]380
[7482]381
[7044]382void Playable::respawn()
[6966]383{
[7044]384  PRINTF(0)("Playable respawn\n");
385  // only if this is the spaceship of the player
[9235]386  if( State::getGameRules() && State::getPlayer() && this == State::getPlayer()->getPlayable())
[7044]387    State::getGameRules()->onPlayerSpawn();
[6966]388
[7118]389  this->reset();
390  this->bDead = false;
[6436]391}
392
[6966]393
[7088]394
[8724]395
[9235]396void Playable::destroy(WorldEntity* killer)
[7044]397{
[7118]398  if( !this->bDead)
399  {
400    PRINTF(0)("Playable dies\n");
[7338]401    // only if this is the spaceship of the player
[7118]402    if (State::isOnline())
403    {
404      if( this == State::getPlayer()->getPlayable())
405        State::getGameRules()->onPlayerDeath();
406    }
407    this->bDead = true;
[9406]408
[9235]409    if( State::getGameRules() != NULL)
410      State::getGameRules()->registerKill(Kill(killer, this));
[7072]411  }
[7044]412}
413
414
[6986]415
416
417
[5896]418/**
[7346]419 * @brief add an event to the event list of events this Playable can capture
[5898]420 * @param eventType the Type of event to add
[5889]421 */
[5896]422void Playable::registerEvent(int eventType)
[5889]423{
424  this->events.push_back(eventType);
425
[5896]426  if (this->currentPlayer != NULL)
[7868]427    this->currentPlayer->subscribeEvent(ES_GAME, eventType);
[5889]428}
429
[5896]430/**
[7339]431 * @brief remove an event to the event list this Playable can capture.
[5898]432 * @param event the event to unregister.
[5896]433 */
434void Playable::unregisterEvent(int eventType)
435{
[7338]436  std::vector<int>::iterator rmEvent = std::find(this->events.begin(), this->events.end(), eventType);
437  this->events.erase(rmEvent);
[5889]438
[5896]439  if (this->currentPlayer != NULL)
[7868]440    this->currentPlayer->unsubscribeEvent(ES_GAME, eventType);
[5896]441}
[5889]442
[6804]443/**
444 * @brief ticks a Playable
445 * @param dt: the passed time since the last Tick
446 */
447void Playable::tick(float dt)
448{
[7337]449  this->weaponMan.tick(dt);
[6804]450  if (this->bFire)
[7337]451    weaponMan.fire();
[6804]452}
[5896]453
[6804]454
455/**
456 * @brief processes Playable events.
457 * @param event the Captured Event.
458 */
459void Playable::process(const Event &event)
460{
461  if( event.type == KeyMapper::PEV_FIRE1)
462    this->bFire = event.bPressed;
463  else if( event.type == KeyMapper::PEV_NEXT_WEAPON && event.bPressed)
464  {
465    this->nextWeaponConfig();
466  }
467  else if ( event.type == KeyMapper::PEV_PREVIOUS_WEAPON && event.bPressed)
468    this->previousWeaponConfig();
469}
470
471
[6959]472
[7346]473/**
474 * @brief converts a string into a Playable::Playmode.
475 * @param playmode the string naming the Playable::Playmode to convert.
476 * @returns the Playable::Playmode converted from playmode.
477 */
[7339]478Playable::Playmode Playable::stringToPlaymode(const std::string& playmode)
479{
[7412]480  if (playmode == Playable::playmodeNames[0])
[7339]481    return Playable::Vertical;
[7412]482  if (playmode == Playable::playmodeNames[1])
[7339]483    return Playable::Horizontal;
[7412]484  if (playmode == Playable::playmodeNames[2])
[7339]485    return Playable::FromBehind;
[7412]486  if (playmode == Playable::playmodeNames[3])
[7339]487    return Playable::Full3D;
[8055]488  if (playmode == Playable::playmodeNames[4])
489    return Playable::FirstPerson;
[7339]490
491  return Playable::Full3D;
492}
493
[7346]494
495/**
496 * @brief converts a playmode into a string.
497 * @param playmode the Playable::Playmode to convert.
498 * @returns the String.
499 */
[7412]500const std::string& Playable::playmodeToString(Playable::Playmode playmode)
[7339]501{
502  switch(playmode)
503  {
504    case Playable::Vertical:
[7412]505      return Playable::playmodeNames[0];
[7339]506    case Playable::Horizontal:
[7412]507      return Playable::playmodeNames[1];
[7339]508    case Playable::FromBehind:
[7412]509      return Playable::playmodeNames[2];
[7339]510    case Playable::Full3D:
[7412]511      return Playable::playmodeNames[3];
[8055]512    case Playable::FirstPerson:
513      return Playable::playmodeNames[4];
[7339]514
515    default:
[7412]516      return Playable::playmodeNames[3];
[7339]517  }
[7412]518}
[7339]519
[7412]520/**
521 * @brief PlaymodeNames
522 */
523const std::string Playable::playmodeNames[] =
524{
525  "Vertical",
526  "Horizontal",
527  "FromBehind",
[8055]528  "Full3D",
529  "FirstPerson"
[7412]530};
[9656]531
532
533/**
534 * handler for changes on registred vars
535 * @param id id's which changed
536 */
537void Playable::varChangeHandler( std::list< int > & id )
538{
539  if ( std::find( id.begin(), id.end(), this->teamChangeHandler) != id.end() )
540  {
541    this->setTeam(this->teamId);
542  }
543
544  WorldEntity::varChangeHandler(id);
545}
Note: See TracBrowser for help on using the repository browser.