Add weapon move-type effectiveness
This commit is contained in:
@@ -708,16 +708,19 @@ func get_damage_preview(attacker_id: String, target_id: String) -> Dictionary:
|
||||
return {}
|
||||
|
||||
var attack_locked := _unit_has_action_lock(attacker, "attack")
|
||||
var effective_bonus := 0 if attack_locked else _weapon_effectiveness_bonus(attacker, target)
|
||||
var damage := 0 if attack_locked else calculate_damage(attacker, target)
|
||||
var target_hp_after: int = maxi(0, int(target["hp"]) - damage)
|
||||
var counter_damage := 0
|
||||
var attacker_hp_after := int(attacker["hp"])
|
||||
var hit_chance := 0 if attack_locked else calculate_hit_chance(attacker, target)
|
||||
var counter_hit_chance := 0
|
||||
var counter_effective_bonus := 0
|
||||
var counter_in_range := false
|
||||
if not attack_locked and (target_hp_after > 0 or hit_chance < 100):
|
||||
counter_in_range = _is_in_attack_range(target, attacker["pos"])
|
||||
if counter_in_range:
|
||||
counter_effective_bonus = _weapon_effectiveness_bonus(target, attacker)
|
||||
counter_damage = calculate_damage(target, attacker)
|
||||
counter_hit_chance = calculate_hit_chance(target, attacker)
|
||||
attacker_hp_after = maxi(0, int(attacker["hp"]) - counter_damage)
|
||||
@@ -725,6 +728,8 @@ func get_damage_preview(attacker_id: String, target_id: String) -> Dictionary:
|
||||
"attacker_id": attacker_id,
|
||||
"target_id": target_id,
|
||||
"damage": damage,
|
||||
"effective_bonus": effective_bonus,
|
||||
"effective_target_type": _weapon_effectiveness_target_type(target) if effective_bonus > 0 else "",
|
||||
"hit_chance": hit_chance,
|
||||
"target_hp_after": target_hp_after,
|
||||
"would_defeat": int(target["hp"]) - damage <= 0,
|
||||
@@ -732,6 +737,8 @@ func get_damage_preview(attacker_id: String, target_id: String) -> Dictionary:
|
||||
"attack_locked": attack_locked,
|
||||
"counter_in_range": counter_in_range,
|
||||
"counter_damage": counter_damage,
|
||||
"counter_effective_bonus": counter_effective_bonus,
|
||||
"counter_effective_target_type": _weapon_effectiveness_target_type(attacker) if counter_effective_bonus > 0 else "",
|
||||
"counter_hit_chance": counter_hit_chance,
|
||||
"attacker_hp_after": attacker_hp_after,
|
||||
"counter_would_defeat": attacker_hp_after <= 0
|
||||
@@ -828,7 +835,8 @@ func get_item_preview(user_id: String, item_id: String, target_cell: Vector2i) -
|
||||
|
||||
func calculate_damage(attacker: Dictionary, target: Dictionary) -> int:
|
||||
var terrain_defense := get_terrain_defense(target["pos"])
|
||||
return max(1, _effective_stat(attacker, "atk") - _effective_stat(target, "def") - terrain_defense)
|
||||
var effective_bonus := _weapon_effectiveness_bonus(attacker, target)
|
||||
return max(1, _effective_stat(attacker, "atk") + effective_bonus - _effective_stat(target, "def") - terrain_defense)
|
||||
|
||||
|
||||
func calculate_hit_chance(attacker: Dictionary, target: Dictionary) -> int:
|
||||
@@ -851,6 +859,49 @@ func calculate_skill_heal(caster: Dictionary, target: Dictionary, skill: Diction
|
||||
return max(0, min(raw_heal, missing_hp))
|
||||
|
||||
|
||||
func _weapon_effectiveness_bonus(attacker: Dictionary, target: Dictionary) -> int:
|
||||
var weapon := _equipped_weapon(attacker)
|
||||
if weapon.is_empty():
|
||||
return 0
|
||||
if not _weapon_is_effective_against(weapon, target):
|
||||
return 0
|
||||
return max(0, int(weapon.get("effective_bonus_damage", 0)))
|
||||
|
||||
|
||||
func _weapon_is_effective_against(weapon: Dictionary, target: Dictionary) -> bool:
|
||||
var target_move_type := _weapon_effectiveness_target_type(target)
|
||||
if target_move_type.is_empty():
|
||||
return false
|
||||
var effective_types = weapon.get("effective_vs_move_types", [])
|
||||
if typeof(effective_types) != TYPE_ARRAY:
|
||||
return false
|
||||
for move_type in effective_types:
|
||||
if str(move_type) == target_move_type:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _weapon_effectiveness_target_type(target: Dictionary) -> String:
|
||||
return str(target.get("move_type", "foot")).strip_edges()
|
||||
|
||||
|
||||
func _format_move_type(move_type: String) -> String:
|
||||
return move_type.replace("_", " ").capitalize()
|
||||
|
||||
|
||||
func _equipped_weapon(unit: Dictionary) -> Dictionary:
|
||||
var equipment = unit.get("equipment", {})
|
||||
if typeof(equipment) != TYPE_DICTIONARY:
|
||||
return {}
|
||||
var weapon_id := str(equipment.get("weapon", ""))
|
||||
if weapon_id.is_empty():
|
||||
return {}
|
||||
var weapon := get_item_def(weapon_id)
|
||||
if str(weapon.get("kind", "")) != "weapon":
|
||||
return {}
|
||||
return weapon
|
||||
|
||||
|
||||
func get_status_effect_summary(unit_id: String) -> String:
|
||||
var unit := get_unit(unit_id)
|
||||
if unit.is_empty():
|
||||
@@ -2630,7 +2681,11 @@ func _resolve_attack(attacker: Dictionary, target: Dictionary, is_counter := fal
|
||||
return {"hit": false, "defeated": false}
|
||||
var damage := calculate_damage(attacker, target)
|
||||
target["hp"] = max(0, int(target["hp"]) - damage)
|
||||
_emit_log("%s %s %s for %d damage. Hit %d%%." % [attacker["name"], verb, target["name"], damage, hit_chance])
|
||||
var effective_bonus := _weapon_effectiveness_bonus(attacker, target)
|
||||
var effective_text := ""
|
||||
if effective_bonus > 0:
|
||||
effective_text = " Effective +%d vs %s." % [effective_bonus, _format_move_type(_weapon_effectiveness_target_type(target))]
|
||||
_emit_log("%s %s %s for %d damage. Hit %d%%.%s" % [attacker["name"], verb, target["name"], damage, hit_chance, effective_text])
|
||||
_emit_combat_feedback(target, "-%d" % damage, "damage")
|
||||
|
||||
if int(target["hp"]) <= 0:
|
||||
|
||||
Reference in New Issue
Block a user