Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/controllers/ActionpointController.h @ 11378

Last change on this file since 11378 was 11112, checked in by landauf, 9 years ago

removed unnecessary boost include

  • Property svn:eol-style set to native
File size: 12.4 KB
RevLine 
[10864]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:
[10885]23 *      Gani Aliguzhinov
[10864]24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#ifndef _ActionpointController_H__
30#define _ActionpointController_H__
31
[10871]32#include "controllers/FightingController.h"
[10877]33#include "tools/Timer.h"
34#include "tools/interfaces/Tickable.h"
[10888]35#include "../modules/pickup/PickupSpawner.h"
36#include <map>
[10864]37
38namespace orxonox
39{
[10898]40    /**
41    @brief
42        ActionpointController is a state machine with states:
43            1) NONE
44            2) FLY: fly towards a point
45            3) FIGHT: fight enemies that are in attackRange_ (see FightingController)
46            4) PROTECT: follow this->protect_
47            5) FIGHTALL: fight all enemies on the map
48            6) ATTACK: fight a specific spaceship
49        This controller always executes an action that is in the back of the vector being used.
50        After current this->action_ is completed, next action becomes the top action (one that will
51        be returned by someVector.back()), and current action either will be removed (if not looping),
52        or moved to the top (if looping).
53
54        Every second action(), which is once in two seconds, this searches the area for enemies that are in attack range, if finds anyone,
55        pushes Action::FIGHT to the stack. That makes spaceship fight enemies inside of a sphere, and when all enemies in range are dead,
56        Action::FIGHT is removed from the stack, and spaceship resumes doing whatever action was being executed before.
57
58        In XML one has to attack Actionpoints in order to achieve any complex behaviour, but in Controller all actionpoints are effectively
59        being stored in an array of type Point::Value.
[10955]60    @note
61        ActionpointController will not work, if there is no MasterController in the level!
[10974]62        All the demos are in a file called AITest.oxw. In the menu look for New AI Testing Level.
[10898]63    */
[11071]64    enum class Action
[10864]65    { 
[11071]66        NONE, FLY, FIGHT, PROTECT, FIGHTALL, ATTACK
67    };
[10864]68   
69    struct Point {
[11071]70        Action action;
[10864]71        std::string name;
72        Vector3 position;
73        bool inLoop;
[11071]74    };
[10864]75
[10877]76    class _OrxonoxExport ActionpointController : public FightingController, public Tickable
[10864]77    {
78        public:
[10915]79           
[10885]80            ActionpointController(Context* context);
81            virtual ~ActionpointController();
[11071]82            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
[10864]83               
[10898]84            /**
85            @brief
[10955]86                tick is called every tick by Game (?).
87                In tick ship flies and fires.
88            */
[11071]89            virtual void tick(float dt) override;
[10955]90            /**
91            @brief
[10898]92                XML method, example XML usage:
[11099]93
94                @code
[10898]95                <SpaceShip position="-2000, 1500, -1000" lookat="0,0,0" team=0 name="ss2">
96                  <templates>
97                    <Template link=spaceshipassff />
98                  </templates>
99                  <controller>
100                    <DivisionController team=0 formationMode="finger4">
101                      <actionpoints>
102                        <Actionpoint position="0,0,0" action="FLY" />
103                        <Actionpoint position="-1000,750,-500" action="ATTACK" attack="attack" />
104                        <Actionpoint position="-1000,750,-500" action="PROTECt" protectMe=true />
105                        <Actionpoint position="-1000,750,-500" action="PROTECt" protect="protect" />
106                        <Actionpoint position="-1000,750,-500" action="FIGHTALL" />
107                       </actionpoints>
108                    </DivisionController>
109                  </controller>
110                </SpaceShip>
[11099]111                @endcode
[10898]112               
113                Full description:
114                Adds an Actionpoint to this->actionpoints_. Actionpoint can take arguments like action="attack" attack="name".
115                For documentation on Actionpoint XML arguments, check out Actionpoint.h class
116                If any WorldEntity that is not Actionpoint or its child being sent to actionpoints through XML,
117                action would be assumed to be Action::FLY and target position to be position of the entity. Also, if not Actionpoint
[11099]118                is passed, it is assumed to be in a loop. How it works is: in \<actionpoints\> first all Actionpoints between
[10898]119                first Actionpoint with loopStart=true and first following Actionpoint with loopEnd=true are included in a single loop.
120                If they are adjacent (in the input array) with WorldEntity, then WorldEntity is also in a loop.
121                All the Worldentities are assumed to be in loop.
122               
123                Loop example:
[11099]124
125                @code
[10898]126                <SpaceShip position="-1500, 1500, -1000" lookat="0,0,0" team=0 name="ss1">
127                  <templates>
128                    <Template link=spaceshipassff />
129                  </templates>
130                  <controller>
131                    <DivisionController team=0 formationMode="wall">
132                      <actionpoints>
133                        <Actionpoint position="  0,2000,-600" action="FLY" loopStart=true/>
134                        <Actionpoint position="  0,2000,-1000" action="FLY"  />
135                        <Actionpoint position="400,2000,-1000" action="FLY" />
136                        <Actionpoint position="400,2000,-600" action="FLY" loopEnd=true />
137                      </actionpoints>
138                    </DivisionController>
139                  </controller>
140                </SpaceShip>
[11099]141                @endcode
[10898]142               
143                other loop example:
[11099]144
145                @code
[10898]146                <SpaceShip position="-1500, -1500, -1500" lookat="0,0,0" team=0 name="ss1">
147                  <templates>
148                    <Template link=spaceshipassff />
149                  </templates>
150                  <controller>
151                    <DivisionController team=0 formationMode="diamond">
152                      <actionpoints>
153                        <Model mesh="cube.mesh" scale=8 position="  0,2000,-600" />
154                        <Model mesh="cube.mesh" scale=8 position="  0,2000,-1000" />
155                        <Model mesh="cube.mesh" scale=8 position="400,2000,-1000" />
156                        <Model mesh="cube.mesh" scale=8 position="400,2000,-600" />
157                      </actionpoints>
158                    </DivisionController>
159                  </controller>
[11099]160                </SpaceShip>
161                @endcode
[10885]162
[10898]163            @note
[11099]164                Don't use several loops, and don't use WorldEntities as input to \<actionpoints\> as I didn't test it well, but you
[10898]165                can try if feeling lucky. 
166            */
167            void addActionpoint(WorldEntity* actionpoint); 
[10912]168            WorldEntity* getActionpoint(unsigned int index) const;   
169            void setDefaultFightAll(bool value)
170                { this->bDefaultFightAll_ = value; }
171            bool getDefaultFightAll ()
172                { return this->bDefaultFightAll_; }
173            void setDefaultPatrol(bool value)
174                { this->bDefaultPatrol_ = value; }
175            bool getDefaultPatrol ()
176                { return this->bDefaultPatrol_; }
[10935]177               
[10912]178
[10864]179            virtual void stayNearProtect();
[10955]180            virtual void action(); //<! action() is called in regular intervals managing the bot's behaviour. Only gets called by MasterController
[10885]181            virtual void takeActionpoints (const std::vector<Point>& vector, const std::vector<Point>& loop, bool b);
[10864]182
[11071]183            virtual Action getAction ();
[10885]184            virtual std::string getActionName();
185
[11071]186            void setAction (Action action);
187            void setAction (Action action, ControllableEntity* target);
188            void setAction (Action action, const Vector3& target);
189            void setAction (Action action, const Vector3& target,  const Quaternion& orient );
[10864]190
[10877]191            virtual bool setWingman(ActionpointController* wingman)
192                { return false; }
193            virtual bool hasWingman()
194                { return true; }
195            virtual bool setFollower(ActionpointController* myFollower)
196                { return false; }
197            virtual bool hasFollower()
198                { return true; }
[10898]199
[10912]200
[10864]201        protected:
[10885]202                void startAttackingEnemiesThatAreClose();
203                WeakPtr<ActionpointController> myWingman_;
204                WeakPtr<ActionpointController> myFollower_;
205                WeakPtr<ActionpointController> myDivisionLeader_;
[10864]206            //----[Actionpoint information]----
[11071]207                Action action_;
[10864]208                std::string protectName_;
209                std::string targetName_;
[11071]210                std::vector<WeakPtr<WorldEntity>> actionpoints_;
[10864]211                float squaredaccuracy_;
[11071]212                std::vector<Point> parsedActionpoints_; //<! actionpoints as they are stored here after being parsed from XML
213                std::vector<Point> loopActionpoints_;   //<! actionpoints that are to be looped
[10974]214                bool bInLoop_;                          //<! variable for addActionpoint method
[10898]215                bool bLoop_;                            //<! is state machine looping?
[10974]216                bool bEndLoop_;                         //<! variable for addActionpoint method
[10898]217                bool bTakenOver_;                       //<! are actionpoints taken over from the leader when he died? if yes, top actionpoint
218                                                        //<! is to be executed for the state machine to start working
[10864]219            //----[/Actionpoint information]----
220                void setProtect (ControllableEntity* protect);
221                ControllableEntity* getProtect (); 
[10898]222                WeakPtr<ControllableEntity> protect_;   //<! entity that is to be protected if this->action_ == Action::PROTECT
223                void fillLoop();                        //<! moves actionpoints that are should be in loop from parsedActionpoints_ to loopActionpoints_
[10885]224                void fillLoopReversed();
[10898]225                void moveBackToTop();                   //<! analog of removing back actionpoint for loopActionpoints_: instead of removing it,
226                                                        //<! move it to the top, so that it will be executed later on.
[10864]227                void setClosestTarget();
228                Pawn* closestTarget();
229            //----[Actionpoint methods]----
[10898]230                /**
231                @brief
232                    Sets this->target_, this->targetPosition_, this->protect_ and this->action_ depending
233                    on the current actionpoint in the vector parsedActionpoints_ if not looping or
234                    loopActionpoints_ if looping.
235                @note
236                */
237                void executeActionpoint(); 
238                /**
239                @brief
240                    If this->bLoop_, move back action to top (back is the current one, top is the last),
241                    otherwise remove back actionpoint.
242                @note
243                    actionpoints_ is only used for XML, real state stacks are parsedActionpoints_ and loopActionpoints_
244                */           
245                void nextActionpoint();                 
[10864]246            //----[Actionpoint methods]----         
[10877]247
[10974]248                bool bDefaultFightAll_;     //<! if true, when no action set, this will fight all
[10912]249
[10974]250                bool bPatrolling_;        //<! true if current action_ is FIGHT because this found enemies that are close, need this to correctly go back to looping if was looping
251                bool bDefaultPatrol_;       //<! if true, this will look out for enemies that are close if this is just flying or doing nothing
[10946]252                unsigned int ticks_;     //<! local tick counter           
[10864]253    };
254}
255
256#endif /* _ActionpointController_H__ */
Note: See TracBrowser for help on using the repository browser.