Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/proxy/src/world_entities/playable.cc @ 9500

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

compiles again, the Playables should now be able to choose their design per team

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