OpenClonk
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 width, int32_t height)
50 {
51  // Init sectors
52  Sectors.Init(width, height);
53 }
54 
56 {
57  // Add inactive objects to the inactive list only
58  if (object->Status == C4OS_INACTIVE)
59  {
61  }
62  // If this is a foreground object, add it to the list
63  if (object->Category & C4D_Foreground)
64  {
66  }
67  // Manipulate main list
69  return false;
70  // Add to sectors
71  Sectors.Add(object, this);
72  return true;
73 }
74 
75 
77 {
78  // If it's an inactive object, simply remove it from the inactive list
79  if (object->Status == C4OS_INACTIVE)
80  {
81  return InactiveObjects.Remove(object);
82  }
83  // Remove from sectors
84  Sectors.Remove(object);
85  // Remove from forelist
86  ForeObjects.Remove(object);
87  // Manipulate main list
88  return C4ObjectList::Remove(object);
89 }
90 
91 void C4GameObjects::CrossCheck() // Every Tick1 by ExecObjects
92 {
93  // Reverse area check: Checks for all <ball> at <goal>
94  // Using a sports metaphor here, because that is easier to visualize when reading the code
95 
96  // Only those objects that have one of the required OCFs will be checked for collision/collection.
97  // This lets us filter the objects early, so that the loop does not get too large.
98  DWORD goal_required_ocf = OCF_None | OCF_Collection | OCF_Alive;
99 
100  // Only those objects that have one of the required OCFs can cause a collision/collection
101  DWORD ball_required_ocf = OCF_None | OCF_HitSpeed2;
102  // Fewer checks for collection
103  if (!::Game.iTick3)
104  {
105  ball_required_ocf |= OCF_Carryable;
106  }
107 
108  for (C4Object* goal : *this)
109  {
110  if (goal->Status && !goal->Contained && (goal->OCF & goal_required_ocf))
111  {
112  uint32_t Marker = GetNextMarker();
113  C4LSector *sector;
114  for (C4ObjectList *in_goal_area = goal->Area.FirstObjects(&sector); in_goal_area; in_goal_area = goal->Area.NextObjects(in_goal_area, &sector))
115  {
116  for (C4Object* ball : *in_goal_area)
117  {
118  if ((ball != goal) // Ball should not hit itself,
119  && ball->Status // it cannot hit if it was deleted,
120  && !ball->Contained // it cannot hit if it is contained,
121  && (ball->OCF & ball_required_ocf) // it must have either of the required OFCs,
122  && (goal->Layer == ball->Layer) // and must be in the correct layer
123  // TODO: Instead of a custom check, use C4Rect::Contains with the correct coordinates
124  && Inside<int32_t>(ball->GetX() - (goal->GetX() + goal->Shape.x), 0, goal->Shape.Wdt - 1)
125  && Inside<int32_t>(ball->GetY() - (goal->GetY() + goal->Shape.y), 0, goal->Shape.Hgt - 1))
126  {
127  // Handle cross check only once
128  if (ball->Marker == Marker)
129  {
130  continue;
131  }
132  ball->Marker = Marker;
133 
134  // Collision check
135 
136  // Note: the layer check was already done further above.
137 
138  if ((goal->OCF & OCF_Alive) // <goal> must be alive,
139  && (ball->OCF & OCF_HitSpeed2) // <ball> is fast enough (otherwise a fast <goal> will collide when passing a non-moving ball)
140  && (ball->Category & C4D_Object)) // <ball> is an object
141  {
142  C4Real relative_xdir = ball->xdir - goal->xdir;
143  C4Real relative_ydir = ball->ydir - goal->ydir;
144  C4Real hit_speed = relative_xdir * relative_xdir + relative_ydir * relative_ydir;
145  // Only hit if the relative speed is larger than HitSpeed2, and the <goal> does not prevent getting hit
146  if ((hit_speed > HitSpeed2) && !goal->Call(PSF_QueryCatchBlow, &C4AulParSet(ball)))
147  {
148  int32_t hit_energy = fixtoi(hit_speed * ball->Mass / 5);
149  // Hit energy reduced to 1/3rd, but do not drop to zero because of this division.
150  // However, if the hit energy is low because of either speed or <ball> mass, then
151  // having it stay 0 is OK.
152  if (hit_energy != 0)
153  {
154  hit_energy = std::max(hit_energy / 3, 1);
155  }
156  // Apply damage to the goal - not sure why this is divided by 5 yet again,
157  // and this time we allow it being reduced to 0...
158  int32_t damage = -hit_energy / 5;
159  goal->DoEnergy(damage, false, C4FxCall_EngObjHit, ball->Controller);
160  // Fling it around:
161  // light objects will be flung with full speed,
162  // heavier objects will be affected less
163  int min_mass = 50;
164  int goal_mass = std::max<int32_t>(goal->Mass, min_mass);
165  C4PropList* pActionDef = goal->GetAction();
166  if (!::Game.iTick3 || (pActionDef && pActionDef->GetPropertyP(P_Procedure) != DFA_FLIGHT))
167  {
168  goal->Fling(ball->xdir * min_mass / goal_mass, -Abs(ball->ydir / 2) * min_mass / goal_mass, false);
169  }
170  // Callback with the damage value
171  goal->Call(PSF_CatchBlow, &C4AulParSet(damage, ball));
172  // <goal> might have been tampered with
173  if (!goal->Status || goal->Contained || !(goal->OCF & goal_required_ocf))
174  {
175  goto check_next_goal;
176  }
177  // Skip collection check
178  continue;
179  }
180  }
181 
182  // Collection check
183 
184  // Note: the layer check was already done further above.
185  // This is confusing, because this requires
186  // the ball to be both inside the goal shape AND the goal collection area, so
187  // collection areas that go further than the goal shape are useless, as well
188  // as collection areas that are entirely outside of the goal shape.
189 
190  if ((goal->OCF & OCF_Collection) // <goal> has a collection area?
191  && (ball->OCF & OCF_Carryable) // <ball> can be collected?
192  // TODO: Instead of a custom check, use C4Rect::Contains with the correct coordinates
193  && Inside<int32_t>(ball->GetX() - (goal->GetX() + goal->Def->Collection.x), 0, goal->Def->Collection.Wdt - 1)
194  && Inside<int32_t>(ball->GetY() - (goal->GetY() + goal->Def->Collection.y), 0, goal->Def->Collection.Hgt - 1))
195  {
196  goal->Collect(ball);
197  // <goal> might have been tampered with
198  if (!goal->Status || goal->Contained || !(goal->OCF & goal_required_ocf))
199  {
200  goto check_next_goal;
201  }
202  }
203  }
204  }
205  }
206  // Goto-marker for more obvious loop-control
207  check_next_goal: ;
208  }
209  }
210 }
211 
213 {
214  // Synchronize unsorted objects
215  ResortUnsorted();
216  // Synchronize solidmasks
218 }
219 
220 C4Object *C4GameObjects::ObjectPointer(int32_t object_number)
221 {
222  // Search own list
223  C4PropList *object = C4PropListNumbered::GetByNumber(object_number);
224  if (object)
225  {
226  return object->GetObject();
227  }
228  return nullptr;
229 }
230 
232 {
233  C4Object *object = ObjectPointer(object_number);
234  if (object && !object->Status)
235  {
236  return nullptr;
237  }
238  return object;
239 }
240 
242 {
243  for (C4Object *object : *this)
244  {
245  if (object->Status)
246  {
247  object->UpdateSolidMask(false);
248  }
249  }
250 }
251 
252 void C4GameObjects::DeleteObjects(bool delete_inactive_objects)
253 {
256  ForeObjects.Clear();
257  if (delete_inactive_objects)
258  {
260  }
261 }
262 
263 void C4GameObjects::Clear(bool clear_inactive_objects)
264 {
265  DeleteObjects(clear_inactive_objects);
266  if (clear_inactive_objects)
267  {
269  }
270  LastUsedMarker = 0;
271 }
272 
273 int C4GameObjects::PostLoad(bool keep_inactive_objects, C4ValueNumbers *numbers)
274 {
275  // Process objects
276  int32_t max_object_number = 0;
277  for (C4Object *object : reverse())
278  {
279  // Keep track of numbers
280  max_object_number = std::max(max_object_number, object->Number);
281  // Add to list of foreobjects
282  if (object->Category & C4D_Foreground)
283  {
284  ForeObjects.Add(object, C4ObjectList::stMain, this);
285  }
286  // Unterminate end
287  }
288 
289  // Denumerate pointers:
290  // On section load, inactive object numbers will be adjusted afterwards,
291  // so fake inactive object list empty meanwhile.
292  // Note: this has to be done to prevent an assertion fail when denumerating
293  // non-enumerated inactive objects, even if object numbers did not collide.
294  C4ObjectList inactiveObjectsCopy;
295  if (keep_inactive_objects)
296  {
297  inactiveObjectsCopy.Copy(InactiveObjects);
299  }
300  // Denumerate pointers
301  Denumerate(numbers);
302  // Update object enumeration index now, because calls like OnSynchronized might create objects
303  C4PropListNumbered::SetEnumerationIndex(max_object_number);
304  // end faking and adjust object numbers
305  if (keep_inactive_objects)
306  {
307  InactiveObjects.Copy(inactiveObjectsCopy);
308  inactiveObjectsCopy.Clear();
310  }
311 
312  // Special checks:
313  // -contained/contents-consistency
314  // -StaticBack-objects zero speed
315  for (C4Object *object : *this)
316  {
317  if (object->Status)
318  {
319  // Staticback must not have speed
320  if (object->Category & C4D_StaticBack)
321  {
322  object->xdir = object->ydir = 0;
323  }
324  // contained must be in contents list
325  if (object->Contained)
326  {
327  if (!object->Contained->Contents.GetLink(object))
328  {
329  DebugLogF("Error in Objects.txt: Container of #%d is #%d, but not found in contents list!", object->Number, object->Contained->Number);
330  object->Contained->Contents.Add(object, C4ObjectList::stContents);
331  }
332  }
333  // All contents must have contained set; otherwise, remove them!
334  auto contents_iterator = object->Contents.begin();
335  while (!contents_iterator.atEnd())
336  {
337  C4Object* contained_object = *contents_iterator;
338  // Check double links
339  auto contents_iterator2 = object->Contents.begin();
340  if (contents_iterator2.find(contained_object) && contents_iterator2 != contents_iterator)
341  {
342  DebugLogF("Error in Objects.txt: Double containment of #%d by #%d!", contained_object->Number, object->Number);
343  // This remove-call will only remove the previous (doubled) link, so cLnkCont should be save
344  object->Contents.Remove(contained_object);
345  // Contents checked already
346  continue;
347  }
348  // Check contents/contained-relation
349  if (contained_object->Status && contained_object->Contained != object)
350  {
351  DebugLogF("Error in Objects.txt: Object #%d not in container #%d as referenced!", contained_object->Number, object->Number);
352  contained_object->Contained = object;
353  }
354  contents_iterator++;
355  }
356  }
357  }
358  // Sort out inactive objects
359  for (C4Object *object : *this)
360  {
361  if (object->Status == C4OS_INACTIVE)
362  {
363  Remove(object);
365  }
366  }
367 
368  {
369  C4DebugRecOff DBGRECOFF; // - script callbacks that would kill DebugRec-sync for runtime start
370  // Update graphics
371  UpdateGraphics(false);
372  // Update faces
373  UpdateFaces(false);
374  // Update ocf
375  SetOCF();
376  }
377 
378  // Make sure list is sorted by category - after sorting out inactives, because inactives aren't sorted into the main list
379  FixObjectOrder();
380 
381  // Misc updates
382  for (C4Object *object : *this)
383  {
384  if (object->Status)
385  {
386  // Add to plrview
387  object->UpdateLight();
388  // Update flipdir (for old objects.txt with no flipdir defined),
389  // assigns Action.DrawDir as well
390  object->UpdateFlipDir();
391  // Initial OCF update
392  object->SetOCF();
393  }
394  }
395  // Done
396  return ObjectCount();
397 }
398 
400 {
401  C4ObjectList::Denumerate(numbers);
402  InactiveObjects.Denumerate(numbers);
403 }
404 
406 {
407  // Call in sublists
410 }
411 
412 C4Value C4GameObjects::GRBroadcast(const char *function_name, C4AulParSet *parameters, bool pass_error, bool reject_test)
413 {
414  // Call objects first - scenario script might overwrite hostility, etc...
415  for (C4Object *object : *this)
416  {
417  if (object && (object->Category & (C4D_Goal | C4D_Rule | C4D_Environment)) && object->Status)
418  {
419  C4Value vResult = object->Call(function_name, parameters, pass_error);
420  // Rejection tests abort on first nonzero result
421  if (reject_test && !!vResult)
422  {
423  return vResult;
424  }
425  }
426  }
427  return C4Value();
428 }
429 
431 {
432  // Position might have changed. Update sector lists
433  Sectors.Update(object, this);
434 }
435 
437 {
438  // Object order for this object was changed. Readd object to sectors
439  Sectors.Remove(object);
440  Sectors.Add(object, this);
441 }
442 
444 {
445  // Fixes the object order so it matches the global object order sorting constraints
446  C4ObjectLink *pLnk0 = First;
447  C4ObjectLink *pLnkL = Last;
448  while (pLnk0 != pLnkL)
449  {
450  C4ObjectLink *pLnk1stUnsorted = nullptr;
451  C4ObjectLink *pLnkLastUnsorted = nullptr;
452  C4ObjectLink *pLnkPrev = nullptr;
453  C4ObjectLink *pLnk;
454  C4Object *pLastWarnObj = nullptr;
455  // Forward fix
456  int lastPlane = 2147483647; //INT32_MAX;
457  for (pLnk = pLnk0; pLnk != pLnkL->Next; pLnk = pLnk->Next)
458  {
459  C4Object *pObj = pLnk->Obj;
460  if (pObj->Unsorted || !pObj->Status)
461  {
462  continue;
463  }
464  int currentPlane = pObj->GetPlane();
465  // Must have nonzero Plane
466  if (!currentPlane)
467  {
468  DebugLogF("Objects.txt: Object #%d has zero Plane!", (int) pObj->Number);
469  pObj->SetPlane(lastPlane); currentPlane = lastPlane;
470  }
471  // Fix order
472  if (currentPlane > lastPlane)
473  {
474  // SORT ERROR! (note that pLnkPrev can't be 0)
475  if (pLnkPrev->Obj != pLastWarnObj)
476  {
477  DebugLogF("Objects.txt: Wrong object order of #%d-#%d! (down)", (int) pObj->Number, (int) pLnkPrev->Obj->Number);
478  pLastWarnObj = pLnkPrev->Obj;
479  }
480  pLnk->Obj = pLnkPrev->Obj;
481  pLnkPrev->Obj = pObj;
482  pLnkLastUnsorted = pLnkPrev;
483  }
484  else
485  {
486  lastPlane = currentPlane;
487  }
488  pLnkPrev = pLnk;
489  }
490  if (!pLnkLastUnsorted)
491  {
492  break; // Done
493  }
494  pLnkL = pLnkLastUnsorted;
495  // Backwards fix
496  lastPlane = -2147483647-1; //INT32_MIN;
497  for (pLnk = pLnkL; pLnk != pLnk0->Prev; pLnk = pLnk->Prev)
498  {
499  C4Object *pObj = pLnk->Obj;
500  if (pObj->Unsorted || !pObj->Status)
501  {
502  continue;
503  }
504  int currentPlane = pObj->GetPlane();
505  if (currentPlane < lastPlane)
506  {
507  // SORT ERROR! (note that pLnkPrev can't be 0)
508  if (pLnkPrev->Obj != pLastWarnObj)
509  {
510  DebugLogF("Objects.txt: Wrong object order of #%d-#%d! (up)", (int) pObj->Number, (int) pLnkPrev->Obj->Number);
511  pLastWarnObj = pLnkPrev->Obj;
512  }
513  pLnk->Obj = pLnkPrev->Obj;
514  pLnkPrev->Obj = pObj;
515  pLnk1stUnsorted = pLnkPrev;
516  }
517  else
518  {
519  lastPlane = currentPlane;
520  }
521  pLnkPrev = pLnk;
522  }
523  if (!pLnk1stUnsorted)
524  {
525  break; // Done
526  }
527  pLnk0 = pLnk1stUnsorted;
528  }
529  // Objects fixed!
530 }
531 
533 {
534  for (C4Object *object : *this)
535  {
536  if (object->Unsorted)
537  {
538  // Readd to main object list
539  Remove(object);
540  // Reset flag so that Add correctly sorts this object
541  object->Unsorted = false;
542  if (!Add(object))
543  {
544  // readd failed: Better kill object to prevent leaking...
545  Game.ClearPointers(object);
546  delete object;
547  }
548  }
549  }
550 }
551 
553 {
554  // Validate in sublists
555  // Note: Both functions need to be called,
556  // before the evaluation. Do not call foo() && bar()
557  // because then only foo() will be evaluated.
558  bool object_list_valid = C4ObjectList::ValidateOwners();
559  bool inactive_objects_valid = InactiveObjects.ValidateOwners();
560  return object_list_valid && inactive_objects_valid;
561 }
562 
564 {
565  // Assign in sublists
566  // Note: Both functions need to be called,
567  // before the evaluation. Do not call foo() && bar()
568  // because then only foo() will be evaluated.
569  bool object_list_assigned = C4ObjectList::AssignInfo();
570  bool inactive_objects_assigned = InactiveObjects.AssignInfo();
571  return object_list_assigned && inactive_objects_assigned;
572 }
573 
575 {
576  for (C4Object *object : reverse())
577  {
578  if (object->Status)
579  {
580  object->AssignLightRange();
581  }
582  }
583 }
584 
586 {
587  for (C4Object *object : *this)
588  {
589  if (object)
590  {
591  object->SyncClearance();
592  }
593  }
594 }
595 
597 {
598  for (C4Object *object : *this)
599  {
600  if (object)
601  {
602  object->Call(PSF_OnSynchronized);
603  }
604  }
605 }
606 
608 {
609  for (C4Object *object : *this)
610  {
611  if (object)
612  {
613  object->Audible = object->AudiblePan = 0;
614  object->AudiblePlayer = NO_OWNER;
615  }
616  }
617 }
618 
620 {
621  for (C4Object *object : *this)
622  {
623  if (object->Status)
624  {
625  object->SetOCF();
626  }
627  }
628 }
629 
631 {
632  // Get a new marker.
633  uint32_t marker = ++LastUsedMarker;
634  // If all markers are exceeded, restart marker at 1 and reset all object markers to zero.
635  if (!marker)
636  {
637  for (C4Object *object : *this)
638  {
639  if (object)
640  {
641  object->Marker = 0;
642  }
643  }
644  marker = ++LastUsedMarker;
645  }
646  return marker;
647 }
const uint32_t OCF_Carryable
Definition: C4Constants.h:82
const uint32_t OCF_Collection
Definition: C4Constants.h:93
const uint32_t OCF_Alive
Definition: C4Constants.h:103
const uint32_t OCF_None
Definition: C4Constants.h:77
const uint32_t OCF_HitSpeed2
Definition: C4Constants.h:91
const int NO_OWNER
Definition: C4Constants.h:137
const int32_t C4D_Goal
Definition: C4Def.h:46
const int32_t C4D_Foreground
Definition: C4Def.h:53
const int32_t C4D_Rule
Definition: C4Def.h:47
const int32_t C4D_StaticBack
Definition: C4Def.h:40
const int32_t C4D_Object
Definition: C4Def.h:44
const int32_t C4D_Environment
Definition: C4Def.h:48
#define C4FxCall_EngObjHit
Definition: C4Effect.h:57
#define PSF_CatchBlow
Definition: C4GameScript.h:72
#define PSF_OnSynchronized
Definition: C4GameScript.h:79
#define PSF_QueryCatchBlow
Definition: C4GameScript.h:73
C4Game Game
Definition: C4Globals.cpp:52
bool DebugLogF(const char *strMessage ...)
Definition: C4Log.cpp:290
#define C4OS_INACTIVE
Definition: C4Object.h:36
C4ObjectLink * Prev
Definition: C4ObjectList.h:29
C4ObjectLink * Next
Definition: C4ObjectList.h:29
C4Object * Obj
Definition: C4ObjectList.h:28
const C4Real HitSpeed2
Definition: C4Physics.h:29
int fixtoi(const C4Fixed &x)
Definition: C4Real.h:259
@ DFA_FLIGHT
@ P_Procedure
uint32_t DWORD
T Abs(T val)
Definition: Standard.h:42
C4Rect Collection
Definition: C4Def.h:106
Definition: C4Real.h:59
int32_t iTick3
Definition: C4Game.h:130
void ClearPointers(C4Object *obj)
Definition: C4Game.cpp:1125
void Init(int32_t width, int32_t height)
bool Remove(C4Object *game_object) override
void Default() override
C4Object * ObjectPointer(int32_t object_number)
uint32_t GetNextMarker()
void AssignLightRange()
void UpdatePos(C4Object *game_object)
C4Value GRBroadcast(const char *function_name, C4AulParSet *parameters, bool pass_error, bool reject_test)
virtual bool Add(C4Object *new_obj, SortType sort_type, C4ObjectList *sorted_list=nullptr)
void UpdateScriptPointers()
C4ObjectList ForeObjects
Definition: C4GameObjects.h:44
C4LSectors Sectors
Definition: C4GameObjects.h:42
void Clear() override
Definition: C4GameObjects.h:36
C4Object * SafeObjectPointer(int32_t object_number)
bool ValidateOwners() override
C4ObjectList InactiveObjects
Definition: C4GameObjects.h:43
void Denumerate(C4ValueNumbers *)
bool AssignInfo() override
int PostLoad(bool keep_inactive_objects, C4ValueNumbers *)
void UpdatePosResort(C4Object *game_object)
void UpdateSolidMasks()
~C4GameObjects() override
void ResetAudibility()
C4ObjectList * NextObjects(C4ObjectList *pPrev, C4LSector **ppSct)
Definition: C4Sector.cpp:303
C4ObjectList * FirstObjects(C4LSector **ppSct)
Definition: C4Sector.h:118
void Update(C4Object *pObj, C4ObjectList *pMainList)
Definition: C4Sector.cpp:109
void Clear()
Definition: C4Sector.cpp:74
void Add(C4Object *pObj, C4ObjectList *pMainList)
Definition: C4Sector.cpp:91
void Init(int Wdt, int Hgt)
Definition: C4Sector.cpp:58
void Remove(C4Object *pObj)
Definition: C4Sector.cpp:151
void ClearObjects()
Definition: C4Sector.cpp:225
C4Real ydir
Definition: C4Object.h:124
C4PropList * GetAction() const
C4Real xdir
Definition: C4Object.h:124
void SetPlane(int32_t z)
Definition: C4Object.h:178
int32_t GetX() const
Definition: C4Object.h:285
int32_t Category
Definition: C4Object.h:111
uint32_t OCF
Definition: C4Object.h:132
void Fling(C4Real txdir, C4Real tydir, bool fAddSpeed)
C4ObjectPtr Layer
Definition: C4Object.h:134
int32_t GetY() const
Definition: C4Object.h:286
bool Unsorted
Definition: C4Object.h:127
bool Collect(C4Object *pObj)
C4NotifyingObjectList Contents
Definition: C4Object.h:151
int32_t GetPlane() const
Definition: C4Object.h:179
C4ObjectPtr Contained
Definition: C4Object.h:142
int32_t Mass
Definition: C4Object.h:113
C4Def * Def
Definition: C4Object.h:141
C4LArea Area
Definition: C4Object.h:112
C4Shape Shape
Definition: C4Object.h:146
void DoEnergy(int32_t iChange, bool fExact, int32_t iCause, int32_t iCausedByPlr)
Definition: C4Object.cpp:585
virtual void Clear()
void UpdateFaces(bool update_shape)
void UpdateGraphics(bool graphics_changed)
void UpdateScriptPointers()
virtual void Default()
C4ObjectLink * First
Definition: C4ObjectList.h:51
virtual bool AssignInfo()
void Copy(const C4ObjectList &list)
iterator begin() const
const C4ObjectLink * GetLink(const C4Object *obj) const
virtual bool Add(C4Object *new_obj, SortType sort_type, C4ObjectList *sorted_list=nullptr)
virtual bool ValidateOwners()
C4ObjectLink * Last
Definition: C4ObjectList.h:51
const ReverseView reverse() const
Definition: C4ObjectList.h:104
virtual bool Remove(C4Object *obj)
int ObjectCount(C4ID id=C4ID::None) const
void DeleteObjects()
void Denumerate(C4ValueNumbers *)
int32_t Status
Definition: C4PropList.h:173
C4PropertyName GetPropertyP(C4PropertyName k) const
Definition: C4PropList.cpp:824
C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
Definition: C4PropList.h:114
static void UnshelveNumberedPropLists()
Definition: C4PropList.cpp:99
static void SetEnumerationIndex(int32_t iMaxObjectNumber)
Definition: C4PropList.cpp:69
static C4PropList * GetByNumber(int32_t iNumber)
Definition: C4PropList.cpp:51
int32_t y
Definition: C4Rect.h:30
int32_t Hgt
Definition: C4Rect.h:30
int32_t Wdt
Definition: C4Rect.h:30
int32_t x
Definition: C4Rect.h:30