1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ 2 3 #ifndef EXPLOSION_GENERATOR_H 4 #define EXPLOSION_GENERATOR_H 5 6 #include <map> 7 #include <string> 8 #include <vector> 9 #include <boost/shared_ptr.hpp> 10 11 #include "Sim/Objects/WorldObject.h" 12 13 #define CEG_PREFIX_STRING "custom:" 14 15 class LuaParser; 16 class LuaTable; 17 class float3; 18 class CUnit; 19 class IExplosionGenerator; 20 21 22 class CExpGenSpawnable: public CWorldObject 23 { 24 CR_DECLARE(CExpGenSpawnable) 25 public: 26 CExpGenSpawnable(); 27 CExpGenSpawnable(const float3& pos, const float3& spd); 28 ~CExpGenSpawnable()29 virtual ~CExpGenSpawnable() {} 30 virtual void Init(const CUnit* owner, const float3& offset) = 0; 31 }; 32 33 34 35 // Finds C++ classes with class aliases 36 class ClassAliasList 37 { 38 public: 39 void Load(const LuaTable&); Clear()40 void Clear() { aliases.clear(); } 41 42 creg::Class* GetClass(const std::string& name) const; 43 std::string FindAlias(const std::string& className) const; 44 45 private: 46 std::map<std::string, std::string> aliases; 47 }; 48 49 50 51 // loads and stores a list of explosion generators 52 class CExplosionGeneratorHandler 53 { 54 public: 55 enum { 56 EXPGEN_ID_INVALID = -1u, 57 EXPGEN_ID_STANDARD = 0u, 58 }; 59 60 CExplosionGeneratorHandler(); 61 ~CExplosionGeneratorHandler(); 62 63 void ParseExplosionTables(); 64 void ReloadGenerators(const std::string&); 65 66 unsigned int LoadGeneratorID(const std::string& tag); 67 IExplosionGenerator* LoadGenerator(const std::string& tag); 68 IExplosionGenerator* GetGenerator(unsigned int expGenID); 69 70 bool GenExplosion( 71 unsigned int expGenID, 72 const float3& pos, 73 const float3& dir, 74 float damage, 75 float radius, 76 float gfxMod, 77 CUnit* owner, 78 CUnit* hit 79 ); 80 GetExplosionTableRoot()81 const LuaTable* GetExplosionTableRoot() const { return explTblRoot; } GetProjectileClasses()82 const ClassAliasList& GetProjectileClasses() const { return projectileClasses; } GetGeneratorClasses()83 const ClassAliasList& GetGeneratorClasses() const { return generatorClasses; } 84 85 protected: 86 ClassAliasList projectileClasses; 87 ClassAliasList generatorClasses; 88 89 LuaParser* exploParser; 90 LuaParser* aliasParser; 91 LuaTable* explTblRoot; 92 93 std::vector<IExplosionGenerator*> explosionGenerators; 94 95 std::map<std::string, unsigned int> expGenTagIdentMap; 96 std::map<unsigned int, std::string> expGenIdentTagMap; 97 98 typedef std::map<std::string, unsigned int>::const_iterator TagIdentMapConstIt; 99 typedef std::map<unsigned int, std::string>::const_iterator IdentTagMapConstIt; 100 }; 101 102 103 104 105 // Base explosion generator class 106 class IExplosionGenerator 107 { 108 CR_DECLARE(IExplosionGenerator) 109 IExplosionGenerator()110 IExplosionGenerator(): generatorID(CExplosionGeneratorHandler::EXPGEN_ID_INVALID) {} ~IExplosionGenerator()111 virtual ~IExplosionGenerator() {} 112 113 virtual bool Load(CExplosionGeneratorHandler* handler, const std::string& tag) = 0; Reload(CExplosionGeneratorHandler * handler,const std::string & tag)114 virtual bool Reload(CExplosionGeneratorHandler* handler, const std::string& tag) { return true; } 115 virtual bool Explosion( 116 const float3& pos, 117 const float3& dir, 118 float damage, 119 float radius, 120 float gfxMod, 121 CUnit* owner, 122 CUnit* hit 123 ) = 0; 124 GetGeneratorID()125 unsigned int GetGeneratorID() const { return generatorID; } SetGeneratorID(unsigned int id)126 void SetGeneratorID(unsigned int id) { generatorID = id; } 127 128 protected: 129 unsigned int generatorID; 130 }; 131 132 133 // spawns non-scriptable explosion effects via hardcoded rules 134 // has no internal state so we never need to allocate instances 135 class CStdExplosionGenerator: public IExplosionGenerator 136 { CR_DECLARE(CStdExplosionGenerator)137 CR_DECLARE(CStdExplosionGenerator) 138 139 public: 140 CStdExplosionGenerator(): IExplosionGenerator() {} 141 Load(CExplosionGeneratorHandler * handler,const std::string & tag)142 bool Load(CExplosionGeneratorHandler* handler, const std::string& tag) { return false; } 143 bool Explosion( 144 const float3& pos, 145 const float3& dir, 146 float damage, 147 float radius, 148 float gfxMod, 149 CUnit* owner, 150 CUnit* hit 151 ); 152 }; 153 154 155 // Uses explosion info from a script file; defines the 156 // result of an explosion as a series of new projectiles 157 class CCustomExplosionGenerator: public IExplosionGenerator 158 { 159 CR_DECLARE(CCustomExplosionGenerator) 160 CR_DECLARE_SUB(ProjectileSpawnInfo) 161 CR_DECLARE_SUB(GroundFlashInfo) 162 CR_DECLARE_SUB(ExpGenParams) 163 164 protected: 165 struct ProjectileSpawnInfo { 166 CR_DECLARE_STRUCT(ProjectileSpawnInfo) 167 ProjectileSpawnInfoProjectileSpawnInfo168 ProjectileSpawnInfo() 169 : projectileClass(NULL) 170 , count(0) 171 , flags(0) 172 {} ProjectileSpawnInfoProjectileSpawnInfo173 ProjectileSpawnInfo(const ProjectileSpawnInfo& psi) 174 : projectileClass(psi.projectileClass) 175 , code(psi.code) 176 , count(psi.count) 177 , flags(psi.flags) 178 {} 179 180 creg::Class* projectileClass; 181 182 /// parsed explosion script code 183 std::vector<char> code; 184 185 /// number of projectiles spawned of this type 186 unsigned int count; 187 unsigned int flags; 188 }; 189 190 // TODO: Handle ground flashes with more flexibility like the projectiles 191 struct GroundFlashInfo { 192 CR_DECLARE_STRUCT(GroundFlashInfo) 193 GroundFlashInfoGroundFlashInfo194 GroundFlashInfo() 195 : flashSize(0.0f) 196 , flashAlpha(0.0f) 197 , circleGrowth(0.0f) 198 , circleAlpha(0.0f) 199 , ttl(0) 200 , flags(0) 201 , color(ZeroVector) 202 {} 203 204 float flashSize; 205 float flashAlpha; 206 float circleGrowth; 207 float circleAlpha; 208 int ttl; 209 unsigned int flags; 210 float3 color; 211 }; 212 213 struct ExpGenParams { 214 CR_DECLARE_STRUCT(ExpGenParams) 215 216 std::vector<ProjectileSpawnInfo> projectiles; 217 218 GroundFlashInfo groundFlash; 219 220 bool useDefaultExplosions; 221 }; 222 223 public: CCustomExplosionGenerator()224 CCustomExplosionGenerator(): IExplosionGenerator() {} 225 226 static bool OutputProjectileClassInfo(); 227 static unsigned int GetFlagsFromTable(const LuaTable& table); 228 static unsigned int GetFlagsFromHeight(float height, float groundHeight); 229 230 /// @throws content_error/runtime_error on errors 231 bool Load(CExplosionGeneratorHandler* handler, const std::string& tag); 232 bool Reload(CExplosionGeneratorHandler* handler, const std::string& tag); 233 bool Explosion(const float3& pos, const float3& dir, float damage, float radius, float gfxMod, CUnit* owner, CUnit* hit); 234 235 236 enum { 237 SPW_WATER = 1, 238 SPW_GROUND = 2, 239 SPW_AIR = 4, 240 SPW_UNDERWATER = 8, 241 SPW_UNIT = 16, // only execute when the explosion hits a unit 242 SPW_NO_UNIT = 32, // only execute when the explosion doesn't hit a unit (environment) 243 }; 244 245 enum { 246 OP_END = 0, 247 OP_STOREI = 1, // int 248 OP_STOREF = 2, // float 249 OP_STOREC = 3, // char 250 OP_ADD = 4, 251 OP_RAND = 5, 252 OP_DAMAGE = 6, 253 OP_INDEX = 7, 254 OP_LOADP = 8, // load a void* into the pointer register 255 OP_STOREP = 9, // store the pointer register into a void* 256 OP_DIR = 10, // store the float3 direction 257 OP_SAWTOOTH = 11, // Performs a modulo to create a sawtooth wave 258 OP_DISCRETE = 12, // Floors the value to a multiple of its parameter 259 OP_SINE = 13, // Uses val as the phase of a sine wave 260 OP_YANK = 14, // Moves the input value into a buffer, returns zero 261 OP_MULTIPLY = 15, // Multiplies with buffer value 262 OP_ADDBUFF = 16, // Adds buffer value 263 OP_POW = 17, // Power with code as exponent 264 OP_POWBUFF = 18, // Power with buffer as exponent 265 }; 266 267 private: 268 void ParseExplosionCode(ProjectileSpawnInfo* psi, const int offset, const boost::shared_ptr<creg::IType> type, const std::string& script, std::string& code); 269 void ExecuteExplosionCode(const char* code, float damage, char* instance, int spawnIndex, const float3& dir); 270 271 protected: 272 ExpGenParams expGenParams; 273 }; 274 275 276 extern CExplosionGeneratorHandler* explGenHandler; 277 278 #endif // EXPLOSION_GENERATOR_H 279