Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8714 was 8490, checked in by patrick, 19 years ago

merged the bsp branche back to trunk

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