feat: Adds hireables (#1393)

This commit is contained in:
Kamron Batman 2023-04-16 20:24:14 -07:00 committed by GitHub
parent fea7aef95f
commit cc6fee28d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 1449 additions and 0 deletions

View file

@ -0,0 +1,30 @@
{
"version": 0,
"type": "Server.Mobiles.BaseHire",
"properties": [
{
"name": "NextPay",
"type": "System.DateTime",
"rule": "PrimitiveTypeMigrationRule",
"ruleArguments": [
""
]
},
{
"name": "IsHired",
"type": "bool",
"rule": "PrimitiveTypeMigrationRule",
"ruleArguments": [
""
]
},
{
"name": "HoldGold",
"type": "int",
"rule": "PrimitiveTypeMigrationRule",
"ruleArguments": [
""
]
}
]
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HireBard"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HireBardArcher"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HireBeggar"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HireFighter"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HireMage"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HirePaladin"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HirePeasant"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HireRanger"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HireRangerArcher"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HireSailor"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HireThief"
}

View file

@ -0,0 +1,318 @@
using Server.ContextMenus;
using Server.Items;
using System;
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Collections;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class BaseHire : BaseCreature
{
[SerializableField(0)]
[SerializedCommandProperty(AccessLevel.GameMaster)]
private DateTime _nextPay;
[SerializableField(2)]
[SerializedCommandProperty(AccessLevel.GameMaster)]
private int _holdGold;
[CommandProperty(AccessLevel.GameMaster)]
public int Pay => PerDayCost();
public int GoldOnDeath { get; set; }
[SerializableProperty(1)]
[CommandProperty(AccessLevel.GameMaster)]
public bool IsHired
{
get => _isHired;
set
{
_isHired = value;
Delta(MobileDelta.Noto);
InvalidateProperties();
this.MarkDirty();
}
}
public BaseHire(AIType AI) : base(AI, FightMode.Aggressor)
{
ControlSlots = 2;
HoldGold = 8;
}
public BaseHire() : base(AIType.AI_Melee, FightMode.Aggressor) => ControlSlots = 2;
public override bool IsBondable => false;
public override bool KeepsItemsOnDeath => true;
[AfterDeserialization]
private void AfterDeserialization()
{
if (IsHired)
{
PayTimer.RegisterTimer(this);
}
}
public override bool OnBeforeDeath()
{
GoldOnDeath = Backpack?.GetAmount(typeof(Gold)) ?? 0;
return base.OnBeforeDeath();
}
public override void Delete()
{
base.Delete();
PayTimer.RemoveTimer(this);
}
public override void OnDeath(Container c)
{
if (GoldOnDeath > 0)
{
c.DropItem(new Gold(GoldOnDeath));
}
base.OnDeath(c);
}
public virtual Mobile GetOwner()
{
if (!Controlled)
{
return null;
}
var owner = ControlMaster;
IsHired = true;
if (owner == null)
{
return null;
}
if (owner.Deleted)
{
Say(1005653); // Hmmm. I seem to have lost my master.
SetControlMaster(null);
return null;
}
return owner;
}
public virtual bool AddHire(Mobile m)
{
Mobile owner = GetOwner();
if (owner != null)
{
m.SendLocalizedMessage(1043283, owner.Name); // I am following ~1_NAME~.
return false;
}
if (SetControlMaster(m))
{
IsHired = true;
return true;
}
return false;
}
public int PerDayCost() =>
(int)(Skills[SkillName.Anatomy].Value +
Skills[SkillName.Tactics].Value +
Skills[SkillName.Macing].Value +
Skills[SkillName.Swords].Value +
Skills[SkillName.Fencing].Value +
Skills[SkillName.Archery].Value +
Skills[SkillName.MagicResist].Value +
Skills[SkillName.Healing].Value +
Skills[SkillName.Magery].Value +
Skills[SkillName.Parry].Value) / 35 + 1;
private bool OnHireDragDrop(Mobile from, Item item)
{
if (Pay == 0)
{
SayTo(from, 500200); // I have no need for that.
return false;
}
// Is the creature already hired
if (Controlled)
{
SayTo(from, 1042495); // I have already been hired.
return false;
}
// Is the item the payment in gold
if (item is not Gold)
{
SayTo(from, 1043268); // Tis crass of me, but I want gold
return false;
}
// Is the payment in gold sufficient
if (item.Amount < Pay)
{
SayHireCost();
return false;
}
if (from.Followers + ControlSlots > from.FollowersMax)
{
SayTo(from, 500896); // I see you already have an escort.
return false;
}
// Try to add the hireling as a follower
if (!AddHire(from))
{
return false;
}
// I thank thee for paying me. I will work for thee for ~1_NUMBER~ days.
SayTo(from, 1043258, $"{item.Amount / Pay}"); // Stupid that they don't have "day" cliloc
HoldGold += item.Amount;
NextPay = Core.Now + PayTimer.GetInterval();
PayTimer.RegisterTimer(this);
return true;
}
public override bool OnDragDrop(Mobile from, Item item) => OnHireDragDrop(from, item) || base.OnDragDrop(from, item);
internal void SayHireCost()
{
// I am available for hire for ~1_AMOUNT~ gold coins a day. If thou dost give me gold, I will work for thee.
Say(1043256, $"{Pay}");
}
public override void OnSpeech(SpeechEventArgs e)
{
// Check for a greeting, a 'hire', or a 'servant'
if (!e.Handled && e.Mobile.InRange(this, 6) && (e.HasKeyword(0x003B) || e.HasKeyword(0x0162) || e.HasKeyword(0x000C)))
{
if (Controlled)
{
Say(1042495); // I have already been hired.
}
else
{
e.Handled = true;
SayHireCost();
}
}
base.OnSpeech(e);
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
if (Deleted)
{
return;
}
if (!Controlled)
{
if (CanPaperdollBeOpenedBy(from))
{
list.Add(new PaperdollEntry(this));
}
list.Add(new HireEntry(this));
}
else
{
base.GetContextMenuEntries(from, list);
}
}
public class PayTimer : Timer
{
private readonly HashSet<BaseHire> _hires = new();
public static PayTimer Instance { get; set; }
public PayTimer() : base(TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1))
{
}
public static TimeSpan GetInterval() => TimeSpan.FromMinutes(30.0);
protected override void OnTick()
{
using var queue = PooledRefQueue<Mobile>.Create();
foreach (var hire in _hires)
{
if (hire.NextPay > Core.Now)
{
continue;
}
hire.NextPay = Core.Now + GetInterval();
int pay = hire.Pay;
if (hire.HoldGold <= pay)
{
queue.Enqueue(hire);
}
else
{
hire.HoldGold -= pay;
}
}
while (queue.Count > 0)
{
var hire = (BaseHire)queue.Dequeue();
hire.GetOwner(); // Sets owner to null
hire.Say(503235); // I regret nothing!
hire.Delete();
}
}
public static void RegisterTimer(BaseHire hire)
{
Instance ??= new PayTimer();
if (!Instance.Running)
{
Instance.Start();
}
Instance._hires.Add(hire);
}
public static void RemoveTimer(BaseHire hire)
{
if (Instance?._hires.Remove(hire) == true && Instance._hires.Count == 0)
{
Instance.Stop();
}
}
}
public class HireEntry : ContextMenuEntry
{
private readonly BaseHire _hire;
public HireEntry(BaseHire hire) : base(6120, 3) => _hire = hire;
public override void OnClick()
{
_hire.SayHireCost();
}
}
}

View file

@ -0,0 +1,108 @@
using Server.Items;
using ModernUO.Serialization;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class HireBard : BaseHire
{
[Constructible]
public HireBard()
{
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Skirt(Utility.RandomDyedHue()));
break;
}
case 1:
{
EquipItem(new Kilt(Utility.RandomNeutralHue()));
break;
}
}
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
EquipItem(new ShortPants(Utility.RandomNeutralHue()));
}
Title = "the bard";
HairItemID = Race.RandomHair(Female);
HairHue = Race.RandomHairHue();
Race.RandomFacialHair(this);
SetStr(16, 16);
SetDex(26, 26);
SetInt(26, 26);
SetDamage(5, 10);
SetSkill(SkillName.Tactics, 35, 57);
SetSkill(SkillName.Magery, 22, 22);
SetSkill(SkillName.Swords, 45, 67);
SetSkill(SkillName.Archery, 36, 67);
SetSkill(SkillName.Parry, 45, 60);
SetSkill(SkillName.Musicianship, 66.0, 97.5);
SetSkill(SkillName.Peacemaking, 65.0, 87.5);
Fame = 100;
Karma = 100;
EquipItem(new Shoes(Utility.RandomNeutralHue()));
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Doublet(Utility.RandomDyedHue()));
break;
}
case 1:
{
EquipItem(new Shirt(Utility.RandomDyedHue()));
break;
}
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.Average);
if (Utility.RandomBool())
{
PackItem(Loot.RandomInstrument());
}
switch (Utility.Random(2))
{
case 0:
{
PackItem(new Longsword());
break;
}
case 1:
{
PackItem(new Bow());
PackItem(new Arrow(100));
break;
}
}
PackGold(10, 50);
}
public override bool ClickTitle => false;
}

View file

@ -0,0 +1,108 @@
using Server.Items;
using ModernUO.Serialization;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class HireBardArcher : BaseHire
{
[Constructible]
public HireBardArcher() : base(AIType.AI_Archer)
{
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Skirt(Utility.RandomDyedHue()));
break;
}
case 1:
{
EquipItem(new Kilt(Utility.RandomNeutralHue()));
break;
}
}
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
EquipItem(new ShortPants(Utility.RandomNeutralHue()));
}
Title = "the bard";
HairItemID = Race.RandomHair(Female);
HairHue = Race.RandomHairHue();
Race.RandomFacialHair(this);
SetStr(16, 16);
SetDex(26, 26);
SetInt(26, 26);
SetDamage(5, 10);
SetSkill(SkillName.Tactics, 35, 57);
SetSkill(SkillName.Magery, 22, 22);
SetSkill(SkillName.Swords, 45, 67);
SetSkill(SkillName.Archery, 36, 67);
SetSkill(SkillName.Parry, 45, 60);
SetSkill(SkillName.Musicianship, 66.0, 97.5);
SetSkill(SkillName.Peacemaking, 65.0, 87.5);
Fame = 100;
Karma = 100;
EquipItem(new Shoes(Utility.RandomNeutralHue()));
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Doublet(Utility.RandomDyedHue()));
break;
}
case 1:
{
EquipItem(new Shirt(Utility.RandomDyedHue()));
break;
}
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.Average);
if (Utility.RandomBool())
{
PackItem(Loot.RandomInstrument());
}
switch (Utility.Random(2))
{
case 0:
{
PackItem(new Longsword());
break;
}
case 1:
{
PackItem(new Bow());
PackItem(new Arrow(100));
break;
}
}
PackGold(10, 50);
}
public override bool ClickTitle => false;
}

View file

@ -0,0 +1,80 @@
using ModernUO.Serialization;
using Server.Items;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class HireBeggar : BaseHire
{
[Constructible]
public HireBeggar()
{
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Skirt(Utility.RandomNeutralHue()));
break;
}
case 1:
{
EquipItem(new Kilt(Utility.RandomNeutralHue()));
break;
}
}
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
EquipItem(new ShortPants(Utility.RandomNeutralHue()));
}
Title = "the beggar";
HairItemID = Race.RandomHair(Female);
HairHue = Race.RandomHairHue();
Race.RandomFacialHair(this);
SetStr(26, 26);
SetDex(21, 21);
SetInt(36, 36);
SetDamage(1, 1);
SetSkill(SkillName.Begging, 66, 97);
SetSkill(SkillName.Tactics, 5, 27);
SetSkill(SkillName.Wrestling, 5, 27);
SetSkill(SkillName.Magery, 2, 2);
Fame = 0;
Karma = 0;
EquipItem(new Sandals(Utility.RandomNeutralHue()));
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Doublet(Utility.RandomNeutralHue()));
break;
}
case 1:
{
EquipItem(new Shirt(Utility.RandomNeutralHue()));
break;
}
}
PackGold(0, 25);
}
public override bool ClickTitle => false;
}

View file

@ -0,0 +1,211 @@
using ModernUO.Serialization;
using Server.Items;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class HireFighter : BaseHire
{
[Constructible]
public HireFighter()
{
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
}
Title = "the fighter";
HairItemID = Race.RandomHair(Female);
HairHue = Race.RandomHairHue();
Race.RandomFacialHair(this);
SetStr(91, 91);
SetDex(91, 91);
SetInt(50, 50);
SetDamage(7, 14);
SetSkill(SkillName.Tactics, 36, 67);
SetSkill(SkillName.Magery, 22, 22);
SetSkill(SkillName.Swords, 64, 100);
SetSkill(SkillName.Parry, 60, 82);
SetSkill(SkillName.Macing, 36, 67);
SetSkill(SkillName.Focus, 36, 67);
SetSkill(SkillName.Wrestling, 25, 47);
Fame = 100;
Karma = 100;
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Shoes(Utility.RandomNeutralHue()));
break;
}
case 1:
{
EquipItem(new Boots(Utility.RandomNeutralHue()));
break;
}
}
EquipItem(new Shirt());
// Pick a random sword
switch (Utility.Random(5))
{
case 0:
{
EquipItem(new Longsword());
break;
}
case 1:
{
EquipItem(new Broadsword());
break;
}
case 2:
{
EquipItem(new VikingSword());
break;
}
case 3:
{
EquipItem(new BattleAxe());
break;
}
case 4:
{
EquipItem(new TwoHandedAxe());
break;
}
}
// Pick a random shield
if (FindItemOnLayer(Layer.TwoHanded) == null)
{
switch (Utility.Random(8))
{
case 0:
{
EquipItem(new BronzeShield());
break;
}
case 1:
{
EquipItem(new HeaterShield());
break;
}
case 2:
{
EquipItem(new MetalKiteShield());
break;
}
case 3:
{
EquipItem(new MetalShield());
break;
}
case 4:
{
EquipItem(new WoodenKiteShield());
break;
}
case 5:
{
EquipItem(new WoodenShield());
break;
}
case 6:
{
EquipItem(new OrderShield());
break;
}
case 7:
{
EquipItem(new ChaosShield());
break;
}
}
}
switch (Utility.Random(5))
{
case 0:
{
break;
}
case 1:
{
EquipItem(new Bascinet());
break;
}
case 2:
{
EquipItem(new CloseHelm());
break;
}
case 3:
{
EquipItem(new NorseHelm());
break;
}
case 4:
{
EquipItem(new Helmet());
break;
}
}
// Pick some armour
switch (Utility.Random(4))
{
case 0: // Leather
{
EquipItem(new LeatherChest());
EquipItem(new LeatherArms());
EquipItem(new LeatherGloves());
EquipItem(new LeatherGorget());
EquipItem(new LeatherLegs());
break;
}
case 1: // Studded Leather
{
EquipItem(new StuddedChest());
EquipItem(new StuddedArms());
EquipItem(new StuddedGloves());
EquipItem(new StuddedGorget());
EquipItem(new StuddedLegs());
break;
}
case 2: // Ringmail
{
EquipItem(new RingmailChest());
EquipItem(new RingmailArms());
EquipItem(new RingmailGloves());
EquipItem(new RingmailLegs());
break;
}
case 3: // Chain
{
EquipItem(new ChainChest());
//EquipItem(new ChainCoif());
EquipItem(new ChainLegs());
break;
}
}
PackGold(25, 100);
}
public override bool ClickTitle => false;
}

View file

@ -0,0 +1,63 @@
using ModernUO.Serialization;
using Server.Items;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class HireMage : BaseHire
{
[Constructible]
public HireMage() : base(AIType.AI_Mage)
{
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
Title = "the mage";
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
EquipItem(new ShortPants(Utility.RandomNeutralHue()));
}
HairItemID = Race.RandomHair(Female);
HairHue = Race.RandomHairHue();
Race.RandomFacialHair(this);
SetStr(61, 75);
SetDex(81, 95);
SetInt(86, 100);
SetDamage(10, 23);
SetSkill(SkillName.EvalInt, 100.0, 125);
SetSkill(SkillName.Magery, 100, 125);
SetSkill(SkillName.Meditation, 100, 125);
SetSkill(SkillName.MagicResist, 100, 125);
SetSkill(SkillName.Tactics, 100, 125);
SetSkill(SkillName.Macing, 100, 125);
Fame = 100;
Karma = 100;
EquipItem(new Shirt());
EquipItem(new Robe(Utility.RandomNeutralHue()));
if (Utility.RandomBool())
{
EquipItem(new Shoes(Utility.RandomNeutralHue()));
}
else
{
EquipItem(new ThighBoots());
}
PackGold(20, 100);
}
public override bool ClickTitle => false;
}

View file

@ -0,0 +1,90 @@
using ModernUO.Serialization;
using Server.Items;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class HirePaladin : BaseHire
{
[Constructible]
public HirePaladin()
{
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
}
Title = "the paladin";
HairItemID = Race.RandomHair(Female);
HairHue = Race.RandomHairHue();
Race.RandomFacialHair(this);
switch (Utility.Random(5))
{
case 0:
{
break;
}
case 1:
{
EquipItem(new Bascinet());
break;
}
case 2:
{
EquipItem(new CloseHelm());
break;
}
case 3:
{
EquipItem(new NorseHelm());
break;
}
case 4:
{
EquipItem(new Helmet());
break;
}
}
SetStr(86, 100);
SetDex(81, 95);
SetInt(61, 75);
SetDamage(10, 23);
SetSkill(SkillName.Swords, 66.0, 97.5);
SetSkill(SkillName.Anatomy, 65.0, 87.5);
SetSkill(SkillName.MagicResist, 25.0, 47.5);
SetSkill(SkillName.Healing, 65.0, 87.5);
SetSkill(SkillName.Tactics, 65.0, 87.5);
SetSkill(SkillName.Wrestling, 15.0, 37.5);
SetSkill(SkillName.Parry, 45.0, 60.5);
SetSkill(SkillName.Chivalry, 85, 100);
Fame = 100;
Karma = 250;
EquipItem(new Shoes(Utility.RandomNeutralHue()));
EquipItem(new Shirt());
EquipItem(new VikingSword());
EquipItem(new MetalKiteShield());
EquipItem(new PlateChest());
EquipItem(new PlateLegs());
EquipItem(new PlateArms());
EquipItem(new LeatherGorget());
PackGold(20, 100);
}
public override bool ClickTitle => false;
}

View file

@ -0,0 +1,79 @@
using ModernUO.Serialization;
using Server.Items;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class HirePeasant : BaseHire
{
[Constructible]
public HirePeasant()
{
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Skirt(Utility.RandomNeutralHue()));
break;
}
case 1:
{
EquipItem(new Kilt(Utility.RandomNeutralHue()));
break;
}
}
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
EquipItem(new ShortPants(Utility.RandomNeutralHue()));
}
Title = "the peasant";
HairItemID = Race.RandomHair(Female);
HairHue = Race.RandomHairHue();
Race.RandomFacialHair(this);
EquipItem(new Katana());
SetStr(26, 26);
SetDex(21, 21);
SetInt(16, 16);
SetDamage(10, 23);
SetSkill(SkillName.Tactics, 5, 27);
SetSkill(SkillName.Wrestling, 5, 5);
SetSkill(SkillName.Swords, 5, 27);
Fame = 0;
Karma = 0;
EquipItem(new Sandals(Utility.RandomNeutralHue()));
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Doublet(Utility.RandomNeutralHue()));
break;
}
case 1:
{
EquipItem(new Shirt(Utility.RandomNeutralHue()));
break;
}
}
PackGold(0, 25);
}
public override bool ClickTitle => false;
}

View file

@ -0,0 +1,85 @@
using ModernUO.Serialization;
using Server.Items;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class HireRanger : BaseHire
{
[Constructible]
public HireRanger()
{
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
EquipItem(new ShortPants(Utility.RandomNeutralHue()));
}
Title = "the ranger";
HairItemID = Race.RandomHair(Female);
HairHue = Race.RandomHairHue();
Race.RandomFacialHair(this);
SetStr(91, 91);
SetDex(76, 76);
SetInt(61, 61);
SetDamage(13, 24);
SetSkill(SkillName.Wrestling, 15, 37);
SetSkill(SkillName.Parry, 45, 60);
SetSkill(SkillName.Archery, 66, 97);
SetSkill(SkillName.Magery, 62, 62);
SetSkill(SkillName.Swords, 35, 57);
SetSkill(SkillName.Fencing, 15, 37);
SetSkill(SkillName.Tactics, 65, 87);
Fame = 100;
Karma = 125;
EquipItem(new Shoes(Utility.RandomNeutralHue()));
EquipItem(new Shirt());
// Pick a random sword
switch (Utility.Random(3))
{
case 0:
{
EquipItem(new Longsword());
break;
}
case 1:
{
EquipItem(new VikingSword());
break;
}
case 2:
{
EquipItem(new Broadsword());
break;
}
}
EquipItem(new StuddedChest());
EquipItem(new StuddedArms());
EquipItem(new StuddedGloves());
EquipItem(new StuddedLegs());
EquipItem(new StuddedGorget());
}
public override void GenerateLoot()
{
AddLoot(LootPack.Average);
PackItem(new Arrow(20));
PackGold(10, 75);
}
}

View file

@ -0,0 +1,79 @@
using ModernUO.Serialization;
using Server.Items;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class HireRangerArcher : BaseHire
{
[Constructible]
public HireRangerArcher() : base(AIType.AI_Archer)
{
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
}
Title = "the ranger";
HairItemID = Race.RandomHair(Female);
HairHue = Race.RandomHairHue();
Race.RandomFacialHair(this);
SetStr(91, 91);
SetDex(76, 76);
SetInt(61, 61);
SetDamage(13, 24);
SetSkill(SkillName.Wrestling, 15, 37);
SetSkill(SkillName.Parry, 45, 60);
SetSkill(SkillName.Archery, 66, 97);
SetSkill(SkillName.Magery, 62, 62);
SetSkill(SkillName.Swords, 35, 57);
SetSkill(SkillName.Fencing, 15, 37);
SetSkill(SkillName.Tactics, 65, 87);
Fame = 100;
Karma = 125;
EquipItem(new Shoes(Utility.RandomNeutralHue()));
EquipItem(new Shirt());
// Pick a random sword
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Bow());
break;
}
case 1:
{
EquipItem(new CompositeBow());
break;
}
}
EquipItem(new RangerChest());
EquipItem(new RangerArms());
EquipItem(new RangerGloves());
EquipItem(new RangerGorget());
EquipItem(new RangerLegs());
}
public override void GenerateLoot()
{
PackItem(new Arrow(100));
}
public override bool ClickTitle => false;
}

View file

@ -0,0 +1,70 @@
using ModernUO.Serialization;
using Server.Items;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class HireSailor : BaseHire
{
[Constructible]
public HireSailor()
{
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
EquipItem(new ShortPants(Utility.RandomNeutralHue()));
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
EquipItem(new ShortPants(Utility.RandomNeutralHue()));
}
Title = "the sailor";
HairItemID = Race.RandomHair(Female);
HairHue = Race.RandomHairHue();
Race.RandomFacialHair(this);
SetStr(86);
SetDex(66);
SetInt(41);
SetDamage(10, 23);
SetSkill(SkillName.Stealing, 66.0, 97.5);
SetSkill(SkillName.Peacemaking, 65.0, 87.5);
SetSkill(SkillName.MagicResist, 25.0, 47.5);
SetSkill(SkillName.Healing, 65.0, 87.5);
SetSkill(SkillName.Tactics, 65.0, 87.5);
SetSkill(SkillName.Fencing, 65.0, 87.5);
SetSkill(SkillName.Parry, 45.0, 60.5);
SetSkill(SkillName.Lockpicking, 65, 87);
SetSkill(SkillName.Hiding, 65, 87);
SetSkill(SkillName.Snooping, 65, 87);
Fame = 100;
Karma = 0;
EquipItem(new Shoes(Utility.RandomNeutralHue()));
EquipItem(new Cutlass());
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Doublet(Utility.RandomDyedHue()));
break;
}
case 1:
{
EquipItem(new Shirt(Utility.RandomDyedHue()));
break;
}
}
}
public override bool ClickTitle => false;
}

View file

@ -0,0 +1,84 @@
using ModernUO.Serialization;
using Server.Items;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class HireThief : BaseHire
{
[Constructible]
public HireThief()
{
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Skirt(Utility.RandomNeutralHue()));
break;
}
case 1:
{
EquipItem(new Kilt(Utility.RandomNeutralHue()));
break;
}
}
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
EquipItem(new ShortPants(Utility.RandomNeutralHue()));
}
Title = "the thief";
HairItemID = Race.RandomHair(Female);
HairHue = Race.RandomHairHue();
Race.RandomFacialHair(this);
SetStr(81, 95);
SetDex(86, 100);
SetInt(61, 75);
SetDamage(10, 23);
SetSkill(SkillName.Stealing, 66.0, 97.5);
SetSkill(SkillName.Peacemaking, 65.0, 87.5);
SetSkill(SkillName.MagicResist, 25.0, 47.5);
SetSkill(SkillName.Healing, 65.0, 87.5);
SetSkill(SkillName.Tactics, 65.0, 87.5);
SetSkill(SkillName.Fencing, 65.0, 87.5);
SetSkill(SkillName.Parry, 45.0, 60.5);
SetSkill(SkillName.Lockpicking, 65, 87);
SetSkill(SkillName.Hiding, 65, 87);
SetSkill(SkillName.Snooping, 65, 87);
Fame = 100;
Karma = 0;
EquipItem(new Sandals(Utility.RandomNeutralHue()));
EquipItem(new Dagger());
switch (Utility.Random(2))
{
case 0:
{
EquipItem(new Doublet(Utility.RandomNeutralHue()));
break;
}
case 1:
{
EquipItem(new Shirt(Utility.RandomNeutralHue()));
break;
}
}
PackGold(0, 25);
}
public override bool ClickTitle => false;
}