Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

split up some code

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