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); }
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); }
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); }
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); }
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; 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); }
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; } if (HasFire) { // Burn: m_TicksLeftBurning = BURN_TICKS; // Periodically damage: m_TicksSinceLastFireDamage++; if (m_TicksSinceLastFireDamage >= FIRE_TICKS_PER_DAMAGE) { if (!m_IsFireproof) { TakeDamage(dtFireContact, NULL, FIRE_DAMAGE, 0); } m_TicksSinceLastFireDamage = 0; } } else { m_TicksSinceLastFireDamage = 0; } // If just started / finished burning, notify descendants: if ((m_TicksLeftBurning > 0) && !HasBeenBurning) { OnStartedBurning(); } else if ((m_TicksLeftBurning <= 0) && HasBeenBurning) { OnFinishedBurning(); } }