Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/towerdefenseFS15/src/orxonox/controllers/FormationController.cc @ 10336

Last change on this file since 10336 was 10335, checked in by erbj, 10 years ago

tower don't shoot at the centerpoint anymore(because we shifted it by 2000,hack) and the tower and model are two different things now

  • Property svn:eol-style set to native
File size: 37.2 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->target_.setCallback(createFunctor(&FormationController::targetDied, this));
91    }
92
93    FormationController::~FormationController()
94    {
95        if (this->isInitialized())
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        }
123    }
124
125    void FormationController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
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
136    /**
137        @brief Activates / deactivates formationflight behaviour
138        @param form activate formflight if form is true
139    */
140    void FormationController::formationflight(const bool form)
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
167    /**
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
197    /**
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
224    /**
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
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
259    void FormationController::removeFromFormation()
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
279        Vector2 coord = get2DViewcoordinates(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, target);
280        float distance = (target - this->getControllableEntity()->getPosition()).length();
281        float rotateX = clamp(coord.x * 10, -1.0f, 1.0f);
282        float rotateY = clamp(coord.y * 10, -1.0f, 1.0f);
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
289                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_FREE * rotateX);
290                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_FREE * rotateY);
291            }
292
293            if (this->target_ && distance <  200 && this->getControllableEntity()->getVelocity().squaredLength() > this->target_->getVelocity().squaredLength())
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            {
305                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_MASTER * rotateX);
306                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_MASTER * rotateY);
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
320            this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR_MASTER * rotateX);
321            this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR_MASTER * rotateY);
322
323            if (distance < 300)
324            {
325                if (bHasTargetOrientation_)
326                {
327                    copyTargetOrientation();
328                }
329                if (distance < 100)
330                { //linear speed reduction
331                    this->getControllableEntity()->moveFrontBack(distance/100.0f*0.4f*SPEED_MASTER);
332                }
333                else
334                    this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER);
335            }
336            else
337                this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER + distance/300.0f);
338        }
339
340        if (distance < 10)
341        {
342            this->positionReached();
343            bHasTargetOrientation_=false;
344        }
345    }
346
347
348
349    void FormationController::moveToTargetPosition()
350    {
351        this->moveToPosition(this->targetPosition_);
352    }
353
354    //copy the Roll orientation of given Quaternion.
355    void FormationController::copyOrientation(const Quaternion& orient)
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
373    /**
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    {
391        if (this->state_==SLAVE)
392           return;
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        {
402
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    }
463
464    /**
465        @brief Commands the slaves of a master into a formation. Sufficiently fast not to be called within tick. Initiated by a master.
466    */
467    void FormationController::commandSlaves()
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
481        // formation:
482        {
483            dest += 1.0f*orient*WorldEntity::BACK;
484            Vector3 pos = Vector3::ZERO;
485            bool left=true;
486            int i = 1;
487
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);
498                }
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
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            {
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                }
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
564  /**
565        @brief Frees all slaves from a master. Initiated by a master.
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    {
627        if (!this->getControllableEntity() || this->state_==MASTER)
628            return;
629
630        //search new Master, then take lead
631        if (this->state_==FREE && this->myMaster_==0)
632        {
633          searchNewMaster();
634        }
635
636        if (this->state_==SLAVE)  //become master of this formation
637        {
638            this->slaves_=this->myMaster_->slaves_;
639            this->myMaster_->slaves_.clear();
640            this->myMaster_->state_=SLAVE;
641            this->myMaster_->myMaster_=this;
642
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       }
685    }
686
687
688    /**
689      @brief Sets the new mode. If master, set it for all slaves.
690    */
691    void FormationController::setFormationMode(FormationMode val)
692    {
693        this->formationMode_ = val;
694        if (this->state_ == MASTER)
695        {
696            for(std::vector<FormationController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
697            {
698                 (*it)->formationMode_ = val;
699                 if (val == ATTACK)
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)
713        {
714            this->specificMasterAction_ = NONE;
715            this->searchNewTarget();
716        }
717        else
718            specificMasterActionHoldCount_--;
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    {
742        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->targetPosition_);
743
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);
746
747        this->getControllableEntity()->moveFrontBack(SPEED_MASTER);
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    {
765        this->moveToTargetPosition();
766        this->getControllableEntity()->rotateRoll(0.8f);
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        {
804            float posHuman = humanPawn->getPosition().length();
805            float distance = 0.0f;
806            float minDistance = FLT_MAX;
807            int index = 0;
808            int i = 0;
809
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;
815            }
816            allMasters[index]->followInit(humanPawn);
817        }
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
840    /**
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
868    /**
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
880    void FormationController::setTargetPosition(const Vector3& target)
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    {
894        this->targetOrientation_=orient;
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
944    void FormationController::forgetTarget()
945    {
946        this->target_ = 0;
947        this->bShooting_ = false;
948    }
949
950    void FormationController::targetDied()
951    {
952        this->forgetTarget();
953        this->searchRandomTargetPosition();
954    }
955
956    bool FormationController::sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
957    {
958
959
960        if (entity1 == entity2)
961            return true;
962
963        int team1 = entity1->getTeam();
964        int team2 = entity2->getTeam();
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.