feat: add xorshift and unitFloat
This commit is contained in:
1 parent
2e76ff9143
commit
0cc5b9527b
1 file changed
+177
@@ -0,0 +1,177 @@
|
|||||||
|
#include "vf/Damage.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace vf {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
uint32_t xorshift(uint32_t& state) {
|
||||||
|
state ^= state << 13;
|
||||||
|
state ^= state >> 17;
|
||||||
|
state ^= state << 5;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
float unitFloat(uint32_t& rng) { return static_cast<float>(xorshift(rng)) / 4294967295.0f; }
|
||||||
|
|
||||||
|
int rollBelow(uint32_t& rng, int bound) {
|
||||||
|
if (bound <= 1) return 0;
|
||||||
|
return static_cast<int>(xorshift(rng) % static_cast<uint32_t>(bound));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vanilla per-slot durability bases, scaled by the material factor below.
|
||||||
|
int slotDurabilityBase(Armor::Slot slot) {
|
||||||
|
switch (slot) {
|
||||||
|
case Armor::Slot::Helmet: return 11;
|
||||||
|
case Armor::Slot::Chestplate: return 16;
|
||||||
|
case Armor::Slot::Leggings: return 15;
|
||||||
|
case Armor::Slot::Boots: return 13;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int materialDurabilityFactor(Armor::Material material) {
|
||||||
|
switch (material) {
|
||||||
|
case Armor::Material::Leather: return 5;
|
||||||
|
case Armor::Material::Chain: return 15;
|
||||||
|
case Armor::Material::Iron: return 15;
|
||||||
|
case Armor::Material::Gold: return 7;
|
||||||
|
case Armor::Material::Diamond: return 33;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int protectionPointsFor(const EnchantSet& enchants, DamageType type) {
|
||||||
|
int points = 0;
|
||||||
|
int general = enchants.levelOf(EnchantKind::Protection);
|
||||||
|
if (general > 0 && type != DamageType::Void && type != DamageType::Starve) points += general;
|
||||||
|
if (isFireDamage(type)) points += 2 * enchants.levelOf(EnchantKind::FireProtection);
|
||||||
|
if (type == DamageType::Explosion) points += 2 * enchants.levelOf(EnchantKind::BlastProtection);
|
||||||
|
if (isProjectileDamage(type)) {
|
||||||
|
points += 2 * enchants.levelOf(EnchantKind::ProjectileProtection);
|
||||||
|
}
|
||||||
|
if (type == DamageType::Fall) points += 3 * enchants.levelOf(EnchantKind::FeatherFalling);
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unbreakingBlocksWear(int unbreakingLevel, uint32_t& rng) {
|
||||||
|
if (unbreakingLevel <= 0) return false;
|
||||||
|
float ignoreChance = 0.6f + 0.4f / static_cast<float>(unbreakingLevel + 1);
|
||||||
|
return unitFloat(rng) < ignoreChance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 knockbackAlong(const Vec3& heading, float strength) {
|
||||||
|
Vec3 flat = normalize(Vec3{heading.x, 0.0f, heading.z});
|
||||||
|
if (length(flat) <= 0.0f) flat = {1.0f, 0.0f, 0.0f};
|
||||||
|
float horizontal = 0.4f + strength * 0.5f;
|
||||||
|
return {flat.x * horizontal, 0.4f, flat.z * horizontal};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool bypassesArmor(DamageType type) {
|
||||||
|
switch (type) {
|
||||||
|
case DamageType::Void:
|
||||||
|
case DamageType::Starve:
|
||||||
|
case DamageType::Suffocation:
|
||||||
|
case DamageType::Magic:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bypassesInvulnerability(DamageType type) {
|
||||||
|
return type == DamageType::Void || type == DamageType::Starve;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bypassesMitigation(DamageType type) { return type == DamageType::Void; }
|
||||||
|
|
||||||
|
bool isFireDamage(DamageType type) {
|
||||||
|
return type == DamageType::Fire || type == DamageType::Lava;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isProjectileDamage(DamageType type) { return type == DamageType::Projectile; }
|
||||||
|
|
||||||
|
HurtSource meleeSource(int attackerId, const Vec3& origin, bool byPlayer) {
|
||||||
|
HurtSource source;
|
||||||
|
source.type = DamageType::Melee;
|
||||||
|
source.origin = origin;
|
||||||
|
source.attackerId = attackerId;
|
||||||
|
source.ownerId = attackerId;
|
||||||
|
source.byPlayer = byPlayer;
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
HurtSource projectileSource(int projectileId, int ownerId, const Vec3& origin, bool byPlayer) {
|
||||||
|
HurtSource source;
|
||||||
|
source.type = DamageType::Projectile;
|
||||||
|
source.origin = origin;
|
||||||
|
source.attackerId = projectileId;
|
||||||
|
source.ownerId = ownerId;
|
||||||
|
source.byPlayer = byPlayer;
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
HurtSource environmentSource(DamageType type, const Vec3& origin) {
|
||||||
|
HurtSource source;
|
||||||
|
source.type = type;
|
||||||
|
source.origin = origin;
|
||||||
|
source.fiery = isFireDamage(type);
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
Armor makeArmor(Armor::Material material, Armor::Slot slot) {
|
||||||
|
Armor piece;
|
||||||
|
piece.material = material;
|
||||||
|
piece.slot = slot;
|
||||||
|
piece.maxDurability = slotDurabilityBase(slot) * materialDurabilityFactor(material);
|
||||||
|
piece.durability = piece.maxDurability;
|
||||||
|
return piece;
|
||||||
|
}
|
||||||
|
|
||||||
|
int armorPoints(const Armor& piece) {
|
||||||
|
if (!piece.worn()) return 0;
|
||||||
|
switch (piece.material) {
|
||||||
|
case Armor::Material::Leather:
|
||||||
|
switch (piece.slot) {
|
||||||
|
case Armor::Slot::Helmet: return 1;
|
||||||
|
case Armor::Slot::Chestplate: return 3;
|
||||||
|
case Armor::Slot::Leggings: return 2;
|
||||||
|
default: return 1;
|
||||||
|
}
|
||||||
|
case Armor::Material::Chain:
|
||||||
|
switch (piece.slot) {
|
||||||
|
case Armor::Slot::Helmet: return 2;
|
||||||
|
case Armor::Slot::Chestplate: return 5;
|
||||||
|
case Armor::Slot::Leggings: return 4;
|
||||||
|
default: return 1;
|
||||||
|
}
|
||||||
|
case Armor::Material::Iron:
|
||||||
|
switch (piece.slot) {
|
||||||
|
case Armor::Slot::Helmet: return 2;
|
||||||
|
case Armor::Slot::Chestplate: return 6;
|
||||||
|
case Armor::Slot::Leggings: return 5;
|
||||||
|
default: return 2;
|
||||||
|
}
|
||||||
|
case Armor::Material::Gold:
|
||||||
|
switch (piece.slot) {
|
||||||
|
case Armor::Slot::Helmet: return 2;
|
||||||
|
case Armor::Slot::Chestplate: return 5;
|
||||||
|
case Armor::Slot::Leggings: return 3;
|
||||||
|
default: return 1;
|
||||||
|
}
|
||||||
|
case Armor::Material::Diamond:
|
||||||
|
switch (piece.slot) {
|
||||||
|
case Armor::Slot::Helmet: return 3;
|
||||||
|
case Armor::Slot::Chestplate: return 8;
|
||||||
|
case Armor::Slot::Leggings: return 6;
|
||||||
|
default: return 3;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user