Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Yeay, works. The pickuping efficiency isn't as good as expected though.

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