Files
Unstable Kitsune b918192e4e Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
2023-11-28 23:20:26 -05:00

1087 lines
40 KiB
C#

using System;
using System.Collections.Generic;
using Server.Engines.Quests;
using Server.Engines.Quests.Collector;
using Server.Items;
using Server.Mobiles;
using Server.Network;
using Server.Targeting;
namespace Server.Engines.Harvest
{
public class Fishing : HarvestSystem
{
private static Fishing m_System;
public static Fishing System
{
get
{
if (m_System == null)
m_System = new Fishing();
return m_System;
}
}
private readonly HarvestDefinition m_Definition;
public HarvestDefinition Definition
{
get
{
return this.m_Definition;
}
}
private Fishing()
{
HarvestResource[] res;
HarvestVein[] veins;
#region Fishing
HarvestDefinition fish = new HarvestDefinition();
// Resource banks are every 8x8 tiles
fish.BankWidth = 8;
fish.BankHeight = 8;
// Every bank holds from 5 to 15 fish
fish.MinTotal = 5;
fish.MaxTotal = 15;
// A resource bank will respawn its content every 10 to 20 minutes
fish.MinRespawn = TimeSpan.FromMinutes(10.0);
fish.MaxRespawn = TimeSpan.FromMinutes(20.0);
// Skill checking is done on the Fishing skill
fish.Skill = SkillName.Fishing;
// Set the list of harvestable tiles
fish.Tiles = m_WaterTiles;
fish.SpecialTiles = m_LavaTiles;
fish.RangedTiles = true;
// Players must be within 4 tiles to harvest
fish.MaxRange = 4;
// One fish per harvest action
fish.ConsumedPerHarvest = 1;
fish.ConsumedPerFeluccaHarvest = 1;
// The fishing
fish.EffectActions = new int[] { Core.SA ? 6 : 12 };
fish.EffectSounds = new int[0];
fish.EffectCounts = new int[] { 1 };
fish.EffectDelay = TimeSpan.Zero;
fish.EffectSoundDelay = TimeSpan.FromSeconds(8.0);
fish.NoResourcesMessage = 503172; // The fish don't seem to be biting here.
fish.FailMessage = 503171; // You fish a while, but fail to catch anything.
fish.TimedOutOfRangeMessage = 500976; // You need to be closer to the water to fish!
fish.OutOfRangeMessage = 500976; // You need to be closer to the water to fish!
fish.PackFullMessage = 503176; // You do not have room in your backpack for a fish.
fish.ToolBrokeMessage = 503174; // You broke your fishing pole.
res = new HarvestResource[]
{
new HarvestResource(00.0, 00.0, 120.0, 1043297, typeof(Fish))
};
veins = new HarvestVein[]
{
new HarvestVein(100.0, 0.0, res[0], null)
};
fish.Resources = res;
fish.Veins = veins;
if (Core.ML)
{
fish.BonusResources = new BonusHarvestResource[]
{
new BonusHarvestResource(0, 97.0, null, null), //set to same chance as mining ml gems
new BonusHarvestResource(80.0, 2.0, 1113764, typeof(DelicateScales)),
new BonusHarvestResource(80.0, 1.0, 1072597, typeof(WhitePearl))
};
}
this.m_Definition = fish;
this.Definitions.Add(fish);
#endregion
}
public override void OnConcurrentHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
{
from.SendLocalizedMessage(500972); // You are already fishing.
}
private class MutateEntry
{
public double m_ReqSkill, m_MinSkill, m_MaxSkill;
public bool m_DeepWater;
public Type[] m_Types;
public MutateEntry(double reqSkill, double minSkill, double maxSkill, bool deepWater, params Type[] types)
{
m_ReqSkill = reqSkill;
m_MinSkill = minSkill;
m_MaxSkill = maxSkill;
m_DeepWater = deepWater;
m_Types = types;
}
}
private static MutateEntry[] m_MutateTable = new MutateEntry[]
{
new MutateEntry( 80.0, 80.0, 1865.0, true, typeof( SpecialFishingNet ) ),
new MutateEntry( 90.0, 80.0, 1875.0, true, typeof( TreasureMap ) ),
new MutateEntry( 100.0, 80.0, 750.0, true, typeof( MessageInABottle ) ),
new MutateEntry( 80.0, 80.0, 4080.0, true, typeof( BigFish ) ),
new MutateEntry( 0.0, 125.0, -2375.0, false, typeof( PrizedFish ), typeof( WondrousFish ), typeof( TrulyRareFish ), typeof( PeculiarFish ) ),
new MutateEntry( 0.0, 125.0, -420.0, false, typeof( Boots ), typeof( Shoes ), typeof( Sandals ), typeof( ThighBoots ) ),
new MutateEntry( 80.0, 80.0, 2500.0, false, typeof( MudPuppy ), typeof( RedHerring) ),
new MutateEntry( 0.0, 200.0, -200.0, false, new Type[1]{ null } )
};
private static MutateEntry[] m_SiegeMutateTable = new MutateEntry[]
{
new MutateEntry( 80.0, 80.0, 1865.0, true, typeof( SpecialFishingNet ) ),
new MutateEntry( 0.0, 200.0, -200.0, false, new Type[1]{ null } ),
new MutateEntry( 100.0, 80.0, 1865.0, true, typeof( MessageInABottle ) ),
new MutateEntry( 80.0, 80.0, 4080.0, true, typeof( BigFish ) ),
new MutateEntry( 0.0, 125.0, -2375.0, false, typeof( PrizedFish ), typeof( WondrousFish ), typeof( TrulyRareFish ), typeof( PeculiarFish ) ),
new MutateEntry( 0.0, 105.0, -420.0, false, typeof( Boots ), typeof( Shoes ), typeof( Sandals ), typeof( ThighBoots ) ),
new MutateEntry( 80.0, 80.0, 2500.0, false, typeof( MudPuppy ), typeof( RedHerring) ),
new MutateEntry( 0.0, 200.0, -200.0, false, new Type[1]{ null } )
};
private static MutateEntry[] m_LavaMutateTable = new MutateEntry[]
{
new MutateEntry( 0.0, 80.0, 333, false, typeof(StoneFootwear)),
new MutateEntry( 80.0, 80.0, 333, false, typeof(CrackedLavaRockEast), typeof(CrackedLavaRockSouth)),
new MutateEntry( 85.0, 80.0, 333, false, typeof(StonePaver)),
new MutateEntry( 80.0, 80.0, 4080, false, typeof(BaseWeapon))
};
public override bool SpecialHarvest(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc)
{
PlayerMobile player = from as PlayerMobile;
Container pack = from.Backpack;
if (player != null)
{
QuestSystem qs = player.Quest;
if (qs is CollectorQuest)
{
QuestObjective obj = qs.FindObjective(typeof(FishPearlsObjective));
if (obj != null && !obj.Completed)
{
if (Utility.RandomDouble() < 0.5)
{
player.SendLocalizedMessage(1055086, "", 0x59); // You pull a shellfish out of the water, and find a rainbow pearl inside of it.
obj.CurProgress++;
}
else
{
player.SendLocalizedMessage(1055087, "", 0x2C); // You pull a shellfish out of the water, but it doesn't have a rainbow pearl.
}
return true;
}
}
if (from.Region.IsPartOf("Underworld"))
{
foreach (BaseQuest quest in player.Quests)
{
if (quest is SomethingFishy && Utility.RandomDouble() < 0.1)
{
Item red = new RedHerring();
from.AddToBackpack(red);
player.SendLocalizedMessage(1095047, "", 0x23); // You pull a shellfish out of the water, but it doesn't have a rainbow pearl.
return true;
}
if (quest is ScrapingtheBottom && Utility.RandomDouble() < 0.1)
{
Item mug = new MudPuppy();
from.AddToBackpack(mug);
player.SendLocalizedMessage(1095064, "", 0x23); // You pull a shellfish out of the water, but it doesn't have a rainbow pearl.
return true;
}
}
}
#region High Seas Charydbis
if (Core.HS && tool is FishingPole && CharydbisSpawner.SpawnInstance != null && CharydbisSpawner.SpawnInstance.IsSummoned)
{
Item oracle = from.Backpack.FindItemByType(typeof(OracleOfTheSea));
FishingPole pole = tool as FishingPole;
CharydbisSpawner sp = CharydbisSpawner.SpawnInstance;
if (oracle != null && sp != null)
{
if (from.Map != sp.Map)
from.SendLocalizedMessage(1150861); //Charybdis have never been seen in these waters, try somewhere else.
else if (pole.BaitType == typeof(Charydbis) && from.Skills[SkillName.Fishing].Value >= 100)
{
if (sp.Charydbis == null && !sp.HasSpawned && sp.CurrentLocation.Contains(loc))
{
Server.Multis.BaseBoat boat = Server.Multis.BaseBoat.FindBoatAt(from, from.Map);
sp.SpawnCharydbis(from, loc, sp.Map, boat);
sp.HasSpawned = true;
pole.OnFishedHarvest(from, true);
return true;
}
else if (sp.LastLocation.Contains(loc))
{
from.SendLocalizedMessage(1150862); //The charybdis has moved on from this location, consult Oracle Of The Seas again.
}
}
else
from.SendLocalizedMessage(1150858); //You see a few bubbles, but no charybdis.
}
}
#endregion
}
return false;
}
public override Type MutateType(Type type, Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, HarvestResource resource)
{
if (FishInfo.IsRareFish(type))
return type;
bool deepWater = IsDeepWater(loc, map);
bool junkproof = HasTypeHook(tool, HookType.JunkProof);
double skillBase = from.Skills[SkillName.Fishing].Base;
double skillValue = from.Skills[SkillName.Fishing].Value;
var table = Siege.SiegeShard ? m_SiegeMutateTable : m_MutateTable;
for (int i = 0; i < table.Length; ++i)
{
MutateEntry entry = m_MutateTable[i];
// RedHerring / MudPuppy
if (i == 6 && (from.Region == null || !from.Region.IsPartOf("Underworld")))
continue;
if (junkproof && i == 5 && 0.80 >= Utility.RandomDouble())
continue;
if (!deepWater && entry.m_DeepWater)
continue;
if (skillBase >= entry.m_ReqSkill)
{
double chance = (skillValue - entry.m_MinSkill) / (entry.m_MaxSkill - entry.m_MinSkill);
if (chance > Utility.RandomDouble())
return entry.m_Types[Utility.Random(entry.m_Types.Length)];
}
}
return type;
}
private bool IsDeepWater(Point3D p, Map map)
{
return Items.SpecialFishingNet.ValidateDeepWater(map, p.X, p.Y) && (map == Map.Trammel || map == Map.Felucca || map == Map.Tokuno);
}
public override bool CheckResources(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed)
{
Container pack = from.Backpack;
if (pack != null)
{
List<SOS> messages = pack.FindItemsByType<SOS>();
for (int i = 0; i < messages.Count; ++i)
{
SOS sos = messages[i];
if ((from.Map == Map.Felucca || from.Map == Map.Trammel) && from.InRange(sos.TargetLocation, 60))
return true;
}
}
return base.CheckResources(from, tool, def, map, loc, timed);
}
public override Item Construct(Type type, Mobile from, Item tool)
{
// Searing Weapon Support
if (type == typeof(BaseWeapon))
return null;
if (type == typeof(TreasureMap))
{
int level;
if (from is PlayerMobile && ((PlayerMobile)from).Young && from.Map == Map.Trammel && TreasureMap.IsInHavenIsland(from))
level = 0;
else
level = 1;
return new TreasureMap(level, from.Map == Map.Felucca ? Map.Felucca : Map.Trammel);
}
else if (type == typeof(MessageInABottle))
{
return new MessageInABottle(from.Map == Map.Felucca ? Map.Felucca : Map.Trammel);
}
else if (type == typeof(WhitePearl))
{
return new WhitePearl();
}
Container pack = from.Backpack;
if (pack != null)
{
List<SOS> messages = pack.FindItemsByType<SOS>();
for (int i = 0; i < messages.Count; ++i)
{
SOS sos = messages[i];
if ((from.Map == Map.Felucca || from.Map == Map.Trammel) && from.InRange(sos.TargetLocation, 60))
{
Item preLoot = null;
bool dredge = HasTypeHook(tool, HookType.Dredging);
switch (Utility.Random(Core.HS ? 17 : 16))
{
case 0: // Body parts
case 1:
{
int[] list = new int[]
{
0x1CDD, 0x1CE5, // arm
0x1CE0, 0x1CE8, // torso
0x1CE1, 0x1CE9, // head
0x1CE2, 0x1CEC // leg
};
preLoot = new ShipwreckedItem(Utility.RandomList(list), dredge);
break;
}
case 2: // Bone parts
case 3:
{
int[] list = new int[]
{
0x1AE0, 0x1AE1, 0x1AE2, 0x1AE3, 0x1AE4, // skulls
0x1B09, 0x1B0A, 0x1B0B, 0x1B0C, 0x1B0D, 0x1B0E, 0x1B0F, 0x1B10, // bone piles
0x1B15, 0x1B16 // pelvis bones
};
preLoot = new ShipwreckedItem(Utility.RandomList(list), dredge);
break;
}
case 4: // Paintings and portraits
case 5:
{
preLoot = new ShipwreckedItem(Utility.Random(0xE9F, 10), dredge);
break;
}
case 6: // Pillows
case 7:
{
preLoot = new ShipwreckedItem(Utility.Random(0x13A4, 11), dredge);
break;
}
case 8: // Shells
case 9:
{
preLoot = new ShipwreckedItem(Utility.Random(0xFC4, 9), dredge);
break;
}
case 10: //Hats
case 11:
{
if (Utility.RandomBool())
preLoot = new SkullCap();
else
preLoot = new TricorneHat();
break;
}
case 12: // Misc
case 13:
{
int[] list = new int[]
{
0x1EB5, // unfinished barrel
0xA2A, // stool
0xC1F, // broken clock
0x1047, 0x1048, // globe
0x1EB1, 0x1EB2, 0x1EB3, 0x1EB4 // barrel staves
};
if (Utility.Random(list.Length + 1) == 0)
preLoot = new Candelabra();
else
preLoot = new ShipwreckedItem(Utility.RandomList(list), dredge);
break;
}
#region High Seas
case 14:
{
int[] list = new int[]
{
0x1E19, 0x1E1A, 0x1E1B, //Fish heads
0x1E2A, 0x1E2B, //Oars
0x1E71, 0x1E7A, //Unfinished drawers
0x1E75, //Unfinished legs
};
double ran = Utility.RandomDouble();
if (ran < 0.05)
preLoot = new YellowPolkaDotBikini();
else if (ran < 0.25)
preLoot = new ShipwreckedItem(list[Utility.RandomMinMax(3, 7)], dredge);
else
preLoot = new ShipwreckedItem(list[Utility.Random(3)], dredge);
break;
}
#endregion
}
if (preLoot != null)
{
if (preLoot is IShipwreckedItem)
((IShipwreckedItem)preLoot).IsShipwreckedItem = true;
return preLoot;
}
LockableContainer chest;
if (0.01 > Utility.RandomDouble())
{
chest = new ShipsStrongbox(sos.Level);
}
else
{
if (Utility.RandomBool())
chest = new MetalGoldenChest();
else
chest = new WoodenChest();
}
if (sos.IsAncient)
{
chest.Hue = 0x481;
}
TreasureMapChest.Fill(from, chest, Math.Max(1, Math.Min(4, sos.Level)), true);
sos.OnSOSComplete(chest);
if (sos.IsAncient)
chest.DropItem(new FabledFishingNet());
else
chest.DropItem(new SpecialFishingNet());
chest.Movable = true;
chest.Locked = false;
chest.TrapType = TrapType.None;
chest.TrapPower = 0;
chest.TrapLevel = 0;
chest.IsShipwreckedItem = true;
sos.Delete();
return chest;
}
}
}
return base.Construct(type, from, tool);
}
public override bool Give(Mobile m, Item item, bool placeAtFeet)
{
if (item is TreasureMap || item is MessageInABottle || item is SpecialFishingNet)
{
BaseCreature serp;
if (0.25 > Utility.RandomDouble())
serp = new DeepSeaSerpent();
else
serp = new SeaSerpent();
int x = m.X, y = m.Y;
Map map = m.Map;
for (int i = 0; map != null && i < 20; ++i)
{
int tx = m.X - 10 + Utility.Random(21);
int ty = m.Y - 10 + Utility.Random(21);
LandTile t = map.Tiles.GetLandTile(tx, ty);
if (t.Z == -5 && ((t.ID >= 0xA8 && t.ID <= 0xAB) || (t.ID >= 0x136 && t.ID <= 0x137)) && !Spells.SpellHelper.CheckMulti(new Point3D(tx, ty, -5), map))
{
x = tx;
y = ty;
break;
}
}
serp.MoveToWorld(new Point3D(x, y, -5), map);
serp.Home = serp.Location;
serp.RangeHome = 10;
serp.PackItem(item);
m.SendLocalizedMessage(503170); // Uh oh! That doesn't look like a fish!
return true; // we don't want to give the item to the player, it's on the serpent
}
if (item is BigFish || item is WoodenChest || item is MetalGoldenChest)
placeAtFeet = true;
#region High Seas
if (item is RareFish)
{
RareFish fish = (RareFish)item;
if (FishInfo.IsRareFish(fish.GetType()))
{
fish.Fisher = m;
fish.DateCaught = DateTime.Now;
fish.Stackable = false;
fish.Weight = Math.Max(1, 200 - (int)Math.Sqrt(Utility.RandomMinMax(0, 40000)));
}
}
#endregion
return base.Give(m, item, placeAtFeet);
}
public override void SendSuccessTo(Mobile from, Item item, HarvestResource resource)
{
if (item is BigFish)
{
from.SendLocalizedMessage(1042635); // Your fishing pole bends as you pull a big fish from the depths!
((BigFish)item).Fisher = from;
((BigFish)item).DateCaught = DateTime.Now;
}
#region Stygian Abyss
else if (item is RedHerring)
from.SendLocalizedMessage(1095047, null, 0x23); // You take the Red Herring and put it into your pack. The only thing more surprising than the fact that there is a fish called the Red Herring is the fact that you fished for it!
else if (item is MudPuppy)
from.SendLocalizedMessage(1095064, null, 0x23); // You take the Mud Puppy and put it into your pack. Not surprisingly, it is very muddy.
#endregion
else if (item is WoodenChest || item is MetalGoldenChest)
{
from.SendLocalizedMessage(503175); // You pull up a heavy chest from the depths of the ocean!
}
else
{
int number;
string name;
if (item is BaseMagicFish)
{
number = 1008124;
name = "a mess of small fish";
}
else if (item is Fish)
{
number = 1008124;
name = item.ItemData.Name;
}
else if (item is BaseShoes)
{
number = 1008124;
name = item.ItemData.Name;
}
else if (item is TreasureMap)
{
number = 1008125;
name = "a sodden piece of parchment";
}
else if (item is MessageInABottle)
{
number = 1008125;
name = "a bottle, with a message in it";
}
else if (item is SpecialFishingNet)
{
number = 1008125;
name = "a special fishing net"; // TODO: this is just a guess--what should it really be named?
}
else if (item is BaseHighseasFish)
{
if (FishInfo.IsRareFish(item.GetType()))
{
from.SendLocalizedMessage(1043297, "a rare fish");
}
else if (item.LabelNumber < 1)
{
from.SendLocalizedMessage(1043297, "a fish");
}
else
from.SendLocalizedMessage(1043297, String.Format("#{0}", item.LabelNumber));
return;
}
else if (item.LabelNumber > 0)
{
from.SendLocalizedMessage(1043297, String.Format("#{0}", item.LabelNumber));
return;
}
else
{
number = 1043297;
if ((item.ItemData.Flags & TileFlag.ArticleA) != 0)
name = "a " + item.ItemData.Name;
else if ((item.ItemData.Flags & TileFlag.ArticleAn) != 0)
name = "an " + item.ItemData.Name;
else
name = item.ItemData.Name;
}
NetState ns = from.NetState;
if (ns == null)
return;
if (number == 1043297 || ns.HighSeas)
from.SendLocalizedMessage(number, name);
else
from.SendLocalizedMessage(number, true, name);
}
}
public override void StartHarvesting(Mobile from, Item tool, object toHarvest)
{
if (from != null && tool != null && tool.IsChildOf(from.Backpack))
{
Item item = from.FindItemOnLayer(Layer.OneHanded);
Item item2 = from.FindItemOnLayer(Layer.TwoHanded);
if (item != null)
from.AddToBackpack(item);
if (item2 != null)
from.AddToBackpack(item2);
Timer.DelayCall(TimeSpan.FromMilliseconds(250), () =>
{
from.EquipItem(tool);
});
}
base.StartHarvesting(from, tool, toHarvest);
}
public override void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
{
base.OnHarvestStarted(from, tool, def, toHarvest);
int tileID;
Map map;
Point3D loc;
if (this.GetHarvestDetails(from, tool, toHarvest, out tileID, out map, out loc))
Timer.DelayCall(TimeSpan.FromSeconds(1.5),
delegate
{
if (Core.ML)
from.RevealingAction();
int sound = 0x364;
int effect = 0x352D;
if (IsLavaHarvest(tool, toHarvest))
{
sound = 0x60A;
effect = 0x1A75;
}
Effects.SendLocationEffect(loc, map, effect, 16, 4);
Effects.PlaySound(loc, map, sound);
});
}
public override void OnHarvestFinished(Mobile from, Item tool, HarvestDefinition def, HarvestVein vein, HarvestBank bank, HarvestResource resource, object harvested)
{
base.OnHarvestFinished(from, tool, def, vein, bank, resource, harvested);
if (Core.ML)
from.RevealingAction();
}
public override object GetLock(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
{
return this;
}
public override bool BeginHarvesting(Mobile from, Item tool)
{
if (!base.BeginHarvesting(from, tool))
return false;
from.SendLocalizedMessage(500974); // What water do you want to fish in?
return true;
}
public override bool CheckHarvest(Mobile from, Item tool)
{
if (!base.CheckHarvest(from, tool))
return false;
if (from.Mounted || from.Flying)
{
from.SendLocalizedMessage(500971); // You can't fish while riding!
return false;
}
return true;
}
public override bool CheckHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
{
if (!base.CheckHarvest(from, tool, def, toHarvest))
return false;
if (from.Mounted || from.Flying)
{
from.SendLocalizedMessage(500971); // You can't fish while riding!
return false;
}
return true;
}
private static readonly int[] m_WaterTiles = new int[]
{
0x00A8, 0x00AB,
0x0136, 0x0137,
0x5797, 0x579C,
0x746E, 0x7485,
0x7490, 0x74AB,
0x74B5, 0x75D5
};
#region HighSeas
public static int[] LavaTiles { get { return m_LavaTiles; } }
private static int[] m_LavaTiles = new int[]
{
0x1F4, 0x1F5,
0x1F6, 0x1F7,
4846, 4847, 4848, 4849, 4850,
4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4560, 4561, 4562,
4864, 4865, 4866, 4867, 4868,
4870, 4871, 4872, 4873, 4874,
4876, 4877, 4878, 4879, 4880,
4882, 4883, 4884, 4885, 4886,
4888, 4889, 4890, 4891, 4892,
};
public override bool GetHarvestDetails(Mobile from, Item tool, object toHarvest, out int tileID, out Map map, out Point3D loc)
{
bool lava = HasTypeHook(tool, HookType.Lava);
if (toHarvest is Static && !((Static)toHarvest).Movable)
{
Static obj = (Static)toHarvest;
if (lava)
tileID = obj.ItemID;
else
tileID = (obj.ItemID & 0x3FFF) | 0x4000;
map = obj.Map;
loc = obj.GetWorldLocation();
}
else if (toHarvest is StaticTarget)
{
StaticTarget obj = (StaticTarget)toHarvest;
if (lava)
tileID = obj.ItemID;
else
tileID = (obj.ItemID & 0x3FFF) | 0x4000;
map = from.Map;
loc = obj.Location;
}
else if (toHarvest is LandTarget)
{
LandTarget obj = (LandTarget)toHarvest;
tileID = obj.TileID;
map = from.Map;
loc = obj.Location;
}
else
{
tileID = 0;
map = null;
loc = Point3D.Zero;
return false;
}
//Lava tile, no lava hook
if (ValidateSpecialTile(tileID) && !lava)
return false;
return (map != null && map != Map.Internal);
}
public override HarvestDefinition GetDefinition(int tileID, Item tool)
{
if (tool is FishingPole)
{
FishingPole pole = (FishingPole)tool;
bool usingLavaHook = HasTypeHook(pole, HookType.Lava);
if (usingLavaHook && ValidateSpecialTile(tileID))
return GetDefinitionFromSpecialTile(tileID);
}
return base.GetDefinition(tileID, tool);
}
public bool ValidateSpecialTile(int tileID)
{
foreach (int id in m_LavaTiles)
{
if (tileID == id)
return true;
}
return false;
}
public bool IsLavaHarvest(Item tool, object toHarvest)
{
int id = 0;
if (!HasTypeHook(tool, HookType.Lava))
return false;
if (toHarvest is StaticTarget)
id = ((StaticTarget)toHarvest).ItemID;
else if (toHarvest is LandTarget)
id = ((LandTarget)toHarvest).TileID;
else if (toHarvest is Static && !((Static)toHarvest).Movable)
id = ((Static)toHarvest).ItemID;
return ValidateSpecialTile(id);
}
public bool IsLavaHarvest(Item tool, int id)
{
if (!HasTypeHook(tool, HookType.Lava))
return false;
return ValidateSpecialTile(id);
}
public override void OnToolUsed(Mobile from, Item tool, bool caughtsomething)
{
if (tool is FishingPole)
((FishingPole)tool).OnFishedHarvest(from, caughtsomething);
}
public static bool HasTypeHook(Item tool, HookType type)
{
if (tool is FishingPole)
return ((FishingPole)tool).HookType == type;
return false;
}
public override Type GetResourceType(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, HarvestResource resource)
{
Type type = FishInfo.GetSpecialItem(from, tool, loc, false);
if (type == null)
type = base.GetResourceType(from, tool, def, map, loc, resource);
return type;
}
public override void FinishHarvesting(Mobile from, Item tool, HarvestDefinition def, object toHarvest, object locked)
{
//Lava fishing needs to have its own set of rules.
if (IsLavaHarvest(tool, toHarvest))
{
from.EndAction(locked);
if (!CheckHarvest(from, tool))
return;
int tileID;
Map map;
Point3D loc;
if (!GetHarvestDetails(from, tool, toHarvest, out tileID, out map, out loc))
{
OnBadHarvestTarget(from, tool, toHarvest);
return;
}
else if (!def.Validate(tileID) && !def.ValidateSpecial(tileID))
{
OnBadHarvestTarget(from, tool, toHarvest);
return;
}
if (!CheckRange(from, tool, def, map, loc, true))
return;
else if (!CheckResources(from, tool, def, map, loc, true))
return;
else if (!CheckHarvest(from, tool, def, toHarvest))
return;
HarvestBank bank = def.GetBank(map, loc.X, loc.Y);
if (bank == null)
return;
HarvestVein vein = bank.Vein;
if (vein == null)
return;
Type type = null;
HarvestResource resource = MutateResource(from, tool, def, map, loc, vein, vein.PrimaryResource, vein.FallbackResource);
if (from.CheckSkill(def.Skill, resource.MinSkill, resource.MaxSkill))
{
//Special eye candy item
type = GetSpecialLavaItem(from, tool, map, loc, toHarvest);
//Special fish
if (type == null)
type = FishInfo.GetSpecialItem(from, tool, loc, IsLavaHarvest(tool, tileID));
if (type != null)
{
Item item = Construct(type, from, tool);
if (item == null)
{
type = null;
}
else
{
if (from.AccessLevel == AccessLevel.Player)
bank.Consume(Convert.ToInt32(map != null && map.Rules == MapRules.FeluccaRules ? Math.Ceiling(item.Amount / 2.0) : item.Amount), from);
if (Give(from, item, true))
{
SendSuccessTo(from, item, null);
}
else
{
SendPackFullTo(from, item, def, null);
item.Delete();
}
}
}
}
if (type == null)
{
def.SendMessageTo(from, def.FailMessage);
double skill = (double)from.Skills[SkillName.Fishing].Value / 50;
if (0.5 / skill > Utility.RandomDouble())
OnToolUsed(from, tool, false);
}
else
OnToolUsed(from, tool, true);
OnHarvestFinished(from, tool, def, vein, bank, null, null);
}
else
base.FinishHarvesting(from, tool, def, toHarvest, locked);
}
public override bool CheckHarvestSkill(Map map, Point3D loc, Mobile from, HarvestResource res, HarvestDefinition def)
{
bool deepWater = IsDeepWater(loc, map);
double value = from.Skills[SkillName.Fishing].Value;
if (deepWater && value < 75.0) // can't fish here yet
return from.Skills[def.Skill].Value >= res.ReqSkill;
if (!deepWater && value >= 75.0) // you can fish, but no gains!
return true;
return base.CheckHarvestSkill(map, loc, from, res, def);
}
public Type GetSpecialLavaItem(Mobile from, Item type, Map map, Point3D pnt, object toHarvest)
{
Type newType = null;
double skillBase = from.Skills[SkillName.Fishing].Base;
double skillValue = Math.Min(120.0, from.Skills[SkillName.Fishing].Value);
//Same method as mutate entries
for (int i = 0; i < m_LavaMutateTable.Length; ++i)
{
MutateEntry entry = m_LavaMutateTable[i];
if (skillBase >= entry.m_ReqSkill)
{
double chance = (skillValue - entry.m_MinSkill) / (entry.m_MaxSkill - entry.m_MinSkill);
if (map != null && map.Rules == MapRules.FeluccaRules)
chance *= 1.5;
if (chance > Utility.RandomDouble())
{
newType = entry.m_Types[Utility.Random(entry.m_Types.Length)];
if (newType == typeof(BaseWeapon))
{
BaseWeapon wep = Loot.RandomWeapon();
if (wep != null)
{
wep.AttachSocket(new SearingWeapon(wep));
from.AddToBackpack(wep);
from.SendMessage("You have pulled out an item : mysterious weapon");
return typeof(BaseWeapon);
}
}
}
}
}
return newType;
}
#endregion
}
}