Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ScriptableController_HS17/src/orxonox/worldentities/ControllableEntity.cc @ 11593

Last change on this file since 11593 was 11583, checked in by kohlia, 7 years ago

Near object, near point and at area work!

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