Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ai/src/orxonox/controllers/ArtificialController.cc @ 7033

Last change on this file since 7033 was 7033, checked in by landauf, 14 years ago

uncommented one line to make it compile again

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