Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gamecontent/src/orxonox/worldentities/ControllableEntity.cc @ 8923

Last change on this file since 8923 was 8923, checked in by jo, 13 years ago

Tutorial level enhancements (quest work, better texts are still needed), reverted old rocket hack, reworked configurable botlevel for the ai.

  • Property svn:eol-style set to native
File size: 23.6 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#include "network/NetworkFunction.h"
39
40#include "Scene.h"
41#include "infos/PlayerInfo.h"
42#include "controllers/NewHumanController.h"
43#include "graphics/Camera.h"
44#include "worldentities/CameraPosition.h"
45#include "overlays/OverlayGroup.h"
46
47namespace orxonox
48{
49    CreateFactory(ControllableEntity);
50
51    registerMemberNetworkFunction( ControllableEntity, fire );
52    registerMemberNetworkFunction( ControllableEntity, setTargetInternal );
53
54    ControllableEntity::ControllableEntity(BaseObject* creator) : MobileEntity(creator)
55    {
56        RegisterObject(ControllableEntity);
57
58        this->bHasLocalController_ = false;
59        this->bHasHumanController_ = false;
60
61        this->server_overwrite_ = 0;
62        this->client_overwrite_ = 0;
63        this->player_ = 0;
64        this->formerPlayer_ = NULL;
65        this->playerID_ = OBJECTID_UNKNOWN;
66        this->hud_ = 0;
67        this->camera_ = 0;
68        this->xmlcontroller_ = 0;
69        //this->controller_ = 0;
70        this->reverseCamera_ = 0;
71        this->bDestroyWhenPlayerLeft_ = false;
72        this->cameraPositionRootNode_ = this->node_->createChildSceneNode();
73        this->currentCameraPosition_ = 0;
74        this->bMouseLook_ = false;
75        this->mouseLookSpeed_ = 200;
76
77        this->server_position_         = Vector3::ZERO;
78        this->client_position_         = Vector3::ZERO;
79        this->server_linear_velocity_  = Vector3::ZERO;
80        this->client_linear_velocity_  = Vector3::ZERO;
81        this->server_orientation_      = Quaternion::IDENTITY;
82        this->client_orientation_      = Quaternion::IDENTITY;
83        this->server_angular_velocity_ = Vector3::ZERO;
84        this->client_angular_velocity_ = Vector3::ZERO;
85
86        this->setConfigValues();
87        this->setPriority( Priority::VeryHigh );
88        this->registerVariables();
89    }
90
91    ControllableEntity::~ControllableEntity()
92    {
93        if (this->isInitialized())
94        {
95            this->bDestroyWhenPlayerLeft_ = false;
96
97            if (this->getPlayer() && this->getPlayer()->getControllableEntity() == this)
98                this->getPlayer()->stopControl();
99
100            if (this->xmlcontroller_)
101                this->xmlcontroller_->destroy();
102
103            if (this->hud_)
104                this->hud_->destroy();
105
106            if (this->camera_)
107                this->camera_->destroy();
108
109            for (std::list<SmartPtr<CameraPosition> >::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
110                (*it)->destroy();
111
112            if (this->getScene()->getSceneManager())
113                this->getScene()->getSceneManager()->destroySceneNode(this->cameraPositionRootNode_->getName());
114        }
115    }
116
117    void ControllableEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
118    {
119        SUPER(ControllableEntity, XMLPort, xmlelement, mode);
120
121        XMLPortParam(ControllableEntity, "hudtemplate", setHudTemplate, getHudTemplate, xmlelement, mode);
122        XMLPortParam(ControllableEntity, "camerapositiontemplate", setCameraPositionTemplate, getCameraPositionTemplate, xmlelement, mode);
123
124        XMLPortObject(ControllableEntity, CameraPosition, "camerapositions", addCameraPosition, getCameraPosition, xmlelement, mode);
125        XMLPortObject(ControllableEntity, Controller,     "controller",      setXMLController,  getXMLController,  xmlelement, mode);
126    }
127
128    void ControllableEntity::setConfigValues()
129    {
130        SetConfigValue(mouseLookSpeed_, 3.0f);
131    }
132
133    void ControllableEntity::preDestroy()
134    {
135        // HACK - solve this clean and without preDestroy hook for multiplayer where removePlayer() isn't called
136        if (this->isInitialized() && this->bHasLocalController_ && this->bHasHumanController_)
137            this->stopLocalHumanControl();
138    }
139
140    void ControllableEntity::addCameraPosition(CameraPosition* position)
141    {
142        if (!position->getIsAbsolute())
143        {
144            if (position->getAllowMouseLook())
145                position->attachToNode(this->cameraPositionRootNode_);
146            else
147                this->attach(position);
148        }
149        else
150        {
151            WorldEntity* parent = this->getParent();
152            if (parent)
153                parent->attach(position);
154        }
155
156        if (!position->getRenderCamera())
157            this->cameraPositions_.push_back(position);
158        else
159            this->setReverseCamera(position);
160    }
161
162    CameraPosition* ControllableEntity::getCameraPosition(unsigned int index) const
163    {
164        unsigned int i = 0;
165        for (std::list<SmartPtr<CameraPosition> >::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
166        {
167            if (i == index)
168                return (*it);
169            ++i;
170        }
171        return 0;
172    }
173
174    unsigned int ControllableEntity::getCurrentCameraIndex() const
175    {
176        if (this->cameraPositions_.size() <= 0)
177            return 0;
178
179        unsigned int counter = 0;
180        for (std::list<SmartPtr<CameraPosition> >::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
181        {
182            if ((*it) == this->currentCameraPosition_)
183                break;
184            counter++;
185        }
186        if (counter >= this->cameraPositions_.size())
187            return 0;
188
189        return counter;
190    }
191
192    bool ControllableEntity::setCameraPosition(unsigned int index)
193    {
194        if(this->camera_ != NULL && this->cameraPositions_.size() > 0)
195        {
196            if(index >= this->cameraPositions_.size())
197                index = 0;
198
199            CameraPosition* position = this->getCameraPosition(index);
200            position->attachCamera(this->camera_);
201            this->currentCameraPosition_ = position;
202            return true;
203        }
204
205        return false;
206    }
207
208    void ControllableEntity::switchCamera()
209    {
210        if (this->camera_)
211        {
212            if (this->camera_->getParent() == this && this->cameraPositions_.size() > 0)
213            {
214                this->cameraPositions_.front()->attachCamera(this->camera_);
215                this->currentCameraPosition_ = this->cameraPositions_.front().get();
216            }
217            else if (this->cameraPositions_.size() > 0)
218            {
219                for (std::list<SmartPtr<CameraPosition> >::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
220                {
221                    if ((*it) == this->camera_->getParent())
222                    {
223                        ++it;
224                        if (it != this->cameraPositions_.end())
225                        {
226                            (*it)->attachCamera(this->camera_);
227                            this->currentCameraPosition_ = *it;
228                        }
229                        else
230                        {
231                            (*this->cameraPositions_.begin())->attachCamera(this->camera_);
232                            this->currentCameraPosition_ = *this->cameraPositions_.begin();
233                        }
234                        break;
235                    }
236                }
237            }
238            else
239            {
240                this->camera_->attachToNode(this->cameraPositionRootNode_);
241                this->currentCameraPosition_ = 0;
242            }
243
244            // disable mouse look if the new camera position doesn't allow it
245            if (this->currentCameraPosition_ && !this->currentCameraPosition_->getAllowMouseLook() && this->bMouseLook_)
246                this->mouseLook();
247
248            // disable drag if in mouse look
249            if (this->bMouseLook_)
250                this->getCamera()->setDrag(false);
251        }
252    }
253
254    void ControllableEntity::mouseLook()
255    {
256        // enable mouse look only if allowed - disabling it works always
257        if (this->currentCameraPosition_ && (this->currentCameraPosition_->getAllowMouseLook() || this->bMouseLook_))
258        {
259            this->bMouseLook_ = !this->bMouseLook_;
260
261            if (!this->bMouseLook_)
262            {
263                this->cameraPositionRootNode_->setOrientation(Quaternion::IDENTITY);
264                this->cameraPositionRootNode_->_update(true, false); // update the camera node because otherwise the camera will drag back in position which looks strange
265
266                NewHumanController* controller = dynamic_cast<NewHumanController*>(this->getController());
267                if (controller)
268                    controller->centerCursor();
269            }
270
271            if (this->getCamera())
272            {
273                if (!this->bMouseLook_ && this->currentCameraPosition_->getDrag())
274                    this->getCamera()->setDrag(true);
275                else
276                    this->getCamera()->setDrag(false);
277            }
278        }
279    }
280
281    void ControllableEntity::rotateYaw(const Vector2& value)
282    {
283        if (this->bMouseLook_)
284            this->cameraPositionRootNode_->yaw(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
285    }
286
287    void ControllableEntity::rotatePitch(const Vector2& value)
288    {
289        if (this->bMouseLook_)
290            this->cameraPositionRootNode_->pitch(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
291    }
292
293    void ControllableEntity::rotateRoll(const Vector2& value)
294    {
295        if (this->bMouseLook_)
296            this->cameraPositionRootNode_->roll(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
297    }
298
299    void ControllableEntity::fire(unsigned int firemode)
300    {
301        if(GameMode::isMaster())
302        {
303            this->fired(firemode);
304        }
305        else
306        {
307            callMemberNetworkFunction(ControllableEntity, fire, this->getObjectID(), 0, firemode);
308        }
309    }
310
311    void ControllableEntity::setController(Controller* val)
312    {
313        this->controller_ = val;
314    }
315
316    void ControllableEntity::setTarget( WorldEntity* target )
317    {
318        this->target_ = target;
319        if ( !GameMode::isMaster() )
320        {
321            if ( target != 0 )
322            {
323                callMemberNetworkFunction(ControllableEntity, setTargetInternal, this->getObjectID(), 0, target->getObjectID() );
324            }
325           else
326           {
327                callMemberNetworkFunction(ControllableEntity, setTargetInternal, this->getObjectID(), 0, OBJECTID_UNKNOWN );
328           }
329        }
330    }
331
332    void ControllableEntity::setTargetInternal( uint32_t targetID )
333    {
334        this->setTarget( orxonox_cast<WorldEntity*>(Synchronisable::getSynchronisable(targetID)) );
335    }
336
337    void ControllableEntity::setPlayer(PlayerInfo* player)
338    {
339        if (!player)
340        {
341            this->removePlayer();
342            return;
343        }
344
345        this->player_ = player;
346        this->formerPlayer_ = player;
347        this->playerID_ = player->getObjectID();
348        this->bHasLocalController_ = player->isLocalPlayer();
349        this->bHasHumanController_ = player->isHumanPlayer();
350
351        if (this->bHasLocalController_ && this->bHasHumanController_)
352        {
353            this->startLocalHumanControl();
354
355            if (!GameMode::isMaster())
356            {
357                this->client_overwrite_ = this->server_overwrite_;
358                this->setSyncMode(ObjectDirection::Bidirectional);
359            }
360        }
361
362        this->changedPlayer();
363    }
364
365    void ControllableEntity::removePlayer()
366    {
367        if (this->bHasLocalController_ && this->bHasHumanController_)
368            this->stopLocalHumanControl();
369
370        this->player_ = 0;
371        this->playerID_ = OBJECTID_UNKNOWN;
372        this->bHasLocalController_ = false;
373        this->bHasHumanController_ = false;
374        this->setSyncMode(ObjectDirection::ToClient);
375
376        this->changedPlayer();
377
378        if (this->bDestroyWhenPlayerLeft_)
379            this->destroy();
380    }
381
382    void ControllableEntity::networkcallback_changedplayerID()
383    {
384        // just do this in case the entity wasn't yet synchronized when the corresponding PlayerInfo got our objectID
385        if (this->playerID_ != OBJECTID_UNKNOWN)
386        {
387            this->player_ = orxonox_cast<PlayerInfo*>(Synchronisable::getSynchronisable(this->playerID_));
388            if (this->player_ && (this->player_->getControllableEntity() != this))
389                this->player_->startControl(this);
390        }
391    }
392
393    void ControllableEntity::startLocalHumanControl()
394    {
395        if (!this->camera_ && GameMode::showsGraphics())
396        {
397            this->camera_ = new Camera(this);
398            this->camera_->requestFocus();
399            if (!this->cameraPositionTemplate_.empty())
400                this->addTemplate(this->cameraPositionTemplate_);
401            if (this->cameraPositions_.size() > 0)
402            {
403                this->cameraPositions_.front()->attachCamera(this->camera_);
404                this->currentCameraPosition_ = this->cameraPositions_.front();
405            }
406            else
407            {
408                this->camera_->attachToNode(this->cameraPositionRootNode_);
409                this->currentCameraPosition_ = 0;
410            }
411        }
412
413        this->createHud();
414    }
415
416    // HACK-ish
417    void ControllableEntity::createHud(void)
418    {
419        if (!this->hud_ && GameMode::showsGraphics())
420        {
421            if (!this->hudtemplate_.empty())
422            {
423                this->hud_ = new OverlayGroup(this);
424                this->hud_->addTemplate(this->hudtemplate_);
425                this->hud_->setOwner(this);
426            }
427        }
428    }
429
430    void ControllableEntity::destroyHud(void)
431    {
432        if (this->hud_ != NULL)
433        {
434            this->hud_->destroy();
435            this->hud_ = NULL;
436        }
437    }
438
439    void ControllableEntity::stopLocalHumanControl()
440    {
441        if (this->camera_)
442        {
443            this->camera_->detachFromParent();
444            this->camera_->destroy();
445            this->camera_ = 0;
446        }
447
448        if (this->hud_)
449        {
450            this->hud_->destroy();
451            this->hud_ = 0;
452        }
453    }
454
455    void ControllableEntity::setXMLController(Controller* controller)
456    {
457        if (!this->xmlcontroller_)
458        {
459            this->xmlcontroller_ = controller;
460            this->bHasLocalController_ = true;
461            this->xmlcontroller_->setControllableEntity(this);
462        }
463        else
464            orxout(internal_warning) << "ControllableEntity \"" << this->getName() << "\" already has a Controller." << endl;
465    }
466
467    void ControllableEntity::parentChanged()
468    {
469        WorldEntity::parentChanged();
470
471        WorldEntity* parent = this->getParent();
472        if (parent)
473        {
474            for (std::list<SmartPtr<CameraPosition> >::iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
475                if ((*it)->getIsAbsolute())
476                    parent->attach((*it));
477        }
478    }
479
480    void ControllableEntity::tick(float dt)
481    {
482        MobileEntity::tick(dt);
483
484        if (this->isActive())
485        {
486            // Check whether Bullet doesn't do the physics for us
487            if (!this->isDynamic())
488            {
489                if (GameMode::isMaster())
490                {
491                    this->server_position_ = this->getPosition();
492                    this->server_orientation_ = this->getOrientation();
493                    this->server_linear_velocity_ = this->getVelocity();
494                    this->server_angular_velocity_ = this->getAngularVelocity();
495                }
496                else if (this->bHasLocalController_)
497                {
498                    this->client_position_ = this->getPosition();
499                    this->client_orientation_ = this->getOrientation();
500                    this->client_linear_velocity_ = this->getVelocity();
501                    this->client_angular_velocity_ = this->getAngularVelocity();
502                }
503            }
504        }
505    }
506
507    void ControllableEntity::registerVariables()
508    {
509        registerVariable(this->cameraPositionTemplate_,  VariableDirection::ToClient);
510        registerVariable(this->hudtemplate_,             VariableDirection::ToClient);
511
512        registerVariable(this->server_position_,         VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerPosition));
513        registerVariable(this->server_linear_velocity_,  VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerLinearVelocity));
514        registerVariable(this->server_orientation_,      VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerOrientation));
515        registerVariable(this->server_angular_velocity_, VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerAngularVelocity));
516
517        registerVariable(this->server_overwrite_,        VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processOverwrite));
518        registerVariable(this->client_overwrite_,        VariableDirection::ToServer);
519
520        registerVariable(this->client_position_,         VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientPosition));
521        registerVariable(this->client_linear_velocity_,  VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientLinearVelocity));
522        registerVariable(this->client_orientation_,      VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientOrientation));
523        registerVariable(this->client_angular_velocity_, VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientAngularVelocity));
524
525
526        registerVariable(this->playerID_,                VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::networkcallback_changedplayerID));
527    }
528
529    void ControllableEntity::processServerPosition()
530    {
531        if (!this->bHasLocalController_)
532            MobileEntity::setPosition(this->server_position_);
533    }
534
535    void ControllableEntity::processServerLinearVelocity()
536    {
537        if (!this->bHasLocalController_)
538            MobileEntity::setVelocity(this->server_linear_velocity_);
539    }
540
541    void ControllableEntity::processServerOrientation()
542    {
543        if (!this->bHasLocalController_)
544            MobileEntity::setOrientation(this->server_orientation_);
545    }
546
547    void ControllableEntity::processServerAngularVelocity()
548    {
549        if (!this->bHasLocalController_)
550            MobileEntity::setAngularVelocity(this->server_angular_velocity_);
551    }
552
553    void ControllableEntity::processOverwrite()
554    {
555        if (this->bHasLocalController_)
556        {
557            this->setPosition(this->server_position_);
558            this->setOrientation(this->server_orientation_);
559            this->setVelocity(this->server_linear_velocity_);
560            this->setAngularVelocity(this->server_angular_velocity_);
561
562            this->client_overwrite_ = this->server_overwrite_;
563        }
564    }
565
566    void ControllableEntity::processClientPosition()
567    {
568        if (this->server_overwrite_ == this->client_overwrite_)
569        {
570            MobileEntity::setPosition(this->client_position_);
571            this->server_position_ = this->getPosition();
572        }
573    }
574
575    void ControllableEntity::processClientLinearVelocity()
576    {
577        if (this->server_overwrite_ == this->client_overwrite_)
578        {
579            MobileEntity::setVelocity(this->client_linear_velocity_);
580            this->server_linear_velocity_ = this->getVelocity();
581        }
582    }
583
584    void ControllableEntity::processClientOrientation()
585    {
586        if (this->server_overwrite_ == this->client_overwrite_)
587        {
588            MobileEntity::setOrientation(this->client_orientation_);
589            this->server_orientation_ = this->getOrientation();
590        }
591    }
592
593    void ControllableEntity::processClientAngularVelocity()
594    {
595        if (this->server_overwrite_ == this->client_overwrite_)
596        {
597            MobileEntity::setAngularVelocity(this->client_angular_velocity_);
598            this->server_angular_velocity_ = this->getAngularVelocity();
599        }
600    }
601
602    void ControllableEntity::setPosition(const Vector3& position)
603    {
604        if (GameMode::isMaster())
605        {
606            MobileEntity::setPosition(position);
607            this->server_position_ = this->getPosition();
608            ++this->server_overwrite_;
609        }
610        else if (this->bHasLocalController_)
611        {
612            MobileEntity::setPosition(position);
613            this->client_position_ = this->getPosition();
614        }
615    }
616
617    void ControllableEntity::setOrientation(const Quaternion& orientation)
618    {
619        if (GameMode::isMaster())
620        {
621            MobileEntity::setOrientation(orientation);
622            this->server_orientation_ = this->getOrientation();
623            ++this->server_overwrite_;
624        }
625        else if (this->bHasLocalController_)
626        {
627            MobileEntity::setOrientation(orientation);
628            this->client_orientation_ = this->getOrientation();
629        }
630    }
631
632    void ControllableEntity::setVelocity(const Vector3& velocity)
633    {
634        if (GameMode::isMaster())
635        {
636            MobileEntity::setVelocity(velocity);
637            this->server_linear_velocity_ = this->getVelocity();
638            ++this->server_overwrite_;
639        }
640        else if (this->bHasLocalController_)
641        {
642            MobileEntity::setVelocity(velocity);
643            this->client_linear_velocity_ = this->getVelocity();
644        }
645    }
646
647    void ControllableEntity::setAngularVelocity(const Vector3& velocity)
648    {
649        if (GameMode::isMaster())
650        {
651            MobileEntity::setAngularVelocity(velocity);
652            this->server_angular_velocity_ = this->getAngularVelocity();
653            ++this->server_overwrite_;
654        }
655        else if (this->bHasLocalController_)
656        {
657            MobileEntity::setAngularVelocity(velocity);
658            this->client_angular_velocity_ = this->getAngularVelocity();
659        }
660    }
661
662    void ControllableEntity::setWorldTransform(const btTransform& worldTrans)
663    {
664        MobileEntity::setWorldTransform(worldTrans);
665        if (GameMode::isMaster())
666        {
667            this->server_position_ = this->getPosition();
668            this->server_orientation_ = this->getOrientation();
669            this->server_linear_velocity_ = this->getVelocity();
670            this->server_angular_velocity_ = this->getAngularVelocity();
671        }
672        else if (this->bHasLocalController_)
673        {
674            this->client_position_ = this->getPosition();
675            this->client_orientation_ = this->getOrientation();
676            this->client_linear_velocity_ = this->getVelocity();
677            this->client_angular_velocity_ = this->getAngularVelocity();
678        }
679    }
680}
Note: See TracBrowser for help on using the repository browser.