Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/archive/tutorial4/src/orxonox/controllers/FormationController.cc @ 12373

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

merged core6 back to trunk

  • Property svn:eol-style set to native
File size: 37.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    // Sets newMaster as the new master within the formation. Called by the master.
537    void FormationController::setNewMasterWithinFormation(FormationController* newMaster)
538        {
539            if(this->state_ != MASTER || newMaster->myMaster_ != this) return;
540
541            if (!this->slaves_.empty())
542            {
543                std::vector<FormationController*>::iterator it2 = std::find(this->slaves_.begin(), this->slaves_.end(), newMaster);
544                if (it2 != this->slaves_.end())
545                {
546                    this->slaves_.erase(it2);
547                }
548
549                newMaster->state_ = MASTER;
550                newMaster->slaves_ = this->slaves_;
551                newMaster->myMaster_ = 0;
552
553                for(std::vector<FormationController*>::iterator it = newMaster->slaves_.begin(); it != newMaster->slaves_.end(); it++)
554                {
555                    (*it)->myMaster_ = newMaster;
556                }
557            }
558
559            this->slaves_.clear();
560            this->specificMasterAction_ = NONE;
561            this->state_ = FREE;
562        }
563
564
565
566  /**
567        @brief Frees all slaves from a master. Initiated by a master.
568    */
569    void FormationController::freeSlaves()
570    {
571        if(this->state_ != MASTER) return;
572
573        for(std::vector<FormationController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
574        {
575            (*it)->state_ = FREE;
576            (*it)->myMaster_ = 0;
577        }
578        this->slaves_.clear();
579    }
580
581    /**
582        @brief Master sets its slaves free for @ref FREEDOM_COUNT seconds.
583    */
584    void FormationController::forceFreeSlaves()
585    {
586        if(this->state_ != MASTER) return;
587
588        for(std::vector<FormationController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
589        {
590            (*it)->state_ = FREE;
591            (*it)->forceFreedom();
592            (*it)->targetPosition_ = this->targetPosition_;
593            (*it)->bShooting_ = true;
594//             (*it)->getControllableEntity()->fire(0);// fire once for fun
595        }
596    }
597
598    void FormationController::loseMasterState()
599    {
600        this->freeSlaves();
601        this->state_ = FREE;
602    }
603
604
605    void FormationController::forceFreedom()
606    {
607        this->freedomCount_ = FREEDOM_COUNT;
608    }
609
610    /**
611        @brief Checks wether caller has been forced free, decrements time to stay forced free.
612        @return true if forced free.
613    */
614    bool FormationController::forcedFree()
615    {
616        if(this->freedomCount_ > 0)
617        {
618            this->freedomCount_--;
619            return true;
620        } else return false;
621    }
622
623
624    /**
625        @brief Call to take the lead of formation (if free, become slave of nearest formation, then, if Slave, become Master)
626    */
627    void FormationController::takeLeadOfFormation()
628    {
629        if (!this->getControllableEntity() || this->state_==MASTER)
630            return;
631
632        //search new Master, then take lead
633        if (this->state_==FREE && this->myMaster_==0)
634        {
635          searchNewMaster();
636        }
637
638        if (this->state_==SLAVE)  //become master of this formation
639        {
640            this->slaves_=this->myMaster_->slaves_;
641            this->myMaster_->slaves_.clear();
642            this->myMaster_->state_=SLAVE;
643            this->myMaster_->myMaster_=this;
644
645            //delete myself in slavelist
646            std::vector<FormationController*>::iterator it2 = std::find(this->slaves_.begin(), this->slaves_.end(), this);
647            if (it2 != this->slaves_.end())
648            {
649                 this->slaves_.erase(it2);
650            }
651            //add previous master
652            this->slaves_.push_back(this->myMaster_);
653            //set this as new master
654            for(std::vector<FormationController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
655            {
656                 (*it)->myMaster_=this;
657            }
658            this->myMaster_=0;
659            this->state_=MASTER;
660        }
661        /*/debug
662        if (this->state_==SLAVE)
663           {orxout(debug_output) << this << " is slave "<< endl;}
664        else if (this->state_==MASTER)
665           {orxout(debug_output) << this << " is now a master of "<<this->slaves_.size()<<" slaves."<< endl;}
666        if (this->state_==FREE)
667           {orxout(debug_output) << this << " is free "<< endl;}*/
668    }
669    /**
670      @brief if called, half of the formation will attack the originator
671    */
672    void FormationController::masterAttacked(Pawn* originator)
673    {
674       if (this->state_!=MASTER) return;
675       unsigned int i=0;
676       for(std::vector<FormationController*>::reverse_iterator it = slaves_.rbegin(); it != slaves_.rend(); it++)
677       {
678           if ((*it)->state_!=FREE)
679           {
680               (*it)->state_=FREE;
681               (*it)->forceFreedom();
682               (*it)->target_=originator;
683           }
684           i++;
685           if (i>=slaves_.size()/2) break; //half the formation should attack.
686       }
687    }
688
689
690    /**
691      @brief Sets the new mode. If master, set it for all slaves.
692    */
693    void FormationController::setFormationMode(FormationMode val)
694    {
695        this->formationMode_ = val;
696        if (this->state_ == MASTER)
697        {
698            for(std::vector<FormationController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
699            {
700                 (*it)->formationMode_ = val;
701                 if (val == ATTACK)
702                     (*it)->forgetTarget();
703            }
704        }
705    }
706
707    /**
708        @brief Used to continue a "specific master action" for a certain time and resuming normal behaviour after.
709    */
710    void FormationController::specificMasterActionHold()
711    {
712        if(this->state_ != MASTER) return;
713
714        if (specificMasterActionHoldCount_ == 0)
715        {
716            this->specificMasterAction_ = NONE;
717            this->searchNewTarget();
718        }
719        else
720            specificMasterActionHoldCount_--;
721    }
722
723    /**
724        @brief Master initializes a 180 degree turn. Leads to a "specific master action".
725    */
726    void FormationController::turn180Init()
727    {
728        if(this->state_ != MASTER) return;
729
730        Quaternion orient = this->getControllableEntity()->getOrientation();
731
732        this->setTargetPosition(this->getControllableEntity()->getPosition() + 1000.0f*orient*WorldEntity::BACK);
733
734        this->specificMasterActionHoldCount_ = 4;
735
736        this->specificMasterAction_ = TURN180;
737    }
738
739    /**
740        @brief Execute the 180 degree turn. Called within tick.
741    */
742    void FormationController::turn180()
743    {
744        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->targetPosition_);
745
746        this->getControllableEntity()->rotateYaw(-2.0f * sgn(coord.x) * coord.x*coord.x);
747        this->getControllableEntity()->rotatePitch(2.0f * sgn(coord.y) * coord.y*coord.y);
748
749        this->getControllableEntity()->moveFrontBack(SPEED_MASTER);
750    }
751
752    /**
753        @brief Master initializes a spin around its looking direction axis. Leads to a "specific master action".
754    */
755    void FormationController::spinInit()
756    {
757        if(this->state_ != MASTER) return;
758        this->specificMasterAction_ = SPIN;
759        this->specificMasterActionHoldCount_ = 10;
760    }
761
762    /**
763        @brief Execute the spin. Called within tick.
764    */
765    void FormationController::spin()
766    {
767        this->moveToTargetPosition();
768        this->getControllableEntity()->rotateRoll(0.8f);
769    }
770
771  /**
772        @brief A human player gets followed by its nearest master. Initiated by console command, so far intended for demonstration puproses (possible future pickup).
773    */
774    void FormationController::followme()
775    {
776
777        Pawn *humanPawn = NULL;
778        NewHumanController *currentHumanController = NULL;
779        std::vector<FormationController*> allMasters;
780
781        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
782        {
783            Controller* controller = 0;
784
785            if (it->getController())
786                controller = it->getController();
787            else if (it->getXMLController())
788                controller = it->getXMLController();
789
790            if (!controller)
791                continue;
792
793            currentHumanController = orxonox_cast<NewHumanController*>(controller);
794
795            if(currentHumanController) humanPawn = *it;
796
797            FormationController *aiController = orxonox_cast<FormationController*>(controller);
798
799            if(aiController && aiController->state_ == MASTER)
800                allMasters.push_back(aiController);
801
802        }
803
804        if((humanPawn != NULL) && (allMasters.size() != 0))
805        {
806            float posHuman = humanPawn->getPosition().length();
807            float distance = 0.0f;
808            float minDistance = FLT_MAX;
809            int index = 0;
810            int i = 0;
811
812            for(std::vector<FormationController*>::iterator it = allMasters.begin(); it != allMasters.end(); it++, i++)
813            {
814                if (!FormationController::sameTeam((*it)->getControllableEntity(), humanPawn, (*it)->getGametype())) continue;
815                distance = posHuman - (*it)->getControllableEntity()->getPosition().length();
816                if(distance < minDistance) index = i;
817            }
818            allMasters[index]->followInit(humanPawn);
819        }
820    }
821
822    /**
823        @brief Master begins to follow a pawn. Is a "specific master action".
824        @param pawn pawn to follow.
825        @param always follows pawn forever if true (false if omitted).
826        @param secondsToFollow seconds to follow the pawn if always is false. Will follow pawn 100 seconds if omitted (set in header).
827    */
828    void FormationController::followInit(Pawn* pawn, const bool always, const int secondsToFollow)
829    {
830        if (pawn == NULL || this->state_ != MASTER)
831            return;
832        this->specificMasterAction_  =  FOLLOW;
833
834        this->setTarget(pawn);
835        if (!always)
836            this->specificMasterActionHoldCount_ = secondsToFollow;
837        else
838            this->specificMasterActionHoldCount_ = INT_MAX; //for now...
839
840    }
841
842    /**
843        @brief Master begins to follow a randomly chosen human player of the same team. Is a "specific master action".
844    */
845    void FormationController::followRandomHumanInit()
846    {
847
848        Pawn *humanPawn = NULL;
849        NewHumanController *currentHumanController = NULL;
850
851        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
852        {
853            if (!it->getController())
854                continue;
855
856            currentHumanController = orxonox_cast<NewHumanController*>(it->getController());
857            if(currentHumanController)
858            {
859                if (!FormationController::sameTeam(this->getControllableEntity(), *it, this->getGametype())) continue;
860                humanPawn = *it;
861                break;
862            }
863        }
864
865        if((humanPawn != NULL))
866                this->followInit(humanPawn);
867    }
868
869
870    /**
871        @brief Master follows target with adjusted speed. Called within tick.
872    */
873    void FormationController::follow()
874    {
875        if (this->target_)
876            this->moveToPosition(this->target_->getPosition());
877        else
878            this->specificMasterActionHoldCount_ = 0;
879    }
880
881
882    void FormationController::setTargetPosition(const Vector3& target)
883    {
884        this->targetPosition_ = target;
885        this->bHasTargetPosition_ = true;
886    }
887
888    void FormationController::searchRandomTargetPosition()
889    {
890        this->targetPosition_ = Vector3(rnd(-2000,2000), rnd(-2000,2000), rnd(-2000,2000));
891        this->bHasTargetPosition_ = true;
892    }
893
894    void FormationController::setTargetOrientation(const Quaternion& orient)
895    {
896        this->targetOrientation_=orient;
897        this->bHasTargetOrientation_=true;
898    }
899
900    void FormationController::setTargetOrientation(Pawn* target)
901    {
902        if (target)
903            setTargetOrientation(target->getOrientation());
904    }
905
906    void FormationController::setTarget(Pawn* target)
907    {
908        this->target_ = target;
909
910        if (target)
911            this->targetPosition_ = target->getPosition();
912    }
913
914    void FormationController::searchNewTarget()
915    {
916        if (!this->getControllableEntity())
917            return;
918
919        this->targetPosition_ = this->getControllableEntity()->getPosition();
920        this->forgetTarget();
921
922        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
923        {
924            if (FormationController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
925                continue;
926
927            /* So AI won't choose invisible Spaceships as target */
928            if (!it->getRadarVisibility())
929                continue;
930
931            if (static_cast<ControllableEntity*>(*it) != this->getControllableEntity())
932            {
933                float speed = this->getControllableEntity()->getVelocity().length();
934                Vector3 distanceCurrent = this->targetPosition_ - this->getControllableEntity()->getPosition();
935                Vector3 distanceNew = it->getPosition() - this->getControllableEntity()->getPosition();
936                if (!this->target_ || it->getPosition().squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceNew) / speed / distanceNew.length()) / math::twoPi)
937                        < this->targetPosition_.squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / math::twoPi) + rnd(-250, 250))
938                {
939                    this->target_ = (*it);
940                    this->targetPosition_ = it->getPosition();
941                }
942            }
943        }
944    }
945
946    void FormationController::forgetTarget()
947    {
948        this->target_ = 0;
949        this->bShooting_ = false;
950    }
951
952    void FormationController::targetDied()
953    {
954        this->forgetTarget();
955        this->searchRandomTargetPosition();
956    }
957
958    bool FormationController::sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
959    {
960        if (entity1 == entity2)
961            return true;
962
963        int team1 = -1;
964        int team2 = -1;
965
966        Controller* controller = 0;
967        if (entity1->getController())
968            controller = entity1->getController();
969        else
970            controller = entity1->getXMLController();
971        if (controller)
972        {
973            FormationController* ac = orxonox_cast<FormationController*>(controller);
974            if (ac)
975                team1 = ac->getTeam();
976        }
977
978        if (entity2->getController())
979            controller = entity2->getController();
980        else
981            controller = entity2->getXMLController();
982        if (controller)
983        {
984            FormationController* ac = orxonox_cast<FormationController*>(controller);
985            if (ac)
986                team2 = ac->getTeam();
987        }
988
989        TeamDeathmatch* tdm = orxonox_cast<TeamDeathmatch*>(gametype);
990        if (tdm)
991        {
992            if (entity1->getPlayer())
993                team1 = tdm->getTeam(entity1->getPlayer());
994
995            if (entity2->getPlayer())
996                team2 = tdm->getTeam(entity2->getPlayer());
997        }
998
999        Mission* miss = orxonox_cast<Mission*>(gametype);
1000        if (miss)
1001        {
1002            if (entity1->getPlayer())
1003                team1 = miss->getTeam(entity1->getPlayer());
1004
1005            if (entity2->getPlayer())
1006                team2 = miss->getTeam(entity2->getPlayer());
1007        }
1008
1009        TeamBaseMatchBase* base = 0;
1010        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
1011        if (base)
1012        {
1013            switch (base->getState())
1014            {
1015                case BaseState::ControlTeam1:
1016                    team1 = 0;
1017                    break;
1018                case BaseState::ControlTeam2:
1019                    team1 = 1;
1020                    break;
1021                case BaseState::Uncontrolled:
1022                default:
1023                    team1 = -1;
1024            }
1025        }
1026        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
1027        if (base)
1028        {
1029            switch (base->getState())
1030            {
1031                case BaseState::ControlTeam1:
1032                    team2 = 0;
1033                    break;
1034                case BaseState::ControlTeam2:
1035                    team2 = 1;
1036                    break;
1037                case BaseState::Uncontrolled:
1038                default:
1039                    team2 = -1;
1040            }
1041        }
1042
1043        DroneController* droneController = 0;
1044        droneController = orxonox_cast<DroneController*>(entity1->getController());
1045        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2)
1046            return true;
1047        droneController = orxonox_cast<DroneController*>(entity2->getController());
1048        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1)
1049            return true;
1050        DroneController* droneController1 = orxonox_cast<DroneController*>(entity1->getController());
1051        DroneController* droneController2 = orxonox_cast<DroneController*>(entity2->getController());
1052        if (droneController1 && droneController2 && droneController1->getOwner() == droneController2->getOwner())
1053            return true;
1054
1055        Dynamicmatch* dynamic = orxonox_cast<Dynamicmatch*>(gametype);
1056        if (dynamic)
1057        {
1058            if (dynamic->notEnoughPigs||dynamic->notEnoughKillers||dynamic->notEnoughChasers) {return false;}
1059
1060            if (entity1->getPlayer())
1061                team1 = dynamic->getParty(entity1->getPlayer());
1062
1063            if (entity2->getPlayer())
1064                team2 = dynamic->getParty(entity2->getPlayer());
1065
1066            if (team1 ==-1 ||team2 ==-1 ) {return false;}
1067            else if (team1 == dynamic->chaser && team2 != dynamic->chaser) {return false;}
1068            else if (team1 == dynamic->piggy && team2 == dynamic->chaser) {return false;}
1069            else if (team1 == dynamic->killer && team2 == dynamic->chaser) {return false;}
1070            else return true;
1071        }
1072
1073        return (team1 == team2 && team1 != -1);
1074    }
1075
1076    void FormationController::absoluteMoveToPosition(const Vector3& target)
1077    {
1078        float minDistance = 40.0f;
1079        if (!this->getControllableEntity())
1080            return;
1081
1082        Vector2 coord = get2DViewcoordinates(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, target);
1083        float distance = (target - this->getControllableEntity()->getPosition()).length();
1084
1085            if (this->target_ || distance > minDistance)
1086            {
1087                // Multiply with ROTATEFACTOR_FREE to make them a bit slower
1088                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_FREE * clamp(coord.x * 10, -1.0f, 1.0f));
1089                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_FREE * clamp(coord.y * 10, -1.0f, 1.0f));
1090                this->getControllableEntity()->moveFrontBack(SPEED_FREE);
1091            }
1092
1093
1094        if (distance < minDistance)
1095        {
1096            this->positionReached();
1097        }
1098    }
1099
1100}
Note: See TracBrowser for help on using the repository browser.