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