コード例 #1
0
ファイル: C4Effect.cpp プロジェクト: lluchs/clonk-rage
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(Game.Material.Map[iMat].Density) &&
        Game.Material.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++) {
        BubbleOut(tx + Random(16) - 8, ty + Random(16) - 6);
        if (GBackLiquid(tx, ty) && !GBackSemiSolid(tx, sy))
          Game.PXS.Create(Game.Landscape.ExtractMaterial(tx, ty), itofix(tx),
                          itofix(sy), FIXED100(Random(151) - 75),
                          FIXED100(-Random(200)));
      }
    }
  // Splash sound
  if (amt >= 20)
    StartSoundEffect("Splash2", false, 100, pByObj);
  else if (amt > 1)
    StartSoundEffect("Splash1", false, 100, pByObj);
}
コード例 #2
0
ファイル: C4Effect.cpp プロジェクト: 772/openclonk
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);
}
コード例 #3
0
bool C4MassMover::Init(int32_t tx, int32_t ty)
{
	// Out of bounds check
	if (!Inside<int32_t>(tx,0,::Landscape.GetWidth()-1) || !Inside<int32_t>(ty,0,::Landscape.GetHeight()-1))
		return false;
	// Check mat
	Mat=GBackMat(tx,ty);
	x=tx; y=ty;
	::MassMover.Count++;
	return (Mat!=MNone);
}
コード例 #4
0
void C4EditCursor::UpdateStatusBar()
{
	int32_t X=this->X, Y=this->Y;
	StdStrBuf str;
	switch (Mode)
	{
		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	case C4CNS_ModePlay:
		if (::MouseControl.GetCaption()) str.CopyUntil(::MouseControl.GetCaption(),'|');
		break;
		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	case C4CNS_ModeEdit:
		str.Format("%i/%i (%s)",X,Y,Target ? (Target->GetName()) : LoadResStr("IDS_CNS_NOTHING") );
		break;
		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	case C4CNS_ModeDraw:
		str.Format("%i/%i (%s)",X,Y,MatValid(GBackMat(X,Y)) ? ::MaterialMap.Map[GBackMat(X,Y)].Name : LoadResStr("IDS_CNS_NOTHING") );
		break;
		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	}
	Console.DisplayInfoText(C4ConsoleGUI::CONSOLE_Cursor, str);
}
コード例 #5
0
bool C4MassMover::Corrosion(int32_t dx, int32_t dy)
{
	// check reaction map of massmover-mat to target mat
	int32_t tmat=GBackMat(x+dx,y+dy);
	C4MaterialReaction *pReact = ::MaterialMap.GetReactionUnsafe(Mat, tmat);
	if (pReact)
	{
		C4Real xdir=Fix0, ydir=Fix0;
		if ((*pReact->pFunc)(pReact, x,y, x+dx,y+dy, xdir,ydir, Mat,tmat, meeMassMove, NULL))
			return true;
	}
	return false;
}
コード例 #6
0
ファイル: C4Shape.cpp プロジェクト: ev1313/yaC
BOOL C4Shape::ContactCheck(int32_t cx, int32_t cy) {
// Check all vertices at given object position.
// Set ContactCNAT and ContactCount.
// Set VtxContactCNAT and VtxContactMat.
// Return TRUE on any contact.

#ifdef C4ENGINE

  ContactCNAT = CNAT_None;
  ContactCount = 0;

  for (int32_t cvtx = 0; cvtx < VtxNum; cvtx++)

    // Ignore vertex if collision has been flagged out
    if (!(VtxCNAT[cvtx] & CNAT_NoCollision))

    {
      VtxContactCNAT[cvtx] = CNAT_None;
      VtxContactMat[cvtx] = GBackMat(cx + VtxX[cvtx], cy + VtxY[cvtx]);

      if (GBackDensity(cx + VtxX[cvtx], cy + VtxY[cvtx]) >= 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)
          VtxContactCNAT[cvtx] |= CNAT_Top;
        if (GBackDensity(cx + VtxX[cvtx], cy + VtxY[cvtx] + 1) >=
            ContactDensity)
          VtxContactCNAT[cvtx] |= CNAT_Bottom;
        if (GBackDensity(cx + VtxX[cvtx] - 1, cy + VtxY[cvtx]) >=
            ContactDensity)
          VtxContactCNAT[cvtx] |= CNAT_Left;
        if (GBackDensity(cx + VtxX[cvtx] + 1, cy + VtxY[cvtx]) >=
            ContactDensity)
          VtxContactCNAT[cvtx] |= CNAT_Right;
      }
    }

#endif

  return ContactCount;
}
コード例 #7
0
bool C4MassMover::Execute()
{
	int32_t tx,ty;

	// Lost target material
	if (GBackMat(x,y)!=Mat) { Cease(); return false; }

	// Check for transfer target space
	C4Material *pMat = ::MaterialMap.Map+Mat;
	tx=x; ty=y;
	if (!::Landscape.FindMatPath(tx,ty,+1,pMat->Density,pMat->MaxSlide))
	{
		// Contact material reaction check: corrosion/evaporation/inflammation/etc.
		if (Corrosion(+0,+1) || Corrosion(-1,+0) || Corrosion(+1,+0))
		{
			// material has been used up
			::Landscape.ExtractMaterial(x,y,false);
			return true;
		}

		// No space, die
		Cease(); return false;
	}

	// do check at this pos for conversion check
	/*  if (Corrosion(0,0))
	    {
	    // material has been used up by conversion
	    ::Landscape.ExtractMaterial(x,y);
	    return true;
	    }*/

	// Transfer mass
	int32_t mat = ::Landscape.ExtractMaterial(x,y,false);
	if (Random(10))
		::Landscape.InsertDeadMaterial(mat, tx, ty);
	else
		::Landscape.InsertMaterial(mat, &tx, &ty, 0, 1); // modifies tx/ty to actual insertion position

	// Create new mover at target
	::MassMover.Create(tx,ty,!Random(3));

	return true;
}
コード例 #8
0
void C4EditCursor::ApplyToolPicker()
{
	int32_t iMaterial;
	BYTE byIndex;
	switch (::Landscape.Mode)
	{
	case C4LSC_Static:
		{
			bool material_set = false;
			// Material-texture from map
			if ((byIndex=::Landscape.GetMapIndex(X/::Landscape.MapZoom,Y/::Landscape.MapZoom)))
			{
				const C4TexMapEntry *pTex = ::TextureMap.GetEntry(byIndex & (IFT-1));
				if (pTex && pTex->GetMaterialName() && *pTex->GetMaterialName())
				{
					Console.ToolsDlg.SelectMaterial(pTex->GetMaterialName());
					Console.ToolsDlg.SelectTexture(pTex->GetTextureName());
					Console.ToolsDlg.SetIFT(!!(byIndex & ~(IFT-1)));
					material_set = true;
				}
			}
			// default to sky, because invalid materials are always rendered as sky
			if (!material_set) Console.ToolsDlg.SelectMaterial(C4TLS_MatSky);
			break;
		}
	case C4LSC_Exact:
		// Material only from landscape
		if (MatValid(iMaterial=GBackMat(X,Y)))
		{
			Console.ToolsDlg.SelectMaterial(::MaterialMap.Map[iMaterial].Name);
			Console.ToolsDlg.SetIFT(!!GBackIFT(X,Y));
		}
		else
			Console.ToolsDlg.SelectMaterial(C4TLS_MatSky);
		break;
	}
	Hold=false;
}
コード例 #9
0
ファイル: C4Material.cpp プロジェクト: Rocket-Fish/openclonk
bool C4MaterialMap::mrfConvert(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)
{
	if (pReaction->fUserDefined) if (!mrfUserCheck(pReaction, iX, iY, iLSPosX, iLSPosY, fXDir, fYDir, iPxsMat, iLsMat, evEvent, pfPosChanged)) return false;
	switch (evEvent)
	{
	case meePXSMove: // PXS movement
		// for hardcoded stuff: only InMatConvert is Snow in Water, which does not have any collision proc
		if (!pReaction->fUserDefined) break;
		// user-defined conversions may also convert upon hitting materials

	case meePXSPos: // PXS check before movement
	{
		// Check depth
		int32_t iDepth = pReaction->fUserDefined ? pReaction->iDepth : ::MaterialMap.Map[iPxsMat].InMatConvertDepth;
		if (!iDepth || GBackMat(iX, iY - iDepth) == iLsMat)
		{
			// Convert
			iPxsMat = pReaction->fUserDefined ? pReaction->iConvertMat : ::MaterialMap.Map[iPxsMat].InMatConvertTo;
			if (!MatValid(iPxsMat))
				// Convert failure (target mat not be loaded, or target may be C4TLS_MatSky): Kill Pix
				return true;
			// stop movement after conversion
			fXDir = fYDir = 0;
			if (pfPosChanged) *pfPosChanged = true;
		}
	}
	break;

	case meeMassMove: // MassMover-movement
		// Conversion-transfer to PXS
		::PXS.Create(iPxsMat,itofix(iX),itofix(iY));
		return true;
	}
	// not handled
	return false;
}
コード例 #10
0
void C4PXS::Execute()
{
#ifdef DEBUGREC_PXS
	if (Config.General.DebugRec)
	{
		C4RCExecPXS rc;
		rc.x=x; rc.y=y; rc.iMat=Mat;
		rc.pos = 0;
		AddDbgRec(RCT_ExecPXS, &rc, sizeof(rc));
	}
#endif
	int32_t inmat;

	// Safety
	if (!MatValid(Mat))
		{ Deactivate(); return; }

	// Out of bounds
	if ((x<0) || (x>=::Landscape.GetWidth()) || (y<-10) || (y>=::Landscape.GetHeight()))
		{ Deactivate(); return; }

	// Material conversion
	int32_t iX = fixtoi(x), iY = fixtoi(y);
	inmat=GBackMat(iX,iY);
	C4MaterialReaction *pReact = ::MaterialMap.GetReactionUnsafe(Mat, inmat);
	if (pReact && (*pReact->pFunc)(pReact, iX,iY, iX,iY, xdir,ydir, Mat,inmat, meePXSPos, NULL))
		{ Deactivate(); return; }

	// Gravity
	ydir+=GravAccel;

	if (GBackDensity(iX, iY + 1) < ::MaterialMap.Map[Mat].Density)
	{
		// Air speed: Wind plus some random
		int32_t iWind = Weather.GetWind(iX, iY);
		C4Real txdir = itofix(iWind, 15) + C4REAL256(Random(1200) - 600);
		C4Real tydir = C4REAL256(Random(1200) - 600);

		// Air friction, based on WindDrift. MaxSpeed is ignored.
		int32_t iWindDrift = std::max(::MaterialMap.Map[Mat].WindDrift - 20, 0);
		xdir += ((txdir - xdir) * iWindDrift) * WindDrift_Factor;
		ydir += ((tydir - ydir) * iWindDrift) * WindDrift_Factor;
	}

	C4Real ctcox = x + xdir;
	C4Real ctcoy = y + ydir;

	int32_t iToX = fixtoi(ctcox), iToY = fixtoi(ctcoy);

	// In bounds?
	if (Inside<int32_t>(iToX, 0, ::Landscape.GetWidth()-1) && Inside<int32_t>(iToY, 0, ::Landscape.GetHeight()-1))
		// Check path
		if (::Landscape._PathFree(iX, iY, iToX, iToY))
		{
			x=ctcox; y=ctcoy;
			return;
		}

	// Test path to target position
	int32_t iX0 = iX, iY0 = iY;
	bool fStopMovement = false;
	do
	{
		// Step
		int32_t inX = iX + Sign(iToX - iX), inY = iY + Sign(iToY - iY);
		// Contact?
		inmat = GBackMat(inX, inY);
		C4MaterialReaction *pReact = ::MaterialMap.GetReactionUnsafe(Mat, inmat);
		if (pReact)
		{
			if ((*pReact->pFunc)(pReact, iX,iY, inX,inY, xdir,ydir, Mat,inmat, meePXSMove, &fStopMovement))
			{
				// destructive contact
				Deactivate();
				return;
			}
			else
			{
				// no destructive contact, but speed or position changed: Stop moving for now
				if (fStopMovement)
				{
					// But keep fractional positions to allow proper movement on moving ground
					if (iX != iX0) x = itofix(iX);
					if (iY != iY0) y = itofix(iY);
					return;
				}
				// there was a reaction func, but it didn't do anything - continue movement
			}
		}
		iX = inX; iY = inY;
	}
	while (iX != iToX || iY != iToY);

	// No contact? Free movement
	x=ctcox; y=ctcoy;
#ifdef DEBUGREC_PXS
	if (Config.General.DebugRec)
	{
		C4RCExecPXS rc;
		rc.x=x; rc.y=y; rc.iMat=Mat;
		rc.pos = 1;
		AddDbgRec(RCT_ExecPXS, &rc, sizeof(rc));
	}
#endif
	return;
}
コード例 #11
0
ファイル: C4Effect.cpp プロジェクト: lluchs/clonk-rage
int32_t FnFxFireStart(C4AulContext *ctx, C4Object *pObj, int32_t iNumber,
                      int32_t iTemp, int32_t iCausedBy, bool fBlasted,
                      C4Object *pIncineratingObject) {
  // safety
  if (!pObj)
    return -1;
  // temp readd
  if (iTemp) {
    pObj->SetOnFire(true);
    return 1;
  }
  // fail if already on fire
  if (pObj->GetOnFire())
    return -1;
  // get associated effect
  C4Effect *pEffect;
  if (!(pEffect = pObj->pEffects))
    return -1;
  if (!(pEffect = pEffect->Get(iNumber, true)))
    return -1;
  // structures must eject contents now, because DoCon is not guaranteed to be
  // executed!
  // In extinguishing material
  BOOL fFireCaused = TRUE;
  int32_t iMat;
  if (MatValid(iMat = GBackMat(pObj->x, pObj->y)))
    if (Game.Material.Map[iMat].Extinguisher) {
      // blasts should changedef in water, too!
      if (fBlasted)
        if (pObj->Def->BurnTurnTo != C4ID_None)
          pObj->ChangeDef(pObj->Def->BurnTurnTo);
      // no fire caused
      fFireCaused = FALSE;
    }
  // BurnTurnTo
  if (fFireCaused)
    if (pObj->Def->BurnTurnTo != C4ID_None)
      pObj->ChangeDef(pObj->Def->BurnTurnTo);
  // eject contents
  C4Object *cobj;
  if (!pObj->Def->IncompleteActivity && !pObj->Def->NoBurnDecay)
    while (cobj = pObj->Contents.GetObject()) {
      cobj->Controller = iCausedBy; // update controller, so incinerating a hut
                                    // full of flints attributes the damage to
                                    // the incinerator
      if (pObj->Contained)
        cobj->Enter(pObj->Contained);
      else
        cobj->Exit(cobj->x, cobj->y);
    }
  // Detach attached objects
  cobj = 0;
  if (!pObj->Def->IncompleteActivity && !pObj->Def->NoBurnDecay)
    while (cobj = Game.FindObject(0, 0, 0, 0, 0, OCF_All, 0, pObj, 0, 0,
                                  ANY_OWNER, cobj))
      if ((cobj->Action.Act > ActIdle) &&
          (cobj->Def->ActMap[cobj->Action.Act].Procedure == DFA_ATTACH))
        cobj->SetAction(ActIdle);
  // fire caused?
  if (!fFireCaused) {
    // if object was blasted but not incinerated (i.e., inside extinguisher)
    // do a script callback
    if (fBlasted)
      pObj->Call(PSF_IncinerationEx, &C4AulParSet(C4VInt(iCausedBy)));
    return -1;
  }
  // determine fire appearance
  int32_t iFireMode;
  if (!(iFireMode = pObj->Call(PSF_FireMode).getInt())) {
    // set default fire modes
    DWORD dwCat = pObj->Category;
    if (dwCat & (C4D_Living | C4D_StaticBack)) // Tiere, Bäume
      iFireMode = C4Fx_FireMode_LivingVeg;
    else if (dwCat & (C4D_Structure | C4D_Vehicle)) // Gebäude und Fahrzeuge
                                                    // sind unten meist kantig
      iFireMode = C4Fx_FireMode_StructVeh;
    else
      iFireMode = C4Fx_FireMode_Object;
  } else if (!Inside<int32_t>(iFireMode, 1, C4Fx_FireMode_Last)) {
    DebugLogF("Warning: FireMode %d of object %s (%s) is invalid!", iFireMode,
              pObj->GetName(), pObj->Def->GetName());
    iFireMode = C4Fx_FireMode_Object;
  }
  // store causes in effect vars
  FxFireVarMode(pEffect).SetInt(iFireMode);
  FxFireVarCausedBy(pEffect)
      .SetInt(iCausedBy); // used in C4Object::GetFireCause and timer!
  FxFireVarBlasted(pEffect).SetBool(fBlasted);
  FxFireVarIncineratingObj(pEffect).SetObject(pIncineratingObject);
  // Set values
  pObj->SetOnFire(true);
  pObj->FirePhase = Random(MaxFirePhase);
  if (pObj->Shape.Wdt * pObj->Shape.Hgt > 500)
    StartSoundEffect("Inflame", false, 100, pObj);
  if (pObj->Def->Mass >= 100)
    StartSoundEffect("Fire", true, 100, pObj);
  // Engine script call
  pObj->Call(PSF_Incineration, &C4AulParSet(C4VInt(iCausedBy)));
  // Done, success
  return C4Fx_OK;
}