Use rune natural attack speed for unarmed mobs
Unarmed mobs used a flat 5000 ms swing delay. Parse rune_naturalattacks from the rune template and use its speed (x100 ms) instead, with the AttackDelay modifier and 1.0 s floor applied as for weapons. Siege engines now fire every 17.5 s (speed 175); most creatures swing every 3.5 s. Falls back to 5000 ms when the rune has no natural attack. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ab1c3f12d3
commit
9aa44d4e9a
2 files changed
+54
No files matched your search
@@ -215,6 +215,22 @@ public enum CombatManager {
|
||||
wepSpeed = 10; //Old was 10, but it can be reached lower with legit buffs,effects.
|
||||
|
||||
delay = (long)wepSpeed * 100L;
|
||||
} else if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob)) {
|
||||
|
||||
//unarmed mob, use the natural attack speed from its rune
|
||||
|
||||
float naturalSpeed = getNaturalAttackSpeed((Mob) attacker, slot);
|
||||
|
||||
if (naturalSpeed > 0) {
|
||||
|
||||
if (attacker.getBonuses() != null && attacker.getBonuses().getFloatPercentAll(mbEnums.ModType.AttackDelay, mbEnums.SourceType.None) != 0f) //add effects speed bonus
|
||||
naturalSpeed *= (1 + attacker.getBonuses().getFloatPercentAll(mbEnums.ModType.AttackDelay, mbEnums.SourceType.None));
|
||||
|
||||
if (naturalSpeed < 10)
|
||||
naturalSpeed = 10;
|
||||
|
||||
delay = (long) naturalSpeed * 100L;
|
||||
}
|
||||
}
|
||||
|
||||
if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob))
|
||||
@@ -646,6 +662,25 @@ public enum CombatManager {
|
||||
|
||||
}
|
||||
|
||||
public static float getNaturalAttackSpeed(Mob mob, mbEnums.EquipSlotType slot) {
|
||||
|
||||
// Returns the rune natural attack speed (x100 ms) for this hand, or 0 if the rune has none.
|
||||
|
||||
ItemTemplate rune = ItemTemplate.templates.get(mob.loadID);
|
||||
int hand = slot.equals(mbEnums.EquipSlotType.LHELD) ? 2 : 1;
|
||||
|
||||
if (rune == null || rune.rune_natural_attacks.isEmpty())
|
||||
return 0;
|
||||
|
||||
for (float[] attack : rune.rune_natural_attacks)
|
||||
if (attack.length > 3 && (int) attack[3] == hand)
|
||||
return attack[0];
|
||||
|
||||
// No entry for this hand, fall back to the first natural attack
|
||||
|
||||
return rune.rune_natural_attacks.get(0)[0];
|
||||
}
|
||||
|
||||
public static int calculatePetDamage(AbstractCharacter agent) {
|
||||
//damage calc for pet
|
||||
float range;
|
||||
|
||||
@@ -138,6 +138,10 @@ public class ItemTemplate {
|
||||
public final EnumSet<mbEnums.MobBehaviourType> rune_group_role_set = EnumSet.noneOf(mbEnums.MobBehaviourType.class);
|
||||
public boolean rune_renderable = false;
|
||||
public int rune_natural_power_attack;
|
||||
// [AI] One float[] per rune_naturalattacks entry. Layout inferred from game data, not yet verified in IDA:
|
||||
// [0] attack speed (x100 ms), [1] range, [2] ?, [3] hand (1 = right, 2 = left), [4] weapon/ammo template id,
|
||||
// [5] projectile speed?, [6] swing anim, [7] damage type index, [8] min damage, [9] max damage
|
||||
public final ArrayList<float[]> rune_natural_attacks = new ArrayList<>();
|
||||
public final HashMap<String, String> rune_sparse_data = new HashMap<>();
|
||||
public final HashMap<String, int[]> rune_skill_adj = new HashMap<>();
|
||||
public final EnumSet<mbEnums.MonsterType> rune_enemy_monster_types = EnumSet.noneOf(mbEnums.MonsterType.class);
|
||||
@@ -554,6 +558,21 @@ public class ItemTemplate {
|
||||
rune_renderable = jsonObject.getBoolean("rune_renderable");
|
||||
rune_natural_power_attack = jsonObject.getInt("rune_natural_power_attack");
|
||||
|
||||
if (jsonObject.has("rune_naturalattacks")) {
|
||||
|
||||
JSONArray natural_attacks_json = jsonObject.getJSONArray("rune_naturalattacks");
|
||||
|
||||
for (Object attackEntry : natural_attacks_json) {
|
||||
JSONArray attackArray = (JSONArray) attackEntry;
|
||||
float[] attack = new float[attackArray.length()];
|
||||
|
||||
for (int i = 0; i < attackArray.length(); i++)
|
||||
attack[i] = attackArray.getFloat(i);
|
||||
|
||||
rune_natural_attacks.add(attack);
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject rune_sparse_json = jsonObject.getJSONObject("rune_sparse_data");
|
||||
|
||||
for (String sparseType : rune_sparse_json.keySet()) {
|
||||
|
||||
Reference in new issue
Block a user