Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

ships spread before fight

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