OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4GameObjects.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 // game object lists
18 
19 #include "C4Include.h"
20 #include "object/C4GameObjects.h"
21 
22 #include "script/C4Effect.h"
23 #include "object/C4Def.h"
24 #include "object/C4Object.h"
25 #include "object/C4ObjectCom.h"
26 #include "game/C4Physics.h"
27 #include "lib/C4Random.h"
29 #include "game/C4Game.h"
30 #include "lib/C4Log.h"
31 #include "player/C4PlayerList.h"
32 #include "control/C4Record.h"
33 
35 {
36  Default();
37 }
38 
40 {
41  Sectors.Clear();
42 }
43 
45 {
46  Sectors.Clear();
47  LastUsedMarker = 0;
49 }
50 
51 void C4GameObjects::Init(int32_t iWidth, int32_t iHeight)
52 {
53  // init sectors
54  Sectors.Init(iWidth, iHeight);
55 }
56 
58 {
59  // add inactive objects to the inactive list only
60  if (nObj->Status == C4OS_INACTIVE)
62  // if this is a foreground object, add it to the list
63  if (nObj->Category & C4D_Foreground)
65  // manipulate main list
67  return false;
68  // add to sectors
69  Sectors.Add(nObj, this);
70  return true;
71 }
72 
73 
75 {
76  // if it's an inactive object, simply remove from the inactiv elist
77  if (pObj->Status == C4OS_INACTIVE) return InactiveObjects.Remove(pObj);
78  // remove from sectors
79  Sectors.Remove(pObj);
80  // remove from forelist
81  ForeObjects.Remove(pObj);
82  // manipulate main list
83  return C4ObjectList::Remove(pObj);
84 }
85 
87 {
88  return Sectors.SectorAt(ix, iy)->ObjectShapes;
89 }
90 
91 void C4GameObjects::CrossCheck() // Every Tick1 by ExecObjects
92 {
93  DWORD focf,tocf;
94 
95  // Reverse area check: Checks for all obj2 at obj1
96 
97  focf = tocf = OCF_None;
98  // High level: Collection, Hit
99  if (!::Game.iTick3)
100  tocf |= OCF_Carryable;
101  focf |= OCF_Collection; focf |= OCF_Alive; tocf |= OCF_HitSpeed2;
102 
103  for (C4Object* obj1 : *this)
104  if (obj1->Status && !obj1->Contained && (obj1->OCF & focf))
105  {
106  uint32_t Marker = GetNextMarker();
107  C4LSector *pSct;
108  for (C4ObjectList *pLst = obj1->Area.FirstObjects(&pSct); pLst; pLst = obj1->Area.NextObjects(pLst, &pSct))
109  for (C4Object* obj2 : *pLst)
110  if ((obj2 != obj1) && obj2->Status && !obj2->Contained && (obj2->OCF & tocf) &&
111  Inside<int32_t>(obj2->GetX() - (obj1->GetX() + obj1->Shape.x), 0, obj1->Shape.Wdt - 1) &&
112  Inside<int32_t>(obj2->GetY() - (obj1->GetY() + obj1->Shape.y), 0, obj1->Shape.Hgt - 1) &&
113  obj1->Layer == obj2->Layer)
114  {
115  // handle collision only once
116  if (obj2->Marker == Marker) continue;
117  obj2->Marker = Marker;
118  // Only hit if target is alive and projectile is an object
119  if ((obj1->OCF & OCF_Alive) && (obj2->Category & C4D_Object))
120  {
121  C4Real dXDir = obj2->xdir - obj1->xdir, dYDir = obj2->ydir - obj1->ydir;
122  C4Real speed = dXDir * dXDir + dYDir * dYDir;
123  // Only hit if obj2's speed and relative speeds are larger than HitSpeed2
124  if ((obj2->OCF & OCF_HitSpeed2) && speed > HitSpeed2 &&
125  !obj1->Call(PSF_QueryCatchBlow, &C4AulParSet(obj2)))
126  {
127  int32_t iHitEnergy = fixtoi(speed * obj2->Mass / 5);
128  // Hit energy reduced to 1/3rd, but do not drop to zero because of this division
129  iHitEnergy = std::max<int32_t>(iHitEnergy/3, !!iHitEnergy);
130  obj1->DoEnergy(-iHitEnergy / 5, false, C4FxCall_EngObjHit, obj2->Controller);
131  int tmass = std::max<int32_t>(obj1->Mass, 50);
132  C4PropList* pActionDef = obj1->GetAction();
133  if (!::Game.iTick3 || (pActionDef && pActionDef->GetPropertyP(P_Procedure) != DFA_FLIGHT))
134  obj1->Fling(obj2->xdir * 50 / tmass, -Abs(obj2->ydir / 2) * 50 / tmass, false);
135  obj1->Call(PSF_CatchBlow, &C4AulParSet(-iHitEnergy / 5, obj2));
136  // obj1 might have been tampered with
137  if (!obj1->Status || obj1->Contained || !(obj1->OCF & focf))
138  goto out1;
139  continue;
140  }
141  }
142  // Collection
143  if ((obj1->OCF & OCF_Collection) && (obj2->OCF & OCF_Carryable) &&
144  Inside<int32_t>(obj2->GetX() - (obj1->GetX() + obj1->Def->Collection.x), 0, obj1->Def->Collection.Wdt - 1) &&
145  Inside<int32_t>(obj2->GetY() - (obj1->GetY() + obj1->Def->Collection.y), 0, obj1->Def->Collection.Hgt - 1))
146  {
147  obj1->Collect(obj2);
148  // obj1 might have been tampered with
149  if (!obj1->Status || obj1->Contained || !(obj1->OCF & focf))
150  goto out1;
151  }
152  }
153  out1: ;
154  }
155 }
156 
157 C4Object* C4GameObjects::AtObject(int ctx, int cty, DWORD &ocf, C4Object *exclude)
158 {
159  DWORD cocf;
160  for (C4Object *cObj : ObjectsAt(ctx,cty))
161  if (!exclude || (cObj!=exclude && exclude->Layer == cObj->Layer)) if (cObj->Status)
162  {
163  cocf=ocf | OCF_Exclusive;
164  if (cObj->At(ctx,cty,cocf))
165  {
166  // Search match
167  if (cocf & ocf) { ocf=cocf; return cObj; }
168  // EXCLUSIVE block
169  else return nullptr;
170  }
171  }
172  return nullptr;
173 }
174 
176 {
177  // synchronize unsorted objects
178  ResortUnsorted();
179  // synchronize solidmasks
181 }
182 
184 {
185  // search own list
187  if (pObj) return pObj->GetObject();
188  return 0;
189 }
190 
192 {
193  C4Object *pObj = ObjectPointer(iNumber);
194  if (pObj) if (!pObj->Status) return nullptr;
195  return pObj;
196 }
197 
199 {
200  for (C4Object *obj : *this)
201  if (obj->Status)
202  obj->UpdateSolidMask(false);
203 }
204 
205 void C4GameObjects::DeleteObjects(bool fDeleteInactive)
206 {
209  ForeObjects.Clear();
210  if (fDeleteInactive) InactiveObjects.DeleteObjects();
211 }
212 
213 void C4GameObjects::Clear(bool fClearInactive)
214 {
215  DeleteObjects(fClearInactive);
216  if (fClearInactive)
218  LastUsedMarker = 0;
219 }
220 
221 int C4GameObjects::PostLoad(bool fKeepInactive, C4ValueNumbers * numbers)
222 {
223  // Process objects
224  int32_t iMaxObjectNumber = 0;
225  for (C4Object *pObj : reverse())
226  {
227  // keep track of numbers
228  iMaxObjectNumber = std::max(iMaxObjectNumber, pObj->Number);
229  // add to list of foreobjects
230  if (pObj->Category & C4D_Foreground)
231  ForeObjects.Add(pObj, C4ObjectList::stMain, this);
232  // Unterminate end
233  }
234 
235  // Denumerate pointers
236  // on section load, inactive object numbers will be adjusted afterwards
237  // so fake inactive object list empty meanwhile
238  // note this has to be done to prevent even if object numbers did not collide
239  // to prevent an assertion fail when denumerating non-enumerated inactive objects
240  C4ObjectList inactiveObjectsCopy;
241  if (fKeepInactive)
242  {
243  inactiveObjectsCopy.Copy(InactiveObjects);
245  }
246  // denumerate pointers
247  Denumerate(numbers);
248  // update object enumeration index now, because calls like OnSynchronized might create objects
249  C4PropListNumbered::SetEnumerationIndex(iMaxObjectNumber);
250  // end faking and adjust object numbers
251  if (fKeepInactive)
252  {
253  InactiveObjects.Copy(inactiveObjectsCopy);
254  inactiveObjectsCopy.Clear();
256  }
257 
258  // special checks:
259  // -contained/contents-consistency
260  // -StaticBack-objects zero speed
261  for (C4Object *pObj : *this)
262  if (pObj->Status)
263  {
264  // staticback must not have speed
265  if (pObj->Category & C4D_StaticBack)
266  {
267  pObj->xdir = pObj->ydir = 0;
268  }
269  // contained must be in contents list
270  if (pObj->Contained)
271  if (!pObj->Contained->Contents.GetLink(pObj))
272  {
273  DebugLogF("Error in Objects.txt: Container of #%d is #%d, but not found in contents list!", pObj->Number, pObj->Contained->Number);
275  }
276  // all contents must have contained set; otherwise, remove them!
277  auto contentsIt = pObj->Contents.begin();
278  while (!contentsIt.atEnd())
279  {
280  C4Object* pObj2 = *contentsIt;
281  // check double links
282  auto it2 = pObj->Contents.begin();
283  if (it2.find(pObj2) && it2 != contentsIt)
284  {
285  DebugLogF("Error in Objects.txt: Double containment of #%d by #%d!", pObj2->Number, pObj->Number);
286  // this remove-call will only remove the previous (dobuled) link, so cLnkCont should be save
287  pObj->Contents.Remove(pObj2);
288  // contents checked already
289  continue;
290  }
291  // check contents/contained-relation
292  if (pObj2->Status && pObj2->Contained != pObj)
293  {
294  DebugLogF("Error in Objects.txt: Object #%d not in container #%d as referenced!", pObj2->Number, pObj->Number);
295  pObj2->Contained = pObj;
296  }
297  contentsIt++;
298  }
299  }
300  // sort out inactive objects
301  for (C4Object *obj : *this)
302  {
303  if (obj->Status == C4OS_INACTIVE)
304  {
305  Remove(obj);
307  }
308  }
309 
310  {
311  C4DebugRecOff DBGRECOFF; // - script callbacks that would kill DebugRec-sync for runtime start
312  // update graphics
313  UpdateGraphics(false);
314  // Update faces
315  UpdateFaces(false);
316  // Update ocf
317  SetOCF();
318  }
319 
320  // make sure list is sorted by category - after sorting out inactives, because inactives aren't sorted into the main list
321  FixObjectOrder();
322 
323  // misc updates
324  for (C4Object *pObj : *this)
325  if (pObj->Status)
326  {
327  // add to plrview
328  pObj->UpdateLight();
329  // update flipdir (for old objects.txt with no flipdir defined)
330  // assigns Action.DrawDir as well
331  pObj->UpdateFlipDir();
332  // initial OCF update
333  pObj->SetOCF();
334  }
335  // Done
336  return ObjectCount();
337 }
338 
340 {
341  C4ObjectList::Denumerate(numbers);
342  InactiveObjects.Denumerate(numbers);
343 }
344 
346 {
347  // call in sublists
350 }
351 
352 C4Value C4GameObjects::GRBroadcast(const char *szFunction, C4AulParSet *pPars, bool fPassError, bool fRejectTest)
353 {
354  // call objects first - scenario script might overwrite hostility, etc...
355  for (C4Object *pObj : *this)
356  if (pObj && (pObj->Category & (C4D_Goal | C4D_Rule | C4D_Environment)) && pObj->Status)
357  {
358  C4Value vResult = pObj->Call(szFunction, pPars, fPassError);
359  // rejection tests abort on first nonzero result
360  if (fRejectTest && !!vResult) return vResult;
361  }
362  return C4Value();
363 }
364 
366 {
367  // Position might have changed. Update sector lists
368  Sectors.Update(pObj, this);
369 }
370 
372 {
373  // Object order for this object was changed. Readd object to sectors
374  Sectors.Remove(pObj);
375  Sectors.Add(pObj, this);
376 }
377 
379 {
380  // fixes the object order so it matches the global object order sorting constraints
381  C4ObjectLink *pLnk0=First, *pLnkL=Last;
382  while (pLnk0 != pLnkL)
383  {
384  C4ObjectLink *pLnk1stUnsorted=nullptr, *pLnkLastUnsorted=nullptr, *pLnkPrev=nullptr, *pLnk;
385  C4Object *pLastWarnObj = nullptr;
386  // forward fix
387  int lastPlane = 2147483647; //INT32_MAX;
388  for (pLnk = pLnk0; pLnk!=pLnkL->Next; pLnk=pLnk->Next)
389  {
390  C4Object *pObj = pLnk->Obj;
391  if (pObj->Unsorted || !pObj->Status) continue;
392  int currentPlane = pObj->GetPlane();
393  // must have nonzero Plane
394  if (!currentPlane)
395  {
396  DebugLogF("Objects.txt: Object #%d has zero Plane!", (int) pObj->Number);
397  pObj->SetPlane(lastPlane); currentPlane = lastPlane;
398  }
399  // fix order
400  if (currentPlane > lastPlane)
401  {
402  // SORT ERROR! (note that pLnkPrev can't be 0)
403  if (pLnkPrev->Obj != pLastWarnObj)
404  {
405  DebugLogF("Objects.txt: Wrong object order of #%d-#%d! (down)", (int) pObj->Number, (int) pLnkPrev->Obj->Number);
406  pLastWarnObj = pLnkPrev->Obj;
407  }
408  pLnk->Obj = pLnkPrev->Obj;
409  pLnkPrev->Obj = pObj;
410  pLnkLastUnsorted = pLnkPrev;
411  }
412  else
413  lastPlane = currentPlane;
414  pLnkPrev = pLnk;
415  }
416  if (!pLnkLastUnsorted) break; // done
417  pLnkL = pLnkLastUnsorted;
418  // backwards fix
419  lastPlane = -2147483647-1; //INT32_MIN;
420  for (pLnk = pLnkL; pLnk!=pLnk0->Prev; pLnk=pLnk->Prev)
421  {
422  C4Object *pObj = pLnk->Obj;
423  if (pObj->Unsorted || !pObj->Status) continue;
424  int currentPlane = pObj->GetPlane();
425  if (currentPlane < lastPlane)
426  {
427  // SORT ERROR! (note that pLnkPrev can't be 0)
428  if (pLnkPrev->Obj != pLastWarnObj)
429  {
430  DebugLogF("Objects.txt: Wrong object order of #%d-#%d! (up)", (int) pObj->Number, (int) pLnkPrev->Obj->Number);
431  pLastWarnObj = pLnkPrev->Obj;
432  }
433  pLnk->Obj = pLnkPrev->Obj;
434  pLnkPrev->Obj = pObj;
435  pLnk1stUnsorted = pLnkPrev;
436  }
437  else
438  lastPlane = currentPlane;
439  pLnkPrev = pLnk;
440  }
441  if (!pLnk1stUnsorted) break; // done
442  pLnk0 = pLnk1stUnsorted;
443  }
444  // objects fixed!
445 }
446 
448 {
449  for (C4Object *cObj : *this)
450  {
451  if (cObj->Unsorted)
452  {
453  // readd to main object list
454  Remove(cObj);
455  // reset flag so that Add correctly sorts this object
456  cObj->Unsorted=false;
457  if (!Add(cObj))
458  {
459  // readd failed: Better kill object to prevent leaking...
460  Game.ClearPointers(cObj);
461  delete cObj;
462  }
463  }
464  }
465 }
466 
468 {
469  // validate in sublists
470  bool fSucc = true;
471  if (!C4ObjectList::ValidateOwners()) fSucc = false;
472  if (!InactiveObjects.ValidateOwners()) fSucc = false;
473  return fSucc;
474 }
475 
477 {
478  // assign in sublists
479  bool fSucc = true;
480  if (!C4ObjectList::AssignInfo()) fSucc = false;
481  if (!InactiveObjects.AssignInfo()) fSucc = false;
482  return fSucc;
483 }
484 
486 {
487  for (C4Object *obj : reverse())
488  if (obj->Status)
489  obj->AssignLightRange();
490 }
491 
493 {
494  for (C4Object *obj : *this)
495  if (obj)
496  obj->SyncClearance();
497 }
498 
500 {
501  for (C4Object *obj : *this)
502  if (obj)
503  obj->Call(PSF_OnSynchronized);
504 }
505 
507 {
508  for (C4Object *obj : *this)
509  if (obj)
510  {
511  obj->Audible = obj->AudiblePan = 0;
512  obj->AudiblePlayer = NO_OWNER;
513  }
514 }
515 
517 {
518  for (C4Object *obj : *this)
519  if (obj->Status)
520  obj->SetOCF();
521 }
522 
524 {
525  // Get a new marker.
526  uint32_t marker = ++LastUsedMarker;
527  // If all markers are exceeded, restart marker at 1 and reset all object markers to zero.
528  if (!marker)
529  {
530  for (C4Object *cobj : *this)
531  {
532  if (cobj)
533  cobj->Marker = 0;
534  }
535  marker = ++LastUsedMarker;
536  }
537  return marker;
538 }
int32_t GetY() const
Definition: C4Object.h:287
C4LArea Area
Definition: C4Object.h:114
const uint32_t OCF_Alive
Definition: C4Constants.h:104
const int32_t C4D_Environment
Definition: C4Def.h:50
const uint32_t OCF_Collection
Definition: C4Constants.h:93
virtual bool Add(C4Object *nObj, SortType eSort, C4ObjectList *pLstSorted=nullptr)
bool Add(C4Object *nObj)
void UpdateFaces(bool bUpdateShape)
void UpdatePosResort(C4Object *pObj)
C4Game Game
Definition: C4Globals.cpp:52
#define PSF_CatchBlow
Definition: C4GameScript.h:72
int32_t Mass
Definition: C4Object.h:115
void Add(C4Object *pObj, C4ObjectList *pMainList)
Definition: C4Sector.cpp:93
void ResetAudibility()
C4Value GRBroadcast(const char *szFunction, C4AulParSet *pPars, bool fPassError, bool fRejectTest)
uint32_t Marker
Definition: C4Object.h:135
C4PropList * GetAction() const
Definition: C4Object.cpp:2689
C4LSector * SectorAt(int ix, int iy)
Definition: C4Sector.cpp:84
static C4PropList * GetByNumber(int32_t iNumber)
Definition: C4PropList.cpp:75
C4ObjectLink * First
Definition: C4ObjectList.h:51
static void SetEnumerationIndex(int32_t iMaxObjectNumber)
Definition: C4PropList.cpp:93
int32_t GetPlane() const
Definition: C4Object.h:180
void Copy(const C4ObjectList &rList)
const C4Real HitSpeed2
Definition: C4Movement.cpp:38
void DeleteObjects()
virtual bool ValidateOwners()
C4ObjectPtr Layer
Definition: C4Object.h:136
void Clear()
Definition: C4Sector.cpp:76
virtual C4Object * GetObject()
Definition: C4PropList.cpp:644
Definition: C4Real.h:58
C4ObjectList InactiveObjects
Definition: C4GameObjects.h:43
int32_t AudiblePlayer
Definition: C4Object.h:121
const C4ObjectLink * GetLink(const C4Object *pObj) const
int32_t Wdt
Definition: C4Rect.h:32
void SetPlane(int32_t z)
Definition: C4Object.h:179
const uint32_t OCF_HitSpeed2
Definition: C4Constants.h:91
const int32_t C4D_Object
Definition: C4Def.h:46
C4NotifyingObjectList Contents
Definition: C4Object.h:152
C4ObjectLink * Next
Definition: C4ObjectList.h:29
bool DebugLogF(const char *strMessage...)
Definition: C4Log.cpp:281
C4Def * Def
Definition: C4Object.h:143
void UpdateScriptPointers()
C4Object * AtObject(int ctx, int cty, DWORD &ocf, C4Object *exclude=nullptr)
int32_t y
Definition: C4Rect.h:32
void Init(int Wdt, int Hgt)
Definition: C4Sector.cpp:60
int32_t AudiblePan
Definition: C4Object.h:121
void UpdateFlipDir()
Definition: C4Object.cpp:444
void UpdateGraphics(bool fGraphicsChanged)
C4Rect Collection
Definition: C4Def.h:108
static void UnshelveNumberedPropLists()
Definition: C4PropList.cpp:123
void SyncClearance()
Definition: C4Object.cpp:2506
void Update(C4Object *pObj, C4ObjectList *pMainList)
Definition: C4Sector.cpp:111
int32_t GetX() const
Definition: C4Object.h:286
uint32_t GetNextMarker()
C4ObjectList * FirstObjects(C4LSector **ppSct)
Definition: C4Sector.h:118
const int NO_OWNER
Definition: C4Constants.h:138
int32_t iTick3
Definition: C4Game.h:131
int32_t Status
Definition: C4PropList.h:170
const int32_t C4D_StaticBack
Definition: C4Def.h:42
bool Collect(C4Object *pObj)
Definition: C4Object.cpp:4182
const int32_t C4D_Rule
Definition: C4Def.h:49
C4ObjectList ObjectShapes
Definition: C4Sector.h:49
C4ObjectLink * Prev
Definition: C4ObjectList.h:29
bool Unsorted
Definition: C4Object.h:129
const uint32_t OCF_Exclusive
Definition: C4Constants.h:89
virtual bool AssignInfo()
int32_t Category
Definition: C4Object.h:113
void Denumerate(C4ValueNumbers *)
const ReverseView reverse() const
Definition: C4ObjectList.h:104
C4LSectors Sectors
Definition: C4GameObjects.h:42
int32_t x
Definition: C4Rect.h:32
#define C4OS_INACTIVE
Definition: C4Object.h:36
int ObjectCount(C4ID id=C4ID::None) const
void ClearPointers(C4Object *cobj)
Definition: C4Game.cpp:925
iterator begin() const
#define PSF_OnSynchronized
Definition: C4GameScript.h:79
void ClearObjects()
Definition: C4Sector.cpp:227
C4ObjectList ForeObjects
Definition: C4GameObjects.h:44
C4Object * SafeObjectPointer(int32_t iNumber)
void DoEnergy(int32_t iChange, bool fExact, int32_t iCause, int32_t iCausedByPlr)
Definition: C4Object.cpp:1121
void UpdateLight()
Definition: C4Object.cpp:4043
void Denumerate(C4ValueNumbers *)
const uint32_t OCF_Carryable
Definition: C4Constants.h:82
#define PSF_QueryCatchBlow
Definition: C4GameScript.h:73
C4ObjectLink * Last
Definition: C4ObjectList.h:51
const int32_t C4D_Goal
Definition: C4Def.h:48
virtual void Default()
#define C4FxCall_EngObjHit
Definition: C4Effect.h:57
void UpdateScriptPointers()
void SetOCF()
Definition: C4Object.cpp:670
C4ObjectPtr Contained
Definition: C4Object.h:144
int32_t Hgt
Definition: C4Rect.h:32
T Abs(T val)
Definition: Standard.h:44
virtual void Clear()
void Init(int32_t iWidth, int32_t iHeight)
C4Shape Shape
Definition: C4Object.h:148
bool Remove(C4Object *pObj)
void AssignLightRange()
int32_t Audible
Definition: C4Object.h:121
uint32_t OCF
Definition: C4Object.h:134
int PostLoad(bool fKeepInactive, C4ValueNumbers *)
void Remove(C4Object *pObj)
Definition: C4Sector.cpp:153
C4Value Call(C4PropertyName k, C4AulParSet *pPars=0, bool fPassErrors=false)
Definition: C4PropList.h:112
void UpdateSolidMask(bool fRestoreAttachedObjects)
Definition: C4Object.cpp:4156
void Fling(C4Real txdir, C4Real tydir, bool fAddSpeed)
Definition: C4Object.cpp:1351
uint32_t DWORD
int fixtoi(const C4Fixed &x)
Definition: C4Real.h:259
C4Real xdir
Definition: C4Object.h:126
const uint32_t OCF_None
Definition: C4Constants.h:77
void UpdateSolidMasks()
C4Object * ObjectPointer(int32_t iNumber)
C4ObjectList * NextObjects(C4ObjectList *pPrev, C4LSector **ppSct)
Definition: C4Sector.cpp:305
C4Real ydir
Definition: C4Object.h:126
const int32_t C4D_Foreground
Definition: C4Def.h:55
virtual bool Remove(C4Object *pObj)
void UpdatePos(C4Object *pObj)
C4ObjectList & ObjectsAt(int ix, int iy)