Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/vs-enhencements/src/world_entities/playable.cc @ 10692

Last change on this file since 10692 was 10678, checked in by nicolasc, 17 years ago

xfer

File size: 13.1 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 "tools/camera.h"
24
25#include "util/loading/load_param.h"
26
27#include "items/power_ups/weapon_power_up.h"
28#include "items/power_ups/param_power_up.h"
29
30#include "game_rules.h"
31
32#include "particles/dot_emitter.h"
33#include "particles/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");
43ObjectListDefinition(Playable);
44
45Playable::Playable()
46    : weaponMan(this)
47    ,supportedPlaymodes(Playable::Full3D),
48    playmode(Playable::Full3D)
49{
50  this->registerObject(this, Playable::_objectList);
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
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 ) );
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  if (!root)
96    return;
97  WorldEntity::loadParams(root);
98
99  LoadParam(root, "abs-dir", this, Playable, setPlayDirection);
100  LoadParam(root, "enter-radius", this, Playable, setEnterRadius)
101      .describe("The Distance one can enter the ship from.");
102}
103
104/**
105 * @brief picks up a powerup
106 * @param powerUp the PowerUp that should be picked.
107 * @returns true on success (pickup was picked, false otherwise)
108 *
109 * This function also checks if the Pickup can be picked up by this Playable
110 */
111bool Playable::pickup(PowerUp* powerUp)
112{
113  /// FIXME TOTALLY
114  if(powerUp->isA(WeaponPowerUp::staticClassID()))
115  {
116    return static_cast<WeaponPowerUp*>(powerUp)->process(&this->getWeaponManager());
117  }
118  else if(powerUp->isA(ParamPowerUp::staticClassID()))
119  {
120    ParamPowerUp* ppu = static_cast<ParamPowerUp*>(powerUp);
121    switch(ppu->getType())
122    {
123      case POWERUP_PARAM_HEALTH:
124        this->increaseHealth(ppu->getValue());
125        return true;
126      case POWERUP_PARAM_MAX_HEALTH:
127        this->increaseHealthMax(ppu->getValue());
128        return true;
129      default:
130        /// EVERYTHING THAT IS NOT HANDLED
131        /// FIXME
132        return false;
133    }
134  }
135  return false;
136}
137
138/**
139 * @brief adds a Weapon to the Playable.
140 * @param weapon the Weapon to add.
141 * @param configID the Configuration ID to add this weapon to.
142 * @param slotID the slotID to add the Weapon to.
143 */
144bool Playable::addWeapon(Weapon* weapon, int configID, int slotID)
145{
146  weapon->setOwner(this->getOwner());
147
148
149  if(this->weaponMan.addWeapon(weapon, configID, slotID))
150  {
151    this->weaponConfigChanged();
152    return true;
153  }
154  else
155  {
156    if (weapon != NULL)
157      PRINTF(2)("Unable to add Weapon (%s::%s) to %s::%s\n",
158                weapon->getClassCName(), weapon->getCName(), this->getClassCName(), this->getCName());
159    else
160      PRINTF(2)("No weapon defined\n");
161    return false;
162
163  }
164}
165
166/**
167 * @brief removes a Weapon.
168 * @param weapon the Weapon to remove.
169 */
170void Playable::removeWeapon(Weapon* weapon)
171{
172  this->weaponMan.removeWeapon(weapon);
173
174  this->weaponConfigChanged();
175}
176
177/**
178 * @brief jumps to the next WeaponConfiguration
179 */
180void Playable::nextWeaponConfig()
181{
182  this->weaponMan.nextWeaponConfig();
183  this->weaponConfigChanged();
184}
185
186/**
187 * @brief moves to the last WeaponConfiguration
188 */
189void Playable::previousWeaponConfig()
190{
191  this->weaponMan.previousWeaponConfig();
192  this->weaponConfigChanged();
193}
194
195/**
196 * @brief tells the Player, that the Weapon-Configuration has changed.
197 *
198 * TODO remove this
199 * This function is needed, so that the WeponManager of this Playable can easily update the HUD
200 */
201void Playable::weaponConfigChanged()
202{
203  if (this->currentPlayer != NULL)
204    this->currentPlayer->weaponConfigChanged();
205}
206
207/**
208 * @brief a Cheat that gives us some Weapons
209 */
210void Playable::addSomeWeapons_CHEAT()
211{
212  if (State::getPlayer() != NULL)
213  {
214    Playable* playable = State::getPlayer()->getPlayable();
215    if (playable != NULL)
216    {
217      PRINTF(2)("ADDING WEAPONS - you cheater\n");
218      playable->addWeapon(Weapon::createWeapon("Hyperblaster"));
219      playable->addWeapon(Weapon::createWeapon("Turret"));
220      playable->addWeapon(Weapon::createWeapon("AimingTurret"));
221      playable->addWeapon(Weapon::createWeapon("Cannon"));
222      playable->addWeapon(Weapon::createWeapon("TargetingTurret"));
223      PRINTF(2)("ADDING WEAPONS FINISHED\n");
224    }
225  }
226}
227
228/**
229 * @brief subscribe to all events the controllable needs
230 * @param player the player that shall controll this Playable
231 * @returns false on error true otherwise.
232 */
233bool Playable::setPlayer(Player* player)
234{
235  // if we already have a Player inside do nothing
236  if (this->currentPlayer != NULL && player != NULL)
237  {
238    return false;
239  }
240
241  // eject the Player if player == NULL
242  if (this->currentPlayer != NULL && player == NULL)
243  {
244    PRINTF(4)("Player gets ejected\n");
245
246    // unsubscibe all events.
247    std::vector<int>::iterator ev;
248    for (ev = this->events.begin(); ev != events.end(); ev++)
249      player->unsubscribeEvent(ES_GAME, (*ev));
250
251    // leave the entity
252    this->leave();
253
254    // eject the current Player.
255    Player* ejectPlayer = this->currentPlayer;
256    this->currentPlayer = NULL;
257    // eject the Player.
258    ejectPlayer->setPlayable(NULL);
259
260    return true;
261  }
262
263  // get the new Player inside
264  if (this->currentPlayer == NULL && player != NULL)
265  {
266    PRINTF(4)("New Player gets inside\n");
267    this->currentPlayer = player;
268    if (this->currentPlayer->getPlayable() != this)
269      this->currentPlayer->setPlayable(this);
270
271    /*EventHandler*/
272    std::vector<int>::iterator ev;
273    for (ev = this->events.begin(); ev != events.end(); ev++)
274      player->subscribeEvent(ES_GAME, (*ev));
275
276    this->enter();
277    return true;
278  }
279
280  return false;
281}
282
283
284/**
285 * @brief sets the TeamID and all the properties needed to be visible on the Playable
286 * @param teamID: the new TeamID of the Entity
287 */
288void Playable::setTeam(int teamID)
289{
290  /// Derive this function to make it look different with differen groups.
291  PRINTF(4)("No special team specific function implemented for %s::%s in Team %d\n", this->getClassCName(), this->getCName(), teamID);
292}
293
294
295/**
296 * @brief attaches the current Camera to this Playable
297 *
298 * this function can be derived, so that any Playable can make the attachment differently.
299 */
300void Playable::attachCamera()
301{
302  State::getCameraNode()->setParentSoft(this);
303  State::getCameraTargetNode()->setParentSoft(this);
304
305}
306
307/**
308 * @brief detaches the Camera
309 * @see void Playable::attachCamera()
310 */
311void  Playable::detachCamera()
312{
313}
314
315
316/**
317 * @brief sets the CameraMode.
318 * @param cameraMode: the Mode to switch to.
319 */
320void Playable::setCameraMode(unsigned int cameraMode)
321{
322  State::getCamera()->setViewMode((Camera::ViewMode)cameraMode);
323}
324
325
326/**
327 * @brief sets the Playmode
328 * @param playmode the Playmode
329 * @returns true on success, false otherwise
330 */
331bool Playable::setPlaymode(Playable::Playmode playmode)
332{
333  if (!this->playmodeSupported(playmode))
334    return false;
335  else
336  {
337    this->enterPlaymode(playmode);
338    this->playmode = playmode;
339    return true;
340  }
341}
342
343/**
344 * @brief This function look, that the Playable rotates to the given rotation.
345 * @param angle the Angle around
346 * @param dirX directionX
347 * @param dirY directionY
348 * @param dirZ directionZ
349 * @param speed how fast to turn there.
350 */
351void Playable::setPlayDirection(float angle, float dirX, float dirY, float dirZ, float speed)
352{
353  this->setPlayDirection(Quaternion(angle, Vector(dirX, dirY, dirZ)), speed);
354}
355
356/**
357 * @brief all Playable will enter the Playmode Differently, say here how to do it.
358 * @param playmode the Playmode to enter.
359 *
360 * In this function all the actions that are required to enter the Playmode are described.
361 * e.g: camera, rotation, wait cycle and so on...
362 *
363 * on enter of this function the playmode is still the old playmode.
364 */
365void Playable::enterPlaymode(Playable::Playmode playmode)
366{
367  switch(playmode)
368  {
369    default:
370      this->attachCamera();
371      break;
372    case Playable::Horizontal:
373      this->setCameraMode(Camera::ViewTop);
374      break;
375    case Playable::Vertical:
376      this->setCameraMode(Camera::ViewLeft);
377      break;
378    case Playable::FromBehind:
379      this->setCameraMode(Camera::ViewBehind);
380      break;
381  }
382}
383
384
385void Playable::respawn()
386{
387  PRINTF(0)("Playable respawn\n");
388  // only if this is the spaceship of the player
389  if( State::getGameRules() && State::getPlayer() && this == State::getPlayer()->getPlayable())
390    State::getGameRules()->onPlayerSpawn();
391
392  this->reset();
393  this->bDead = false;
394}
395
396
397
398
399void Playable::destroy(WorldEntity* killer)
400{
401  if( !this->bDead)
402  {
403    PRINTF(0)("Playable dies\n");
404    // only if this is the spaceship of the player
405    if (State::isOnline())
406    {
407      if( this == State::getPlayer()->getPlayable())
408        State::getGameRules()->onPlayerDeath();
409    }
410    this->bDead = true;
411
412    if( State::getGameRules() != NULL)
413      State::getGameRules()->registerKill(Kill(killer, this));
414  }
415}
416
417
418
419
420
421/**
422 * @brief add an event to the event list of events this Playable can capture
423 * @param eventType the Type of event to add
424 */
425void Playable::registerEvent(int eventType)
426{
427  this->events.push_back(eventType);
428
429  if (this->currentPlayer != NULL)
430    this->currentPlayer->subscribeEvent(ES_GAME, eventType);
431}
432
433/**
434 * @brief remove an event to the event list this Playable can capture.
435 * @param event the event to unregister.
436 */
437void Playable::unregisterEvent(int eventType)
438{
439  std::vector<int>::iterator rmEvent = std::find(this->events.begin(), this->events.end(), eventType);
440  this->events.erase(rmEvent);
441
442  if (this->currentPlayer != NULL)
443    this->currentPlayer->unsubscribeEvent(ES_GAME, eventType);
444}
445
446/**
447 * @brief ticks a Playable
448 * @param dt: the passed time since the last Tick
449 */
450void Playable::tick(float dt)
451{
452  this->weaponMan.tick(dt);
453  if (this->bFire)
454    weaponMan.fire();
455}
456
457
458/**
459 * @brief processes Playable events.
460 * @param event the Captured Event.
461 */
462void Playable::process(const Event &event)
463{
464  if( event.type == KeyMapper::PEV_FIRE1)
465    this->bFire = event.bPressed;
466  else if( event.type == KeyMapper::PEV_NEXT_WEAPON && event.bPressed)
467  {
468    this->nextWeaponConfig();
469  }
470  else if ( event.type == KeyMapper::PEV_PREVIOUS_WEAPON && event.bPressed)
471    this->previousWeaponConfig();
472}
473
474
475
476/**
477 * @brief converts a string into a Playable::Playmode.
478 * @param playmode the string naming the Playable::Playmode to convert.
479 * @returns the Playable::Playmode converted from playmode.
480 */
481Playable::Playmode Playable::stringToPlaymode(const std::string& playmode)
482{
483  if (playmode == Playable::playmodeNames[0])
484    return Playable::Vertical;
485  if (playmode == Playable::playmodeNames[1])
486    return Playable::Horizontal;
487  if (playmode == Playable::playmodeNames[2])
488    return Playable::FromBehind;
489  if (playmode == Playable::playmodeNames[3])
490    return Playable::Full3D;
491  if (playmode == Playable::playmodeNames[4])
492    return Playable::FirstPerson;
493
494  return Playable::Full3D;
495}
496
497
498/**
499 * @brief converts a playmode into a string.
500 * @param playmode the Playable::Playmode to convert.
501 * @returns the String.
502 */
503const std::string& Playable::playmodeToString(Playable::Playmode playmode)
504{
505  switch(playmode)
506  {
507    case Playable::Vertical:
508      return Playable::playmodeNames[0];
509    case Playable::Horizontal:
510      return Playable::playmodeNames[1];
511    case Playable::FromBehind:
512      return Playable::playmodeNames[2];
513    case Playable::Full3D:
514      return Playable::playmodeNames[3];
515    case Playable::FirstPerson:
516      return Playable::playmodeNames[4];
517
518    default:
519      return Playable::playmodeNames[3];
520  }
521}
522
523/**
524 * @brief PlaymodeNames
525 */
526const std::string Playable::playmodeNames[] =
527{
528  "Vertical",
529  "Horizontal",
530  "FromBehind",
531  "Full3D",
532  "FirstPerson"
533};
534
535
536/**
537 * handler for changes on registred vars
538 * @param id id's which changed
539 */
540void Playable::varChangeHandler( std::list< int > & id )
541{
542  if ( std::find( id.begin(), id.end(), this->teamChangeHandler) != id.end() )
543  {
544    this->setTeam(this->teamId);
545  }
546
547  WorldEntity::varChangeHandler(id);
548}
Note: See TracBrowser for help on using the repository browser.