Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

improved dodging

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