Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation3/src/orxonox/controllers/ArtificialController.cc @ 7035

Last change on this file since 7035 was 7035, checked in by dafrick, 14 years ago

Added include in ArtificialController to make it work under linux. Commented some unused variables in DroneController.

  • Property svn:eol-style set to native
File size: 28.1 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 "ArtificialController.h"
30
31#include <vector>
32#include "limits.h"
33#include "core/CoreIncludes.h"
34#include "core/XMLPort.h"
35#include "worldentities/ControllableEntity.h"
36#include "worldentities/pawns/Pawn.h"
37#include "worldentities/pawns/TeamBaseMatchBase.h"
38#include "gametypes/TeamDeathmatch.h"
39#include "gametypes/Dynamicmatch.h"
40#include "controllers/WaypointPatrolController.h"
41#include "controllers/NewHumanController.h"
42#include "controllers/DroneController.h"
43#include "util/Math.h"
44#include "core/ConsoleCommand.h"
45
46namespace orxonox
47{
48    SetConsoleCommand(ArtificialController, formationflight, true);
49    SetConsoleCommand(ArtificialController, masteraction, true);
50    SetConsoleCommand(ArtificialController, followme, true);
51    SetConsoleCommand(ArtificialController, passivebehaviour, true);
52    SetConsoleCommand(ArtificialController, formationsize, true);
53
54    static const unsigned int STANDARD_MAX_FORMATION_SIZE = 7;
55    static const int FORMATION_LENGTH =  130;
56    static const int FORMATION_WIDTH =  110;
57    static const int FREEDOM_COUNT = 4; //seconds the slaves in a formation will be set free when master attacks an enemy
58    static const float SPEED_MASTER = 0.6f;
59    static const float ROTATEFACTOR_MASTER = 0.2f;
60    static const float SPEED_FREE = 0.8f;
61    static const float ROTATEFACTOR_FREE = 0.8f;
62    static const int SECONDS_TO_FOLLOW_HUMAN = 100;
63
64    ArtificialController::ArtificialController(BaseObject* creator) : Controller(creator)
65    {
66        RegisterObject(ArtificialController);
67
68        this->target_ = 0;
69        this->formationFlight_ = true;
70        this->passive_ = false;
71        this->maxFormationSize_ = STANDARD_MAX_FORMATION_SIZE;
72        this->myMaster_ = 0;
73        this->freedomCount_ = 0;
74        this->team_ = -1;
75        this->state_ = FREE;
76        this->specificMasterAction_ = NONE;
77        this->specificMasterActionHoldCount_  = 0;
78        this->bShooting_ = false;
79        this->bHasTargetPosition_ = false;
80        this->targetPosition_ = Vector3::ZERO;
81        this->humanToFollow_ = NULL;
82
83        this->target_.setCallback(createFunctor(&ArtificialController::targetDied, this));
84    }
85
86    ArtificialController::~ArtificialController()
87    {
88    }
89
90    void ArtificialController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
91    {
92        SUPER(ArtificialController, XMLPort, xmlelement, mode);
93
94        XMLPortParam(ArtificialController, "team", setTeam, getTeam, xmlelement, mode).defaultValues(-1);
95        XMLPortParam(ArtificialController, "formationflight", setFormationFlight, getFormationFlight, xmlelement, mode).defaultValues(true);
96        XMLPortParam(ArtificialController, "formation_size", setFormationSize, getFormationSize, xmlelement, mode).defaultValues(STANDARD_MAX_FORMATION_SIZE);
97    }
98
99// Documentation only here to get a faster overview for creating a useful documentation...
100
101    /**
102        @brief Activates / deactivates formationflight behaviour
103        @param form activate formflight if form is true
104    */
105    void ArtificialController::formationflight(bool form)
106    {
107        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
108        {
109            if (!it->getController())
110                continue;
111
112            ArtificialController *aiController = orxonox_cast<ArtificialController*>(it->getController());
113
114            if(aiController)
115            {
116                aiController->formationFlight_ = form;
117                if(!form)
118                {
119                    if(aiController->state_ == MASTER) aiController->freeSlaves();
120                    aiController->state_ = FREE;
121                }
122            }
123        }
124    }
125
126    /**
127        @brief Get all masters to do a "specific master action"
128        @param action which action to perform (integer, so it can be called with a console command (tmp solution))
129    */
130    void ArtificialController::masteraction(int action)
131    {
132        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
133        {
134            if (!it->getController())
135                continue;
136
137            ArtificialController *aiController = orxonox_cast<ArtificialController*>(it->getController());
138
139            if(aiController && aiController->state_ == MASTER)
140            {
141                if (action == 1)
142                    aiController->spinInit();
143                if (action == 2)
144                    aiController->turn180Init();
145            }
146        }
147    }
148
149    /**
150        @brief A human player gets followed by its nearest master. Initiated by console command, intended for demonstration puproses. Does not work at the moment.
151    */
152    void ArtificialController::followme()
153    {
154
155        Pawn *humanPawn = NULL;
156        NewHumanController *currentHumanController = NULL;
157        std::vector<ArtificialController*> allMasters;
158
159        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
160        {
161            if (!it->getController())
162                continue;
163
164            currentHumanController = orxonox_cast<NewHumanController*>(it->getController());
165
166            if(currentHumanController) humanPawn = *it;
167
168            ArtificialController *aiController = orxonox_cast<ArtificialController*>(it->getController());
169
170            if(aiController || aiController->state_ == MASTER)
171                allMasters.push_back(aiController);
172
173        }
174
175        if((humanPawn != NULL) && (allMasters.size() != 0))
176        {
177                float posHuman = humanPawn->getPosition().length();
178                float distance = 0.0f;
179                float minDistance = FLT_MAX;
180                int index = 0;
181                int i = 0;
182
183                for(std::vector<ArtificialController*>::iterator it = allMasters.begin(); it != allMasters.end(); it++)
184                    {
185                        distance = posHuman - (*it)->getControllableEntity()->getPosition().length();
186                        if(distance < minDistance) index = i;
187                    }
188                allMasters[index]->humanToFollow_ = humanPawn;
189//                allMasters[index]->followHuman(humanPawn, false);
190            }
191
192    }
193
194    /**
195        @brief Sets shooting behaviour of pawns.
196        @param passive if true, bots won't shoot.
197    */
198    void ArtificialController::passivebehaviour(bool passive)
199    {
200        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
201        {
202            if (!it->getController())
203                continue;
204
205            ArtificialController *aiController = orxonox_cast<ArtificialController*>(it->getController());
206
207            if(aiController)
208            {
209                aiController->passive_ = passive;
210            }
211        }
212    }
213
214
215    /**
216        @brief Sets maximal formation size
217        @param size maximal formation size.
218    */
219    void ArtificialController::formationsize(int size)
220    {
221        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
222        {
223            if (!it->getController())
224                continue;
225
226            ArtificialController *aiController = orxonox_cast<ArtificialController*>(it->getController());
227
228            if(aiController)
229            {
230                aiController->maxFormationSize_ = size;
231            }
232        }
233    }
234
235    /**
236        @brief Gets called when ControllableEntity is being changed. Resets the bot when it dies.
237    */
238    void ArtificialController::changedControllableEntity()
239    {
240        if(!getControllableEntity()) 
241        {
242        if (this->state_ == SLAVE) unregisterSlave();
243         if (this->state_ == MASTER) setNewMasterWithinFormation();
244        this->slaves_.clear();
245        this->state_ = FREE;
246
247        }
248    }
249
250
251    void ArtificialController::moveToPosition(const Vector3& target)
252    {
253        if (!this->getControllableEntity())
254            return;
255
256        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, target);
257        float distance = (target - this->getControllableEntity()->getPosition()).length();
258
259
260        if(this->state_ == FREE)
261        {
262            if (this->target_ || distance > 10)
263            {
264                // Multiply with 0.8 to make them a bit slower
265                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_FREE * sgn(coord.x) * coord.x*coord.x);
266                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_FREE * sgn(coord.y) * coord.y*coord.y);
267            }
268
269            if (this->target_ && distance < 200 && this->getControllableEntity()->getVelocity().squaredLength() > this->target_->getVelocity().squaredLength())
270            {
271              this->getControllableEntity()->moveFrontBack(-0.05f); // They don't brake with full power to give the player a chance
272            } else this->getControllableEntity()->moveFrontBack(SPEED_FREE);
273        }
274
275
276
277        if(this->state_ == MASTER)
278        {
279            if (this->target_ || distance > 10)
280            {
281                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_MASTER * sgn(coord.x) * coord.x*coord.x);
282                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_MASTER * 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);
288            } else this->getControllableEntity()->moveFrontBack(SPEED_MASTER);
289        }
290
291
292
293        if(this->state_ == SLAVE)
294        {
295
296           this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR_MASTER * sgn(coord.x) * coord.x*coord.x);
297           this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR_MASTER * sgn(coord.y) * coord.y*coord.y);
298
299            if (distance < 300)
300            {
301                if (distance < 40)
302                {
303                    this->getControllableEntity()->moveFrontBack(0.8f*SPEED_MASTER);
304                } else this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER);
305
306            } else {
307                this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER + distance/300.0f);
308            }
309        }
310    }
311
312    void ArtificialController::moveToTargetPosition()
313    {
314        this->moveToPosition(this->targetPosition_);
315    }
316
317    int ArtificialController::getState()
318    {
319        return this->state_;
320    }
321
322    /**
323        @brief Unregisters a slave from its master. Called by a slave.
324    */
325    void ArtificialController::unregisterSlave() {
326        if(myMaster_)
327        {
328            std::vector<ArtificialController*>::iterator it = std::find(myMaster_->slaves_.begin(), myMaster_->slaves_.end(), this);
329            if( it != myMaster_->slaves_.end() )
330                myMaster_->slaves_.erase(it);
331        }
332    }
333
334    void ArtificialController::searchNewMaster()
335    {
336
337        if (!this->getControllableEntity())
338            return;
339
340        this->targetPosition_ = this->getControllableEntity()->getPosition();
341        this->forgetTarget();
342        int teamSize = 0;
343        //go through all pawns
344        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
345        {
346
347            //same team?
348            if (!ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
349                continue;
350
351            //has it an ArtificialController?
352            if (!it->getController())
353                continue;
354
355            //is pawn oneself?
356            if (orxonox_cast<ControllableEntity*>(*it) == this->getControllableEntity())
357                continue;
358
359            teamSize++;
360
361            ArtificialController *newMaster = orxonox_cast<ArtificialController*>(it->getController());
362
363            //is it a master?
364            if (!newMaster || newMaster->getState() != MASTER)
365                continue;
366
367            float distance = (it->getPosition() - this->getControllableEntity()->getPosition()).length();
368
369            // is pawn in range?
370            if (distance < 5000)
371            {
372                if(newMaster->slaves_.size() > this->maxFormationSize_) continue;
373
374                for(std::vector<ArtificialController*>::iterator itSlave = this->slaves_.begin(); itSlave != this->slaves_.end(); itSlave++)
375                {
376                    (*itSlave)->myMaster_ = newMaster;
377                    newMaster->slaves_.push_back(*itSlave);
378                }
379                this->slaves_.clear();
380                this->state_ = SLAVE;
381
382                this->myMaster_ = newMaster;
383                newMaster->slaves_.push_back(this);
384
385                break;
386            }
387        }
388
389        if (state_ != SLAVE  && teamSize != 0) state_ = MASTER;
390
391    }
392
393    /**
394        @brief Commands the slaves of a master into a formation. Called by a master.
395    */
396    void ArtificialController::commandSlaves() 
397    {
398        if(this->state_ != MASTER) return;
399
400        Quaternion orient = this->getControllableEntity()->getOrientation();
401        Vector3 dest = this->getControllableEntity()->getPosition();
402
403        // 1 slave: follow
404        if (this->slaves_.size() == 1)
405        {
406            dest += 4*orient*WorldEntity::BACK;
407            this->slaves_.front()->setTargetPosition(dest);
408        }
409        else 
410        {
411            dest += 1.0f*orient*WorldEntity::BACK;
412            Vector3 pos = Vector3::ZERO;
413            int i = 1;
414
415            for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
416            {
417                pos = Vector3::ZERO;
418                if (i <= 1) pos += dest  + FORMATION_WIDTH*(orient*WorldEntity::LEFT);
419                if (i == 2) pos += dest  + FORMATION_WIDTH*(orient*WorldEntity::RIGHT);
420                if (i == 3) pos += dest  + FORMATION_WIDTH*(orient*WorldEntity::UP);
421                if (i >= 4)
422                {
423                    pos += dest  + FORMATION_WIDTH*(orient*WorldEntity::DOWN);
424                    i = 1;
425                    dest += FORMATION_LENGTH*(orient*WorldEntity::BACK);
426                    (*it)->setTargetPosition(pos);
427                    continue;
428                }
429                i++;
430                (*it)->setTargetPosition(pos);
431            }
432        }
433    }
434
435    /**
436        @brief Sets a new master within the formation. Called by a master.
437    */
438    void ArtificialController::setNewMasterWithinFormation()
439    {
440        if(this->state_ != MASTER) return;
441
442        if (this->slaves_.empty())
443            return;
444
445        ArtificialController *newMaster = this->slaves_.back();
446        this->slaves_.pop_back();
447
448        if(!newMaster) return;
449        newMaster->state_ = MASTER;
450        newMaster->slaves_ = this->slaves_;
451
452        this->slaves_.clear();
453        this->state_ = SLAVE;
454        this->myMaster_ = newMaster;
455
456        for(std::vector<ArtificialController*>::iterator it = newMaster->slaves_.begin(); it != newMaster->slaves_.end(); it++)
457        {
458            (*it)->myMaster_ = newMaster;
459        }
460
461    }
462
463    /**
464        @brief Frees all slaves form a master. Called by a master.
465    */
466    void ArtificialController::freeSlaves()
467    {
468        if(this->state_ != MASTER) return;
469
470        for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
471        {
472            (*it)->state_ = FREE;
473        }
474        this->slaves_.clear();
475    }
476
477    /**
478        @brief Master sets its slaves free for @var FREEDOM_COUNT seconds.
479    */
480    void ArtificialController::forceFreeSlaves()
481    {
482        if(this->state_ != MASTER) return;
483
484        for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
485        {
486            (*it)->state_ = FREE;
487            (*it)->forceFreedom();
488            (*it)->targetPosition_ = this->targetPosition_;
489            (*it)->bShooting_ = true;
490//             (*it)->getControllableEntity()->fire(0);// fire once for fun
491        }
492    }
493
494    void ArtificialController::loseMasterState()
495    {
496        this->freeSlaves();
497        this->state_ = FREE;
498    }
499
500
501    void ArtificialController::forceFreedom()
502    {
503        this->freedomCount_ = FREEDOM_COUNT;
504    }
505
506    /**
507        @brief Checks wether caller has been forced free, decrements time to stay forced free.
508        @return true if forced free.
509    */
510    bool ArtificialController::forcedFree()
511    {
512        if(this->freedomCount_ > 0) 
513        {
514            this->freedomCount_--;
515            return true;
516        } else return false;
517    }
518
519    /**
520        @brief Used to continue a "specific master action" for a certain time and resuming normal behaviour after.
521    */
522    void ArtificialController::specificMasterActionHold()
523    {
524        if(this->state_ != MASTER) return;
525
526        if (specificMasterActionHoldCount_ == 0) 
527         {
528            this->specificMasterAction_ = NONE;
529            this->searchNewTarget();
530         }
531        else specificMasterActionHoldCount_--;
532    }
533
534    /**
535        @brief Master initializes a 180 degree turn. Leads to a "specific master action".
536    */
537    void ArtificialController::turn180Init()
538    {
539        COUT(0) << "~turnInit" << std::endl;
540        if(this->state_ != MASTER) return;
541
542        Quaternion orient = this->getControllableEntity()->getOrientation();
543
544        this->setTargetPosition(this->getControllableEntity()->getPosition() + 1000.0f*orient*WorldEntity::BACK);
545
546        this->specificMasterActionHoldCount_ = 4;
547
548        this->specificMasterAction_ = TURN180;
549    }
550
551    /**
552        @brief Execute the 180 degree turn. Called within tick.
553    */
554    void ArtificialController::turn180()
555    {
556            Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->targetPosition_);
557
558            this->getControllableEntity()->rotateYaw(-2.0f * sgn(coord.x) * coord.x*coord.x);
559            this->getControllableEntity()->rotatePitch(2.0f * sgn(coord.y) * coord.y*coord.y);
560
561            this->getControllableEntity()->moveFrontBack(SPEED_MASTER);
562    }
563
564    /**
565        @brief Master initializes a spin around its looking direction axis. Leads to a "specific master action". Not yet implemented.
566    */
567    void ArtificialController::spinInit()
568    {
569        COUT(0) << "~spinInit" << std::endl;
570        if(this->state_ != MASTER) return;
571        this->specificMasterAction_ = SPIN;
572        this->specificMasterActionHoldCount_ = 10;
573    }
574
575    /**
576        @brief Execute the spin. Called within tick.
577    */
578    void ArtificialController::spin()
579    {
580            this->moveToTargetPosition();
581            this->getControllableEntity()->rotateRoll(0.8f);
582    }
583
584    /**
585        @brief Master begins to follow a human player. Is a "specific master action".
586        @param humanController human to follow.
587        @param alaways follows human forever if true, else it follows it for @var SECONDS_TO_FOLLOW_HUMAN seconds.
588    */
589    void ArtificialController::followHumanInit(Pawn* human, bool always)
590    {
591        COUT(0) << "~followInit" << std::endl;
592        if (human == NULL || this->state_ != MASTER)
593            return;
594
595        this->specificMasterAction_  =  FOLLOWHUMAN;
596
597        this->setTarget(human);
598        if (!always)
599            this->specificMasterActionHoldCount_ = SECONDS_TO_FOLLOW_HUMAN;
600        else 
601            this->specificMasterActionHoldCount_ = INT_MAX; //for now...
602
603    }
604
605    /**
606        @brief Follows target with adjusted speed. Called within tick.
607    */
608    void ArtificialController::follow()
609    {
610        this->moveToTargetPosition(); //standard position apprach for now.
611    }
612
613
614
615    void ArtificialController::setTargetPosition(const Vector3& target)
616    {
617        this->targetPosition_ = target;
618        this->bHasTargetPosition_ = true;
619    }
620
621    void ArtificialController::searchRandomTargetPosition()
622    {
623        this->targetPosition_ = Vector3(rnd(-2000,2000), rnd(-2000,2000), rnd(-2000,2000));
624        this->bHasTargetPosition_ = true;
625    }
626
627    void ArtificialController::setTarget(Pawn* target)
628    {
629        this->target_ = target;
630
631        if (target)
632            this->targetPosition_ = target->getPosition();
633    }
634
635    void ArtificialController::searchNewTarget()
636    {
637        if (!this->getControllableEntity())
638            return;
639
640        this->targetPosition_ = this->getControllableEntity()->getPosition();
641        this->forgetTarget();
642
643        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
644        {
645            if (ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
646                continue;
647
648            if (static_cast<ControllableEntity*>(*it) != this->getControllableEntity())
649            {
650                float speed = this->getControllableEntity()->getVelocity().length();
651                Vector3 distanceCurrent = this->targetPosition_ - this->getControllableEntity()->getPosition();
652                Vector3 distanceNew = it->getPosition() - this->getControllableEntity()->getPosition();
653                if (!this->target_ || it->getPosition().squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceNew) / speed / distanceNew.length()) / (2 * Ogre::Math::PI))
654                        < this->targetPosition_.squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / (2 * Ogre::Math::PI)) + rnd(-250, 250))
655                {
656                    this->target_ = (*it);
657                    this->targetPosition_ = it->getPosition();
658                }
659            }
660        }
661    }
662
663    void ArtificialController::forgetTarget()
664    {
665        this->target_ = 0;
666        this->bShooting_ = false;
667    }
668
669    void ArtificialController::aimAtTarget()
670    {
671        if (!this->target_ || !this->getControllableEntity())
672            return;
673
674        static const float hardcoded_projectile_speed = 1250;
675
676        this->targetPosition_ = getPredictedPosition(this->getControllableEntity()->getPosition(), hardcoded_projectile_speed, this->target_->getPosition(), this->target_->getVelocity());
677        this->bHasTargetPosition_ = (this->targetPosition_ != Vector3::ZERO);
678
679        Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
680        if (pawn)
681            pawn->setAimPosition(this->targetPosition_);
682    }
683
684    bool ArtificialController::isCloseAtTarget(float distance) const
685    {
686        if (!this->getControllableEntity())
687            return false;
688
689        if (!this->target_)
690            return (this->getControllableEntity()->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
691        else
692            return (this->getControllableEntity()->getPosition().squaredDistance(this->target_->getPosition()) < distance*distance);
693    }
694
695    bool ArtificialController::isLookingAtTarget(float angle) const
696    {
697        if (!this->getControllableEntity())
698            return false;
699
700        return (getAngle(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->targetPosition_) < angle);
701    }
702
703    void ArtificialController::abandonTarget(Pawn* target)
704    {
705        if (target == this->target_)
706            this->targetDied();
707    }
708
709    void ArtificialController::targetDied()
710    {
711        this->forgetTarget();
712        this->searchRandomTargetPosition();
713    }
714
715    bool ArtificialController::sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
716    {
717        if (entity1 == entity2)
718            return true;
719
720        int team1 = -1;
721        int team2 = -1;
722
723        Controller* controller = 0;
724        if (entity1->getController())
725            controller = entity1->getController();
726        else
727            controller = entity1->getXMLController();
728        if (controller)
729        {
730            ArtificialController* ac = orxonox_cast<ArtificialController*>(controller);
731            if (ac)
732                team1 = ac->getTeam();
733        }
734
735        if (entity1->getController())
736            controller = entity1->getController();
737        else
738            controller = entity1->getXMLController();
739        if (controller)
740        {
741            ArtificialController* ac = orxonox_cast<ArtificialController*>(controller);
742            if (ac)
743                team2 = ac->getTeam();
744        }
745
746        TeamDeathmatch* tdm = orxonox_cast<TeamDeathmatch*>(gametype);
747        if (tdm)
748        {
749            if (entity1->getPlayer())
750                team1 = tdm->getTeam(entity1->getPlayer());
751
752            if (entity2->getPlayer())
753                team2 = tdm->getTeam(entity2->getPlayer());
754        }
755
756        TeamBaseMatchBase* base = 0;
757        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
758        if (base)
759        {
760            switch (base->getState())
761            {
762                case BaseState::ControlTeam1:
763                    team1 = 0;
764                    break;
765                case BaseState::ControlTeam2:
766                    team1 = 1;
767                    break;
768                case BaseState::Uncontrolled:
769                default:
770                    team1 = -1;
771            }
772        }
773        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
774        if (base)
775        {
776            switch (base->getState())
777            {
778                case BaseState::ControlTeam1:
779                    team2 = 0;
780                    break;
781                case BaseState::ControlTeam2:
782                    team2 = 1;
783                    break;
784                case BaseState::Uncontrolled:
785                default:
786                    team2 = -1;
787            }
788        }
789
790        DroneController* droneController = 0;
791        droneController = orxonox_cast<DroneController*>(entity1->getController());
792        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2)
793            return true;
794        droneController = orxonox_cast<DroneController*>(entity2->getController());
795        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1)
796            return true;
797        DroneController* droneController1 = orxonox_cast<DroneController*>(entity1->getController());
798        DroneController* droneController2 = orxonox_cast<DroneController*>(entity2->getController());
799        if (droneController1 && droneController2 && droneController1->getOwner() == droneController2->getOwner())
800            return true;
801
802        Dynamicmatch* dynamic = orxonox_cast<Dynamicmatch*>(gametype);
803        if (dynamic)
804        {
805            if (dynamic->notEnoughPigs||dynamic->notEnoughKillers||dynamic->notEnoughChasers) {return false;}
806
807            if (entity1->getPlayer())
808                team1 = dynamic->getParty(entity1->getPlayer());
809
810            if (entity2->getPlayer())
811                team2 = dynamic->getParty(entity2->getPlayer());
812
813            if (team1 ==-1 ||team2 ==-1 ) {return false;}
814            else if (team1 == dynamic->chaser && team2 != dynamic->chaser) {return false;}
815            else if (team1 == dynamic->piggy && team2 == dynamic->chaser) {return false;}
816            else if (team1 == dynamic->killer && team2 == dynamic->chaser) {return false;}
817            else return true;
818        }
819
820        return (team1 == team2 && team1 != -1);
821    }
822}
Note: See TracBrowser for help on using the repository browser.