Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8351 was 8351, checked in by rgrieder, 13 years ago

Merged kicklib2 branch back to trunk (includes former branches ois_update, mac_osx and kicklib).

Notes for updating

Linux:
You don't need an extra package for CEGUILua and Tolua, it's already shipped with CEGUI.
However you do need to make sure that the OgreRenderer is installed too with CEGUI 0.7 (may be a separate package).
Also, Orxonox now recognises if you install the CgProgramManager (a separate package available on newer Ubuntu on Debian systems).

Windows:
Download the new dependency packages versioned 6.0 and use these. If you have problems with that or if you don't like the in game console problem mentioned below, you can download the new 4.3 version of the packages (only available for Visual Studio 2005/2008).

Key new features:

  • *Support for Mac OS X*
  • Visual Studio 2010 support
  • Bullet library update to 2.77
  • OIS library update to 1.3
  • Support for CEGUI 0.7 —> Support for Arch Linux and even SuSE
  • Improved install target
  • Compiles now with GCC 4.6
  • Ogre Cg Shader plugin activated for Linux if available
  • And of course lots of bug fixes

There are also some regressions:

  • No support for CEGUI 0.5, Ogre 1.4 and boost 1.35 - 1.39 any more
  • In game console is not working in main menu for CEGUI 0.7
  • Tolua (just the C lib, not the application) and CEGUILua libraries are no longer in our repository. —> You will need to get these as well when compiling Orxonox
  • And of course lots of new bugs we don't yet know about
  • Property svn:eol-style set to native
File size: 35.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 "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
385    void ArtificialController::moveToTargetPosition()
386    {
387        this->moveToPosition(this->targetPosition_);
388    }
389
390
391    /**
392        @brief Unregisters a slave from its master. Initiated by a slave.
393    */
394    void ArtificialController::unregisterSlave()
395    {
396        if (this->myMaster_)
397        {
398            std::vector<ArtificialController*>::iterator it = std::find(this->myMaster_->slaves_.begin(), this->myMaster_->slaves_.end(), this);
399            if (it != this->myMaster_->slaves_.end())
400                this->myMaster_->slaves_.erase(it);
401        }
402
403        this->myMaster_ = 0;
404        this->state_ = FREE;
405    }
406
407    void ArtificialController::searchNewMaster()
408    {
409
410        if (!this->getControllableEntity())
411            return;
412
413        this->targetPosition_ = this->getControllableEntity()->getPosition();
414        this->forgetTarget();
415        int teamSize = 0;
416        //go through all pawns
417        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
418        {
419            //same team?
420            if (!ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
421                continue;
422
423            //has it an ArtificialController?
424            Controller* controller = 0;
425
426            if (it->getController())
427                controller = it->getController();
428            else if (it->getXMLController())
429                controller = it->getXMLController();
430
431            if (!controller)
432                continue;
433
434            //is pawn oneself?
435            if (orxonox_cast<ControllableEntity*>(*it) == this->getControllableEntity())
436                continue;
437
438            teamSize++;
439
440            ArtificialController *newMaster = orxonox_cast<ArtificialController*>(controller);
441
442            //is it a master?
443            if (!newMaster || newMaster->state_ != MASTER)
444                continue;
445
446            float distance = (it->getPosition() - this->getControllableEntity()->getPosition()).length();
447
448            // is pawn in range?
449            if (distance < RADIUS_TO_SEARCH_FOR_MASTERS)
450            {
451                if(newMaster->slaves_.size() > this->maxFormationSize_) continue;
452
453                for(std::vector<ArtificialController*>::iterator itSlave = this->slaves_.begin(); itSlave != this->slaves_.end(); itSlave++)
454                {
455                    (*itSlave)->myMaster_ = newMaster;
456                    newMaster->slaves_.push_back(*itSlave);
457                }
458                this->slaves_.clear();
459                this->state_ = SLAVE;
460
461                this->myMaster_ = newMaster;
462                newMaster->slaves_.push_back(this);
463
464                break;
465            }
466        }
467
468        if (this->state_ != SLAVE  && teamSize != 0)
469        {
470            this->state_ = MASTER;
471            this->myMaster_ = 0;
472        }
473    }
474
475    /**
476        @brief Commands the slaves of a master into a formation. Sufficiently fast not to be called within tick. Initiated by a master.
477    */
478    void ArtificialController::commandSlaves()
479    {
480        if(this->state_ != MASTER) return;
481
482        Quaternion orient = this->getControllableEntity()->getOrientation();
483        Vector3 dest = this->getControllableEntity()->getPosition();
484
485        // 1 slave: follow
486        if (this->slaves_.size() == 1)
487        {
488            dest += 4*orient*WorldEntity::BACK;
489            this->slaves_.front()->setTargetPosition(dest);
490        }
491        else
492        {
493            dest += 1.0f*orient*WorldEntity::BACK;
494            Vector3 pos = Vector3::ZERO;
495            int i = 1;
496
497            for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
498            {
499                pos = Vector3::ZERO;
500                if (i <= 1) pos += dest  + (float)FORMATION_WIDTH*(orient*WorldEntity::LEFT);
501                if (i == 2) pos += dest  + (float)FORMATION_WIDTH*(orient*WorldEntity::RIGHT);
502                if (i == 3) pos += dest  + (float)FORMATION_WIDTH*(orient*WorldEntity::UP);
503                if (i >= 4)
504                {
505                    pos += dest  + (float)FORMATION_WIDTH*(orient*WorldEntity::DOWN);
506                    i = 1;
507                    dest += (float)FORMATION_LENGTH*(orient*WorldEntity::BACK);
508                    (*it)->setTargetPosition(pos);
509                    continue;
510                }
511                i++;
512                (*it)->setTargetPosition(pos);
513            }
514        }
515    }
516
517    /**
518        @brief Sets a new master within the formation. Called by a master.
519    */
520    void ArtificialController::setNewMasterWithinFormation()
521    {
522        if(this->state_ != MASTER) return;
523
524        if (!this->slaves_.empty())
525        {
526            ArtificialController *newMaster = this->slaves_.back();
527            this->slaves_.pop_back();
528
529            newMaster->state_ = MASTER;
530            newMaster->slaves_ = this->slaves_;
531            newMaster->myMaster_ = 0;
532
533            for(std::vector<ArtificialController*>::iterator it = newMaster->slaves_.begin(); it != newMaster->slaves_.end(); it++)
534            {
535                (*it)->myMaster_ = newMaster;
536            }
537        }
538
539        this->slaves_.clear();
540        this->specificMasterAction_ = NONE;
541        this->state_ = FREE;
542    }
543
544    /**
545        @brief Frees all slaves form a master. Initiated by a master.
546    */
547    void ArtificialController::freeSlaves()
548    {
549        if(this->state_ != MASTER) return;
550
551        for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
552        {
553            (*it)->state_ = FREE;
554            (*it)->myMaster_ = 0;
555        }
556        this->slaves_.clear();
557    }
558
559    /**
560        @brief Master sets its slaves free for @ref FREEDOM_COUNT seconds.
561    */
562    void ArtificialController::forceFreeSlaves()
563    {
564        if(this->state_ != MASTER) return;
565
566        for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
567        {
568            (*it)->state_ = FREE;
569            (*it)->forceFreedom();
570            (*it)->targetPosition_ = this->targetPosition_;
571            (*it)->bShooting_ = true;
572//             (*it)->getControllableEntity()->fire(0);// fire once for fun
573        }
574    }
575
576    void ArtificialController::loseMasterState()
577    {
578        this->freeSlaves();
579        this->state_ = FREE;
580    }
581
582
583    void ArtificialController::forceFreedom()
584    {
585        this->freedomCount_ = FREEDOM_COUNT;
586    }
587
588    /**
589        @brief Checks wether caller has been forced free, decrements time to stay forced free.
590        @return true if forced free.
591    */
592    bool ArtificialController::forcedFree()
593    {
594        if(this->freedomCount_ > 0)
595        {
596            this->freedomCount_--;
597            return true;
598        } else return false;
599    }
600
601    /**
602        @brief Used to continue a "specific master action" for a certain time and resuming normal behaviour after.
603    */
604    void ArtificialController::specificMasterActionHold()
605    {
606        if(this->state_ != MASTER) return;
607
608        if (specificMasterActionHoldCount_ == 0)
609         {
610            this->specificMasterAction_ = NONE;
611            this->searchNewTarget();
612         }
613        else specificMasterActionHoldCount_--;
614    }
615
616    /**
617        @brief Master initializes a 180 degree turn. Leads to a "specific master action".
618    */
619    void ArtificialController::turn180Init()
620    {
621        if(this->state_ != MASTER) return;
622
623        Quaternion orient = this->getControllableEntity()->getOrientation();
624
625        this->setTargetPosition(this->getControllableEntity()->getPosition() + 1000.0f*orient*WorldEntity::BACK);
626
627        this->specificMasterActionHoldCount_ = 4;
628
629        this->specificMasterAction_ = TURN180;
630    }
631
632    /**
633        @brief Execute the 180 degree turn. Called within tick.
634    */
635    void ArtificialController::turn180()
636    {
637            Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->targetPosition_);
638
639            this->getControllableEntity()->rotateYaw(-2.0f * sgn(coord.x) * coord.x*coord.x);
640            this->getControllableEntity()->rotatePitch(2.0f * sgn(coord.y) * coord.y*coord.y);
641
642            this->getControllableEntity()->moveFrontBack(SPEED_MASTER);
643    }
644
645    /**
646        @brief Master initializes a spin around its looking direction axis. Leads to a "specific master action".
647    */
648    void ArtificialController::spinInit()
649    {
650        if(this->state_ != MASTER) return;
651        this->specificMasterAction_ = SPIN;
652        this->specificMasterActionHoldCount_ = 10;
653    }
654
655    /**
656        @brief Execute the spin. Called within tick.
657    */
658    void ArtificialController::spin()
659    {
660            this->moveToTargetPosition();
661            this->getControllableEntity()->rotateRoll(0.8f);
662    }
663
664    /**
665        @brief Master begins to follow a pawn. Is a "specific master action".
666        @param pawn pawn to follow.
667        @param always follows pawn forever if true (false if omitted).
668        @param secondsToFollow seconds to follow the pawn if always is false. Will follow pawn 100 seconds if omitted (set in header).
669    */
670    void ArtificialController::followInit(Pawn* pawn, const bool always, const int secondsToFollow)
671    {
672        if (pawn == NULL || this->state_ != MASTER)
673            return;
674        this->specificMasterAction_  =  FOLLOW;
675
676        this->setTarget(pawn);
677        if (!always)
678            this->specificMasterActionHoldCount_ = secondsToFollow;
679        else
680            this->specificMasterActionHoldCount_ = INT_MAX; //for now...
681
682    }
683
684
685    /**
686        @brief Master begins to follow a randomly chosen human player of the same team. Is a "specific master action".
687    */
688    void ArtificialController::followRandomHumanInit()
689    {
690
691        Pawn *humanPawn = NULL;
692        NewHumanController *currentHumanController = NULL;
693
694        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
695        {
696            if (!it->getController())
697                continue;
698
699            currentHumanController = orxonox_cast<NewHumanController*>(it->getController());
700            if(currentHumanController)
701            {
702                if (!ArtificialController::sameTeam(this->getControllableEntity(), *it, this->getGametype())) continue;
703                humanPawn = *it;
704                break;
705            }
706        }
707
708        if((humanPawn != NULL))
709                this->followInit(humanPawn);
710    }
711
712    /**
713        @brief Master follows target with adjusted speed. Called within tick.
714    */
715    void ArtificialController::follow()
716    {
717        if (this->target_)
718            this->moveToPosition(this->target_->getPosition());
719        else
720            this->specificMasterActionHoldCount_ = 0;
721/*
722        if (!this->getControllableEntity())
723            return;
724
725        float distance = (this->target_->getPosition() - this->getControllableEntity()->getPosition()).length();
726
727        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->target_->getPosition());
728
729
730        this->getControllableEntity()->rotateYaw(-0.8f * sgn(coord.x) * coord.x*coord.x);
731        this->getControllableEntity()->rotatePitch(0.8f * sgn(coord.y) * coord.y*coord.y);
732
733        float speedDiv = this->getControllableEntity()->getVelocity().squaredLength() - this->target_->getVelocity().squaredLength();
734
735COUT(0) << "~follow distance: " << distance << "SpeedCounter: " << this->speedCounter_ << "~speedDiv: " << speedDiv << std::endl;
736        if (distance < 800)
737        {
738            if (distance < 200)
739            {
740                this->speedCounter_ -= 0.5f;
741                if(this->speedCounter_ < 0) this->speedCounter_ = 0.0f;
742                this->getControllableEntity()->moveFrontBack(speedCounter_);
743            } else {
744                if(speedDiv < 0)
745                    this->speedCounter_ +=  0.01f;
746                else
747                    this->speedCounter_ -= 0.05f;
748                this->getControllableEntity()->moveFrontBack(speedCounter_);
749            }
750
751        } else {
752            this->speedCounter_ += 0.05f;
753            this->getControllableEntity()->moveFrontBack(speedCounter_ + distance/300.0f);
754        }
755//         if (this->getControllableEntity()->getVelocity().squaredLength() > 50.0f) this->speedCounter_ = 0;
756
757*/
758    }
759
760
761    /**
762        @brief Slave moving behaviour when master is following a pawn, gets redirected from moveToPosition(const Vector3& target)). Called within tick.
763    */
764    void ArtificialController::followForSlaves(const Vector3& target)
765    {
766
767/*
768        if (!this->getControllableEntity() && !this->myMaster_ && this->myMaster_->state_ != FOLLOW && !this->myMaster_->target_)
769            return;
770
771        float distance = (target - this->getControllableEntity()->getPosition()).length();
772
773        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, target);
774
775
776        this->getControllableEntity()->rotateYaw(-0.8f * sgn(coord.x) * coord.x*coord.x);
777        this->getControllableEntity()->rotatePitch(0.8f * sgn(coord.y) * coord.y*coord.y);
778
779
780        float speedDiv = this->getControllableEntity()->getVelocity().squaredLength() - this->myMaster_->target_->getVelocity().squaredLength();
781
782
783         if (distance < 800)
784        {
785            if (distance < 200)
786            {
787                this->speedCounter_ -= 5.0f;
788                if(this->speedCounter_ < 0) this->speedCounter_ = 0.0f;
789                this->getControllableEntity()->moveFrontBack(speedCounter_);
790            } else {
791                if(speedDiv < 0)
792                    this->speedCounter_ +=  0.01f;
793                else
794                    this->speedCounter_ -= 0.05f;
795                this->getControllableEntity()->moveFrontBack(speedCounter_);
796            }
797
798        } else {
799            this->speedCounter_ += 0.05f;
800            this->getControllableEntity()->moveFrontBack(speedCounter_ + distance/300.0f);
801        }
802//         if (this->getControllableEntity()->getVelocity().squaredLength() > 50.0f) this->speedCounter_ = 0;
803*/
804    }
805
806
807    void ArtificialController::setTargetPosition(const Vector3& target)
808    {
809        this->targetPosition_ = target;
810        this->bHasTargetPosition_ = true;
811    }
812
813    void ArtificialController::searchRandomTargetPosition()
814    {
815        this->targetPosition_ = Vector3(rnd(-2000,2000), rnd(-2000,2000), rnd(-2000,2000));
816        this->bHasTargetPosition_ = true;
817    }
818
819    void ArtificialController::setTarget(Pawn* target)
820    {
821        this->target_ = target;
822
823        if (target)
824            this->targetPosition_ = target->getPosition();
825    }
826
827    void ArtificialController::searchNewTarget()
828    {
829        if (!this->getControllableEntity())
830            return;
831
832        this->targetPosition_ = this->getControllableEntity()->getPosition();
833        this->forgetTarget();
834
835        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
836        {
837            if (ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
838                continue;
839
840            /* So AI won't choose invisible Spaceships as target */
841            if (!it->getRadarVisibility())
842                continue;
843
844            if (static_cast<ControllableEntity*>(*it) != this->getControllableEntity())
845            {
846                float speed = this->getControllableEntity()->getVelocity().length();
847                Vector3 distanceCurrent = this->targetPosition_ - this->getControllableEntity()->getPosition();
848                Vector3 distanceNew = it->getPosition() - this->getControllableEntity()->getPosition();
849                if (!this->target_ || it->getPosition().squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceNew) / speed / distanceNew.length()) / math::twoPi)
850                        < this->targetPosition_.squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / math::twoPi) + rnd(-250, 250))
851                {
852                    this->target_ = (*it);
853                    this->targetPosition_ = it->getPosition();
854                }
855            }
856        }
857    }
858
859    void ArtificialController::forgetTarget()
860    {
861        this->target_ = 0;
862        this->bShooting_ = false;
863    }
864
865    void ArtificialController::aimAtTarget()
866    {
867        if (!this->target_ || !this->getControllableEntity())
868            return;
869
870        static const float hardcoded_projectile_speed = 1250;
871
872        this->targetPosition_ = getPredictedPosition(this->getControllableEntity()->getPosition(), hardcoded_projectile_speed, this->target_->getPosition(), this->target_->getVelocity());
873        this->bHasTargetPosition_ = (this->targetPosition_ != Vector3::ZERO);
874
875        Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
876        if (pawn)
877            pawn->setAimPosition(this->targetPosition_);
878    }
879
880    bool ArtificialController::isCloseAtTarget(float distance) const
881    {
882        if (!this->getControllableEntity())
883            return false;
884
885        if (!this->target_)
886            return (this->getControllableEntity()->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
887        else
888            return (this->getControllableEntity()->getPosition().squaredDistance(this->target_->getPosition()) < distance*distance);
889    }
890
891    bool ArtificialController::isLookingAtTarget(float angle) const
892    {
893        if (!this->getControllableEntity())
894            return false;
895
896        return (getAngle(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->targetPosition_) < angle);
897    }
898
899    void ArtificialController::abandonTarget(Pawn* target)
900    {
901        if (target == this->target_)
902            this->targetDied();
903    }
904
905    void ArtificialController::targetDied()
906    {
907        this->forgetTarget();
908        this->searchRandomTargetPosition();
909    }
910
911    bool ArtificialController::sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
912    {
913        if (entity1 == entity2)
914            return true;
915
916        int team1 = -1;
917        int team2 = -1;
918
919        Controller* controller = 0;
920        if (entity1->getController())
921            controller = entity1->getController();
922        else
923            controller = entity1->getXMLController();
924        if (controller)
925        {
926            ArtificialController* ac = orxonox_cast<ArtificialController*>(controller);
927            if (ac)
928                team1 = ac->getTeam();
929        }
930
931        if (entity2->getController())
932            controller = entity2->getController();
933        else
934            controller = entity2->getXMLController();
935        if (controller)
936        {
937            ArtificialController* ac = orxonox_cast<ArtificialController*>(controller);
938            if (ac)
939                team2 = ac->getTeam();
940        }
941
942        TeamDeathmatch* tdm = orxonox_cast<TeamDeathmatch*>(gametype);
943        if (tdm)
944        {
945            if (entity1->getPlayer())
946                team1 = tdm->getTeam(entity1->getPlayer());
947
948            if (entity2->getPlayer())
949                team2 = tdm->getTeam(entity2->getPlayer());
950        }
951
952        TeamBaseMatchBase* base = 0;
953        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
954        if (base)
955        {
956            switch (base->getState())
957            {
958                case BaseState::ControlTeam1:
959                    team1 = 0;
960                    break;
961                case BaseState::ControlTeam2:
962                    team1 = 1;
963                    break;
964                case BaseState::Uncontrolled:
965                default:
966                    team1 = -1;
967            }
968        }
969        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
970        if (base)
971        {
972            switch (base->getState())
973            {
974                case BaseState::ControlTeam1:
975                    team2 = 0;
976                    break;
977                case BaseState::ControlTeam2:
978                    team2 = 1;
979                    break;
980                case BaseState::Uncontrolled:
981                default:
982                    team2 = -1;
983            }
984        }
985
986        DroneController* droneController = 0;
987        droneController = orxonox_cast<DroneController*>(entity1->getController());
988        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2)
989            return true;
990        droneController = orxonox_cast<DroneController*>(entity2->getController());
991        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1)
992            return true;
993        DroneController* droneController1 = orxonox_cast<DroneController*>(entity1->getController());
994        DroneController* droneController2 = orxonox_cast<DroneController*>(entity2->getController());
995        if (droneController1 && droneController2 && droneController1->getOwner() == droneController2->getOwner())
996            return true;
997
998        Dynamicmatch* dynamic = orxonox_cast<Dynamicmatch*>(gametype);
999        if (dynamic)
1000        {
1001            if (dynamic->notEnoughPigs||dynamic->notEnoughKillers||dynamic->notEnoughChasers) {return false;}
1002
1003            if (entity1->getPlayer())
1004                team1 = dynamic->getParty(entity1->getPlayer());
1005
1006            if (entity2->getPlayer())
1007                team2 = dynamic->getParty(entity2->getPlayer());
1008
1009            if (team1 ==-1 ||team2 ==-1 ) {return false;}
1010            else if (team1 == dynamic->chaser && team2 != dynamic->chaser) {return false;}
1011            else if (team1 == dynamic->piggy && team2 == dynamic->chaser) {return false;}
1012            else if (team1 == dynamic->killer && team2 == dynamic->chaser) {return false;}
1013            else return true;
1014        }
1015
1016        return (team1 == team2 && team1 != -1);
1017    }
1018}
Note: See TracBrowser for help on using the repository browser.