Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8711 was 8711, checked in by jo, 14 years ago

Bots are ready for rocket usage. (The hit rate for rockets is just about 60% though.). Note that this is just a proof of concept implementation. The next goal is a more generic implementation that adjusts the AI to any spaceship, not only the assff and similar ones.

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