feat: add weaponAttackDamage and weaponAttackSpeed to Equipment
This commit is contained in:
1 parent
f21ca33cdc
commit
c38bf7b07a
1 file changed
+159
@@ -151,3 +151,162 @@ const char* attributeName(AttributeModifier::Attribute attribute) {
|
|||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float weaponAttackDamage(ItemId item) {
|
||||||
|
if (!isTool(item)) return unarmedAttackDamage;
|
||||||
|
const ItemInfo& info = itemInfo(item);
|
||||||
|
switch (info.toolType) {
|
||||||
|
case ToolType::Sword: return swordDamage(info.toolTier);
|
||||||
|
case ToolType::Axe: return axeDamage(info.toolTier);
|
||||||
|
case ToolType::Pickaxe: return pickaxeDamage(info.toolTier);
|
||||||
|
case ToolType::Shovel: return pickaxeDamage(info.toolTier) + 0.5f;
|
||||||
|
case ToolType::Hoe: return unarmedAttackDamage;
|
||||||
|
case ToolType::None: break;
|
||||||
|
}
|
||||||
|
return unarmedAttackDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
float weaponAttackSpeed(ItemId item) {
|
||||||
|
if (!isTool(item)) return unarmedAttackSpeed;
|
||||||
|
const ItemInfo& info = itemInfo(item);
|
||||||
|
switch (info.toolType) {
|
||||||
|
case ToolType::Sword: return 1.6f;
|
||||||
|
case ToolType::Axe: return axeSpeed(info.toolTier);
|
||||||
|
case ToolType::Pickaxe: return 1.2f;
|
||||||
|
case ToolType::Shovel: return 1.0f;
|
||||||
|
case ToolType::Hoe: return hoeSpeed(info.toolTier);
|
||||||
|
case ToolType::None: break;
|
||||||
|
}
|
||||||
|
return unarmedAttackSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
float weaponAttackReach(ItemId item) {
|
||||||
|
if (!isTool(item)) return unarmedAttackReach;
|
||||||
|
switch (itemInfo(item).toolType) {
|
||||||
|
case ToolType::Sword: return unarmedAttackReach + 0.5f;
|
||||||
|
case ToolType::Axe:
|
||||||
|
case ToolType::Hoe: return unarmedAttackReach + 0.25f;
|
||||||
|
case ToolType::Pickaxe:
|
||||||
|
case ToolType::Shovel:
|
||||||
|
case ToolType::None: break;
|
||||||
|
}
|
||||||
|
return unarmedAttackReach;
|
||||||
|
}
|
||||||
|
|
||||||
|
float armorWeightPenalty(int armorPoints) {
|
||||||
|
if (armorPoints <= 0) return 0.0f;
|
||||||
|
float penalty = 0.01f * static_cast<float>(armorPoints);
|
||||||
|
return penalty > 0.35f ? 0.35f : penalty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EquipmentStats::applyTo(CombatStats& stats) const {
|
||||||
|
stats.armor = armor;
|
||||||
|
stats.baseAttackDamage = attackDamage;
|
||||||
|
stats.attackSpeed = attackSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Equipment::accepts(EquipSlot slot, const MetaStack& stack) const {
|
||||||
|
if (stack.empty()) return false;
|
||||||
|
if (!isHandSlot(slot)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Equipment::equip(EquipSlot slot, const MetaStack& stack) {
|
||||||
|
if (!accepts(slot, stack)) return false;
|
||||||
|
hands[static_cast<std::size_t>(handIndex(slot))] = stack;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Equipment::equipArmor(const Armor& piece) {
|
||||||
|
return equipArmorAt(equipSlotFor(piece.slot), piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Equipment::equipArmorAt(EquipSlot slot, const Armor& piece) {
|
||||||
|
if (!isArmorSlot(slot)) return false;
|
||||||
|
if (piece.material == Armor::Material::None) return false;
|
||||||
|
if (armorSlotFor(slot) != piece.slot) return false;
|
||||||
|
worn.at(piece.slot) = piece;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaStack Equipment::unequip(EquipSlot slot) {
|
||||||
|
if (!isHandSlot(slot)) return MetaStack{};
|
||||||
|
MetaStack removed = hands[static_cast<std::size_t>(handIndex(slot))];
|
||||||
|
hands[static_cast<std::size_t>(handIndex(slot))].clear();
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
Armor Equipment::unequipArmor(EquipSlot slot) {
|
||||||
|
if (!isArmorSlot(slot)) return Armor{};
|
||||||
|
Armor& piece = worn.at(armorSlotFor(slot));
|
||||||
|
Armor removed = piece;
|
||||||
|
piece = Armor{};
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MetaStack& Equipment::hand(EquipSlot slot) const {
|
||||||
|
if (!isHandSlot(slot)) return noStack();
|
||||||
|
return hands[static_cast<std::size_t>(handIndex(slot))];
|
||||||
|
}
|
||||||
|
|
||||||
|
const Armor& Equipment::armorPiece(EquipSlot slot) const {
|
||||||
|
Armor::Slot mapped = armorSlotFor(slot);
|
||||||
|
if (mapped == Armor::Slot::Count) return noArmor();
|
||||||
|
return worn.at(mapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
EquipmentStats Equipment::stats() const {
|
||||||
|
EquipmentStats stats;
|
||||||
|
stats.armor = worn;
|
||||||
|
stats.armorPoints = worn.totalPoints();
|
||||||
|
stats.armorToughness = worn.totalToughness();
|
||||||
|
|
||||||
|
for (int i = 0; i < static_cast<int>(Armor::Slot::Count); ++i) {
|
||||||
|
Armor::Slot armorSlot = static_cast<Armor::Slot>(i);
|
||||||
|
const Armor& piece = worn.at(armorSlot);
|
||||||
|
if (!piece.worn()) continue;
|
||||||
|
EquipSlot slot = equipSlotFor(armorSlot);
|
||||||
|
addModifier(stats, AttributeModifier::Attribute::ArmorPoints,
|
||||||
|
AttributeModifier::Operation::Add, static_cast<float>(armorPoints(piece)), slot);
|
||||||
|
addModifier(stats, AttributeModifier::Attribute::ArmorToughness,
|
||||||
|
AttributeModifier::Operation::Add, armorToughness(piece), slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
float weight = armorWeightPenalty(stats.armorPoints);
|
||||||
|
stats.movementSpeed = 1.0f - weight;
|
||||||
|
addModifier(stats, AttributeModifier::Attribute::MovementSpeed,
|
||||||
|
AttributeModifier::Operation::MultiplyTotal, -weight, EquipSlot::Chest);
|
||||||
|
|
||||||
|
const MetaStack& weapon = hands[0];
|
||||||
|
if (!weapon.empty()) {
|
||||||
|
stats.weaponEnchants = weapon.meta.enchants;
|
||||||
|
stats.attackDamage = weaponAttackDamage(weapon.item);
|
||||||
|
stats.attackSpeed = weaponAttackSpeed(weapon.item);
|
||||||
|
stats.attackReach = weaponAttackReach(weapon.item);
|
||||||
|
stats.miningSpeed = toolTierSpeedMultiplier(itemInfo(weapon.item).toolTier);
|
||||||
|
|
||||||
|
int efficiency = weapon.meta.enchants.levelOf(EnchantKind::Efficiency);
|
||||||
|
if (efficiency > 0) {
|
||||||
|
float bonus = static_cast<float>(efficiency * efficiency + 1);
|
||||||
|
stats.miningSpeed += bonus;
|
||||||
|
addModifier(stats, AttributeModifier::Attribute::MiningSpeed,
|
||||||
|
AttributeModifier::Operation::Add, bonus, EquipSlot::MainHand);
|
||||||
|
}
|
||||||
|
|
||||||
|
addModifier(stats, AttributeModifier::Attribute::AttackDamage,
|
||||||
|
AttributeModifier::Operation::Add, stats.attackDamage - unarmedAttackDamage,
|
||||||
|
EquipSlot::MainHand);
|
||||||
|
addModifier(stats, AttributeModifier::Attribute::AttackSpeed,
|
||||||
|
AttributeModifier::Operation::Add, stats.attackSpeed - unarmedAttackSpeed,
|
||||||
|
EquipSlot::MainHand);
|
||||||
|
addModifier(stats, AttributeModifier::Attribute::AttackReach,
|
||||||
|
AttributeModifier::Operation::Add, stats.attackReach - unarmedAttackReach,
|
||||||
|
EquipSlot::MainHand);
|
||||||
|
addModifier(stats, AttributeModifier::Attribute::MiningSpeed,
|
||||||
|
AttributeModifier::Operation::Add,
|
||||||
|
toolTierSpeedMultiplier(itemInfo(weapon.item).toolTier) - 1.0f,
|
||||||
|
EquipSlot::MainHand);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user