Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9543 was 9507, checked in by patrick, 18 years ago

the player team change should now work on all clients in the network, its now a global synch variable

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