450 lines
19 KiB
C#
450 lines
19 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
using Server;
|
|
using Server.Multis;
|
|
using Server.Regions;
|
|
using Server.Mobiles;
|
|
using Server.Engines.Quests;
|
|
|
|
namespace Server.Items
|
|
{
|
|
public class FishInfo
|
|
{
|
|
public static void Configure()
|
|
{
|
|
//Rare Fish; 0 - 15
|
|
m_FishInfos.Add(new FishInfo(2506, typeof(AutumnDragonfish), 1116090, "Ilshenar", false, RareChance, 105.4));//Confirmed
|
|
m_FishInfos.Add(new FishInfo(2591, typeof(BlueLobster), 1116366, "Ice", false, RareChance, 103.1)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(1157, typeof(BullFish), 1116095, "Labyrinth", false, RareChance, 105.4)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(1167, typeof(CrystalFish), 1116092, "Prism of Light", false, RareChance, 105.4)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2578, typeof(FairySalmon), 1116089, "TerMur", false, RareChance, 85.8)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(1461, typeof(FireFish), 1116093, "Shame", false, RareChance, 95.8)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(1257, typeof(GiantKoi), 1116088, "Tokuno", true, RareChance, 95.8)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2579/*1287*/, typeof(GreatBarracuda),1116100, "Felucca", true, RareChance, 89.0)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2959, typeof(HolyMackerel), 1116087, "Gravewater Lake", false, RareChance, 102.9)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2075, typeof(LavaFish), 1116096, "Abyss", false, RareChance, 110.0)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2075/*1152*/, typeof(ReaperFish), 1116094, "Doom", false, RareChance, 98.1)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2539, typeof(SpiderCrab), 1116367, "Terathan Keep", false, RareChance, 103.1)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2558, typeof(StoneCrab), 1116365, "T2A", true, RareChance, 103.1)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(43, typeof(SummerDragonfish), 1116091, "Destard", false, RareChance, 105.2)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(1154, typeof(UnicornFish), 1116086, "Twisted Weald", false, RareChance, 110.0)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2515, typeof(YellowtailBarracuda), 1116098, "Trammel", true, RareChance, 81.9));//Confirmed
|
|
|
|
//Legendary Fish ; 16-34
|
|
m_FishInfos.Add(new FishInfo(2406, typeof(AbyssalDragonfish), 1116118, "Destard", false, LegendaryChance, 120.0)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2500, typeof(BlackMarlin), 1116099, "Felucca", true, LegendaryChance, 110.1)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2117, typeof(BloodLobster), 1116370, "Shame", false, LegendaryChance, 115.1)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(0, typeof(BlueMarlin), 1116097, "Trammel", true, LegendaryChance, 105.0)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(1777, typeof(DreadLobster), 1116371, "Doom", false, LegendaryChance, 115.1));
|
|
m_FishInfos.Add(new FishInfo(1158, typeof(DungeonPike), 1116107, "Terathan Keep", false, LegendaryChance, 105.1)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2576, typeof(GiantSamuraiFish), 1116103, "Tokuno", true, LegendaryChance, 110.1)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(1281, typeof(GoldenTuna), 1116102, "Tokuno", true, LegendaryChance, 105.0)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2604, typeof(Kingfish), 1116085, "TrammelAndFelucca", true, LegendaryChance, 92.2)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(1463, typeof(LanternFish), 1116106, "Prism of Light", false, LegendaryChance, 105.1)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(1283, typeof(RainbowFish), 1116108, "Twisted Weald", false, LegendaryChance, 105.1));
|
|
m_FishInfos.Add(new FishInfo(2076, typeof(SeekerFish), 1116109, "Labyrinth", false, LegendaryChance, 105.1));
|
|
m_FishInfos.Add(new FishInfo(0, typeof(SpringDragonfish), 1116104, "Ilshenar", false, LegendaryChance, 120.0)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(1837, typeof(StoneFish), 1116110, "T2A", true, LegendaryChance, 115.1)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2600, typeof(TunnelCrab), 1116372, "Underworld", false, LegendaryChance, 115.1)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2069, typeof(VoidCrab), 1116368, "TerMur", false, LegendaryChance, 120.0)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2071, typeof(VoidLobster), 1116369, "Abyss", false, LegendaryChance, 120.0));
|
|
m_FishInfos.Add(new FishInfo(2499, typeof(WinterDragonfish), 1116105, "Ice", false, LegendaryChance, 120.0)); //Confirmed
|
|
m_FishInfos.Add(new FishInfo(2551, typeof(ZombieFish), 1116101, "Gravewater Lake", false, LegendaryChance, 115.1)); //Confirmed
|
|
|
|
//Cannot fish up but used for bait
|
|
m_FishInfos.Add(new FishInfo(1170, typeof(Charydbis), 1150208, "cannotfishup", true, LegendaryChance, 120.0));
|
|
|
|
m_InvalidatedLocations = false;
|
|
Timer.DelayCall(TimeSpan.FromSeconds(10), new TimerCallback(InvalidateLocations));
|
|
}
|
|
|
|
public static List<FishInfo> FishInfos { get { return m_FishInfos; } }
|
|
private static List<FishInfo> m_FishInfos = new List<FishInfo>();
|
|
|
|
private int m_Hue;
|
|
private Type m_Type;
|
|
private object m_Label;
|
|
private object m_Location;
|
|
private bool m_RequiresDeepWater;
|
|
private double m_BaseChance;
|
|
private double m_MinSkill;
|
|
|
|
public int Hue { get { return m_Hue; } }
|
|
public Type Type { get { return m_Type; } }
|
|
public object LabelNumber { get { return m_Label; } }
|
|
public object Location { get { return m_Location; } set { m_Location = value; } }
|
|
public bool RequiresDeepWater { get { return m_RequiresDeepWater; } }
|
|
public double BaseChance { get { return m_BaseChance; } }
|
|
public double MinSkill { get { return m_MinSkill; } }
|
|
|
|
public static readonly double RareChance = 0.0075;
|
|
public static readonly double LegendaryChance = 0.001;
|
|
|
|
public static bool m_InvalidatedLocations;
|
|
|
|
public FishInfo(int hue, Type type, object label, object found, bool deepwater, double basechance, double minskill)
|
|
{
|
|
m_Hue = hue;
|
|
m_Type = type;
|
|
m_Label = label;
|
|
m_Location = found;
|
|
m_RequiresDeepWater = deepwater;
|
|
m_BaseChance = basechance;
|
|
m_MinSkill = minskill;
|
|
}
|
|
|
|
public static void InvalidateLocations()
|
|
{
|
|
if (m_InvalidatedLocations)
|
|
return;
|
|
|
|
int c = 0;
|
|
|
|
foreach (FishInfo info in m_FishInfos)
|
|
{
|
|
if (info.Location is string)
|
|
{
|
|
string str = info.Location as string;
|
|
|
|
if (str == "Trammel")
|
|
{
|
|
info.Location = Map.Trammel;
|
|
c++;
|
|
}
|
|
else if (str == "Felucca")
|
|
{
|
|
info.Location = Map.Felucca;
|
|
c++;
|
|
}
|
|
else if (str == "Tokuno")
|
|
{
|
|
info.Location = Map.Tokuno;
|
|
c++;
|
|
}
|
|
else if (str == "Ilshenar")
|
|
{
|
|
info.Location = Map.Ilshenar;
|
|
c++;
|
|
}
|
|
else if (str == "Malas")
|
|
{
|
|
info.Location = Map.Malas;
|
|
c++;
|
|
}
|
|
else if (str == "TerMur")
|
|
{
|
|
info.Location = Map.TerMur;
|
|
c++;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_InvalidatedLocations = true;
|
|
//Console.WriteLine("Invalidated {0} Map Locations in FishInfo.cs", c.ToString());
|
|
}
|
|
|
|
public static bool IsRareFish(Type type)
|
|
{
|
|
return m_FishInfos.Any(info => info.Type == type);
|
|
}
|
|
|
|
public static FishInfo GetInfo(Type type)
|
|
{
|
|
return m_FishInfos.FirstOrDefault(info => info.Type == type);
|
|
}
|
|
|
|
public static FishInfo GetInfo(int hue)
|
|
{
|
|
return m_FishInfos.FirstOrDefault(info => info.Hue == hue);
|
|
}
|
|
|
|
public static int GetIndexFromType(Type type)
|
|
{
|
|
if(type == null)
|
|
return -1;
|
|
|
|
for(int i = 0; i < m_FishInfos.Count; i++)
|
|
if(m_FishInfos[i].Type == type)
|
|
return i;
|
|
return -1;
|
|
}
|
|
|
|
public static Type GetTypeFromIndex(int index)
|
|
{
|
|
if(index < 0 || index >= m_FishInfos.Count)
|
|
return m_FishInfos[0].Type;
|
|
|
|
return m_FishInfos[index].Type;
|
|
}
|
|
|
|
public static int GetFishHue(int index)
|
|
{
|
|
if (index < 0 || index >= m_FishInfos.Count)
|
|
return 0;
|
|
|
|
return m_FishInfos[index].Hue;
|
|
}
|
|
|
|
public static int GetFishHue(Type type)
|
|
{
|
|
foreach (FishInfo info in m_FishInfos)
|
|
if (info.Type == type)
|
|
return info.Hue;
|
|
return 0;
|
|
}
|
|
|
|
public static object GetFishLabel(int index)
|
|
{
|
|
if (index < 0 || index >= m_FishInfos.Count)
|
|
return 0;
|
|
|
|
return m_FishInfos[index].LabelNumber;
|
|
}
|
|
|
|
public static object GetFishLabel(Type type)
|
|
{
|
|
foreach (FishInfo info in FishInfos)
|
|
{
|
|
if (info.Type == type)
|
|
return info.LabelNumber;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static string GetFishLocation(Type type)
|
|
{
|
|
foreach (FishInfo info in FishInfos)
|
|
{
|
|
if (info.Type == type)
|
|
return info.Location.ToString();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static Type GetSpecialItem(Mobile from, Item harvestItem, Point3D pnt, bool rareOnly)
|
|
{
|
|
return GetSpecialItem(from, harvestItem, pnt, 0, rareOnly);
|
|
}
|
|
|
|
public static Type GetSpecialItem(Mobile from, Item harvestItem, Point3D pnt, double bump, bool rareOnly)
|
|
{
|
|
InvalidateLocations();
|
|
|
|
Map map = from.Map;
|
|
Point3D fromLoc = from.Location;
|
|
|
|
Region reg = from.Region;
|
|
|
|
if (reg.Parent != null)
|
|
reg = reg.Parent;
|
|
|
|
double skill = from.Skills[SkillName.Fishing].Value;
|
|
bool fishing = harvestItem is FishingPole;
|
|
|
|
Type bait = null;
|
|
Type item = null;
|
|
bool enhanced = false;
|
|
|
|
if (harvestItem is FishingPole)
|
|
{
|
|
bait = ((FishingPole)harvestItem).BaitType;
|
|
enhanced = ((FishingPole)harvestItem).EnhancedBait;
|
|
}
|
|
else if (harvestItem is LobsterTrap)
|
|
{
|
|
bait = ((LobsterTrap)harvestItem).BaitType;
|
|
enhanced = ((LobsterTrap)harvestItem).EnhancedBait;
|
|
}
|
|
|
|
//insertion of baited type first to increase chances of fishing it up!
|
|
List<FishInfo> infos = new List<FishInfo>(m_FishInfos);
|
|
|
|
if (bait != null)
|
|
{
|
|
for (int i = 0; i < infos.Count; i++)
|
|
{
|
|
FishInfo info = infos[i];
|
|
if (info.Type == bait)
|
|
{
|
|
infos.Remove(info);
|
|
infos.Insert(0, info);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < infos.Count; i++)
|
|
{
|
|
FishInfo info = infos[i];
|
|
|
|
double baitStr = info.GetBaitStrength(bait, from, enhanced);
|
|
|
|
if ((info.RequiresDeepWater && !IsDeepWater(pnt, map, reg)) || skill < info.MinSkill)
|
|
continue;
|
|
|
|
if (fishing && info.Type.IsSubclassOf(typeof(BaseCrabAndLobster)))
|
|
continue;
|
|
|
|
if (!fishing && !info.Type.IsSubclassOf(typeof(BaseCrabAndLobster)))
|
|
continue;
|
|
|
|
if (info.Location is string)
|
|
{
|
|
string loc = (string)info.Location;
|
|
|
|
if (loc.ToLower() == "cannotfishup")
|
|
continue;
|
|
|
|
if (loc.ToLower() == "t2a" && Server.Spells.SpellHelper.IsAnyT2A(map, fromLoc) && info.Roll(from, baitStr, bump))
|
|
item = info.Type;
|
|
|
|
if (loc.ToLower() == "trammelandfelucca" && (map == Map.Trammel || map == Map.Felucca) && !Server.Spells.SpellHelper.IsAnyT2A(map, fromLoc) && info.Roll(from, baitStr, bump))
|
|
item = info.Type;
|
|
|
|
if (loc.ToLower() == "fire island" && IsFireIsland(fromLoc, map) && info.Roll(from, baitStr, bump))
|
|
item = info.Type;
|
|
|
|
if (loc.ToLower() == "gravewater lake" && IsGravewaterLake(fromLoc, map))
|
|
item = info.Type;
|
|
|
|
if (from.Region != null && from.Region.IsPartOf(loc) && info.Roll(from, baitStr, bump))
|
|
item = info.Type;
|
|
|
|
}
|
|
else if (info.Location is Map)
|
|
{
|
|
Map locMap = (Map)info.Location;
|
|
|
|
if (map == locMap && info.Roll(from, baitStr, bump))
|
|
item = info.Type;
|
|
}
|
|
}
|
|
|
|
ColUtility.Free(infos);
|
|
|
|
if (!rareOnly && item == null && from is PlayerMobile)
|
|
{
|
|
double chance = skill / 121.5;
|
|
|
|
bool dungeon = IsDungeon(pnt, map, reg);
|
|
bool shore = IsShore(pnt, map, reg);
|
|
bool deep = IsDeepWater(pnt, map, reg);
|
|
|
|
if (fishing && chance >= Utility.RandomDouble())
|
|
{
|
|
if (dungeon && skill >= 106.0)
|
|
item = BaseHighseasFish.DungeonFish[Utility.Random(BaseHighseasFish.DungeonFish.Length)];
|
|
else if (deep && skill >= 80.0)
|
|
item = BaseHighseasFish.DeepWaterFish[Utility.Random(BaseHighseasFish.DeepWaterFish.Length)];
|
|
else if(shore && skill >= 50.0)
|
|
item = BaseHighseasFish.ShoreFish[Utility.Random(BaseHighseasFish.ShoreFish.Length)];
|
|
}
|
|
else if (skill >= 50.0 && !fishing && chance >= Utility.RandomDouble())
|
|
{
|
|
item = BaseHighseasFish.LobstersAndCrabs[Utility.Random(BaseHighseasFish.LobstersAndCrabs.Length)];
|
|
}
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
public double GetBaitStrength(Type baitType, Mobile from, bool enhanced)
|
|
{
|
|
if (baitType != this.Type)
|
|
return 1.0;
|
|
|
|
double str = enhanced ? 3.0 : 2.0;
|
|
|
|
for (int i = 0; i < from.Items.Count; i++)
|
|
{
|
|
Item item = from.Items[i];
|
|
if (item is IFishingAttire)
|
|
{
|
|
if (item is ISetItem)
|
|
{
|
|
if (((ISetItem)item).SetEquipped)
|
|
{
|
|
str += ((double)((IFishingAttire)item).SetBonus / 100) / (double)((ISetItem)item).Pieces;
|
|
}
|
|
else
|
|
{
|
|
str += (double)((IFishingAttire)item).BaitBonus / 100;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
str += (double)((IFishingAttire)item).BaitBonus / 100;
|
|
}
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
public bool Roll(Mobile from, double baitStr, double bump)
|
|
{
|
|
double baseChance = MagicalFishFinder.HasSchool(from) ? BaseChance * 10 : BaseChance;
|
|
|
|
return (baseChance + bump) * baitStr > Utility.RandomDouble();
|
|
}
|
|
|
|
public static bool IsDeepWater(Point3D pnt, Map map, Region region)
|
|
{
|
|
return SpecialFishingNet.FullValidation(map, pnt.X, pnt.Y) && !IsDungeon(pnt, map, region);
|
|
}
|
|
|
|
public static bool IsShore(Point3D pnt, Map map, Region region)
|
|
{
|
|
return !IsDeepWater(pnt, map, region) && !IsDungeon(pnt, map, region);
|
|
}
|
|
|
|
public static bool IsDungeon(Point3D pnt, Map map, Region region)
|
|
{
|
|
return region.IsPartOf<DungeonRegion>() || IsMondainDungeon(region) || Server.Spells.SpellHelper.IsTrammelWind(map, pnt) || Server.Spells.SpellHelper.IsFeluccaWind(map, pnt);
|
|
}
|
|
|
|
public static bool IsMondainDungeon(Region region)
|
|
{
|
|
if (region.IsPartOf("Twisted Weald"))
|
|
return true;
|
|
if (region.IsPartOf("Sanctuary"))
|
|
return true;
|
|
if (region.IsPartOf("Prism of Light"))
|
|
return true;
|
|
if (region.IsPartOf("Citadel"))
|
|
return true;
|
|
if (region.IsPartOf("Bedlam"))
|
|
return true;
|
|
if (region.IsPartOf("Blighted Grove"))
|
|
return true;
|
|
if (region.IsPartOf("Painted Caves"))
|
|
return true;
|
|
if (region.IsPartOf("Palace of Paroxysmus"))
|
|
return true;
|
|
if (region.IsPartOf("Labyrinth"))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
public static bool IsFireIsland(Point3D p, Map map)
|
|
{
|
|
return (map == Map.Felucca || map == Map.Trammel) && (p.X > 4559 && p.X < 4636 && p.Y > 3548 && p.Y < 3627
|
|
|| p.X > 4465 && p.X < 4493 && p.Y > 4479 && p.Y < 3746);
|
|
}
|
|
|
|
public static bool IsGravewaterLake(Point3D p, Map map)
|
|
{
|
|
return map == Map.Malas && ((p.X >= 1440 && p.X <= 1863 && p.Y >= 1527 && p.Y <= 1746) || (p.X >= 1381 && p.X <= 1596 && p.Y >= 1565 && p.Y <= 1789));
|
|
}
|
|
|
|
public static Type[] SOSArtifacts { get { return m_SOSArtifacts; } }
|
|
private static Type[] m_SOSArtifacts = new Type[]
|
|
{
|
|
typeof(AntiqueWeddingDress), typeof(GrapeVine),
|
|
typeof(KelpWovenLeggings), typeof(LargeFishingNet),
|
|
typeof(RunedDriftwoodBow), typeof(ValkyrieArmor)
|
|
};
|
|
|
|
}
|
|
}
|