📄 centity.java
字号:
// Offensive characterization - damage potentials for(Mounted m : entity.getWeaponList()) { int arc = entity.getWeaponArc(entity.getEquipmentNum(m)); WeaponType weapon = (WeaponType) m.getType(); // Don't count weapons that don't have ammo, are destroyed/jammed if (m.isDestroyed()) continue; if (m.isJammed()) continue; if (weapon.getName() == "Stop Swarm Attack") // This isn't an attack continue; // This is bad stuff. Infantry/BA weapons that don't require ammo // SHOULD return AmmoType.T_NA from getAmmoType. They don't, so // in the meantime check against a list of all infantry/BA weapons that // do use ammo // TODO: Fix ammo type of all non-ammo using infantry/BA weapons and fix this code! if (!(entity instanceof Infantry)){ if (m.getLinked() == null & weapon.getAmmoType() != AmmoType.T_NA){ continue; } } else { // Ignore list: T_BA_MG T_BA_SMALL_LASER // Also, ignore anything with the F_INFANTRY flag if (!weapon.hasFlag(WeaponType.F_INFANTRY) & weapon.getAmmoType() != AmmoType.T_NA){ if (m.getLinked() == null){ if (weapon.getAmmoType() != AmmoType.T_BA_MG & weapon.getAmmoType() != AmmoType.T_BA_SMALL_LASER){ continue; } } } } num_weapons++; heat_total += weapon.getHeat(); int min = weapon.getMinimumRange(); int lr = weapon.getExtremeRange(); double ed; int gunnery = entity.getCrew().getGunnery(); // Range used to start at 1; updated to account for stacking for (int curRange = 0; curRange <= lr && curRange <= MAX_RANGE; curRange++) { ed = CEntity.getExpectedDamage(entity, m, curRange, gunnery); if (curRange <= min & curRange <= MIN_BRACKET) { this.minRangeMods[curRange] += 1 + min - curRange; } // Weapons that generate heat are derated based on the // units current heat level, 'cause building more heat is bad this.addDamage( arc, entity.isSecondaryArcWeapon(entity.getEquipmentNum(m)), curRange, ed * ((weapon.getHeat() > 0) ? heat_mod : 1)); } this.long_range = Math.max(this.long_range, Math.min(lr, MAX_RANGE)); } // Add in approximate physical damages from Mechs if (this.entity instanceof Mech){ this.addDamage(Compute.ARC_LEFTARM, true, 1, (tsm_offset ? 1.0 : 0.5) * this.entity.getWeight()/10 * Compute.oddsAbove(this.entity.getCrew().getPiloting())/100); this.addDamage(Compute.ARC_RIGHTARM, true, 1, (tsm_offset ? 1.0 : 0.5) * this.entity.getWeight()/10 * Compute.oddsAbove(this.entity.getCrew().getPiloting())/100); } // Average out the minimum range modifiers for (int r = 1; r < this.minRangeMods.length; r++) { if (num_weapons > 0) this.minRangeMods[r] = (int) Math.round(( (double) this.minRangeMods[r]) / (double) num_weapons); } this.computeRange(Compute.ARC_FORWARD); // Heat characterization - how badly will it overheat this round int heat = 0; if (entity instanceof Mech){ heat = heat_total - capacity; // Include heat from active stealth armor if (entity instanceof Mech && entity.isStealthActive()){ heat += 10; } // Include heat from infernos if (entity.infernos.isStillBurning()){ heat += 6; } // Include heat from engine hits if (entity instanceof Mech){ heat += entity.getEngineCritHeat(); } // Include heat for standing in a fire if (entity.getPosition() != null){ if (tb.game.getBoard().getHex(entity.getPosition()) != null) { if (tb.game.getBoard().getHex(entity.getPosition()). terrainLevel(Terrains.FIRE) == 2) { heat += 5; } } } // Include heat from ambient temperature heat += tb.game.getTemperatureDifference(); } if (heat <= 4){ this.overheat = OVERHEAT_NONE; } if (heat > 3){ this.overheat = OVERHEAT_LOW; } if (heat > 9 & !this.tsm_offset){ this.overheat = OVERHEAT_HIGH; } if (heat > 12 & this.tsm_offset){ this.overheat = OVERHEAT_HIGH; } // Make a guess as to whether MASC should be turned on or off // TODO: Link this to a Bot configuration file if (entity instanceof Mech){ if (((Mech) entity).hasMASC()){ if (((Mech) entity).getMASCTarget() <= 5 + Compute.randomInt(6)){ masc_threat = false; } else { masc_threat = true; } } } // Defensive characterization - protection values double max = 1.0; // Initialize armor values double armor[][] = MECH_ARMOR; if (this.entity instanceof Tank) { if (((Tank) entity).hasNoTurret()) { armor = TANK_ARMOR; } else { armor = TANK_WT_ARMOR; } } if (this.entity instanceof Infantry) { if (!(this.entity instanceof BattleArmor)){ armor = INFANTRY_ARMOR; } else { if (this.entity.isClan()){ armor = CLBA_ARMOR; } else { armor = ISBA_ARMOR; } } } if (this.entity instanceof Protomech) { if (((Protomech) entity).hasMainGun()) { armor = PROTOMECH_MG_ARMOR; } else { armor = PROTOMECH_ARMOR; } } if (this.entity instanceof GunEmplacement) { armor = ((GunEmplacement) entity).hasTurret() ? GUN_EMPLACEMENT_TURRET_ARMOR : GUN_EMPLACEMENT_ARMOR; } // Arcs for the outside loop are those used for incoming damage: // front, rear, left, right as per static variables in ToHitData for (int arc = FIRST_ARC; arc <= LAST_PRIMARY_ARC; arc++) { this.armor_health[arc] = 0.0; // "i" is a location index. It matches the location static variables // for each sub-entity type (Mech, Tank, etc) for (int i = 0; i < armor[arc].length; i++) { this.armor_health[arc] += armor[arc][i] * getArmorValue(i, arc == ToHitData.SIDE_REAR); } // ProtoMechs have a "near miss" location that isn't accounted for in // the hit-table-probability array. Rolling 3 or 11 on 2d6 is 4/36. if (entity instanceof Protomech){ this.armor_health[arc] *= 1.22; } max = Math.max(armor_health[arc], max); this.armor_percent[arc] = this.armor_health[arc] / max; } // Calculate an average armor value for the entire entity // TODO: Change to array, with an entry for each arc this.avg_armor = (armor_health[0] + armor_health[1] + armor_health[2] + armor_health[3]) / 4; // Calculate average internal structure across the unit // Default to Mech unit, which has 7 locations plus the head (ignored due to low // hit probability and low standard IS) this.avg_iarmor = this.entity.getTotalInternal() / 7.0; if (entity instanceof Infantry){ this.avg_iarmor = entity instanceof BattleArmor ? ((BattleArmor) entity).getShootingStrength() : 1.0; } if (entity instanceof Tank){ this.avg_iarmor = this.entity.getTotalInternal() / (((Tank) entity).hasNoTurret() ? 4.0 : 5.0); } if (entity instanceof Protomech){ this.avg_iarmor = this.entity.getTotalInternal() / (((Protomech) entity).hasMainGun() ? 5.0 : 6.0); } if (entity instanceof GunEmplacement){ this.avg_iarmor = 1.0; } } /** * Add a statistical damage into the arc/range table. The arc is based upon * firing arcs defined in Compute. If the unit is a Mech capable of flipping * arms, full arm damages are applied to the rear arc; otherwise only add * half as the Mech can only twist in one direction. */ private void addDamage(int arc, boolean secondary, int r, double ed) { if (arc == Compute.ARC_360 | arc == Compute.ARC_MAINGUN) { for (int i = FIRST_ARC; i <= LAST_ARC; i++){ damages[i][r] += ed; } } else { if (secondary){ // Weapon can be applied to a secondary arc, // such as a torso twist or turret rotate if (arc == Compute.ARC_FORWARD){ damages[Compute.ARC_FORWARD][r] += ed; damages[Compute.ARC_LEFTARM][r] += ed; damages[Compute.ARC_RIGHTARM][r] += ed; } // Flipping arms allows both arms to fire into the rear arc. // Otherwise, its limited to one. Approximate with a 50/50 // split. if (arc == Compute.ARC_LEFTARM | arc == Compute.ARC_LEFTSIDE){ damages[Compute.ARC_FORWARD][r] += ed; damages[Compute.ARC_LEFTARM][r] += ed; damages[Compute.ARC_REAR][r] += this.entity.canFlipArms() ? ed : (0.5 * ed); } if (arc == Compute.ARC_RIGHTARM | arc == Compute.ARC_RIGHTSIDE){ damages[Compute.ARC_FORWARD][r] += ed; damages[Compute.ARC_RIGHTARM][r] += ed; damages[Compute.ARC_REAR][r] += this.entity.canFlipArms() ? ed : (0.5 * ed); } if (arc == Compute.ARC_REAR){ damages[Compute.ARC_REAR][r] += ed; damages[Compute.ARC_LEFTARM][r] += ed; damages[Compute.ARC_RIGHTARM][r] += ed; } } else { if (arc == Compute.ARC_FORWARD){ damages[Compute.ARC_FORWARD][r] += ed; } if (arc == Compute.ARC_LEFTARM | arc == Compute.ARC_LEFTSIDE){ damages[Compute.ARC_FORWARD][r] += ed; damages[Compute.ARC_LEFTARM][r] += ed; } if (arc == Compute.ARC_RIGHTARM | arc == Compute.ARC_RIGHTSIDE){ damages[Compute.ARC_FORWARD][r] += ed; damages[Compute.ARC_RIGHTARM][r] += ed; } if (arc == Compute.ARC_REAR){ damages[Compute.ARC_REAR][r] += ed; } } } } /** * Fills range damage values for short, medium, long, and all, plus * sets the range bracket for the entity, which is 1/3 of long range * or 1/4 extreme range. The arc argument follows Compute.ARC_XXX * format. */ public void computeRange(int arc) { double optimizer[] = {0, 0, 0, 0}; Arrays.fill(range_damages, 0); // Create short, medium, and long range values for each arc this.rd_bracket = this.long_range/4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -