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