bool ObjectComJump(C4Object *cObj) // by ObjectComUp, ExecCMDFMoveTo, FnJump
{
    // Only if walking
    if (cObj->GetProcedure()!=DFA_WALK) return false;
    // Calculate direction & forces
    C4Real TXDir=Fix0;
    C4PropList *pActionWalk = cObj->GetAction();
    C4Real iPhysicalWalk = C4REAL100(pActionWalk->GetPropertyInt(P_Speed)) * itofix(cObj->GetCon(), FullCon);
    C4Real iPhysicalJump = C4REAL100(cObj->GetPropertyInt(P_JumpSpeed)) * itofix(cObj->GetCon(), FullCon);

    if (cObj->Action.ComDir==COMD_Left || cObj->Action.ComDir==COMD_UpLeft)  TXDir=-iPhysicalWalk;
    else if (cObj->Action.ComDir==COMD_Right || cObj->Action.ComDir==COMD_UpRight) TXDir=+iPhysicalWalk;
    C4Real x = cObj->fix_x, y = cObj->fix_y;
    // find bottom-most vertex, correct starting position for simulation
    int32_t iBtmVtx = cObj->Shape.GetBottomVertex();
    if (iBtmVtx != -1) {
        x += cObj->Shape.GetVertexX(iBtmVtx);
        y += cObj->Shape.GetVertexY(iBtmVtx);
    }
    // Try dive
    if (cObj->Shape.ContactDensity > C4M_Liquid)
        if (SimFlightHitsLiquid(x,y,TXDir,-iPhysicalJump))
            if (ObjectActionDive(cObj,TXDir,-iPhysicalJump))
                return true;
    // Regular jump
    return ObjectActionJump(cObj,TXDir,-iPhysicalJump,true);
}
Exemple #2
0
bool C4ValueProviderAction::Execute()
{
	// Object might have been removed
	if(!Object) return false;

	const C4Action& Action = Object->Action;
	C4PropList* pActionDef = Object->GetAction();

	// TODO: We could cache these...
	const StdMeshAnimation* animation = Action.Animation->GetAnimation();
	const int32_t length = pActionDef->GetPropertyInt(P_Length);
	const int32_t delay = pActionDef->GetPropertyInt(P_Delay);

	if (delay)
		Value = itofix(Action.Phase * delay + Action.PhaseDelay) * ftofix(animation->Length) / (delay * length);
	else
		Value = itofix(Action.Phase) * ftofix(animation->Length) / length;

	return true;
}
void C4GraphicsOverlay::UpdateFacet()
{
	// special: Nothing to update for object and pSourceGfx may be NULL
	// If there will ever be something to init here, UpdateFacet() will also need to be called when objects have been loaded
	if (eMode == MODE_Object) return;
	// otherwise, source graphics must be specified
	if (!pSourceGfx) return;
	C4Def *pDef = pSourceGfx->pDef;
	assert(pDef);
	fZoomToShape = false;
	// Clear old mesh instance, if any
	delete pMeshInstance; pMeshInstance = NULL;
	// update by mode
	switch (eMode)
	{
	case MODE_None:
		break;

	case MODE_Base: // def base graphics
		if (pSourceGfx->Type == C4DefGraphics::TYPE_Bitmap)
			fctBlit.Set(pSourceGfx->GetBitmap(), 0, 0, pDef->Shape.Wdt, pDef->Shape.Hgt, pDef->Shape.x+pDef->Shape.Wdt/2, pDef->Shape.y+pDef->Shape.Hgt/2);
		else if (pSourceGfx->Type == C4DefGraphics::TYPE_Mesh)
			pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh, 1.0f);
		break;

	case MODE_Action: // graphics of specified action
	{
		// Clear old facet
		fctBlit.Default();

		// Ensure there is actually an action set
		if (!Action[0])
			return;

		C4Value v;
		pDef->GetProperty(P_ActMap, &v);
		C4PropList *actmap = v.getPropList();
		if (!actmap)
			return;

		actmap->GetPropertyByS(::Strings.RegString(Action), &v);
		C4PropList *action = v.getPropList();
		if (!action)
			return;

		if (pSourceGfx->Type == C4DefGraphics::TYPE_Bitmap)
		{
			fctBlit.Set(pSourceGfx->GetBitmap(),
			            action->GetPropertyInt(P_X), action->GetPropertyInt(P_Y),
			            action->GetPropertyInt(P_Wdt), action->GetPropertyInt(P_Hgt));
			// FIXME: fctBlit.TargetX has to be set here
		}
		else if (pSourceGfx->Type == C4DefGraphics::TYPE_Mesh)
		{
			C4String* AnimationName = action->GetPropertyStr(P_Animation);
			if (!AnimationName) return;

			pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh, 1.0f);
			const StdMeshAnimation* Animation = pSourceGfx->Mesh->GetSkeleton().GetAnimationByName(AnimationName->GetData());
			if (!Animation) return;

			pMeshInstance->PlayAnimation(*Animation, 0, NULL, new C4ValueProviderRef<int32_t>(iPhase, ftofix(Animation->Length / action->GetPropertyInt(P_Length))), new C4ValueProviderConst(itofix(1)), true);
		}

		break;
	}
	case MODE_ObjectPicture: // ingame picture of object
		// calculated at runtime
		break;

	case MODE_IngamePicture:
	case MODE_Picture: // def picture
		fZoomToShape = true;
		// drawn at runtime
		break;

	case MODE_ExtraGraphics: // like ColorByOwner-sfc
		// calculated at runtime
		break;

	case MODE_Rank:
		// drawn at runtime
		break;

	case MODE_Object:
		// TODO
		break;
	}
}
Exemple #4
0
void C4Object::DoMovement()
{
	int32_t iContact=0;
	bool fAnyContact=false; int iContacts = 0;
	BYTE fTurned=0,fRedirectYR=0,fNoAttach=0;
	// Restrictions
	if (Def->NoHorizontalMove) xdir=0;
	// Dig free target area
	C4PropList* pActionDef = GetAction();
	if (pActionDef)
		if (pActionDef->GetPropertyInt(P_DigFree))
		{
			int ctcox, ctcoy;
			// Shape size square
			if (pActionDef->GetPropertyInt(P_DigFree)==1)
			{
				ctcox=fixtoi(fix_x+xdir); ctcoy=fixtoi(fix_y+ydir);
				::Landscape.DigFreeRect(ctcox+Shape.GetX(),ctcoy+Shape.GetY(),Shape.Wdt,Shape.Hgt,this);
			}
			// Free size round (variable size)
			else
			{
				ctcox=fixtoi(fix_x+xdir); ctcoy=fixtoi(fix_y+ydir);
				int32_t rad = pActionDef->GetPropertyInt(P_DigFree);
				if (Con<FullCon) rad = rad*6*Con/5/FullCon;
				::Landscape.DigFree(ctcox,ctcoy-1,rad,this);
			}
		}

	// store previous movement and ocf
	C4Real oldxdir(xdir), oldydir(ydir);
	uint32_t old_ocf = OCF;

	bool fMoved = false;
	C4Real new_x = fix_x + xdir;
	C4Real new_y = fix_y + ydir;
	SideBounds(new_x);

	if (!Action.t_attach) // Unattached movement  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
	{
		// Horizontal movement - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
		// Move to target
		while (fixtoi(new_x) != fixtoi(fix_x))
		{
			// Next step
			int step = Sign(new_x - fix_x);
			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)
			{
				// Abort horizontal movement
				new_x = fix_x;
				// Vertical redirection (always)
				RedirectForce(xdir,ydir,-1);
				ApplyFriction(ydir,ContactVtxFriction(this));
			}
			else // Free horizontal movement
			{
				DoMotion(step, 0);
				fMoved = true;
			}
		}
		// Vertical movement - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
		// Movement target
		new_y = fix_y + ydir;
		// Movement bounds (vertical)
		VerticalBounds(new_y);
		// Move to target
		while (fixtoi(new_y) != fixtoi(fix_y))
		{
			// Next step
			int step = Sign(new_y - fix_y);
			if ((iContact=ContactCheck(GetX(), GetY() + step, nullptr, ydir > 0)))
			{
				fAnyContact=true; iContacts |= t_contact;
				new_y = fix_y;
				// Vertical contact horizontal friction
				ApplyFriction(xdir,ContactVtxFriction(this));
				// Redirection slide or rotate
				if (!ContactVtxCNAT(this,CNAT_Left))
					RedirectForce(ydir,xdir,-1);
				else if (!ContactVtxCNAT(this,CNAT_Right))
					RedirectForce(ydir,xdir,+1);
				else
				{
					// living things are always capable of keeping their rotation
					if (OCF & OCF_Rotate) if (iContact==1) if (!Alive)
							{
								RedirectForce(ydir,rdir,-ContactVtxWeight(this));
								fRedirectYR=1;
							}
					ydir=0;
				}
			}
			else // Free vertical movement
			{
				DoMotion(0,step);
				fMoved = true;
			}
		}
	}
	if (Action.t_attach) // Attached movement = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
	{
		VerticalBounds(new_y);
		// Move to target
		do
		{
			// Set next step target
			int step_x = 0, step_y = 0;
			if (fixtoi(new_x) != GetX())
				step_x = Sign(fixtoi(new_x) - GetX());
			else if (fixtoi(new_y) != GetY())
				step_y = Sign(fixtoi(new_y) - GetY());
			int32_t ctx = GetX() + step_x;
			int32_t cty = GetY() + step_y;
			// Attachment check
			if (!Shape.Attach(ctx,cty,Action.t_attach))
				fNoAttach=1;
			else
			{
				// Attachment change to ctx/cty overrides target
				if (ctx != GetX() + step_x)
				{
					xdir = Fix0; new_x = itofix(ctx);
				}
				if (cty != GetY() + step_y)
				{
					ydir = Fix0; new_y = itofix(cty);
				}
			}
			// Contact check & evaluation
			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)
			{
				// Abort movement
				if (ctx != GetX())
				{
					ctx = GetX(); new_x = fix_x;
				}
				if (cty != GetY())
				{
					cty = GetY(); new_y = fix_y;
				}
			}
			DoMotion(ctx - GetX(), cty - GetY());
			fMoved = true;
		}
		while (fixtoi(new_x) != GetX() || fixtoi(new_y) != GetY());
	}

	if(fix_x != new_x || fix_y != new_y)
	{
		fMoved = true;
		if (pSolidMaskData) pSolidMaskData->Remove(true);
		fix_x = new_x;
		fix_y = new_y;
	}
	// Rotation  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	if (OCF & OCF_Rotate && !!rdir)
	{
		C4Real target_r = fix_r + rdir * 5;
		// Rotation limit
		if (Def->Rotateable>1)
		{
			if (target_r > itofix(Def->Rotateable))
				{ target_r = itofix(Def->Rotateable); rdir=0; }
			if (target_r < itofix(-Def->Rotateable))
				{ target_r = itofix(-Def->Rotateable); rdir=0; }
		}
		int32_t ctx=GetX(); int32_t cty=GetY();
		// Move to target
		while (fixtoi(fix_r) != fixtoi(target_r))
		{
			// Save step undos
			C4Real lcobjr = fix_r; C4Shape lshape=Shape;
			// Try next step
			fix_r += Sign(target_r - fix_r);
			UpdateShape();
			// attached rotation: rotate around attachment pos
			if (Action.t_attach && !fNoAttach)
			{
				// more accurately, attachment should be evaluated by a rotation around the attachment vertex
				// however, as long as this code is only used for some surfaces adjustment for large vehicles,
				// it's enough to assume rotation around the center
				ctx=GetX(); cty=GetY();
				// evaluate attachment, but do not bother about attachment loss
				// that will then be done in next execution cycle
				Shape.Attach(ctx,cty,Action.t_attach);
			}
			// check for contact
			if ((iContact=ContactCheck(ctx,cty))) // Contact
			{
				fAnyContact=true; iContacts |= t_contact;
				// Undo step and abort movement
				Shape=lshape;
				target_r = fix_r = lcobjr;
				// last UpdateShape-call might have changed sector lists!
				UpdatePos();
				// Redirect to GetY()
				if (iContact==1) if (!fRedirectYR)
						RedirectForce(rdir,ydir,-1);
				// Stop rotation
				rdir=0;
			}
			else
			{
				fTurned=1;
				if (ctx != GetX() || cty != GetY())
				{
					fix_x = itofix(ctx); fix_y = itofix(cty);
				}
			}
		}
		// Circle bounds
		if (target_r < -FixHalfCircle) { target_r += FixFullCircle; }
		if (target_r > +FixHalfCircle) { target_r -= FixFullCircle; }
		fix_r = target_r;
	}
	// Reput solid mask if moved by motion
	if (fMoved || fTurned) UpdateSolidMask(true);
	// Misc checks ===========================================================================================
	// InLiquid check
	// this equals C4Object::UpdateLiquid, but the "fNoAttach=false;"-line
	if (IsInLiquidCheck()) // In Liquid
	{
		if (!InLiquid) // Enter liquid
		{
			if (OCF & OCF_HitSpeed2) if (Mass>3)
					Splash(GetX(),GetY()+1,std::min(Shape.Wdt*Shape.Hgt/10,20),this);
			fNoAttach=false;
			InLiquid=1;
		}
	}
	else // Out of liquid
	{
		if (InLiquid) // Leave liquid
			InLiquid=0;
	}
	// Contact Action
	if (fAnyContact)
	{
		t_contact = iContacts;
		ContactAction();
	}
	// Attachment Loss Action
	if (fNoAttach)
		NoAttachAction();
	// Movement Script Execution
	if (fAnyContact)
	{
		C4AulParSet pars(C4VInt(fixtoi(oldxdir, 100)), C4VInt(fixtoi(oldydir, 100)));
		if (old_ocf & OCF_HitSpeed1) Call(PSF_Hit, &pars);
		if (old_ocf & OCF_HitSpeed2) Call(PSF_Hit2, &pars);
		if (old_ocf & OCF_HitSpeed3) Call(PSF_Hit3, &pars);
	}
	// Rotation gfx
	if (fTurned)
		UpdateFace(true);
	else
		// pos changed?
		if (fMoved) UpdatePos();
}
Exemple #5
0
bool C4SoundModifier::GetBoolProp(C4PropertyName key, bool default_value)
{
    // get scaled property and fill in default value
    C4PropList *p = props._getPropList();
    return (p->GetPropertyInt(key, int32_t(default_value ? 1 : 0)) != 0);
}
Exemple #6
0
float C4SoundModifier::GetFloatProp(C4PropertyName key, float ratio, float default_value)
{
    // get scaled property and fill in default value
    C4PropList *p = props._getPropList();
    return float(p->GetPropertyInt(key, int32_t(default_value * ratio))) / ratio;
}