Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core6/src/orxonox/controllers/FormationController.cc @ 9654

Last change on this file since 9654 was 9654, checked in by landauf, 11 years ago

added RegisterClass() where it was missing

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