Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Bug is triggered in AIController.cc @ line 243. Can't find the reason at the moment.

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