Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

check in

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