public static void SiegeRepair_Callback(object state) { object[] args = (object[])state; Mobile from = (Mobile)args[0]; XmlSiege a = (XmlSiege)args[1]; int nhits = (int)args[2]; if (a != null) { a.Hits += nhits; from.SendMessage("{0} hits repaired", nhits); a.BeingRepaired = false; } }
protected override void OnTick() { ISiegeProjectile pitem = this.m_Projectile as ISiegeProjectile; if (this.m_weapon != null && !this.m_weapon.Deleted && pitem != null) { int animationid = pitem.AnimationID; int animationhue = pitem.AnimationHue; switch (this.m_step) { case 0: case 4: this.m_weapon.DisplayLaunch(0); break; case 1: case 3: this.m_weapon.DisplayLaunch(1); break; case 2: this.m_weapon.DisplayLaunch(2); // launch sounds Effects.PlaySound(this.m_weapon, this.m_weapon.Map, 0x4C9); Effects.PlaySound(this.m_weapon, this.m_weapon.Map, 0x2B2); // show the projectile moving to the target if (this.m_target is Mobile) { XmlSiege.SendMovingProjectileEffect(this.m_weapon, null, animationid, this.m_weapon.ProjectileLaunchPoint, this.m_targetloc, 7, 0, false, true, animationhue); } else { XmlSiege.SendMovingProjectileEffect(this.m_weapon, this.m_target, animationid, this.m_weapon.ProjectileLaunchPoint, this.m_targetloc, 7, 0, false, true, animationhue); } // delayed damage at the target to account for travel distance of the projectile Timer.DelayCall(this.m_damagedelay, new TimerStateCallback(this.m_weapon.DamageTarget_Callback), new object[] { this.m_from, this.m_weapon, this.m_target, this.m_targetloc, this.m_Projectile }); break; } // advance to the next step this.m_weapon.DoTimer(this.m_from, this.m_weapon, this.m_target, this.m_targetloc, this.m_Projectile, this.m_damagedelay, ++this.m_step); } }
public virtual void LaunchProjectile(Mobile from, Item projectile, IEntity target, Point3D targetloc, TimeSpan delay) { ISiegeProjectile pitem = projectile as ISiegeProjectile; if (pitem == null) { return; } int animationid = pitem.AnimationID; int animationhue = pitem.AnimationHue; // show the projectile moving to the target XmlSiege.SendMovingProjectileEffect(this, target, animationid, this.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 virtual bool AttackTarget(Mobile from, IEntity target, Point3D targetloc, bool checkLOS) { ISiegeProjectile projectile = this.m_Projectile as ISiegeProjectile; if (from == null || from.Map == null || projectile == null) { return(false); } if (!this.HasFiringAngle(targetloc)) { from.SendMessage("No firing angle"); return(false); } // check the target range int distance = (int)XmlSiege.GetDistance(targetloc, this.Location); int projectilerange = (int)(projectile.Range * this.WeaponRangeFactor); if (projectilerange < distance) { from.SendMessage("Out of range"); return(false); } if (distance <= this.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 && !this.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 = this.WeaponLoadingDelay - dexbonus - firingspeedbonus; this.m_NextFiringTime = DateTime.UtcNow + 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 this.m_Projectile.Consume(1); // update the properties display this.Projectile = this.m_Projectile; return(true); } this.LaunchProjectile(from, this.m_Projectile, target, targetloc, TimeSpan.FromSeconds((double)distance * 0.08)); return(true); }
private void Explode(Mobile from, Point3D loc, Map map) { if (map == null) { return; } IPooledEnumerable eable = map.GetObjectsInRange(loc, 2); ArrayList toExplode = new ArrayList(); foreach (object o in eable) { if (o is Mobile || o is BaseMulti || o is BaseAddon || o is PelopsItem) { toExplode.Add(o); } } eable.Free(); int d = 0; // Damage scalar int damage = 0; int MinDamage = 6; int MaxDamage = 60; for (int i = 0; i < toExplode.Count; ++i) { object o; o = toExplode[i]; if (o is Mobile) { Mobile m = (Mobile)o; if (m.InRange(loc, 0)) { d = 1; } else if (m.InRange(loc, 1)) { d = 2; } else if (m.InRange(loc, 2)) { d = 3; } if (from != null || (SpellHelper.ValidIndirectTarget(from, m) && from.CanBeHarmful(m, false))) { if (from != null) { from.DoHarmful(m); } damage = Utility.RandomMinMax((MinDamage / d), (MaxDamage / d)); if (d == 1) { AOS.Damage(m, from, damage, 50, 50, 0, 0, 0); // Same tile 50% physical 50% fire } else { AOS.Damage(m, from, damage, 0, 100, 0, 0, 0); // 2 tile radius 100% fire damage } } } else if (o is BaseMulti || o is BaseAddon /*|| o is PelopsItem*/) { // apply siege damage, all physical XmlSiege.Attack(from, o, 60, 0); } } }
public void OnHit(Mobile from, ISiegeWeapon 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) { XmlSiege a = (XmlSiege)XmlAttach.FindAttachment(target, typeof(XmlSiege)); if (a != null) { damagelist.Add(a); } } // apply splash damage to objects with a siege attachment IPooledEnumerable itemlist = from.Map.GetItemsInRange(targetloc, this.Area); if (itemlist != null) { foreach (Item item in itemlist) { if (item == null || item.Deleted) { continue; } XmlSiege a = (XmlSiege)XmlAttach.FindAttachment(item, typeof(XmlSiege)); if (a != null && !damagelist.Contains(a)) { damagelist.Add(a); } else if (item is AddonComponent) { a = (XmlSiege)XmlAttach.FindAttachment(((AddonComponent)item).Addon, typeof(XmlSiege)); if (a != null && !damagelist.Contains(a)) { damagelist.Add(a); } } } } int scaledfiredamage = (int)(this.FireDamage * this.StructureDamageMultiplier * weapon.WeaponDamageFactor); int scaledphysicaldamage = (int)(this.PhysicalDamage * this.StructureDamageMultiplier * weapon.WeaponDamageFactor); foreach (XmlSiege a in damagelist) { // apply siege damage a.ApplyScaledDamage(from, scaledfiredamage, scaledphysicaldamage); } // apply splash damage to mobiles ArrayList mobdamage = new ArrayList(); IPooledEnumerable moblist = from.Map.GetMobilesInRange(targetloc, this.Area); if (moblist != null) { foreach (Mobile m in moblist) { if (m == null || m.Deleted || !from.CanBeHarmful(m, false)) { continue; } mobdamage.Add(m); } } int totaldamage = this.FireDamage + this.PhysicalDamage; if (totaldamage > 0) { int scaledmobdamage = (int)(totaldamage * this.MobDamageMultiplier * weapon.WeaponDamageFactor); int phys = 100 * this.PhysicalDamage / totaldamage; int fire = 100 * this.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 this.Consume(1); weapon.Projectile = this; }
public virtual bool AttackTarget(Mobile from, IEntity target, Point3D targetloc, bool checkLOS) { ISiegeProjectile projectile = m_Projectile as ISiegeProjectile; 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)XmlSiege.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; // calculate the cooldown time with dexterity bonus and firing speed bonus on top of the base delay double loadingdelay = WeaponLoadingDelay - dexbonus - firingspeedbonus; m_NextFiringTime = DateTime.UtcNow + TimeSpan.FromSeconds(loadingdelay); LaunchProjectile(from, m_Projectile, target, targetloc, TimeSpan.FromSeconds((double)distance * 0.05)); return(true); }
public void OnHit(Mobile from, ISiegeWeapon weapon, IEntity target, Point3D targetloc) { if (weapon == null || from == null) { return; } // play explosion sound at target Effects.PlaySound(targetloc, weapon.Map, 0x11D); // show effects in the area around target int explosion = 0x36b0; int firecolumn = 0x3709; var rectangle = new Rectangle2D(targetloc.X - Area, targetloc.Y - Area, Area * 2 + 1, Area * 2 + 1); // iterate coordinates of rectangle for (int x = rectangle.Start.X; x < rectangle.End.X; x++) { for (int y = rectangle.Start.Y; y < rectangle.End.Y; y++) { if (Utility.RandomBool()) { Effects.SendLocationEffect(new Point3D(x, y, targetloc.Z), from.Map, explosion, 13); } else { Effects.SendLocationEffect(new Point3D(x, y, targetloc.Z), from.Map, firecolumn, 15); } } } 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) { XmlSiege a = (XmlSiege)XmlAttach.FindAttachment(target, typeof(XmlSiege)); 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; } XmlSiege a = (XmlSiege)XmlAttach.FindAttachment(item, typeof(XmlSiege)); if (a != null && !damagelist.Contains(a)) { damagelist.Add(a); } else // if it had no siege attachment and the item is an addoncomponent, then check the parent addon if (item is AddonComponent) { a = (XmlSiege)XmlAttach.FindAttachment(((AddonComponent)item).Addon, typeof(XmlSiege)); if (a != null && !damagelist.Contains(a)) { damagelist.Add(a); } } } itemlist.Free(); } int scaledfiredamage = (int)(FireDamage * StructureDamageMultiplier * weapon.WeaponDamageFactor); int scaledphysicaldamage = (int)(PhysicalDamage * StructureDamageMultiplier * weapon.WeaponDamageFactor); foreach (XmlSiege a in damagelist) { // apply siege damage a.ApplyScaledDamage(from, scaledfiredamage, scaledphysicaldamage); } // 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); } moblist.Free(); } 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 if (!weapon.FreeConsume()) { Consume(1); } weapon.Projectile = this; }
protected override void OnTarget(Mobile from, object targeted) { if (from == null || m_tool == null || from.Map == null) { return; } // find any xmlsiege attachment on the target XmlSiege a = (XmlSiege)XmlAttach.FindAttachment(targeted, typeof(XmlSiege)); // if it isnt on the target, but the target is an addon, then check the addon if (a == null && targeted is AddonComponent) { a = (XmlSiege)XmlAttach.FindAttachment(((AddonComponent)targeted).Addon, typeof(XmlSiege)); } // if it still isnt found, the look for nearby targets if (a == null) { Point3D loc = Point3D.Zero; if (targeted is IEntity) { loc = ((IEntity)targeted).Location; } else if (targeted is StaticTarget) { loc = ((StaticTarget)targeted).Location; } else if (targeted is LandTarget) { loc = ((LandTarget)targeted).Location; } if (loc != Point3D.Zero) { foreach (Item p in from.Map.GetItemsInRange(loc, RepairRange)) { a = (XmlSiege)XmlAttach.FindAttachment(p, typeof(XmlSiege)); if (a != null) { break; } } } } // repair the target if (a != null) { if (a.Hits >= a.HitsMax) { from.SendMessage("This does not require repair."); return; } if (a.BeingRepaired) { from.SendMessage("You must wait to repair again."); return; } Container pack = from.Backpack; // does the player have it? if (pack != null) { int nhits = 0; double resourcepenalty = 1; // require more resources for repairing destroyed structures if (a.Hits == 0) { resourcepenalty = RepairDestroyedResourcePenalty; } // dont consume resources for staff if (from.AccessLevel > AccessLevel.Player) { resourcepenalty = 0; } int requirediron = (int)(a.Iron * resourcepenalty); int requiredstone = (int)(a.Stone * resourcepenalty); int requiredwood = (int)(a.Wood * resourcepenalty); int niron = pack.ConsumeUpTo(typeof(IronIngot), requirediron); int nstone = pack.ConsumeUpTo(typeof(BaseGranite), requiredstone); int nwood = pack.ConsumeUpTo(typeof(Board), requiredwood); if (niron == requirediron && nstone == requiredstone && nwood == requiredwood) { nhits += m_tool.HitsPerRepair; } if (nhits == 0) { from.SendMessage("Insufficient resources to complete the repair. Resources lost."); return; } from.PlaySound(0x2A); // play anvil sound from.SendMessage("You begin your repair"); m_tool.UsesRemaining--; if (m_tool.UsesRemaining == 0) { from.SendLocalizedMessage(1044038); // You have worn out your tool! m_tool.Delete(); } a.BeingRepaired = true; double smithskill = from.Skills[SkillName.Blacksmith].Value; double carpentryskill = from.Skills[SkillName.Carpentry].Value; double timepenalty = 1; if (a.Hits == 0) { // repairing destroyed structures requires more time timepenalty = RepairDestroyedTimePenalty; } // compute repair speed with modifiers TimeSpan repairtime = TimeSpan.FromSeconds(m_tool.BaseRepairTime * timepenalty - from.Dex / 40.0 - smithskill / 50.0 - carpentryskill / 50.0); // allow staff instant repair if (from.AccessLevel > AccessLevel.Player) { repairtime = TimeSpan.Zero; } // setup for the delayed repair Timer.DelayCall(repairtime, new TimerStateCallback(SiegeRepair_Callback), new object[] { from, a, nhits }); } } else { from.SendMessage("Invalid target"); return; } }