Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/controllers/ArtificialController.cc @ 8706

Last change on this file since 8706 was 8706, checked in by dafrick, 13 years ago

Merging presentation branch back into trunk.
There are many new features and also a lot of other changes and bugfixes, if you want to know, digg through the svn log.
Not everything is yet working as it should, but it should be fairly stable. If you habe any bug reports, just send me an email.

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