Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/campaignHS15/src/orxonox/controllers/CommonController.cc @ 10864

Last change on this file since 10864 was 10864, checked in by gania, 9 years ago

split up some code

File size: 20.7 KB
RevLine 
[10719]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
[10799]11 *   of the License, or ( at your option )any later version.
[10719]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 *      Dominik Solenicki
26 *
27 */
28#include "controllers/CommonController.h"
[10759]29#include "core/XMLPort.h"
30
[10851]31//stuff for sameTeam function
[10838]32#include "worldentities/pawns/TeamBaseMatchBase.h"
33#include "gametypes/TeamDeathmatch.h"
34#include "gametypes/Dynamicmatch.h"
35#include "gametypes/Mission.h"
36#include "gametypes/Gametype.h"
37#include "controllers/WaypointPatrolController.h"
38#include "controllers/NewHumanController.h"
39#include "controllers/DroneController.h"
40
[10863]41//Today, on 25th of November, 2015, I hereby officially declare my code a huge pack of bullshit that I do not understand.
42//#Almost2KLines
43//#SpaghettiCode
44//#ISworeiWouldNever
45//#ItAllStartedSoWell
[10838]46
[10719]47namespace orxonox
48{
49
[10799]50    RegisterClass( CommonController );
[10826]51    const float SPEED = 0.9f/0.02f;
52    const float ROTATEFACTOR = 1.0f/0.02f;
[10719]53
[10851]54    //Table of content:
55    //Constructor, Destructor & tick
56    //XML methods
57    //World interaction
58    //Helper methods
59    //Flying methods
60    //Fighting methods
61    //Actionpoint methods
62
63
64    //------------------------------------------------------------------------------
65    //------------------------Constructor, Destructor & tick------------------------
66    //------------------------------------------------------------------------------
67   
[10799]68    CommonController::CommonController( Context* context ): Controller( context )
[10719]69    {
[10851]70        this->bFirstTick_ = true;
[10854]71        this->tolerance_ = 50;
[10803]72        this->stopLookingAtTarget();
[10851]73        this->attackRange_ = 2500;
[10799]74        RegisterObject( CommonController );
[10864]75
[10719]76    }
[10799]77    CommonController::~CommonController() 
[10719]78    {
[10864]79       
[10731]80    }
[10840]81    void CommonController::tick(float dt)
82    {
[10864]83       
[10843]84        SUPER(CommonController, tick, dt);
[10840]85    }
86
[10851]87    //------------------------------------------------------------------------------
88    //----------------------------------XML methods---------------------------------
89    //------------------------------------------------------------------------------
90   
91    void CommonController::XMLPort( Element& xmlelement, XMLPort::Mode mode )
[10838]92    {
[10851]93        SUPER( CommonController, XMLPort, xmlelement, mode );
94        XMLPortParam( CommonController, "formationMode", setFormationModeXML, getFormationModeXML,  xmlelement, mode );
[10838]95    }
[10799]96    void CommonController::setFormationModeXML( std::string val )
[10759]97    {
[10799]98        const std::string valUpper = getUppercase( val );
[10759]99        FormationMode::Value value;
[10826]100       
101        if ( valUpper == "WALL" )
[10759]102            value = FormationMode::WALL;
[10799]103        else if ( valUpper == "FINGER4" )
[10759]104            value = FormationMode::FINGER4;
[10799]105        else if ( valUpper == "DIAMOND" )
[10759]106            value = FormationMode::DIAMOND;
107        else
[10799]108            ThrowException( ParseError, std::string( "Attempting to set an unknown FormationMode: '" )+ val + "'." );
109        this->setFormationMode( value );
[10759]110    }
[10799]111    std::string CommonController::getFormationModeXML() 
[10759]112    {
[10799]113        switch ( this->formationMode_ )
[10759]114        {
115            case FormationMode::WALL:
[10851]116            { return "WALL"; break; }
[10759]117            case FormationMode::FINGER4:
[10851]118            { return "FINGER4"; break; }
[10759]119            case FormationMode::DIAMOND:
[10851]120            { return "DIAMOND"; break; }
[10759]121            default:
[10851]122                return "DIAMOND"; break;
[10759]123        }
124    }
[10851]125    void CommonController::setFormationMode(FormationMode::Value val)
126    { 
127        this->formationMode_ = val; 
[10805]128    }
[10851]129    FormationMode::Value CommonController::getFormationMode() const
130    { 
131        return this->formationMode_; 
[10832]132    }
[10851]133    void CommonController::setRank(Rank::Value val)
134    { 
135        this->rank_ = val; 
[10805]136    }
[10851]137    Rank::Value CommonController::getRank() const
138    { 
139        return this->rank_; 
[10805]140    }
[10864]141   
[10851]142    //------------------------------------------------------------------------------
143    //-------------------------------World interaction------------------------------
144    //------------------------------------------------------------------------------
[10832]145
[10851]146    //"Virtual" methods
[10799]147    bool CommonController::setWingman ( CommonController* wingman )
[10851]148    { return false; }
[10799]149    bool CommonController::hasWingman() 
[10851]150    { return true; }
[10799]151    bool CommonController::hasTarget() 
[10793]152    {
[10799]153        if ( this->target_ )
[10793]154            return true;
155        return false;
156    }
[10851]157    ControllableEntity* CommonController::getTarget()
[10793]158    {
[10851]159        return this->target_;
[10793]160    }
[10864]161 
[10729]162
[10851]163    //------------------------------------------------------------------------------
164    //--------------------------------Helper methods--------------------------------
165    //------------------------------------------------------------------------------
[10763]166
[10799]167    float CommonController::randomInRange( float a, float b )
[10796]168    {
[10799]169        float random = rnd( 1.0f );
[10796]170        float diff = b - a;
171        float r = random * diff;
172        return a + r;
173    }
[10826]174    float CommonController::distance (ControllableEntity* entity1, ControllableEntity* entity2)
175    {
176        if (!entity1 || !entity2)
177            return std::numeric_limits<float>::infinity();
178        return ( entity1->getPosition() - entity2->getPosition() ).length();
179    }
[10838]180    bool CommonController::sameTeam (ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
[10826]181    {
[10838]182        /*if (!entity1 || !entity2)
[10826]183            return false;
[10838]184        return entity1->getTeam() == entity2->getTeam();*/
185        if (entity1 == entity2)
186            return true;
187
188        int team1 = entity1->getTeam();
189        int team2 = entity2->getTeam();
190
191        Controller* controller = 0;
192        if (entity1->getController())
193            controller = entity1->getController();
194        else
195            controller = entity1->getXMLController();
196        if (controller)
197        {
198            CommonController* ac = orxonox_cast<CommonController*>(controller);
199            if (ac)
200                team1 = ac->getTeam();
201        }
202
203        if (entity2->getController())
204            controller = entity2->getController();
205        else
206            controller = entity2->getXMLController();
207        if (controller)
208        {
209            CommonController* ac = orxonox_cast<CommonController*>(controller);
210            if (ac)
211                team2 = ac->getTeam();
212        }
213
214        TeamGametype* tdm = orxonox_cast<TeamGametype*>(gametype);
215        if (tdm)
216        {
217            if (entity1->getPlayer())
218                team1 = tdm->getTeam(entity1->getPlayer());
219
220            if (entity2->getPlayer())
221                team2 = tdm->getTeam(entity2->getPlayer());
222        }
223
224        TeamBaseMatchBase* base = 0;
225        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
226        if (base)
227        {
228            switch (base->getState())
229            {
230                case BaseState::ControlTeam1:
231                    team1 = 0;
232                    break;
233                case BaseState::ControlTeam2:
234                    team1 = 1;
235                    break;
236                case BaseState::Uncontrolled:
237                default:
238                    team1 = -1;
239            }
240        }
241        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
242        if (base)
243        {
244            switch (base->getState())
245            {
246                case BaseState::ControlTeam1:
247                    team2 = 0;
248                    break;
249                case BaseState::ControlTeam2:
250                    team2 = 1;
251                    break;
252                case BaseState::Uncontrolled:
253                default:
254                    team2 = -1;
255            }
256        }
257
258        DroneController* droneController = 0;
259        droneController = orxonox_cast<DroneController*>(entity1->getController());
260        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2)
261            return true;
262        droneController = orxonox_cast<DroneController*>(entity2->getController());
263        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1)
264            return true;
265        DroneController* droneController1 = orxonox_cast<DroneController*>(entity1->getController());
266        DroneController* droneController2 = orxonox_cast<DroneController*>(entity2->getController());
267        if (droneController1 && droneController2 && droneController1->getOwner() == droneController2->getOwner())
268            return true;
269
270        Dynamicmatch* dynamic = orxonox_cast<Dynamicmatch*>(gametype);
271        if (dynamic)
272        {
273            if (dynamic->notEnoughPigs||dynamic->notEnoughKillers||dynamic->notEnoughChasers) {return false;}
274
275            if (entity1->getPlayer())
276                team1 = dynamic->getParty(entity1->getPlayer());
277
278            if (entity2->getPlayer())
279                team2 = dynamic->getParty(entity2->getPlayer());
280
281            if (team1 ==-1 ||team2 ==-1 ) {return false;}
282            else if (team1 == dynamic->chaser && team2 != dynamic->chaser) {return false;}
283            else if (team1 == dynamic->piggy && team2 == dynamic->chaser) {return false;}
284            else if (team1 == dynamic->killer && team2 == dynamic->chaser) {return false;}
285            else return true;
286        }
287
288        return (team1 == team2 && team1 != -1);
[10826]289    }
[10851]290    bool CommonController::isLooking( ControllableEntity* entityThatLooks, ControllableEntity* entityBeingLookedAt, float angle )
291    {
292        if ( !entityThatLooks || !entityBeingLookedAt )
293            return false;
294        return ( getAngle( entityThatLooks ->getPosition() , 
295            entityThatLooks->getOrientation()  * WorldEntity::FRONT, 
296            entityBeingLookedAt->getWorldPosition() ) < angle );
297    }
298    std::string CommonController::getName(Pawn* entity)
299    {
300        std::string name = entity->getName();
301        if (name == "")
302        {
303            const void * address = static_cast<const void*>(entity);
304            std::stringstream ss;
305            ss << address; 
306            name = ss.str();           
307        }
308        return name;
309    }
310    float CommonController::squaredDistanceToTarget()  const
311    {
312        if ( !this->getControllableEntity()  )
313            return 0;
314        if ( !this->target_ || !this->getControllableEntity() )
315            return ( this->getControllableEntity() ->getPosition() .squaredDistance( this->targetPosition_ ) );
316        else
317            return ( this->getControllableEntity() ->getPosition() .squaredDistance( this->positionOfTarget_ ) );
318    }
319    bool CommonController::isLookingAtTarget( float angle )
320    {
321        if ( !this->getControllableEntity()  || !this->target_ )
322            return false;
323        return this->isLooking(this->getControllableEntity(), this->getTarget(), angle);
324    }
325
326
327    //------------------------------------------------------------------------------
328    //--------------------------------Flying methods--------------------------------
329    //------------------------------------------------------------------------------
330
331    void CommonController::stopMoving()
332    {
333        this->bHasTargetPosition_ = false;
334    }
335    void CommonController::stopLookingAtTarget()
336    {
337        this->bLookAtTarget_ = false;
338    }
339    void CommonController::startLookingAtTarget()
340    {
341        this->bLookAtTarget_ = true;
342    }
343    void CommonController::moveToPosition( const Vector3& target, float dt )
344    {
345        ControllableEntity* entity = this->getControllableEntity();
346        Vector2 coord = get2DViewCoordinates
347            ( entity->getPosition() , 
348            entity->getOrientation()  * WorldEntity::FRONT, 
349            entity->getOrientation()  * WorldEntity::UP, 
350            target );
351
352        float distance = ( target - this->getControllableEntity() ->getPosition() ).length();
353        float rotateX = -clamp( coord.x * 10, -1.0f, 1.0f );
354        float rotateY = clamp( coord.y * 10, -1.0f, 1.0f );
355
356        if ( distance > this->tolerance_ )
357        {
358            this->getControllableEntity() ->rotateYaw( ROTATEFACTOR * rotateX * dt );
359            this->getControllableEntity() ->rotatePitch( ROTATEFACTOR * rotateY * dt );
360
361            if ( distance < 300 )
362            {
363                if ( bHasTargetOrientation_ )
364                {
365                    copyTargetOrientation( dt );
366                }
367            }
[10854]368            if (distance > this->tolerance_*1.5f || (rotateX > -0.01 && rotateX < 0.01 && rotateY > -0.01 && rotateY < 0.01))
[10851]369                this->getControllableEntity() ->moveFrontBack( SPEED * dt );
370        }
371        else
372        {     
373            bHasTargetPosition_ = false;
374            bHasTargetOrientation_ = false;
375        }
376    }
377    void CommonController::moveToTargetPosition(float dt)
378    {
379        this->moveToPosition (this->targetPosition_, dt);
380    }
381    void CommonController::copyOrientation( const Quaternion& orient, float dt )
382    {
383        //roll angle difference in radian
384        float diff=orient.getRoll(false).valueRadians() -
385                        ( this->getControllableEntity() ->getOrientation() .getRoll( false ).valueRadians() );
386        while( diff>math::twoPi )diff-=math::twoPi;
387        while( diff<-math::twoPi )diff+=math::twoPi;
[10859]388        this->getControllableEntity() ->rotateRoll( diff*0.2f*ROTATEFACTOR * dt );
[10851]389    }
390    void CommonController::copyTargetOrientation( float dt )
391    {
392        if ( bHasTargetOrientation_ )
393        {   
394            copyOrientation( targetOrientation_, dt );
395        }
396    }
397    void CommonController::lookAtTarget(float dt)
398    {
399        ControllableEntity* entity = this->getControllableEntity();
400        if ( !entity )
401            return;
402        Vector2 coord = get2DViewCoordinates
403            ( entity->getPosition() , 
404            entity->getOrientation()  * WorldEntity::FRONT, 
405            entity->getOrientation()  * WorldEntity::UP, 
406            positionOfTarget_ );
407
408        //rotates should be in range [-1,+1], clamp cuts off all that is not
409        float rotateX = -clamp( coord.x * 10, -1.0f, 1.0f );
410        float rotateY = clamp( coord.y * 10, -1.0f, 1.0f ); 
411   
412        //Yaw and Pitch are enough to start facing the target
413        this->getControllableEntity() ->rotateYaw( ROTATEFACTOR * rotateX * dt );
414        this->getControllableEntity() ->rotatePitch( ROTATEFACTOR * rotateY * dt );
415    }
416    void CommonController::setTargetPosition( const Vector3& target )
417    {
418        this->targetPosition_ = target;
419        this->bHasTargetPosition_ = true;
420    }
421
422    void CommonController::setTargetOrientation( const Quaternion& orient )
423    {
424        this->targetOrientation_=orient;
425        this->bHasTargetOrientation_=true;
426    }
427
428    void CommonController::setTargetOrientation( ControllableEntity* target )
429    {
430        if ( target )
431            setTargetOrientation( target->getOrientation() );
432    }
433
434    //------------------------------------------------------------------------------
435    //-------------------------------Fighting methods-------------------------------
436    //------------------------------------------------------------------------------
437
438    void CommonController::setTarget( ControllableEntity* target )
439    {
440        this->target_ = target;       
441        if ( this->target_ )
442        {
443            this->setPositionOfTarget( target_->getWorldPosition() );
444        }
445    }
446    void CommonController::setPositionOfTarget( const Vector3& target )
447    {
448        this->positionOfTarget_ = target;
449        this->bHasPositionOfTarget_ = true;
450    }
451    void CommonController::setOrientationOfTarget( const Quaternion& orient )
452    {
453        this->orientationOfTarget_=orient;
454        this->bHasOrientationOfTarget_=true;
455    }
[10864]456   
[10851]457    void CommonController::maneuver() 
458    {
459        maneuverCounter_++;
460        if (maneuverCounter_ > 5)
461            maneuverCounter_ = 0;
462
463        if ( !this->target_ || !this->getControllableEntity())
464            return;
465       
466        Vector3 thisPosition = this->getControllableEntity()->getWorldPosition();
467        this->setPositionOfTarget( getPredictedPosition( 
468            thisPosition, 
469            hardcoded_projectile_speed, 
470            this->target_->getWorldPosition() , 
471            this->target_->getVelocity() 
472            )  );
473        this->setOrientationOfTarget( this->target_->getOrientation() );
474
475        Vector3 diffVector = this->positionOfTarget_ - thisPosition;
476        float diffLength = diffVector.length();
477        Vector3 diffUnit = diffVector/diffLength;
478
479        bool bTargetIsLookingAtThis = this->isLooking ( this->target_, getControllableEntity(), math::pi/10.0f );
480       
481        //too far? well, come closer then
482        if ( diffLength > this->attackRange_ )
483        {
484            this->setTargetPosition( this->positionOfTarget_ );
485        }
486        //too close? How do u expect to dodge anything? Just attack!
487        else if ( diffLength < 500 )
488        {   
489            //at this point, just look and shoot
490            if ( diffLength < 250 )
491            {
492                this->stopMoving();
493                this->startLookingAtTarget();
494            }
495            else
496            {
497                this->setTargetPosition( this->positionOfTarget_ );
498            }
499        }
500        //Good distance? Check if target looks at us. It doesn't? Go hunt!
501        else if ( !bTargetIsLookingAtThis )
502        {
503            this->setTargetPosition( this->positionOfTarget_ );
504        }
505        //That's unfortunate, he is looking and probably shooting... try to dodge what we can... 
506        else 
507        {   
508            if (maneuverCounter_ == 0)
509            {
510                this->setTargetPosition( this->positionOfTarget_ );   
511                return;
512            }
513            dodge( thisPosition, diffUnit );
514        }
515    }
516   
517    void CommonController::dodge(Vector3& thisPosition, Vector3& diffUnit)
518    {
519        float factorX = 0, factorY = 0, factorZ = 0;
520        float rand = randomInRange (0, 1);
521   
522        if (rand <= 0.5)
523        { factorX = 1; }
524        else
525        { factorX = -1; }
526        rand = randomInRange (0, 1);
527        if (rand <= 0.5)
528        { factorY = 1; }
529        else
530        { factorY = -1; }
531        rand = randomInRange (0, 1);
532        if (rand <= 0.5)
533        { factorZ = 1; }
534        else
535        { factorZ = -1; }
536
537        Vector3 target = ( diffUnit )* 8000.0f;
538        Vector3* randVector = new Vector3( 
539            factorX * randomInRange( 10000, 40000 ), 
540            factorY * randomInRange( 10000, 40000 ), 
541            factorZ * randomInRange( 10000, 40000 ) 
542        );
543        Vector3 projection = randVector->dotProduct( diffUnit )* diffUnit;
544        *randVector -= projection;
545        target += *randVector;
546        this->setTargetPosition( thisPosition + target );
547    }
548    bool CommonController::canFire() 
549    {
550        //no target? why fire?
551        if ( !this->target_ )
552            return false;
553
554        Vector3 newPositionOfTarget = getPredictedPosition( this->getControllableEntity() ->getWorldPosition() , 
555            hardcoded_projectile_speed, this->target_->getWorldPosition() , this->target_->getVelocity() );
556        if ( newPositionOfTarget != Vector3::ZERO )
557        {
558            this->setPositionOfTarget( newPositionOfTarget );
559        }
560
561        float squaredDistance = squaredDistanceToTarget();
562
563        if ( squaredDistance < this->attackRange_*this->attackRange_ && this->isLookingAtTarget( math::pi / 20.0f)) 
564        {
565            return true;
566        }
567        else
568        {
569            return false;
570        }
571    }
[10799]572    void CommonController::doFire() 
[10780]573    {
[10799]574        if ( !this->target_ || !this->getControllableEntity() )
[10803]575        {
[10780]576            return;
[10803]577        }
578     
[10799]579        Pawn* pawn = orxonox_cast<Pawn*>( this->getControllableEntity() );
[10793]580
[10799]581        if ( pawn )
[10800]582            pawn->setAimPosition( this->positionOfTarget_ );
[10799]583        this->getControllableEntity() ->fire( 0 );
[10731]584    }
[10725]585
[10851]586
[10864]587   
[10856]588    void CommonController::boostControl()
589    {
590        SpaceShip* ship = orxonox_cast<SpaceShip*>(this->getControllableEntity());
591        if(ship == NULL) return;
592        if(ship->getBoostPower()*1.5f > ship->getInitialBoostPower() ) //upper limit ->boost
593        {
594
595            this->getControllableEntity()->boost(true);
596        }
597        else if(ship->getBoostPower()*4.0f < ship->getInitialBoostPower()) //lower limit ->do not boost
598        {
599           this->getControllableEntity()->boost(false);
600        }
601    }
[10719]602}
Note: See TracBrowser for help on using the repository browser.