Merge remote-tracking branch 'Hircine/Enchantments'
This commit is contained in:
commit
9a4e8bf83f
@ -431,10 +431,45 @@ void cBlockHandler::DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterfac
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: Add a proper overridable function for this
|
// TODO: Add a proper overridable function for this
|
||||||
Pickups.Add(m_BlockType, 1, Meta);
|
if (a_Digger != NULL)
|
||||||
|
{
|
||||||
|
cEnchantments Enchantments = a_Digger->GetEquippedWeapon().m_Enchantments;
|
||||||
|
if ((Enchantments.GetLevel(cEnchantments::enchSilkTouch) > 0) && a_Digger->IsPlayer())
|
||||||
|
{
|
||||||
|
switch (m_BlockType)
|
||||||
|
{
|
||||||
|
case E_BLOCK_CAKE:
|
||||||
|
case E_BLOCK_CARROTS:
|
||||||
|
case E_BLOCK_COCOA_POD:
|
||||||
|
case E_BLOCK_DOUBLE_STONE_SLAB:
|
||||||
|
case E_BLOCK_DOUBLE_WOODEN_SLAB:
|
||||||
|
case E_BLOCK_FIRE:
|
||||||
|
case E_BLOCK_FARMLAND:
|
||||||
|
case E_BLOCK_MELON_STEM:
|
||||||
|
case E_BLOCK_MOB_SPAWNER:
|
||||||
|
case E_BLOCK_NETHER_WART:
|
||||||
|
case E_BLOCK_POTATOES:
|
||||||
|
case E_BLOCK_PUMPKIN_STEM:
|
||||||
|
case E_BLOCK_SNOW:
|
||||||
|
case E_BLOCK_SUGARCANE:
|
||||||
|
case E_BLOCK_TALL_GRASS:
|
||||||
|
case E_BLOCK_CROPS:
|
||||||
|
{
|
||||||
|
// Silktouch can't be used for this blocks
|
||||||
|
ConvertToPickups(Pickups, Meta);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
default: Pickups.Add(m_BlockType, 1, Meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Pickups.Add(m_BlockType, 1, Meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow plugins to modify the pickups:
|
// Allow plugins to modify the pickups:
|
||||||
a_BlockPluginInterface.CallHookBlockToPickups(a_Digger, a_BlockX, a_BlockY, a_BlockZ, m_BlockType, Meta, Pickups);
|
a_BlockPluginInterface.CallHookBlockToPickups(a_Digger, a_BlockX, a_BlockY, a_BlockZ, m_BlockType, Meta, Pickups);
|
||||||
|
|
||||||
|
@ -30,18 +30,18 @@ public:
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLOCKTYPE BlockBelow = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
|
cEnchantments Enchantments = a_Player->GetInventory().GetEquippedItem().m_Enchantments;
|
||||||
if (!cBlockInfo::FullyOccupiesVoxel(BlockBelow) && !IsBlockLiquid(BlockBelow))
|
if (Enchantments.GetLevel(cEnchantments::enchSilkTouch) == 0)
|
||||||
{
|
{
|
||||||
return;
|
BLOCKTYPE BlockBelow = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
|
||||||
}
|
if (!cBlockInfo::FullyOccupiesVoxel(BlockBelow) && !IsBlockLiquid(BlockBelow))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_WATER, 0);
|
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_WATER, 0);
|
||||||
// This is called later than the real destroying of this ice block
|
// This is called later than the real destroying of this ice block
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,6 +90,13 @@ void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFa
|
|||||||
|
|
||||||
// Broadcast arrow hit sound
|
// Broadcast arrow hit sound
|
||||||
m_World->BroadcastSoundEffect("random.bowhit", (double)X, (double)Y, (double)Z, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
m_World->BroadcastSoundEffect("random.bowhit", (double)X, (double)Y, (double)Z, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
||||||
|
|
||||||
|
if ((m_World->GetBlock(Hit) == E_BLOCK_TNT) && IsOnFire())
|
||||||
|
{
|
||||||
|
m_World->SetBlock(X, Y, Z, E_BLOCK_AIR, 0);
|
||||||
|
m_World->SpawnPrimedTNT(X, Y, Z);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -103,8 +110,36 @@ void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
|
|||||||
{
|
{
|
||||||
Damage += m_World->GetTickRandomNumber(Damage / 2 + 2);
|
Damage += m_World->GetTickRandomNumber(Damage / 2 + 2);
|
||||||
}
|
}
|
||||||
a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 1);
|
|
||||||
|
int PowerLevel = m_CreatorData.m_Enchantments.GetLevel(cEnchantments::enchPower);
|
||||||
|
if (PowerLevel > 0)
|
||||||
|
{
|
||||||
|
int ExtraDamage = 0.25 * (PowerLevel + 1);
|
||||||
|
Damage += ceil(ExtraDamage);
|
||||||
|
}
|
||||||
|
|
||||||
|
int KnockbackAmount = 1;
|
||||||
|
int PunchLevel = m_CreatorData.m_Enchantments.GetLevel(cEnchantments::enchPunch);
|
||||||
|
if (PunchLevel > 0)
|
||||||
|
{
|
||||||
|
Vector3d LookVector = GetLookVector();
|
||||||
|
Vector3f FinalSpeed = Vector3f(0, 0, 0);
|
||||||
|
switch (PunchLevel)
|
||||||
|
{
|
||||||
|
case 1: FinalSpeed = LookVector * Vector3d(5, 0.3, 5); break;
|
||||||
|
case 2: FinalSpeed = LookVector * Vector3d(8, 0.3, 8); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
a_EntityHit.SetSpeed(FinalSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, KnockbackAmount);
|
||||||
|
|
||||||
|
if (IsOnFire() && !a_EntityHit.IsSubmerged() && !a_EntityHit.IsSwimming())
|
||||||
|
{
|
||||||
|
a_EntityHit.StartBurning(100);
|
||||||
|
}
|
||||||
|
|
||||||
// Broadcast successful hit sound
|
// Broadcast successful hit sound
|
||||||
GetWorld()->BroadcastSoundEffect("random.successful_hit", GetPosX(), GetPosY(), GetPosZ(), 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
GetWorld()->BroadcastSoundEffect("random.successful_hit", GetPosX(), GetPosY(), GetPosZ(), 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
class cArrowEntity :
|
class cArrowEntity :
|
||||||
@ -46,7 +47,7 @@ public:
|
|||||||
|
|
||||||
/// Returns the damage modifier coeff.
|
/// Returns the damage modifier coeff.
|
||||||
double GetDamageCoeff(void) const { return m_DamageCoeff; }
|
double GetDamageCoeff(void) const { return m_DamageCoeff; }
|
||||||
|
|
||||||
/// Sets the damage modifier coeff
|
/// Sets the damage modifier coeff
|
||||||
void SetDamageCoeff(double a_DamageCoeff) { m_DamageCoeff = a_DamageCoeff; }
|
void SetDamageCoeff(double a_DamageCoeff) { m_DamageCoeff = a_DamageCoeff; }
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ protected:
|
|||||||
|
|
||||||
/// If true, the arrow is in the process of being collected - don't go to anyone else
|
/// If true, the arrow is in the process of being collected - don't go to anyone else
|
||||||
bool m_bIsCollected;
|
bool m_bIsCollected;
|
||||||
|
|
||||||
/// Stores the block position that arrow is lodged into, sets m_IsInGround to false if it becomes air
|
/// Stores the block position that arrow is lodged into, sets m_IsInGround to false if it becomes air
|
||||||
Vector3i m_HitBlockPos;
|
Vector3i m_HitBlockPos;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "../Tracer.h"
|
#include "../Tracer.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "Items/ItemHandler.h"
|
#include "Items/ItemHandler.h"
|
||||||
|
#include "../FastRandom.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -316,8 +317,107 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
|
|||||||
|
|
||||||
// IsOnGround() only is false if the player is moving downwards
|
// IsOnGround() only is false if the player is moving downwards
|
||||||
// TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain)
|
// TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain)
|
||||||
if (!Player->IsOnGround())
|
cEnchantments Enchantments = Player->GetEquippedItem().m_Enchantments;
|
||||||
|
|
||||||
|
int SharpnessLevel = Enchantments.GetLevel(cEnchantments::enchSharpness);
|
||||||
|
int SmiteLevel = Enchantments.GetLevel(cEnchantments::enchSmite);
|
||||||
|
int BaneOfArthropodsLevel = Enchantments.GetLevel(cEnchantments::enchBaneOfArthropods);
|
||||||
|
|
||||||
|
if (SharpnessLevel > 0)
|
||||||
{
|
{
|
||||||
|
a_TDI.FinalDamage += 1.25 * SharpnessLevel;
|
||||||
|
}
|
||||||
|
else if (SmiteLevel > 0)
|
||||||
|
{
|
||||||
|
if (IsMob())
|
||||||
|
{
|
||||||
|
cMonster * Monster = (cMonster *)this;
|
||||||
|
switch (Monster->GetMobType())
|
||||||
|
{
|
||||||
|
case cMonster::mtSkeleton:
|
||||||
|
case cMonster::mtZombie:
|
||||||
|
case cMonster::mtWither:
|
||||||
|
case cMonster::mtZombiePigman:
|
||||||
|
{
|
||||||
|
a_TDI.FinalDamage += 2.5 * SmiteLevel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (BaneOfArthropodsLevel > 0)
|
||||||
|
{
|
||||||
|
if (IsMob())
|
||||||
|
{
|
||||||
|
cMonster * Monster = (cMonster *)this;
|
||||||
|
switch (Monster->GetMobType())
|
||||||
|
{
|
||||||
|
case cMonster::mtSpider:
|
||||||
|
case cMonster::mtCaveSpider:
|
||||||
|
case cMonster::mtSilverfish:
|
||||||
|
{
|
||||||
|
a_TDI.RawDamage += 2.5 * BaneOfArthropodsLevel;
|
||||||
|
// TODO: Add slowness effect
|
||||||
|
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int FireAspectLevel = Enchantments.GetLevel(cEnchantments::enchFireAspect);
|
||||||
|
if (FireAspectLevel > 0)
|
||||||
|
{
|
||||||
|
int BurnTicks = 3;
|
||||||
|
|
||||||
|
if (FireAspectLevel > 1)
|
||||||
|
{
|
||||||
|
BurnTicks += 4 * (FireAspectLevel - 1);
|
||||||
|
}
|
||||||
|
if (!IsMob() && !IsSubmerged() && !IsSwimming())
|
||||||
|
{
|
||||||
|
StartBurning(BurnTicks * 20);
|
||||||
|
}
|
||||||
|
else if (IsMob() && !IsSubmerged() && !IsSwimming())
|
||||||
|
{
|
||||||
|
cMonster * Monster = (cMonster *)this;
|
||||||
|
switch (Monster->GetMobType())
|
||||||
|
{
|
||||||
|
case cMonster::mtGhast:
|
||||||
|
case cMonster::mtZombiePigman:
|
||||||
|
case cMonster::mtMagmaCube:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
default: StartBurning(BurnTicks * 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ThornsLevel = 0;
|
||||||
|
const cItem ArmorItems[] = { GetEquippedHelmet(), GetEquippedChestplate(), GetEquippedLeggings(), GetEquippedBoots() };
|
||||||
|
for (size_t i = 0; i < ARRAYCOUNT(ArmorItems); i++)
|
||||||
|
{
|
||||||
|
cItem Item = ArmorItems[i];
|
||||||
|
ThornsLevel = std::max(ThornsLevel, Item.m_Enchantments.GetLevel(cEnchantments::enchThorns));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ThornsLevel > 0)
|
||||||
|
{
|
||||||
|
int Chance = ThornsLevel * 15;
|
||||||
|
|
||||||
|
cFastRandom Random;
|
||||||
|
int RandomValue = Random.GenerateRandomInteger(0, 100);
|
||||||
|
|
||||||
|
if (RandomValue <= Chance)
|
||||||
|
{
|
||||||
|
a_TDI.Attacker->TakeDamage(dtAttack, this, 0, Random.GenerateRandomInteger(1, 4), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Player->IsOnGround())
|
||||||
|
{
|
||||||
if ((a_TDI.DamageType == dtAttack) || (a_TDI.DamageType == dtArrowAttack))
|
if ((a_TDI.DamageType == dtAttack) || (a_TDI.DamageType == dtArrowAttack))
|
||||||
{
|
{
|
||||||
a_TDI.FinalDamage += 2;
|
a_TDI.FinalDamage += 2;
|
||||||
@ -328,6 +428,87 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
|
|||||||
Player->GetStatManager().AddValue(statDamageDealt, (StatValue)floor(a_TDI.FinalDamage * 10 + 0.5));
|
Player->GetStatManager().AddValue(statDamageDealt, (StatValue)floor(a_TDI.FinalDamage * 10 + 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsPlayer())
|
||||||
|
{
|
||||||
|
double TotalEPF = 0.0;
|
||||||
|
double EPFProtection = 0.00;
|
||||||
|
double EPFFireProtection = 0.00;
|
||||||
|
double EPFBlastProtection = 0.00;
|
||||||
|
double EPFProjectileProtection = 0.00;
|
||||||
|
double EPFFeatherFalling = 0.00;
|
||||||
|
|
||||||
|
const cItem ArmorItems[] = { GetEquippedHelmet(), GetEquippedChestplate(), GetEquippedLeggings(), GetEquippedBoots() };
|
||||||
|
for (size_t i = 0; i < ARRAYCOUNT(ArmorItems); i++)
|
||||||
|
{
|
||||||
|
cItem Item = ArmorItems[i];
|
||||||
|
if (Item.m_Enchantments.GetLevel(cEnchantments::enchProtection) > 0)
|
||||||
|
{
|
||||||
|
EPFProtection += (6 + pow(Item.m_Enchantments.GetLevel(cEnchantments::enchProtection), 2)) * 0.75 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Item.m_Enchantments.GetLevel(cEnchantments::enchFireProtection) > 0)
|
||||||
|
{
|
||||||
|
EPFFireProtection += (6 + pow(Item.m_Enchantments.GetLevel(cEnchantments::enchFireProtection), 2)) * 1.25 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Item.m_Enchantments.GetLevel(cEnchantments::enchFeatherFalling) > 0)
|
||||||
|
{
|
||||||
|
EPFFeatherFalling += (6 + pow(Item.m_Enchantments.GetLevel(cEnchantments::enchFeatherFalling), 2)) * 2.5 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Item.m_Enchantments.GetLevel(cEnchantments::enchBlastProtection) > 0)
|
||||||
|
{
|
||||||
|
EPFBlastProtection += (6 + pow(Item.m_Enchantments.GetLevel(cEnchantments::enchBlastProtection), 2)) * 1.5 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Item.m_Enchantments.GetLevel(cEnchantments::enchProjectileProtection) > 0)
|
||||||
|
{
|
||||||
|
EPFProjectileProtection += (6 + pow(Item.m_Enchantments.GetLevel(cEnchantments::enchProjectileProtection), 2)) * 1.5 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TotalEPF = EPFProtection + EPFFireProtection + EPFFeatherFalling + EPFBlastProtection + EPFProjectileProtection;
|
||||||
|
|
||||||
|
EPFProtection = EPFProtection / TotalEPF;
|
||||||
|
EPFFireProtection = EPFFireProtection / TotalEPF;
|
||||||
|
EPFFeatherFalling = EPFFeatherFalling / TotalEPF;
|
||||||
|
EPFBlastProtection = EPFBlastProtection / TotalEPF;
|
||||||
|
EPFProjectileProtection = EPFProjectileProtection / TotalEPF;
|
||||||
|
|
||||||
|
if (TotalEPF > 25) TotalEPF = 25;
|
||||||
|
|
||||||
|
cFastRandom Random;
|
||||||
|
float RandomValue = Random.GenerateRandomInteger(50, 100) * 0.01;
|
||||||
|
|
||||||
|
TotalEPF = ceil(TotalEPF * RandomValue);
|
||||||
|
|
||||||
|
if (TotalEPF > 20) TotalEPF = 20;
|
||||||
|
|
||||||
|
EPFProtection = TotalEPF * EPFProtection;
|
||||||
|
EPFFireProtection = TotalEPF * EPFFireProtection;
|
||||||
|
EPFFeatherFalling = TotalEPF * EPFFeatherFalling;
|
||||||
|
EPFBlastProtection = TotalEPF * EPFBlastProtection;
|
||||||
|
EPFProjectileProtection = TotalEPF * EPFProjectileProtection;
|
||||||
|
|
||||||
|
int RemovedDamage = 0;
|
||||||
|
|
||||||
|
if (a_TDI.DamageType != dtInVoid) RemovedDamage += ceil(EPFProtection * 0.04 * a_TDI.FinalDamage);
|
||||||
|
|
||||||
|
if ((a_TDI.DamageType == dtFalling) || (a_TDI.DamageType == dtFall) || (a_TDI.DamageType == dtEnderPearl)) RemovedDamage += ceil(EPFFeatherFalling * 0.04 * a_TDI.FinalDamage);
|
||||||
|
|
||||||
|
if (a_TDI.DamageType == dtBurning) RemovedDamage += ceil(EPFFireProtection * 0.04 * a_TDI.FinalDamage);
|
||||||
|
|
||||||
|
if (a_TDI.DamageType == dtExplosion) RemovedDamage += ceil(EPFBlastProtection * 0.04 * a_TDI.FinalDamage);
|
||||||
|
|
||||||
|
if (a_TDI.DamageType == dtProjectile) RemovedDamage += ceil(EPFBlastProtection * 0.04 * a_TDI.FinalDamage);
|
||||||
|
|
||||||
|
if (a_TDI.FinalDamage < RemovedDamage) RemovedDamage = 0;
|
||||||
|
|
||||||
|
a_TDI.FinalDamage -= RemovedDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
m_Health -= (short)a_TDI.FinalDamage;
|
m_Health -= (short)a_TDI.FinalDamage;
|
||||||
|
|
||||||
// TODO: Apply damage to armor
|
// TODO: Apply damage to armor
|
||||||
@ -1252,6 +1433,8 @@ void cEntity::HandleAir(void)
|
|||||||
// See if the entity is /submerged/ water (block above is water)
|
// See if the entity is /submerged/ water (block above is water)
|
||||||
// Get the type of block the entity is standing in:
|
// Get the type of block the entity is standing in:
|
||||||
|
|
||||||
|
int RespirationLevel = GetEquippedHelmet().m_Enchantments.GetLevel(cEnchantments::enchRespiration);
|
||||||
|
|
||||||
if (IsSubmerged())
|
if (IsSubmerged())
|
||||||
{
|
{
|
||||||
if (!IsPlayer()) // Players control themselves
|
if (!IsPlayer()) // Players control themselves
|
||||||
@ -1259,6 +1442,11 @@ void cEntity::HandleAir(void)
|
|||||||
SetSpeedY(1); // Float in the water
|
SetSpeedY(1); // Float in the water
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (RespirationLevel > 0)
|
||||||
|
{
|
||||||
|
((cPawn *)this)->AddEntityEffect(cEntityEffect::effNightVision, 200, 5, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_AirLevel <= 0)
|
if (m_AirLevel <= 0)
|
||||||
{
|
{
|
||||||
// Runs the air tick timer to check whether the player should be damaged
|
// Runs the air tick timer to check whether the player should be damaged
|
||||||
@ -1285,6 +1473,12 @@ void cEntity::HandleAir(void)
|
|||||||
// Set the air back to maximum
|
// Set the air back to maximum
|
||||||
m_AirLevel = MAX_AIR_LEVEL;
|
m_AirLevel = MAX_AIR_LEVEL;
|
||||||
m_AirTickTimer = DROWNING_TICKS;
|
m_AirTickTimer = DROWNING_TICKS;
|
||||||
|
|
||||||
|
if (RespirationLevel > 0)
|
||||||
|
{
|
||||||
|
m_AirTickTimer = DROWNING_TICKS + (RespirationLevel * 15 * 20);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "../Chunk.h"
|
#include "../Chunk.h"
|
||||||
#include "../Items/ItemHandler.h"
|
#include "../Items/ItemHandler.h"
|
||||||
#include "../Vector3.h"
|
#include "../Vector3.h"
|
||||||
|
#include "../FastRandom.h"
|
||||||
|
|
||||||
#include "../WorldStorage/StatSerializer.h"
|
#include "../WorldStorage/StatSerializer.h"
|
||||||
#include "../CompositeChat.h"
|
#include "../CompositeChat.h"
|
||||||
@ -1795,6 +1796,28 @@ void cPlayer::UseEquippedItem(int a_Amount)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the item has an unbreaking enchantment, give it a random chance of not breaking:
|
||||||
|
cItem Item = GetEquippedItem();
|
||||||
|
int UnbreakingLevel = Item.m_Enchantments.GetLevel(cEnchantments::enchUnbreaking);
|
||||||
|
if (UnbreakingLevel > 0)
|
||||||
|
{
|
||||||
|
int chance;
|
||||||
|
if (ItemCategory::IsArmor(Item.m_ItemType))
|
||||||
|
{
|
||||||
|
chance = 60 + (40 / (UnbreakingLevel + 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chance = 100 / (UnbreakingLevel + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
cFastRandom Random;
|
||||||
|
if (Random.NextInt(101) <= chance)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (GetInventory().DamageEquippedItem(a_Amount))
|
if (GetInventory().DamageEquippedItem(a_Amount))
|
||||||
{
|
{
|
||||||
m_World->BroadcastSoundEffect("random.break", GetPosX(), GetPosY(), GetPosZ(), 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
m_World->BroadcastSoundEffect("random.break", GetPosX(), GetPosY(), GetPosZ(), 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
||||||
|
@ -222,7 +222,8 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a
|
|||||||
m_ProjectileKind(a_Kind),
|
m_ProjectileKind(a_Kind),
|
||||||
m_CreatorData(
|
m_CreatorData(
|
||||||
((a_Creator != NULL) ? a_Creator->GetUniqueID() : -1),
|
((a_Creator != NULL) ? a_Creator->GetUniqueID() : -1),
|
||||||
((a_Creator != NULL) ? (a_Creator->IsPlayer() ? ((cPlayer *)a_Creator)->GetName() : "") : "")
|
((a_Creator != NULL) ? (a_Creator->IsPlayer() ? ((cPlayer *)a_Creator)->GetName() : "") : ""),
|
||||||
|
((a_Creator != NULL) ? a_Creator->GetEquippedWeapon().m_Enchantments : cEnchantments())
|
||||||
),
|
),
|
||||||
m_IsInGround(false)
|
m_IsInGround(false)
|
||||||
{
|
{
|
||||||
@ -235,7 +236,7 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a
|
|||||||
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) :
|
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) :
|
||||||
super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height),
|
super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height),
|
||||||
m_ProjectileKind(a_Kind),
|
m_ProjectileKind(a_Kind),
|
||||||
m_CreatorData(a_Creator->GetUniqueID(), a_Creator->IsPlayer() ? ((cPlayer *)a_Creator)->GetName() : ""),
|
m_CreatorData(a_Creator->GetUniqueID(), a_Creator->IsPlayer() ? ((cPlayer *)a_Creator)->GetName() : "", a_Creator->GetEquippedWeapon().m_Enchantments),
|
||||||
m_IsInGround(false)
|
m_IsInGround(false)
|
||||||
{
|
{
|
||||||
SetSpeed(a_Speed);
|
SetSpeed(a_Speed);
|
||||||
|
@ -94,14 +94,16 @@ protected:
|
|||||||
*/
|
*/
|
||||||
struct CreatorData
|
struct CreatorData
|
||||||
{
|
{
|
||||||
CreatorData(int a_UniqueID, const AString & a_Name) :
|
CreatorData(int a_UniqueID, const AString & a_Name, const cEnchantments & a_Enchantments) :
|
||||||
m_UniqueID(a_UniqueID),
|
m_UniqueID(a_UniqueID),
|
||||||
m_Name(a_Name)
|
m_Name(a_Name),
|
||||||
|
m_Enchantments(a_Enchantments)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const int m_UniqueID;
|
const int m_UniqueID;
|
||||||
AString m_Name;
|
AString m_Name;
|
||||||
|
cEnchantments m_Enchantments;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The type of projectile I am */
|
/** The type of projectile I am */
|
||||||
|
@ -75,7 +75,6 @@ public:
|
|||||||
Arrow = NULL;
|
Arrow = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
a_Player->GetWorld()->BroadcastSoundEffect("random.bow", a_Player->GetPosX(), a_Player->GetPosY(), a_Player->GetPosZ(), 0.5, (float)Force);
|
a_Player->GetWorld()->BroadcastSoundEffect("random.bow", a_Player->GetPosX(), a_Player->GetPosY(), a_Player->GetPosZ(), 0.5, (float)Force);
|
||||||
if (!a_Player->IsGameModeCreative())
|
if (!a_Player->IsGameModeCreative())
|
||||||
{
|
{
|
||||||
@ -83,8 +82,19 @@ public:
|
|||||||
{
|
{
|
||||||
a_Player->GetInventory().RemoveItem(cItem(E_ITEM_ARROW));
|
a_Player->GetInventory().RemoveItem(cItem(E_ITEM_ARROW));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Arrow->SetPickupState(cArrowEntity::psNoPickup);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
a_Player->UseEquippedItem();
|
a_Player->UseEquippedItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchFlame) > 0)
|
||||||
|
{
|
||||||
|
Arrow->StartBurning(100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user