Reorganizes Project (#41)
This commit is contained in:
parent
08bf44af9a
commit
3614a66aee
3499 changed files with 79 additions and 55 deletions
121
Projects/Scripts/Engines/Plants/EmptyTheBowlGump.cs
Normal file
121
Projects/Scripts/Engines/Plants/EmptyTheBowlGump.cs
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
public class EmptyTheBowlGump : Gump
|
||||
{
|
||||
private PlantItem m_Plant;
|
||||
|
||||
public EmptyTheBowlGump(PlantItem plant) : base(20, 20)
|
||||
{
|
||||
m_Plant = plant;
|
||||
|
||||
DrawBackground();
|
||||
|
||||
AddLabel(90, 70, 0x44, "Empty the bowl?");
|
||||
|
||||
DrawPicture();
|
||||
|
||||
AddButton(98, 150, 0x47E, 0x480, 1); // Cancel
|
||||
|
||||
AddButton(138, 151, 0xD2, 0xD2, 2); // Help
|
||||
AddLabel(143, 151, 0x835, "?");
|
||||
|
||||
AddButton(168, 150, 0x481, 0x483, 3); // Ok
|
||||
}
|
||||
|
||||
private void DrawBackground()
|
||||
{
|
||||
AddBackground(50, 50, 200, 150, 0xE10);
|
||||
|
||||
AddItem(45, 45, 0xCEF);
|
||||
AddItem(45, 118, 0xCF0);
|
||||
|
||||
AddItem(211, 45, 0xCEB);
|
||||
AddItem(211, 118, 0xCEC);
|
||||
}
|
||||
|
||||
private void DrawPicture()
|
||||
{
|
||||
AddItem(90, 100, 0x1602);
|
||||
AddImage(140, 102, 0x15E1);
|
||||
AddItem(160, 100, 0x15FD);
|
||||
|
||||
if (m_Plant.PlantStatus != PlantStatus.BowlOfDirt && m_Plant.PlantStatus < PlantStatus.Plant)
|
||||
AddItem(156, 130, 0xDCF); // Seed
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
Mobile from = sender.Mobile;
|
||||
|
||||
if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus >= PlantStatus.DecorativePlant)
|
||||
return;
|
||||
|
||||
if (info.ButtonID == 3 && !from.InRange(m_Plant.GetWorldLocation(), 3))
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_Plant.IsUsableBy(from))
|
||||
{
|
||||
m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 1: // Cancel
|
||||
{
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Help
|
||||
{
|
||||
from.Send(new DisplayHelpTopic(71, true)); // EMPTYING THE BOWL
|
||||
|
||||
from.SendGump(new EmptyTheBowlGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Ok
|
||||
{
|
||||
PlantBowl bowl = new PlantBowl();
|
||||
|
||||
if (!from.PlaceInBackpack(bowl))
|
||||
{
|
||||
bowl.Delete();
|
||||
|
||||
m_Plant.LabelTo(from, 1053047); // You cannot empty a bowl with a full pack!
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_Plant.PlantStatus != PlantStatus.BowlOfDirt && m_Plant.PlantStatus < PlantStatus.Plant)
|
||||
{
|
||||
Seed seed = new Seed(m_Plant.PlantType, m_Plant.PlantHue, m_Plant.ShowType);
|
||||
|
||||
if (!from.PlaceInBackpack(seed))
|
||||
{
|
||||
bowl.Delete();
|
||||
seed.Delete();
|
||||
|
||||
m_Plant.LabelTo(from, 1053047); // You cannot empty a bowl with a full pack!
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_Plant.Delete();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
425
Projects/Scripts/Engines/Plants/MainPlantGump.cs
Normal file
425
Projects/Scripts/Engines/Plants/MainPlantGump.cs
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
using System;
|
||||
using Server.Gumps;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
public class MainPlantGump : Gump
|
||||
{
|
||||
private PlantItem m_Plant;
|
||||
|
||||
public MainPlantGump(PlantItem plant) : base(20, 20)
|
||||
{
|
||||
m_Plant = plant;
|
||||
|
||||
DrawBackground();
|
||||
|
||||
DrawPlant();
|
||||
|
||||
AddButton(71, 67, 0xD4, 0xD4, 1); // Reproduction menu
|
||||
AddItem(59, 68, 0xD08);
|
||||
|
||||
PlantSystem system = plant.PlantSystem;
|
||||
|
||||
AddButton(71, 91, 0xD4, 0xD4, 2); // Infestation
|
||||
AddItem(8, 96, 0x372);
|
||||
AddPlus(95, 92, system.Infestation);
|
||||
|
||||
AddButton(71, 115, 0xD4, 0xD4, 3); // Fungus
|
||||
AddItem(58, 115, 0xD16);
|
||||
AddPlus(95, 116, system.Fungus);
|
||||
|
||||
AddButton(71, 139, 0xD4, 0xD4, 4); // Poison
|
||||
AddItem(59, 143, 0x1AE4);
|
||||
AddPlus(95, 140, system.Poison);
|
||||
|
||||
AddButton(71, 163, 0xD4, 0xD4, 5); // Disease
|
||||
AddItem(55, 167, 0x1727);
|
||||
AddPlus(95, 164, system.Disease);
|
||||
|
||||
AddButton(209, 67, 0xD2, 0xD2, 6); // Water
|
||||
AddItem(193, 67, 0x1F9D);
|
||||
AddPlusMinus(196, 67, system.Water);
|
||||
|
||||
AddButton(209, 91, 0xD4, 0xD4, 7); // Poison potion
|
||||
AddItem(201, 91, 0xF0A);
|
||||
AddLevel(196, 91, system.PoisonPotion);
|
||||
|
||||
AddButton(209, 115, 0xD4, 0xD4, 8); // Cure potion
|
||||
AddItem(201, 115, 0xF07);
|
||||
AddLevel(196, 115, system.CurePotion);
|
||||
|
||||
AddButton(209, 139, 0xD4, 0xD4, 9); // Heal potion
|
||||
AddItem(201, 139, 0xF0C);
|
||||
AddLevel(196, 139, system.HealPotion);
|
||||
|
||||
AddButton(209, 163, 0xD4, 0xD4, 10); // Strength potion
|
||||
AddItem(201, 163, 0xF09);
|
||||
AddLevel(196, 163, system.StrengthPotion);
|
||||
|
||||
AddImage(48, 47, 0xD2);
|
||||
AddLevel(54, 47, (int)m_Plant.PlantStatus);
|
||||
|
||||
AddImage(232, 47, 0xD2);
|
||||
AddGrowthIndicator(239, 47);
|
||||
|
||||
AddButton(48, 183, 0xD2, 0xD2, 11); // Help
|
||||
AddLabel(54, 183, 0x835, "?");
|
||||
|
||||
AddButton(232, 183, 0xD4, 0xD4, 12); // Empty the bowl
|
||||
AddItem(219, 180, 0x15FD);
|
||||
}
|
||||
|
||||
private void DrawBackground()
|
||||
{
|
||||
AddBackground(50, 50, 200, 150, 0xE10);
|
||||
|
||||
AddItem(45, 45, 0xCEF);
|
||||
AddItem(45, 118, 0xCF0);
|
||||
|
||||
AddItem(211, 45, 0xCEB);
|
||||
AddItem(211, 118, 0xCEC);
|
||||
}
|
||||
|
||||
private void DrawPlant()
|
||||
{
|
||||
PlantStatus status = m_Plant.PlantStatus;
|
||||
|
||||
if (status < PlantStatus.FullGrownPlant)
|
||||
{
|
||||
AddImage(110, 85, 0x589);
|
||||
|
||||
AddItem(122, 94, 0x914);
|
||||
AddItem(135, 94, 0x914);
|
||||
AddItem(120, 112, 0x914);
|
||||
AddItem(135, 112, 0x914);
|
||||
|
||||
if (status >= PlantStatus.Stage2) AddItem(127, 112, 0xC62);
|
||||
if (status == PlantStatus.Stage3 || status == PlantStatus.Stage4) AddItem(129, 85, 0xC7E);
|
||||
if (status >= PlantStatus.Stage4)
|
||||
{
|
||||
AddItem(121, 117, 0xC62);
|
||||
AddItem(133, 117, 0xC62);
|
||||
}
|
||||
|
||||
if (status >= PlantStatus.Stage5)
|
||||
{
|
||||
AddItem(110, 100, 0xC62);
|
||||
AddItem(140, 100, 0xC62);
|
||||
AddItem(110, 130, 0xC62);
|
||||
AddItem(140, 130, 0xC62);
|
||||
}
|
||||
|
||||
if (status >= PlantStatus.Stage6)
|
||||
{
|
||||
AddItem(105, 115, 0xC62);
|
||||
AddItem(145, 115, 0xC62);
|
||||
AddItem(125, 90, 0xC62);
|
||||
AddItem(125, 135, 0xC62);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo(m_Plant.PlantType);
|
||||
PlantHueInfo hueInfo = PlantHueInfo.GetInfo(m_Plant.PlantHue);
|
||||
|
||||
// The large images for these trees trigger a client crash, so use a smaller, generic tree.
|
||||
if (m_Plant.PlantType == PlantType.CypressTwisted || m_Plant.PlantType == PlantType.CypressStraight)
|
||||
AddItem(130 + typeInfo.OffsetX, 96 + typeInfo.OffsetY, 0x0CCA, hueInfo.Hue);
|
||||
else
|
||||
AddItem(130 + typeInfo.OffsetX, 96 + typeInfo.OffsetY, typeInfo.ItemID, hueInfo.Hue);
|
||||
}
|
||||
|
||||
if (status != PlantStatus.BowlOfDirt)
|
||||
{
|
||||
int message = m_Plant.PlantSystem.GetLocalizedHealth();
|
||||
|
||||
switch (m_Plant.PlantSystem.Health)
|
||||
{
|
||||
case PlantHealth.Dying:
|
||||
{
|
||||
AddItem(92, 167, 0x1B9D);
|
||||
AddItem(161, 167, 0x1B9D);
|
||||
|
||||
AddHtmlLocalized(136, 167, 42, 20, message, 0x00FC00);
|
||||
|
||||
break;
|
||||
}
|
||||
case PlantHealth.Wilted:
|
||||
{
|
||||
AddItem(91, 164, 0x18E6);
|
||||
AddItem(161, 164, 0x18E6);
|
||||
|
||||
AddHtmlLocalized(132, 167, 42, 20, message, 0x00C207);
|
||||
|
||||
break;
|
||||
}
|
||||
case PlantHealth.Healthy:
|
||||
{
|
||||
AddItem(96, 168, 0xC61);
|
||||
AddItem(162, 168, 0xC61);
|
||||
|
||||
AddHtmlLocalized(129, 167, 42, 20, message, 0x008200);
|
||||
|
||||
break;
|
||||
}
|
||||
case PlantHealth.Vibrant:
|
||||
{
|
||||
AddItem(93, 162, 0x1A99);
|
||||
AddItem(162, 162, 0x1A99);
|
||||
|
||||
AddHtmlLocalized(129, 167, 42, 20, message, 0x0083E0);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddPlus(int x, int y, int value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case 1:
|
||||
AddLabel(x, y, 0x35, "+");
|
||||
break;
|
||||
case 2:
|
||||
AddLabel(x, y, 0x21, "+");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddPlusMinus(int x, int y, int value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case 0:
|
||||
AddLabel(x, y, 0x21, "-");
|
||||
break;
|
||||
case 1:
|
||||
AddLabel(x, y, 0x35, "-");
|
||||
break;
|
||||
case 3:
|
||||
AddLabel(x, y, 0x35, "+");
|
||||
break;
|
||||
case 4:
|
||||
AddLabel(x, y, 0x21, "+");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLevel(int x, int y, int value)
|
||||
{
|
||||
AddLabel(x, y, 0x835, value.ToString());
|
||||
}
|
||||
|
||||
private void AddGrowthIndicator(int x, int y)
|
||||
{
|
||||
if (!m_Plant.IsGrowable)
|
||||
return;
|
||||
|
||||
switch (m_Plant.PlantSystem.GrowthIndicator)
|
||||
{
|
||||
case PlantGrowthIndicator.InvalidLocation:
|
||||
AddLabel(x, y, 0x21, "!");
|
||||
break;
|
||||
case PlantGrowthIndicator.NotHealthy:
|
||||
AddLabel(x, y, 0x21, "-");
|
||||
break;
|
||||
case PlantGrowthIndicator.Delay:
|
||||
AddLabel(x, y, 0x35, "-");
|
||||
break;
|
||||
case PlantGrowthIndicator.Grown:
|
||||
AddLabel(x, y, 0x3, "+");
|
||||
break;
|
||||
case PlantGrowthIndicator.DoubleGrown:
|
||||
AddLabel(x, y, 0x3F, "+");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
Mobile from = sender.Mobile;
|
||||
|
||||
if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus >= PlantStatus.DecorativePlant)
|
||||
return;
|
||||
|
||||
if ((info.ButtonID >= 6 && info.ButtonID <= 10 || info.ButtonID == 12) &&
|
||||
!from.InRange(m_Plant.GetWorldLocation(), 3))
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_Plant.IsUsableBy(from))
|
||||
{
|
||||
m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 1: // Reproduction menu
|
||||
{
|
||||
if (m_Plant.PlantStatus > PlantStatus.BowlOfDirt)
|
||||
{
|
||||
from.SendGump(new ReproductionGump(m_Plant));
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1061885); // You need to plant a seed in the bowl first.
|
||||
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Infestation
|
||||
{
|
||||
from.Send(new DisplayHelpTopic(54, true)); // INFESTATION LEVEL
|
||||
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Fungus
|
||||
{
|
||||
from.Send(new DisplayHelpTopic(56, true)); // FUNGUS LEVEL
|
||||
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: // Poison
|
||||
{
|
||||
from.Send(new DisplayHelpTopic(58, true)); // POISON LEVEL
|
||||
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: // Disease
|
||||
{
|
||||
from.Send(new DisplayHelpTopic(60, true)); // DISEASE LEVEL
|
||||
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 6: // Water
|
||||
{
|
||||
BaseBeverage bev = from.Backpack.FindItemsByType<BaseBeverage>().Find(beverage =>
|
||||
beverage.IsEmpty && beverage.Pourable && beverage.Content == BeverageType.Water);
|
||||
|
||||
if (bev == null)
|
||||
{
|
||||
from.Target = new PlantPourTarget(m_Plant);
|
||||
from.SendLocalizedMessage(1060808,
|
||||
"#" + m_Plant
|
||||
.GetLocalizedPlantStatus()); // Target the container you wish to use to water the ~1_val~.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Plant.Pour(from, bev);
|
||||
}
|
||||
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 7: // Poison potion
|
||||
{
|
||||
AddPotion(from, PotionEffect.PoisonGreater, PotionEffect.PoisonDeadly);
|
||||
|
||||
break;
|
||||
}
|
||||
case 8: // Cure potion
|
||||
{
|
||||
AddPotion(from, PotionEffect.CureGreater);
|
||||
|
||||
break;
|
||||
}
|
||||
case 9: // Heal potion
|
||||
{
|
||||
AddPotion(from, PotionEffect.HealGreater);
|
||||
|
||||
break;
|
||||
}
|
||||
case 10: // Strength potion
|
||||
{
|
||||
AddPotion(from, PotionEffect.StrengthGreater);
|
||||
|
||||
break;
|
||||
}
|
||||
case 11: // Help
|
||||
{
|
||||
from.Send(new DisplayHelpTopic(48, true)); // PLANT GROWING
|
||||
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 12: // Empty the bowl
|
||||
{
|
||||
from.SendGump(new EmptyTheBowlGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddPotion(Mobile from, params PotionEffect[] effects)
|
||||
{
|
||||
Item item = GetPotion(from, effects);
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
m_Plant.Pour(from, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Plant.ApplyPotion(effects[0], true, out int message))
|
||||
{
|
||||
from.SendLocalizedMessage(1061884); // You don't have any strong potions of that type in your pack.
|
||||
|
||||
from.Target = new PlantPourTarget(m_Plant);
|
||||
from.SendLocalizedMessage(1060808,
|
||||
"#" + m_Plant
|
||||
.GetLocalizedPlantStatus()); // Target the container you wish to use to water the ~1_val~.
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_Plant.LabelTo(from, message);
|
||||
}
|
||||
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
}
|
||||
|
||||
public static Item GetPotion(Mobile from, PotionEffect[] effects)
|
||||
{
|
||||
if (from.Backpack == null)
|
||||
return null;
|
||||
|
||||
Item[] items = from.Backpack.FindItemsByType(new[] { typeof(BasePotion), typeof(PotionKeg) });
|
||||
|
||||
foreach (Item item in items)
|
||||
if (item is BasePotion potion)
|
||||
{
|
||||
if (Array.IndexOf(effects, potion.PotionEffect) >= 0)
|
||||
return potion;
|
||||
}
|
||||
else
|
||||
{
|
||||
PotionKeg keg = (PotionKeg)item;
|
||||
|
||||
if (keg.Held > 0 && Array.IndexOf(effects, keg.Type) >= 0)
|
||||
return keg;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Engines/Plants/MiscItems/FertileDirt.cs
Normal file
31
Projects/Scripts/Engines/Plants/MiscItems/FertileDirt.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class FertileDirt : Item
|
||||
{
|
||||
[Constructible]
|
||||
public FertileDirt(int amount = 1) : base(0xF81)
|
||||
{
|
||||
Stackable = true;
|
||||
Weight = 1.0;
|
||||
Amount = amount;
|
||||
}
|
||||
|
||||
public FertileDirt(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
750
Projects/Scripts/Engines/Plants/MiscItems/GreenThorns.cs
Normal file
750
Projects/Scripts/Engines/Plants/MiscItems/GreenThorns.cs
Normal file
|
|
@ -0,0 +1,750 @@
|
|||
using System;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class GreenThorns : Item
|
||||
{
|
||||
[Constructible]
|
||||
public GreenThorns(int amount = 1) : base(0xF42)
|
||||
{
|
||||
Stackable = true;
|
||||
Weight = 1.0;
|
||||
Hue = 0x42;
|
||||
Amount = amount;
|
||||
}
|
||||
|
||||
public GreenThorns(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1060837; // green thorns
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (!IsChildOf(from.Backpack))
|
||||
{
|
||||
from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!from.CanBeginAction<GreenThorns>())
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2,
|
||||
1061908); // * You must wait a while before planting another thorn. *
|
||||
return;
|
||||
}
|
||||
|
||||
from.Target = new InternalTarget(this);
|
||||
from.SendLocalizedMessage(1061906); // Choose a spot to plant the thorn.
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private GreenThorns m_Thorn;
|
||||
|
||||
public InternalTarget(GreenThorns thorn) : base(3, true, TargetFlags.None)
|
||||
{
|
||||
m_Thorn = thorn;
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
if (m_Thorn.Deleted)
|
||||
return;
|
||||
|
||||
if (!m_Thorn.IsChildOf(from.Backpack))
|
||||
{
|
||||
from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!from.CanBeginAction<GreenThorns>())
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2,
|
||||
1061908); // * You must wait a while before planting another thorn. *
|
||||
return;
|
||||
}
|
||||
|
||||
if (from.Map != Map.Trammel && from.Map != Map.Felucca)
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x2B2, true,
|
||||
"No solen lairs exist on this facet. Try again in Trammel or Felucca.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(targeted is LandTarget land))
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2,
|
||||
1061912); // * You cannot plant a green thorn there! *
|
||||
}
|
||||
else
|
||||
{
|
||||
GreenThornsEffect effect = GreenThornsEffect.Create(from, land);
|
||||
|
||||
if (effect == null)
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2,
|
||||
1061913); // * You sense it would be useless to plant a green thorn there. *
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Thorn.Consume();
|
||||
|
||||
from.LocalOverheadMessage(MessageType.Emote, 0x961,
|
||||
1061914); // * You push the strange green thorn into the ground *
|
||||
from.NonlocalOverheadMessage(MessageType.Emote, 0x961, 1061915,
|
||||
from.Name); // * ~1_PLAYER_NAME~ pushes a strange green thorn into the ground. *
|
||||
|
||||
from.BeginAction<GreenThorns>();
|
||||
new EndActionTimer(from).Start();
|
||||
|
||||
effect.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetOutOfRange(Mobile from, object targeted)
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502825); // That location is too far away
|
||||
}
|
||||
}
|
||||
|
||||
private class EndActionTimer : Timer
|
||||
{
|
||||
private Mobile m_From;
|
||||
|
||||
public EndActionTimer(Mobile from) : base(TimeSpan.FromMinutes(3.0))
|
||||
{
|
||||
m_From = from;
|
||||
Priority = TimerPriority.FiveSeconds;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_From.EndAction<GreenThorns>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class GreenThornsEffect : Timer
|
||||
{
|
||||
private static TilesAndEffect[] m_Table =
|
||||
{
|
||||
new TilesAndEffect(new[]
|
||||
{
|
||||
0x71, 0x7C,
|
||||
0x82, 0xA7,
|
||||
0xDC, 0xE3,
|
||||
0xE8, 0xEB,
|
||||
0x141, 0x144,
|
||||
0x14C, 0x14F,
|
||||
0x169, 0x174,
|
||||
0x1DC, 0x1E7,
|
||||
0x1EC, 0x1EF,
|
||||
0x272, 0x275,
|
||||
0x27E, 0x281,
|
||||
0x2D0, 0x2D7,
|
||||
0x2E5, 0x2FF,
|
||||
0x303, 0x31F,
|
||||
0x32C, 0x32F,
|
||||
0x33D, 0x340,
|
||||
0x345, 0x34C,
|
||||
0x355, 0x358,
|
||||
0x367, 0x36E,
|
||||
0x377, 0x37A,
|
||||
0x38D, 0x390,
|
||||
0x395, 0x39C,
|
||||
0x3A5, 0x3A8,
|
||||
0x3F6, 0x405,
|
||||
0x547, 0x54E,
|
||||
0x553, 0x556,
|
||||
0x597, 0x59E,
|
||||
0x623, 0x63A,
|
||||
0x6F3, 0x6FA,
|
||||
0x777, 0x791,
|
||||
0x79A, 0x7A9,
|
||||
0x7AE, 0x7B1
|
||||
},
|
||||
typeof(DirtGreenThornsEffect)),
|
||||
|
||||
new TilesAndEffect(new[]
|
||||
{
|
||||
0x9, 0x15,
|
||||
0x150, 0x15C
|
||||
},
|
||||
typeof(FurrowsGreenThornsEffect)),
|
||||
|
||||
new TilesAndEffect(new[]
|
||||
{
|
||||
0x9C4, 0x9EB,
|
||||
0x3D65, 0x3D65,
|
||||
0x3DC0, 0x3DD9,
|
||||
0x3DDB, 0x3DDC,
|
||||
0x3DDE, 0x3EF0,
|
||||
0x3FF6, 0x3FF6,
|
||||
0x3FFC, 0x3FFE
|
||||
},
|
||||
typeof(SwampGreenThornsEffect)),
|
||||
|
||||
new TilesAndEffect(new[]
|
||||
{
|
||||
0x10C, 0x10F,
|
||||
0x114, 0x117,
|
||||
0x119, 0x11D,
|
||||
0x179, 0x18A,
|
||||
0x385, 0x38C,
|
||||
0x391, 0x394,
|
||||
0x39D, 0x3A4,
|
||||
0x3A9, 0x3AC,
|
||||
0x5BF, 0x5D6,
|
||||
0x5DF, 0x5E2,
|
||||
0x745, 0x748,
|
||||
0x751, 0x758,
|
||||
0x75D, 0x760,
|
||||
0x76D, 0x773
|
||||
},
|
||||
typeof(SnowGreenThornsEffect)),
|
||||
|
||||
new TilesAndEffect(new[]
|
||||
{
|
||||
0x16, 0x3A,
|
||||
0x44, 0x4B,
|
||||
0x11E, 0x121,
|
||||
0x126, 0x12D,
|
||||
0x192, 0x192,
|
||||
0x1A8, 0x1AB,
|
||||
0x1B9, 0x1D1,
|
||||
0x282, 0x285,
|
||||
0x28A, 0x291,
|
||||
0x335, 0x33C,
|
||||
0x341, 0x344,
|
||||
0x34D, 0x354,
|
||||
0x359, 0x35C,
|
||||
0x3B7, 0x3BE,
|
||||
0x3C7, 0x3CA,
|
||||
0x5A7, 0x5B2,
|
||||
0x64B, 0x652,
|
||||
0x657, 0x65A,
|
||||
0x663, 0x66A,
|
||||
0x66F, 0x672,
|
||||
0x7BD, 0x7D0
|
||||
},
|
||||
typeof(SandGreenThornsEffect))
|
||||
};
|
||||
|
||||
private int m_Step;
|
||||
|
||||
public GreenThornsEffect(Point3D location, Map map, Mobile from) : base(TimeSpan.FromSeconds(2.5))
|
||||
{
|
||||
Location = location;
|
||||
Map = map;
|
||||
From = from;
|
||||
|
||||
Priority = TimerPriority.TwoFiftyMS;
|
||||
}
|
||||
|
||||
public Point3D Location{ get; }
|
||||
|
||||
public Map Map{ get; }
|
||||
|
||||
public Mobile From{ get; }
|
||||
|
||||
public static GreenThornsEffect Create(Mobile from, LandTarget land)
|
||||
{
|
||||
if (!from.Map.CanSpawnMobile(land.Location))
|
||||
return null;
|
||||
|
||||
int tileID = land.TileID;
|
||||
|
||||
foreach (TilesAndEffect taep in m_Table)
|
||||
{
|
||||
bool contains = false;
|
||||
|
||||
for (int i = 0; !contains && i < taep.Tiles.Length; i += 2)
|
||||
contains = tileID >= taep.Tiles[i] && tileID <= taep.Tiles[i + 1];
|
||||
|
||||
if (contains)
|
||||
{
|
||||
GreenThornsEffect effect =
|
||||
(GreenThornsEffect)Activator.CreateInstance(taep.Effect, land.Location, from.Map, from);
|
||||
return effect;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
TimeSpan nextDelay = Play(m_Step++);
|
||||
|
||||
if (nextDelay > TimeSpan.Zero)
|
||||
{
|
||||
Delay = nextDelay;
|
||||
|
||||
Start();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract TimeSpan Play(int step);
|
||||
|
||||
protected bool SpawnItem(Item item)
|
||||
{
|
||||
for (int i = 0; i < 5; i++) // Try 5 times
|
||||
{
|
||||
int x = Location.X + Utility.RandomMinMax(-1, 1);
|
||||
int y = Location.Y + Utility.RandomMinMax(-1, 1);
|
||||
int z = Map.GetAverageZ(x, y);
|
||||
|
||||
if (Map.CanFit(x, y, Location.Z, 1))
|
||||
{
|
||||
item.MoveToWorld(new Point3D(x, y, Location.Z), Map);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Map.CanFit(x, y, z, 1))
|
||||
{
|
||||
item.MoveToWorld(new Point3D(x, y, z), Map);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected bool SpawnCreature(BaseCreature creature)
|
||||
{
|
||||
for (int i = 0; i < 5; i++) // Try 5 times
|
||||
{
|
||||
int x = Location.X + Utility.RandomMinMax(-1, 1);
|
||||
int y = Location.Y + Utility.RandomMinMax(-1, 1);
|
||||
int z = Map.GetAverageZ(x, y);
|
||||
|
||||
if (Map.CanSpawnMobile(x, y, Location.Z))
|
||||
{
|
||||
creature.MoveToWorld(new Point3D(x, y, Location.Z), Map);
|
||||
creature.Combatant = From;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Map.CanSpawnMobile(x, y, z))
|
||||
{
|
||||
creature.MoveToWorld(new Point3D(x, y, z), Map);
|
||||
creature.Combatant = From;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private class TilesAndEffect
|
||||
{
|
||||
public TilesAndEffect(int[] tiles, Type effect)
|
||||
{
|
||||
Tiles = tiles;
|
||||
Effect = effect;
|
||||
}
|
||||
|
||||
public int[] Tiles{ get; }
|
||||
|
||||
public Type Effect{ get; }
|
||||
}
|
||||
}
|
||||
|
||||
public class DirtGreenThornsEffect : GreenThornsEffect
|
||||
{
|
||||
public DirtGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from)
|
||||
{
|
||||
}
|
||||
|
||||
protected override TimeSpan Play(int step)
|
||||
{
|
||||
switch (step)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x106);
|
||||
Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3735, 1,
|
||||
182, 0xBE3);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x222);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x21F);
|
||||
|
||||
return TimeSpan.FromSeconds(5.0);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
EffectItem dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0));
|
||||
dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, true,
|
||||
"* The ground erupts with chaotic growth! *");
|
||||
|
||||
Effects.PlaySound(Location, Map, 0x12D);
|
||||
|
||||
SpawnReagents();
|
||||
SpawnReagents();
|
||||
|
||||
return TimeSpan.FromSeconds(2.0);
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x12D);
|
||||
|
||||
SpawnReagents();
|
||||
SpawnReagents();
|
||||
|
||||
return TimeSpan.FromSeconds(2.0);
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x12D);
|
||||
|
||||
SpawnReagents();
|
||||
SpawnReagents();
|
||||
|
||||
return TimeSpan.FromSeconds(3.0);
|
||||
}
|
||||
default:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x12D);
|
||||
|
||||
SpawnReagents();
|
||||
SpawnReagents();
|
||||
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SpawnReagents()
|
||||
{
|
||||
Item reagents;
|
||||
int amount = Utility.RandomMinMax(10, 25);
|
||||
|
||||
switch (Utility.Random(9))
|
||||
{
|
||||
case 0:
|
||||
reagents = new BlackPearl(amount);
|
||||
break;
|
||||
case 1:
|
||||
reagents = new Bloodmoss(amount);
|
||||
break;
|
||||
case 2:
|
||||
reagents = new Garlic(amount);
|
||||
break;
|
||||
case 3:
|
||||
reagents = new Ginseng(amount);
|
||||
break;
|
||||
case 4:
|
||||
reagents = new MandrakeRoot(amount);
|
||||
break;
|
||||
case 5:
|
||||
reagents = new Nightshade(amount);
|
||||
break;
|
||||
case 6:
|
||||
reagents = new SulfurousAsh(amount);
|
||||
break;
|
||||
case 7:
|
||||
reagents = new SpidersSilk(amount);
|
||||
break;
|
||||
default:
|
||||
reagents = new FertileDirt(amount);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!SpawnItem(reagents))
|
||||
reagents.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
public class FurrowsGreenThornsEffect : GreenThornsEffect
|
||||
{
|
||||
public FurrowsGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from)
|
||||
{
|
||||
}
|
||||
|
||||
protected override TimeSpan Play(int step)
|
||||
{
|
||||
switch (step)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x106);
|
||||
Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3735, 1,
|
||||
182, 0xBE3);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
EffectItem hole = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(10.0));
|
||||
hole.ItemID = 0x913;
|
||||
|
||||
Effects.PlaySound(Location, Map, 0x222);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x21F);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
default:
|
||||
{
|
||||
EffectItem dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0));
|
||||
dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, true,
|
||||
"* A magical bunny leaps out of its hole, disturbed by the thorn's effect! *");
|
||||
|
||||
BaseCreature spawn = new VorpalBunny();
|
||||
if (!SpawnCreature(spawn))
|
||||
spawn.Delete();
|
||||
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SwampGreenThornsEffect : GreenThornsEffect
|
||||
{
|
||||
public SwampGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from)
|
||||
{
|
||||
}
|
||||
|
||||
protected override TimeSpan Play(int step)
|
||||
{
|
||||
switch (step)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x106);
|
||||
Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3735, 1,
|
||||
182, 0xBE3);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x222);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x21F);
|
||||
|
||||
return TimeSpan.FromSeconds(1.0);
|
||||
}
|
||||
default:
|
||||
{
|
||||
EffectItem dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0));
|
||||
dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, true,
|
||||
"* Strange green tendrils rise from the ground, whipping wildly! *");
|
||||
Effects.PlaySound(Location, Map, 0x2B0);
|
||||
|
||||
BaseCreature spawn = new WhippingVine();
|
||||
if (!SpawnCreature(spawn))
|
||||
spawn.Delete();
|
||||
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SnowGreenThornsEffect : GreenThornsEffect
|
||||
{
|
||||
public SnowGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from)
|
||||
{
|
||||
}
|
||||
|
||||
protected override TimeSpan Play(int step)
|
||||
{
|
||||
switch (step)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x106);
|
||||
Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3735, 1,
|
||||
182, 0xBE3);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x222);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x21F);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
default:
|
||||
{
|
||||
EffectItem dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0));
|
||||
dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, true,
|
||||
"* Slithering ice serpents rise to the surface to investigate the disturbance! *");
|
||||
|
||||
BaseCreature spawn = new GiantIceWorm();
|
||||
if (!SpawnCreature(spawn))
|
||||
spawn.Delete();
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
BaseCreature snake = new IceSnake();
|
||||
if (!SpawnCreature(snake))
|
||||
snake.Delete();
|
||||
}
|
||||
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SandGreenThornsEffect : GreenThornsEffect
|
||||
{
|
||||
public SandGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from)
|
||||
{
|
||||
}
|
||||
|
||||
protected override TimeSpan Play(int step)
|
||||
{
|
||||
switch (step)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x106);
|
||||
Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3735, 1,
|
||||
182, 0xBE3);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x222);
|
||||
|
||||
return TimeSpan.FromSeconds(4.0);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x21F);
|
||||
|
||||
return TimeSpan.FromSeconds(5.0);
|
||||
}
|
||||
default:
|
||||
{
|
||||
EffectItem dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0));
|
||||
dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, true,
|
||||
"* The sand collapses, revealing a dark hole. *");
|
||||
|
||||
GreenThornsSHTeleporter.Create(Location, Map);
|
||||
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class GreenThornsSHTeleporter : Item
|
||||
{
|
||||
public static readonly Point3D Destination = new Point3D(5738, 1856, 0);
|
||||
|
||||
private GreenThornsSHTeleporter() : base(0x913)
|
||||
{
|
||||
Movable = false;
|
||||
Hue = 0x1;
|
||||
}
|
||||
|
||||
public GreenThornsSHTeleporter(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "a hole";
|
||||
|
||||
public static void Create(Point3D location, Map map)
|
||||
{
|
||||
GreenThornsSHTeleporter tele = new GreenThornsSHTeleporter();
|
||||
|
||||
tele.MoveToWorld(location, map);
|
||||
|
||||
new InternalTimer(tele).Start();
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (from.InRange(this, 3))
|
||||
{
|
||||
BaseCreature.TeleportPets(from, Destination, Map);
|
||||
|
||||
from.Location = Destination;
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1019045); // I can't reach that.
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
Delete();
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private GreenThornsSHTeleporter m_Teleporter;
|
||||
|
||||
public InternalTimer(GreenThornsSHTeleporter teleporter) : base(TimeSpan.FromMinutes(1.0))
|
||||
{
|
||||
m_Teleporter = teleporter;
|
||||
Priority = TimerPriority.FiveSeconds;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_Teleporter.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
136
Projects/Scripts/Engines/Plants/MiscItems/OrangePetals.cs
Normal file
136
Projects/Scripts/Engines/Plants/MiscItems/OrangePetals.cs
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class OrangePetals : Item
|
||||
{
|
||||
private static Dictionary<Mobile, OrangePetalsContext> m_Table = new Dictionary<Mobile, OrangePetalsContext>();
|
||||
|
||||
[Constructible]
|
||||
public OrangePetals(int amount = 1) : base(0x1021)
|
||||
{
|
||||
Stackable = true;
|
||||
Hue = 0x2B;
|
||||
Amount = amount;
|
||||
}
|
||||
|
||||
public OrangePetals(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1053122; // orange petals
|
||||
|
||||
public override double DefaultWeight => 0.1;
|
||||
|
||||
public override bool CheckItemUse(Mobile from, Item item)
|
||||
{
|
||||
if (item != this)
|
||||
return base.CheckItemUse(from, item);
|
||||
|
||||
if (from != RootParent)
|
||||
{
|
||||
from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it.
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.CheckItemUse(from, item);
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
OrangePetalsContext context = GetContext(from);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061904);
|
||||
return;
|
||||
}
|
||||
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061905);
|
||||
from.PlaySound(0x3B);
|
||||
|
||||
Timer timer = new OrangePetalsTimer(from);
|
||||
timer.Start();
|
||||
|
||||
AddContext(from, new OrangePetalsContext(timer));
|
||||
|
||||
Consume();
|
||||
}
|
||||
|
||||
private static void AddContext(Mobile m, OrangePetalsContext context)
|
||||
{
|
||||
m_Table[m] = context;
|
||||
}
|
||||
|
||||
public static void RemoveContext(Mobile m)
|
||||
{
|
||||
OrangePetalsContext context = GetContext(m);
|
||||
|
||||
if (context != null)
|
||||
RemoveContext(m, context);
|
||||
}
|
||||
|
||||
private static void RemoveContext(Mobile m, OrangePetalsContext context)
|
||||
{
|
||||
m_Table.Remove(m);
|
||||
|
||||
context.Timer.Stop();
|
||||
}
|
||||
|
||||
private static OrangePetalsContext GetContext(Mobile m)
|
||||
{
|
||||
m_Table.TryGetValue(m, out OrangePetalsContext context);
|
||||
return context;
|
||||
}
|
||||
|
||||
public static bool UnderEffect(Mobile m)
|
||||
{
|
||||
return m_Table.ContainsKey(m);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
|
||||
private class OrangePetalsTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
|
||||
public OrangePetalsTimer(Mobile from) : base(TimeSpan.FromMinutes(5.0))
|
||||
{
|
||||
m_Mobile = from;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (!m_Mobile.Deleted)
|
||||
m_Mobile.LocalOverheadMessage(MessageType.Regular, 0x3F, true,
|
||||
"* You feel the effects of your poison resistance wearing off *");
|
||||
|
||||
RemoveContext(m_Mobile);
|
||||
}
|
||||
}
|
||||
|
||||
private class OrangePetalsContext
|
||||
{
|
||||
public OrangePetalsContext(Timer timer)
|
||||
{
|
||||
Timer = timer;
|
||||
}
|
||||
|
||||
public Timer Timer{ get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
96
Projects/Scripts/Engines/Plants/MiscItems/RedLeaves.cs
Normal file
96
Projects/Scripts/Engines/Plants/MiscItems/RedLeaves.cs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
using Server.Targeting;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class RedLeaves : Item
|
||||
{
|
||||
[Constructible]
|
||||
public RedLeaves(int amount = 1) : base(0x1E85)
|
||||
{
|
||||
Stackable = true;
|
||||
Hue = 0x21;
|
||||
Amount = amount;
|
||||
}
|
||||
|
||||
public RedLeaves(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1053123; // red leaves
|
||||
|
||||
public override double DefaultWeight => 0.1;
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (!IsChildOf(from.Backpack))
|
||||
{
|
||||
from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
from.Target = new InternalTarget(this);
|
||||
from.SendLocalizedMessage(1061907); // Choose a book you wish to seal with the wax from the red leaf.
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private RedLeaves m_RedLeaves;
|
||||
|
||||
public InternalTarget(RedLeaves redLeaves) : base(3, false, TargetFlags.None)
|
||||
{
|
||||
m_RedLeaves = redLeaves;
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
if (m_RedLeaves.Deleted)
|
||||
return;
|
||||
|
||||
if (!m_RedLeaves.IsChildOf(from.Backpack))
|
||||
{
|
||||
from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(targeted is Item item) || !item.IsChildOf(from.Backpack))
|
||||
{
|
||||
from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it.
|
||||
}
|
||||
else if (!(item is BaseBook))
|
||||
{
|
||||
item.LabelTo(from, 1061911); // You can only use red leaves to seal the ink into book pages!
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseBook book = (BaseBook)item;
|
||||
|
||||
if (!book.Writable)
|
||||
{
|
||||
book.LabelTo(from, 1061909); // The ink in this book has already been sealed.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RedLeaves.Consume();
|
||||
book.Writable = false;
|
||||
|
||||
book.LabelTo(from, 1061910); // You seal the ink to the page using wax from the red leaf.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
71
Projects/Scripts/Engines/Plants/MiscMobiles/GiantIceWorm.cs
Normal file
71
Projects/Scripts/Engines/Plants/MiscMobiles/GiantIceWorm.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
namespace Server.Mobiles
|
||||
{
|
||||
public class GiantIceWorm : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public GiantIceWorm() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
Body = 89;
|
||||
BaseSoundID = 0xDC;
|
||||
|
||||
SetStr(216, 245);
|
||||
SetDex(76, 100);
|
||||
SetInt(66, 85);
|
||||
|
||||
SetHits(130, 147);
|
||||
|
||||
SetDamage(7, 17);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 10);
|
||||
SetDamageType(ResistanceType.Cold, 90);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 30, 35);
|
||||
SetResistance(ResistanceType.Fire, 0);
|
||||
SetResistance(ResistanceType.Cold, 80, 90);
|
||||
SetResistance(ResistanceType.Poison, 15, 25);
|
||||
SetResistance(ResistanceType.Energy, 10, 20);
|
||||
|
||||
SetSkill(SkillName.Poisoning, 75.1, 95.0);
|
||||
SetSkill(SkillName.MagicResist, 45.1, 60.0);
|
||||
SetSkill(SkillName.Tactics, 75.1, 80.0);
|
||||
SetSkill(SkillName.Wrestling, 60.1, 80.0);
|
||||
|
||||
Fame = 4500;
|
||||
Karma = -4500;
|
||||
|
||||
VirtualArmor = 40;
|
||||
|
||||
Tamable = true;
|
||||
ControlSlots = 1;
|
||||
MinTameSkill = 71.1;
|
||||
}
|
||||
|
||||
public GiantIceWorm(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string CorpseName => "a giant ice worm corpse";
|
||||
public override bool SubdueBeforeTame => true;
|
||||
public override string DefaultName => "a giant ice worm";
|
||||
|
||||
public override Poison PoisonImmune => Poison.Greater;
|
||||
|
||||
public override Poison HitPoison => Poison.Greater;
|
||||
|
||||
public override FoodType FavoriteFood => FoodType.Meat;
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Projects/Scripts/Engines/Plants/Network/DisplayHelpTopic.cs
Normal file
15
Projects/Scripts/Engines/Plants/Network/DisplayHelpTopic.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
namespace Server.Network
|
||||
{
|
||||
public class DisplayHelpTopic : Packet
|
||||
{
|
||||
public DisplayHelpTopic(int topicID, bool display) : base(0xBF)
|
||||
{
|
||||
EnsureCapacity(11);
|
||||
|
||||
m_Stream.Write((short)0x17);
|
||||
m_Stream.Write((byte)1);
|
||||
m_Stream.Write(topicID);
|
||||
m_Stream.Write(display);
|
||||
}
|
||||
}
|
||||
}
|
||||
194
Projects/Scripts/Engines/Plants/PlantBowl.cs
Normal file
194
Projects/Scripts/Engines/Plants/PlantBowl.cs
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
using Server.Items;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
public class PlantBowl : Item
|
||||
{
|
||||
private static int[] m_DirtPatchTiles =
|
||||
{
|
||||
0x9, 0x15,
|
||||
0x71, 0x7C,
|
||||
0x82, 0xA7,
|
||||
0xDC, 0xE3,
|
||||
0xE8, 0xEB,
|
||||
0x141, 0x144,
|
||||
0x14C, 0x15C,
|
||||
0x169, 0x174,
|
||||
0x1DC, 0x1EF,
|
||||
0x272, 0x275,
|
||||
0x27E, 0x281,
|
||||
0x2D0, 0x2D7,
|
||||
0x2E5, 0x2FF,
|
||||
0x303, 0x31F,
|
||||
0x32C, 0x32F,
|
||||
0x33D, 0x340,
|
||||
0x345, 0x34C,
|
||||
0x355, 0x358,
|
||||
0x367, 0x36E,
|
||||
0x377, 0x37A,
|
||||
0x38D, 0x390,
|
||||
0x395, 0x39C,
|
||||
0x3A5, 0x3A8,
|
||||
0x3F6, 0x405,
|
||||
0x547, 0x54E,
|
||||
0x553, 0x556,
|
||||
0x597, 0x59E,
|
||||
0x623, 0x63A,
|
||||
0x6F3, 0x6FA,
|
||||
0x777, 0x791,
|
||||
0x79A, 0x7A9,
|
||||
0x7AE, 0x7B1,
|
||||
0x98C, 0x99F,
|
||||
0x9AC, 0x9BF,
|
||||
0x5B27, 0x5B3E,
|
||||
0x71F4, 0x71FB,
|
||||
0x72C9, 0x72CA
|
||||
};
|
||||
|
||||
[Constructible]
|
||||
public PlantBowl() : base(0x15FD)
|
||||
{
|
||||
Weight = 1.0;
|
||||
}
|
||||
|
||||
public PlantBowl(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1060834; // a plant bowl
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (!IsChildOf(from.Backpack))
|
||||
{
|
||||
from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
from.Target = new InternalTarget(this);
|
||||
from.SendLocalizedMessage(1061897); // Choose a patch of dirt to scoop up.
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
|
||||
public static bool IsDirtPatch(object obj)
|
||||
{
|
||||
int tileID;
|
||||
|
||||
if (obj is Static staticObj && !staticObj.Movable)
|
||||
tileID = (staticObj.ItemID & 0x3FFF) | 0x4000;
|
||||
else if (obj is StaticTarget staticTarget)
|
||||
tileID = (staticTarget.ItemID & 0x3FFF) | 0x4000;
|
||||
else if (obj is LandTarget landTarget)
|
||||
tileID = landTarget.TileID;
|
||||
else
|
||||
return false;
|
||||
|
||||
bool contains = false;
|
||||
|
||||
for (int i = 0; !contains && i < m_DirtPatchTiles.Length; i += 2)
|
||||
contains = tileID >= m_DirtPatchTiles[i] && tileID <= m_DirtPatchTiles[i + 1];
|
||||
|
||||
return contains;
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private PlantBowl m_PlantBowl;
|
||||
|
||||
public InternalTarget(PlantBowl plantBowl) : base(3, true, TargetFlags.None)
|
||||
{
|
||||
m_PlantBowl = plantBowl;
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
if (m_PlantBowl.Deleted)
|
||||
return;
|
||||
|
||||
if (!m_PlantBowl.IsChildOf(from.Backpack))
|
||||
{
|
||||
from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (targeted is FertileDirt dirt)
|
||||
{
|
||||
int _dirtNeeded = Core.ML ? 20 : 40;
|
||||
|
||||
if (!dirt.IsChildOf(from.Backpack))
|
||||
{
|
||||
from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it.
|
||||
}
|
||||
else if (dirt.Amount < _dirtNeeded)
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2,
|
||||
1061896); // You need more dirt to fill a plant bowl!
|
||||
}
|
||||
else
|
||||
{
|
||||
PlantItem fullBowl = new PlantItem(true);
|
||||
|
||||
if (from.PlaceInBackpack(fullBowl))
|
||||
{
|
||||
dirt.Consume(_dirtNeeded);
|
||||
m_PlantBowl.Delete();
|
||||
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2,
|
||||
1061895); // You fill the bowl with fresh dirt.
|
||||
}
|
||||
else
|
||||
{
|
||||
fullBowl.Delete();
|
||||
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2,
|
||||
1061894); // There is no room in your backpack for a bowl full of dirt!
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (IsDirtPatch(targeted))
|
||||
{
|
||||
PlantItem fullBowl = new PlantItem();
|
||||
|
||||
if (from.PlaceInBackpack(fullBowl))
|
||||
{
|
||||
m_PlantBowl.Delete();
|
||||
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061895); // You fill the bowl with fresh dirt.
|
||||
}
|
||||
else
|
||||
{
|
||||
fullBowl.Delete();
|
||||
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2,
|
||||
1061894); // There is no room in your backpack for a bowl full of dirt!
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2,
|
||||
1061893); // You'll want to gather fresh dirt in order to raise a healthy plant!
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetOutOfRange(Mobile from, object targeted)
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502825); // That location is too far away
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
184
Projects/Scripts/Engines/Plants/PlantHue.cs
Normal file
184
Projects/Scripts/Engines/Plants/PlantHue.cs
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
[Flags]
|
||||
public enum PlantHue
|
||||
{
|
||||
Plain = 0x1 | Crossable | Reproduces,
|
||||
|
||||
Red = 0x2 | Crossable | Reproduces,
|
||||
Blue = 0x4 | Crossable | Reproduces,
|
||||
Yellow = 0x8 | Crossable | Reproduces,
|
||||
|
||||
BrightRed = Red | Bright,
|
||||
BrightBlue = Blue | Bright,
|
||||
BrightYellow = Yellow | Bright,
|
||||
|
||||
Purple = Red | Blue,
|
||||
Green = Blue | Yellow,
|
||||
Orange = Red | Yellow,
|
||||
|
||||
BrightPurple = Purple | Bright,
|
||||
BrightGreen = Green | Bright,
|
||||
BrightOrange = Orange | Bright,
|
||||
|
||||
Black = 0x10,
|
||||
White = 0x20,
|
||||
Pink = 0x40,
|
||||
Magenta = 0x80,
|
||||
Aqua = 0x100,
|
||||
FireRed = 0x200,
|
||||
|
||||
None = 0,
|
||||
Reproduces = 0x2000000,
|
||||
Crossable = 0x4000000,
|
||||
Bright = 0x8000000
|
||||
}
|
||||
|
||||
public class PlantHueInfo
|
||||
{
|
||||
private static Dictionary<PlantHue, PlantHueInfo> m_Table;
|
||||
|
||||
static PlantHueInfo()
|
||||
{
|
||||
m_Table = new Dictionary<PlantHue, PlantHueInfo>
|
||||
{
|
||||
[PlantHue.Plain] = new PlantHueInfo(0, 1060813, PlantHue.Plain, 0x835),
|
||||
[PlantHue.Red] = new PlantHueInfo(0x66D, 1060814, PlantHue.Red, 0x24),
|
||||
[PlantHue.Blue] = new PlantHueInfo(0x53D, 1060815, PlantHue.Blue, 0x6),
|
||||
[PlantHue.Yellow] = new PlantHueInfo(0x8A5, 1060818, PlantHue.Yellow, 0x38),
|
||||
[PlantHue.BrightRed] = new PlantHueInfo(0x21, 1060814, PlantHue.BrightRed, 0x21),
|
||||
[PlantHue.BrightBlue] = new PlantHueInfo(0x5, 1060815, PlantHue.BrightBlue, 0x6),
|
||||
[PlantHue.BrightYellow] = new PlantHueInfo(0x38, 1060818, PlantHue.BrightYellow, 0x35),
|
||||
[PlantHue.Purple] = new PlantHueInfo(0xD, 1060816, PlantHue.Purple, 0x10),
|
||||
[PlantHue.Green] = new PlantHueInfo(0x59B, 1060819, PlantHue.Green, 0x42),
|
||||
[PlantHue.Orange] = new PlantHueInfo(0x46F, 1060817, PlantHue.Orange, 0x2E),
|
||||
[PlantHue.BrightPurple] = new PlantHueInfo(0x10, 1060816, PlantHue.BrightPurple, 0xD),
|
||||
[PlantHue.BrightGreen] = new PlantHueInfo(0x42, 1060819, PlantHue.BrightGreen, 0x3F),
|
||||
[PlantHue.BrightOrange] = new PlantHueInfo(0x2B, 1060817, PlantHue.BrightOrange, 0x2B),
|
||||
[PlantHue.Black] = new PlantHueInfo(0x455, 1060820, PlantHue.Black, 0),
|
||||
[PlantHue.White] = new PlantHueInfo(0x481, 1060821, PlantHue.White, 0x481),
|
||||
[PlantHue.Pink] = new PlantHueInfo(0x48E, 1061854, PlantHue.Pink),
|
||||
[PlantHue.Magenta] = new PlantHueInfo(0x486, 1061852, PlantHue.Magenta),
|
||||
[PlantHue.Aqua] = new PlantHueInfo(0x495, 1061853, PlantHue.Aqua),
|
||||
[PlantHue.FireRed] = new PlantHueInfo(0x489, 1061855, PlantHue.FireRed)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
private PlantHueInfo(int hue, int name, PlantHue plantHue) : this(hue, name, plantHue, hue)
|
||||
{
|
||||
}
|
||||
|
||||
private PlantHueInfo(int hue, int name, PlantHue plantHue, int gumpHue)
|
||||
{
|
||||
Hue = hue;
|
||||
Name = name;
|
||||
PlantHue = plantHue;
|
||||
GumpHue = gumpHue;
|
||||
}
|
||||
|
||||
public int Hue{ get; }
|
||||
|
||||
public int Name{ get; }
|
||||
|
||||
public PlantHue PlantHue{ get; }
|
||||
|
||||
public int GumpHue{ get; }
|
||||
|
||||
public static PlantHueInfo GetInfo(PlantHue plantHue)
|
||||
{
|
||||
return m_Table.TryGetValue(plantHue, out PlantHueInfo info) ? info : m_Table[PlantHue.Plain];
|
||||
}
|
||||
|
||||
public static PlantHue RandomFirstGeneration()
|
||||
{
|
||||
switch (Utility.Random(4))
|
||||
{
|
||||
case 0: return PlantHue.Plain;
|
||||
case 1: return PlantHue.Red;
|
||||
case 2: return PlantHue.Blue;
|
||||
default: return PlantHue.Yellow;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CanReproduce(PlantHue plantHue)
|
||||
{
|
||||
return (plantHue & PlantHue.Reproduces) != PlantHue.None;
|
||||
}
|
||||
|
||||
public static bool IsCrossable(PlantHue plantHue)
|
||||
{
|
||||
return (plantHue & PlantHue.Crossable) != PlantHue.None;
|
||||
}
|
||||
|
||||
public static bool IsBright(PlantHue plantHue)
|
||||
{
|
||||
return (plantHue & PlantHue.Bright) != PlantHue.None;
|
||||
}
|
||||
|
||||
public static PlantHue GetNotBright(PlantHue plantHue)
|
||||
{
|
||||
return plantHue & ~PlantHue.Bright;
|
||||
}
|
||||
|
||||
public static bool IsPrimary(PlantHue plantHue)
|
||||
{
|
||||
return plantHue == PlantHue.Red || plantHue == PlantHue.Blue || plantHue == PlantHue.Yellow;
|
||||
}
|
||||
|
||||
public static PlantHue Cross(PlantHue first, PlantHue second)
|
||||
{
|
||||
if (!IsCrossable(first) || !IsCrossable(second))
|
||||
return PlantHue.None;
|
||||
|
||||
if (Utility.RandomDouble() < 0.01)
|
||||
return Utility.RandomBool() ? PlantHue.Black : PlantHue.White;
|
||||
|
||||
if (first == PlantHue.Plain || second == PlantHue.Plain)
|
||||
return PlantHue.Plain;
|
||||
|
||||
PlantHue notBrightFirst = GetNotBright(first);
|
||||
PlantHue notBrightSecond = GetNotBright(second);
|
||||
|
||||
if (notBrightFirst == notBrightSecond)
|
||||
return first | PlantHue.Bright;
|
||||
|
||||
bool firstPrimary = IsPrimary(notBrightFirst);
|
||||
bool secondPrimary = IsPrimary(notBrightSecond);
|
||||
|
||||
if (firstPrimary && secondPrimary)
|
||||
return notBrightFirst | notBrightSecond;
|
||||
|
||||
if (firstPrimary)
|
||||
return notBrightFirst;
|
||||
|
||||
if (secondPrimary)
|
||||
return notBrightSecond;
|
||||
|
||||
return notBrightFirst & notBrightSecond;
|
||||
}
|
||||
|
||||
public bool IsCrossable()
|
||||
{
|
||||
return IsCrossable(PlantHue);
|
||||
}
|
||||
|
||||
public bool IsBright()
|
||||
{
|
||||
return IsBright(PlantHue);
|
||||
}
|
||||
|
||||
public PlantHue GetNotBright()
|
||||
{
|
||||
return GetNotBright(PlantHue);
|
||||
}
|
||||
|
||||
public bool IsPrimary()
|
||||
{
|
||||
return IsPrimary(PlantHue);
|
||||
}
|
||||
}
|
||||
}
|
||||
558
Projects/Scripts/Engines/Plants/PlantItem.cs
Normal file
558
Projects/Scripts/Engines/Plants/PlantItem.cs
Normal file
|
|
@ -0,0 +1,558 @@
|
|||
using System.Collections.Generic;
|
||||
using Server.ContextMenus;
|
||||
using Server.Gumps;
|
||||
using Server.Items;
|
||||
using Server.Multis;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
public enum PlantStatus
|
||||
{
|
||||
BowlOfDirt = 0,
|
||||
Seed = 1,
|
||||
Sapling = 2,
|
||||
Plant = 4,
|
||||
FullGrownPlant = 7,
|
||||
DecorativePlant = 10,
|
||||
DeadTwigs = 11,
|
||||
|
||||
Stage1 = 1,
|
||||
Stage2 = 2,
|
||||
Stage3 = 3,
|
||||
Stage4 = 4,
|
||||
Stage5 = 5,
|
||||
Stage6 = 6,
|
||||
Stage7 = 7,
|
||||
Stage8 = 8,
|
||||
Stage9 = 9
|
||||
}
|
||||
|
||||
public class PlantItem : Item, ISecurable
|
||||
{
|
||||
/*
|
||||
* Clients 7.0.12.0+ expect a container type in the plant label.
|
||||
* To support older (and only older) clients, change this to false.
|
||||
*/
|
||||
private static readonly bool ShowContainerType = true;
|
||||
private PlantHue m_PlantHue;
|
||||
|
||||
private PlantStatus m_PlantStatus;
|
||||
private PlantType m_PlantType;
|
||||
private bool m_ShowType;
|
||||
|
||||
[Constructible]
|
||||
public PlantItem(bool fertileDirt = false) : base(0x1602)
|
||||
{
|
||||
Weight = 1.0;
|
||||
|
||||
m_PlantStatus = PlantStatus.BowlOfDirt;
|
||||
PlantSystem = new PlantSystem(this, fertileDirt);
|
||||
Level = SecureLevel.Owner;
|
||||
|
||||
Plants.Add(this);
|
||||
}
|
||||
|
||||
public PlantItem(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public PlantSystem PlantSystem{ get; private set; }
|
||||
|
||||
public override bool ForceShowProperties => ObjectPropertyList.Enabled;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public PlantStatus PlantStatus
|
||||
{
|
||||
get => m_PlantStatus;
|
||||
set
|
||||
{
|
||||
if (m_PlantStatus == value || value < PlantStatus.BowlOfDirt || value > PlantStatus.DeadTwigs)
|
||||
return;
|
||||
|
||||
double ratio;
|
||||
if (PlantSystem != null)
|
||||
ratio = (double)PlantSystem.Hits / PlantSystem.MaxHits;
|
||||
else
|
||||
ratio = 1.0;
|
||||
|
||||
m_PlantStatus = value;
|
||||
|
||||
if (m_PlantStatus >= PlantStatus.DecorativePlant)
|
||||
{
|
||||
PlantSystem = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PlantSystem == null)
|
||||
PlantSystem = new PlantSystem(this, false);
|
||||
|
||||
int hits = (int)(PlantSystem.MaxHits * ratio);
|
||||
|
||||
if (hits == 0 && m_PlantStatus > PlantStatus.BowlOfDirt)
|
||||
PlantSystem.Hits = hits + 1;
|
||||
else
|
||||
PlantSystem.Hits = hits;
|
||||
}
|
||||
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public PlantType PlantType
|
||||
{
|
||||
get => m_PlantType;
|
||||
set
|
||||
{
|
||||
m_PlantType = value;
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public PlantHue PlantHue
|
||||
{
|
||||
get => m_PlantHue;
|
||||
set
|
||||
{
|
||||
m_PlantHue = value;
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool ShowType
|
||||
{
|
||||
get => m_ShowType;
|
||||
set
|
||||
{
|
||||
m_ShowType = value;
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool ValidGrowthLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsLockedDown && RootParent == null)
|
||||
return true;
|
||||
|
||||
|
||||
if (!(RootParent is Mobile owner))
|
||||
return false;
|
||||
|
||||
return IsChildOf(owner.Backpack) || IsChildOf(owner.FindBankNoCreate());
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool IsGrowable => m_PlantStatus >= PlantStatus.BowlOfDirt && m_PlantStatus <= PlantStatus.Stage9;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool IsCrossable => PlantHueInfo.IsCrossable(PlantHue) && PlantTypeInfo.IsCrossable(PlantType);
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool Reproduces => PlantHueInfo.CanReproduce(PlantHue) && PlantTypeInfo.CanReproduce(PlantType);
|
||||
|
||||
public static List<PlantItem> Plants{ get; } = new List<PlantItem>();
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public SecureLevel Level{ get; set; }
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
if (m_PlantStatus >= PlantStatus.DeadTwigs)
|
||||
LabelTo(from, LabelNumber);
|
||||
else if (m_PlantStatus >= PlantStatus.DecorativePlant)
|
||||
LabelTo(from, 1061924); // a decorative plant
|
||||
else if (m_PlantStatus >= PlantStatus.FullGrownPlant)
|
||||
LabelTo(from, PlantTypeInfo.GetInfo(m_PlantType).Name);
|
||||
else
|
||||
LabelTo(from, 1029913); // plant bowl
|
||||
}
|
||||
|
||||
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
|
||||
{
|
||||
base.GetContextMenuEntries(from, list);
|
||||
SetSecureLevelEntry.AddTo(from, this, list);
|
||||
}
|
||||
|
||||
public int GetLocalizedPlantStatus()
|
||||
{
|
||||
if (m_PlantStatus >= PlantStatus.Plant)
|
||||
return 1060812; // plant
|
||||
if (m_PlantStatus >= PlantStatus.Sapling)
|
||||
return 1023305; // sapling
|
||||
if (m_PlantStatus >= PlantStatus.Seed)
|
||||
return 1060810; // seed
|
||||
return 1026951; // dirt
|
||||
}
|
||||
|
||||
public int GetLocalizedContainerType()
|
||||
{
|
||||
return 1150435; // bowl
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (m_PlantStatus >= PlantStatus.DeadTwigs)
|
||||
{
|
||||
ItemID = 0x1B9D;
|
||||
Hue = PlantHueInfo.GetInfo(m_PlantHue).Hue;
|
||||
}
|
||||
else if (m_PlantStatus >= PlantStatus.FullGrownPlant)
|
||||
{
|
||||
ItemID = PlantTypeInfo.GetInfo(m_PlantType).ItemID;
|
||||
Hue = PlantHueInfo.GetInfo(m_PlantHue).Hue;
|
||||
}
|
||||
else if (m_PlantStatus >= PlantStatus.Plant)
|
||||
{
|
||||
ItemID = 0x1600;
|
||||
Hue = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemID = 0x1602;
|
||||
Hue = 0;
|
||||
}
|
||||
|
||||
InvalidateProperties();
|
||||
}
|
||||
|
||||
public override void AddNameProperty(ObjectPropertyList list)
|
||||
{
|
||||
if (m_PlantStatus >= PlantStatus.DeadTwigs)
|
||||
{
|
||||
base.AddNameProperty(list);
|
||||
}
|
||||
else if (m_PlantStatus < PlantStatus.Seed)
|
||||
{
|
||||
string args;
|
||||
|
||||
if (ShowContainerType)
|
||||
args = $"#{GetLocalizedContainerType()}\t#{PlantSystem.GetLocalizedDirtStatus()}";
|
||||
else
|
||||
args = $"#{PlantSystem.GetLocalizedDirtStatus()}";
|
||||
|
||||
list.Add(1060830, args); // a ~1_val~ of ~2_val~ dirt
|
||||
}
|
||||
else
|
||||
{
|
||||
PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo(m_PlantType);
|
||||
PlantHueInfo hueInfo = PlantHueInfo.GetInfo(m_PlantHue);
|
||||
|
||||
if (m_PlantStatus >= PlantStatus.DecorativePlant)
|
||||
{
|
||||
list.Add(typeInfo.GetPlantLabelDecorative(hueInfo), $"#{hueInfo.Name}\t#{typeInfo.Name}");
|
||||
}
|
||||
else if (m_PlantStatus >= PlantStatus.FullGrownPlant)
|
||||
{
|
||||
list.Add(typeInfo.GetPlantLabelFullGrown(hueInfo),
|
||||
$"#{PlantSystem.GetLocalizedHealth()}\t#{hueInfo.Name}\t#{typeInfo.Name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
string args;
|
||||
|
||||
if (ShowContainerType)
|
||||
args =
|
||||
$"#{GetLocalizedContainerType()}\t#{PlantSystem.GetLocalizedDirtStatus()}\t#{PlantSystem.GetLocalizedHealth()}";
|
||||
else
|
||||
args = $"#{PlantSystem.GetLocalizedDirtStatus()}\t#{PlantSystem.GetLocalizedHealth()}";
|
||||
|
||||
if (m_ShowType)
|
||||
{
|
||||
args += $"\t#{hueInfo.Name}\t#{typeInfo.Name}\t#{GetLocalizedPlantStatus()}";
|
||||
|
||||
if (m_PlantStatus == PlantStatus.Plant)
|
||||
list.Add(typeInfo.GetPlantLabelPlant(hueInfo), args);
|
||||
else
|
||||
list.Add(typeInfo.GetPlantLabelSeed(hueInfo), args);
|
||||
}
|
||||
else
|
||||
{
|
||||
args +=
|
||||
$"\t#{(typeInfo.PlantCategory == PlantCategory.Default ? hueInfo.Name : (int)typeInfo.PlantCategory)}\t#{GetLocalizedPlantStatus()}";
|
||||
|
||||
list.Add(hueInfo.IsBright() ? 1060832 : 1060831,
|
||||
args); // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUsableBy(Mobile from)
|
||||
{
|
||||
return IsChildOf(from.Backpack) || IsChildOf(from.FindBankNoCreate()) || IsLockedDown && IsAccessibleTo(from) ||
|
||||
RootParent is Item root && root.IsSecure && root.IsAccessibleTo(from);
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (m_PlantStatus >= PlantStatus.DecorativePlant)
|
||||
return;
|
||||
|
||||
Point3D loc = GetWorldLocation();
|
||||
|
||||
if (!from.InLOS(loc) || !from.InRange(loc, 2))
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1019045); // I can't reach that.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsUsableBy(from))
|
||||
{
|
||||
LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
from.SendGump(new MainPlantGump(this));
|
||||
}
|
||||
|
||||
public void PlantSeed(Mobile from, Seed seed)
|
||||
{
|
||||
if (m_PlantStatus >= PlantStatus.FullGrownPlant)
|
||||
{
|
||||
LabelTo(from, 1061919); // You must use a seed on some prepared soil!
|
||||
}
|
||||
else if (!IsUsableBy(from))
|
||||
{
|
||||
LabelTo(from, 1061921); // The bowl of dirt must be in your pack, or you must lock it down.
|
||||
}
|
||||
else if (m_PlantStatus != PlantStatus.BowlOfDirt)
|
||||
{
|
||||
from.SendLocalizedMessage(1080389,
|
||||
"#" + GetLocalizedPlantStatus()); // This bowl of dirt already has a ~1_val~ in it!
|
||||
}
|
||||
else if (PlantSystem.Water < 2)
|
||||
{
|
||||
LabelTo(from, 1061920); // The dirt needs to be softened first.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_PlantType = seed.PlantType;
|
||||
m_PlantHue = seed.PlantHue;
|
||||
m_ShowType = seed.ShowType;
|
||||
|
||||
seed.Consume();
|
||||
|
||||
PlantStatus = PlantStatus.Seed;
|
||||
|
||||
PlantSystem.Reset(false);
|
||||
|
||||
LabelTo(from, 1061922); // You plant the seed in the bowl of dirt.
|
||||
}
|
||||
}
|
||||
|
||||
public void Die()
|
||||
{
|
||||
if (m_PlantStatus >= PlantStatus.FullGrownPlant)
|
||||
{
|
||||
PlantStatus = PlantStatus.DeadTwigs;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlantStatus = PlantStatus.BowlOfDirt;
|
||||
PlantSystem.Reset(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void Pour(Mobile from, Item item)
|
||||
{
|
||||
if (m_PlantStatus >= PlantStatus.DeadTwigs)
|
||||
return;
|
||||
|
||||
if (m_PlantStatus == PlantStatus.DecorativePlant)
|
||||
{
|
||||
LabelTo(from, 1053049); // This is a decorative plant, it does not need watering!
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsUsableBy(from))
|
||||
{
|
||||
LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (item is BaseBeverage beverage)
|
||||
{
|
||||
if (beverage.IsEmpty || !beverage.Pourable || beverage.Content != BeverageType.Water)
|
||||
{
|
||||
LabelTo(from, 1053069); // You can't use that on a plant!
|
||||
return;
|
||||
}
|
||||
|
||||
if (!beverage.ValidateUse(from, true))
|
||||
return;
|
||||
|
||||
beverage.Quantity--;
|
||||
PlantSystem.Water++;
|
||||
|
||||
from.PlaySound(0x4E);
|
||||
LabelTo(from, 1061858); // You soften the dirt with water.
|
||||
}
|
||||
else if (item is BasePotion potion)
|
||||
{
|
||||
if (ApplyPotion(potion.PotionEffect, false, out int message))
|
||||
{
|
||||
potion.Consume();
|
||||
from.PlaySound(0x240);
|
||||
from.AddToBackpack(new Bottle());
|
||||
}
|
||||
|
||||
LabelTo(from, message);
|
||||
}
|
||||
else if (item is PotionKeg keg)
|
||||
{
|
||||
if (keg.Held <= 0)
|
||||
{
|
||||
LabelTo(from, 1053069); // You can't use that on a plant!
|
||||
return;
|
||||
}
|
||||
|
||||
if (ApplyPotion(keg.Type, false, out int message))
|
||||
{
|
||||
keg.Held--;
|
||||
from.PlaySound(0x240);
|
||||
}
|
||||
|
||||
LabelTo(from, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
LabelTo(from, 1053069); // You can't use that on a plant!
|
||||
}
|
||||
}
|
||||
|
||||
public bool ApplyPotion(PotionEffect effect, bool testOnly, out int message)
|
||||
{
|
||||
if (m_PlantStatus >= PlantStatus.DecorativePlant)
|
||||
{
|
||||
message = 1053049; // This is a decorative plant, it does not need watering!
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_PlantStatus == PlantStatus.BowlOfDirt)
|
||||
{
|
||||
message = 1053066; // You should only pour potions on a plant or seed!
|
||||
return false;
|
||||
}
|
||||
|
||||
bool full = false;
|
||||
|
||||
if (effect == PotionEffect.PoisonGreater || effect == PotionEffect.PoisonDeadly)
|
||||
{
|
||||
if (PlantSystem.IsFullPoisonPotion)
|
||||
full = true;
|
||||
else if (!testOnly)
|
||||
PlantSystem.PoisonPotion++;
|
||||
}
|
||||
else if (effect == PotionEffect.CureGreater)
|
||||
{
|
||||
if (PlantSystem.IsFullCurePotion)
|
||||
full = true;
|
||||
else if (!testOnly)
|
||||
PlantSystem.CurePotion++;
|
||||
}
|
||||
else if (effect == PotionEffect.HealGreater)
|
||||
{
|
||||
if (PlantSystem.IsFullHealPotion)
|
||||
full = true;
|
||||
else if (!testOnly)
|
||||
PlantSystem.HealPotion++;
|
||||
}
|
||||
else if (effect == PotionEffect.StrengthGreater)
|
||||
{
|
||||
if (PlantSystem.IsFullStrengthPotion)
|
||||
full = true;
|
||||
else if (!testOnly)
|
||||
PlantSystem.StrengthPotion++;
|
||||
}
|
||||
else if (effect == PotionEffect.PoisonLesser || effect == PotionEffect.Poison ||
|
||||
effect == PotionEffect.CureLesser || effect == PotionEffect.Cure ||
|
||||
effect == PotionEffect.HealLesser || effect == PotionEffect.Heal || effect == PotionEffect.Strength)
|
||||
{
|
||||
message = 1053068; // This potion is not powerful enough to use on a plant!
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
message = 1053069; // You can't use that on a plant!
|
||||
return false;
|
||||
}
|
||||
|
||||
if (full)
|
||||
{
|
||||
message = 1053065; // The plant is already soaked with this type of potion!
|
||||
return false;
|
||||
}
|
||||
|
||||
message = 1053067; // You pour the potion over the plant.
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(2); // version
|
||||
|
||||
writer.Write((int)Level);
|
||||
|
||||
writer.Write((int)m_PlantStatus);
|
||||
writer.Write((int)m_PlantType);
|
||||
writer.Write((int)m_PlantHue);
|
||||
writer.Write(m_ShowType);
|
||||
|
||||
if (m_PlantStatus < PlantStatus.DecorativePlant)
|
||||
PlantSystem.Save(writer);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 2:
|
||||
case 1:
|
||||
{
|
||||
Level = (SecureLevel)reader.ReadInt();
|
||||
goto case 0;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
if (version < 1)
|
||||
Level = SecureLevel.CoOwners;
|
||||
|
||||
m_PlantStatus = (PlantStatus)reader.ReadInt();
|
||||
m_PlantType = (PlantType)reader.ReadInt();
|
||||
m_PlantHue = (PlantHue)reader.ReadInt();
|
||||
m_ShowType = reader.ReadBool();
|
||||
|
||||
if (m_PlantStatus < PlantStatus.DecorativePlant)
|
||||
PlantSystem = new PlantSystem(this, reader);
|
||||
|
||||
if (version < 2 && PlantHueInfo.IsCrossable(m_PlantHue))
|
||||
m_PlantHue |= PlantHue.Reproduces;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Plants.Add(this);
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
|
||||
Plants.Remove(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Projects/Scripts/Engines/Plants/PlantPourTarget.cs
Normal file
32
Projects/Scripts/Engines/Plants/PlantPourTarget.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
using Server.Targeting;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
public class PlantPourTarget : Target
|
||||
{
|
||||
private PlantItem m_Plant;
|
||||
|
||||
public PlantPourTarget(PlantItem plant) : base(3, true, TargetFlags.None)
|
||||
{
|
||||
m_Plant = plant;
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
if (!m_Plant.Deleted && from.InRange(m_Plant.GetWorldLocation(), 3) && targeted is Item item)
|
||||
m_Plant.Pour(from, item);
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish(Mobile from)
|
||||
{
|
||||
if (!m_Plant.Deleted && m_Plant.PlantStatus < PlantStatus.DecorativePlant &&
|
||||
from.InRange(m_Plant.GetWorldLocation(), 3) && m_Plant.IsUsableBy(from))
|
||||
{
|
||||
if (from.HasGump<MainPlantGump>())
|
||||
from.CloseGump<MainPlantGump>();
|
||||
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
Projects/Scripts/Engines/Plants/PlantResources.cs
Normal file
48
Projects/Scripts/Engines/Plants/PlantResources.cs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
public class PlantResourceInfo
|
||||
{
|
||||
private static PlantResourceInfo[] m_ResourceList =
|
||||
{
|
||||
new PlantResourceInfo(PlantType.ElephantEarPlant, PlantHue.BrightRed, typeof(RedLeaves)),
|
||||
new PlantResourceInfo(PlantType.PonytailPalm, PlantHue.BrightRed, typeof(RedLeaves)),
|
||||
new PlantResourceInfo(PlantType.CenturyPlant, PlantHue.BrightRed, typeof(RedLeaves)),
|
||||
new PlantResourceInfo(PlantType.Poppies, PlantHue.BrightOrange, typeof(OrangePetals)),
|
||||
new PlantResourceInfo(PlantType.Bulrushes, PlantHue.BrightOrange, typeof(OrangePetals)),
|
||||
new PlantResourceInfo(PlantType.PampasGrass, PlantHue.BrightOrange, typeof(OrangePetals)),
|
||||
new PlantResourceInfo(PlantType.SnakePlant, PlantHue.BrightGreen, typeof(GreenThorns)),
|
||||
new PlantResourceInfo(PlantType.BarrelCactus, PlantHue.BrightGreen, typeof(GreenThorns)),
|
||||
new PlantResourceInfo(PlantType.CocoaTree, PlantHue.Plain, typeof(CocoaPulp))
|
||||
};
|
||||
|
||||
private PlantResourceInfo(PlantType plantType, PlantHue plantHue, Type resourceType)
|
||||
{
|
||||
PlantType = plantType;
|
||||
PlantHue = plantHue;
|
||||
ResourceType = resourceType;
|
||||
}
|
||||
|
||||
public PlantType PlantType{ get; }
|
||||
|
||||
public PlantHue PlantHue{ get; }
|
||||
|
||||
public Type ResourceType{ get; }
|
||||
|
||||
public static PlantResourceInfo GetInfo(PlantType plantType, PlantHue plantHue)
|
||||
{
|
||||
foreach (PlantResourceInfo info in m_ResourceList)
|
||||
if (info.PlantType == plantType && info.PlantHue == plantHue)
|
||||
return info;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Item CreateResource()
|
||||
{
|
||||
return (Item)Activator.CreateInstance(ResourceType);
|
||||
}
|
||||
}
|
||||
}
|
||||
684
Projects/Scripts/Engines/Plants/PlantSystem.cs
Normal file
684
Projects/Scripts/Engines/Plants/PlantSystem.cs
Normal file
|
|
@ -0,0 +1,684 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Misc;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
public enum PlantHealth
|
||||
{
|
||||
Dying,
|
||||
Wilted,
|
||||
Healthy,
|
||||
Vibrant
|
||||
}
|
||||
|
||||
public enum PlantGrowthIndicator
|
||||
{
|
||||
None,
|
||||
InvalidLocation,
|
||||
NotHealthy,
|
||||
Delay,
|
||||
Grown,
|
||||
DoubleGrown
|
||||
}
|
||||
|
||||
public class PlantSystem
|
||||
{
|
||||
public static readonly TimeSpan CheckDelay = TimeSpan.FromHours(23.0);
|
||||
|
||||
private int m_AvailableResources;
|
||||
private int m_AvailableSeeds;
|
||||
private int m_CurePotion;
|
||||
private int m_Disease;
|
||||
private int m_Fungus;
|
||||
private int m_HealPotion;
|
||||
|
||||
private int m_Hits;
|
||||
private int m_Infestation;
|
||||
private int m_LeftResources;
|
||||
private int m_LeftSeeds;
|
||||
private int m_Poison;
|
||||
private int m_PoisonPotion;
|
||||
private PlantHue m_SeedHue;
|
||||
|
||||
private PlantType m_SeedType;
|
||||
private int m_StrengthPotion;
|
||||
|
||||
private int m_Water;
|
||||
|
||||
public PlantSystem(PlantItem plant, bool fertileDirt)
|
||||
{
|
||||
Plant = plant;
|
||||
FertileDirt = fertileDirt;
|
||||
|
||||
NextGrowth = DateTime.UtcNow + CheckDelay;
|
||||
GrowthIndicator = PlantGrowthIndicator.None;
|
||||
m_Hits = MaxHits;
|
||||
m_LeftSeeds = 8;
|
||||
m_LeftResources = 8;
|
||||
}
|
||||
|
||||
public PlantSystem(PlantItem plant, GenericReader reader)
|
||||
{
|
||||
Plant = plant;
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
FertileDirt = reader.ReadBool();
|
||||
|
||||
if (version >= 1)
|
||||
NextGrowth = reader.ReadDateTime();
|
||||
else
|
||||
NextGrowth = reader.ReadDeltaTime();
|
||||
|
||||
GrowthIndicator = (PlantGrowthIndicator)reader.ReadInt();
|
||||
|
||||
m_Water = reader.ReadInt();
|
||||
|
||||
m_Hits = reader.ReadInt();
|
||||
m_Infestation = reader.ReadInt();
|
||||
m_Fungus = reader.ReadInt();
|
||||
m_Poison = reader.ReadInt();
|
||||
m_Disease = reader.ReadInt();
|
||||
m_PoisonPotion = reader.ReadInt();
|
||||
m_CurePotion = reader.ReadInt();
|
||||
m_HealPotion = reader.ReadInt();
|
||||
m_StrengthPotion = reader.ReadInt();
|
||||
|
||||
Pollinated = reader.ReadBool();
|
||||
m_SeedType = (PlantType)reader.ReadInt();
|
||||
m_SeedHue = (PlantHue)reader.ReadInt();
|
||||
m_AvailableSeeds = reader.ReadInt();
|
||||
m_LeftSeeds = reader.ReadInt();
|
||||
|
||||
m_AvailableResources = reader.ReadInt();
|
||||
m_LeftResources = reader.ReadInt();
|
||||
|
||||
if (version < 2 && PlantHueInfo.IsCrossable(m_SeedHue))
|
||||
m_SeedHue |= PlantHue.Reproduces;
|
||||
}
|
||||
|
||||
public PlantItem Plant{ get; }
|
||||
|
||||
public bool FertileDirt{ get; set; }
|
||||
|
||||
public DateTime NextGrowth{ get; private set; }
|
||||
|
||||
public PlantGrowthIndicator GrowthIndicator{ get; private set; }
|
||||
|
||||
public bool IsFullWater => m_Water >= 4;
|
||||
|
||||
public int Water
|
||||
{
|
||||
get => m_Water;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
m_Water = 0;
|
||||
else if (value > 4)
|
||||
m_Water = 4;
|
||||
else
|
||||
m_Water = value;
|
||||
|
||||
Plant.InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public int Hits
|
||||
{
|
||||
get => m_Hits;
|
||||
set
|
||||
{
|
||||
if (m_Hits == value)
|
||||
return;
|
||||
|
||||
if (value < 0)
|
||||
m_Hits = 0;
|
||||
else if (value > MaxHits)
|
||||
m_Hits = MaxHits;
|
||||
else
|
||||
m_Hits = value;
|
||||
|
||||
if (m_Hits == 0)
|
||||
Plant.Die();
|
||||
|
||||
Plant.InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxHits => 10 + (int)Plant.PlantStatus * 2;
|
||||
|
||||
public PlantHealth Health
|
||||
{
|
||||
get
|
||||
{
|
||||
int perc = m_Hits * 100 / MaxHits;
|
||||
|
||||
if (perc < 33)
|
||||
return PlantHealth.Dying;
|
||||
if (perc < 66)
|
||||
return PlantHealth.Wilted;
|
||||
if (perc < 100)
|
||||
return PlantHealth.Healthy;
|
||||
return PlantHealth.Vibrant;
|
||||
}
|
||||
}
|
||||
|
||||
public int Infestation
|
||||
{
|
||||
get => m_Infestation;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
m_Infestation = 0;
|
||||
else if (value > 2)
|
||||
m_Infestation = 2;
|
||||
else
|
||||
m_Infestation = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Fungus
|
||||
{
|
||||
get => m_Fungus;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
m_Fungus = 0;
|
||||
else if (value > 2)
|
||||
m_Fungus = 2;
|
||||
else
|
||||
m_Fungus = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Poison
|
||||
{
|
||||
get => m_Poison;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
m_Poison = 0;
|
||||
else if (value > 2)
|
||||
m_Poison = 2;
|
||||
else
|
||||
m_Poison = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Disease
|
||||
{
|
||||
get => m_Disease;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
m_Disease = 0;
|
||||
else if (value > 2)
|
||||
m_Disease = 2;
|
||||
else
|
||||
m_Disease = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFullPoisonPotion => m_PoisonPotion >= 2;
|
||||
|
||||
public int PoisonPotion
|
||||
{
|
||||
get => m_PoisonPotion;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
m_PoisonPotion = 0;
|
||||
else if (value > 2)
|
||||
m_PoisonPotion = 2;
|
||||
else
|
||||
m_PoisonPotion = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFullCurePotion => m_CurePotion >= 2;
|
||||
|
||||
public int CurePotion
|
||||
{
|
||||
get => m_CurePotion;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
m_CurePotion = 0;
|
||||
else if (value > 2)
|
||||
m_CurePotion = 2;
|
||||
else
|
||||
m_CurePotion = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFullHealPotion => m_HealPotion >= 2;
|
||||
|
||||
public int HealPotion
|
||||
{
|
||||
get => m_HealPotion;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
m_HealPotion = 0;
|
||||
else if (value > 2)
|
||||
m_HealPotion = 2;
|
||||
else
|
||||
m_HealPotion = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFullStrengthPotion => m_StrengthPotion >= 2;
|
||||
|
||||
public int StrengthPotion
|
||||
{
|
||||
get => m_StrengthPotion;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
m_StrengthPotion = 0;
|
||||
else if (value > 2)
|
||||
m_StrengthPotion = 2;
|
||||
else
|
||||
m_StrengthPotion = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasMaladies => Infestation > 0 || Fungus > 0 || Poison > 0 || Disease > 0 || Water != 2;
|
||||
|
||||
public bool PollenProducing => Plant.IsCrossable && Plant.PlantStatus >= PlantStatus.FullGrownPlant;
|
||||
|
||||
public bool Pollinated{ get; set; }
|
||||
|
||||
public PlantType SeedType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Pollinated)
|
||||
return m_SeedType;
|
||||
return Plant.PlantType;
|
||||
}
|
||||
set => m_SeedType = value;
|
||||
}
|
||||
|
||||
public PlantHue SeedHue
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Pollinated)
|
||||
return m_SeedHue;
|
||||
return Plant.PlantHue;
|
||||
}
|
||||
set => m_SeedHue = value;
|
||||
}
|
||||
|
||||
public int AvailableSeeds
|
||||
{
|
||||
get => m_AvailableSeeds;
|
||||
set
|
||||
{
|
||||
if (value >= 0) m_AvailableSeeds = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int LeftSeeds
|
||||
{
|
||||
get => m_LeftSeeds;
|
||||
set
|
||||
{
|
||||
if (value >= 0) m_LeftSeeds = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int AvailableResources
|
||||
{
|
||||
get => m_AvailableResources;
|
||||
set
|
||||
{
|
||||
if (value >= 0) m_AvailableResources = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int LeftResources
|
||||
{
|
||||
get => m_LeftResources;
|
||||
set
|
||||
{
|
||||
if (value >= 0) m_LeftResources = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset(bool potions)
|
||||
{
|
||||
NextGrowth = DateTime.UtcNow + CheckDelay;
|
||||
GrowthIndicator = PlantGrowthIndicator.None;
|
||||
|
||||
Hits = MaxHits;
|
||||
m_Infestation = 0;
|
||||
m_Fungus = 0;
|
||||
m_Poison = 0;
|
||||
m_Disease = 0;
|
||||
|
||||
if (potions)
|
||||
{
|
||||
m_PoisonPotion = 0;
|
||||
m_CurePotion = 0;
|
||||
m_HealPotion = 0;
|
||||
m_StrengthPotion = 0;
|
||||
}
|
||||
|
||||
Pollinated = false;
|
||||
m_AvailableSeeds = 0;
|
||||
m_LeftSeeds = 8;
|
||||
|
||||
m_AvailableResources = 0;
|
||||
m_LeftResources = 8;
|
||||
}
|
||||
|
||||
public int GetLocalizedDirtStatus()
|
||||
{
|
||||
if (Water <= 1)
|
||||
return 1060826; // hard
|
||||
if (Water <= 2)
|
||||
return 1060827; // soft
|
||||
if (Water <= 3)
|
||||
return 1060828; // squishy
|
||||
return 1060829; // sopping wet
|
||||
}
|
||||
|
||||
public int GetLocalizedHealth()
|
||||
{
|
||||
switch (Health)
|
||||
{
|
||||
case PlantHealth.Dying: return 1060825; // dying
|
||||
case PlantHealth.Wilted: return 1060824; // wilted
|
||||
case PlantHealth.Healthy: return 1060823; // healthy
|
||||
default: return 1060822; // vibrant
|
||||
}
|
||||
}
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
EventSink.WorldLoad += EventSink_WorldLoad;
|
||||
|
||||
if (!AutoRestart.Enabled)
|
||||
EventSink.WorldSave += EventSink_WorldSave;
|
||||
|
||||
EventSink.Login += EventSink_Login;
|
||||
}
|
||||
|
||||
private static void EventSink_Login(LoginEventArgs args)
|
||||
{
|
||||
Mobile from = args.Mobile;
|
||||
|
||||
from.Backpack?.FindItemsByType<PlantItem>().ForEach(plant =>
|
||||
{
|
||||
if (plant.IsGrowable)
|
||||
plant.PlantSystem.DoGrowthCheck();
|
||||
});
|
||||
|
||||
from.FindBankNoCreate()?.FindItemsByType<PlantItem>().ForEach(plant =>
|
||||
{
|
||||
if (plant.IsGrowable)
|
||||
plant.PlantSystem.DoGrowthCheck();
|
||||
});
|
||||
}
|
||||
|
||||
public static void GrowAll()
|
||||
{
|
||||
List<PlantItem> plants = PlantItem.Plants;
|
||||
DateTime now = DateTime.UtcNow;
|
||||
|
||||
for (int i = plants.Count - 1; i >= 0; --i)
|
||||
{
|
||||
PlantItem plant = plants[i];
|
||||
|
||||
if (plant.IsGrowable && !(plant.RootParent is Mobile) && now >= plant.PlantSystem.NextGrowth)
|
||||
plant.PlantSystem.DoGrowthCheck();
|
||||
}
|
||||
}
|
||||
|
||||
private static void EventSink_WorldLoad()
|
||||
{
|
||||
GrowAll();
|
||||
}
|
||||
|
||||
private static void EventSink_WorldSave(WorldSaveEventArgs args)
|
||||
{
|
||||
GrowAll();
|
||||
}
|
||||
|
||||
public void DoGrowthCheck()
|
||||
{
|
||||
if (!Plant.IsGrowable)
|
||||
return;
|
||||
|
||||
if (DateTime.UtcNow < NextGrowth)
|
||||
{
|
||||
GrowthIndicator = PlantGrowthIndicator.Delay;
|
||||
return;
|
||||
}
|
||||
|
||||
NextGrowth = DateTime.UtcNow + CheckDelay;
|
||||
|
||||
if (!Plant.ValidGrowthLocation)
|
||||
{
|
||||
GrowthIndicator = PlantGrowthIndicator.InvalidLocation;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Plant.PlantStatus == PlantStatus.BowlOfDirt)
|
||||
{
|
||||
if (Water > 2 || Utility.RandomDouble() < 0.9)
|
||||
Water--;
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyBeneficialEffects();
|
||||
|
||||
if (!ApplyMaladiesEffects()) // Dead
|
||||
return;
|
||||
|
||||
Grow();
|
||||
|
||||
UpdateMaladies();
|
||||
}
|
||||
|
||||
private void ApplyBeneficialEffects()
|
||||
{
|
||||
if (PoisonPotion >= Infestation)
|
||||
{
|
||||
PoisonPotion -= Infestation;
|
||||
Infestation = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Infestation -= PoisonPotion;
|
||||
PoisonPotion = 0;
|
||||
}
|
||||
|
||||
if (CurePotion >= Fungus)
|
||||
{
|
||||
CurePotion -= Fungus;
|
||||
Fungus = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Fungus -= CurePotion;
|
||||
CurePotion = 0;
|
||||
}
|
||||
|
||||
if (HealPotion >= Poison)
|
||||
{
|
||||
HealPotion -= Poison;
|
||||
Poison = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Poison -= HealPotion;
|
||||
HealPotion = 0;
|
||||
}
|
||||
|
||||
if (HealPotion >= Disease)
|
||||
{
|
||||
HealPotion -= Disease;
|
||||
Disease = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Disease -= HealPotion;
|
||||
HealPotion = 0;
|
||||
}
|
||||
|
||||
if (!HasMaladies)
|
||||
{
|
||||
if (HealPotion > 0)
|
||||
Hits += HealPotion * 7;
|
||||
else
|
||||
Hits += 2;
|
||||
}
|
||||
|
||||
HealPotion = 0;
|
||||
}
|
||||
|
||||
private bool ApplyMaladiesEffects()
|
||||
{
|
||||
int damage = 0;
|
||||
|
||||
if (Infestation > 0)
|
||||
damage += Infestation * Utility.RandomMinMax(3, 6);
|
||||
|
||||
if (Fungus > 0)
|
||||
damage += Fungus * Utility.RandomMinMax(3, 6);
|
||||
|
||||
if (Poison > 0)
|
||||
damage += Poison * Utility.RandomMinMax(3, 6);
|
||||
|
||||
if (Disease > 0)
|
||||
damage += Disease * Utility.RandomMinMax(3, 6);
|
||||
|
||||
if (Water > 2)
|
||||
damage += (Water - 2) * Utility.RandomMinMax(3, 6);
|
||||
else if (Water < 2)
|
||||
damage += (2 - Water) * Utility.RandomMinMax(3, 6);
|
||||
|
||||
Hits -= damage;
|
||||
|
||||
return Plant.IsGrowable && Plant.PlantStatus != PlantStatus.BowlOfDirt;
|
||||
}
|
||||
|
||||
private void Grow()
|
||||
{
|
||||
if (Health < PlantHealth.Healthy)
|
||||
{
|
||||
GrowthIndicator = PlantGrowthIndicator.NotHealthy;
|
||||
}
|
||||
else if (FertileDirt && Plant.PlantStatus <= PlantStatus.Stage5 && Utility.RandomDouble() < 0.1)
|
||||
{
|
||||
int curStage = (int)Plant.PlantStatus;
|
||||
Plant.PlantStatus = (PlantStatus)(curStage + 2);
|
||||
|
||||
GrowthIndicator = PlantGrowthIndicator.DoubleGrown;
|
||||
}
|
||||
else if (Plant.PlantStatus < PlantStatus.Stage9)
|
||||
{
|
||||
int curStage = (int)Plant.PlantStatus;
|
||||
Plant.PlantStatus = (PlantStatus)(curStage + 1);
|
||||
|
||||
GrowthIndicator = PlantGrowthIndicator.Grown;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Pollinated && LeftSeeds > 0 && Plant.Reproduces)
|
||||
{
|
||||
LeftSeeds--;
|
||||
AvailableSeeds++;
|
||||
}
|
||||
|
||||
if (LeftResources > 0 && PlantResourceInfo.GetInfo(Plant.PlantType, Plant.PlantHue) != null)
|
||||
{
|
||||
LeftResources--;
|
||||
AvailableResources++;
|
||||
}
|
||||
|
||||
GrowthIndicator = PlantGrowthIndicator.Grown;
|
||||
}
|
||||
|
||||
if (Plant.PlantStatus >= PlantStatus.Stage9 && !Pollinated)
|
||||
{
|
||||
Pollinated = true;
|
||||
SeedType = Plant.PlantType;
|
||||
SeedHue = Plant.PlantHue;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateMaladies()
|
||||
{
|
||||
double infestationChance = 0.30 - StrengthPotion * 0.075 + (Water - 2) * 0.10;
|
||||
|
||||
PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo(Plant.PlantType);
|
||||
if (typeInfo.Flowery)
|
||||
infestationChance += 0.10;
|
||||
|
||||
if (PlantHueInfo.IsBright(Plant.PlantHue))
|
||||
infestationChance += 0.10;
|
||||
|
||||
if (Utility.RandomDouble() < infestationChance)
|
||||
Infestation++;
|
||||
|
||||
|
||||
double fungusChance = 0.15 - StrengthPotion * 0.075 + (Water - 2) * 0.10;
|
||||
|
||||
if (Utility.RandomDouble() < fungusChance)
|
||||
Fungus++;
|
||||
|
||||
if (Water > 2 || Utility.RandomDouble() < 0.9)
|
||||
Water--;
|
||||
|
||||
if (PoisonPotion > 0)
|
||||
{
|
||||
Poison += PoisonPotion;
|
||||
PoisonPotion = 0;
|
||||
}
|
||||
|
||||
if (CurePotion > 0)
|
||||
{
|
||||
Disease += CurePotion;
|
||||
CurePotion = 0;
|
||||
}
|
||||
|
||||
StrengthPotion = 0;
|
||||
}
|
||||
|
||||
public void Save(GenericWriter writer)
|
||||
{
|
||||
writer.Write(2); // version
|
||||
|
||||
writer.Write(FertileDirt);
|
||||
|
||||
writer.Write(NextGrowth);
|
||||
writer.Write((int)GrowthIndicator);
|
||||
|
||||
writer.Write(m_Water);
|
||||
|
||||
writer.Write(m_Hits);
|
||||
writer.Write(m_Infestation);
|
||||
writer.Write(m_Fungus);
|
||||
writer.Write(m_Poison);
|
||||
writer.Write(m_Disease);
|
||||
writer.Write(m_PoisonPotion);
|
||||
writer.Write(m_CurePotion);
|
||||
writer.Write(m_HealPotion);
|
||||
writer.Write(m_StrengthPotion);
|
||||
|
||||
writer.Write(Pollinated);
|
||||
writer.Write((int)m_SeedType);
|
||||
writer.Write((int)m_SeedHue);
|
||||
writer.Write(m_AvailableSeeds);
|
||||
writer.Write(m_LeftSeeds);
|
||||
|
||||
writer.Write(m_AvailableResources);
|
||||
writer.Write(m_LeftResources);
|
||||
}
|
||||
}
|
||||
}
|
||||
365
Projects/Scripts/Engines/Plants/PlantType.cs
Normal file
365
Projects/Scripts/Engines/Plants/PlantType.cs
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
namespace Server.Engines.Plants
|
||||
{
|
||||
public enum PlantType
|
||||
{
|
||||
CampionFlowers,
|
||||
Poppies,
|
||||
Snowdrops,
|
||||
Bulrushes,
|
||||
Lilies,
|
||||
PampasGrass,
|
||||
Rushes,
|
||||
ElephantEarPlant,
|
||||
Fern,
|
||||
PonytailPalm,
|
||||
SmallPalm,
|
||||
CenturyPlant,
|
||||
WaterPlant,
|
||||
SnakePlant,
|
||||
PricklyPearCactus,
|
||||
BarrelCactus,
|
||||
TribarrelCactus,
|
||||
CommonGreenBonsai,
|
||||
CommonPinkBonsai,
|
||||
UncommonGreenBonsai,
|
||||
UncommonPinkBonsai,
|
||||
RareGreenBonsai,
|
||||
RarePinkBonsai,
|
||||
ExceptionalBonsai,
|
||||
ExoticBonsai,
|
||||
Cactus,
|
||||
FlaxFlowers,
|
||||
FoxgloveFlowers,
|
||||
HopsEast,
|
||||
OrfluerFlowers,
|
||||
CypressTwisted,
|
||||
HedgeShort,
|
||||
JuniperBush,
|
||||
SnowdropPatch,
|
||||
Cattails,
|
||||
PoppyPatch,
|
||||
SpiderTree,
|
||||
WaterLily,
|
||||
CypressStraight,
|
||||
HedgeTall,
|
||||
HopsSouth,
|
||||
SugarCanes,
|
||||
CocoaTree
|
||||
}
|
||||
|
||||
public enum PlantCategory
|
||||
{
|
||||
Default,
|
||||
Common = 1063335, //
|
||||
Uncommon = 1063336, //
|
||||
Rare = 1063337, // Bonsai
|
||||
Exceptional = 1063341, //
|
||||
Exotic = 1063342, //
|
||||
Peculiar = 1080528,
|
||||
Fragrant = 1080529
|
||||
}
|
||||
|
||||
public class PlantTypeInfo
|
||||
{
|
||||
private static PlantTypeInfo[] m_Table =
|
||||
{
|
||||
new PlantTypeInfo(0xC83, 0, 0, PlantType.CampionFlowers, false, true, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xC86, 0, 0, PlantType.Poppies, false, true, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xC88, 0, 10, PlantType.Snowdrops, false, true, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xC94, -15, 0, PlantType.Bulrushes, false, true, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xC8B, 0, 0, PlantType.Lilies, false, true, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xCA5, -8, 0, PlantType.PampasGrass, false, true, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xCA7, -10, 0, PlantType.Rushes, false, true, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xC97, -20, 0, PlantType.ElephantEarPlant, true, false, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xC9F, -20, 0, PlantType.Fern, false, false, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xCA6, -16, -5, PlantType.PonytailPalm, false, false, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xC9C, -5, -10, PlantType.SmallPalm, false, false, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xD31, 0, -27, PlantType.CenturyPlant, true, false, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xD04, 0, 10, PlantType.WaterPlant, true, false, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xCA9, 0, 0, PlantType.SnakePlant, true, false, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xD2C, 0, 10, PlantType.PricklyPearCactus, false, false, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xD26, 0, 10, PlantType.BarrelCactus, false, false, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0xD27, 0, 10, PlantType.TribarrelCactus, false, false, true, true, PlantCategory.Default),
|
||||
new PlantTypeInfo(0x28DC, -5, 5, PlantType.CommonGreenBonsai, true, false, false, false, PlantCategory.Common),
|
||||
new PlantTypeInfo(0x28DF, -5, 5, PlantType.CommonPinkBonsai, true, false, false, false, PlantCategory.Common),
|
||||
new PlantTypeInfo(0x28DD, -5, 5, PlantType.UncommonGreenBonsai, true, false, false, false,
|
||||
PlantCategory.Uncommon),
|
||||
new PlantTypeInfo(0x28E0, -5, 5, PlantType.UncommonPinkBonsai, true, false, false, false,
|
||||
PlantCategory.Uncommon),
|
||||
new PlantTypeInfo(0x28DE, -5, 5, PlantType.RareGreenBonsai, true, false, false, false, PlantCategory.Rare),
|
||||
new PlantTypeInfo(0x28E1, -5, 5, PlantType.RarePinkBonsai, true, false, false, false, PlantCategory.Rare),
|
||||
new PlantTypeInfo(0x28E2, -5, 5, PlantType.ExceptionalBonsai, true, false, false, false,
|
||||
PlantCategory.Exceptional),
|
||||
new PlantTypeInfo(0x28E3, -5, 5, PlantType.ExoticBonsai, true, false, false, false, PlantCategory.Exotic),
|
||||
new PlantTypeInfo(0x0D25, 0, 0, PlantType.Cactus, false, false, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x1A9A, 5, 10, PlantType.FlaxFlowers, false, true, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0C84, 0, 0, PlantType.FoxgloveFlowers, false, true, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x1A9F, 5, -25, PlantType.HopsEast, false, false, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0CC1, 0, 0, PlantType.OrfluerFlowers, false, true, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0CFE, -45, -30, PlantType.CypressTwisted, false, false, false, false,
|
||||
PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0C8F, 0, 0, PlantType.HedgeShort, false, false, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0CC8, 0, 0, PlantType.JuniperBush, true, false, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0C8E, -20, 0, PlantType.SnowdropPatch, false, true, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0CB7, 0, 0, PlantType.Cattails, false, false, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0CBE, -20, 0, PlantType.PoppyPatch, false, true, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0CC9, 0, 0, PlantType.SpiderTree, false, false, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0DC1, -5, 15, PlantType.WaterLily, false, true, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0CFB, -45, -30, PlantType.CypressStraight, false, false, false, false,
|
||||
PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x0DB8, 0, -20, PlantType.HedgeTall, false, false, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x1AA1, 10, -25, PlantType.HopsSouth, false, false, false, false, PlantCategory.Peculiar),
|
||||
new PlantTypeInfo(0x246C, -25, -20, PlantType.SugarCanes, false, false, false, false, PlantCategory.Peculiar,
|
||||
1114898, 1114898, 1094702, 1094703, 1095221, 1113715),
|
||||
new PlantTypeInfo(0xC9E, -40, -30, PlantType.CocoaTree, false, false, false, true, PlantCategory.Fragrant,
|
||||
1080536, 1080536, 1080534, 1080531, 1080533, 1113716)
|
||||
};
|
||||
|
||||
private int m_PlantLabelDecorative;
|
||||
private int m_PlantLabelFullGrown;
|
||||
private int m_PlantLabelPlant;
|
||||
|
||||
// Cliloc overrides
|
||||
private int m_PlantLabelSeed;
|
||||
private int m_SeedLabel;
|
||||
private int m_SeedLabelPlural;
|
||||
|
||||
private PlantTypeInfo(int itemID, int offsetX, int offsetY, PlantType plantType, bool containsPlant, bool flowery,
|
||||
bool crossable, bool reproduces, PlantCategory plantCategory, int plantLabelSeed = -1, int plantLabelPlant = -1,
|
||||
int plantLabelFullGrown = -1, int plantLabelDecorative = -1, int seedLabel = -1, int seedLabelPlural = -1)
|
||||
{
|
||||
ItemID = itemID;
|
||||
OffsetX = offsetX;
|
||||
OffsetY = offsetY;
|
||||
PlantType = plantType;
|
||||
ContainsPlant = containsPlant;
|
||||
Flowery = flowery;
|
||||
Crossable = crossable;
|
||||
Reproduces = reproduces;
|
||||
PlantCategory = plantCategory;
|
||||
m_PlantLabelSeed = plantLabelSeed;
|
||||
m_PlantLabelPlant = plantLabelPlant;
|
||||
m_PlantLabelFullGrown = plantLabelFullGrown;
|
||||
m_PlantLabelDecorative = plantLabelDecorative;
|
||||
m_SeedLabel = seedLabel;
|
||||
m_SeedLabelPlural = seedLabelPlural;
|
||||
}
|
||||
|
||||
public int ItemID{ get; }
|
||||
|
||||
public int OffsetX{ get; }
|
||||
|
||||
public int OffsetY{ get; }
|
||||
|
||||
public PlantType PlantType{ get; }
|
||||
|
||||
public PlantCategory PlantCategory{ get; }
|
||||
|
||||
public int Name => ItemID < 0x4000 ? 1020000 + ItemID : 1078872 + ItemID;
|
||||
|
||||
public bool ContainsPlant{ get; }
|
||||
|
||||
public bool Flowery{ get; }
|
||||
|
||||
public bool Crossable{ get; }
|
||||
|
||||
public bool Reproduces{ get; }
|
||||
|
||||
public static PlantTypeInfo GetInfo(PlantType plantType)
|
||||
{
|
||||
int index = (int)plantType;
|
||||
|
||||
if (index >= 0 && index < m_Table.Length)
|
||||
return m_Table[index];
|
||||
return m_Table[0];
|
||||
}
|
||||
|
||||
public static PlantType RandomFirstGeneration()
|
||||
{
|
||||
switch (Utility.Random(3))
|
||||
{
|
||||
case 0: return PlantType.CampionFlowers;
|
||||
case 1: return PlantType.Fern;
|
||||
default: return PlantType.TribarrelCactus;
|
||||
}
|
||||
}
|
||||
|
||||
public static PlantType RandomPeculiarGroupOne()
|
||||
{
|
||||
switch (Utility.Random(6))
|
||||
{
|
||||
case 0: return PlantType.Cactus;
|
||||
case 1: return PlantType.FlaxFlowers;
|
||||
case 2: return PlantType.FoxgloveFlowers;
|
||||
case 3: return PlantType.HopsEast;
|
||||
case 4: return PlantType.CocoaTree;
|
||||
default: return PlantType.OrfluerFlowers;
|
||||
}
|
||||
}
|
||||
|
||||
public static PlantType RandomPeculiarGroupTwo()
|
||||
{
|
||||
switch (Utility.Random(5))
|
||||
{
|
||||
case 0: return PlantType.CypressTwisted;
|
||||
case 1: return PlantType.HedgeShort;
|
||||
case 2: return PlantType.JuniperBush;
|
||||
case 3: return PlantType.CocoaTree;
|
||||
default: return PlantType.SnowdropPatch;
|
||||
}
|
||||
}
|
||||
|
||||
public static PlantType RandomPeculiarGroupThree()
|
||||
{
|
||||
switch (Utility.Random(5))
|
||||
{
|
||||
case 0: return PlantType.Cattails;
|
||||
case 1: return PlantType.PoppyPatch;
|
||||
case 2: return PlantType.SpiderTree;
|
||||
case 3: return PlantType.CocoaTree;
|
||||
default: return PlantType.WaterLily;
|
||||
}
|
||||
}
|
||||
|
||||
public static PlantType RandomPeculiarGroupFour()
|
||||
{
|
||||
switch (Utility.Random(5))
|
||||
{
|
||||
case 0: return PlantType.CypressStraight;
|
||||
case 1: return PlantType.HedgeTall;
|
||||
case 2: return PlantType.HopsSouth;
|
||||
case 3: return PlantType.CocoaTree;
|
||||
default: return PlantType.SugarCanes;
|
||||
}
|
||||
}
|
||||
|
||||
public static PlantType RandomBonsai(double increaseRatio)
|
||||
{
|
||||
/* Chances of each plant type are equal to the chances of the previous plant type * increaseRatio:
|
||||
* E.g.:
|
||||
* chances_of_uncommon = chances_of_common * increaseRatio
|
||||
* chances_of_rare = chances_of_uncommon * increaseRatio
|
||||
* ...
|
||||
*
|
||||
* If increaseRatio < 1 -> rare plants are actually rarer than the others
|
||||
* If increaseRatio > 1 -> rare plants are actually more common than the others (it might be the case with certain monsters)
|
||||
*
|
||||
* If a plant type (common, uncommon, ...) has 2 different colors, they have the same chances:
|
||||
* chances_of_green_common = chances_of_pink_common = chances_of_common / 2
|
||||
* ...
|
||||
*/
|
||||
|
||||
double k1 = increaseRatio >= 0.0 ? increaseRatio : 0.0;
|
||||
double k2 = k1 * k1;
|
||||
double k3 = k2 * k1;
|
||||
double k4 = k3 * k1;
|
||||
|
||||
double exp1 = k1 + 1.0;
|
||||
double exp2 = k2 + exp1;
|
||||
double exp3 = k3 + exp2;
|
||||
double exp4 = k4 + exp3;
|
||||
|
||||
double rand = Utility.RandomDouble();
|
||||
|
||||
if (rand < 0.5 / exp4)
|
||||
return PlantType.CommonGreenBonsai;
|
||||
if (rand < 1.0 / exp4)
|
||||
return PlantType.CommonPinkBonsai;
|
||||
if (rand < (k1 * 0.5 + 1.0) / exp4)
|
||||
return PlantType.UncommonGreenBonsai;
|
||||
if (rand < exp1 / exp4)
|
||||
return PlantType.UncommonPinkBonsai;
|
||||
if (rand < (k2 * 0.5 + exp1) / exp4)
|
||||
return PlantType.RareGreenBonsai;
|
||||
if (rand < exp2 / exp4)
|
||||
return PlantType.RarePinkBonsai;
|
||||
if (rand < exp3 / exp4)
|
||||
return PlantType.ExceptionalBonsai;
|
||||
return PlantType.ExoticBonsai;
|
||||
}
|
||||
|
||||
public static bool IsCrossable(PlantType plantType)
|
||||
{
|
||||
return GetInfo(plantType).Crossable;
|
||||
}
|
||||
|
||||
public static PlantType Cross(PlantType first, PlantType second)
|
||||
{
|
||||
if (!IsCrossable(first) || !IsCrossable(second))
|
||||
return PlantType.CampionFlowers;
|
||||
|
||||
int firstIndex = (int)first;
|
||||
int secondIndex = (int)second;
|
||||
|
||||
if (firstIndex + 1 == secondIndex || firstIndex == secondIndex + 1)
|
||||
return Utility.RandomBool() ? first : second;
|
||||
return (PlantType)((firstIndex + secondIndex) / 2);
|
||||
}
|
||||
|
||||
public static bool CanReproduce(PlantType plantType)
|
||||
{
|
||||
return GetInfo(plantType).Reproduces;
|
||||
}
|
||||
|
||||
public int GetPlantLabelSeed(PlantHueInfo hueInfo)
|
||||
{
|
||||
if (m_PlantLabelSeed != -1)
|
||||
return m_PlantLabelSeed;
|
||||
|
||||
return
|
||||
hueInfo.IsBright()
|
||||
? 1061887
|
||||
: 1061888; // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~ ~6_val~
|
||||
}
|
||||
|
||||
public int GetPlantLabelPlant(PlantHueInfo hueInfo)
|
||||
{
|
||||
if (m_PlantLabelPlant != -1)
|
||||
return m_PlantLabelPlant;
|
||||
|
||||
if (ContainsPlant)
|
||||
return
|
||||
hueInfo.IsBright()
|
||||
? 1060832
|
||||
: 1060831; // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~
|
||||
return
|
||||
hueInfo.IsBright()
|
||||
? 1061887
|
||||
: 1061888; // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~ ~6_val~
|
||||
}
|
||||
|
||||
public int GetPlantLabelFullGrown(PlantHueInfo hueInfo)
|
||||
{
|
||||
if (m_PlantLabelFullGrown != -1)
|
||||
return m_PlantLabelFullGrown;
|
||||
|
||||
if (ContainsPlant)
|
||||
return hueInfo.IsBright() ? 1061891 : 1061889; // a ~1_HEALTH~ [bright] ~2_COLOR~ ~3_NAME~
|
||||
return hueInfo.IsBright() ? 1061892 : 1061890; // a ~1_HEALTH~ [bright] ~2_COLOR~ ~3_NAME~ plant
|
||||
}
|
||||
|
||||
public int GetPlantLabelDecorative(PlantHueInfo hueInfo)
|
||||
{
|
||||
if (m_PlantLabelDecorative != -1)
|
||||
return m_PlantLabelDecorative;
|
||||
|
||||
return hueInfo.IsBright() ? 1074267 : 1070973; // a decorative [bright] ~1_COLOR~ ~2_TYPE~
|
||||
}
|
||||
|
||||
public int GetSeedLabel(PlantHueInfo hueInfo)
|
||||
{
|
||||
if (m_SeedLabel != -1)
|
||||
return m_SeedLabel;
|
||||
|
||||
return hueInfo.IsBright() ? 1061918 : 1061917; // [bright] ~1_COLOR~ ~2_TYPE~ seed
|
||||
}
|
||||
|
||||
public int GetSeedLabelPlural(PlantHueInfo hueInfo)
|
||||
{
|
||||
if (m_SeedLabelPlural != -1)
|
||||
return m_SeedLabelPlural;
|
||||
|
||||
return hueInfo.IsBright() ? 1113493 : 1113492; // ~1_amount~ [bright] ~2_color~ ~3_type~ seeds
|
||||
}
|
||||
}
|
||||
}
|
||||
91
Projects/Scripts/Engines/Plants/PollinateTarget.cs
Normal file
91
Projects/Scripts/Engines/Plants/PollinateTarget.cs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
using Server.Targeting;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
public class PollinateTarget : Target
|
||||
{
|
||||
private PlantItem m_Plant;
|
||||
|
||||
public PollinateTarget(PlantItem plant) : base(3, true, TargetFlags.None)
|
||||
{
|
||||
m_Plant = plant;
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
if (!m_Plant.Deleted && m_Plant.PlantStatus < PlantStatus.DecorativePlant &&
|
||||
from.InRange(m_Plant.GetWorldLocation(), 3))
|
||||
{
|
||||
if (!m_Plant.IsUsableBy(from))
|
||||
{
|
||||
m_Plant.LabelTo(from,
|
||||
1061856); // You must have the item in your backpack or locked down in order to use it.
|
||||
}
|
||||
else if (!m_Plant.IsCrossable)
|
||||
{
|
||||
m_Plant.LabelTo(from, 1053050); // You cannot gather pollen from a mutated plant!
|
||||
}
|
||||
else if (!m_Plant.PlantSystem.PollenProducing)
|
||||
{
|
||||
m_Plant.LabelTo(from, 1053051); // You cannot gather pollen from a plant in this stage of development!
|
||||
}
|
||||
else if (m_Plant.PlantSystem.Health < PlantHealth.Healthy)
|
||||
{
|
||||
m_Plant.LabelTo(from, 1053052); // You cannot gather pollen from an unhealthy plant!
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(targeted is PlantItem targ) || targ.PlantStatus >= PlantStatus.DecorativePlant ||
|
||||
targ.PlantStatus <= PlantStatus.BowlOfDirt)
|
||||
{
|
||||
m_Plant.LabelTo(from, 1053070); // You can only pollinate other specially grown plants!
|
||||
}
|
||||
else if (!targ.IsUsableBy(from))
|
||||
{
|
||||
targ.LabelTo(from,
|
||||
1061856); // You must have the item in your backpack or locked down in order to use it.
|
||||
}
|
||||
else if (!targ.IsCrossable)
|
||||
{
|
||||
targ.LabelTo(from, 1053073); // You cannot cross-pollinate with a mutated plant!
|
||||
}
|
||||
else if (!targ.PlantSystem.PollenProducing)
|
||||
{
|
||||
targ.LabelTo(from, 1053074); // This plant is not in the flowering stage. You cannot pollinate it!
|
||||
}
|
||||
else if (targ.PlantSystem.Health < PlantHealth.Healthy)
|
||||
{
|
||||
targ.LabelTo(from, 1053075); // You cannot pollinate an unhealthy plant!
|
||||
}
|
||||
else if (targ.PlantSystem.Pollinated)
|
||||
{
|
||||
targ.LabelTo(from, 1053072); // This plant has already been pollinated!
|
||||
}
|
||||
else if (targ == m_Plant)
|
||||
{
|
||||
targ.PlantSystem.Pollinated = true;
|
||||
targ.PlantSystem.SeedType = m_Plant.PlantType;
|
||||
targ.PlantSystem.SeedHue = m_Plant.PlantHue;
|
||||
|
||||
targ.LabelTo(from, 1053071); // You pollinate the plant with its own pollen.
|
||||
}
|
||||
else
|
||||
{
|
||||
targ.PlantSystem.Pollinated = true;
|
||||
targ.PlantSystem.SeedType = PlantTypeInfo.Cross(m_Plant.PlantType, targ.PlantType);
|
||||
targ.PlantSystem.SeedHue = PlantHueInfo.Cross(m_Plant.PlantHue, targ.PlantHue);
|
||||
|
||||
targ.LabelTo(from, 1053076); // You successfully cross-pollinate the plant.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish(Mobile from)
|
||||
{
|
||||
if (!m_Plant.Deleted && m_Plant.PlantStatus < PlantStatus.DecorativePlant &&
|
||||
m_Plant.PlantStatus != PlantStatus.BowlOfDirt && from.InRange(m_Plant.GetWorldLocation(), 3) &&
|
||||
m_Plant.IsUsableBy(from)) from.SendGump(new ReproductionGump(m_Plant));
|
||||
}
|
||||
}
|
||||
}
|
||||
263
Projects/Scripts/Engines/Plants/ReproductionGump.cs
Normal file
263
Projects/Scripts/Engines/Plants/ReproductionGump.cs
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
public class ReproductionGump : Gump
|
||||
{
|
||||
private PlantItem m_Plant;
|
||||
|
||||
public ReproductionGump(PlantItem plant) : base(20, 20)
|
||||
{
|
||||
m_Plant = plant;
|
||||
|
||||
DrawBackground();
|
||||
|
||||
AddButton(70, 67, 0xD4, 0xD4, 1); // Main menu
|
||||
AddItem(57, 65, 0x1600);
|
||||
|
||||
AddLabel(108, 67, 0x835, "Reproduction");
|
||||
|
||||
if (m_Plant.PlantStatus == PlantStatus.Stage9)
|
||||
{
|
||||
AddButton(212, 67, 0xD4, 0xD4, 2); // Set to decorative
|
||||
AddItem(202, 68, 0xC61);
|
||||
AddLabel(216, 66, 0x21, "/");
|
||||
}
|
||||
|
||||
AddButton(80, 116, 0xD4, 0xD4, 3); // Pollination
|
||||
AddItem(66, 117, 0x1AA2);
|
||||
AddPollinationState(106, 116);
|
||||
|
||||
AddButton(128, 116, 0xD4, 0xD4, 4); // Resources
|
||||
AddItem(113, 120, 0x1021);
|
||||
AddResourcesState(149, 116);
|
||||
|
||||
AddButton(177, 116, 0xD4, 0xD4, 5); // Seeds
|
||||
AddItem(160, 121, 0xDCF);
|
||||
AddSeedsState(199, 116);
|
||||
|
||||
AddButton(70, 163, 0xD2, 0xD2, 6); // Gather pollen
|
||||
AddItem(56, 164, 0x1AA2);
|
||||
|
||||
AddButton(138, 163, 0xD2, 0xD2, 7); // Gather resources
|
||||
AddItem(123, 167, 0x1021);
|
||||
|
||||
AddButton(212, 163, 0xD2, 0xD2, 8); // Gather seeds
|
||||
AddItem(195, 168, 0xDCF);
|
||||
}
|
||||
|
||||
private void DrawBackground()
|
||||
{
|
||||
AddBackground(50, 50, 200, 150, 0xE10);
|
||||
|
||||
AddImage(60, 90, 0xE17);
|
||||
AddImage(120, 90, 0xE17);
|
||||
|
||||
AddImage(60, 145, 0xE17);
|
||||
AddImage(120, 145, 0xE17);
|
||||
|
||||
AddItem(45, 45, 0xCEF);
|
||||
AddItem(45, 118, 0xCF0);
|
||||
|
||||
AddItem(211, 45, 0xCEB);
|
||||
AddItem(211, 118, 0xCEC);
|
||||
}
|
||||
|
||||
private void AddPollinationState(int x, int y)
|
||||
{
|
||||
PlantSystem system = m_Plant.PlantSystem;
|
||||
|
||||
if (!system.PollenProducing)
|
||||
AddLabel(x, y, 0x35, "-");
|
||||
else if (!system.Pollinated)
|
||||
AddLabel(x, y, 0x21, "!");
|
||||
else
|
||||
AddLabel(x, y, 0x3F, "+");
|
||||
}
|
||||
|
||||
private void AddResourcesState(int x, int y)
|
||||
{
|
||||
PlantResourceInfo resInfo = PlantResourceInfo.GetInfo(m_Plant.PlantType, m_Plant.PlantHue);
|
||||
|
||||
PlantSystem system = m_Plant.PlantSystem;
|
||||
int totalResources = system.AvailableResources + system.LeftResources;
|
||||
|
||||
if (resInfo == null || totalResources == 0)
|
||||
AddLabel(x + 5, y, 0x21, "X");
|
||||
else
|
||||
AddLabel(x, y, PlantHueInfo.GetInfo(m_Plant.PlantHue).GumpHue,
|
||||
$"{system.AvailableResources}/{totalResources}");
|
||||
}
|
||||
|
||||
private void AddSeedsState(int x, int y)
|
||||
{
|
||||
PlantSystem system = m_Plant.PlantSystem;
|
||||
int totalSeeds = system.AvailableSeeds + system.LeftSeeds;
|
||||
|
||||
if (!m_Plant.Reproduces || totalSeeds == 0)
|
||||
AddLabel(x + 5, y, 0x21, "X");
|
||||
else
|
||||
AddLabel(x, y, PlantHueInfo.GetInfo(system.SeedHue).GumpHue,
|
||||
$"{system.AvailableSeeds}/{totalSeeds}");
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
Mobile from = sender.Mobile;
|
||||
|
||||
if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus >= PlantStatus.DecorativePlant ||
|
||||
m_Plant.PlantStatus == PlantStatus.BowlOfDirt)
|
||||
return;
|
||||
|
||||
if (info.ButtonID >= 6 && info.ButtonID <= 8 && !from.InRange(m_Plant.GetWorldLocation(), 3))
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_Plant.IsUsableBy(from))
|
||||
{
|
||||
m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 1: // Main menu
|
||||
{
|
||||
from.SendGump(new MainPlantGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Set to decorative
|
||||
{
|
||||
if (m_Plant.PlantStatus == PlantStatus.Stage9) from.SendGump(new SetToDecorativeGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Pollination
|
||||
{
|
||||
from.Send(new DisplayHelpTopic(67, true)); // POLLINATION STATE
|
||||
|
||||
from.SendGump(new ReproductionGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: // Resources
|
||||
{
|
||||
from.Send(new DisplayHelpTopic(69, true)); // RESOURCE PRODUCTION
|
||||
|
||||
from.SendGump(new ReproductionGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: // Seeds
|
||||
{
|
||||
from.Send(new DisplayHelpTopic(68, true)); // SEED PRODUCTION
|
||||
|
||||
from.SendGump(new ReproductionGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 6: // Gather pollen
|
||||
{
|
||||
if (!m_Plant.IsCrossable)
|
||||
{
|
||||
m_Plant.LabelTo(from, 1053050); // You cannot gather pollen from a mutated plant!
|
||||
}
|
||||
else if (!m_Plant.PlantSystem.PollenProducing)
|
||||
{
|
||||
m_Plant.LabelTo(from,
|
||||
1053051); // You cannot gather pollen from a plant in this stage of development!
|
||||
}
|
||||
else if (m_Plant.PlantSystem.Health < PlantHealth.Healthy)
|
||||
{
|
||||
m_Plant.LabelTo(from, 1053052); // You cannot gather pollen from an unhealthy plant!
|
||||
}
|
||||
else
|
||||
{
|
||||
from.Target = new PollinateTarget(m_Plant);
|
||||
from.SendLocalizedMessage(1053054); // Target the plant you wish to cross-pollinate to.
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
from.SendGump(new ReproductionGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 7: // Gather resources
|
||||
{
|
||||
PlantResourceInfo resInfo = PlantResourceInfo.GetInfo(m_Plant.PlantType, m_Plant.PlantHue);
|
||||
PlantSystem system = m_Plant.PlantSystem;
|
||||
|
||||
if (resInfo == null)
|
||||
{
|
||||
if (m_Plant.IsCrossable)
|
||||
m_Plant.LabelTo(from, 1053056); // This plant has no resources to gather!
|
||||
else
|
||||
m_Plant.LabelTo(from, 1053055); // Mutated plants do not produce resources!
|
||||
}
|
||||
else if (system.AvailableResources == 0)
|
||||
{
|
||||
m_Plant.LabelTo(from, 1053056); // This plant has no resources to gather!
|
||||
}
|
||||
else
|
||||
{
|
||||
Item resource = resInfo.CreateResource();
|
||||
|
||||
if (from.PlaceInBackpack(resource))
|
||||
{
|
||||
system.AvailableResources--;
|
||||
m_Plant.LabelTo(from, 1053059); // You gather resources from the plant.
|
||||
}
|
||||
else
|
||||
{
|
||||
resource.Delete();
|
||||
m_Plant.LabelTo(from,
|
||||
1053058); // You attempt to gather as many resources as you can hold, but your backpack is full.
|
||||
}
|
||||
}
|
||||
|
||||
from.SendGump(new ReproductionGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 8: // Gather seeds
|
||||
{
|
||||
PlantSystem system = m_Plant.PlantSystem;
|
||||
|
||||
if (!m_Plant.Reproduces)
|
||||
{
|
||||
m_Plant.LabelTo(from, 1053060); // Mutated plants do not produce seeds!
|
||||
}
|
||||
else if (system.AvailableSeeds == 0)
|
||||
{
|
||||
m_Plant.LabelTo(from, 1053061); // This plant has no seeds to gather!
|
||||
}
|
||||
else
|
||||
{
|
||||
Seed seed = new Seed(system.SeedType, system.SeedHue, true);
|
||||
|
||||
if (from.PlaceInBackpack(seed))
|
||||
{
|
||||
system.AvailableSeeds--;
|
||||
m_Plant.LabelTo(from, 1053063); // You gather seeds from the plant.
|
||||
}
|
||||
else
|
||||
{
|
||||
seed.Delete();
|
||||
m_Plant.LabelTo(from,
|
||||
1053062); // You attempt to gather as many seeds as you can hold, but your backpack is full.
|
||||
}
|
||||
}
|
||||
|
||||
from.SendGump(new ReproductionGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
225
Projects/Scripts/Engines/Plants/Seed.cs
Normal file
225
Projects/Scripts/Engines/Plants/Seed.cs
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
using Server.Targeting;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
public class Seed : Item
|
||||
{
|
||||
private PlantHue m_PlantHue;
|
||||
private PlantType m_PlantType;
|
||||
private bool m_ShowType;
|
||||
|
||||
[Constructible]
|
||||
public Seed() : this(PlantTypeInfo.RandomFirstGeneration(), PlantHueInfo.RandomFirstGeneration())
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
public Seed(PlantType plantType, PlantHue plantHue, bool showType = false) : base(0xDCF)
|
||||
{
|
||||
Weight = 1.0;
|
||||
Stackable = Core.SA;
|
||||
|
||||
m_PlantType = plantType;
|
||||
m_PlantHue = plantHue;
|
||||
m_ShowType = showType;
|
||||
|
||||
Hue = PlantHueInfo.GetInfo(plantHue).Hue;
|
||||
}
|
||||
|
||||
public Seed(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public PlantType PlantType
|
||||
{
|
||||
get => m_PlantType;
|
||||
set
|
||||
{
|
||||
m_PlantType = value;
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public PlantHue PlantHue
|
||||
{
|
||||
get => m_PlantHue;
|
||||
set
|
||||
{
|
||||
m_PlantHue = value;
|
||||
Hue = PlantHueInfo.GetInfo(value).Hue;
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool ShowType
|
||||
{
|
||||
get => m_ShowType;
|
||||
set
|
||||
{
|
||||
m_ShowType = value;
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1060810; // seed
|
||||
|
||||
public override bool ForceShowProperties => ObjectPropertyList.Enabled;
|
||||
|
||||
public static Seed RandomBonsaiSeed()
|
||||
{
|
||||
return RandomBonsaiSeed(0.5);
|
||||
}
|
||||
|
||||
public static Seed RandomBonsaiSeed(double increaseRatio)
|
||||
{
|
||||
return new Seed(PlantTypeInfo.RandomBonsai(increaseRatio), PlantHue.Plain);
|
||||
}
|
||||
|
||||
public static Seed RandomPeculiarSeed(int group)
|
||||
{
|
||||
switch (group)
|
||||
{
|
||||
case 1: return new Seed(PlantTypeInfo.RandomPeculiarGroupOne(), PlantHue.Plain);
|
||||
case 2: return new Seed(PlantTypeInfo.RandomPeculiarGroupTwo(), PlantHue.Plain);
|
||||
case 3: return new Seed(PlantTypeInfo.RandomPeculiarGroupThree(), PlantHue.Plain);
|
||||
default: return new Seed(PlantTypeInfo.RandomPeculiarGroupFour(), PlantHue.Plain);
|
||||
}
|
||||
}
|
||||
|
||||
private int GetLabel(out string args)
|
||||
{
|
||||
PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo(m_PlantType);
|
||||
PlantHueInfo hueInfo = PlantHueInfo.GetInfo(m_PlantHue);
|
||||
|
||||
int title;
|
||||
|
||||
if (m_ShowType || typeInfo.PlantCategory == PlantCategory.Default)
|
||||
title = hueInfo.Name;
|
||||
else
|
||||
title = (int)typeInfo.PlantCategory;
|
||||
|
||||
if (Amount == 1)
|
||||
{
|
||||
if (m_ShowType)
|
||||
{
|
||||
args = $"#{title}\t#{typeInfo.Name}";
|
||||
return typeInfo.GetSeedLabel(hueInfo);
|
||||
}
|
||||
|
||||
args = $"#{title}";
|
||||
return hueInfo.IsBright() ? 1060839 : 1060838; // [bright] ~1_val~ seed
|
||||
}
|
||||
|
||||
if (m_ShowType)
|
||||
{
|
||||
args = $"{Amount}\t#{title}\t#{typeInfo.Name}";
|
||||
return typeInfo.GetSeedLabelPlural(hueInfo);
|
||||
}
|
||||
|
||||
args = $"{Amount}\t#{title}";
|
||||
return hueInfo.IsBright() ? 1113491 : 1113490; // ~1_amount~ [bright] ~2_val~ seeds
|
||||
}
|
||||
|
||||
public override void AddNameProperty(ObjectPropertyList list)
|
||||
{
|
||||
list.Add(GetLabel(out string args), args);
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
LabelTo(from, GetLabel(out string args), args);
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (!IsChildOf(from.Backpack))
|
||||
{
|
||||
from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
from.Target = new InternalTarget(this);
|
||||
LabelTo(from, 1061916); // Choose a bowl of dirt to plant this seed in.
|
||||
}
|
||||
|
||||
public override bool StackWith(Mobile from, Item dropped, bool playSound)
|
||||
{
|
||||
return dropped is Seed other && other.PlantType == m_PlantType && other.PlantHue == m_PlantHue &&
|
||||
other.ShowType == m_ShowType && base.StackWith(from, other, playSound);
|
||||
}
|
||||
|
||||
public override void OnAfterDuped(Item newItem)
|
||||
{
|
||||
if (!(newItem is Seed newSeed))
|
||||
return;
|
||||
|
||||
newSeed.PlantType = m_PlantType;
|
||||
newSeed.PlantHue = m_PlantHue;
|
||||
newSeed.ShowType = m_ShowType;
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(2); // version
|
||||
|
||||
writer.Write((int)m_PlantType);
|
||||
writer.Write((int)m_PlantHue);
|
||||
writer.Write(m_ShowType);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
m_PlantType = (PlantType)reader.ReadInt();
|
||||
m_PlantHue = (PlantHue)reader.ReadInt();
|
||||
m_ShowType = reader.ReadBool();
|
||||
|
||||
if (Weight != 1.0)
|
||||
Weight = 1.0;
|
||||
|
||||
if (version < 1)
|
||||
Stackable = Core.SA;
|
||||
|
||||
if (version < 2 && PlantHueInfo.IsCrossable(m_PlantHue))
|
||||
m_PlantHue |= PlantHue.Reproduces;
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private Seed m_Seed;
|
||||
|
||||
public InternalTarget(Seed seed) : base(-1, false, TargetFlags.None)
|
||||
{
|
||||
m_Seed = seed;
|
||||
CheckLOS = false;
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
if (m_Seed.Deleted)
|
||||
return;
|
||||
|
||||
if (!m_Seed.IsChildOf(from.Backpack))
|
||||
{
|
||||
from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (targeted is PlantItem plant)
|
||||
plant.PlantSeed(from, m_Seed);
|
||||
else if (targeted is Item item)
|
||||
item.LabelTo(from, 1061919); // You must use a seed on a bowl of dirt!
|
||||
else
|
||||
from.SendLocalizedMessage(1061919); // You must use a seed on a bowl of dirt!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
84
Projects/Scripts/Engines/Plants/SetToDecorativeGump.cs
Normal file
84
Projects/Scripts/Engines/Plants/SetToDecorativeGump.cs
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.Plants
|
||||
{
|
||||
public class SetToDecorativeGump : Gump
|
||||
{
|
||||
private PlantItem m_Plant;
|
||||
|
||||
public SetToDecorativeGump(PlantItem plant) : base(20, 20)
|
||||
{
|
||||
m_Plant = plant;
|
||||
|
||||
DrawBackground();
|
||||
|
||||
AddLabel(115, 85, 0x44, "Set plant");
|
||||
AddLabel(82, 105, 0x44, "to decorative mode?");
|
||||
|
||||
AddButton(98, 140, 0x47E, 0x480, 1); // Cancel
|
||||
|
||||
AddButton(138, 141, 0xD2, 0xD2, 2); // Help
|
||||
AddLabel(143, 141, 0x835, "?");
|
||||
|
||||
AddButton(168, 140, 0x481, 0x483, 3); // Ok
|
||||
}
|
||||
|
||||
private void DrawBackground()
|
||||
{
|
||||
AddBackground(50, 50, 200, 150, 0xE10);
|
||||
|
||||
AddItem(25, 45, 0xCEB);
|
||||
AddItem(25, 118, 0xCEC);
|
||||
|
||||
AddItem(227, 45, 0xCEF);
|
||||
AddItem(227, 118, 0xCF0);
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
Mobile from = sender.Mobile;
|
||||
|
||||
if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus != PlantStatus.Stage9)
|
||||
return;
|
||||
|
||||
if (info.ButtonID == 3 && !from.InRange(m_Plant.GetWorldLocation(), 3))
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_Plant.IsUsableBy(from))
|
||||
{
|
||||
m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it.
|
||||
return;
|
||||
}
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 1: // Cancel
|
||||
{
|
||||
from.SendGump(new ReproductionGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Help
|
||||
{
|
||||
from.Send(new DisplayHelpTopic(70, true)); // DECORATIVE MODE
|
||||
|
||||
from.SendGump(new SetToDecorativeGump(m_Plant));
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Ok
|
||||
{
|
||||
m_Plant.PlantStatus = PlantStatus.DecorativePlant;
|
||||
m_Plant.LabelTo(from,
|
||||
1053077); // You prune the plant. This plant will no longer produce resources or seeds, but will require no upkeep.
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue