Reorganizes Project (#41)

This commit is contained in:
Kamron Batman 2019-08-02 18:13:40 -07:00 • committed by GitHub
parent 08bf44af9a
commit 3614a66aee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3499 changed files with 79 additions and 55 deletions

View file

@ -0,0 +1,351 @@
using System;
using Server.Items;
using Server.Multis;
using Server.Network;
using Server.Targeting;
namespace Server.Mobiles
{
public abstract class BaseMount : BaseCreature, IMount
{
private Mobile m_Rider;
public BaseMount(string name, int bodyID, int itemID, AIType aiType, FightMode fightMode, int rangePerception,
int rangeFight, double activeSpeed, double passiveSpeed) : base(aiType, fightMode, rangePerception, rangeFight,
activeSpeed, passiveSpeed)
{
Name = name;
Body = bodyID;
InternalItem = new MountItem(this, itemID);
}
public BaseMount(Serial serial)
: base(serial)
{
}
public virtual TimeSpan MountAbilityDelay => TimeSpan.Zero;
[CommandProperty(AccessLevel.GameMaster)]
public DateTime NextMountAbility{ get; set; }
protected Item InternalItem{ get; private set; }
public virtual bool AllowMaleRider => true;
public virtual bool AllowFemaleRider => true;
[Hue]
[CommandProperty(AccessLevel.GameMaster)]
public override int Hue
{
get => base.Hue;
set
{
base.Hue = value;
if (InternalItem != null)
InternalItem.Hue = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int ItemID
{
get => InternalItem?.ItemID ?? 0;
set
{
if (InternalItem != null)
InternalItem.ItemID = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Rider
{
get => m_Rider;
set
{
if (m_Rider != value)
{
if (value == null)
{
Point3D loc = m_Rider.Location;
Map map = m_Rider.Map;
if (map == null || map == Map.Internal)
{
loc = m_Rider.LogoutLocation;
map = m_Rider.LogoutMap;
}
Direction = m_Rider.Direction;
Location = loc;
Map = map;
InternalItem?.Internalize();
}
else
{
if (m_Rider != null) Dismount(m_Rider);
Dismount(value);
if (InternalItem != null)
value.AddItem(InternalItem);
value.Direction = Direction;
Internalize();
if (value.Target is Bola.BolaTarget) Target.Cancel(value);
}
m_Rider = value;
}
}
}
public virtual void OnRiderDamaged(int amount, Mobile from, bool willKill)
{
if (m_Rider == null)
return;
Mobile attacker = from ?? m_Rider.FindMostRecentDamager(true);
if (!(attacker == this || attacker == m_Rider || willKill || DateTime.UtcNow < NextMountAbility)
&& DoMountAbility(amount, from))
NextMountAbility = DateTime.UtcNow + MountAbilityDelay;
}
public override bool OnBeforeDeath()
{
Rider = null;
return base.OnBeforeDeath();
}
public override void OnAfterDelete()
{
InternalItem?.Delete();
InternalItem = null;
base.OnAfterDelete();
}
public override void OnDelete()
{
Rider = null;
base.OnDelete();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
writer.Write(NextMountAbility);
writer.Write(m_Rider);
writer.Write(InternalItem);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
{
NextMountAbility = reader.ReadDateTime();
goto case 0;
}
case 0:
{
m_Rider = reader.ReadMobile();
InternalItem = reader.ReadItem();
if (InternalItem == null)
Delete();
break;
}
}
}
public virtual void OnDisallowedRider(Mobile m)
{
m.SendMessage("You may not ride this creature.");
}
public override void OnDoubleClick(Mobile from)
{
if (IsDeadPet)
return;
if (from.IsBodyMod && !from.Body.IsHuman)
{
if (Core.AOS) // You cannot ride a mount in your current form.
PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1062061, from.NetState);
else
from.SendLocalizedMessage(1061628); // You can't do that while polymorphed.
return;
}
if (!CheckMountAllowed(from))
return;
if (from.Mounted)
{
from.SendLocalizedMessage(1005583); // Please dismount first.
return;
}
if (from.Female ? !AllowFemaleRider : !AllowMaleRider)
{
OnDisallowedRider(from);
return;
}
if (!DesignContext.Check(from))
return;
if (from.HasTrade)
{
from.SendLocalizedMessage(1042317, "", 0x41); // You may not ride at this time
return;
}
if (from.InRange(this, 1))
{
bool canAccess = from.AccessLevel >= AccessLevel.GameMaster
|| Controlled && ControlMaster == from
|| Summoned && SummonMaster == from;
if (canAccess)
{
if (Poisoned)
PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1049692,
from.NetState); // This mount is too ill to ride.
else
Rider = from;
}
else if (!Controlled && !Summoned)
{
// That mount does not look broken! You would have to tame it to ride it.
PrivateOverheadMessage(MessageType.Regular, 0x3B2, 501263, from.NetState);
}
else
{
// This isn't your mount; it refuses to let you ride.
PrivateOverheadMessage(MessageType.Regular, 0x3B2, 501264, from.NetState);
}
}
else
{
from.SendLocalizedMessage(500206); // That is too far away to ride.
}
}
public static void Dismount(Mobile m)
{
IMount mount = m.Mount;
if (mount != null)
mount.Rider = null;
}
// 1040024 You are still too dazed from being knocked off your mount to ride!
// 1062910 You cannot mount while recovering from a bola throw.
// 1070859 You cannot mount while recovering from a dismount special maneuver.
public static bool CheckMountAllowed(Mobile mob)
{
bool result = true;
if (mob is PlayerMobile mobile && mobile.MountBlockReason != BlockMountType.None)
{
mobile.SendLocalizedMessage((int)mobile.MountBlockReason);
result = false;
}
return result;
}
public virtual bool DoMountAbility(int damage, Mobile attacker)
{
return false;
}
}
public class MountItem : Item, IMountItem
{
private BaseMount m_Mount;
public MountItem(BaseMount mount, int itemID) : base(itemID)
{
Layer = Layer.Mount;
Movable = false;
m_Mount = mount;
}
public MountItem(Serial serial) : base(serial)
{
}
public override double DefaultWeight => 0;
public IMount Mount => m_Mount;
public override void OnAfterDelete()
{
m_Mount?.Delete();
m_Mount = null;
base.OnAfterDelete();
}
public override DeathMoveResult OnParentDeath(Mobile parent)
{
if (m_Mount != null)
m_Mount.Rider = null;
return DeathMoveResult.RemainEquipped;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(m_Mount);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Mount = reader.ReadMobile() as BaseMount;
if (m_Mount == null)
Delete();
break;
}
}
}
}
}

View file

@ -0,0 +1,171 @@
using System.Collections.Generic;
using Server.ContextMenus;
using Server.Items;
namespace Server.Mobiles
{
public class Beetle : BaseMount
{
[Constructible]
public Beetle(string name = "a giant beetle") :
base(name, 0x317, 0x3EBC, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.25, 0.5)
{
SetStr(300);
SetDex(100);
SetInt(500);
SetHits(200);
SetDamage(7, 20);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 30, 40);
SetResistance(ResistanceType.Fire, 20, 30);
SetResistance(ResistanceType.Cold, 20, 30);
SetResistance(ResistanceType.Poison, 20, 30);
SetResistance(ResistanceType.Energy, 20, 30);
SetSkill(SkillName.MagicResist, 80.0);
SetSkill(SkillName.Tactics, 100.0);
SetSkill(SkillName.Wrestling, 100.0);
Fame = 4000;
Karma = -4000;
Tamable = true;
ControlSlots = 3;
MinTameSkill = 29.1;
Container pack = Backpack;
pack?.Delete();
pack = new StrongBackpack();
pack.Movable = false;
AddItem(pack);
}
public Beetle(Serial serial) : base(serial)
{
}
public override string CorpseName => "a giant beetle corpse";
public virtual double BoostedSpeed => 0.1;
public override bool SubdueBeforeTame => true; // Must be beaten into submission
public override bool ReduceSpeedWithDamage => false;
public override FoodType FavoriteFood => FoodType.Meat;
public override int GetAngerSound()
{
return 0x21D;
}
public override int GetIdleSound()
{
return 0x21D;
}
public override int GetAttackSound()
{
return 0x162;
}
public override int GetHurtSound()
{
return 0x163;
}
public override int GetDeathSound()
{
return 0x21D;
}
public override void OnHarmfulSpell(Mobile from)
{
if (!Controlled && ControlMaster == null)
CurrentSpeed = BoostedSpeed;
}
public override void OnCombatantChange()
{
if (Combatant == null && !Controlled && ControlMaster == null)
CurrentSpeed = PassiveSpeed;
}
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();
}
#region Pack Animal Methods
public override bool OnBeforeDeath()
{
if (!base.OnBeforeDeath())
return false;
PackAnimal.CombineBackpacks(this);
return true;
}
public override DeathMoveResult GetInventoryMoveResultFor(Item item)
{
return DeathMoveResult.MoveToCorpse;
}
public override bool IsSnoop(Mobile from)
{
if (PackAnimal.CheckAccess(this, from))
return false;
return base.IsSnoop(from);
}
public override bool OnDragDrop(Mobile from, Item item)
{
if (CheckFeed(from, item))
return true;
if (PackAnimal.CheckAccess(this, from))
{
AddToBackpack(item);
return true;
}
return base.OnDragDrop(from, item);
}
public override bool CheckNonlocalDrop(Mobile from, Item item, Item target)
{
return PackAnimal.CheckAccess(this, from);
}
public override bool CheckNonlocalLift(Mobile from, Item item)
{
return PackAnimal.CheckAccess(this, from);
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
PackAnimal.GetContextMenuEntries(this, from, list);
}
#endregion
}
}

View file

@ -0,0 +1,61 @@
namespace Server.Mobiles
{
public class DesertOstard : BaseMount
{
[Constructible]
public DesertOstard(string name = "a desert ostard") :
base(name, 0xD2, 0x3EA3, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
BaseSoundID = 0x270;
SetStr(94, 170);
SetDex(56, 75);
SetInt(6, 10);
SetHits(71, 88);
SetMana(0);
SetDamage(5, 11);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 15, 20);
SetResistance(ResistanceType.Fire, 5, 15);
SetSkill(SkillName.MagicResist, 25.1, 30.0);
SetSkill(SkillName.Tactics, 25.3, 40.0);
SetSkill(SkillName.Wrestling, 29.3, 44.0);
Fame = 450;
Karma = 0;
Tamable = true;
ControlSlots = 1;
MinTameSkill = 29.1;
}
public DesertOstard(Serial serial) : base(serial)
{
}
public override string CorpseName => "an ostard corpse";
public override int Meat => 3;
public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay;
public override PackInstinct PackInstinct => PackInstinct.Ostard;
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();
}
}
}

View file

@ -0,0 +1,839 @@
using System;
using Server.Engines.VeteranRewards;
using Server.Items;
using Server.Multis;
using Server.Spells;
namespace Server.Mobiles
{
public class EtherealMount : Item, IMount, IMountItem, IRewardItem
{
private bool m_IsDonationItem;
private int m_MountedID;
private int m_RegularID;
private Mobile m_Rider;
[Constructible]
public EtherealMount(int itemID, int mountID)
: base(itemID)
{
m_MountedID = mountID;
m_RegularID = itemID;
m_Rider = null;
Layer = Layer.Invalid;
LootType = LootType.Blessed;
}
public EtherealMount(Serial serial)
: base(serial)
{
}
public override double DefaultWeight => 1.0;
[CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)]
public bool IsDonationItem
{
get => m_IsDonationItem;
set
{
m_IsDonationItem = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int MountedID
{
get => m_MountedID;
set
{
if (m_MountedID != value)
{
m_MountedID = value;
if (m_Rider != null)
ItemID = value;
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int RegularID
{
get => m_RegularID;
set
{
if (m_RegularID != value)
{
m_RegularID = value;
if (m_Rider == null)
ItemID = value;
}
}
}
public override bool DisplayLootType => false;
public virtual int FollowerSlots => 1;
public virtual int EtherealHue => 0x4001;
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Rider
{
get => m_Rider;
set
{
if (value != m_Rider)
{
if (value == null)
{
Internalize();
UnmountMe();
RemoveFollowers();
m_Rider = null;
}
else
{
if (m_Rider != null)
Dismount(m_Rider);
Dismount(value);
RemoveFollowers();
m_Rider = value;
AddFollowers();
MountMe();
}
}
}
}
public void OnRiderDamaged(int amount, Mobile from, bool willKill)
{
}
public IMount Mount => this;
[CommandProperty(AccessLevel.GameMaster)]
public bool IsRewardItem{ get; set; }
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (m_IsDonationItem)
{
list.Add("Donation Ethereal");
list.Add("7.5 sec slower cast time if not a 9mo. Veteran");
}
if (Core.ML && IsRewardItem)
list.Add(RewardSystem.GetRewardYearLabel(this, new object[] { })); // X Year Veteran Reward
}
public void RemoveFollowers()
{
if (m_Rider != null)
m_Rider.Followers -= FollowerSlots;
if (m_Rider?.Followers < 0)
m_Rider.Followers = 0;
}
public void AddFollowers()
{
if (m_Rider != null)
m_Rider.Followers += FollowerSlots;
}
public virtual bool Validate(Mobile from)
{
if (Parent == null)
{
from.SayTo(from, 1010095); // This must be on your person to use.
return false;
}
if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this) || !BaseMount.CheckMountAllowed(from))
return false;
if (from.Mounted)
{
from.SendLocalizedMessage(1005583); // Please dismount first.
return false;
}
if (from.IsBodyMod && !from.Body.IsHuman)
{
from.SendLocalizedMessage(1061628); // You can't do that while polymorphed.
return false;
}
if (from.HasTrade)
{
from.SendLocalizedMessage(1042317, "", 0x41); // You may not ride at this time
return false;
}
if (from.Followers + FollowerSlots > from.FollowersMax)
{
from.SendLocalizedMessage(1049679); // You have too many followers to summon your mount.
return false;
}
return DesignContext.Check(from);
}
public override void OnDoubleClick(Mobile from)
{
if (Validate(from))
new EtherealSpell(this, from).Cast();
}
public override void OnSingleClick(Mobile from)
{
base.OnSingleClick(from);
LabelTo(from, m_IsDonationItem ? "Donation Ethereal" : "Veteran Reward");
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(3); // version
writer.Write(m_IsDonationItem);
writer.Write(IsRewardItem);
writer.Write(m_MountedID);
writer.Write(m_RegularID);
writer.Write(m_Rider);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
LootType = LootType.Blessed;
int version = reader.ReadInt();
switch (version)
{
case 3:
{
m_IsDonationItem = reader.ReadBool();
goto case 2;
}
case 2:
{
IsRewardItem = reader.ReadBool();
goto case 0;
}
case 1:
reader.ReadInt();
goto case 0;
case 0:
{
m_MountedID = reader.ReadInt();
m_RegularID = reader.ReadInt();
m_Rider = reader.ReadMobile();
if (m_MountedID == 0x3EA2)
m_MountedID = 0x3EAA;
break;
}
}
AddFollowers();
if (version < 3 && Weight == 0)
Weight = -1;
}
public override DeathMoveResult OnParentDeath(Mobile parent)
{
Rider = null; //get off, move to pack
return DeathMoveResult.RemainEquipped;
}
public static void Dismount(Mobile m)
{
IMount mount = m.Mount;
if (mount != null)
mount.Rider = null;
}
public void UnmountMe()
{
Container bp = m_Rider.Backpack;
ItemID = m_RegularID;
Layer = Layer.Invalid;
Movable = true;
if (Hue == EtherealHue)
Hue = 0;
if (bp != null)
{
bp.DropItem(this);
}
else
{
Point3D loc = m_Rider.Location;
Map map = m_Rider.Map;
if (map == null || map == Map.Internal)
{
loc = m_Rider.LogoutLocation;
map = m_Rider.LogoutMap;
}
MoveToWorld(loc, map);
}
}
public void MountMe()
{
ItemID = m_MountedID;
Layer = Layer.Mount;
Movable = false;
if (Hue == 0)
Hue = EtherealHue;
ProcessDelta();
m_Rider.ProcessDelta();
m_Rider.EquipItem(this);
m_Rider.ProcessDelta();
ProcessDelta();
}
public static void StopMounting(Mobile mob)
{
(mob.Spell as EtherealSpell)?.Stop();
}
private class EtherealSpell : Spell
{
private static SpellInfo m_Info = new SpellInfo("Ethereal Mount", "", 230);
private EtherealMount m_Mount;
private Mobile m_Rider;
private bool m_Stop;
public EtherealSpell(EtherealMount mount, Mobile rider)
: base(rider, null, m_Info)
{
m_Rider = rider;
m_Mount = mount;
}
public override bool ClearHandsOnCast => false;
public override bool RevealOnCast => false;
public override double CastDelayFastScalar => 0;
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(
m_Mount.IsDonationItem && RewardSystem.GetRewardLevel(m_Rider) < 3 ? 7.5 + (Core.AOS ? 3.0 : 2.0) :
Core.AOS ? 3.0 : 2.0);
public override TimeSpan GetCastRecovery()
{
return TimeSpan.Zero;
}
public override int GetMana()
{
return 0;
}
public override bool ConsumeReagents()
{
return true;
}
public override bool CheckFizzle()
{
return true;
}
public void Stop()
{
m_Stop = true;
Disturb(DisturbType.Hurt, false);
}
public override bool CheckDisturb(DisturbType type, bool checkFirst, bool resistable)
{
if (type == DisturbType.EquipRequest || type == DisturbType.UseRequest /* || type == DisturbType.Hurt*/)
return false;
return true;
}
public override void DoHurtFizzle()
{
if (!m_Stop)
base.DoHurtFizzle();
}
public override void DoFizzle()
{
if (!m_Stop)
base.DoFizzle();
}
public override void OnDisturb(DisturbType type, bool message)
{
if (message && !m_Stop)
Caster.SendLocalizedMessage(
1049455); // You have been disrupted while attempting to summon your ethereal mount!
//m_Mount.UnmountMe();
}
public override void OnCast()
{
if (!m_Mount.Deleted && m_Mount.Rider == null && m_Mount.Validate(m_Rider))
m_Mount.Rider = m_Rider;
FinishSequence();
}
}
}
public class EtherealHorse : EtherealMount
{
[Constructible]
public EtherealHorse()
: base(0x20DD, 0x3EAA)
{
}
public EtherealHorse(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1041298; // Ethereal Horse Statuette
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();
if (Name == "an ethereal horse")
Name = null;
if (ItemID == 0x2124)
ItemID = 0x20DD;
}
}
public class EtherealLlama : EtherealMount
{
[Constructible]
public EtherealLlama()
: base(0x20F6, 0x3EAB)
{
}
public EtherealLlama(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1041300; // Ethereal Llama Statuette
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();
if (Name == "an ethereal llama")
Name = null;
}
}
public class EtherealOstard : EtherealMount
{
[Constructible]
public EtherealOstard()
: base(0x2135, 0x3EAC)
{
}
public EtherealOstard(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1041299; // Ethereal Ostard Statuette
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();
if (Name == "an ethereal ostard")
Name = null;
}
}
public class EtherealRidgeback : EtherealMount
{
[Constructible]
public EtherealRidgeback()
: base(0x2615, 0x3E9A)
{
}
public EtherealRidgeback(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1049747; // Ethereal Ridgeback Statuette
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();
if (Name == "an ethereal ridgeback")
Name = null;
}
}
public class EtherealUnicorn : EtherealMount
{
[Constructible]
public EtherealUnicorn()
: base(0x25CE, 0x3E9B)
{
}
public EtherealUnicorn(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1049745; // Ethereal Unicorn Statuette
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();
if (Name == "an ethereal unicorn")
Name = null;
}
}
public class EtherealBeetle : EtherealMount
{
[Constructible]
public EtherealBeetle()
: base(0x260F, 0x3E97)
{
}
public EtherealBeetle(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1049748; // Ethereal Beetle Statuette
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();
if (Name == "an ethereal beetle")
Name = null;
}
}
public class EtherealKirin : EtherealMount
{
[Constructible]
public EtherealKirin()
: base(0x25A0, 0x3E9C)
{
}
public EtherealKirin(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1049746; // Ethereal Ki-Rin Statuette
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();
if (Name == "an ethereal kirin")
Name = null;
}
}
public class EtherealSwampDragon : EtherealMount
{
[Constructible]
public EtherealSwampDragon()
: base(0x2619, 0x3E98)
{
}
public EtherealSwampDragon(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1049749; // Ethereal Swamp Dragon Statuette
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();
if (Name == "an ethereal swamp dragon")
Name = null;
}
}
public class RideablePolarBear : EtherealMount
{
[Constructible]
public RideablePolarBear()
: base(0x20E1, 0x3EC5)
{
}
public RideablePolarBear(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1076159; // Rideable Polar Bear
public override int EtherealHue => 0;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
public class EtherealCuSidhe : EtherealMount
{
[Constructible]
public EtherealCuSidhe()
: base(0x2D96, 0x3E91)
{
}
public EtherealCuSidhe(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1080386; // Ethereal Cu Sidhe Statuette
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
public class EtherealHiryu : EtherealMount
{
[Constructible]
public EtherealHiryu()
: base(0x276A, 0x3E94)
{
}
public EtherealHiryu(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1113813; // Ethereal Hiryu Statuette
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
public class EtherealReptalon : EtherealMount
{
[Constructible]
public EtherealReptalon()
: base(0x2d95, 0x3e90)
{
}
public EtherealReptalon(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1113812; // Ethereal Reptalon Statuette
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
public class ChargerOfTheFallen : EtherealMount
{
[Constructible]
public ChargerOfTheFallen()
: base(0x2D9C, 0x3E92)
{
}
public ChargerOfTheFallen(Serial serial)
: base(serial)
{
}
public override int LabelNumber => 1074816; // Charger of the Fallen Statuette
public override int EtherealHue => 0;
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();
if (version <= 1 && Hue != 0) Hue = 0;
}
}
}

View file

@ -0,0 +1,84 @@
using System;
using Server.Items;
namespace Server.Mobiles
{
public class FireSteed : BaseMount
{
[Constructible]
public FireSteed(string name = "a fire steed") :
base(name, 0xBE, 0x3E9E, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
BaseSoundID = 0xA8;
SetStr(376, 400);
SetDex(91, 120);
SetInt(291, 300);
SetHits(226, 240);
SetDamage(11, 30);
SetDamageType(ResistanceType.Physical, 20);
SetDamageType(ResistanceType.Fire, 80);
SetResistance(ResistanceType.Physical, 30, 40);
SetResistance(ResistanceType.Fire, 70, 80);
SetResistance(ResistanceType.Cold, 20, 30);
SetResistance(ResistanceType.Poison, 30, 40);
SetResistance(ResistanceType.Energy, 30, 40);
SetSkill(SkillName.MagicResist, 100.0, 120.0);
SetSkill(SkillName.Tactics, 100.0);
SetSkill(SkillName.Wrestling, 100.0);
Fame = 20000;
Karma = -20000;
Tamable = true;
ControlSlots = 2;
MinTameSkill = 106.0;
}
public FireSteed(Serial serial) : base(serial)
{
}
public override string CorpseName => "a fire steed corpse";
public override bool HasBreath => true; // fire breath enabled
public override FoodType FavoriteFood => FoodType.Meat;
public override PackInstinct PackInstinct => PackInstinct.Daemon | PackInstinct.Equine;
public override void GenerateLoot()
{
PackItem(new SulfurousAsh(Utility.RandomMinMax(151, 300)));
PackItem(new Ruby(Utility.RandomMinMax(16, 30)));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (BaseSoundID <= 0)
BaseSoundID = 0xA8;
if (version < 1)
for (int i = 0; i < Skills.Length; ++i)
{
Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9);
if (Skills[i].Base > Skills[i].Cap) Skills[i].Base = Skills[i].Cap;
}
}
}
}

View file

@ -0,0 +1,62 @@
namespace Server.Mobiles
{
public class ForestOstard : BaseMount
{
[Constructible]
public ForestOstard(string name = "a forest ostard") :
base(name, 0xDB, 0x3EA5, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
Hue = Utility.RandomSlimeHue() | 0x8000;
BaseSoundID = 0x270;
SetStr(94, 170);
SetDex(56, 75);
SetInt(6, 10);
SetHits(71, 88);
SetMana(0);
SetDamage(8, 14);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 15, 20);
SetSkill(SkillName.MagicResist, 27.1, 32.0);
SetSkill(SkillName.Tactics, 29.3, 44.0);
SetSkill(SkillName.Wrestling, 29.3, 44.0);
Fame = 450;
Karma = 0;
Tamable = true;
ControlSlots = 1;
MinTameSkill = 29.1;
}
public ForestOstard(Serial serial) : base(serial)
{
}
public override string CorpseName => "an ostard corpse";
public override int Meat => 3;
public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay;
public override PackInstinct PackInstinct => PackInstinct.Ostard;
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();
}
}
}

View file

@ -0,0 +1,65 @@
namespace Server.Mobiles
{
public class FrenziedOstard : BaseMount
{
[Constructible]
public FrenziedOstard(string name = "a frenzied ostard") :
base(name, 0xDA, 0x3EA4, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Hue = Race.Human.RandomHairHue() | 0x8000;
BaseSoundID = 0x275;
SetStr(94, 170);
SetDex(96, 115);
SetInt(6, 10);
SetHits(71, 110);
SetMana(0);
SetDamage(11, 17);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 25, 30);
SetResistance(ResistanceType.Fire, 10, 15);
SetResistance(ResistanceType.Poison, 20, 25);
SetResistance(ResistanceType.Energy, 20, 25);
SetSkill(SkillName.MagicResist, 75.1, 80.0);
SetSkill(SkillName.Tactics, 79.3, 94.0);
SetSkill(SkillName.Wrestling, 79.3, 94.0);
Fame = 1500;
Karma = -1500;
Tamable = true;
ControlSlots = 1;
MinTameSkill = 77.1;
}
public FrenziedOstard(Serial serial) : base(serial)
{
}
public override string CorpseName => "an ostard corpse";
public override int Meat => 3;
public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish | FoodType.Eggs | FoodType.FruitsAndVegies;
public override PackInstinct PackInstinct => PackInstinct.Ostard;
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();
}
}
}

View file

@ -0,0 +1,60 @@
namespace Server.Mobiles
{
public class HellSteed : BaseMount
{
[Constructible]
public HellSteed(string name = "a hellsteed") :
base(name, 793, 0x3EBB, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
SetStats(this);
}
public HellSteed(Serial serial) : base(serial)
{
}
public override string CorpseName => "a hellsteed corpse";
public override bool HasBreath => true;
public override int BreathChaosDamage => 100;
public override Poison PoisonImmune => Poison.Lethal;
public static void SetStats(BaseCreature steed)
{
steed.SetStr(201, 210);
steed.SetDex(101, 110);
steed.SetInt(101, 115);
steed.SetHits(201, 220);
steed.SetDamage(20, 24);
steed.SetDamageType(ResistanceType.Physical, 25);
steed.SetDamageType(ResistanceType.Fire, 75);
steed.SetResistance(ResistanceType.Physical, 60, 70);
steed.SetResistance(ResistanceType.Fire, 90);
steed.SetResistance(ResistanceType.Poison, 100);
steed.SetSkill(SkillName.MagicResist, 90.1, 110.0);
steed.SetSkill(SkillName.Tactics, 50.0);
steed.SetSkill(SkillName.Wrestling, 90.1, 110.0);
steed.Fame = 0;
steed.Karma = 0;
}
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();
}
}
}

View file

@ -0,0 +1,258 @@
using System;
using System.Collections.Generic;
using Server.Engines.Plants;
using Server.Items;
namespace Server.Mobiles
{
public class Hiryu : BaseMount
{
private static Dictionary<Mobile, ExpireTimer> m_Table = new Dictionary<Mobile, ExpireTimer>();
[Constructible]
public Hiryu()
: base("a hiryu", 243, 0x3E94, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Hue = GetHue();
SetStr(1201, 1410);
SetDex(171, 270);
SetInt(301, 325);
SetHits(901, 1100);
SetMana(60);
SetDamage(20, 30);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 55, 70);
SetResistance(ResistanceType.Fire, 70, 90);
SetResistance(ResistanceType.Cold, 15, 25);
SetResistance(ResistanceType.Poison, 40, 50);
SetResistance(ResistanceType.Energy, 40, 50);
SetSkill(SkillName.Anatomy, 75.1, 80.0);
SetSkill(SkillName.MagicResist, 85.1, 100.0);
SetSkill(SkillName.Tactics, 100.1, 110.0);
SetSkill(SkillName.Wrestling, 100.1, 120.0);
Fame = 18000;
Karma = -18000;
Tamable = true;
ControlSlots = 4;
MinTameSkill = 98.7;
if (Utility.RandomDouble() < .33)
PackItem(Seed.RandomBonsaiSeed());
if (Core.ML && Utility.RandomDouble() < .33)
PackItem(Seed.RandomPeculiarSeed(3));
}
public Hiryu(Serial serial)
: base(serial)
{
}
public override string CorpseName => "a hiryu corpse";
public override double WeaponAbilityChance => 0.07; /* 1 in 15 chance of using per landed hit */
public override bool StatLossAfterTame => true;
public override int TreasureMapLevel => 5;
public override int Meat => 16;
public override int Hides => 60;
public override FoodType FavoriteFood => FoodType.Meat;
public override bool CanAngerOnTame => true;
public override WeaponAbility GetWeaponAbility()
{
return WeaponAbility.Dismount;
}
private static int GetHue()
{
int rand = Utility.Random(1075);
/*
1000 1075 No Hue Color 93.02% 0x0
*
10 1075 Ice Green 0.93% 0x847F
10 1075 Light Blue 0.93% 0x848D
10 1075 Strong Cyan 0.93% 0x8495
10 1075 Agapite 0.93% 0x8899
10 1075 Gold 0.93% 0x8032
*
8 1075 Blue and Yellow 0.74% 0x8487
*
5 1075 Ice Blue 0.47% 0x8482
*
3 1075 Cyan 0.28% 0x8123
3 1075 Light Green 0.28% 0x8295
*
2 1075 Strong Yellow 0.19% 0x8037
2 1075 Green 0.19% 0x8030 //this one is an approximation
*
1 1075 Strong Purple 0.09% 0x8490
1 1075 Strong Green 0.09% 0x855C
* */
if (rand <= 0)
return 0x855C;
if (rand <= 1)
return 0x8490;
if (rand <= 3)
return 0x8030;
if (rand <= 5)
return 0x8037;
if (rand <= 8)
return 0x8295;
if (rand <= 11)
return 0x8123;
if (rand <= 16)
return 0x8482;
if (rand <= 24)
return 0x8487;
if (rand <= 34)
return 0x8032;
if (rand <= 44)
return 0x8899;
if (rand <= 54)
return 0x8495;
if (rand <= 64)
return 0x848D;
if (rand <= 74)
return 0x847F;
return 0;
}
public override int GetAngerSound()
{
return 0x4FE;
}
public override int GetIdleSound()
{
return 0x4FD;
}
public override int GetAttackSound()
{
return 0x4FC;
}
public override int GetHurtSound()
{
return 0x4FF;
}
public override int GetDeathSound()
{
return 0x4FB;
}
public override void GenerateLoot()
{
AddLoot(LootPack.FilthyRich, 3);
AddLoot(LootPack.Gems, 4);
}
public override void OnGaveMeleeAttack(Mobile defender)
{
base.OnGaveMeleeAttack(defender);
if (0.1 <= Utility.RandomDouble())
return;
/* Grasping Claw
* Start cliloc: 1070836
* Effect: Physical resistance -15% for 5 seconds
* End cliloc: 1070838
* Effect: Type: "3" - From: "0x57D4F5B" (player) - To: "0x0" - ItemId: "0x37B9" - ItemIdName: "glow" - FromLocation: "(1149 808, 32)" - ToLocation: "(1149 808, 32)" - Speed: "10" - Duration: "5" - FixedDirection: "True" - Explode: "False"
*/
if (m_Table.TryGetValue(defender, out ExpireTimer timer))
{
timer.DoExpire();
defender.SendLocalizedMessage(1070837); // The creature lands another blow in your weakened state.
}
else
{
defender.SendLocalizedMessage(
1070836); // The blow from the creature's claws has made you more susceptible to physical attacks.
}
int effect = -(defender.PhysicalResistance * 15 / 100);
ResistanceMod mod = new ResistanceMod(ResistanceType.Physical, effect);
defender.FixedEffect(0x37B9, 10, 5);
defender.AddResistanceMod(mod);
timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(5.0));
timer.Start();
m_Table[defender] = timer;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(2);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (version == 0)
Timer.DelayCall(TimeSpan.Zero, delegate { Hue = GetHue(); });
if (version <= 1)
Timer.DelayCall(TimeSpan.Zero, delegate
{
if (InternalItem != null) InternalItem.Hue = Hue;
});
if (version < 2)
for (int i = 0; i < Skills.Length; ++i)
{
Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9);
if (Skills[i].Base > Skills[i].Cap) Skills[i].Base = Skills[i].Cap;
}
}
private class ExpireTimer : Timer
{
private Mobile m_Mobile;
private ResistanceMod m_Mod;
public ExpireTimer(Mobile m, ResistanceMod mod, TimeSpan delay)
: base(delay)
{
m_Mobile = m;
m_Mod = mod;
Priority = TimerPriority.TwoFiftyMS;
}
public void DoExpire()
{
m_Mobile.RemoveResistanceMod(m_Mod);
Stop();
m_Table.Remove(m_Mobile);
}
protected override void OnTick()
{
m_Mobile.SendLocalizedMessage(1070838); // Your resistance to physical attacks has returned.
DoExpire();
}
}
}
}

View file

@ -0,0 +1,74 @@
namespace Server.Mobiles
{
[TypeAlias("Server.Mobiles.BrownHorse", "Server.Mobiles.DirtyHorse", "Server.Mobiles.GrayHorse",
"Server.Mobiles.TanHorse")]
public class Horse : BaseMount
{
private static int[] m_IDs =
{
0xC8, 0x3E9F,
0xE2, 0x3EA0,
0xE4, 0x3EA1,
0xCC, 0x3EA2
};
[Constructible]
public Horse(string name = "a horse") :
base(name, 0xE2, 0x3EA0, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
int random = Utility.Random(4);
Body = m_IDs[random * 2];
ItemID = m_IDs[random * 2 + 1];
BaseSoundID = 0xA8;
SetStr(22, 98);
SetDex(56, 75);
SetInt(6, 10);
SetHits(28, 45);
SetMana(0);
SetDamage(3, 4);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 15, 20);
SetSkill(SkillName.MagicResist, 25.1, 30.0);
SetSkill(SkillName.Tactics, 29.3, 44.0);
SetSkill(SkillName.Wrestling, 29.3, 44.0);
Fame = 300;
Karma = 300;
Tamable = true;
ControlSlots = 1;
MinTameSkill = 29.1;
}
public Horse(Serial serial) : base(serial)
{
}
public override string CorpseName => "a horse corpse";
public override int Meat => 3;
public override int Hides => 10;
public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay;
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();
}
}
}

View file

@ -0,0 +1,128 @@
using System;
using Server.Items;
using Server.Network;
namespace Server.Mobiles
{
public class Kirin : BaseMount
{
[Constructible]
public Kirin(string name = "a ki-rin") :
base(name, 132, 0x3EAD, AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4)
{
BaseSoundID = 0x3C5;
SetStr(296, 325);
SetDex(86, 105);
SetInt(186, 225);
SetHits(191, 210);
SetDamage(16, 22);
SetDamageType(ResistanceType.Physical, 70);
SetDamageType(ResistanceType.Fire, 10);
SetDamageType(ResistanceType.Cold, 10);
SetDamageType(ResistanceType.Energy, 10);
SetResistance(ResistanceType.Physical, 55, 65);
SetResistance(ResistanceType.Fire, 35, 45);
SetResistance(ResistanceType.Cold, 25, 35);
SetResistance(ResistanceType.Poison, 25, 35);
SetResistance(ResistanceType.Energy, 25, 35);
SetSkill(SkillName.EvalInt, 80.1, 90.0);
SetSkill(SkillName.Magery, 60.4, 100.0);
SetSkill(SkillName.Meditation, 90.1, 100.0);
SetSkill(SkillName.MagicResist, 85.3, 100.0);
SetSkill(SkillName.Tactics, 20.1, 22.5);
SetSkill(SkillName.Wrestling, 80.5, 92.5);
Fame = 9000;
Karma = 9000;
Tamable = true;
ControlSlots = 2;
MinTameSkill = 95.1;
}
public Kirin(Serial serial) : base(serial)
{
}
public override string CorpseName => "a ki-rin corpse";
public override bool AllowFemaleRider => false;
public override bool AllowFemaleTamer => false;
public override bool InitialInnocent => true;
public override TimeSpan MountAbilityDelay => TimeSpan.FromHours(1.0);
public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead;
public override int Meat => 3;
public override int Hides => 10;
public override HideType HideType => HideType.Horned;
public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay;
public override void OnDisallowedRider(Mobile m)
{
m.SendLocalizedMessage(1042319); // The Ki-Rin refuses your attempts to mount it.
}
public override bool DoMountAbility(int damage, Mobile attacker)
{
if (Rider == null || attacker == null) //sanity
return false;
if (Rider.Hits - damage < 30 && Rider.Map == attacker.Map && Rider.InRange(attacker, 18)
) //Range and map checked here instead of other base fuction because of abiliites that don't need to check this
{
attacker.BoltEffect(0);
// 35~100 damage, unresistable, by the Ki-rin.
attacker.Damage(Utility.RandomMinMax(35, 100), this,
false); //Don't inform mount about this damage, Still unsure wether or not it's flagged as the mount doing damage or the player. If changed to player, without the extra bool it'd be an infinite loop
Rider.LocalOverheadMessage(MessageType.Regular, 0x3B2,
1042534); // Your mount calls down the forces of nature on your opponent.
Rider.FixedParticles(0, 0, 0, 0x13A7, EffectLayer.Waist);
Rider.PlaySound(0xA9); // Ki-rin's whinny.
return true;
}
return false;
}
public override void GenerateLoot()
{
AddLoot(LootPack.Rich);
AddLoot(LootPack.LowScrolls);
AddLoot(LootPack.Potions);
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
if (Utility.RandomDouble() < 0.35)
c.DropItem(new KirinBrains());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (version == 0)
AI = AIType.AI_Mage;
}
}
}

View file

@ -0,0 +1,252 @@
using System;
using System.Collections.Generic;
using Server.Engines.Plants;
using Server.Items;
namespace Server.Mobiles
{
public class LesserHiryu : BaseMount
{
private static Dictionary<Mobile, ExpireTimer> m_Table = new Dictionary<Mobile, ExpireTimer>();
[Constructible]
public LesserHiryu()
: base("a lesser hiryu", 243, 0x3E94, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Hue = GetHue();
SetStr(301, 410);
SetDex(171, 270);
SetInt(301, 325);
SetHits(401, 600);
SetMana(60);
SetDamage(18, 23);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 45, 70);
SetResistance(ResistanceType.Fire, 60, 80);
SetResistance(ResistanceType.Cold, 5, 15);
SetResistance(ResistanceType.Poison, 30, 40);
SetResistance(ResistanceType.Energy, 30, 40);
SetSkill(SkillName.Anatomy, 75.1, 80.0);
SetSkill(SkillName.MagicResist, 85.1, 100.0);
SetSkill(SkillName.Tactics, 100.1, 110.0);
SetSkill(SkillName.Wrestling, 100.1, 120.0);
Fame = 10000;
Karma = -10000;
Tamable = true;
ControlSlots = 3;
MinTameSkill = 98.7;
if (Utility.RandomDouble() < .33)
PackItem(Seed.RandomBonsaiSeed());
}
public LesserHiryu(Serial serial)
: base(serial)
{
}
public override string CorpseName => "a hiryu corpse";
public override double WeaponAbilityChance => 0.07; /* 1 in 15 chance of using; 1 in 5 chance of success */
public override bool StatLossAfterTame => true;
public override int TreasureMapLevel => 3;
public override int Meat => 16;
public override int Hides => 60;
public override FoodType FavoriteFood => FoodType.Meat;
public override bool CanAngerOnTame => true;
public override WeaponAbility GetWeaponAbility()
{
return WeaponAbility.Dismount;
}
private static int GetHue()
{
int rand = Utility.Random(527);
/*
500 527 No Hue Color 94.88% 0
10 527 Green 1.90% 0x8295
10 527 Green 1.90% 0x8163 (Very Close to Above Green) //this one is an approximation
5 527 Dark Green 0.95% 0x87D4
1 527 Valorite 0.19% 0x88AB
1 527 Midnight Blue 0.19% 0x8258
* */
if (rand <= 0)
return 0x8258;
if (rand <= 1)
return 0x88AB;
if (rand <= 6)
return 0x87D4;
if (rand <= 16)
return 0x8163;
if (rand <= 26)
return 0x8295;
return 0;
}
public override bool OverrideBondingReqs()
{
if (ControlMaster.Skills.Bushido.Base >= 90.0)
return true;
return false;
}
public override int GetAngerSound()
{
return 0x4FE;
}
public override int GetIdleSound()
{
return 0x4FD;
}
public override int GetAttackSound()
{
return 0x4FC;
}
public override int GetHurtSound()
{
return 0x4FF;
}
public override int GetDeathSound()
{
return 0x4FB;
}
public override void GenerateLoot()
{
AddLoot(LootPack.FilthyRich, 2);
AddLoot(LootPack.Gems, 4);
}
public override double GetControlChance(Mobile m, bool useBaseSkill = false)
{
double tamingChance = base.GetControlChance(m, useBaseSkill);
if (tamingChance >= 0.95) return tamingChance;
double skill = useBaseSkill ? m.Skills.Bushido.Base : m.Skills.Bushido.Value;
if (skill < 90.0) return tamingChance;
double bushidoChance = (skill - 30.0) / 100;
if (m.Skills.Bushido.Base >= 120)
bushidoChance += 0.05;
return bushidoChance > tamingChance ? bushidoChance : tamingChance;
}
public override void OnGaveMeleeAttack(Mobile defender)
{
base.OnGaveMeleeAttack(defender);
if (0.1 <= Utility.RandomDouble())
return;
/* Grasping Claw
* Start cliloc: 1070836
* Effect: Physical resistance -15% for 5 seconds
* End cliloc: 1070838
* Effect: Type: "3" - From: "0x57D4F5B" (player) - To: "0x0" - ItemId: "0x37B9" - ItemIdName: "glow" - FromLocation: "(1149 808, 32)" - ToLocation: "(1149 808, 32)" - Speed: "10" - Duration: "5" - FixedDirection: "True" - Explode: "False"
*/
if (m_Table.TryGetValue(defender, out ExpireTimer timer))
{
timer.DoExpire();
defender.SendLocalizedMessage(1070837); // The creature lands another blow in your weakened state.
}
else
{
defender.SendLocalizedMessage(
1070836); // The blow from the creature's claws has made you more susceptible to physical attacks.
}
int effect = -(defender.PhysicalResistance * 15 / 100);
ResistanceMod mod = new ResistanceMod(ResistanceType.Physical, effect);
defender.FixedEffect(0x37B9, 10, 5);
defender.AddResistanceMod(mod);
timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(5.0));
timer.Start();
m_Table[defender] = timer;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(2);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (version == 0)
Timer.DelayCall(TimeSpan.Zero, delegate { Hue = GetHue(); });
if (version <= 1)
Timer.DelayCall(TimeSpan.Zero, delegate
{
if (InternalItem != null) InternalItem.Hue = Hue;
});
if (version < 2)
for (int i = 0; i < Skills.Length; ++i)
{
Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9);
if (Skills[i].Base > Skills[i].Cap) Skills[i].Base = Skills[i].Cap;
}
}
private class ExpireTimer : Timer
{
private Mobile m_Mobile;
private ResistanceMod m_Mod;
public ExpireTimer(Mobile m, ResistanceMod mod, TimeSpan delay)
: base(delay)
{
m_Mobile = m;
m_Mod = mod;
Priority = TimerPriority.TwoFiftyMS;
}
public void DoExpire()
{
m_Mobile.RemoveResistanceMod(m_Mod);
Stop();
m_Table.Remove(m_Mobile);
}
protected override void OnTick()
{
m_Mobile.SendLocalizedMessage(1070838); // Your resistance to physical attacks has returned.
DoExpire();
}
}
}
}

View file

@ -0,0 +1,119 @@
using Server.Items;
namespace Server.Mobiles
{
public class Nightmare : BaseMount
{
[Constructible]
public Nightmare(string name = "a nightmare") :
base(name, 0x74, 0x3EA7, AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4)
{
BaseSoundID = Core.AOS ? 0xA8 : 0x16A;
SetStr(496, 525);
SetDex(86, 105);
SetInt(86, 125);
SetHits(298, 315);
SetDamage(16, 22);
SetDamageType(ResistanceType.Physical, 40);
SetDamageType(ResistanceType.Fire, 40);
SetDamageType(ResistanceType.Energy, 20);
SetResistance(ResistanceType.Physical, 55, 65);
SetResistance(ResistanceType.Fire, 30, 40);
SetResistance(ResistanceType.Cold, 30, 40);
SetResistance(ResistanceType.Poison, 30, 40);
SetResistance(ResistanceType.Energy, 20, 30);
SetSkill(SkillName.EvalInt, 10.4, 50.0);
SetSkill(SkillName.Magery, 10.4, 50.0);
SetSkill(SkillName.MagicResist, 85.3, 100.0);
SetSkill(SkillName.Tactics, 97.6, 100.0);
SetSkill(SkillName.Wrestling, 80.5, 92.5);
Fame = 14000;
Karma = -14000;
VirtualArmor = 60;
Tamable = true;
ControlSlots = 2;
MinTameSkill = 95.1;
switch (Utility.Random(3))
{
case 0:
{
BodyValue = 116;
ItemID = 16039;
break;
}
case 1:
{
BodyValue = 178;
ItemID = 16041;
break;
}
case 2:
{
BodyValue = 179;
ItemID = 16055;
break;
}
}
PackItem(new SulfurousAsh(Utility.RandomMinMax(3, 5)));
}
public Nightmare(Serial serial) : base(serial)
{
}
public override string CorpseName => "a nightmare corpse";
public override bool HasBreath => true; // fire breath enabled
public override int Meat => 5;
public override int Hides => 10;
public override HideType HideType => HideType.Barbed;
public override FoodType FavoriteFood => FoodType.Meat;
public override bool CanAngerOnTame => true;
public override void GenerateLoot()
{
AddLoot(LootPack.Rich);
AddLoot(LootPack.Average);
AddLoot(LootPack.LowScrolls);
AddLoot(LootPack.Potions);
}
public override int GetAngerSound()
{
if (!Controlled)
return 0x16A;
return base.GetAngerSound();
}
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();
if (Core.AOS && BaseSoundID == 0x16A)
BaseSoundID = 0xA8;
else if (!Core.AOS && BaseSoundID == 0xA8)
BaseSoundID = 0x16A;
}
}
}

View file

@ -0,0 +1,64 @@
namespace Server.Mobiles
{
public class RidableLlama : BaseMount
{
[Constructible]
public RidableLlama(string name = "a ridable llama") :
base(name, 0xDC, 0x3EA6, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
BaseSoundID = 0x3F3;
SetStr(21, 49);
SetDex(56, 75);
SetInt(16, 30);
SetHits(15, 27);
SetMana(0);
SetDamage(3, 5);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 10, 15);
SetResistance(ResistanceType.Fire, 5, 10);
SetResistance(ResistanceType.Cold, 5, 10);
SetResistance(ResistanceType.Poison, 5, 10);
SetResistance(ResistanceType.Energy, 5, 10);
SetSkill(SkillName.MagicResist, 15.1, 20.0);
SetSkill(SkillName.Tactics, 19.2, 29.0);
SetSkill(SkillName.Wrestling, 19.2, 29.0);
Fame = 300;
Karma = 0;
Tamable = true;
ControlSlots = 1;
MinTameSkill = 29.1;
}
public RidableLlama(Serial serial) : base(serial)
{
}
public override string CorpseName => "a llama corpse";
public override int Meat => 1;
public override int Hides => 12;
public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay;
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();
}
}
}

View file

@ -0,0 +1,75 @@
namespace Server.Mobiles
{
public class Ridgeback : BaseMount
{
[Constructible]
public Ridgeback(string name = "a ridgeback") :
base(name, 187, 0x3EBA, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
BaseSoundID = 0x3F3;
SetStr(58, 100);
SetDex(56, 75);
SetInt(16, 30);
SetHits(41, 54);
SetMana(0);
SetDamage(3, 5);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 15, 25);
SetResistance(ResistanceType.Fire, 5, 10);
SetResistance(ResistanceType.Cold, 5, 10);
SetResistance(ResistanceType.Poison, 5, 10);
SetResistance(ResistanceType.Energy, 5, 10);
SetSkill(SkillName.MagicResist, 25.3, 40.0);
SetSkill(SkillName.Tactics, 29.3, 44.0);
SetSkill(SkillName.Wrestling, 35.1, 45.0);
Fame = 300;
Karma = 0;
Tamable = true;
ControlSlots = 1;
MinTameSkill = 83.1;
}
public Ridgeback(Serial serial) : base(serial)
{
}
public override string CorpseName => "a ridgeback corpse";
public override int Meat => 1;
public override int Hides => 12;
public override HideType HideType => HideType.Spined;
public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay;
public override bool OverrideBondingReqs()
{
return true;
}
public override double GetControlChance(Mobile m, bool useBaseSkill = false)
{
return 1.0;
}
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();
}
}
}

View file

@ -0,0 +1,75 @@
namespace Server.Mobiles
{
public class SavageRidgeback : BaseMount
{
[Constructible]
public SavageRidgeback(string name = "a savage ridgeback") :
base(name, 188, 0x3EB8, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
BaseSoundID = 0x3F3;
SetStr(58, 100);
SetDex(56, 75);
SetInt(16, 30);
SetHits(41, 54);
SetMana(0);
SetDamage(3, 5);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 15, 20);
SetResistance(ResistanceType.Fire, 10, 15);
SetResistance(ResistanceType.Cold, 15, 20);
SetResistance(ResistanceType.Poison, 10, 15);
SetResistance(ResistanceType.Energy, 10, 15);
SetSkill(SkillName.MagicResist, 25.3, 40.0);
SetSkill(SkillName.Tactics, 29.3, 44.0);
SetSkill(SkillName.Wrestling, 35.1, 45.0);
Fame = 300;
Karma = 0;
Tamable = true;
ControlSlots = 1;
MinTameSkill = 83.1;
}
public SavageRidgeback(Serial serial) : base(serial)
{
}
public override string CorpseName => "a savage ridgeback corpse";
public override int Meat => 1;
public override int Hides => 12;
public override HideType HideType => HideType.Spined;
public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay;
public override bool OverrideBondingReqs()
{
return true;
}
public override double GetControlChance(Mobile m, bool useBaseSkill = false)
{
return 1.0;
}
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();
}
}
}

View file

@ -0,0 +1,72 @@
namespace Server.Mobiles
{
public class ScaledSwampDragon : BaseMount
{
[Constructible]
public ScaledSwampDragon(string name = "a swamp dragon") :
base(name, 0x31F, 0x3EBE, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
SetStr(201, 300);
SetDex(66, 85);
SetInt(61, 100);
SetHits(121, 180);
SetDamage(3, 4);
SetDamageType(ResistanceType.Physical, 75);
SetDamageType(ResistanceType.Poison, 25);
SetResistance(ResistanceType.Physical, 35, 40);
SetResistance(ResistanceType.Fire, 20, 30);
SetResistance(ResistanceType.Cold, 20, 40);
SetResistance(ResistanceType.Poison, 20, 30);
SetResistance(ResistanceType.Energy, 30, 40);
SetSkill(SkillName.Anatomy, 45.1, 55.0);
SetSkill(SkillName.MagicResist, 45.1, 55.0);
SetSkill(SkillName.Tactics, 45.1, 55.0);
SetSkill(SkillName.Wrestling, 45.1, 55.0);
Fame = 2000;
Karma = -2000;
Tamable = true;
ControlSlots = 1;
MinTameSkill = 93.9;
}
public ScaledSwampDragon(Serial serial) : base(serial)
{
}
public override string CorpseName => "a swamp dragon corpse";
public override bool AutoDispel => !Controlled;
public override FoodType FavoriteFood => FoodType.Meat;
public override bool OverrideBondingReqs()
{
return true;
}
public override double GetControlChance(Mobile m, bool useBaseSkill = false)
{
return 1.0;
}
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();
}
}
}

View file

@ -0,0 +1,35 @@
namespace Server.Mobiles
{
public class SeaHorse : BaseMount
{
[Constructible]
public SeaHorse(string name = "a sea horse") :
base(name, 0x90, 0x3EB3, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
InitStats(Utility.Random(50, 30), Utility.Random(50, 30), 10);
Skills.MagicResist.Base = 25.0 + Utility.RandomDouble() * 5.0;
Skills.Wrestling.Base = 35.0 + Utility.RandomDouble() * 10.0;
Skills.Tactics.Base = 30.0 + Utility.RandomDouble() * 15.0;
}
public SeaHorse(Serial serial) : base(serial)
{
}
public override string CorpseName => "a sea horse corpse";
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();
}
}
}

View file

@ -0,0 +1,39 @@
namespace Server.Mobiles
{
public class SilverSteed : BaseMount
{
[Constructible]
public SilverSteed(string name = "a silver steed") :
base(name, 0x75, 0x3EA8, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
InitStats(Utility.Random(50, 30), Utility.Random(50, 30), 10);
Skills.MagicResist.Base = 25.0 + Utility.RandomDouble() * 5.0;
Skills.Wrestling.Base = 35.0 + Utility.RandomDouble() * 10.0;
Skills.Tactics.Base = 30.0 + Utility.RandomDouble() * 15.0;
ControlSlots = 1;
Tamable = true;
MinTameSkill = 103.1;
}
public SilverSteed(Serial serial) : base(serial)
{
}
public override string CorpseName => "a silver steed corpse";
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();
}
}
}

View file

@ -0,0 +1,68 @@
namespace Server.Mobiles
{
public class SkeletalMount : BaseMount
{
[Constructible]
public SkeletalMount(string name = null) :
base(name, 793, 0x3EBB, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
SetStr(91, 100);
SetDex(46, 55);
SetInt(46, 60);
SetHits(41, 50);
SetDamage(5, 12);
SetDamageType(ResistanceType.Physical, 50);
SetDamageType(ResistanceType.Cold, 50);
SetResistance(ResistanceType.Physical, 50, 60);
SetResistance(ResistanceType.Cold, 90, 95);
SetResistance(ResistanceType.Poison, 100);
SetResistance(ResistanceType.Energy, 10, 15);
SetSkill(SkillName.MagicResist, 95.1, 100.0);
SetSkill(SkillName.Tactics, 50.0);
SetSkill(SkillName.Wrestling, 70.1, 80.0);
Fame = 0;
Karma = 0;
}
public SkeletalMount(Serial serial) : base(serial)
{
}
public override string CorpseName => "an undead horse corpse";
public override string DefaultName => "a skeletal steed";
public override Poison PoisonImmune => Poison.Lethal;
public override bool BleedImmune => true;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
Tamable = false;
MinTameSkill = 0.0;
ControlSlots = 0;
break;
}
}
}
}
}

View file

@ -0,0 +1,219 @@
using Server.Items;
namespace Server.Mobiles
{
public class SwampDragon : BaseMount
{
private Mobile m_BardingCrafter;
private bool m_BardingExceptional;
private int m_BardingHP;
private CraftResource m_BardingResource;
private bool m_HasBarding;
[Constructible]
public SwampDragon(string name = "a swamp dragon") :
base(name, 0x31A, 0x3EBD, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
BaseSoundID = 0x16A;
SetStr(201, 300);
SetDex(66, 85);
SetInt(61, 100);
SetHits(121, 180);
SetDamage(3, 4);
SetDamageType(ResistanceType.Physical, 75);
SetDamageType(ResistanceType.Poison, 25);
SetResistance(ResistanceType.Physical, 35, 40);
SetResistance(ResistanceType.Fire, 20, 30);
SetResistance(ResistanceType.Cold, 20, 40);
SetResistance(ResistanceType.Poison, 20, 30);
SetResistance(ResistanceType.Energy, 30, 40);
SetSkill(SkillName.Anatomy, 45.1, 55.0);
SetSkill(SkillName.MagicResist, 45.1, 55.0);
SetSkill(SkillName.Tactics, 45.1, 55.0);
SetSkill(SkillName.Wrestling, 45.1, 55.0);
Fame = 2000;
Karma = -2000;
Hue = 0x851;
Tamable = true;
ControlSlots = 1;
MinTameSkill = 93.9;
}
public SwampDragon(Serial serial) : base(serial)
{
}
public override string CorpseName => "a swamp dragon corpse";
[CommandProperty(AccessLevel.GameMaster)]
public Mobile BardingCrafter
{
get => m_BardingCrafter;
set
{
m_BardingCrafter = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool BardingExceptional
{
get => m_BardingExceptional;
set
{
m_BardingExceptional = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int BardingHP
{
get => m_BardingHP;
set
{
m_BardingHP = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool HasBarding
{
get => m_HasBarding;
set
{
m_HasBarding = value;
if (m_HasBarding)
{
Hue = CraftResources.GetHue(m_BardingResource);
BodyValue = 0x31F;
ItemID = 0x3EBE;
}
else
{
Hue = 0x851;
BodyValue = 0x31A;
ItemID = 0x3EBD;
}
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public CraftResource BardingResource
{
get => m_BardingResource;
set
{
m_BardingResource = value;
if (m_HasBarding)
Hue = CraftResources.GetHue(value);
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int BardingMaxHP => m_BardingExceptional ? 2500 : 1000;
public override bool ReacquireOnMovement => true;
public override bool AutoDispel => !Controlled;
public override FoodType FavoriteFood => FoodType.Meat;
public override int Meat => 19;
public override int Hides => 20;
public override int Scales => 5;
public override ScaleType ScaleType => ScaleType.Green;
public override bool CanAngerOnTame => true;
public override bool OverrideBondingReqs()
{
return true;
}
public override int GetIdleSound()
{
return 0x2CE;
}
public override int GetDeathSound()
{
return 0x2CC;
}
public override int GetHurtSound()
{
return 0x2D1;
}
public override int GetAttackSound()
{
return 0x2C8;
}
public override double GetControlChance(Mobile m, bool useBaseSkill = false)
{
return 1.0;
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (m_HasBarding && m_BardingExceptional && m_BardingCrafter != null)
list.Add(1060853, m_BardingCrafter.Name); // armor exceptionally crafted by ~1_val~
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
writer.Write(m_BardingExceptional);
writer.Write(m_BardingCrafter);
writer.Write(m_HasBarding);
writer.Write(m_BardingHP);
writer.Write((int)m_BardingResource);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
{
m_BardingExceptional = reader.ReadBool();
m_BardingCrafter = reader.ReadMobile();
m_HasBarding = reader.ReadBool();
m_BardingHP = reader.ReadInt();
m_BardingResource = (CraftResource)reader.ReadInt();
break;
}
}
if (Hue == 0 && !m_HasBarding)
Hue = 0x851;
if (BaseSoundID == -1)
BaseSoundID = 0x16A;
}
}
}

View file

@ -0,0 +1,133 @@
using System;
using Server.Items;
using Server.Network;
namespace Server.Mobiles
{
public class Unicorn : BaseMount
{
[Constructible]
public Unicorn(string name = "a unicorn") :
base(name, 0x7A, 0x3EB4, AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4)
{
BaseSoundID = 0x4BC;
SetStr(296, 325);
SetDex(96, 115);
SetInt(186, 225);
SetHits(191, 210);
SetDamage(16, 22);
SetDamageType(ResistanceType.Physical, 75);
SetDamageType(ResistanceType.Energy, 25);
SetResistance(ResistanceType.Physical, 55, 65);
SetResistance(ResistanceType.Fire, 25, 40);
SetResistance(ResistanceType.Cold, 25, 40);
SetResistance(ResistanceType.Poison, 55, 65);
SetResistance(ResistanceType.Energy, 25, 40);
SetSkill(SkillName.EvalInt, 80.1, 90.0);
SetSkill(SkillName.Magery, 60.2, 80.0);
SetSkill(SkillName.Meditation, 50.1, 60.0);
SetSkill(SkillName.MagicResist, 75.3, 90.0);
SetSkill(SkillName.Tactics, 20.1, 22.5);
SetSkill(SkillName.Wrestling, 80.5, 92.5);
Fame = 9000;
Karma = 9000;
Tamable = true;
ControlSlots = 2;
MinTameSkill = 95.1;
}
public Unicorn(Serial serial) : base(serial)
{
}
public override string CorpseName => "a unicorn corpse";
public override bool AllowMaleRider => false;
public override bool AllowMaleTamer => false;
public override bool InitialInnocent => true;
public override TimeSpan MountAbilityDelay => TimeSpan.FromHours(1.0);
public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead;
public override Poison PoisonImmune => Poison.Lethal;
public override int Meat => 3;
public override int Hides => 10;
public override HideType HideType => HideType.Horned;
public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay;
public override void OnDisallowedRider(Mobile m)
{
m.SendLocalizedMessage(1042318); // The unicorn refuses to allow you to ride it.
}
public override bool DoMountAbility(int damage, Mobile attacker)
{
if (Rider == null || attacker == null) //sanity
return false;
if (Rider.Poisoned && Rider.Hits - damage < 40)
{
Poison p = Rider.Poison;
if (p != null)
{
int chanceToCure = 10000 + (int)(Skills.Magery.Value * 75) -
(p.Level + 1) * (Core.AOS ? p.Level < 4 ? 3300 : 3100 : 1750);
chanceToCure /= 100;
if (chanceToCure > Utility.Random(100))
if (Rider.CurePoison(this)) //TODO: Confirm if mount is the one flagged for curing it or the rider is
{
Rider.LocalOverheadMessage(MessageType.Regular, 0x3B2, true,
"Your mount senses you are in danger and aids you with magic.");
Rider.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist);
Rider.PlaySound(0x1E0); // Cure spell effect.
Rider.PlaySound(0xA9); // Unicorn's whinny.
return true;
}
}
}
return false;
}
public override void GenerateLoot()
{
AddLoot(LootPack.Rich);
AddLoot(LootPack.LowScrolls);
AddLoot(LootPack.Potions);
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
if (Utility.RandomDouble() < 0.35)
c.DropItem(new UnicornRibs());
}
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();
}
}
}

View file

@ -0,0 +1,64 @@
namespace Server.Mobiles
{
public abstract class BaseWarHorse : BaseMount
{
public BaseWarHorse(int bodyID, int itemID, AIType aiType, FightMode fightMode, int rangePerception, int rangeFight,
double activeSpeed, double passiveSpeed) : base("a war horse", bodyID, itemID, aiType, fightMode,
rangePerception, rangeFight, activeSpeed, passiveSpeed)
{
BaseSoundID = 0xA8;
InitStats(Utility.Random(300, 100), 125, 60);
SetStr(400);
SetDex(125);
SetInt(51, 55);
SetHits(240);
SetMana(0);
SetDamage(5, 8);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 40, 50);
SetResistance(ResistanceType.Fire, 30, 40);
SetResistance(ResistanceType.Cold, 30, 40);
SetResistance(ResistanceType.Poison, 30, 40);
SetResistance(ResistanceType.Energy, 30, 40);
SetSkill(SkillName.MagicResist, 25.1, 30.0);
SetSkill(SkillName.Tactics, 29.3, 44.0);
SetSkill(SkillName.Wrestling, 29.3, 44.0);
Fame = 300;
Karma = 300;
Tamable = true;
ControlSlots = 1;
MinTameSkill = 29.1;
}
public BaseWarHorse(Serial serial) : base(serial)
{
}
public override string CorpseName => "a war horse corpse";
public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay;
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();
}
}
}

View file

@ -0,0 +1,28 @@
namespace Server.Mobiles
{
public class CoMWarHorse : BaseWarHorse
{
[Constructible]
public CoMWarHorse() : base(0x77, 0x3EB1, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
}
public CoMWarHorse(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();
}
}
}

View file

@ -0,0 +1,28 @@
namespace Server.Mobiles
{
public class MinaxWarHorse : BaseWarHorse
{
[Constructible]
public MinaxWarHorse() : base(0x78, 0x3EAF, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
}
public MinaxWarHorse(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();
}
}
}

View file

@ -0,0 +1,28 @@
namespace Server.Mobiles
{
public class SLWarHorse : BaseWarHorse
{
[Constructible]
public SLWarHorse() : base(0x79, 0x3EB0, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
}
public SLWarHorse(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();
}
}
}

View file

@ -0,0 +1,28 @@
namespace Server.Mobiles
{
public class TBWarHorse : BaseWarHorse
{
[Constructible]
public TBWarHorse() : base(0x76, 0x3EB2, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
}
public TBWarHorse(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();
}
}
}