public static Fix16 calcFowardThrust(SeekingWeaponInfo skrinfo) { int wpnskrspd = skrinfo.SeekerSpeed; int hitpoints = skrinfo.SeekerDurability; Fix16 mass = hitpoints * 0.1; return((Fix16)wpnskrspd * mass * (Fix16)10.0); }
public static Compass calcRotate(SeekingWeaponInfo skrinfo) { int wpnskrspd = skrinfo.SeekerSpeed; int hitpoints = skrinfo.SeekerDurability; Fix16 mass = hitpoints * 0.1; int wpnskrEvade = Mod.Current.Settings.SeekerEvasion; return(new Compass((Fix16)wpnskrspd * mass * (Fix16)10 / ((Fix16)2.5 - (Fix16)wpnskrEvade * (Fix16)0.01), false)); }
public static Fix16 calcStrafeThrust(SeekingWeaponInfo skrinfo) { int wpnskrspd = skrinfo.SeekerSpeed; int hitpoints = skrinfo.SeekerDurability; Fix16 mass = hitpoints * 0.1; int wpnskrEvade = Mod.Current.Settings.SeekerEvasion; return((Fix16)wpnskrspd * mass * (Fix16)5.0 / ((Fix16)4 - (Fix16)wpnskrEvade * (Fix16)0.01)); }
public CombatSeeker(CombatObject attacker, CombatWeapon launcher, int ID) : base(null, new PointXd(attacker.cmbt_loc), new PointXd(attacker.cmbt_vel), ID, "SKR") { WorkingObject = this; SeekingWeaponInfo skrinfo = (SeekingWeaponInfo)launcher.weapon.Template.ComponentTemplate.WeaponInfo; Hitpoints = MaxHitpoints = skrinfo.SeekerDurability; cmbt_mass = (Fix16)Hitpoints * 0.1;//(Fix16)s.MaxHitpoints; // sure why not? maxfowardThrust = calcFowardThrust(skrinfo); maxStrafeThrust = calcStrafeThrust(skrinfo); maxRotate = calcRotate(skrinfo); cmbt_thrust = new PointXd(0, 0, 0); cmbt_accel = new PointXd(0, 0, 0); newDice(ID); #if DEBUG Console.WriteLine("MaxAccel = " + maxfowardThrust / cmbt_mass); #endif this.launcher = launcher; }
public CombatWeapon(Component weapon) { #if DEBUG Console.WriteLine("Creating New CombatWeapon"); #endif this.weapon = weapon; #if DEBUG Console.WriteLine("Getting Weapon Template WeaponInfo"); #endif var wpninfo = weapon.Template.ComponentTemplate.WeaponInfo; #if DEBUG Console.WriteLine("Done"); Console.WriteLine("Getting Range info"); #endif int wpMaxR = wpninfo.MaxRange; #if DEBUG Console.WriteLine("Done MaxRange"); #endif int wpMinR = wpninfo.MinRange; #if DEBUG Console.WriteLine("Done MinRange"); #endif #if DEBUG Console.WriteLine("done getting random info"); #endif if (wpninfo.DisplayEffect.GetType() == typeof(Combat.BeamWeaponDisplayEffect)) { weaponType = "Beam"; maxRange_distance = (Fix16)wpMaxR * Battle_Space.KilometersPerSquare; minRange = (Fix16)wpMinR * Battle_Space.KilometersPerSquare; } else if (wpninfo.DisplayEffect.GetType() == typeof(Combat.ProjectileWeaponDisplayEffect)) { weaponType = "Bolt"; boltSpeed = (Fix16)wpMaxR * Battle_Space.KilometersPerSquare; maxRange_time = (Fix16)1; // (maxTime for bolts) untill mod files can handle this, bolt weapons range is the distance it can go in 1 sec. minRange = ((Fix16)wpMinR / boltSpeed); //(minTime for bolts) distance / speed = time } else if (wpninfo.DisplayEffect.GetType() == typeof(Combat.SeekerWeaponDisplayEffect)) { #if DEBUG Console.WriteLine("CombatWeapon is a Seeker"); #endif SeekingWeaponInfo seekerinfo = (SeekingWeaponInfo)weapon.Template.ComponentTemplate.WeaponInfo; weaponType = "Seeker"; boltSpeed = 0; //seekers get launched at 0 speed. int mass = seekerinfo.SeekerDurability; // sure why not? int wpnskrspd = seekerinfo.SeekerSpeed; //Fix16 Thrust = (Fix16)wpnskrspd * mass * (Fix16)0.001; //boltSpeed = (Fix16)wpMaxR * (Fix16)1000 * (Fix16)(Battle_Space.TickLength); // convert from kilometers per second to meters per tick maxRange_time = (Fix16)wpMaxR / (Fix16)wpnskrspd; // (maxTime for Missiles) untill mod files can handle this, bolt weapons range is the distance it can go in 1 sec. } else //treat it like a beam I guess. { weaponType = "Unknown"; maxRange_distance = (Fix16)wpMaxR * Battle_Space.KilometersPerSquare; minRange = (Fix16)wpMinR * Battle_Space.KilometersPerSquare; } double wpiReloadRate = wpninfo.ReloadRate; reloadRate = (Fix16)wpiReloadRate; nextReload = 1; #if DEBUG Console.WriteLine("Done creating CombatWeapon"); #endif }
public static Fix16 seekerTimeToTarget(CombatObject attacker, CombatObject target, SeekingWeaponInfo skrinfo) { //Fix16 distance_toTarget = Trig.distance(attacker.cmbt_loc, target.cmbt_loc); PointXd px = new PointXd(attacker.cmbt_loc - target.cmbt_loc); Fix16 distance_toTarget = px.Length; //SeekingWeaponInfo seekerinfo = (SeekingWeaponInfo)weapon.Template.ComponentTemplate.WeaponInfo; int hitpoints = skrinfo.SeekerDurability; Fix16 mass = hitpoints * 0.1; int wpnskrspd = skrinfo.SeekerSpeed; Fix16 Thrust = calcFowardThrust(skrinfo); Fix16 acceleration = Thrust / mass * -1; //*-1 because we should be accelerating towards the target, not away. Fix16 startV = seekerClosingSpeed_base(attacker, target); //Fix16 endV = ??? Fix16 baseTimetoTarget = distance_toTarget / startV; //Fix16 deltaV = baseTimetoTarget //Fix16[] ttt = NMath.quadratic(acceleration, startV, distance_toTarget); Fix64[] ttt2 = NMath.quadratic64(acceleration, startV, distance_toTarget); Fix16 TimetoTarget; if (ttt2[2] == 1) { TimetoTarget = Fix16.Max((Fix16)ttt2[0], (Fix16)ttt2[1]); } else { TimetoTarget = (Fix16)ttt2[0]; } #if DEBUG Console.WriteLine("SeekerTimeToTarget = " + TimetoTarget); #endif return(TimetoTarget); }
public override IEnumerable <IModObject> Load(Mod mod) { foreach (var rec in DataFile.Records) { var c = new ComponentTemplate(); c.TemplateParameters = rec.Parameters; mod.ComponentTemplates.Add(c); int index = -1; c.ModID = rec.Get <string>("ID", c); c.Name = rec.Get <string>("Name", c); c.Description = rec.Get <string>("Description", c); var picfield = rec.FindField("Pic", ref index, false, 0, true); if (picfield != null) { c.PictureName = picfield.CreateFormula <string>(c); } else { c.PictureName = "Comp_" + rec.Get <int>("Pic Num", c).Value.ToString("000"); // for compatibility with SE4 } c.Size = rec.Get <int>("Tonnage Space Taken", c); c.Durability = rec.Get <int>("Tonnage Structure", c); foreach (var costfield in rec.Fields.Where(cf => cf.Name.StartsWith("Cost "))) { c.Cost[Resource.Find(costfield.Name.Substring("Cost ".Length))] = costfield.CreateFormula <int>(c); } var vtoverridefield = rec.FindField(new string[] { "Vehicle List Type Override", "Vechicle List Type Override" }, ref index, false, 0, true); // silly Aaron can't spell "vehicle" if (vtoverridefield != null) { c.VehicleTypes = ParseVehicleTypes(vtoverridefield.Value, ",", rec); } else { c.VehicleTypes = ParseVehicleTypes(rec.Get <string>("Vehicle Type", c), @"\", rec); } c.SupplyUsage = rec.Get <int>("Supply Amount Used", c); var restrictions = rec.Get <string>("Restrictions", c); if (!string.IsNullOrEmpty(restrictions) && restrictions != "None") { var word = restrictions.Value.Split(' ').First(); int num; if (numbers.Contains(word)) { c.MaxPerVehicle = numbers.IndexOf(word); } else if (int.TryParse(word, out num)) { c.MaxPerVehicle = num; } else { Mod.Errors.Add(new DataParsingException("Can't parse \"" + word + "\" as a max-per-vehicle restriction.", Mod.CurrentFileName, rec)); } } c.Group = rec.Get <string>("General Group", c); c.Family = rec.Get <string>("Family", c); c.RomanNumeral = rec.Get <int>("Roman Numeral", c); c.StellarConstructionGroup = rec.Get <string>("Custom Group", c); foreach (var tr in RequirementLoader.LoadEmpireRequirements(rec, c, RequirementType.Unlock)) { c.UnlockRequirements.Add(tr); } // TODO - build and use requirements foreach (var abil in AbilityLoader.Load(Filename, rec, c)) { c.Abilities.Add(abil); } var wfield = rec.FindField("Weapon Type", ref index, false, 0, true); if (wfield != null) { WeaponInfo w = null; if (wfield.Value == "Seeking" || wfield.Value == "Seeking Point-Defense") { var sw = new SeekingWeaponInfo(); sw.SeekerSpeed = rec.Get <int>("Weapon Seeker Speed", c); sw.SeekerDurability = rec.Get <int>("Weapon Seeker Dmg Res", c); w = sw; } else if (wfield.Value == "Direct Fire" || wfield.Value == "Point-Defense") { var dfw = new DirectFireWeaponInfo(); dfw.AccuracyModifier = rec.Get <int>("Weapon Modifier", c); w = dfw; } else if (wfield.Value == "Warhead" || wfield.Value == "Warhead Point-Defense") { var ww = new WarheadWeaponInfo(); w = ww; } else if (string.IsNullOrEmpty(wfield.Value) || wfield.Value == "None") { w = null; } else { Mod.Errors.Add(new DataParsingException("Invalid weapon type \"" + wfield.Value + "\".", Mod.CurrentFileName, rec, wfield)); } if (w != null) { if (wfield.Value.EndsWith("Point-Defense")) { w.IsPointDefense = true; } var wtoverridefield = rec.FindField("Weapon List Target Override", ref index, false, 0, true); if (wtoverridefield != null) { w.Targets = ParseWeaponTargets(wtoverridefield.Value, ",", rec); } else { w.Targets = ParseWeaponTargets(rec.Get <string>("Weapon Target", c), @"\", rec); } w.MinRange = rec.Get <int>(new string[] { "Min Range", "Minimum Range", "Weapon Min Range", "Weapon Minimum Range" }, c) ?? 0; w.MaxRange = rec.Get <int>(new string[] { "Max Range", "Maximum Range", "Weapon Max Range", "Weapon Maximum Range" }, c) ?? 20; var dmgfield = rec.FindField(new string[] { "Damage", "Weapon Damage", "Damage At Rng", "Weapon Damage At Rng", "Damage At Range", "Weapon Damage At Range" }, ref index); if (dmgfield.Value.StartsWith("=")) { w.Damage = dmgfield.CreateFormula <int>(c); } else { string dmgstr = null; try { var dict = new SafeDictionary <int, int>(); var split = dmgfield.Value.Split(' '); for (var i = 0; i < split.Length; i++) { if (split[i].ToInt() == 0) { continue; } dict[i + 1] = split[i].ToInt(); } // HACK - SE4 doesn't explicitly specify damage at range zero so copy the damage at range one value if (dict[1] != 0) { dict[0] = dict[1]; w.MinRange = 0; } w.MinRange = dict.Keys.Min(); w.MaxRange = dict.Keys.Max(); w.Damage = dict.BuildMultiConditionalLessThanOrEqual(c, "range", 0); } catch (Exception ex) { Mod.Errors.Add(new DataParsingException("Can't parse \"" + dmgstr + "\" as a damage string: " + ex.Message, Mod.CurrentFileName, rec)); } } var damTypeName = rec.Get <string>("Weapon Damage Type", c); w.DamageType = Mod.Current.DamageTypes.FindByName(damTypeName); if (w.DamageType == null) { // no valid damage type? then make it normal damage and log a warning w.DamageType = DamageType.Normal; Mod.Errors.Add(new DataParsingException("Unknown damage type \"" + damTypeName + "\"; setting " + c + "'s damage type to Normal.", Mod.CurrentFileName, rec)); } w.ReloadRate = rec.Get <double>("Weapon Reload Rate", c); var wdisptype = rec.Get <string>("Weapon Display Type", c); var wdispname = rec.Get <string>("Weapon Display", c); if (wdisptype == "Beam") { w.DisplayEffect = new BeamWeaponDisplayEffect(wdispname); } else if (wdisptype == "Torp" || wdisptype == "Torpedo" || wdisptype == "Projectile") { w.DisplayEffect = new ProjectileWeaponDisplayEffect(wdispname); } else if (wdisptype == "Seeker") { w.DisplayEffect = new SeekerWeaponDisplayEffect(wdispname); } else { Mod.Errors.Add(new DataParsingException("Invalid weapon display effect type \"" + wdisptype + "\".", Mod.CurrentFileName, rec)); } // sanity check if (wdisptype == "Beam" && w is SeekingWeaponInfo) { Mod.Errors.Add(new DataParsingException("A seeking weapon cannot use a beam display effect.", Mod.CurrentFileName, rec)); } w.Sound = rec.Get <string>("Weapon Sound", c); w.Family = rec.Get <string>("Weapon Family", c); } c.WeaponInfo = w; yield return(c); } } }