Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

CommonController now has static methods only. Replace with a namespace?

File size: 19.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            this->bFirstTick_ = false;
85                SUPER(ActionpointController, tick, dt);
86        }
87    ActionpointController::~ActionpointController()
88    {
89        loopActionpoints_.clear();
90        parsedActionpoints_.clear();
91        actionpoints_.clear();
92    }
93    void ActionpointController::setProtect (ControllableEntity* protect)
94    {
95        this->protect_ = protect;
96    }
97    ControllableEntity* ActionpointController::getProtect ()
98    {
99        return this->protect_;
100    }
101    void ActionpointController::addActionpoint(WorldEntity* actionpoint)
102    {
103        std::string actionName;
104        Vector3 position;
105        std::string targetName;
106        bool inLoop = false;
107        Point p;
108        if (static_cast<Actionpoint*> (actionpoint))
109        {
110            Actionpoint* ap = static_cast<Actionpoint*> (actionpoint);
111            actionName = ap->getActionXML();
112            targetName = ap->getName();
113            position = ap->getWorldPosition();
114
115            if (this->bEndLoop_)
116            {
117                this->bInLoop_ = false;
118            }
119            if (!this->bInLoop_ && ap->getLoopStart())
120            {
121                this->bInLoop_ = true;
122            }
123            if (this->bInLoop_ && ap->getLoopEnd())
124            {
125                this->bEndLoop_ = true;
126            }
127            inLoop = this->bInLoop_;
128
129            Action::Value value;
130           
131            if ( actionName == "FIGHT" )
132            { value = Action::FIGHT; }
133            else if ( actionName == "FLY" )
134            { value = Action::FLY; }
135            else if ( actionName == "PROTECT" )
136            { value = Action::PROTECT; }
137            else if ( actionName == "NONE" )
138            { value = Action::NONE; }
139            else if ( actionName == "FIGHTALL" )
140            { value = Action::FIGHTALL; }
141            else if ( actionName == "ATTACK" )
142            { value = Action::ATTACK; }
143            else
144                ThrowException( ParseError, std::string( "Attempting to set an unknown Action: '" )+ actionName + "'." );
145            p.action = value; p.name = targetName; p.position = position; p.inLoop = inLoop;
146        }
147        else
148        {
149            p.action = Action::FLY; p.name = ""; p.position = actionpoint->getWorldPosition(); p.inLoop = inLoop;
150        }
151            parsedActionpoints_.push_back(p);
152            this->actionpoints_.push_back(actionpoint);
153    }
154    WorldEntity* ActionpointController::getActionpoint(unsigned int index) const
155    {
156        if (index < this->actionpoints_.size())
157            return this->actionpoints_[index];
158        else
159            return 0;
160    }
161
162      Action::Value ActionpointController::getAction ()
163    {
164        return this->action_;
165    }
166    std::string ActionpointController::getActionName()
167    {
168        switch ( this->action_ )
169        {
170            case Action::FIGHT:
171            { return "FIGHT"; break; }
172            case Action::FLY:
173            { return "FLY"; break; }
174            case Action::PROTECT:
175            { return "PROTECT"; break; }
176            case Action::NONE:
177            { return "NONE"; break; }
178            case Action::FIGHTALL:
179            { return "FIGHTALL"; break; }
180            case Action::ATTACK:
181            { return "ATTACK"; break; }
182            default:
183                return "NONE";
184                break;
185        }
186    }
187    void ActionpointController::setAction (Action::Value action)
188    {
189        this->action_ = action;
190    }
191    void ActionpointController::setAction (Action::Value action, ControllableEntity* target)
192    {
193        this->action_ = action;
194        if (action == Action::FIGHT || action == Action::FIGHTALL || action == Action::ATTACK)
195        {   
196            if (target)
197                this->setTarget (target);
198        }
199        else if (action == Action::PROTECT)
200        {
201            if (target)
202                this->setProtect (target);
203        }
204    }
205    void ActionpointController::setAction (Action::Value action, const Vector3& target)
206    {
207        this->action_ = action;
208        if (action == Action::FLY)
209        {
210            this->setTargetPosition (target);
211        }
212    }
213    void ActionpointController::setAction (Action::Value action, const Vector3& target,  const Quaternion& orient )
214    {
215        this->action_ = action;
216        if (action == Action::FLY)
217        {
218            this->setTargetPosition (target);
219            this->setTargetOrientation (orient);
220        } 
221    }
222   
223    //------------------------------------------------------------------------------
224    //------------------------------Actionpoint methods-----------------------------
225    //------------------------------------------------------------------------------
226
227    //POST: this starts doing what was asked by the last element of parsedActionpoints_,
228    //if last element was failed to be parsed, next element will be executed.
229    void ActionpointController::executeActionpoint()
230    {
231        Point p;
232        if (this->bLoop_ && !loopActionpoints_.empty())
233        {
234            p = loopActionpoints_.back();
235        }
236        else if (this->bLoop_)
237        {
238            this->bLoop_ = false;
239            return;
240        }
241        else if (!this->bLoop_ && !parsedActionpoints_.empty())
242        {
243            p = parsedActionpoints_.back();
244        }
245        else
246        {
247            this->setTarget(0);
248            this->setTargetPosition(this->getControllableEntity()->getWorldPosition());
249            this->action_ = Action::NONE;
250            return;
251        }
252        if (!this->bLoop_ && this->parsedActionpoints_.back().inLoop)
253        {
254            //MOVES all points that are in loop to a loop vector
255            this->fillLoop();
256            this->bLoop_ = true;
257            executeActionpoint();
258            return;
259        }
260        this->action_ = p.action;
261        switch ( this->action_ )
262        {
263            case Action::FIGHT:
264            {
265                std::string targetName = p.name;
266                if (targetName == "")
267                {
268                    break;
269                }
270                for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
271                {
272                    if (CommonController::getName(*itP) == targetName)
273                    {
274                        this->setTarget (static_cast<ControllableEntity*>(*itP));
275                    }
276                }         
277                break;
278            }
279            case Action::FLY:
280            {
281                this->setTargetPosition( p.position );
282                if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
283                {
284                    this->nextActionpoint();
285                    this->executeActionpoint();
286                }
287                break;
288            }
289            case Action::PROTECT:
290            {
291               
292                std::string protectName = p.name;
293                if (protectName == "reservedKeyword:human")
294                {
295                    for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
296                    {
297                        if (orxonox_cast<ControllableEntity*>(*itP) && ((*itP)->getController()) && ((*itP)->getController()->getIdentifier()->getName() == "NewHumanController"))
298                        {
299                            this->setProtect (static_cast<ControllableEntity*>(*itP));
300                        }
301                    }
302                }
303                else
304                {
305                    for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
306                    {
307                        if (CommonController::getName(*itP) == protectName)
308                        {
309                            this->setProtect (static_cast<ControllableEntity*>(*itP));
310                        }
311                    }                           
312                }
313                if (!this->getProtect())
314                {
315                    this->nextActionpoint();
316                    this->executeActionpoint();
317                }
318                break;
319            }
320            case Action::NONE:
321            {
322                break;
323            }
324            case Action::FIGHTALL:
325            {
326                break;
327            }
328            case Action::ATTACK:
329            {
330                std::string targetName = p.name;
331
332                for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
333                {
334                    if (CommonController::getName(*itP) == targetName)
335                    {
336                        this->setTarget (static_cast<ControllableEntity*>(*itP));
337                    }
338                }
339                if (!this->hasTarget())
340                {
341                    this->nextActionpoint();
342                    this->executeActionpoint();
343                }
344                break;
345            }
346            default:
347                break;
348        }
349       
350    }
351
352   
353    void ActionpointController::stayNearProtect()
354    {
355        Vector3* targetRelativePosition;
356        targetRelativePosition = new Vector3 (0, 300, 300); 
357        Vector3 targetAbsolutePosition = ((this->getProtect()->getWorldPosition()) + 
358            (this->getProtect()->getWorldOrientation()* (*targetRelativePosition)));
359        this->setTargetPosition(targetAbsolutePosition);
360    }
361    void ActionpointController::nextActionpoint()
362    {
363        if (!this || !this->getControllableEntity())
364            return;
365        if (this->bLoop_)
366        {
367            if (!this->loopActionpoints_.empty())
368            {
369                this->moveBackToTop();
370            }
371        }
372        else
373        {
374            if (!this->parsedActionpoints_.empty())
375            {
376                this->parsedActionpoints_.pop_back();
377            }           
378        }
379        this->setAction(Action::NONE);
380    }
381    void ActionpointController::moveBackToTop()
382    {
383        Point temp = loopActionpoints_.back();
384        loopActionpoints_.pop_back();
385        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
386        loopActionpoints_.push_back(temp);
387        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
388    }
389    void ActionpointController::fillLoop()
390    {
391        loopActionpoints_.clear();
392        fillLoopReversed();
393        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
394    }
395    void ActionpointController::fillLoopReversed()
396    {
397        if (parsedActionpoints_.back().inLoop)
398        {
399            loopActionpoints_.push_back(parsedActionpoints_.back());
400            parsedActionpoints_.pop_back();
401        }
402        if (parsedActionpoints_.back().inLoop)
403        {
404            fillLoopReversed();
405        }
406    }
407    void ActionpointController::action()
408    {
409        if (!this || !this->getControllableEntity())
410            return;
411        // orxout (internal_error) << "Size of actions is " << this->parsedActionpoints_.size() << endl;
412        this->startAttackingEnemiesThatAreClose();
413        //No action -> pop one from stack
414        if (this->action_ == Action::NONE || this->bTakenOver_)
415        {
416            if (this->parsedActionpoints_.empty() && this->loopActionpoints_.empty())
417            {
418                Point p = { Action::FIGHTALL, "", Vector3::ZERO, false };
419                this->parsedActionpoints_.push_back (p);
420            }
421            this->executeActionpoint();
422            this->bTakenOver_ = false;
423        }
424        //Action fightall -> fight till nobody alive
425        if (this->action_ == Action::FIGHTALL)
426        {
427            if (!this->hasTarget())
428            {
429                //----find a target----
430                ControllableEntity* newTarget = this->closestTarget();   
431                if (newTarget)
432                {
433                    this->setAction (Action::FIGHTALL, newTarget);
434                }
435                else
436                {
437                    this->nextActionpoint();
438                    return;
439                }
440            }
441            else if (this->hasTarget())
442            {
443
444            }
445        }
446        //Action fight -> fight as long as enemies in range
447        else if (this->action_ == Action::FIGHT)
448        {
449            if (!this->hasTarget())
450            {
451                //----find a target----
452                ControllableEntity* newTarget = this->closestTarget();   
453                if (newTarget && 
454                        CommonController::distance (this->getControllableEntity(), newTarget) < this->attackRange_)
455                {
456                    this->setAction (Action::FIGHT, newTarget);
457                }
458                else
459                {
460                    this->nextActionpoint();
461                    return;
462                }
463            }
464            else if (this->hasTarget())
465            {
466                //----fly in formation if far enough----
467                Vector3 diffVector = this->positionOfTarget_ - this->getControllableEntity()->getWorldPosition();         
468                   
469                if (diffVector.length() > this->attackRange_)
470                {
471                    ControllableEntity* newTarget = this->closestTarget();
472                   
473                    if (newTarget && 
474                        CommonController::distance (this->getControllableEntity(), newTarget) < this->attackRange_)
475                    {
476                        this->setAction (Action::FIGHT, newTarget);
477                    }
478                    else
479                    {
480                        this->nextActionpoint();
481                        return;
482                    }
483                }
484            }
485        }
486        else if (this->action_ == Action::FLY)
487        {
488            if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
489            {
490                this->nextActionpoint();   
491                return;
492            }
493        }
494        else if (this->action_ == Action::PROTECT)
495        {
496            if (!this->getProtect())
497            {
498                this->nextActionpoint(); 
499                return;
500            }
501            this->stayNearProtect();
502        }
503        else if (this->action_ == Action::ATTACK)
504        {   
505            if (!this->hasTarget())
506            {
507                this->nextActionpoint();
508                return;
509            }
510        }
511        if (this->hasTarget())
512        {
513            //----choose where to go----
514            this->maneuver();
515            //----fire if you can----
516            this->bShooting_ = this->canFire();               
517        }
518    }
519    void ActionpointController::takeActionpoints (std::vector<Point > vector, std::vector<Point > loop, bool b)
520    {
521      this->parsedActionpoints_ = vector;
522      this->loopActionpoints_ = loop;
523      this->bLoop_ = b;
524      this->bTakenOver_ = true;
525      // orxout(internal_error) << "Top action is " << this->parsedActionpoints_.back().action << endl;
526    }
527    void ActionpointController::setClosestTarget()
528    {
529        this->setTarget (static_cast<ControllableEntity*>( closestTarget() ) ); 
530    }
531    Pawn* ActionpointController::closestTarget()
532    {
533        if (!this->getControllableEntity())
534            return 0;
535
536        Pawn* closestTarget = 0;
537        float minDistance =  std::numeric_limits<float>::infinity();
538        Gametype* gt = this->getGametype();
539        for (ObjectList<Pawn>::iterator itP = ObjectList<Pawn>::begin(); itP; ++itP)
540        {
541            if ( CommonController::sameTeam (this->getControllableEntity(), static_cast<ControllableEntity*>(*itP), gt) )
542                continue;
543
544            float distance = CommonController::distance (*itP, this->getControllableEntity());
545            if (distance < minDistance)
546            {
547                closestTarget = *itP;
548                minDistance = distance;
549            }
550        }
551        if (closestTarget)
552        {
553           return closestTarget;
554        } 
555        return 0; 
556    }
557    void ActionpointController::startAttackingEnemiesThatAreClose()
558    {
559        if (this->action_ != Action::FIGHT && this->action_ != Action::FIGHTALL)
560        {
561            if ( (this->target_ && CommonController::distance (this->getControllableEntity(), this->target_) > this->attackRange_) 
562                || !this->target_ )
563            {
564                Pawn* newTarget = this->closestTarget();
565                if ( newTarget && 
566                    CommonController::distance (this->getControllableEntity(), static_cast<ControllableEntity*>(newTarget))
567                        <= this->attackRange_ )
568                {
569                    Point p = { Action::FIGHT, CommonController::getName(newTarget), Vector3::ZERO, false };
570                    this->parsedActionpoints_.push_back(p);
571                    this->executeActionpoint();
572                }
573            }
574        }
575    }
576}
Note: See TracBrowser for help on using the repository browser.