forked from Mirrors/openclonk
Allow object interaction with closed borders
Conceptually, the landscape stretches infinitely on both left and right hand borders of the map. So far, the "closed" part of the border only blocked objects from passing through. (Additionally, there was a bug where you could scale the border under certain circumstances.) This patch allows objects to properly move around on the map borders, including scaling the fake terrain.stable-5.3
parent
192bc4a03d
commit
27eb5dd65a
|
@ -160,10 +160,10 @@ void C4Object::TargetBounds(C4Real &ctco, int32_t limit_low, int32_t limit_hi, i
|
|||
}
|
||||
}
|
||||
|
||||
int32_t C4Object::ContactCheck(int32_t iAtX, int32_t iAtY)
|
||||
int32_t C4Object::ContactCheck(int32_t iAtX, int32_t iAtY, uint32_t *border_hack_contacts)
|
||||
{
|
||||
// Check shape contact at given position
|
||||
Shape.ContactCheck(iAtX,iAtY);
|
||||
Shape.ContactCheck(iAtX,iAtY,border_hack_contacts);
|
||||
|
||||
// Store shape contact values in object t_contact
|
||||
t_contact=Shape.ContactCNAT;
|
||||
|
@ -261,9 +261,14 @@ void C4Object::DoMovement()
|
|||
{
|
||||
// Next step
|
||||
int step = Sign<C4Real>(new_x - fix_x);
|
||||
if ((iContact=ContactCheck(GetX() + step, GetY())))
|
||||
uint32_t border_hack_contacts = 0;
|
||||
iContact=ContactCheck(GetX() + step, GetY(), &border_hack_contacts);
|
||||
if (iContact || border_hack_contacts)
|
||||
{
|
||||
fAnyContact=true; iContacts |= t_contact | border_hack_contacts;
|
||||
}
|
||||
if (iContact)
|
||||
{
|
||||
fAnyContact=true; iContacts |= t_contact;
|
||||
// Abort horizontal movement
|
||||
ctcox = GetX();
|
||||
new_x = fix_x;
|
||||
|
@ -342,9 +347,14 @@ void C4Object::DoMovement()
|
|||
}
|
||||
}
|
||||
// Contact check & evaluation
|
||||
if ((iContact=ContactCheck(ctx,cty)))
|
||||
uint32_t border_hack_contacts = 0;
|
||||
iContact=ContactCheck(ctx,cty,&border_hack_contacts);
|
||||
if (iContact || border_hack_contacts)
|
||||
{
|
||||
fAnyContact=true; iContacts |= border_hack_contacts | t_contact;
|
||||
}
|
||||
if (iContact)
|
||||
{
|
||||
fAnyContact=true; iContacts |= t_contact;
|
||||
// Abort movement
|
||||
if (ctx != GetX())
|
||||
{
|
||||
|
|
|
@ -274,7 +274,7 @@ public:
|
|||
void GetOCFForPos(int32_t ctx, int32_t cty, DWORD &ocf);
|
||||
bool CloseMenu(bool fForce);
|
||||
bool ActivateMenu(int32_t iMenu, int32_t iMenuSelect=0, int32_t iMenuData=0, int32_t iMenuPosition=0, C4Object *pTarget=NULL);
|
||||
int32_t ContactCheck(int32_t atx, int32_t aty);
|
||||
int32_t ContactCheck(int32_t atx, int32_t aty, uint32_t *border_hack_contacts=0);
|
||||
bool Contact(int32_t cnat);
|
||||
void TargetBounds(C4Real &ctco, int32_t limit_low, int32_t limit_hi, int32_t cnat_low, int32_t cnat_hi);
|
||||
enum { SAC_StartCall = 1, SAC_EndCall = 2, SAC_AbortCall = 4 };
|
||||
|
|
|
@ -345,7 +345,7 @@ bool C4Shape::CheckContact(int32_t cx, int32_t cy)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool C4Shape::ContactCheck(int32_t cx, int32_t cy)
|
||||
bool C4Shape::ContactCheck(int32_t cx, int32_t cy, uint32_t *border_hack_contacts)
|
||||
{
|
||||
// Check all vertices at given object position.
|
||||
// Set ContactCNAT and ContactCount.
|
||||
|
@ -362,25 +362,31 @@ bool C4Shape::ContactCheck(int32_t cx, int32_t cy)
|
|||
if (!(VtxCNAT[cvtx] & CNAT_NoCollision))
|
||||
|
||||
{
|
||||
|
||||
VtxContactCNAT[cvtx]=CNAT_None;
|
||||
VtxContactMat[cvtx]=GBackMat(cx+VtxX[cvtx],cy+VtxY[cvtx]);
|
||||
int32_t x = cx+VtxX[cvtx];
|
||||
int32_t y = cy+VtxY[cvtx];
|
||||
VtxContactMat[cvtx]=GBackMat(x,y);
|
||||
|
||||
if (GBackDensity(cx+VtxX[cvtx],cy+VtxY[cvtx]) >= ContactDensity)
|
||||
if (GBackDensity(x,y) >= ContactDensity)
|
||||
{
|
||||
ContactCNAT |= VtxCNAT[cvtx];
|
||||
VtxContactCNAT[cvtx]|=CNAT_Center;
|
||||
ContactCount++;
|
||||
// Vertex center contact, now check top,bottom,left,right
|
||||
if (GBackDensity(cx+VtxX[cvtx],cy+VtxY[cvtx]-1) >= ContactDensity)
|
||||
if (GBackDensity(x,y-1) >= ContactDensity)
|
||||
VtxContactCNAT[cvtx]|=CNAT_Top;
|
||||
if (GBackDensity(cx+VtxX[cvtx],cy+VtxY[cvtx]+1) >= ContactDensity)
|
||||
if (GBackDensity(x,y+1) >= ContactDensity)
|
||||
VtxContactCNAT[cvtx]|=CNAT_Bottom;
|
||||
if (GBackDensity(cx+VtxX[cvtx]-1,cy+VtxY[cvtx]) >= ContactDensity)
|
||||
if (GBackDensity(x-1,y) >= ContactDensity)
|
||||
VtxContactCNAT[cvtx]|=CNAT_Left;
|
||||
if (GBackDensity(cx+VtxX[cvtx]+1,cy+VtxY[cvtx]) >= ContactDensity)
|
||||
if (GBackDensity(x+1,y) >= ContactDensity)
|
||||
VtxContactCNAT[cvtx]|=CNAT_Right;
|
||||
}
|
||||
if (border_hack_contacts)
|
||||
{
|
||||
if (x == 0 && GBackDensity(x-1, y) >= ContactDensity) *border_hack_contacts |= CNAT_Left;
|
||||
else if (x == ::Landscape.Width && GBackDensity(x+1, y) >= ContactDensity) *border_hack_contacts |= CNAT_Right;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ public:
|
|||
int32_t GetY() { return y; }
|
||||
bool AddVertex(int32_t iX, int32_t iY);
|
||||
bool CheckContact(int32_t cx, int32_t cy);
|
||||
bool ContactCheck(int32_t cx, int32_t cy);
|
||||
bool ContactCheck(int32_t cx, int32_t cy, uint32_t *border_hack_contacts=0);
|
||||
bool Attach(int32_t &cx, int32_t &cy, BYTE cnat_pos);
|
||||
bool LineConnect(int32_t tx, int32_t ty, int32_t cvtx, int32_t ld, int32_t oldx, int32_t oldy);
|
||||
bool InsertVertex(int32_t iPos, int32_t tx, int32_t ty);
|
||||
|
|
Loading…
Reference in New Issue