Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9839 was 9800, checked in by jo, 11 years ago

Make the AI aware of the inherent team (number) of controllable entities. (Per default it is -1 → the behaviour will only change, if an uncontrolled controllable entities team is set per XML.)

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