Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
bool C4Object::Enter(C4Object *pTarget, bool fCalls, bool fCopyMotion, bool *pfRejectCollect)
{
	// 0. Query entrance and collection
	// 1. Exit if contained.
	// 2. Set new container.
	// 3. Update Contents and mass of the new container.
	// 4. Call collection for container
	// 5. Call entrance for object.

	// No valid target or target is self
	if (!pTarget || (pTarget==this)) return false;
	// check if entrance is allowed
	if (!! Call(PSF_RejectEntrance, &C4AulParSet(pTarget))) return false;
	// check if we end up in an endless container-recursion
	for (C4Object *pCnt=pTarget->Contained; pCnt; pCnt=pCnt->Contained)
		if (pCnt==this) return false;
	// Check RejectCollect, if desired
	if (pfRejectCollect)
	{
		if (!!pTarget->Call(PSF_RejectCollection,&C4AulParSet(Def, this)))
		{
			*pfRejectCollect = true;
			return false;
		}
		*pfRejectCollect = false;
	}
	// Exit if contained
	if (Contained) if (!Exit(GetX(),GetY())) return false;
	if (Contained || !Status || !pTarget->Status) return false;
	// Failsafe updates
	if (Menu)
	{
		CloseMenu(true);
		// CloseMenu might do bad stuff
		if (Contained || !Status || !pTarget->Status) return false;
	}
	SetOCF();
	// Set container
	Contained=pTarget;
	// Enter
	if (!Contained->Contents.Add(this, C4ObjectList::stContents))
	{
		Contained=nullptr;
		return false;
	}
	// Assume that the new container controls this object, if it cannot control itself (i.e.: Alive)
	// So it can be traced back who caused the damage, if a projectile hits its target
	if (!Alive)
		Controller = pTarget->Controller;
	// Misc updates
	// motion must be copied immediately, so the position will be correct when OCF is set, and
	// OCF_Available will be set for newly bought items, even if 50/50 is solid in the landscape
	// however, the motion must be preserved sometimes to keep flags like OCF_HitSpeed upon collection
	if (fCopyMotion)
	{
		// remove any solidmask before copying the motion...
		UpdateSolidMask(false);
		CopyMotion(Contained);
	}
	SetOCF();
	UpdateFace(true);
	// Update container
	Contained->UpdateMass();
	Contained->SetOCF();
	// Object list callback (before script callbacks, because script callbacks may exit again)
	ObjectListChangeListener.OnObjectContainerChanged(this, nullptr, Contained);
	// Collection call
	if (fCalls) pTarget->Call(PSF_Collection2,&C4AulParSet(this));
	if (!Contained || !Contained->Status || !pTarget->Status) return true;
	// Entrance call
	if (fCalls) Call(PSF_Entrance,&C4AulParSet(Contained));
	if (!Contained || !Contained->Status || !pTarget->Status) return true;
	// Success
	return true;
}