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
Nicolas Hake 2012-10-10 21:28:25 +02:00
parent 192bc4a03d
commit 27eb5dd65a
4 changed files with 32 additions and 16 deletions

View File

@ -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())
{

View File

@ -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 };

View File

@ -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;
}
}

View File

@ -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);