void C4Object::SideBounds(C4Real &ctcox) { // layer bounds if (Layer) if (Layer->Def->BorderBound & C4D_Border_Layer) { C4PropList* pActionDef = GetAction(); if (!pActionDef || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH) { TargetBounds(ctcox, Layer->GetX() + Layer->Shape.GetX() - Shape.GetX(), Layer->GetX() + Layer->Shape.GetX() + Layer->Shape.Wdt + Shape.GetX(), CNAT_Left, CNAT_Right); } } // landscape bounds if (Def->BorderBound & C4D_Border_Sides) TargetBounds(ctcox,0-Shape.GetX(),GBackWdt+Shape.GetX(),CNAT_Left,CNAT_Right); }
void C4Object::VerticalBounds(C4Real &ctcoy) { // layer bounds if (Layer) if (Layer->Def->BorderBound & C4D_Border_Layer) { C4PropList* pActionDef = GetAction(); if (!pActionDef || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH) { TargetBounds(ctcoy, Layer->GetY() + Layer->Shape.GetY() - Shape.GetY(), Layer->GetY() + Layer->Shape.GetY() + Layer->Shape.Hgt + Shape.GetY(), CNAT_Top, CNAT_Bottom); } } // landscape bounds if (Def->BorderBound & C4D_Border_Top) TargetBounds(ctcoy,0-Shape.GetY(),+1000000,CNAT_Top,CNAT_Bottom); if (Def->BorderBound & C4D_Border_Bottom) TargetBounds(ctcoy,-1000000,GBackHgt+Shape.GetY(),CNAT_Top,CNAT_Bottom); }
bool ObjectComDrop(C4Object *cObj, C4Object *pThing) { // No object specified, first from contents if (!pThing) pThing = cObj->Contents.GetObject(); // Nothing to throw if (!pThing) return false; // Force and direction // When dropping diagonally, drop from edge of shape // When doing a diagonal forward drop during flight, exit a bit closer to the Clonk to allow planned tumbling // Except when hangling, so you can mine effectively form the ceiling, and when swimming because you cannot tumble then C4Real pthrow=C4REAL100(cObj->GetPropertyInt(P_ThrowSpeed)); int32_t tdir=0; int right=0; bool isHanglingOrSwimming = false; int32_t iProc = -1; C4PropList* pActionDef = cObj->GetAction(); if (pActionDef) { iProc = pActionDef->GetPropertyP(P_Procedure); if (iProc == DFA_HANGLE || iProc == DFA_SWIM) isHanglingOrSwimming = true; } int32_t iOutposReduction = 1; // don't exit object too far forward during jump if (iProc != DFA_SCALE) // never diagonal during scaling (can have com into wall during scaling!) { if (ComDirLike(cObj->Action.ComDir, COMD_Left)) { tdir=-1; right = 0; if (cObj->xdir < C4REAL10(15) && !isHanglingOrSwimming) --iOutposReduction; } if (ComDirLike(cObj->Action.ComDir, COMD_Right)) { tdir=+1; right = 1; if (cObj->xdir > C4REAL10(-15) && !isHanglingOrSwimming) --iOutposReduction; } } // Exit object pThing->Exit(cObj->GetX() + (cObj->Shape.x + cObj->Shape.Wdt * right) * !!tdir * iOutposReduction, cObj->GetY()+cObj->Shape.y+cObj->Shape.Hgt-(pThing->Shape.y+pThing->Shape.Hgt),0,pthrow*tdir,Fix0,Fix0); // Update OCF cObj->SetOCF(); // Ungrab ObjectComUnGrab(cObj); // Done return true; }
void C4Object::VerticalBounds(C4Real &ctcoy) { // layer bounds if (Layer && Layer->GetPropertyInt(P_BorderBound) & C4D_Border_Layer) { C4PropList* pActionDef = GetAction(); if (!pActionDef || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH) { C4Real tbound = itofix(Layer->GetY() + Layer->Shape.GetY() - Shape.GetY()), bbound = itofix(Layer->GetY() + Layer->Shape.GetY() + Layer->Shape.Hgt - (Shape.GetY() + Shape.Hgt)); if (ctcoy < tbound) StopAndContact(ctcoy, tbound, ydir, CNAT_Top); if (ctcoy > bbound) StopAndContact(ctcoy, bbound, ydir, CNAT_Bottom); } } // landscape bounds C4Real tbound = itofix(0 - Shape.GetY()), bbound = itofix(GBackHgt - (Shape.GetY() + Shape.Hgt)); if (ctcoy < tbound && GetPropertyInt(P_BorderBound) & C4D_Border_Top) StopAndContact(ctcoy, tbound, ydir, CNAT_Top); if (ctcoy > bbound && GetPropertyInt(P_BorderBound) & C4D_Border_Bottom) StopAndContact(ctcoy, bbound, ydir, CNAT_Bottom); }
// Stop the object and do contact calls if it collides with the border void C4Object::SideBounds(C4Real &ctcox) { // layer bounds if (Layer && Layer->GetPropertyInt(P_BorderBound) & C4D_Border_Layer) { C4PropList* pActionDef = GetAction(); if (!pActionDef || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH) { C4Real lbound = itofix(Layer->GetX() + Layer->Shape.GetX() - Shape.GetX()), rbound = itofix(Layer->GetX() + Layer->Shape.GetX() + Layer->Shape.Wdt - (Shape.GetX() + Shape.Wdt)); if (ctcox < lbound) StopAndContact(ctcox, lbound, xdir, CNAT_Left); if (ctcox > rbound) StopAndContact(ctcox, rbound, xdir, CNAT_Right); } } // landscape bounds C4Real lbound = itofix(0 - Shape.GetX()), rbound = itofix(GBackWdt - (Shape.GetX() + Shape.Wdt)); if (ctcox < lbound && GetPropertyInt(P_BorderBound) & C4D_Border_Sides) StopAndContact(ctcox, lbound, xdir, CNAT_Left); if (ctcox > rbound && GetPropertyInt(P_BorderBound) & C4D_Border_Sides) StopAndContact(ctcox, rbound, xdir, CNAT_Right); }
bool C4Object::ExecMovement() // Every Tick1 by Execute { // update in which material this object is UpdateInMat(); // Containment check if (Contained) { CopyMotion(Contained); return true; } // General mobility check if (Category & C4D_StaticBack) return false; // Movement execution if (Mobile) // Object is moving { // Move object DoMovement(); // Demobilization check if ((xdir==0) && (ydir==0) && (rdir==0)) Mobile=0; // Check for stabilization if (rdir==0) Stabilize(); } else // Object is static { // Check for stabilization Stabilize(); // Check for mobilization if (!::Game.iTick10) { // Gravity mobilization xdir=ydir=rdir=0; Mobile=1; } } // Enforce zero rotation if (!Def->Rotateable) fix_r=Fix0; // Out of bounds check if ((!Inside<int32_t>(GetX() + Shape.GetX(), -Shape.Wdt, GBackWdt) && !(GetPropertyInt(P_BorderBound) & C4D_Border_Sides)) || ((GetY() + Shape.GetY() > GBackHgt) && !(GetPropertyInt(P_BorderBound) & C4D_Border_Bottom))) { C4PropList* pActionDef = GetAction(); // Never remove attached objects: If they are truly outside landscape, their target will be removed, // and the attached objects follow one frame later if (!pActionDef || !Action.Target || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH) { bool fRemove = true; // never remove HUD objects if (Category & C4D_Parallax) { int parX, parY; GetParallaxity(&parX, &parY); fRemove = false; if (GetX()>GBackWdt || GetY()>GBackHgt) fRemove = true; // except if they are really out of the viewport to the right... else if (GetX()<0 && !!parX) fRemove = true; // ...or it's not HUD horizontally and it's out to the left else if (!parX && GetX()<-GBackWdt) fRemove = true; // ...or it's HUD horizontally and it's out to the left } if (fRemove) { AssignDeath(true); AssignRemoval(); } } } return true; }