Exemplo n.º 1
0
bool ObjectComPunch(C4Object *cObj, C4Object *pTarget, int32_t punch)
{
	if (!cObj || !pTarget) return false;
	if (!punch) return true;
	bool fBlowStopped = !!pTarget->Call(PSF_QueryCatchBlow,&C4AulParSet(cObj));
	if (fBlowStopped && punch>1) punch=punch/2; // half damage for caught blow, so shield+armor help in fistfight and vs monsters
	pTarget->DoEnergy(-punch, false, C4FxCall_EngGetPunched, cObj->Controller);
	int32_t tdir=+1; if (cObj->Action.Dir==DIR_Left) tdir=-1;
	pTarget->Action.ComDir=COMD_Stop;
	// No tumbles when blow was caught
	if (fBlowStopped) return false;
	// Hard punch
	if (punch>=10)
		if (ObjectActionTumble(pTarget,pTarget->Action.Dir,C4REAL100(150)*tdir,itofix(-2)))
		{
			pTarget->Call(PSF_CatchBlow,&C4AulParSet(punch, cObj));
			return true;
		}

	// Regular punch
	if (ObjectActionGetPunched(pTarget,C4REAL100(250)*tdir,Fix0))
	{
		pTarget->Call(PSF_CatchBlow,&C4AulParSet(punch, cObj));
		return true;
	}

	return false;
}
Exemplo n.º 2
0
bool C4MaterialMap::mrfScript(C4MaterialReaction *pReaction, int32_t &iX, int32_t &iY, int32_t iLSPosX, int32_t iLSPosY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, MaterialInteractionEvent evEvent, bool *pfPosChanged)
{
	// do generic checks for user-defined reactions
	if (!mrfUserCheck(pReaction, iX, iY, iLSPosX, iLSPosY, fXDir, fYDir, iPxsMat, iLsMat, evEvent, pfPosChanged))
		return false;

	// check script func
	if (!pReaction->pScriptFunc) return false;
	// OK - let's call it!
	//                      0           1           2                3                        4                           5                      6               7              8
	int32_t iXDir1, iYDir1, iXDir2, iYDir2;
	C4AulParSet pars(iX, iY, iLSPosX, iLSPosY, iXDir1 = fixtoi(fXDir, 100), iYDir1 = fixtoi(fYDir, 100), iPxsMat, iLsMat, int(evEvent));
	if (!!pReaction->pScriptFunc->Exec(NULL, &pars, false))
	{
		// PXS shall be killed!
		return true;
	}
	// PXS shall exist further: write back parameters
	iPxsMat = pars[6].getInt();
	int32_t iX2 = pars[0].getInt(), iY2 = pars[1].getInt();
	iXDir2 = pars[4].getInt(); iYDir2 = pars[5].getInt();
	if (iX!=iX2 || iY!=iY2 || iXDir1!=iXDir2 || iYDir1!=iYDir2)
	{
		// changes to pos/speed detected
		if (pfPosChanged) *pfPosChanged = true;
		iX=iX2; iY=iY2;
		fXDir = C4REAL100(iXDir2);
		fYDir = C4REAL100(iYDir2);
	}
	// OK; done
	return false;
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
void Splash(int32_t tx, int32_t ty, int32_t amt, C4Object *pByObj)
{
	// Splash only if there is free space above
	if (GBackSemiSolid(tx, ty - 15)) return;
	// get back mat
	int32_t iMat = GBackMat(tx, ty);
	// check liquid
	if (MatValid(iMat))
		if (DensityLiquid(::MaterialMap.Map[iMat].Density) && ::MaterialMap.Map[iMat].Instable)
		{
			int32_t sy = ty;
			while (GBackLiquid(tx, sy) && sy > ty - 20 && sy >= 0) sy--;
			// Splash bubbles and liquid
			for (int32_t cnt=0; cnt<amt; cnt++)
			{
				int32_t bubble_x = tx+Random(16)-8;
				int32_t bubble_y = ty+Random(16)-6;
				BubbleOut(bubble_x,bubble_y);
				if (GBackLiquid(tx,ty) && !GBackSemiSolid(tx, sy))
				{
					C4Real xdir = C4REAL100(Random(151)-75);
					C4Real ydir = C4REAL100(-Random(200));
					::PXS.Create(::Landscape.ExtractMaterial(tx,ty,false),
					             itofix(tx),itofix(sy),
					             xdir,
					             ydir);
				}
			}
		}
	// Splash sound
	if (amt>=20)
		StartSoundEffect("Splash2",false,100,pByObj);
	else if (amt>1) StartSoundEffect("Splash1",false,100,pByObj);
}
Exemplo n.º 5
0
bool mrfInsertCheck(int32_t &iX, int32_t &iY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, bool *pfPosChanged)
{
	// always manipulating pos/speed here
	if (pfPosChanged) *pfPosChanged = true;

	// Move up by up to 3px to account for moving SolidMasks, other material insertions, etc.
	int32_t mdens = std::min(::MaterialMap.Map[iPxsMat].Density, C4M_Solid);
	int32_t max_upwards = 3;
	bool was_pushed_upwards = false;
	while (max_upwards-- && (::Landscape.GetDensity(iX, iY) >= mdens))
	{
		--iY;
		was_pushed_upwards = true;
	}

	// Rough contact? May splash
	if (fYDir > itofix(1))
		if (::MaterialMap.Map[iPxsMat].SplashRate && !Random(::MaterialMap.Map[iPxsMat].SplashRate))
		{
			fYDir = -fYDir/8;
			fXDir = fXDir/8 + C4REAL100(Random(200) - 100);
			if (fYDir) return false;
		}

	// Contact: Stop
	fYDir = -GravAccel;

	// Incendiary mats smoke on contact even before doing their slide
	if (::MaterialMap.Map[iPxsMat].Incendiary)
		if (!Random(25))
		{
			Smoke(iX, iY, 4 + Random(3));
		}

	// Move by mat path/slide
	int32_t iSlideX = iX, iSlideY = iY;
	
	if (::Landscape.FindMatSlide(iSlideX,iSlideY,Sign(GravAccel),mdens,::MaterialMap.Map[iPxsMat].MaxSlide))
	{
		// Sliding on equal material: Move directly to optimize insertion of rain onto lakes
		// Also move directly when shifted upwards to ensure movement on permamently moving SolidMask
		if (iPxsMat == iLsMat || was_pushed_upwards)
			{ iX = iSlideX; iY = iSlideY; fXDir = 0; return false; }
		// Otherwise, just move using xdir/ydir for nice visuals when rain is moving over landscape
		// Accelerate into the direction
		fXDir = (fXDir * 10 + Sign(iSlideX - iX)) / 11 + C4REAL10(Random(5)-2);
		// Slide target in range? Move there directly.
		if (Abs(iX - iSlideX) <= Abs(fixtoi(fXDir)))
		{
			iX = iSlideX;
			iY = iSlideY;
			if (fYDir <= 0) fXDir = 0;
		}
		// Continue existance
		return false;
	}
	// insertion OK
	return true;
}
Exemplo n.º 6
0
void C4Sky::Execute()
{
	// surface exists?
	if (!Surface) return;
	// advance pos
	x+=xdir; y+=ydir;
	// clip by bounds
	if (x>=itofix(Width)) x-=itofix(Width);
	if (y>=itofix(Height)) y-=itofix(Height);
	// update speed
	if (ParallaxMode == C4SkyPM_Wind) xdir=C4REAL100(::Weather.Wind);
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
bool ObjectActionThrow(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
	C4Real pthrow=C4REAL100(cObj->GetPropertyInt(P_ThrowSpeed));
	int32_t iDir=1; if (cObj->Action.Dir==DIR_Left) iDir=-1;
	// Set action
	if (!cObj->SetActionByName("Throw")) return false;
	// Exit object
	pThing->Exit(cObj->GetX(),
	             cObj->GetY()+cObj->Shape.y-1,
	             Random(360),
	             pthrow*iDir+cObj->xdir,-pthrow+cObj->ydir,pthrow*iDir);
	// Success
	return true;
}
Exemplo n.º 9
0
 */

/* Object motion, collision, friction */

#include <C4Include.h>
#include <C4Object.h>

#include <C4Effect.h>
#include <C4Physics.h>
#include <C4SolidMask.h>
#include <C4Landscape.h>
#include <C4Game.h>

/* Some physical constants */

const C4Real FRedirect=C4REAL100(50);
const C4Real FFriction=C4REAL100(30);
const C4Real FixFullCircle=itofix(360),FixHalfCircle=FixFullCircle/2;
const C4Real FloatFriction=C4REAL100(2);
const C4Real RotateAccel=C4REAL100(20);
const C4Real HitSpeed1=C4REAL100(150); // Hit Event
const C4Real HitSpeed2=itofix(2); // Cross Check Hit
const C4Real HitSpeed3=itofix(6); // Scale disable, kneel
const C4Real HitSpeed4=itofix(8); // Flat
const C4Real DefaultGravAccel=C4REAL100(20);

/* Some helper functions */

void RedirectForce(C4Real &from, C4Real &to, int32_t tdir)
{
	C4Real fred;