Esempio n. 1
0
 /*
 ====================================================================
 CreateAction a unit by passing a Unit struct with the following stuff set:
   x, y, str, entr, exp, delay, orient, nation, player.
 This function will use the passed values to create a Unit struct
 with all values set then.
 ====================================================================
 */
 public static Unit CreateUnit(Unit_Lib_Entry prop, Unit_Lib_Entry trsp_prop, Unit unit_base)
 {
     Unit unit;
     if (prop == null) return null;
     unit = new Unit();
     /* shallow copy of properties */
     unit.prop = prop;
     unit.sel_prop = unit.prop;
     unit.embark = UnitEmbarkTypes.EMBARK_NONE;
     /* assign the passed transporter without any check */
     if (trsp_prop != null && (prop.flags & UnitFlags.FLYING) != UnitFlags.FLYING && (prop.flags & UnitFlags.SWIMMING) != UnitFlags.SWIMMING)
     {
         unit.trsp_prop = trsp_prop;
         /* a sea/air ground transporter is active per default */
         if ((trsp_prop.flags & UnitFlags.SWIMMING) == UnitFlags.SWIMMING)
         {
             unit.embark = UnitEmbarkTypes.EMBARK_SEA;
             unit.sel_prop = unit.trsp_prop;
         }
         if ((trsp_prop.flags & UnitFlags.FLYING) == UnitFlags.FLYING)
         {
             unit.embark = UnitEmbarkTypes.EMBARK_AIR;
             unit.sel_prop = unit.trsp_prop;
         }
     }
     /* copy the base values */
     unit.delay = unit_base.delay;
     unit.x = unit_base.x; unit.y = unit_base.y;
     unit.str = unit_base.str; unit.entr = unit_base.entr;
     unit.player = unit_base.player;
     unit.nation = unit_base.nation;
     unit.name = unit_base.name;
     unit.AddExperience(unit_base.exp_level * 100);
     unit.orient = unit_base.orient;
     unit.AdjustIcon();
     unit.unused = true;
     unit.supply_level = 100;
     unit.cur_ammo = unit.prop.ammo;
     unit.cur_fuel = unit.prop.fuel;
     if ((unit.cur_fuel == 0) && (unit.trsp_prop != null) &&
         (!string.IsNullOrEmpty(unit.trsp_prop.id)) && unit.trsp_prop.fuel > 0)
         unit.cur_fuel = unit.trsp_prop.fuel;
     unit.tag = unit_base.tag;
     /* update life bar properties */
     update_bar(unit);
     /* allocate backup mem */
     unit.backup = new Unit();
     return unit;
 }
Esempio n. 2
0
 public FIGHT_TYPES Attack(Unit target, UNIT_ATTACK type, bool real, bool force_rugged)
 {
     int unit_old_str = this.str;//, target_old_str = target.str;
     int unit_old_ini = this.sel_prop.ini, target_old_ini = target.sel_prop.ini;
     int unit_dam = 0, unit_suppr = 0, target_dam = 0, target_suppr = 0;
     int rugged_chance;
     bool rugged_def = false;
     int exp_mod;
     FIGHT_TYPES ret = FIGHT_TYPES.AR_NONE; /* clear flags */
     ATTACK_FLAGS strike;
     /* check if rugged defense occurs */
     if (real && type == UNIT_ATTACK.UNIT_ACTIVE_ATTACK)
         if (this.CheckRuggedDefense(target) || (force_rugged && this.IsClose(target)))
         {
             rugged_chance = this.GetRuggedDefenseChance(target);
             if (Misc.DICE(100) <= rugged_chance || force_rugged)
                 rugged_def = true;
         }
     /* PG's formula for initiative is
        min { base initiative, terrain max initiative } +
        ( exp_level + 1 ) / 2 + D3 */
     /* against aircrafts the initiative is used since terrain does not matter */
     /* target's terrain is used for fight */
     if ((this.sel_prop.flags & UnitFlags.FLYING) != UnitFlags.FLYING &&
         (target.sel_prop.flags & UnitFlags.FLYING) != UnitFlags.FLYING)
     {
         this.sel_prop.ini = Math.Min(this.sel_prop.ini, target.terrain.max_ini);
         target.sel_prop.ini = Math.Min(target.sel_prop.ini, target.terrain.max_ini);
     }
     this.sel_prop.ini += (this.exp_level + 1) / 2;
     target.sel_prop.ini += (target.exp_level + 1) / 2;
     /* special initiative rules:
        antitank inits attack tank|recon: atk 0, def 99
        tank inits attack against anti-tank: atk 0, def 99
        defensive fire: atk 99, def 0
        submarine attacks: atk 99, def 0
        ranged attack: atk 99, def 0
        rugged defense: atk 0
        air unit attacks air defense: atk = def
        non-art vs art: atk 0, def 99 */
     if ((this.sel_prop.flags & UnitFlags.ANTI_TANK) == UnitFlags.ANTI_TANK)
         if ((target.sel_prop.flags & UnitFlags.TANK) == UnitFlags.TANK)
         {
             this.sel_prop.ini = 0;
             target.sel_prop.ini = 99;
         }
     if (((this.sel_prop.flags & UnitFlags.DIVING) == UnitFlags.DIVING) ||
          ((this.sel_prop.flags & UnitFlags.ARTILLERY) == UnitFlags.ARTILLERY) ||
          ((this.sel_prop.flags & UnitFlags.AIR_DEFENSE) == UnitFlags.AIR_DEFENSE) ||
          type == UNIT_ATTACK.UNIT_DEFENSIVE_ATTACK
     )
     {
         this.sel_prop.ini = 99;
         target.sel_prop.ini = 0;
     }
     if ((this.sel_prop.flags & UnitFlags.FLYING) == UnitFlags.FLYING)
         if ((target.sel_prop.flags & UnitFlags.AIR_DEFENSE) == UnitFlags.AIR_DEFENSE)
             this.sel_prop.ini = target.sel_prop.ini;
     if (rugged_def)
         this.sel_prop.ini = 0;
     if (force_rugged)
         target.sel_prop.ini = 99;
     /* the dice is rolled after these changes */
     if (real)
     {
         this.sel_prop.ini += Misc.DICE(3);
         target.sel_prop.ini += Misc.DICE(3);
     }
     #if DEBUG
     if (real)
     {
         Console.WriteLine("{0} Initiative: {1}", this.name, this.sel_prop.ini);
         Console.WriteLine("{0} Initiative: {1}", target.name, target.sel_prop.ini);
         if (this.CheckRuggedDefense(target))
             Console.WriteLine("Rugged Defense: {0} ({1})",
                     rugged_def ? "yes" : "no",
                     this.GetRuggedDefenseChance(target));
     }
     #endif
     /* in a real combat a submarine may evade */
     if (real && type == UNIT_ATTACK.UNIT_ACTIVE_ATTACK && ((target.sel_prop.flags & UnitFlags.DIVING) == UnitFlags.DIVING))
     {
         if (Misc.DICE(10) <= 7 + (target.exp_level - this.exp_level) / 2)
         {
             strike = ATTACK_FLAGS.ATK_NO_STRIKE;
             ret |= FIGHT_TYPES.AR_EVADED;
         }
         else
             strike = ATTACK_FLAGS.ATK_UNIT_FIRST;
     #if DEBUG
         Console.WriteLine("\nSubmarine Evasion: {0} ({1}%)\n",
          (strike == ATTACK_FLAGS.ATK_NO_STRIKE) ? "yes" : "no",
          10 * (7 + (target.exp_level - this.exp_level) / 2));
     #endif
     }
     else
         /* who is first? */
         if (this.sel_prop.ini == target.sel_prop.ini)
             strike = ATTACK_FLAGS.ATK_BOTH_STRIKE;
         else
             if (this.sel_prop.ini > target.sel_prop.ini)
                 strike = ATTACK_FLAGS.ATK_UNIT_FIRST;
             else
                 strike = ATTACK_FLAGS.ATK_TARGET_FIRST;
     /* the one with the highest initiative begins first if not defensive fire or artillery */
     if (strike == ATTACK_FLAGS.ATK_BOTH_STRIKE)
     {
         /* both strike at the same time */
         GetDamage(this, this, target, type, real, rugged_def, out target_dam, out target_suppr);
         if (target.CheckAttack(this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK))
             GetDamage(this, target, this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK, real, rugged_def, out unit_dam, out unit_suppr);
         target.ApplyDamage(target_dam, target_suppr, this);
         this.ApplyDamage(unit_dam, unit_suppr, target);
     }
     else
         if (strike == ATTACK_FLAGS.ATK_UNIT_FIRST)
         {
             /* unit strikes first */
             GetDamage(this, this, target, type, real, rugged_def, out target_dam, out target_suppr);
             if (target.ApplyDamage(target_dam, target_suppr, this) != 0)
                 if (target.CheckAttack(this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK) && type != UNIT_ATTACK.UNIT_DEFENSIVE_ATTACK)
                 {
                     GetDamage(this, target, this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK, real, rugged_def, out unit_dam, out unit_suppr);
                     this.ApplyDamage(unit_dam, unit_suppr, target);
                 }
         }
         else
             if (strike == ATTACK_FLAGS.ATK_TARGET_FIRST)
             {
                 /* target strikes first */
                 if (target.CheckAttack(this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK))
                 {
                     GetDamage(this, target, this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK, real, rugged_def, out unit_dam, out unit_suppr);
                     if (this.ApplyDamage(unit_dam, unit_suppr, target) == 0)
                         ret |= FIGHT_TYPES.AR_UNIT_ATTACK_BROKEN_UP;
                 }
                 if (unit_get_cur_str(this) > 0)
                 {
                     GetDamage(this, this, target, type, real, rugged_def, out target_dam, out target_suppr);
                     target.ApplyDamage(target_dam, target_suppr, this);
                 }
             }
     /* check return value */
     if (this.str == 0)
         ret |= FIGHT_TYPES.AR_UNIT_KILLED;
     else
         if (unit_get_cur_str(this) == 0)
             ret |= FIGHT_TYPES.AR_UNIT_SUPPRESSED;
     if (target.str == 0)
         ret |= FIGHT_TYPES.AR_TARGET_KILLED;
     else
         if (unit_get_cur_str(target) == 0)
             ret |= FIGHT_TYPES.AR_TARGET_SUPPRESSED;
     if (rugged_def)
         ret |= FIGHT_TYPES.AR_RUGGED_DEFENSE;
     if (real)
     {
         /* cost ammo */
         if (Config.supply)
         {
             //if (DICE(10)<=target_old_str)
             this.cur_ammo--;
             if (target.CheckAttack(this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK) && target.cur_ammo > 0)
                 //if (DICE(10)<=unit_old_str)
                 target.cur_ammo--;
         }
         /* costs attack */
         if (this.cur_atk_count > 0) this.cur_atk_count--;
         /* target: loose entrenchment if damage was taken or with a unit.str*10% chance */
         if (target.entr > 0)
             if (target_dam > 0 || Misc.DICE(10) <= unit_old_str)
                 target.entr--;
         /* attacker looses entrenchment if it got hurt */
         if (this.entr > 0 && unit_dam > 0)
             this.entr--;
         /* gain experience */
         exp_mod = target.exp_level - this.exp_level;
         if (exp_mod < 1) exp_mod = 1;
         this.AddExperience(exp_mod * target_dam + unit_dam);
         exp_mod = this.exp_level - target.exp_level;
         if (exp_mod < 1) exp_mod = 1;
         target.AddExperience(exp_mod * unit_dam + target_dam);
         if (this.IsClose(target))
         {
             this.AddExperience(10);
             target.AddExperience(10);
         }
         /* adjust life bars */
         update_bar(this);
         update_bar(target);
     }
     this.sel_prop.ini = unit_old_ini;
     target.sel_prop.ini = target_old_ini;
     return ret;
 }
Esempio n. 3
0
        /*
        ====================================================================
        Merge these two units: unit is the new unit and source must be
        removed from map and memory after this function was called.
        ====================================================================
        */
        public void Merge(Unit unit, Unit source)
        {
            /* units relative weight */
            float weight1, weight2, total;
            int i;
            /* compute weight */
            weight1 = unit.str; weight2 = source.str;
            total = unit.str + source.str;
            /* adjust so weight1 + weigth2 = 1 */
            weight1 /= total; weight2 /= total;
            /* no other actions allowed */
            unit.unused = false; unit.cur_mov = 0; unit.cur_atk_count = 0;
            /* repair damage */
            unit.str += source.str;
            /* reorganization costs some entrenchment: the new units are assumed to have
               entrenchment 0 since they come. new entr is rounded weighted sum */
            unit.entr = (int)Math.Floor((float)unit.entr * weight1 + 0.5); /* + 0 * weight2 */
            /* update experience */
            i = (int)(weight1 * unit.exp + weight2 * source.exp);
            unit.exp = 0; unit.AddExperience(i);
            /* update unit::prop */
            /* related initiative */
            unit.prop.ini = (int)(weight1 * unit.prop.ini + weight2 * source.prop.ini);
            /* minimum movement */
            if (source.prop.mov < unit.prop.mov)
                unit.prop.mov = source.prop.mov;
            /* maximum spotting */
            if (source.prop.spt > unit.prop.spt)
                unit.prop.spt = source.prop.spt;
            /* maximum range */
            if (source.prop.rng > unit.prop.rng)
                unit.prop.rng = source.prop.rng;
            /* relative attack count */
            unit.prop.atk_count = (int)(weight1 * unit.prop.atk_count + weight2 * source.prop.atk_count);
            if (unit.prop.atk_count == 0) unit.prop.atk_count = 1;
            /* relative attacks */
            /* if attack is negative simply use absolute value; only restore negative if both units are negative */
            for (i = 0; i < DB.UnitLib.trgt_type_count; i++)
            {
                bool neg = (unit.prop.atks[i] < 0 && source.prop.atks[i] < 0);
                unit.prop.atks[i] = (int)(weight1 * Math.Abs(unit.prop.atks[i]) + weight2 * (source.prop.atks[i]));
                if (neg) unit.prop.atks[i] *= -1;
            }
            /* relative defence */
            unit.prop.def_grnd = (int)(weight1 * unit.prop.def_grnd + weight2 * source.prop.def_grnd);
            unit.prop.def_air = (int)(weight1 * unit.prop.def_air + weight2 * source.prop.def_air);
            unit.prop.def_cls = (int)(weight1 * unit.prop.def_cls + weight2 * source.prop.def_cls);
            /* relative ammo */
            unit.prop.ammo = (int)(weight1 * unit.prop.ammo + weight2 * source.prop.ammo);
            unit.cur_ammo = (int)(weight1 * unit.cur_ammo + weight2 * source.cur_ammo);
            /* relative fuel */
            unit.prop.fuel = (int)(weight1 * unit.prop.fuel + weight2 * source.prop.fuel);
            unit.cur_fuel = (int)(weight1 * unit.cur_fuel + weight2 * source.cur_fuel);
            /* merge flags */
            unit.prop.flags |= source.prop.flags;
            /* sounds, picture are kept */
            /* unit::trans_prop isn't updated so far: */
            /* transporter of first unit is kept if any else second unit's transporter is used */
            if (string.IsNullOrEmpty(unit.trsp_prop.id) && !string.IsNullOrEmpty(source.trsp_prop.id))
            {
            #if TODO
                memcpy(&unit.trsp_prop, &source.trsp_prop, sizeof(Unit_Lib_Entry));

            #endif

                /* as this must be a ground transporter copy current fuel value */
                unit.cur_fuel = source.cur_fuel;
                throw new NotImplementedException();
            }
            update_bar(unit);
        }