Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/formation/src/orxonox/controllers/Masterable.cc @ 8965

Last change on this file since 8965 was 8965, checked in by willis, 13 years ago

added some Mode features, fixed a speed issue

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