Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/formation/src/orxonox/controllers/FormationController.cc @ 9216

Last change on this file since 9216 was 8991, checked in by jo, 13 years ago

Works. (Seperate/independent states are used to manage the behaviour).

File size: 34.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
29#include <climits>
30#include "controllers/FormationController.h"
31
32#include "core/CoreIncludes.h"
33
34#include "core/XMLPort.h"
35#include "core/command/ConsoleCommand.h"
36
37#include "worldentities/ControllableEntity.h"
38#include "worldentities/pawns/Pawn.h"
39#include "worldentities/pawns/TeamBaseMatchBase.h"
40#include "gametypes/TeamDeathmatch.h"
41#include "gametypes/Dynamicmatch.h"
42//#include "gametypes/Mission.h" TODO: include mission after merging
43#include "gametypes/Gametype.h"
44#include "controllers/WaypointPatrolController.h"
45#include "controllers/NewHumanController.h"
46#include "controllers/DroneController.h"
47
48
49namespace orxonox
50{
51
52  SetConsoleCommand("FormationController", "formationflight",  &FormationController::formationflight);
53  SetConsoleCommand("FormationController", "masteraction",     &FormationController::masteraction);
54  SetConsoleCommand("FormationController", "followme",         &FormationController::followme);
55  SetConsoleCommand("FormationController", "passivebehaviour", &FormationController::passivebehaviour);
56  SetConsoleCommand("FormationController", "formationsize",    &FormationController::formationsize);
57
58
59
60
61  static const unsigned int STANDARD_MAX_FORMATION_SIZE = 9;
62  static const int RADIUS_TO_SEARCH_FOR_MASTERS = 5000;
63  static const int FORMATION_LENGTH =  110;
64  static const int FORMATION_WIDTH =  110;
65  static const int FREEDOM_COUNT = 4; //seconds the slaves in a formation will be set free when master attacks an enemy
66  static const float SPEED_MASTER = 0.6f;
67  static const float ROTATEFACTOR_MASTER = 0.2f;
68  static const float SPEED_FREE = 0.8f;
69  static const float ROTATEFACTOR_FREE = 0.8f;
70
71  FormationController::FormationController(BaseObject* creator) : Controller(creator)
72  {
73        RegisterObject(FormationController);
74
75        this->target_ = 0;
76        this->formationFlight_ = false;
77        this->passive_ = false;
78        this->maxFormationSize_ = STANDARD_MAX_FORMATION_SIZE;
79        this->myMaster_ = 0;
80        this->freedomCount_ = 0;
81
82        this->state_ = FREE;
83        this->formationMode_ = NORMAL;
84        this->specificMasterAction_ = NONE;
85        this->specificMasterActionHoldCount_  = 0;
86        this->bShooting_ = false;
87        this->bHasTargetPosition_ = false;
88        this->bHasTargetOrientation_=false;
89        this->speedCounter_ = 0.2f;
90        this->targetPosition_ = Vector3::ZERO;
91        //this->team_=-1;
92        this->target_.setCallback(createFunctor(&FormationController::targetDied, this));
93  }
94
95  FormationController::~FormationController()
96  {
97    if (this->isInitialized())
98        {
99            this->removeFromFormation();
100
101            for (ObjectList<FormationController>::iterator it = ObjectList<FormationController>::begin(); it; ++it)
102            {
103                if (*it != this)
104                {
105                    if (it->myMaster_ == this)
106                    {
107                        orxout(internal_error) << this << " is still master in " << (*it) << endl;
108                        it->myMaster_ = 0;
109                    }
110
111                    while (true)
112                    {
113                        std::vector<FormationController*>::iterator it2 = std::find(it->slaves_.begin(), it->slaves_.end(), this);
114                        if (it2 != it->slaves_.end())
115                        {
116                            orxout(internal_error) << this << " is still slave in " << (*it) << endl;
117                            it->slaves_.erase(it2);
118                        }
119                        else
120                            break;
121                    }
122                }
123            }
124        }
125  }
126
127  void FormationController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
128    {
129        SUPER(FormationController, XMLPort, xmlelement, mode);
130
131        XMLPortParam(FormationController, "formationFlight", setFormationFlight, getFormationFlight, xmlelement, mode).defaultValues(false);
132        XMLPortParam(FormationController, "formationSize", setFormationSize, getFormationSize, xmlelement, mode).defaultValues(STANDARD_MAX_FORMATION_SIZE);
133        XMLPortParam(FormationController, "passive", setPassive, getPassive, xmlelement, mode).defaultValues(false);
134    }
135
136
137
138  /**
139        @brief Activates / deactivates formationflight behaviour
140        @param form activate formflight if form is true
141    */
142  void FormationController::formationflight(const bool form)
143    {
144        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
145        {
146            Controller* controller = 0;
147
148            if (it->getController())
149                controller = it->getController();
150            else if (it->getXMLController())
151                controller = it->getXMLController();
152
153            if (!controller)
154                continue;
155
156            FormationController *aiController = orxonox_cast<FormationController*>(controller);
157
158            if (aiController)
159            {
160                aiController->formationFlight_ = form;
161                if (!form)
162                {
163                    aiController->removeFromFormation();
164                }
165            }
166        }
167    }
168
169  /**
170        @brief Get all masters to do a "specific master action"
171        @param action which action to perform (integer, so it can be called with a console command (tmp solution))
172    */
173    void FormationController::masteraction(const int action)
174    {
175        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
176        {
177            Controller* controller = 0;
178
179            if (it->getController())
180                controller = it->getController();
181            else if (it->getXMLController())
182                controller = it->getXMLController();
183
184            if (!controller)
185                continue;
186
187            FormationController *aiController = orxonox_cast<FormationController*>(controller);
188
189            if(aiController && aiController->state_ == MASTER)
190            {
191                if (action == 1)
192                    aiController->spinInit();
193                if (action == 2)
194                    aiController->turn180Init();
195            }
196        }
197    }
198
199  /**
200        @brief Sets shooting behaviour of pawns.
201        @param passive if true, bots won't shoot.
202    */
203    void FormationController::passivebehaviour(const bool passive)
204    {
205        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
206        {
207            Controller* controller = 0;
208
209            if (it->getController())
210                controller = it->getController();
211            else if (it->getXMLController())
212                controller = it->getXMLController();
213
214            if (!controller)
215                continue;
216
217            FormationController *aiController = orxonox_cast<FormationController*>(controller);
218
219            if(aiController)
220            {
221                aiController->passive_ = passive;
222            }
223        }
224    }
225
226  /**
227        @brief Sets maximal formation size
228        @param size maximal formation size.
229    */
230    void FormationController::formationsize(const int size)
231    {
232        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
233        {
234            Controller* controller = 0;
235
236            if (it->getController())
237                controller = it->getController();
238            else if (it->getXMLController())
239                controller = it->getXMLController();
240
241            if (!controller)
242                continue;
243
244            FormationController *aiController = orxonox_cast<FormationController*>(controller);
245
246            if(aiController)
247            {
248                aiController->maxFormationSize_ = size;
249            }
250        }
251    }
252
253  void FormationController::removeFromFormation()
254    {
255        if (this->state_ == SLAVE || this->myMaster_) // slaves can also be temporary free, so check if myMaster_ is set
256            this->unregisterSlave();
257        else if (this->state_ == MASTER)
258            this->setNewMasterWithinFormation();
259    }
260
261    void FormationController::moveToPosition(const Vector3& target)
262    {
263        if (!this->getControllableEntity())
264            return;
265
266        // Slave uses special movement if its master is in FOLLOW mode
267        if(this->state_ == SLAVE && this->myMaster_ && this->myMaster_->specificMasterAction_ == FOLLOW)
268        {
269//             this->followForSlaves(target);
270//             return;
271        }
272
273        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, target);
274        float distance = (target - this->getControllableEntity()->getPosition()).length();
275
276
277        if(this->state_ == FREE)
278        {
279            if (this->target_ || distance > 10)
280            {
281                // Multiply with ROTATEFACTOR_FREE to make them a bit slower
282                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_FREE * sgn(coord.x) * coord.x*coord.x);
283                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_FREE * sgn(coord.y) * coord.y*coord.y);
284            }
285
286            if (this->target_ && distance < 200 && this->getControllableEntity()->getVelocity().squaredLength() > this->target_->getVelocity().squaredLength())
287            {
288              this->getControllableEntity()->moveFrontBack(-0.05f); // They don't brake with full power to give the player a chance
289            } else this->getControllableEntity()->moveFrontBack(SPEED_FREE);
290        }
291
292
293
294        if(this->state_ == MASTER)
295        {
296            if (this->target_ || distance > 10)
297            {
298                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_MASTER * sgn(coord.x) * coord.x*coord.x);
299                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_MASTER * sgn(coord.y) * coord.y*coord.y);
300            }
301
302            if (this->target_ && distance < 200 && this->getControllableEntity()->getVelocity().squaredLength() > this->target_->getVelocity().squaredLength())
303            {
304                this->getControllableEntity()->moveFrontBack(-0.05f);
305            } else this->getControllableEntity()->moveFrontBack(SPEED_MASTER);
306        }
307
308
309
310        if(this->state_ == SLAVE)
311        {
312
313           this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR_MASTER * sgn(coord.x) * coord.x*coord.x);
314           this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR_MASTER * sgn(coord.y) * coord.y*coord.y);
315
316            if (distance < 300)
317            {
318                 if (bHasTargetOrientation_)
319                    {
320                        copyTargetOrientation();
321                    }
322                if (distance < 100)
323                {   //linear speed reduction
324                    this->getControllableEntity()->moveFrontBack(distance/100.0f*0.4f*SPEED_MASTER);
325                   
326                } else this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER);
327
328            } else {
329                this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER + distance/300.0f);
330            }
331        }
332
333        if (distance < 10)
334        {
335            this->positionReached();
336            bHasTargetOrientation_=false;
337        }
338    }
339
340
341
342  void FormationController::moveToTargetPosition()
343    {
344        this->moveToPosition(this->targetPosition_);
345    }
346
347  //copy the Roll orientation of given Quaternion.
348  void FormationController::copyOrientation(const Quaternion& orient)
349    {
350        //roll angle difference in radian
351        float diff=orient.getRoll(false).valueRadians()-(this->getControllableEntity()->getOrientation().getRoll(false).valueRadians());
352        while(diff>math::twoPi) diff-=math::twoPi;
353        while(diff<-math::twoPi) diff+=math::twoPi;
354        this->getControllableEntity()->rotateRoll(diff*ROTATEFACTOR_MASTER);
355    }
356
357    void FormationController::copyTargetOrientation()
358    {
359        if (bHasTargetOrientation_)
360        {
361            copyOrientation(targetOrientation_);
362        }
363    }
364
365
366   /**
367        @brief Unregisters a slave from its master. Initiated by a slave.
368    */
369    void FormationController::unregisterSlave()
370    {
371        if (this->myMaster_)
372        {
373            std::vector<FormationController*>::iterator it = std::find(this->myMaster_->slaves_.begin(), this->myMaster_->slaves_.end(), this);
374            if (it != this->myMaster_->slaves_.end())
375                this->myMaster_->slaves_.erase(it);
376        }
377
378        this->myMaster_ = 0;
379        this->state_ = FREE;
380    }
381
382    void FormationController::searchNewMaster()
383    {
384
385        if (!this->getControllableEntity())
386            return;
387
388        this->targetPosition_ = this->getControllableEntity()->getPosition();
389        this->forgetTarget();
390        int teamSize = 0;
391        //go through all pawns
392        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
393        {
394           
395            //same team?
396            Gametype* gt=this->getGametype();
397            if (!gt)
398            {
399                gt=it->getGametype();
400            }
401            if (!FormationController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it),gt))
402                continue;
403
404            //has it an FormationController?
405            Controller* controller = 0;
406
407            if (it->getController())
408                controller = it->getController();
409            else if (it->getXMLController())
410                controller = it->getXMLController();
411
412            if (!controller)
413                continue;
414
415            //is pawn oneself?
416            if (orxonox_cast<ControllableEntity*>(*it) == this->getControllableEntity())
417                continue;
418
419            teamSize++;
420
421            FormationController *newMaster = orxonox_cast<FormationController*>(controller);
422
423            //is it a master?
424            if (!newMaster || newMaster->state_ != MASTER)
425                continue;
426
427            float distance = (it->getPosition() - this->getControllableEntity()->getPosition()).length();
428
429            // is pawn in range?
430            if (distance < RADIUS_TO_SEARCH_FOR_MASTERS)
431            {
432                if(newMaster->slaves_.size() > this->maxFormationSize_) continue;
433
434                for(std::vector<FormationController*>::iterator itSlave = this->slaves_.begin(); itSlave != this->slaves_.end(); itSlave++)
435                {
436                    (*itSlave)->myMaster_ = newMaster;
437                    newMaster->slaves_.push_back(*itSlave);
438                }
439                this->slaves_.clear();
440                this->state_ = SLAVE;
441
442                this->myMaster_ = newMaster;
443                newMaster->slaves_.push_back(this);
444
445                break;
446            }
447        }
448
449        if (this->state_ != SLAVE  && teamSize != 0)
450        {
451            this->state_ = MASTER;
452            this->myMaster_ = 0;
453        }
454    }
455 /**
456        @brief Commands the slaves of a master into a formation. Sufficiently fast not to be called within tick. Initiated by a master.
457    */
458
459void FormationController::commandSlaves()
460    {
461        if(this->state_ != MASTER) return;
462
463        Quaternion orient = this->getControllableEntity()->getOrientation();
464        Vector3 dest = this->getControllableEntity()->getPosition();
465
466        // 1 slave: follow
467        if (this->slaves_.size() == 1)
468        {
469            dest += 4*orient*WorldEntity::BACK;
470            this->slaves_.front()->setTargetPosition(dest);
471        }
472        else
473        // formation:
474        {
475            dest += 1.0f*orient*WorldEntity::BACK;
476            Vector3 pos = Vector3::ZERO;
477                 bool left=true;
478            int i = 1;
479           
480            for(std::vector<FormationController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
481            {
482                pos = Vector3::ZERO;
483                if (left)
484                {
485                    pos+=dest+i*FORMATION_WIDTH*(orient*WorldEntity::LEFT);
486                } else{
487                    pos+=dest+i*FORMATION_WIDTH*(orient*WorldEntity::RIGHT);
488                    i++;
489                    dest+=FORMATION_LENGTH*(orient*WorldEntity::BACK);
490                }               
491                (*it)->setTargetOrientation(orient);
492                (*it)->setTargetPosition(pos);
493                left=!left;
494            }
495        }
496    }
497
498    /**
499        @brief Sets a new master within the formation. Called by a master.
500    */
501    void FormationController::setNewMasterWithinFormation()
502    {
503        if(this->state_ != MASTER) return;
504
505        if (!this->slaves_.empty())
506        {
507            FormationController *newMaster = this->slaves_.back();
508            this->slaves_.pop_back();
509
510            newMaster->state_ = MASTER;
511            newMaster->slaves_ = this->slaves_;
512            newMaster->myMaster_ = 0;
513
514            for(std::vector<FormationController*>::iterator it = newMaster->slaves_.begin(); it != newMaster->slaves_.end(); it++)
515            {
516                (*it)->myMaster_ = newMaster;
517            }
518        }
519
520        this->slaves_.clear();
521        this->specificMasterAction_ = NONE;
522        this->state_ = FREE;
523    }
524
525
526  /**
527        @brief Frees all slaves form a master. Initiated by a master.
528    */
529    void FormationController::freeSlaves()
530    {
531        if(this->state_ != MASTER) return;
532
533        for(std::vector<FormationController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
534        {
535            (*it)->state_ = FREE;
536            (*it)->myMaster_ = 0;
537        }
538        this->slaves_.clear();
539    }
540
541    /**
542        @brief Master sets its slaves free for @ref FREEDOM_COUNT seconds.
543    */
544    void FormationController::forceFreeSlaves()
545    {
546        if(this->state_ != MASTER) return;
547
548        for(std::vector<FormationController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
549        {
550            (*it)->state_ = FREE;
551            (*it)->forceFreedom();
552            (*it)->targetPosition_ = this->targetPosition_;
553            (*it)->bShooting_ = true;
554//             (*it)->getControllableEntity()->fire(0);// fire once for fun
555        }
556    }
557
558    void FormationController::loseMasterState()
559    {
560        this->freeSlaves();
561        this->state_ = FREE;
562    }
563
564
565    void FormationController::forceFreedom()
566    {
567        this->freedomCount_ = FREEDOM_COUNT;
568    }
569
570    /**
571        @brief Checks wether caller has been forced free, decrements time to stay forced free.
572        @return true if forced free.
573    */
574    bool FormationController::forcedFree()
575    {
576        if(this->freedomCount_ > 0)
577        {
578            this->freedomCount_--;
579            return true;
580        } else return false;
581    }
582
583
584    /**
585        @brief Call to take the lead of formation (if free, become slave of nearest formation, then, if Slave, become Master)
586    */
587    void FormationController::takeLeadOfFormation()
588    {
589        if (!this->getControllableEntity())
590            return;
591
592        if (this->state_==MASTER) return;
593        //search new Master, then take lead
594        if (this->state_==FREE)
595        {
596          searchNewMaster();
597        }
598
599        if (this->state_==SLAVE)  //become master of this formation
600        {   
601            this->slaves_=this->myMaster_->slaves_;
602            this->myMaster_->slaves_.clear();
603            this->myMaster_->state_=SLAVE;
604            this->myMaster_->myMaster_=this;
605           
606            //delete myself in slavelist
607            std::vector<FormationController*>::iterator it2 = std::find(this->slaves_.begin(), this->slaves_.end(), this);
608            if (it2 != this->slaves_.end())
609            {
610                 this->slaves_.erase(it2);
611            }
612            //add previous master
613            this->slaves_.push_back(this->myMaster_);
614            //set this as new master
615            for(std::vector<FormationController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
616            {
617                 (*it)->myMaster_=this;
618            }
619            this->myMaster_=0;
620            this->state_=MASTER;
621        }
622        /*/debug
623        if (this->state_==SLAVE)
624           {orxout(debug_output) << this << " is slave "<< endl;}
625        else if (this->state_==MASTER)
626           {orxout(debug_output) << this << " is now a master of "<<this->slaves_.size()<<" slaves."<< endl;}
627        if (this->state_==FREE)
628           {orxout(debug_output) << this << " is free "<< endl;}*/
629    }
630    /**
631      @brief if called, half of the formation will attack the originator
632    */
633    void FormationController::masterAttacked(Pawn* originator)
634    {
635       if (this->state_!=MASTER) return;
636       unsigned int i=0;
637       for(std::vector<FormationController*>::reverse_iterator it = slaves_.rbegin(); it != slaves_.rend(); it++)
638       {
639           if ((*it)->state_!=FREE)
640           {
641               (*it)->state_=FREE;
642               (*it)->forceFreedom();
643               (*it)->target_=originator;
644           }
645           i++;
646           if (i>=slaves_.size()/2) break; //half the formation should attack.
647       }
648    }     
649
650
651    /**
652      @brief Sets the new mode. If master, set it for all slaves.
653    */
654    void FormationController::setFormationMode(FormationMode val)
655    {
656        this->formationMode_ = val;
657        if (this->state_ == MASTER)
658        {
659            for(std::vector<FormationController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
660            {
661                 (*it)->formationMode_ = val;
662                 if (val == ATTACK)
663                     (*it)->forgetTarget();
664            }
665        }
666    }
667
668    /**
669        @brief Used to continue a "specific master action" for a certain time and resuming normal behaviour after.
670    */
671    void FormationController::specificMasterActionHold()
672    {
673        if(this->state_ != MASTER) return;
674
675        if (specificMasterActionHoldCount_ == 0)
676         {
677            this->specificMasterAction_ = NONE;
678            this->searchNewTarget();
679         }
680        else specificMasterActionHoldCount_--;
681    }
682
683    /**
684        @brief Master initializes a 180 degree turn. Leads to a "specific master action".
685    */
686    void FormationController::turn180Init()
687    {
688        if(this->state_ != MASTER) return;
689
690        Quaternion orient = this->getControllableEntity()->getOrientation();
691
692        this->setTargetPosition(this->getControllableEntity()->getPosition() + 1000.0f*orient*WorldEntity::BACK);
693
694        this->specificMasterActionHoldCount_ = 4;
695
696        this->specificMasterAction_ = TURN180;
697    }
698
699    /**
700        @brief Execute the 180 degree turn. Called within tick.
701    */
702    void FormationController::turn180()
703    {
704            Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->targetPosition_);
705
706            this->getControllableEntity()->rotateYaw(-2.0f * sgn(coord.x) * coord.x*coord.x);
707            this->getControllableEntity()->rotatePitch(2.0f * sgn(coord.y) * coord.y*coord.y);
708
709            this->getControllableEntity()->moveFrontBack(SPEED_MASTER);
710    }
711
712    /**
713        @brief Master initializes a spin around its looking direction axis. Leads to a "specific master action".
714    */
715    void FormationController::spinInit()
716    {
717        if(this->state_ != MASTER) return;
718        this->specificMasterAction_ = SPIN;
719        this->specificMasterActionHoldCount_ = 10;
720    }
721
722    /**
723        @brief Execute the spin. Called within tick.
724    */
725    void FormationController::spin()
726    {
727            this->moveToTargetPosition();
728            this->getControllableEntity()->rotateRoll(0.8f);
729    }
730
731  /**
732        @brief A human player gets followed by its nearest master. Initiated by console command, so far intended for demonstration puproses (possible future pickup).
733    */
734    void FormationController::followme()
735    {
736
737        Pawn *humanPawn = NULL;
738        NewHumanController *currentHumanController = NULL;
739        std::vector<FormationController*> allMasters;
740
741        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
742        {
743            Controller* controller = 0;
744
745            if (it->getController())
746                controller = it->getController();
747            else if (it->getXMLController())
748                controller = it->getXMLController();
749
750            if (!controller)
751                continue;
752
753            currentHumanController = orxonox_cast<NewHumanController*>(controller);
754
755            if(currentHumanController) humanPawn = *it;
756
757            FormationController *aiController = orxonox_cast<FormationController*>(controller);
758
759            if(aiController && aiController->state_ == MASTER)
760                allMasters.push_back(aiController);
761
762        }
763
764        if((humanPawn != NULL) && (allMasters.size() != 0))
765        {
766                float posHuman = humanPawn->getPosition().length();
767                float distance = 0.0f;
768                float minDistance = FLT_MAX;
769                int index = 0;
770                int i = 0;
771
772                for(std::vector<FormationController*>::iterator it = allMasters.begin(); it != allMasters.end(); it++, i++)
773                    {
774                        if (!FormationController::sameTeam((*it)->getControllableEntity(), humanPawn, (*it)->getGametype())) continue;
775                        distance = posHuman - (*it)->getControllableEntity()->getPosition().length();
776                        if(distance < minDistance) index = i;
777                    }
778                allMasters[index]->followInit(humanPawn);
779            }
780
781    }
782
783
784
785
786
787    /**
788        @brief Master begins to follow a pawn. Is a "specific master action".
789        @param pawn pawn to follow.
790        @param always follows pawn forever if true (false if omitted).
791        @param secondsToFollow seconds to follow the pawn if always is false. Will follow pawn 100 seconds if omitted (set in header).
792    */
793    void FormationController::followInit(Pawn* pawn, const bool always, const int secondsToFollow)
794    {
795        if (pawn == NULL || this->state_ != MASTER)
796            return;
797        this->specificMasterAction_  =  FOLLOW;
798
799        this->setTarget(pawn);
800        if (!always)
801            this->specificMasterActionHoldCount_ = secondsToFollow;
802        else
803            this->specificMasterActionHoldCount_ = INT_MAX; //for now...
804
805    }
806
807   /**
808        @brief Master begins to follow a randomly chosen human player of the same team. Is a "specific master action".
809    */
810    void FormationController::followRandomHumanInit()
811    {
812
813        Pawn *humanPawn = NULL;
814        NewHumanController *currentHumanController = NULL;
815
816        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
817        {
818            if (!it->getController())
819                continue;
820
821            currentHumanController = orxonox_cast<NewHumanController*>(it->getController());
822            if(currentHumanController)
823            {
824                if (!FormationController::sameTeam(this->getControllableEntity(), *it, this->getGametype())) continue;
825                humanPawn = *it;
826                break;
827            }
828        }
829
830        if((humanPawn != NULL))
831                this->followInit(humanPawn);
832    }
833
834
835  /**
836        @brief Master follows target with adjusted speed. Called within tick.
837    */
838    void FormationController::follow()
839    {
840        if (this->target_)
841            this->moveToPosition(this->target_->getPosition());
842        else
843            this->specificMasterActionHoldCount_ = 0;
844    }
845
846
847  void FormationController::setTargetPosition(const Vector3& target)
848    {
849        this->targetPosition_ = target;
850        this->bHasTargetPosition_ = true;
851    }
852
853    void FormationController::searchRandomTargetPosition()
854    {
855        this->targetPosition_ = Vector3(rnd(-2000,2000), rnd(-2000,2000), rnd(-2000,2000));
856        this->bHasTargetPosition_ = true;
857    }
858
859    void FormationController::setTargetOrientation(const Quaternion& orient)
860    {
861        this->targetOrientation_=orient;       
862        this->bHasTargetOrientation_=true;
863    }
864
865    void FormationController::setTargetOrientation(Pawn* target)
866    {
867        if (target)
868            setTargetOrientation(target->getOrientation());
869    }
870
871    void FormationController::setTarget(Pawn* target)
872    {
873        this->target_ = target;
874
875        if (target)
876            this->targetPosition_ = target->getPosition();
877    }
878
879    void FormationController::searchNewTarget()
880    {
881        if (!this->getControllableEntity())
882            return;
883
884        this->targetPosition_ = this->getControllableEntity()->getPosition();
885        this->forgetTarget();
886
887        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
888        {
889            if (FormationController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
890                continue;
891
892            /* So AI won't choose invisible Spaceships as target */
893            if (!it->getRadarVisibility())
894                continue;
895
896            if (static_cast<ControllableEntity*>(*it) != this->getControllableEntity())
897            {
898                float speed = this->getControllableEntity()->getVelocity().length();
899                Vector3 distanceCurrent = this->targetPosition_ - this->getControllableEntity()->getPosition();
900                Vector3 distanceNew = it->getPosition() - this->getControllableEntity()->getPosition();
901                if (!this->target_ || it->getPosition().squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceNew) / speed / distanceNew.length()) / math::twoPi)
902                        < this->targetPosition_.squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / math::twoPi) + rnd(-250, 250))
903                {
904                    this->target_ = (*it);
905                    this->targetPosition_ = it->getPosition();
906                }
907            }
908        }
909    }
910
911  void FormationController::forgetTarget()
912    {
913        this->target_ = 0;
914        this->bShooting_ = false;
915    }
916
917   void FormationController::targetDied()
918    {
919        this->forgetTarget();
920        this->searchRandomTargetPosition();
921    }
922
923  bool FormationController::sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
924    {
925        if (entity1 == entity2)
926            return true;
927
928        int team1 = -1;
929        int team2 = -1;
930
931        Controller* controller = 0;
932        if (entity1->getController())
933            controller = entity1->getController();
934        else
935            controller = entity1->getXMLController();
936        if (controller)
937        {
938            FormationController* ac = orxonox_cast<FormationController*>(controller);
939            if (ac)
940                team1 = ac->getTeam();
941        }
942
943        if (entity2->getController())
944            controller = entity2->getController();
945        else
946            controller = entity2->getXMLController();
947        if (controller)
948        {
949            FormationController* ac = orxonox_cast<FormationController*>(controller);
950            if (ac)
951                team2 = ac->getTeam();
952        }
953
954        TeamDeathmatch* tdm = orxonox_cast<TeamDeathmatch*>(gametype);
955        if (tdm)
956        {
957            if (entity1->getPlayer())
958                team1 = tdm->getTeam(entity1->getPlayer());
959
960            if (entity2->getPlayer())
961                team2 = tdm->getTeam(entity2->getPlayer());
962        }
963
964        /*Mission* miss = orxonox_cast<Mission*>(gametype); //NEW
965        if (miss)
966        {
967            if (entity1->getPlayer())
968                team1 = miss->getTeam(entity1->getPlayer());
969
970            if (entity2->getPlayer())
971                team2 = miss->getTeam(entity2->getPlayer());
972        }*/
973
974        TeamBaseMatchBase* base = 0;
975        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
976        if (base)
977        {
978            switch (base->getState())
979            {
980                case BaseState::ControlTeam1:
981                    team1 = 0;
982                    break;
983                case BaseState::ControlTeam2:
984                    team1 = 1;
985                    break;
986                case BaseState::Uncontrolled:
987                default:
988                    team1 = -1;
989            }
990        }
991        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
992        if (base)
993        {
994            switch (base->getState())
995            {
996                case BaseState::ControlTeam1:
997                    team2 = 0;
998                    break;
999                case BaseState::ControlTeam2:
1000                    team2 = 1;
1001                    break;
1002                case BaseState::Uncontrolled:
1003                default:
1004                    team2 = -1;
1005            }
1006        }
1007
1008        DroneController* droneController = 0;
1009        droneController = orxonox_cast<DroneController*>(entity1->getController());
1010        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2)
1011            return true;
1012        droneController = orxonox_cast<DroneController*>(entity2->getController());
1013        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1)
1014            return true;
1015        DroneController* droneController1 = orxonox_cast<DroneController*>(entity1->getController());
1016        DroneController* droneController2 = orxonox_cast<DroneController*>(entity2->getController());
1017        if (droneController1 && droneController2 && droneController1->getOwner() == droneController2->getOwner())
1018            return true;
1019
1020        Dynamicmatch* dynamic = orxonox_cast<Dynamicmatch*>(gametype);
1021        if (dynamic)
1022        {
1023            if (dynamic->notEnoughPigs||dynamic->notEnoughKillers||dynamic->notEnoughChasers) {return false;}
1024
1025            if (entity1->getPlayer())
1026                team1 = dynamic->getParty(entity1->getPlayer());
1027
1028            if (entity2->getPlayer())
1029                team2 = dynamic->getParty(entity2->getPlayer());
1030
1031            if (team1 ==-1 ||team2 ==-1 ) {return false;}
1032            else if (team1 == dynamic->chaser && team2 != dynamic->chaser) {return false;}
1033            else if (team1 == dynamic->piggy && team2 == dynamic->chaser) {return false;}
1034            else if (team1 == dynamic->killer && team2 == dynamic->chaser) {return false;}
1035            else return true;
1036        }
1037
1038        return (team1 == team2 && team1 != -1);
1039    }
1040
1041}
Note: See TracBrowser for help on using the repository browser.