示例#1
0
        public static List <int> targets_in_range(int min_range, int max_range, HashSet <Vector2> move_range, List <int> units, bool walls)
        {
            List <int> result = new List <int>();

            foreach (Vector2 loc in move_range)
            {
                // If all units have been checked, break
                if (units.Count == 0)
                {
                    break;
                }
                // Loop through units
                int i = 0;
                while (i < units.Count)
                {
                    int id = units[i];
                    Combat_Map_Object target = Global.game_map.attackable_map_object(id);
                    int dist = manhatten_dist(loc, target.loc) / 10;
                    if (dist <= max_range && dist >= min_range && (walls ? clear_firing_line(loc, target.loc) : true))
                    {
                        result.Add(id);
                        units.Remove(id);
                    }
                    else
                    {
                        i++;
                    }
                }
            }
            return(result);
        }
示例#2
0
        private void add_attacks(
            Game_Unit battler_1, Combat_Map_Object battler_2,
            int i, Data_Weapon weapon)
        {
#if DEBUG
            System.Diagnostics.Debug.Assert(i == 1 || i == 2);
#endif
            Game_Unit         attacker = i == 2 ? battler_2 as Game_Unit : battler_1;
            Combat_Map_Object target   = i == 2 ? battler_1 : battler_2;

            int num_hits = 1;
            if (!attacker.is_brave_blocked())
            {
                // If only single hits against terrain
                if (!(target != null && !target.is_unit() &&
                      Constants.Combat.BRAVE_BLOCKED_AGAINST_DESTROYABLE))
                {
                    num_hits = weapon.HitsPerAttack;
                }
            }
            for (int j = 0; j < num_hits; j++)
            {
                add_attacks(battler_1, battler_2, i);
            }
        }
示例#3
0
 protected override int combat_attacks(Game_Unit battler_1, Combat_Map_Object battler_2,
                                       out int numAttacks1, out int numAttacks2)
 {
     // Only one attack per target for area of effect
     numAttacks1 = 1;
     numAttacks2 = 0;
     return(Math.Max(numAttacks1, numAttacks2));
 }
        public Terrain_Round_Data(Game_Unit battler_1, Combat_Map_Object battler_2, int distance)
        {
            Battler1      = battler_1;
            TargetTerrain = battler_2;

            List <int?> ary = combat_stats(distance);

            Stats = ary;
        }
示例#5
0
        private void add_attacks(
            Game_Unit battler_1, Combat_Map_Object battler_2, int i)
        {
            Game_Unit         attacker = battler_1;
            Combat_Map_Object target   = battler_2;

            if (i == 2)
            {
                if (!battler_2.is_unit())
                {
                    return;
                }
                attacker = battler_2 as Game_Unit;
                target   = battler_1;
            }

            bool cont = false;

            while (!cont)
            {
                int  attacker_index = 0;
                bool attack_occurs  = attackable(attacker, target);
                if (attack_occurs)
                {
                    attacker_index = i;
                    if (Skip_Attack.Contains(attacker_index))
                    {
                        attacker_index = 0;
                        Skip_Attack.pop();
                    }
                }
                if (attacker_index > 0)
                {
                    if (battler_2 == null)
                    {
                        add_solo_attack(battler_1, attacker_index);
                    }
                    else if (battler_2.is_unit())
                    {
                        add_attack(battler_1, battler_2 as Game_Unit, attacker_index);
                    }
                    else
                    {
                        add_attack(battler_1, battler_2 as Combat_Map_Object, attacker_index);
                    }
                }

                cont = true;
                // If an added attack is buffered
                if (Add_Attack.Count > 0)
                {
                    attacker_index = Add_Attack.pop();
                    cont           = false;
                }
            }
        }
示例#6
0
        public override void apply_combat(bool immediate_level, bool skip_exp)
        {
            // Prevents data from being applied multiple times
            if (Applied)
            {
                return;
            }
            Applied = true;

            Game_Unit         battler_1 = Global.game_map.units[Battler_1_Id];
            Combat_Map_Object battler_2 = Global.game_map.get_map_object((int)Battler_2_Id) as Combat_Map_Object;
            int battler_1_hp            = battler_1.hp;
            int battler_2_hp            = battler_2 != null ? battler_2.hp : -1;

            for (int i = 0; i < Data.Count; i++)
            {
                Combat_Round_Data data = Data[i].Key;
                data.cause_damage();
            }
            Global.game_state.add_combat_metric(Metrics.CombatTypes.DestroyableTerrain,
                                                Battler_1_Id, Battler_2_Id, battler_1_hp, battler_2_hp, Weapon_1_Id, Weapon_2_Id,
                                                Data.Where(x => x.Key.Attacker == 1).Count(), Data.Where(x => x.Key.Attacker != 1).Count());

            use_weapons(battler_1, null);

            battler_1.actor.clear_added_attacks();
            if (skip_exp)
            {
                Exp_Gain1 = 0;
                Exp_Gain2 = 0;
            }
            else
            {
                exp_gain(battler_1.actor, Exp_Gain1);
                if (battler_1.is_player_team)
                {
                    if (Global.game_state.is_battle_map && !Global.game_system.In_Arena)
                    {
                        Global.game_system.chapter_exp_gain += Exp_Gain1;
                    }
                }
            }
            if (Wexp1 > 0)
            {
                TactileLibrary.WeaponType type = battler_1.actor.valid_weapon_type_of(Global.data_weapons[Weapon_1_Id]);
                battler_1.actor.wexp_gain(type, Wexp1);
            }
            if (immediate_level)
            {
                if (battler_1.actor.needed_levels > 0)
                {
                    battler_1.actor.level_up();
                }
                battler_1.actor.clear_wlvl_up();
            }
        }
示例#7
0
 protected override void process_attacks(Game_Unit battler_1, Combat_Map_Object battler_2)
 {
     if (Global.game_temp.scripted_battle_stats != null)
     {
         process_scripted_attacks(battler_1, battler_2, Global.game_temp.scripted_battle_stats);
     }
     else
     {
         base.process_attacks(battler_1, battler_2);
     }
 }
示例#8
0
 protected virtual int combat_attacks(Game_Unit battler_1, Combat_Map_Object battler_2,
                                      out int numAttacks1, out int numAttacks2)
 {
     numAttacks1 = battler_1.attacks_per_round(battler_2, Distance);
     numAttacks2 = 0;
     if (battler_2 != null && battler_2.is_unit())
     {
         numAttacks2 = (battler_2 as Game_Unit).attacks_per_round(battler_1, Distance);
     }
     return(Math.Max(numAttacks1, numAttacks2));
 }
示例#9
0
 protected override int combat_attacks(Game_Unit battler_1, Combat_Map_Object battler_2,
                                       out int numAttacks1, out int numAttacks2)
 {
     // No double casting
     numAttacks1 = 1;
     numAttacks2 = 0;
     if (battler_2 != null && battler_2.is_unit())
     {
         numAttacks2 = 1;
     }
     return(Math.Max(numAttacks1, numAttacks2));
 }
示例#10
0
 public static void SetWeaponTriangle(
     Weapon_Triangle_Arrow wta,
     Game_Unit attacker,
     Combat_Map_Object target,
     TactileLibrary.Data_Weapon weapon1,
     TactileLibrary.Data_Weapon weapon2,
     int distance)
 {
     SetWeaponTriangle(
         wta, null,
         attacker, target,
         weapon1, weapon2,
         distance);
 }
示例#11
0
 protected virtual void set_variables(Game_Unit battler_1, Combat_Map_Object battler_2)
 {
     Hp1         = battler_1.actor.hp;
     MaxHp1      = battler_1.actor.maxhp;
     Team1       = battler_1.team;
     Name1       = battler_1.actor.name;
     Exp1        = battler_1.actor.exp;
     Weapon_1_Id = battler_1.actor.weapon_id;
     if (battler_2 != null)
     {
         Hp2         = battler_2.hp;
         MaxHp2      = battler_2.maxhp;
         Team2       = battler_2.team;
         Name2       = battler_2.name;
         Exp2        = 0;
         Weapon_2_Id = -1;
     }
 }
示例#12
0
        public int get_multi(Game_Unit unit, Combat_Map_Object target, TactileLibrary.Data_Weapon weapon, int distance)
        {
            int multi = 0;

            if (!target.is_unit())
            {
                return(0);
            }
            if (weapon.Brave() && !unit.is_brave_blocked())
            {
                multi += 4;
            }
            if (unit.can_double_attack(target, distance))
            {
                multi += 2;
            }
            return(multi / 2);
        }
示例#13
0
        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());
            }
        }
示例#14
0
        protected void process_attacks(Game_Unit battler_1, Combat_Map_Object battler_2, int targetId)
        {
            battler_1.start_attack(-1, battler_2);
            if (battler_2 is Game_Unit)
            {
                (battler_2 as Game_Unit).start_attack(-1, battler_1);
            }

            bool ambush = battler_2 != null && battler_2.is_unit() &&
                          Global.game_map.units[targetId].counters_first(Global.game_map.units[Battler_1_Id]);

            int num_attacks1, num_attacks2;

            for (int i = 0; i < combat_attacks(
                     battler_1, battler_2, out num_attacks1, out num_attacks2); i++)
            {
                if (ambush)
                {
                    if (battler_2 != null && battler_2.is_unit() &&
                        i < num_attacks2 && this.weapon2 != null)
                    {
                        add_attacks(battler_1, battler_2, 2, this.weapon2);
                    }
                }
                // Add hits for battler_1 in this attack
                if (i < num_attacks1)
                {
                    if (i < num_attacks1)
                    {
                        add_attacks(battler_1, battler_2, 1, this.weapon1);
                    }
                }
                if (!ambush)
                {
                    if (battler_2 != null && battler_2.is_unit() &&
                        i < num_attacks2 && this.weapon2 != null)
                    {
                        add_attacks(battler_1, battler_2, 2, this.weapon2);
                    }
                }
            }
        }
示例#15
0
        protected void cause_damage(Combat_Map_Object attacker, Combat_Map_Object target, bool test)
        {
            // If the attack didn't backfire, cause damage as normal then apply on-hit healing here
            if (!Result.backfire)
            {
                target.combat_damage(Result.dmg, attacker, Result.state_change, Result.backfire, test);
                attacker.hp += Result.immediate_life_steal;
            }
            // Else it backfired, and damage is caused
            else
            {
                attacker.combat_damage(Result.dmg - Result.immediate_life_steal, target, Result.state_change, Result.backfire, test);
            }

            // Then apply is delayed life gain, such as from Resire or Nosferatu
            if (Result.delayed_life_steal && !attacker.is_dead)
            {
                attacker.hp += Result.delayed_life_steal_amount;
            }
        }
示例#16
0
        protected override void setup()
        {
            Game_Unit         battler_1 = Global.game_map.units[Battler_1_Id];
            Combat_Map_Object target    = Global.game_map.get_map_object((int)Battler_2_Id) as Combat_Map_Object;

            set_variables(battler_1, target);
            List <int> attack_array = new List <int>();

            battler_1.store_state();
            process_attacks(battler_1, target);
            battler_1.restore_state();
            // Set battle end stats
            if (Data.Count == 0)
            {
                throw new NotImplementedException("A battle with no attacks tried to occur");
            }
            Data[Data.Count - 1].Key.end_battle(Distance, Data[Data.Count - 1].Value);
            // Check if a battler has been killed
            if (battler_1.is_dead)
            {
                Kill = 1;
            }
            else if (target.hp <= Data
                     .Select(x => x.Key)
                     .Where(x => (x.Attacker == 1 ^ x.Result.backfire) && x.Result.hit)
                     .Select(x => x.Result.dmg).Sum()) // target.is_dead) //Debug
            {
                Kill = 2;
            }
            // Exp/Wexp
            Wexp1     = 0;
            Wexp2     = 0;
            Exp_Gain1 = 0;
            Exp_Gain2 = 0;
            // Reset HP
            battler_1.actor.hp = Hp1;
            target.hp          = Hp2;
            // Reset skills
            battler_1.actor.reset_skills(true);
        }
示例#17
0
        protected void add_attack(Game_Unit battler_1, Combat_Map_Object battler_2, int attacker)
        {
            battler_1.start_attack(Data.Count(x => x.Key.Attacker == attacker), battler_2);
            add_data(battler_1, battler_2);
            Data[Data.Count - 1].Key.Attacker = attacker;
            // Checks if this is the first attack of this unit
            for (int i = 0; i < Data.Count - 1; i++)
            {
                if (Data[i].Key.Attacker == Data[Data.Count - 1].Key.Attacker)
                {
                    Data[Data.Count - 1].Key.First_Attack = false;
                    break;
                }
            }
            if (attacker == 1)
            {
                Attacked_1 = true;
            }
            else
            {
                Attacked_2 = true;
            }
            ((Terrain_Round_Data)Data[Data.Count - 1].Key).set_attack(Distance, Data[Data.Count - 1].Value);
            // Add Attacks
            if (battler_1.actor.added_attacks.Count > 0)
            {
                foreach (int attack in battler_1.actor.added_attacks)
                {
                    Add_Attack.Add(attack == 1 ? 1 : 2);
                }
            }
            battler_1.actor.clear_added_attacks();

            Exp_Gain1 = Math.Max(0, Exp_Gain1);
            int uses = battler_1.weapon_use_count(Data[Data.Count - 1].Key.Result.hit);

            add_weapon_uses(ref Weapon_1_Uses, uses, this.weapon1);
        }
示例#18
0
        private void process_scripted_attacks(Game_Unit battler_1, Combat_Map_Object battler_2, Scripted_Combat_Script script)
        {
            battler_1.start_attack(-1, battler_2);
            if (battler_2 is Game_Unit)
            {
                (battler_2 as Game_Unit).start_attack(-1, battler_1);
            }

            for (int i = 0; i < script.Stats.Count; i++)
            {
                if (script.Stats[i].Result != Attack_Results.End)
                {
                    bool cont = false;
                    while (!cont)
                    {
                        cont = true;
                        int attacker = script.Stats[i].Attacker;
                        if (attacker > 0)
                        {
                            if (battler_2 == null)
                            {
                                add_solo_attack(battler_1, attacker);
                            }
                            else if (battler_2.is_unit())
                            {
                                add_attack(battler_1, battler_2 as Game_Unit, script.Stats[i]);
                            }
                            else
                            {
                                add_attack(battler_1, battler_2 as Combat_Map_Object, attacker);
                            }
                        }
                    }
                }
            }
            Kill = script.kill;
        }
示例#19
0
 public virtual void combat_damage(int dmg, Combat_Map_Object attacker, List <KeyValuePair <int, bool> > states, bool backfire, bool test)
 {
     hp -= dmg;
 }
示例#20
0
 protected override void set_variables(Game_Unit battler_1, Combat_Map_Object battler_2)
 {
     base.set_variables(battler_1, battler_2);
     Mode = get_staff_mode(Weapon_1_Id);
 }
示例#21
0
 protected virtual void process_attacks(Game_Unit battler_1, Combat_Map_Object battler_2)
 {
     process_attacks(battler_1, battler_2, battler_2 == null ? -1 : (int)Battler_2_Id);
 }
示例#22
0
 protected virtual void add_data(Game_Unit battler_1, Combat_Map_Object battler_2)
 {
     Data.Add(new KeyValuePair <Combat_Round_Data, List <Combat_Action_Data> >(
                  new Terrain_Round_Data(battler_1, battler_2, Distance), new List <Combat_Action_Data>()));
 }
示例#23
0
        protected virtual bool attackable(Game_Unit attacker, Combat_Map_Object target)
        {
            // If target doesn't exist because it's a flare use/etc
            if (target == null)
            {
                return(true);
            }

            // If attacker is dead return
            //@Debug: make sure units who are out of hp but technically aren't
            // dead for whatever reason will stop
            if (attacker.hp <= 0) //@Debug: .is_dead)
            {
                return(false);
            }

            bool is_target_unit = false;

            // If the target is already dead, stop attacking
            if (target.hp <= 0)
            {
                // Don't return if either battler wants the attacks to continue
                if (!attacker.continue_attacking() &&
                    !(target.is_unit() && (target as Game_Unit).continue_attacking()))
                {
                    return(false);
                }
            }
            Game_Unit target_unit = null;

            if (target.is_unit())
            {
                is_target_unit = true;
                target_unit    = (Game_Unit)target;
            }

            var weapon = attacker.id == Battler_1_Id ? this.weapon1 : this.weapon2;

            if (weapon == null)
            {
                return(false);
            }

            // If target is berserk ally and attacker isn't berserk, don't hurt your friend >:
            if (is_target_unit && attacker.id != Battler_1_Id &&
                !attacker.is_attackable_team(target_unit) && !can_counter_ally(attacker))
            {
                return(false);
            }

            int hit, uses;

            if (attacker.id == Battler_1_Id)
            {
                List <int?> ary = Combat.combat_stats(attacker.id, target.id, Distance);
                hit  = 100;
                uses = Weapon_1_Uses;
                if (ary[0] == null && !weapon.is_staff())
                {
                    return(false); // This is newly added to account for the attacker being put to sleep, did any other cases make hit null?
                }
                if (ary[0] != null)
                {
                    hit = (int)ary[0];
                }
            }
            else
            {
                List <int?> ary = Combat.combat_stats(target.id, attacker.id, Distance);
                if (ary[4] == null)
                {
                    return(false);
                }
                hit  = (int)ary[4];
                uses = Weapon_2_Uses;
            }

            // Breaks if the attacker can't fight/broke their weapon
            if (hit < 0 || attacker.is_weapon_broke(uses))
            {
                return(false);
            }

            return(true);
        }