Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/campaignHS15/src/orxonox/controllers/ActionpointController.h @ 10935

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

cleaned source up a bit

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