Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10863 was 10863, checked in by gania, 8 years ago
File size: 42.5 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 *      Dominik Solenicki
26 *
27 */
28#include "controllers/CommonController.h"
29#include "core/XMLPort.h"
30
31//stuff for sameTeam function
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
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
46
47namespace orxonox
48{
49
50    RegisterClass( CommonController );
51    const float SPEED = 0.9f/0.02f;
52    const float ROTATEFACTOR = 1.0f/0.02f;
53
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   
68    CommonController::CommonController( Context* context ): Controller( context )
69    {
70        this->squaredaccuracy_ = 2500;
71        this->bFirstTick_ = true;
72        this->tolerance_ = 50;
73        this->action_ = Action::NONE;
74        this->stopLookingAtTarget();
75        this->attackRange_ = 2500;
76        this->bInLoop_ = false;
77        this->bLoop_ = false;
78        this->bEndLoop_ = false;
79        this->parsedActionpoints_.clear();
80        RegisterObject( CommonController );
81        this->bTakenOver_ = false;
82    }
83    CommonController::~CommonController() 
84    {
85        parsedActionpoints_.clear();
86        actionpoints_.clear();
87    }
88    void CommonController::tick(float dt)
89    {
90        if (this->bHasTargetPosition_)
91        {
92            this->moveToTargetPosition(dt);
93        }
94        else if (this->bLookAtTarget_)
95        {
96            this->lookAtTarget(dt);
97        }
98        if (bShooting_)
99        {
100            this->doFire();
101        }
102        if (this->bFirstTick_)
103        {
104            std::reverse(parsedActionpoints_.begin(), parsedActionpoints_.end());
105            std::reverse(actionpoints_.begin(), actionpoints_.end());
106            if (this->parsedActionpoints_.empty())
107            {
108                this->action_ = Action::FIGHTALL;
109            }
110        }
111        if (this->bFirstTick_)
112            this->bFirstTick_ = false;
113        SUPER(CommonController, tick, dt);
114    }
115
116    //------------------------------------------------------------------------------
117    //----------------------------------XML methods---------------------------------
118    //------------------------------------------------------------------------------
119   
120    void CommonController::XMLPort( Element& xmlelement, XMLPort::Mode mode )
121    {
122        SUPER( CommonController, XMLPort, xmlelement, mode );
123        XMLPortParam( CommonController, "formationMode", setFormationModeXML, getFormationModeXML,  xmlelement, mode );
124        XMLPortObject(CommonController, WorldEntity, "actionpoints", addActionpoint, getActionpoint,  xmlelement, mode);
125    }
126    void CommonController::setFormationModeXML( std::string val )
127    {
128        const std::string valUpper = getUppercase( val );
129        FormationMode::Value value;
130       
131        if ( valUpper == "WALL" )
132            value = FormationMode::WALL;
133        else if ( valUpper == "FINGER4" )
134            value = FormationMode::FINGER4;
135        else if ( valUpper == "DIAMOND" )
136            value = FormationMode::DIAMOND;
137        else
138            ThrowException( ParseError, std::string( "Attempting to set an unknown FormationMode: '" )+ val + "'." );
139        this->setFormationMode( value );
140    }
141    std::string CommonController::getFormationModeXML() 
142    {
143        switch ( this->formationMode_ )
144        {
145            case FormationMode::WALL:
146            { return "WALL"; break; }
147            case FormationMode::FINGER4:
148            { return "FINGER4"; break; }
149            case FormationMode::DIAMOND:
150            { return "DIAMOND"; break; }
151            default:
152                return "DIAMOND"; break;
153        }
154    }
155    void CommonController::setFormationMode(FormationMode::Value val)
156    { 
157        this->formationMode_ = val; 
158    }
159    FormationMode::Value CommonController::getFormationMode() const
160    { 
161        return this->formationMode_; 
162    }
163    void CommonController::setRank(Rank::Value val)
164    { 
165        this->rank_ = val; 
166    }
167    Rank::Value CommonController::getRank() const
168    { 
169        return this->rank_; 
170    }
171    void CommonController::addActionpoint(WorldEntity* actionpoint)
172    {
173        std::string actionName;
174        Vector3 position;
175        std::string targetName;
176        bool inLoop = false;
177        Point p;
178        if (static_cast<Actionpoint*> (actionpoint))
179        {
180            Actionpoint* ap = static_cast<Actionpoint*> (actionpoint);
181            actionName = ap->getActionXML();
182            targetName = ap->getName();
183            position = ap->getWorldPosition();
184
185            if (this->bEndLoop_)
186            {
187                this->bInLoop_ = false;
188            }
189            if (!this->bInLoop_ && ap->getLoopStart())
190            {
191                this->bInLoop_ = true;
192            }
193            if (this->bInLoop_ && ap->getLoopEnd())
194            {
195                this->bEndLoop_ = true;
196            }
197            inLoop = this->bInLoop_;
198
199            Action::Value value;
200           
201            if ( actionName == "FIGHT" )
202            { value = Action::FIGHT; }
203            else if ( actionName == "FLY" )
204            { value = Action::FLY; }
205            else if ( actionName == "PROTECT" )
206            { value = Action::PROTECT; }
207            else if ( actionName == "NONE" )
208            { value = Action::NONE; }
209            else if ( actionName == "FIGHTALL" )
210            { value = Action::FIGHTALL; }
211            else if ( actionName == "ATTACK" )
212            { value = Action::ATTACK; }
213            else
214                ThrowException( ParseError, std::string( "Attempting to set an unknown Action: '" )+ actionName + "'." );
215            p.action = value; p.name = targetName; p.position = position; p.inLoop = inLoop;
216        }
217        else
218        {
219            p.action = Action::FLY; p.name = ""; p.position = actionpoint->getWorldPosition(); p.inLoop = inLoop;
220        }
221            parsedActionpoints_.push_back(p);
222            this->actionpoints_.push_back(actionpoint);
223    }
224    WorldEntity* CommonController::getActionpoint(unsigned int index) const
225    {
226        if (index < this->actionpoints_.size())
227            return this->actionpoints_[index];
228        else
229            return 0;
230    }
231
232    //------------------------------------------------------------------------------
233    //-------------------------------World interaction------------------------------
234    //------------------------------------------------------------------------------
235
236    //"Virtual" methods
237    bool CommonController::setWingman ( CommonController* wingman )
238    { return false; }
239    bool CommonController::hasWingman() 
240    { return true; }
241    bool CommonController::hasTarget() 
242    {
243        if ( this->target_ )
244            return true;
245        return false;
246    }
247    ControllableEntity* CommonController::getTarget()
248    {
249        return this->target_;
250    }
251    Action::Value CommonController::getAction ()
252    {
253        return this->action_;
254    }
255    std::string CommonController::getActionName()
256    {
257        switch ( this->action_ )
258        {
259            case Action::FIGHT:
260            { return "FIGHT"; break; }
261            case Action::FLY:
262            { return "FLY"; break; }
263            case Action::PROTECT:
264            { return "PROTECT"; break; }
265            case Action::NONE:
266            { return "NONE"; break; }
267            case Action::FIGHTALL:
268            { return "FIGHTALL"; break; }
269            case Action::ATTACK:
270            { return "ATTACK"; break; }
271            default:
272                return "NONE";
273                break;
274        }
275    }
276    void CommonController::setAction (Action::Value action)
277    {
278        this->action_ = action;
279    }
280    void CommonController::setAction (Action::Value action, ControllableEntity* target)
281    {
282        this->action_ = action;
283        if (action == Action::FIGHT || action == Action::FIGHTALL || action == Action::ATTACK)
284        {   
285            if (target)
286                this->setTarget (target);
287        }
288        else if (action == Action::PROTECT)
289        {
290            if (target)
291                this->setProtect (target);
292        }
293    }
294    void CommonController::setAction (Action::Value action, const Vector3& target)
295    {
296        this->action_ = action;
297        if (action == Action::FLY)
298        {
299            this->setTargetPosition (target);
300        }
301    }
302    void CommonController::setAction (Action::Value action, const Vector3& target,  const Quaternion& orient )
303    {
304        this->action_ = action;
305        if (action == Action::FLY)
306        {
307            this->setTargetPosition (target);
308            this->setTargetOrientation (orient);
309        } 
310    }
311
312    //------------------------------------------------------------------------------
313    //--------------------------------Helper methods--------------------------------
314    //------------------------------------------------------------------------------
315
316    float CommonController::randomInRange( float a, float b )
317    {
318        float random = rnd( 1.0f );
319        float diff = b - a;
320        float r = random * diff;
321        return a + r;
322    }
323    float CommonController::distance (ControllableEntity* entity1, ControllableEntity* entity2)
324    {
325        if (!entity1 || !entity2)
326            return std::numeric_limits<float>::infinity();
327        return ( entity1->getPosition() - entity2->getPosition() ).length();
328    }
329    bool CommonController::sameTeam (ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
330    {
331        /*if (!entity1 || !entity2)
332            return false;
333        return entity1->getTeam() == entity2->getTeam();*/
334        if (entity1 == entity2)
335            return true;
336
337        int team1 = entity1->getTeam();
338        int team2 = entity2->getTeam();
339
340        Controller* controller = 0;
341        if (entity1->getController())
342            controller = entity1->getController();
343        else
344            controller = entity1->getXMLController();
345        if (controller)
346        {
347            CommonController* ac = orxonox_cast<CommonController*>(controller);
348            if (ac)
349                team1 = ac->getTeam();
350        }
351
352        if (entity2->getController())
353            controller = entity2->getController();
354        else
355            controller = entity2->getXMLController();
356        if (controller)
357        {
358            CommonController* ac = orxonox_cast<CommonController*>(controller);
359            if (ac)
360                team2 = ac->getTeam();
361        }
362
363        TeamGametype* tdm = orxonox_cast<TeamGametype*>(gametype);
364        if (tdm)
365        {
366            if (entity1->getPlayer())
367                team1 = tdm->getTeam(entity1->getPlayer());
368
369            if (entity2->getPlayer())
370                team2 = tdm->getTeam(entity2->getPlayer());
371        }
372
373        TeamBaseMatchBase* base = 0;
374        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
375        if (base)
376        {
377            switch (base->getState())
378            {
379                case BaseState::ControlTeam1:
380                    team1 = 0;
381                    break;
382                case BaseState::ControlTeam2:
383                    team1 = 1;
384                    break;
385                case BaseState::Uncontrolled:
386                default:
387                    team1 = -1;
388            }
389        }
390        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
391        if (base)
392        {
393            switch (base->getState())
394            {
395                case BaseState::ControlTeam1:
396                    team2 = 0;
397                    break;
398                case BaseState::ControlTeam2:
399                    team2 = 1;
400                    break;
401                case BaseState::Uncontrolled:
402                default:
403                    team2 = -1;
404            }
405        }
406
407        DroneController* droneController = 0;
408        droneController = orxonox_cast<DroneController*>(entity1->getController());
409        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2)
410            return true;
411        droneController = orxonox_cast<DroneController*>(entity2->getController());
412        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1)
413            return true;
414        DroneController* droneController1 = orxonox_cast<DroneController*>(entity1->getController());
415        DroneController* droneController2 = orxonox_cast<DroneController*>(entity2->getController());
416        if (droneController1 && droneController2 && droneController1->getOwner() == droneController2->getOwner())
417            return true;
418
419        Dynamicmatch* dynamic = orxonox_cast<Dynamicmatch*>(gametype);
420        if (dynamic)
421        {
422            if (dynamic->notEnoughPigs||dynamic->notEnoughKillers||dynamic->notEnoughChasers) {return false;}
423
424            if (entity1->getPlayer())
425                team1 = dynamic->getParty(entity1->getPlayer());
426
427            if (entity2->getPlayer())
428                team2 = dynamic->getParty(entity2->getPlayer());
429
430            if (team1 ==-1 ||team2 ==-1 ) {return false;}
431            else if (team1 == dynamic->chaser && team2 != dynamic->chaser) {return false;}
432            else if (team1 == dynamic->piggy && team2 == dynamic->chaser) {return false;}
433            else if (team1 == dynamic->killer && team2 == dynamic->chaser) {return false;}
434            else return true;
435        }
436
437        return (team1 == team2 && team1 != -1);
438    }
439    bool CommonController::isLooking( ControllableEntity* entityThatLooks, ControllableEntity* entityBeingLookedAt, float angle )
440    {
441        if ( !entityThatLooks || !entityBeingLookedAt )
442            return false;
443        return ( getAngle( entityThatLooks ->getPosition() , 
444            entityThatLooks->getOrientation()  * WorldEntity::FRONT, 
445            entityBeingLookedAt->getWorldPosition() ) < angle );
446    }
447    std::string CommonController::getName(Pawn* entity)
448    {
449        std::string name = entity->getName();
450        if (name == "")
451        {
452            const void * address = static_cast<const void*>(entity);
453            std::stringstream ss;
454            ss << address; 
455            name = ss.str();           
456        }
457        return name;
458    }
459    float CommonController::squaredDistanceToTarget()  const
460    {
461        if ( !this->getControllableEntity()  )
462            return 0;
463        if ( !this->target_ || !this->getControllableEntity() )
464            return ( this->getControllableEntity() ->getPosition() .squaredDistance( this->targetPosition_ ) );
465        else
466            return ( this->getControllableEntity() ->getPosition() .squaredDistance( this->positionOfTarget_ ) );
467    }
468    bool CommonController::isLookingAtTarget( float angle )
469    {
470        if ( !this->getControllableEntity()  || !this->target_ )
471            return false;
472        return this->isLooking(this->getControllableEntity(), this->getTarget(), angle);
473    }
474
475
476    //------------------------------------------------------------------------------
477    //--------------------------------Flying methods--------------------------------
478    //------------------------------------------------------------------------------
479
480    void CommonController::stopMoving()
481    {
482        this->bHasTargetPosition_ = false;
483    }
484    void CommonController::stopLookingAtTarget()
485    {
486        this->bLookAtTarget_ = false;
487    }
488    void CommonController::startLookingAtTarget()
489    {
490        this->bLookAtTarget_ = true;
491    }
492    void CommonController::moveToPosition( const Vector3& target, float dt )
493    {
494        ControllableEntity* entity = this->getControllableEntity();
495        Vector2 coord = get2DViewCoordinates
496            ( entity->getPosition() , 
497            entity->getOrientation()  * WorldEntity::FRONT, 
498            entity->getOrientation()  * WorldEntity::UP, 
499            target );
500
501        float distance = ( target - this->getControllableEntity() ->getPosition() ).length();
502        float rotateX = -clamp( coord.x * 10, -1.0f, 1.0f );
503        float rotateY = clamp( coord.y * 10, -1.0f, 1.0f );
504
505        if ( distance > this->tolerance_ )
506        {
507            this->getControllableEntity() ->rotateYaw( ROTATEFACTOR * rotateX * dt );
508            this->getControllableEntity() ->rotatePitch( ROTATEFACTOR * rotateY * dt );
509
510            if ( distance < 300 )
511            {
512                if ( bHasTargetOrientation_ )
513                {
514                    copyTargetOrientation( dt );
515                }
516            }
517            if (distance > this->tolerance_*1.5f || (rotateX > -0.01 && rotateX < 0.01 && rotateY > -0.01 && rotateY < 0.01))
518                this->getControllableEntity() ->moveFrontBack( SPEED * dt );
519        }
520        else
521        {     
522            bHasTargetPosition_ = false;
523            bHasTargetOrientation_ = false;
524        }
525    }
526    void CommonController::moveToTargetPosition(float dt)
527    {
528        this->moveToPosition (this->targetPosition_, dt);
529    }
530    void CommonController::copyOrientation( const Quaternion& orient, float dt )
531    {
532        //roll angle difference in radian
533        float diff=orient.getRoll(false).valueRadians() -
534                        ( this->getControllableEntity() ->getOrientation() .getRoll( false ).valueRadians() );
535        while( diff>math::twoPi )diff-=math::twoPi;
536        while( diff<-math::twoPi )diff+=math::twoPi;
537        this->getControllableEntity() ->rotateRoll( diff*0.2f*ROTATEFACTOR * dt );
538    }
539    void CommonController::copyTargetOrientation( float dt )
540    {
541        if ( bHasTargetOrientation_ )
542        {   
543            copyOrientation( targetOrientation_, dt );
544        }
545    }
546    void CommonController::lookAtTarget(float dt)
547    {
548        ControllableEntity* entity = this->getControllableEntity();
549        if ( !entity )
550            return;
551        Vector2 coord = get2DViewCoordinates
552            ( entity->getPosition() , 
553            entity->getOrientation()  * WorldEntity::FRONT, 
554            entity->getOrientation()  * WorldEntity::UP, 
555            positionOfTarget_ );
556
557        //rotates should be in range [-1,+1], clamp cuts off all that is not
558        float rotateX = -clamp( coord.x * 10, -1.0f, 1.0f );
559        float rotateY = clamp( coord.y * 10, -1.0f, 1.0f ); 
560   
561        //Yaw and Pitch are enough to start facing the target
562        this->getControllableEntity() ->rotateYaw( ROTATEFACTOR * rotateX * dt );
563        this->getControllableEntity() ->rotatePitch( ROTATEFACTOR * rotateY * dt );
564    }
565    void CommonController::setTargetPosition( const Vector3& target )
566    {
567        this->targetPosition_ = target;
568        this->bHasTargetPosition_ = true;
569    }
570
571    void CommonController::setTargetOrientation( const Quaternion& orient )
572    {
573        this->targetOrientation_=orient;
574        this->bHasTargetOrientation_=true;
575    }
576
577    void CommonController::setTargetOrientation( ControllableEntity* target )
578    {
579        if ( target )
580            setTargetOrientation( target->getOrientation() );
581    }
582
583    //------------------------------------------------------------------------------
584    //-------------------------------Fighting methods-------------------------------
585    //------------------------------------------------------------------------------
586
587    void CommonController::setTarget( ControllableEntity* target )
588    {
589        this->target_ = target;       
590        if ( this->target_ )
591        {
592            this->setPositionOfTarget( target_->getWorldPosition() );
593        }
594    }
595    void CommonController::setPositionOfTarget( const Vector3& target )
596    {
597        this->positionOfTarget_ = target;
598        this->bHasPositionOfTarget_ = true;
599    }
600    void CommonController::setOrientationOfTarget( const Quaternion& orient )
601    {
602        this->orientationOfTarget_=orient;
603        this->bHasOrientationOfTarget_=true;
604    }
605    void CommonController::setProtect (ControllableEntity* protect)
606    {
607        this->protect_ = protect;
608    }
609    ControllableEntity* CommonController::getProtect ()
610    {
611        return this->protect_;
612    }
613    void CommonController::maneuver() 
614    {
615        maneuverCounter_++;
616        if (maneuverCounter_ > 5)
617            maneuverCounter_ = 0;
618
619        if ( !this->target_ || !this->getControllableEntity())
620            return;
621       
622        Vector3 thisPosition = this->getControllableEntity()->getWorldPosition();
623        this->setPositionOfTarget( getPredictedPosition( 
624            thisPosition, 
625            hardcoded_projectile_speed, 
626            this->target_->getWorldPosition() , 
627            this->target_->getVelocity() 
628            )  );
629        this->setOrientationOfTarget( this->target_->getOrientation() );
630
631        Vector3 diffVector = this->positionOfTarget_ - thisPosition;
632        float diffLength = diffVector.length();
633        Vector3 diffUnit = diffVector/diffLength;
634
635        bool bTargetIsLookingAtThis = this->isLooking ( this->target_, getControllableEntity(), math::pi/10.0f );
636       
637        //too far? well, come closer then
638        if ( diffLength > this->attackRange_ )
639        {
640            this->setTargetPosition( this->positionOfTarget_ );
641        }
642        //too close? How do u expect to dodge anything? Just attack!
643        else if ( diffLength < 500 )
644        {   
645            //at this point, just look and shoot
646            if ( diffLength < 250 )
647            {
648                this->stopMoving();
649                this->startLookingAtTarget();
650            }
651            else
652            {
653                this->setTargetPosition( this->positionOfTarget_ );
654            }
655        }
656        //Good distance? Check if target looks at us. It doesn't? Go hunt!
657        else if ( !bTargetIsLookingAtThis )
658        {
659            this->setTargetPosition( this->positionOfTarget_ );
660        }
661        //That's unfortunate, he is looking and probably shooting... try to dodge what we can... 
662        else 
663        {   
664            if (maneuverCounter_ == 0)
665            {
666                this->setTargetPosition( this->positionOfTarget_ );   
667                return;
668            }
669            dodge( thisPosition, diffUnit );
670        }
671    }
672   
673    void CommonController::dodge(Vector3& thisPosition, Vector3& diffUnit)
674    {
675        float factorX = 0, factorY = 0, factorZ = 0;
676        float rand = randomInRange (0, 1);
677   
678        if (rand <= 0.5)
679        { factorX = 1; }
680        else
681        { factorX = -1; }
682        rand = randomInRange (0, 1);
683        if (rand <= 0.5)
684        { factorY = 1; }
685        else
686        { factorY = -1; }
687        rand = randomInRange (0, 1);
688        if (rand <= 0.5)
689        { factorZ = 1; }
690        else
691        { factorZ = -1; }
692
693        Vector3 target = ( diffUnit )* 8000.0f;
694        Vector3* randVector = new Vector3( 
695            factorX * randomInRange( 10000, 40000 ), 
696            factorY * randomInRange( 10000, 40000 ), 
697            factorZ * randomInRange( 10000, 40000 ) 
698        );
699        Vector3 projection = randVector->dotProduct( diffUnit )* diffUnit;
700        *randVector -= projection;
701        target += *randVector;
702        this->setTargetPosition( thisPosition + target );
703    }
704    bool CommonController::canFire() 
705    {
706        //no target? why fire?
707        if ( !this->target_ )
708            return false;
709
710        Vector3 newPositionOfTarget = getPredictedPosition( this->getControllableEntity() ->getWorldPosition() , 
711            hardcoded_projectile_speed, this->target_->getWorldPosition() , this->target_->getVelocity() );
712        if ( newPositionOfTarget != Vector3::ZERO )
713        {
714            this->setPositionOfTarget( newPositionOfTarget );
715        }
716
717        float squaredDistance = squaredDistanceToTarget();
718
719        if ( squaredDistance < this->attackRange_*this->attackRange_ && this->isLookingAtTarget( math::pi / 20.0f)) 
720        {
721            return true;
722        }
723        else
724        {
725            return false;
726        }
727    }
728    void CommonController::doFire() 
729    {
730        if ( !this->target_ || !this->getControllableEntity() )
731        {
732            return;
733        }
734     
735        Pawn* pawn = orxonox_cast<Pawn*>( this->getControllableEntity() );
736
737        if ( pawn )
738            pawn->setAimPosition( this->positionOfTarget_ );
739        this->getControllableEntity() ->fire( 0 );
740    }
741    void CommonController::setClosestTarget()
742    {
743        this->setTarget (static_cast<ControllableEntity*>( closestTarget() ) ); 
744    }
745    Pawn* CommonController::closestTarget()
746    {
747        if (!this->getControllableEntity())
748            return 0;
749
750        Pawn* closestTarget = 0;
751        float minDistance =  std::numeric_limits<float>::infinity();
752        Gametype* gt = this->getGametype();
753        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
754        {
755            if ( CommonController::sameTeam (this->getControllableEntity(), static_cast<ControllableEntity*>(*itP), gt) )
756                continue;
757
758            float distance = CommonController::distance (*itP, this->getControllableEntity());
759            if (distance < minDistance)
760            {
761                closestTarget = *itP;
762                minDistance = distance;
763            }
764        }
765        if (closestTarget)
766        {
767           return closestTarget;
768        } 
769        return 0; 
770    }
771    void CommonController::startAttackingEnemiesThatAreClose()
772    {
773        if (this->action_ != Action::FIGHT && this->action_ != Action::FIGHTALL)
774        {
775            if ( (this->target_ && this->distance (this->getControllableEntity(), this->target_) > this->attackRange_) 
776                || !this->target_ )
777            {
778                Pawn* newTarget = this->closestTarget();
779                if ( newTarget && 
780                    this->distance (this->getControllableEntity(), static_cast<ControllableEntity*>(newTarget))
781                        <= this->attackRange_ )
782                {
783                    Point p = { Action::FIGHT, this->getName(newTarget), Vector3::ZERO, false };
784                    this->parsedActionpoints_.push_back(p);
785                    this->executeActionpoint();
786                }
787            }
788        }
789    }
790
791    //------------------------------------------------------------------------------
792    //------------------------------Actionpoint methods-----------------------------
793    //------------------------------------------------------------------------------
794
795    //POST: this starts doing what was asked by the last element of parsedActionpoints_,
796    //if last element was failed to be parsed, next element will be executed.
797    void CommonController::executeActionpoint()
798    {
799        if (this->bLoop_)
800        {
801            if (!this->loopActionpoints_.empty())
802            {
803                this->action_ = this->loopActionpoints_.back().action;
804                switch ( this->action_ )
805                {
806                    case Action::FIGHT:
807                    {
808                        std::string targetName = this->loopActionpoints_.back().name;
809                        if (targetName == "")
810                        {
811                            break;
812                        }
813                        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
814                        {
815                            if (CommonController::getName(*itP) == targetName)
816                            {
817                                this->setTarget (static_cast<ControllableEntity*>(*itP));
818                            }
819                        }         
820                        break;
821                    }
822                    case Action::FLY:
823                    {
824                        this->setTargetPosition( this->loopActionpoints_.back().position );
825                        if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
826                        {
827                            this->nextActionpoint();
828                            this->executeActionpoint();
829                        }
830                        break;
831                    }
832                    case Action::PROTECT:
833                    {
834                        std::string protectName = this->loopActionpoints_.back().name;
835                        if (protectName == "reservedKeyword:human")
836                        {
837                            for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
838                            {
839                                if (orxonox_cast<ControllableEntity*>(*itP) && ((*itP)->getController()) && orxonox_cast <NewHumanController*> ((*itP)->getController()))
840                                {
841                                    this->setProtect (static_cast<ControllableEntity*>(*itP));
842                                }
843                            }
844                        }
845                        else
846                        {
847                            for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
848                            {
849                                if (CommonController::getName(*itP) == protectName)
850                                {
851                                    this->setProtect (static_cast<ControllableEntity*>(*itP));
852                                }
853                            }                           
854                        }
855                        if (!this->getProtect())
856                        {
857                            this->nextActionpoint();
858                            this->executeActionpoint();
859                        }
860                        break;
861                    }
862                    case Action::NONE:
863                    {
864                        break;
865                    }
866                    case Action::FIGHTALL:
867                    {
868                        break;
869                    }
870                    case Action::ATTACK:
871                    {
872                        std::string targetName = this->loopActionpoints_.back().name;
873
874                        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
875                        {
876                            if (CommonController::getName(*itP) == targetName)
877                            {
878                                this->setTarget (static_cast<ControllableEntity*>(*itP));
879                            }
880                        }
881                        if (!this->hasTarget())
882                        {
883                            this->nextActionpoint();
884                            this->executeActionpoint();
885                        }
886                        break;
887                    }
888                    default:
889                        break;
890                }
891            }
892            else
893            {
894                this->bLoop_ = false;
895            }
896        }
897        else
898        {
899            if (!this->parsedActionpoints_.empty())
900            {
901                if (this->parsedActionpoints_.back().inLoop)
902                {
903                    //MOVES all points that are in loop to a loop vector
904                    this->fillLoop();
905                    this->bLoop_ = true;
906                    executeActionpoint();
907                    return;
908                }
909                this->action_ = this->parsedActionpoints_.back().action;
910                switch ( this->action_ )
911                {
912                    case Action::FIGHT:
913                    {
914                        std::string targetName = this->parsedActionpoints_.back().name;
915                        if (targetName == "")
916                        {
917                            break;
918                        }
919                        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
920                        {
921                            if (CommonController::getName(*itP) == targetName)
922                            {
923                                this->setTarget (static_cast<ControllableEntity*>(*itP));
924                            }
925                        }         
926                        break;
927                    }
928                    case Action::FLY:
929                    {
930                        this->setTargetPosition( this->parsedActionpoints_.back().position );
931                        if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
932                        {
933                            this->nextActionpoint();
934                            this->executeActionpoint();
935                        }
936                        break;
937                    }
938                    case Action::PROTECT:
939                    {
940                       
941                        std::string protectName = this->parsedActionpoints_.back().name;
942                        if (protectName == "reservedKeyword:human")
943                        {
944                            for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
945                            {
946                                if (orxonox_cast<ControllableEntity*>(*itP) && ((*itP)->getController()) && orxonox_cast <NewHumanController*> ((*itP)->getController()))
947                                {
948                                    this->setProtect (static_cast<ControllableEntity*>(*itP));
949                                }
950                            }
951                        }
952                        else
953                        {
954                            for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
955                            {
956                                if (CommonController::getName(*itP) == protectName)
957                                {
958                                    this->setProtect (static_cast<ControllableEntity*>(*itP));
959                                }
960                            }                           
961                        }
962                        if (!this->getProtect())
963                        {
964                            this->nextActionpoint();
965                            this->executeActionpoint();
966                        }
967                        break;
968                    }
969                    case Action::NONE:
970                    {
971                        break;
972                    }
973                    case Action::FIGHTALL:
974                    {
975                        break;
976                    }
977                    case Action::ATTACK:
978                    {
979                        std::string targetName = this->parsedActionpoints_.back().name;
980
981                        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
982                        {
983                            if (CommonController::getName(*itP) == targetName)
984                            {
985                                this->setTarget (static_cast<ControllableEntity*>(*itP));
986                            }
987                        }
988                        if (!this->hasTarget())
989                        {
990                            this->nextActionpoint();
991                            this->executeActionpoint();
992                        }
993                        break;
994                    }
995                    default:
996                        break;
997                }
998            }
999            else
1000            {
1001                this->setTarget(0);
1002                this->setTargetPosition(this->getControllableEntity()->getWorldPosition());
1003                this->action_ = Action::NONE;
1004            }
1005        }
1006
1007    }
1008    void CommonController::stayNearProtect()
1009    {
1010        Vector3* targetRelativePosition;
1011        targetRelativePosition = new Vector3 (0, 300, 300); 
1012        Vector3 targetAbsolutePosition = ((this->getProtect()->getWorldPosition()) + 
1013            (this->getProtect()->getWorldOrientation()* (*targetRelativePosition)));
1014        this->setTargetPosition(targetAbsolutePosition);
1015    }
1016    void CommonController::nextActionpoint()
1017    {
1018        if (!this || !this->getControllableEntity())
1019            return;
1020        if (this->bLoop_)
1021        {
1022            if (!this->loopActionpoints_.empty())
1023            {
1024                this->moveBackToTop();
1025            }
1026        }
1027        else
1028        {
1029            if (!this->parsedActionpoints_.empty())
1030            {
1031                this->parsedActionpoints_.pop_back();
1032            }           
1033        }
1034        this->setAction(Action::NONE);
1035    }
1036    void CommonController::moveBackToTop()
1037    {
1038        Point temp = loopActionpoints_.back();
1039        loopActionpoints_.pop_back();
1040        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
1041        loopActionpoints_.push_back(temp);
1042        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
1043    }
1044    void CommonController::fillLoop()
1045    {
1046        loopActionpoints_.clear();
1047        fillLoopReversed();
1048        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
1049    }
1050    void CommonController::fillLoopReversed()
1051    {
1052        if (parsedActionpoints_.back().inLoop)
1053        {
1054            loopActionpoints_.push_back(parsedActionpoints_.back());
1055            parsedActionpoints_.pop_back();
1056        }
1057        if (parsedActionpoints_.back().inLoop)
1058        {
1059            fillLoopReversed();
1060        }
1061    }
1062    void CommonController::action()
1063    {
1064        if (!this || !this->getControllableEntity())
1065            return;
1066        // orxout (internal_error) << "Size of actions is " << this->parsedActionpoints_.size() << endl;
1067        this->startAttackingEnemiesThatAreClose();
1068        //No action -> pop one from stack
1069        if (this->action_ == Action::NONE || this->bTakenOver_)
1070        {
1071            if (this->parsedActionpoints_.empty() && this->loopActionpoints_.empty())
1072            {
1073                Point p = { Action::FIGHTALL, "", Vector3::ZERO, false };
1074                this->parsedActionpoints_.push_back (p);
1075            }
1076            this->executeActionpoint();
1077            this->bTakenOver_ = false;
1078        }
1079        //Action fightall -> fight till nobody alive
1080        if (this->action_ == Action::FIGHTALL)
1081        {
1082            if (!this->hasTarget())
1083            {
1084                //----find a target----
1085                ControllableEntity* newTarget = this->closestTarget();   
1086                if (newTarget)
1087                {
1088                    this->setAction (Action::FIGHTALL, newTarget);
1089                }
1090                else
1091                {
1092                    this->nextActionpoint();
1093                    return;
1094                }
1095            }
1096            else if (this->hasTarget())
1097            {
1098
1099            }
1100        }
1101        //Action fight -> fight as long as enemies in range
1102        else if (this->action_ == Action::FIGHT)
1103        {
1104            if (!this->hasTarget())
1105            {
1106                //----find a target----
1107                ControllableEntity* newTarget = this->closestTarget();   
1108                if (newTarget && 
1109                        CommonController::distance (this->getControllableEntity(), newTarget) < this->attackRange_)
1110                {
1111                    this->setAction (Action::FIGHT, newTarget);
1112                }
1113                else
1114                {
1115                    this->nextActionpoint();
1116                    return;
1117                }
1118            }
1119            else if (this->hasTarget())
1120            {
1121                //----fly in formation if far enough----
1122                Vector3 diffVector = this->positionOfTarget_ - this->getControllableEntity()->getWorldPosition();         
1123                   
1124                if (diffVector.length() > this->attackRange_)
1125                {
1126                    ControllableEntity* newTarget = this->closestTarget();
1127                   
1128                    if (newTarget && 
1129                        CommonController::distance (this->getControllableEntity(), newTarget) < this->attackRange_)
1130                    {
1131                        this->setAction (Action::FIGHT, newTarget);
1132                    }
1133                    else
1134                    {
1135                        this->nextActionpoint();
1136                        return;
1137                    }
1138                }
1139            }
1140        }
1141        else if (this->action_ == Action::FLY)
1142        {
1143            if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
1144            {
1145                this->nextActionpoint();   
1146                return;
1147            }
1148        }
1149        else if (this->action_ == Action::PROTECT)
1150        {
1151            if (!this->getProtect())
1152            {
1153                this->nextActionpoint(); 
1154                return;
1155            }
1156            this->stayNearProtect();
1157        }
1158        else if (this->action_ == Action::ATTACK)
1159        {   
1160            if (!this->hasTarget())
1161            {
1162                this->nextActionpoint();
1163                return;
1164            }
1165        }
1166        if (this->hasTarget())
1167        {
1168            //----choose where to go----
1169            this->maneuver();
1170            //----fire if you can----
1171            this->bShooting_ = this->canFire();               
1172        }
1173    }
1174    void CommonController::takeActionpoints (std::vector<Point > vector, std::vector<Point > loop, bool b)
1175    {
1176      this->parsedActionpoints_ = vector;
1177      this->loopActionpoints_ = loop;
1178      this->bLoop_ = this->bLoop_;
1179      this->bTakenOver_ = true;
1180      // orxout(internal_error) << "Top action is " << this->parsedActionpoints_.back().action << endl;
1181    }
1182    void CommonController::boostControl()
1183    {
1184        SpaceShip* ship = orxonox_cast<SpaceShip*>(this->getControllableEntity());
1185        if(ship == NULL) return;
1186        if(ship->getBoostPower()*1.5f > ship->getInitialBoostPower() ) //upper limit ->boost
1187        {
1188
1189            this->getControllableEntity()->boost(true);
1190        }
1191        else if(ship->getBoostPower()*4.0f < ship->getInitialBoostPower()) //lower limit ->do not boost
1192        {
1193           this->getControllableEntity()->boost(false);
1194        }
1195    }
1196}
Note: See TracBrowser for help on using the repository browser.