Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

converted hack to a legal class

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