internal int avo(Game_Unit target, bool staff = false, WeaponTriangle tri = WeaponTriangle.Nothing) { int actor_avo, bonus = 0, skill_avo; // Terrain avoid bonus if (Global.scene.is_map_scene) { bool magic_attack = target != null && target.check_magic_attack(target.actor.weapon, Distance); var terrain_bonus = attacker.terrain_avo_bonus(target, magic_attack); if (terrain_bonus.IsSomething) { bonus += terrain_bonus; } } if (staff) { actor_avo = res() * 5; bonus += Distance * 2; } else { actor_avo = base_avo(); } skill_avo = 0; attacker.avo_skill(ref skill_avo, ref actor_avo, ref bonus, attacker_weapon, target, tri); // Support avoid bonus bonus += support_bonus(Combat_Stat_Labels.Avo); return(Math.Max(0, actor_avo + bonus + skill_avo)); }
private int hit_target(Game_Unit target) { Data_Weapon weapon = this.attacker_weapon; // Checks if weapon is magic bool magic_attack = attacker.check_magic_attack(weapon, Distance); bool is_staff = weapon.is_staff(); Game_Actor actor2 = target.actor; Data_Weapon weapon2 = actor2.weapon; bool boss_staff = false; int actor_hit, weapon_hit, skill_hit, support_hit, s_bonus; int hit_rate, target_avo; if (is_staff) { actor_hit = attacker.atk_pow(weapon, magic_attack) * 5 + attacker.stat(Stat_Labels.Skl); weapon_hit = weapon.Hit; skill_hit = 0; attacker.hit_skill( ref skill_hit, ref weapon_hit, ref actor_hit, weapon, target, magic_attack, Distance); support_hit = support_bonus(Combat_Stat_Labels.Hit); s_bonus = 0; hit_rate = Math.Max(0, actor_hit + weapon_hit + skill_hit + support_hit + s_bonus); target_avo = this.target_stats().staff_avo(); boss_staff = target.boss; } else { actor_hit = base_hit(weapon, magic_attack); weapon_hit = weapon.Hit; skill_hit = 0; attacker.hit_skill( ref skill_hit, ref weapon_hit, ref actor_hit, weapon, target, magic_attack, Distance); support_hit = support_bonus(Combat_Stat_Labels.Hit); s_bonus = attacker.actor.s_rank_bonus(weapon); // Weapon triangle WeaponTriangle tri = Combat.weapon_triangle(attacker, target, weapon, weapon2, Distance); if (tri != WeaponTriangle.Nothing) { weapon_hit += Weapon_Triangle.HIT_BONUS * (tri == WeaponTriangle.Advantage ? 1 : -1) * Combat.weapon_triangle_mult(attacker, target, weapon, weapon2, Distance); } hit_rate = Math.Max(0, actor_hit + weapon_hit + skill_hit + support_hit + s_bonus); target_avo = this.target_stats().avo(Combat.reverse_wta(tri)); } int total_hit = hit_rate - target_avo; int result = attacker.hit_target_skill( target, weapon, Distance, Math.Max(total_hit, 0) / (boss_staff ? 2 : 1)); return(result); }
public static void SetWeaponTriangle( Weapon_Triangle_Arrow wta1, Weapon_Triangle_Arrow wta2, Game_Unit attacker, Combat_Map_Object target, TactileLibrary.Data_Weapon weapon1, TactileLibrary.Data_Weapon weapon2, int distance) { //@Yeti: use in all the places weapon triangle arrow is used Game_Unit targetUnit = null; if (target.is_unit()) { targetUnit = target as Game_Unit; } ResetWeaponTriangle(wta1, wta2); WeaponTriangle tri = WeaponTriangle.Nothing; if (targetUnit != null) { tri = Combat.weapon_triangle(attacker, targetUnit, weapon1, weapon2, distance); } if (tri != WeaponTriangle.Nothing) { wta1.value = tri; if (wta2 != null && weapon2 != null) { wta2.value = Combat.reverse_wta(tri); } } float effectiveness = weapon1.effective_multiplier(attacker, targetUnit, false); wta1.set_effectiveness((int)effectiveness, targetUnit != null && targetUnit.halve_effectiveness()); if (wta2 != null && weapon2 != null) { effectiveness = weapon2.effective_multiplier(targetUnit, attacker, false); wta2.set_effectiveness((int)effectiveness, attacker.halve_effectiveness()); } }
private int dmg_target(Game_Unit target) { Data_Weapon weapon = this.attacker_weapon; // Checks if weapon is magic bool magic_attack = attacker.check_magic_attack(weapon, Distance); bool imbue = (magic_attack && attacker.actor.power_type() == Power_Types.Strength); bool is_staff = weapon.is_staff(); Game_Actor actor2 = target.actor; Data_Weapon weapon2 = actor2.weapon; int total_damage, target_def; int actor_dmg, weapon_dmg, skill_dmg, support_dmg; // Staff if (is_staff) { actor_dmg = attacker.atk_pow(weapon, magic_attack); weapon_dmg = weapon.Mgt; skill_dmg = 0; attacker.dmg_staff_skill( ref skill_dmg, ref weapon_dmg, ref actor_dmg, target, magic_attack, Distance); support_dmg = support_bonus(Combat_Stat_Labels.Dmg); target_def = 0; } // Weapon else { var target_stats = this.target_stats(); target_def = magic_attack ? target_stats.res() : target_stats.def(); target_def = (weapon.Ignores_Def() ? target_def / 2 : target_def); if (weapon.Halves_HP()) { int total_weapon_damage = target_def + (int)Math.Ceiling(target.actor.hp / 2.0f); actor_dmg = (int)Math.Ceiling(total_weapon_damage / 2.0f); weapon_dmg = (int)Math.Floor(total_weapon_damage / 2.0f); } else { actor_dmg = weapon.Ignores_Pow() ? 0 : ((int)(attacker.atk_pow(weapon, magic_attack) * (imbue ? Constants.Combat.MAGIC_WEAPON_STR_RATE : 1))); weapon_dmg = (int)(weapon.Mgt * (imbue ? Constants.Combat.MAGIC_WEAPON_MGT_RATE : 1)); if (weapon.Ignores_Def()) { weapon_dmg += target_def; } } // Weapon triangle skill_dmg = 0; WeaponTriangle tri = Combat.weapon_triangle(attacker, target, weapon, weapon2, Distance); if (tri != WeaponTriangle.Nothing) { skill_dmg += Weapon_Triangle.DMG_BONUS * (tri == WeaponTriangle.Advantage ? 1 : -1) * Combat.weapon_triangle_mult(attacker, target, weapon, weapon2, Distance); } float effectiveness = weapon.effective_multiplier(attacker, target); skill_dmg += (int)((weapon_dmg + skill_dmg) * (effectiveness - 1)); support_dmg = support_bonus(Combat_Stat_Labels.Dmg); attacker.dmg_skill( ref skill_dmg, ref weapon_dmg, ref actor_dmg, ref support_dmg, ref target_def, weapon, target, weapon2, tri, magic_attack, Distance, effectiveness); } total_damage = actor_dmg + weapon_dmg + skill_dmg + support_dmg - target_def; int result = attacker.dmg_target_skill(target, weapon, Distance, Math.Max(0, total_damage)); return(result); }
internal override int avo(WeaponTriangle tri) { return(avo(this.target as Game_Unit, tri)); }
protected override void set_images() { Icon1.flash = false; Icon2.flash = false; Mult1.value = 0; Mult2.value = 0; WTA1.set_effectiveness(1); WTA2.set_effectiveness(1); Game_Unit unit = get_unit(); Game_Actor actor1 = unit.actor; Combat_Map_Object target = Global.game_map.attackable_map_object(this.target); Game_Unit target_unit = null; Game_Actor actor2 = null; bool is_target_unit = false; if (target.is_unit()) { is_target_unit = true; target_unit = (Game_Unit)target; actor2 = target_unit.actor; Window.team2 = target_unit.team; } else { Window.team2 = target.team; } int distance = combat_distance(unit.id, this.target); // Get weapon data TactileLibrary.Data_Weapon weapon1 = actor1.weapon, weapon2 = null; if (is_target_unit) { weapon2 = actor2.weapon; } // Weapon triangle arrows WTA1.value = 0; WTA2.value = 0; WeaponTriangle tri = WeaponTriangle.Nothing; if (is_target_unit) { tri = Combat.weapon_triangle(unit, target_unit, weapon1, weapon2, distance); } if (tri != WeaponTriangle.Nothing) { WTA1.value = tri; if (weapon2 != null) { WTA2.value = Combat.reverse_wta(tri); } } List <int?> combat_stats = get_combat_stats(unit.id, this.target, distance); Stats = new List <Sprite>(); for (int i = 0; i < stat_rows * 2; i++) { RightAdjustedText text = new RightAdjustedText(); Stats.Add(text); text.draw_offset = new Vector2(68 - (48 * (i / 4)), 4 + ((i % 4 + 1) * LINE_HEIGHT)); text.SetFont(Config.UI_FONT, Global.Content, "Blue"); text.text = "0"; } // Sets first units's stats // Name1.draw_offset = new Vector2(44, 4); Name1.text = actor1.name; Name1.offset = new Vector2(Name1.text_width / 2, 0); // Multiplier Mult1.value = Mult1.get_multi(unit, target, weapon1, distance); // Icon Icon1.index = weapon1.Image_Index; Icon1.texture = Global.Content.Load <Texture2D>(@"Graphics/Icons/" + weapon1.Image_Name); if (weapon1.effective_multiplier(unit, target_unit) > 1) { Icon1.flash = true; } float effectiveness = weapon1.effective_multiplier(unit, target_unit, false); WTA1.set_effectiveness((int)effectiveness, is_target_unit && target_unit.halve_effectiveness()); // Hp if (actor1.hp >= Math.Pow(10, Global.BattleSceneConfig.StatusHpCounterValues)) { ((RightAdjustedText)Stats[0]).text = "--"; } else { ((RightAdjustedText)Stats[0]).text = actor1.hp.ToString(); } // Dmg ((RightAdjustedText)Stats[1]).text = combat_stats[1].ToString(); // Hit if (combat_stats[0] >= 100) { ((RightAdjustedText)Stats[2]).SetFont("Blue_100", Global.Content); } ((RightAdjustedText)Stats[2]).text = combat_stats[0].ToString(); // Crt if (combat_stats[2] >= 100) { ((RightAdjustedText)Stats[3]).SetFont("Blue_100", Global.Content); } ((RightAdjustedText)Stats[3]).text = combat_stats[2].ToString(); // Sets second units's stats // string name2 = is_target_unit ? actor2.name : target.name; Name2.draw_offset = new Vector2(28, 4 + (Window.rows + 1) * LINE_HEIGHT); Name2.offset = new Vector2(Font_Data.text_width(name2, Config.UI_FONT) / 2, 0); Name2.text = name2; // Icon if (weapon2 != null) { Target_Weapon.text = weapon2.Name; Target_Weapon.draw_offset = new Vector2( 32 - Target_Weapon.text_width / 2, 4 + (Window.rows + 2) * LINE_HEIGHT); Icon2.index = weapon2.Image_Index; Icon2.texture = Global.Content.Load <Texture2D>(@"Graphics/Icons/" + weapon2.Image_Name); if (weapon2.effective_multiplier(target_unit, unit) > 1) { Icon2.flash = true; } effectiveness = weapon2.effective_multiplier(target_unit, unit, false); WTA2.set_effectiveness((int)effectiveness, unit.halve_effectiveness()); } else { Target_Weapon.draw_offset = new Vector2( 32 - Font_Data.text_width("---", Config.UI_FONT) / 2, 4 + (Window.rows + 2) * LINE_HEIGHT); Target_Weapon.text = "---"; Icon2.texture = null; } // Hp //int target_hp = is_target_unit ? actor2.hp : ((Destroyable_Object)target).hp; //Debug if (target.hp >= Math.Pow(10, Global.BattleSceneConfig.StatusHpCounterValues)) { ((RightAdjustedText)Stats[4]).text = "--"; } else { ((RightAdjustedText)Stats[4]).text = target.hp.ToString(); } if (is_target_unit && can_counter(unit, target_unit, weapon1, distance)) { // Multiplier Mult2.value = Mult2.get_multi(target_unit, unit, weapon2, distance); // Dmg ((RightAdjustedText)Stats[5]).text = combat_stats[5].ToString(); // Hit if (combat_stats[4] >= 100) { ((RightAdjustedText)Stats[6]).SetFont("Blue_100", Global.Content); } ((RightAdjustedText)Stats[6]).text = combat_stats[4].ToString(); // Crt if (combat_stats[6] >= 100) { ((RightAdjustedText)Stats[7]).SetFont("Blue_100", Global.Content); } ((RightAdjustedText)Stats[7]).text = combat_stats[6].ToString(); } else { ((RightAdjustedText)Stats[5]).text = "--"; ((RightAdjustedText)Stats[6]).text = "--"; ((RightAdjustedText)Stats[7]).text = "--"; } refresh(); }
protected void refresh_battle_stats(bool just_stats) { if (!just_stats) { foreach (Item_Icon_Sprite icon in Weapon_Icons) { icon.texture = null; } foreach (TextSprite name in Weapon_Names) { name.text = ""; } TactileLibrary.Data_Weapon weapon1 = null; TactileLibrary.Data_Weapon weapon2 = null; WTAs[0].value = 0; if (Global.scene.scene_type == "Scene_Dance" || Global.scene.scene_type == "Scene_Promotion") { int item_index = -1; if (Global.scene.scene_type == "Scene_Dance") { item_index = Global.game_state.dance_item; } else if (Global.scene.scene_type == "Scene_Promotion") { item_index = Global.game_state.item_used; } if (item_index > -1) { TactileLibrary.Item_Data item_data = battler_1.actor.items[item_index]; TactileLibrary.Data_Equipment item1 = item_data.to_equipment; Weapon_Icons[0].texture = Global.Content.Load <Texture2D>(@"Graphics/Icons/" + item1.Image_Name); Weapon_Icons[0].index = item1.Image_Index; Weapon_Names[0].offset.X = Font_Data.text_width(item1.full_name()) / 2; Weapon_Names[0].text = item1.full_name(); } if (battler_2 != null) { WTAs[1].value = 0; weapon2 = battler_2.actor.weapon; if (weapon2 != null) { Weapon_Icons[1].texture = Global.Content.Load <Texture2D>(@"Graphics/Icons/" + weapon2.Image_Name); Weapon_Icons[1].index = weapon2.Image_Index; Weapon_Names[1].offset.X = Font_Data.text_width(weapon2.full_name()) / 2; Weapon_Names[1].text = weapon2.full_name(); } } } else { weapon1 = battler_1.actor.weapon; Weapon_Icons[0].texture = Global.Content.Load <Texture2D>(@"Graphics/Icons/" + weapon1.Image_Name); Weapon_Icons[0].index = weapon1.Image_Index; if (!(Data is Staff_Data) || ((Staff_Data)Data).attack_staff) { Weapon_Icons[0].flash = weapon1.effective_multiplier(battler_1, battler_2) > 1; } Weapon_Names[0].offset.X = Font_Data.text_width(weapon1.full_name()) / 2; Weapon_Names[0].text = weapon1.full_name(); if (battler_2 != null) { WTAs[1].value = 0; weapon2 = battler_2.actor.weapon; if (weapon2 != null) { Weapon_Icons[1].texture = Global.Content.Load <Texture2D>(@"Graphics/Icons/" + weapon2.Image_Name); Weapon_Icons[1].index = weapon2.Image_Index; if (!(Data is Staff_Data) || ((Staff_Data)Data).attack_staff) { Weapon_Icons[1].flash = weapon2.effective_multiplier(battler_2, battler_1) > 1; } Weapon_Names[1].offset.X = Font_Data.text_width(weapon2.full_name()) / 2; Weapon_Names[1].text = weapon2.full_name(); // Attack Multiplier if (!weapon1.is_staff()) { } // Mults[1].value = Mults[1].get_multi(battler_2, battler_1, weapon2); //Debug } if (!weapon1.is_staff()) { // Weapon triangle arrows WeaponTriangle tri = Combat.weapon_triangle(battler_1, battler_2, weapon1, weapon2, Data.Distance); if (tri != WeaponTriangle.Nothing) { WTAs[0].value = tri; if (weapon2 != null) { WTAs[1].value = Combat.reverse_wta(tri); } } // Attack Multiplier //Mults[0].value = Mults[0].get_multi(battler_1, battler_2, weapon1); //Debug } } } } for (int i = 0; i < Stat_Imgs.Count; i++) { if (Stats[i] == null) { Stat_Imgs[i].text = "--"; } else if (Stats[i] < 0) { Stat_Imgs[i].text = "--"; } else { Stat_Imgs[i].text = Stats[i].ToString(); } } }
List <GameAction> InitiateCombat(FE7UnitEntity attacker, FE7UnitEntity defender, int engagementRange) { List <GameAction> ret = new List <GameAction>(); if (!attacker.EquippedWeapon.Range.Contains(engagementRange)) { throw new WeaponException("Attack at improper range"); } bool defenderCanRetalliate = defender.EquippedWeapon.Range.Contains(engagementRange); int attackerAttackSpeed = attacker.AttackSpeed; int defenderAttackSpeed = defender.AttackSpeed; bool attackerDouble = attackerAttackSpeed - defenderAttackSpeed >= 4; bool defenderDouble = defenderAttackSpeed - attackerAttackSpeed >= 4; WeaponTriangle attackerWeapTriBonus = CalculateWeaponTriangle(attacker.EquippedWeapon.WeaponType, defender.EquippedWeapon.WeaponType); WeaponTriangle defenderWeapTriBonus = CalculateWeaponTriangle(defender.EquippedWeapon.WeaponType, attacker.EquippedWeapon.WeaponType); //[Precalculated -- Weapon Hit + (Skill x 2) + (Luck / 2) ]+ Support bonus + Weapon Triangle bonus + S Rank bonus + Tactician bonus int attackerHit = attacker.HitChance + 0 + ((int)attackerWeapTriBonus * 15) + 0 + 0; int defenderHit = defender.HitChance + 0 + ((int)defenderWeapTriBonus * 15) + 0 + 0; // [Precalculated -- (Attack Speed x 2) + Luck ]+ Support bonus + Terrain bonus + Tactician bonus defenderHit -= attacker.Avoid + 0 + CalcTerrainAvoidBonus(attacker.Terrain) + 0; attackerHit -= defender.Avoid + 0 + CalcTerrainAvoidBonus(defender.Terrain) + 0; // Weapon Critical + (Skill / 2) + Support bonus + Critical bonus + S Rank bonus - Crit Avoid [opponent's Luck + Support + Tactician Bonus] int attackerCrit = attacker.CritChance + 0 + 0 + 0 - defender.Luck - 0 - 0; int defenderCrit = defender.CritChance + 0 + 0 + 0 - attacker.Luck - 0 - 0; // StrengthMagic + Weapon Might + [ Weapon Triangle bonus x Effective coefficient] + Support bonus int attackerDamage = attacker.Might + ((int)attackerWeapTriBonus * 1) + 0 - CalcTerrainDefBonus(defender.Terrain); int defenderDamage = defender.Might + ((int)defenderWeapTriBonus * 1) + 0 - CalcTerrainDefBonus(attacker.Terrain); //attacker attacks first. GameAction attackerResult = ProcessAttack(MakeAttack(attackerHit, attackerCrit, attackerDamage), attacker, defender); ret.Add(attackerResult); //check to see if Defender is still alive. defender.TakeDamage(attackerResult); if (defender.HP > 0 && defenderCanRetalliate && defender.EquippedWeapon.WeaponType != FE7WeaponType.None) { //defender attacks GameAction defenderResult = ProcessAttack(MakeAttack(defenderHit, defenderCrit, defenderDamage), defender, attacker); ret.Add(defenderResult); attacker.TakeDamage(defenderResult); } //check to see if attacker is still alive if (attacker.HP > 0 && attackerDouble) { //attack again. GameAction followupResult = ProcessAttack(MakeAttack(attackerHit, attackerCrit, attackerDamage), attacker, defender); ret.Add(followupResult); //check to see if Defender is still alive. defender.TakeDamage(followupResult); } else if (defender.HP > 0 && defenderDouble && defender.EquippedWeapon.WeaponType != FE7WeaponType.None) { //defender attacks again. GameAction followupResult = ProcessAttack(MakeAttack(defenderHit, defenderCrit, defenderDamage), defender, attacker); ret.Add(followupResult); attacker.TakeDamage(followupResult); } //Now we check if either died. if (defender.HP > 0 && attacker.HP > 0) { //no one died. ret.Add(new CombatDrawAction(attacker, defender)); } else if (attacker.HP > 0) { //defender died ret.Add(new CombatDefenderDefeatAction(attacker, defender)); } else if (defender.HP > 0) { //attacker died ret.Add(new CombatAttackerDefeatAction(attacker, defender)); } else { //they both died. This shouldn't happen. Oops. throw new CombatEngineException("Both units dead after combat"); } return(ret); }
internal int avo(Game_Unit target, WeaponTriangle tri) { return(avo(target, false, tri)); }
internal virtual int avo(WeaponTriangle tri) { return(avo(null, tri)); }