Rename cEntity swim states (#3996)
* Replace cEntity:m_IsSubmerged with m_IsHeadInWater * Replace cEntity:m_IsSwimming with m_IsInWater * Add API documentation for new symbols * Apply SetSwimState to all entities, not just mobs and players * Pickups now use IsOnFire to check if they are on fire before destruction Fixes #3987
This commit is contained in:
parent
44519225b2
commit
ad22922393
@ -3724,6 +3724,46 @@ local Hash = cCryptoHash.sha1HexString("DataToHash")
|
|||||||
},
|
},
|
||||||
Notes = "Returns true if the entity is invisible",
|
Notes = "Returns true if the entity is invisible",
|
||||||
},
|
},
|
||||||
|
IsInFire =
|
||||||
|
{
|
||||||
|
Returns =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Type = "boolean",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Notes = "Returns true if any part of the entity is in a fire block",
|
||||||
|
},
|
||||||
|
IsInLava =
|
||||||
|
{
|
||||||
|
Returns =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Type = "boolean",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Notes = "Returns true if any part of the entity is in a lava block",
|
||||||
|
},
|
||||||
|
IsInWater =
|
||||||
|
{
|
||||||
|
Returns =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Type = "boolean",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Notes = "Returns true if any part of the entity is in a water block",
|
||||||
|
},
|
||||||
|
IsHeadInWater =
|
||||||
|
{
|
||||||
|
Returns =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Type = "boolean",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Notes = "Returns true if the entity's head is in a water block",
|
||||||
|
},
|
||||||
IsItemFrame =
|
IsItemFrame =
|
||||||
{
|
{
|
||||||
Returns =
|
Returns =
|
||||||
@ -3872,7 +3912,7 @@ local Hash = cCryptoHash.sha1HexString("DataToHash")
|
|||||||
Type = "boolean",
|
Type = "boolean",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Notes = "Returns true if the mob or player is submerged in water (head is in a water block). Note, this function is only updated with mobs or players.",
|
Notes = "Returns true if the entity's head is in a water block <b>Currently deprecated in favour of IsHeadInWater()</b>",
|
||||||
},
|
},
|
||||||
IsSwimming =
|
IsSwimming =
|
||||||
{
|
{
|
||||||
@ -3882,7 +3922,7 @@ local Hash = cCryptoHash.sha1HexString("DataToHash")
|
|||||||
Type = "boolean",
|
Type = "boolean",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Notes = "Returns true if the mob or player is swimming in water (feet are in a water block). Note, this function is only updated with mobs or players.",
|
Notes = "Returns true if any part of the entity is in a water block. Note, this function is only updated with mobs or players. <b>Currently deprecated in favour of IsInWater()</b>",
|
||||||
},
|
},
|
||||||
IsTicking =
|
IsTicking =
|
||||||
{
|
{
|
||||||
|
@ -3954,6 +3954,56 @@ static int tolua_cCompositeChat_UnderlineUrls(lua_State * tolua_S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int tolua_cEntity_IsSubmerged(lua_State * tolua_S)
|
||||||
|
{
|
||||||
|
// Check the params:
|
||||||
|
cLuaState L(tolua_S);
|
||||||
|
if (!L.CheckParamSelf("cEntity"))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the params:
|
||||||
|
cEntity * self = nullptr;
|
||||||
|
L.GetStackValue(1, self);
|
||||||
|
|
||||||
|
// API function deprecated:
|
||||||
|
LOGWARNING("cEntity:IsSubmerged() is deprecated. Use cEntity:IsHeadInWater() instead.");
|
||||||
|
cLuaState::LogStackTrace(tolua_S);
|
||||||
|
|
||||||
|
L.Push(self->IsHeadInWater());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int tolua_cEntity_IsSwimming(lua_State * tolua_S)
|
||||||
|
{
|
||||||
|
// Check the params:
|
||||||
|
cLuaState L(tolua_S);
|
||||||
|
if (!L.CheckParamSelf("cEntity"))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the params:
|
||||||
|
cEntity * self = nullptr;
|
||||||
|
L.GetStackValue(1, self);
|
||||||
|
|
||||||
|
// API function deprecated
|
||||||
|
LOGWARNING("cEntity:IsSwimming() is deprecated. Use cEntity:IsInWater() instead.");
|
||||||
|
cLuaState::LogStackTrace(tolua_S);
|
||||||
|
|
||||||
|
L.Push(self->IsInWater());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tolua_cEntity_GetPosition(lua_State * tolua_S)
|
static int tolua_cEntity_GetPosition(lua_State * tolua_S)
|
||||||
{
|
{
|
||||||
cLuaState L(tolua_S);
|
cLuaState L(tolua_S);
|
||||||
@ -4073,6 +4123,8 @@ void cManualBindings::Bind(lua_State * tolua_S)
|
|||||||
|
|
||||||
tolua_beginmodule(tolua_S, "cEntity");
|
tolua_beginmodule(tolua_S, "cEntity");
|
||||||
tolua_constant(tolua_S, "INVALID_ID", cEntity::INVALID_ID);
|
tolua_constant(tolua_S, "INVALID_ID", cEntity::INVALID_ID);
|
||||||
|
tolua_function(tolua_S, "IsSubmerged", tolua_cEntity_IsSubmerged);
|
||||||
|
tolua_function(tolua_S, "IsSwimming", tolua_cEntity_IsSwimming);
|
||||||
tolua_function(tolua_S, "GetPosition", tolua_cEntity_GetPosition);
|
tolua_function(tolua_S, "GetPosition", tolua_cEntity_GetPosition);
|
||||||
tolua_function(tolua_S, "GetSpeed", tolua_cEntity_GetSpeed);
|
tolua_function(tolua_S, "GetSpeed", tolua_cEntity_GetSpeed);
|
||||||
tolua_endmodule(tolua_S);
|
tolua_endmodule(tolua_S);
|
||||||
@ -4238,7 +4290,3 @@ void cManualBindings::Bind(lua_State * tolua_S)
|
|||||||
|
|
||||||
tolua_endmodule(tolua_S);
|
tolua_endmodule(tolua_S);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos)
|
|||||||
double KnockbackAmount = 11 + 10 * PunchLevel;
|
double KnockbackAmount = 11 + 10 * PunchLevel;
|
||||||
a_EntityHit.TakeDamage(dtRangedAttack, GetCreatorUniqueID(), Damage, KnockbackAmount);
|
a_EntityHit.TakeDamage(dtRangedAttack, GetCreatorUniqueID(), Damage, KnockbackAmount);
|
||||||
|
|
||||||
if (IsOnFire() && !a_EntityHit.IsSubmerged() && !a_EntityHit.IsSwimming())
|
if (IsOnFire() && !a_EntityHit.IsInWater())
|
||||||
{
|
{
|
||||||
a_EntityHit.StartBurning(100);
|
a_EntityHit.StartBurning(100);
|
||||||
}
|
}
|
||||||
@ -218,7 +218,3 @@ void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,8 +54,10 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
|
|||||||
m_TicksSinceLastFireDamage(0),
|
m_TicksSinceLastFireDamage(0),
|
||||||
m_TicksLeftBurning(0),
|
m_TicksLeftBurning(0),
|
||||||
m_TicksSinceLastVoidDamage(0),
|
m_TicksSinceLastVoidDamage(0),
|
||||||
m_IsSwimming(false),
|
m_IsInFire(false),
|
||||||
m_IsSubmerged(false),
|
m_IsInLava(false),
|
||||||
|
m_IsInWater(false),
|
||||||
|
m_IsHeadInWater(false),
|
||||||
m_AirLevel(MAX_AIR_LEVEL),
|
m_AirLevel(MAX_AIR_LEVEL),
|
||||||
m_AirTickTimer(DROWNING_TICKS),
|
m_AirTickTimer(DROWNING_TICKS),
|
||||||
m_TicksAlive(0),
|
m_TicksAlive(0),
|
||||||
@ -477,11 +479,11 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
|
|||||||
{
|
{
|
||||||
BurnTicks += 4 * (FireAspectLevel - 1);
|
BurnTicks += 4 * (FireAspectLevel - 1);
|
||||||
}
|
}
|
||||||
if (!IsMob() && !IsSubmerged() && !IsSwimming())
|
if (!IsMob() && !IsInWater())
|
||||||
{
|
{
|
||||||
StartBurning(BurnTicks * 20);
|
StartBurning(BurnTicks * 20);
|
||||||
}
|
}
|
||||||
else if (IsMob() && !IsSubmerged() && !IsSwimming())
|
else if (IsMob() && !IsInWater())
|
||||||
{
|
{
|
||||||
cMonster * Monster = reinterpret_cast<cMonster *>(this);
|
cMonster * Monster = reinterpret_cast<cMonster *>(this);
|
||||||
switch (Monster->GetMobType())
|
switch (Monster->GetMobType())
|
||||||
@ -831,6 +833,7 @@ void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
m_InvulnerableTicks--;
|
m_InvulnerableTicks--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Non-players are destroyed as soon as they fall out of the world:
|
||||||
if ((GetPosY() < 0) && (!IsPlayer()))
|
if ((GetPosY() < 0) && (!IsPlayer()))
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
@ -848,11 +851,16 @@ void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Position changed -> super::Tick() called
|
// Position changed -> super::Tick() called:
|
||||||
GET_AND_VERIFY_CURRENT_CHUNK(NextChunk, POSX_TOINT, POSZ_TOINT)
|
GET_AND_VERIFY_CURRENT_CHUNK(NextChunk, POSX_TOINT, POSZ_TOINT)
|
||||||
|
|
||||||
|
// Set swim states (water, lava, and fire):
|
||||||
|
SetSwimState(*NextChunk);
|
||||||
|
|
||||||
|
// Handle catching on fire and burning:
|
||||||
TickBurning(*NextChunk);
|
TickBurning(*NextChunk);
|
||||||
|
|
||||||
|
// Damage players if they are in the void
|
||||||
if (GetPosY() < VOID_BOUNDARY)
|
if (GetPosY() < VOID_BOUNDARY)
|
||||||
{
|
{
|
||||||
TickInVoid(*NextChunk);
|
TickInVoid(*NextChunk);
|
||||||
@ -862,6 +870,7 @@ void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
m_TicksSinceLastVoidDamage = 0;
|
m_TicksSinceLastVoidDamage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle cactus damage or destruction:
|
||||||
if (
|
if (
|
||||||
IsMob() || IsPickup() || IsExpOrb() ||
|
IsMob() || IsPickup() || IsExpOrb() ||
|
||||||
(IsPlayer() && !((reinterpret_cast<cPlayer *>(this))->IsGameModeCreative() || (reinterpret_cast<cPlayer *>(this))->IsGameModeSpectator()))
|
(IsPlayer() && !((reinterpret_cast<cPlayer *>(this))->IsGameModeCreative() || (reinterpret_cast<cPlayer *>(this))->IsGameModeSpectator()))
|
||||||
@ -869,12 +878,10 @@ void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
{
|
{
|
||||||
DetectCacti();
|
DetectCacti();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle drowning:
|
||||||
if (IsMob() || IsPlayer())
|
if (IsMob() || IsPlayer())
|
||||||
{
|
{
|
||||||
// Set swimming state
|
|
||||||
SetSwimState(*NextChunk);
|
|
||||||
|
|
||||||
// Handle drowning
|
|
||||||
HandleAir();
|
HandleAir();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1192,60 +1199,13 @@ void cEntity::TickBurning(cChunk & a_Chunk)
|
|||||||
m_TicksLeftBurning--;
|
m_TicksLeftBurning--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the burning times, based on surroundings:
|
if (IsInWater())
|
||||||
int MinRelX = FloorC(GetPosX() - m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
|
|
||||||
int MaxRelX = FloorC(GetPosX() + m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
|
|
||||||
int MinRelZ = FloorC(GetPosZ() - m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
|
|
||||||
int MaxRelZ = FloorC(GetPosZ() + m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
|
|
||||||
int MinY = Clamp(POSY_TOINT, 0, cChunkDef::Height - 1);
|
|
||||||
int MaxY = Clamp(FloorC(GetPosY() + m_Height), 0, cChunkDef::Height - 1);
|
|
||||||
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
|
// Extinguish the fire
|
||||||
m_TicksLeftBurning = 0;
|
m_TicksLeftBurning = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasLava)
|
if (IsInLava())
|
||||||
{
|
{
|
||||||
// Burn:
|
// Burn:
|
||||||
m_TicksLeftBurning = BURN_TICKS;
|
m_TicksLeftBurning = BURN_TICKS;
|
||||||
@ -1266,7 +1226,7 @@ void cEntity::TickBurning(cChunk & a_Chunk)
|
|||||||
m_TicksSinceLastLavaDamage = 0;
|
m_TicksSinceLastLavaDamage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasFire)
|
if (IsInFire())
|
||||||
{
|
{
|
||||||
// Burn:
|
// Burn:
|
||||||
m_TicksLeftBurning = BURN_TICKS;
|
m_TicksLeftBurning = BURN_TICKS;
|
||||||
@ -1275,7 +1235,7 @@ void cEntity::TickBurning(cChunk & a_Chunk)
|
|||||||
m_TicksSinceLastFireDamage++;
|
m_TicksSinceLastFireDamage++;
|
||||||
if (m_TicksSinceLastFireDamage >= FIRE_TICKS_PER_DAMAGE)
|
if (m_TicksSinceLastFireDamage >= FIRE_TICKS_PER_DAMAGE)
|
||||||
{
|
{
|
||||||
if (!IsFireproof() && !HasLava)
|
if (!IsFireproof() && !IsInLava())
|
||||||
{
|
{
|
||||||
TakeDamage(dtFireContact, nullptr, FIRE_DAMAGE, 0);
|
TakeDamage(dtFireContact, nullptr, FIRE_DAMAGE, 0);
|
||||||
}
|
}
|
||||||
@ -1644,37 +1604,70 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn)
|
|||||||
|
|
||||||
void cEntity::SetSwimState(cChunk & a_Chunk)
|
void cEntity::SetSwimState(cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
|
m_IsInFire = false;
|
||||||
|
m_IsInLava = false;
|
||||||
|
m_IsInWater = false;
|
||||||
|
m_IsHeadInWater = false;
|
||||||
|
|
||||||
int RelY = FloorC(GetPosY() + 0.1);
|
int RelY = FloorC(GetPosY() + 0.1);
|
||||||
int HeadRelY = CeilC(GetPosY() + GetHeight()) - 1;
|
int HeadRelY = CeilC(GetPosY() + GetHeight()) - 1;
|
||||||
ASSERT(RelY <= HeadRelY);
|
ASSERT(RelY <= HeadRelY);
|
||||||
if ((RelY < 0) || (HeadRelY >= cChunkDef::Height))
|
if ((RelY < 0) || (HeadRelY >= cChunkDef::Height))
|
||||||
{
|
{
|
||||||
m_IsSwimming = false;
|
|
||||||
m_IsSubmerged = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLOCKTYPE BlockIn;
|
int MinRelX = FloorC(GetPosX() - m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
|
||||||
|
int MaxRelX = FloorC(GetPosX() + m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
|
||||||
|
int MinRelZ = FloorC(GetPosZ() - m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||||
|
int MaxRelZ = FloorC(GetPosZ() + m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||||
|
int MinY = Clamp(POSY_TOINT, 0, cChunkDef::Height - 1);
|
||||||
|
int MaxY = Clamp(FloorC(GetPosY() + m_Height), 0, cChunkDef::Height - 1);
|
||||||
|
|
||||||
|
for (int x = MinRelX; x <= MaxRelX; x++)
|
||||||
|
{
|
||||||
|
for (int z = MinRelZ; z <= MaxRelZ; z++)
|
||||||
|
{
|
||||||
|
for (int y = MinY; y <= MaxY; y++)
|
||||||
|
{
|
||||||
|
BLOCKTYPE Block;
|
||||||
|
if (!a_Chunk.UnboundedRelGetBlockType(x, y, z, Block))
|
||||||
|
{
|
||||||
|
LOGD("SetSwimState failure: RelX = %d, RelY = %d, RelZ = %d, Pos = %.02f, %.02f}",
|
||||||
|
x, y, z, GetPosX(), GetPosZ()
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Block == E_BLOCK_FIRE)
|
||||||
|
{
|
||||||
|
m_IsInFire = true;
|
||||||
|
}
|
||||||
|
else if (IsBlockLava(Block))
|
||||||
|
{
|
||||||
|
m_IsInLava = true;
|
||||||
|
}
|
||||||
|
else if (IsBlockWater(Block))
|
||||||
|
{
|
||||||
|
m_IsInWater = true;
|
||||||
|
}
|
||||||
|
} // for y
|
||||||
|
} // for z
|
||||||
|
} // for x
|
||||||
|
|
||||||
|
// Check if the entity's head is in water.
|
||||||
int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
|
int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
|
||||||
int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
|
int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||||
|
int HeadHeight = CeilC(GetPosY() + GetHeight()) - 1;
|
||||||
// Check if the player is swimming:
|
BLOCKTYPE BlockIn;
|
||||||
if (!a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn))
|
if (!a_Chunk.UnboundedRelGetBlockType(RelX, HeadHeight, RelZ, BlockIn))
|
||||||
{
|
{
|
||||||
// This sometimes happens on Linux machines
|
LOGD("SetSwimState failure: RelX = %d, RelY = %d, RelZ = %d, Pos = %.02f, %.02f}",
|
||||||
// Ref.: https://forum.cuberite.org/thread-1244.html
|
RelX, HeadHeight, RelZ, GetPosX(), GetPosZ()
|
||||||
LOGD("SetSwimState failure: RelX = %d, RelZ = %d, Pos = %.02f, %.02f}",
|
|
||||||
RelX, RelY, GetPosX(), GetPosZ()
|
|
||||||
);
|
);
|
||||||
m_IsSwimming = false;
|
|
||||||
m_IsSubmerged = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_IsSwimming = IsBlockWater(BlockIn);
|
m_IsHeadInWater = IsBlockWater(BlockIn);
|
||||||
|
|
||||||
// Check if the player is submerged:
|
|
||||||
VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, HeadRelY, RelZ, BlockIn));
|
|
||||||
m_IsSubmerged = IsBlockWater(BlockIn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1710,7 +1703,7 @@ void cEntity::HandleAir(void)
|
|||||||
|
|
||||||
int RespirationLevel = static_cast<int>(GetEquippedHelmet().m_Enchantments.GetLevel(cEnchantments::enchRespiration));
|
int RespirationLevel = static_cast<int>(GetEquippedHelmet().m_Enchantments.GetLevel(cEnchantments::enchRespiration));
|
||||||
|
|
||||||
if (IsSubmerged())
|
if (IsHeadInWater())
|
||||||
{
|
{
|
||||||
if (!IsPlayer()) // Players control themselves
|
if (!IsPlayer()) // Players control themselves
|
||||||
{
|
{
|
||||||
|
@ -481,11 +481,17 @@ public:
|
|||||||
virtual bool IsRclking (void) const {return false; }
|
virtual bool IsRclking (void) const {return false; }
|
||||||
virtual bool IsInvisible(void) const { return false; }
|
virtual bool IsInvisible(void) const { return false; }
|
||||||
|
|
||||||
/** Returns whether the player is swimming or not */
|
/** Returns true if any part of the entity is in a fire block */
|
||||||
virtual bool IsSwimming(void) const{ return m_IsSwimming; }
|
virtual bool IsInFire(void) const { return m_IsInFire; }
|
||||||
|
|
||||||
/** Return whether the player is under water or not */
|
/** Returns true if any part of the entity is in a lava block */
|
||||||
virtual bool IsSubmerged(void) const{ return m_IsSubmerged; }
|
virtual bool IsInLava(void) const { return m_IsInLava; }
|
||||||
|
|
||||||
|
/** Returns true if any part of the entity is in a water block */
|
||||||
|
virtual bool IsInWater(void) const { return m_IsInWater; }
|
||||||
|
|
||||||
|
/** Returns true if any part of the entity is in a water block */
|
||||||
|
virtual bool IsHeadInWater(void) const { return m_IsHeadInWater; }
|
||||||
|
|
||||||
/** Gets remaining air of a monster */
|
/** Gets remaining air of a monster */
|
||||||
int GetAirLevel(void) const { return m_AirLevel; }
|
int GetAirLevel(void) const { return m_AirLevel; }
|
||||||
@ -619,8 +625,17 @@ protected:
|
|||||||
/** Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void. */
|
/** Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void. */
|
||||||
int m_TicksSinceLastVoidDamage;
|
int m_TicksSinceLastVoidDamage;
|
||||||
|
|
||||||
/** If an entity is currently swimming in or submerged under water */
|
/** If any part of the entity is in a fire block */
|
||||||
bool m_IsSwimming, m_IsSubmerged;
|
bool m_IsInFire;
|
||||||
|
|
||||||
|
/** If any part of the entity is in a lava block */
|
||||||
|
bool m_IsInLava;
|
||||||
|
|
||||||
|
/** If any part of the entity is in a water block */
|
||||||
|
bool m_IsInWater;
|
||||||
|
|
||||||
|
/** If the entity's head is in a water block */
|
||||||
|
bool m_IsHeadInWater;
|
||||||
|
|
||||||
/** Air level of a mobile */
|
/** Air level of a mobile */
|
||||||
int m_AirLevel;
|
int m_AirLevel;
|
||||||
@ -647,7 +662,8 @@ protected:
|
|||||||
/** Called in each tick to handle air-related processing i.e. drowning */
|
/** Called in each tick to handle air-related processing i.e. drowning */
|
||||||
virtual void HandleAir(void);
|
virtual void HandleAir(void);
|
||||||
|
|
||||||
/** Called once per tick to set IsSwimming and IsSubmerged */
|
/** Called once per tick to set m_IsInFire, m_IsInLava, m_IsInWater and
|
||||||
|
m_IsHeadInWater */
|
||||||
virtual void SetSwimState(cChunk & a_Chunk);
|
virtual void SetSwimState(cChunk & a_Chunk);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -693,7 +709,3 @@ private:
|
|||||||
cMonsterList m_LeashedMobs;
|
cMonsterList m_LeashedMobs;
|
||||||
|
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ bool cPawn::IsInvisible() const
|
|||||||
|
|
||||||
void cPawn::HandleAir(void)
|
void cPawn::HandleAir(void)
|
||||||
{
|
{
|
||||||
if (IsSubmerged() && HasEntityEffect(cEntityEffect::effWaterBreathing))
|
if (IsHeadInWater() && HasEntityEffect(cEntityEffect::effWaterBreathing))
|
||||||
{
|
{
|
||||||
// Prevent the oxygen from decreasing
|
// Prevent the oxygen from decreasing
|
||||||
return;
|
return;
|
||||||
@ -486,6 +486,3 @@ cEntityEffect * cPawn::GetEntityEffect(cEntityEffect::eType a_EffectType)
|
|||||||
auto itr = m_EntityEffects.find(a_EffectType);
|
auto itr = m_EntityEffects.find(a_EffectType);
|
||||||
return (itr != m_EntityEffects.end()) ? itr->second.get() : nullptr;
|
return (itr != m_EntityEffects.end()) ? itr->second.get() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,17 +147,8 @@ void cPickup::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
// Position might have changed due to physics. So we have to make sure we have the correct chunk.
|
// Position might have changed due to physics. So we have to make sure we have the correct chunk.
|
||||||
GET_AND_VERIFY_CURRENT_CHUNK(CurrentChunk, BlockX, BlockZ)
|
GET_AND_VERIFY_CURRENT_CHUNK(CurrentChunk, BlockX, BlockZ)
|
||||||
|
|
||||||
int RelBlockX = BlockX - (CurrentChunk->GetPosX() * cChunkDef::Width);
|
// Destroy the pickup if it is on fire:
|
||||||
int RelBlockZ = BlockZ - (CurrentChunk->GetPosZ() * cChunkDef::Width);
|
if (IsOnFire())
|
||||||
|
|
||||||
// If the pickup is on the bottommost block position, make it think the void is made of air: (#131)
|
|
||||||
BLOCKTYPE BlockBelow = (BlockY > 0) ? CurrentChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
|
|
||||||
BLOCKTYPE BlockIn = CurrentChunk->GetBlock(RelBlockX, BlockY, RelBlockZ);
|
|
||||||
|
|
||||||
if (
|
|
||||||
IsBlockLava(BlockBelow) || (BlockBelow == E_BLOCK_FIRE) ||
|
|
||||||
IsBlockLava(BlockIn) || (BlockIn == E_BLOCK_FIRE)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
m_bCollected = true;
|
m_bCollected = true;
|
||||||
m_Timer = std::chrono::milliseconds(0); // We have to reset the timer.
|
m_Timer = std::chrono::milliseconds(0); // We have to reset the timer.
|
||||||
@ -261,7 +252,3 @@ bool cPickup::CollectedBy(cPlayer & a_Dest)
|
|||||||
// LOG("Pickup %d cannot be collected by \"%s\", because there's no space in the inventory.", a_Dest->GetName().c_str(), m_UniqueID);
|
// LOG("Pickup %d cannot be collected by \"%s\", because there's no space in the inventory.", a_Dest->GetName().c_str(), m_UniqueID);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,9 +92,6 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
|
|||||||
{
|
{
|
||||||
ASSERT(a_PlayerName.length() <= 16); // Otherwise this player could crash many clients...
|
ASSERT(a_PlayerName.length() <= 16); // Otherwise this player could crash many clients...
|
||||||
|
|
||||||
m_IsSwimming = false;
|
|
||||||
m_IsSubmerged = false;
|
|
||||||
|
|
||||||
m_InventoryWindow = new cInventoryWindow(*this);
|
m_InventoryWindow = new cInventoryWindow(*this);
|
||||||
m_CurrentWindow = m_InventoryWindow;
|
m_CurrentWindow = m_InventoryWindow;
|
||||||
m_InventoryWindow->OpenedByPlayer(*this);
|
m_InventoryWindow->OpenedByPlayer(*this);
|
||||||
@ -2503,12 +2500,7 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIs
|
|||||||
m_Stats.AddValue(statDistClimbed, FloorC<StatValue>(a_DeltaPos.y * 100 + 0.5));
|
m_Stats.AddValue(statDistClimbed, FloorC<StatValue>(a_DeltaPos.y * 100 + 0.5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsSubmerged())
|
else if (IsInWater())
|
||||||
{
|
|
||||||
m_Stats.AddValue(statDistDove, Value);
|
|
||||||
AddFoodExhaustion(0.00015 * static_cast<double>(Value));
|
|
||||||
}
|
|
||||||
else if (IsSwimming())
|
|
||||||
{
|
{
|
||||||
m_Stats.AddValue(statDistSwum, Value);
|
m_Stats.AddValue(statDistSwum, Value);
|
||||||
AddFoodExhaustion(0.00015 * static_cast<double>(Value));
|
AddFoodExhaustion(0.00015 * static_cast<double>(Value));
|
||||||
|
@ -193,10 +193,10 @@ void cEnderman::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take damage when touching water, drowning damage seems to be most appropriate
|
// Take damage when wet, drowning damage seems to be most appropriate
|
||||||
if (
|
if (
|
||||||
cChunkDef::IsValidHeight(POSY_TOINT) &&
|
cChunkDef::IsValidHeight(POSY_TOINT) &&
|
||||||
(GetWorld()->IsWeatherWetAtXYZ(GetPosition().Floor()) || IsSwimming())
|
(GetWorld()->IsWeatherWetAtXYZ(GetPosition().Floor()) || IsInWater())
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EventLosePlayer();
|
EventLosePlayer();
|
||||||
|
@ -194,7 +194,7 @@ void cMonster::MoveToWayPoint(cChunk & a_Chunk)
|
|||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
(IsOnGround() && (GetSpeed().SqrLength() <= 0.5)) || // If walking on the ground, we need to slow down first, otherwise we miss the jump
|
(IsOnGround() && (GetSpeed().SqrLength() <= 0.5)) || // If walking on the ground, we need to slow down first, otherwise we miss the jump
|
||||||
IsSwimming()
|
IsInWater()
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
m_bOnGround = false;
|
m_bOnGround = false;
|
||||||
@ -221,7 +221,7 @@ void cMonster::MoveToWayPoint(cChunk & a_Chunk)
|
|||||||
{
|
{
|
||||||
Distance *= 2.5f;
|
Distance *= 2.5f;
|
||||||
}
|
}
|
||||||
else if (IsSwimming())
|
else if (IsInWater())
|
||||||
{
|
{
|
||||||
Distance *= 1.3f;
|
Distance *= 1.3f;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ void cSquid::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsSubmerged())
|
if (!IsHeadInWater())
|
||||||
{
|
{
|
||||||
if (m_AirLevel <= 0)
|
if (m_AirLevel <= 0)
|
||||||
{
|
{
|
||||||
@ -79,6 +79,3 @@ void cSquid::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
|
|
||||||
super::Tick(a_Dt, a_Chunk);
|
super::Tick(a_Dt, a_Chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user