Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

fixed a bug in DivisionController, made action transitions smoother

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