Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ai2/src/orxonox/controllers/ArtificialController.cc @ 8733

Last change on this file since 8733 was 8733, checked in by jo, 13 years ago

Further narrowing down. The bug is triggered, when a bot calls fire(3) - whenever a bot launches a rocket.

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