Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/controllers/FormationController.cc @ 9255

Last change on this file since 9255 was 9255, checked in by landauf, 12 years ago

fixed warnings in msvc
removed authorship for code that wasn't written by me

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