1 /** @file generator.h World map (particle) generator. 2 * 3 * @authors Copyright © 2003-2017 Jaakko Keränen <jaakko.keranen@iki.fi> 4 * @authors Copyright © 2006-2015 Daniel Swanson <danij@dengine.net> 5 * 6 * @par License 7 * GPL: http://www.gnu.org/licenses/gpl.html 8 * 9 * <small>This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. This program is distributed in the hope that it 13 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15 * Public License for more details. You should have received a copy of the GNU 16 * General Public License along with this program; if not, write to the Free 17 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18 * 02110-1301 USA</small> 19 */ 20 21 #ifndef CLIENT_WORLD_GENERATOR_H 22 #define CLIENT_WORLD_GENERATOR_H 23 24 #include <de/Vector> 25 #include <doomsday/defs/dedtypes.h> 26 #include "map.h" 27 28 class Line; 29 class Plane; 30 struct mobj_s; 31 32 namespace world { 33 34 class BspLeaf; 35 36 /** 37 * POD structure used when querying the current state of a particle. 38 */ 39 struct ParticleInfo 40 { 41 de::dint stage; ///< -1 => particle doesn't exist 42 de::dshort tics; 43 fixed_t origin[3]; ///< Coordinates. 44 fixed_t mov[3]; ///< Momentum. 45 world::BspLeaf *bspLeaf; ///< Updated when needed. 46 Line *contact; ///< Updated when lines hit/avoided. 47 de::dushort yaw, pitch; ///< Rotation angles (0-65536 => 0-360). 48 }; 49 50 /** 51 * Particle generator. 52 */ 53 struct Generator 54 { 55 /** 56 * Particle animation is defined as a sequence of (perhaps interpolated) 57 * property value stages. 58 */ 59 struct ParticleStage 60 { 61 enum Flag 62 { 63 StageTouch = 0x1, ///< Touching ends current stage. 64 DieTouch = 0x2, ///< Dies from first touch. 65 Bright = 0x4, ///< Fullbright. 66 Shading = 0x8, ///< Pseudo-3D. 67 PlaneFlat = 0x10, ///< Touches a plane => render as flat. 68 StageWallTouch = 0x20, ///< Touch a wall => end stage. 69 StageFlatTouch = 0x40, ///< Touch a flat => end stage. 70 WallFlat = 0x80, ///< Touches a wall => render as flat. 71 SphereForce = 0x100, 72 ZeroYaw = 0x200, ///< Set particle yaw to zero. 73 ZeroPitch = 0x400, ///< Set particle pitch to zero. 74 RandomYaw = 0x800, 75 RandomPitch = 0x1000 76 }; 77 Q_DECLARE_FLAGS(Flags, Flag) 78 79 de::dshort type; 80 Flags flags; 81 fixed_t resistance; 82 fixed_t bounce; 83 fixed_t radius; 84 fixed_t gravity; 85 }; 86 87 enum Flag 88 { 89 Static = 0x1, ///< Can't be replaced by anything. 90 RelativeVelocity = 0x2, ///< Particles inherit source's velocity. 91 SpawnOnly = 0x4, ///< Generator is spawned only when source is being spawned. 92 RelativeVector = 0x8, ///< Rotate spawn vector w/mobj angle. 93 BlendAdditive = 0x10, ///< Render using additive blending. 94 SpawnFloor = 0x20, ///< Flat-trig: spawn on floor. 95 SpawnCeiling = 0x40, ///< Flat-trig: spawn on ceiling. 96 SpawnSpace = 0x80, ///< Flat-trig: spawn in air. 97 Density = 0x100, ///< Definition specifies a density. 98 ModelOnly = 0x200, ///< Only spawn if source is a 3D model. 99 ScaledRate = 0x400, ///< Spawn rate affected by a factor. 100 Group = 0x800, ///< Triggered by all in anim group. 101 BlendSubtract = 0x1000, ///< Subtractive blending. 102 BlendReverseSubtract = 0x2000, ///< Reverse subtractive blending. 103 BlendMultiply = 0x4000, ///< Multiplicative blending. 104 BlendInverseMultiply = 0x8000, ///< Inverse multiplicative blending. 105 StateChain = 0x10000 ///< Chain after existing state gen(s). 106 }; 107 Q_DECLARE_FLAGS(Flags, Flag) 108 109 /// Unique identifier associated with each generator (1-based). 110 typedef de::dshort Id; 111 112 public: /// @todo make private: 113 thinker_t thinker; ///< Func = P_PtcGenThinker 114 Plane *plane; ///< Flat-triggered. 115 ded_ptcgen_t const *def; ///< The definition of this generator. 116 struct mobj_s *source; ///< If mobj-triggered. 117 de::dint srcid; ///< Source mobj ID. 118 de::dint type; ///< Type-triggered; mobj type number (-1=none). 119 de::dint type2; ///< Type-triggered; alternate type. 120 fixed_t originAtSpawn[3]; ///< Used by untriggered/damage gens. 121 fixed_t vector[3]; ///< Converted from the definition. 122 de::dfloat spawnRateMultiplier; 123 de::dint count; ///< Number of particles generated thus far. 124 ParticleStage *stages; 125 126 public: 127 /** 128 * Returns the map in which the generator exists. 129 * 130 * @see Thinker_Map() 131 */ 132 world::Map &map() const; 133 134 /** 135 * Returns the unique identifier of the generator. The identifier is 1-based. 136 */ 137 Id id() const; 138 139 /** 140 * Change the unique identifier of the generator. The identifier is 1-based. 141 * 142 * @param newId New identifier to apply. 143 */ 144 void setId(Id newId); 145 146 /** 147 * Set gen->count prior to calling this function. 148 */ 149 void configureFromDef(ded_ptcgen_t const *def); 150 151 /** 152 * Generate and/or move the particles. 153 */ 154 void runTick(); 155 156 /** 157 * Run the generator's thinker for the given number of @a tics. 158 */ 159 void presimulate(de::dint tics); 160 161 /** 162 * Returns the age of the generator (time since spawn), in tics. 163 */ 164 de::dint age() const; 165 166 /** 167 * Determine the @em approximate origin of the generator in map space. 168 * 169 * @note In the case of generator attached to a mobj this is the @em current, 170 * unsmoothed origin of the mobj offset by the @em initial origin at generator 171 * spawn time. For all other types of generator the initial origin at generator 172 * spawn time is returned. 173 */ 174 de::Vector3d origin() const; 175 176 /** 177 * Returns @c true iff the generator is @em static, meaning it will not be 178 * replaced under any circumstances. 179 */ 180 bool isStatic() const; 181 182 /** 183 * Returns @c true iff the generator is @em untriggered. 184 */ 185 bool isUntriggered() const; 186 187 /** 188 * Change the @em untriggered state of the generator. 189 */ 190 void setUntriggered(bool yes = true); 191 192 /** 193 * Returns the currently configured blending mode for the generator. 194 */ 195 blendmode_t blendmode() const; 196 197 /** 198 * Returns the total number of @em active particles for the generator. 199 */ 200 de::dint activeParticleCount() const; 201 202 /** 203 * Provides readonly access to the generator particle info data. 204 */ 205 ParticleInfo const *particleInfo() const; 206 207 public: /// @todo make private: 208 /** 209 * Clears all memory used for manipulating the generated particles. 210 */ 211 void clearParticles(); 212 213 /** 214 * Attempt to spawn a new particle. 215 * 216 * @return Index of the newly spawned particle; otherwise @c -1. 217 */ 218 de::dint newParticle(); 219 220 /** 221 * The movement is done in two steps: 222 * Z movement is done first. Skyflat kills the particle. 223 * XY movement checks for hits with solid walls (no backsector). 224 * This is supposed to be fast and simple (but not too simple). 225 */ 226 void moveParticle(de::dint index); 227 228 void spinParticle(ParticleInfo &pt); 229 230 de::dfloat particleZ(ParticleInfo const &pt) const; 231 232 de::Vector3f particleOrigin(ParticleInfo const &pt) const; 233 de::Vector3f particleMomentum(ParticleInfo const &pt) const; 234 235 public: 236 /** 237 * Register the console commands, variables, etc..., of this module. 238 */ 239 static void consoleRegister(); 240 241 private: 242 Id _id; ///< Unique in the map. 243 Flags _flags; 244 de::dint _age; ///< Time since spawn, in tics. 245 de::dfloat _spawnCount; 246 bool _untriggered; ///< @c true= consider this as not yet triggered. 247 de::dint _spawnCP; ///< Particle spawn cursor. 248 ParticleInfo *_pinfo; ///< Info about each generated particle. 249 }; 250 251 Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::Flags) 252 Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::ParticleStage::Flags) 253 254 typedef Generator::ParticleStage GeneratorParticleStage; 255 256 void Generator_Delete(Generator *gen); 257 void Generator_Thinker(Generator *gen); 258 259 } // namespace world 260 261 #endif // CLIENT_WORLD_GENERATOR_H 262