Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/campaignHS15/src/orxonox/controllers/ActionpointController.cc @ 10871

Last change on this file since 10871 was 10871, checked in by gania, 8 years ago

Split up CommonController, so it is easier to debug

File size: 23.7 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 "ActionpointController.h"
30
31#include "core/XMLPort.h"
32
33#include "controllers/NewHumanController.h"
34
35namespace orxonox
36{
37
38    RegisterClass(ActionpointController);
39
40    //CommonController contains all common functionality of AI Controllers
41    ActionpointController::ActionpointController(Context* context) : FightingController(context)
42    {
43              this->bInLoop_ = false;
44        this->bLoop_ = false;
45        this->bEndLoop_ = false;
46        this->parsedActionpoints_.clear();
47        this->bTakenOver_ = false;
48        this->action_ = Action::NONE;
49        this->squaredaccuracy_ = 2500;
50
51
52        RegisterObject(ActionpointController);
53
54    }
55    void ActionpointController::XMLPort( Element& xmlelement, XMLPort::Mode mode )
56    {
57        SUPER( ActionpointController, XMLPort, xmlelement, mode );
58        XMLPortObject(ActionpointController, WorldEntity, "actionpoints", addActionpoint, getActionpoint,  xmlelement, mode);
59    }
60        void ActionpointController::tick(float dt)
61        {
62                if (this->bHasTargetPosition_)
63        {
64            this->moveToTargetPosition(dt);
65        }
66        else if (this->bLookAtTarget_)
67        {
68            this->lookAtTarget(dt);
69        }
70        if (bShooting_)
71        {
72            this->doFire();
73        }
74        if (this->bFirstTick_)
75        {
76            std::reverse(parsedActionpoints_.begin(), parsedActionpoints_.end());
77            std::reverse(actionpoints_.begin(), actionpoints_.end());
78            if (this->parsedActionpoints_.empty())
79            {
80                this->action_ = Action::FIGHTALL;
81            }
82        }
83        if (this->bFirstTick_)
84            this->bFirstTick_ = false;
85                SUPER(ActionpointController, tick, dt);
86        }
87    ActionpointController::~ActionpointController()
88    {
89        loopActionpoints_.clear();
90        parsedActionpoints_.clear();
91        actionpoints_.clear();
92    }
93    void ActionpointController::setProtect (ControllableEntity* protect)
94    {
95        this->protect_ = protect;
96    }
97    ControllableEntity* ActionpointController::getProtect ()
98    {
99        return this->protect_;
100    }
101    void ActionpointController::addActionpoint(WorldEntity* actionpoint)
102    {
103        std::string actionName;
104        Vector3 position;
105        std::string targetName;
106        bool inLoop = false;
107        Point p;
108        if (static_cast<Actionpoint*> (actionpoint))
109        {
110            Actionpoint* ap = static_cast<Actionpoint*> (actionpoint);
111            actionName = ap->getActionXML();
112            targetName = ap->getName();
113            position = ap->getWorldPosition();
114
115            if (this->bEndLoop_)
116            {
117                this->bInLoop_ = false;
118            }
119            if (!this->bInLoop_ && ap->getLoopStart())
120            {
121                this->bInLoop_ = true;
122            }
123            if (this->bInLoop_ && ap->getLoopEnd())
124            {
125                this->bEndLoop_ = true;
126            }
127            inLoop = this->bInLoop_;
128
129            Action::Value value;
130           
131            if ( actionName == "FIGHT" )
132            { value = Action::FIGHT; }
133            else if ( actionName == "FLY" )
134            { value = Action::FLY; }
135            else if ( actionName == "PROTECT" )
136            { value = Action::PROTECT; }
137            else if ( actionName == "NONE" )
138            { value = Action::NONE; }
139            else if ( actionName == "FIGHTALL" )
140            { value = Action::FIGHTALL; }
141            else if ( actionName == "ATTACK" )
142            { value = Action::ATTACK; }
143            else
144                ThrowException( ParseError, std::string( "Attempting to set an unknown Action: '" )+ actionName + "'." );
145            p.action = value; p.name = targetName; p.position = position; p.inLoop = inLoop;
146        }
147        else
148        {
149            p.action = Action::FLY; p.name = ""; p.position = actionpoint->getWorldPosition(); p.inLoop = inLoop;
150        }
151            parsedActionpoints_.push_back(p);
152            this->actionpoints_.push_back(actionpoint);
153    }
154    WorldEntity* ActionpointController::getActionpoint(unsigned int index) const
155    {
156        if (index < this->actionpoints_.size())
157            return this->actionpoints_[index];
158        else
159            return 0;
160    }
161
162      Action::Value ActionpointController::getAction ()
163    {
164        return this->action_;
165    }
166    std::string ActionpointController::getActionName()
167    {
168        switch ( this->action_ )
169        {
170            case Action::FIGHT:
171            { return "FIGHT"; break; }
172            case Action::FLY:
173            { return "FLY"; break; }
174            case Action::PROTECT:
175            { return "PROTECT"; break; }
176            case Action::NONE:
177            { return "NONE"; break; }
178            case Action::FIGHTALL:
179            { return "FIGHTALL"; break; }
180            case Action::ATTACK:
181            { return "ATTACK"; break; }
182            default:
183                return "NONE";
184                break;
185        }
186    }
187    void ActionpointController::setAction (Action::Value action)
188    {
189        this->action_ = action;
190    }
191    void ActionpointController::setAction (Action::Value action, ControllableEntity* target)
192    {
193        this->action_ = action;
194        if (action == Action::FIGHT || action == Action::FIGHTALL || action == Action::ATTACK)
195        {   
196            if (target)
197                this->setTarget (target);
198        }
199        else if (action == Action::PROTECT)
200        {
201            if (target)
202                this->setProtect (target);
203        }
204    }
205    void ActionpointController::setAction (Action::Value action, const Vector3& target)
206    {
207        this->action_ = action;
208        if (action == Action::FLY)
209        {
210            this->setTargetPosition (target);
211        }
212    }
213    void ActionpointController::setAction (Action::Value action, const Vector3& target,  const Quaternion& orient )
214    {
215        this->action_ = action;
216        if (action == Action::FLY)
217        {
218            this->setTargetPosition (target);
219            this->setTargetOrientation (orient);
220        } 
221    }
222   
223    //------------------------------------------------------------------------------
224    //------------------------------Actionpoint methods-----------------------------
225    //------------------------------------------------------------------------------
226
227    //POST: this starts doing what was asked by the last element of parsedActionpoints_,
228    //if last element was failed to be parsed, next element will be executed.
229    void ActionpointController::executeActionpoint()
230    {
231        if (this->bLoop_)
232        {
233            if (!this->loopActionpoints_.empty())
234            {
235                this->action_ = this->loopActionpoints_.back().action;
236                switch ( this->action_ )
237                {
238                    case Action::FIGHT:
239                    {
240                        std::string targetName = this->loopActionpoints_.back().name;
241                        if (targetName == "")
242                        {
243                            break;
244                        }
245                        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
246                        {
247                            if (CommonController::getName(*itP) == targetName)
248                            {
249                                this->setTarget (static_cast<ControllableEntity*>(*itP));
250                            }
251                        }         
252                        break;
253                    }
254                    case Action::FLY:
255                    {
256                        this->setTargetPosition( this->loopActionpoints_.back().position );
257                        if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
258                        {
259                            this->nextActionpoint();
260                            this->executeActionpoint();
261                        }
262                        break;
263                    }
264                    case Action::PROTECT:
265                    {
266                        std::string protectName = this->loopActionpoints_.back().name;
267                        if (protectName == "reservedKeyword:human")
268                        {
269                            for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
270                            {
271                                if (orxonox_cast<ControllableEntity*>(*itP) && ((*itP)->getController()) && orxonox_cast <NewHumanController*> ((*itP)->getController()))
272                                {
273                                    this->setProtect (static_cast<ControllableEntity*>(*itP));
274                                }
275                            }
276                        }
277                        else
278                        {
279                            for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
280                            {
281                                if (CommonController::getName(*itP) == protectName)
282                                {
283                                    this->setProtect (static_cast<ControllableEntity*>(*itP));
284                                }
285                            }                           
286                        }
287                        if (!this->getProtect())
288                        {
289                            this->nextActionpoint();
290                            this->executeActionpoint();
291                        }
292                        break;
293                    }
294                    case Action::NONE:
295                    {
296                        break;
297                    }
298                    case Action::FIGHTALL:
299                    {
300                        break;
301                    }
302                    case Action::ATTACK:
303                    {
304                        std::string targetName = this->loopActionpoints_.back().name;
305
306                        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
307                        {
308                            if (CommonController::getName(*itP) == targetName)
309                            {
310                                this->setTarget (static_cast<ControllableEntity*>(*itP));
311                            }
312                        }
313                        if (!this->hasTarget())
314                        {
315                            this->nextActionpoint();
316                            this->executeActionpoint();
317                        }
318                        break;
319                    }
320                    default:
321                    {
322                        break;
323                    }
324                     
325                }
326            }
327            else
328            {
329                this->bLoop_ = false;
330            }
331        }
332        else
333        {
334            if (!this->parsedActionpoints_.empty())
335            {
336                if (this->parsedActionpoints_.back().inLoop)
337                {
338                    //MOVES all points that are in loop to a loop vector
339                    this->fillLoop();
340                    this->bLoop_ = true;
341                    executeActionpoint();
342                    return;
343                }
344                this->action_ = this->parsedActionpoints_.back().action;
345                switch ( this->action_ )
346                {
347                    case Action::FIGHT:
348                    {
349                        std::string targetName = this->parsedActionpoints_.back().name;
350                        if (targetName == "")
351                        {
352                            break;
353                        }
354                        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
355                        {
356                            if (CommonController::getName(*itP) == targetName)
357                            {
358                                this->setTarget (static_cast<ControllableEntity*>(*itP));
359                            }
360                        }         
361                        break;
362                    }
363                    case Action::FLY:
364                    {
365                        this->setTargetPosition( this->parsedActionpoints_.back().position );
366                        if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
367                        {
368                            this->nextActionpoint();
369                            this->executeActionpoint();
370                        }
371                        break;
372                    }
373                    case Action::PROTECT:
374                    {
375                       
376                        std::string protectName = this->parsedActionpoints_.back().name;
377                        if (protectName == "reservedKeyword:human")
378                        {
379                            for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
380                            {
381                                if (orxonox_cast<ControllableEntity*>(*itP) && ((*itP)->getController()) && orxonox_cast <NewHumanController*> ((*itP)->getController()))
382                                {
383                                    this->setProtect (static_cast<ControllableEntity*>(*itP));
384                                }
385                            }
386                        }
387                        else
388                        {
389                            for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
390                            {
391                                if (CommonController::getName(*itP) == protectName)
392                                {
393                                    this->setProtect (static_cast<ControllableEntity*>(*itP));
394                                }
395                            }                           
396                        }
397                        if (!this->getProtect())
398                        {
399                            this->nextActionpoint();
400                            this->executeActionpoint();
401                        }
402                        break;
403                    }
404                    case Action::NONE:
405                    {
406                        break;
407                    }
408                    case Action::FIGHTALL:
409                    {
410                        break;
411                    }
412                    case Action::ATTACK:
413                    {
414                        std::string targetName = this->parsedActionpoints_.back().name;
415
416                        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
417                        {
418                            if (CommonController::getName(*itP) == targetName)
419                            {
420                                this->setTarget (static_cast<ControllableEntity*>(*itP));
421                            }
422                        }
423                        if (!this->hasTarget())
424                        {
425                            this->nextActionpoint();
426                            this->executeActionpoint();
427                        }
428                        break;
429                    }
430                    default:
431                        break;
432                }
433            }
434
435            else
436            {
437                this->setTarget(0);
438                this->setTargetPosition(this->getControllableEntity()->getWorldPosition());
439                this->action_ = Action::NONE;
440            }
441        }
442      }
443
444   
445    void ActionpointController::stayNearProtect()
446    {
447        Vector3* targetRelativePosition;
448        targetRelativePosition = new Vector3 (0, 300, 300); 
449        Vector3 targetAbsolutePosition = ((this->getProtect()->getWorldPosition()) + 
450            (this->getProtect()->getWorldOrientation()* (*targetRelativePosition)));
451        this->setTargetPosition(targetAbsolutePosition);
452    }
453    void ActionpointController::nextActionpoint()
454    {
455        if (!this || !this->getControllableEntity())
456            return;
457        if (this->bLoop_)
458        {
459            if (!this->loopActionpoints_.empty())
460            {
461                this->moveBackToTop();
462            }
463        }
464        else
465        {
466            if (!this->parsedActionpoints_.empty())
467            {
468                this->parsedActionpoints_.pop_back();
469            }           
470        }
471        this->setAction(Action::NONE);
472    }
473    void ActionpointController::moveBackToTop()
474    {
475        Point temp = loopActionpoints_.back();
476        loopActionpoints_.pop_back();
477        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
478        loopActionpoints_.push_back(temp);
479        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
480    }
481    void ActionpointController::fillLoop()
482    {
483        loopActionpoints_.clear();
484        fillLoopReversed();
485        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
486    }
487    void ActionpointController::fillLoopReversed()
488    {
489        if (parsedActionpoints_.back().inLoop)
490        {
491            loopActionpoints_.push_back(parsedActionpoints_.back());
492            parsedActionpoints_.pop_back();
493        }
494        if (parsedActionpoints_.back().inLoop)
495        {
496            fillLoopReversed();
497        }
498    }
499    void ActionpointController::action()
500    {
501        if (!this || !this->getControllableEntity())
502            return;
503        // orxout (internal_error) << "Size of actions is " << this->parsedActionpoints_.size() << endl;
504        this->startAttackingEnemiesThatAreClose();
505        //No action -> pop one from stack
506        if (this->action_ == Action::NONE || this->bTakenOver_)
507        {
508            if (this->parsedActionpoints_.empty() && this->loopActionpoints_.empty())
509            {
510                Point p = { Action::FIGHTALL, "", Vector3::ZERO, false };
511                this->parsedActionpoints_.push_back (p);
512            }
513            this->executeActionpoint();
514            this->bTakenOver_ = false;
515        }
516        //Action fightall -> fight till nobody alive
517        if (this->action_ == Action::FIGHTALL)
518        {
519            if (!this->hasTarget())
520            {
521                //----find a target----
522                ControllableEntity* newTarget = this->closestTarget();   
523                if (newTarget)
524                {
525                    this->setAction (Action::FIGHTALL, newTarget);
526                }
527                else
528                {
529                    this->nextActionpoint();
530                    return;
531                }
532            }
533            else if (this->hasTarget())
534            {
535
536            }
537        }
538        //Action fight -> fight as long as enemies in range
539        else if (this->action_ == Action::FIGHT)
540        {
541            if (!this->hasTarget())
542            {
543                //----find a target----
544                ControllableEntity* newTarget = this->closestTarget();   
545                if (newTarget && 
546                        CommonController::distance (this->getControllableEntity(), newTarget) < this->attackRange_)
547                {
548                    this->setAction (Action::FIGHT, newTarget);
549                }
550                else
551                {
552                    this->nextActionpoint();
553                    return;
554                }
555            }
556            else if (this->hasTarget())
557            {
558                //----fly in formation if far enough----
559                Vector3 diffVector = this->positionOfTarget_ - this->getControllableEntity()->getWorldPosition();         
560                   
561                if (diffVector.length() > this->attackRange_)
562                {
563                    ControllableEntity* newTarget = this->closestTarget();
564                   
565                    if (newTarget && 
566                        CommonController::distance (this->getControllableEntity(), newTarget) < this->attackRange_)
567                    {
568                        this->setAction (Action::FIGHT, newTarget);
569                    }
570                    else
571                    {
572                        this->nextActionpoint();
573                        return;
574                    }
575                }
576            }
577        }
578        else if (this->action_ == Action::FLY)
579        {
580            if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
581            {
582                this->nextActionpoint();   
583                return;
584            }
585        }
586        else if (this->action_ == Action::PROTECT)
587        {
588            if (!this->getProtect())
589            {
590                this->nextActionpoint(); 
591                return;
592            }
593            this->stayNearProtect();
594        }
595        else if (this->action_ == Action::ATTACK)
596        {   
597            if (!this->hasTarget())
598            {
599                this->nextActionpoint();
600                return;
601            }
602        }
603        if (this->hasTarget())
604        {
605            //----choose where to go----
606            this->maneuver();
607            //----fire if you can----
608            this->bShooting_ = this->canFire();               
609        }
610    }
611    void ActionpointController::takeActionpoints (std::vector<Point > vector, std::vector<Point > loop, bool b)
612    {
613      this->parsedActionpoints_ = vector;
614      this->loopActionpoints_ = loop;
615      this->bLoop_ = this->bLoop_;
616      this->bTakenOver_ = true;
617      // orxout(internal_error) << "Top action is " << this->parsedActionpoints_.back().action << endl;
618    }
619    void ActionpointController::setClosestTarget()
620    {
621        this->setTarget (static_cast<ControllableEntity*>( closestTarget() ) ); 
622    }
623    Pawn* ActionpointController::closestTarget()
624    {
625        if (!this->getControllableEntity())
626            return 0;
627
628        Pawn* closestTarget = 0;
629        float minDistance =  std::numeric_limits<float>::infinity();
630        Gametype* gt = this->getGametype();
631        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
632        {
633            if ( CommonController::sameTeam (this->getControllableEntity(), static_cast<ControllableEntity*>(*itP), gt) )
634                continue;
635
636            float distance = CommonController::distance (*itP, this->getControllableEntity());
637            if (distance < minDistance)
638            {
639                closestTarget = *itP;
640                minDistance = distance;
641            }
642        }
643        if (closestTarget)
644        {
645           return closestTarget;
646        } 
647        return 0; 
648    }
649    void ActionpointController::startAttackingEnemiesThatAreClose()
650    {
651        if (this->action_ != Action::FIGHT && this->action_ != Action::FIGHTALL)
652        {
653            if ( (this->target_ && this->distance (this->getControllableEntity(), this->target_) > this->attackRange_) 
654                || !this->target_ )
655            {
656                Pawn* newTarget = this->closestTarget();
657                if ( newTarget && 
658                    this->distance (this->getControllableEntity(), static_cast<ControllableEntity*>(newTarget))
659                        <= this->attackRange_ )
660                {
661                    Point p = { Action::FIGHT, this->getName(newTarget), Vector3::ZERO, false };
662                    this->parsedActionpoints_.push_back(p);
663                    this->executeActionpoint();
664                }
665            }
666        }
667    }
668}
Note: See TracBrowser for help on using the repository browser.