1 /** @file p_object.h  World map objects.
2  *
3  * @authors Copyright © 2003-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4  * @authors Copyright © 2005-2015 Daniel Swanson <danij@dengine.net>
5  * @authors Copyright © 2006 Jamie Jones <jamie_jones_au@yahoo.com.au>
6  *
7  * @par License
8  * GPL: http://www.gnu.org/licenses/gpl.html
9  *
10  * <small>This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by the
12  * Free Software Foundation; either version 2 of the License, or (at your
13  * option) any later version. This program is distributed in the hope that it
14  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16  * Public License for more details. You should have received a copy of the GNU
17  * General Public License along with this program; if not, see:
18  * http://www.gnu.org/licenses</small>
19  */
20 
21 #ifndef WORLD_P_OBJECT_H
22 #define WORLD_P_OBJECT_H
23 
24 #if defined(__JDOOM__) || defined(__JHERETIC__) || defined(__JHEXEN__)
25 #  error Attempted to include internal Doomsday p_object.h from a game
26 #endif
27 
28 #include <de/aabox.h>
29 #include <de/Record>
30 #include <de/Vector>
31 #include <doomsday/defs/ded.h>
32 #include <doomsday/world/thinker.h>
33 #include <doomsday/world/mobj.h>
34 
35 #include "world/bspleaf.h"
36 #include "api_map.h"
37 #include "dd_def.h"
38 #ifdef __CLIENT__
39 #  include "resource/framemodeldef.h"
40 #endif
41 
42 namespace world {
43 class Subsector;
44 }
45 class Plane;
46 
47 #define MOBJ_SIZE               gx.GetInteger(DD_MOBJ_SIZE)
48 
49 class MobjThinker : public ThinkerT<mobj_t>
50 {
51 public:
ThinkerT(MOBJ_SIZE,alloc)52     MobjThinker(AllocMethod alloc = AllocateStandard) : ThinkerT(MOBJ_SIZE, alloc) {}
MobjThinker(mobj_t const & existingToCopy)53     MobjThinker(mobj_t const &existingToCopy) : ThinkerT(existingToCopy, MOBJ_SIZE) {}
MobjThinker(mobj_t * existingToTake)54     MobjThinker(mobj_t *existingToTake) : ThinkerT(existingToTake, MOBJ_SIZE) {}
55 
zap(mobj_t & mob)56     static void zap(mobj_t &mob) { ThinkerT::zap(mob, MOBJ_SIZE); }
57 };
58 
59 #define DEFAULT_FRICTION        FIX2FLT(0xe800)
60 #define NOMOMENTUM_THRESHOLD    (0.0001)
61 
62 #define IS_BLOCK_LINKED(mo)     ((mo)->bNext != 0)
63 
64 DENG_EXTERN_C de::dint useSRVO, useSRVOAngle;
65 
66 void P_InitUnusedMobjList();
67 
68 /**
69  * To be called to register the commands and variables of this module.
70  */
71 void Mobj_ConsoleRegister();
72 
73 mobj_t *P_MobjCreate(thinkfunc_t function, de::Vector3d const &origin, angle_t angle,
74     coord_t radius, coord_t height, de::dint ddflags);
75 
76 void P_MobjRecycle(mobj_t *mob);
77 
78 /**
79  * Returns the map in which the map-object exists. Note that a map-object may exist in a
80  * map while not being @em linked into data structures such as the blockmap and sectors.
81  * To determine whether the map-object is linked, call @ref Mobj_IsLinked().
82  *
83  * @see Thinker_Map()
84  */
85 world::Map &Mobj_Map(mobj_t const &mob);
86 
87 /**
88  * Returns @c true if the map-object has been linked into the map. The only time this is
89  * not true is if @ref Mobj_SetOrigin() has not yet been called.
90  *
91  * @param mob  Map-object.
92  *
93  * @todo Automatically link all new mobjs into the map (making this redundant).
94  */
95 bool Mobj_IsLinked(mobj_t const &mob);
96 
97 /**
98  * Returns a copy of the map-object's origin in map space.
99  */
100 de::Vector3d Mobj_Origin(mobj_t const &mob);
101 
102 /**
103  * Returns the map-object's visual center (i.e., origin plus z-height offset).
104  */
105 de::Vector3d Mobj_Center(mobj_t &mob);
106 
107 /**
108  * Set the origin of the map-object in map space.
109  *
110  * @return  @c true if successful, @c false otherwise. The object's position is not changed
111  *          if the move fails.
112  *
113  * @note Internal to the engine.
114  */
115 dd_bool Mobj_SetOrigin(mobj_t *mob, coord_t x, coord_t y, coord_t z);
116 
117 /**
118  * Returns the map BSP leaf at the origin of the map-object. Note that the mobj must be
119  * linked in the map (i.e., @ref Mobj_SetOrigin() has been called).
120  *
121  * @param mob  Map-object.
122  *
123  * @see Mobj_IsLinked(), Mobj_SetOrigin()
124  */
125 world::BspLeaf &Mobj_BspLeafAtOrigin(mobj_t const &mob);
126 
127 /**
128  * Returns @c true if the BSP leaf at the map-object's origin is known (i.e., it has been
129  * linked into the map by calling @ref Mobj_SetOrigin() and has a convex geometry).
130  *
131  * @param mob  Map-object.
132  */
133 bool Mobj_HasSubsector(mobj_t const &mob);
134 
135 /**
136  * Returns the subsector in which the map-object currently resides.
137  *
138  * @param mob  Map-object.
139  *
140  * @see Mobj_HasSubsector()
141  */
142 world::Subsector &Mobj_Subsector(mobj_t const &mob);
143 
144 /**
145  * Returns a pointer to subsector in which the mobj currently resides, or @c nullptr
146  * if not linked or the BSP leaf at the origin has no convex geometry.
147  *
148  * @param mob  Map-object.
149  *
150  * @see Mobj_HasSubsector()
151  */
152 world::Subsector *Mobj_SubsectorPtr(mobj_t const &mob);
153 
154 /**
155  * Creates a new map-object triggered particle generator based on the given definition.
156  * The generator is added to the list of active ptcgens.
157  */
158 void Mobj_SpawnParticleGen(mobj_t *source, ded_ptcgen_t const *def);
159 
160 #ifdef __CLIENT__
161 
162 /**
163  * Determines whether the Z origin of the mobj lies above the visual ceiling, or below the
164  * visual floor plane of the BSP leaf at the origin. This can be used to determine whether
165  * this origin should be adjusted with respect to smoothed plane movement.
166  */
167 dd_bool Mobj_OriginBehindVisPlane(mobj_t *mob);
168 
169 /**
170  * To be called when Lumobjs are disabled to perform necessary bookkeeping.
171  */
172 void Mobj_UnlinkLumobjs(mobj_t *mob);
173 
174 /**
175  * Generates Lumobjs for the map-object.
176  * @note: This is called each frame for each luminous object!
177  */
178 void Mobj_GenerateLumobjs(mobj_t *mob);
179 
180 void Mobj_AnimateHaloOcclussion(mobj_t &mob);
181 
182 /**
183  * Calculate the strength of the shadow this map-object should cast.
184  *
185  * @note Implemented using a greatly simplified version of the lighting equation;
186  *       no light diminishing or light range compression.
187  */
188 de::dfloat Mobj_ShadowStrength(mobj_t const &mob);
189 
190 /**
191  * Determines which of the available sprites is in effect for the current map-object state
192  * and frame. May return @c nullptr if the state and/or frame is not valid.
193  */
194 de::Record const *Mobj_SpritePtr(mobj_t const &mob);
195 
196 /**
197  * Determines which of the available model definitions (if any), are in effect for the
198  * current map-object state and frame. (Interlinks are resolved).
199  *
200  * @param nextModef  If non-zero the model definition for the @em next frame is written here.
201  * @param interp     If non-zero and both model definitions are found the current interpolation
202  *                   point between the two is written here.
203  *
204  * @return  Active model definition for the current frame (if any).
205  */
206 FrameModelDef *Mobj_ModelDef(mobj_t const &mob, FrameModelDef **nextModef = nullptr,
207                         de::dfloat *interp = nullptr);
208 
209 /**
210  * Calculates the shadow radius of the map-object. Falls back to Mobj_VisualRadius().
211  *
212  * @param mob  Map-object.
213  *
214  * @return Radius for shadow.
215  */
216 coord_t Mobj_ShadowRadius(mobj_t const &mob);
217 
218 #endif // __CLIENT__
219 
220 coord_t Mobj_ApproxPointDistance(mobj_t const *mob, coord_t const *point);
221 
222 /**
223  * Returns @c true if the map-object is physically inside (and @em presently linked to)
224  * some Sector of the owning Map.
225  */
226 bool Mobj_IsSectorLinked(mobj_t const &mob);
227 
228 /**
229  * Returns the current "float bob" offset (if enabled); otherwise @c 0.
230  */
231 coord_t Mobj_BobOffset(mobj_t const &mob);
232 
233 de::dfloat Mobj_Alpha(mobj_t const &mob);
234 
235 /**
236  * Returns the physical radius of the mobj.
237  *
238  * @param mob  Map-object.
239  *
240  * @see Mobj_VisualRadius()
241  */
242 coord_t Mobj_Radius(mobj_t const &mob);
243 
244 /**
245  * Returns the radius of the mobj as it would visually appear to be, according
246  * to the current visualization (either a sprite or a 3D model).
247  *
248  * @param mob  Map-object.
249  *
250  * @see Mobj_Radius()
251  */
252 coord_t Mobj_VisualRadius(mobj_t const &mob);
253 
254 /**
255  * Returns an axis-aligned bounding box for the mobj in map space, centered
256  * on the origin with dimensions equal to @code radius * 2 @endcode.
257  *
258  * @param mob  Map-object.
259  *
260  * @see Mobj_Radius()
261  */
262 AABoxd Mobj_Bounds(mobj_t const &mob);
263 
264 #endif  // WORLD_P_OBJECT_H
265