本文整理汇总了C++中cChunk::GetPosX方法的典型用法代码示例。如果您正苦于以下问题:C++ cChunk::GetPosX方法的具体用法?C++ cChunk::GetPosX怎么用?C++ cChunk::GetPosX使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类cChunk
的用法示例。
在下文中一共展示了cChunk::GetPosX方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: SetSwimState
void cEntity::SetSwimState(cChunk & a_Chunk)
{
int RelY = (int)floor(GetPosY() + 0.1);
if ((RelY < 0) || (RelY >= cChunkDef::Height - 1))
{
m_IsSwimming = false;
m_IsSubmerged = false;
return;
}
BLOCKTYPE BlockIn;
int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
// Check if the player is swimming:
if (!a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn))
{
// This sometimes happens on Linux machines
// Ref.: http://forum.mc-server.org/showthread.php?tid=1244
LOGD("SetSwimState failure: RelX = %d, RelZ = %d, Pos = %.02f, %.02f}",
RelX, RelY, GetPosX(), GetPosZ()
);
m_IsSwimming = false;
m_IsSubmerged = false;
return;
}
m_IsSwimming = IsBlockWater(BlockIn);
// Check if the player is submerged:
VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY + 1, RelZ, BlockIn));
m_IsSubmerged = IsBlockWater(BlockIn);
}
示例2: Tick
void cSquid::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
m_PathfinderActivated = false; // Disable Pathfinding until it's fixed. TODO
// We must first process current location, and only then tick, otherwise we risk processing a location in a chunk
// that is not where the entity currently resides (FS #411)
Vector3d Pos = GetPosition();
// TODO: Not a real behavior, but cool :D
int RelY = FloorC(Pos.y);
if ((RelY < 0) || (RelY >= cChunkDef::Height))
{
return;
}
int RelX = FloorC(Pos.x) - a_Chunk.GetPosX() * cChunkDef::Width;
int RelZ = FloorC(Pos.z) - a_Chunk.GetPosZ() * cChunkDef::Width;
BLOCKTYPE BlockType;
if (a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockType) && !IsBlockWater(BlockType) && !IsOnFire())
{
// Burn for 10 ticks, then decide again
StartBurning(10);
}
super::Tick(a_Dt, a_Chunk);
}
示例3: HandlePhysics
void cFireworkEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
int PosY = POSY_TOINT;
if ((PosY < 0) || (PosY >= cChunkDef::Height))
{
goto setspeed;
}
if (m_IsInGround)
{
if (a_Chunk.GetBlock(RelX, POSY_TOINT + 1, RelZ) == E_BLOCK_AIR)
{
m_IsInGround = false;
}
else
{
return;
}
}
else
{
if (a_Chunk.GetBlock(RelX, POSY_TOINT + 1, RelZ) != E_BLOCK_AIR)
{
OnHitSolidBlock(GetPosition(), BLOCK_FACE_YM);
return;
}
}
setspeed:
AddSpeedY(1);
AddPosition(GetSpeed() * (a_Dt / 1000));
}
示例4: SetSwimState
void cPlayer::SetSwimState(cChunk & a_Chunk)
{
int RelY = (int)floor(m_LastPosY + 0.1);
if ((RelY < 0) || (RelY >= cChunkDef::Height - 1))
{
m_IsSwimming = false;
m_IsSubmerged = false;
return;
}
BLOCKTYPE BlockIn;
int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width;
int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width;
// Check if the player is swimming:
// Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk
if (!a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn))
{
// This sometimes happens on Linux machines
// Ref.: http://forum.mc-server.org/showthread.php?tid=1244
LOGD("SetSwimState failure: RelX = %d, RelZ = %d, LastPos = {%.02f, %.02f}, Pos = %.02f, %.02f}",
RelX, RelY, m_LastPosX, m_LastPosZ, GetPosX(), GetPosZ()
);
m_IsSwimming = false;
m_IsSubmerged = false;
return;
}
m_IsSwimming = IsBlockWater(BlockIn);
// Check if the player is submerged:
VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY + 1, RelZ, BlockIn));
m_IsSubmerged = IsBlockWater(BlockIn);
}
示例5: Tick
void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
if (!IsTicking())
{
// The base class tick destroyed us
return;
}
m_Timer += a_Dt;
if (m_bIsCollected)
{
if (m_Timer > std::chrono::milliseconds(500))
{
Destroy();
return;
}
}
else if (m_Timer > std::chrono::minutes(5))
{
Destroy();
return;
}
if (m_IsInGround)
{
if (!m_HasTeleported) // Sent a teleport already, don't do again
{
if (m_HitGroundTimer > std::chrono::milliseconds(500))
{
m_World->BroadcastTeleportEntity(*this);
m_HasTeleported = true;
}
else
{
m_HitGroundTimer += a_Dt;
}
}
int RelPosX = m_HitBlockPos.x - a_Chunk.GetPosX() * cChunkDef::Width;
int RelPosZ = m_HitBlockPos.z - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);
if (Chunk == nullptr)
{
// Inside an unloaded chunk, abort
return;
}
if (Chunk->GetBlock(RelPosX, m_HitBlockPos.y, RelPosZ) == E_BLOCK_AIR) // Block attached to was destroyed?
{
m_IsInGround = false; // Yes, begin simulating physics again
}
}
}
示例6: Tick
void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
m_Timer += a_Dt;
if (m_bIsCollected)
{
if (m_Timer > 500.f) // 0.5 seconds
{
Destroy();
return;
}
}
else if (m_Timer > 1000 * 60 * 5) // 5 minutes
{
Destroy();
return;
}
if (m_IsInGround)
{
// When an arrow hits, the client doesn't think its in the ground and keeps on moving, IF BroadcastMovementUpdate() and TeleportEntity was called during flight, AT ALL
// Fix is to simply not sync with the client and send a teleport to confirm pos after arrow has stabilised (around 1 sec after landing)
// We can afford to do this because xoft's algorithm for trajectory is near perfect, so things are pretty close anyway without sync
// Besides, this seems to be what the vanilla server does, note how arrows teleport half a second after they hit to the server position
if (m_HitGroundTimer != -1) // Sent a teleport already, don't do again
{
if (m_HitGroundTimer > 1000.f) // Send after a second, could be less, but just in case
{
m_World->BroadcastTeleportEntity(*this);
m_HitGroundTimer = -1;
}
else
{
m_HitGroundTimer += a_Dt;
}
}
int RelPosX = m_HitBlockPos.x - a_Chunk.GetPosX() * cChunkDef::Width;
int RelPosZ = m_HitBlockPos.z - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);
if (Chunk == NULL)
{
// Inside an unloaded chunk, abort
return;
}
if (Chunk->GetBlock(RelPosX, m_HitBlockPos.y, RelPosZ) == E_BLOCK_AIR) // Block attached to was destroyed?
{
m_IsInGround = false; // Yes, begin simulating physics again
}
}
}
示例7: Check
void cBlockHandler::Check(cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface, int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk)
{
if (!CanBeAt(a_ChunkInterface, a_RelX, a_RelY, a_RelZ, a_Chunk))
{
if (DoesDropOnUnsuitable())
{
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
DropBlock(a_ChunkInterface, *a_Chunk.GetWorld(), a_PluginInterface, nullptr, BlockX, a_RelY, BlockZ);
}
a_Chunk.SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);
}
else
{
// Wake up the simulators for this block:
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
a_Chunk.GetWorld()->GetSimulatorManager()->WakeUp(BlockX, a_RelY, BlockZ, &a_Chunk);
}
}
示例8: MoveItemsOut
/// Moves items out from this hopper into the destination. Returns true if the contents have changed.
bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
{
if (a_CurrentTick - m_LastMoveItemsOutTick < TICKS_PER_TRANSFER)
{
// Too early after the previous transfer
return false;
}
int bx, by, bz;
NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ);
if (!GetOutputBlockPos(Meta, bx, by, bz))
{
// Not attached to another container
return false;
}
if (by < 0)
{
// Cannot output below the zero-th block level
return false;
}
// Convert coords to relative:
int rx = bx - a_Chunk.GetPosX() * cChunkDef::Width;
int rz = bz - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * DestChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(rx, rz);
if (DestChunk == NULL)
{
// The destination chunk has been unloaded, don't tick
return false;
}
// Call proper moving function, based on the blocktype present at the coords:
bool res = false;
switch (DestChunk->GetBlock(rx, by, rz))
{
case E_BLOCK_CHEST: res = MoveItemsToChest(*DestChunk, bx, by, bz); break;
case E_BLOCK_FURNACE: res = MoveItemsToFurnace(*DestChunk, bx, by, bz, Meta); break;
case E_BLOCK_DISPENSER:
case E_BLOCK_DROPPER: res = MoveItemsToGrid(((cDropSpenserEntity *)DestChunk->GetBlockEntity(bx, by, bz))->GetContents()); break;
case E_BLOCK_HOPPER: res = MoveItemsToGrid(((cHopperEntity *) DestChunk->GetBlockEntity(bx, by, bz))->GetContents()); break;
case E_BLOCK_LIT_FURNACE: res = MoveItemsToFurnace(*DestChunk, bx, by, bz, Meta); break;
}
// If the item has been moved, reset the last tick:
if (res)
{
m_LastMoveItemsOutTick = a_CurrentTick;
}
return res;
}
示例9: HandlePhysics
void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
int PosY = (int)floor(GetPosY());
if ((PosY <= 0) || (PosY >= cChunkDef::Height))
{
// Outside the world, just process normal falling physics
super::HandlePhysics(a_Dt, a_Chunk);
BroadcastMovementUpdate();
return;
}
int RelPosX = (int)floor(GetPosX()) - a_Chunk.GetPosX() * cChunkDef::Width;
int RelPosZ = (int)floor(GetPosZ()) - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);
if (Chunk == NULL)
{
// Inside an unloaded chunk, bail out all processing
return;
}
BLOCKTYPE BelowType = Chunk->GetBlock(RelPosX, PosY - 1, RelPosZ);
BLOCKTYPE InsideType = Chunk->GetBlock(RelPosX, PosY, RelPosZ);
if (IsBlockRail(BelowType))
{
HandleRailPhysics(a_Dt, *Chunk);
}
else
{
if (IsBlockRail(InsideType))
{
SetPosY(PosY + 1);
HandleRailPhysics(a_Dt, *Chunk);
}
else
{
super::HandlePhysics(a_Dt, *Chunk);
BroadcastMovementUpdate();
}
}
}
示例10: Tick
void cSquid::Tick(float a_Dt, cChunk & a_Chunk)
{
// We must first process current location, and only then tick, otherwise we risk processing a location in a chunk
// that is not where the entity currently resides (FS #411)
Vector3d Pos = GetPosition();
// TODO: Not a real behavior, but cool :D
int RelY = (int)floor(Pos.y);
if ((RelY < 0) || (RelY >= cChunkDef::Height))
{
return;
}
int RelX = (int)floor(Pos.x) - a_Chunk.GetPosX() * cChunkDef::Width;
int RelZ = (int)floor(Pos.z) - a_Chunk.GetPosZ() * cChunkDef::Width;
if (!IsBlockWater(a_Chunk.GetBlock(RelX, RelY, RelZ)) && !IsOnFire())
{
// Burn for 10 ticks, then decide again
StartBurning(10);
}
super::Tick(a_Dt, a_Chunk);
}
示例11: SetSwimState
void cPlayer::SetSwimState(cChunk & a_Chunk)
{
int RelY = (int)floor(m_LastPosY + 0.1);
if ((RelY < 0) || (RelY >= cChunkDef::Height - 1))
{
m_IsSwimming = false;
m_IsSubmerged = false;
return;
}
BLOCKTYPE BlockIn;
int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width;
int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width;
// Check if the player is swimming:
// Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk
VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn));
m_IsSwimming = IsBlockWater(BlockIn);
// Check if the player is submerged:
VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY + 1, RelZ, BlockIn));
m_IsSubmerged = IsBlockWater(BlockIn);
}
示例12: HandlePhysics
void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
if (IsDestroyed()) // Mainly to stop detector rails triggering again after minecart is dead
{
return;
}
int PosY = POSY_TOINT;
if ((PosY <= 0) || (PosY >= cChunkDef::Height))
{
// Outside the world, just process normal falling physics
super::HandlePhysics(a_Dt, a_Chunk);
BroadcastMovementUpdate();
return;
}
int RelPosX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
int RelPosZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);
if (Chunk == NULL)
{
// Inside an unloaded chunk, bail out all processing
return;
}
BLOCKTYPE InsideType;
NIBBLETYPE InsideMeta;
Chunk->GetBlockTypeMeta(RelPosX, PosY, RelPosZ, InsideType, InsideMeta);
if (!IsBlockRail(InsideType))
{
Chunk->GetBlockTypeMeta(RelPosX, PosY + 1, RelPosZ, InsideType, InsideMeta); // When an descending minecart hits a flat rail, it goes through the ground; check for this
if (IsBlockRail(InsideType)) AddPosY(1); // Push cart upwards
}
bool WasDetectorRail = false;
if (IsBlockRail(InsideType))
{
if (InsideType == E_BLOCK_RAIL)
{
SnapToRail(InsideMeta);
}
else
{
SnapToRail(InsideMeta & 0x07);
}
switch (InsideType)
{
case E_BLOCK_RAIL:
HandleRailPhysics(InsideMeta, a_Dt);
break;
case E_BLOCK_ACTIVATOR_RAIL:
break;
case E_BLOCK_POWERED_RAIL:
HandlePoweredRailPhysics(InsideMeta);
break;
case E_BLOCK_DETECTOR_RAIL:
{
HandleDetectorRailPhysics(InsideMeta, a_Dt);
WasDetectorRail = true;
break;
}
default:
VERIFY(!"Unhandled rail type despite checking if block was rail!");
break;
}
AddPosition(GetSpeed() * (a_Dt / 1000)); // Commit changes; as we use our own engine when on rails, this needs to be done, whereas it is normally in Entity.cpp
}
else
{
// Not on rail, default physics
SetPosY(floor(GetPosY()) + 0.35); // HandlePhysics overrides this if minecart can fall, else, it is to stop ground clipping minecart bottom when off-rail
super::HandlePhysics(a_Dt, *Chunk);
}
if (m_bIsOnDetectorRail && !Vector3i(POSX_TOINT, POSY_TOINT, POSZ_TOINT).Equals(m_DetectorRailPosition))
{
m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07);
m_bIsOnDetectorRail = false;
}
else if (WasDetectorRail)
{
m_bIsOnDetectorRail = true;
m_DetectorRailPosition = Vector3i(POSX_TOINT, POSY_TOINT, POSZ_TOINT);
}
// Broadcast positioning changes to client
BroadcastMovementUpdate();
}
示例13: Tick
void cFallingBlock::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
// GetWorld()->BroadcastTeleportEntity(*this); // Test position
int BlockX = POSX_TOINT;
int BlockY = (int)(GetPosY() - 0.5);
int BlockZ = POSZ_TOINT;
if (BlockY < 0)
{
// Fallen out of this world, just continue falling until out of sight, then destroy:
if (BlockY < VOID_BOUNDARY)
{
Destroy(true);
}
return;
}
if (BlockY >= cChunkDef::Height)
{
// Above the world, just wait for it to fall back down
return;
}
BLOCKTYPE BlockBelow = a_Chunk.GetBlock(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
NIBBLETYPE BelowMeta = a_Chunk.GetMeta(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
if (cSandSimulator::DoesBreakFallingThrough(BlockBelow, BelowMeta))
{
// Fallen onto a block that breaks this into pickups (e. g. half-slab)
// Must finish the fall with coords one below the block:
cSandSimulator::FinishFalling(m_World, BlockX, BlockY, BlockZ, m_BlockType, m_BlockMeta);
Destroy(true);
return;
}
else if (!cSandSimulator::CanContinueFallThrough(BlockBelow))
{
// Fallen onto a solid block
/*
LOGD(
"Sand: Checked below at {%d, %d, %d} (rel {%d, %d, %d}), it's %s, finishing the fall.",
BlockX, BlockY, BlockZ,
BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width,
ItemTypeToString(BlockBelow).c_str()
);
*/
if (BlockY < cChunkDef::Height - 1)
{
cSandSimulator::FinishFalling(m_World, BlockX, BlockY + 1, BlockZ, m_BlockType, m_BlockMeta);
}
Destroy(true);
return;
}
float MilliDt = a_Dt.count() * 0.001f;
AddSpeedY(MilliDt * -9.8f);
AddPosition(GetSpeed() * MilliDt);
// If not static (one billionth precision) broadcast movement
if ((fabs(GetSpeedX()) > std::numeric_limits<double>::epsilon()) || (fabs(GetSpeedZ()) > std::numeric_limits<double>::epsilon()))
{
BroadcastMovementUpdate();
}
}
示例14: HandleRailPhysics
void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk)
{
super::HandlePhysics(a_Dt, a_Chunk); // Main physics handling
/*
NOTE: Please bear in mind that taking away from negatives make them even more negative,
adding to negatives make them positive, etc.
*/
// Get block meta below the cart
int RelPosX = (int)floor(GetPosX()) - a_Chunk.GetPosX() * cChunkDef::Width;
int RelPosZ = (int)floor(GetPosZ()) - a_Chunk.GetPosZ() * cChunkDef::Width;
NIBBLETYPE BelowMeta = a_Chunk.GetMeta(RelPosX, (int)floor(GetPosY() - 1), RelPosZ);
double SpeedX = GetSpeedX(), SpeedY = GetSpeedY(), SpeedZ = GetSpeedZ(); // Get current speed
switch (BelowMeta)
{
case E_META_RAIL_ZM_ZP: // NORTHSOUTH
{
SetRotation(270);
SpeedY = 0; // Don't move vertically as on ground
SpeedX = 0; // Correct diagonal movement from curved rails
if (SpeedZ != 0) // Don't do anything if cart is stationary
{
if (SpeedZ > 0)
{
// Going SOUTH, slow down
SpeedZ = SpeedZ - 0.1;
}
else
{
// Going NORTH, slow down
SpeedZ = SpeedZ + 0.1;
}
}
break;
}
case E_META_RAIL_XM_XP: // EASTWEST
{
SetRotation(180);
SpeedY = 0;
SpeedZ = 0;
if (SpeedX != 0)
{
if (SpeedX > 0)
{
SpeedX = SpeedX - 0.1;
}
else
{
SpeedX = SpeedX + 0.1;
}
}
break;
}
case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH
{
SetRotation(270);
SetPosY(floor(GetPosY()) + 0.2); // It seems it doesn't work without levitation :/
SpeedX = 0;
if (SpeedZ >= 0)
{
// SpeedZ POSITIVE, going SOUTH
if (SpeedZ <= MAX_SPEED) // Speed limit
{
SpeedZ = SpeedZ + 0.5; // Speed up
SpeedY = (0 - SpeedZ); // Downward movement is negative (0 minus positive numbers is negative)
}
else
{
SpeedZ = MAX_SPEED; // Enforce speed limit
SpeedY = (0 - SpeedZ);
}
}
else
{
// SpeedZ NEGATIVE, going NORTH
SpeedZ = SpeedZ + 0.4; // Slow down
SpeedY = (0 - SpeedZ); // Upward movement is positive (0 minus negative number is positive number)
}
break;
}
case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH
{
SetRotation(270);
SetPosY(floor(GetPosY()) + 0.2);
SpeedX = 0;
if (SpeedZ > 0)
{
// SpeedZ POSITIVE, going SOUTH
SpeedZ = SpeedZ - 0.4; // Slow down
SpeedY = SpeedZ; // Upward movement positive
//.........这里部分代码省略.........
示例15: TickBurning
void cEntity::TickBurning(cChunk & a_Chunk)
{
// Remember the current burning state:
bool HasBeenBurning = (m_TicksLeftBurning > 0);
if (m_World->IsWeatherWet())
{
if (POSY_TOINT > m_World->GetHeight(POSX_TOINT, POSZ_TOINT))
{
m_TicksLeftBurning = 0;
}
}
// Do the burning damage:
if (m_TicksLeftBurning > 0)
{
m_TicksSinceLastBurnDamage++;
if (m_TicksSinceLastBurnDamage >= BURN_TICKS_PER_DAMAGE)
{
if (!m_IsFireproof)
{
TakeDamage(dtOnFire, NULL, BURN_DAMAGE, 0);
}
m_TicksSinceLastBurnDamage = 0;
}
m_TicksLeftBurning--;
}
// Update the burning times, based on surroundings:
int MinRelX = (int)floor(GetPosX() - m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
int MaxRelX = (int)floor(GetPosX() + m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
int MinRelZ = (int)floor(GetPosZ() - m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
int MaxRelZ = (int)floor(GetPosZ() + m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
int MinY = std::max(0, std::min(cChunkDef::Height - 1, POSY_TOINT));
int MaxY = std::max(0, std::min(cChunkDef::Height - 1, (int)ceil (GetPosY() + m_Height)));
bool HasWater = false;
bool HasLava = false;
bool HasFire = false;
for (int x = MinRelX; x <= MaxRelX; x++)
{
for (int z = MinRelZ; z <= MaxRelZ; z++)
{
int RelX = x;
int RelZ = z;
for (int y = MinY; y <= MaxY; y++)
{
BLOCKTYPE Block;
a_Chunk.UnboundedRelGetBlockType(RelX, y, RelZ, Block);
switch (Block)
{
case E_BLOCK_FIRE:
{
HasFire = true;
break;
}
case E_BLOCK_LAVA:
case E_BLOCK_STATIONARY_LAVA:
{
HasLava = true;
break;
}
case E_BLOCK_STATIONARY_WATER:
case E_BLOCK_WATER:
{
HasWater = true;
break;
}
} // switch (BlockType)
} // for y
} // for z
} // for x
if (HasWater)
{
// Extinguish the fire
m_TicksLeftBurning = 0;
}
if (HasLava)
{
// Burn:
m_TicksLeftBurning = BURN_TICKS;
// Periodically damage:
m_TicksSinceLastLavaDamage++;
if (m_TicksSinceLastLavaDamage >= LAVA_TICKS_PER_DAMAGE)
{
if (!m_IsFireproof)
{
TakeDamage(dtLavaContact, NULL, LAVA_DAMAGE, 0);
}
m_TicksSinceLastLavaDamage = 0;
}
}
else
{
m_TicksSinceLastLavaDamage = 0;
//.........这里部分代码省略.........