Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
70
Scripts/Services/Harvest/Core/BonusHarvestResource.cs
Normal file
70
Scripts/Services/Harvest/Core/BonusHarvestResource.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Engines.Harvest
|
||||
{
|
||||
public class BonusHarvestResource
|
||||
{
|
||||
private readonly TextDefinition m_SuccessMessage;
|
||||
private Type m_Type;
|
||||
private double m_ReqSkill, m_Chance;
|
||||
public BonusHarvestResource(double reqSkill, double chance, TextDefinition message, Type type)
|
||||
: this(reqSkill, chance, message, type, null)
|
||||
{ }
|
||||
public BonusHarvestResource(double reqSkill, double chance, TextDefinition message, Type type, Map requiredMap)
|
||||
{
|
||||
this.m_ReqSkill = reqSkill;
|
||||
|
||||
this.m_Chance = chance;
|
||||
this.m_Type = type;
|
||||
this.m_SuccessMessage = message;
|
||||
RequiredMap = requiredMap;
|
||||
}
|
||||
|
||||
public Map RequiredMap { get; private set; }
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Type;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Type = value;
|
||||
}
|
||||
}
|
||||
public double ReqSkill
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_ReqSkill;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_ReqSkill = value;
|
||||
}
|
||||
}
|
||||
public double Chance
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Chance;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Chance = value;
|
||||
}
|
||||
}
|
||||
public TextDefinition SuccessMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_SuccessMessage;
|
||||
}
|
||||
}
|
||||
public void SendSuccessTo(Mobile m)
|
||||
{
|
||||
TextDefinition.SendMessageTo(m, this.m_SuccessMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
99
Scripts/Services/Harvest/Core/HarvestBank.cs
Normal file
99
Scripts/Services/Harvest/Core/HarvestBank.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Engines.Harvest
|
||||
{
|
||||
public class HarvestBank
|
||||
{
|
||||
private readonly int m_Maximum;
|
||||
readonly HarvestDefinition m_Definition;
|
||||
private int m_Current;
|
||||
private DateTime m_NextRespawn;
|
||||
private HarvestVein m_Vein, m_DefaultVein;
|
||||
public HarvestBank(HarvestDefinition def, HarvestVein defaultVein)
|
||||
{
|
||||
this.m_Maximum = Utility.RandomMinMax(def.MinTotal, def.MaxTotal);
|
||||
this.m_Current = this.m_Maximum;
|
||||
this.m_DefaultVein = defaultVein;
|
||||
this.m_Vein = this.m_DefaultVein;
|
||||
|
||||
this.m_Definition = def;
|
||||
}
|
||||
|
||||
public HarvestDefinition Definition
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Definition;
|
||||
}
|
||||
}
|
||||
public int Current
|
||||
{
|
||||
get
|
||||
{
|
||||
this.CheckRespawn();
|
||||
return this.m_Current;
|
||||
}
|
||||
}
|
||||
public HarvestVein Vein
|
||||
{
|
||||
get
|
||||
{
|
||||
this.CheckRespawn();
|
||||
return this.m_Vein;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.m_Vein = value;
|
||||
}
|
||||
}
|
||||
public HarvestVein DefaultVein
|
||||
{
|
||||
get
|
||||
{
|
||||
this.CheckRespawn();
|
||||
return this.m_DefaultVein;
|
||||
}
|
||||
}
|
||||
public void CheckRespawn()
|
||||
{
|
||||
if (this.m_Current == this.m_Maximum || this.m_NextRespawn > DateTime.UtcNow)
|
||||
return;
|
||||
|
||||
this.m_Current = this.m_Maximum;
|
||||
|
||||
if (this.m_Definition.RandomizeVeins)
|
||||
{
|
||||
this.m_DefaultVein = this.m_Definition.GetVeinFrom(Utility.RandomDouble());
|
||||
}
|
||||
|
||||
this.m_Vein = this.m_DefaultVein;
|
||||
}
|
||||
|
||||
public void Consume(int amount, Mobile from)
|
||||
{
|
||||
this.CheckRespawn();
|
||||
|
||||
if (this.m_Current == this.m_Maximum)
|
||||
{
|
||||
double min = this.m_Definition.MinRespawn.TotalMinutes;
|
||||
double max = this.m_Definition.MaxRespawn.TotalMinutes;
|
||||
double rnd = Utility.RandomDouble();
|
||||
|
||||
this.m_Current = this.m_Maximum - amount;
|
||||
|
||||
double minutes = min + (rnd * (max - min));
|
||||
if (this.m_Definition.RaceBonus && from.Race == Race.Elf) //def.RaceBonus = Core.ML
|
||||
minutes *= .75; //25% off the time.
|
||||
|
||||
this.m_NextRespawn = DateTime.UtcNow + TimeSpan.FromMinutes(minutes);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_Current -= amount;
|
||||
}
|
||||
|
||||
if (this.m_Current < 0)
|
||||
this.m_Current = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
171
Scripts/Services/Harvest/Core/HarvestDefinition.cs
Normal file
171
Scripts/Services/Harvest/Core/HarvestDefinition.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Server.Engines.Harvest
|
||||
{
|
||||
public class HarvestDefinition
|
||||
{
|
||||
public HarvestDefinition()
|
||||
{
|
||||
Banks = new Dictionary<Map, Dictionary<Point2D, HarvestBank>>();
|
||||
}
|
||||
|
||||
public int BankWidth { get; set; }
|
||||
public int BankHeight { get; set; }
|
||||
public int MinTotal { get; set; }
|
||||
public int MaxTotal { get; set; }
|
||||
public int[] Tiles { get; set; }
|
||||
public int[] SpecialTiles { get; set; }
|
||||
public bool RangedTiles { get; set; }
|
||||
public TimeSpan MinRespawn { get; set; }
|
||||
public TimeSpan MaxRespawn { get; set; }
|
||||
public int MaxRange { get; set; }
|
||||
public int ConsumedPerHarvest { get; set; }
|
||||
public int ConsumedPerFeluccaHarvest { get; set; }
|
||||
public bool PlaceAtFeetIfFull { get; set; }
|
||||
public SkillName Skill { get; set; }
|
||||
public int[] EffectActions { get; set; }
|
||||
public int[] EffectCounts { get; set; }
|
||||
public int[] EffectSounds { get; set; }
|
||||
public TimeSpan EffectSoundDelay { get; set; }
|
||||
public TimeSpan EffectDelay { get; set; }
|
||||
public object NoResourcesMessage { get; set; }
|
||||
public object OutOfRangeMessage { get; set; }
|
||||
public object TimedOutOfRangeMessage { get; set; }
|
||||
public object DoubleHarvestMessage { get; set; }
|
||||
public object FailMessage { get; set; }
|
||||
public object PackFullMessage { get; set; }
|
||||
public object ToolBrokeMessage { get; set; }
|
||||
public HarvestResource[] Resources { get; set; }
|
||||
public HarvestVein[] Veins { get; set; }
|
||||
public BonusHarvestResource[] BonusResources { get; set; }
|
||||
public bool RaceBonus { get; set; }
|
||||
public bool RandomizeVeins { get; set; }
|
||||
public Dictionary<Map, Dictionary<Point2D, HarvestBank>> Banks { get; set; }
|
||||
|
||||
public void SendMessageTo(Mobile from, object message)
|
||||
{
|
||||
if (message is int)
|
||||
from.SendLocalizedMessage((int)message);
|
||||
else if (message is string)
|
||||
from.SendMessage((string)message);
|
||||
}
|
||||
|
||||
public HarvestBank GetBank(Map map, int x, int y)
|
||||
{
|
||||
if (map == null || map == Map.Internal)
|
||||
return null;
|
||||
|
||||
x /= BankWidth;
|
||||
y /= BankHeight;
|
||||
|
||||
Banks.TryGetValue(map, out Dictionary<Point2D, HarvestBank> banks);
|
||||
|
||||
if (banks == null)
|
||||
Banks[map] = banks = new Dictionary<Point2D, HarvestBank>();
|
||||
|
||||
Point2D key = new Point2D(x, y);
|
||||
banks.TryGetValue(key, out HarvestBank bank);
|
||||
|
||||
if (bank == null)
|
||||
banks[key] = bank = new HarvestBank(this, GetVeinAt(map, x, y));
|
||||
|
||||
return bank;
|
||||
}
|
||||
|
||||
public HarvestVein GetVeinAt(Map map, int x, int y)
|
||||
{
|
||||
if (Veins.Length == 1)
|
||||
return Veins[0];
|
||||
|
||||
double randomValue;
|
||||
|
||||
if (RandomizeVeins)
|
||||
{
|
||||
randomValue = Utility.RandomDouble();
|
||||
}
|
||||
else
|
||||
{
|
||||
Random random = new Random((x * 17) + (y * 11) + (map.MapID * 3));
|
||||
randomValue = random.NextDouble();
|
||||
}
|
||||
|
||||
return GetVeinFrom(randomValue);
|
||||
}
|
||||
|
||||
public HarvestVein GetVeinFrom(double randomValue)
|
||||
{
|
||||
if (Veins.Length == 1)
|
||||
return Veins[0];
|
||||
|
||||
randomValue *= 100;
|
||||
|
||||
for (int i = 0; i < Veins.Length; ++i)
|
||||
{
|
||||
if (randomValue <= Veins[i].VeinChance)
|
||||
return Veins[i];
|
||||
|
||||
randomValue -= Veins[i].VeinChance;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public BonusHarvestResource GetBonusResource()
|
||||
{
|
||||
if (BonusResources == null)
|
||||
return null;
|
||||
|
||||
double randomValue = Utility.RandomDouble() * 100;
|
||||
|
||||
for (int i = 0; i < BonusResources.Length; ++i)
|
||||
{
|
||||
if (randomValue <= BonusResources[i].Chance)
|
||||
return BonusResources[i];
|
||||
|
||||
randomValue -= BonusResources[i].Chance;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool Validate(int tileID)
|
||||
{
|
||||
if (RangedTiles)
|
||||
{
|
||||
bool contains = false;
|
||||
|
||||
for (int i = 0; !contains && i < Tiles.Length; i += 2)
|
||||
contains = tileID >= Tiles[i] && tileID <= Tiles[i + 1];
|
||||
|
||||
return contains;
|
||||
}
|
||||
else
|
||||
{
|
||||
int dist = -1;
|
||||
|
||||
for (int i = 0; dist < 0 && i < Tiles.Length; ++i)
|
||||
dist = Tiles[i] - tileID;
|
||||
|
||||
return dist == 0;
|
||||
}
|
||||
}
|
||||
|
||||
#region High Seas
|
||||
public bool ValidateSpecial(int tileID)
|
||||
{
|
||||
//No Special tiles were initiated so always true
|
||||
if (SpecialTiles == null || SpecialTiles.Length == 0)
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < SpecialTiles.Length; i++)
|
||||
{
|
||||
if (tileID == SpecialTiles[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
30
Scripts/Services/Harvest/Core/HarvestResource.cs
Normal file
30
Scripts/Services/Harvest/Core/HarvestResource.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Engines.Harvest
|
||||
{
|
||||
public class HarvestResource
|
||||
{
|
||||
public HarvestResource(double reqSkill, double minSkill, double maxSkill, object message, params Type[] types)
|
||||
{
|
||||
ReqSkill = reqSkill;
|
||||
MinSkill = minSkill;
|
||||
MaxSkill = maxSkill;
|
||||
Types = types;
|
||||
SuccessMessage = message;
|
||||
}
|
||||
|
||||
public Type[] Types { get; set; }
|
||||
public double ReqSkill { get; set; }
|
||||
public double MinSkill { get; set; }
|
||||
public double MaxSkill { get; set; }
|
||||
public object SuccessMessage { get; }
|
||||
|
||||
public void SendSuccessTo(Mobile m)
|
||||
{
|
||||
if (SuccessMessage is int)
|
||||
m.SendLocalizedMessage((int)SuccessMessage);
|
||||
else if (SuccessMessage is string)
|
||||
m.SendMessage((string)SuccessMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Scripts/Services/Harvest/Core/HarvestSoundTimer.cs
Normal file
34
Scripts/Services/Harvest/Core/HarvestSoundTimer.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Engines.Harvest
|
||||
{
|
||||
public class HarvestSoundTimer : Timer
|
||||
{
|
||||
private readonly Mobile m_From;
|
||||
private readonly Item m_Tool;
|
||||
private readonly HarvestSystem m_System;
|
||||
private readonly HarvestDefinition m_Definition;
|
||||
private readonly object m_ToHarvest;
|
||||
private readonly object m_Locked;
|
||||
private readonly bool m_Last;
|
||||
public HarvestSoundTimer(Mobile from, Item tool, HarvestSystem system, HarvestDefinition def, object toHarvest, object locked, bool last)
|
||||
: base(def.EffectSoundDelay)
|
||||
{
|
||||
this.m_From = from;
|
||||
this.m_Tool = tool;
|
||||
this.m_System = system;
|
||||
this.m_Definition = def;
|
||||
this.m_ToHarvest = toHarvest;
|
||||
this.m_Locked = locked;
|
||||
this.m_Last = last;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
this.m_System.DoHarvestingSound(this.m_From, this.m_Tool, this.m_Definition, this.m_ToHarvest);
|
||||
|
||||
if (this.m_Last)
|
||||
this.m_System.FinishHarvesting(this.m_From, this.m_Tool, this.m_Definition, this.m_ToHarvest, this.m_Locked);
|
||||
}
|
||||
}
|
||||
}
|
||||
130
Scripts/Services/Harvest/Core/HarvestTarget.cs
Normal file
130
Scripts/Services/Harvest/Core/HarvestTarget.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using Server.Engines.Quests;
|
||||
using Server.Engines.Quests.Hag;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Engines.Harvest
|
||||
{
|
||||
public class HarvestTarget : Target
|
||||
{
|
||||
private readonly Item m_Tool;
|
||||
private readonly HarvestSystem m_System;
|
||||
|
||||
public HarvestTarget(Item tool, HarvestSystem system)
|
||||
: base(-1, true, TargetFlags.None)
|
||||
{
|
||||
m_Tool = tool;
|
||||
m_System = system;
|
||||
|
||||
DisallowMultis = true;
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
if (m_System is Mining)
|
||||
{
|
||||
if (targeted is StaticTarget)
|
||||
{
|
||||
int itemID = ((StaticTarget)targeted).ItemID;
|
||||
|
||||
// grave
|
||||
if (itemID == 0xED3 || itemID == 0xEDF || itemID == 0xEE0 || itemID == 0xEE1 || itemID == 0xEE2 || itemID == 0xEE8)
|
||||
{
|
||||
PlayerMobile player = from as PlayerMobile;
|
||||
|
||||
if (player != null)
|
||||
{
|
||||
QuestSystem qs = player.Quest;
|
||||
|
||||
if (qs is WitchApprenticeQuest)
|
||||
{
|
||||
FindIngredientObjective obj = qs.FindObjective(typeof(FindIngredientObjective)) as FindIngredientObjective;
|
||||
|
||||
if (obj != null && !obj.Completed && obj.Ingredient == Ingredient.Bones)
|
||||
{
|
||||
player.SendLocalizedMessage(1055037); // You finish your grim work, finding some of the specific bones listed in the Hag's recipe.
|
||||
obj.Complete();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (targeted is LandTarget && ((LandTarget)targeted).TileID >= 113 && ((LandTarget)targeted).TileID <= 120)
|
||||
{
|
||||
if (Server.Engines.Quests.TheGreatVolcanoQuest.OnHarvest(from, m_Tool))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_System is Lumberjacking && targeted is IChopable)
|
||||
((IChopable)targeted).OnChop(from);
|
||||
else if (m_System is Lumberjacking && targeted is IAxe && m_Tool is BaseAxe)
|
||||
{
|
||||
IAxe obj = (IAxe)targeted;
|
||||
Item item = (Item)targeted;
|
||||
|
||||
if (!item.IsChildOf(from.Backpack))
|
||||
from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used.
|
||||
else if (obj.Axe(from, (BaseAxe)m_Tool))
|
||||
from.PlaySound(0x13E);
|
||||
}
|
||||
else if (m_System is Lumberjacking && targeted is ICarvable)
|
||||
((ICarvable)targeted).Carve(from, (Item)m_Tool);
|
||||
else if (m_System is Lumberjacking && FurnitureAttribute.Check(targeted as Item))
|
||||
DestroyFurniture(from, (Item)targeted);
|
||||
else if (m_System is Mining && targeted is TreasureMap)
|
||||
((TreasureMap)targeted).OnBeginDig(from);
|
||||
#region High Seas
|
||||
else if (m_System is Mining && targeted is NiterDeposit)
|
||||
((NiterDeposit)targeted).OnMine(from, m_Tool);
|
||||
else if (m_System is Lumberjacking && targeted is CrackedLavaRockEast)
|
||||
((CrackedLavaRockEast)targeted).OnCrack(from);
|
||||
else if (m_System is Lumberjacking && targeted is CrackedLavaRockSouth)
|
||||
((CrackedLavaRockSouth)targeted).OnCrack(from);
|
||||
#endregion
|
||||
else
|
||||
{
|
||||
// If we got here and we're lumberjacking then we didn't target something that can be done from the pack
|
||||
if (m_System is Lumberjacking && m_Tool.Parent != from)
|
||||
{
|
||||
from.SendLocalizedMessage(500487); // The axe must be equipped for any serious wood chopping.
|
||||
return;
|
||||
}
|
||||
m_System.StartHarvesting(from, m_Tool, targeted);
|
||||
}
|
||||
}
|
||||
|
||||
private void DestroyFurniture(Mobile from, Item item)
|
||||
{
|
||||
if (!from.InRange(item.GetWorldLocation(), 3))
|
||||
{
|
||||
from.SendLocalizedMessage(500446); // That is too far away.
|
||||
return;
|
||||
}
|
||||
else if (!item.IsChildOf(from.Backpack) && !item.Movable)
|
||||
{
|
||||
from.SendLocalizedMessage(500462); // You can't destroy that while it is here.
|
||||
return;
|
||||
}
|
||||
|
||||
from.SendLocalizedMessage(500461); // You destroy the item.
|
||||
Effects.PlaySound(item.GetWorldLocation(), item.Map, 0x3B3);
|
||||
|
||||
if (item is Container)
|
||||
{
|
||||
if (item is TrapableContainer)
|
||||
(item as TrapableContainer).ExecuteTrap(from);
|
||||
|
||||
((Container)item).Destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Scripts/Services/Harvest/Core/HarvestTimer.cs
Normal file
33
Scripts/Services/Harvest/Core/HarvestTimer.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Engines.Harvest
|
||||
{
|
||||
public class HarvestTimer : Timer
|
||||
{
|
||||
private readonly Mobile m_From;
|
||||
private readonly Item m_Tool;
|
||||
private readonly HarvestSystem m_System;
|
||||
private readonly HarvestDefinition m_Definition;
|
||||
private readonly object m_ToHarvest;
|
||||
private readonly object m_Locked;
|
||||
private readonly int m_Count;
|
||||
private int m_Index;
|
||||
public HarvestTimer(Mobile from, Item tool, HarvestSystem system, HarvestDefinition def, object toHarvest, object locked)
|
||||
: base(TimeSpan.Zero, def.EffectDelay)
|
||||
{
|
||||
this.m_From = from;
|
||||
this.m_Tool = tool;
|
||||
this.m_System = system;
|
||||
this.m_Definition = def;
|
||||
this.m_ToHarvest = toHarvest;
|
||||
this.m_Locked = locked;
|
||||
this.m_Count = Utility.RandomList(def.EffectCounts);
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (!this.m_System.OnHarvesting(this.m_From, this.m_Tool, this.m_Definition, this.m_ToHarvest, this.m_Locked, ++this.m_Index == this.m_Count))
|
||||
this.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Scripts/Services/Harvest/Core/HarvestVein.cs
Normal file
20
Scripts/Services/Harvest/Core/HarvestVein.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace Server.Engines.Harvest
|
||||
{
|
||||
public class HarvestVein
|
||||
{
|
||||
public HarvestVein(double veinChance, double chanceToFallback, HarvestResource primaryResource, HarvestResource fallbackResource)
|
||||
{
|
||||
VeinChance = veinChance;
|
||||
ChanceToFallback = chanceToFallback;
|
||||
PrimaryResource = primaryResource;
|
||||
FallbackResource = fallbackResource;
|
||||
}
|
||||
|
||||
public double VeinChance { get; set; }
|
||||
public double ChanceToFallback { get; set; }
|
||||
public HarvestResource PrimaryResource { get; set; }
|
||||
public HarvestResource FallbackResource { get; set; }
|
||||
}
|
||||
}
|
||||
1086
Scripts/Services/Harvest/Fishing.cs
Normal file
1086
Scripts/Services/Harvest/Fishing.cs
Normal file
File diff suppressed because it is too large
Load Diff
784
Scripts/Services/Harvest/HarvestSystem.cs
Normal file
784
Scripts/Services/Harvest/HarvestSystem.cs
Normal file
@@ -0,0 +1,784 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Items;
|
||||
using Server.Targeting;
|
||||
using Server.Engines.Quests;
|
||||
using Server.Engines.Quests.Hag;
|
||||
using Server.Mobiles;
|
||||
using System.Linq;
|
||||
|
||||
namespace Server.Engines.Harvest
|
||||
{
|
||||
public abstract class HarvestSystem
|
||||
{
|
||||
public static void Configure()
|
||||
{
|
||||
EventSink.TargetByResourceMacro += TargetByResource;
|
||||
}
|
||||
|
||||
public HarvestSystem()
|
||||
{
|
||||
Definitions = new List<HarvestDefinition>();
|
||||
}
|
||||
|
||||
public List<HarvestDefinition> Definitions { get; }
|
||||
|
||||
public virtual bool CheckTool(Mobile from, Item tool)
|
||||
{
|
||||
bool wornOut = tool == null || tool.Deleted || (tool is IUsesRemaining && ((IUsesRemaining)tool).UsesRemaining <= 0);
|
||||
|
||||
if (wornOut)
|
||||
from.SendLocalizedMessage(1044038); // You have worn out your tool!
|
||||
|
||||
return !wornOut;
|
||||
}
|
||||
|
||||
public virtual bool CheckHarvest(Mobile from, Item tool)
|
||||
{
|
||||
return CheckTool(from, tool);
|
||||
}
|
||||
|
||||
public virtual bool CheckHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
|
||||
{
|
||||
return CheckTool(from, tool);
|
||||
}
|
||||
|
||||
public virtual bool CheckRange(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed)
|
||||
{
|
||||
bool inRange = from.Map == map && from.InRange(loc, def.MaxRange);
|
||||
|
||||
if (!inRange)
|
||||
def.SendMessageTo(from, timed ? def.TimedOutOfRangeMessage : def.OutOfRangeMessage);
|
||||
|
||||
return inRange;
|
||||
}
|
||||
|
||||
public virtual bool CheckResources(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed)
|
||||
{
|
||||
HarvestBank bank = def.GetBank(map, loc.X, loc.Y);
|
||||
bool available = bank != null && bank.Current >= def.ConsumedPerHarvest;
|
||||
|
||||
if (!available)
|
||||
def.SendMessageTo(from, timed ? def.DoubleHarvestMessage : def.NoResourcesMessage);
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
public virtual void OnBadHarvestTarget(Mobile from, Item tool, object toHarvest)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual object GetLock(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
|
||||
{
|
||||
/* Here we prevent multiple harvesting.
|
||||
*
|
||||
* Some options:
|
||||
* - 'return tool;' : This will allow the player to harvest more than once concurrently, but only if they use multiple tools. This seems to be as OSI.
|
||||
* - 'return GetType();' : This will disallow multiple harvesting of the same type. That is, we couldn't mine more than once concurrently, but we could be both mining and lumberjacking.
|
||||
* - 'return typeof( HarvestSystem );' : This will completely restrict concurrent harvesting.
|
||||
*/
|
||||
return tool;
|
||||
}
|
||||
|
||||
public virtual void OnConcurrentHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool BeginHarvesting(Mobile from, Item tool)
|
||||
{
|
||||
if (!CheckHarvest(from, tool))
|
||||
return false;
|
||||
|
||||
EventSink.InvokeResourceHarvestAttempt(new ResourceHarvestAttemptEventArgs(from, tool, this));
|
||||
from.Target = new HarvestTarget(tool, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void FinishHarvesting(Mobile from, Item tool, HarvestDefinition def, object toHarvest, object locked)
|
||||
{
|
||||
from.EndAction(locked);
|
||||
|
||||
if (!CheckHarvest(from, tool))
|
||||
return;
|
||||
|
||||
if (!GetHarvestDetails(from, tool, toHarvest, out int tileID, out Map map, out Point3D 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;
|
||||
|
||||
if (SpecialHarvest(from, tool, def, map, loc))
|
||||
return;
|
||||
|
||||
HarvestBank bank = def.GetBank(map, loc.X, loc.Y);
|
||||
|
||||
if (bank == null)
|
||||
return;
|
||||
|
||||
HarvestVein vein = bank.Vein;
|
||||
|
||||
if (vein != null)
|
||||
vein = MutateVein(from, tool, def, bank, toHarvest, vein);
|
||||
|
||||
if (vein == null)
|
||||
return;
|
||||
|
||||
HarvestResource primary = vein.PrimaryResource;
|
||||
HarvestResource fallback = vein.FallbackResource;
|
||||
HarvestResource resource = MutateResource(from, tool, def, map, loc, vein, primary, fallback);
|
||||
|
||||
double skillBase = from.Skills[def.Skill].Base;
|
||||
|
||||
Type type = null;
|
||||
|
||||
if(CheckHarvestSkill(map, loc, from, resource, def))
|
||||
{
|
||||
type = GetResourceType(from, tool, def, map, loc, resource);
|
||||
|
||||
if (type != null)
|
||||
type = MutateType(type, from, tool, def, map, loc, resource);
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
Item item = Construct(type, from, tool);
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
type = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
int amount = def.ConsumedPerHarvest;
|
||||
int feluccaAmount = def.ConsumedPerFeluccaHarvest;
|
||||
|
||||
if (item is BaseGranite)
|
||||
feluccaAmount = 3;
|
||||
|
||||
Caddellite.OnHarvest(from, tool, this, item);
|
||||
|
||||
//The whole harvest system is kludgy and I'm sure this is just adding to it.
|
||||
if (item.Stackable)
|
||||
{
|
||||
int racialAmount = (int)Math.Ceiling(amount * 1.1);
|
||||
int feluccaRacialAmount = (int)Math.Ceiling(feluccaAmount * 1.1);
|
||||
|
||||
bool eligableForRacialBonus = (def.RaceBonus && from.Race == Race.Human);
|
||||
bool inFelucca = map == Map.Felucca && !Siege.SiegeShard;
|
||||
|
||||
if (eligableForRacialBonus && inFelucca && bank.Current >= feluccaRacialAmount && 0.1 > Utility.RandomDouble())
|
||||
item.Amount = feluccaRacialAmount;
|
||||
else if (inFelucca && bank.Current >= feluccaAmount)
|
||||
item.Amount = feluccaAmount;
|
||||
else if (eligableForRacialBonus && bank.Current >= racialAmount && 0.1 > Utility.RandomDouble())
|
||||
item.Amount = racialAmount;
|
||||
else
|
||||
item.Amount = amount;
|
||||
|
||||
// Void Pool Rewards
|
||||
item.Amount += WoodsmansTalisman.CheckHarvest(from, type, this);
|
||||
}
|
||||
|
||||
if (from.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
bank.Consume(amount, from);
|
||||
}
|
||||
|
||||
if (Give(from, item, def.PlaceAtFeetIfFull))
|
||||
{
|
||||
SendSuccessTo(from, item, resource);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendPackFullTo(from, item, def, resource);
|
||||
item.Delete();
|
||||
}
|
||||
|
||||
BonusHarvestResource bonus = def.GetBonusResource();
|
||||
Item bonusItem = null;
|
||||
|
||||
if (bonus != null && bonus.Type != null && skillBase >= bonus.ReqSkill)
|
||||
{
|
||||
if (bonus.RequiredMap == null || bonus.RequiredMap == from.Map)
|
||||
{
|
||||
bonusItem = Construct(bonus.Type, from, tool);
|
||||
Caddellite.OnHarvest(from, tool, this, bonusItem);
|
||||
|
||||
if (Give(from, bonusItem, true)) //Bonuses always allow placing at feet, even if pack is full irregrdless of def
|
||||
{
|
||||
bonus.SendSuccessTo(from);
|
||||
}
|
||||
else
|
||||
{
|
||||
bonusItem.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EventSink.InvokeResourceHarvestSuccess(new ResourceHarvestSuccessEventArgs(from, tool, item, bonusItem, this));
|
||||
}
|
||||
|
||||
#region High Seas
|
||||
OnToolUsed(from, tool, item != null);
|
||||
#endregion
|
||||
}
|
||||
|
||||
// Siege rules will take into account axes and polearms used for lumberjacking
|
||||
if (tool is IUsesRemaining && (tool is BaseHarvestTool || tool is Pickaxe || tool is SturdyPickaxe || tool is GargoylesPickaxe || Siege.SiegeShard))
|
||||
{
|
||||
IUsesRemaining toolWithUses = (IUsesRemaining)tool;
|
||||
|
||||
toolWithUses.ShowUsesRemaining = true;
|
||||
|
||||
if (toolWithUses.UsesRemaining > 0)
|
||||
--toolWithUses.UsesRemaining;
|
||||
|
||||
if (toolWithUses.UsesRemaining < 1)
|
||||
{
|
||||
tool.Delete();
|
||||
def.SendMessageTo(from, def.ToolBrokeMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == null)
|
||||
def.SendMessageTo(from, def.FailMessage);
|
||||
|
||||
OnHarvestFinished(from, tool, def, vein, bank, resource, toHarvest);
|
||||
}
|
||||
|
||||
public virtual bool CheckHarvestSkill(Map map, Point3D loc, Mobile from, HarvestResource resource, HarvestDefinition def)
|
||||
{
|
||||
return from.Skills[def.Skill].Value >= resource.ReqSkill && from.CheckSkill(def.Skill, resource.MinSkill, resource.MaxSkill);
|
||||
}
|
||||
|
||||
public virtual void OnToolUsed(Mobile from, Item tool, bool caughtSomething)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnHarvestFinished(Mobile from, Item tool, HarvestDefinition def, HarvestVein vein, HarvestBank bank, HarvestResource resource, object harvested)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool SpecialHarvest(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual Item Construct(Type type, Mobile from, Item tool)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Activator.CreateInstance(type) as Item;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual HarvestVein MutateVein(Mobile from, Item tool, HarvestDefinition def, HarvestBank bank, object toHarvest, HarvestVein vein)
|
||||
{
|
||||
return vein;
|
||||
}
|
||||
|
||||
public virtual void SendSuccessTo(Mobile from, Item item, HarvestResource resource)
|
||||
{
|
||||
resource.SendSuccessTo(from);
|
||||
}
|
||||
|
||||
public virtual void SendPackFullTo(Mobile from, Item item, HarvestDefinition def, HarvestResource resource)
|
||||
{
|
||||
def.SendMessageTo(from, def.PackFullMessage);
|
||||
}
|
||||
|
||||
public virtual bool Give(Mobile m, Item item, bool placeAtFeet)
|
||||
{
|
||||
if (m.PlaceInBackpack(item))
|
||||
return true;
|
||||
|
||||
if (!placeAtFeet)
|
||||
return false;
|
||||
|
||||
Map map = m.Map;
|
||||
|
||||
if (map == null || map == Map.Internal)
|
||||
return false;
|
||||
|
||||
List<Item> atFeet = new List<Item>();
|
||||
|
||||
IPooledEnumerable eable = m.GetItemsInRange(0);
|
||||
|
||||
foreach (Item obj in eable)
|
||||
atFeet.Add(obj);
|
||||
|
||||
eable.Free();
|
||||
|
||||
for (int i = 0; i < atFeet.Count; ++i)
|
||||
{
|
||||
Item check = atFeet[i];
|
||||
|
||||
if (check.StackWith(m, item, false))
|
||||
return true;
|
||||
}
|
||||
|
||||
ColUtility.Free(atFeet);
|
||||
|
||||
item.MoveToWorld(m.Location, map);
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual Type MutateType(Type type, Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, HarvestResource resource)
|
||||
{
|
||||
return from.Region.GetResource(type);
|
||||
}
|
||||
|
||||
public virtual Type GetResourceType(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, HarvestResource resource)
|
||||
{
|
||||
if (resource.Types.Length > 0)
|
||||
return resource.Types[Utility.Random(resource.Types.Length)];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual HarvestResource MutateResource(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, HarvestVein vein, HarvestResource primary, HarvestResource fallback)
|
||||
{
|
||||
bool racialBonus = def.RaceBonus && from.Race == Race.Elf;
|
||||
|
||||
if (vein.ChanceToFallback > (Utility.RandomDouble() + (racialBonus ? .20 : 0)))
|
||||
return fallback;
|
||||
|
||||
double skillValue = from.Skills[def.Skill].Value;
|
||||
|
||||
if (fallback != null && (skillValue < primary.ReqSkill || skillValue < primary.MinSkill))
|
||||
return fallback;
|
||||
|
||||
return primary;
|
||||
}
|
||||
|
||||
public virtual bool OnHarvesting(Mobile from, Item tool, HarvestDefinition def, object toHarvest, object locked, bool last)
|
||||
{
|
||||
if (!CheckHarvest(from, tool))
|
||||
{
|
||||
from.EndAction(locked);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetHarvestDetails(from, tool, toHarvest, out int tileID, out Map map, out Point3D loc))
|
||||
{
|
||||
from.EndAction(locked);
|
||||
OnBadHarvestTarget(from, tool, toHarvest);
|
||||
return false;
|
||||
}
|
||||
else if (!def.Validate(tileID) && !def.ValidateSpecial(tileID))
|
||||
{
|
||||
from.EndAction(locked);
|
||||
OnBadHarvestTarget(from, tool, toHarvest);
|
||||
return false;
|
||||
}
|
||||
else if (!CheckRange(from, tool, def, map, loc, true))
|
||||
{
|
||||
from.EndAction(locked);
|
||||
return false;
|
||||
}
|
||||
else if (!CheckResources(from, tool, def, map, loc, true))
|
||||
{
|
||||
from.EndAction(locked);
|
||||
return false;
|
||||
}
|
||||
else if (!CheckHarvest(from, tool, def, toHarvest))
|
||||
{
|
||||
from.EndAction(locked);
|
||||
return false;
|
||||
}
|
||||
|
||||
DoHarvestingEffect(from, tool, def, map, loc);
|
||||
|
||||
new HarvestSoundTimer(from, tool, this, def, toHarvest, locked, last).Start();
|
||||
|
||||
return !last;
|
||||
}
|
||||
|
||||
public virtual void DoHarvestingSound(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
|
||||
{
|
||||
if (def.EffectSounds.Length > 0)
|
||||
from.PlaySound(Utility.RandomList(def.EffectSounds));
|
||||
}
|
||||
|
||||
public virtual void DoHarvestingEffect(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc)
|
||||
{
|
||||
from.Direction = from.GetDirectionTo(loc);
|
||||
|
||||
if (!from.Mounted)
|
||||
{
|
||||
if (Core.SA)
|
||||
{
|
||||
from.Animate(AnimationType.Attack, Utility.RandomList(def.EffectActions));
|
||||
}
|
||||
else
|
||||
{
|
||||
from.Animate(Utility.RandomList(def.EffectActions), 5, 1, true, false, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual HarvestDefinition GetDefinition(int tileID)
|
||||
{
|
||||
return GetDefinition(tileID, null);
|
||||
}
|
||||
|
||||
public virtual HarvestDefinition GetDefinition(int tileID, Item tool)
|
||||
{
|
||||
HarvestDefinition def = null;
|
||||
|
||||
for (int i = 0; def == null && i < Definitions.Count; ++i)
|
||||
{
|
||||
HarvestDefinition check = Definitions[i];
|
||||
|
||||
if (check.Validate(tileID))
|
||||
def = check;
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
#region High Seas
|
||||
public virtual HarvestDefinition GetDefinitionFromSpecialTile(int tileID)
|
||||
{
|
||||
HarvestDefinition def = null;
|
||||
|
||||
for (int i = 0; def == null && i < Definitions.Count; ++i)
|
||||
{
|
||||
HarvestDefinition check = Definitions[i];
|
||||
|
||||
if (check.ValidateSpecial(tileID))
|
||||
def = check;
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public virtual void StartHarvesting(Mobile from, Item tool, object toHarvest)
|
||||
{
|
||||
if (!CheckHarvest(from, tool))
|
||||
return;
|
||||
|
||||
if (!GetHarvestDetails(from, tool, toHarvest, out int tileID, out Map map, out Point3D loc))
|
||||
{
|
||||
OnBadHarvestTarget(from, tool, toHarvest);
|
||||
return;
|
||||
}
|
||||
|
||||
HarvestDefinition def = GetDefinition(tileID, tool);
|
||||
|
||||
if (def == null)
|
||||
{
|
||||
OnBadHarvestTarget(from, tool, toHarvest);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CheckRange(from, tool, def, map, loc, false))
|
||||
return;
|
||||
else if (!CheckResources(from, tool, def, map, loc, false))
|
||||
return;
|
||||
else if (!CheckHarvest(from, tool, def, toHarvest))
|
||||
return;
|
||||
|
||||
object toLock = GetLock(from, tool, def, toHarvest);
|
||||
|
||||
if (!from.BeginAction(toLock))
|
||||
{
|
||||
OnConcurrentHarvest(from, tool, def, toHarvest);
|
||||
return;
|
||||
}
|
||||
|
||||
new HarvestTimer(from, tool, this, def, toHarvest, toLock).Start();
|
||||
OnHarvestStarted(from, tool, def, toHarvest);
|
||||
}
|
||||
|
||||
public virtual bool GetHarvestDetails(Mobile from, Item tool, object toHarvest, out int tileID, out Map map, out Point3D loc)
|
||||
{
|
||||
if (toHarvest is Static && !((Static)toHarvest).Movable)
|
||||
{
|
||||
Static obj = (Static)toHarvest;
|
||||
|
||||
tileID = (obj.ItemID & 0x3FFF) | 0x4000;
|
||||
map = obj.Map;
|
||||
loc = obj.GetWorldLocation();
|
||||
}
|
||||
else if (toHarvest is StaticTarget)
|
||||
{
|
||||
StaticTarget obj = (StaticTarget)toHarvest;
|
||||
|
||||
tileID = (obj.ItemID & 0x3FFF) | 0x4000;
|
||||
map = from.Map;
|
||||
loc = obj.Location;
|
||||
}
|
||||
else if (toHarvest is LandTarget obj)
|
||||
{
|
||||
tileID = obj.TileID;
|
||||
map = from.Map;
|
||||
loc = obj.Location;
|
||||
}
|
||||
else
|
||||
{
|
||||
tileID = 0;
|
||||
map = null;
|
||||
loc = Point3D.Zero;
|
||||
return false;
|
||||
}
|
||||
|
||||
return map != null && map != Map.Internal;
|
||||
}
|
||||
|
||||
#region Enhanced Client
|
||||
public static void TargetByResource(TargetByResourceMacroEventArgs e)
|
||||
{
|
||||
Mobile m = e.Mobile;
|
||||
Item tool = e.Tool;
|
||||
|
||||
HarvestSystem system = null;
|
||||
HarvestDefinition def = null;
|
||||
|
||||
if (tool is IHarvestTool)
|
||||
{
|
||||
system = ((IHarvestTool)tool).HarvestSystem;
|
||||
}
|
||||
|
||||
if (system != null)
|
||||
{
|
||||
switch (e.ResourceType)
|
||||
{
|
||||
case 0: // ore
|
||||
if (system is Mining)
|
||||
def = ((Mining)system).OreAndStone;
|
||||
break;
|
||||
case 1: // sand
|
||||
if (system is Mining)
|
||||
def = ((Mining)system).Sand;
|
||||
break;
|
||||
case 2: // wood
|
||||
if (system is Lumberjacking)
|
||||
def = ((Lumberjacking)system).Definition;
|
||||
break;
|
||||
case 3: // grave
|
||||
if (TryHarvestGrave(m))
|
||||
return;
|
||||
break;
|
||||
case 4: // red shrooms
|
||||
if (TryHarvestShrooms(m))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (def != null && FindValidTile(m, def, out object toHarvest))
|
||||
{
|
||||
system.StartHarvesting(m, tool, toHarvest);
|
||||
return;
|
||||
}
|
||||
|
||||
system.OnBadHarvestTarget(m, tool, new LandTarget(new Point3D(0, 0, 0), Map.Felucca));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool FindValidTile(Mobile m, HarvestDefinition definition, out object toHarvest)
|
||||
{
|
||||
Map map = m.Map;
|
||||
toHarvest = null;
|
||||
|
||||
if (m == null || map == null || map == Map.Internal)
|
||||
return false;
|
||||
|
||||
for (int x = m.X - 1; x <= m.X + 1; x++)
|
||||
{
|
||||
for (int y = m.Y - 1; y <= m.Y + 1; y++)
|
||||
{
|
||||
StaticTile[] tiles = map.Tiles.GetStaticTiles(x, y, false);
|
||||
|
||||
if (tiles.Length > 0)
|
||||
{
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
int id = (tile.ID & 0x3FFF) | 0x4000;
|
||||
|
||||
if (definition.Validate(id))
|
||||
{
|
||||
toHarvest = new StaticTarget(new Point3D(x, y, tile.Z), tile.ID);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LandTile lt = map.Tiles.GetLandTile(x, y);
|
||||
|
||||
if (definition.Validate(lt.ID))
|
||||
{
|
||||
toHarvest = new LandTarget(new Point3D(x, y, lt.Z), map);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryHarvestGrave(Mobile m)
|
||||
{
|
||||
Map map = m.Map;
|
||||
|
||||
if (map == null)
|
||||
return false;
|
||||
|
||||
for (int x = m.X - 1; x <= m.X + 1; x++)
|
||||
{
|
||||
for (int y = m.Y - 1; y <= m.Y + 1; y++)
|
||||
{
|
||||
StaticTile[] tiles = map.Tiles.GetStaticTiles(x, y, false);
|
||||
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
int itemID = tile.ID;
|
||||
|
||||
if (itemID == 0xED3 || itemID == 0xEDF || itemID == 0xEE0 || itemID == 0xEE1 || itemID == 0xEE2 || itemID == 0xEE8)
|
||||
{
|
||||
if (m is PlayerMobile player)
|
||||
{
|
||||
QuestSystem qs = player.Quest;
|
||||
|
||||
if (qs is WitchApprenticeQuest)
|
||||
{
|
||||
if (qs.FindObjective(typeof(FindIngredientObjective)) is FindIngredientObjective obj && !obj.Completed && obj.Ingredient == Ingredient.Bones)
|
||||
{
|
||||
player.SendLocalizedMessage(1055037); // You finish your grim work, finding some of the specific bones listed in the Hag's recipe.
|
||||
obj.Complete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryHarvestShrooms(Mobile m)
|
||||
{
|
||||
Map map = m.Map;
|
||||
|
||||
if (map == null)
|
||||
return false;
|
||||
|
||||
for (int x = m.X - 1; x <= m.X + 1; x++)
|
||||
{
|
||||
for (int y = m.Y - 1; y <= m.Y + 1; y++)
|
||||
{
|
||||
StaticTile[] tiles = map.Tiles.GetStaticTiles(x, y, false);
|
||||
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
int itemID = tile.ID;
|
||||
|
||||
if (itemID == 0xD15 || itemID == 0xD16)
|
||||
{
|
||||
if (m is PlayerMobile player)
|
||||
{
|
||||
QuestSystem qs = player.Quest;
|
||||
|
||||
if (qs is WitchApprenticeQuest)
|
||||
{
|
||||
if (qs.FindObjective(typeof(FindIngredientObjective)) is FindIngredientObjective obj && !obj.Completed && obj.Ingredient == Ingredient.RedMushrooms)
|
||||
{
|
||||
player.SendLocalizedMessage(1055036); // You slice a red cap mushroom from its stem.
|
||||
obj.Complete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public interface IChopable
|
||||
{
|
||||
void OnChop(Mobile from);
|
||||
}
|
||||
|
||||
public interface IHarvestTool : IEntity
|
||||
{
|
||||
Engines.Harvest.HarvestSystem HarvestSystem { get; }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class FurnitureAttribute : Attribute
|
||||
{
|
||||
public FurnitureAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
private static bool IsNotChoppables(Item item)
|
||||
{
|
||||
return _NotChoppables.Any(t => t == item.GetType());
|
||||
}
|
||||
|
||||
private static Type[] _NotChoppables = new Type[]
|
||||
{
|
||||
typeof(CommodityDeedBox), typeof(ChinaCabinet), typeof(PieSafe), typeof(AcademicBookCase), typeof(JewelryBox),
|
||||
typeof(WoodenBookcase), typeof(Countertop), typeof(Mailbox)
|
||||
};
|
||||
|
||||
public static bool Check(Item item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsNotChoppables(item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.GetType().IsDefined(typeof(FurnitureAttribute), false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (item is AddonComponent && ((AddonComponent)item).Addon != null && ((AddonComponent)item).Addon.GetType().IsDefined(typeof(FurnitureAttribute), false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
297
Scripts/Services/Harvest/Lumberjacking.cs
Normal file
297
Scripts/Services/Harvest/Lumberjacking.cs
Normal file
@@ -0,0 +1,297 @@
|
||||
using System;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
using System.Linq;
|
||||
|
||||
namespace Server.Engines.Harvest
|
||||
{
|
||||
public class Lumberjacking : HarvestSystem
|
||||
{
|
||||
private static Lumberjacking m_System;
|
||||
|
||||
public static Lumberjacking System
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_System == null)
|
||||
m_System = new Lumberjacking();
|
||||
|
||||
return m_System;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly HarvestDefinition m_Definition;
|
||||
|
||||
public HarvestDefinition Definition
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.m_Definition;
|
||||
}
|
||||
}
|
||||
|
||||
private Lumberjacking()
|
||||
{
|
||||
HarvestResource[] res;
|
||||
HarvestVein[] veins;
|
||||
|
||||
#region Lumberjacking
|
||||
HarvestDefinition lumber = new HarvestDefinition();
|
||||
|
||||
// Resource banks are every 4x3 tiles
|
||||
lumber.BankWidth = 4;
|
||||
lumber.BankHeight = 3;
|
||||
|
||||
// Every bank holds from 20 to 45 logs
|
||||
lumber.MinTotal = 20;
|
||||
lumber.MaxTotal = 45;
|
||||
|
||||
// A resource bank will respawn its content every 20 to 30 minutes
|
||||
lumber.MinRespawn = TimeSpan.FromMinutes(20.0);
|
||||
lumber.MaxRespawn = TimeSpan.FromMinutes(30.0);
|
||||
|
||||
// Skill checking is done on the Lumberjacking skill
|
||||
lumber.Skill = SkillName.Lumberjacking;
|
||||
|
||||
// Set the list of harvestable tiles
|
||||
lumber.Tiles = m_TreeTiles;
|
||||
|
||||
// Players must be within 2 tiles to harvest
|
||||
lumber.MaxRange = 2;
|
||||
|
||||
// Ten logs per harvest action
|
||||
lumber.ConsumedPerHarvest = 10;
|
||||
lumber.ConsumedPerFeluccaHarvest = 20;
|
||||
|
||||
// The chopping effect
|
||||
lumber.EffectActions = new int[] { Core.SA ? 7 : 13 };
|
||||
lumber.EffectSounds = new int[] { 0x13E };
|
||||
lumber.EffectCounts = (Core.AOS ? new int[] { 1 } : new int[] { 1, 2, 2, 2, 3 });
|
||||
lumber.EffectDelay = TimeSpan.FromSeconds(1.6);
|
||||
lumber.EffectSoundDelay = TimeSpan.FromSeconds(0.9);
|
||||
|
||||
lumber.NoResourcesMessage = 500493; // There's not enough wood here to harvest.
|
||||
lumber.FailMessage = 500495; // You hack at the tree for a while, but fail to produce any useable wood.
|
||||
lumber.OutOfRangeMessage = 500446; // That is too far away.
|
||||
lumber.PackFullMessage = 500497; // You can't place any wood into your backpack!
|
||||
lumber.ToolBrokeMessage = 500499; // You broke your axe.
|
||||
|
||||
if (Core.ML)
|
||||
{
|
||||
res = new HarvestResource[]
|
||||
{
|
||||
new HarvestResource(00.0, 00.0, 100.0, 1072540, typeof(Log)),
|
||||
new HarvestResource(65.0, 25.0, 105.0, 1072541, typeof(OakLog)),
|
||||
new HarvestResource(80.0, 40.0, 120.0, 1072542, typeof(AshLog)),
|
||||
new HarvestResource(95.0, 55.0, 135.0, 1072543, typeof(YewLog)),
|
||||
new HarvestResource(100.0, 60.0, 140.0, 1072544, typeof(HeartwoodLog)),
|
||||
new HarvestResource(100.0, 60.0, 140.0, 1072545, typeof(BloodwoodLog)),
|
||||
new HarvestResource(100.0, 60.0, 140.0, 1072546, typeof(FrostwoodLog)),
|
||||
};
|
||||
|
||||
veins = new HarvestVein[]
|
||||
{
|
||||
new HarvestVein(49.0, 0.0, res[0], null), // Ordinary Logs
|
||||
new HarvestVein(30.0, 0.5, res[1], res[0]), // Oak
|
||||
new HarvestVein(10.0, 0.5, res[2], res[0]), // Ash
|
||||
new HarvestVein(05.0, 0.5, res[3], res[0]), // Yew
|
||||
new HarvestVein(03.0, 0.5, res[4], res[0]), // Heartwood
|
||||
new HarvestVein(02.0, 0.5, res[5], res[0]), // Bloodwood
|
||||
new HarvestVein(01.0, 0.5, res[6], res[0]), // Frostwood
|
||||
};
|
||||
|
||||
lumber.BonusResources = new BonusHarvestResource[]
|
||||
{
|
||||
new BonusHarvestResource(0, 82.0, null, null), //Nothing
|
||||
new BonusHarvestResource(100, 10.0, 1072548, typeof(BarkFragment)),
|
||||
new BonusHarvestResource(100, 03.0, 1072550, typeof(LuminescentFungi)),
|
||||
new BonusHarvestResource(100, 02.0, 1072547, typeof(SwitchItem)),
|
||||
new BonusHarvestResource(100, 01.0, 1072549, typeof(ParasiticPlant)),
|
||||
new BonusHarvestResource(100, 01.0, 1072551, typeof(BrilliantAmber)),
|
||||
new BonusHarvestResource(100, 01.0, 1113756, typeof(CrystalShards), Map.TerMur),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
res = new HarvestResource[]
|
||||
{
|
||||
new HarvestResource(00.0, 00.0, 100.0, 500498, typeof(Log))
|
||||
};
|
||||
|
||||
veins = new HarvestVein[]
|
||||
{
|
||||
new HarvestVein(100.0, 0.0, res[0], null)
|
||||
};
|
||||
}
|
||||
|
||||
lumber.Resources = res;
|
||||
lumber.Veins = veins;
|
||||
|
||||
lumber.RaceBonus = Core.ML;
|
||||
lumber.RandomizeVeins = Core.ML;
|
||||
|
||||
this.m_Definition = lumber;
|
||||
this.Definitions.Add(lumber);
|
||||
#endregion
|
||||
}
|
||||
|
||||
public override Type MutateType(Type type, Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, HarvestResource resource)
|
||||
{
|
||||
var newType = type;
|
||||
|
||||
if (tool is HarvestersAxe && ((HarvestersAxe)tool).Charges > 0)
|
||||
{
|
||||
if (type == typeof(Log))
|
||||
newType = typeof(Board);
|
||||
else if (type == typeof(OakLog))
|
||||
newType = typeof(OakBoard);
|
||||
else if (type == typeof(AshLog))
|
||||
newType = typeof(AshBoard);
|
||||
else if (type == typeof(YewLog))
|
||||
newType = typeof(YewBoard);
|
||||
else if (type == typeof(HeartwoodLog))
|
||||
newType = typeof(HeartwoodBoard);
|
||||
else if (type == typeof(BloodwoodLog))
|
||||
newType = typeof(BloodwoodBoard);
|
||||
else if (type == typeof(FrostwoodLog))
|
||||
newType = typeof(FrostwoodBoard);
|
||||
|
||||
if (newType != type)
|
||||
{
|
||||
((HarvestersAxe)tool).Charges--;
|
||||
}
|
||||
}
|
||||
|
||||
return newType;
|
||||
}
|
||||
|
||||
public override void SendSuccessTo(Mobile from, Item item, HarvestResource resource)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
if (item != null && item.GetType().IsSubclassOf(typeof(BaseWoodBoard)))
|
||||
{
|
||||
from.SendLocalizedMessage(1158776); // The axe magically creates boards from your logs.
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var res in m_Definition.Resources.Where(r => r.Types != null))
|
||||
{
|
||||
foreach (var type in res.Types)
|
||||
{
|
||||
if (item.GetType() == type)
|
||||
{
|
||||
res.SendSuccessTo(from);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.SendSuccessTo(from, item, resource);
|
||||
}
|
||||
|
||||
public override bool CheckHarvest(Mobile from, Item tool)
|
||||
{
|
||||
if (!base.CheckHarvest(from, tool))
|
||||
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 (tool.Parent != from && from.Backpack != null && !tool.IsChildOf(from.Backpack))
|
||||
{
|
||||
from.SendLocalizedMessage(1080058); // This must be in your backpack to use it.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override Type GetResourceType(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, HarvestResource resource)
|
||||
{
|
||||
#region Void Pool Items
|
||||
HarvestMap hmap = HarvestMap.CheckMapOnHarvest(from, loc, def);
|
||||
|
||||
if (hmap != null && hmap.Resource >= CraftResource.RegularWood && hmap.Resource <= CraftResource.Frostwood)
|
||||
{
|
||||
hmap.UsesRemaining--;
|
||||
hmap.InvalidateProperties();
|
||||
|
||||
CraftResourceInfo info = CraftResources.GetInfo(hmap.Resource);
|
||||
|
||||
if (info != null)
|
||||
return info.ResourceTypes[0];
|
||||
}
|
||||
#endregion
|
||||
|
||||
return base.GetResourceType(from, tool, def, map, loc, resource);
|
||||
}
|
||||
|
||||
public override bool CheckResources(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed)
|
||||
{
|
||||
if (HarvestMap.CheckMapOnHarvest(from, loc, def) == null)
|
||||
return base.CheckResources(from, tool, def, map, loc, timed);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnBadHarvestTarget(Mobile from, Item tool, object toHarvest)
|
||||
{
|
||||
if (toHarvest is Mobile)
|
||||
((Mobile)toHarvest).PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500450, from.NetState); // You can only skin dead creatures.
|
||||
else if (toHarvest is Item)
|
||||
((Item)toHarvest).LabelTo(from, 500464); // Use this on corpses to carve away meat and hide
|
||||
else if (toHarvest is Targeting.StaticTarget || toHarvest is Targeting.LandTarget)
|
||||
from.SendLocalizedMessage(500489); // You can't use an axe on that.
|
||||
else
|
||||
from.SendLocalizedMessage(1005213); // You can't do that
|
||||
}
|
||||
|
||||
public override void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
|
||||
{
|
||||
base.OnHarvestStarted(from, tool, def, toHarvest);
|
||||
|
||||
if (Core.ML)
|
||||
from.RevealingAction();
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
Array.Sort(m_TreeTiles);
|
||||
}
|
||||
|
||||
#region Tile lists
|
||||
private static readonly int[] m_TreeTiles = new int[]
|
||||
{
|
||||
0x4CCA, 0x4CCB, 0x4CCC, 0x4CCD, 0x4CD0, 0x4CD3, 0x4CD6, 0x4CD8,
|
||||
0x4CDA, 0x4CDD, 0x4CE0, 0x4CE3, 0x4CE6, 0x4CF8, 0x4CFB, 0x4CFE,
|
||||
0x4D01, 0x4D41, 0x4D42, 0x4D43, 0x4D44, 0x4D57, 0x4D58, 0x4D59,
|
||||
0x4D5A, 0x4D5B, 0x4D6E, 0x4D6F, 0x4D70, 0x4D71, 0x4D72, 0x4D84,
|
||||
0x4D85, 0x4D86, 0x52B5, 0x52B6, 0x52B7, 0x52B8, 0x52B9, 0x52BA,
|
||||
0x52BB, 0x52BC, 0x52BD,
|
||||
0x4CCE, 0x4CCF, 0x4CD1, 0x4CD2, 0x4CD4, 0x4CD5, 0x4CD7, 0x4CD9,
|
||||
0x4CDB, 0x4CDC, 0x4CDE, 0x4CDF, 0x4CE1, 0x4CE2, 0x4CE4, 0x4CE5,
|
||||
0x4CE7, 0x4CE8, 0x4CF9, 0x4CFA, 0x4CFC, 0x4CFD, 0x4CFF, 0x4D00,
|
||||
0x4D02, 0x4D03, 0x4D45, 0x4D46, 0x4D47, 0x4D48, 0x4D49, 0x4D4A,
|
||||
0x4D4B, 0x4D4C, 0x4D4D, 0x4D4E, 0x4D4F, 0x4D50, 0x4D51, 0x4D52,
|
||||
0x4D53, 0x4D5C, 0x4D5D, 0x4D5E, 0x4D5F, 0x4D60, 0x4D61, 0x4D62,
|
||||
0x4D63, 0x4D64, 0x4D65, 0x4D66, 0x4D67, 0x4D68, 0x4D69, 0x4D73,
|
||||
0x4D74, 0x4D75, 0x4D76, 0x4D77, 0x4D78, 0x4D79, 0x4D7A, 0x4D7B,
|
||||
0x4D7C, 0x4D7D, 0x4D7E, 0x4D7F, 0x4D87, 0x4D88, 0x4D89, 0x4D8A,
|
||||
0x4D8B, 0x4D8C, 0x4D8D, 0x4D8E, 0x4D8F, 0x4D90, 0x4D95, 0x4D96,
|
||||
0x4D97, 0x4D99, 0x4D9A, 0x4D9B, 0x4D9D, 0x4D9E, 0x4D9F, 0x4DA1,
|
||||
0x4DA2, 0x4DA3, 0x4DA5, 0x4DA6, 0x4DA7, 0x4DA9, 0x4DAA, 0x4DAB,
|
||||
0x52BE, 0x52BF, 0x52C0, 0x52C1, 0x52C2, 0x52C3, 0x52C4, 0x52C5,
|
||||
0x52C6, 0x52C7
|
||||
};
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
566
Scripts/Services/Harvest/Mining.cs
Normal file
566
Scripts/Services/Harvest/Mining.cs
Normal file
@@ -0,0 +1,566 @@
|
||||
using System;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
using System.Linq;
|
||||
|
||||
namespace Server.Engines.Harvest
|
||||
{
|
||||
public class Mining : HarvestSystem
|
||||
{
|
||||
private static Mining m_System;
|
||||
|
||||
public static Mining System
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_System == null)
|
||||
m_System = new Mining();
|
||||
|
||||
return m_System;
|
||||
}
|
||||
}
|
||||
|
||||
public HarvestDefinition OreAndStone { get; }
|
||||
|
||||
public HarvestDefinition Sand { get; }
|
||||
|
||||
private Mining()
|
||||
{
|
||||
HarvestResource[] res;
|
||||
HarvestVein[] veins;
|
||||
|
||||
#region Mining for ore and stone
|
||||
HarvestDefinition oreAndStone = OreAndStone = new HarvestDefinition();
|
||||
|
||||
// Resource banks are every 8x8 tiles
|
||||
oreAndStone.BankWidth = 8;
|
||||
oreAndStone.BankHeight = 8;
|
||||
|
||||
// Every bank holds from 10 to 34 ore
|
||||
oreAndStone.MinTotal = 10;
|
||||
oreAndStone.MaxTotal = 34;
|
||||
|
||||
// A resource bank will respawn its content every 10 to 20 minutes
|
||||
oreAndStone.MinRespawn = TimeSpan.FromMinutes(10.0);
|
||||
oreAndStone.MaxRespawn = TimeSpan.FromMinutes(20.0);
|
||||
|
||||
// Skill checking is done on the Mining skill
|
||||
oreAndStone.Skill = SkillName.Mining;
|
||||
|
||||
// Set the list of harvestable tiles
|
||||
oreAndStone.Tiles = m_MountainAndCaveTiles;
|
||||
|
||||
// Players must be within 2 tiles to harvest
|
||||
oreAndStone.MaxRange = 2;
|
||||
|
||||
// One ore per harvest action
|
||||
oreAndStone.ConsumedPerHarvest = 1;
|
||||
oreAndStone.ConsumedPerFeluccaHarvest = 2;
|
||||
|
||||
// The digging effect
|
||||
oreAndStone.EffectActions = new int[] { Core.SA ? 3 : 11 };
|
||||
oreAndStone.EffectSounds = new int[] { 0x125, 0x126 };
|
||||
oreAndStone.EffectCounts = new int[] { 1 };
|
||||
oreAndStone.EffectDelay = TimeSpan.FromSeconds(1.6);
|
||||
oreAndStone.EffectSoundDelay = TimeSpan.FromSeconds(0.9);
|
||||
|
||||
oreAndStone.NoResourcesMessage = 503040; // There is no metal here to mine.
|
||||
oreAndStone.DoubleHarvestMessage = 503042; // Someone has gotten to the metal before you.
|
||||
oreAndStone.TimedOutOfRangeMessage = 503041; // You have moved too far away to continue mining.
|
||||
oreAndStone.OutOfRangeMessage = 500446; // That is too far away.
|
||||
oreAndStone.FailMessage = 503043; // You loosen some rocks but fail to find any useable ore.
|
||||
oreAndStone.PackFullMessage = 1010481; // Your backpack is full, so the ore you mined is lost.
|
||||
oreAndStone.ToolBrokeMessage = 1044038; // You have worn out your tool!
|
||||
|
||||
res = new HarvestResource[]
|
||||
{
|
||||
new HarvestResource(00.0, 00.0, 100.0, 1007072, typeof(IronOre), typeof(Granite)),
|
||||
new HarvestResource(65.0, 25.0, 105.0, 1007073, typeof(DullCopperOre), typeof(DullCopperGranite), typeof(DullCopperElemental)),
|
||||
new HarvestResource(70.0, 30.0, 110.0, 1007074, typeof(ShadowIronOre), typeof(ShadowIronGranite), typeof(ShadowIronElemental)),
|
||||
new HarvestResource(75.0, 35.0, 115.0, 1007075, typeof(CopperOre), typeof(CopperGranite), typeof(CopperElemental)),
|
||||
new HarvestResource(80.0, 40.0, 120.0, 1007076, typeof(BronzeOre), typeof(BronzeGranite), typeof(BronzeElemental)),
|
||||
new HarvestResource(85.0, 45.0, 125.0, 1007077, typeof(GoldOre), typeof(GoldGranite), typeof(GoldenElemental)),
|
||||
new HarvestResource(90.0, 50.0, 130.0, 1007078, typeof(AgapiteOre), typeof(AgapiteGranite), typeof(AgapiteElemental)),
|
||||
new HarvestResource(95.0, 55.0, 135.0, 1007079, typeof(VeriteOre), typeof(VeriteGranite), typeof(VeriteElemental)),
|
||||
new HarvestResource(99.0, 59.0, 139.0, 1007080, typeof(ValoriteOre), typeof(ValoriteGranite), typeof(ValoriteElemental))
|
||||
};
|
||||
|
||||
veins = new HarvestVein[]
|
||||
{
|
||||
new HarvestVein(49.6, 0.0, res[0], null), // Iron
|
||||
new HarvestVein(11.2, 0.5, res[1], res[0]), // Dull Copper
|
||||
new HarvestVein(09.8, 0.5, res[2], res[0]), // Shadow Iron
|
||||
new HarvestVein(08.4, 0.5, res[3], res[0]), // Copper
|
||||
new HarvestVein(07.0, 0.5, res[4], res[0]), // Bronze
|
||||
new HarvestVein(05.6, 0.5, res[5], res[0]), // Gold
|
||||
new HarvestVein(04.2, 0.5, res[6], res[0]), // Agapite
|
||||
new HarvestVein(02.8, 0.5, res[7], res[0]), // Verite
|
||||
new HarvestVein(01.4, 0.5, res[8], res[0])// Valorite
|
||||
};
|
||||
|
||||
oreAndStone.Resources = res;
|
||||
oreAndStone.Veins = veins;
|
||||
|
||||
if (Core.ML)
|
||||
{
|
||||
oreAndStone.BonusResources = new BonusHarvestResource[]
|
||||
{
|
||||
new BonusHarvestResource(0, 99.2, null, null), //Nothing
|
||||
new BonusHarvestResource(100, .1, 1072562, typeof(BlueDiamond)),
|
||||
new BonusHarvestResource(100, .1, 1072567, typeof(DarkSapphire)),
|
||||
new BonusHarvestResource(100, .1, 1072570, typeof(EcruCitrine)),
|
||||
new BonusHarvestResource(100, .1, 1072564, typeof(FireRuby)),
|
||||
new BonusHarvestResource(100, .1, 1072566, typeof(PerfectEmerald)),
|
||||
new BonusHarvestResource(100, .1, 1072568, typeof(Turquoise)),
|
||||
new BonusHarvestResource(100, .1, 1077180, typeof(SmallPieceofBlackrock)),
|
||||
new BonusHarvestResource(100, .1, 1113344, typeof(CrystallineBlackrock), Map.TerMur)
|
||||
};
|
||||
}
|
||||
|
||||
oreAndStone.RaceBonus = Core.ML;
|
||||
oreAndStone.RandomizeVeins = Core.ML;
|
||||
|
||||
Definitions.Add(oreAndStone);
|
||||
#endregion
|
||||
|
||||
#region Mining for sand
|
||||
HarvestDefinition sand = Sand = new HarvestDefinition();
|
||||
|
||||
// Resource banks are every 8x8 tiles
|
||||
sand.BankWidth = 8;
|
||||
sand.BankHeight = 8;
|
||||
|
||||
// Every bank holds from 6 to 12 sand
|
||||
sand.MinTotal = 6;
|
||||
sand.MaxTotal = 13;
|
||||
|
||||
// A resource bank will respawn its content every 10 to 20 minutes
|
||||
sand.MinRespawn = TimeSpan.FromMinutes(10.0);
|
||||
sand.MaxRespawn = TimeSpan.FromMinutes(20.0);
|
||||
|
||||
// Skill checking is done on the Mining skill
|
||||
sand.Skill = SkillName.Mining;
|
||||
|
||||
// Set the list of harvestable tiles
|
||||
sand.Tiles = m_SandTiles;
|
||||
|
||||
// Players must be within 2 tiles to harvest
|
||||
sand.MaxRange = 2;
|
||||
|
||||
// One sand per harvest action
|
||||
sand.ConsumedPerHarvest = 1;
|
||||
sand.ConsumedPerFeluccaHarvest = 2;
|
||||
|
||||
// The digging effect
|
||||
sand.EffectActions = new int[] { Core.SA ? 3 : 11 };
|
||||
sand.EffectSounds = new int[] { 0x125, 0x126 };
|
||||
sand.EffectCounts = new int[] { 6 };
|
||||
sand.EffectDelay = TimeSpan.FromSeconds(1.6);
|
||||
sand.EffectSoundDelay = TimeSpan.FromSeconds(0.9);
|
||||
|
||||
sand.NoResourcesMessage = 1044629; // There is no sand here to mine.
|
||||
sand.DoubleHarvestMessage = 1044629; // There is no sand here to mine.
|
||||
sand.TimedOutOfRangeMessage = 503041; // You have moved too far away to continue mining.
|
||||
sand.OutOfRangeMessage = 500446; // That is too far away.
|
||||
sand.FailMessage = 1044630; // You dig for a while but fail to find any of sufficient quality for glassblowing.
|
||||
sand.PackFullMessage = 1044632; // Your backpack can't hold the sand, and it is lost!
|
||||
sand.ToolBrokeMessage = 1044038; // You have worn out your tool!
|
||||
|
||||
res = new HarvestResource[]
|
||||
{
|
||||
new HarvestResource(100.0, 70.0, 100.0, 1044631, typeof(Sand))
|
||||
};
|
||||
|
||||
veins = new HarvestVein[]
|
||||
{
|
||||
new HarvestVein(100.0, 0.0, res[0], null)
|
||||
};
|
||||
|
||||
sand.Resources = res;
|
||||
sand.Veins = veins;
|
||||
|
||||
Definitions.Add(sand);
|
||||
#endregion
|
||||
}
|
||||
|
||||
public override Type GetResourceType(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, HarvestResource resource)
|
||||
{
|
||||
if (def == OreAndStone)
|
||||
{
|
||||
#region Void Pool Items
|
||||
HarvestMap hmap = HarvestMap.CheckMapOnHarvest(from, loc, def);
|
||||
|
||||
if (hmap != null && hmap.Resource >= CraftResource.Iron && hmap.Resource <= CraftResource.Valorite)
|
||||
{
|
||||
hmap.UsesRemaining--;
|
||||
hmap.InvalidateProperties();
|
||||
|
||||
CraftResourceInfo info = CraftResources.GetInfo(hmap.Resource);
|
||||
|
||||
if (info != null)
|
||||
return info.ResourceTypes[1];
|
||||
}
|
||||
#endregion
|
||||
|
||||
PlayerMobile pm = from as PlayerMobile;
|
||||
|
||||
if (tool is ImprovedRockHammer)
|
||||
{
|
||||
if (from.Skills[SkillName.Mining].Base >= 100.0)
|
||||
return resource.Types[1];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
if (pm != null && pm.GemMining && pm.ToggleMiningGem && from.Skills[SkillName.Mining].Base >= 100.0 && 0.1 > Utility.RandomDouble())
|
||||
return Loot.GemTypes[Utility.Random(Loot.GemTypes.Length)];
|
||||
|
||||
double chance = tool is RockHammer ? 0.50 : 0.15;
|
||||
|
||||
if (pm != null && pm.StoneMining && (pm.ToggleMiningStone || pm.ToggleStoneOnly) && from.Skills[SkillName.Mining].Base >= 100.0 && chance > Utility.RandomDouble())
|
||||
return resource.Types[1];
|
||||
|
||||
if (pm != null && pm.ToggleStoneOnly)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return resource.Types[0];
|
||||
}
|
||||
|
||||
return base.GetResourceType(from, tool, def, map, loc, resource);
|
||||
}
|
||||
|
||||
public override void SendSuccessTo(Mobile from, Item item, HarvestResource resource)
|
||||
{
|
||||
if (item is BaseGranite)
|
||||
from.SendLocalizedMessage(1044606); // You carefully extract some workable stone from the ore vein!
|
||||
else if (item is IGem)
|
||||
from.SendLocalizedMessage(1112233); // You carefully extract a glistening gem from the vein!
|
||||
else if (item != null)
|
||||
{
|
||||
foreach (var res in OreAndStone.Resources.Where(r => r.Types != null))
|
||||
{
|
||||
foreach (var type in res.Types)
|
||||
{
|
||||
if (item.GetType() == type)
|
||||
{
|
||||
res.SendSuccessTo(from);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.SendSuccessTo(from, item, resource);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CheckResources(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed)
|
||||
{
|
||||
if (HarvestMap.CheckMapOnHarvest(from, loc, def) == null)
|
||||
return base.CheckResources(from, tool, def, map, loc, timed);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool CheckHarvest(Mobile from, Item tool)
|
||||
{
|
||||
if (!base.CheckHarvest(from, tool))
|
||||
return false;
|
||||
|
||||
if (from.IsBodyMod && !from.Body.IsHuman)
|
||||
{
|
||||
from.SendLocalizedMessage(501865); // You can't mine while polymorphed.
|
||||
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 (def == Sand && !(from is PlayerMobile && from.Skills[SkillName.Mining].Base >= 100.0 && ((PlayerMobile)from).SandMining))
|
||||
{
|
||||
OnBadHarvestTarget(from, tool, toHarvest);
|
||||
return false;
|
||||
}
|
||||
else if (from.Mounted)
|
||||
{
|
||||
from.SendLocalizedMessage(501864); // You can't mine while riding.
|
||||
return false;
|
||||
}
|
||||
else if (from.IsBodyMod && !from.Body.IsHuman)
|
||||
{
|
||||
from.SendLocalizedMessage(501865); // You can't mine while polymorphed.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override HarvestVein MutateVein(Mobile from, Item tool, HarvestDefinition def, HarvestBank bank, object toHarvest, HarvestVein vein)
|
||||
{
|
||||
if (tool is GargoylesPickaxe && def == OreAndStone)
|
||||
{
|
||||
int veinIndex = Array.IndexOf(def.Veins, vein);
|
||||
|
||||
if (veinIndex >= 0 && veinIndex < (def.Veins.Length - 1))
|
||||
return def.Veins[veinIndex + 1];
|
||||
}
|
||||
|
||||
return base.MutateVein(from, tool, def, bank, toHarvest, vein);
|
||||
}
|
||||
|
||||
private static readonly int[] m_Offsets = new int[]
|
||||
{
|
||||
-1, -1,
|
||||
-1, 0,
|
||||
-1, 1,
|
||||
0, -1,
|
||||
0, 1,
|
||||
1, -1,
|
||||
1, 0,
|
||||
1, 1
|
||||
};
|
||||
|
||||
public override void OnHarvestFinished(Mobile from, Item tool, HarvestDefinition def, HarvestVein vein, HarvestBank bank, HarvestResource resource, object harvested)
|
||||
{
|
||||
if (tool is GargoylesPickaxe && def == OreAndStone && 0.1 > Utility.RandomDouble() && HarvestMap.CheckMapOnHarvest(from, harvested, def) == null)
|
||||
{
|
||||
HarvestResource res = vein.PrimaryResource;
|
||||
|
||||
if (res == resource && res.Types.Length >= 3)
|
||||
{
|
||||
try
|
||||
{
|
||||
Map map = from.Map;
|
||||
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
if (Activator.CreateInstance(res.Types[2], new object[] { 25 }) is BaseCreature spawned)
|
||||
{
|
||||
int offset = Utility.Random(8) * 2;
|
||||
|
||||
for (int i = 0; i < m_Offsets.Length; i += 2)
|
||||
{
|
||||
int x = from.X + m_Offsets[(offset + i) % m_Offsets.Length];
|
||||
int y = from.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length];
|
||||
|
||||
if (map.CanSpawnMobile(x, y, from.Z))
|
||||
{
|
||||
spawned.OnBeforeSpawn(new Point3D(x, y, from.Z), map);
|
||||
spawned.MoveToWorld(new Point3D(x, y, from.Z), map);
|
||||
spawned.Combatant = from;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int z = map.GetAverageZ(x, y);
|
||||
|
||||
if (Math.Abs(z - from.Z) < 10 && map.CanSpawnMobile(x, y, z))
|
||||
{
|
||||
spawned.OnBeforeSpawn(new Point3D(x, y, z), map);
|
||||
spawned.MoveToWorld(new Point3D(x, y, z), map);
|
||||
spawned.Combatant = from;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spawned.OnBeforeSpawn(from.Location, from.Map);
|
||||
spawned.MoveToWorld(from.Location, from.Map);
|
||||
spawned.Combatant = from;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region High Seas
|
||||
public override bool SpecialHarvest(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc)
|
||||
{
|
||||
if (!Core.HS)
|
||||
return base.SpecialHarvest(from, tool, def, map, loc);
|
||||
|
||||
HarvestBank bank = def.GetBank(map, loc.X, loc.Y);
|
||||
|
||||
if (bank == null)
|
||||
return false;
|
||||
|
||||
bool boat = Multis.BaseBoat.FindBoatAt(from, from.Map) != null;
|
||||
bool dungeon = IsDungeonRegion(from);
|
||||
|
||||
if (!boat && !dungeon)
|
||||
return false;
|
||||
|
||||
if (boat || !NiterDeposit.HasBeenChecked(bank))
|
||||
{
|
||||
int luck = from is PlayerMobile ? ((PlayerMobile)from).RealLuck : from.Luck;
|
||||
double bonus = (from.Skills[SkillName.Mining].Value / 9999) + ((double)luck / 150000);
|
||||
|
||||
if (boat)
|
||||
bonus -= bonus * .33;
|
||||
|
||||
if (dungeon)
|
||||
NiterDeposit.AddBank(bank);
|
||||
|
||||
if (Utility.RandomDouble() < bonus)
|
||||
{
|
||||
int size = Utility.RandomMinMax(1, 5);
|
||||
|
||||
if (luck / 2500.0 > Utility.RandomDouble())
|
||||
size++;
|
||||
|
||||
NiterDeposit niter = new NiterDeposit(size);
|
||||
|
||||
if (!dungeon)
|
||||
{
|
||||
niter.MoveToWorld(new Point3D(loc.X, loc.Y, from.Z + 3), from.Map);
|
||||
from.SendLocalizedMessage(1149918, niter.Size.ToString()); //You have uncovered a ~1_SIZE~ deposit of niter! Mine it to obtain saltpeter.
|
||||
NiterDeposit.AddBank(bank);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
int x = Utility.RandomMinMax(loc.X - 2, loc.X + 2);
|
||||
int y = Utility.RandomMinMax(loc.Y - 2, loc.Y + 2);
|
||||
int z = from.Z;
|
||||
|
||||
if (from.Map.CanSpawnMobile(x, y, z))
|
||||
{
|
||||
niter.MoveToWorld(new Point3D(x, y, z), from.Map);
|
||||
from.SendLocalizedMessage(1149918, niter.Size.ToString()); //You have uncovered a ~1_SIZE~ deposit of niter! Mine it to obtain saltpeter.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
niter.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsDungeonRegion(Mobile from)
|
||||
{
|
||||
if (from == null)
|
||||
return false;
|
||||
|
||||
Map map = from.Map;
|
||||
Region reg = from.Region;
|
||||
Rectangle2D bounds = new Rectangle2D(0, 0, 5114, 4100);
|
||||
|
||||
if ((map == Map.Felucca || map == Map.Trammel) && bounds.Contains(new Point2D(from.X, from.Y)))
|
||||
return false;
|
||||
|
||||
return reg != null && (reg.IsPartOf<Regions.DungeonRegion>() || map == Map.Ilshenar);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override bool BeginHarvesting(Mobile from, Item tool)
|
||||
{
|
||||
if (!base.BeginHarvesting(from, tool))
|
||||
return false;
|
||||
|
||||
from.SendLocalizedMessage(503033); // Where do you wish to dig?
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
|
||||
{
|
||||
base.OnHarvestStarted(from, tool, def, toHarvest);
|
||||
|
||||
if (Core.ML)
|
||||
from.RevealingAction();
|
||||
}
|
||||
|
||||
public override void OnBadHarvestTarget(Mobile from, Item tool, object toHarvest)
|
||||
{
|
||||
if (toHarvest is LandTarget)
|
||||
{
|
||||
from.SendLocalizedMessage(501862); // You can't mine there.
|
||||
}
|
||||
else if (!(toHarvest is LandTarget))
|
||||
{
|
||||
from.SendLocalizedMessage(501863); // You can't mine that.
|
||||
}
|
||||
else if (from.Mounted || from.Flying)
|
||||
{
|
||||
from.SendLocalizedMessage(501864); // You can't dig while riding or flying.
|
||||
}
|
||||
}
|
||||
|
||||
#region Tile lists
|
||||
private static readonly int[] m_MountainAndCaveTiles = new int[]
|
||||
{
|
||||
220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
|
||||
230, 231, 236, 237, 238, 239, 240, 241, 242, 243,
|
||||
244, 245, 246, 247, 252, 253, 254, 255, 256, 257,
|
||||
258, 259, 260, 261, 262, 263, 268, 269, 270, 271,
|
||||
272, 273, 274, 275, 276, 277, 278, 279, 286, 287,
|
||||
288, 289, 290, 291, 292, 293, 294, 296, 296, 297,
|
||||
321, 322, 323, 324, 467, 468, 469, 470, 471, 472,
|
||||
473, 474, 476, 477, 478, 479, 480, 481, 482, 483,
|
||||
484, 485, 486, 487, 492, 493, 494, 495, 543, 544,
|
||||
545, 546, 547, 548, 549, 550, 551, 552, 553, 554,
|
||||
555, 556, 557, 558, 559, 560, 561, 562, 563, 564,
|
||||
565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
|
||||
575, 576, 577, 578, 579, 581, 582, 583, 584, 585,
|
||||
586, 587, 588, 589, 590, 591, 592, 593, 594, 595,
|
||||
596, 597, 598, 599, 600, 601, 610, 611, 612, 613,
|
||||
1010, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749,
|
||||
1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1771, 1772,
|
||||
1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782,
|
||||
1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1801, 1802,
|
||||
1803, 1804, 1805, 1806, 1807, 1808, 1809, 1811, 1812, 1813,
|
||||
1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823,
|
||||
1824, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839,
|
||||
1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849,
|
||||
1850, 1851, 1852, 1853, 1854, 1861, 1862, 1863, 1864, 1865,
|
||||
1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875,
|
||||
1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1981,
|
||||
1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991,
|
||||
1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2028, 2029, 2030, 2031, 2032, 2033, 2100,
|
||||
2101, 2102, 2103, 2104, 2105,
|
||||
0x453B, 0x453C, 0x453D, 0x453E, 0x453F, 0x4540, 0x4541,
|
||||
0x4542, 0x4543, 0x4544, 0x4545, 0x4546, 0x4547, 0x4548,
|
||||
0x4549, 0x454A, 0x454B, 0x454C, 0x454D, 0x454E, 0x454F
|
||||
};
|
||||
|
||||
private static readonly int[] m_SandTiles = new int[]
|
||||
{
|
||||
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||
42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
|
||||
62, 68, 69, 70, 71, 72, 73, 74, 75,
|
||||
286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
|
||||
296, 297, 298, 299, 300, 301, 402, 424, 425, 426,
|
||||
427, 441, 442, 443, 444, 445, 446, 447, 448, 449,
|
||||
450, 451, 452, 453, 454, 455, 456, 457, 458, 459,
|
||||
460, 461, 462, 463, 464, 465, 642, 643, 644, 645,
|
||||
650, 651, 652, 653, 654, 655, 656, 657, 821, 822,
|
||||
823, 824, 825, 826, 827, 828, 833, 834, 835, 836,
|
||||
845, 846, 847, 848, 849, 850, 851, 852, 857, 858,
|
||||
859, 860, 951, 952, 953, 954, 955, 956, 957, 958,
|
||||
967, 968, 969, 970,
|
||||
1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455,
|
||||
1456, 1457, 1458, 1611, 1612, 1613, 1614, 1615, 1616,
|
||||
1617, 1618, 1623, 1624, 1625, 1626, 1635, 1636, 1637,
|
||||
1638, 1639, 1640, 1641, 1642, 1647, 1648, 1649, 1650
|
||||
};
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user