Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/playability/src/world_entities/playable.cc @ 10589

Last change on this file since 10589 was 10368, checked in by patrick, 18 years ago

merged the branche playability into the trunk

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