public virtual void LaunchProjectile(Mobile from, Item projectile, IEntity target, Point3D targetloc, TimeSpan delay) { IShipProjectile pitem = projectile as IShipProjectile; if (pitem == null) { return; } int animationid = pitem.AnimationID; int animationhue = pitem.AnimationHue; Effects.PlaySound(target, from.Map, Utility.RandomList(0x11B, 0x11C, 0x11D)); // show the projectile moving to the target XmlBoatFight.SendMovingProjectileEffect(this, target, animationid, ProjectileLaunchPoint, targetloc, 7, 0, false, true, animationhue); // delayed damage at the target to account for travel distance of the projectile Timer.DelayCall(delay, new TimerStateCallback(DamageTarget_Callback), new object[] { from, this, target, targetloc, projectile }); return; }
public void OnHit(Mobile from, IShipWeapon weapon, IEntity target, Point3D targetloc) { if (weapon == null || from == null) { return; } // play explosion sound at target Effects.PlaySound(targetloc, weapon.Map, 0x11D); ArrayList damagelist = new ArrayList(); // deal with the fact that for multis, the targetloc and the actual multi location may differ // so deal the multi damage first if (target is BaseMulti) { XmlBoatFight a = (XmlBoatFight)XmlAttach.FindAttachment(target, typeof(XmlBoatFight)); if (a != null) { damagelist.Add(a); } } // apply splash damage to objects with a siege attachment IPooledEnumerable itemlist = from.Map.GetItemsInRange(targetloc, Area); if (itemlist != null) { foreach (Item item in itemlist) { if (item == null || item.Deleted) { continue; } XmlBoatFight a = (XmlBoatFight)XmlAttach.FindAttachment(item, typeof(XmlBoatFight)); if (a != null && !damagelist.Contains(a)) { damagelist.Add(a); } else if (item is AddonComponent) { a = (XmlBoatFight)XmlAttach.FindAttachment(((AddonComponent)item).Addon, typeof(XmlBoatFight)); if (a != null && !damagelist.Contains(a)) { damagelist.Add(a); } } } } int scaledfiredamage = (int)(FireDamage * StructureDamageMultiplier * weapon.WeaponDamageFactor); int scaledphysicaldamage = (int)(PhysicalDamage * StructureDamageMultiplier * weapon.WeaponDamageFactor); foreach (XmlBoatFight a in damagelist) { // apply siege damage a.ApplyScaledDamage(from, scaledfiredamage, scaledphysicaldamage); #region HS Ships int HitsAfterDamage = a.Hits; int HitsMax = a.HitsMax; if (target is BaseGalleon) { BaseGalleon targetedGalleon = (BaseGalleon)target; targetedGalleon.Durability = (ushort)(100 * HitsAfterDamage / HitsMax); } #endregion } // apply splash damage to mobiles ArrayList mobdamage = new ArrayList(); IPooledEnumerable moblist = from.Map.GetMobilesInRange(targetloc, Area); if (moblist != null) { foreach (Mobile m in moblist) { if (m == null || m.Deleted || !from.CanBeHarmful(m, false)) { continue; } mobdamage.Add(m); } } int totaldamage = FireDamage + PhysicalDamage; if (totaldamage > 0) { int scaledmobdamage = (int)(totaldamage * MobDamageMultiplier * weapon.WeaponDamageFactor); int phys = 100 * PhysicalDamage / totaldamage; int fire = 100 * FireDamage / totaldamage; foreach (Mobile m in mobdamage) { // AOS.Damage( Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy ) AOS.Damage(m, from, scaledmobdamage, phys, fire, 0, 0, 0); } } // consume the ammunition Consume(1); weapon.Projectile = this; }
public virtual bool AttackTarget(Mobile from, IEntity target, Point3D targetloc, bool checkLOS) { IShipProjectile projectile = _projectile as IShipProjectile; if (from == null || from.Map == null || projectile == null) { return(false); } if (!HasFiringAngle(targetloc)) { from.SendMessage("No firing angle"); return(false); } // check the target range int distance = (int)XmlBoatFight.GetDistance(targetloc, Location); int projectilerange = (int)(projectile.Range * WeaponRangeFactor); if (projectilerange < distance) { from.SendMessage("Out of range"); return(false); } if (distance <= MinTargetRange) { from.SendMessage("Target is too close"); return(false); } // check the target line of sight int height = 1; if (target is Item) { height = ((Item)target).ItemData.Height; } else if (target is Mobile) { height = 14; } Point3D adjustedloc = new Point3D(targetloc.X, targetloc.Y, targetloc.Z + height); if (checkLOS && !Map.LineOfSight(this, adjustedloc)) { from.SendMessage("Cannot see target"); return(false); } // ok, the projectile is being fired // calculate attack parameters double firingspeedbonus = projectile.FiringSpeed / 10.0; double dexbonus = (double)from.Dex / 30.0; int weaponskill = (int)from.Skills[SkillName.ArmsLore].Value; int accuracybonus = projectile.AccuracyBonus; // calculate the cooldown time with dexterity bonus and firing speed bonus on top of the base delay double loadingdelay = WeaponLoadingDelay - dexbonus - firingspeedbonus; _nextFiringTime = DateTime.Now + TimeSpan.FromSeconds(loadingdelay); // calculate the accuracy based on distance and weapon skill int accuracy = distance * 10 - weaponskill + accuracybonus; if (Utility.Random(100) < accuracy) { from.SendMessage("Target missed"); // consume the ammunition _projectile.Consume(1); // update the properties display Projectile = _projectile; return(true); } LaunchProjectile(from, _projectile, target, targetloc, TimeSpan.FromSeconds((double)distance * 0.08)); return(true); }