Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/worldentities/ControllableEntity.cc @ 5929

Last change on this file since 5929 was 5929, checked in by rgrieder, 15 years ago

Merged core5 branch back to the trunk.
Key features include clean level unloading and an extended XML event system.

Two important notes:
Delete your keybindings.ini files! * or you will still get parser errors when loading the key bindings.
Delete build_dir/lib/modules/libgamestates.module! * or orxonox won't start.
Best thing to do is to delete the build folder ;)

  • Property svn:eol-style set to native
File size: 19.0 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      Reto Grieder
26 *
27 */
28
29#include "ControllableEntity.h"
30
31#include <OgreSceneManager.h>
32#include <OgreSceneNode.h>
33
34#include "core/CoreIncludes.h"
35#include "core/ConfigValueIncludes.h"
36#include "core/GameMode.h"
37#include "core/XMLPort.h"
38
39#include "Scene.h"
40#include "infos/PlayerInfo.h"
41#include "controllers/Controller.h"
42#include "graphics/Camera.h"
43#include "worldentities/CameraPosition.h"
44#include "overlays/OverlayGroup.h"
45
46namespace orxonox
47{
48    CreateFactory(ControllableEntity);
49
50    ControllableEntity::ControllableEntity(BaseObject* creator) : MobileEntity(creator)
51    {
52        RegisterObject(ControllableEntity);
53
54        this->bHasLocalController_ = false;
55        this->bHasHumanController_ = false;
56
57        this->server_overwrite_ = 0;
58        this->client_overwrite_ = 0;
59        this->player_ = 0;
60        this->playerID_ = OBJECTID_UNKNOWN;
61        this->hud_ = 0;
62        this->camera_ = 0;
63        this->xmlcontroller_ = 0;
64        this->reverseCamera_ = 0;
65        this->bDestroyWhenPlayerLeft_ = false;
66        this->cameraPositionRootNode_ = this->node_->createChildSceneNode();
67        this->bMouseLook_ = false;
68        this->mouseLookSpeed_ = 200;
69
70        this->server_position_         = Vector3::ZERO;
71        this->client_position_         = Vector3::ZERO;
72        this->server_linear_velocity_  = Vector3::ZERO;
73        this->client_linear_velocity_  = Vector3::ZERO;
74        this->server_orientation_      = Quaternion::IDENTITY;
75        this->client_orientation_      = Quaternion::IDENTITY;
76        this->server_angular_velocity_ = Vector3::ZERO;
77        this->client_angular_velocity_ = Vector3::ZERO;
78
79
80        this->setConfigValues();
81        this->setPriority( Priority::VeryHigh );
82        this->registerVariables();
83    }
84
85    ControllableEntity::~ControllableEntity()
86    {
87        if (this->isInitialized())
88        {
89            this->bDestroyWhenPlayerLeft_ = false;
90
91            if (this->bHasLocalController_ && this->bHasHumanController_)
92                this->stopLocalHumanControl();
93
94            if (this->getPlayer() && this->getPlayer()->getControllableEntity() == this)
95                this->getPlayer()->stopControl();
96
97            if (this->xmlcontroller_)
98                this->xmlcontroller_->destroy();
99
100            if (this->hud_)
101                this->hud_->destroy();
102
103            if (this->camera_)
104                this->camera_->destroy();
105
106            for (std::list<SmartPtr<CameraPosition> >::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
107                (*it)->destroy();
108
109            if (this->getScene()->getSceneManager())
110                this->getScene()->getSceneManager()->destroySceneNode(this->cameraPositionRootNode_->getName());
111        }
112    }
113
114    void ControllableEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
115    {
116        SUPER(ControllableEntity, XMLPort, xmlelement, mode);
117
118        XMLPortParam(ControllableEntity, "hudtemplate", setHudTemplate, getHudTemplate, xmlelement, mode);
119        XMLPortParam(ControllableEntity, "camerapositiontemplate", setCameraPositionTemplate, getCameraPositionTemkplate, xmlelement, mode);
120
121        XMLPortObject(ControllableEntity, CameraPosition, "camerapositions", addCameraPosition, getCameraPosition, xmlelement, mode);
122        XMLPortObject(ControllableEntity, Controller,     "controller",      setXMLController,  getXMLController,  xmlelement, mode);
123    }
124
125    void ControllableEntity::setConfigValues()
126    {
127        SetConfigValue(mouseLookSpeed_, 3.0f);
128    }
129
130    void ControllableEntity::addCameraPosition(CameraPosition* position)
131    {
132        if (!position->getIsAbsolute())
133        {
134            if (position->getAllowMouseLook())
135                position->attachToNode(this->cameraPositionRootNode_);
136            else
137                this->attach(position);
138        }
139        else
140        {
141            WorldEntity* parent = this->getParent();
142            if (parent)
143                parent->attach(position);
144        }
145
146        if (!position->getRenderCamera())
147            this->cameraPositions_.push_back(position);
148        else
149            this->setReverseCamera(position);
150    }
151
152    CameraPosition* ControllableEntity::getCameraPosition(unsigned int index) const
153    {
154        unsigned int i = 0;
155        for (std::list<SmartPtr<CameraPosition> >::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
156        {
157            if (i == index)
158                return (*it);
159            ++i;
160        }
161        return 0;
162    }
163
164    void ControllableEntity::switchCamera()
165    {
166        if (this->camera_)
167        {
168            if (this->camera_->getParent() == this && this->cameraPositions_.size() > 0)
169            {
170                this->cameraPositions_.front()->attachCamera(this->camera_);
171            }
172            else if (this->cameraPositions_.size() > 0)
173            {
174                for (std::list<SmartPtr<CameraPosition> >::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
175                {
176                    if ((*it) == this->camera_->getParent())
177                    {
178                        ++it;
179                        if (it != this->cameraPositions_.end())
180                            (*it)->attachCamera(this->camera_);
181                        else
182                            (*this->cameraPositions_.begin())->attachCamera(this->camera_);
183                        break;
184                    }
185                }
186            }
187            else
188            {
189                this->camera_->attachToNode(this->cameraPositionRootNode_);
190            }
191        }
192    }
193
194    void ControllableEntity::mouseLook()
195    {
196        this->bMouseLook_ = !this->bMouseLook_;
197
198        if (!this->bMouseLook_)
199            this->cameraPositionRootNode_->setOrientation(Quaternion::IDENTITY);
200    }
201
202    void ControllableEntity::rotateYaw(const Vector2& value)
203    {
204        if (this->bMouseLook_)
205            this->cameraPositionRootNode_->yaw(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
206    }
207
208    void ControllableEntity::rotatePitch(const Vector2& value)
209    {
210        if (this->bMouseLook_)
211            this->cameraPositionRootNode_->pitch(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
212    }
213
214    void ControllableEntity::rotateRoll(const Vector2& value)
215    {
216        if (this->bMouseLook_)
217            this->cameraPositionRootNode_->roll(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
218    }
219
220    void ControllableEntity::setPlayer(PlayerInfo* player)
221    {
222        if (!player)
223        {
224            this->removePlayer();
225            return;
226        }
227
228        this->player_ = player;
229        this->playerID_ = player->getObjectID();
230        this->bHasLocalController_ = player->isLocalPlayer();
231        this->bHasHumanController_ = player->isHumanPlayer();
232
233        if (this->bHasLocalController_ && this->bHasHumanController_)
234        {
235            this->startLocalHumanControl();
236
237            if (!GameMode::isMaster())
238            {
239                this->client_overwrite_ = this->server_overwrite_;
240                this->setSyncMode(ObjectDirection::Bidirectional);
241            }
242        }
243
244        this->changedPlayer();
245    }
246
247    void ControllableEntity::removePlayer()
248    {
249        if (this->bHasLocalController_ && this->bHasHumanController_)
250            this->stopLocalHumanControl();
251
252        this->player_ = 0;
253        this->playerID_ = OBJECTID_UNKNOWN;
254        this->bHasLocalController_ = false;
255        this->bHasHumanController_ = false;
256        this->setSyncMode(ObjectDirection::ToClient);
257
258        this->changedPlayer();
259
260        if (this->bDestroyWhenPlayerLeft_)
261            this->destroy();
262    }
263
264    void ControllableEntity::networkcallback_changedplayerID()
265    {
266        // just do this in case the entity wasn't yet synchronized when the corresponding PlayerInfo got our objectID
267        if (this->playerID_ != OBJECTID_UNKNOWN)
268        {
269            this->player_ = orxonox_cast<PlayerInfo*>(Synchronisable::getSynchronisable(this->playerID_));
270            if (this->player_ && (this->player_->getControllableEntity() != this))
271                this->player_->startControl(this);
272        }
273    }
274
275    void ControllableEntity::startLocalHumanControl()
276    {
277        if (!this->camera_ && GameMode::showsGraphics())
278        {
279            this->camera_ = new Camera(this);
280            this->camera_->requestFocus();
281            if (this->cameraPositionTemplate_ != "")
282                this->addTemplate(this->cameraPositionTemplate_);
283            if (this->cameraPositions_.size() > 0)
284                this->cameraPositions_.front()->attachCamera(this->camera_);
285            else
286                this->camera_->attachToNode(this->cameraPositionRootNode_);
287        }
288
289        if (!this->hud_ && GameMode::showsGraphics())
290        {
291            if (this->hudtemplate_ != "")
292            {
293                this->hud_ = new OverlayGroup(this);
294                this->hud_->addTemplate(this->hudtemplate_);
295                this->hud_->setOwner(this);
296            }
297        }
298    }
299
300    void ControllableEntity::stopLocalHumanControl()
301    {
302        if (this->camera_)
303        {
304            this->camera_->detachFromParent();
305            this->camera_->destroy();
306            this->camera_ = 0;
307        }
308
309        if (this->hud_)
310        {
311            this->hud_->destroy();
312            this->hud_ = 0;
313        }
314    }
315
316    void ControllableEntity::setXMLController(Controller* controller)
317    {
318        if (!this->xmlcontroller_)
319        {
320            this->xmlcontroller_ = controller;
321            this->bHasLocalController_ = true;
322            this->xmlcontroller_->setControllableEntity(this);
323        }
324        else
325            COUT(2) << "Warning: ControllableEntity \"" << this->getName() << "\" already has a Controller." << std::endl;
326    }
327
328    void ControllableEntity::parentChanged()
329    {
330        WorldEntity::parentChanged();
331
332        WorldEntity* parent = this->getParent();
333        if (parent)
334        {
335            for (std::list<SmartPtr<CameraPosition> >::iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
336                if ((*it)->getIsAbsolute())
337                    parent->attach((*it));
338        }
339    }
340
341    void ControllableEntity::tick(float dt)
342    {
343        MobileEntity::tick(dt);
344
345        if (this->isActive())
346        {
347            // Check whether Bullet doesn't do the physics for us
348            if (!this->isDynamic())
349            {
350                if (GameMode::isMaster())
351                {
352                    this->server_position_ = this->getPosition();
353                    this->server_orientation_ = this->getOrientation();
354                    this->server_linear_velocity_ = this->getVelocity();
355                    this->server_angular_velocity_ = this->getAngularVelocity();
356                }
357                else if (this->bHasLocalController_)
358                {
359                    this->client_position_ = this->getPosition();
360                    this->client_orientation_ = this->getOrientation();
361                    this->client_linear_velocity_ = this->getVelocity();
362                    this->client_angular_velocity_ = this->getAngularVelocity();
363                }
364            }
365        }
366    }
367
368    void ControllableEntity::registerVariables()
369    {
370        registerVariable(this->cameraPositionTemplate_,  VariableDirection::ToClient);
371        registerVariable(this->hudtemplate_,             VariableDirection::ToClient);
372
373        registerVariable(this->server_position_,         VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerPosition));
374        registerVariable(this->server_linear_velocity_,  VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerLinearVelocity));
375        registerVariable(this->server_orientation_,      VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerOrientation));
376        registerVariable(this->server_angular_velocity_, VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerAngularVelocity));
377
378        registerVariable(this->server_overwrite_,        VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processOverwrite));
379        registerVariable(this->client_overwrite_,        VariableDirection::ToServer);
380
381        registerVariable(this->client_position_,         VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientPosition));
382        registerVariable(this->client_linear_velocity_,  VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientLinearVelocity));
383        registerVariable(this->client_orientation_,      VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientOrientation));
384        registerVariable(this->client_angular_velocity_, VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientAngularVelocity));
385
386
387        registerVariable(this->playerID_,                VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::networkcallback_changedplayerID));
388    }
389
390    void ControllableEntity::processServerPosition()
391    {
392        if (!this->bHasLocalController_)
393            MobileEntity::setPosition(this->server_position_);
394    }
395
396    void ControllableEntity::processServerLinearVelocity()
397    {
398        if (!this->bHasLocalController_)
399            MobileEntity::setVelocity(this->server_linear_velocity_);
400    }
401
402    void ControllableEntity::processServerOrientation()
403    {
404        if (!this->bHasLocalController_)
405            MobileEntity::setOrientation(this->server_orientation_);
406    }
407
408    void ControllableEntity::processServerAngularVelocity()
409    {
410        if (!this->bHasLocalController_)
411            MobileEntity::setAngularVelocity(this->server_angular_velocity_);
412    }
413
414    void ControllableEntity::processOverwrite()
415    {
416        if (this->bHasLocalController_)
417        {
418            this->setPosition(this->server_position_);
419            this->setOrientation(this->server_orientation_);
420            this->setVelocity(this->server_linear_velocity_);
421            this->setAngularVelocity(this->server_angular_velocity_);
422
423            this->client_overwrite_ = this->server_overwrite_;
424        }
425    }
426
427    void ControllableEntity::processClientPosition()
428    {
429        if (this->server_overwrite_ == this->client_overwrite_)
430        {
431            MobileEntity::setPosition(this->client_position_);
432            this->server_position_ = this->getPosition();
433        }
434    }
435
436    void ControllableEntity::processClientLinearVelocity()
437    {
438        if (this->server_overwrite_ == this->client_overwrite_)
439        {
440            MobileEntity::setVelocity(this->client_linear_velocity_);
441            this->server_linear_velocity_ = this->getVelocity();
442        }
443    }
444
445    void ControllableEntity::processClientOrientation()
446    {
447        if (this->server_overwrite_ == this->client_overwrite_)
448        {
449            MobileEntity::setOrientation(this->client_orientation_);
450            this->server_orientation_ = this->getOrientation();
451        }
452    }
453
454    void ControllableEntity::processClientAngularVelocity()
455    {
456        if (this->server_overwrite_ == this->client_overwrite_)
457        {
458            MobileEntity::setAngularVelocity(this->client_angular_velocity_);
459            this->server_angular_velocity_ = this->getAngularVelocity();
460        }
461    }
462
463    void ControllableEntity::setPosition(const Vector3& position)
464    {
465        if (GameMode::isMaster())
466        {
467            MobileEntity::setPosition(position);
468            this->server_position_ = this->getPosition();
469            ++this->server_overwrite_;
470        }
471        else if (this->bHasLocalController_)
472        {
473            MobileEntity::setPosition(position);
474            this->client_position_ = this->getPosition();
475        }
476    }
477
478    void ControllableEntity::setOrientation(const Quaternion& orientation)
479    {
480        if (GameMode::isMaster())
481        {
482            MobileEntity::setOrientation(orientation);
483            this->server_orientation_ = this->getOrientation();
484            ++this->server_overwrite_;
485        }
486        else if (this->bHasLocalController_)
487        {
488            MobileEntity::setOrientation(orientation);
489            this->client_orientation_ = this->getOrientation();
490        }
491    }
492
493    void ControllableEntity::setVelocity(const Vector3& velocity)
494    {
495        if (GameMode::isMaster())
496        {
497            MobileEntity::setVelocity(velocity);
498            this->server_linear_velocity_ = this->getVelocity();
499            ++this->server_overwrite_;
500        }
501        else if (this->bHasLocalController_)
502        {
503            MobileEntity::setVelocity(velocity);
504            this->client_linear_velocity_ = this->getVelocity();
505        }
506    }
507
508    void ControllableEntity::setAngularVelocity(const Vector3& velocity)
509    {
510        if (GameMode::isMaster())
511        {
512            MobileEntity::setAngularVelocity(velocity);
513            this->server_angular_velocity_ = this->getAngularVelocity();
514            ++this->server_overwrite_;
515        }
516        else if (this->bHasLocalController_)
517        {
518            MobileEntity::setAngularVelocity(velocity);
519            this->client_angular_velocity_ = this->getAngularVelocity();
520        }
521    }
522
523    void ControllableEntity::setWorldTransform(const btTransform& worldTrans)
524    {
525        MobileEntity::setWorldTransform(worldTrans);
526        if (GameMode::isMaster())
527        {
528            this->server_position_ = this->getPosition();
529            this->server_orientation_ = this->getOrientation();
530            this->server_linear_velocity_ = this->getVelocity();
531            this->server_angular_velocity_ = this->getAngularVelocity();
532        }
533        else if (this->bHasLocalController_)
534        {
535            this->client_position_ = this->getPosition();
536            this->client_orientation_ = this->getOrientation();
537            this->client_linear_velocity_ = this->getVelocity();
538            this->client_angular_velocity_ = this->getAngularVelocity();
539        }
540    }
541}
Note: See TracBrowser for help on using the repository browser.