Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10927 was 10927, checked in by gania, 9 years ago

fixed?

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