Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

works for the most part, still need to fix Section and Wingman

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