private void RepairStart(BaseBoat boat, Mobile from, DamageType damageType) { if (boat == null || from == null) { return; } from.BeginAction(typeof(ShipRepairTool)); Timer.DelayCall(RepairDuration, delegate { from.EndAction(typeof(ShipRepairTool)); }); Effects.PlaySound(from.Location, from.Map, 0x23D); if (!from.Mounted && from.Body.IsHuman) { from.Animate(11, 5, 1, true, false, 0); } shipRepairTimer = new ShipRepairTimer(boat, from, this, damageType, RepairInterval); shipRepairTimer.Start(); //Henchman Repair Assistance List <Mobile> m_MobilesOnBoat = boat.GetMobilesOnBoat(false, false); foreach (Mobile mobile in m_MobilesOnBoat) { if (mobile is HenchmanNavyCarpenter) { HenchmanNavyCarpenter navyCarpenter = mobile as HenchmanNavyCarpenter; mobile.Say("Assisting with ship repair!"); navyCarpenter.AssistRepair(); } if (mobile is HenchmanPirateCarpenter) { HenchmanPirateCarpenter pirateCarpenter = mobile as HenchmanPirateCarpenter; mobile.Say("Assisting with ship repair!"); pirateCarpenter.AssistRepair(); } } }
public void ResolveCannonHit(Mobile from, Point3D targetLocation) { ArrayList validTargets = new ArrayList(); Map map = Map; BaseBoat boatFrom = BaseBoat.FindBoatAt(from.Location, map); BaseBoat targetBoat = BaseBoat.FindBoatAt(targetLocation, map); bool hitObject = false; bool hitBoat = false; bool showExplosion = true; IPooledEnumerable nearbyMobiles = map.GetMobilesInRange(targetLocation, BaseBoat.CannonExplosionRange); foreach (Mobile mobile in nearbyMobiles) { if (!validTargets.Contains(mobile)) { validTargets.Add(mobile); } } nearbyMobiles.Free(); List <Mobile> m_MobilesOnSourceBoat = new List <Mobile>(); List <Mobile> m_Targets = new List <Mobile>(); double baseCannonDamage = (double)(Utility.RandomMinMax(BaseBoat.CannonDamageMin, BaseBoat.CannonDamageMax)); if (m_Boat == null) { m_MobilesOnSourceBoat.Add(from); } else { baseCannonDamage = m_Boat.CannonDamageScalar * baseCannonDamage; m_MobilesOnSourceBoat = m_Boat.GetMobilesOnBoat(false, false); } bool targetLocationIsBoat = false; if (targetBoat != null) { targetLocationIsBoat = true; m_Targets = targetBoat.GetMobilesOnBoat(false, false); validTargets.Add(targetBoat); } else { m_Targets = new List <Mobile>(); } double damageDealt; for (int a = 0; a < validTargets.Count; ++a) { damageDealt = baseCannonDamage; object target = validTargets[a]; int d = 0; int damage = 0; bool largeCreatureHit = false; PlayerMobile pm_Target; BaseCreature bc_Target; //Large Boss-Size Creature Hit: Don't Deal Damage to Boat Underneath it if (target is Mobile) { bc_Target = target as BaseCreature; if (bc_Target != null) { if (bc_Target.IsChamp() || bc_Target.IsBoss() || bc_Target.IsLoHBoss() || bc_Target.IsEventBoss()) { largeCreatureHit = true; } } } if (target is Mobile) { Mobile mobile = target as Mobile; pm_Target = mobile as PlayerMobile; bc_Target = mobile as BaseCreature; if (!mobile.Alive) { continue; } //Mobile is somehow on boat that cannon is shooting from BaseBoat mobileBoat = BaseBoat.FindBoatAt(mobile.Location, mobile.Map); if (m_Boat != null && mobileBoat != null) { if (m_Boat == mobileBoat) { continue; } } hitObject = true; bool dealDamage = true; bool directHit = false; if (mobile.InRange(targetLocation, 0)) { directHit = true; } bool isOnWater = BaseBoat.IsWaterTile(mobile.Location, mobile.Map); if (from != null || (SpellHelper.ValidIndirectTarget(from, mobile) && from.CanBeHarmful(mobile, false))) { //Player if (pm_Target != null) { damageDealt *= BaseBoat.CannonPlayerDamageMultiplier; } //Creature if (bc_Target != null) { if (bc_Target.IsOceanCreature) { damageDealt *= BaseBoat.CannonOceanCreatureDamageMultiplier; } else { damageDealt *= BaseBoat.CannonMobileDamageMultiplier; } } if (!directHit) { damageDealt *= BaseBoat.CannonIndirectHitDamageMultiplier; } if (dealDamage) { from.DoHarmful(mobile); int finalDamage = (int)Math.Round(damageDealt); BaseCreature bc_Creature = mobile as BaseCreature; if (bc_Creature != null) { bool willKill = false; if (bc_Creature.Hits - finalDamage <= 0) { willKill = true; } bc_Creature.OnGotCannonHit(finalDamage, from, willKill); } new Blood().MoveToWorld(mobile.Location, mobile.Map); AOS.Damage(mobile, from, finalDamage, 100, 0, 0, 0, 0); } } } else if (target is DerelictCargo) { DerelictCargo crate = target as DerelictCargo; crate.TakeDamage(from, (int)damageDealt); } else if (target is BaseBoat && !largeCreatureHit) { BaseBoat boatTarget = target as BaseBoat; if (from != null && m_Boat != null && boatTarget != null) { //Somehow Hitting Own Boat if (m_Boat == boatTarget) { continue; } CannonDoHarmful(from, m_MobilesOnSourceBoat, m_Targets); hitObject = true; hitBoat = true; bool dealDamage = true; if (dealDamage) { DamageType damageType = boatTarget.GetDamageTypeByTargetingMode(m_Boat.TargetingMode); int finalDamage = (int)(Math.Round(damageDealt)); boatTarget.ReceiveDamage(from, m_Boat, finalDamage, damageType); } } } } if (hitObject) { IEntity explosionLocationEntity = new Entity(Serial.Zero, new Point3D(targetLocation.X, targetLocation.Y, targetLocation.Z - 1), map); int explosionHue = 0; int explosionSound = 0x307; if (m_Boat.MobileFactionType == MobileFactionType.Undead) { explosionHue = 2630; explosionSound = 0x56E; } if (showExplosion) { Effects.SendLocationParticles(explosionLocationEntity, Utility.RandomList(14013, 14015, 14027, 14012), 30, 7, explosionHue, 0, 5044, 0); Effects.PlaySound(explosionLocationEntity.Location, map, explosionSound); } } else { Splash(targetLocation, map); } }
public void FireCannon(ShipCannon shipCannon, Mobile from, Point3D targetLocation, Map map, bool hit, bool showSmoke) { if (shipCannon == null) { return; } int cannonballItemID = 0xE73; int cannonballHue = 0; int smokeHue = 0; bool fixedDirection = false; double shotDelay = .04; int shotSpeed = 6; Point3D smokeLocation = shipCannon.Location; switch (shipCannon.Facing) { case Direction.North: { } break; case Direction.East: { smokeLocation.X++; } break; case Direction.South: { smokeLocation.Y++; } break; case Direction.West: { smokeLocation.X--; } break; } if (m_Boat != null) { double gunsPercent = (double)((float)m_Boat.GunPoints / (float)m_Boat.MaxGunPoints); double misfireChance = BaseBoat.CannonMaxMisfireChance * (1 - gunsPercent); double chance = Utility.RandomDouble(); double distance = Utility.GetDistanceToSqrt(shipCannon.Location, targetLocation); double flatDistance = Utility.GetDistance(shipCannon.Location, targetLocation); //Misfire if (chance < misfireChance) { List <Mobile> m_MobilesOnBoat = m_Boat.GetMobilesOnBoat(true, true); foreach (Mobile mobile in m_MobilesOnBoat) { if (m_Boat.IsOwner(mobile) || m_Boat.IsCoOwner(mobile) || m_Boat.IsFriend(mobile)) { mobile.SendMessage("Misfire!"); } } Effects.SendLocationEffect(shipCannon.Location, map, 0x3735, 10); Effects.PlaySound(shipCannon.Location, map, 0x475); return; } if (m_Boat.MobileFactionType == MobileFactionType.Undead) { cannonballItemID = Utility.RandomList(6880, 6881, 6882, 6883, 6884); smokeHue = 2630; } //Hit if (hit) { m_Boat.LastCombatTime = DateTime.UtcNow; Effects.PlaySound(shipCannon.Location, map, 0x664); if (showSmoke) { Effects.SendLocationEffect(smokeLocation, map, 0x36CB, 10, smokeHue, 0); } SpellHelper.AdjustField(ref targetLocation, map, 12, false); IEntity startLocation = new Entity(Serial.Zero, new Point3D(shipCannon.Location.X, shipCannon.Location.Y, shipCannon.Location.Z + 10), map); IEntity endLocation = new Entity(Serial.Zero, new Point3D(targetLocation.X, targetLocation.Y, targetLocation.Z + 5), map); Effects.SendMovingEffect(startLocation, endLocation, cannonballItemID, shotSpeed, 0, fixedDirection, false, cannonballHue, 0); double effectDelay = distance * shotDelay; Timer.DelayCall(TimeSpan.FromSeconds(effectDelay), delegate { ResolveCannon(shipCannon, from, targetLocation, map, hit); }); } //Miss else { int xOffset = 0; int yOffset = 0; double effectiveDistance = distance; int distanceOffset = (int)(Math.Floor(effectiveDistance / 2)); if (distance >= 2) { xOffset = Utility.RandomMinMax(0, distanceOffset); if (Utility.RandomDouble() > .5) { xOffset *= -1; } yOffset = Utility.RandomMinMax(0, distanceOffset); if (Utility.RandomDouble() > .5) { yOffset *= -1; } } Effects.PlaySound(shipCannon.Location, map, 0x664); Effects.SendLocationEffect(smokeLocation, map, 0x36CB, 10, smokeHue, 0); IEntity startLocation = new Entity(Serial.Zero, new Point3D(shipCannon.Location.X, shipCannon.Location.Y, shipCannon.Location.Z + 10), map); IEntity endLocation = new Entity(Serial.Zero, new Point3D(targetLocation.X + xOffset, targetLocation.Y + yOffset, targetLocation.Z + 5), map); Effects.SendMovingEffect(startLocation, endLocation, cannonballItemID, shotSpeed, 0, fixedDirection, false, cannonballHue, 0); Point3D splashLocation = new Point3D(targetLocation.X + xOffset, targetLocation.Y + yOffset, +targetLocation.Z); double newDistance = from.GetDistanceToSqrt(splashLocation); double effectDelay = newDistance * shotDelay; Timer.DelayCall(TimeSpan.FromSeconds(effectDelay), delegate { ResolveCannon(shipCannon, from, splashLocation, map, hit); }); } } }
protected override void OnTarget(Mobile from, object target) { bool foundAnyone = false; from.RevealingAction(); from.NextSkillTime = Core.TickCount + (int)(SkillCooldown.DetectHiddenCooldown * 1000); Point3D p; if (target is Mobile) { p = ((Mobile)target).Location; } else if (target is Item) { p = ((Item)target).Location; } else if (target is IPoint3D) { p = new Point3D((IPoint3D)target); } else { p = from.Location; } //Boat Searching: Automatic Success for Owner, Co-Owner, Owner BaseBoat boat = BaseBoat.FindBoatAt(p, from.Map); if (boat != null) { if (!boat.Contains(from)) { from.SendMessage("You must be onboard this boat in order to search it."); return; } if (boat.IsFriend(from) || boat.IsCoOwner(from) || boat.IsOwner(from)) { List <Mobile> m_MobilesOnBoard = boat.GetMobilesOnBoat(false, true); foreach (Mobile mobile in m_MobilesOnBoard) { if (mobile == from) { continue; } if (mobile.Hidden && !mobile.RevealImmune && from.AccessLevel >= mobile.AccessLevel) { mobile.RevealingAction(); mobile.SendLocalizedMessage(500814); // You have been revealed! foundAnyone = true; } } if (foundAnyone) { from.SendMessage("You reveal what was hidden."); } else { from.SendMessage("You search the decks and find no one hiding onboard."); } } return; } //House Searching: Automatic Success for Owner, Co-Owner, Owner BaseHouse house = BaseHouse.FindHouseAt(p, from.Map, 16); if (house != null) { if (!house.Contains(from.Location)) { from.SendMessage("You must be inside this house in order to search it."); return; } if (house.IsFriend(from) || house.IsCoOwner(from) || house.IsOwner(from)) { IPooledEnumerable nearbyMobiles = from.Map.GetMobilesInRange(p, HouseSearchRange); foreach (Mobile mobile in nearbyMobiles) { if (mobile == from) { continue; } BaseHouse mobileHouse = BaseHouse.FindHouseAt(p, from.Map, 16); if (mobile == null || mobileHouse != house) { continue; } if (mobile.Hidden && !mobile.RevealImmune && from.AccessLevel >= mobile.AccessLevel) { mobile.RevealingAction(); mobile.SendLocalizedMessage(500814); // You have been revealed! foundAnyone = true; } } nearbyMobiles.Free(); if (foundAnyone) { from.SendMessage("You reveal what was hidden."); } else { from.SendMessage("You search the home and find no one hiding within."); } } return; } from.CheckSkill(SkillName.DetectHidden, 0.0, 100.0, 1.0); double successChance = (from.Skills[SkillName.DetectHidden].Value / 100); int searchRadius = (int)(Math.Floor(from.Skills[SkillName.DetectHidden].Value / 100) * MaxSearchRadius); if (Utility.RandomDouble() <= successChance) { IPooledEnumerable nearbyMobiles = from.Map.GetMobilesInRange(p, searchRadius); foreach (Mobile mobile in nearbyMobiles) { if (mobile == from) { continue; } if (mobile.Hidden && !mobile.RevealImmune && from.AccessLevel >= mobile.AccessLevel) { mobile.RevealingAction(); mobile.SendLocalizedMessage(500814); // You have been revealed! foundAnyone = true; } } nearbyMobiles.Free(); if (foundAnyone) { from.SendMessage("You reveal what was hidden."); } else { from.SendMessage("You search the area but find nothing hidden."); } } else { from.SendMessage("You are not certain what lies hidden nearby."); return; } }
public void OnTarget(Mobile from, Point3D point) { BaseBoat fromBoat = BaseBoat.FindBoatAt(from.Location, from.Map); BaseBoat targetBoat = BaseBoat.FindBoatAt(point, this.Map); if (targetBoat != null) { bool automaticBoarding = false; if (targetBoat.MobileControlType != MobileControlType.Player && !targetBoat.HasCrewAlive()) { automaticBoarding = true; } double shipHullPercent = (double)((float)targetBoat.HitPoints / (float)targetBoat.MaxHitPoints); if (targetBoat.IsOwner(from) || targetBoat.IsCoOwner(from) || targetBoat.IsFriend(from)) { from.SendMessage("You already have access to that boat."); return; } else if (shipHullPercent > m_MinimumHullPercent && !automaticBoarding) { from.SendMessage("The hull of that ship is not yet damaged enough to risk a boarding attempt."); return; } else { double baseSuccessChance = m_FullSuccessChancePercent; double hullPercentFactor = (m_MinimumHullPercent - shipHullPercent) * (1 / m_MinimumHullPercent); if (hullPercentFactor < 0) { hullPercentFactor = 0; } double finalSuccessChance = hullPercentFactor * baseSuccessChance; if (targetBoat.MobileControlType != MobileControlType.Player) { ; } finalSuccessChance *= m_NPCShipBonusMultiplier; //Successful Boarding if ((Utility.RandomDouble() <= finalSuccessChance) || automaticBoarding) { //Valid Boarding if (targetBoat.Embark(from, true)) { List <Mobile> targets = targetBoat.GetMobilesOnBoat(false, false); //Mobile Boarding Boat Becomes Aggressor to Everyone on Target Boat (Who Belongs on the Boat) foreach (Mobile target in targets) { //Target Belongs on Boat if (targetBoat.Crew.Contains(target) || targetBoat.IsFriend(target) || targetBoat.IsCoOwner(target) || targetBoat.IsOwner(target)) { //Do Harmful Action to Target if (from.CanBeHarmful(target, false)) { from.DoHarmful(target); } } } from.SendMessage("You board the ship!"); Effects.PlaySound(from.Location, from.Map, 0x056); //Alternate Sound 0x0EF if (targetBoat.TillerMan != null) { if (targetBoat.HasCrewAlive()) { targetBoat.TillerMan.Say("Arr! We've been boarded!"); } } from.NextBoardingAttemptAllowed = DateTime.UtcNow + boardingCooldown; CurrentCharges--; return; } else { from.NextBoardingAttemptAllowed = DateTime.UtcNow + boardingCooldown; from.SendMessage("You fail to board the ship"); Effects.PlaySound(from.Location, from.Map, 0x5D2); CurrentCharges--; return; } } //Failed Boarding Attempt else { from.NextBoardingAttemptAllowed = DateTime.UtcNow + boardingCooldown; from.SendMessage("You fail to board the ship"); Effects.PlaySound(from.Location, from.Map, 0x5D2); CurrentCharges--; return; } } } }
private void FinishRepairs(BaseBoat boat, Mobile from, DamageType damageType, bool needMaterials) { if (boat == null || from == null) { return; } //Repair Timer Refreshed (Other player repaired before this player finished) if (boat.NextTimeRepairable > DateTime.UtcNow) { from.SendMessage("You finish your repairs, however someone has more recently completed repairs on the ship."); return; } if (needMaterials == true) { switch (damageType) { case DamageType.Hull: { if (IsDamaged(boat, from, DamageType.Hull) == false) { from.SendMessage("The ship's hull is no longer damaged."); return; } else if (!CheckRepairMaterials(boat, from, DamageType.Hull)) { from.SendMessage("You lack the materials needed for repairs."); return; } break; } case DamageType.Sails: { if (IsDamaged(boat, from, DamageType.Sails) == false) { from.SendMessage("The ship's sails are no longer damaged."); return; } else if (!CheckRepairMaterials(boat, from, DamageType.Sails)) { from.SendMessage("You lack the materials needed for repairs."); return; } break; } case DamageType.Guns: { if (IsDamaged(boat, from, DamageType.Guns) == false) { from.SendMessage("The ship's guns are no longer damaged."); return; } else if (!CheckRepairMaterials(boat, from, DamageType.Guns)) { from.SendMessage("You lack the materials needed for repairs."); return; } break; } } } int repairAmount = 0; double skillPercentBonus = 0; bool doubleTimeActive = false; double doubleTimeBonus = 0; int repairAssistants = 0; double bonusPerRepairAssistant = .25; //Henchman Repair Assistance List <Mobile> m_MobilesOnBoat = boat.GetMobilesOnBoat(false, false); foreach (Mobile mobile in m_MobilesOnBoat) { if (mobile is HenchmanNavyCarpenter) { repairAssistants++; } if (mobile is HenchmanPirateCarpenter) { repairAssistants++; } } double repairBonusScalar = 1.0; switch (damageType) { case DamageType.Hull: { skillPercentBonus = ((from.Skills[SkillName.Carpentry].Value / 100) * skillBonusPercent / 2); repairAmount = (int)((double)boat.MaxHitPoints * (hullRepairPercent + skillPercentBonus) * (1 + doubleTimeBonus + ((double)repairAssistants * bonusPerRepairAssistant))); boat.HitPoints += repairAmount; if (needMaterials) { UseRepairMaterials(boat, from, DamageType.Hull); } if (boat.TillerMan != null) { boat.TillerMan.Say("Ship's hull repaired!!"); } from.SendMessage("You repair the ship's hull."); } break; case DamageType.Sails: { skillPercentBonus += ((from.Skills[SkillName.Tailoring].Value / 100) * skillBonusPercent); repairAmount = (int)((double)boat.MaxSailPoints * (sailRepairPercent + skillPercentBonus) * (1 + ((double)repairAssistants * bonusPerRepairAssistant))); boat.SailPoints += repairAmount; if (needMaterials) { UseRepairMaterials(boat, from, DamageType.Sails); } if (boat.TillerMan != null) { boat.TillerMan.Say("Ship's sails repaired!"); } from.SendMessage("You repair the ship's sails."); } break; case DamageType.Guns: { skillPercentBonus += ((from.Skills[SkillName.Blacksmith].Value / 100) * skillBonusPercent); repairAmount = (int)((double)boat.MaxGunPoints * (gunRepairPercent + skillPercentBonus) * (1 + ((double)repairAssistants * bonusPerRepairAssistant))); boat.GunPoints += repairAmount; if (needMaterials) { UseRepairMaterials(boat, from, DamageType.Guns); } if (boat.TillerMan != null) { boat.TillerMan.Say("Ship's guns repaired!"); } from.SendMessage("You repair the ship's guns."); } break; } boat.TimeLastRepaired = DateTime.UtcNow; if (from.AccessLevel == AccessLevel.Player) { //Out of Ship Combat if (boat.LastCombatTime + boat.TimeNeededToBeOutOfCombat <= DateTime.UtcNow) { boat.NextTimeRepairable = DateTime.UtcNow; // + RepairDuration; } //Still in Ship Combat else { boat.NextTimeRepairable = DateTime.UtcNow + InCombatRepairCooldown; } } CurrentCharges--; }
protected override void OnTick() { //No Longer Alive if (!m_From.Alive) { this.Stop(); return; } //No Longer On Ship or Close Enough to the Ship to Repair if (!(m_Boat.Contains(m_From) || m_Boat.GetBoatToLocationDistance(m_Boat, m_From.Location) <= 6)) { m_From.SendMessage("You are not close enough to the ship to finish your repairs."); this.Stop(); return; } m_From.RevealingAction(); //Repair Time Remains if ((m_Start + m_ShipRepairTools.RepairDuration) > DateTime.UtcNow) { Effects.PlaySound(m_From.Location, m_From.Map, 0x23D); if (!m_From.Mounted) { m_From.Animate(11, 5, 1, true, false, 0); } } //Repairs Complete else { Effects.PlaySound(m_From.Location, m_From.Map, 0x23D); if (!m_From.Mounted) { m_From.Animate(11, 5, 1, true, false, 0); } Stop(); m_ShipRepairTools.FinishRepairs(m_Boat, m_From, m_DamageType, true); } //Henchman Repair Assistance List <Mobile> m_MobilesOnBoat = m_Boat.GetMobilesOnBoat(false, false); foreach (Mobile mobile in m_MobilesOnBoat) { if (mobile is HenchmanNavyCarpenter) { HenchmanNavyCarpenter navyCarpenter = mobile as HenchmanNavyCarpenter; navyCarpenter.AssistRepair(); } if (mobile is HenchmanPirateCarpenter) { HenchmanPirateCarpenter pirateCarpenter = mobile as HenchmanPirateCarpenter; pirateCarpenter.AssistRepair(); } } }