Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

First successful attempt, to make bots shoot rockets. Unfortunately they're shooting the wrong ones.

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