Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10854 was 10854, checked in by gania, 8 years ago

Fixed some bugs, only DivisionController works for now

File size: 33.6 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or ( at your option )any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      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
42namespace orxonox
43{
44
45    RegisterClass( CommonController );
46    const float SPEED = 0.9f/0.02f;
47    const float ROTATEFACTOR = 1.0f/0.02f;
48
49    //Table of content:
50    //Constructor, Destructor & tick
51    //XML methods
52    //World interaction
53    //Helper methods
54    //Flying methods
55    //Fighting methods
56    //Actionpoint methods
57
58
59    //------------------------------------------------------------------------------
60    //------------------------Constructor, Destructor & tick------------------------
61    //------------------------------------------------------------------------------
62   
63    CommonController::CommonController( Context* context ): Controller( context )
64    {
65        this->squaredaccuracy_ = 10000;
66        this->bFirstTick_ = true;
67        this->tolerance_ = 50;
68        this->action_ = Action::NONE;
69        this->stopLookingAtTarget();
70        this->attackRange_ = 2500;
71        RegisterObject( CommonController );
72    }
73    CommonController::~CommonController() 
74    {
75       
76    }
77    void CommonController::tick(float dt)
78    {
79        if (this->bHasTargetPosition_)
80        {
81            this->moveToTargetPosition(dt);
82        }
83        else if (this->bLookAtTarget_)
84        {
85            this->lookAtTarget(dt);
86        }
87        if (bShooting_)
88        {
89            this->doFire();
90        }
91        if (this->bFirstTick_)
92        {
93            std::reverse(parsedActionpoints_.begin(), parsedActionpoints_.end());
94            std::reverse(actionpoints_.begin(), actionpoints_.end());
95        }
96        if (this->bFirstTick_)
97            this->bFirstTick_ = false;
98        SUPER(CommonController, tick, dt);
99    }
100
101    //------------------------------------------------------------------------------
102    //----------------------------------XML methods---------------------------------
103    //------------------------------------------------------------------------------
104   
105    void CommonController::XMLPort( Element& xmlelement, XMLPort::Mode mode )
106    {
107        SUPER( CommonController, XMLPort, xmlelement, mode );
108        XMLPortParam( CommonController, "formationMode", setFormationModeXML, getFormationModeXML,  xmlelement, mode );
109        XMLPortObject(CommonController, WorldEntity, "actionpoints", addActionpoint, getActionpoint,  xmlelement, mode);
110    }
111    void CommonController::setFormationModeXML( std::string val )
112    {
113        const std::string valUpper = getUppercase( val );
114        FormationMode::Value value;
115       
116        if ( valUpper == "WALL" )
117            value = FormationMode::WALL;
118        else if ( valUpper == "FINGER4" )
119            value = FormationMode::FINGER4;
120        else if ( valUpper == "DIAMOND" )
121            value = FormationMode::DIAMOND;
122        else
123            ThrowException( ParseError, std::string( "Attempting to set an unknown FormationMode: '" )+ val + "'." );
124        this->setFormationMode( value );
125    }
126    std::string CommonController::getFormationModeXML() 
127    {
128        switch ( this->formationMode_ )
129        {
130            case FormationMode::WALL:
131            { return "WALL"; break; }
132            case FormationMode::FINGER4:
133            { return "FINGER4"; break; }
134            case FormationMode::DIAMOND:
135            { return "DIAMOND"; break; }
136            default:
137                return "DIAMOND"; break;
138        }
139    }
140    void CommonController::setFormationMode(FormationMode::Value val)
141    { 
142        this->formationMode_ = val; 
143    }
144    FormationMode::Value CommonController::getFormationMode() const
145    { 
146        return this->formationMode_; 
147    }
148    void CommonController::setRank(Rank::Value val)
149    { 
150        this->rank_ = val; 
151    }
152    Rank::Value CommonController::getRank() const
153    { 
154        return this->rank_; 
155    }
156    void CommonController::addActionpoint(WorldEntity* actionpoint)
157    {
158        std::string actionName;
159        Vector3 position;
160        std::string targetName;
161        Point p;
162        if (static_cast<Actionpoint*> (actionpoint))
163        {
164            Actionpoint* ap = static_cast<Actionpoint*> (actionpoint);
165            actionName = ap->getActionXML();
166            targetName = ap->getName();
167            position = ap->getWorldPosition();
168
169            Action::Value value;
170           
171            if ( actionName == "FIGHT" )
172            { value = Action::FIGHT; }
173            else if ( actionName == "FLY" )
174            { value = Action::FLY; }
175            else if ( actionName == "PROTECT" )
176            { value = Action::PROTECT; }
177            else if ( actionName == "NONE" )
178            { value = Action::NONE; }
179            else if ( actionName == "FIGHTALL" )
180            { value = Action::FIGHTALL; }
181            else if ( actionName == "ATTACK" )
182            { value = Action::ATTACK; }
183            else
184                ThrowException( ParseError, std::string( "Attempting to set an unknown Action: '" )+ actionName + "'." );
185            p.action = value; p.name = targetName; p.position = position;
186            parsedActionpoints_.push_back(p);
187        }
188        else
189        {
190            p.action = Action::FLY; p.name = ""; p.position = actionpoint->getWorldPosition();
191        }
192            parsedActionpoints_.push_back(p);
193            this->actionpoints_.push_back(actionpoint);
194    }
195    WorldEntity* CommonController::getActionpoint(unsigned int index) const
196    {
197        if (index < this->actionpoints_.size())
198            return this->actionpoints_[index];
199        else
200            return 0;
201    }
202
203    //------------------------------------------------------------------------------
204    //-------------------------------World interaction------------------------------
205    //------------------------------------------------------------------------------
206
207    //"Virtual" methods
208    bool CommonController::setWingman ( CommonController* wingman )
209    { return false; }
210    bool CommonController::hasWingman() 
211    { return true; }
212    bool CommonController::hasTarget() 
213    {
214        if ( this->target_ )
215            return true;
216        return false;
217    }
218    ControllableEntity* CommonController::getTarget()
219    {
220        return this->target_;
221    }
222    Action::Value CommonController::getAction ()
223    {
224        return this->action_;
225    }
226    std::string CommonController::getActionName()
227    {
228        switch ( this->action_ )
229        {
230            case Action::FIGHT:
231            { return "FIGHT"; break; }
232            case Action::FLY:
233            { return "FLY"; break; }
234            case Action::PROTECT:
235            { return "PROTECT"; break; }
236            case Action::NONE:
237            { return "NONE"; break; }
238            case Action::FIGHTALL:
239            { return "FIGHTALL"; break; }
240            case Action::ATTACK:
241            { return "ATTACK"; break; }
242            default:
243                return "NONE";
244                break;
245        }
246    }
247    void CommonController::setAction (Action::Value action)
248    {
249        this->action_ = action;
250    }
251    void CommonController::setAction (Action::Value action, ControllableEntity* target)
252    {
253        this->action_ = action;
254        if (action == Action::FIGHT || action == Action::FIGHTALL || action == Action::ATTACK)
255        {   
256            if (target)
257                this->setTarget (target);
258        }
259        else if (action == Action::PROTECT)
260        {
261            if (target)
262                this->setProtect (target);
263        }
264    }
265    void CommonController::setAction (Action::Value action, const Vector3& target)
266    {
267        this->action_ = action;
268        if (action == Action::FLY)
269        {
270            this->setTargetPosition (target);
271        }
272    }
273    void CommonController::setAction (Action::Value action, const Vector3& target,  const Quaternion& orient )
274    {
275        this->action_ = action;
276        if (action == Action::FLY)
277        {
278            this->setTargetPosition (target);
279            this->setTargetOrientation (orient);
280        } 
281    }
282
283    //------------------------------------------------------------------------------
284    //--------------------------------Helper methods--------------------------------
285    //------------------------------------------------------------------------------
286
287    float CommonController::randomInRange( float a, float b )
288    {
289        float random = rnd( 1.0f );
290        float diff = b - a;
291        float r = random * diff;
292        return a + r;
293    }
294    float CommonController::distance (ControllableEntity* entity1, ControllableEntity* entity2)
295    {
296        if (!entity1 || !entity2)
297            return std::numeric_limits<float>::infinity();
298        return ( entity1->getPosition() - entity2->getPosition() ).length();
299    }
300    bool CommonController::sameTeam (ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
301    {
302        /*if (!entity1 || !entity2)
303            return false;
304        return entity1->getTeam() == entity2->getTeam();*/
305        if (entity1 == entity2)
306            return true;
307
308        int team1 = entity1->getTeam();
309        int team2 = entity2->getTeam();
310
311        Controller* controller = 0;
312        if (entity1->getController())
313            controller = entity1->getController();
314        else
315            controller = entity1->getXMLController();
316        if (controller)
317        {
318            CommonController* ac = orxonox_cast<CommonController*>(controller);
319            if (ac)
320                team1 = ac->getTeam();
321        }
322
323        if (entity2->getController())
324            controller = entity2->getController();
325        else
326            controller = entity2->getXMLController();
327        if (controller)
328        {
329            CommonController* ac = orxonox_cast<CommonController*>(controller);
330            if (ac)
331                team2 = ac->getTeam();
332        }
333
334        TeamGametype* tdm = orxonox_cast<TeamGametype*>(gametype);
335        if (tdm)
336        {
337            if (entity1->getPlayer())
338                team1 = tdm->getTeam(entity1->getPlayer());
339
340            if (entity2->getPlayer())
341                team2 = tdm->getTeam(entity2->getPlayer());
342        }
343
344        TeamBaseMatchBase* base = 0;
345        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
346        if (base)
347        {
348            switch (base->getState())
349            {
350                case BaseState::ControlTeam1:
351                    team1 = 0;
352                    break;
353                case BaseState::ControlTeam2:
354                    team1 = 1;
355                    break;
356                case BaseState::Uncontrolled:
357                default:
358                    team1 = -1;
359            }
360        }
361        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
362        if (base)
363        {
364            switch (base->getState())
365            {
366                case BaseState::ControlTeam1:
367                    team2 = 0;
368                    break;
369                case BaseState::ControlTeam2:
370                    team2 = 1;
371                    break;
372                case BaseState::Uncontrolled:
373                default:
374                    team2 = -1;
375            }
376        }
377
378        DroneController* droneController = 0;
379        droneController = orxonox_cast<DroneController*>(entity1->getController());
380        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2)
381            return true;
382        droneController = orxonox_cast<DroneController*>(entity2->getController());
383        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1)
384            return true;
385        DroneController* droneController1 = orxonox_cast<DroneController*>(entity1->getController());
386        DroneController* droneController2 = orxonox_cast<DroneController*>(entity2->getController());
387        if (droneController1 && droneController2 && droneController1->getOwner() == droneController2->getOwner())
388            return true;
389
390        Dynamicmatch* dynamic = orxonox_cast<Dynamicmatch*>(gametype);
391        if (dynamic)
392        {
393            if (dynamic->notEnoughPigs||dynamic->notEnoughKillers||dynamic->notEnoughChasers) {return false;}
394
395            if (entity1->getPlayer())
396                team1 = dynamic->getParty(entity1->getPlayer());
397
398            if (entity2->getPlayer())
399                team2 = dynamic->getParty(entity2->getPlayer());
400
401            if (team1 ==-1 ||team2 ==-1 ) {return false;}
402            else if (team1 == dynamic->chaser && team2 != dynamic->chaser) {return false;}
403            else if (team1 == dynamic->piggy && team2 == dynamic->chaser) {return false;}
404            else if (team1 == dynamic->killer && team2 == dynamic->chaser) {return false;}
405            else return true;
406        }
407
408        return (team1 == team2 && team1 != -1);
409    }
410    bool CommonController::isLooking( ControllableEntity* entityThatLooks, ControllableEntity* entityBeingLookedAt, float angle )
411    {
412        if ( !entityThatLooks || !entityBeingLookedAt )
413            return false;
414        return ( getAngle( entityThatLooks ->getPosition() , 
415            entityThatLooks->getOrientation()  * WorldEntity::FRONT, 
416            entityBeingLookedAt->getWorldPosition() ) < angle );
417    }
418    std::string CommonController::getName(Pawn* entity)
419    {
420        std::string name = entity->getName();
421        if (name == "")
422        {
423            const void * address = static_cast<const void*>(entity);
424            std::stringstream ss;
425            ss << address; 
426            name = ss.str();           
427        }
428        return name;
429    }
430    float CommonController::squaredDistanceToTarget()  const
431    {
432        if ( !this->getControllableEntity()  )
433            return 0;
434        if ( !this->target_ || !this->getControllableEntity() )
435            return ( this->getControllableEntity() ->getPosition() .squaredDistance( this->targetPosition_ ) );
436        else
437            return ( this->getControllableEntity() ->getPosition() .squaredDistance( this->positionOfTarget_ ) );
438    }
439    bool CommonController::isLookingAtTarget( float angle )
440    {
441        if ( !this->getControllableEntity()  || !this->target_ )
442            return false;
443        return this->isLooking(this->getControllableEntity(), this->getTarget(), angle);
444    }
445
446
447    //------------------------------------------------------------------------------
448    //--------------------------------Flying methods--------------------------------
449    //------------------------------------------------------------------------------
450
451    void CommonController::stopMoving()
452    {
453        this->bHasTargetPosition_ = false;
454    }
455    void CommonController::stopLookingAtTarget()
456    {
457        this->bLookAtTarget_ = false;
458    }
459    void CommonController::startLookingAtTarget()
460    {
461        this->bLookAtTarget_ = true;
462    }
463    void CommonController::moveToPosition( const Vector3& target, float dt )
464    {
465        ControllableEntity* entity = this->getControllableEntity();
466        Vector2 coord = get2DViewCoordinates
467            ( entity->getPosition() , 
468            entity->getOrientation()  * WorldEntity::FRONT, 
469            entity->getOrientation()  * WorldEntity::UP, 
470            target );
471
472        float distance = ( target - this->getControllableEntity() ->getPosition() ).length();
473        float rotateX = -clamp( coord.x * 10, -1.0f, 1.0f );
474        float rotateY = clamp( coord.y * 10, -1.0f, 1.0f );
475
476        if ( distance > this->tolerance_ )
477        {
478            this->getControllableEntity() ->rotateYaw( ROTATEFACTOR * rotateX * dt );
479            this->getControllableEntity() ->rotatePitch( ROTATEFACTOR * rotateY * dt );
480
481            if ( distance < 300 )
482            {
483                if ( bHasTargetOrientation_ )
484                {
485                    copyTargetOrientation( dt );
486                }
487            }
488            if (distance > this->tolerance_*1.5f || (rotateX > -0.01 && rotateX < 0.01 && rotateY > -0.01 && rotateY < 0.01))
489                this->getControllableEntity() ->moveFrontBack( SPEED * dt );
490        }
491        else
492        {     
493            bHasTargetPosition_ = false;
494            bHasTargetOrientation_ = false;
495        }
496    }
497    void CommonController::moveToTargetPosition(float dt)
498    {
499        this->moveToPosition (this->targetPosition_, dt);
500    }
501    void CommonController::copyOrientation( const Quaternion& orient, float dt )
502    {
503        //roll angle difference in radian
504        float diff=orient.getRoll(false).valueRadians() -
505                        ( this->getControllableEntity() ->getOrientation() .getRoll( false ).valueRadians() );
506        while( diff>math::twoPi )diff-=math::twoPi;
507        while( diff<-math::twoPi )diff+=math::twoPi;
508        this->getControllableEntity() ->rotateRoll( diff*ROTATEFACTOR * dt );
509    }
510    void CommonController::copyTargetOrientation( float dt )
511    {
512        if ( bHasTargetOrientation_ )
513        {   
514            copyOrientation( targetOrientation_, dt );
515        }
516    }
517    void CommonController::lookAtTarget(float dt)
518    {
519        ControllableEntity* entity = this->getControllableEntity();
520        if ( !entity )
521            return;
522        Vector2 coord = get2DViewCoordinates
523            ( entity->getPosition() , 
524            entity->getOrientation()  * WorldEntity::FRONT, 
525            entity->getOrientation()  * WorldEntity::UP, 
526            positionOfTarget_ );
527
528        //rotates should be in range [-1,+1], clamp cuts off all that is not
529        float rotateX = -clamp( coord.x * 10, -1.0f, 1.0f );
530        float rotateY = clamp( coord.y * 10, -1.0f, 1.0f ); 
531   
532        //Yaw and Pitch are enough to start facing the target
533        this->getControllableEntity() ->rotateYaw( ROTATEFACTOR * rotateX * dt );
534        this->getControllableEntity() ->rotatePitch( ROTATEFACTOR * rotateY * dt );
535    }
536    void CommonController::setTargetPosition( const Vector3& target )
537    {
538        this->targetPosition_ = target;
539        this->bHasTargetPosition_ = true;
540    }
541
542    void CommonController::setTargetOrientation( const Quaternion& orient )
543    {
544        this->targetOrientation_=orient;
545        this->bHasTargetOrientation_=true;
546    }
547
548    void CommonController::setTargetOrientation( ControllableEntity* target )
549    {
550        if ( target )
551            setTargetOrientation( target->getOrientation() );
552    }
553
554    //------------------------------------------------------------------------------
555    //-------------------------------Fighting methods-------------------------------
556    //------------------------------------------------------------------------------
557
558    void CommonController::setTarget( ControllableEntity* target )
559    {
560        this->target_ = target;       
561        if ( this->target_ )
562        {
563            this->setPositionOfTarget( target_->getWorldPosition() );
564        }
565    }
566    void CommonController::setPositionOfTarget( const Vector3& target )
567    {
568        this->positionOfTarget_ = target;
569        this->bHasPositionOfTarget_ = true;
570    }
571    void CommonController::setOrientationOfTarget( const Quaternion& orient )
572    {
573        this->orientationOfTarget_=orient;
574        this->bHasOrientationOfTarget_=true;
575    }
576    void CommonController::setProtect (ControllableEntity* protect)
577    {
578        this->protect_ = protect;
579    }
580    ControllableEntity* CommonController::getProtect ()
581    {
582        return this->protect_;
583    }
584    void CommonController::maneuver() 
585    {
586        maneuverCounter_++;
587        if (maneuverCounter_ > 5)
588            maneuverCounter_ = 0;
589
590        if ( !this->target_ || !this->getControllableEntity())
591            return;
592       
593        Vector3 thisPosition = this->getControllableEntity()->getWorldPosition();
594        this->setPositionOfTarget( getPredictedPosition( 
595            thisPosition, 
596            hardcoded_projectile_speed, 
597            this->target_->getWorldPosition() , 
598            this->target_->getVelocity() 
599            )  );
600        this->setOrientationOfTarget( this->target_->getOrientation() );
601
602        Vector3 diffVector = this->positionOfTarget_ - thisPosition;
603        float diffLength = diffVector.length();
604        Vector3 diffUnit = diffVector/diffLength;
605
606        bool bTargetIsLookingAtThis = this->isLooking ( this->target_, getControllableEntity(), math::pi/10.0f );
607       
608        //too far? well, come closer then
609        if ( diffLength > this->attackRange_ )
610        {
611            this->setTargetPosition( this->positionOfTarget_ );
612        }
613        //too close? How do u expect to dodge anything? Just attack!
614        else if ( diffLength < 500 )
615        {   
616            //at this point, just look and shoot
617            if ( diffLength < 250 )
618            {
619                this->stopMoving();
620                this->startLookingAtTarget();
621            }
622            else
623            {
624                this->setTargetPosition( this->positionOfTarget_ );
625            }
626        }
627        //Good distance? Check if target looks at us. It doesn't? Go hunt!
628        else if ( !bTargetIsLookingAtThis )
629        {
630            this->setTargetPosition( this->positionOfTarget_ );
631        }
632        //That's unfortunate, he is looking and probably shooting... try to dodge what we can... 
633        else 
634        {   
635            if (maneuverCounter_ == 0)
636            {
637                this->setTargetPosition( this->positionOfTarget_ );   
638                return;
639            }
640            dodge( thisPosition, diffUnit );
641        }
642    }
643   
644    void CommonController::dodge(Vector3& thisPosition, Vector3& diffUnit)
645    {
646        float factorX = 0, factorY = 0, factorZ = 0;
647        float rand = randomInRange (0, 1);
648   
649        if (rand <= 0.5)
650        { factorX = 1; }
651        else
652        { factorX = -1; }
653        rand = randomInRange (0, 1);
654        if (rand <= 0.5)
655        { factorY = 1; }
656        else
657        { factorY = -1; }
658        rand = randomInRange (0, 1);
659        if (rand <= 0.5)
660        { factorZ = 1; }
661        else
662        { factorZ = -1; }
663
664        Vector3 target = ( diffUnit )* 8000.0f;
665        Vector3* randVector = new Vector3( 
666            factorX * randomInRange( 10000, 40000 ), 
667            factorY * randomInRange( 10000, 40000 ), 
668            factorZ * randomInRange( 10000, 40000 ) 
669        );
670        Vector3 projection = randVector->dotProduct( diffUnit )* diffUnit;
671        *randVector -= projection;
672        target += *randVector;
673        this->setTargetPosition( thisPosition + target );
674    }
675    bool CommonController::canFire() 
676    {
677        //no target? why fire?
678        if ( !this->target_ )
679            return false;
680
681        Vector3 newPositionOfTarget = getPredictedPosition( this->getControllableEntity() ->getWorldPosition() , 
682            hardcoded_projectile_speed, this->target_->getWorldPosition() , this->target_->getVelocity() );
683        if ( newPositionOfTarget != Vector3::ZERO )
684        {
685            this->setPositionOfTarget( newPositionOfTarget );
686        }
687
688        float squaredDistance = squaredDistanceToTarget();
689
690        if ( squaredDistance < this->attackRange_*this->attackRange_ && this->isLookingAtTarget( math::pi / 20.0f)) 
691        {
692            return true;
693        }
694        else
695        {
696            return false;
697        }
698    }
699    void CommonController::doFire() 
700    {
701        if ( !this->target_ || !this->getControllableEntity() )
702        {
703            return;
704        }
705     
706        Pawn* pawn = orxonox_cast<Pawn*>( this->getControllableEntity() );
707
708        if ( pawn )
709            pawn->setAimPosition( this->positionOfTarget_ );
710        this->getControllableEntity() ->fire( 0 );
711    }
712    void CommonController::setClosestTarget()
713    {
714        this->setTarget (static_cast<ControllableEntity*>( closestTarget() ) ); 
715    }
716    Pawn* CommonController::closestTarget()
717    {
718        if (!this->getControllableEntity())
719            return 0;
720
721        Pawn* closestTarget = 0;
722        float minDistance =  std::numeric_limits<float>::infinity();
723        Gametype* gt = this->getGametype();
724        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
725        {
726            if ( CommonController::sameTeam (this->getControllableEntity(), static_cast<ControllableEntity*>(*itP), gt) )
727                continue;
728
729            float distance = CommonController::distance (*itP, this->getControllableEntity());
730            if (distance < minDistance)
731            {
732                closestTarget = *itP;
733                minDistance = distance;
734            }
735        }
736        if (closestTarget)
737        {
738           return closestTarget;
739        } 
740        return 0; 
741    }
742    void CommonController::startAttackingEnemiesThatAreClose()
743    {
744        if (this->action_ != Action::FIGHT && this->action_ != Action::FIGHTALL)
745        {
746            if ( (this->target_ && this->distance (this->getControllableEntity(), this->target_) > this->attackRange_) 
747                || !this->target_ )
748            {
749                Pawn* newTarget = this->closestTarget();
750                if ( newTarget && 
751                    this->distance (this->getControllableEntity(), static_cast<ControllableEntity*>(newTarget))
752                        <= this->attackRange_ )
753                {
754                    Point p = { Action::FIGHT, this->getName(newTarget), Vector3::ZERO };
755                    this->parsedActionpoints_.push_back(p);
756                    this->executeActionpoint();
757                }
758            }
759        }
760    }
761
762    //------------------------------------------------------------------------------
763    //------------------------------Actionpoint methods-----------------------------
764    //------------------------------------------------------------------------------
765
766    //POST: this starts doing what was asked by the last element of parsedActionpoints_,
767    //if last element was failed to be parsed, next element will be executed.
768    void CommonController::executeActionpoint()
769    {
770        if (!this->parsedActionpoints_.empty())
771        {
772            this->action_ = this->parsedActionpoints_.back().action;
773
774            switch ( this->action_ )
775            {
776                case Action::FIGHT:
777                {
778                    std::string targetName = this->parsedActionpoints_.back().name;
779                    if (targetName == "")
780                    {
781                        break;
782                    }
783                    for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
784                    {
785                        if (CommonController::getName(*itP) == targetName)
786                        {
787                            this->setTarget (static_cast<ControllableEntity*>(*itP));
788                        }
789                    }         
790                    break;
791                }
792                case Action::FLY:
793                {
794                    this->setTargetPosition( this->parsedActionpoints_.back().position );
795                    if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
796                    {
797                        this->nextActionpoint();
798                        this->executeActionpoint();
799                    }
800                    break;
801                }
802                case Action::PROTECT:
803                {
804                    std::string protectName = this->parsedActionpoints_.back().name;
805
806                    for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
807                    {
808                        if (CommonController::getName(*itP) == protectName)
809                        {
810                            this->setProtect (static_cast<ControllableEntity*>(*itP));
811                        }
812                    }
813                    if (!this->getProtect())
814                    {
815                        this->nextActionpoint();
816                        this->executeActionpoint();
817                    }
818                    break;
819                }
820                case Action::NONE:
821                {
822                    break;
823                }
824                case Action::FIGHTALL:
825                {
826                    break;
827                }
828                case Action::ATTACK:
829                {
830                    std::string targetName = this->parsedActionpoints_.back().name;
831
832                    for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
833                    {
834                        if (CommonController::getName(*itP) == targetName)
835                        {
836                            this->setTarget (static_cast<ControllableEntity*>(*itP));
837                        }
838                    }
839                    if (!this->hasTarget())
840                    {
841                        this->nextActionpoint();
842                        this->executeActionpoint();
843                    }
844                    break;
845                }
846                default:
847                    break;
848            }
849        }
850        else
851        {
852            this->setTarget(0);
853            this->setTargetPosition(this->getControllableEntity()->getWorldPosition());
854            this->action_ = Action::NONE;
855        }
856    }
857    void CommonController::stayNearProtect()
858    {
859        Vector3* targetRelativePosition;
860        targetRelativePosition = new Vector3 (0, 300, 300); 
861        Vector3 targetAbsolutePosition = ((this->getProtect()->getWorldPosition()) + 
862            (this->getProtect()->getWorldOrientation()* (*targetRelativePosition)));
863        this->setTargetPosition(targetAbsolutePosition);
864    }
865    void CommonController::nextActionpoint()
866    {
867        if (!this->parsedActionpoints_.empty())
868        {
869            this->parsedActionpoints_.pop_back();
870        }
871        this->setAction(Action::NONE);
872    }
873    void CommonController::action()
874    {
875        this->startAttackingEnemiesThatAreClose();
876        //No action -> pop one from stack
877        if (this->action_ == Action::NONE)
878        {
879            this->executeActionpoint();
880        }
881        //Action fightall -> fight till nobody alive
882        if (this->action_ == Action::FIGHTALL)
883        {
884            if (!this->hasTarget())
885            {
886                //----find a target----
887                ControllableEntity* newTarget = this->closestTarget();   
888                if (newTarget)
889                {
890                    this->setAction (Action::FIGHTALL, newTarget);
891                }
892                else
893                {
894                    this->nextActionpoint();
895                    return;
896                }
897            }
898            else if (this->hasTarget())
899            {
900
901            }
902        }
903        //Action fight -> fight as long as enemies in range
904        else if (this->action_ == Action::FIGHT)
905        {
906            if (!this->hasTarget())
907            {
908                //----find a target----
909                ControllableEntity* newTarget = this->closestTarget();   
910                if (newTarget && 
911                        CommonController::distance (this->getControllableEntity(), newTarget) < this->attackRange_)
912                {
913                    this->setAction (Action::FIGHT, newTarget);
914                }
915                else
916                {
917                    this->nextActionpoint();
918                    return;
919                }
920            }
921            else if (this->hasTarget())
922            {
923                //----fly in formation if far enough----
924                Vector3 diffVector = this->positionOfTarget_ - this->getControllableEntity()->getWorldPosition();         
925                   
926                if (diffVector.length() > this->attackRange_)
927                {
928                    ControllableEntity* newTarget = this->closestTarget();
929                   
930                    if (newTarget && 
931                        CommonController::distance (this->getControllableEntity(), newTarget) < this->attackRange_)
932                    {
933                        this->setAction (Action::FIGHT, newTarget);
934                    }
935                    else
936                    {
937                        this->nextActionpoint();
938                        return;
939                    }
940                }
941            }
942        }
943        else if (this->action_ == Action::FLY)
944        {
945            if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
946            {
947                this->nextActionpoint();   
948                return;
949            }
950        }
951        else if (this->action_ == Action::PROTECT)
952        {
953            if (!this->getProtect())
954            {
955                this->nextActionpoint(); 
956                return;
957            }
958            this->stayNearProtect();
959        }
960        else if (this->action_ == Action::ATTACK)
961        {   
962            if (!this->hasTarget())
963            {
964                this->nextActionpoint();
965                return;
966            }
967        }
968        if (this->hasTarget())
969        {
970            //----choose where to go----
971            this->maneuver();
972            //----fire if you can----
973            this->bShooting_ = this->canFire();               
974        }
975    }
976}
Note: See TracBrowser for help on using the repository browser.