OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4Movement.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 
18 /* Object motion, collision, friction */
19 
20 #include "C4Include.h"
21 
22 #include "game/C4Physics.h"
23 #include "landscape/C4Landscape.h"
24 #include "landscape/C4SolidMask.h"
25 #include "object/C4Def.h"
26 #include "object/C4Object.h"
27 #include "script/C4Effect.h"
28 
29 /* Some physical constants */
30 
33 const C4Real FixFullCircle=itofix(360),FixHalfCircle=FixFullCircle/2;
36 const C4Real HitSpeed1=C4REAL100(150); // Hit Event
37 const C4Real HitSpeed2=itofix(2); // Cross Check Hit
38 const C4Real HitSpeed3=itofix(6); // Scale disable, kneel
39 const C4Real HitSpeed4=itofix(8); // Flat
41 
42 /* Some helper functions */
43 
44 void RedirectForce(C4Real &from, C4Real &to, int32_t tdir)
45 {
46  C4Real fred;
47  fred=std::min(Abs(from), FRedirect);
48  from-=fred*Sign(from);
49  to+=fred*tdir;
50 }
51 
52 void ApplyFriction(C4Real &tval, int32_t percent)
53 {
54  C4Real ffric=FFriction*percent/100;
55  if (tval>+ffric) { tval-=ffric; return; }
56  if (tval<-ffric) { tval+=ffric; return; }
57  tval=0;
58 }
59 
60 // Compares all Shape.VtxContactCNAT[] CNAT flags to search flag.
61 // Returns true if CNAT match has been found.
62 
63 bool ContactVtxCNAT(C4Object *cobj, BYTE cnat_dir)
64 {
65  int32_t cnt;
66  bool fcontact=false;
67  for (cnt=0; cnt<cobj->Shape.VtxNum; cnt++)
68  if (cobj->Shape.VtxContactCNAT[cnt] & cnat_dir)
69  fcontact=true;
70  return fcontact;
71 }
72 
73 // Finds first vertex with contact flag set.
74 // Returns -1/0/+1 for relation on vertex to object center.
75 
76 int32_t ContactVtxWeight(C4Object *cobj)
77 {
78  int32_t cnt;
79  for (cnt=0; cnt<cobj->Shape.VtxNum; cnt++)
80  if (cobj->Shape.VtxContactCNAT[cnt])
81  {
82  if (cobj->Shape.VtxX[cnt]<0) return -1;
83  if (cobj->Shape.VtxX[cnt]>0) return +1;
84  }
85  return 0;
86 }
87 
88 // ContactVtxFriction: Returns 0-100 friction value of first
89 // contacted vertex;
90 
92 {
93  int32_t cnt;
94  for (cnt=0; cnt<cobj->Shape.VtxNum; cnt++)
95  if (cobj->Shape.VtxContactCNAT[cnt])
96  return cobj->Shape.VtxFriction[cnt];
97  return 0;
98 }
99 
100 const char *CNATName(int32_t cnat)
101 {
102  switch (cnat)
103  {
104  case CNAT_None: return "None";
105  case CNAT_Left: return "Left";
106  case CNAT_Right: return "Right";
107  case CNAT_Top: return "Top";
108  case CNAT_Bottom: return "Bottom";
109  case CNAT_Center: return "Center";
110  }
111  return "Undefined";
112 }
113 
114 bool C4Object::Contact(int32_t iCNAT)
115 {
117  {
118  return !! Call(FormatString(PSF_Contact, CNATName(iCNAT)).getData());
119  }
120  return false;
121 }
122 
123 void C4Object::DoMotion(int32_t mx, int32_t my)
124 {
126  fix_x += mx; fix_y += my;
127 }
128 
129 void C4Object::StopAndContact(C4Real & ctco, C4Real limit, C4Real & speed, int32_t cnat)
130 {
131  ctco = limit;
132  speed = 0;
133  Contact(cnat);
134 }
135 
136 int32_t C4Object::ContactCheck(int32_t iAtX, int32_t iAtY, uint32_t *border_hack_contacts, bool collide_halfvehic)
137 {
138  // Check shape contact at given position
139  Shape.ContactCheck(iAtX,iAtY,border_hack_contacts,collide_halfvehic);
140 
141  // Store shape contact values in object t_contact
143 
144  // Contact script call for the first contacted cnat
145  if (Shape.ContactCNAT)
146  for (int32_t ccnat=0; ccnat<4; ccnat++) // Left, right, top bottom
147  if (Shape.ContactCNAT & (1<<ccnat))
148  if (Contact(1<<ccnat))
149  break; // Will stop on first positive return contact call!
150 
151  // Return shape contact count
152  return Shape.ContactCount;
153 }
154 
155 // Stop the object and do contact calls if it collides with the border
157 {
158  // layer bounds
160  {
161  C4PropList* pActionDef = GetAction();
162  if (!pActionDef || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH)
163  {
164  C4Real lbound = itofix(Layer->GetX() + Layer->Shape.GetX() - Shape.GetX()),
165  rbound = itofix(Layer->GetX() + Layer->Shape.GetX() + Layer->Shape.Wdt - (Shape.GetX() + Shape.Wdt));
166  if (ctcox < lbound) StopAndContact(ctcox, lbound, xdir, CNAT_Left);
167  if (ctcox > rbound) StopAndContact(ctcox, rbound, xdir, CNAT_Right);
168  }
169  }
170  // landscape bounds
171  C4Real lbound = itofix(0 - Shape.GetX()),
172  rbound = itofix(::Landscape.GetWidth() - (Shape.GetX() + Shape.Wdt));
173  if (ctcox < lbound && GetPropertyInt(P_BorderBound) & C4D_Border_Sides)
174  StopAndContact(ctcox, lbound, xdir, CNAT_Left);
175  if (ctcox > rbound && GetPropertyInt(P_BorderBound) & C4D_Border_Sides)
176  StopAndContact(ctcox, rbound, xdir, CNAT_Right);
177 }
178 
180 {
181  // layer bounds
183  {
184  C4PropList* pActionDef = GetAction();
185  if (!pActionDef || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH)
186  {
187  C4Real tbound = itofix(Layer->GetY() + Layer->Shape.GetY() - Shape.GetY()),
188  bbound = itofix(Layer->GetY() + Layer->Shape.GetY() + Layer->Shape.Hgt - (Shape.GetY() + Shape.Hgt));
189  if (ctcoy < tbound) StopAndContact(ctcoy, tbound, ydir, CNAT_Top);
190  if (ctcoy > bbound) StopAndContact(ctcoy, bbound, ydir, CNAT_Bottom);
191  }
192  }
193  // landscape bounds
194  C4Real tbound = itofix(0 - Shape.GetY()),
195  bbound = itofix(::Landscape.GetHeight() - (Shape.GetY() + Shape.Hgt));
196  if (ctcoy < tbound && GetPropertyInt(P_BorderBound) & C4D_Border_Top)
197  StopAndContact(ctcoy, tbound, ydir, CNAT_Top);
198  if (ctcoy > bbound && GetPropertyInt(P_BorderBound) & C4D_Border_Bottom)
199  StopAndContact(ctcoy, bbound, ydir, CNAT_Bottom);
200 }
201 
203 {
204  int32_t iContact=0;
205  bool fAnyContact=false; int iContacts = 0;
206  BYTE fTurned=0,fRedirectYR=0,fNoAttach=0;
207  // Restrictions
208  if (Def->NoHorizontalMove) xdir=0;
209  // Dig free target area
210  C4PropList* pActionDef = GetAction();
211  if (pActionDef)
212  if (pActionDef->GetPropertyInt(P_DigFree))
213  {
214  int ctcox, ctcoy;
215  // Shape size square
216  if (pActionDef->GetPropertyInt(P_DigFree)==1)
217  {
218  ctcox=fixtoi(fix_x+xdir); ctcoy=fixtoi(fix_y+ydir);
219  ::Landscape.DigFreeRect(ctcox+Shape.GetX(),ctcoy+Shape.GetY(),Shape.Wdt,Shape.Hgt,this);
220  }
221  // Free size round (variable size)
222  else
223  {
224  ctcox=fixtoi(fix_x+xdir); ctcoy=fixtoi(fix_y+ydir);
225  int32_t rad = pActionDef->GetPropertyInt(P_DigFree);
226  if (Con<FullCon) rad = rad*6*Con/5/FullCon;
227  ::Landscape.DigFree(ctcox,ctcoy-1,rad,this);
228  }
229  }
230 
231  // store previous movement and ocf
232  C4Real oldxdir(xdir), oldydir(ydir);
233  uint32_t old_ocf = OCF;
234 
235  bool fMoved = false;
236  C4Real new_x = fix_x + xdir;
237  C4Real new_y = fix_y + ydir;
238  SideBounds(new_x);
239 
240  if (!Action.t_attach) // Unattached movement = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
241  {
242  // Horizontal movement - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
243  // Move to target
244  while (fixtoi(new_x) != fixtoi(fix_x))
245  {
246  // Next step
247  int step = Sign(new_x - fix_x);
248  uint32_t border_hack_contacts = 0;
249  iContact=ContactCheck(GetX() + step, GetY(), &border_hack_contacts);
250  if (iContact || border_hack_contacts)
251  {
252  fAnyContact=true; iContacts |= t_contact | border_hack_contacts;
253  }
254  if (iContact)
255  {
256  // Abort horizontal movement
257  new_x = fix_x;
258  // Vertical redirection (always)
259  RedirectForce(xdir,ydir,-1);
260  ApplyFriction(ydir,ContactVtxFriction(this));
261  }
262  else // Free horizontal movement
263  {
264  DoMotion(step, 0);
265  fMoved = true;
266  }
267  }
268  // Vertical movement - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
269  // Movement target
270  new_y = fix_y + ydir;
271  // Movement bounds (vertical)
272  VerticalBounds(new_y);
273  // Move to target
274  while (fixtoi(new_y) != fixtoi(fix_y))
275  {
276  // Next step
277  int step = Sign(new_y - fix_y);
278  if ((iContact=ContactCheck(GetX(), GetY() + step, nullptr, ydir > 0)))
279  {
280  fAnyContact=true; iContacts |= t_contact;
281  new_y = fix_y;
282  // Vertical contact horizontal friction
283  ApplyFriction(xdir,ContactVtxFriction(this));
284  // Redirection slide or rotate
285  if (!ContactVtxCNAT(this,CNAT_Left))
286  RedirectForce(ydir,xdir,-1);
287  else if (!ContactVtxCNAT(this,CNAT_Right))
288  RedirectForce(ydir,xdir,+1);
289  else
290  {
291  // living things are always capable of keeping their rotation
292  if (OCF & OCF_Rotate) if (iContact==1) if (!Alive)
293  {
294  RedirectForce(ydir,rdir,-ContactVtxWeight(this));
295  fRedirectYR=1;
296  }
297  ydir=0;
298  }
299  }
300  else // Free vertical movement
301  {
302  DoMotion(0,step);
303  fMoved = true;
304  }
305  }
306  }
307  if (Action.t_attach) // Attached movement = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
308  {
309  VerticalBounds(new_y);
310  // Move to target
311  do
312  {
313  // Set next step target
314  int step_x = 0, step_y = 0;
315  if (fixtoi(new_x) != GetX())
316  step_x = Sign(fixtoi(new_x) - GetX());
317  else if (fixtoi(new_y) != GetY())
318  step_y = Sign(fixtoi(new_y) - GetY());
319  int32_t ctx = GetX() + step_x;
320  int32_t cty = GetY() + step_y;
321  // Attachment check
322  if (!Shape.Attach(ctx,cty,Action.t_attach))
323  fNoAttach=1;
324  else
325  {
326  // Attachment change to ctx/cty overrides target
327  if (ctx != GetX() + step_x)
328  {
329  xdir = Fix0; new_x = itofix(ctx);
330  }
331  if (cty != GetY() + step_y)
332  {
333  ydir = Fix0; new_y = itofix(cty);
334  }
335  }
336  // Contact check & evaluation
337  uint32_t border_hack_contacts = 0;
338  iContact=ContactCheck(ctx,cty,&border_hack_contacts);
339  if (iContact || border_hack_contacts)
340  {
341  fAnyContact=true; iContacts |= border_hack_contacts | t_contact;
342  }
343  if (iContact)
344  {
345  // Abort movement
346  if (ctx != GetX())
347  {
348  ctx = GetX(); new_x = fix_x;
349  }
350  if (cty != GetY())
351  {
352  cty = GetY(); new_y = fix_y;
353  }
354  }
355  DoMotion(ctx - GetX(), cty - GetY());
356  fMoved = true;
357  }
358  while (fixtoi(new_x) != GetX() || fixtoi(new_y) != GetY());
359  }
360 
361  if(fix_x != new_x || fix_y != new_y)
362  {
363  fMoved = true;
365  fix_x = new_x;
366  fix_y = new_y;
367  }
368  // Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
369  if (OCF & OCF_Rotate && !!rdir)
370  {
371  C4Real target_r = fix_r + rdir * 5;
372  // Rotation limit
373  if (Def->Rotateable>1)
374  {
375  if (target_r > itofix(Def->Rotateable))
376  { target_r = itofix(Def->Rotateable); rdir=0; }
377  if (target_r < itofix(-Def->Rotateable))
378  { target_r = itofix(-Def->Rotateable); rdir=0; }
379  }
380  int32_t ctx=GetX(); int32_t cty=GetY();
381  // Move to target
382  while (fixtoi(fix_r) != fixtoi(target_r))
383  {
384  // Save step undos
385  C4Real lcobjr = fix_r; C4Shape lshape=Shape;
386  // Try next step
387  fix_r += Sign(target_r - fix_r);
388  UpdateShape();
389  // attached rotation: rotate around attachment pos
390  if (Action.t_attach && !fNoAttach)
391  {
392  // more accurately, attachment should be evaluated by a rotation around the attachment vertex
393  // however, as long as this code is only used for some surfaces adjustment for large vehicles,
394  // it's enough to assume rotation around the center
395  ctx=GetX(); cty=GetY();
396  // evaluate attachment, but do not bother about attachment loss
397  // that will then be done in next execution cycle
398  Shape.Attach(ctx,cty,Action.t_attach);
399  }
400  // check for contact
401  if ((iContact=ContactCheck(ctx,cty))) // Contact
402  {
403  fAnyContact=true; iContacts |= t_contact;
404  // Undo step and abort movement
405  Shape=lshape;
406  target_r = fix_r = lcobjr;
407  // last UpdateShape-call might have changed sector lists!
408  UpdatePos();
409  // Redirect to GetY()
410  if (iContact==1) if (!fRedirectYR)
411  RedirectForce(rdir,ydir,-1);
412  // Stop rotation
413  rdir=0;
414  }
415  else
416  {
417  fTurned=1;
418  if (ctx != GetX() || cty != GetY())
419  {
420  fix_x = itofix(ctx); fix_y = itofix(cty);
421  }
422  }
423  }
424  // Circle bounds
425  if (target_r < -FixHalfCircle) { target_r += FixFullCircle; }
426  if (target_r > +FixHalfCircle) { target_r -= FixFullCircle; }
427  fix_r = target_r;
428  }
429  // Reput solid mask if moved by motion
430  if (fMoved || fTurned) UpdateSolidMask(true);
431  // Misc checks ===========================================================================================
432  // InLiquid check
433  // this equals C4Object::UpdateLiquid, but the "fNoAttach=false;"-line
434  if (IsInLiquidCheck()) // In Liquid
435  {
436  if (!InLiquid) // Enter liquid
437  {
438  if (OCF & OCF_HitSpeed2)
439  if (Mass>3) Splash();
440  fNoAttach=false;
441  InLiquid=true;
442  }
443  }
444  else // Out of liquid
445  {
446  if (InLiquid) // Leave liquid
447  InLiquid=false;
448  }
449  // Contact Action
450  if (fAnyContact)
451  {
452  t_contact = iContacts;
453  ContactAction();
454  }
455  // Attachment Loss Action
456  if (fNoAttach)
457  NoAttachAction();
458  // Movement Script Execution
459  if (fAnyContact)
460  {
461  C4AulParSet pars(fixtoi(oldxdir, 100), fixtoi(oldydir, 100));
462  if (old_ocf & OCF_HitSpeed1) Call(PSF_Hit, &pars);
463  if (old_ocf & OCF_HitSpeed2) Call(PSF_Hit2, &pars);
464  if (old_ocf & OCF_HitSpeed3) Call(PSF_Hit3, &pars);
465  }
466  // Rotation gfx
467  if (fTurned)
468  UpdateFace(true);
469  else
470  // pos changed?
471  if (fMoved) UpdatePos();
472 }
473 
475 {
476  // def allows stabilization?
477  if (Def->NoStabilize) return;
478  // normalize angle
479  C4Real nr = fix_r;
480  while (nr < itofix(-180)) nr += 360;
481  while (nr > itofix(180)) nr -= 360;
482  if (nr != Fix0)
483  if (Inside<C4Real>(nr,itofix(-StableRange),itofix(+StableRange)))
484  {
485  // Save step undos
486  C4Real lcobjr=fix_r;
487  C4Shape lshape=Shape;
488  // Try rotation
489  fix_r=Fix0;
490  UpdateShape();
491  if (ContactCheck(GetX(),GetY()))
492  { // Undo rotation
493  Shape=lshape;
494  fix_r=lcobjr;
495  }
496  else
497  { // Stabilization okay
498  UpdateFace(true);
499  }
500  }
501 }
502 
504 {
505  // Designed for contained objects, no static
506  if (fix_x != from->fix_x || fix_y != from->fix_y)
507  {
508  fix_x=from->fix_x; fix_y=from->fix_y;
509  // Resort into sectors
510  UpdatePos();
511  }
512  xdir=from->xdir; ydir=from->ydir;
513 }
514 
516 {
517  fix_x=tx; fix_y=ty;
518  UpdatePos();
519  UpdateSolidMask(false);
520 }
521 
522 void C4Object::MovePosition(int32_t dx, int32_t dy)
523 {
524  MovePosition(itofix(dx), itofix(dy));
525 }
526 
528 {
529  // move object position; repositions SolidMask
531  fix_x+=dx;
532  fix_y+=dy;
533  UpdatePos();
534  UpdateSolidMask(true);
535 }
536 
537 
538 bool C4Object::ExecMovement() // Every Tick1 by Execute
539 {
540  // update in which material this object is
541  UpdateInMat();
542 
543  // Containment check
544  if (Contained)
545  {
547 
548  return true;
549  }
550 
551  // General mobility check
552  if (Category & C4D_StaticBack) return false;
553 
554  // Movement execution
555  if (Mobile) // Object is moving
556  {
557  // Move object
558  DoMovement();
559  // Demobilization check
560  if ((xdir==0) && (ydir==0) && (rdir==0)) Mobile=false;
561  // Check for stabilization
562  if (rdir==0) Stabilize();
563  }
564  else // Object is static
565  {
566  // Check for stabilization
567  Stabilize();
568  // Check for mobilization
569  if (!::Game.iTick10)
570  {
571  // Gravity mobilization
572  xdir=ydir=rdir=0;
573  Mobile=true;
574  }
575  }
576 
577  // Enforce zero rotation
578  if (!Def->Rotateable) fix_r=Fix0;
579 
580  // Out of bounds check
581  if ((!Inside<int32_t>(GetX() + Shape.GetX(), -Shape.Wdt, ::Landscape.GetWidth()) && !(GetPropertyInt(P_BorderBound) & C4D_Border_Sides))
583  {
584  C4PropList* pActionDef = GetAction();
585  // Never remove attached objects: If they are truly outside landscape, their target will be removed,
586  // and the attached objects follow one frame later
587  if (!pActionDef || !Action.Target || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH)
588  {
589  bool fRemove = true;
590  // never remove HUD objects
591  if (Category & C4D_Parallax)
592  {
593  int parX, parY;
594  GetParallaxity(&parX, &parY);
595  fRemove = false;
596  if (GetX()>::Landscape.GetWidth() || GetY()>::Landscape.GetHeight()) fRemove = true; // except if they are really out of the viewport to the right...
597  else if (GetX()<0 && !!parX) fRemove = true; // ...or it's not HUD horizontally and it's out to the left
598  else if (!parX && GetX()<-::Landscape.GetWidth()) fRemove = true; // ...or it's HUD horizontally and it's out to the left
599  }
600  if (fRemove)
601  {
602  AssignDeath(true);
603  AssignRemoval();
604  }
605  }
606  }
607  return true;
608 }
609 
610 bool SimFlight(C4Real &x, C4Real &y, C4Real &xdir, C4Real &ydir, int32_t iDensityMin, int32_t iDensityMax, int32_t &iIter)
611 {
612  bool hitOnTime = true;
613  bool fBreak = false;
614  int32_t ctcox,ctcoy,cx,cy,i;
615  cx = fixtoi(x); cy = fixtoi(y);
616  i = iIter;
617  do
618  {
619  if (!--i) {hitOnTime = false; break;}
620  // If the object isn't moving and there is no gravity either, abort
621  if (xdir == 0 && ydir == 0 && GravAccel == 0)
622  return false;
623  // If the object is above the landscape flying upwards in no/negative gravity, abort
624  if (ydir <= 0 && GravAccel <= 0 && cy < 0)
625  return false;
626  // Set target position by momentum
627  x+=xdir; y+=ydir;
628  // Movement to target
629  ctcox=fixtoi(x); ctcoy=fixtoi(y);
630  // Bounds
631  if (!Inside<int32_t>(ctcox,0,::Landscape.GetWidth()) || (ctcoy>=::Landscape.GetHeight()))
632  return false;
633  // Move to target
634  do
635  {
636  // Set next step target
637  cx+=Sign(ctcox-cx); cy+=Sign(ctcoy-cy);
638  // Contact check
639  if (Inside(GBackDensity(cx,cy), iDensityMin, iDensityMax))
640  { fBreak = true; break; }
641  }
642  while ((cx!=ctcox) || (cy!=ctcoy));
643  // Adjust GravAccel once per frame
644  ydir+=GravAccel;
645  }
646  while (!fBreak);
647  // write position back
648  x = itofix(cx); y = itofix(cy);
649 
650  // how many steps did it take to get here?
651  iIter -= i;
652 
653  return hitOnTime;
654 }
655 
656 bool SimFlightHitsLiquid(C4Real fcx, C4Real fcy, C4Real xdir, C4Real ydir)
657 {
658  // Start in water?
659  int temp;
660  if (DensityLiquid(GBackDensity(fixtoi(fcx), fixtoi(fcy))))
661  if (!SimFlight(fcx, fcy, xdir, ydir, 0, C4M_Liquid - 1, temp=10))
662  return false;
663  // Hits liquid?
664  if (!SimFlight(fcx, fcy, xdir, ydir, C4M_Liquid, 100, temp=-1))
665  return false;
666  // liquid & deep enough?
667  return GBackLiquid(fixtoi(fcx), fixtoi(fcy)) && GBackLiquid(fixtoi(fcx), fixtoi(fcy) + 9);
668 }
669 
C4PropertyName GetPropertyP(C4PropertyName k) const
Definition: C4PropList.cpp:851
int32_t GetY() const
Definition: C4Object.h:287
const uint32_t OCF_HitSpeed1
Definition: C4Constants.h:84
int32_t ContactCheck(int32_t atx, int32_t aty, uint32_t *border_hack_contacts=nullptr, bool collide_halfvehic=false)
Definition: C4Movement.cpp:136
const C4Real FFriction
Definition: C4Movement.cpp:32
#define PSF_Hit
Definition: C4GameScript.h:49
void MovePosition(int32_t dx, int32_t dy)
Definition: C4Movement.cpp:522
void ForcePosition(C4Real tx, C4Real ty)
Definition: C4Movement.cpp:515
C4Game Game
Definition: C4Globals.cpp:52
int32_t GetY() const
Definition: C4Shape.h:64
const C4Real HitSpeed1
Definition: C4Movement.cpp:36
const C4Real DefaultGravAccel
Definition: C4Movement.cpp:40
bool Alive
Definition: C4Object.h:175
int32_t DigFree(int32_t tx, int32_t ty, int32_t rad, C4Object *by_object=nullptr, bool no_dig2objects=false, bool no_instability_check=false)
bool SimFlightHitsLiquid(C4Real fcx, C4Real fcy, C4Real xdir, C4Real ydir)
Definition: C4Movement.cpp:656
const int StableRange
Definition: C4Physics.h:23
int32_t Mass
Definition: C4Object.h:115
void Remove(bool fBackupAttachment)
void AssignDeath(bool fForced)
Definition: C4Object.cpp:993
C4PropList * GetAction() const
Definition: C4Object.cpp:2678
C4Real rdir
Definition: C4Object.h:126
const int32_t C4D_Border_Sides
Definition: C4Def.h:65
#define GravAccel
Definition: C4Physics.h:27
int32_t DigFreeRect(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, C4Object *by_object=nullptr, bool no_dig2objects=false, bool no_instability_check=false)
C4Real C4REAL100(int x)
Definition: C4Real.h:267
uint8_t BYTE
int Sign(T val)
Definition: Standard.h:45
const int32_t C4D_Border_Top
Definition: C4Def.h:66
C4ObjectPtr Layer
Definition: C4Object.h:136
int32_t NoHorizontalMove
Definition: C4Def.h:122
const C4Real FRedirect
Definition: C4Movement.cpp:31
Definition: C4Real.h:58
bool Mobile
Definition: C4Object.h:128
const int32_t FullCon
Definition: C4Constants.h:182
int32_t ContactCount
Definition: C4Shape.h:50
void UpdatePos()
Definition: C4Object.cpp:370
int32_t Rotateable
Definition: C4Def.h:119
int32_t VtxFriction[C4D_MaxVertex]
Definition: C4Shape.h:47
const char * CNATName(int32_t cnat)
Definition: C4Movement.cpp:100
int32_t Wdt
Definition: C4Rect.h:30
bool InLiquid
Definition: C4Object.h:131
const uint32_t OCF_HitSpeed2
Definition: C4Constants.h:91
void SideBounds(C4Real &ctcox)
Definition: C4Movement.cpp:156
const int32_t C4D_Border_Bottom
Definition: C4Def.h:67
const C4Real FloatFriction
Definition: C4Movement.cpp:34
C4Def * Def
Definition: C4Object.h:143
int32_t t_attach
Definition: C4Object.h:86
void ApplyFriction(C4Real &tval, int32_t percent)
Definition: C4Movement.cpp:52
void RedirectForce(C4Real &from, C4Real &to, int32_t tdir)
Definition: C4Movement.cpp:44
void UpdateShape(bool bUpdateVertices=true)
Definition: C4Object.cpp:343
#define PSF_Hit2
Definition: C4GameScript.h:50
uint32_t t_contact
Definition: C4Object.h:133
int32_t ContactVtxFriction(C4Object *cobj)
Definition: C4Movement.cpp:91
bool DensityLiquid(int32_t dens)
Definition: C4Landscape.h:208
C4Landscape Landscape
void DoMovement()
Definition: C4Movement.cpp:202
bool ContactCheck(int32_t cx, int32_t cy, uint32_t *border_hack_contacts=nullptr, bool collide_halfvehic=false)
Definition: C4Shape.cpp:352
void ContactAction()
Definition: C4Object.cpp:2921
int32_t VtxContactCNAT[C4D_MaxVertex]
Definition: C4Shape.h:52
void NoAttachAction()
Definition: C4Object.cpp:2886
int32_t ContactCNAT
Definition: C4Shape.h:49
int32_t Con
Definition: C4Object.h:173
int32_t GetX() const
Definition: C4Shape.h:63
int32_t VtxNum
Definition: C4Shape.h:43
int32_t GetX() const
Definition: C4Object.h:286
void AssignRemoval(bool fExitContents=false)
Definition: C4Object.cpp:254
int32_t VtxX[C4D_MaxVertex]
Definition: C4Shape.h:44
C4Fixed itofix(int32_t x)
Definition: C4Real.h:261
const C4Real FixFullCircle
Definition: C4Movement.cpp:33
const int32_t C4D_StaticBack
Definition: C4Def.h:40
const uint32_t OCF_Rotate
Definition: C4Constants.h:88
int32_t iTick10
Definition: C4Game.h:129
void UpdateFace(bool bUpdateShape, bool fTemp=false)
Definition: C4Object.cpp:378
bool IsInLiquidCheck() const
Definition: C4Object.cpp:4105
int32_t Category
Definition: C4Object.h:113
void VerticalBounds(C4Real &ctcoy)
Definition: C4Movement.cpp:179
void CopyMotion(C4Object *from)
Definition: C4Movement.cpp:503
int32_t GetHeight() const
bool ExecMovement()
Definition: C4Movement.cpp:538
C4ObjectPtr Target
Definition: C4Object.h:87
const BYTE CNAT_None
Definition: C4Constants.h:109
int32_t ContactVtxWeight(C4Object *cobj)
Definition: C4Movement.cpp:76
C4Real fix_r
Definition: C4Object.h:125
C4Real fix_x
Definition: C4Object.h:125
const BYTE CNAT_Top
Definition: C4Constants.h:112
void GetParallaxity(int32_t *parX, int32_t *parY) const
Definition: C4Object.cpp:4270
const int32_t C4D_Border_Layer
Definition: C4Def.h:68
int32_t GBackDensity(int32_t x, int32_t y)
Definition: C4Landscape.h:226
const C4Real RotateAccel
Definition: C4Movement.cpp:35
#define PSF_Contact
Definition: C4GameScript.h:69
const BYTE CNAT_Right
Definition: C4Constants.h:111
int32_t NoStabilize
Definition: C4Def.h:138
const C4Real HitSpeed3
Definition: C4Movement.cpp:38
#define PSF_Hit3
Definition: C4GameScript.h:51
const uint32_t OCF_HitSpeed3
Definition: C4Constants.h:92
void Stabilize()
Definition: C4Movement.cpp:474
int32_t GetPropertyInt(C4PropertyName k, int32_t default_val=0) const
Definition: C4PropList.cpp:882
bool SimFlight(C4Real &x, C4Real &y, C4Real &xdir, C4Real &ydir, int32_t iDensityMin, int32_t iDensityMax, int32_t &iIter)
Definition: C4Movement.cpp:610
const int32_t C4D_Parallax
Definition: C4Def.h:51
C4Real fix_y
Definition: C4Object.h:125
C4ObjectPtr Contained
Definition: C4Object.h:144
int32_t Hgt
Definition: C4Rect.h:30
const C4Real HitSpeed4
Definition: C4Movement.cpp:39
T Abs(T val)
Definition: Standard.h:42
const C4Real HitSpeed2
Definition: C4Movement.cpp:37
C4Action Action
Definition: C4Object.h:147
C4Shape Shape
Definition: C4Object.h:148
const int32_t C4M_Liquid
Definition: C4Constants.h:175
uint32_t OCF
Definition: C4Object.h:134
void UpdateSolidMask(bool fRestoreAttachedObjects)
Definition: C4Object.cpp:4145
bool ContactVtxCNAT(C4Object *cobj, BYTE cnat_dir)
Definition: C4Movement.cpp:63
C4SolidMask * pSolidMaskData
Definition: C4Object.h:176
int fixtoi(const C4Fixed &x)
Definition: C4Real.h:259
C4Real xdir
Definition: C4Object.h:126
const C4Real FixHalfCircle
Definition: C4Movement.cpp:33
bool Inside(T ival, U lbound, V rbound)
Definition: Standard.h:43
void StopAndContact(C4Real &ctco, C4Real limit, C4Real &speed, int32_t cnat)
Definition: C4Movement.cpp:129
const BYTE CNAT_Left
Definition: C4Constants.h:110
const BYTE CNAT_Bottom
Definition: C4Constants.h:113
bool Attach(int32_t &cx, int32_t &cy, BYTE cnat_pos)
Definition: C4Shape.cpp:185
C4Real ydir
Definition: C4Object.h:126
bool GBackLiquid(int32_t x, int32_t y)
Definition: C4Landscape.h:241
int32_t GetWidth() const
void DoMotion(int32_t mx, int32_t my)
Definition: C4Movement.cpp:123
bool Contact(int32_t cnat)
Definition: C4Movement.cpp:114
const C4Real Fix0
Definition: C4Real.h:312
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
Definition: C4PropList.h:110
const BYTE CNAT_Center
Definition: C4Constants.h:114