Overwrite

Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
Unstable Kitsune
2023-11-28 23:20:26 -05:00
parent 3cd54811de
commit b918192e4e
11608 changed files with 2644205 additions and 47 deletions

View File

@@ -0,0 +1,54 @@
#region References
using System.Collections.Generic;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Targeting;
#endregion
namespace Server.Targets
{
public class AIControlMobileTarget : Target
{
private readonly List<BaseAI> m_List;
private readonly OrderType m_Order;
private readonly BaseCreature m_Mobile;
public AIControlMobileTarget(BaseAI ai, OrderType order)
: base(-1, false, (order == OrderType.Attack ? TargetFlags.Harmful : TargetFlags.None))
{
m_List = new List<BaseAI>();
m_Order = order;
AddAI(ai);
m_Mobile = ai.m_Mobile;
}
public OrderType Order { get { return m_Order; } }
public void AddAI(BaseAI ai)
{
if (!m_List.Contains(ai))
m_List.Add(ai);
}
protected override void OnTarget(Mobile from, object o)
{
if (o is IDamageable)
{
var dam = o as IDamageable;
for (var i = 0; i < m_List.Count; ++i)
m_List[i].EndPickTarget(from, dam, m_Order);
}
else if (o is MoonglowDonationBox && m_Order == OrderType.Transfer && from is PlayerMobile)
{
var pm = (PlayerMobile)from;
var box = (MoonglowDonationBox)o;
pm.SendGump(new ConfirmTransferPetGump(box, from.Location, m_Mobile));
}
}
}
}

View File

@@ -0,0 +1,136 @@
// Ideas
// When you run on animals the panic
// When if ( distance < 8 && Utility.RandomDouble() * Math.Sqrt( (8 - distance) / 6 ) >= incoming.Skills[SkillName.AnimalTaming].Value )
// More your close, the more it can panic
/*
* AnimalHunterAI, AnimalHidingAI, AnimalDomesticAI...
*
*/
namespace Server.Mobiles
{
public class AnimalAI : BaseAI
{
public AnimalAI(BaseCreature m)
: base(m)
{ }
public override bool DoActionWander()
{
// Old:
#if false
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, true, false, true))
{
m_Mobile.DebugSay( "There is something near, I go away" );
Action = ActionType.Backoff;
}
else if ( m_Mobile.IsHurt() || m_Mobile.Combatant != null )
{
m_Mobile.DebugSay( "I am hurt or being attacked, I flee" );
Action = ActionType.Flee;
}
else
{
base.DoActionWander();
}
return true;
#endif
// New, only flee @ 10%
var hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax;
if (!m_Mobile.Summoned && !m_Mobile.Controlled && hitPercent < 0.1 && m_Mobile.CanFlee) // Less than 10% health
{
m_Mobile.DebugSay("I am low on health!");
Action = ActionType.Flee;
}
else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
var combatant = m_Mobile.Combatant;
if (combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map)
{
m_Mobile.DebugSay("My combatant is gone..");
Action = ActionType.Wander;
return true;
}
if (WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
{
if (!DirectionLocked)
m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
}
else
{
if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1)
{
m_Mobile.DebugSay("I cannot find {0}", combatant.Name);
Action = ActionType.Wander;
return true;
}
m_Mobile.DebugSay("I should be closer to {0}", combatant.Name);
}
if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee)
{
var hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax;
if (hitPercent < 0.1)
{
m_Mobile.DebugSay("I am low on health!");
Action = ActionType.Flee;
}
}
return true;
}
public override bool DoActionBackoff()
{
var hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax;
if (!m_Mobile.Summoned && !m_Mobile.Controlled && hitPercent < 0.1 && m_Mobile.CanFlee) // Less than 10% health
{
Action = ActionType.Flee;
}
else
{
if (AcquireFocusMob(m_Mobile.RangePerception * 2, FightMode.Closest, true, false, true))
{
if (WalkMobileRange(m_Mobile.FocusMob, 1, false, m_Mobile.RangePerception, m_Mobile.RangePerception * 2))
{
m_Mobile.DebugSay("Well, here I am safe");
Action = ActionType.Wander;
}
}
else
{
m_Mobile.DebugSay("I have lost my focus, lets relax");
Action = ActionType.Wander;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,121 @@
using System;
namespace Server.Mobiles
{
public class ArcherAI : BaseAI
{
public ArcherAI(BaseCreature m)
: base(m)
{ }
public override bool DoActionWander()
{
m_Mobile.DebugSay("I have no combatant");
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("I have detected {0} and I will attack", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
return base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
var c = m_Mobile.Combatant;
if (c == null || c.Deleted || !c.Alive || (c is Mobile && ((Mobile)c).IsDeadBondedPet))
{
m_Mobile.DebugSay("My combatant is deleted");
Action = ActionType.Guard;
return true;
}
if (Core.TickCount - m_Mobile.LastMoveTime > 1000)
{
if (WalkMobileRange(c, 1, true, m_Mobile.RangeFight, m_Mobile.Weapon.MaxRange))
{
if (!DirectionLocked)
m_Mobile.Direction = m_Mobile.GetDirectionTo(c.Location);
}
else if (c != null)
{
m_Mobile.DebugSay("I am still not in range of {0}", c.Name);
if ((int)m_Mobile.GetDistanceToSqrt(c) > m_Mobile.RangePerception + 1)
{
m_Mobile.DebugSay("I have lost {0}", c.Name);
Action = ActionType.Guard;
return true;
}
}
}
if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee)
{
if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100)
{
// We are low on health, should we flee?
if (Utility.Random(100) <= Math.Max(10, 10 + c.Hits - m_Mobile.Hits))
{
m_Mobile.DebugSay("I am going to flee from {0}", c.Name);
Action = ActionType.Flee;
}
}
}
return true;
}
public override bool DoActionGuard()
{
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionGuard();
}
return true;
}
public override bool DoActionFlee()
{
var c = m_Mobile.Combatant as Mobile;
if ( m_Mobile.Hits > (m_Mobile.HitsMax / 2))
{
// If I have a target, go back and fight them
if (c != null && m_Mobile.GetDistanceToSqrt(c) <= m_Mobile.RangePerception * 2)
{
m_Mobile.DebugSay("I am stronger now, reengaging {0}", c.Name);
Action = ActionType.Combat;
}
else
{
m_Mobile.DebugSay("I am stronger now, my guard is up");
Action = ActionType.Guard;
}
}
else
{
base.DoActionFlee();
}
return true;
}
}
}

3127
Scripts/Mobiles/AI/BaseAI.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
namespace Server.Mobiles
{
public class BerserkAI : BaseAI
{
public BerserkAI(BaseCreature m)
: base(m)
{ }
public override bool DoActionWander()
{
m_Mobile.DebugSay("I have No Combatant");
if (AcquireFocusMob(m_Mobile.RangePerception, FightMode.Closest, false, true, true))
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("I have detected " + m_Mobile.FocusMob.Name + " and I will attack");
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
if (m_Mobile.Combatant == null || m_Mobile.Combatant.Deleted)
{
m_Mobile.DebugSay("My combatant is deleted");
Action = ActionType.Guard;
return true;
}
if (WalkMobileRange(m_Mobile.Combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
{
if (!DirectionLocked)
m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant.Location);
}
else
{
if (m_Mobile.Combatant != null)
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("I am still not in range of " + m_Mobile.Combatant.Name);
if ((int)m_Mobile.GetDistanceToSqrt(m_Mobile.Combatant) > m_Mobile.RangePerception + 1)
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("I have lost " + m_Mobile.Combatant.Name);
Action = ActionType.Guard;
return true;
}
}
}
return true;
}
public override bool DoActionGuard()
{
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, true, true))
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionGuard();
}
return true;
}
}
}

View File

@@ -0,0 +1,177 @@
#region References
using Server.Spells.First;
using Server.Spells.Fourth;
using Server.Spells.Second;
using Server.Targeting;
#endregion
namespace Server.Mobiles
{
public class HealerAI : BaseAI
{
private static readonly NeedDelegate m_Cure = NeedCure;
private static readonly NeedDelegate m_GHeal = NeedGHeal;
private static readonly NeedDelegate m_LHeal = NeedLHeal;
private static readonly NeedDelegate[] m_ACure = {m_Cure};
private static readonly NeedDelegate[] m_AGHeal = {m_GHeal};
private static readonly NeedDelegate[] m_ALHeal = {m_LHeal};
private static readonly NeedDelegate[] m_All = {m_Cure, m_GHeal, m_LHeal};
public HealerAI(BaseCreature m)
: base(m)
{ }
private delegate bool NeedDelegate(Mobile m);
public override bool Think()
{
if (m_Mobile.Deleted)
return false;
var targ = m_Mobile.Target;
if (targ != null)
{
if (targ is CureSpell.InternalTarget)
{
ProcessTarget(targ, m_ACure);
}
else if (targ is GreaterHealSpell.InternalTarget)
{
ProcessTarget(targ, m_AGHeal);
}
else if (targ is HealSpell.InternalTarget)
{
ProcessTarget(targ, m_ALHeal);
}
else
{
targ.Cancel(m_Mobile, TargetCancelType.Canceled);
}
}
else
{
var toHelp = Find(m_All);
if (toHelp != null)
{
if (NeedCure(toHelp))
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("{0} needs a cure", toHelp.Name);
if (!(new CureSpell(m_Mobile, null)).Cast())
new CureSpell(m_Mobile, null).Cast();
}
else if (NeedGHeal(toHelp))
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("{0} needs a greater heal", toHelp.Name);
if (!(new GreaterHealSpell(m_Mobile, null)).Cast())
new HealSpell(m_Mobile, null).Cast();
}
else if (NeedLHeal(toHelp))
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("{0} needs a lesser heal", toHelp.Name);
new HealSpell(m_Mobile, null).Cast();
}
}
else
{
if (AcquireFocusMob(m_Mobile.RangePerception, FightMode.Weakest, false, true, false))
{
WalkMobileRange(m_Mobile.FocusMob, 1, false, 4, 7);
}
else
{
WalkRandomInHome(3, 2, 1);
}
}
}
return true;
}
private static bool NeedCure(Mobile m)
{
return m.Poisoned;
}
private static bool NeedGHeal(Mobile m)
{
return m.Hits < m.HitsMax - 40;
}
private static bool NeedLHeal(Mobile m)
{
return m.Hits < m.HitsMax - 10;
}
private void ProcessTarget(Target targ, NeedDelegate[] func)
{
var toHelp = Find(func);
if (toHelp != null)
{
if (targ.Range != -1 && !m_Mobile.InRange(toHelp, targ.Range))
{
DoMove(m_Mobile.GetDirectionTo(toHelp) | Direction.Running);
}
else
{
targ.Invoke(m_Mobile, toHelp);
}
}
else
{
targ.Cancel(m_Mobile, TargetCancelType.Canceled);
}
}
private Mobile Find(params NeedDelegate[] funcs)
{
if (m_Mobile.Deleted)
return null;
var map = m_Mobile.Map;
if (map != null)
{
var prio = 0.0;
Mobile found = null;
IPooledEnumerable eable = m_Mobile.GetMobilesInRange(m_Mobile.RangePerception);
foreach (Mobile m in eable)
{
if (!m_Mobile.CanSee(m) || !(m is BaseCreature) || ((BaseCreature)m).Team != m_Mobile.Team)
continue;
for (var i = 0; i < funcs.Length; ++i)
{
if (funcs[i](m))
{
var val = -m_Mobile.GetDistanceToSqrt(m);
if (found == null || val > prio)
{
prio = val;
found = m;
}
break;
}
}
}
eable.Free();
return found;
}
return null;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,172 @@
#region References
using Server.Spells;
using Server.Spells.Mysticism;
#endregion
namespace Server.Mobiles
{
public class MysticAI : MageAI
{
public override SkillName CastSkill { get { return SkillName.Mysticism; } }
public override bool UsesMagery
{
get { return m_Mobile.Skills[SkillName.Magery].Base >= 20.0 && !m_Mobile.Controlled; }
}
public MysticAI(BaseCreature m)
: base(m)
{ }
public override Spell GetRandomDamageSpell()
{
if (UsesMagery && 0.5 > Utility.RandomDouble())
{
return base.GetRandomDamageSpell();
}
var mana = m_Mobile.Mana;
var select = 1;
if (mana >= 50)
select = 5;
else if (mana >= 20)
select = 3;
else if (mana >= 9)
select = 2;
switch (Utility.Random(select))
{
case 0:
return new NetherBoltSpell(m_Mobile, null);
case 1:
return new EagleStrikeSpell(m_Mobile, null);
case 2:
return new BombardSpell(m_Mobile, null);
case 3:
return new HailStormSpell(m_Mobile, null);
case 4:
return new NetherCycloneSpell(m_Mobile, null);
}
return null;
}
public override Spell GetRandomCurseSpell()
{
if (UsesMagery && 0.5 > Utility.RandomDouble())
{
return base.GetRandomCurseSpell();
}
var mana = m_Mobile.Mana;
var select = 1;
if (mana >= 40)
select = 4;
else if (mana >= 14)
select = 3;
else if (mana >= 8)
select = 2;
switch (Utility.Random(select))
{
case 0:
return new PurgeMagicSpell(m_Mobile, null);
case 1:
return new SleepSpell(m_Mobile, null);
case 2:
return new MassSleepSpell(m_Mobile, null);
case 3:
return new SpellPlagueSpell(m_Mobile, null);
}
return null;
}
public override Spell GetHealSpell()
{
if (UsesMagery && 0.5 > Utility.RandomDouble())
{
return base.GetHealSpell();
}
if (m_Mobile.Mana >= 20)
return new CleansingWindsSpell(m_Mobile, null);
return null;
}
public override Spell GetCureSpell()
{
if (UsesMagery)
{
return base.GetCureSpell();
}
return null;
}
public override Spell GetRandomBuffSpell()
{
if (UsesMagery)
{
return base.GetRandomBuffSpell();
}
return null;
}
public override Spell RandomCombatSpell()
{
var spell = CheckCastHealingSpell();
if (spell != null)
return spell;
switch (Utility.Random(6))
{
case 0: // Curse
{
m_Mobile.DebugSay("Cursing Thou!");
spell = GetRandomCurseSpell();
break;
}
case 1:
case 2:
case 3:
case 4:
case 5: // damage
{
m_Mobile.DebugSay("Just doing damage");
spell = GetRandomDamageSpell();
}
break;
}
return spell;
}
protected override bool ProcessTarget()
{
var t = m_Mobile.Target;
if (t == null)
return false;
if (t is HailStormSpell.InternalTarget || t is NetherCycloneSpell.InternalTarget)
{
if (m_Mobile.Combatant != null && m_Mobile.InRange(m_Mobile.Combatant.Location, 8))
{
t.Invoke(m_Mobile, m_Mobile.Combatant);
}
else
t.Invoke(m_Mobile, m_Mobile);
return true;
}
return base.ProcessTarget();
}
}
}

View File

@@ -0,0 +1,107 @@
#region References
using Server.Spells;
using Server.Spells.Necromancy;
#endregion
namespace Server.Mobiles
{
public class NecroAI : MageAI
{
public override SkillName CastSkill { get { return SkillName.Necromancy; } }
public override bool UsesMagery { get { return false; } }
public NecroAI(BaseCreature m)
: base(m)
{ }
public override Spell GetRandomDamageSpell()
{
var mana = m_Mobile.Mana;
var select = 1;
if (mana >= 29)
select = 4;
else if (mana >= 23)
select = 3;
else if (mana >= 17)
select = 2;
switch (Utility.Random(select))
{
case 0:
return new PainSpikeSpell(m_Mobile, null);
case 1:
return new PoisonStrikeSpell(m_Mobile, null);
case 2:
return new WitherSpell(m_Mobile, null);
case 3:
return new StrangleSpell(m_Mobile, null);
}
return null;
}
public override Spell GetRandomSummonSpell()
{
if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.Mana >= 23)
{
return new AnimateDeadSpell(m_Mobile, null);
}
return null;
}
public override Spell GetRandomCurseSpell()
{
var mana = m_Mobile.Mana;
var select = 1;
if (mana >= 17)
select = 5;
else if (mana >= 13)
select = 4;
else if (mana >= 11)
select = 3;
switch (Utility.Random(select))
{
case 0:
return new CurseWeaponSpell(m_Mobile, null);
case 1:
Spell spell;
if (NecroMageAI.CheckCastCorpseSkin(m_Mobile))
spell = new CorpseSkinSpell(m_Mobile, null);
else
spell = new CurseWeaponSpell(m_Mobile, null);
return spell;
case 2:
return new EvilOmenSpell(m_Mobile, null);
case 3:
return new BloodOathSpell(m_Mobile, null);
case 4:
return new MindRotSpell(m_Mobile, null);
}
return null;
}
public override Spell GetCureSpell()
{
return null;
}
public override Spell GetRandomBuffSpell()
{
return new CurseWeaponSpell(m_Mobile, null);
}
public override Spell GetHealSpell()
{
m_Mobile.UseSkill(SkillName.SpiritSpeak);
return null;
}
}
}

View File

@@ -0,0 +1,190 @@
#region References
using Server.Spells;
using Server.Spells.First;
using Server.Spells.Fourth;
using Server.Spells.Necromancy;
using Server.Spells.Second;
#endregion
namespace Server.Mobiles
{
public class NecroMageAI : MageAI
{
/*private Mobile m_Animated;
public Mobile Animated
{
get { return m_Animated; }
set { m_Animated = value; }
}*/
public override SkillName CastSkill { get { return SkillName.Magery; } }
public NecroMageAI(BaseCreature m)
: base(m)
{ }
public override Spell GetRandomDamageSpell()
{
if (0.5 > Utility.RandomDouble())
{
return base.GetRandomDamageSpell();
}
var mana = m_Mobile.Mana;
var select = 1;
if (mana >= 29)
select = 4;
else if (mana >= 23)
select = 3;
else if (mana >= 17)
select = 2;
switch (Utility.Random(select))
{
case 0:
return new PainSpikeSpell(m_Mobile, null);
case 1:
return new PoisonStrikeSpell(m_Mobile, null);
case 2:
return new WitherSpell(m_Mobile, null);
case 3:
return new StrangleSpell(m_Mobile, null);
}
return null;
}
public override Spell GetRandomCurseSpell()
{
if (0.5 > Utility.RandomDouble())
{
return base.GetRandomCurseSpell();
}
var mana = m_Mobile.Mana;
var select = 1;
if (mana >= 17)
select = 4;
else if (mana >= 13)
select = 3;
else if (mana >= 11)
select = 2;
switch (Utility.Random(select))
{
case 0:
Spell spell;
if (CheckCastCorpseSkin(m_Mobile))
spell = new CorpseSkinSpell(m_Mobile, null);
else
spell = new EvilOmenSpell(m_Mobile, null);
return spell;
case 1:
return new EvilOmenSpell(m_Mobile, null);
case 2:
return new BloodOathSpell(m_Mobile, null);
case 3:
return new MindRotSpell(m_Mobile, null);
}
return null;
}
public override Spell GetRandomBuffSpell()
{
if (0.5 > Utility.RandomDouble())
{
return base.GetRandomBuffSpell();
}
if (!SmartAI && Utility.RandomBool())
{
return new CurseWeaponSpell(m_Mobile, null);
}
return GetRandomSummonSpell();
}
public override Spell GetRandomSummonSpell()
{
if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.Mana >= 23)
{
return new AnimateDeadSpell(m_Mobile, null);
}
return null;
}
protected override Spell CheckCastHealingSpell()
{
if (m_Mobile.Summoned || m_Mobile.Hits >= m_Mobile.HitsMax)
return null;
if (0.1 > Utility.RandomDouble())
m_Mobile.UseSkill(SkillName.SpiritSpeak);
else
return base.CheckCastHealingSpell();
return null;
}
public override bool DoActionGuard()
{
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("I am going to attack {0}", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
if (m_Mobile.Poisoned)
{
new CureSpell(m_Mobile, null).Cast();
}
else if (!m_Mobile.Summoned)
{
if (ScaleBySkill(HealChance, SkillName.Necromancy) > Utility.RandomDouble() &&
m_Mobile.Hits < m_Mobile.HitsMax - 30)
{
m_Mobile.UseSkill(SkillName.SpiritSpeak);
}
else if (ScaleBySkill(HealChance, SkillName.Magery) > Utility.RandomDouble())
{
if (m_Mobile.Hits < (m_Mobile.HitsMax - 50))
{
if (!new GreaterHealSpell(m_Mobile, null).Cast())
new HealSpell(m_Mobile, null).Cast();
}
else if (m_Mobile.Hits < (m_Mobile.HitsMax - 10))
{
new HealSpell(m_Mobile, null).Cast();
}
}
else
{
base.DoActionGuard();
}
}
else
{
base.DoActionGuard();
}
}
return true;
}
public static bool CheckCastCorpseSkin(BaseCreature bc)
{
return bc.ColdDamage != 100 && bc.PhysicalDamage != 100;
}
}
}

View File

@@ -0,0 +1,202 @@
#region References
using System;
using System.Collections.Generic;
using Server.Items;
using Server.Spells;
using Server.Spells.Ninjitsu;
#endregion
namespace Server.Mobiles
{
public class NinjaAI : MeleeAI
{
private DateTime m_NextCastTime;
private DateTime m_NextRanged;
public NinjaAI(BaseCreature bc)
: base(bc)
{
m_NextCastTime = DateTime.UtcNow;
}
private void TryPerformHide()
{
if (!m_Mobile.Alive || m_Mobile.Deleted)
return;
if (!m_Mobile.Hidden && Core.TickCount - m_Mobile.NextSkillTime >= 0)
{
var chance = 0.05;
if (m_Mobile.Hits < 20)
chance = 0.10;
if (m_Mobile.Poisoned)
chance = 0.01;
if (Utility.RandomDouble() < chance)
HideSelf();
}
}
private void HideSelf()
{
Effects.SendLocationParticles(
EffectItem.Create(m_Mobile.Location, m_Mobile.Map, EffectItem.DefaultDuration),
0x3728,
10,
10,
2023);
m_Mobile.PlaySound(0x22F);
m_Mobile.Hidden = true;
m_Mobile.UseSkill(SkillName.Stealth);
}
public virtual SpecialMove GetHiddenSpecialMove()
{
var skill = (int)m_Mobile.Skills[SkillName.Ninjitsu].Value;
if (skill < 40)
return null;
if (skill >= 60)
{
//return .5 > Utility.RandomDouble() ? new SupriseAttack() : new Backstab();
return .5 > Utility.RandomDouble() ? SpellRegistry.GetSpecialMove(504) : SpellRegistry.GetSpecialMove(505);
}
return SpellRegistry.GetSpecialMove(505); //new Backstab();
}
public virtual SpecialMove GetSpecialMove()
{
var skill = (int)m_Mobile.Skills[SkillName.Ninjitsu].Value;
if (skill < 40)
return null;
var avail = 1;
if (skill >= 85)
avail = 3;
else if (skill >= 80)
avail = 2;
switch (Utility.Random(avail))
{
case 0:
return SpellRegistry.GetSpecialMove(500); //new FocusAttack();
case 1:
return SpellRegistry.GetSpecialMove(503); //new KiAttack();
case 2:
return SpellRegistry.GetSpecialMove(501); //new DeathStrike();
}
return null;
}
public void DoRangedAttack()
{
var c = m_Mobile.Combatant as Mobile;
if (c == null)
return;
var list = new List<INinjaWeapon>();
var d = (int)m_Mobile.GetDistanceToSqrt(c.Location);
foreach (var item in m_Mobile.Items)
if (item is INinjaWeapon && ((INinjaWeapon)item).UsesRemaining > 0 && d >= ((INinjaWeapon)item).WeaponMinRange &&
d <= ((INinjaWeapon)item).WeaponMaxRange)
list.Add(item as INinjaWeapon);
if (m_Mobile.Backpack != null)
{
foreach (var item in m_Mobile.Backpack.Items)
if (item is INinjaWeapon && ((INinjaWeapon)item).UsesRemaining > 0 && d >= ((INinjaWeapon)item).WeaponMinRange &&
d <= ((INinjaWeapon)item).WeaponMaxRange)
list.Add(item as INinjaWeapon);
}
if (list.Count > 0)
{
var toUse = list[Utility.Random(list.Count)];
if (toUse != null)
NinjaWeapon.Shoot(m_Mobile, c, toUse);
}
ColUtility.Free(list);
m_NextRanged = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 120));
}
public override bool DoActionWander()
{
base.DoActionWander();
if (m_Mobile.Combatant == null)
TryPerformHide();
return true;
}
public override bool DoActionCombat()
{
base.DoActionCombat();
if (m_Mobile.Combatant == null)
return true;
var special = SpecialMove.GetCurrentMove(m_Mobile);
if (special == null && m_NextCastTime < DateTime.UtcNow && 0.05 > Utility.RandomDouble())
{
if (0.05 > Utility.RandomDouble())
{
new MirrorImage(m_Mobile, null).Cast();
}
else
{
if (m_Mobile.Hidden)
special = GetHiddenSpecialMove();
else
special = GetSpecialMove();
if (special != null)
{
SpecialMove.SetCurrentMove(m_Mobile, special);
m_NextCastTime = DateTime.UtcNow + GetCastDelay();
}
}
}
if (m_NextRanged < DateTime.UtcNow && 0.08 > Utility.RandomDouble())
DoRangedAttack();
return true;
}
public override bool DoActionFlee()
{
base.DoActionFlee();
TryPerformHide();
return true;
}
public TimeSpan GetCastDelay()
{
var skill = (int)m_Mobile.Skills[SkillName.Ninjitsu].Value;
if (skill >= 85)
return TimeSpan.FromSeconds(15);
if (skill > 40)
return TimeSpan.FromSeconds(30);
return TimeSpan.FromSeconds(45);
}
}
}

View File

@@ -0,0 +1,85 @@
#region References
using Server.Spells;
using Server.Spells.Chivalry;
#endregion
namespace Server.Mobiles
{
public class PaladinAI : MageAI
{
public override SkillName CastSkill { get { return SkillName.Chivalry; } }
public override bool UsesMagery { get { return false; } }
public override double HealChance { get { return .1; } }
public PaladinAI(BaseCreature m)
: base(m)
{ }
public override Spell GetRandomDamageSpell()
{
if (m_Mobile.Mana > 10 && 0.1 > Utility.RandomDouble())
return new HolyLightSpell(m_Mobile, null);
return null;
}
public override Spell GetRandomCurseSpell()
{
if (m_Mobile.Mana > 10)
return new DispelEvilSpell(m_Mobile, null);
return null;
}
public override Spell GetRandomBuffSpell()
{
var mana = m_Mobile.Mana;
var select = 1;
if (mana >= 15)
select = 3;
if (mana >= 20 && !EnemyOfOneSpell.UnderEffect(m_Mobile))
select = 4;
switch (Utility.Random(select))
{
case 0:
return new RemoveCurseSpell(m_Mobile, null);
case 1:
return new DivineFurySpell(m_Mobile, null);
case 2:
return new ConsecrateWeaponSpell(m_Mobile, null);
case 3:
return new EnemyOfOneSpell(m_Mobile, null);
}
return new ConsecrateWeaponSpell(m_Mobile, null);
}
public override Spell GetHealSpell()
{
if (m_Mobile.Mana > 10)
return new CloseWoundsSpell(m_Mobile, null);
return null;
}
public override Spell GetCureSpell()
{
if (m_Mobile.Mana > 10)
return new CleanseByFireSpell(m_Mobile, null);
return null;
}
protected override bool ProcessTarget()
{
if (m_Mobile.Target == null)
return false;
m_Mobile.Target.Invoke(m_Mobile, m_Mobile);
return true;
}
}
}

View File

@@ -0,0 +1,129 @@
#region References
using System;
using Server.Spells;
using Server.Spells.Bushido;
#endregion
namespace Server.Mobiles
{
public class SamuraiAI : MeleeAI
{
private DateTime m_NextCastTime;
private DateTime m_NextSpecial;
public SamuraiAI(BaseCreature bc)
: base(bc)
{
m_NextCastTime = DateTime.UtcNow;
m_NextSpecial = DateTime.UtcNow;
}
public virtual SpecialMove GetSpecialMove()
{
var skill = (int)m_Mobile.Skills[SkillName.Bushido].Value;
if (skill <= 50)
return null;
if (m_Mobile.Combatant != null && m_Mobile.Combatant.Hits <= 10 && skill >= 25)
return SpellRegistry.GetSpecialMove(400); //new HonerableExecution();
if (skill >= 70 && CheckForMomentumStrike() && 0.5 > Utility.RandomDouble())
return SpellRegistry.GetSpecialMove(405); //new MomentumStrike();
return SpellRegistry.GetSpecialMove(404); // new LightningStrike();
}
private bool CheckForMomentumStrike()
{
var count = 0;
IPooledEnumerable eable = m_Mobile.GetMobilesInRange(1);
foreach (Mobile m in eable)
{
if (m.CanBeHarmful(m_Mobile) && m != m_Mobile)
count++;
}
eable.Free();
return count > 1;
}
public virtual Spell GetRandomSpell()
{
// 25 - Confidence
// 40 - Counter Attack
// 60 - Evasion
var skill = (int)m_Mobile.Skills[SkillName.Bushido].Value;
if (skill < 25)
return null;
var avail = 1;
if (skill >= 60)
avail = 3;
else if (skill >= 40)
avail = 2;
switch (Utility.Random(avail))
{
case 0:
return new Confidence(m_Mobile, null);
case 1:
return new CounterAttack(m_Mobile, null);
case 2:
return new Evasion(m_Mobile, null);
}
return null;
}
public override bool DoActionCombat()
{
base.DoActionCombat();
var c = m_Mobile.Combatant as Mobile;
if (c != null)
{
var move = SpecialMove.GetCurrentMove(m_Mobile);
if (move == null && m_NextSpecial < DateTime.UtcNow && 0.05 > Utility.RandomDouble())
{
move = GetSpecialMove();
if (move != null)
{
SpecialMove.SetCurrentMove(m_Mobile, move);
m_NextSpecial = DateTime.UtcNow + GetCastDelay();
}
}
else if (m_Mobile.Spell == null && m_NextCastTime < DateTime.UtcNow && 0.05 > Utility.RandomDouble())
{
var spell = GetRandomSpell();
if (spell != null)
{
spell.Cast();
m_NextCastTime = DateTime.UtcNow + GetCastDelay();
}
}
}
return true;
}
public TimeSpan GetCastDelay()
{
var skill = (int)m_Mobile.Skills[SkillName.Bushido].Value;
if (skill >= 60)
return TimeSpan.FromSeconds(15);
if (skill > 25)
return TimeSpan.FromSeconds(30);
return TimeSpan.FromSeconds(45);
}
}
}

View File

@@ -0,0 +1,820 @@
#region References
using System;
using Server.Spells;
using Server.Spells.Fifth;
using Server.Spells.First;
using Server.Spells.Fourth;
using Server.Spells.Necromancy;
using Server.Spells.Second;
using Server.Spells.Seventh;
using Server.Spells.Sixth;
using Server.Spells.Third;
using Server.Targeting;
#endregion
namespace Server.Mobiles
{
public class SpellbinderAI : BaseAI
{
private static readonly int[] m_Offsets =
{
-1, -1, -1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 0, 1, 1, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -1, -2, -1, 2, 0, -2, 0,
2, 1, -2, 1, 2, 2, -2, 2, -1, 2, 0, 2, 1, 2, 2
};
private const double HealChance = 0.05; // 5% chance to heal at gm necromancy, uses spirit speak healing
private const double TeleportChance = 0.05; // 5% chance to teleport at gm magery
private const double DispelChance = 0.75; // 75% chance to dispel at gm magery
private DateTime m_NextCastTime;
private DateTime m_NextHealTime = DateTime.UtcNow;
public SpellbinderAI(BaseCreature m)
: base(m)
{ }
public override bool Think()
{
if (m_Mobile.Deleted)
return false;
var targ = m_Mobile.Target;
if (targ != null)
{
ProcessTarget(targ);
return true;
}
return base.Think();
}
public virtual double ScaleByNecromancy(double v)
{
return m_Mobile.Skills[SkillName.Necromancy].Value * v * 0.01;
}
public virtual double ScaleByMagery(double v)
{
return m_Mobile.Skills[SkillName.Magery].Value * v * 0.01;
}
public override bool DoActionWander()
{
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("I am going to attack {0}", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
m_NextCastTime = DateTime.UtcNow;
}
else if (m_Mobile.Mana < m_Mobile.ManaMax)
{
m_Mobile.DebugSay("I am going to meditate");
m_Mobile.UseSkill(SkillName.Meditation);
}
else
{
m_Mobile.DebugSay("I am wandering");
m_Mobile.Warmode = false;
base.DoActionWander();
if (m_Mobile.Poisoned)
{
new CureSpell(m_Mobile, null).Cast();
}
else if (!m_Mobile.Summoned)
{
if (m_Mobile.Hits < (m_Mobile.HitsMax - 50))
{
if (!new GreaterHealSpell(m_Mobile, null).Cast())
new HealSpell(m_Mobile, null).Cast();
}
else if (m_Mobile.Hits < (m_Mobile.HitsMax - 10))
{
new HealSpell(m_Mobile, null).Cast();
}
}
}
return true;
}
public void RunTo(Mobile m)
{
if (m.Paralyzed || m.Frozen)
{
if (m_Mobile.InRange(m, 1))
RunFrom(m);
else if (!m_Mobile.InRange(m, m_Mobile.RangeFight > 2 ? m_Mobile.RangeFight : 2) && !MoveTo(m, true, 1))
OnFailedMove();
}
else
{
if (!m_Mobile.InRange(m, m_Mobile.RangeFight))
{
if (!MoveTo(m, true, 1))
OnFailedMove();
}
else if (m_Mobile.InRange(m, m_Mobile.RangeFight - 1))
{
RunFrom(m);
}
}
}
public void RunFrom(IDamageable m)
{
Run((Direction)((int)m_Mobile.GetDirectionTo(m) - 4) & Direction.Mask);
}
public void OnFailedMove()
{
if (!m_Mobile.DisallowAllMoves && ScaleByMagery(TeleportChance) > Utility.RandomDouble())
{
if (m_Mobile.Target != null)
m_Mobile.Target.Cancel(m_Mobile, TargetCancelType.Canceled);
new TeleportSpell(m_Mobile, null).Cast();
m_Mobile.DebugSay("I am stuck, I'm going to try teleporting away");
}
else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
m_Mobile.DebugSay("I am stuck");
}
}
public void Run(Direction d)
{
if ((m_Mobile.Spell != null && m_Mobile.Spell.IsCasting) || !m_Mobile.CanMove || m_Mobile.Paralyzed ||
m_Mobile.Frozen || m_Mobile.DisallowAllMoves)
return;
m_Mobile.Direction = d | Direction.Running;
if (!DoMove(m_Mobile.Direction, true))
OnFailedMove();
}
public virtual Spell GetRandomCurseSpell()
{
var necro = (int)((m_Mobile.Skills[SkillName.Necromancy].Value + 50.0) / (100.0 / 7.0));
var mage = (int)((m_Mobile.Skills[SkillName.Magery].Value + 50.0) / (100.0 / 7.0));
if (mage < 1)
mage = 1;
if (necro < 1)
necro = 1;
if (m_Mobile.Skills[SkillName.Necromancy].Value > 30 && Utility.Random(necro) > Utility.Random(mage))
{
switch (Utility.Random(necro - 5))
{
case 0:
case 1:
return new CorpseSkinSpell(m_Mobile, null);
case 2:
case 3:
return new MindRotSpell(m_Mobile, null);
default:
return new MindRotSpell(m_Mobile, null);
}
}
if (Utility.RandomBool() && mage > 3)
return new CurseSpell(m_Mobile, null);
switch (Utility.Random(3))
{
default:
case 0:
return new WeakenSpell(m_Mobile, null);
case 1:
return new ClumsySpell(m_Mobile, null);
case 2:
return new FeeblemindSpell(m_Mobile, null);
}
}
public virtual Spell GetRandomManaDrainSpell()
{
if (Utility.RandomBool())
{
if (m_Mobile.Skills[SkillName.Magery].Value >= 80.0)
return new ManaVampireSpell(m_Mobile, null);
}
return new ManaDrainSpell(m_Mobile, null);
}
public virtual Spell DoDispel(Mobile toDispel)
{
if (ScaleByMagery(DispelChance) > Utility.RandomDouble())
return new DispelSpell(m_Mobile, null);
return ChooseSpell(toDispel);
}
public virtual Spell ChooseSpell(IDamageable c)
{
var spell = CheckCastHealingSpell();
if (spell != null)
return spell;
if (!(c is Mobile))
{
return null;
}
var mob = c as Mobile;
var damage = ((m_Mobile.Skills[SkillName.SpiritSpeak].Value - mob.Skills[SkillName.MagicResist].Value) / 10) +
(mob.Player ? 18 : 30);
if (damage > c.Hits)
spell = new ManaDrainSpell(m_Mobile, null);
switch (Utility.Random(16))
{
case 0:
case 1:
case 2: // Poison them
{
m_Mobile.DebugSay("Attempting to BloodOath");
if (!mob.Poisoned)
spell = new BloodOathSpell(m_Mobile, null);
break;
}
case 3: // Bless ourselves.
{
m_Mobile.DebugSay("Blessing myself");
spell = new BlessSpell(m_Mobile, null);
break;
}
case 4:
case 5:
case 6: // Curse them.
{
m_Mobile.DebugSay("Attempting to curse");
spell = GetRandomCurseSpell();
break;
}
case 7: // Paralyze them.
{
m_Mobile.DebugSay("Attempting to paralyze");
if (m_Mobile.Skills[SkillName.Magery].Value > 50.0)
spell = new ParalyzeSpell(m_Mobile, null);
break;
}
case 8: // Drain mana
{
m_Mobile.DebugSay("Attempting to drain mana");
spell = GetRandomManaDrainSpell();
break;
}
case 9: // Blood oath them
{
m_Mobile.DebugSay("Attempting to blood oath");
if (m_Mobile.Skills[SkillName.Necromancy].Value > 30 && BloodOathSpell.GetBloodOath(mob) != m_Mobile)
spell = new BloodOathSpell(m_Mobile, null);
break;
}
}
return spell;
}
public override bool DoActionCombat()
{
var c = m_Mobile.Combatant;
m_Mobile.Warmode = true;
if (c == null || c.Deleted || !c.Alive || (c is Mobile && ((Mobile)c).IsDeadBondedPet) || !m_Mobile.CanSee(c) ||
!m_Mobile.CanBeHarmful(c, false) || c.Map != m_Mobile.Map)
{
// Our combatant is deleted, dead, hidden, or we cannot hurt them
// Try to find another combatant
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("Something happened to my combatant, so I am going to fight {0}", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = c = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
else
{
m_Mobile.DebugSay("Something happened to my combatant, and nothing is around. I am on guard.");
Action = ActionType.Guard;
return true;
}
}
if (!m_Mobile.InLOS(c))
{
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.Combatant = c = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
}
if (!m_Mobile.StunReady && m_Mobile.Skills[SkillName.Wrestling].Value >= 80.0 &&
m_Mobile.Skills[SkillName.Anatomy].Value >= 80.0)
EventSink.InvokeStunRequest(new StunRequestEventArgs(m_Mobile));
if (!m_Mobile.InRange(c, m_Mobile.RangePerception))
{
// They are somewhat far away, can we find something else?
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.Combatant = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
else if (!m_Mobile.InRange(c, m_Mobile.RangePerception * 3))
{
m_Mobile.Combatant = null;
}
c = m_Mobile.Combatant;
if (c == null)
{
m_Mobile.DebugSay("My combatant has fled, so I am on guard");
Action = ActionType.Guard;
return true;
}
}
if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee)
{
if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100)
{
// We are low on health, should we flee?
if (Utility.Random(100) <= Math.Max(10, 10 + c.Hits - m_Mobile.Hits))
{
m_Mobile.DebugSay("I am going to flee from {0}", c.Name);
Action = ActionType.Flee;
return true;
}
}
}
if (m_Mobile.Spell == null && DateTime.UtcNow > m_NextCastTime && m_Mobile.InRange(c, 12))
{
// We are ready to cast a spell
Spell spell = null;
var toDispel = FindDispelTarget(true);
if (m_Mobile.Poisoned) // Top cast priority is cure
{
m_Mobile.DebugSay("I am going to cure myself");
spell = new CureSpell(m_Mobile, null);
}
else if (toDispel != null) // Something dispellable is attacking us
{
m_Mobile.DebugSay("I am going to dispel {0}", toDispel);
spell = DoDispel(toDispel);
}
else if (c is Mobile && (((Mobile)c).Spell is HealSpell || ((Mobile)c).Spell is GreaterHealSpell) &&
!((Mobile)c).Poisoned) // They have a heal spell out
{
spell = new BloodOathSpell(m_Mobile, null);
}
else
{
spell = ChooseSpell(c);
}
// Now we have a spell picked
// Move first before casting
if (toDispel != null)
{
if (m_Mobile.InRange(toDispel, 10))
RunFrom(toDispel);
else if (!m_Mobile.InRange(toDispel, 12))
RunTo(toDispel);
}
else if (c is Mobile)
{
RunTo((Mobile)c);
}
if (spell != null)
spell.Cast();
TimeSpan delay;
if (spell is DispelSpell)
delay = TimeSpan.FromSeconds(m_Mobile.ActiveSpeed);
else
delay = GetDelay();
m_NextCastTime = DateTime.UtcNow + delay;
}
else if (c is Mobile && (m_Mobile.Spell == null || !m_Mobile.Spell.IsCasting))
{
RunTo((Mobile)c);
}
return true;
}
public override bool DoActionGuard()
{
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("I am going to attack {0}", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
if (m_Mobile.Poisoned)
{
new CureSpell(m_Mobile, null).Cast();
}
else if (!m_Mobile.Summoned && ((ScaleByMagery(HealChance) > Utility.RandomDouble())))
{
if (m_Mobile.Hits < (m_Mobile.HitsMax - 50))
{
if (!new GreaterHealSpell(m_Mobile, null).Cast())
new HealSpell(m_Mobile, null).Cast();
}
else if (m_Mobile.Hits < (m_Mobile.HitsMax - 10))
{
new HealSpell(m_Mobile, null).Cast();
}
else
{
base.DoActionGuard();
}
}
else
{
base.DoActionGuard();
}
}
return true;
}
public override bool DoActionFlee()
{
var c = m_Mobile.Combatant as Mobile;
if ((m_Mobile.Mana > 20 || m_Mobile.Mana == m_Mobile.ManaMax) && m_Mobile.Hits > (m_Mobile.HitsMax / 2))
{
// If I have a target, go back and fight them
if (c != null && m_Mobile.GetDistanceToSqrt(c) <= m_Mobile.RangePerception * 2)
{
m_Mobile.DebugSay("I am stronger now, reengaging {0}", c.Name);
Action = ActionType.Combat;
}
else
{
m_Mobile.DebugSay("I am stronger now, my guard is up");
Action = ActionType.Guard;
}
}
else
{
base.DoActionFlee();
}
return true;
}
public Mobile FindDispelTarget(bool activeOnly)
{
if (m_Mobile.Deleted || m_Mobile.Int < 95 || CanDispel(m_Mobile) || m_Mobile.AutoDispel)
return null;
if (activeOnly)
{
var aggressed = m_Mobile.Aggressed;
var aggressors = m_Mobile.Aggressors;
Mobile active = null;
var activePrio = 0.0;
var comb = m_Mobile.Combatant as Mobile;
if (comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && m_Mobile.InRange(comb, 12) &&
CanDispel(comb))
{
active = comb;
activePrio = m_Mobile.GetDistanceToSqrt(comb);
if (activePrio <= 2)
return active;
}
for (var i = 0; i < aggressed.Count; ++i)
{
var info = aggressed[i];
var m = info.Defender;
if (m != comb && m.Combatant == m_Mobile && m_Mobile.InRange(m, 12) && CanDispel(m))
{
var prio = m_Mobile.GetDistanceToSqrt(m);
if (active == null || prio < activePrio)
{
active = m;
activePrio = prio;
if (activePrio <= 2)
return active;
}
}
}
for (var i = 0; i < aggressors.Count; ++i)
{
var info = aggressors[i];
var m = info.Attacker;
if (m != comb && m.Combatant == m_Mobile && m_Mobile.InRange(m, 12) && CanDispel(m))
{
var prio = m_Mobile.GetDistanceToSqrt(m);
if (active == null || prio < activePrio)
{
active = m;
activePrio = prio;
if (activePrio <= 2)
return active;
}
}
}
return active;
}
var map = m_Mobile.Map;
if (map != null)
{
Mobile active = null, inactive = null;
double actPrio = 0.0, inactPrio = 0.0;
var comb = m_Mobile.Combatant as Mobile;
if (comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && CanDispel(comb))
{
active = inactive = comb;
actPrio = inactPrio = m_Mobile.GetDistanceToSqrt(comb);
}
IPooledEnumerable eable = m_Mobile.GetMobilesInRange(12);
foreach (Mobile m in eable)
{
if (m != m_Mobile && CanDispel(m))
{
var prio = m_Mobile.GetDistanceToSqrt(m);
if (!activeOnly && (inactive == null || prio < inactPrio))
{
inactive = m;
inactPrio = prio;
}
if ((m_Mobile.Combatant == m || m.Combatant == m_Mobile) && (active == null || prio < actPrio))
{
active = m;
actPrio = prio;
}
}
}
eable.Free();
return active != null ? active : inactive;
}
return null;
}
public bool CanDispel(Mobile m)
{
return (m is BaseCreature && ((BaseCreature)m).Summoned && m_Mobile.CanBeHarmful(m, false) &&
!((BaseCreature)m).IsAnimatedDead);
}
private Spell CheckCastHealingSpell()
{
// If I'm poisoned, always attempt to cure.
if (m_Mobile.Poisoned)
return new CureSpell(m_Mobile, null);
// Summoned creatures never heal themselves.
if (m_Mobile.Summoned)
return null;
if (m_Mobile.Controlled)
{
if (DateTime.UtcNow < m_NextHealTime)
return null;
}
if (ScaleByMagery(HealChance) < Utility.RandomDouble())
return null;
Spell spell = null;
if (m_Mobile.Hits < (m_Mobile.HitsMax - 50))
{
spell = new GreaterHealSpell(m_Mobile, null);
if (spell == null)
spell = new HealSpell(m_Mobile, null);
}
else if (m_Mobile.Hits < (m_Mobile.HitsMax - 10))
spell = new HealSpell(m_Mobile, null);
double delay;
if (m_Mobile.Int >= 500)
delay = Utility.RandomMinMax(7, 10);
else
delay = Math.Sqrt(600 - m_Mobile.Int);
m_Mobile.UseSkill(SkillName.SpiritSpeak);
m_NextHealTime = DateTime.UtcNow + TimeSpan.FromSeconds(delay);
return spell;
}
private TimeSpan GetDelay()
{
var del = ScaleByMagery(3.0);
var min = 6.0 - (del * 0.75);
var max = 6.0 - (del * 1.25);
return TimeSpan.FromSeconds(min + ((max - min) * Utility.RandomDouble()));
}
private void ProcessTarget(Target targ)
{
var isDispel = (targ is DispelSpell.InternalTarget);
var isParalyze = (targ is ParalyzeSpell.InternalTarget);
var isTeleport = (targ is TeleportSpell.InternalTarget);
var teleportAway = false;
Mobile toTarget;
if (isDispel)
{
toTarget = FindDispelTarget(false);
if (toTarget != null && m_Mobile.InRange(toTarget, 10))
RunFrom(toTarget);
}
else if (isParalyze || isTeleport)
{
toTarget = FindDispelTarget(true);
if (toTarget == null)
{
toTarget = m_Mobile.Combatant as Mobile;
if (toTarget != null)
RunTo(toTarget);
}
else if (m_Mobile.InRange(toTarget, 10))
{
RunFrom(toTarget);
teleportAway = true;
}
else
{
teleportAway = true;
}
}
else
{
toTarget = m_Mobile.Combatant as Mobile;
if (toTarget != null)
RunTo(toTarget);
}
if ((targ.Flags & TargetFlags.Harmful) != 0 && toTarget != null)
{
if ((targ.Range == -1 || m_Mobile.InRange(toTarget, targ.Range)) && m_Mobile.CanSee(toTarget) &&
m_Mobile.InLOS(toTarget))
{
targ.Invoke(m_Mobile, toTarget);
}
else if (isDispel)
{
targ.Cancel(m_Mobile, TargetCancelType.Canceled);
}
}
else if ((targ.Flags & TargetFlags.Beneficial) != 0)
{
targ.Invoke(m_Mobile, m_Mobile);
}
else if (isTeleport && toTarget != null)
{
var map = m_Mobile.Map;
if (map == null)
{
targ.Cancel(m_Mobile, TargetCancelType.Canceled);
return;
}
int px, py;
if (teleportAway)
{
var rx = m_Mobile.X - toTarget.X;
var ry = m_Mobile.Y - toTarget.Y;
var d = m_Mobile.GetDistanceToSqrt(toTarget);
px = toTarget.X + (int)(rx * (10 / d));
py = toTarget.Y + (int)(ry * (10 / d));
}
else
{
px = toTarget.X;
py = toTarget.Y;
}
for (var i = 0; i < m_Offsets.Length; i += 2)
{
int x = m_Offsets[i], y = m_Offsets[i + 1];
var p = new Point3D(px + x, py + y, 0);
var lt = new LandTarget(p, map);
if ((targ.Range == -1 || m_Mobile.InRange(p, targ.Range)) && m_Mobile.InLOS(lt) &&
map.CanSpawnMobile(px + x, py + y, lt.Z) && !SpellHelper.CheckMulti(p, map))
{
targ.Invoke(m_Mobile, lt);
return;
}
}
var teleRange = targ.Range;
if (teleRange < 0)
teleRange = 12;
for (var i = 0; i < 10; ++i)
{
var randomPoint = new Point3D(
m_Mobile.X - teleRange + Utility.Random(teleRange * 2 + 1),
m_Mobile.Y - teleRange + Utility.Random(teleRange * 2 + 1),
0);
var lt = new LandTarget(randomPoint, map);
if (m_Mobile.InLOS(lt) && map.CanSpawnMobile(lt.X, lt.Y, lt.Z) && !SpellHelper.CheckMulti(randomPoint, map))
{
targ.Invoke(m_Mobile, new LandTarget(randomPoint, map));
return;
}
}
targ.Cancel(m_Mobile, TargetCancelType.Canceled);
}
else
{
targ.Cancel(m_Mobile, TargetCancelType.Canceled);
}
}
}
}

View File

@@ -0,0 +1,126 @@
#region References
using Server.Items;
using Server.Spells;
using Server.Spells.Spellweaving;
#endregion
namespace Server.Mobiles
{
public class SpellweavingAI : MageAI
{
public override SkillName CastSkill { get { return SkillName.Spellweaving; } }
public override bool UsesMagery
{
get { return m_Mobile.Skills[SkillName.Magery].Base >= 20.0 && !m_Mobile.Controlled; }
}
public SpellweavingAI(BaseCreature m)
: base(m)
{ }
public override Spell GetRandomBuffSpell()
{
if (UsesMagery && 0.5 > Utility.RandomDouble())
{
return base.GetRandomBuffSpell();
}
var mana = m_Mobile.Mana;
var wep = m_Mobile.Weapon as BaseWeapon;
if (mana >= 50 && !ArcaneEmpowermentSpell.IsUnderEffects(m_Mobile) && 0.5 >= Utility.RandomDouble())
return new ArcaneEmpowermentSpell(m_Mobile, null);
if (mana >= 32 && wep != null && !ImmolatingWeaponSpell.IsImmolating(m_Mobile, wep))
return new ImmolatingWeaponSpell(m_Mobile, null);
return null;
}
public override Spell GetRandomCurseSpell()
{
if (UsesMagery)
{
return base.GetRandomCurseSpell();
}
return null;
}
public override Spell GetRandomDamageSpell()
{
if (UsesMagery && 0.5 > Utility.RandomDouble())
{
return base.GetRandomDamageSpell();
}
var mana = m_Mobile.Mana;
var select = 1;
if (mana >= 50)
select = 4;
else if (mana >= 40)
select = 3;
else if (mana >= 30)
select = 2;
switch (Utility.Random(select))
{
case 0:
return new ThunderstormSpell(m_Mobile, null);
case 1:
return new EssenceOfWindSpell(m_Mobile, null);
case 2:
return new WildfireSpell(m_Mobile, null);
case 3:
return new WordOfDeathSpell(m_Mobile, null);
}
return null;
}
public override Spell GetHealSpell()
{
if (UsesMagery && 0.5 > Utility.RandomDouble())
{
return base.GetHealSpell();
}
if (m_Mobile.Mana >= 24)
{
return new GiftOfRenewalSpell(m_Mobile, null);
}
return null;
}
public override Spell GetCureSpell()
{
if (UsesMagery)
{
return base.GetCureSpell();
}
return null;
}
protected override bool ProcessTarget()
{
var t = m_Mobile.Target;
if (t is WildfireSpell.InternalTarget)
{
if (m_Mobile.Combatant != null && m_Mobile.InRange(m_Mobile.Combatant.Location, 8))
{
t.Invoke(m_Mobile, m_Mobile.Combatant);
}
else
t.Invoke(m_Mobile, m_Mobile);
return true;
}
return base.ProcessTarget();
}
}
}

View File

@@ -0,0 +1,155 @@
#region References
using System;
#endregion
namespace Server.Mobiles
{
public class MeleeAI : BaseAI
{
public MeleeAI(BaseCreature m)
: base(m)
{ }
public override bool DoActionWander()
{
m_Mobile.DebugSay("I have no combatant");
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
var c = m_Mobile.Combatant;
if (c == null || c.Deleted || c.Map != m_Mobile.Map || !c.Alive || (c is Mobile && ((Mobile)c).IsDeadBondedPet))
{
m_Mobile.DebugSay("My combatant is gone, so my guard is up");
Action = ActionType.Guard;
return true;
}
if (!m_Mobile.InRange(c, m_Mobile.RangePerception))
{
// They are somewhat far away, can we find something else?
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.Combatant = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
else if (!m_Mobile.InRange(c, m_Mobile.RangePerception * 3))
{
m_Mobile.Combatant = null;
}
c = m_Mobile.Combatant;
if (c == null)
{
m_Mobile.DebugSay("My combatant has fled, so I am on guard");
Action = ActionType.Guard;
return true;
}
}
if (MoveTo(c, true, m_Mobile.RangeFight))
{
if (!DirectionLocked)
m_Mobile.Direction = m_Mobile.GetDirectionTo(c);
}
else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
return true;
}
else if (m_Mobile.GetDistanceToSqrt(c) > m_Mobile.RangePerception + 1)
{
m_Mobile.DebugSay("I cannot find {0}, so my guard is up", c.Name);
Action = ActionType.Guard;
return true;
}
else
{
m_Mobile.DebugSay("I should be closer to {0}", c.Name);
}
if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee)
{
if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100)
{
// We are low on health, should we flee?
if (Utility.Random(100) <= Math.Max(10, 10 + c.Hits - m_Mobile.Hits))
{
m_Mobile.DebugSay("I am going to flee from {0}", c.Name);
Action = ActionType.Flee;
}
}
}
return true;
}
public override bool DoActionGuard()
{
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionGuard();
}
return true;
}
public override bool DoActionFlee()
{
var c = m_Mobile.Combatant as Mobile;
if (m_Mobile.Hits > (m_Mobile.HitsMax / 2))
{
// If I have a target, go back and fight them
if (c != null && m_Mobile.GetDistanceToSqrt(c) <= m_Mobile.RangePerception * 2)
{
m_Mobile.DebugSay("I am stronger now, reengaging {0}", c.Name);
Action = ActionType.Combat;
}
else
{
m_Mobile.DebugSay("I am stronger now, my guard is up");
Action = ActionType.Guard;
}
}
else
{
base.DoActionFlee();
}
return true;
}
}
}

View File

@@ -0,0 +1,92 @@
#region References
using System;
using Server.Mobiles;
#endregion
namespace Server
{
public class OppositionGroup
{
private static readonly OppositionGroup m_TerathansAndOphidians = new OppositionGroup(
new[]
{
new[] {typeof(TerathanAvenger), typeof(TerathanDrone), typeof(TerathanMatriarch), typeof(TerathanWarrior)},
new[]
{
typeof(OphidianArchmage), typeof(OphidianKnight), typeof(OphidianMage), typeof(OphidianMatriarch),
typeof(OphidianWarrior)
}
});
private static readonly OppositionGroup m_SavagesAndOrcs = new OppositionGroup(
new[]
{
new[]
{
typeof(Orc), typeof(OrcBomber), typeof(OrcBrute), typeof(OrcCaptain), typeof(OrcChopper), typeof(OrcishLord),
typeof(OrcishMage), typeof(OrcScout), typeof(SpawnedOrcishLord)
},
new[] {typeof(Savage), typeof(SavageRider), typeof(SavageRidgeback), typeof(SavageShaman)}
});
private static readonly OppositionGroup m_FeyAndUndead = new OppositionGroup(
new[]
{
new[]
{
typeof(Centaur), typeof(EtherealWarrior), typeof(Kirin), typeof(LordOaks), typeof(Pixie), typeof(Silvani),
typeof(Unicorn), typeof(Wisp), typeof(Treefellow), typeof(MLDryad), typeof(Satyr)
},
new[]
{
typeof(AncientLich), typeof(Bogle), typeof(BoneKnight), typeof(BoneMagi), typeof(DarknightCreeper), typeof(Ghoul),
typeof(LadyOfTheSnow), typeof(Lich), typeof(LichLord), typeof(Mummy), typeof(RevenantLion), typeof(RottingCorpse),
typeof(Shade), typeof(ShadowKnight), typeof(SkeletalDragon), typeof(SkeletalDrake), typeof(SkeletalKnight),
typeof(SkeletalMage), typeof(Skeleton), typeof(Spectre), typeof(Wraith), typeof(Zombie)
}
});
private readonly Type[][] m_Types;
public OppositionGroup(Type[][] types)
{
m_Types = types;
}
public static OppositionGroup TerathansAndOphidians { get { return m_TerathansAndOphidians; } }
public static OppositionGroup SavagesAndOrcs { get { return m_SavagesAndOrcs; } }
public static OppositionGroup FeyAndUndead { get { return m_FeyAndUndead; } }
public bool IsEnemy(object from, object target)
{
var fromGroup = IndexOf(from);
var targGroup = IndexOf(target);
return (fromGroup != -1 && targGroup != -1 && fromGroup != targGroup);
}
public int IndexOf(object obj)
{
if (obj == null)
return -1;
var type = obj.GetType();
for (var i = 0; i < m_Types.Length; ++i)
{
var group = m_Types[i];
var contains = false;
for (var j = 0; !contains && j < group.Length; ++j)
contains = group[j].IsAssignableFrom(type);
if (contains)
return i;
}
return -1;
}
}
}

View File

@@ -0,0 +1,330 @@
#region References
using System;
using Server.Items;
using Server.Spells;
using Server.Targeting;
#endregion
namespace Server.Mobiles
{
public class OrcScoutAI : BaseAI
{
private static readonly double teleportChance = 0.04;
private static readonly int[] m_Offsets = {0, 0, -1, -1, 0, -1, 1, -1, -1, 0, 1, 0, -1, -1, 0, 1, 1, 1};
public OrcScoutAI(BaseCreature m)
: base(m)
{ }
public override bool DoActionWander()
{
m_Mobile.DebugSay("I have no combatant");
PerformHide();
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
if (m_Mobile.Combatant != null)
{
Action = ActionType.Combat;
return true;
}
base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
var c = m_Mobile.Combatant as Mobile;
if (c == null || c.Deleted || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet)
{
m_Mobile.DebugSay("My combatant is gone, so my guard is up");
Action = ActionType.Guard;
return true;
}
if (Utility.RandomDouble() < teleportChance)
{
TryToTeleport();
}
if (!m_Mobile.InRange(c, m_Mobile.RangePerception))
{
// They are somewhat far away, can we find something else?
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.Combatant = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
else if (!m_Mobile.InRange(c, m_Mobile.RangePerception * 3))
{
m_Mobile.Combatant = null;
}
c = m_Mobile.Combatant as Mobile;
if (c == null)
{
m_Mobile.DebugSay("My combatant has fled, so I am on guard");
Action = ActionType.Guard;
return true;
}
}
if (MoveTo(c, true, m_Mobile.RangeFight))
{
if (!DirectionLocked)
m_Mobile.Direction = m_Mobile.GetDirectionTo(c);
}
else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
return true;
}
else if (m_Mobile.GetDistanceToSqrt(c) > m_Mobile.RangePerception + 1)
{
m_Mobile.DebugSay("I cannot find {0}, so my guard is up", c.Name);
Action = ActionType.Guard;
return true;
}
else
{
m_Mobile.DebugSay("I should be closer to {0}", c.Name);
}
if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee)
{
/* // When we have no ammo, we flee
Container pack = m_Mobile.Backpack;
if (pack == null || pack.FindItemByType(typeof(Arrow)) == null)
{
Action = ActionType.Flee;
if (Utility.RandomDouble() < teleportChance + 0.1)
{
TryToTeleport();
}
return true;
}
*/
if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100)
{
// We are low on health, should we flee?
if (Utility.Random(100) <= Math.Max(10, 10 + c.Hits - m_Mobile.Hits))
{
m_Mobile.DebugSay("I am going to flee from {0}", c.Name);
Action = ActionType.Flee;
if (Utility.RandomDouble() < teleportChance + 0.1)
{
TryToTeleport();
}
}
}
}
return true;
}
public override bool DoActionGuard()
{
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionGuard();
}
return true;
}
public override bool DoActionFlee()
{
var c = m_Mobile.Combatant as Mobile;
// Container pack = m_Mobile.Backpack;
// bool hasAmmo = !(pack == null || pack.FindItemByType(typeof(Arrow)) == null);
// They can shoot even with no ammo!
if ( /*hasAmmo && */m_Mobile.Hits > m_Mobile.HitsMax / 2)
{
// If I have a target, go back and fight them
if (c != null && m_Mobile.GetDistanceToSqrt(c) <= m_Mobile.RangePerception * 2)
{
m_Mobile.DebugSay("I am stronger now, reengaging {0}", c.Name);
Action = ActionType.Combat;
}
else
{
m_Mobile.DebugSay("I am stronger now, my guard is up");
Action = ActionType.Guard;
}
}
else
{
PerformHide();
base.DoActionFlee();
}
return true;
}
private Mobile FindNearestAggressor()
{
Mobile nearest = null;
var dist = 9999.0;
IPooledEnumerable eable = m_Mobile.GetMobilesInRange(m_Mobile.RangePerception);
foreach (Mobile m in eable)
{
if (m.Player && !m.Hidden && m.IsPlayer() && m.Combatant == m_Mobile)
{
if (dist > m.GetDistanceToSqrt(m_Mobile))
{
nearest = m;
}
}
}
eable.Free();
return nearest;
}
private void TryToTeleport()
{
var m = FindNearestAggressor();
if (m == null || m.Map == null || m_Mobile.Map == null)
{
return;
}
if (m_Mobile.GetDistanceToSqrt(m) > m_Mobile.RangePerception + 1)
{
return;
}
var px = m_Mobile.X;
var py = m_Mobile.Y;
var dx = m_Mobile.X - m.X;
var dy = m_Mobile.Y - m.Y;
// get vector's length
var l = Math.Sqrt((dx * dx + dy * dy));
if (l == 0)
{
var rand = Utility.Random(8) + 1;
rand *= 2;
dx = m_Offsets[rand];
dy = m_Offsets[rand + 1];
l = Math.Sqrt((dx * dx + dy * dy));
}
// normalize vector
var dpx = (dx) / l;
var dpy = (dy) / l;
// move
px += (int)(dpx * (4 + Utility.Random(3)));
py += (int)(dpy * (4 + Utility.Random(3)));
for (var i = 0; i < m_Offsets.Length; i += 2)
{
int x = m_Offsets[i], y = m_Offsets[i + 1];
var p = new Point3D(px + x, py + y, 0);
var lt = new LandTarget(p, m_Mobile.Map);
if (m_Mobile.InLOS(lt) && m_Mobile.Map.CanSpawnMobile(px + x, py + y, lt.Z) &&
!SpellHelper.CheckMulti(p, m_Mobile.Map))
{
m_Mobile.FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
m_Mobile.PlaySound(0x1FE);
m_Mobile.Location = new Point3D(lt.X, lt.Y, lt.Z);
m_Mobile.ProcessDelta();
return;
}
}
}
private void HideSelf()
{
if (Core.TickCount >= m_Mobile.NextSkillTime)
{
Effects.SendLocationParticles(
EffectItem.Create(m_Mobile.Location, m_Mobile.Map, EffectItem.DefaultDuration),
0x3728,
10,
10,
2023);
m_Mobile.PlaySound(0x22F);
m_Mobile.Hidden = true;
m_Mobile.UseSkill(SkillName.Stealth);
}
}
private void PerformHide()
{
if (!m_Mobile.Alive || m_Mobile.Deleted)
{
return;
}
if (!m_Mobile.Hidden)
{
var chance = 0.05;
if (m_Mobile.Hits < 20)
{
chance = 0.1;
}
if (m_Mobile.Poisoned)
{
chance = 0.01;
}
if (Utility.RandomDouble() < chance)
{
HideSelf();
}
}
}
}
}

View File

@@ -0,0 +1,94 @@
/*
* PredatorAI, its an animal that can attack
* Dont flee but dont attack if not hurt or attacked
*
*/
namespace Server.Mobiles
{
public class PredatorAI : BaseAI
{
public PredatorAI(BaseCreature m)
: base(m)
{ }
public override bool DoActionWander()
{
if (m_Mobile.Combatant != null)
{
m_Mobile.DebugSay("I am hurt or being attacked, I kill him");
Action = ActionType.Combat;
}
else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, true, false, true))
{
m_Mobile.DebugSay("There is something near, I go away");
Action = ActionType.Backoff;
}
else
{
base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
var combatant = m_Mobile.Combatant as Mobile;
if (combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map)
{
m_Mobile.DebugSay("My combatant is gone, so my guard is up");
Action = ActionType.Wander;
return true;
}
if (WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
{
if (!DirectionLocked)
m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
}
else
{
if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1)
{
m_Mobile.DebugSay("I cannot find {0}", combatant.Name);
Action = ActionType.Wander;
return true;
}
m_Mobile.DebugSay("I should be closer to {0}", combatant.Name);
}
return true;
}
public override bool DoActionBackoff()
{
if (m_Mobile.IsHurt() || m_Mobile.Combatant != null)
{
Action = ActionType.Combat;
}
else
{
if (AcquireFocusMob(m_Mobile.RangePerception * 2, FightMode.Closest, true, false, true))
{
if (WalkMobileRange(m_Mobile.FocusMob, 1, false, m_Mobile.RangePerception, m_Mobile.RangePerception * 2))
{
m_Mobile.DebugSay("Well, here I am safe");
Action = ActionType.Wander;
}
}
else
{
m_Mobile.DebugSay("I have lost my focus, lets relax");
Action = ActionType.Wander;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,255 @@
#region References
using System;
using System.Collections;
using Server.Factions;
using Server.Mobiles;
#endregion
namespace Server
{
public class SpeedInfo
{
public static readonly double MinDelay = 0.1;
public static readonly double MaxDelay = 0.5;
public static readonly double MinDelayWild = 0.4;
public static readonly double MaxDelayWild = 0.8;
public static bool GetSpeedsNew(BaseCreature bc, ref double activeSpeed, ref double passiveSpeed)
{
var maxDex = GetMaxMovementDex(bc);
var dex = Math.Min(maxDex, Math.Max(25, bc.Dex));
var min = bc.IsMonster || InActivePVPCombat(bc) ? MinDelayWild : MinDelay;
var max = bc.IsMonster || InActivePVPCombat(bc) ? MaxDelayWild : MaxDelay;
if (bc.IsParagon)
{
min /= 2;
max = min + .4;
}
activeSpeed = max - ((max - min) * ((double)dex / maxDex));
if (activeSpeed < min)
{
activeSpeed = min;
}
passiveSpeed = activeSpeed * 2;
return true;
}
private static int GetMaxMovementDex(BaseCreature bc)
{
return bc.IsMonster ? 150 : 190;
}
public static bool InActivePVPCombat(BaseCreature bc)
{
return bc.Combatant != null && bc.ControlOrder != OrderType.Follow && bc.Combatant is PlayerMobile;
}
public static double TransformMoveDelay(BaseCreature bc, double delay)
{
var adjusted = bc.IsMonster ? MaxDelayWild : MaxDelay;
if (!bc.IsDeadPet && (bc.ReduceSpeedWithDamage || bc.IsSubdued))
{
var offset = (double)bc.Stam / (double)bc.StamMax;
if (offset < 1.0)
{
delay = delay + ((adjusted - delay) * (1.0 - offset));
}
}
if (delay > adjusted)
{
delay = adjusted;
}
return delay;
}
public static bool UseNewSpeeds { get { return true; } }
public double ActiveSpeed { get; set; }
public double PassiveSpeed { get; set; }
public Type[] Types { get; set; }
public SpeedInfo(double activeSpeed, double passiveSpeed, Type[] types)
{
ActiveSpeed = activeSpeed;
PassiveSpeed = passiveSpeed;
Types = types;
}
/*public static bool Contains(object obj)
{
if (UseNewSpeeds)
return false;
if (m_Table == null)
LoadTable();
var sp = (SpeedInfo)m_Table[obj.GetType()];
return (sp != null);
}*/
public static bool GetSpeeds(BaseCreature bc, ref double activeSpeed, ref double passiveSpeed)
{
if (UseNewSpeeds)
{
GetSpeedsNew(bc, ref activeSpeed, ref passiveSpeed);
}
else
{
if (m_Table == null)
LoadTable();
var sp = (SpeedInfo)m_Table[bc.GetType()];
if (sp == null)
return false;
activeSpeed = sp.ActiveSpeed;
passiveSpeed = sp.PassiveSpeed;
}
return true;
}
private static void LoadTable()
{
m_Table = new Hashtable();
for (var i = 0; i < m_Speeds.Length; ++i)
{
var info = m_Speeds[i];
var types = info.Types;
for (var j = 0; j < types.Length; ++j)
m_Table[types[j]] = info;
}
}
private static Hashtable m_Table;
private static readonly SpeedInfo[] m_Speeds =
{
// Slow
new SpeedInfo(
0.3,
0.6,
new[]
{
typeof(AntLion), typeof(ArcticOgreLord), typeof(BogThing), typeof(Bogle), typeof(BoneKnight),
typeof(EarthElemental), typeof(Ettin), typeof(FrostOoze), typeof(FrostTroll), typeof(GazerLarva), typeof(Ghoul),
typeof(Golem), typeof(HeadlessOne), typeof(Jwilson), typeof(Mummy), typeof(Ogre), typeof(OgreLord),
typeof(PlagueBeast), typeof(Quagmire), typeof(Rat), typeof(RottingCorpse), typeof(Sewerrat), typeof(Skeleton),
typeof(Slime), typeof(Zombie), typeof(Walrus), typeof(RestlessSoul), typeof(CrystalElemental),
typeof(DarknightCreeper), typeof(MoundOfMaggots), typeof(Juggernaut), typeof(Yamandon), typeof(Serado),
typeof(RuddyBoura), typeof(LowlandBoura), typeof(HighPlainsBoura), typeof(Relanord), typeof(Ortanord),
typeof(Korpre), typeof(Anzuanord), typeof(Anlorzen), typeof(UndeadGuardian), typeof(PutridUndeadGuardian),
typeof(CorgulTheSoulBinder), typeof(GooeyMaggots), typeof(Fezzik), typeof(Ronin)
}),
// Fast
new SpeedInfo(
0.2,
0.4,
new[]
{
typeof(LordOaks), typeof(Silvani), typeof(AirElemental), typeof(AncientWyrm), typeof(Balron), typeof(BladeSpirits),
typeof(DreadSpider), typeof(Efreet), typeof(EtherealWarrior), typeof(Lich), typeof(Nightmare),
typeof(OphidianArchmage), typeof(OphidianMage), typeof(OphidianWarrior), typeof(OphidianMatriarch),
typeof(OphidianKnight), typeof(PoisonElemental), typeof(Revenant), typeof(SandVortex), typeof(SavageRider),
typeof(SavageShaman), typeof(SnowElemental), typeof(WhiteWyrm), typeof(Wisp), typeof(DemonKnight),
typeof(GiantBlackWidow), typeof(SummonedAirElemental), typeof(LesserHiryu), typeof(Hiryu), typeof(LadyOfTheSnow),
typeof(RaiJu), typeof(RuneBeetle), typeof(Changeling), typeof(SentinelSpider), typeof(Anlorvaglem), typeof(Medusa),
typeof(PrimevalLich), typeof(StygianDragon), typeof(CoralSnake), typeof(DarkWisp), typeof(DreamWraith),
typeof(FireAnt), typeof(KepetchAmbusher), typeof(LavaElemental), typeof(MaddeningHorror), typeof(Wight),
typeof(WolfSpider), typeof(UndeadGargoyle), typeof(SlasherOfVeils), typeof(SavagePackWolf), typeof(DemonicJailor),
typeof(SilverSerpent),
#region ML named mobs - before Paragon speedboost
typeof(LadyJennifyr), typeof(LadyMarai), typeof(MasterJonath), typeof(MasterMikael), typeof(MasterTheophilus),
typeof(RedDeath), typeof(SirPatrick), typeof(Rend), typeof(Grobu), typeof(Gnaw), typeof(Guile), typeof(Irk),
typeof(Spite), typeof(LadyLissith), typeof(LadySabrix), typeof(Malefic), typeof(Silk), typeof(Virulent)
// TODO: Where to put Lurg, Putrefier, Swoop and Pyre? They seem slower.
#endregion
}),
// Very Fast
new SpeedInfo(
0.175,
0.350,
new[]
{
typeof(Barracoon), typeof(Neira), typeof(Rikktor), typeof(EnergyVortex), typeof(EliteNinja), typeof(Pixie),
typeof(FleshRenderer), typeof(KhaldunRevenant), typeof(FactionDragoon), typeof(FactionKnight),
typeof(FactionPaladin), typeof(FactionHenchman), typeof(FactionMercenary), typeof(FactionNecromancer),
typeof(FactionSorceress), typeof(FactionWizard), typeof(FactionBerserker), typeof(FactionPaladin),
typeof(Leviathan), typeof(FireBeetle), typeof(FanDancer), typeof(FactionDeathKnight), typeof(ClockworkExodus),
typeof(Navrey), typeof(Raptor), typeof(TrapdoorSpider)
}),
// Extremely Fast
new SpeedInfo(0.08, 0.20, new[] {typeof(Miasma), typeof(Semidar), typeof(Mephitis)}),
// Medium
new SpeedInfo(
0.25,
0.5,
new[]
{
typeof(ToxicElemental), typeof(AgapiteElemental), typeof(Alligator), typeof(AncientLich), typeof(Betrayer),
typeof(Bird), typeof(BlackBear), typeof(BlackSolenInfiltratorQueen), typeof(BlackSolenInfiltratorWarrior),
typeof(BlackSolenQueen), typeof(BlackSolenWarrior), typeof(BlackSolenWorker), typeof(BloodElemental), typeof(Boar),
typeof(Bogling), typeof(BoneMagi), typeof(Brigand), typeof(BronzeElemental), typeof(BrownBear), typeof(Bull),
typeof(BullFrog), typeof(Cat), typeof(Centaur), typeof(ChaosDaemon), typeof(Chicken), typeof(GolemController),
typeof(CopperElemental), typeof(CopperElemental), typeof(Cougar), typeof(Cow), typeof(Cyclops), typeof(Daemon),
typeof(DeepSeaSerpent), typeof(DesertOstard), typeof(DireWolf), typeof(Dog), typeof(Dolphin), typeof(Dragon),
typeof(Drake), typeof(DullCopperElemental), typeof(Eagle), typeof(ElderGazer), typeof(EvilMage),
typeof(EvilMageLord), typeof(Executioner), typeof(Savage), typeof(FireElemental), typeof(FireGargoyle),
typeof(FireSteed), typeof(ForestOstard), typeof(FrenziedOstard), typeof(FrostSpider), typeof(Gargoyle),
typeof(Gazer), typeof(IceSerpent), typeof(GiantRat), typeof(GiantSerpent), typeof(GiantSpider), typeof(GiantToad),
typeof(Goat), typeof(GoldenElemental), typeof(Gorilla), typeof(GreatHart), typeof(GreyWolf), typeof(GrizzlyBear),
typeof(Guardian), typeof(Harpy), typeof(Harrower), typeof(HellHound), typeof(Hind), typeof(HordeMinion),
typeof(Horse), typeof(IceElemental), typeof(IceFiend), typeof(IceSnake), typeof(Imp), typeof(JackRabbit),
typeof(Kirin), typeof(Kraken), typeof(PredatorHellCat), typeof(LavaLizard), typeof(LavaSerpent), typeof(LavaSnake),
typeof(Lizardman), typeof(Llama), typeof(Mongbat), typeof(StrongMongbat), typeof(MountainGoat), typeof(Orc),
typeof(OrcBomber), typeof(OrcBrute), typeof(OrcCaptain), typeof(OrcishLord), typeof(OrcishMage), typeof(PackHorse),
typeof(PackLlama), typeof(Panther), typeof(Pig), typeof(PlagueSpawn), typeof(PolarBear), typeof(Rabbit),
typeof(Ratman), typeof(RatmanArcher), typeof(RatmanMage), typeof(RedSolenInfiltratorQueen),
typeof(RedSolenInfiltratorWarrior), typeof(RedSolenQueen), typeof(RedSolenWarrior), typeof(RedSolenWorker),
typeof(RidableLlama), typeof(Ridgeback), typeof(Scorpion), typeof(SeaSerpent), typeof(SerpentineDragon),
typeof(Shade), typeof(ShadowIronElemental), typeof(ShadowWisp), typeof(ShadowWyrm), typeof(Sheep),
typeof(SilverSteed), typeof(SkeletalDragon), typeof(SkeletalMage), typeof(SkeletalMount), typeof(HellCat),
typeof(Snake), typeof(SnowLeopard), typeof(SpectralArmour), typeof(Spectre), typeof(StoneGargoyle),
typeof(StoneHarpy), typeof(SwampDragon), typeof(ScaledSwampDragon), typeof(SwampTentacle), typeof(TerathanAvenger),
typeof(TerathanDrone), typeof(TerathanMatriarch), typeof(TerathanWarrior), typeof(TimberWolf), typeof(Titan),
typeof(Troll), typeof(Unicorn), typeof(ValoriteElemental), typeof(VeriteElemental), typeof(CoMWarHorse),
typeof(MinaxWarHorse), typeof(SLWarHorse), typeof(TBWarHorse), typeof(WaterElemental), typeof(WhippingVine),
typeof(WhiteWolf), typeof(Wraith), typeof(Wyvern), typeof(KhaldunZealot), typeof(KhaldunSummoner),
typeof(SavageRidgeback), typeof(LichLord), typeof(SkeletalKnight), typeof(SummonedDaemon),
typeof(SummonedEarthElemental), typeof(SummonedWaterElemental), typeof(SummonedFireElemental), typeof(MeerWarrior),
typeof(MeerEternal), typeof(MeerMage), typeof(MeerCaptain), typeof(JukaLord), typeof(JukaMage),
typeof(JukaWarrior), typeof(AbysmalHorror), typeof(BoneDemon), typeof(Devourer), typeof(FleshGolem),
typeof(Gibberling), typeof(GoreFiend), typeof(Impaler), typeof(PatchworkSkeleton), typeof(Ravager),
typeof(ShadowKnight), typeof(SkitteringHopper), typeof(Treefellow), typeof(VampireBat), typeof(WailingBanshee),
typeof(WandererOfTheVoid), typeof(Cursed), typeof(GrimmochDrummel), typeof(LysanderGathenwale), typeof(MorgBergen),
typeof(ShadowFiend), typeof(SpectralArmour), typeof(TavaraSewel), typeof(ArcaneDaemon), typeof(Doppleganger),
typeof(EnslavedGargoyle), typeof(ExodusMinion), typeof(ExodusOverseer), typeof(GargoyleDestroyer),
typeof(GargoyleEnforcer), typeof(Moloch), typeof(BakeKitsune), typeof(DeathwatchBeetleHatchling), typeof(Kappa),
typeof(KazeKemono), typeof(DeathwatchBeetle), typeof(TsukiWolf), typeof(YomotsuElder), typeof(YomotsuPriest),
typeof(YomotsuWarrior), typeof(RevenantLion), typeof(Oni), typeof(Gaman), typeof(Crane), typeof(Beetle),
typeof(ColdDrake), typeof(Vasanord), typeof(Ballem), typeof(Betballem), typeof(Anlorlem), typeof(BloodWorm),
typeof(GreenGoblin), typeof(EnslavedGreenGoblin), typeof(GreenGoblinAlchemist), typeof(GreenGoblinScout),
typeof(Kepetch), typeof(ClanRC), typeof(EnslavedGoblinKeeper), typeof(EnslavedGoblinMage),
typeof(EnslavedGoblinScout), typeof(EnslavedGrayGoblin), typeof(GrayGoblin), typeof(GrayGoblinKeeper),
typeof(GrayGoblinMage), typeof(Gremlin), typeof(SkeletalDrake), typeof(Slith), typeof(StoneSlith),
typeof(ToxicSlith), typeof(WyvernRenowned), typeof(GrayGoblinMageRenowned), typeof(FireDaemon), typeof(AcidSlug)
})
};
}
}

View File

@@ -0,0 +1,195 @@
#region References
using System;
using Server.Items;
#endregion
namespace Server.Mobiles
{
public class ThiefAI : BaseAI
{
private Item m_toDisarm;
public ThiefAI(BaseCreature m)
: base(m)
{ }
public override bool DoActionWander()
{
m_Mobile.DebugSay("I have no combatant");
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionWander();
}
return true;
}
public override bool DoActionCombat()
{
var c = m_Mobile.Combatant as Mobile;
if (c == null || c.Deleted || c.Map != m_Mobile.Map)
{
m_Mobile.DebugSay("My combatant is gone, so my guard is up");
Action = ActionType.Guard;
return true;
}
if (WalkMobileRange(c, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
{
if (!DirectionLocked)
m_Mobile.Direction = m_Mobile.GetDirectionTo(c);
if (m_toDisarm == null)
{
m_toDisarm = c.FindItemOnLayer(Layer.OneHanded);
}
if (m_toDisarm == null)
{
m_toDisarm = c.FindItemOnLayer(Layer.TwoHanded);
}
if (m_toDisarm != null && m_toDisarm.IsChildOf(m_Mobile.Backpack))
{
m_toDisarm = c.FindItemOnLayer(Layer.OneHanded);
if (m_toDisarm == null)
{
m_toDisarm = c.FindItemOnLayer(Layer.TwoHanded);
}
}
if (!Core.AOS && !m_Mobile.DisarmReady && m_Mobile.Skills[SkillName.Wrestling].Value >= 80.0 &&
m_Mobile.Skills[SkillName.ArmsLore].Value >= 80.0 && m_toDisarm != null)
{
EventSink.InvokeDisarmRequest(new DisarmRequestEventArgs(m_Mobile));
}
if (m_toDisarm != null && m_toDisarm.IsChildOf(c.Backpack) && m_Mobile.NextSkillTime <= Core.TickCount &&
(m_toDisarm.LootType != LootType.Blessed && m_toDisarm.LootType != LootType.Newbied))
{
m_Mobile.DebugSay("Trying to steal from combatant.");
m_Mobile.UseSkill(SkillName.Stealing);
if (m_Mobile.Target != null)
{
m_Mobile.Target.Invoke(m_Mobile, m_toDisarm);
}
}
else if (m_toDisarm == null && m_Mobile.NextSkillTime <= Core.TickCount)
{
var cpack = c.Backpack;
if (cpack != null)
{
var steala = cpack.FindItemByType(typeof(Bandage));
if (steala != null)
{
m_Mobile.DebugSay("Trying to steal from combatant.");
m_Mobile.UseSkill(SkillName.Stealing);
if (m_Mobile.Target != null)
{
m_Mobile.Target.Invoke(m_Mobile, steala);
}
}
var stealb = cpack.FindItemByType(typeof(Nightshade));
if (stealb != null)
{
m_Mobile.DebugSay("Trying to steal from combatant.");
m_Mobile.UseSkill(SkillName.Stealing);
if (m_Mobile.Target != null)
{
m_Mobile.Target.Invoke(m_Mobile, stealb);
}
}
var stealc = cpack.FindItemByType(typeof(BlackPearl));
if (stealc != null)
{
m_Mobile.DebugSay("Trying to steal from combatant.");
m_Mobile.UseSkill(SkillName.Stealing);
if (m_Mobile.Target != null)
{
m_Mobile.Target.Invoke(m_Mobile, stealc);
}
}
var steald = cpack.FindItemByType(typeof(MandrakeRoot));
if (steald != null)
{
m_Mobile.DebugSay("Trying to steal from combatant.");
m_Mobile.UseSkill(SkillName.Stealing);
if (m_Mobile.Target != null)
{
m_Mobile.Target.Invoke(m_Mobile, steald);
}
}
else if (steala == null && stealb == null && stealc == null && steald == null)
{
m_Mobile.DebugSay("I am going to flee from {0}", c.Name);
Action = ActionType.Flee;
}
}
}
}
else
{
m_Mobile.DebugSay("I should be closer to {0}", c.Name);
}
if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee)
{
if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100)
{
// We are low on health, should we flee?
if (Utility.Random(100) <= Math.Max(10, 10 + c.Hits - m_Mobile.Hits))
{
m_Mobile.DebugSay("I am going to flee from {0}", c.Name);
Action = ActionType.Flee;
}
}
}
return true;
}
public override bool DoActionGuard()
{
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name);
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
}
else
{
base.DoActionGuard();
}
return true;
}
}
}

View File

@@ -0,0 +1,158 @@
namespace Server.Mobiles
{
public class VendorAI : BaseAI
{
public VendorAI(BaseCreature m)
: base(m)
{ }
public override bool DoActionWander()
{
m_Mobile.DebugSay("I'm fine");
if (m_Mobile.Combatant != null)
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("{0} is attacking me", m_Mobile.Combatant.Name);
if (m_Mobile.CanCallGuards)
m_Mobile.Say(Utility.RandomList(1005305, 501603));
Action = ActionType.Flee;
}
else
{
if (m_Mobile.FocusMob != null)
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("{0} has talked to me", m_Mobile.FocusMob.Name);
Action = ActionType.Interact;
}
else
{
m_Mobile.Warmode = false;
base.DoActionWander();
}
}
return true;
}
public override bool DoActionInteract()
{
var customer = m_Mobile.FocusMob as Mobile;
if (m_Mobile.Combatant != null)
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("{0} is attacking me", m_Mobile.Combatant.Name);
if (m_Mobile.CanCallGuards)
m_Mobile.Say(Utility.RandomList(1005305, 501603));
Action = ActionType.Flee;
return true;
}
if (customer == null || customer.Deleted || customer.Map != m_Mobile.Map)
{
m_Mobile.DebugSay("My customer have disapeared");
m_Mobile.FocusMob = null;
Action = ActionType.Wander;
}
else
{
if (customer.InRange(m_Mobile, m_Mobile.RangeFight))
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("I am with {0}", customer.Name);
if (!DirectionLocked)
m_Mobile.Direction = m_Mobile.GetDirectionTo(customer);
}
else
{
if (m_Mobile.Debug)
m_Mobile.DebugSay("{0} is gone", customer.Name);
m_Mobile.FocusMob = null;
Action = ActionType.Wander;
}
}
return true;
}
public override bool DoActionGuard()
{
m_Mobile.FocusMob = m_Mobile.Combatant as Mobile;
return base.DoActionGuard();
}
public override bool HandlesOnSpeech(Mobile from)
{
if (from.InRange(m_Mobile, 4))
return true;
return base.HandlesOnSpeech(from);
}
// Temporary
public override void OnSpeech(SpeechEventArgs e)
{
base.OnSpeech(e);
var from = e.Mobile;
if (m_Mobile is BaseVendor && from.InRange(m_Mobile, Core.AOS ? 1 : 4) && !e.Handled)
{
if (e.HasKeyword(0x14D)) // *vendor sell*
{
e.Handled = true;
((BaseVendor)m_Mobile).VendorSell(from);
m_Mobile.FocusMob = from;
}
else if (e.HasKeyword(0x3C)) // *vendor buy*
{
e.Handled = true;
((BaseVendor)m_Mobile).VendorBuy(from);
m_Mobile.FocusMob = from;
}
else if (WasNamed(e.Speech))
{
if (e.HasKeyword(0x177)) // *sell*
{
e.Handled = true;
((BaseVendor)m_Mobile).VendorSell(from);
}
else if (e.HasKeyword(0x171)) // *buy*
{
e.Handled = true;
((BaseVendor)m_Mobile).VendorBuy(from);
}
m_Mobile.FocusMob = from;
}
}
}
public override double TransformMoveDelay(double delay)
{
if (m_Mobile is BaseVendor)
{
return ((BaseVendor)m_Mobile).GetMoveDelay;
}
return base.TransformMoveDelay(delay);
}
}
}

View File

@@ -0,0 +1,426 @@
using System;
using Server.Engines.CannedEvil;
using Server.Items;
using System.Collections.Generic;
using System.Linq;
using Server.Network;
namespace Server.Mobiles
{
[CorpseName("an abyssal infernal corpse")]
public class AbyssalInfernal : BaseChampion
{
private static Dictionary<Mobile, Point3D> m_Table = new Dictionary<Mobile, Point3D>();
private DateTime m_NextAbility;
[Constructable]
public AbyssalInfernal()
: base(AIType.AI_Mage)
{
Body = 713;
Name = "Abyssal Infernal";
SetStr(1200, 1300);
SetDex(100, 125);
SetInt(600, 700);
SetHits(30000);
SetStam(203, 650);
SetDamage(11, 18);
SetDamageType(ResistanceType.Physical, 60);
SetDamageType(ResistanceType.Fire, 20);
SetDamageType(ResistanceType.Energy, 20);
SetResistance(ResistanceType.Physical, 50, 60);
SetResistance(ResistanceType.Fire, 60, 70);
SetResistance(ResistanceType.Cold, 50, 60);
SetResistance(ResistanceType.Poison, 30, 40);
SetResistance(ResistanceType.Energy, 70, 80);
SetSkill(SkillName.Anatomy, 110.0, 120.0);
SetSkill(SkillName.Magery, 130.0, 140.0);
SetSkill(SkillName.EvalInt, 120.0, 140.0);
SetSkill(SkillName.MagicResist, 120);
SetSkill(SkillName.Tactics, 120.0);
SetSkill(SkillName.Wrestling, 110.0, 120.0);
SetSkill(SkillName.Meditation, 100.0);
Fame = 28000;
Karma = -28000;
VirtualArmor = 40;
}
public AbyssalInfernal(Serial serial)
: base(serial)
{
}
public override ChampionSkullType SkullType { get { return ChampionSkullType.None; } }
public override Type[] UniqueList { get { return new Type[] { typeof(TongueOfTheBeast), typeof(DeathsHead), typeof(WallOfHungryMouths), typeof(AbyssalBlade) }; } }
public override Type[] SharedList { get { return new Type[] { typeof(RoyalGuardInvestigatorsCloak), typeof(DetectiveBoots), typeof(JadeArmband) }; } }
public override Type[] DecorativeList { get { return new Type[] { typeof(MagicalDoor) }; } }
public override MonsterStatuetteType[] StatueTypes { get { return new MonsterStatuetteType[] { MonsterStatuetteType.AbyssalInfernal, MonsterStatuetteType.ArchDemon }; } }
public override Poison PoisonImmune { get { return Poison.Lethal; } }
public override ScaleType ScaleType { get { return ScaleType.All; } }
public override int Scales { get { return 20; } }
public override int GetAttackSound() { return 0x5D4; }
public override int GetDeathSound() { return 0x5D5; }
public override int GetHurtSound() { return 0x5D6; }
public override int GetIdleSound() { return 0x5D7; }
public override void GenerateLoot()
{
AddLoot(LootPack.SuperBoss, 4);
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
if (Utility.RandomBool())
{
switch (Utility.Random(2))
{
case 0:
c.DropItem(new HornAbyssalInferno());
break;
case 1:
c.DropItem(new NetherCycloneScroll());
break;
}
}
}
public override void OnThink()
{
base.OnThink();
if (Combatant == null)
return;
if (m_NextAbility < DateTime.UtcNow)
{
switch (Utility.Random(3))
{
case 0: { DoCondemn(); break; }
case 1: { DoSummon(); break; }
case 2: { DoNuke(); break; }
}
m_NextAbility = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(35, 45));
}
}
private Mobile GetRandomTarget(int range, bool playersOnly)
{
List<Mobile> list = GetTargets(range, playersOnly);
Mobile m = null;
if (list != null && list.Count > 0)
{
m = list[Utility.Random(list.Count)];
ColUtility.Free(list);
}
return m;
}
private List<Mobile> GetTargets(int range, bool playersOnly)
{
List<Mobile> targets = new List<Mobile>();
IPooledEnumerable eable = GetMobilesInRange(range);
foreach (Mobile m in eable)
{
if (m == this || !CanBeHarmful(m))
continue;
if (!playersOnly && m is BaseCreature && (((BaseCreature)m).Controlled || ((BaseCreature)m).Summoned || ((BaseCreature)m).Team != Team))
targets.Add(m);
else if (m.Player)
targets.Add(m);
}
eable.Free();
return targets;
}
#region Condemn
private static Point3D[] _Locs = new Point3D[]
{
new Point3D(6949, 701, 32),
new Point3D(6941, 761, 32),
new Point3D(7015, 688, 32),
new Point3D(7043, 751, 32),
new Point3D(6999, 798, 32),
};
public void DoCondemn()
{
Map map = Map;
if (map != null)
{
Mobile toCondemn = GetRandomTarget(8, true);
if (toCondemn != null && !m_Table.ContainsKey(toCondemn))
{
m_Table[toCondemn] = toCondemn.Location;
var loc = _Locs[Utility.Random(_Locs.Length)];
toCondemn.MoveToWorld(loc, map);
toCondemn.FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
toCondemn.PlaySound(0x1FE);
toCondemn.Frozen = true;
int seconds = 15;
BuffInfo.AddBuff(toCondemn, new BuffInfo(BuffIcon.TrueFear, 1153791, 1153827, TimeSpan.FromSeconds(seconds), toCondemn));
Timer.DelayCall(TimeSpan.FromSeconds(seconds), () =>
{
toCondemn.Frozen = false;
toCondemn.SendLocalizedMessage(1005603); // You can move again!
loc = m_Table.ToList().Find(x => x.Key == toCondemn).Value;
toCondemn.MoveToWorld(loc, map);
m_Table.Remove(toCondemn);
});
}
}
}
#endregion
public void DoNuke()
{
if (!Alive || Map == null)
return;
Say(1112362); // You will burn to a pile of ash!
int range = 8;
Effects.PlaySound(Location, Map, 0x349);
//Flame Columns
for (int i = 0; i < 2; i++)
{
Misc.Geometry.Circle2D(Location, Map, i, (pnt, map) =>
{
Effects.SendLocationParticles(EffectItem.Create(pnt, map, EffectItem.DefaultDuration), 0x3709, 10, 30, 5052);
});
}
//Flash then boom
Timer.DelayCall(TimeSpan.FromSeconds(1), () =>
{
if (Alive && Map != null)
{
Effects.PlaySound(Location, Map, 0x44B);
Packet flash = ScreenLightFlash.Instance;
IPooledEnumerable e = Map.GetClientsInRange(Location, (range * 4) + 5);
foreach (NetState ns in e)
{
if (ns.Mobile != null)
ns.Mobile.Send(flash);
}
e.Free();
for (int i = 0; i < range; i++)
{
Misc.Geometry.Circle2D(Location, Map, i, (pnt, map) =>
{
Effects.SendLocationEffect(pnt, map, 14000, 14, 10, Utility.RandomMinMax(2497, 2499), 2);
});
}
}
});
IPooledEnumerable eable = GetMobilesInRange(range);
foreach (Mobile m in eable)
{
if ((m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile)) && CanBeHarmful(m))
Timer.DelayCall(TimeSpan.FromSeconds(1.75), new TimerStateCallback(DoDamage_Callback), m);
}
eable.Free();
}
private void DoDamage_Callback(object o)
{
Mobile m = o as Mobile;
if (m != null && Map != null)
{
IMount mount = m.Mount;
if (mount != null)
{
if (m is PlayerMobile)
((PlayerMobile)m).SetMountBlock(BlockMountType.Dazed, TimeSpan.FromSeconds(10), true);
else
mount.Rider = null;
}
else if (m.Flying)
{
((PlayerMobile)m).SetMountBlock(BlockMountType.Dazed, TimeSpan.FromSeconds(10), true);
}
DoHarmful(m);
AOS.Damage(m, this, Utility.RandomMinMax(90, 110), 0, 0, 0, 0, 100);
m.Frozen = true;
Timer.DelayCall(TimeSpan.FromSeconds(3), () =>
{
m.Frozen = false;
m.SendLocalizedMessage(1005603); // You can move again!
});
}
}
#region Spawn
public List<BaseCreature> SummonedHelpers { get; set; }
private static Type[] SummonTypes = new Type[]
{
typeof(HellHound), typeof(Phoenix),
typeof(FireSteed), typeof(FireElemental),
typeof(LavaElemental), typeof(FireGargoyle),
typeof(Efreet), typeof(Gargoyle),
typeof(Nightmare), typeof(HellCat)
};
public int TotalSummons()
{
if (SummonedHelpers == null || SummonedHelpers.Count == 0)
return 0;
return SummonedHelpers.Where(bc => bc != null && bc.Alive).Count();
}
public virtual void DoSummon()
{
if (Map == null || TotalSummons() > 0)
return;
Type type = SummonTypes[Utility.Random(SummonTypes.Length)];
for (int i = 0; i < 3; i++)
{
if (Combatant == null)
return;
Point3D p = Combatant.Location;
for (int j = 0; j < 10; j++)
{
int x = Utility.RandomMinMax(p.X - 3, p.X + 3);
int y = Utility.RandomMinMax(p.Y - 3, p.Y + 3);
int z = Map.GetAverageZ(x, y);
if (Map.CanSpawnMobile(x, y, z))
{
p = new Point3D(x, y, z);
break;
}
}
BaseCreature spawn = Activator.CreateInstance(type) as BaseCreature;
if (spawn != null)
{
spawn.MoveToWorld(p, Map);
spawn.Team = Team;
spawn.SummonMaster = this;
Timer.DelayCall(TimeSpan.FromSeconds(1), (o) =>
{
BaseCreature s = o as BaseCreature;
if (s != null && s.Combatant != null)
{
if (!(s.Combatant is PlayerMobile) || !((PlayerMobile)s.Combatant).HonorActive)
s.Combatant = Combatant;
}
}, spawn);
AddHelper(spawn);
}
}
}
protected virtual void AddHelper(BaseCreature bc)
{
if (SummonedHelpers == null)
SummonedHelpers = new List<BaseCreature>();
if (!SummonedHelpers.Contains(bc))
SummonedHelpers.Add(bc);
}
public override void Delete()
{
base.Delete();
if (SummonedHelpers != null)
{
ColUtility.Free(SummonedHelpers);
}
}
#endregion
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
writer.Write(SummonedHelpers == null ? 0 : SummonedHelpers.Count);
if (SummonedHelpers != null)
SummonedHelpers.ForEach(m => writer.Write(m));
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
int count = reader.ReadInt();
if (count > 0)
{
for (int i = 0; i < count; i++)
{
BaseCreature summon = reader.ReadMobile() as BaseCreature;
if (summon != null)
{
if (SummonedHelpers == null)
SummonedHelpers = new List<BaseCreature>();
SummonedHelpers.Add(summon);
}
}
}
m_NextAbility = DateTime.UtcNow;
}
}
}

View File

@@ -0,0 +1,360 @@
using System;
using Server.Engines.CannedEvil;
using Server.Items;
using Server.Spells.Fifth;
using Server.Spells.Seventh;
namespace Server.Mobiles
{
public class Barracoon : BaseChampion
{
[Constructable]
public Barracoon()
: base(AIType.AI_Melee)
{
Name = "Barracoon";
Title = "the piper";
Body = 0x190;
Hue = 0x83EC;
SetStr(283, 425);
SetDex(72, 150);
SetInt(505, 750);
SetHits(12000);
SetStam(102, 300);
SetMana(505, 750);
SetDamage(29, 38);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 65, 75);
SetResistance(ResistanceType.Fire, 70, 80);
SetResistance(ResistanceType.Cold, 65, 80);
SetResistance(ResistanceType.Poison, 70, 75);
SetResistance(ResistanceType.Energy, 70, 80);
SetSkill(SkillName.MagicResist, 100.0);
SetSkill(SkillName.Tactics, 118.3, 120.2);
SetSkill(SkillName.Wrestling, 118.4, 122.7);
Fame = 22500;
Karma = -22500;
VirtualArmor = 70;
AddItem(new FancyShirt(Utility.RandomGreenHue()));
AddItem(new LongPants(Utility.RandomYellowHue()));
AddItem(new JesterHat(Utility.RandomPinkHue()));
AddItem(new Cloak(Utility.RandomPinkHue()));
AddItem(new Sandals());
HairItemID = 0x203B; // Short Hair
HairHue = 0x94;
m_SpecialSlayerMechanics = true;
}
public Barracoon(Serial serial)
: base(serial)
{
}
public override ChampionSkullType SkullType
{
get
{
return ChampionSkullType.Greed;
}
}
public override Type[] UniqueList
{
get
{
return new Type[] { typeof(FangOfRactus) };
}
}
public override Type[] SharedList
{
get
{
return new Type[]
{
typeof(EmbroideredOakLeafCloak),
typeof(DjinnisRing),
typeof(DetectiveBoots),
typeof(GauntletsOfAnger)
};
}
}
public override Type[] DecorativeList
{
get
{
return new Type[] { typeof(SwampTile), typeof(MonsterStatuette) };
}
}
public override MonsterStatuetteType[] StatueTypes
{
get
{
return new MonsterStatuetteType[] { MonsterStatuetteType.Slime };
}
}
public override bool AlwaysMurderer
{
get
{
return true;
}
}
public override bool AutoDispel
{
get
{
return true;
}
}
public override double AutoDispelChance
{
get
{
return 1.0;
}
}
public override bool BardImmune
{
get
{
return !Core.SE;
}
}
public override bool AllureImmune
{
get
{
return true;
}
}
public override bool Unprovokable
{
get
{
return Core.SE;
}
}
public override bool Uncalmable
{
get
{
return Core.SE;
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Deadly;
}
}
public override bool ShowFameTitle
{
get
{
return false;
}
}
public override bool ClickTitle
{
get
{
return false;
}
}
public override bool ForceStayHome { get { return true; } }
public override void GenerateLoot()
{
AddLoot(LootPack.UltraRich, 3);
}
public void Polymorph(Mobile m)
{
if (!m.CanBeginAction(typeof(PolymorphSpell)) || !m.CanBeginAction(typeof(IncognitoSpell)) || m.IsBodyMod)
return;
IMount mount = m.Mount;
if (mount != null)
mount.Rider = null;
if (m.Flying)
m.ToggleFlying();
if (m.Mounted)
return;
if (m.BeginAction(typeof(PolymorphSpell)))
{
m.BodyMod = 42;
m.HueMod = 0;
if (m == this) {
m_SlayerVulnerabilities.Add("Vermin");
m_SlayerVulnerabilities.Add("Repond");
}
new ExpirePolymorphTimer(m).Start();
}
}
public void SpawnRatmen(Mobile target)
{
Map map = Map;
if (map == null)
return;
int rats = 0;
IPooledEnumerable eable = GetMobilesInRange(10);
foreach (Mobile m in eable)
{
if (m is Ratman || m is RatmanArcher || m is RatmanMage)
++rats;
}
eable.Free();
if (rats < 16)
{
PlaySound(0x3D);
int newRats = Utility.RandomMinMax(3, 6);
for (int i = 0; i < newRats; ++i)
{
BaseCreature rat;
switch ( Utility.Random(5) )
{
default:
case 0:
case 1:
rat = new Ratman();
break;
case 2:
case 3:
rat = new RatmanArcher();
break;
case 4:
rat = new RatmanMage();
break;
}
rat.Team = Team;
bool validLocation = false;
Point3D loc = Location;
for (int j = 0; !validLocation && j < 10; ++j)
{
int x = X + Utility.Random(3) - 1;
int y = Y + Utility.Random(3) - 1;
int z = map.GetAverageZ(x, y);
if (validLocation = map.CanFit(x, y, Z, 16, false, false))
loc = new Point3D(x, y, Z);
else if (validLocation = map.CanFit(x, y, z, 16, false, false))
loc = new Point3D(x, y, z);
}
rat.IsChampionSpawn = true;
rat.MoveToWorld(loc, map);
rat.Combatant = target;
}
}
}
public void DoSpecialAbility(Mobile target)
{
if (target == null || target.Deleted) //sanity
return;
if (target.Player && 0.6 >= Utility.RandomDouble()) // 60% chance to polymorph attacker into a ratman
Polymorph(target);
if (0.1 >= Utility.RandomDouble()) // 10% chance to more ratmen
SpawnRatmen(target);
if (0.05 >= Utility.RandomDouble() && !IsBodyMod) // 5% chance to polymorph into a ratman
Polymorph(this);
}
public override void OnGotMeleeAttack(Mobile attacker)
{
base.OnGotMeleeAttack(attacker);
DoSpecialAbility(attacker);
}
public override void OnGaveMeleeAttack(Mobile defender)
{
base.OnGaveMeleeAttack(defender);
DoSpecialAbility(defender);
}
public override void OnDamagedBySpell(Mobile from)
{
base.OnDamagedBySpell(from);
DoSpecialAbility(from);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
m_SlayerVulnerabilities.Clear();
}
private class ExpirePolymorphTimer : Timer
{
private Mobile m_Owner;
public ExpirePolymorphTimer(Mobile owner)
: base(TimeSpan.FromMinutes(3.0)) //3.0
{
m_Owner = owner;
Priority = TimerPriority.OneSecond;
}
protected override void OnTick()
{
if (!m_Owner.CanBeginAction(typeof(PolymorphSpell)))
{
m_Owner.BodyMod = 0;
m_Owner.HueMod = -1;
m_Owner.EndAction(typeof(PolymorphSpell));
if (m_Owner.SlayerVulnerabilities != null)
{
m_Owner.SlayerVulnerabilities.Remove("Vermin");
m_Owner.SlayerVulnerabilities.Remove("Repond");
}
}
}
}
}
}

View File

@@ -0,0 +1,302 @@
using System;
using System.Collections.Generic;
using Server.Engines.CannedEvil;
using Server.Items;
using Server.Services.Virtues;
namespace Server.Mobiles
{
public abstract class BaseChampion : BaseCreature
{
public BaseChampion(AIType aiType)
: this(aiType, FightMode.Closest)
{
}
public BaseChampion(AIType aiType, FightMode mode)
: base(aiType, mode, 18, 1, 0.1, 0.2)
{
}
public BaseChampion(Serial serial)
: base(serial)
{
}
public override bool CanBeParagon { get { return false; } }
public abstract ChampionSkullType SkullType { get; }
public abstract Type[] UniqueList { get; }
public abstract Type[] SharedList { get; }
public abstract Type[] DecorativeList { get; }
public abstract MonsterStatuetteType[] StatueTypes { get; }
public virtual bool NoGoodies
{
get
{
return false;
}
}
public virtual bool CanGivePowerscrolls { get { return true; } }
public static void GivePowerScrollTo(Mobile m, Item item, BaseChampion champ)
{
if (m == null) //sanity
return;
if (!Core.SE || m.Alive)
m.AddToBackpack(item);
else
{
if (m.Corpse != null && !m.Corpse.Deleted)
m.Corpse.DropItem(item);
else
m.AddToBackpack(item);
}
if (item is PowerScroll && m is PlayerMobile)
{
PlayerMobile pm = (PlayerMobile)m;
for (int j = 0; j < pm.JusticeProtectors.Count; ++j)
{
Mobile prot = pm.JusticeProtectors[j];
if (prot.Map != m.Map || prot.Murderer || prot.Criminal || !JusticeVirtue.CheckMapRegion(m, prot) || !prot.InRange(champ, 100))
continue;
int chance = 0;
switch( VirtueHelper.GetLevel(prot, VirtueName.Justice) )
{
case VirtueLevel.Seeker:
chance = 60;
break;
case VirtueLevel.Follower:
chance = 80;
break;
case VirtueLevel.Knight:
chance = 100;
break;
}
if (chance > Utility.Random(100))
{
PowerScroll powerScroll = CreateRandomPowerScroll();
prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice!
if (!Core.SE || prot.Alive)
prot.AddToBackpack(powerScroll);
else
{
if (prot.Corpse != null && !prot.Corpse.Deleted)
prot.Corpse.DropItem(powerScroll);
else
prot.AddToBackpack(powerScroll);
}
}
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public virtual Item GetArtifact()
{
double random = Utility.RandomDouble();
if (0.05 >= random)
return this.CreateArtifact(this.UniqueList);
else if (0.15 >= random)
return this.CreateArtifact(this.SharedList);
else if (0.30 >= random)
return this.CreateArtifact(this.DecorativeList);
return null;
}
public Item CreateArtifact(Type[] list)
{
if (list.Length == 0)
return null;
int random = Utility.Random(list.Length);
Type type = list[random];
Item artifact = Loot.Construct(type);
if (artifact is MonsterStatuette && this.StatueTypes.Length > 0)
{
((MonsterStatuette)artifact).Type = this.StatueTypes[Utility.Random(this.StatueTypes.Length)];
((MonsterStatuette)artifact).LootType = LootType.Regular;
}
return artifact;
}
public virtual void GivePowerScrolls()
{
if (this.Map != Map.Felucca)
return;
List<Mobile> toGive = new List<Mobile>();
List<DamageStore> rights = GetLootingRights();
for (int i = rights.Count - 1; i >= 0; --i)
{
DamageStore ds = rights[i];
if (ds.m_HasRight && InRange(ds.m_Mobile, 100) && ds.m_Mobile.Map == this.Map)
toGive.Add(ds.m_Mobile);
}
if (toGive.Count == 0)
return;
for (int i = 0; i < toGive.Count; i++)
{
Mobile m = toGive[i];
if (!(m is PlayerMobile))
continue;
bool gainedPath = false;
int pointsToGain = 800;
if (VirtueHelper.Award(m, VirtueName.Valor, pointsToGain, ref gainedPath))
{
if (gainedPath)
m.SendLocalizedMessage(1054032); // You have gained a path in Valor!
else
m.SendLocalizedMessage(1054030); // You have gained in Valor!
//No delay on Valor gains
}
}
// Randomize - PowerScrolls
for (int i = 0; i < toGive.Count; ++i)
{
int rand = Utility.Random(toGive.Count);
Mobile hold = toGive[i];
toGive[i] = toGive[rand];
toGive[rand] = hold;
}
for (int i = 0; i < ChampionSystem.PowerScrollAmount; ++i)
{
Mobile m = toGive[i % toGive.Count];
PowerScroll ps = CreateRandomPowerScroll();
m.SendLocalizedMessage(1049524); // You have received a scroll of power!
GivePowerScrollTo(m, ps, this);
}
if (Core.TOL)
{
// Randomize - Primers
for (int i = 0; i < toGive.Count; ++i)
{
int rand = Utility.Random(toGive.Count);
Mobile hold = toGive[i];
toGive[i] = toGive[rand];
toGive[rand] = hold;
}
for (int i = 0; i < ChampionSystem.PowerScrollAmount; ++i)
{
Mobile m = toGive[i % toGive.Count];
SkillMasteryPrimer p = CreateRandomPrimer();
m.SendLocalizedMessage(1156209); // You have received a mastery primer!
GivePowerScrollTo(m, p, this);
}
}
ColUtility.Free(toGive);
}
public virtual void OnChampPopped(ChampionSpawn spawn)
{
}
public override bool OnBeforeDeath()
{
if (CanGivePowerscrolls && !NoKillAwards)
{
this.GivePowerScrolls();
if (this.NoGoodies)
return base.OnBeforeDeath();
GoldShower.DoForChamp(Location, Map);
}
return base.OnBeforeDeath();
}
public override void OnDeath(Container c)
{
if (this.Map == Map.Felucca)
{
//TODO: Confirm SE change or AoS one too?
List<DamageStore> rights = GetLootingRights();
List<Mobile> toGive = new List<Mobile>();
for (int i = rights.Count - 1; i >= 0; --i)
{
DamageStore ds = rights[i];
if (ds.m_HasRight)
toGive.Add(ds.m_Mobile);
}
if (SkullType != ChampionSkullType.None)
{
if (toGive.Count > 0)
toGive[Utility.Random(toGive.Count)].AddToBackpack(new ChampionSkull(this.SkullType));
else
c.DropItem(new ChampionSkull(this.SkullType));
}
if(Core.SA)
RefinementComponent.Roll(c, 3, 0.10);
}
base.OnDeath(c);
}
private static PowerScroll CreateRandomPowerScroll()
{
int level;
double random = Utility.RandomDouble();
if (0.05 >= random)
level = 20;
else if (0.4 >= random)
level = 15;
else
level = 10;
return PowerScroll.CreateRandomNoCraft(level, level);
}
private static SkillMasteryPrimer CreateRandomPrimer()
{
return SkillMasteryPrimer.GetRandom();
}
}
}

View File

@@ -0,0 +1,182 @@
using System;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName("a chief paroxysmus corpse")]
public class ChiefParoxysmus : BasePeerless
{
[Constructable]
public ChiefParoxysmus()
: base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Name = "a chief paroxysmus";
Body = 0x100;
SetStr(1232, 1400);
SetDex(76, 82);
SetInt(76, 85);
SetHits(50000);
SetDamage(27, 31);
SetDamageType(ResistanceType.Physical, 80);
SetDamageType(ResistanceType.Poison, 20);
SetResistance(ResistanceType.Physical, 75, 85);
SetResistance(ResistanceType.Fire, 40, 50);
SetResistance(ResistanceType.Cold, 50, 60);
SetResistance(ResistanceType.Poison, 55, 65);
SetResistance(ResistanceType.Energy, 50, 60);
SetSkill(SkillName.Wrestling, 120.0);
SetSkill(SkillName.Tactics, 120.0);
SetSkill(SkillName.MagicResist, 120.0);
SetSkill(SkillName.Anatomy, 120.0);
SetSkill(SkillName.Poisoning, 120.0);
PackResources(8);
PackTalismans(5);
Timer.DelayCall(TimeSpan.FromSeconds(1), new TimerCallback(SpawnBulbous)); //BulbousPutrification
Fame = 25000;
Karma = -25000;
SetAreaEffect(AreaEffect.PoisonBreath);
}
public ChiefParoxysmus(Serial serial)
: base(serial)
{
}
public override bool GivesMLMinorArtifact
{
get
{
return true;
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Lethal;
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.AosSuperBoss, 8);
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
c.DropItem(new LardOfParoxysmus());
switch ( Utility.Random(3) )
{
case 0:
c.DropItem(new ParoxysmusDinner());
break;
case 1:
c.DropItem(new ParoxysmusCorrodedStein());
break;
case 2:
c.DropItem(new StringOfPartsOfParoxysmusVictims());
break;
}
if (Utility.RandomDouble() < 0.6)
c.DropItem(new ParrotItem());
if (Utility.RandomBool())
c.DropItem(new SweatOfParoxysmus());
if (Utility.RandomDouble() < 0.05)
c.DropItem(new ParoxysmusSwampDragonStatuette());
if (Utility.RandomDouble() < 0.05)
c.DropItem(new ScepterOfTheChief());
}
public override int GetDeathSound()
{
return 0x56F;
}
public override int GetAttackSound()
{
return 0x570;
}
public override int GetIdleSound()
{
return 0x571;
}
public override int GetAngerSound()
{
return 0x572;
}
public override int GetHurtSound()
{
return 0x573;
}
public override void OnDamage(int amount, Mobile from, bool willKill)
{
base.OnDamage(amount, from, willKill);
// eats pet or summons
if (from is BaseCreature)
{
BaseCreature creature = (BaseCreature)from;
if (creature.Controlled || creature.Summoned)
{
Heal(creature.Hits);
creature.Kill();
Effects.PlaySound(Location, Map, 0x574);
}
}
// teleports player near
if (from is PlayerMobile && !InRange(from.Location, 1))
{
Combatant = from;
from.MoveToWorld(GetSpawnPosition(1), Map);
from.FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
from.PlaySound(0x1FE);
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public virtual void SpawnBulbous()
{
for (int i = 0; i < 3; i++)
{
SpawnHelper(new BulbousPutrification(), GetSpawnPosition(4));
}
}
}
}

View File

@@ -0,0 +1,364 @@
using System;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName("a crimson dragon corpse")]
public class CrimsonDragon : BasePeerless
{
public override bool GiveMLSpecial { get { return false; } }
private DateTime m_NextTerror;
[Constructable]
public CrimsonDragon()
: base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Name = "a crimson dragon";
Body = 197;
BaseSoundID = 362;
SetStr(2034, 2140);
SetDex(215, 256);
SetInt(1025, 1116);
SetHits(25000);
SetDamage(8, 10);
SetDamageType(ResistanceType.Physical, 50);
SetDamageType(ResistanceType.Fire, 50);
SetResistance(ResistanceType.Physical, 80, 85);
SetResistance(ResistanceType.Fire, 100);
SetResistance(ResistanceType.Cold, 50, 60);
SetResistance(ResistanceType.Poison, 80, 85);
SetResistance(ResistanceType.Energy, 80, 85);
SetSkill(SkillName.EvalInt, 110.2, 125.3);
SetSkill(SkillName.Magery, 110.9, 125.5);
SetSkill(SkillName.MagicResist, 116.3, 125.0);
SetSkill(SkillName.Tactics, 111.7, 126.3);
SetSkill(SkillName.Wrestling, 120.5, 128.0);
SetSkill(SkillName.Meditation, 119.4, 130.0);
SetSkill(SkillName.Anatomy, 118.7, 125.0);
SetSkill(SkillName.DetectHidden, 120.0);
// ingredients
PackResources(8);
Fame = 20000;
Karma = -20000;
VirtualArmor = 70;
SetSpecialAbility(SpecialAbility.DragonBreath);
}
public CrimsonDragon(Serial serial)
: base(serial)
{
}
public override bool AlwaysMurderer
{
get
{
return true;
}
}
public override bool Unprovokable
{
get
{
return true;
}
}
public override bool BardImmune
{
get
{
return true;
}
}
public override bool ReacquireOnMovement
{
get
{
return true;
}
}
public override bool AutoDispel
{
get
{
return true;
}
}
public override bool Uncalmable
{
get
{
return true;
}
}
public override int Meat
{
get
{
return 19;
}
}
public override int Hides
{
get
{
return 40;
}
}
public override HideType HideType
{
get
{
return HideType.Barbed;
}
}
public override int Scales
{
get
{
return 12;
}
}
public override ScaleType ScaleType
{
get
{
return (ScaleType)Utility.Random(4);
}
}
public override FoodType FavoriteFood
{
get
{
return FoodType.Meat;
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Lethal;
}
}
public override Poison HitPoison
{
get
{
return Utility.RandomBool() ? Poison.Deadly : Poison.Lethal;
}
}
public override int TreasureMapLevel
{
get
{
return 5;
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.AosSuperBoss, 8);
AddLoot(LootPack.Gems, 12);
}
public override int GetIdleSound()
{
return 0x2D3;
}
public override int GetHurtSound()
{
return 0x2D1;
}
public override void OnDamagedBySpell(Mobile caster)
{
if (Map != null && caster != this && 0.50 > Utility.RandomDouble())
{
Map = caster.Map;
Location = caster.Location;
Combatant = caster;
Effects.PlaySound(Location, Map, 0x1FE);
}
base.OnDamagedBySpell(caster);
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
base.OnMovement(m, oldLocation);
if (m_NextTerror < DateTime.UtcNow && m != null && InRange(m.Location, 3) && m.IsPlayer())
{
m.Frozen = true;
m.SendLocalizedMessage(1080342, Name, 33); // Terror slices into your very being, destroying any chance of resisting ~1_name~ you might have had
Timer.DelayCall(TimeSpan.FromSeconds(5), new TimerStateCallback(Terrorize), m);
}
}
public override void OnGotMeleeAttack(Mobile attacker)
{
if (Map != null && attacker != this && 0.1 > Utility.RandomDouble())
{
if (attacker is BaseCreature)
{
BaseCreature pet = (BaseCreature)attacker;
if (pet.ControlMaster != null && (attacker is Dragon || attacker is GreaterDragon || attacker is SkeletalDragon || attacker is WhiteWyrm || attacker is Drake))
{
Combatant = null;
pet.Combatant = null;
Combatant = null;
pet.ControlMaster = null;
pet.Controlled = false;
attacker.Emote(String.Format("* {0} decided to go wild *", attacker.Name));
}
if (pet.ControlMaster != null && 0.1 > Utility.RandomDouble())
{
Combatant = null;
pet.Combatant = pet.ControlMaster;
Combatant = null;
attacker.Emote(String.Format("* {0} is being angered *", attacker.Name));
}
}
}
base.OnGotMeleeAttack(attacker);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override bool OnBeforeDeath()
{
Hue = 16385;
if (!NoKillAwards)
{
Map map = Map;
if (map != null)
{
for (int x = -7; x <= 7; ++x)
{
for (int y = -7; y <= 3; ++y)
{
double dist = Math.Sqrt(x * x + y * y);
if (dist <= 12)
new GoodiesTimer(map, X + x, Y + y).Start();
}
}
}
}
return base.OnBeforeDeath();
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
if (Utility.RandomDouble() < 0.6)
c.DropItem(new ParrotItem());
if (Utility.RandomDouble() < 0.025)
c.DropItem(new CrimsonCincture());
}
private void Terrorize(object o)
{
if (o is Mobile)
{
Mobile m = (Mobile)o;
m.Frozen = false;
m.SendLocalizedMessage(1005603); // You can move again!
m_NextTerror = DateTime.UtcNow + TimeSpan.FromMinutes(5);
}
}
private class GoodiesTimer : Timer
{
private readonly Map m_Map;
private readonly int m_X;
private readonly int m_Y;
public GoodiesTimer(Map map, int x, int y)
: base(TimeSpan.FromSeconds(Utility.RandomDouble() * 10.0))
{
m_Map = map;
m_X = x;
m_Y = y;
}
protected override void OnTick()
{
int z = m_Map.GetAverageZ(m_X, m_Y);
bool canFit = m_Map.CanFit(m_X, m_Y, z, 6, false, false);
for (int i = -3; !canFit && i <= 3; ++i)
{
canFit = m_Map.CanFit(m_X, m_Y, z + i, 6, false, false);
if (canFit)
z += i;
}
if (!canFit)
return;
Gold g = new Gold(300, 500);
g.MoveToWorld(new Point3D(m_X, m_Y, z), m_Map);
if (0.5 >= Utility.RandomDouble())
{
switch (Utility.Random(3))
{
case 0: // Fire column
{
Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), 0x3709, 10, 30, 5052);
Effects.PlaySound(g, g.Map, 0x208);
break;
}
case 1: // Explosion
{
Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), 0x36BD, 20, 10, 5044);
Effects.PlaySound(g, g.Map, 0x307);
break;
}
case 2: // Ball of fire
{
Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), 0x36FE, 10, 10, 5052);
break;
}
}
}
}
}
}
}

View File

@@ -0,0 +1,490 @@
using Server;
using System;
using Server.Items;
using Server.Mobiles;
using System.Collections.Generic;
namespace Server.Engines.Despise
{
public class DespiseBoss : BaseCreature
{
public static readonly int ArtifactChance = 5;
public virtual BaseCreature SummonWisp { get { return null; } }
public virtual double WispScalar { get { return 0.33; } }
private BaseCreature m_Wisp;
private Timer m_SummonTimer;
[CommandProperty(AccessLevel.GameMaster)]
public BaseCreature Wisp { get { return m_Wisp; } }
public DespiseBoss(AIType ai, FightMode fightmode) : base(ai, fightmode, 10, 1, .1, .2)
{
m_SummonTimer = Timer.DelayCall(TimeSpan.FromSeconds(5), new TimerCallback(SummonWisp_Callback));
FollowersMax = 100;
}
public void SetNonMovable(Item item)
{
item.Movable = false;
AddItem(item);
}
public override int Damage(int amount, Mobile from, bool informMount, bool checkDisrupt)
{
if (from is DespiseCreature)
return base.Damage(amount, from, informMount, checkDisrupt);
return 0;
}
public override void OnKilledBy( Mobile mob )
{
if(mob is PlayerMobile)
{
int chance = ArtifactChance + (int)Math.Min(10, ((PlayerMobile)mob).Luck / 180);
if (chance >= Utility.Random(100))
{
Type t = m_Artifacts[Utility.Random(m_Artifacts.Length)];
if (t != null)
{
Item arty = Loot.Construct(t);
if (arty != null)
{
Container pack = mob.Backpack;
if (pack == null || !pack.TryDropItem(mob, arty, false))
{
mob.BankBox.DropItem(arty);
mob.SendMessage("An artifact has been placed in your bankbox!");
}
else
mob.SendLocalizedMessage(1153440); // An artifact has been placed in your backpack!
}
}
}
}
}
public override void AlterMeleeDamageTo(Mobile to, ref int damage)
{
base.AlterMeleeDamageTo(to, ref damage);
if(m_Wisp != null && !m_Wisp.Deleted && m_Wisp.Alive)
damage += (int)((double)damage * WispScalar);
}
public override void AlterMeleeDamageFrom(Mobile from, ref int damage)
{
base.AlterMeleeDamageFrom(from, ref damage);
if(m_Wisp != null && !m_Wisp.Deleted && m_Wisp.Alive)
damage -= (int)((double)damage * WispScalar);
}
public override void AlterSpellDamageTo(Mobile to, ref int damage)
{
base.AlterSpellDamageTo(to, ref damage);
if (m_Wisp != null && !m_Wisp.Deleted && m_Wisp.Alive)
damage += (int)((double)damage * WispScalar);
}
public override void AlterSpellDamageFrom(Mobile from, ref int damage)
{
base.AlterSpellDamageFrom(from, ref damage);
if (m_Wisp != null && !m_Wisp.Deleted && m_Wisp.Alive)
damage -= (int)((double)damage * WispScalar);
}
public override void OnThink()
{
base.OnThink();
if(m_SummonTimer == null && (m_Wisp == null || !m_Wisp.Alive || m_Wisp.Deleted))
{
m_SummonTimer = Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(40, 60)), new TimerCallback(SummonWisp_Callback));
}
}
public void SummonWisp_Callback()
{
m_Wisp = SummonWisp;
BaseCreature.Summon(m_Wisp, true, this, this.Location, 0, TimeSpan.FromMinutes(90));
m_SummonTimer = null;
}
public override void Delete()
{
base.Delete();
if (m_Wisp != null && m_Wisp.Alive)
m_Wisp.Kill();
}
public static Type[] Artifacts { get { return m_Artifacts; } }
private static Type[] m_Artifacts = new Type[]
{
typeof(CompassionsEye),
typeof(UnicornManeWovenSandals),
typeof(UnicornManeWovenTalons),
typeof(DespicableQuiver),
typeof(UnforgivenVeil),
typeof(HailstormHuman),
typeof(HailstormGargoyle),
};
public DespiseBoss(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
writer.Write(m_Wisp);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
m_Wisp = reader.ReadMobile() as BaseCreature;
}
}
public class AdrianTheGloriousLord : DespiseBoss
{
[Constructable]
public AdrianTheGloriousLord() : base(AIType.AI_Mage, FightMode.Closest)
{
Name = "Adrian";
Title = "the Glorious Lord";
Race = Race.Human;
Body = 0x190;
Female = false;
Hue = Race.RandomSkinHue();
HairItemID = 8252;
HairHue = 153;
SetStr( 900, 1200 );
SetDex( 500, 600 );
SetInt( 500, 600 );
SetHits( 60000 );
SetStam( 415 );
SetMana( 22000 );
SetDamage( 18, 28 );
SetDamageType( ResistanceType.Physical, 100 );
SetResistance( ResistanceType.Physical, 40, 60 );
SetResistance( ResistanceType.Fire, 40, 60 );
SetResistance( ResistanceType.Cold, 40, 60 );
SetResistance( ResistanceType.Poison, 40, 60 );
SetResistance( ResistanceType.Energy, 40, 60 );
SetSkill( SkillName.MagicResist, 120 );
SetSkill( SkillName.Tactics, 120 );
SetSkill( SkillName.Wrestling, 120 );
SetSkill( SkillName.Anatomy, 120 );
SetSkill( SkillName.Magery, 120 );
SetSkill( SkillName.EvalInt, 120 );
SetSkill( SkillName.Mysticism, 120 );
SetSkill( SkillName.Focus, 160 );
Fame = 22000;
Karma = 22000;
Item boots = new ThighBoots();
boots.Hue = 1;
Item scimitar = new Item(5046);
scimitar.Hue = 1818;
scimitar.Layer = Layer.OneHanded;
SetNonMovable(boots);
SetNonMovable(scimitar);
SetNonMovable(new LongPants(1818));
SetNonMovable(new FancyShirt(194));
SetNonMovable(new Doublet(1281));
}
public override bool InitialInnocent { get { return true; } }
public override BaseCreature SummonWisp { get { return new EnsorcledWisp(); } }
public override void GenerateLoot()
{
AddLoot( LootPack.SuperBoss, 3);
}
public AdrianTheGloriousLord(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class AndrosTheDreadLord : DespiseBoss
{
[Constructable]
public AndrosTheDreadLord() : base(AIType.AI_Mage, FightMode.Closest)
{
Name = "Andros";
Title = "the Dread Lord";
Race = Race.Human;
Body = 0x190;
Female = false;
Hue = Race.RandomSkinHue();
HairItemID = 0;
SetStr( 900, 1200 );
SetDex( 500, 600 );
SetInt( 500, 600 );
SetHits( 60000 );
SetStam( 415 );
SetMana( 22000 );
SetDamage( 18, 28 );
SetDamageType( ResistanceType.Physical, 100 );
SetResistance( ResistanceType.Physical, 40, 60 );
SetResistance( ResistanceType.Fire, 40, 60 );
SetResistance( ResistanceType.Cold, 40, 60 );
SetResistance( ResistanceType.Poison, 40, 60 );
SetResistance( ResistanceType.Energy, 40, 60 );
SetSkill( SkillName.MagicResist, 120 );
SetSkill( SkillName.Tactics, 120 );
SetSkill( SkillName.Wrestling, 120 );
SetSkill( SkillName.Anatomy, 120 );
SetSkill( SkillName.Magery, 120 );
SetSkill( SkillName.EvalInt, 120 );
SetSkill( SkillName.Mysticism, 120 );
SetSkill( SkillName.Focus, 160 );
Fame = 22000;
Karma = -22000;
Item boots = new ThighBoots();
boots.Hue = 1;
Item staff = new Item(3721);
staff.Layer = Layer.TwoHanded;
SetNonMovable(boots);
SetNonMovable(new LongPants(1818));
SetNonMovable(new FancyShirt(2726));
SetNonMovable(new Doublet(1153));
SetNonMovable(staff);
}
public override bool AlwaysMurderer { get { return true; } }
public override BaseCreature SummonWisp { get { return new CorruptedWisp(); } }
public override void GenerateLoot()
{
AddLoot( LootPack.SuperBoss, 3);
}
public AndrosTheDreadLord(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class EnsorcledWisp : BaseCreature
{
public EnsorcledWisp() : base(AIType.AI_Melee, FightMode.None, 10, 1, .2, .4)
{
Name = "Ensorcled Wisp";
Body = 165;
Hue = 0x901;
BaseSoundID = 466;
SetStr( 600, 700 );
SetDex( 500, 600 );
SetInt( 500, 600 );
SetHits( 7000, 8000 );
SetDamage( 12, 19 );
SetDamageType( ResistanceType.Physical, 40 );
SetDamageType( ResistanceType.Fire, 30 );
SetDamageType( ResistanceType.Energy, 30 );
SetResistance( ResistanceType.Physical, 50 );
SetResistance( ResistanceType.Fire, 60, 70 );
SetResistance( ResistanceType.Cold, 60, 70 );
SetResistance( ResistanceType.Poison, 50, 60 );
SetResistance( ResistanceType.Energy, 60, 70 );
SetSkill( SkillName.MagicResist, 110, 125 );
SetSkill( SkillName.Tactics, 110, 125 );
SetSkill( SkillName.Wrestling, 110, 125 );
SetSkill( SkillName.Anatomy, 110, 125 );
Fame = 8000;
Karma = 8000;
}
public override void OnThink()
{
base.OnThink();
if (ControlTarget != ControlMaster || ControlOrder != OrderType.Follow)
{
ControlTarget = ControlMaster;
ControlOrder = OrderType.Follow;
}
}
public override void GenerateLoot()
{
AddLoot( LootPack.FilthyRich, 3);
}
public override bool OnBeforeDeath()
{
Summoned = false;
PackItem(new Gold(Utility.Random(800, 1000)));
return base.OnBeforeDeath();
}
public override bool InitialInnocent { get { return true; } }
//public override bool ForceNotoriety { get { return true; } }
public EnsorcledWisp(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class CorruptedWisp : BaseCreature
{
public CorruptedWisp() : base(AIType.AI_Melee, FightMode.None, 10, 1, .2, .4)
{
Name = "Corrupted Wisp";
Body = 165;
Hue = 1955;
BaseSoundID = 466;
SetStr( 600, 700 );
SetDex( 500, 600 );
SetInt( 500, 600 );
SetHits( 7000, 8000 );
SetDamage( 12, 19 );
SetDamageType( ResistanceType.Physical, 40 );
SetDamageType( ResistanceType.Fire, 30 );
SetDamageType( ResistanceType.Energy, 30 );
SetResistance( ResistanceType.Physical, 50 );
SetResistance( ResistanceType.Fire, 60, 70 );
SetResistance( ResistanceType.Cold, 60, 70 );
SetResistance( ResistanceType.Poison, 50, 60 );
SetResistance( ResistanceType.Energy, 60, 70 );
SetSkill( SkillName.MagicResist, 110, 125 );
SetSkill( SkillName.Tactics, 110, 125 );
SetSkill( SkillName.Wrestling, 110, 125 );
SetSkill( SkillName.Anatomy, 110, 125 );
Fame = 8000;
Karma = -8000;
}
public override void OnThink()
{
base.OnThink();
if (ControlTarget != ControlMaster || ControlOrder != OrderType.Follow)
{
ControlTarget = ControlMaster;
ControlOrder = OrderType.Follow;
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.FilthyRich, 3);
}
public override bool OnBeforeDeath()
{
Summoned = false;
PackItem(new Gold(Utility.Random(800, 1000)));
return base.OnBeforeDeath();
}
public override bool AlwaysMurderer { get { return true; } }
//public override bool ForceNotoriety { get { return true; } }
public CorruptedWisp(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,299 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Items;
using Server.Misc;
using Server.Spells;
using Server.Spells.Third;
using Server.Spells.Sixth;
using Server.Targeting;
namespace Server.Mobiles
{
[CorpseName( "a dread horns corpse" )]
public class DreadHorn : BasePeerless
{
public virtual int StrikingRange{ get{ return 12; } }
[Constructable]
public DreadHorn() : base( AIType.AI_Spellweaving, FightMode.Closest, 10, 1, 0.2, 0.4 )
{
Name = "a Dread Horn";
Body = 257;
BaseSoundID = 0xA8;
SetStr( 878, 993 );
SetDex( 581, 683 );
SetInt( 1200, 1300 );
SetHits( 50000 );
SetStam( 507, 669 );
SetMana( 1200, 1300 );
SetDamage( 21, 28 );
SetDamageType( ResistanceType.Physical, 40 );
SetDamageType( ResistanceType.Poison, 60 );
SetResistance( ResistanceType.Physical, 40, 55 );
SetResistance( ResistanceType.Fire, 50, 65 );
SetResistance( ResistanceType.Cold, 50, 65 );
SetResistance( ResistanceType.Poison, 65, 75 );
SetResistance( ResistanceType.Energy, 60, 75 );
SetSkill( SkillName.Wrestling, 90.0 );
SetSkill( SkillName.Tactics, 90.0 );
SetSkill( SkillName.MagicResist, 110.0 );
SetSkill( SkillName.Poisoning, 120.0 );
SetSkill( SkillName.Magery, 110.0 );
SetSkill( SkillName.EvalInt, 110.0 );
SetSkill( SkillName.Meditation, 110.0 );
SetSkill(SkillName.Spellweaving, 120.0);
// TODO 1-3 spellweaving scroll
Fame = 32000;
Karma = -32000;
PackResources( 8 );
PackTalismans( 5 );
m_Change = DateTime.UtcNow;
m_Stomp = DateTime.UtcNow;
m_Teleport = DateTime.UtcNow;
for (int i = 0; i < Utility.RandomMinMax(1, 3); i++)
{
PackItem(Loot.RandomScroll(0, Loot.ArcanistScrollTypes.Length, SpellbookType.Arcanist));
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.AosSuperBoss, 8);
AddLoot(LootPack.LowScrolls, 4);
AddLoot(LootPack.MedScrolls, 4);
AddLoot(LootPack.HighScrolls, 4);
}
public override void OnThink()
{
base.OnThink();
if ( Combatant != null )
{
if ( m_Change < DateTime.UtcNow && Utility.RandomDouble() < 0.1 )
ChangeOpponent();
if ( m_Stomp < DateTime.UtcNow && Utility.RandomDouble() < 0.1 )
HoofStomp();
if (m_Teleport < DateTime.UtcNow && Utility.RandomDouble() < 0.1)
Teleport();
}
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
c.DropItem( new DreadHornMane() );
if ( Utility.RandomDouble() < 0.6 )
c.DropItem( new TaintedMushroom() );
if ( Utility.RandomDouble() < 0.6 )
c.DropItem( new ParrotItem() );
if ( Utility.RandomDouble() < 0.5 )
c.DropItem( new MangledHeadOfDreadhorn() );
if ( Utility.RandomDouble() < 0.5 )
c.DropItem( new HornOfTheDreadhorn() );
if ( Utility.RandomDouble() < 0.05 )
c.DropItem( new PristineDreadHorn() );
if ( Utility.RandomDouble() < 0.05 )
c.DropItem( new DreadFlute() );
if ( Utility.RandomDouble() < 0.05 )
c.DropItem( new DreadsRevenge() );
}
public override int Hides{ get{ return 10; } }
public override HideType HideType{ get{ return HideType.Regular; } }
public override int Meat{ get{ return 5; } }
public override MeatType MeatType{ get{ return MeatType.Ribs; } }
public override bool GivesMLMinorArtifact { get { return true; } }
public override bool Unprovokable{ get{ return true; } }
public override Poison PoisonImmune{ get{ return Poison.Deadly; } }
public override Poison HitPoison{ get{ return Poison.Lethal; } }
public override int TreasureMapLevel{ get{ return 5; } }
public DreadHorn( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
m_Change = DateTime.UtcNow;
m_Stomp = DateTime.UtcNow;
m_Teleport = DateTime.UtcNow;
}
private DateTime m_Change;
private DateTime m_Stomp;
private DateTime m_Teleport;
private void Teleport()
{
var toTele = SpellHelper.AcquireIndirectTargets(this, Location, Map, StrikingRange).OfType<PlayerMobile>().ToList();
if (toTele.Count > 0)
{
var from = toTele[Utility.Random(toTele.Count)];
if (from != null)
{
Combatant = from;
from.MoveToWorld(GetSpawnPosition(1), Map);
from.FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
from.PlaySound(0x1FE);
from.ApplyPoison(this, HitPoison);
}
}
ColUtility.Free(toTele);
m_Teleport = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(40, 60));
}
public void ChangeOpponent()
{
Mobile agro, best = null;
double distance, random = Utility.RandomDouble();
if (random < 0.75)
{
// find random target relatively close
for (int i = 0; i < Aggressors.Count && best == null; i++)
{
agro = Validate(Aggressors[i].Attacker);
if (agro == null)
continue;
distance = StrikingRange - GetDistanceToSqrt(agro);
if (distance > 0 && distance < StrikingRange - 2 && InLOS(agro.Location))
{
distance /= StrikingRange;
if (random < distance)
best = agro;
}
}
}
else
{
int damage = 0;
// find a player who dealt most damage
for (int i = 0; i < DamageEntries.Count; i++)
{
agro = Validate(DamageEntries[i].Damager);
if (agro == null)
continue;
distance = GetDistanceToSqrt(agro);
if (distance < StrikingRange && DamageEntries[i].DamageGiven > damage && InLOS(agro.Location))
{
best = agro;
damage = DamageEntries[i].DamageGiven;
}
}
}
if (best != null)
{
// teleport
best.Location = BasePeerless.GetSpawnPosition(Location, Map, 1);
best.FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
best.PlaySound(0x1FE);
Timer.DelayCall(TimeSpan.FromSeconds(1), () =>
{
best.ApplyPoison(this, HitPoison);
best.FixedParticles(0x374A, 10, 15, 5021, EffectLayer.Waist);
best.PlaySound(0x474);
});
m_Change = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(5, 10));
}
}
public void HoofStomp()
{
if (Map == null)
return;
foreach (Mobile m in SpellHelper.AcquireIndirectTargets(this, Location, Map, StrikingRange).OfType<Mobile>())
{
if (m.GetStatMod("DreadHornStr") == null)
{
double percent = m.Skills.MagicResist.Value / 100;
int malas = (int)(-20 + (percent * 5.2));
m.AddStatMod(new StatMod(StatType.Str, "DreadHornStr", m.Str < Math.Abs(malas) ? m.Str / 2 : malas, TimeSpan.FromSeconds(60)));
m.AddStatMod(new StatMod(StatType.Dex, "DreadHornDex", m.Dex < Math.Abs(malas) ? m.Dex / 2 : malas, TimeSpan.FromSeconds(60)));
m.AddStatMod(new StatMod(StatType.Int, "DreadHornInt", m.Int < Math.Abs(malas) ? m.Int / 2 : malas, TimeSpan.FromSeconds(60)));
}
m.SendLocalizedMessage(1075081); // *Dreadhorn’s eyes light up, his mouth almost a grin, as he slams one hoof to the ground!*
}
// earthquake
PlaySound( 0x2F3 );
m_Stomp = DateTime.UtcNow + TimeSpan.FromSeconds( Utility.RandomMinMax( 60, 80 ) );
}
public static bool IsUnderInfluence(Mobile m)
{
return m.GetStatMod("DreadHornStr") != null;
}
public Mobile Validate( Mobile m )
{
Mobile agro;
if ( m is BaseCreature )
agro = ( (BaseCreature) m ).ControlMaster;
else
agro = m;
if ( !CanBeHarmful( agro, false ) || !agro.Player /*|| Combatant == agro*/ )
return null;
return agro;
}
}
}

View File

@@ -0,0 +1,564 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Server.Items;
using Server.Engines.CannedEvil;
using Server.Services.Virtues;
namespace Server.Mobiles
{
public class Harrower : BaseCreature
{
private int m_StatCap = Config.Get("PlayerCaps.TotalStatCap", 225);
private static readonly SpawnEntry[] m_Entries = new SpawnEntry[]
{
new SpawnEntry(new Point3D(5242, 945, -40), new Point3D(1176, 2638, 0)), // Destard
new SpawnEntry(new Point3D(5225, 798, 0), new Point3D(1176, 2638, 0)), // Destard
new SpawnEntry(new Point3D(5556, 886, 30), new Point3D(1298, 1080, 0)), // Despise
new SpawnEntry(new Point3D(5187, 615, 0), new Point3D(4111, 432, 5)), // Deceit
new SpawnEntry(new Point3D(5319, 583, 0), new Point3D(4111, 432, 5)), // Deceit
new SpawnEntry(new Point3D(5713, 1334, -1), new Point3D(2923, 3407, 8)), // Fire
new SpawnEntry(new Point3D(5860, 1460, -2), new Point3D(2923, 3407, 8)), // Fire
new SpawnEntry(new Point3D(5328, 1620, 0), new Point3D(5451, 3143, -60)), // Terathan Keep
new SpawnEntry(new Point3D(5690, 538, 0), new Point3D(2042, 224, 14)), // Wrong
new SpawnEntry(new Point3D(5609, 195, 0), new Point3D(514, 1561, 0)), // Shame
new SpawnEntry(new Point3D(5475, 187, 0), new Point3D(514, 1561, 0)), // Shame
new SpawnEntry(new Point3D(6085, 179, 0), new Point3D(4721, 3822, 0)), // Hythloth
new SpawnEntry(new Point3D(6084, 66, 0), new Point3D(4721, 3822, 0)), // Hythloth
/*new SpawnEntry(new Point3D(5499, 2003, 0), new Point3D(2499, 919, 0)), // Covetous*/
new SpawnEntry(new Point3D(5579, 1858, 0), new Point3D(2499, 919, 0))// Covetous
};
private static readonly ArrayList m_Instances = new ArrayList();
private static readonly double[] m_Offsets = new double[]
{
Math.Cos(000.0 / 180.0 * Math.PI), Math.Sin(000.0 / 180.0 * Math.PI),
Math.Cos(040.0 / 180.0 * Math.PI), Math.Sin(040.0 / 180.0 * Math.PI),
Math.Cos(080.0 / 180.0 * Math.PI), Math.Sin(080.0 / 180.0 * Math.PI),
Math.Cos(120.0 / 180.0 * Math.PI), Math.Sin(120.0 / 180.0 * Math.PI),
Math.Cos(160.0 / 180.0 * Math.PI), Math.Sin(160.0 / 180.0 * Math.PI),
Math.Cos(200.0 / 180.0 * Math.PI), Math.Sin(200.0 / 180.0 * Math.PI),
Math.Cos(240.0 / 180.0 * Math.PI), Math.Sin(240.0 / 180.0 * Math.PI),
Math.Cos(280.0 / 180.0 * Math.PI), Math.Sin(280.0 / 180.0 * Math.PI),
Math.Cos(320.0 / 180.0 * Math.PI), Math.Sin(320.0 / 180.0 * Math.PI),
};
private bool m_TrueForm;
private bool m_IsSpawned;
private Item m_GateItem;
private List<HarrowerTentacles> m_Tentacles;
Dictionary<Mobile, int> m_DamageEntries;
[Constructable]
public Harrower()
: base(AIType.AI_NecroMage, FightMode.Closest, 18, 1, 0.2, 0.4)
{
Name = "the harrower";
BodyValue = 146;
SetStr(900, 1000);
SetDex(125, 135);
SetInt(1000, 1200);
Fame = 22500;
Karma = -22500;
VirtualArmor = 60;
SetDamageType(ResistanceType.Physical, 50);
SetDamageType(ResistanceType.Energy, 50);
SetResistance(ResistanceType.Physical, 55, 65);
SetResistance(ResistanceType.Fire, 60, 80);
SetResistance(ResistanceType.Cold, 60, 80);
SetResistance(ResistanceType.Poison, 60, 80);
SetResistance(ResistanceType.Energy, 60, 80);
SetSkill(SkillName.Wrestling, 90.1, 100.0);
SetSkill(SkillName.Tactics, 90.2, 110.0);
SetSkill(SkillName.MagicResist, 120.2, 160.0);
SetSkill(SkillName.Magery, 120.0);
SetSkill(SkillName.EvalInt, 120.0);
SetSkill(SkillName.Meditation, 120.0);
m_Tentacles = new List<HarrowerTentacles>();
}
public Harrower(Serial serial)
: base(serial)
{
}
public static ArrayList Instances
{
get
{
return m_Instances;
}
}
public static bool CanSpawn
{
get
{
return (m_Instances.Count == 0);
}
}
public Type[] UniqueList
{
get
{
return new Type[] { typeof(AcidProofRobe) };
}
}
public Type[] SharedList
{
get
{
return new Type[] { typeof(TheRobeOfBritanniaAri) };
}
}
public Type[] DecorativeList
{
get
{
return new Type[] { typeof(EvilIdolSkull), typeof(SkullPole) };
}
}
public override bool AutoDispel
{
get
{
return true;
}
}
public override bool Unprovokable
{
get
{
return true;
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Lethal;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public override int HitsMax
{
get
{
return m_TrueForm ? 65000 : 30000;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public override int ManaMax
{
get
{
return 5000;
}
}
public override bool DisallowAllMoves
{
get
{
return m_TrueForm;
}
}
public override bool TeleportsTo { get { return true; } }
public static Harrower Spawn(Point3D platLoc, Map platMap)
{
if (m_Instances.Count > 0)
return null;
SpawnEntry entry = m_Entries[Utility.Random(m_Entries.Length)];
Harrower harrower = new Harrower();
harrower.m_IsSpawned = true;
m_Instances.Add(harrower);
harrower.MoveToWorld(entry.m_Location, Map.Felucca);
harrower.m_GateItem = new HarrowerGate(harrower, platLoc, platMap, entry.m_Entrance, Map.Felucca);
return harrower;
}
public override void GenerateLoot()
{
AddLoot(LootPack.SuperBoss, 2);
AddLoot(LootPack.Meager);
}
public void Morph()
{
if (m_TrueForm)
return;
m_TrueForm = true;
Name = "the true harrower";
BodyValue = 780;
Hue = 0x497;
Hits = HitsMax;
Stam = StamMax;
Mana = ManaMax;
ProcessDelta();
Say(1049499); // Behold my true form!
Map map = Map;
if (map != null)
{
for (int i = 0; i < m_Offsets.Length; i += 2)
{
double rx = m_Offsets[i];
double ry = m_Offsets[i + 1];
int dist = 0;
bool ok = false;
int x = 0, y = 0, z = 0;
while (!ok && dist < 10)
{
int rdist = 10 + dist;
x = X + (int)(rx * rdist);
y = Y + (int)(ry * rdist);
z = map.GetAverageZ(x, y);
if (!(ok = map.CanFit(x, y, Z, 16, false, false)))
ok = map.CanFit(x, y, z, 16, false, false);
if (dist >= 0)
dist = -(dist + 1);
else
dist = -(dist - 1);
}
if (!ok)
continue;
HarrowerTentacles spawn = new HarrowerTentacles(this);
spawn.Team = Team;
spawn.MoveToWorld(new Point3D(x, y, z), map);
m_Tentacles.Add(spawn);
}
}
}
public override void OnAfterDelete()
{
m_Instances.Remove(this);
base.OnAfterDelete();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)1); // version
writer.Write(m_IsSpawned);
writer.Write(m_TrueForm);
writer.Write(m_GateItem);
writer.WriteMobileList<HarrowerTentacles>(m_Tentacles);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch ( version )
{
case 1:
{
m_IsSpawned = reader.ReadBool();
goto case 0;
}
case 0:
{
m_TrueForm = reader.ReadBool();
m_GateItem = reader.ReadItem();
m_Tentacles = reader.ReadStrongMobileList<HarrowerTentacles>();
break;
}
}
if (m_IsSpawned)
m_Instances.Add(this);
}
public void GivePowerScrolls()
{
List<Mobile> toGive = new List<Mobile>();
List<DamageStore> rights = GetLootingRights();
for (int i = rights.Count - 1; i >= 0; --i)
{
DamageStore ds = rights[i];
if (ds.m_HasRight)
toGive.Add(ds.m_Mobile);
}
if (toGive.Count == 0)
return;
// Randomize
for (int i = 0; i < toGive.Count; ++i)
{
int rand = Utility.Random(toGive.Count);
Mobile hold = toGive[i];
toGive[i] = toGive[rand];
toGive[rand] = hold;
}
for (int i = 0; i < ChampionSystem.StatScrollAmount; ++i)
{
Mobile m = toGive[i % toGive.Count];
m.SendLocalizedMessage(1049524); // You have received a scroll of power!
m.AddToBackpack(new StatCapScroll(m_StatCap + RandomStatScrollLevel()));
if (m is PlayerMobile)
{
PlayerMobile pm = (PlayerMobile)m;
for (int j = 0; j < pm.JusticeProtectors.Count; ++j)
{
Mobile prot = (Mobile)pm.JusticeProtectors[j];
if (prot.Map != m.Map || prot.Murderer || prot.Criminal || !JusticeVirtue.CheckMapRegion(m, prot))
continue;
int chance = 0;
switch ( VirtueHelper.GetLevel(prot, VirtueName.Justice) )
{
case VirtueLevel.Seeker:
chance = 60;
break;
case VirtueLevel.Follower:
chance = 80;
break;
case VirtueLevel.Knight:
chance = 100;
break;
}
if (chance > Utility.Random(100))
{
prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice!
prot.AddToBackpack(new StatCapScroll(m_StatCap + RandomStatScrollLevel()));
}
}
}
}
}
private static int RandomStatScrollLevel()
{
double random = Utility.RandomDouble();
if (0.1 >= random)
return 25;
else if (0.25 >= random)
return 20;
else if (0.45 >= random)
return 15;
else if (0.70 >= random)
return 10;
return 5;
}
public override bool OnBeforeDeath()
{
if (m_TrueForm)
{
List<DamageStore> rights = GetLootingRights();
for (int i = rights.Count - 1; i >= 0; --i)
{
DamageStore ds = rights[i];
if (ds.m_HasRight && ds.m_Mobile is PlayerMobile)
PlayerMobile.ChampionTitleInfo.AwardHarrowerTitle((PlayerMobile)ds.m_Mobile);
}
if (!NoKillAwards)
{
GivePowerScrolls();
Map map = Map;
GoldShower.DoForHarrower(Location, Map);
m_DamageEntries = new Dictionary<Mobile, int>();
for (int i = 0; i < m_Tentacles.Count; ++i)
{
Mobile m = m_Tentacles[i];
if (!m.Deleted)
m.Kill();
RegisterDamageTo(m);
}
m_Tentacles.Clear();
RegisterDamageTo(this);
AwardArtifact(GetArtifact());
if (m_GateItem != null)
m_GateItem.Delete();
}
return base.OnBeforeDeath();
}
else
{
Morph();
return false;
}
}
public virtual void RegisterDamageTo(Mobile m)
{
if (m == null)
return;
foreach (DamageEntry de in m.DamageEntries)
{
Mobile damager = de.Damager;
Mobile master = damager.GetDamageMaster(m);
if (master != null)
damager = master;
RegisterDamage(damager, de.DamageGiven);
}
}
public void RegisterDamage(Mobile from, int amount)
{
if (from == null || !from.Player)
return;
if (m_DamageEntries.ContainsKey(from))
m_DamageEntries[from] += amount;
else
m_DamageEntries.Add(from, amount);
from.SendMessage(String.Format("Total Damage: {0}", m_DamageEntries[from]));
}
public void AwardArtifact(Item artifact)
{
if (artifact == null)
return;
int totalDamage = 0;
Dictionary<Mobile, int> validEntries = new Dictionary<Mobile, int>();
foreach (KeyValuePair<Mobile, int> kvp in m_DamageEntries)
{
if (IsEligible(kvp.Key, artifact))
{
validEntries.Add(kvp.Key, kvp.Value);
totalDamage += kvp.Value;
}
}
int randomDamage = Utility.RandomMinMax(1, totalDamage);
totalDamage = 0;
foreach (KeyValuePair<Mobile, int> kvp in validEntries)
{
totalDamage += kvp.Value;
if (totalDamage >= randomDamage)
{
GiveArtifact(kvp.Key, artifact);
return;
}
}
artifact.Delete();
}
public void GiveArtifact(Mobile to, Item artifact)
{
if (to == null || artifact == null)
return;
to.PlaySound(0x5B4);
Container pack = to.Backpack;
if (pack == null || !pack.TryDropItem(to, artifact, false))
artifact.Delete();
else
to.SendLocalizedMessage(1062317); // For your valor in combating the fallen beast, a special artifact has been bestowed on you.
}
public bool IsEligible(Mobile m, Item Artifact)
{
return m.Player && m.Alive && m.InRange(Location, 32) && m.Backpack != null && m.Backpack.CheckHold(m, Artifact, false);
}
public Item GetArtifact()
{
double random = Utility.RandomDouble();
if (0.05 >= random)
return CreateArtifact(UniqueList);
else if (0.15 >= random)
return CreateArtifact(SharedList);
else if (0.30 >= random)
return CreateArtifact(DecorativeList);
return null;
}
public Item CreateArtifact(Type[] list)
{
if (list.Length == 0)
return null;
int random = Utility.Random(list.Length);
Type type = list[random];
return Loot.Construct(type);
}
private class SpawnEntry
{
public readonly Point3D m_Location;
public readonly Point3D m_Entrance;
public SpawnEntry(Point3D loc, Point3D ent)
{
m_Location = loc;
m_Entrance = ent;
}
}
}
}

View File

@@ -0,0 +1,261 @@
using System;
using System.Collections;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName("a tentacles corpse")]
public class HarrowerTentacles : BaseCreature
{
private Mobile m_Harrower;
private DrainTimer m_Timer;
[Constructable]
public HarrowerTentacles()
: this(null)
{
}
public HarrowerTentacles(Mobile harrower)
: base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
this.m_Harrower = harrower;
this.Name = "tentacles of the harrower";
this.Body = 129;
this.SetStr(901, 1000);
this.SetDex(126, 140);
this.SetInt(1001, 1200);
this.SetHits(541, 600);
this.SetDamage(13, 20);
this.SetDamageType(ResistanceType.Physical, 20);
this.SetDamageType(ResistanceType.Fire, 20);
this.SetDamageType(ResistanceType.Cold, 20);
this.SetDamageType(ResistanceType.Poison, 20);
this.SetDamageType(ResistanceType.Energy, 20);
this.SetResistance(ResistanceType.Physical, 55, 65);
this.SetResistance(ResistanceType.Fire, 35, 45);
this.SetResistance(ResistanceType.Cold, 35, 45);
this.SetResistance(ResistanceType.Poison, 35, 45);
this.SetResistance(ResistanceType.Energy, 35, 45);
this.SetSkill(SkillName.Meditation, 100.0);
this.SetSkill(SkillName.MagicResist, 120.1, 140.0);
this.SetSkill(SkillName.Swords, 90.1, 100.0);
this.SetSkill(SkillName.Tactics, 90.1, 100.0);
this.SetSkill(SkillName.Wrestling, 90.1, 100.0);
this.Fame = 15000;
this.Karma = -15000;
this.VirtualArmor = 60;
this.m_Timer = new DrainTimer(this);
this.m_Timer.Start();
this.PackReg(50);
this.PackNecroReg(15, 75);
switch (Utility.Random(3))
{
case 0: PackItem(new VampiricEmbraceScroll()); break;
}
}
public HarrowerTentacles(Serial serial)
: base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Harrower
{
get
{
return this.m_Harrower;
}
set
{
this.m_Harrower = value;
}
}
public override bool AutoDispel
{
get
{
return true;
}
}
public override bool Unprovokable
{
get
{
return true;
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Lethal;
}
}
public override bool DisallowAllMoves
{
get
{
return true;
}
}
public override void CheckReflect(Mobile caster, ref bool reflect)
{
reflect = true;
}
public override int GetIdleSound()
{
return 0x101;
}
public override int GetAngerSound()
{
return 0x5E;
}
public override int GetDeathSound()
{
return 0x1C2;
}
public override int GetAttackSound()
{
return -1; // unknown
}
public override int GetHurtSound()
{
return 0x289;
}
public override void GenerateLoot()
{
this.AddLoot(LootPack.FilthyRich, 2);
this.AddLoot(LootPack.MedScrolls, 3);
this.AddLoot(LootPack.HighScrolls, 2);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
writer.Write(this.m_Harrower);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch ( version )
{
case 0:
{
this.m_Harrower = reader.ReadMobile();
this.m_Timer = new DrainTimer(this);
this.m_Timer.Start();
break;
}
}
}
public override void OnAfterDelete()
{
if (this.m_Timer != null)
this.m_Timer.Stop();
this.m_Timer = null;
base.OnAfterDelete();
}
private class DrainTimer : Timer
{
private static readonly ArrayList m_ToDrain = new ArrayList();
private readonly HarrowerTentacles m_Owner;
public DrainTimer(HarrowerTentacles owner)
: base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0))
{
this.m_Owner = owner;
this.Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
if (this.m_Owner.Deleted)
{
this.Stop();
return;
}
IPooledEnumerable eable = m_Owner.GetMobilesInRange(9);
foreach (Mobile m in eable)
{
if (m == this.m_Owner || m == this.m_Owner.Harrower || !this.m_Owner.CanBeHarmful(m))
continue;
if (m is BaseCreature)
{
BaseCreature bc = m as BaseCreature;
if (bc.Controlled || bc.Summoned)
m_ToDrain.Add(m);
}
else if (m.Player)
{
m_ToDrain.Add(m);
}
}
eable.Free();
foreach (Mobile m in m_ToDrain)
{
this.m_Owner.DoHarmful(m);
m.FixedParticles(0x374A, 10, 15, 5013, 0x455, 0, EffectLayer.Waist);
m.PlaySound(0x1F1);
int drain = Utility.RandomMinMax(14, 30);
//Monster Stealables
if (m is PlayerMobile)
{
PlayerMobile pm = m as PlayerMobile;
drain = (int)LifeShieldLotion.HandleLifeDrain(pm, drain);
}
//end
this.m_Owner.Hits += drain;
if (this.m_Owner.Harrower != null)
this.m_Owner.Harrower.Hits += drain;
m.Damage(drain, this.m_Owner);
}
m_ToDrain.Clear();
}
}
}
}

View File

@@ -0,0 +1,288 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName("a lady melisande corpse")]
public class LadyMelisande : BasePeerless
{
[Constructable]
public LadyMelisande()
: base(AIType.AI_NecroMage, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Name = "a lady melisande";
Body = 0x102;
BaseSoundID = 451;
SetStr(400, 1000);
SetDex(300, 400);
SetInt(1500, 1700);
SetHits(100000);
SetDamage(11, 18);
SetDamageType(ResistanceType.Physical, 50);
SetDamageType(ResistanceType.Energy, 50);
SetResistance(ResistanceType.Physical, 40, 60);
SetResistance(ResistanceType.Fire, 40, 50);
SetResistance(ResistanceType.Cold, 55, 65);
SetResistance(ResistanceType.Poison, 70, 75);
SetResistance(ResistanceType.Energy, 70, 80);
SetSkill(SkillName.Wrestling, 100, 105);
SetSkill(SkillName.Tactics, 100, 105);
SetSkill(SkillName.MagicResist, 120);
SetSkill(SkillName.Magery, 120);
SetSkill(SkillName.EvalInt, 120);
SetSkill(SkillName.Meditation, 120);
SetSkill(SkillName.Necromancy, 120);
SetSkill(SkillName.SpiritSpeak, 120);
PackResources(8);
PackTalismans(5);
Timer.DelayCall(TimeSpan.FromSeconds(1), new TimerCallback(SpawnSatyrs));
Fame = 25000;
Karma = -25000;
VirtualArmor = 50;
for (int i = 0; i < Utility.RandomMinMax(0, 1); i++)
{
PackItem(Loot.RandomScroll(0, Loot.ArcanistScrollTypes.Length, SpellbookType.Arcanist));
}
SetAreaEffect(AreaEffect.AuraOfNausea);
}
public override void GenerateLoot()
{
AddLoot(LootPack.SuperBoss, 8);
AddLoot(LootPack.Parrot, 1);
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
c.DropItem(new DiseasedBark());
c.DropItem(new EternallyCorruptTree());
int drop = Utility.Random(4, 8);
for (int i = 0; i < drop; i++)
c.DropItem(new MelisandesFermentedWine());
if (Utility.RandomDouble() < 0.6)
c.DropItem(new ParrotItem());
if (Utility.RandomDouble() < 0.2225)
{
switch ( Utility.Random(3) )
{
case 0:
c.DropItem(new MelisandesHairDye());
break;
case 1:
c.DropItem(new MelisandesCorrodedHatchet());
break;
case 2:
c.DropItem(new AlbinoSquirrelImprisonedInCrystal());
break;
}
}
}
public override void OnThink()
{
base.OnThink();
Mobile combatant = Combatant as Mobile;
if (combatant != null)
{
if (CanTakeLife(combatant))
TakeLife(combatant);
if (CanSmackTalk())
SmackTalk();
}
}
public override void SetLocation(Point3D newLocation, bool isTeleport)
{
if (newLocation.Z > -10)
base.SetLocation(newLocation, isTeleport);
}
public override void OnDamage(int amount, Mobile from, bool willKill)
{
if (willKill)
{
SpawnHelper(new Reaper(), 6490, 948, 19);
SpawnHelper(new InsaneDryad(), 6497, 946, 17);
SpawnHelper(new StoneHarpy(), 6511, 946, 28);
Say(1075118); // Noooooo! You shall never defeat me. Even if I should fall, my tree will sustain me and I will rise again.
}
base.OnDamage(amount, from, willKill);
}
public override bool GivesMLMinorArtifact
{
get
{
return true;
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Lethal;
}
}
public override int TreasureMapLevel
{
get
{
return 5;
}
}
public LadyMelisande(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
#region Smack Talk
private DateTime m_NextSmackTalk;
public bool CanSmackTalk()
{
if (m_NextSmackTalk > DateTime.UtcNow)
return false;
if (Combatant == null)
return false;
return Hits > 0.5 * HitsMax;
}
public void SmackTalk()
{
Say(Utility.RandomMinMax(1075102, 1075115)); // Muahahahaha! I'll feast on your flesh.
m_NextSmackTalk = DateTime.UtcNow + TimeSpan.FromSeconds(2 + Utility.RandomDouble() * 3);
}
#endregion
#region Take Life
private DateTime m_NextTakeLife;
public bool CanTakeLife(Mobile from)
{
if (m_NextTakeLife > DateTime.UtcNow)
return false;
if (!CanBeHarmful(from))
return false;
if (Hits > 0.1 * HitsMax || Hits < 0.025 * HitsMax)
return false;
return true;
}
public void TakeLife(Mobile from)
{
Hits += from.Hits / (from.Player ? 2 : 6);
FixedParticles(0x376A, 9, 32, 5005, EffectLayer.Waist);
PlaySound(0x1F2);
Say(1075117); // Muahahaha! Your life essence is MINE!
Say(1075120); // An unholy aura surrounds Lady Melisande as her wounds begin to close.
m_NextTakeLife = DateTime.UtcNow + TimeSpan.FromSeconds(15 + Utility.RandomDouble() * 45);
}
#endregion
#region Helpers
public override bool CanSpawnHelpers
{
get
{
return true;
}
}
public override int MaxHelpersWaves
{
get
{
return 1;
}
}
public override void SpawnHelpers()
{
int count = 4;
if (Altar != null)
{
count = Math.Min(Altar.Fighters.Count, 4);
for (int i = 0; i < count; i++)
{
Mobile fighter = Altar.Fighters[i];
if (CanBeHarmful(fighter))
{
EnslavedSatyr satyr = new EnslavedSatyr();
satyr.FightMode = FightMode.Closest;
SpawnHelper(satyr, GetSpawnPosition(fighter.Location, fighter.Map, 2));
satyr.Combatant = fighter;
fighter.SendLocalizedMessage(1075116); // A twisted satyr scrambles onto the branch beside you and attacks!
}
}
}
else
{
for (int i = 0; i < count; i++)
SpawnHelper(new EnslavedSatyr(), 4);
}
}
public void SpawnSatyrs()
{
SpawnHelper(new EnslavedSatyr(), 6485, 945, 19);
SpawnHelper(new EnslavedSatyr(), 6486, 948, 22);
SpawnHelper(new EnslavedSatyr(), 6487, 945, 17);
SpawnHelper(new EnslavedSatyr(), 6488, 947, 23);
}
#endregion
}
}

View File

@@ -0,0 +1,332 @@
using System;
using Server.Engines.CannedEvil;
using Server.Items;
namespace Server.Mobiles
{
public class LordOaks : BaseChampion
{
private Mobile m_Queen;
private bool m_SpawnedQueen;
[Constructable]
public LordOaks()
: base(AIType.AI_Paladin, FightMode.Evil)
{
Body = 175;
Name = "Lord Oaks";
SetStr(403, 850);
SetDex(101, 150);
SetInt(503, 800);
SetHits(12000);
SetStam(202, 400);
SetDamage(21, 33);
SetDamageType(ResistanceType.Physical, 75);
SetDamageType(ResistanceType.Fire, 25);
SetResistance(ResistanceType.Physical, 85, 90);
SetResistance(ResistanceType.Fire, 60, 70);
SetResistance(ResistanceType.Cold, 60, 70);
SetResistance(ResistanceType.Poison, 80, 90);
SetResistance(ResistanceType.Energy, 80, 90);
SetSkill(SkillName.Anatomy, 75.1, 100.0);
SetSkill(SkillName.EvalInt, 120.1, 130.0);
SetSkill(SkillName.Magery, 120.0);
SetSkill(SkillName.Meditation, 120.1, 130.0);
SetSkill(SkillName.MagicResist, 100.5, 150.0);
SetSkill(SkillName.Tactics, 100.0);
SetSkill(SkillName.Wrestling, 100.0);
SetSkill(SkillName.Chivalry, 100.0);
Fame = 22500;
Karma = 22500;
VirtualArmor = 100;
}
public LordOaks(Serial serial)
: base(serial)
{
}
public override ChampionSkullType SkullType
{
get
{
return ChampionSkullType.Enlightenment;
}
}
public override Type[] UniqueList
{
get
{
return new Type[] { typeof(OrcChieftainHelm) };
}
}
public override Type[] SharedList
{
get
{
return new Type[]
{
typeof(RoyalGuardSurvivalKnife),
typeof(DjinnisRing),
typeof(LieutenantOfTheBritannianRoyalGuard),
typeof(SamaritanRobe),
typeof(DetectiveBoots),
typeof(TheMostKnowledgePerson)
};
}
}
public override Type[] DecorativeList
{
get
{
return new Type[]
{
typeof(WaterTile),
typeof(WindSpirit),
typeof(Pier),
};
}
}
public override MonsterStatuetteType[] StatueTypes
{
get
{
return new MonsterStatuetteType[] { };
}
}
public override bool AutoDispel
{
get
{
return true;
}
}
public override bool CanFly
{
get
{
return true;
}
}
public override bool BardImmune
{
get
{
return !Core.SE;
}
}
public override bool Unprovokable
{
get
{
return Core.SE;
}
}
public override bool Uncalmable
{
get
{
return Core.SE;
}
}
public override TribeType Tribe { get { return TribeType.Fey; } }
public override OppositionGroup OppositionGroup
{
get
{
return OppositionGroup.FeyAndUndead;
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Deadly;
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.UltraRich, 5);
}
public void SpawnPixies(Mobile target)
{
Map map = Map;
if (map == null)
return;
Say(1042154); // You shall never defeat me as long as I have my queen!
int newPixies = Utility.RandomMinMax(3, 6);
for (int i = 0; i < newPixies; ++i)
{
Pixie pixie = new Pixie();
pixie.Team = Team;
pixie.FightMode = FightMode.Closest;
bool validLocation = false;
Point3D loc = Location;
for (int j = 0; !validLocation && j < 10; ++j)
{
int x = X + Utility.Random(3) - 1;
int y = Y + Utility.Random(3) - 1;
int z = map.GetAverageZ(x, y);
if (validLocation = map.CanFit(x, y, Z, 16, false, false))
loc = new Point3D(x, y, Z);
else if (validLocation = map.CanFit(x, y, z, 16, false, false))
loc = new Point3D(x, y, z);
}
pixie.MoveToWorld(loc, map);
pixie.Combatant = target;
}
}
public override int GetAngerSound()
{
return 0x2F8;
}
public override int GetIdleSound()
{
return 0x2F8;
}
public override int GetAttackSound()
{
return Utility.Random(0x2F5, 2);
}
public override int GetHurtSound()
{
return 0x2F9;
}
public override int GetDeathSound()
{
return 0x2F7;
}
public void CheckQueen()
{
if (Map == null)
return;
if (!m_SpawnedQueen)
{
Say(1042153); // Come forth my queen!
m_Queen = new Silvani();
((BaseCreature)m_Queen).Team = Team;
m_Queen.MoveToWorld(Location, Map);
m_SpawnedQueen = true;
}
else if (m_Queen != null && m_Queen.Deleted)
{
m_Queen = null;
}
}
public override void AlterDamageScalarFrom(Mobile caster, ref double scalar)
{
CheckQueen();
if (m_Queen != null)
{
scalar *= 0.1;
if (0.1 >= Utility.RandomDouble())
SpawnPixies(caster);
}
}
public override void OnGaveMeleeAttack(Mobile defender)
{
base.OnGaveMeleeAttack(defender);
if (0.25 > Utility.RandomDouble())
{
int toSap = Utility.RandomMinMax(20, 30);
switch (Utility.Random(3))
{
case 0:
defender.Damage(toSap, this);
Hits += toSap;
break;
case 1:
defender.Stam -= toSap;
Stam += toSap;
break;
case 2:
defender.Mana -= toSap;
Mana += toSap;
break;
}
}
/*defender.Damage(Utility.Random(20, 10), this);
defender.Stam -= Utility.Random(20, 10);
defender.Mana -= Utility.Random(20, 10);*/
}
public override void OnGotMeleeAttack(Mobile attacker)
{
base.OnGotMeleeAttack(attacker);
CheckQueen();
if (m_Queen != null && 0.1 >= Utility.RandomDouble())
SpawnPixies(attacker);
/*attacker.Damage(Utility.Random(20, 10), this);
attacker.Stam -= Utility.Random(20, 10);
attacker.Mana -= Utility.Random(20, 10);*/
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
writer.Write(m_Queen);
writer.Write(m_SpawnedQueen);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch ( version )
{
case 0:
{
m_Queen = reader.ReadMobile();
m_SpawnedQueen = reader.ReadBool();
break;
}
}
}
}
}

View File

@@ -0,0 +1,809 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Server.Items;
using Server.Mobiles;
using Server.Network;
namespace Server.Mobiles
{
[CorpseName("a medusa corpse")]
public class Medusa : BaseSABoss, ICarvable
{
private List<Mobile> m_TurnedToStone = new List<Mobile>();
public List<Mobile> AffectedMobiles { get { return m_TurnedToStone; } }
public List<Mobile> m_Helpers = new List<Mobile>();
private int m_Scales;
private DateTime m_GazeDelay;
private DateTime m_StoneDelay;
private DateTime m_NextCarve;
[Constructable]
public Medusa()
: base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.1, 0.2)
{
Name = "Medusa";
Body = 728;
SetStr(1235, 1391);
SetDex(128, 139);
SetInt(537, 664);
SetHits(60000);
SetDamage(21, 28);
SetDamageType(ResistanceType.Physical, 60);
SetDamageType(ResistanceType.Fire, 20);
SetDamageType(ResistanceType.Energy, 20);
SetResistance(ResistanceType.Physical, 55, 65);
SetResistance(ResistanceType.Fire, 55, 65);
SetResistance(ResistanceType.Cold, 55, 65);
SetResistance(ResistanceType.Poison, 80, 90);
SetResistance(ResistanceType.Energy, 60, 75);
SetSkill(SkillName.Anatomy, 110.6, 116.1);
SetSkill(SkillName.EvalInt, 100.0, 114.4);
SetSkill(SkillName.Magery, 100.0);
SetSkill(SkillName.Meditation, 118.2, 127.8);
SetSkill(SkillName.MagicResist, 120.0);
SetSkill(SkillName.Tactics, 111.9, 134.5);
SetSkill(SkillName.Wrestling, 119.7, 128.9);
Fame = 22000;
Karma = -22000;
VirtualArmor = 60;
PackItem(new Arrow(Utility.RandomMinMax(100, 200)));
IronwoodCompositeBow Bow = new IronwoodCompositeBow();
Bow.Movable = false;
AddItem(Bow);
m_Scales = Utility.RandomMinMax(1, 2) + 7;
SetWeaponAbility(WeaponAbility.MortalStrike);
SetSpecialAbility(SpecialAbility.VenomousBite);
}
public Medusa(Serial serial)
: base(serial)
{
}
public override Type[] UniqueSAList
{
get { return new Type[] { typeof(Slither), typeof(IronwoodCompositeBow), typeof(Venom), typeof(PetrifiedSnake), typeof(StoneDragonsTooth), typeof(MedusaFloorTileAddonDeed) }; }
}
public override Type[] SharedSAList
{
get { return new Type[] { typeof(SummonersKilt) }; }
}
public override bool IgnoreYoungProtection { get { return true; } }
public override bool AutoDispel { get { return true; } }
public override double AutoDispelChance { get { return 1.0; } }
public override bool BardImmune { get { return true; } }
public override Poison PoisonImmune { get { return Poison.Lethal; } }
public override Poison HitPoison { get { return (0.8 >= Utility.RandomDouble() ? Poison.Deadly : Poison.Lethal); } }
public override int GetIdleSound() { return 1557; }
public override int GetAngerSound() { return 1554; }
public override int GetHurtSound() { return 1556; }
public override int GetDeathSound() { return 1555; }
public override void OnCarve(Mobile from, Corpse corpse, Item with)
{
int amount = Utility.Random(5) + 1;
corpse.DropItem(new MedusaDarkScales(amount));
if(0.20 > Utility.RandomDouble())
corpse.DropItem(new MedusaBlood());
base.OnCarve(from, corpse, with);
corpse.Carved = true;
}
public override void OnGotMeleeAttack(Mobile m)
{
base.OnGotMeleeAttack(m);
if (0.05 > Utility.RandomDouble())
ReleaseStoneMonster();
}
public override void OnDamagedBySpell(Mobile m)
{
base.OnDamagedBySpell(m);
if (0.05 > Utility.RandomDouble())
ReleaseStoneMonster();
}
public override void OnHarmfulSpell(Mobile from)
{
base.OnHarmfulSpell(from);
if (0.05 > Utility.RandomDouble())
ReleaseStoneMonster();
}
public void RemoveAffectedMobiles(Mobile toRemove)
{
if (m_TurnedToStone.Contains(toRemove))
m_TurnedToStone.Remove(toRemove);
}
public Mobile FindRandomMedusaTarget()
{
List<Mobile> list = new List<Mobile>();
IPooledEnumerable eable = this.GetMobilesInRange(12);
foreach (Mobile m in eable)
{
if ( m == null || m == this || m_TurnedToStone.Contains(m) || !CanBeHarmful(m) || !InLOS(m) || m.AccessLevel > AccessLevel.Player)
continue;
//Pets
if (m is BaseCreature && (((BaseCreature)m).GetMaster() is PlayerMobile))
list.Add(m);
//players
else if (m is PlayerMobile)
list.Add(m);
}
eable.Free();
if (list.Count == 0)
return null;
if (list.Count == 1)
return list[0];
return list[Utility.Random(list.Count)];
}
public static bool CheckBlockGaze(Mobile m)
{
if (m == null)
return false;
Item helm = m.FindItemOnLayer(Layer.Helm);
Item neck = m.FindItemOnLayer(Layer.Neck);
Item ear = m.FindItemOnLayer(Layer.Earrings);
Item shi = m.FindItemOnLayer(Layer.TwoHanded);
bool deflect = false;
int perc = 0;
if (helm != null)
{
if (helm is BaseArmor && ((BaseArmor)helm).GorgonLenseCharges > 0)
{
perc = GetScaleEffectiveness(((BaseArmor)helm).GorgonLenseType);
if (perc > Utility.Random(100))
{
((BaseArmor)helm).GorgonLenseCharges--;
deflect = true;
}
}
else if (helm is BaseClothing && ((BaseClothing)helm).GorgonLenseCharges > 0)
{
perc = GetScaleEffectiveness(((BaseClothing)helm).GorgonLenseType);
if (perc > Utility.Random(100))
{
((BaseClothing)helm).GorgonLenseCharges--;
deflect = true;
}
}
}
if (!deflect && shi != null && shi is BaseShield && ((BaseArmor)shi).GorgonLenseCharges > 0)
{
perc = GetScaleEffectiveness(((BaseArmor)shi).GorgonLenseType);
if (perc > Utility.Random(100))
{
((BaseArmor)shi).GorgonLenseCharges--;
deflect = true;
}
}
if (!deflect && neck != null)
{
if (neck is BaseArmor && ((BaseArmor)neck).GorgonLenseCharges > 0)
{
perc = GetScaleEffectiveness(((BaseArmor)neck).GorgonLenseType);
if (perc > Utility.Random(100))
{
((BaseArmor)neck).GorgonLenseCharges--;
deflect = true;
}
}
else if (neck is BaseJewel && ((BaseJewel)neck).GorgonLenseCharges > 0)
{
perc = GetScaleEffectiveness(((BaseJewel)neck).GorgonLenseType);
if (perc > Utility.Random(100))
{
((BaseJewel)neck).GorgonLenseCharges--;
deflect = true;
}
}
else if (neck is BaseClothing && ((BaseClothing)neck).GorgonLenseCharges > 0)
{
perc = GetScaleEffectiveness(((BaseClothing)neck).GorgonLenseType);
if (perc > Utility.Random(100))
{
((BaseClothing)neck).GorgonLenseCharges--;
deflect = true;
}
}
}
if (!deflect && ear != null)
{
if (ear is BaseJewel && ((BaseJewel)ear).GorgonLenseCharges > 0)
{
perc = GetScaleEffectiveness(((BaseJewel)ear).GorgonLenseType);
if (perc > Utility.Random(100))
{
((BaseJewel)ear).GorgonLenseCharges--;
deflect = true;
}
}
}
return deflect;
}
private static int GetScaleEffectiveness(LenseType type)
{
switch (type)
{
case LenseType.None: return 0;
case LenseType.Enhanced: return 100;
case LenseType.Regular: return 50;
case LenseType.Limited: return 15;
}
return 0;
}
public bool Carve(Mobile from, Item item)
{
if (m_Scales > 0)
{
if (DateTime.UtcNow < m_NextCarve)
{
from.SendLocalizedMessage(1112677); // The creature is still recovering from the previous harvest. Try again in a few seconds.
}
else
{
int amount = Math.Min(m_Scales, Utility.RandomMinMax(2, 3));
m_Scales -= amount;
Item scales = new MedusaLightScales(amount);
if (from.PlaceInBackpack(scales))
{
// You harvest magical resources from the creature and place it in your bag.
from.SendLocalizedMessage(1112676);
}
else
{
scales.MoveToWorld(from.Location, from.Map);
}
new Blood(0x122D).MoveToWorld(Location, Map);
m_NextCarve = DateTime.UtcNow + TimeSpan.FromMinutes(1.0);
return true;
}
}
else
from.SendLocalizedMessage(1112674); // There's nothing left to harvest from this creature.
return false;
}
public override void OnThink()
{
base.OnThink();
if (Combatant == null)
return;
if (m_StoneDelay < DateTime.UtcNow)
SpawnStone();
if (m_GazeDelay < DateTime.UtcNow)
DoGaze();
}
public void DoGaze()
{
Mobile target = FindRandomMedusaTarget();
Map map = Map;
if (map == null || target == null)
return;
if ((target is BaseCreature && ((BaseCreature)target).SummonMaster != this) || CanBeHarmful(target))
{
if (CheckBlockGaze(target))
{
if (GorgonLense.TotalCharges(target) == 0)
target.SendLocalizedMessage(1112600); // Your lenses crumble. You are no longer protected from Medusa's gaze!
else
target.SendLocalizedMessage(1112599); //Your Gorgon Lens deflect Medusa's petrifying gaze!
}
else
{
BaseCreature clone = new MedusaClone(target);
bool validLocation = false;
Point3D loc = Location;
for (int j = 0; !validLocation && j < 10; ++j)
{
int x = X + Utility.Random(10) - 1;
int y = Y + Utility.Random(10) - 1;
int z = map.GetAverageZ(x, y);
if (validLocation = map.CanFit(x, y, Z, 16, false, false))
loc = new Point3D(x, y, Z);
else if (validLocation = map.CanFit(x, y, z, 16, false, false))
loc = new Point3D(x, y, z);
}
Effects.SendLocationEffect(loc, target.Map, 0x37B9, 10, 5);
clone.Frozen = clone.Blessed = true;
clone.SolidHueOverride = 761;
target.Frozen = target.Blessed = true;
target.SolidHueOverride = 761;
//clone.MoveToWorld(loc, target.Map);
BaseCreature.Summon(clone, false, this, loc, 0, TimeSpan.FromMinutes(90));
if (target is BaseCreature && !((BaseCreature)target).Summoned && ((BaseCreature)target).GetMaster() != null)
((BaseCreature)target).GetMaster().SendLocalizedMessage(1113281, null, 43); // Your pet has been petrified!
else
target.SendLocalizedMessage(1112768); // You have been turned to stone!!!
new GazeTimer(target, clone, this, Utility.RandomMinMax(5, 10)).Start();
m_GazeDelay = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(45, 75));
m_Helpers.Add(clone);
m_TurnedToStone.Add(target);
BuffInfo.AddBuff(target, new BuffInfo(BuffIcon.MedusaStone, 1153790, 1153825));
return;
}
}
m_GazeDelay = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(25, 65));
}
public void SpawnStone()
{
DefragHelpers();
Map map = Map;
if (map == null)
return;
int stones = 0;
foreach (Mobile m in m_Helpers)
{
if (!(m is MedusaClone))
++stones;
}
if (stones >= 5)
return;
else
{
BaseCreature stone = GetRandomStoneMonster();
bool validLocation = false;
Point3D loc = Location;
for (int j = 0; !validLocation && j < 10; ++j)
{
int x = X + Utility.Random(10) - 1;
int y = Y + Utility.Random(10) - 1;
int z = map.GetAverageZ(x, y);
if (validLocation = map.CanFit(x, y, Z, 16, false, false))
loc = new Point3D(x, y, Z);
else if (validLocation = map.CanFit(x, y, z, 16, false, false))
loc = new Point3D(x, y, z);
}
BaseCreature.Summon(stone, false, this, loc, 0, TimeSpan.FromMinutes(90));
//stone.MoveToWorld(loc, map);
stone.Frozen = stone.Blessed = true;
stone.SolidHueOverride = 761;
stone.Combatant = null;
m_Helpers.Add(stone);
}
m_StoneDelay = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 150));
}
private void DefragHelpers()
{
List<Mobile> toDelete = new List<Mobile>();
foreach (Mobile m in m_Helpers)
{
if(m == null)
continue;
if (!m.Alive || m.Deleted)
toDelete.Add(m);
}
foreach (Mobile m in toDelete)
{
if (m_Helpers.Contains(m))
m_Helpers.Remove(m);
}
}
private BaseCreature GetRandomStoneMonster()
{
switch (Utility.Random(6))
{
default:
case 0: return new OphidianWarrior();
case 1: return new OphidianArchmage();
case 2: return new WailingBanshee();
case 3: return new OgreLord();
case 4: return new Dragon();
case 5: return new UndeadGargoyle();
}
}
public void ReleaseStoneMonster()
{
List<Mobile> stones = new List<Mobile>();
foreach (Mobile mob in m_Helpers)
{
if (!(mob is MedusaClone) && mob.Alive)
stones.Add(mob);
}
if(stones.Count == 0)
return;
Mobile m = stones[Utility.Random(stones.Count)];
if (m != null)
{
m.Frozen = m.Blessed = false;
m.SolidHueOverride = -1;
Mobile closest = null;
int dist = 12;
m_Helpers.Remove(m);
IPooledEnumerable eable = m.GetMobilesInRange(12);
foreach (Mobile targ in eable)
{
if (targ != null && targ.Player)
{
targ.SendLocalizedMessage(1112767, null, 43); // Medusa releases one of the petrified creatures!!
targ.Combatant = targ;
}
if (targ is PlayerMobile || (targ is BaseCreature && ((BaseCreature)targ).GetMaster() is PlayerMobile))
{
int d = (int)m.GetDistanceToSqrt(targ.Location);
if (d < dist)
{
dist = d;
closest = targ;
}
}
}
eable.Free();
if (closest != null)
m.Combatant = closest;
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.SuperBoss, 8);
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
if (Utility.RandomDouble() < 0.025)
c.DropItem(new MedusaStatue());
}
public override void OnAfterDelete()
{
foreach (Mobile m in m_Helpers)
{
if (m != null && !m.Deleted)
m.Delete();
}
base.OnAfterDelete();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
writer.Write((int)m_Scales);
writer.Write(m_Helpers.Count);
foreach (Mobile helper in m_Helpers)
writer.Write(helper);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
m_Scales = reader.ReadInt();
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
Mobile m = reader.ReadMobile();
if (m != null && m.Alive)
m_Helpers.Add(m);
}
}
public class GazeTimer : Timer
{
private Mobile target;
private Mobile clone;
private Medusa m_Medusa;
private int m_Count;
public GazeTimer(Mobile m, Mobile mc, Medusa medusa, int duration)
: base(TimeSpan.FromSeconds(duration), TimeSpan.FromSeconds(duration))
{
target = m;
clone = mc;
m_Medusa = medusa;
m_Count = 0;
}
protected override void OnTick()
{
++m_Count;
if (m_Count == 1 && target != null)
{
target.Frozen = false;
target.SolidHueOverride = -1;
target.Blessed = false;
m_Medusa.RemoveAffectedMobiles(target);
if (target is BaseCreature && !((BaseCreature)target).Summoned && ((BaseCreature)target).GetMaster() != null)
((BaseCreature)target).GetMaster().SendLocalizedMessage(1113285, null, 43); // Beware! A statue of your pet has been created!
BuffInfo.RemoveBuff(target, BuffIcon.MedusaStone);
}
else if (m_Count == 2 && clone != null)
{
clone.SolidHueOverride = -1;
clone.Frozen = clone.Blessed = false;
int dist = 12;
Mobile closest = null;
IPooledEnumerable eable = clone.GetMobilesInRange(12);
foreach (Mobile m in eable)
{
int d = (int)clone.GetDistanceToSqrt(m.Location);
if (m != null && m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile))
{
if (m.NetState != null)
{
m.Send(new RemoveMobile(clone));
m.NetState.Send(MobileIncoming.Create(m.NetState, m, clone));
m.SendLocalizedMessage(1112767); // Medusa releases one of the petrified creatures!!
}
if (d < dist)
{
dist = d;
closest = m;
}
}
}
eable.Free();
if (closest != null)
clone.Combatant = closest;
}
else
Stop();
}
}
}
public class MedusaClone : BaseCreature, IFreezable
{
public MedusaClone(Mobile m)
: base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
SolidHueOverride = 33;
Clone(m);
}
public MedusaClone(Serial serial)
: base(serial)
{
}
public override bool DeleteCorpseOnDeath
{
get
{
return true;
}
}
public override bool ReacquireOnMovement
{
get
{
return true;
}
}
public override bool AlwaysMurderer
{
get
{
return !Frozen;
}
}
public void Clone(Mobile m)
{
if (m == null)
{
Delete();
return;
}
Body = m.Body;
Str = m.Str;
Dex = m.Dex;
Int = m.Int;
Hits = m.HitsMax;
Hue = m.Hue;
Female = m.Female;
Name = m.Name;
NameHue = m.NameHue;
Title = m.Title;
Kills = m.Kills;
HairItemID = m.HairItemID;
HairHue = m.HairHue;
FacialHairItemID = m.FacialHairItemID;
FacialHairHue = m.FacialHairHue;
BaseSoundID = m.BaseSoundID;
for (int i = 0; i < m.Skills.Length; ++i)
{
Skills[i].Base = m.Skills[i].Base;
Skills[i].Cap = m.Skills[i].Cap;
}
for (int i = 0; i < m.Items.Count; i++)
{
if (m.Items[i].Layer != Layer.Backpack && m.Items[i].Layer != Layer.Mount && m.Items[i].Layer != Layer.Bank)
AddItem(CloneItem(m.Items[i]));
}
}
public Item CloneItem(Item item)
{
Item cloned = new Item(item.ItemID);
cloned.Layer = item.Layer;
cloned.Name = item.Name;
cloned.Hue = item.Hue;
cloned.Weight = item.Weight;
cloned.Movable = false;
return cloned;
}
public override void OnDoubleClick(Mobile from)
{
if (Frozen)
DisplayPaperdollTo(from);
else
base.OnDoubleClick(from);
}
public void OnRequestedAnimation(Mobile from)
{
if (Frozen)
{
from.Send(new UpdateStatueAnimation(this, 1, 31, 5));
}
}
public override void OnDelete()
{
Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3728, 10, 15, 5042);
base.OnDelete();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
Delete();
}
}
}
namespace Server.Commands
{
public class AddCloneCommands
{
public static void Initialize()
{
CommandSystem.Register("addclone", AccessLevel.Seer, new CommandEventHandler(AddClone_OnCommand));
}
[Description("")]
public static void AddClone_OnCommand(CommandEventArgs e)
{
BaseCreature clone = new MedusaClone(e.Mobile);
clone.Frozen = clone.Blessed = true;
clone.MoveToWorld(e.Mobile.Location, e.Mobile.Map);
}
}
}

View File

@@ -0,0 +1,123 @@
using System;
using Server.Engines.CannedEvil;
using Server.Items;
using System.Collections.Generic;
namespace Server.Mobiles
{
public class Mephitis : BaseChampion
{
[Constructable]
public Mephitis()
: base(AIType.AI_Melee)
{
Body = 173;
Name = "Mephitis";
BaseSoundID = 0x183;
SetStr(505, 1000);
SetDex(102, 300);
SetInt(402, 600);
SetHits(12000);
SetStam(105, 600);
SetDamage(21, 33);
SetDamageType(ResistanceType.Physical, 50);
SetDamageType(ResistanceType.Poison, 50);
SetResistance(ResistanceType.Physical, 75, 80);
SetResistance(ResistanceType.Fire, 60, 70);
SetResistance(ResistanceType.Cold, 60, 70);
SetResistance(ResistanceType.Poison, 100);
SetResistance(ResistanceType.Energy, 60, 70);
SetSkill(SkillName.MagicResist, 70.7, 140.0);
SetSkill(SkillName.Tactics, 97.6, 100.0);
SetSkill(SkillName.Wrestling, 97.6, 100.0);
Fame = 22500;
Karma = -22500;
VirtualArmor = 80;
SetSpecialAbility(SpecialAbility.Webbing);
ForceActiveSpeed = 0.3;
ForcePassiveSpeed = 0.6;
}
public Mephitis(Serial serial)
: base(serial)
{
}
public override ChampionSkullType SkullType
{
get
{
return ChampionSkullType.Venom;
}
}
public override Type[] UniqueList
{
get
{
return new Type[] { typeof(Calm) };
}
}
public override Type[] SharedList
{
get
{
return new Type[] { typeof(OblivionsNeedle), typeof(ANecromancerShroud) };
}
}
public override Type[] DecorativeList
{
get
{
return new Type[] { typeof(Web), typeof(MonsterStatuette) };
}
}
public override MonsterStatuetteType[] StatueTypes
{
get
{
return new MonsterStatuetteType[] { MonsterStatuetteType.Spider };
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Lethal;
}
}
public override Poison HitPoison
{
get
{
return Poison.Lethal;
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.UltraRich, 4);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,347 @@
using System;
using System.Linq;
using Server.Items;
using Server.Network;
using Server.Spells;
namespace Server.Mobiles
{
[CorpseName("a monstrous interred grizzle corpse")]
public class MonstrousInterredGrizzle : BasePeerless
{
private static readonly int[] m_Tiles = new int[]
{
-2, 0,
2, 0,
2, -2,
2, 2,
-2, -2,
-2, 2,
0, 2,
1, 0,
0, -2
};
private readonly DateTime m_NextDrop = DateTime.UtcNow;
[Constructable]
public MonstrousInterredGrizzle()
: base(AIType.AI_Spellweaving, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Name = "a monstrous interred grizzle";
Body = 0x103;
BaseSoundID = 589;
SetStr(1198, 1207);
SetDex(127, 135);
SetInt(595, 646);
SetHits(50000);
SetDamage(27, 31);
SetDamageType(ResistanceType.Physical, 60);
SetDamageType(ResistanceType.Fire, 20);
SetDamageType(ResistanceType.Energy, 20);
SetResistance(ResistanceType.Physical, 48, 52);
SetResistance(ResistanceType.Fire, 77, 82);
SetResistance(ResistanceType.Cold, 56, 61);
SetResistance(ResistanceType.Poison, 32, 40);
SetResistance(ResistanceType.Energy, 69, 71);
SetSkill(SkillName.Wrestling, 112.6, 116.9);
SetSkill(SkillName.Tactics, 118.5, 119.2);
SetSkill(SkillName.MagicResist, 120);
SetSkill(SkillName.Anatomy, 111.0, 111.7);
SetSkill(SkillName.Magery, 100.0);
SetSkill(SkillName.EvalInt, 100);
SetSkill(SkillName.Meditation, 100);
SetSkill(SkillName.Spellweaving, 100.0);
Fame = 24000;
Karma = -24000;
VirtualArmor = 80;
PackResources(8);
PackTalismans(5);
for (int i = 0; i < Utility.RandomMinMax(1, 6); i++)
{
PackItem(Loot.RandomScroll(0, Loot.ArcanistScrollTypes.Length, SpellbookType.Arcanist));
}
SetSpecialAbility(SpecialAbility.HowlOfCacophony);
}
public MonstrousInterredGrizzle(Serial serial)
: base(serial)
{
}
public override bool GivesMLMinorArtifact
{
get
{
return true;
}
}
public override int TreasureMapLevel
{
get
{
return 5;
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.AosSuperBoss, 8);
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
c.DropItem(new GrizzledBones());
switch (Utility.Random(4))
{
case 0:
c.DropItem(new TombstoneOfTheDamned());
break;
case 1:
c.DropItem(new GlobOfMonstreousInterredGrizzle());
break;
case 2:
c.DropItem(new MonsterousInterredGrizzleMaggots());
break;
case 3:
c.DropItem(new GrizzledSkullCollection());
break;
}
if (Utility.RandomDouble() < 0.6)
c.DropItem(new ParrotItem());
if (Utility.RandomDouble() < 0.05)
c.DropItem(new GrizzledMareStatuette());
if (Utility.RandomDouble() < 0.05)
{
switch (Utility.Random(5))
{
case 0:
c.DropItem(new GrizzleGauntlets());
break;
case 1:
c.DropItem(new GrizzleGreaves());
break;
case 2:
c.DropItem(new GrizzleHelm());
break;
case 3:
c.DropItem(new GrizzleTunic());
break;
case 4:
c.DropItem(new GrizzleVambraces());
break;
}
}
}
public override int GetDeathSound()
{
return 0x57F;
}
public override int GetAttackSound()
{
return 0x580;
}
public override int GetIdleSound()
{
return 0x581;
}
public override int GetAngerSound()
{
return 0x582;
}
public override int GetHurtSound()
{
return 0x583;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void OnDamage(int amount, Mobile from, bool willKill)
{
if (Utility.RandomDouble() < 0.06)
SpillAcid(null, Utility.RandomMinMax(1, 3));
base.OnDamage(amount, from, willKill);
}
public override Item NewHarmfulItem()
{
return new InfernalOoze(this, Utility.RandomBool());
}
}
public class InfernalOoze : Item
{
private bool m_Corrosive;
private int m_Damage;
private Mobile m_Owner;
private Timer m_Timer;
private DateTime m_StartTime;
public InfernalOoze(Mobile owner)
: this(owner, false)
{
}
[Constructable]
public InfernalOoze(Mobile owner, bool corrosive, int damage = 40)
: base(0x122A)
{
Movable = false;
m_Owner = owner;
Hue = 0x95;
m_Damage = damage;
m_Corrosive = corrosive;
m_StartTime = DateTime.UtcNow;
m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), OnTick);
}
[CommandProperty(AccessLevel.GameMaster)]
public bool Corrosive
{
get { return m_Corrosive; }
set { m_Corrosive = value; }
}
private void OnTick()
{
if (ItemID == 0x122A && m_StartTime + TimeSpan.FromSeconds(30) < DateTime.UtcNow)
{
ItemID++;
}
else if (m_StartTime + TimeSpan.FromSeconds(35) < DateTime.UtcNow)
{
Delete();
return;
}
if (m_Owner == null)
return;
if (!Deleted && Map != Map.Internal && Map != null)
{
foreach (var m in SpellHelper.AcquireIndirectTargets(m_Owner, Location, Map, 0).OfType<Mobile>())
{
OnMoveOver(m);
}
}
}
public override bool OnMoveOver(Mobile m)
{
if (Map == null)
return base.OnMoveOver(m);
if ((m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile) || m.Player)
{
Damage(m);
}
return base.OnMoveOver(m);
}
public virtual void Damage(Mobile m)
{
if (m_Corrosive)
{
for (int i = 0; i < m.Items.Count; i++)
{
IDurability item = m.Items[i] as IDurability;
if (item != null && Utility.RandomDouble() < 0.25)
{
if (item.HitPoints > 10)
item.HitPoints -= 10;
else
item.HitPoints -= 1;
}
}
}
else
{
int dmg = m_Damage;
if (m is PlayerMobile)
{
PlayerMobile pm = m as PlayerMobile;
dmg = (int)BalmOfProtection.HandleDamage(pm, dmg);
AOS.Damage(m, m_Owner, dmg, 0, 0, 0, 100, 0);
}
else
{
AOS.Damage(m, m_Owner, dmg, 0, 0, 0, 100, 0);
}
}
}
public override void Delete()
{
base.Delete();
if (m_Timer != null)
{
m_Timer.Stop();
m_Timer = null;
}
}
public InfernalOoze(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
Delete();
}
}
}

View File

@@ -0,0 +1,42 @@
using System;
namespace Server.Items
{
public class EyeOfNavrey : Item
{
[Constructable]
public EyeOfNavrey()
: base(0x318D)
{
this.Weight = 1;
this.Hue = 68;
this.LootType = LootType.Blessed;
}
public EyeOfNavrey(Serial serial)
: base(serial)
{
}
public override int LabelNumber
{
get
{
return 1095154;
}
}// Eye of Navrey Night-Eyes
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,185 @@
using System;
using System.Collections.Generic;
using Server.Engines.Quests;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName("a navrey corpse")]
public class Navrey : BaseCreature
{
private NavreysController m_Spawner;
[CommandProperty(AccessLevel.GameMaster)]
public bool UsedPillars { get; set; }
private static readonly Type[] m_Artifact = new Type[]
{
typeof(NightEyes),
typeof(Tangle1)
};
[Constructable]
public Navrey(NavreysController spawner)
: base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4)
{
m_Spawner = spawner;
Name = "Navrey Night-Eyes";
Body = 735;
BaseSoundID = 389;
SetStr(1000, 1500);
SetDex(200, 250);
SetInt(150, 200);
SetHits(30000, 35000);
SetDamage(25, 40);
SetDamageType(ResistanceType.Physical, 50);
SetDamageType(ResistanceType.Fire, 25);
SetDamageType(ResistanceType.Energy, 25);
SetResistance(ResistanceType.Physical, 55, 65);
SetResistance(ResistanceType.Fire, 45, 55);
SetResistance(ResistanceType.Cold, 60, 70);
SetResistance(ResistanceType.Poison, 100);
SetResistance(ResistanceType.Energy, 65, 80);
SetSkill(SkillName.Anatomy, 50.0, 80.0);
SetSkill(SkillName.EvalInt, 90.0, 100.0);
SetSkill(SkillName.Magery, 90.0, 100.0);
SetSkill(SkillName.MagicResist, 100.0, 130.0);
SetSkill(SkillName.Meditation, 80.0, 100.0);
SetSkill(SkillName.Poisoning, 100.0);
SetSkill(SkillName.Tactics, 90.0, 100.0);
SetSkill(SkillName.Wrestling, 91.6, 98.2);
Fame = 24000;
Karma = -24000;
VirtualArmor = 90;
for (int i = 0; i < Utility.RandomMinMax(1, 3); i++)
{
PackItem(Loot.RandomScroll(0, Loot.MysticismScrollTypes.Length, SpellbookType.Mystic));
}
SetSpecialAbility(SpecialAbility.Webbing);
}
public Navrey(Serial serial)
: base(serial)
{
}
public override double TeleportChance { get { return 0; } }
public override bool AlwaysMurderer { get { return true; } }
public override Poison PoisonImmune { get { return Poison.Parasitic; } }
public override Poison HitPoison { get { return Poison.Lethal; } }
public override int Meat { get { return 1; } }
public static void DistributeRandomArtifact(BaseCreature bc, Type[] typelist)
{
int random = Utility.Random(typelist.Length);
Item item = Loot.Construct(typelist[random]);
DistributeArtifact(DemonKnight.FindRandomPlayer(bc), item);
}
public static void DistributeArtifact(Mobile to, Item artifact)
{
if (artifact == null)
return;
if (to != null)
{
Container pack = to.Backpack;
if (pack == null || !pack.TryDropItem(to, artifact, false))
to.BankBox.DropItem(artifact);
to.SendLocalizedMessage(502088); // A special gift has been placed in your backpack.
}
else
{
artifact.Delete();
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.AosSuperBoss, 3);
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
if (m_Spawner != null)
m_Spawner.OnNavreyKilled();
if (Utility.RandomBool())
c.AddItem(new UntranslatedAncientTome());
if (0.1 >= Utility.RandomDouble())
c.AddItem(ScrollOfTranscendence.CreateRandom(30, 30));
if (0.1 >= Utility.RandomDouble())
c.AddItem(new TatteredAncientScroll());
if (Utility.RandomDouble() < 0.10)
c.DropItem(new LuckyCoin());
if (Utility.RandomDouble() < 0.025)
DistributeRandomArtifact(this, m_Artifact);
// distribute quest items for the 'Green with Envy' quest given by Vernix
List<DamageStore> rights = GetLootingRights();
for (int i = rights.Count - 1; i >= 0; --i)
{
DamageStore ds = rights[i];
if (!ds.m_HasRight)
rights.RemoveAt(i);
}
// for each with looting rights... give an eye of navrey if they have the quest
foreach (DamageStore d in rights)
{
PlayerMobile pm = d.m_Mobile as PlayerMobile;
if (null != pm)
{
foreach (BaseQuest quest in pm.Quests)
{
if (quest is GreenWithEnvyQuest)
{
Container pack = pm.Backpack;
Item item = new EyeOfNavrey();
if (pack == null || !pack.TryDropItem(pm, item, false))
pm.BankBox.DropItem(item);
pm.SendLocalizedMessage(1095155); // As Navrey Night-Eyes dies, you find and claim one of her eyes as proof of her demise.
break;
}
}
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)1);
writer.Write((Item)m_Spawner);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (version >= 1)
m_Spawner = reader.ReadItem() as NavreysController;
}
}
}

View File

@@ -0,0 +1,387 @@
using System;
using Server.Engines.CannedEvil;
using Server.Items;
namespace Server.Mobiles
{
public class Neira : BaseChampion
{
private const double SpeedBoostScalar = 1.2;
private bool m_SpeedBoost;
[Constructable]
public Neira()
: base(AIType.AI_Mage)
{
Name = "Neira";
Title = "the necromancer";
Body = 401;
Hue = 0x83EC;
SetStr(305, 425);
SetDex(72, 150);
SetInt(505, 750);
SetHits(4800);
SetStam(102, 300);
SetDamage(25, 35);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 25, 30);
SetResistance(ResistanceType.Fire, 35, 45);
SetResistance(ResistanceType.Cold, 50, 60);
SetResistance(ResistanceType.Poison, 30, 40);
SetResistance(ResistanceType.Energy, 20, 30);
SetSkill(SkillName.EvalInt, 120.0);
SetSkill(SkillName.Magery, 120.0);
SetSkill(SkillName.Meditation, 120.0);
SetSkill(SkillName.MagicResist, 150.0);
SetSkill(SkillName.Tactics, 97.6, 100.0);
SetSkill(SkillName.Wrestling, 97.6, 100.0);
Fame = 22500;
Karma = -22500;
VirtualArmor = 30;
Female = true;
Item shroud = new HoodedShroudOfShadows();
shroud.Movable = false;
AddItem(shroud);
Scimitar weapon = new Scimitar();
weapon.Skill = SkillName.Wrestling;
weapon.Hue = 38;
weapon.Movable = false;
AddItem(weapon);
//new SkeletalMount().Rider = this;
AddItem(new VirtualMountItem(this));
}
public Neira(Serial serial)
: base(serial)
{
}
public override ChampionSkullType SkullType
{
get
{
return ChampionSkullType.Death;
}
}
public override Type[] UniqueList
{
get
{
return new Type[] { typeof(ShroudOfDeceit) };
}
}
public override Type[] SharedList
{
get
{
return new Type[]
{
typeof(ANecromancerShroud),
typeof(CaptainJohnsHat),
typeof(DetectiveBoots)
};
}
}
public override Type[] DecorativeList
{
get
{
return new Type[] { typeof(WallBlood), typeof(TatteredAncientMummyWrapping) };
}
}
public override MonsterStatuetteType[] StatueTypes
{
get
{
return new MonsterStatuetteType[] { };
}
}
public override bool AlwaysMurderer
{
get
{
return true;
}
}
public override bool BardImmune
{
get
{
return !Core.SE;
}
}
public override bool Unprovokable
{
get
{
return Core.SE;
}
}
public override bool Uncalmable
{
get
{
return Core.SE;
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Deadly;
}
}
public override bool ShowFameTitle
{
get
{
return false;
}
}
public override bool ClickTitle
{
get
{
return false;
}
}
public override bool ForceStayHome { get { return true; } }
public override void GenerateLoot()
{
AddLoot(LootPack.UltraRich, 3);
AddLoot(LootPack.Meager);
}
public override bool OnBeforeDeath()
{
IMount mount = Mount;
if (mount != null)
mount.Rider = null;
if (mount is Mobile)
((Mobile)mount).Delete();
return base.OnBeforeDeath();
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
NecromancerSpellbook book = new NecromancerSpellbook();
book.Content = (1ul << book.BookCount) - 1;
c.DropItem(book);
}
public override void OnDamage(int amount, Mobile from, bool willKill)
{
CheckSpeedBoost();
base.OnDamage(amount, from, willKill);
}
public override void OnGaveMeleeAttack(Mobile defender)
{
base.OnGaveMeleeAttack(defender);
if (0.1 >= Utility.RandomDouble()) // 10% chance to drop or throw an unholy bone
AddUnholyBone(defender, 0.25);
CheckSpeedBoost();
}
public override void OnGotMeleeAttack(Mobile attacker)
{
base.OnGotMeleeAttack(attacker);
if (0.1 >= Utility.RandomDouble()) // 10% chance to drop or throw an unholy bone
AddUnholyBone(attacker, 0.25);
}
public override void AlterDamageScalarFrom(Mobile caster, ref double scalar)
{
base.AlterDamageScalarFrom(caster, ref scalar);
if (0.1 >= Utility.RandomDouble()) // 10% chance to throw an unholy bone
AddUnholyBone(caster, 1.0);
}
public void AddUnholyBone(Mobile target, double chanceToThrow)
{
if (Map == null)
return;
if (chanceToThrow >= Utility.RandomDouble())
{
Direction = GetDirectionTo(target);
MovingEffect(target, 0xF7E, 10, 1, true, false, 0x496, 0);
new DelayTimer(this, target).Start();
}
else
{
new UnholyBone().MoveToWorld(Location, Map);
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)1); // version
writer.Write(m_SpeedBoost);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch( version )
{
case 1:
{
m_SpeedBoost = reader.ReadBool();
break;
}
}
}
private void CheckSpeedBoost()
{
if (Hits < (HitsMax / 4))
{
if (!m_SpeedBoost)
{
ActiveSpeed /= SpeedBoostScalar;
PassiveSpeed /= SpeedBoostScalar;
m_SpeedBoost = true;
}
}
else if (m_SpeedBoost)
{
ActiveSpeed *= SpeedBoostScalar;
PassiveSpeed *= SpeedBoostScalar;
m_SpeedBoost = false;
}
}
private class VirtualMount : IMount
{
private readonly VirtualMountItem m_Item;
public VirtualMount(VirtualMountItem item)
{
m_Item = item;
}
public Mobile Rider
{
get
{
return m_Item.Rider;
}
set
{
}
}
public virtual void OnRiderDamaged(Mobile from, ref int amount, bool willKill)
{
}
}
private class VirtualMountItem : Item, IMountItem
{
private readonly VirtualMount m_Mount;
private Mobile m_Rider;
public VirtualMountItem(Mobile mob)
: base(0x3EBB)
{
Layer = Layer.Mount;
Movable = false;
m_Rider = mob;
m_Mount = new VirtualMount(this);
}
public VirtualMountItem(Serial serial)
: base(serial)
{
m_Mount = new VirtualMount(this);
}
public Mobile Rider
{
get
{
return m_Rider;
}
}
public IMount Mount
{
get
{
return m_Mount;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
writer.Write((Mobile)m_Rider);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
m_Rider = reader.ReadMobile();
if (m_Rider == null)
Delete();
}
}
private class DelayTimer : Timer
{
private readonly Mobile m_Mobile;
private readonly Mobile m_Target;
public DelayTimer(Mobile m, Mobile target)
: base(TimeSpan.FromSeconds(1.0))
{
m_Mobile = m;
m_Target = target;
}
protected override void OnTick()
{
if (m_Mobile.CanBeHarmful(m_Target))
{
m_Mobile.DoHarmful(m_Target);
AOS.Damage(m_Target, m_Mobile, Utility.RandomMinMax(10, 20), 100, 0, 0, 0, 0);
new UnholyBone().MoveToWorld(m_Target.Location, m_Target.Map);
}
}
}
}
}

View File

@@ -0,0 +1,520 @@
using System;
using System.Collections;
using Server.Engines.CannedEvil;
using Server.Items;
using System.Collections.Generic;
using Server.Network;
using System.Linq;
namespace Server.Mobiles
{
[CorpseName("a Primeval Lich corpse")]
public class PrimevalLich : BaseChampion
{
private DateTime m_NextDiscordTime;
private DateTime m_NextAbilityTime;
private Timer m_Timer;
[Constructable]
public PrimevalLich()
: base(AIType.AI_NecroMage)
{
Name = "Primeval Lich";
Body = 830;
SetStr(500);
SetDex(100);
SetInt(1000);
SetHits(30000);
SetMana(5000);
SetDamage(17, 21);
SetDamageType(ResistanceType.Physical, 20);
SetDamageType(ResistanceType.Fire, 20);
SetDamageType(ResistanceType.Cold, 20);
SetDamageType(ResistanceType.Energy, 20);
SetDamageType(ResistanceType.Poison, 20);
SetResistance(ResistanceType.Physical, 30);
SetResistance(ResistanceType.Fire, 30);
SetResistance(ResistanceType.Cold, 30);
SetResistance(ResistanceType.Poison, 30);
SetResistance(ResistanceType.Energy, 20);
SetSkill(SkillName.EvalInt, 90, 120.0);
SetSkill(SkillName.Magery, 90, 120.0);
SetSkill(SkillName.Meditation, 100, 120.0);
SetSkill(SkillName.Necromancy, 120.0);
SetSkill(SkillName.SpiritSpeak, 120.0);
SetSkill(SkillName.MagicResist, 120, 140.0);
SetSkill(SkillName.Tactics, 90, 120);
SetSkill(SkillName.Wrestling, 100, 120);
Fame = 28000;
Karma = -28000;
VirtualArmor = 80;
m_Timer = new TeleportTimer(this);
m_Timer.Start();
}
public PrimevalLich(Serial serial)
: base(serial)
{
}
public override int GetAttackSound() { return 0x61E; }
public override int GetDeathSound() { return 0x61F; }
public override int GetHurtSound() { return 0x620; }
public override int GetIdleSound() { return 0x621; }
public override bool CanRummageCorpses { get { return true; } }
public override bool BleedImmune { get { return true; } }
public override Poison PoisonImmune { get { return Poison.Lethal; } }
public override bool ShowFameTitle { get { return false; } }
public override bool ClickTitle { get { return false; } }
public override ChampionSkullType SkullType { get { return ChampionSkullType.None; } }
public override Type[] UniqueList
{
get
{
return new Type[] { typeof(BansheesCall), typeof(CastOffZombieSkin), typeof(ChannelersDefender), typeof(LightsRampart) };
}
}
public override Type[] SharedList
{
get
{
return new Type[] { typeof(TokenOfHolyFavor), typeof(TheMostKnowledgePerson), typeof(LieutenantOfTheBritannianRoyalGuard), typeof(ProtectoroftheBattleMage) };
}
}
public override Type[] DecorativeList
{
get
{
return new Type[] { typeof(MummifiedCorpse) };
}
}
public override MonsterStatuetteType[] StatueTypes
{
get
{
return new MonsterStatuetteType[] { };
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.UltraRich, 3);
AddLoot(LootPack.Meager);
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
c.DropItem(new PrimalLichDust());
c.DropItem(new RisingColossusScroll());
}
public void ChangeCombatant()
{
ForceReacquire();
BeginFlee(TimeSpan.FromSeconds(2.5));
}
public override void OnThink()
{
if (m_NextDiscordTime <= DateTime.UtcNow)
{
Mobile target = Combatant as Mobile;
if (target != null && target.InRange(this, 8) && CanBeHarmful(target))
Discord(target);
}
}
public override void OnGotMeleeAttack(Mobile attacker)
{
base.OnGotMeleeAttack(attacker);
if (0.05 >= Utility.RandomDouble())
SpawnShadowDwellers(attacker);
}
public override void AlterDamageScalarFrom(Mobile caster, ref double scalar)
{
if (0.05 >= Utility.RandomDouble())
SpawnShadowDwellers(caster);
}
public override void OnGaveMeleeAttack(Mobile defender)
{
base.OnGaveMeleeAttack(defender);
if (DateTime.UtcNow > m_NextAbilityTime && 0.2 > Utility.RandomDouble())
{
switch (Utility.Random(2))
{
case 0: BlastRadius(); break;
case 1: Lightning(); break;
}
m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(25, 35));
}
}
#region Blast Radius
private static readonly int BlastRange = 16;
private static readonly double[] BlastChance = new double[]
{
0.0, 0.0, 0.05, 0.95, 0.95, 0.95, 0.05, 0.95, 0.95,
0.95, 0.05, 0.95, 0.95, 0.95, 0.05, 0.95, 0.95
};
private void BlastRadius()
{
// TODO: Based on OSI taken videos, not accurate, but an aproximation
Point3D loc = Location;
for (int x = -BlastRange; x <= BlastRange; x++)
{
for (int y = -BlastRange; y <= BlastRange; y++)
{
Point3D p = new Point3D(loc.X + x, loc.Y + y, loc.Z);
int dist = (int)Math.Round(Utility.GetDistanceToSqrt(loc, p));
if (dist <= BlastRange && BlastChance[dist] > Utility.RandomDouble())
{
Timer.DelayCall(TimeSpan.FromSeconds(0.1 * dist), new TimerCallback(
delegate
{
int hue = Utility.RandomList(90, 95);
Effects.SendPacket(loc, Map, new HuedEffect(EffectType.FixedXYZ, Serial.Zero, Serial.Zero, 0x3709, p, p, 20, 30, true, false, hue, 4));
}
));
}
}
}
PlaySound(0x64C);
IPooledEnumerable eable = GetMobilesInRange(BlastRange);
foreach (Mobile m in eable)
{
if (this != m && GetDistanceToSqrt(m) <= BlastRange && CanBeHarmful(m))
{
if (m is ShadowDweller)
continue;
DoHarmful(m);
double damage = m.Hits * 0.6;
if (damage < 100.0)
damage = 100.0;
else if (damage > 200.0)
damage = 200.0;
DoHarmful(m);
AOS.Damage(m, this, (int)damage, 0, 0, 0, 0, 100);
}
}
eable.Free();
}
#endregion
#region Lightning
private void Lightning()
{
int count = 0;
IPooledEnumerable eable = GetMobilesInRange(BlastRange);
foreach (Mobile m in eable)
{
if (m is ShadowDweller)
continue;
if (m.IsPlayer() && GetDistanceToSqrt(m) <= BlastRange && CanBeHarmful(m))
{
DoHarmful(m);
Effects.SendBoltEffect(m, false, 0);
Effects.PlaySound(m, m.Map, 0x51D);
double damage = m.Hits * 0.6;
if (damage < 100.0)
damage = 100.0;
else if (damage > 200.0)
damage = 200.0;
AOS.Damage(m, this, (int)damage, 0, 0, 0, 0, 100);
count++;
if (count >= 6)
break;
}
}
eable.Free();
}
#endregion
#region Teleport
private class TeleportTimer : Timer
{
private Mobile m_Owner;
private static int[] m_Offsets = new int[]
{
-1, -1,
-1, 0,
-1, 1,
0, -1,
0, 1,
1, -1,
1, 0,
1, 1
};
public TeleportTimer(Mobile owner)
: base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0))
{
m_Owner = owner;
}
protected override void OnTick()
{
if (m_Owner.Deleted)
{
Stop();
return;
}
Map map = m_Owner.Map;
if (map == null)
return;
if (0.25 < Utility.RandomDouble())
return;
Mobile toTeleport = null;
foreach (Mobile m in m_Owner.GetMobilesInRange(BlastRange))
{
if (m != m_Owner && m.IsPlayer() && m_Owner.CanBeHarmful(m) && m_Owner.CanSee(m))
{
if (m is ShadowDweller)
continue;
toTeleport = m;
break;
}
}
if (toTeleport != null)
{
int offset = Utility.Random(8) * 2;
Point3D to = m_Owner.Location;
for (int i = 0; i < m_Offsets.Length; i += 2)
{
int x = m_Owner.X + m_Offsets[(offset + i) % m_Offsets.Length];
int y = m_Owner.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length];
if (map.CanSpawnMobile(x, y, m_Owner.Z))
{
to = new Point3D(x, y, m_Owner.Z);
break;
}
else
{
int z = map.GetAverageZ(x, y);
if (map.CanSpawnMobile(x, y, z))
{
to = new Point3D(x, y, z);
break;
}
}
}
Mobile m = toTeleport;
Point3D from = m.Location;
m.Location = to;
Server.Spells.SpellHelper.Turn(m_Owner, toTeleport);
Server.Spells.SpellHelper.Turn(toTeleport, m_Owner);
m.ProcessDelta();
Effects.SendLocationParticles(EffectItem.Create(from, m.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, 2023);
Effects.SendLocationParticles(EffectItem.Create(to, m.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, 5023);
m.PlaySound(0x1FE);
m_Owner.Combatant = toTeleport;
}
}
}
#endregion
#region Unholy Touch
private static Dictionary<Mobile, Timer> m_UnholyTouched = new Dictionary<Mobile, Timer>();
public void Discord(Mobile target)
{
if (Utility.RandomDouble() < 0.9 && !m_UnholyTouched.ContainsKey(target))
{
double scalar = -((20 - (target.Skills[SkillName.MagicResist].Value / 10)) / 100);
ArrayList mods = new ArrayList();
if (target.PhysicalResistance > 0)
{
mods.Add(new ResistanceMod(ResistanceType.Physical, (int)((double)target.PhysicalResistance * scalar)));
}
if (target.FireResistance > 0)
{
mods.Add(new ResistanceMod(ResistanceType.Fire, (int)((double)target.FireResistance * scalar)));
}
if (target.ColdResistance > 0)
{
mods.Add(new ResistanceMod(ResistanceType.Cold, (int)((double)target.ColdResistance * scalar)));
}
if (target.PoisonResistance > 0)
{
mods.Add(new ResistanceMod(ResistanceType.Poison, (int)((double)target.PoisonResistance * scalar)));
}
if (target.EnergyResistance > 0)
{
mods.Add(new ResistanceMod(ResistanceType.Energy, (int)((double)target.EnergyResistance * scalar)));
}
for (int i = 0; i < target.Skills.Length; ++i)
{
if (target.Skills[i].Value > 0)
{
mods.Add(new DefaultSkillMod((SkillName)i, true, target.Skills[i].Value * scalar));
}
}
target.PlaySound(0x458);
ApplyMods(target, mods);
m_UnholyTouched[target] = Timer.DelayCall(TimeSpan.FromSeconds(30), new TimerCallback(
delegate
{
ClearMods(target, mods);
m_UnholyTouched.Remove(target);
}));
}
m_NextDiscordTime = DateTime.UtcNow + TimeSpan.FromSeconds(5 + Utility.RandomDouble() * 22);
}
private static void ApplyMods(Mobile from, ArrayList mods)
{
for (int i = 0; i < mods.Count; ++i)
{
object mod = mods[i];
if (mod is ResistanceMod)
from.AddResistanceMod((ResistanceMod)mod);
else if (mod is StatMod)
from.AddStatMod((StatMod)mod);
else if (mod is SkillMod)
from.AddSkillMod((SkillMod)mod);
}
}
private static void ClearMods(Mobile from, ArrayList mods)
{
for (int i = 0; i < mods.Count; ++i)
{
object mod = mods[i];
if (mod is ResistanceMod)
from.RemoveResistanceMod((ResistanceMod)mod);
else if (mod is StatMod)
from.RemoveStatMod(((StatMod)mod).Name);
else if (mod is SkillMod)
from.RemoveSkillMod((SkillMod)mod);
}
}
#endregion
public void SpawnShadowDwellers(Mobile target)
{
Map map = Map;
if (map == null)
return;
int newShadowDwellers = Utility.RandomMinMax(2, 3);
for (int i = 0; i < newShadowDwellers; ++i)
{
ShadowDweller shadowdweller = new ShadowDweller();
shadowdweller.Team = Team;
shadowdweller.FightMode = FightMode.Closest;
bool validLocation = false;
Point3D loc = Location;
for (int j = 0; !validLocation && j < 10; ++j)
{
int x = X + Utility.Random(3) - 1;
int y = Y + Utility.Random(3) - 1;
int z = map.GetAverageZ(x, y);
if (validLocation = map.CanFit(x, y, Z, 16, false, false))
loc = new Point3D(x, y, Z);
else if (validLocation = map.CanFit(x, y, z, 16, false, false))
loc = new Point3D(x, y, z);
}
shadowdweller.MoveToWorld(loc, map);
shadowdweller.Combatant = target;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
m_Timer = new TeleportTimer(this);
m_Timer.Start();
}
}
}

View File

@@ -0,0 +1,223 @@
using System;
using System.Collections;
using Server.Engines.CannedEvil;
using Server.Items;
namespace Server.Mobiles
{
public class Rikktor : BaseChampion
{
[Constructable]
public Rikktor()
: base(AIType.AI_Melee)
{
Body = 172;
Name = "Rikktor";
SetStr(701, 900);
SetDex(201, 350);
SetInt(51, 100);
SetHits(15000);
SetStam(203, 650);
SetDamage(28, 55);
SetDamageType(ResistanceType.Physical, 25);
SetDamageType(ResistanceType.Fire, 50);
SetDamageType(ResistanceType.Energy, 25);
SetResistance(ResistanceType.Physical, 80, 90);
SetResistance(ResistanceType.Fire, 80, 90);
SetResistance(ResistanceType.Cold, 30, 40);
SetResistance(ResistanceType.Poison, 80, 90);
SetResistance(ResistanceType.Energy, 80, 90);
SetSkill(SkillName.Anatomy, 100.0);
SetSkill(SkillName.MagicResist, 140.2, 160.0);
SetSkill(SkillName.Tactics, 100.0);
SetSkill(SkillName.Wrestling, 118.4, 123.9);
Fame = 22500;
Karma = -22500;
VirtualArmor = 130;
ForceActiveSpeed = 0.35;
ForcePassiveSpeed = 0.7;
}
public Rikktor(Serial serial)
: base(serial)
{
}
public override ChampionSkullType SkullType
{
get
{
return ChampionSkullType.Power;
}
}
public override Type[] UniqueList
{
get
{
return new Type[] { typeof(CrownOfTalKeesh) };
}
}
public override Type[] SharedList
{
get
{
return new Type[]
{
typeof(TheMostKnowledgePerson),
typeof(BraveKnightOfTheBritannia),
typeof(LieutenantOfTheBritannianRoyalGuard)
};
}
}
public override Type[] DecorativeList
{
get
{
return new Type[]
{
typeof(LavaTile),
typeof(MonsterStatuette),
typeof(MonsterStatuette)
};
}
}
public override MonsterStatuetteType[] StatueTypes
{
get
{
return new MonsterStatuetteType[]
{
MonsterStatuetteType.OphidianArchMage,
MonsterStatuetteType.OphidianWarrior
};
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Lethal;
}
}
public override ScaleType ScaleType
{
get
{
return ScaleType.All;
}
}
public override int Scales
{
get
{
return 20;
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.UltraRich, 4);
}
public override void OnGaveMeleeAttack(Mobile defender)
{
base.OnGaveMeleeAttack(defender);
if (0.2 >= Utility.RandomDouble())
this.Earthquake();
}
public void Earthquake()
{
Map map = this.Map;
if (map == null)
return;
ArrayList targets = new ArrayList();
IPooledEnumerable eable = GetMobilesInRange(8);
foreach (Mobile m in eable)
{
if (m == this || !this.CanBeHarmful(m))
continue;
if (m is BaseCreature && (((BaseCreature)m).Controlled || ((BaseCreature)m).Summoned || ((BaseCreature)m).Team != this.Team))
targets.Add(m);
else if (m.Player)
targets.Add(m);
}
eable.Free();
this.PlaySound(0x2F3);
for (int i = 0; i < targets.Count; ++i)
{
Mobile m = (Mobile)targets[i];
double damage = m.Hits * 0.6;
if (damage < 10.0)
damage = 10.0;
else if (damage > 75.0)
damage = 75.0;
this.DoHarmful(m);
AOS.Damage(m, this, (int)damage, 100, 0, 0, 0, 0);
if (m.Alive && m.Body.IsHuman && !m.Mounted)
m.Animate(20, 7, 1, true, false, 0); // take hit
}
}
public override int GetAngerSound()
{
return Utility.Random(0x2CE, 2);
}
public override int GetIdleSound()
{
return 0x2D2;
}
public override int GetAttackSound()
{
return Utility.Random(0x2C7, 5);
}
public override int GetHurtSound()
{
return 0x2D1;
}
public override int GetDeathSound()
{
return 0x2CC;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,131 @@
using System;
using System.Collections;
using Server.Engines.CannedEvil;
using Server.Items;
namespace Server.Mobiles
{
public class Semidar : BaseChampion
{
[Constructable]
public Semidar()
: base(AIType.AI_Mage)
{
Name = "Semidar";
Body = 174;
BaseSoundID = 0x4B0;
SetStr(502, 600);
SetDex(102, 200);
SetInt(601, 750);
SetHits(10000);
SetStam(103, 250);
SetDamage(29, 35);
SetDamageType(ResistanceType.Physical, 75);
SetDamageType(ResistanceType.Fire, 25);
SetResistance(ResistanceType.Physical, 75, 90);
SetResistance(ResistanceType.Fire, 65, 75);
SetResistance(ResistanceType.Cold, 60, 70);
SetResistance(ResistanceType.Poison, 65, 75);
SetResistance(ResistanceType.Energy, 65, 75);
SetSkill(SkillName.EvalInt, 95.1, 100.0);
SetSkill(SkillName.Magery, 90.1, 105.0);
SetSkill(SkillName.Meditation, 95.1, 100.0);
SetSkill(SkillName.MagicResist, 120.2, 140.0);
SetSkill(SkillName.Tactics, 90.1, 105.0);
SetSkill(SkillName.Wrestling, 90.1, 105.0);
Fame = 24000;
Karma = -24000;
VirtualArmor = 20;
SetSpecialAbility(SpecialAbility.LifeDrain);
ForceActiveSpeed = 0.3;
ForcePassiveSpeed = 0.6;
}
public Semidar(Serial serial)
: base(serial)
{
}
public override ChampionSkullType SkullType
{
get
{
return ChampionSkullType.Pain;
}
}
public override Type[] UniqueList
{
get
{
return new Type[] { typeof(GladiatorsCollar) };
}
}
public override Type[] SharedList
{
get
{
return new Type[] { typeof(RoyalGuardSurvivalKnife), typeof(TheMostKnowledgePerson), typeof(LieutenantOfTheBritannianRoyalGuard) };
}
}
public override Type[] DecorativeList
{
get
{
return new Type[] { typeof(LavaTile), typeof(DemonSkull) };
}
}
public override MonsterStatuetteType[] StatueTypes
{
get
{
return new MonsterStatuetteType[] { };
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Lethal;
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.UltraRich, 4);
AddLoot(LootPack.FilthyRich);
}
public override void CheckReflect(Mobile caster, ref bool reflect)
{
if (!caster.Female && !caster.IsBodyMod)
reflect = true; // Always reflect if caster isn't female
}
/*public override void AlterDamageScalarFrom(Mobile caster, ref double scalar)
{
if (caster.Body.IsMale)
scalar = 20; // Male bodies always reflect.. damage scaled 20x
}*/
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,254 @@
using System;
using System.Collections;
using Server.Engines.CannedEvil;
using Server.Items;
namespace Server.Mobiles
{
public class Serado : BaseChampion
{
[Constructable]
public Serado()
: base(AIType.AI_Melee)
{
Name = "Serado";
Title = "the awakened";
Body = 249;
Hue = 0x96C;
SetStr(1000);
SetDex(150);
SetInt(300);
SetHits(9000);
SetMana(300);
SetDamage(29, 35);
SetDamageType(ResistanceType.Physical, 70);
SetDamageType(ResistanceType.Poison, 20);
SetDamageType(ResistanceType.Energy, 10);
SetResistance(ResistanceType.Physical, 30);
SetResistance(ResistanceType.Fire, 60);
SetResistance(ResistanceType.Cold, 60);
SetResistance(ResistanceType.Poison, 90);
SetResistance(ResistanceType.Energy, 50);
SetSkill(SkillName.MagicResist, 120.0);
SetSkill(SkillName.Tactics, 120.0);
SetSkill(SkillName.Wrestling, 70.0);
SetSkill(SkillName.Poisoning, 150.0);
Fame = 22500;
Karma = -22500;
PackItem(Engines.Plants.Seed.RandomBonsaiSeed());
SetWeaponAbility(WeaponAbility.DoubleStrike);
SetAreaEffect(AreaEffect.PoisonBreath);
}
public Serado(Serial serial)
: base(serial)
{
}
public override ChampionSkullType SkullType
{
get
{
return ChampionSkullType.Power;
}
}
public override Type[] UniqueList
{
get
{
return new Type[] { typeof(Pacify) };
}
}
public override Type[] SharedList
{
get
{
return new Type[]
{
typeof(BraveKnightOfTheBritannia),
typeof(DetectiveBoots),
typeof(EmbroideredOakLeafCloak),
typeof(LieutenantOfTheBritannianRoyalGuard)
};
}
}
public override Type[] DecorativeList
{
get
{
return new Type[] { typeof(Futon), typeof(SwampTile) };
}
}
public override MonsterStatuetteType[] StatueTypes
{
get
{
return new MonsterStatuetteType[] { };
}
}
public override int TreasureMapLevel
{
get
{
return 5;
}
}
public override Poison HitPoison
{
get
{
return Poison.Lethal;
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Lethal;
}
}
public override double HitPoisonChance
{
get
{
return 0.8;
}
}
public override int Feathers
{
get
{
return 30;
}
}
public override bool ShowFameTitle
{
get
{
return false;
}
}
public override bool ClickTitle
{
get
{
return false;
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.UltraRich, 4);
AddLoot(LootPack.FilthyRich);
AddLoot(LootPack.Gems, 6);
}
// TODO: Hit Lightning Area
public override void OnDamagedBySpell(Mobile attacker)
{
base.OnDamagedBySpell(attacker);
ScaleResistances();
DoCounter(attacker);
}
public override void OnGotMeleeAttack(Mobile attacker)
{
base.OnGotMeleeAttack(attacker);
ScaleResistances();
DoCounter(attacker);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
private void ScaleResistances()
{
double hitsLost = (HitsMax - Hits) / (double)HitsMax;
SetResistance(ResistanceType.Physical, 30 + (int)(hitsLost * (95 - 30)));
SetResistance(ResistanceType.Fire, 60 + (int)(hitsLost * (95 - 60)));
SetResistance(ResistanceType.Cold, 60 + (int)(hitsLost * (95 - 60)));
SetResistance(ResistanceType.Poison, 90 + (int)(hitsLost * (95 - 90)));
SetResistance(ResistanceType.Energy, 50 + (int)(hitsLost * (95 - 50)));
}
private void DoCounter(Mobile attacker)
{
if (Map == null || (attacker is BaseCreature && ((BaseCreature)attacker).BardProvoked))
return;
if (0.2 > Utility.RandomDouble())
{
/* Counterattack with Hit Poison Area
* 20-25 damage, unresistable
* Lethal poison, 100% of the time
* Particle effect: Type: "2" From: "0x4061A107" To: "0x0" ItemId: "0x36BD" ItemIdName: "explosion" FromLocation: "(296 615, 17)" ToLocation: "(296 615, 17)" Speed: "1" Duration: "10" FixedDirection: "True" Explode: "False" Hue: "0xA6" RenderMode: "0x0" Effect: "0x1F78" ExplodeEffect: "0x1" ExplodeSound: "0x0" Serial: "0x4061A107" Layer: "255" Unknown: "0x0"
* Doesn't work on provoked monsters
*/
Mobile target = null;
if (attacker is BaseCreature)
{
Mobile m = ((BaseCreature)attacker).GetMaster();
if (m != null)
target = m;
}
if (target == null || !target.InRange(this, 25))
target = attacker;
Animate(10, 4, 1, true, false, 0);
ArrayList targets = new ArrayList();
IPooledEnumerable eable = target.GetMobilesInRange(8);
foreach (Mobile m in eable)
{
if (m == this || !CanBeHarmful(m))
continue;
if (m is BaseCreature && (((BaseCreature)m).Controlled || ((BaseCreature)m).Summoned || ((BaseCreature)m).Team != Team))
targets.Add(m);
else if (m.Player)
targets.Add(m);
}
eable.Free();
for (int i = 0; i < targets.Count; ++i)
{
Mobile m = (Mobile)targets[i];
DoHarmful(m);
AOS.Damage(m, this, Utility.RandomMinMax(20, 25), true, 0, 0, 0, 100, 0);
m.FixedParticles(0x36BD, 1, 10, 0x1F78, 0xA6, 0, (EffectLayer)255);
m.ApplyPoison(this, Poison.Lethal);
}
}
}
}
}

View File

@@ -0,0 +1,60 @@
using System;
namespace Server.Mobiles
{
public class ServantOfSemidar : BaseCreature
{
[Constructable]
public ServantOfSemidar()
: base(AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4)
{
this.Name = "a servant of Semidar";
this.Body = 0x26;
}
public ServantOfSemidar(Serial serial)
: base(serial)
{
}
public override bool DisallowAllMoves
{
get
{
return true;
}
}
public override bool InitialInnocent
{
get
{
return true;
}
}
public override bool CanBeDamaged()
{
return false;
}
public override void AddNameProperties(ObjectPropertyList list)
{
base.AddNameProperties(list);
list.Add(1005494); // enslaved
}
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();
}
}
}

View File

@@ -0,0 +1,217 @@
using System;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName("a shimmering effusion corpse")]
public class ShimmeringEffusion : BasePeerless
{
[Constructable]
public ShimmeringEffusion()
: base(AIType.AI_Spellweaving, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Name = "a shimmering effusion";
Body = 0x105;
SetStr(500, 550);
SetDex(350, 400);
SetInt(1500, 1600);
SetHits(20000);
SetDamage(27, 31);
SetDamageType(ResistanceType.Physical, 20);
SetDamageType(ResistanceType.Fire, 20);
SetDamageType(ResistanceType.Cold, 20);
SetDamageType(ResistanceType.Poison, 20);
SetDamageType(ResistanceType.Energy, 20);
SetResistance(ResistanceType.Physical, 60, 80);
SetResistance(ResistanceType.Fire, 60, 80);
SetResistance(ResistanceType.Cold, 60, 80);
SetResistance(ResistanceType.Poison, 60, 80);
SetResistance(ResistanceType.Energy, 60, 80);
SetSkill(SkillName.Wrestling, 100.0, 105.0);
SetSkill(SkillName.Tactics, 100.0, 105.0);
SetSkill(SkillName.MagicResist, 150);
SetSkill(SkillName.Magery, 150.0);
SetSkill(SkillName.EvalInt, 150.0);
SetSkill(SkillName.Meditation, 120.0);
SetSkill(SkillName.Spellweaving, 120.0);
Fame = 30000;
Karma = -30000;
PackResources(8);
PackTalismans(5);
for (int i = 0; i < Utility.RandomMinMax(1, 6); i++)
{
PackItem(Loot.RandomScroll(0, Loot.ArcanistScrollTypes.Length, SpellbookType.Arcanist));
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.SuperBoss, 8);
AddLoot(LootPack.Parrot, 2);
AddLoot(LootPack.HighScrolls, 3);
AddLoot(LootPack.MedScrolls, 3);
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
c.DropItem(new CapturedEssence());
c.DropItem(new ShimmeringCrystals());
if (Utility.RandomDouble() < 0.05)
{
switch ( Utility.Random(4) )
{
case 0:
c.DropItem(new ShimmeringEffusionStatuette());
break;
case 1:
c.DropItem(new CorporealBrumeStatuette());
break;
case 2:
c.DropItem(new MantraEffervescenceStatuette());
break;
case 3:
c.DropItem(new FetidEssenceStatuette());
break;
}
}
if (Utility.RandomDouble() < 0.05)
c.DropItem(new FerretImprisonedInCrystal());
if (Utility.RandomDouble() < 0.025)
c.DropItem(new CrystallineRing());
}
public override bool AutoDispel
{
get
{
return true;
}
}
public override int TreasureMapLevel
{
get
{
return 5;
}
}
public override bool HasFireRing
{
get
{
return true;
}
}
public override double FireRingChance
{
get
{
return 0.1;
}
}
public override int GetIdleSound()
{
return 0x1BF;
}
public override int GetAttackSound()
{
return 0x1C0;
}
public override int GetHurtSound()
{
return 0x1C1;
}
public override int GetDeathSound()
{
return 0x1C2;
}
#region Helpers
public override bool CanSpawnHelpers
{
get
{
return true;
}
}
public override int MaxHelpersWaves
{
get
{
return 4;
}
}
public override double SpawnHelpersChance
{
get
{
return 0.1;
}
}
public override void SpawnHelpers()
{
int amount = 1;
if (Altar != null)
amount = Altar.Fighters.Count;
if (amount > 5)
amount = 5;
for (int i = 0; i < amount; i ++)
{
switch ( Utility.Random(3) )
{
case 0:
SpawnHelper(new MantraEffervescence(), 2);
break;
case 1:
SpawnHelper(new CorporealBrume(), 2);
break;
case 2:
SpawnHelper(new FetidEssence(), 2);
break;
}
}
}
#endregion
public ShimmeringEffusion(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,165 @@
using System;
namespace Server.Mobiles
{
public class Silvani : BaseCreature
{
[Constructable]
public Silvani()
: base(AIType.AI_Mage, FightMode.Evil, 18, 1, 0.1, 0.2)
{
this.Name = "Silvani";
this.Body = 176;
this.BaseSoundID = 0x467;
this.SetStr(253, 400);
this.SetDex(157, 850);
this.SetInt(503, 800);
this.SetHits(600);
this.SetDamage(27, 38);
this.SetDamageType(ResistanceType.Physical, 75);
this.SetDamageType(ResistanceType.Cold, 25);
this.SetResistance(ResistanceType.Physical, 45, 55);
this.SetResistance(ResistanceType.Fire, 30, 40);
this.SetResistance(ResistanceType.Cold, 30, 40);
this.SetResistance(ResistanceType.Poison, 40, 50);
this.SetResistance(ResistanceType.Energy, 40, 50);
this.SetSkill(SkillName.EvalInt, 100.0);
this.SetSkill(SkillName.Magery, 97.6, 107.5);
this.SetSkill(SkillName.Meditation, 100.0);
this.SetSkill(SkillName.MagicResist, 100.5, 150.0);
this.SetSkill(SkillName.Tactics, 97.6, 100.0);
this.SetSkill(SkillName.Wrestling, 97.6, 100.0);
this.Fame = 20000;
this.Karma = 20000;
this.VirtualArmor = 50;
}
public Silvani(Serial serial)
: base(serial)
{
}
public override TribeType Tribe { get { return TribeType.Fey; } }
public override OppositionGroup OppositionGroup
{
get
{
return OppositionGroup.FeyAndUndead;
}
}
public override bool CanFly
{
get
{
return true;
}
}
public override bool Unprovokable
{
get
{
return true;
}
}
public override Poison PoisonImmune
{
get
{
return Poison.Regular;
}
}
public override int TreasureMapLevel
{
get
{
return 5;
}
}
public override void GenerateLoot()
{
this.AddLoot(LootPack.UltraRich, 2);
}
public void SpawnPixies(Mobile target)
{
Map map = this.Map;
if (map == null)
return;
int newPixies = Utility.RandomMinMax(3, 6);
for (int i = 0; i < newPixies; ++i)
{
Pixie pixie = new Pixie();
pixie.Team = this.Team;
pixie.FightMode = FightMode.Closest;
bool validLocation = false;
Point3D loc = this.Location;
for (int j = 0; !validLocation && j < 10; ++j)
{
int x = this.X + Utility.Random(3) - 1;
int y = this.Y + Utility.Random(3) - 1;
int z = map.GetAverageZ(x, y);
if (validLocation = map.CanFit(x, y, this.Z, 16, false, false))
loc = new Point3D(x, y, this.Z);
else if (validLocation = map.CanFit(x, y, z, 16, false, false))
loc = new Point3D(x, y, z);
}
pixie.MoveToWorld(loc, map);
pixie.Combatant = target;
}
}
public override void AlterDamageScalarFrom(Mobile caster, ref double scalar)
{
if (0.1 >= Utility.RandomDouble())
this.SpawnPixies(caster);
}
public override void OnGaveMeleeAttack(Mobile defender)
{
base.OnGaveMeleeAttack(defender);
defender.Damage(Utility.Random(20, 10), this);
defender.Stam -= Utility.Random(20, 10);
defender.Mana -= Utility.Random(20, 10);
}
public override void OnGotMeleeAttack(Mobile attacker)
{
base.OnGotMeleeAttack(attacker);
if (0.1 >= Utility.RandomDouble())
this.SpawnPixies(attacker);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,205 @@
using System;
using System.Collections;
using Server.Items;
using Server.Spells;
namespace Server.Mobiles
{
[CorpseName("a slasher of veils corpse")]
public class SlasherOfVeils : BaseSABoss
{
private static readonly int[] m_North = new int[]
{
-1, -1,
1, -1,
-1, 2,
1, 2
};
private static readonly int[] m_East = new int[]
{
-1, 0,
2, 0
};
[Constructable]
public SlasherOfVeils()
: base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Name = "The Slasher of Veils";
Body = 741;
SetStr(901, 1010);
SetDex(127, 153);
SetInt(1078, 1263);
SetHits(50000, 65000);
SetMana(10000);
SetDamage(10, 15);
SetDamageType(ResistanceType.Physical, 20);
SetDamageType(ResistanceType.Fire, 20);
SetDamageType(ResistanceType.Cold, 20);
SetDamageType(ResistanceType.Poison, 20);
SetDamageType(ResistanceType.Energy, 20);
SetResistance(ResistanceType.Physical, 65, 80);
SetResistance(ResistanceType.Fire, 70, 80);
SetResistance(ResistanceType.Cold, 70, 80);
SetResistance(ResistanceType.Poison, 70, 80);
SetResistance(ResistanceType.Energy, 70, 80);
SetSkill(SkillName.Anatomy, 110.8, 129.7);
SetSkill(SkillName.EvalInt, 113.4, 130);
SetSkill(SkillName.Magery, 111.7, 130);
SetSkill(SkillName.Spellweaving, 111.1, 125);
SetSkill(SkillName.Meditation, 113.5, 129.9);
SetSkill(SkillName.MagicResist, 110, 129.8);
SetSkill(SkillName.Tactics, 110.5, 126.3);
SetSkill(SkillName.Wrestling, 110.1, 130);
SetSkill(SkillName.DetectHidden, 127.1);
Fame = 35000;
Karma = -35000;
SetSpecialAbility(SpecialAbility.AngryFire);
SetSpecialAbility(SpecialAbility.ManaDrain);
SetWeaponAbility(WeaponAbility.ParalyzingBlow);
SetSpecialAbility(SpecialAbility.TrueFear);
}
public SlasherOfVeils(Serial serial)
: base(serial)
{
}
public override Type[] UniqueSAList
{
get
{
return new Type[] { typeof(ClawsOfTheBerserker), typeof(Lavaliere), typeof(Mangler), typeof(HumanSignOfChaos), typeof(GargishSignOfChaos), typeof(StandardOfChaosG), typeof(StandardOfChaos) };
}
}
public override Type[] SharedSAList
{
get
{
return new Type[] { typeof(AxesOfFury), typeof(BladeOfBattle), typeof(DemonBridleRing), typeof(PetrifiedSnake), typeof(PillarOfStrength), typeof(SwordOfShatteredHopes), typeof(SummonersKilt) };
}
}
public override bool Unprovokable
{
get
{
return false;
}
}
public override bool BardImmune
{
get
{
return false;
}
}
public override int GetIdleSound()
{
return 1589;
}
public override int GetAngerSound()
{
return 1586;
}
public override int GetHurtSound()
{
return 1588;
}
public override int GetDeathSound()
{
return 1587;
}
public override bool AlwaysMurderer { get { return true; } }
public override void GenerateLoot()
{
AddLoot(LootPack.AosSuperBoss, 4);
AddLoot(LootPack.Gems, 8);
}
public override void OnThink()
{
base.OnThink();
//if (Combatant == null)
// return;
//if (Hits > 0.6 * HitsMax && Utility.RandomDouble() < 0.05)
// FireRing();
}
public override void FireRing()
{
for (int i = 0; i < m_North.Length; i += 2)
{
Point3D p = Location;
p.X += m_North[i];
p.Y += m_North[i + 1];
IPoint3D po = p as IPoint3D;
SpellHelper.GetSurfaceTop(ref po);
Effects.SendLocationEffect(po, Map, 0x3E27, 50);
}
for (int i = 0; i < m_East.Length; i += 2)
{
Point3D p = Location;
p.X += m_East[i];
p.Y += m_East[i + 1];
IPoint3D po = p as IPoint3D;
SpellHelper.GetSurfaceTop(ref po);
Effects.SendLocationEffect(po, Map, 0x3E31, 50);
}
}
public override void OnDamagedBySpell(Mobile caster)
{
if (0.5 > Utility.RandomDouble() && caster.InRange(Location, 10) && Map != null && caster.Alive && caster != this && caster.Map == Map)
{
MoveToWorld(caster.Location, Map);
Timer.DelayCall(() =>
{
Combatant = caster;
});
Effects.PlaySound(Location, Map, 0x1FE);
}
base.OnDamagedBySpell(caster);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,463 @@
using System;
using System.Collections.Generic;
using Server.Items;
using Server.Network;
using Server.Spells;
namespace Server.Mobiles
{
[CorpseName("a stygian dragon corpse")]
public class StygianDragon : BaseSABoss
{
private DateTime m_Delay;
[Constructable]
public StygianDragon()
: base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.3, 0.5)
{
Name = "Stygian Dragon";
Body = 826;
BaseSoundID = 362;
SetStr(702);
SetDex(250);
SetInt(180);
SetHits(30000);
SetStam(431);
SetMana(180);
SetDamage(33, 55);
SetDamageType(ResistanceType.Physical, 25);
SetDamageType(ResistanceType.Fire, 50);
SetDamageType(ResistanceType.Energy, 25);
SetResistance(ResistanceType.Physical, 80, 90);
SetResistance(ResistanceType.Fire, 80, 90);
SetResistance(ResistanceType.Cold, 60, 70);
SetResistance(ResistanceType.Poison, 80, 90);
SetResistance(ResistanceType.Energy, 80, 90);
SetSkill(SkillName.Anatomy, 100.0);
SetSkill(SkillName.MagicResist, 150.0, 155.0);
SetSkill(SkillName.Tactics, 120.7, 125.0);
SetSkill(SkillName.Wrestling, 115.0, 117.7);
Fame = 15000;
Karma = -15000;
VirtualArmor = 60;
Tamable = false;
SetWeaponAbility(WeaponAbility.Bladeweave);
SetWeaponAbility(WeaponAbility.TalonStrike);
SetSpecialAbility(SpecialAbility.DragonBreath);
}
public StygianDragon(Serial serial)
: base(serial)
{
}
public override Type[] UniqueSAList
{
get
{
return new Type[]
{
typeof(BurningAmber), typeof(DraconisWrath), typeof(DragonHideShield), typeof(FallenMysticsSpellbook),
typeof(LifeSyphon), typeof(GargishSignOfOrder), typeof(HumanSignOfOrder), typeof(VampiricEssence)
};
}
}
public override Type[] SharedSAList
{
get
{
return new Type[]
{
typeof(AxesOfFury), typeof(SummonersKilt), typeof(GiantSteps),
typeof(TokenOfHolyFavor)
};
}
}
public override bool AlwaysMurderer { get { return true; } }
public override bool Unprovokable { get { return false; } }
public override bool BardImmune { get { return false; } }
public override bool AutoDispel { get { return !Controlled; } }
public override int Meat { get { return 19; } }
public override int Hides { get { return 30; } }
public override HideType HideType { get { return HideType.Barbed; } }
public override int Scales { get { return 7; } }
public override ScaleType ScaleType { get { return (Body == 12 ? ScaleType.Yellow : ScaleType.Red); } }
public override int DragonBlood { get { return 48; } }
public override bool CanFlee { get { return false; } }
public override void GenerateLoot()
{
AddLoot(LootPack.AosSuperBoss, 4);
AddLoot(LootPack.Gems, 8);
}
public override void OnThink()
{
base.OnThink();
if (Combatant == null || !(Combatant is Mobile))
return;
if (DateTime.UtcNow > m_Delay)
{
switch (Utility.Random(3))
{
case 0: CrimsonMeteor(this, (Mobile)Combatant, 70, 125); break;
case 1: DoStygianFireball(); break;
case 2: DoFireColumn(); break;
}
m_Delay = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 60));
}
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
c.DropItem(new StygianDragonHead());
if ( Paragon.ChestChance > Utility.RandomDouble() )
c.DropItem( new ParagonChest( Name, 5 ) );
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)1);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
#region Crimson Meteor
public static void CrimsonMeteor(Mobile owner, Mobile combatant, int minDamage, int maxDamage)
{
if (!combatant.Alive || combatant.Map == null || combatant.Map == Map.Internal)
return;
new CrimsonMeteorTimer(owner, combatant.Location, minDamage, maxDamage).Start();
}
public class CrimsonMeteorTimer : Timer
{
private Mobile m_From;
private Map m_Map;
private int m_Count;
private int m_MaxCount;
private bool m_DoneDamage;
private Point3D m_LastTarget;
private Rectangle2D m_ShowerArea;
private List<Mobile> m_ToDamage;
private int m_MinDamage, m_MaxDamage;
public CrimsonMeteorTimer(Mobile from, Point3D loc, int min, int max)
: base(TimeSpan.FromMilliseconds(250.0), TimeSpan.FromMilliseconds(250.0))
{
m_From = from;
m_Map = from.Map;
m_Count = 0;
m_MaxCount = 25; // in ticks
m_LastTarget = loc;
m_DoneDamage = false;
m_ShowerArea = new Rectangle2D(loc.X - 2, loc.Y - 2, 4, 4);
m_MinDamage = min;
m_MaxDamage = max;
m_ToDamage = new List<Mobile>();
IPooledEnumerable eable = m_Map.GetMobilesInBounds(m_ShowerArea);
foreach (Mobile m in eable)
{
if (m != from && m_From.CanBeHarmful(m))
m_ToDamage.Add(m);
}
eable.Free();
}
protected override void OnTick()
{
if (m_From == null || m_From.Deleted || m_Map == null || m_Map == Map.Internal)
{
Stop();
return;
}
if (0.33 > Utility.RandomDouble())
{
var field = new FireField(m_From, 25, Utility.RandomBool());
field.MoveToWorld(m_LastTarget, m_Map);
}
Point3D start = new Point3D();
Point3D finish = new Point3D();
finish.X = m_ShowerArea.X + Utility.Random(m_ShowerArea.Width);
finish.Y = m_ShowerArea.Y + Utility.Random(m_ShowerArea.Height);
finish.Z = m_From.Z;
SpellHelper.AdjustField(ref finish, m_Map, 16, false);
//objects move from upper right/right to left as per OSI
start.X = finish.X + Utility.RandomMinMax(-4, 4);
start.Y = finish.Y - 15;
start.Z = finish.Z + 50;
Effects.SendMovingParticles(
new Entity(Serial.Zero, start, m_Map),
new Entity(Serial.Zero, finish, m_Map),
0x36D4, 15, 0, false, false, 0, 0, 9502, 1, 0, (EffectLayer)255, 0x100);
Effects.PlaySound(finish, m_Map, 0x11D);
m_LastTarget = finish;
m_Count++;
if (m_Count >= m_MaxCount / 2 && !m_DoneDamage)
{
if (m_ToDamage != null && m_ToDamage.Count > 0)
{
int damage;
foreach (Mobile mob in m_ToDamage)
{
damage = Utility.RandomMinMax(m_MinDamage, m_MaxDamage);
m_From.DoHarmful(mob);
AOS.Damage(mob, m_From, damage, 0, 100, 0, 0, 0);
mob.FixedParticles(0x36BD, 1, 15, 9502, 0, 3, (EffectLayer)255);
}
}
m_DoneDamage = true;
return;
}
if (m_Count >= m_MaxCount)
Stop();
}
}
#endregion
#region Fire Column
public void DoFireColumn()
{
var map = Map;
if (map == null)
return;
Direction columnDir = Utility.GetDirection(this, Combatant);
Packet flash = ScreenLightFlash.Instance;
IPooledEnumerable e = Map.GetClientsInRange(Location, Core.GlobalUpdateRange);
foreach (NetState ns in e)
{
if (ns.Mobile != null)
ns.Mobile.Send(flash);
}
e.Free();
int x = X;
int y = Y;
bool south = columnDir == Direction.East || columnDir == Direction.West;
Movement.Movement.Offset(columnDir, ref x, ref y);
Point3D p = new Point3D(x, y, Z);
SpellHelper.AdjustField(ref p, map, 16, false);
var fire = new FireField(this, Utility.RandomMinMax(25, 32), south);
fire.MoveToWorld(p, map);
for (int i = 0; i < 7; i++)
{
Movement.Movement.Offset(columnDir, ref x, ref y);
p = new Point3D(x, y, Z);
SpellHelper.AdjustField(ref p, map, 16, false);
fire = new FireField(this, Utility.RandomMinMax(25, 32), south);
fire.MoveToWorld(p, map);
}
}
#endregion
#region Fire Field
public class FireField : Item
{
private Mobile m_Owner;
private Timer m_Timer;
private DateTime m_Destroy;
[Constructable]
public FireField(Mobile owner, int duration, bool south)
: base(GetItemID(south))
{
Movable = false;
m_Destroy = DateTime.UtcNow + TimeSpan.FromSeconds(duration);
m_Owner = owner;
m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), new TimerCallback(OnTick));
}
private static int GetItemID(bool south)
{
if (south)
return 0x398C;
else
return 0x3996;
}
public override void OnAfterDelete()
{
if (m_Timer != null)
m_Timer.Stop();
}
private void OnTick()
{
if (DateTime.UtcNow > m_Destroy)
{
Delete();
}
else
{
IPooledEnumerable eable = GetMobilesInRange(0);
List<Mobile> list = new List<Mobile>();
foreach (Mobile m in eable)
{
if (m == null)
{
continue;
}
if (m_Owner == null || CanTargetMob(m))
{
list.Add(m);
}
}
eable.Free();
foreach (var mob in list)
{
DealDamage(mob);
}
ColUtility.Free(list);
}
}
public override bool OnMoveOver(Mobile m)
{
DealDamage(m);
return true;
}
public void DealDamage(Mobile m)
{
if (m != m_Owner && (m_Owner == null || CanTargetMob(m)))
AOS.Damage(m, m_Owner, Utility.RandomMinMax(2, 4), 0, 100, 0, 0, 0);
}
public bool CanTargetMob(Mobile m)
{
return m != m_Owner && m_Owner.CanBeHarmful(m, false) && (m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile));
}
public FireField(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
// Unsaved.
}
public override void Deserialize(GenericReader reader)
{
}
}
#endregion
#region Stygian Fireball
public void DoStygianFireball()
{
if (!(Combatant is Mobile) || !InRange(Combatant.Location, 10))
return;
new StygianFireballTimer(this, (Mobile)Combatant);
PlaySound(0x1F3);
}
private class StygianFireballTimer : Timer
{
private StygianDragon m_Dragon;
private Mobile m_Combatant;
private int m_Ticks;
public StygianFireballTimer(StygianDragon dragon, Mobile combatant)
: base(TimeSpan.FromMilliseconds(200), TimeSpan.FromMilliseconds(200))
{
m_Dragon = dragon;
m_Combatant = combatant;
m_Ticks = 0;
Start();
}
protected override void OnTick()
{
m_Dragon.MovingParticles(m_Combatant, 0x46E6, 7, 0, false, true, 1265, 0, 9502, 4019, 0x026, 0);
if (m_Ticks >= 10)
{
int damage = Utility.RandomMinMax(120, 150);
Timer.DelayCall(TimeSpan.FromSeconds(.20), new TimerStateCallback(DoDamage_Callback), new object[] { m_Combatant, m_Dragon, damage });
Stop();
}
m_Ticks++;
}
public void DoDamage_Callback(object state)
{
object[] obj = (object[])state;
Mobile c = (Mobile)obj[0];
Mobile d = (Mobile)obj[1];
int dam = (int)obj[2];
d.DoHarmful(c);
AOS.Damage(c, d, dam, false, 0, 0, 0, 0, 0, 100, 0, false);
}
}
#endregion
}
}

View File

@@ -0,0 +1,440 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName("a travesty's corpse")]
public class Travesty : BasePeerless
{
public override WeaponAbility GetWeaponAbility()
{
if (Weapon == null)
return null;
BaseWeapon weapon = Weapon as BaseWeapon;
return Utility.RandomBool() ? weapon.PrimaryAbility : weapon.SecondaryAbility;
}
private DateTime m_NextBodyChange;
private DateTime m_NextMirrorImage;
private bool m_SpawnedHelpers;
private Timer m_Timer;
private bool _CanDiscord;
private bool _CanPeace;
private bool _CanProvoke;
public override bool CanDiscord { get { return _CanDiscord; } }
public override bool CanPeace { get { return _CanPeace; } }
public override bool CanProvoke { get { return _CanProvoke; } }
[Constructable]
public Travesty()
: base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Name = "Travesty";
Body = 0x108;
BaseSoundID = 0x46E;
SetStr(900, 950);
SetDex(900, 950);
SetInt(900, 950);
SetHits(35000);
SetDamage(11, 18);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 50, 70);
SetResistance(ResistanceType.Fire, 50, 70);
SetResistance(ResistanceType.Cold, 50, 70);
SetResistance(ResistanceType.Poison, 50, 70);
SetResistance(ResistanceType.Energy, 50, 70);
SetSkill(SkillName.Wrestling, 300.0, 320.0);
SetSkill(SkillName.Tactics, 100.0, 120.0);
SetSkill(SkillName.MagicResist, 100.0, 120.0);
SetSkill(SkillName.Anatomy, 100.0, 120.0);
SetSkill(SkillName.Healing, 100.0, 120.0);
SetSkill(SkillName.Poisoning, 100.0, 120.0);
SetSkill(SkillName.DetectHidden, 100.0);
SetSkill(SkillName.Hiding, 100.0);
SetSkill(SkillName.Parry, 100.0, 110.0);
SetSkill(SkillName.Magery, 100.0, 120.0);
SetSkill(SkillName.EvalInt, 100.0, 120.0);
SetSkill(SkillName.Meditation, 100.0, 120.0);
SetSkill(SkillName.Necromancy, 100.0, 120.0);
SetSkill(SkillName.SpiritSpeak, 100.0, 120.0);
SetSkill(SkillName.Focus, 100.0, 120.0);
SetSkill(SkillName.Spellweaving, 100.0, 120.0);
SetSkill(SkillName.Discordance, 100.0, 120.0);
SetSkill(SkillName.Bushido, 100.0, 120.0);
SetSkill(SkillName.Ninjitsu, 100.0, 120.0);
SetSkill(SkillName.Chivalry, 100.0, 120.0);
SetSkill(SkillName.Musicianship, 100.0, 120.0);
SetSkill(SkillName.Discordance, 100.0, 120.0);
SetSkill(SkillName.Provocation, 100.0, 120.0);
SetSkill(SkillName.Peacemaking, 100.0, 120.0);
Fame = 30000;
Karma = -30000;
VirtualArmor = 50;
PackTalismans(5);
PackResources(8);
for (int i = 0; i < Utility.RandomMinMax(1, 6); i++)
{
PackItem(Loot.RandomScroll(0, Loot.ArcanistScrollTypes.Length, SpellbookType.Arcanist));
}
}
public override bool ShowFameTitle { get { return false; } }
public Travesty(Serial serial)
: base(serial)
{
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
c.DropItem(new EyeOfTheTravesty());
c.DropItem(new OrdersFromMinax());
switch (Utility.Random(3))
{
case 0:
c.DropItem(new TravestysSushiPreparations());
break;
case 1:
c.DropItem(new TravestysFineTeakwoodTray());
break;
case 2:
c.DropItem(new TravestysCollectionOfShells());
break;
}
if (Utility.RandomDouble() < 0.6)
c.DropItem(new ParrotItem());
if (Utility.RandomDouble() < 0.1)
c.DropItem(new TragicRemainsOfTravesty());
if (Utility.RandomDouble() < 0.05)
c.DropItem(new ImprisonedDog());
if (Utility.RandomDouble() < 0.05)
c.DropItem(new MarkOfTravesty());
if (Utility.RandomDouble() < 0.025)
{
c.DropItem(new MalekisHonor());
}
}
public override void OnDamage(int amount, Mobile from, bool willKill)
{
if (0.1 > Utility.RandomDouble() && m_NextMirrorImage < DateTime.UtcNow)
{
new Server.Spells.Ninjitsu.MirrorImage(this, null).Cast();
m_NextMirrorImage = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(20, 45));
}
if (0.25 > Utility.RandomDouble() && DateTime.UtcNow > m_NextBodyChange)
{
ChangeBody();
}
base.OnDamage(amount, from, willKill);
}
public override void GenerateLoot()
{
AddLoot(LootPack.AosSuperBoss, 8);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public void ChangeBody()
{
List<Mobile> list = new List<Mobile>();
IPooledEnumerable eable = Map.GetMobilesInRange(Location, 5);
foreach (Mobile m in eable)
{
if (m.Player && m.AccessLevel == AccessLevel.Player && m.Alive)
list.Add(m);
}
eable.Free();
if (list.Count == 0 || IsBodyMod)
{
return;
}
Mobile attacker = list[Utility.Random(list.Count)];
BodyMod = attacker.Body;
HueMod = attacker.Hue;
NameMod = attacker.Name;
Female = attacker.Female;
Title = "(Travesty)";
HairItemID = attacker.HairItemID;
HairHue = attacker.HairHue;
FacialHairItemID = attacker.FacialHairItemID;
FacialHairHue = attacker.FacialHairHue;
foreach (Item item in attacker.Items)
{
if (item.Layer < Layer.Mount &&
item.Layer != Layer.Backpack &&
item.Layer != Layer.Mount &&
item.Layer != Layer.Bank &&
item.Layer != Layer.Hair &&
item.Layer != Layer.Face &&
item.Layer != Layer.FacialHair)
{
if (FindItemOnLayer(item.Layer) == null)
{
if (item is BaseRanged)
{
Item i = FindItemOnLayer(Layer.TwoHanded);
if (i != null)
i.Delete();
i = FindItemOnLayer(Layer.OneHanded);
if (i != null)
i.Delete();
AddItem(Loot.Construct(item.GetType()));
}
else
{
AddItem(new ClonedItem(item));
}
}
}
}
if (attacker.Skills[SkillName.Swords].Value >= 50.0 || attacker.Skills[SkillName.Fencing].Value >= 50.0 || attacker.Skills[SkillName.Macing].Value >= 50.0)
ChangeAIType(AIType.AI_Melee);
if (attacker.Skills[SkillName.Archery].Value >= 50.0)
ChangeAIType(AIType.AI_Archer);
if (attacker.Skills[SkillName.Spellweaving].Value >= 50.0)
ChangeAIType(AIType.AI_Spellweaving);
if (attacker.Skills[SkillName.Mysticism].Value >= 50.0)
ChangeAIType(AIType.AI_Mystic);
if (attacker.Skills[SkillName.Magery].Value >= 50.0)
ChangeAIType(AIType.AI_Mage);
if (attacker.Skills[SkillName.Necromancy].Value >= 50.0)
ChangeAIType(AIType.AI_Necro);
if (attacker.Skills[SkillName.Ninjitsu].Value >= 50.0)
ChangeAIType(AIType.AI_Ninja);
if (attacker.Skills[SkillName.Bushido].Value >= 50.0)
ChangeAIType(AIType.AI_Samurai);
if (attacker.Skills[SkillName.Necromancy].Value >= 50.0 && attacker.Skills[SkillName.Magery].Value >= 50.0)
ChangeAIType(AIType.AI_NecroMage);
PlaySound(0x511);
FixedParticles(0x376A, 1, 14, 5045, EffectLayer.Waist);
m_NextBodyChange = DateTime.UtcNow + TimeSpan.FromSeconds(10.0);
if (attacker.Skills[SkillName.Healing].Base > 20)
{
SetSpecialAbility(SpecialAbility.Heal);
}
if (attacker.Skills[SkillName.Discordance].Base > 50)
{
_CanDiscord = true;
}
if (attacker.Skills[SkillName.Peacemaking].Base > 50)
{
_CanPeace = true;
}
if (attacker.Skills[SkillName.Provocation].Base > 50)
{
_CanProvoke = true;
}
if (m_Timer != null)
m_Timer.Stop();
m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(1.0), new TimerCallback(RestoreBody));
}
public void DeleteItems()
{
ColUtility.SafeDelete(Items, item => item is ClonedItem || item is BaseRanged);
if (Backpack != null)
{
ColUtility.SafeDelete(Backpack.Items, item => item is ClonedItem || item is BaseRanged);
}
}
public virtual void RestoreBody()
{
BodyMod = 0;
HueMod = -1;
NameMod = null;
Female = false;
Title = null;
_CanDiscord = false;
_CanPeace = false;
_CanProvoke = false;
if (HasAbility(SpecialAbility.Heal))
{
RemoveSpecialAbility(SpecialAbility.Heal);
}
DeleteItems();
ChangeAIType(AIType.AI_Mage);
if (m_Timer != null)
{
m_Timer.Stop();
m_Timer = null;
}
}
public override bool OnBeforeDeath()
{
RestoreBody();
return base.OnBeforeDeath();
}
public override void OnAfterDelete()
{
if (m_Timer != null)
m_Timer.Stop();
base.OnAfterDelete();
}
#region Spawn Helpers
public override bool CanSpawnHelpers { get { return true; } }
public override int MaxHelpersWaves { get { return 1; } }
public override bool CanSpawnWave()
{
if (Hits > 2000)
m_SpawnedHelpers = false;
return !m_SpawnedHelpers && Hits < 2000;
}
public override void SpawnHelpers()
{
m_SpawnedHelpers = true;
SpawnNinjaGroup(new Point3D(80, 1964, 0));
SpawnNinjaGroup(new Point3D(80, 1949, 0));
SpawnNinjaGroup(new Point3D(92, 1948, 0));
SpawnNinjaGroup(new Point3D(92, 1962, 0));
if (Map != null && Map != Map.Internal && Region.IsPartOf("TheCitadel"))
{
var loc = _WarpLocs[Utility.Random(_WarpLocs.Length)];
MoveToWorld(loc, Map);
}
}
public void SpawnNinjaGroup(Point3D _location)
{
SpawnHelper(new DragonsFlameMage(), _location);
SpawnHelper(new SerpentsFangAssassin(), _location);
SpawnHelper(new TigersClawThief(), _location);
}
#endregion
private Point3D[] _WarpLocs =
{
new Point3D(71, 1939, 0),
new Point3D(71, 1955, 0),
new Point3D(69, 1972, 0),
new Point3D(86, 1971, 0),
new Point3D(103, 1972, 0),
new Point3D(86, 1939, 0),
new Point3D(102, 1938, 0),
};
private class ClonedItem : Item
{
public ClonedItem(Item oItem)
: base(oItem.ItemID)
{
Name = oItem.Name;
Weight = oItem.Weight;
Hue = oItem.Hue;
Layer = oItem.Layer;
}
public override DeathMoveResult OnParentDeath(Mobile parent)
{
return DeathMoveResult.RemainEquiped;
}
public override DeathMoveResult OnInventoryDeath(Mobile parent)
{
Delete();
return base.OnInventoryDeath(parent);
}
public ClonedItem(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}
}

View File

@@ -0,0 +1,165 @@
using System;
using Server.Items;
namespace Server.Mobiles
{
public class BaneDragon : BaseMount
{
public static readonly int MaxPower = 10;
[CommandProperty(AccessLevel.GameMaster)]
public int PowerLevel { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int PowerDecay
{
get { return _PowerDecay; }
set
{
_PowerDecay = value;
if (_PowerDecay >= 10)
{
_PowerDecay = 0;
PowerLevel = Math.Max(1, PowerLevel - 1);
}
}
}
private DateTime _NextSpecial;
private int _PowerDecay;
[Constructable]
public BaneDragon()
: base("Bane Dragon", 0x31A, 0x3EBD, AIType.AI_Mage, FightMode.Aggressor, 10, 1, 0.2, 0.4)
{
BaseSoundID = 0x16A;
Hue = 1175;
SetStr(500, 555);
SetDex(85, 125);
SetInt(100, 165);
SetHits(550, 650);
SetDamage(20, 26);
SetDamageType(ResistanceType.Physical, 50);
SetDamageType(ResistanceType.Cold, 25);
SetDamageType(ResistanceType.Poison, 25);
SetResistance(ResistanceType.Physical, 60, 70);
SetResistance(ResistanceType.Fire, 40, 50);
SetResistance(ResistanceType.Cold, 30, 45);
SetResistance(ResistanceType.Poison, 50, 60);
SetResistance(ResistanceType.Energy, 20, 40);
SetSkill(SkillName.Anatomy, 10.0);
SetSkill(SkillName.MagicResist, 85.0);
SetSkill(SkillName.Tactics, 110.0);
SetSkill(SkillName.Wrestling, 90.0);
SetSkill(SkillName.Magery, 45.0);
SetSkill(SkillName.EvalInt, 35.0);
SetSkill(SkillName.Meditation, 35.0);
Fame = 18000;
Karma = -18000;
Tamable = true;
ControlSlots = 3;
MinTameSkill = 107.1;
PowerLevel = 10;
_NextSpecial = DateTime.UtcNow;
}
public override Poison HitPoison { get { return Poison.Lethal; } }
public override bool AlwaysMurderer { get { return true; } }
public override FoodType FavoriteFood { get { return FoodType.BlackrockStew; } }
public override bool CheckFeed(Mobile from, Item dropped)
{
if (dropped is BowlOfBlackrockStew)
{
if (PowerLevel >= MaxPower)
{
from.SendLocalizedMessage(1115755); // The creature looks at you strangely and shakes its head no.
}
else
{
PowerLevel++;
if (PowerLevel >= MaxPower)
{
from.SendLocalizedMessage(1115753); // Your bane dragon is returned to maximum power by this stew.
}
else
{
from.SendLocalizedMessage(1115754); // Your bane dragon seems a bit peckish today and is not at full power.
}
return base.CheckFeed(from, dropped);
}
}
return false;
}
public override void OnHarmfulSpell(Mobile from)
{
if (_NextSpecial < DateTime.UtcNow)
{
DoSpecial(from);
_NextSpecial = DateTime.UtcNow + TimeSpan.FromSeconds((double)Utility.RandomMinMax(15, 30) * (double)(11.0 - PowerLevel));
}
}
public void DoSpecial(Mobile from)
{
if (Controlled)
{
PowerDecay++;
}
MovingParticles(from, 0x36D4, 7, 0, false, true, 1163, 0, 9502, 4019, 0x160, 0);
PlaySound(0x15E);
Timer.DelayCall(TimeSpan.FromSeconds(1), m =>
{
AOS.Damage(m, this, Utility.RandomMinMax(8 * PowerLevel, 10 * PowerLevel), 0, 50, 0, 50, 0);
m.ApplyPoison(this, GetHitPoison());
}, from);
}
public BaneDragon(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)1); // version
writer.Write(PowerLevel);
writer.Write(PowerDecay);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
PowerLevel = reader.ReadInt();
PowerDecay = reader.ReadInt();
break;
case 0: break;
}
}
}
}

View File

@@ -0,0 +1,164 @@
using System;
using Server.Items;
using Server.Items.Holiday;
namespace Server.Mobiles
{
[CorpseName("a killer pumpkin corpse")]
public class PumpkinHead : BaseCreature
{
[Constructable]
public PumpkinHead()
: base(Utility.RandomBool() ? AIType.AI_Melee : AIType.AI_Mage, FightMode.Closest, 10, 1, 0.05, 0.1)
{
Name = "a killer pumpkin";
Body = 1246 + Utility.Random(2);
BaseSoundID = 268;
SetStr(350);
SetDex(125);
SetInt(250);
SetHits(500);
SetMana(1000);
SetDamage(10, 15);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 55);
SetResistance(ResistanceType.Fire, 50);
SetResistance(ResistanceType.Cold, 50);
SetResistance(ResistanceType.Poison, 65);
SetResistance(ResistanceType.Energy, 80);
SetSkill(SkillName.DetectHidden, 100.0);
SetSkill(SkillName.Meditation, 120.0);
SetSkill(SkillName.Necromancy, 100.0);
SetSkill(SkillName.SpiritSpeak, 120.0);
SetSkill(SkillName.Magery, 160.0);
SetSkill(SkillName.EvalInt, 100.0);
SetSkill(SkillName.MagicResist, 100.0);
SetSkill(SkillName.Tactics, 100.0);
SetSkill(SkillName.Wrestling, 80.0);
Fame = 5000;
Karma = -5000;
VirtualArmor = 49;
}
public PumpkinHead(Serial serial)
: base(serial)
{
}
public override bool AutoDispel { get { return true; } }
public override bool BardImmune { get { return true; } }
public override bool Unprovokable { get { return true; } }
public override bool AreaPeaceImmune { get { return true; } }
public override void GenerateLoot()
{
if (Utility.RandomDouble() < .05)
{
if (Core.TOL)
{
switch (Utility.Random(5))
{
case 0:
PackItem(new ObsidianSkull());
break;
case 1:
PackItem(new CrystalSkull());
break;
case 2:
PackItem(new JadeSkull());
break;
case 3:
PackItem(new CarvablePumpkinTall());
break;
case 4:
PackItem(new CarvableGordPumpkinTall());
break;
default:
break;
}
}
else
{
switch (Utility.Random(5))
{
case 0:
PackItem(new PaintedEvilClownMask());
break;
case 1:
PackItem(new PaintedDaemonMask());
break;
case 2:
PackItem(new PaintedPlagueMask());
break;
case 3:
PackItem(new PaintedEvilJesterMask());
break;
case 4:
PackItem(new PaintedPorcelainMask());
break;
default:
break;
}
}
}
PackItem(new WrappedCandy());
AddLoot(LootPack.UltraRich, 2);
}
public virtual void Lifted_Callback(Mobile from)
{
if (from != null && !from.Deleted && from is PlayerMobile)
{
Combatant = from;
Warmode = true;
}
}
public override Item NewHarmfulItem()
{
Item bad = new AcidSlime(TimeSpan.FromSeconds(10), 25, 30);
bad.Name = "gooey nasty pumpkin hummus";
bad.Hue = 144;
return bad;
}
public override void OnDamage(int amount, Mobile from, bool willKill)
{
if (Utility.RandomBool())
{
if (from != null && from.Map != null && Map != Map.Internal && Map == from.Map && from.InRange(this, 12))
{
SpillAcid((willKill) ? this : from, (willKill) ? 3 : 1);
}
}
base.OnDamage(amount, from, willKill);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,68 @@
using System;
namespace Server.Mobiles
{
public class Wanderer : Mobile
{
private readonly Timer m_Timer;
[Constructable]
public Wanderer()
{
this.Name = "Me";
this.Body = 0x1;
this.AccessLevel = AccessLevel.Counselor;
this.m_Timer = new InternalTimer(this);
this.m_Timer.Start();
}
public Wanderer(Serial serial)
: base(serial)
{
this.m_Timer = new InternalTimer(this);
this.m_Timer.Start();
}
public override void OnDelete()
{
this.m_Timer.Stop();
base.OnDelete();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
private class InternalTimer : Timer
{
private readonly Wanderer m_Owner;
private int m_Count = 0;
public InternalTimer(Wanderer owner)
: base(TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(0.1))
{
this.m_Owner = owner;
}
protected override void OnTick()
{
if ((this.m_Count++ & 0x3) == 0)
{
this.m_Owner.Direction = (Direction)(Utility.Random(8) | 0x80);
}
this.m_Owner.Move(this.m_Owner.Direction);
}
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
namespace Server.Mobiles
{
[CorpseName("a war horse corpse")]
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)
{
this.BaseSoundID = 0xA8;
this.InitStats(Utility.Random(300, 100), 125, 60);
this.SetStr(400);
this.SetDex(125);
this.SetInt(51, 55);
this.SetHits(240);
this.SetMana(0);
this.SetDamage(5, 8);
this.SetDamageType(ResistanceType.Physical, 100);
this.SetResistance(ResistanceType.Physical, 40, 50);
this.SetResistance(ResistanceType.Fire, 30, 40);
this.SetResistance(ResistanceType.Cold, 30, 40);
this.SetResistance(ResistanceType.Poison, 30, 40);
this.SetResistance(ResistanceType.Energy, 30, 40);
this.SetSkill(SkillName.MagicResist, 25.1, 30.0);
this.SetSkill(SkillName.Tactics, 29.3, 44.0);
this.SetSkill(SkillName.Wrestling, 29.3, 44.0);
this.Fame = 300;
this.Karma = 300;
this.Tamable = true;
this.ControlSlots = 1;
this.MinTameSkill = 29.1;
}
public BaseWarHorse(Serial serial)
: base(serial)
{
}
public override FoodType FavoriteFood
{
get
{
return FoodType.FruitsAndVegies | FoodType.GrainsAndHay;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
namespace Server.Mobiles
{
public class CoMWarHorse : BaseWarHorse
{
[Constructable]
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((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
namespace Server.Mobiles
{
public class MinaxWarHorse : BaseWarHorse
{
[Constructable]
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((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
namespace Server.Mobiles
{
public class SLWarHorse : BaseWarHorse
{
[Constructable]
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((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
namespace Server.Mobiles
{
public class TBWarHorse : BaseWarHorse
{
[Constructable]
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((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Server.Mobiles
{
public interface IFreezable
{
void OnRequestedAnimation(Mobile from);
}
public interface IRepairableMobile : IEntity
{
Type RepairResource { get; }
int Hits { get; set; }
int HitsMax { get; }
}
public interface IElementalCreature
{
ElementType ElementType { get; }
}
public interface IAuraCreature
{
void AuraEffect(Mobile victim);
}
public enum ElementType
{
Physical,
Fire,
Cold,
Poison,
Energy,
Chaos,
Direct
}
}

View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class Abbein : BaseVendor
{
private readonly List<SBInfo> m_SBInfos = new List<SBInfo>();
[Constructable]
public Abbein()
: base("the wise")
{
this.Name = "Elder Abbein";
}
public Abbein(Serial serial)
: base(serial)
{
}
public override bool CanTeach
{
get
{
return false;
}
}
public override bool IsInvulnerable
{
get
{
return true;
}
}
protected override List<SBInfo> SBInfos
{
get
{
return this.m_SBInfos;
}
}
public override void InitSBInfo()
{
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = true;
this.Race = Race.Elf;
this.Hue = 0x824D;
this.HairItemID = 0x2FD1;
this.HairHue = 0x321;
}
public override void InitOutfit()
{
this.AddItem(new ElvenBoots(0x74B));
this.AddItem(new FemaleElvenRobe(0x8A8));
this.AddItem(new RoyalCirclet());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,571 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests
{
public class OverpopulationQuest : BaseQuest
{
public OverpopulationQuest()
: base()
{
this.AddObjective(new SlayObjective(typeof(Hind), "hinds", 10));
this.AddReward(new BaseReward(typeof(SmallTrinketBag), 1072268));
}
/* Overpopulation */
public override object Title
{
get
{
return 1072252;
}
}
/* I just can't bear it any longer. Sure, it's my job to thin the deer out so
they don't overeat the area and starve themselves come winter time. Sure, I
know we killed off the predators that would do this naturally so now we have
to make up for it. But they're so graceful and innocent. I just can't do it.
Will you? */
public override object Description
{
get
{
return 1072267;
}
}
/* Well, okay. But if you decide you are up for it after all, c'mon back and see me. */
public override object Refuse
{
get
{
return 1072270;
}
}
/* You're not quite done yet. Get back to work! */
public override object Uncomplete
{
get
{
return 1072271;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class WildBoarCullQuest : BaseQuest
{
public WildBoarCullQuest()
: base()
{
this.AddObjective(new SlayObjective(typeof(Boar), "boars", 10));
this.AddReward(new BaseReward(typeof(SmallTrinketBag), 1072268));
}
/* Wild Boar Cull */
public override object Title
{
get
{
return 1072245;
}
}
/* A pity really. With the balance of nature awry, we have no choice but to accept
the responsibility of making it all right. It's all a part of the circle of life,
after all. So, yes, the boars are running rampant. There are far too many in the
region. Will you shoulder your obligations as a higher life form? */
public override object Description
{
get
{
return 1072260;
}
}
/* Well, okay. But if you decide you are up for it after all, c'mon back and see me. */
public override object Refuse
{
get
{
return 1072270;
}
}
/* You're not quite done yet. Get back to work! */
public override object Uncomplete
{
get
{
return 1072271;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class NewLeadershipQuest : BaseQuest
{
public NewLeadershipQuest()
: base()
{
this.AddObjective(new SlayObjective(typeof(SerpentsFangHighExecutioner), "serpent's fang high executioner", 1, "TheCitadel"));
this.AddObjective(new SlayObjective(typeof(TigersClawThief), "tiger's claw thief", 1, "TheCitadel"));
this.AddObjective(new SlayObjective(typeof(DragonsFlameGrandMage), "dragon's flame mage", 1, "TheCitadel"));
this.AddReward(new BaseReward(typeof(RewardBox), 1072584));
}
/* New Leadership */
public override object Title
{
get
{
return 1072905;
}
}
/* I have a task for you ... adventurer. Will you risk all to win great renown? The
Black Order is organized into three sects, each with their own speciality. The Dragon's
Flame serves the will of the Grand Mage, the Tiger's Claw answers to the Master Thief,
and the Serpent's Fang kills at the direction of the High Executioner. Slay all three
and you will strike the order a devastating blow! */
public override object Description
{
get
{
return 1072963;
}
}
/* I do not fault your decision. */
public override object Refuse
{
get
{
return 1072973;
}
}
/* Once you gain entrance into The Citadel, you will need to move cautiously to find
the sect leaders. */
public override object Uncomplete
{
get
{
return 1072974;
}
}
public override bool CanOffer()
{
return MondainsLegacy.Citadel;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class ExAssassinsQuest : BaseQuest
{
public ExAssassinsQuest()
: base()
{
this.AddObjective(new InternalObjective());
this.AddReward(new BaseReward(typeof(TreasureBag), 1072583));
}
/* Ex-Assassins */
public override object Title
{
get
{
return 1072917;
}
}
/* The Serpent's Fang sect members have gone too far! Express to them my displeasure by slaying
ten of them. But remember, I do not condone war on women, so I will only accept the deaths of
men, human and elf. */
public override object Description
{
get
{
return 1072969;
}
}
/* As you wish. */
public override object Refuse
{
get
{
return 1072979;
}
}
/* The Black Order's fortress home is well hidden. Legend has it that a humble fishing village
disguises the magical portal. */
public override object Uncomplete
{
get
{
return 1072980;
}
}
public override bool CanOffer()
{
return MondainsLegacy.Citadel;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
private class InternalObjective : SlayObjective
{
public InternalObjective()
: base(typeof(SerpentsFangAssassin), "male serpent's fang assassins", 10, "TheCitadel")
{
}
public override bool IsObjective(Mobile mob)
{
if (mob.Female)
return false;
return base.IsObjective(mob);
}
}
}
public class ExtinguishingTheFlameQuest : BaseQuest
{
public ExtinguishingTheFlameQuest()
: base()
{
this.AddObjective(new InternalObjective());
this.AddReward(new BaseReward(typeof(TreasureBag), 1072583));
}
/* Extinguishing the Flame */
public override object Title
{
get
{
return 1072911;
}
}
/* The Dragon's Flame sect members have gone too far! Express to them my displeasure by slaying ten
of them. But remember, I do not condone war on women, so I will only accept the deaths of men,
human or elf. Either race will do, I care not for the shape of their ears. Yes, this action will
properly make clear my disapproval and has a pleasing harmony. */
public override object Description
{
get
{
return 1072966;
}
}
/* As you wish. */
public override object Refuse
{
get
{
return 1072979;
}
}
/* The Black Order's fortress home is well hidden. Legend has it that a humble fishing village
disguises the magical portal. */
public override object Uncomplete
{
get
{
return 1072980;
}
}
public override bool CanOffer()
{
return MondainsLegacy.Citadel;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
private class InternalObjective : SlayObjective
{
public InternalObjective()
: base(typeof(DragonsFlameMage), "male dragon's flame mages", 10, "TheCitadel")
{
}
public override bool IsObjective(Mobile mob)
{
if (mob.Female)
return false;
return base.IsObjective(mob);
}
}
}
public class DeathToTheNinjaQuest : BaseQuest
{
public DeathToTheNinjaQuest()
: base()
{
this.AddObjective(new SlayObjective(typeof(EliteNinja), "elite ninjas", 10, "TheCitadel"));
this.AddReward(new BaseReward(typeof(TreasureBag), 1072583));
}
/* Death to the Ninja! */
public override object Title
{
get
{
return 1072913;
}
}
/* I wish to make a statement of censure against the elite ninjas of the Black Order. Deliver, in
the strongest manner, my disdain. But do not make war on women, even those that take arms against
you. It is not ... fitting. */
public override object Description
{
get
{
return 1072967;
}
}
/* As you wish. */
public override object Refuse
{
get
{
return 1072979;
}
}
/* The Black Order's fortress home is well hidden. Legend has it that a humble fishing village
disguises the magical portal. */
public override object Uncomplete
{
get
{
return 1072980;
}
}
public override bool CanOffer()
{
return MondainsLegacy.Citadel;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class CrimeAndPunishmentQuest : BaseQuest
{
public CrimeAndPunishmentQuest()
: base()
{
this.AddObjective(new InternalObjective());
this.AddReward(new BaseReward(typeof(TreasureBag), 1072583));
}
/* Crime and Punishment */
public override object Title
{
get
{
return 1072914;
}
}
/* The Tiger's Claw sect members have gone too far! Express to them my displeasure by slaying
ten of them. But remember, I do not condone war on women, so I will only accept the deaths of
men, human and elf. */
public override object Description
{
get
{
return 1072968;
}
}
/* As you wish. */
public override object Refuse
{
get
{
return 1072979;
}
}
/* The Black Order's fortress home is well hidden. Legend has it that a humble fishing village
disguises the magical portal. */
public override object Uncomplete
{
get
{
return 1072980;
}
}
public override bool CanOffer()
{
return MondainsLegacy.Citadel;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
private class InternalObjective : SlayObjective
{
public InternalObjective()
: base(typeof(TigersClawThief), "male tiger's claw thieves", 10, "TheCitadel")
{
}
public override bool IsObjective(Mobile mob)
{
if (mob.Female)
return false;
return base.IsObjective(mob);
}
}
}
public class Acob : MondainQuester
{
[Constructable]
public Acob()
: base("Elder Acob", "the wise")
{
this.SetSkill(SkillName.Meditation, 60.0, 83.0);
this.SetSkill(SkillName.Focus, 60.0, 83.0);
}
public Acob(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(OverpopulationQuest),
typeof(WildBoarCullQuest),
typeof(NewLeadershipQuest),
typeof(ExAssassinsQuest),
typeof(ExtinguishingTheFlameQuest),
typeof(DeathToTheNinjaQuest),
typeof(CrimeAndPunishmentQuest)
};
}
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = false;
this.Race = Race.Elf;
this.Hue = 0x8389;
this.HairItemID = 0x2FCF;
this.HairHue = 0x389;
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new ElvenBoots(0x73D));
this.AddItem(new HidePants());
this.AddItem(new ElvenShirt(0x71));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,73 @@
using System;
using Server.Items;
namespace Server.Mobiles
{
public class Actor : BaseCreature
{
[Constructable]
public Actor()
: base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4)
{
this.InitStats(31, 41, 51);
this.SpeechHue = Utility.RandomDyedHue();
this.Hue = Utility.RandomSkinHue();
if (this.Female = Utility.RandomBool())
{
this.Body = 0x191;
this.Name = NameList.RandomName("female");
this.AddItem(new FancyDress(Utility.RandomDyedHue()));
this.Title = "the actress";
}
else
{
this.Body = 0x190;
this.Name = NameList.RandomName("male");
this.AddItem(new LongPants(Utility.RandomNeutralHue()));
this.AddItem(new FancyShirt(Utility.RandomDyedHue()));
this.Title = "the actor";
}
this.AddItem(new Boots(Utility.RandomNeutralHue()));
Utility.AssignRandomHair(this);
Container pack = new Backpack();
pack.DropItem(new Gold(250, 300));
pack.Movable = false;
this.AddItem(pack);
}
public Actor(Serial serial)
: base(serial)
{
}
public override bool ClickTitle
{
get
{
return false;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,204 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests
{
public class CleansingOldHavenQuest : BaseQuest
{
public override bool DoneOnce
{
get
{
return true;
}
}
/* Cleansing Old Haven */
public override object Title
{
get
{
return 1077719;
}
}
/* Head East out of town to Old Haven. Consecrate your weapon, cast Divine Fury, and battle monsters there until
you have raised your Chivalry skill to 50.<br><center>------</center><br>Hail, friend. The life of a Paladin is
a life of much sacrifice, humility, bravery, and righteousness. If you wish to pursue such a life, I have an
assignment for you. Adventure east to Old Haven, consecrate your weapon, and lay to rest the undead that inhabit
there.<br><br>Each ability a Paladin wishes to invoke will require a certain amount of "tithing points" to use.
A Paladin can earn these tithing points by donating gold at a shrine or holy place. You may tithe at this shrine.
<br><br>Return to me once you feel that you are worthy of the rank of Apprentice Paladin. */
public override object Description
{
get
{
return 1077722;
}
}
/* Farewell to you my friend. Return to me if you wish to live the life of a Paladin. */
public override object Refuse
{
get
{
return 1077723;
}
}
/* There are still more undead to lay to rest. You still have more to learn. Return to me once you have done so. */
public override object Uncomplete
{
get
{
return 1077724;
}
}
/* Well done, friend. While I know you understand Chivalry is its own reward, I would like to reward you with
something that will protect you in battle. It was passed down to me when I was a lad. Now, I am passing it on you.
It is called the Bulwark Leggings. Thank you for your service. */
public override object Complete
{
get
{
return 1077726;
}
}
public CleansingOldHavenQuest()
: base()
{
this.AddObjective(new ApprenticeObjective(SkillName.Chivalry, 50, "Old Haven Training", 1077720, 1077721));
// 1077720 Your Chivalry potential is greatly enhanced while questing in this area.
// 1077721 You are not in the quest area for Apprentice Paladin. Your Chivalry potential is not enhanced here.
this.AddReward(new BaseReward(typeof(BulwarkLeggings), 1077727));
}
public override bool CanOffer()
{
#region Scroll of Alacrity
PlayerMobile pm = this.Owner as PlayerMobile;
if (pm.AcceleratedStart > DateTime.UtcNow)
{
this.Owner.SendLocalizedMessage(1077951); // You are already under the effect of an accelerated skillgain scroll.
return false;
}
#endregion
else
return this.Owner.Skills.Chivalry.Base < 50;
}
public override void OnCompleted()
{
this.Owner.SendLocalizedMessage(1077725, null, 0x23); // You have achieved the rank of Apprentice Paladin. Return to Aelorn in New Haven to report your progress.
this.Owner.PlaySound(this.CompleteSound);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Aelorn : MondainQuester
{
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(CleansingOldHavenQuest)
};
}
}
public override bool IsActiveVendor
{
get
{
return true;
}
}
public override void InitSBInfo()
{
this.SBInfos.Add(new SBKeeperOfChivalry());
}
[Constructable]
public Aelorn()
: base("Aelorn", "The Chivalry Instructor")
{
this.SetSkill(SkillName.Anatomy, 120.0, 120.0);
this.SetSkill(SkillName.MagicResist, 120.0, 120.0);
this.SetSkill(SkillName.Tactics, 120.0, 120.0);
this.SetSkill(SkillName.Swords, 120.0, 120.0);
this.SetSkill(SkillName.Meditation, 120.0, 120.0);
this.SetSkill(SkillName.Focus, 120.0, 120.0);
this.SetSkill(SkillName.Chivalry, 120.0, 120.0);
}
public Aelorn(Serial serial)
: base(serial)
{
}
public override void Advertise()
{
this.Say(1078133); // Hail, friend. Want to live the life of a paladin?
}
public override void OnOfferFailed()
{
this.Say(1077772); // I cannot teach you, for you know all I can teach!
}
public override void InitBody()
{
this.Female = false;
this.CantWalk = true;
this.Race = Race.Human;
base.InitBody();
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new VikingSword());
this.AddItem(new PlateChest());
this.AddItem(new PlateLegs());
this.AddItem(new PlateGloves());
this.AddItem(new PlateArms());
this.AddItem(new PlateGorget());
this.AddItem(new OrderShield());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
using Server.Items;
namespace Server.Engines.Quests
{
public class Aeluva : MondainQuester
{
[Constructable]
public Aeluva()
: base("Aeluva", "the arcanist")
{
this.SetSkill(SkillName.Meditation, 60.0, 83.0);
this.SetSkill(SkillName.Focus, 60.0, 83.0);
}
public Aeluva(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[] { typeof(PatienceQuest) };
}
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = true;
this.Race = Race.Elf;
this.Hue = 0x8835;
this.HairItemID = 0x2FD0;
this.HairHue = 0x387;
}
public override void InitOutfit()
{
this.AddItem(new ElvenBoots());
this.AddItem(new ElvenShirt());
this.AddItem(new Skirt());
this.AddItem(new Circlet());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
using Server.Items;
namespace Server.Engines.Quests
{
public class Aernya : MondainQuester
{
[Constructable]
public Aernya()
: base("Aernya", "the mistress of admissions")
{
this.SetSkill(SkillName.Focus, 60.0, 83.0);
}
public Aernya(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[] { typeof(MistakenIdentityQuest) };
}
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = true;
this.Race = Race.Human;
this.Hue = 0x8404;
this.HairItemID = 0x2047;
this.HairHue = 0x465;
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new Sandals(0x743));
this.AddItem(new FancyShirt(0x3B3));
this.AddItem(new Cloak(0x3));
this.AddItem(new Skirt());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,138 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests
{
public class IntoTheVoidQuest : BaseQuest
{
public IntoTheVoidQuest()
: base()
{
AddObjective(new SlayObjective(typeof(BaseVoidCreature), "Void Daemons", 10));
AddReward(new BaseReward(typeof(AbyssReaver), 1112694)); // Abyss Reaver
}
public override bool DoneOnce
{
get
{
return true;
}
}
public override object Title
{
get
{
return 1112687;
}
}
public override object Description
{
get
{
return 1112690;
}
}
public override object Refuse
{
get
{
return 1112691;
}
}
public override object Uncomplete
{
get
{
return 1112692;
}
}
public override object Complete
{
get
{
return 1112693;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Agralem : MondainQuester
{
[Constructable]
public Agralem()
: base("Agralem", "the Bladeweaver")
{
SetSkill(SkillName.Anatomy, 65.0, 90.0);
SetSkill(SkillName.MagicResist, 65.0, 90.0);
SetSkill(SkillName.Tactics, 65.0, 90.0);
SetSkill(SkillName.Throwing, 65.0, 90.0);
}
public Agralem(Serial serial)
: base(serial)
{
}
public override void Advertise()
{
Say(1112688); // Daemons from the void! They must be vanquished!
}
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(IntoTheVoidQuest)
};
}
}
public override void InitBody()
{
InitStats(100, 100, 25);
CantWalk = true;
Race = Race.Gargoyle;
Hue = 34536;
HairItemID = 0x425D;
HairHue = 0x31D;
}
public override void InitOutfit()
{
AddItem(new Cyclone());
AddItem(new GargishLeatherKilt(2305));
AddItem(new GargishLeatherChest(2305));
AddItem(new GargishLeatherArms(2305));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,339 @@
using System;
using Server.Items;
namespace Server.Engines.Quests
{
public class TheKingOfClothingQuest : BaseQuest
{
public TheKingOfClothingQuest()
: base()
{
AddObjective(new ObtainObjective(typeof(Kilt), "kilts", 10, 0x1537));
AddReward(new BaseReward(typeof(TailorsCraftsmanSatchel), 1074282));
}
/* The King of Clothing */
public override object Title
{
get
{
return 1073902;
}
}
/* I have heard noble tales of a fine and proud human garment. An article of clothing
fit for both man and god alike. It is called a "kilt" I believe? Could you fetch for
me some of these kilts so I that I might revel in their majesty and glory? */
public override object Description
{
get
{
return 1074092;
}
}
/* I will patiently await your reconsideration. */
public override object Refuse
{
get
{
return 1073921;
}
}
/* I will be in your debt if you bring me kilts. */
public override object Uncomplete
{
get
{
return 1073948;
}
}
/* I say truly - that is a magnificent garment! You have more than earned a reward. */
public override object Complete
{
get
{
return 1073974;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class ThePuffyShirtQuest : BaseQuest
{
public ThePuffyShirtQuest()
: base()
{
AddObjective(new ObtainObjective(typeof(FancyShirt), "fancy shirts", 10, 0x1EFD));
AddReward(new BaseReward(typeof(TailorsCraftsmanSatchel), 1074282));
}
/* The Puffy Shirt */
public override object Title
{
get
{
return 1073903;
}
}
/* We elves believe that beauty is expressed in all things, including the garments we
wear. I wish to understand more about human aesthetics, so please kind traveler - could
you bring to me magnificent examples of human fancy shirts? For my thanks, I could teach
you more about the beauty of elven vestements. */
public override object Description
{
get
{
return 1074093;
}
}
/* I will patiently await your reconsideration. */
public override object Refuse
{
get
{
return 1073921;
}
}
/* I will be in your debt if you bring me fancy shirts. */
public override object Uncomplete
{
get
{
return 1073949;
}
}
/* I appreciate your service. Now, see what elven hands can create. */
public override object Complete
{
get
{
return 1073973;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class FromTheGaultierCollectionQuest : BaseQuest
{
public FromTheGaultierCollectionQuest()
: base()
{
AddObjective(new ObtainObjective(typeof(StuddedBustierArms), "studded bustiers", 10, 0x1C0C));
AddReward(new BaseReward(typeof(TailorsCraftsmanSatchel), 1074282));
}
/* From the Gaultier Collection */
public override object Title
{
get
{
return 1073905;
}
}
/* It is my understanding, the females of humankind actually wear on certain occasions a
studded bustier? This is not simply a fanciful tale? Remarkable! It sounds hideously
uncomfortable as well as ludicrously impracticle. But perhaps, I simply do not understand
the nuances of human clothing. Perhaps, I need to see such a studded bustier for myself? */
public override object Description
{
get
{
return 1074095;
}
}
/* I will patiently await your reconsideration. */
public override object Refuse
{
get
{
return 1073921;
}
}
/* I will be in your debt if you bring me studded bustiers. */
public override object Uncomplete
{
get
{
return 1073951;
}
}
/* Truly, it is worse than I feared. Still, I appreciate your efforts on my behalf. */
public override object Complete
{
get
{
return 1073976;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class HuteCoutureQuest : BaseQuest
{
public HuteCoutureQuest()
: base()
{
AddObjective(new ObtainObjective(typeof(FlowerGarland), "flower garlands", 10, 0x2306));
AddReward(new BaseReward(typeof(TailorsCraftsmanSatchel), 1074282));
}
/* H'ute Couture */
public override object Title
{
get
{
return 1073901;
}
}
/* Most human apparel is interesting to elven eyes. But there is one garment - the flower garland -
which sounds very elven indeed. Could I see how a human crafts such an object of beauty? In exchange,
I could share with you the wonders of elven garments. */
public override object Description
{
get
{
return 1074091;
}
}
/* I will patiently await your reconsideration. */
public override object Refuse
{
get
{
return 1073921;
}
}
/* I will be in your debt if you bring me flower garlands. */
public override object Uncomplete
{
get
{
return 1073947;
}
}
/* I appreciate your service. Now, see what elven hands can create. */
public override object Complete
{
get
{
return 1073973;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Ahie : MondainQuester
{
[Constructable]
public Ahie()
: base("Ahie", "the cloth weaver")
{
SetSkill(SkillName.Meditation, 60.0, 83.0);
SetSkill(SkillName.Focus, 60.0, 83.0);
}
public Ahie(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(TheKingOfClothingQuest),
typeof(ThePuffyShirtQuest),
typeof(FromTheGaultierCollectionQuest),
typeof(HuteCoutureQuest)
};
}
}
public override void InitBody()
{
InitStats(100, 100, 25);
Female = true;
Race = Race.Elf;
Hue = 0x853F;
HairItemID = 0x2FCD;
HairHue = 0x90;
}
public override void InitOutfit()
{
AddItem(new ThighBoots(0x901));
AddItem(new FancyShirt(0x72B));
AddItem(new Cloak(0x1C));
AddItem(new Skirt(0x62));
AddItem(new Circlet());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests.Collector
{
public class AlbertaGiacco : BaseQuester
{
[Constructable]
public AlbertaGiacco()
: base("the respected painter")
{
}
public AlbertaGiacco(Serial serial)
: base(serial)
{
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Hue = 0x83F2;
this.Female = true;
this.Body = 0x191;
this.Name = "Alberta Giacco";
}
public override void InitOutfit()
{
this.AddItem(new FancyShirt());
this.AddItem(new Skirt(0x59B));
this.AddItem(new Boots());
this.AddItem(new FeatheredHat(0x59B));
this.AddItem(new FullApron(0x59B));
this.HairItemID = 0x203D; // Pony Tail
this.HairHue = 0x457;
}
public override bool CanTalkTo(PlayerMobile to)
{
QuestSystem qs = to.Quest as CollectorQuest;
if (qs == null)
return false;
return (qs.IsObjectiveInProgress(typeof(FindAlbertaObjective)) ||
qs.IsObjectiveInProgress(typeof(SitOnTheStoolObjective)) ||
qs.IsObjectiveInProgress(typeof(ReturnPaintingObjective)));
}
public override void OnTalk(PlayerMobile player, bool contextMenu)
{
QuestSystem qs = player.Quest;
if (qs is CollectorQuest)
{
this.Direction = this.GetDirectionTo(player);
QuestObjective obj = qs.FindObjective(typeof(FindAlbertaObjective));
if (obj != null && !obj.Completed)
{
obj.Complete();
}
else if (qs.IsObjectiveInProgress(typeof(SitOnTheStoolObjective)))
{
qs.AddConversation(new AlbertaStoolConversation());
}
else if (qs.IsObjectiveInProgress(typeof(ReturnPaintingObjective)))
{
qs.AddConversation(new AlbertaAfterPaintingConversation());
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using Server.Engines.BulkOrders;
namespace Server.Mobiles
{
public class Alchemist : BaseVendor
{
private readonly List<SBInfo> m_SBInfos = new List<SBInfo>();
[Constructable]
public Alchemist()
: base("the alchemist")
{
this.SetSkill(SkillName.Alchemy, 85.0, 100.0);
this.SetSkill(SkillName.TasteID, 65.0, 88.0);
}
#region Bulk Orders
public override BODType BODType { get { return BODType.Alchemy; } }
public override bool IsValidBulkOrder(Item item)
{
return (item is SmallAlchemyBOD || item is LargeAlchemyBOD);
}
public override bool SupportsBulkOrders(Mobile from)
{
return BulkOrderSystem.NewSystemEnabled && from is PlayerMobile && from.Skills[SkillName.Alchemy].Base > 0;
}
public override void OnSuccessfulBulkOrderReceive(Mobile from)
{
if (from is PlayerMobile)
((PlayerMobile)from).NextAlchemyBulkOrder = TimeSpan.Zero;
}
#endregion
public Alchemist(Serial serial)
: base(serial)
{
}
public override NpcGuild NpcGuild
{
get
{
return NpcGuild.MagesGuild;
}
}
public override VendorShoeType ShoeType
{
get
{
return Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals;
}
}
protected override List<SBInfo> SBInfos
{
get
{
return this.m_SBInfos;
}
}
public override void InitSBInfo()
{
this.m_SBInfos.Add(new SBAlchemist(this));
}
public override void InitOutfit()
{
base.InitOutfit();
this.AddItem(new Server.Items.Robe(Utility.RandomPinkHue()));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,198 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests
{
public class TheArtOfWarQuest : BaseQuest
{
public override bool DoneOnce
{
get
{
return true;
}
}
/* The Art of War */
public override object Title
{
get
{
return 1077667;
}
}
/* Head East out of town to Old Haven. Battle monsters there until you have raised your Tactics skill
to 50.<br><center>------</center><br>Knowing how to hold a weapon is only half of the battle. The other
half is knowing how to use it against an opponent. It's one thing to kill a few bunnies now and then
for fun, but a true warrior knows that the right moves to use against a lich will pretty much get your
arse fried by a dragon.<br><br>I'll help teach you how to fight so that when you do come up against that
dragon, maybe you won't have to walk out of there "OooOOooOOOooOO'ing" and looking for a healer.<br><br>
There are some undead that need cleaning out in Old Haven towards the east. Why don't you head on over
there and practice killing things?<br><br>When you feel like you've got the basics down, come back to me
and I'll see if I can scrounge up an item to help you in your adventures later on. */
public override object Description
{
get
{
return 1077670;
}
}
/* That's too bad. I really thought you had it in you. Well, I'm sure those undead will still be there
later, so if you change your mind, feel free to stop on by and I'll help you the best I can. */
public override object Refuse
{
get
{
return 1077671;
}
}
/* You're making some progress, that i can tell, but you're not quite good enough to last for very long
out there by yourself. Head back to Old Haven, to the east, and kill some more undead. */
public override object Uncomplete
{
get
{
return 1077672;
}
}
/* Hey, good job killing those undead! Hopefully someone will come along and clean up the mess. All that
blood and guts tends to stink after a few days, and when the wind blows in from the east, it can raise a
mighty stink!<br><br>Since you performed valiantly, please take these arms and use them well. I've seen
a few too many harvests to be running around out there myself, so you might as well take it.<br><br>There
is a lot left for you to learn, but I think you'll do fine. Remember to keep your elbows in and stick'em
where it hurts the most! */
public override object Complete
{
get
{
return 1077674;
}
}
public TheArtOfWarQuest()
: base()
{
this.AddObjective(new ApprenticeObjective(SkillName.Tactics, 50, "Old Haven Training", 1077668, 1077669));
// 1077668 You feel like practicing combat here would really help you learn to fight better. Your ability to raise your Tactics skill is enhanced in this area.
// 1077669 You feel less able to absorb the lessons of combat. Your Tactics learning potential is no longer enhanced.
this.AddReward(new BaseReward(typeof(ArmsOfArmstrong), 1077675));
}
public override bool CanOffer()
{
#region Scroll of Alacrity
PlayerMobile pm = this.Owner as PlayerMobile;
if (pm.AcceleratedStart > DateTime.UtcNow)
{
this.Owner.SendLocalizedMessage(1077951); // You are already under the effect of an accelerated skillgain scroll.
return false;
}
#endregion
else
return this.Owner.Skills.Tactics.Base < 50;
}
public override void OnCompleted()
{
this.Owner.SendLocalizedMessage(1077673, null, 0x23); // You have achieved the rank of Apprentice Warrior. Return to Alden Armstrong in New Haven to claim your reward.
this.Owner.PlaySound(this.CompleteSound);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class AldenArmstrong : MondainQuester
{
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(TheArtOfWarQuest)
};
}
}
[Constructable]
public AldenArmstrong()
: base("Alden Armstrong", "The Tactics Instructor")
{
this.SetSkill(SkillName.Anatomy, 120.0, 120.0);
this.SetSkill(SkillName.Parry, 120.0, 120.0);
this.SetSkill(SkillName.Healing, 120.0, 120.0);
this.SetSkill(SkillName.Tactics, 120.0, 120.0);
this.SetSkill(SkillName.Swords, 120.0, 120.0);
this.SetSkill(SkillName.Focus, 120.0, 120.0);
}
public AldenArmstrong(Serial serial)
: base(serial)
{
}
public override void Advertise()
{
this.Say(1078136); // There is an art to slaying your enemies swiftly. It's called tactics, and I can teach it to you.
}
public override void OnOfferFailed()
{
this.Say(1077772); // I cannot teach you, for you know all I can teach!
}
public override void InitBody()
{
this.Female = false;
this.CantWalk = true;
this.Race = Race.Human;
base.InitBody();
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new Shoes());
this.AddItem(new StuddedLegs());
this.AddItem(new StuddedGloves());
this.AddItem(new StuddedGorget());
this.AddItem(new StuddedChest());
this.AddItem(new StuddedArms());
this.AddItem(new Katana());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,201 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests
{
public class DefyingTheArcaneQuest : BaseQuest
{
public override bool DoneOnce
{
get
{
return true;
}
}
/* Defying the Arcane */
public override object Title
{
get
{
return 1077621;
}
}
/* Head East out of town and go to Old Haven. Battle spell casting monsters there until you have raised your
Resisting Spells skill to 50.<br><center>------</center><br>Hail and well met! To become a true master of
the arcane art of Magery, I suggest learning the complementary skill known as Resisting Spells. While the
name of this skill may suggest that it helps with resisting all spells, this is not the case. This skill
helps you lessen the severity of spells that lower your stats or ones that last for a specific duration of
time. It does not lessen damage from spells such as Energy Bolt or Flamestrike.<BR><BR>The Magery spells that
can be resisted are Clumsy, Curse, Feeblemind, Mana Drain, Mana Vampire, Paralyze, Paralyze Field, Poison,
Poison Field, and Weaken.<BR><BR>The Necromancy spells that can be resisted are Blood Oath, Corpse Skin, Mind
Rot, and Pain Spike.<BR><BR>At higher ranks, the Resisting Spells skill also benefits you by adding a bonus to
your minimum elemental resists. This bonus is only applied after all other resist modifications - such as from
equipment - has been calculated. It's also not cumulative. It compares the number of your minimum resists to
the calculated value of your modifications and uses the higher of the two values.<BR><BR>As you can see,
Resisting Spells is a difficult skill to understand, and even more difficult to master. This is because in
order to improve it, you will have to put yourself in harm's way - as in the path of one of the above spells.
<BR><BR>Undead have plagued the town of Old Haven. We need your assistance in cleansing the town of this evil
influence. Old Haven is located east of here. Battle the undead spell casters that inhabit there.<BR><BR>Come
back to me once you feel that you are worthy of the rank of Apprentice Mage and I will reward you with an
arcane prize. */
public override object Description
{
get
{
return 1077623;
}
}
/* The ability to resist powerful spells is a taxing experience. I understand your resistance in wanting to
pursue it. If you wish to reconsider, feel free to return to me for Resisting Spells training. Good journey
to you! */
public override object Refuse
{
get
{
return 1077624;
}
}
/* You have not achieved the rank of Apprentice Mage. Come back to me once you feel that you are worthy of the
rank of Apprentice Mage and I will reward you with an arcane prize. */
public override object Uncomplete
{
get
{
return 1077632;
}
}
/* You have successfully begun your journey in becoming a true master of Magery. On behalf of the New Haven Mage
Council I wish to present you with this bracelet. When worn, the Bracelet of Resilience will enhance your resistances
vs. the elements, physical, and poison harm. The Bracelet of Resilience also magically enhances your ability fend
off ranged and melee attacks. I hope it serves you well.*/
public override object Complete
{
get
{
return 1077626;
}
}
public DefyingTheArcaneQuest()
: base()
{
this.AddObjective(new ApprenticeObjective(SkillName.MagicResist, 50, "Old Haven Training", 1077494, 1077588));
// 1077494 Your Resisting Spells potential is greatly enhanced while questing in this area.
// 1077588 You are not in the quest area for Apprentice Mage. Your Resisting Spells potential is not enhanced here.
this.AddReward(new BaseReward(typeof(BraceletOfResilience), 1077627));
}
public override bool CanOffer()
{
#region Scroll of Alacrity
PlayerMobile pm = this.Owner as PlayerMobile;
if (pm.AcceleratedStart > DateTime.UtcNow)
{
this.Owner.SendLocalizedMessage(1077951); // You are already under the effect of an accelerated skillgain scroll.
return false;
}
#endregion
else
return this.Owner.Skills.MagicResist.Base < 50;
}
public override void OnCompleted()
{
this.Owner.SendLocalizedMessage(1077625, null, 0x23); // You have achieved the rank of Apprentice Mage (for Resisting Spells). Return to Alefian in New Haven to receive your arcane prize.
this.Owner.PlaySound(this.CompleteSound);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Alefian : MondainQuester
{
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(DefyingTheArcaneQuest)
};
}
}
[Constructable]
public Alefian()
: base("Alefian", "The Resisting Spells Instructor")
{
this.SetSkill(SkillName.EvalInt, 120.0, 120.0);
this.SetSkill(SkillName.Inscribe, 120.0, 120.0);
this.SetSkill(SkillName.Magery, 120.0, 120.0);
this.SetSkill(SkillName.MagicResist, 120.0, 120.0);
this.SetSkill(SkillName.Wrestling, 120.0, 120.0);
this.SetSkill(SkillName.Meditation, 120.0, 120.0);
}
public Alefian(Serial serial)
: base(serial)
{
}
public override void Advertise()
{
this.Say(1078130); // A mage should learn how to resist spells.
}
public override void OnOfferFailed()
{
this.Say(1077772); // I cannot teach you, for you know all I can teach!
}
public override void InitBody()
{
this.Female = false;
this.CantWalk = true;
this.Race = Race.Human;
base.InitBody();
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new Robe());
this.AddItem(new Sandals());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,127 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests
{
public class ItsElementalQuest : BaseQuest
{
public ItsElementalQuest()
: base()
{
this.AddObjective(new SlayObjective(typeof(FireElemental), "fire elementals", 4));
this.AddObjective(new SlayObjective(typeof(WaterElemental), "water elementals", 4));
this.AddObjective(new SlayObjective(typeof(EarthElemental), "earth elementals", 4));
this.AddReward(new BaseReward(typeof(TreasureBag), 1072583));
}
/* It's Elemental */
public override object Title
{
get
{
return 1073089;
}
}
/* The universe is all about balance my friend. Tip one end, you must balance the other. That's
why I must ask you to kill not just one kind of elemental, but three kinds. Snuff out some Fire,
douse a few Water, and crush some Earth elementals and I'll pay you for your trouble. */
public override object Description
{
get
{
return 1073579;
}
}
/* I hope you'll reconsider. Until then, farwell. */
public override object Refuse
{
get
{
return 1073580;
}
}
/* Four of each, that's all I ask. Water, earth and fire. */
public override object Uncomplete
{
get
{
return 1073599;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Alejaha : MondainQuester
{
[Constructable]
public Alejaha()
: base("Elder Alejaha", "the wise")
{
this.SetSkill(SkillName.Meditation, 60.0, 83.0);
this.SetSkill(SkillName.Focus, 60.0, 83.0);
}
public Alejaha(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(ItsElementalQuest)
};
}
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = true;
this.Race = Race.Elf;
this.Hue = 0x8361;
this.HairItemID = 0x2FCD;
this.HairHue = 0x852;
}
public override void InitOutfit()
{
this.AddItem(new Sandals(0x1BB));
this.AddItem(new Cloak(0x59));
this.AddItem(new Skirt(0x901));
this.AddItem(new GemmedCirclet());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class Alelle : BaseVendor
{
private readonly List<SBInfo> m_SBInfos = new List<SBInfo>();
[Constructable]
public Alelle()
: base("the aborist")
{
this.Name = "Alelle";
}
public Alelle(Serial serial)
: base(serial)
{
}
public override bool CanTeach
{
get
{
return false;
}
}
public override bool IsInvulnerable
{
get
{
return true;
}
}
protected override List<SBInfo> SBInfos
{
get
{
return this.m_SBInfos;
}
}
public override void InitSBInfo()
{
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = true;
this.Race = Race.Elf;
this.Hue = 0x8374;
this.HairItemID = 0x2FCC;
this.HairHue = 0x238;
}
public override void InitOutfit()
{
this.AddItem(new ElvenBoots(0x1BB));
Item item;
item = new LeafGloves();
item.Hue = 0x1BB;
this.AddItem(item);
item = new LeafChest();
item.Hue = 0x37;
this.AddItem(item);
item = new LeafLegs();
item.Hue = 0x746;
this.AddItem(item);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class Alethanian : BaseVendor
{
private readonly List<SBInfo> m_SBInfos = new List<SBInfo>();
[Constructable]
public Alethanian()
: base("the wise")
{
this.Name = "Elder Alethanian";
}
public Alethanian(Serial serial)
: base(serial)
{
}
public override bool CanTeach
{
get
{
return false;
}
}
public override bool IsInvulnerable
{
get
{
return true;
}
}
protected override List<SBInfo> SBInfos
{
get
{
return this.m_SBInfos;
}
}
public override void InitSBInfo()
{
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = true;
this.Race = Race.Elf;
this.Hue = 0x876C;
this.HairItemID = 0x2FC2;
this.HairHue = 0x368;
}
public override void InitOutfit()
{
this.AddItem(new ElvenBoots());
this.AddItem(new GemmedCirclet());
this.AddItem(new HidePants());
this.AddItem(new HideFemaleChest());
this.AddItem(new HidePauldrons());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,232 @@
using System;
using Server.Items;
using Server.Targeting;
using Server.Mobiles;
using System.Collections;
using System.Collections.Generic;
namespace Server.Engines.Quests
{
public class TheExchangeQuest : BaseQuest
{
public TheExchangeQuest()
: base()
{
this.AddObjective(new ObtainObjective(typeof(WhiteChocolate), "White Chocolates", 5, 0xF11));
this.AddObjective(new ObtainObjective(typeof(DarkSapphire), "Dark Sapphire", 1, 0x3192));
this.AddReward(new BaseReward(typeof(AverageImbuingBag), 1113768));//Average Imbuing Bag
this.AddReward(new BaseReward("Loyalty Rating"));
}
/*The Exchange*/
public override object Title
{
get
{
return 1113777;
}
}
//Hello there! Hail and well met, and all of that. I must apologize in advance for being
//so impatient, but you must help me! You see, my mother and my eldest sister are visiting
//soon, and I haven<65>t seen them in quite awhile, so I want to present them both with a
//surprise when they arrive.<br><br>My sister absolutely adores white chocolate, but
//gargoyles don<6F>t seem to care for it much, so I haven<65>t been able to find any here.
//It was recently my mother<65>s birthday, and I know that she would love some finely
//crafted gargish jewelry, but the jeweler hasn<73>t had her favorite jewel in stock for
//quite some time. If you could help me obtain five pieces of white chocolate and one
//dark sapphire, I will reward you with a bag of hard to obtain imbuing ingredients.
public override object Description
{
get
{
return 1113778;
}
}
//Oh, no, you must help me! Please say that you will!
public override object Refuse
{
get
{
return 1113779;
}
}
//Remember, I need five pieces of white chocolate, and one dark sapphire. Please do hurry!
public override object Uncomplete
{
get
{
return 1113780;
}
}
//Oh, thank you so very much! I cannot begin to thank you enough for helping me find
//these presents. Here is your reward. You<6F>ll have to excuse me while I set this dark
//sapphire in a setting that will best highlight the cut. Farewell!
public override object Complete
{
get
{
return 1113781;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class AWorthyPropositionQuest : BaseQuest
{
public AWorthyPropositionQuest()
: base()
{
this.AddObjective(new ObtainObjective(typeof(BambooFlute), "Bamboo Flutes", 10, 0x2805));
this.AddObjective(new ObtainObjective(typeof(ElvenFletching), "Elven Fletching", 1, 0x5737));
this.AddReward(new BaseReward(typeof(ValuableImbuingBag), 1113769));//Valuable Imbuing Bag
this.AddReward(new BaseReward("Loyalty Rating"));
}
/* A Worthy Proposition */
public override object Title
{
get
{
return 1113782;
}
}
//Hello, welcome to the shop. I don't own it, but the gargoyles here are as keen to
//learn from me as I am from them. They've been helping me with the work on my latest
//invention, but I am short some parts. Perhaps you could help me?<br><br>I have heard
//that the bamboo flutes of the Tokuno Islands are exceptionally strong for their weight,
//and nothing can beat elven fletching for strength in holding them together. If you
//would bring me, say, ten bamboo flutes and some elven fletching, I have some valuable
//imbuing ingredients I<>ll give you in exchange. What do you say?
public override object Description
{
get
{
return 1113783;
}
}
//Well, if you change your mind, I<>ll be here.
public override object Refuse
{
get
{
return 1113784;
}
}
//Hmm, what is that? Oh yes, I would like you to bring me ten bamboo flutes and some elven
//fletching for my fly<6C> er, my invention.
public override object Uncomplete
{
get
{
return 1113785;
}
}
//These are of fine quality! I think they will work just fine to reinforce the floor of the
//basket. What<61>s that? Did I say basket? I meant, bakery! Yes, I am inventing a, um, floor
//for a bakery. There is a great need for that, you know! Ok, now please leave so I can get
//back to work. Thank you, bye, bye!
public override object Complete
{
get
{
return 1113786;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Aliabeth : MondainQuester
{
public override void InitSBInfo()
{
this.SBInfos.Add(new SBTinker(this));
}
[Constructable]
public Aliabeth()
: base("Aliabeth", "the Tinker")
{
this.SetSkill(SkillName.Lockpicking, 60.0, 83.0);
this.SetSkill(SkillName.RemoveTrap, 75.0, 98.0);
this.SetSkill(SkillName.Tinkering, 64.0, 100.0);
}
public Aliabeth(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(AWorthyPropositionQuest),
typeof(TheExchangeQuest),
};
}
}
public override void InitBody()
{
this.Female = true;
//this.CantWalk = true;
this.Race = Race.Human;
base.InitBody();
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new Kilt(Utility.RandomNeutralHue()));
this.AddItem(new Shirt(Utility.RandomNeutralHue()));
this.AddItem(new Sandals());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class Aluniol : BaseVendor
{
private readonly List<SBInfo> m_SBInfos = new List<SBInfo>();
[Constructable]
public Aluniol()
: base("the healer")
{
this.Name = "Aluniol";
}
public Aluniol(Serial serial)
: base(serial)
{
}
public override bool CanTeach
{
get
{
return false;
}
}
public override bool IsInvulnerable
{
get
{
return true;
}
}
protected override List<SBInfo> SBInfos
{
get
{
return this.m_SBInfos;
}
}
public override void InitSBInfo()
{
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = false;
this.Race = Race.Elf;
this.Hue = 0x8383;
this.HairItemID = 0x2FBF;
this.HairHue = 0x323;
}
public override void InitOutfit()
{
this.AddItem(new ElvenBoots(0x1BB));
this.AddItem(new MaleElvenRobe(0x47E));
this.AddItem(new WildStaff());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,241 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests.Ambitious
{
public abstract class BaseAmbitiousSolenQueen : BaseQuester
{
public BaseAmbitiousSolenQueen()
{
}
public BaseAmbitiousSolenQueen(Serial serial)
: base(serial)
{
}
public abstract bool RedSolen { get; }
public override bool DisallowAllMoves
{
get
{
return false;
}
}
public override void InitBody()
{
this.Name = "an ambitious solen queen";
this.Body = 0x30F;
if (!this.RedSolen)
this.Hue = 0x453;
this.SpeechHue = 0;
}
public override int GetIdleSound()
{
return 0x10D;
}
public override void OnTalk(PlayerMobile player, bool contextMenu)
{
this.Direction = this.GetDirectionTo(player);
AmbitiousQueenQuest qs = player.Quest as AmbitiousQueenQuest;
if (qs != null && qs.RedSolen == this.RedSolen)
{
if (qs.IsObjectiveInProgress(typeof(KillQueensObjective)))
{
qs.AddConversation(new DuringKillQueensConversation());
}
else
{
QuestObjective obj = qs.FindObjective(typeof(ReturnAfterKillsObjective));
if (obj != null && !obj.Completed)
{
obj.Complete();
}
else if (qs.IsObjectiveInProgress(typeof(GatherFungiObjective)))
{
qs.AddConversation(new DuringFungiGatheringConversation());
}
else
{
GetRewardObjective lastObj = qs.FindObjective(typeof(GetRewardObjective)) as GetRewardObjective;
if (lastObj != null && !lastObj.Completed)
{
bool bagOfSending = lastObj.BagOfSending;
bool powderOfTranslocation = lastObj.PowderOfTranslocation;
bool gold = lastObj.Gold;
AmbitiousQueenQuest.GiveRewardTo(player, ref bagOfSending, ref powderOfTranslocation, ref gold);
lastObj.BagOfSending = bagOfSending;
lastObj.PowderOfTranslocation = powderOfTranslocation;
lastObj.Gold = gold;
if (!bagOfSending && !powderOfTranslocation && !gold)
{
lastObj.Complete();
}
else
{
qs.AddConversation(new FullBackpackConversation(false, lastObj.BagOfSending, lastObj.PowderOfTranslocation, lastObj.Gold));
}
}
}
}
}
else
{
QuestSystem newQuest = new AmbitiousQueenQuest(player, this.RedSolen);
if (player.Quest == null && QuestSystem.CanOfferQuest(player, typeof(AmbitiousQueenQuest)))
{
newQuest.SendOffer();
}
else
{
newQuest.AddConversation(new DontOfferConversation());
}
}
}
public override bool OnDragDrop(Mobile from, Item dropped)
{
this.Direction = this.GetDirectionTo(from);
PlayerMobile player = from as PlayerMobile;
if (player != null)
{
AmbitiousQueenQuest qs = player.Quest as AmbitiousQueenQuest;
if (qs != null && qs.RedSolen == this.RedSolen)
{
QuestObjective obj = qs.FindObjective(typeof(GatherFungiObjective));
if (obj != null && !obj.Completed)
{
if (dropped is ZoogiFungus)
{
ZoogiFungus fungi = (ZoogiFungus)dropped;
if (fungi.Amount >= 50)
{
obj.Complete();
fungi.Amount -= 50;
if (fungi.Amount == 0)
{
fungi.Delete();
return true;
}
else
{
return false;
}
}
else
{
this.SayTo(player, 1054072); // Our arrangement was for 50 of the zoogi fungus. Please return to me when you have that amount.
return false;
}
}
}
}
}
return base.OnDragDrop(from, dropped);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
public class RedAmbitiousSolenQueen : BaseAmbitiousSolenQueen
{
[Constructable]
public RedAmbitiousSolenQueen()
{
}
public RedAmbitiousSolenQueen(Serial serial)
: base(serial)
{
}
public override bool RedSolen
{
get
{
return true;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
public class BlackAmbitiousSolenQueen : BaseAmbitiousSolenQueen
{
[Constructable]
public BlackAmbitiousSolenQueen()
{
}
public BlackAmbitiousSolenQueen(Serial serial)
: base(serial)
{
}
public override bool RedSolen
{
get
{
return false;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View File

@@ -0,0 +1,204 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests
{
public class TheRightToolForTheJobQuest : BaseQuest
{
public override bool DoneOnce
{
get
{
return true;
}
}
/* The Right Tool for the Job */
public override object Title
{
get
{
return 1077741;
}
}
/* Create new scissors and hammers while inside Amelia's workshop. Try making scissors up to 45 skill, the switch
to making hammers until 50 skill.<br><center>-----</center><br>Hello! I guess you're here to learn something about
Tinkering, eh? You've come to the right place, as Tinkering is what I've dedicated my life to. <br><br>You'll need
two things to get started: a supply of ingots and the right tools for the job. You can either buy ingots from the
market, or go mine them yourself. As for tools, you can try making your own set of Tinker's Tools, or if you'd prefer
to buy them, I have some for sale.<br><br>Working here in my shop will let me give you pointers as you go, so you'll
be able to learn faster than anywhere else. Start off making scissors until you reach 45 tinkering skill, then switch
to hammers until you've achieved 50. Once you've done that, come talk to me and I'll give you something for your hard
work. */
public override object Description
{
get
{
return 1077744;
}
}
/* I<>m disappointed that you aren<65>t interested in learning more about Tinkering. It<49>s really such a useful skill!<br><br>
*Amelia smiles*<br><br>At least you know where to find me if you change your mind, since I rarely spend time outside
of this shop. */
public override object Refuse
{
get
{
return 1077745;
}
}
/* Nice going! You're not quite at Apprentice Tinkering yet, though, so you better get back to work. Remember that the
quickest way to learn is to make scissors up until 45 skill, and then switch to hammers. Also, don't forget that working
here in my shop will let me give you tips so you can learn faster. */
public override object Uncomplete
{
get
{
return 1077746;
}
}
/* You've done it! Look at our brand new Apprentice Tinker! You've still got quite a lot to learn if you want to be a
Grandmaster Tinker, but I believe you can do it! Just keep in mind that if you're tinkering just to practice and improve
your skill, make items that are moderately difficult (60-80% success chance), and try to stick to ones that use less
ingots. <br><br>Come here, my brand new Apprentice Tinker, I want to give you something special. I created this just
for you, so I hope you like it. It's a set of Tinker's Tools that contains a bit of magic. These tools have more charges
than any Tinker's Tools a Tinker can make. You can even use them to make a normal set of tools, so that way you won't
ever find yourself stuck somewhere with no tools! */
public override object Complete
{
get
{
return 1077748;
}
}
public TheRightToolForTheJobQuest()
: base()
{
this.AddObjective(new ApprenticeObjective(SkillName.Tinkering, 50, "Springs And Things Workshop", 1077742, 1077743));
// 1077742 By tinkering inside of Amelia<69>s workshop, she is able to give you advice. This helps you hone your Tinkering skill faster than normal.
// 1077743 Since you<6F>ve left Amelia<69>s workshop, she cannot give you advice. Your Tinkering learning potential is no longer enhanced.
this.AddReward(new BaseReward(typeof(AmeliasToolbox), 1077749));
}
public override bool CanOffer()
{
#region Scroll of Alacrity
PlayerMobile pm = this.Owner as PlayerMobile;
if (pm.AcceleratedStart > DateTime.UtcNow)
{
this.Owner.SendLocalizedMessage(1077951); // You are already under the effect of an accelerated skillgain scroll.
return false;
}
#endregion
else
return this.Owner.Skills.Tinkering.Base < 50;
}
public override void OnCompleted()
{
this.Owner.SendLocalizedMessage(1077747, null, 0x23); // You have achieved the rank of Apprentice Tinker. Talk to Amelia Youngstone in New Haven to see what kind of reward she has waiting for you.
this.Owner.PlaySound(this.CompleteSound);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Amelia : MondainQuester
{
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(TheRightToolForTheJobQuest)
};
}
}
public override void InitSBInfo()
{
this.SBInfos.Add(new SBTinker(this));
}
[Constructable]
public Amelia()
: base("Amelia Youngstone", "The Tinkering Instructor")
{
this.SetSkill(SkillName.ArmsLore, 120.0, 120.0);
this.SetSkill(SkillName.Blacksmith, 120.0, 120.0);
this.SetSkill(SkillName.Magery, 120.0, 120.0);
this.SetSkill(SkillName.Tactics, 120.0, 120.0);
this.SetSkill(SkillName.Swords, 120.0, 120.0);
this.SetSkill(SkillName.Tinkering, 120.0, 120.0);
this.SetSkill(SkillName.Mining, 120.0, 120.0);
}
public Amelia(Serial serial)
: base(serial)
{
}
public override void Advertise()
{
this.Say(1078123); // Tinkering is very useful for a blacksmith. You can make your own tools.
}
public override void OnOfferFailed()
{
this.Say(1077772); // I cannot teach you, for you know all I can teach!
}
public override void InitBody()
{
this.Female = true;
this.CantWalk = true;
this.Race = Race.Human;
base.InitBody();
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new Sandals());
this.AddItem(new ShortPants());
this.AddItem(new HalfApron(0x8AB));
this.AddItem(new Doublet());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using Server.Items;
namespace Server.Mobiles
{
public class Aminia : BaseCreature
{
[Constructable]
public Aminia()
: base(AIType.AI_Melee, FightMode.None, 2, 1, 0.5, 2)
{
this.Name = "Aminia";
this.Title = "the master weaponsmith's wife";
this.Blessed = true;
this.InitStats(100, 100, 25);
this.Female = true;
this.Race = Race.Human;
this.Hue = 0x83ED;
this.HairItemID = 0x203B;
this.HairHue = 0x454;
this.AddItem(new Backpack());
this.AddItem(new Sandals(0x75B));
this.AddItem(new Tunic(0x4BF));
this.AddItem(new Skirt(0x8FD));
}
public Aminia(Serial serial)
: base(serial)
{
}
public override void OnThink()
{
int hours = 0;
int minutes = 0;
Clock.GetTime(this.Map, this.Location.X, this.Location.Y, out hours, out minutes);
if (hours == 21)
{
this.Blessed = false;
this.Body = 0x17;
}
else
{
this.Blessed = true;
this.Body = 0x191;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,194 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests
{
public class KnowThineEnemyQuest : BaseQuest
{
public override bool DoneOnce
{
get
{
return true;
}
}
/* Knowing Thine Enemy */
public override object Title
{
get
{
return 1077685;
}
}
/* Head East out of town to Old Haven. Battle monsters there, or heal yourself and other players, until you
have raised your Anatomy skill to 50.<br><center>------</center><br>Hail and well met. You must be here to
improve your knowledge of Anatomy. Well, you've come to the right place because I can teach you what you need
to know. At least all you'll need to know for now. Haha!<br><br>Knowing about how living things work inside
can be a very useful skill. Not only can you learn where to strike an opponent to hurt him the most, but you
can use what you learn to heal wounds better as well. Just walking around town, you can even tell if someone
is strong or weak or if they happen to be particularly dexterous or not.<BR><BR>If you're interested in learning
more, I'd advise you to head out to Old Haven, just to the east, and jump into the fray. You'll learn best by
engaging in combat while keeping you and your fellow adventurers healed, or you can even try sizing up your
opponents.<br><br>While you're gone, I'll dig up something you may find useful. */
public override object Description
{
get
{
return 1077688;
}
}
/* It's your choice, but I wouldn't head out there without knowing what makes those things tick inside! If you
change your mind, you can find me right here dissecting frogs, cats or even the occasional unlucky adventurer. */
public override object Refuse
{
get
{
return 1077689;
}
}
/* I'm surprised to see you back so soon. You've still got a ways to go if you want to really understand the
science of Anatomy. Head out to Old Haven and practice combat and healing yourself or other adventurers. */
public override object Uncomplete
{
get
{
return 1077690;
}
}
/* By the Virtues, you've done it! Congratulations mate! You still have quite a ways to go if you want to perfect
your knowledge of Anatomy, but I know you'll get there someday. Just keep at it.<br><br>In the meantime, here's a
piece of armor that you might find useful. It's not fancy, but it'll serve you well if you choose to wear it.<br>
<br>Happy adventuring, and remember to keep your cranium separate from your clavicle! */
public override object Complete
{
get
{
return 1077692;
}
}
public KnowThineEnemyQuest()
: base()
{
this.AddObjective(new ApprenticeObjective(SkillName.Anatomy, 50, "Old Haven Training", 1077686, 1077687));
// 1077686 You feel very willing to learn more about the body. Your ability to hone your Anatomy skill is enhanced in this area.
// 1077687 You lose your ambition to learn about the body. Your Anatomy skill learning potential is no longer enhanced.
this.AddReward(new BaseReward(typeof(TunicOfGuarding), 1077693));
}
public override bool CanOffer()
{
#region Scroll of Alacrity
PlayerMobile pm = this.Owner as PlayerMobile;
if (pm.AcceleratedStart > DateTime.UtcNow)
{
this.Owner.SendLocalizedMessage(1077951); // You are already under the effect of an accelerated skillgain scroll.
return false;
}
#endregion
else
return this.Owner.Skills.Anatomy.Base < 50;
}
public override void OnCompleted()
{
this.Owner.SendLocalizedMessage(1077691, null, 0x23); // You have achieved the rank of Apprentice Healer (for Anatomy). Return to Andreas Vesalius in New Haven as soon as you can to claim your reward.
this.Owner.PlaySound(this.CompleteSound);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class AndreasVesalius : MondainQuester
{
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(KnowThineEnemyQuest)
};
}
}
[Constructable]
public AndreasVesalius()
: base("Andreas Vesalius", "The Anatomy Instructor")
{
this.SetSkill(SkillName.Anatomy, 120.0, 120.0);
this.SetSkill(SkillName.Parry, 120.0, 120.0);
this.SetSkill(SkillName.Healing, 120.0, 120.0);
this.SetSkill(SkillName.Tactics, 120.0, 120.0);
this.SetSkill(SkillName.Swords, 120.0, 120.0);
this.SetSkill(SkillName.Focus, 120.0, 120.0);
}
public AndreasVesalius(Serial serial)
: base(serial)
{
}
public override void Advertise()
{
this.Say(1078138); // Learning of the body will allow you to excel in combat.
}
public override void OnOfferFailed()
{
this.Say(1077772); // I cannot teach you, for you know all I can teach!
}
public override void InitBody()
{
this.Female = false;
this.CantWalk = true;
this.Race = Race.Human;
base.InitBody();
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new BlackStaff());
this.AddItem(new Boots());
this.AddItem(new LongPants());
this.AddItem(new Tunic(0x66D));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,185 @@
using System;
using Server.Items;
namespace Server.Engines.Quests
{
public class SplitEndsQuest : BaseQuest
{
public SplitEndsQuest()
: base()
{
this.AddObjective(new ObtainObjective(typeof(Arrow), "arrow", 20, 0xF3F));
this.AddReward(new BaseReward(typeof(FletchersSatchel), 1074282)); // Craftsman's Satchel
}
/* Split Ends */
public override object Title
{
get
{
return 1075506;
}
}
/* *sighs* I think bowcrafting is a might beyond my talents. Say there, you look a bit more confident with tools.
Can I persuade thee to make a few arrows? You could have my satchel in return... 'tis useless to me! You'll need a
fletching kit to start, some feathers, and a few arrow shafts. Just use the fletching kit while you have the other
things, and I'm sure you'll figure out the rest. */
public override object Description
{
get
{
return 1075507;
}
}
/* Oh. Well. I'll just keep trying alone, I suppose... */
public override object Refuse
{
get
{
return 1075508;
}
}
/* You're not quite done yet. Get back to work! */
public override object Uncomplete
{
get
{
return 1072271;
}
}
/* Thanks for helping me out. Here's the reward I promised you. */
public override object Complete
{
get
{
return 1072272;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Andric : MondainQuester
{
[Constructable]
public Andric()
: base("Andric", "the archer trainer")
{
this.SetSkill(SkillName.Archery, 65.0, 88.0);
}
public Andric(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(SplitEndsQuest)
};
}
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = false;
this.CantWalk = true;
this.Race = Race.Human;
this.Hue = 0x8407;
this.HairItemID = 0x2049;
this.HairHue = 0x6CE;
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new Boots(0x1BB));
Item item;
item = new LeatherLegs();
item.Hue = 0x6C8;
this.AddItem(item);
item = new LeatherGloves();
item.Hue = 0x1BB;
this.AddItem(item);
item = new LeatherChest();
item.Hue = 0x1BB;
this.AddItem(item);
item = new LeatherArms();
item.Hue = 0x4C7;
this.AddItem(item);
item = new CompositeBow();
item.Hue = 0x5DD;
this.AddItem(item);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class FletchersSatchel : Backpack
{
[Constructable]
public FletchersSatchel()
: base()
{
this.Hue = BaseReward.SatchelHue();
this.AddItem(new Feather(10));
this.AddItem(new FletcherTools());
}
public FletchersSatchel(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using Server.Items;
namespace Server.Engines.Quests
{
public class Andros : MondainQuester
{
[Constructable]
public Andros()
: base("Andros", "the blacksmith")
{
}
public Andros(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return null;
}
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = false;
this.Race = Race.Human;
this.Hue = 0x8409;
this.HairItemID = 0x2049;
this.HairHue = 0x45E;
this.FacialHairItemID = 0x2041;
this.FacialHairHue = 0x45E;
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new Boots(0x901));
this.AddItem(new LongPants(0x1BB));
this.AddItem(new FancyShirt(0x60B));
this.AddItem(new FullApron(0x901));
this.AddItem(new SmithHammer());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class Aneen : BaseVendor
{
private readonly List<SBInfo> m_SBInfos = new List<SBInfo>();
[Constructable]
public Aneen()
: base("the keeper of tradition")
{
this.Name = "Lorekeeper Aneen";
}
public Aneen(Serial serial)
: base(serial)
{
}
public override bool CanTeach
{
get
{
return false;
}
}
public override bool IsInvulnerable
{
get
{
return true;
}
}
protected override List<SBInfo> SBInfos
{
get
{
return this.m_SBInfos;
}
}
public override void InitSBInfo()
{
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = false;
this.Race = Race.Elf;
this.Hue = 0x83E5;
this.HairItemID = 0x2FBF;
this.HairHue = 0x90;
}
public override void InitOutfit()
{
this.AddItem(new Sandals(0x1BB));
this.AddItem(new MaleElvenRobe(0x48F));
this.AddItem(new Item(0xDF2));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,255 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests
{
public class CircleOfLifeQuest : BaseQuest
{
public CircleOfLifeQuest()
: base()
{
AddObjective(new SlayObjective(typeof(BogThing), "bog things", 8));
AddReward(new BaseReward(typeof(LargeTreasureBag), 1072706));
}
/* Circle of Life */
public override object Title
{
get
{
return 1073656;
}
}
/* There's been a bumper crop of evil with the Bog Things in these parts, my friend. Though they are
foul creatures, they are also most fecund. Slay one and you make the land more fertile. Even better,
slay several and I will give you whatever coin I can spare. */
public override object Description
{
get
{
return 1073695;
}
}
/* Perhaps you'll change your mind and return at some point. */
public override object Refuse
{
get
{
return 1073733;
}
}
/* Continue to seek and kill the Bog Things. */
public override object Uncomplete
{
get
{
return 1073736;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class DustToDustQuest : BaseQuest
{
public DustToDustQuest()
: base()
{
AddObjective(new SlayObjective(typeof(EarthElemental), "earth elementals", 12));
AddReward(new BaseReward(typeof(TreasureBag), 1072583));
}
/* Dust to Dust */
public override object Title
{
get
{
return 1073074;
}
}
/* You want to hear about trouble? I got trouble. How's angry piles of granite walking around for
trouble? Maybe they don't like the mining, maybe it's the farming. I don't know. All I know is
someone's got to turn them back to potting soil. And it'd be worth a pretty penny to the soul that
does it. */
public override object Description
{
get
{
return 1073564;
}
}
/* I hope you'll reconsider. Until then, farwell. */
public override object Refuse
{
get
{
return 1073580;
}
}
/* You got rocks in your head? I said to kill 12 earth elementals, okay? */
public override object Uncomplete
{
get
{
return 1073584;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class ArchSupportQuest : BaseQuest
{
public ArchSupportQuest()
: base()
{
AddObjective(new ObtainObjective(typeof(FootStool), "foot stools", 10, 0xB5E));
AddReward(new BaseReward(typeof(CarpentersCraftsmanSatchel), 1074282));
}
/* Arch Support */
public override object Title
{
get
{
return 1073882;
}
}
/* How clever humans are - to understand the need of feet to rest from time to time! Imagine creating
a special stool just for weary toes. I would like to examine and learn the secret of their making.
Would you bring me some foot stools to examine? */
public override object Description
{
get
{
return 1074072;
}
}
/* I will patiently await your reconsideration. */
public override object Refuse
{
get
{
return 1073921;
}
}
/* I will be in your debt if you bring me foot stools. */
public override object Uncomplete
{
get
{
return 1073928;
}
}
/* My thanks for your service. Now, I will show you something of elven carpentry. */
public override object Complete
{
get
{
return 1073969;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Aniel : MondainQuester
{
[Constructable]
public Aniel()
: base("Aniel", "the aborist")
{
SetSkill(SkillName.Meditation, 60.0, 83.0);
SetSkill(SkillName.Focus, 60.0, 83.0);
}
public Aniel(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(GlassyFoeQuest),
typeof(CircleOfLifeQuest),
typeof(DustToDustQuest),
typeof(ArchSupportQuest)
};
}
}
public override void InitBody()
{
InitStats(100, 100, 25);
Female = false;
Race = Race.Elf;
Hue = 0x8384;
HairItemID = 0x2FC2;
HairHue = 0x36;
}
public override void InitOutfit()
{
AddItem(new ElvenBoots(0x901));
AddItem(new HalfApron(0x759));
AddItem(new ElvenPants(0x901));
AddItem(new LeafChest());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,674 @@
#region References
using System;
using System.Collections.Generic;
using Server.ContextMenus;
using Server.Gumps;
using Server.Items;
using Server.Network;
using Server.Targeting;
using Server.Engines.Quests;
using System.Linq;
#endregion
namespace Server.Mobiles
{
public class AnimalTrainer : BaseVendor
{
private readonly List<SBInfo> m_SBInfos = new List<SBInfo>();
[Constructable]
public AnimalTrainer()
: base("the animal trainer")
{
SetSkill(SkillName.AnimalLore, 64.0, 100.0);
SetSkill(SkillName.AnimalTaming, 90.0, 100.0);
SetSkill(SkillName.Veterinary, 65.0, 88.0);
}
public AnimalTrainer(Serial serial)
: base(serial)
{ }
protected override List<SBInfo> SBInfos { get { return m_SBInfos; } }
public override VendorShoeType ShoeType { get { return Female ? VendorShoeType.ThighBoots : VendorShoeType.Boots; } }
public override void InitSBInfo()
{
m_SBInfos.Add(new SBAnimalTrainer());
}
public override int GetShoeHue()
{
return 0;
}
public override void InitOutfit()
{
base.InitOutfit();
AddItem(Utility.RandomBool() ? new QuarterStaff() : (Item)new ShepherdsCrook());
}
public override void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
{
if (from.Alive)
{
list.Add(new StableEntry(this, from));
if (from.Stabled.Count > 0)
{
list.Add(new ClaimAllEntry(this, from));
}
}
base.AddCustomContextEntries(from, list);
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (PetTrainingHelper.Enabled)
{
list.Add(1072269); // Quest Giver
}
}
private DateTime _NextTalk;
public override void OnMovement(Mobile m, Point3D oldLocation)
{
if (PetTrainingHelper.Enabled && m.Alive && !m.Hidden && m is PlayerMobile)
{
PlayerMobile pm = (PlayerMobile)m;
if (InLOS(m) && InRange(m, 8) && !InRange(oldLocation, 8) && DateTime.UtcNow >= _NextTalk)
{
if (Utility.Random(100) < 50)
Say(1157526); // Such an exciting time to be an Animal Trainer! New taming techniques have been discovered!
_NextTalk = DateTime.UtcNow + TimeSpan.FromSeconds(15);
}
}
}
private Type[] _Quests = { typeof(TamingPetQuest), typeof(UsingAnimalLoreQuest), typeof(LeadingIntoBattleQuest), typeof(TeachingSomethingNewQuest) };
public override void OnDoubleClick(Mobile m)
{
if (PetTrainingHelper.Enabled && m is PlayerMobile && m.InRange(Location, 5))
{
CheckQuest((PlayerMobile)m);
}
}
public bool CheckQuest(PlayerMobile player)
{
for (int i = 0; i < _Quests.Length; i++)
{
var quest = player.Quests.FirstOrDefault(q => q.GetType() == _Quests[i]);
if (quest != null)
{
if (quest.Completed)
{
if (quest.GetType() != typeof(TeachingSomethingNewQuest))
{
quest.GiveRewards();
}
else
{
player.SendGump(new MondainQuestGump(quest, MondainQuestGump.Section.Complete, false, true));
}
return true;
}
else
{
player.SendGump(new MondainQuestGump(quest, MondainQuestGump.Section.InProgress, false));
quest.InProgress();
}
return false;
}
}
BaseQuest questt = new TamingPetQuest();
questt.Owner = player;
questt.Quester = this;
player.CloseGump(typeof(MondainQuestGump));
player.SendGump(new MondainQuestGump(questt));
return true;
}
public static int GetMaxStabled(Mobile from)
{
var taming = from.Skills[SkillName.AnimalTaming].Value;
var anlore = from.Skills[SkillName.AnimalLore].Value;
var vetern = from.Skills[SkillName.Veterinary].Value;
var sklsum = taming + anlore + vetern;
int max = from is PlayerMobile ? ((PlayerMobile)from).RewardStableSlots : 0;
if (sklsum >= 240.0)
{
max += 5;
}
else if (sklsum >= 200.0)
{
max += 4;
}
else if (sklsum >= 160.0)
{
max += 3;
}
else
{
max += 2;
}
// bonus SA stable slots
if (Core.SA)
{
max += 2;
}
//bonus ToL stable slots
if (Core.TOL)
{
max += 2;
}
if (taming >= 100.0)
{
max += (int)((taming - 90.0) / 10);
}
if (anlore >= 100.0)
{
max += (int)((anlore - 90.0) / 10);
}
if (vetern >= 100.0)
{
max += (int)((vetern - 90.0) / 10);
}
return max + Server.Spells.SkillMasteries.MasteryInfo.BoardingSlotIncrease(from);
}
private void CloseClaimList(Mobile from)
{
from.CloseGump(typeof(ClaimListGump));
}
public void BeginClaimList(Mobile from)
{
if (Deleted || !from.CheckAlive())
{
return;
}
var list = new List<BaseCreature>();
for (var i = 0; i < from.Stabled.Count; ++i)
{
var pet = from.Stabled[i] as BaseCreature;
if (pet == null || pet.Deleted)
{
if (pet != null)
{
pet.IsStabled = false;
pet.StabledBy = null;
}
from.Stabled.RemoveAt(i--);
continue;
}
list.Add(pet);
}
if (list.Count > 0)
{
from.SendGump(new ClaimListGump(this, from, list));
}
else
{
SayTo(from, 502671); // But I have no animals stabled with me at the moment!
}
}
public void EndClaimList(Mobile from, BaseCreature pet)
{
if (pet == null || pet.Deleted || from.Map != Map || !from.Stabled.Contains(pet) || !from.CheckAlive())
{
return;
}
if (!from.InRange(this, 14))
{
from.SendLocalizedMessage(500446); // That is too far away.
return;
}
if (CanClaim(from, pet))
{
DoClaim(from, pet);
from.Stabled.Remove(pet);
if (from is PlayerMobile)
{
((PlayerMobile)from).AutoStabled.Remove(pet);
}
}
else
{
SayTo(from, 1049612, pet.Name); // ~1_NAME~ remained in the stables because you have too many followers.
}
}
public void BeginStable(Mobile from)
{
if (Deleted || !from.CheckAlive())
{
return;
}
if ((from.Backpack == null || from.Backpack.GetAmount(typeof(Gold)) < 30) && Banker.GetBalance(from) < 30)
{
SayTo(from, 1042556); // Thou dost not have enough gold, not even in thy bank account.
return;
}
/*
* I charge 30 gold per pet for a real week's stable time.
* I will withdraw it from thy bank account.
* Which animal wouldst thou like to stable here?
*/
from.SendLocalizedMessage(1042558);
from.Target = new StableTarget(this);
}
public void EndStable(Mobile from, BaseCreature pet)
{
if (Deleted || !from.CheckAlive())
{
return;
}
if (pet.Body.IsHuman)
{
SayTo(from, 502672); // HA HA HA! Sorry, I am not an inn.
}
else if (!pet.Controlled)
{
SayTo(from, 1048053); // You can't stable that!
}
else if (pet.ControlMaster != from)
{
SayTo(from, 1042562); // You do not own that pet!
}
else if (pet.IsDeadPet)
{
SayTo(from, 1049668); // Living pets only, please.
}
else if (pet.Summoned)
{
SayTo(from, 502673); // I can not stable summoned creatures.
}
else if (pet.Allured)
{
SayTo(from, 1048053); // You can't stable that!
}
else if ((pet is PackLlama || pet is PackHorse || pet is Beetle) &&
(pet.Backpack != null && pet.Backpack.Items.Count > 0))
{
SayTo(from, 1042563); // You need to unload your pet.
}
else if (pet.Combatant != null && pet.InRange(pet.Combatant, 12) && pet.Map == pet.Combatant.Map)
{
SayTo(from, 1042564); // I'm sorry. Your pet seems to be busy.
}
else if (from.Stabled.Count >= GetMaxStabled(from))
{
SayTo(from, 1042565); // You have too many pets in the stables!
}
else if ((from.Backpack != null && from.Backpack.ConsumeTotal(typeof(Gold), 30)) || Banker.Withdraw(from, 30))
{
pet.ControlTarget = null;
pet.ControlOrder = OrderType.Stay;
pet.Internalize();
pet.SetControlMaster(null);
pet.SummonMaster = null;
pet.IsStabled = true;
pet.StabledBy = from;
if (Core.SE)
{
pet.Loyalty = MaxLoyalty; // Wonderfully happy
}
from.Stabled.Add(pet);
SayTo(from, Core.AOS ? 1049677 : 502679);
// [AOS: Your pet has been stabled.] Very well, thy pet is stabled.
// Thou mayst recover it by saying 'claim' to me. In one real world week,
// I shall sell it off if it is not claimed!
}
else
{
SayTo(from, 502677); // But thou hast not the funds in thy bank account!
}
}
public void Claim(Mobile from)
{
Claim(from, null);
}
public void Claim(Mobile from, string petName)
{
if (Deleted || !from.CheckAlive())
{
return;
}
var claimed = false;
var stabled = 0;
var claimByName = (petName != null);
for (var i = 0; i < from.Stabled.Count; ++i)
{
var pet = from.Stabled[i] as BaseCreature;
if (pet == null || pet.Deleted)
{
if (pet != null)
{
pet.IsStabled = false;
pet.StabledBy = null;
}
from.Stabled.RemoveAt(i--);
continue;
}
++stabled;
if (claimByName && !Insensitive.Equals(pet.Name, petName))
{
continue;
}
if (CanClaim(from, pet))
{
DoClaim(from, pet);
from.Stabled.RemoveAt(i);
if (from is PlayerMobile)
{
((PlayerMobile)from).AutoStabled.Remove(pet);
}
--i;
claimed = true;
}
else
{
SayTo(from, 1049612, pet.Name); // ~1_NAME~ remained in the stables because you have too many followers.
}
}
if (claimed)
{
SayTo(from, 1042559); // Here you go... and good day to you!
}
else if (stabled == 0)
{
SayTo(from, 502671); // But I have no animals stabled with me at the moment!
}
else if (claimByName)
{
BeginClaimList(from);
}
}
public bool CanClaim(Mobile from, BaseCreature pet)
{
return ((from.Followers + pet.ControlSlots) <= from.FollowersMax);
}
private void DoClaim(Mobile from, BaseCreature pet)
{
pet.SetControlMaster(from);
if (pet.Summoned)
{
pet.SummonMaster = from;
}
pet.ControlTarget = from;
pet.ControlOrder = OrderType.Follow;
pet.MoveToWorld(from.Location, from.Map);
pet.IsStabled = false;
pet.StabledBy = null;
if (Core.SE)
{
pet.Loyalty = MaxLoyalty; // Wonderfully Happy
}
}
public override bool HandlesOnSpeech(Mobile from)
{
return true;
}
public override void OnSpeech(SpeechEventArgs e)
{
if (e.Mobile.Map.Rules != MapRules.FeluccaRules && !CheckVendorAccess(e.Mobile))
{
return;
}
if (!e.Handled && e.HasKeyword(0x0008)) // *stable*
{
e.Handled = true;
CloseClaimList(e.Mobile);
BeginStable(e.Mobile);
}
else if (!e.Handled && e.HasKeyword(0x0009)) // *claim*
{
e.Handled = true;
CloseClaimList(e.Mobile);
var index = e.Speech.IndexOf(' ');
if (index != -1)
{
Claim(e.Mobile, e.Speech.Substring(index).Trim());
}
else
{
Claim(e.Mobile);
}
}
else if (!e.Handled && e.Speech.ToLower().IndexOf("stablecount") >= 0)
{
IPooledEnumerable eable = e.Mobile.Map.GetMobilesInRange(e.Mobile.Location, 8);
e.Handled = true;
foreach (Mobile m in eable)
{
if (m is AnimalTrainer)
{
e.Mobile.SendLocalizedMessage(1071250, String.Format("{0}\t{1}", e.Mobile.Stabled.Count.ToString(), GetMaxStabled(e.Mobile).ToString())); // ~1_USED~/~2_MAX~ stable stalls used.
break;
}
}
eable.Free();
}
else
{
base.OnSpeech(e);
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.ReadInt();
}
private class StableEntry : ContextMenuEntry
{
private readonly Mobile m_From;
private readonly AnimalTrainer m_Trainer;
public StableEntry(AnimalTrainer trainer, Mobile from)
: base(6126, 12)
{
m_Trainer = trainer;
m_From = from;
Enabled = from.Map.Rules == MapRules.FeluccaRules || trainer.CheckVendorAccess(from);
}
public override void OnClick()
{
m_Trainer.BeginStable(m_From);
}
}
private class ClaimListGump : Gump
{
private readonly Mobile m_From;
private readonly List<BaseCreature> m_List;
private readonly AnimalTrainer m_Trainer;
public ClaimListGump(AnimalTrainer trainer, Mobile from, List<BaseCreature> list)
: base(50, 50)
{
m_Trainer = trainer;
m_From = from;
m_List = list;
from.CloseGump(typeof(ClaimListGump));
AddPage(0);
AddBackground(0, 0, 325, 50 + (list.Count * 20), 9250);
AddAlphaRegion(5, 5, 315, 40 + (list.Count * 20));
AddHtml(
15,
15,
275,
20,
"<BASEFONT COLOR=#000008>Select a pet to retrieve from the stables:</BASEFONT>",
false,
false);
for (var i = 0; i < list.Count; ++i)
{
var pet = list[i];
if (pet == null || pet.Deleted)
{
continue;
}
AddButton(15, 39 + (i * 20), 10006, 10006, i + 1, GumpButtonType.Reply, 0);
AddHtml(
32,
35 + (i * 20),
275,
18,
String.Format("<BASEFONT COLOR=#C6C6EF>{0}</BASEFONT>", pet.Name),
false,
false);
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
var index = info.ButtonID - 1;
if (index >= 0 && index < m_List.Count)
{
m_Trainer.EndClaimList(m_From, m_List[index]);
}
}
}
private class ClaimAllEntry : ContextMenuEntry
{
private readonly Mobile m_From;
private readonly AnimalTrainer m_Trainer;
public ClaimAllEntry(AnimalTrainer trainer, Mobile from)
: base(6127, 12)
{
m_Trainer = trainer;
m_From = from;
Enabled = from.Map.Rules == MapRules.FeluccaRules || trainer.CheckVendorAccess(from);
}
public override void OnClick()
{
m_Trainer.Claim(m_From);
}
}
private class StableTarget : Target
{
private readonly AnimalTrainer m_Trainer;
public StableTarget(AnimalTrainer trainer)
: base(12, false, TargetFlags.None)
{
m_Trainer = trainer;
}
protected override void OnTarget(Mobile from, object targeted)
{
if (targeted is BaseCreature)
{
m_Trainer.EndStable(from, (BaseCreature)targeted);
}
else if (targeted == from)
{
m_Trainer.SayTo(from, 502672); // HA HA HA! Sorry, I am not an inn.
}
else
{
m_Trainer.SayTo(from, 1048053); // You can't stable that!
}
}
}
}
}

View File

@@ -0,0 +1,200 @@
using System;
using Server.Items;
namespace Server.Engines.Quests
{
public class StopHarpingOnMeQuest : BaseQuest
{
public StopHarpingOnMeQuest()
: base()
{
AddObjective(new ObtainObjective(typeof(LapHarp), "lap harp", 20, 0xEB2));
AddReward(new BaseReward(typeof(CarpentersCraftsmanSatchel), 1074282));
}
/* Stop Harping on Me */
public override object Title
{
get
{
return 1073881;
}
}
/* Humans artistry can be a remarkable thing. For instance, I have heard of a wonderful
instrument which creates the most melodious of music. A lap harp. I would be ever so
grateful if I could examine one in person. */
public override object Description
{
get
{
return 1074071;
}
}
/* I will patiently await your reconsideration. */
public override object Refuse
{
get
{
return 1073921;
}
}
/* I will be in your debt if you bring me lap harp. */
public override object Uncomplete
{
get
{
return 1073927;
}
}
/* My thanks for your service. Now, I will show you something of elven carpentry. */
public override object Complete
{
get
{
return 1073969;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class TheFarEyeQuest : BaseQuest
{
public TheFarEyeQuest()
: base()
{
AddObjective(new ObtainObjective(typeof(Spyglass), "spyglasses", 20, 0x14F5));
AddReward(new BaseReward(typeof(TinkersCraftsmanSatchel), 1074282));
}
/* The Far Eye */
public override object Title
{
get
{
return 1073908;
}
}
/* The wonders of human invention! Turning sand and metal into a far-seeing eye! This is
something I must experience for myself. Bring me some of these spyglasses friend human. */
public override object Description
{
get
{
return 1074098;
}
}
/* I will patiently await your reconsideration. */
public override object Refuse
{
get
{
return 1073921;
}
}
/* I will be in your debt if you bring me spyglasses. */
public override object Uncomplete
{
get
{
return 1073954;
}
}
/* Enjoy my thanks for your service. */
public override object Complete
{
get
{
return 1073978;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Anolly : MondainQuester
{
[Constructable]
public Anolly()
: base("Anolly", "the bark weaver")
{
SetSkill(SkillName.Meditation, 60.0, 83.0);
SetSkill(SkillName.Focus, 60.0, 83.0);
}
public Anolly(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(StopHarpingOnMeQuest),
typeof(TheFarEyeQuest),
typeof(NothingFancyQuest)
};
}
}
public override void InitBody()
{
InitStats(100, 100, 25);
Female = false;
Race = Race.Elf;
Hue = 0x8835;
HairItemID = 0x2FC0;
HairHue = 0x325;
}
public override void InitOutfit()
{
AddItem(new Sandals(0x901));
AddItem(new FullApron(0x1BB));
AddItem(new ShortPants(0x3B2));
AddItem(new SmithHammer());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,147 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.Quests.Zento
{
public class AnsellaGryen : BaseQuester
{
[Constructable]
public AnsellaGryen()
{
}
public AnsellaGryen(Serial serial)
: base(serial)
{
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Hue = 0x83EA;
this.Female = true;
this.Body = 0x191;
this.Name = "Ansella Gryen";
}
public override void InitOutfit()
{
this.HairItemID = 0x203B;
this.HairHue = 0x1BB;
this.AddItem(new SamuraiTabi(0x8FD));
this.AddItem(new FemaleKimono(0x4B6));
this.AddItem(new Obi(0x526));
this.AddItem(new GoldBracelet());
}
public override int GetAutoTalkRange(PlayerMobile m)
{
if (m.Quest == null)
return 3;
else
return -1;
}
public override void OnTalk(PlayerMobile player, bool contextMenu)
{
QuestSystem qs = player.Quest;
if (qs is TerribleHatchlingsQuest)
{
if (qs.IsObjectiveInProgress(typeof(FirstKillObjective)))
{
qs.AddConversation(new DirectionConversation());
}
else if (qs.IsObjectiveInProgress(typeof(SecondKillObjective)) ||
qs.IsObjectiveInProgress(typeof(ThirdKillObjective)))
{
qs.AddConversation(new TakeCareConversation());
}
else
{
QuestObjective obj = qs.FindObjective(typeof(ReturnObjective));
if (obj != null && !obj.Completed)
{
Container cont = GetNewContainer();
cont.DropItem(new Gold(Utility.RandomMinMax(100, 200)));
if (Utility.RandomBool())
{
BaseWeapon weapon = Loot.Construct(Loot.SEWeaponTypes) as BaseWeapon;
if (weapon != null)
{
BaseRunicTool.ApplyAttributesTo(weapon, 3, 10, 30);
cont.DropItem(weapon);
}
}
else
{
BaseArmor armor = Loot.Construct(Loot.SEArmorTypes) as BaseArmor;
if (armor != null)
{
BaseRunicTool.ApplyAttributesTo(armor, 1, 10, 20);
cont.DropItem(armor);
}
}
if (player.PlaceInBackpack(cont))
{
obj.Complete();
}
else
{
cont.Delete();
player.SendLocalizedMessage(1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory.
}
}
}
}
else
{
TerribleHatchlingsQuest newQuest = new TerribleHatchlingsQuest(player);
bool inRestartPeriod = false;
if (qs != null)
{
if (contextMenu)
this.SayTo(player, 1063322); // Before you can help me with the Terrible Hatchlings, you'll need to finish the quest you've already taken!
}
else if (QuestSystem.CanOfferQuest(player, typeof(TerribleHatchlingsQuest), out inRestartPeriod))
{
newQuest.SendOffer();
}
else if (inRestartPeriod && contextMenu)
{
this.SayTo(player, 1049357); // I have nothing more for you at this time.
}
}
}
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 override void TurnToTokuno()
{
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using Server.Items;
namespace Server.Engines.Quests
{
public class Ansikart : MondainQuester
{
[Constructable]
public Ansikart()
: base("Ansikart", "the Artificer")
{
SetSkill(SkillName.ItemID, 60.0, 83.0);
SetSkill(SkillName.Imbuing, 60.0, 83.0);
}
public Ansikart(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(MasteringtheSoulforge),
typeof(ALittleSomething)
};
}
}
public override void InitBody()
{
InitStats(100, 100, 25);
CantWalk = true;
Race = Race.Gargoyle;
Hue = 0x86DF;
HairItemID = 0x425D;
HairHue = 0x321;
}
public override void InitOutfit()
{
AddItem(new SerpentStoneStaff());
AddItem(new GargishClothChest(1428));
AddItem(new GargishClothArms(1445));
AddItem(new GargishClothKilt(1443));
}
public override void Advertise()
{
this.Say(1112528); // Master the art of unraveling magic.
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,144 @@
using System;
using Server.Mobiles;
namespace Server.Items
{
public class FoldedSteel : BaseCollectionMobile
{
[Constructable]
public FoldedSteel()
: base("Arabella", "the samurai")
{
this.StartTier = 10000000;
this.DailyDecay = 100000;
this.DonationLabel = 1073448; // Folded Steel Section Donation Representative.
}
public FoldedSteel(Serial serial)
: base(serial)
{
}
public override Collection CollectionID
{
get
{
return Collection.FoldedSteel;
}
}
public override int MaxTier
{
get
{
return 1;
}
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = true;
this.CantWalk = true;
this.Race = Race.Human;
this.Hue = 0x83EA;
this.HairItemID = 0x2048;
this.HairHue = 0x476;
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new NoDachi());
this.AddItem(new SamuraiTabi(0x589));
this.AddItem(new LeatherSuneate());
this.AddItem(new LeatherJingasa());
this.AddItem(new LeatherDo());
this.AddItem(new LeatherHiroSode());
}
public override void Init()
{
base.Init();
this.Donations.Add(new CollectionItem(typeof(Gold), 0xEEF, 1073116, 0x0, 0.06666));
this.Donations.Add(new CollectionItem(typeof(BankCheck), 0x14F0, 1075013, 0x34, 0.06666));
this.Donations.Add(new CollectionItem(typeof(BrownBook), 0xFEF, 1074906, 0x0, 3));
this.Donations.Add(new CollectionItem(typeof(TanBook), 0xFF0, 1074906, 0x0, 3));
this.Donations.Add(new CollectionItem(typeof(Bokuto), 0x27A8, 1074913, 0x0, 8));
this.Donations.Add(new CollectionItem(typeof(Daisho), 0x27A9, 1074914, 0x0, 22));
this.Donations.Add(new CollectionItem(typeof(NoDachi), 0x27A2, 1074915, 0x0, 27));
this.Donations.Add(new CollectionItem(typeof(BookOfBushido), 0x238C, 1070814, 0x0, 30));
int[] hues = new int[] { 0x1E0, 0x190, 0x151 };
this.Rewards.Add(new CollectionHuedItem(typeof(LibraryFriendBodySash), 0x1541, 1073346, 0x190, 100000.0, hues));
this.Rewards.Add(new CollectionHuedItem(typeof(LibraryFriendFeatheredHat), 0x171A, 1073347, 0x190, 100000.0, hues));
this.Rewards.Add(new CollectionHuedItem(typeof(LibraryFriendSurcoat), 0x1FFD, 1073348, 0x190, 100000.0, hues));
this.Rewards.Add(new CollectionHuedItem(typeof(LibraryFriendPants), 0x1539, 1073349, 0x190, 100000.0, hues));
this.Rewards.Add(new CollectionHuedItem(typeof(LibraryFriendCloak), 0x1515, 1073350, 0x190, 100000.0, hues));
this.Rewards.Add(new CollectionHuedItem(typeof(LibraryFriendDoublet), 0x1F7B, 1073351, 0x190, 100000.0, hues));
this.Rewards.Add(new CollectionHuedItem(typeof(LibraryFriendSkirt), 0x1537, 1073352, 0x190, 100000.0, hues));
this.Rewards.Add(new CollectionTitle(1073341, 1073859, 100000.0)); // Britain Public Library Contributor
hues = new int[] { 0x0, 0x1C2, 0x320, 0x190, 0x1E0 };
this.Rewards.Add(new CollectionHuedItem(typeof(LibraryFriendLantern), 0xA25, 1073339, 0x1C2, 200000.0, hues));
this.Rewards.Add(new CollectionHuedItem(typeof(LibraryFriendReadingChair), 0x2DEB, 1073340, 0x1C2, 200000.0, hues));
this.Rewards.Add(new CollectionTitle(1073342, 1073860, 200000.0)); // Distinguished Library Contributor
this.Rewards.Add(new CollectionHuedItem(typeof(SherryTheMouseQuotes), 0xFBD, 1073300, 0x1C2, 350000.0, hues));
this.Rewards.Add(new CollectionHuedItem(typeof(WyrdBeastmasterQuotes), 0xFBD, 1073310, 0x1C2, 350000.0, hues));
this.Rewards.Add(new CollectionHuedItem(typeof(MercenaryJustinQuotes), 0xFBD, 1073317, 0x1C2, 350000.0, hues));
this.Rewards.Add(new CollectionHuedItem(typeof(HeigelOfMoonglowQuotes), 0xFBD, 1073327, 0x1C2, 350000.0, hues));
this.Rewards.Add(new CollectionHuedItem(typeof(TraderHoraceQuotes), 0xFBD, 1073338, 0x1C2, 350000.0, hues));
this.Rewards.Add(new CollectionTitle(1073343, 1073861, 350000.0)); // Honored Library Contributor
this.Rewards.Add(new CollectionItem(typeof(TreatiseonAlchemyTalisman), 0x2F58, 1073353, 0x0, 550000.0));
this.Rewards.Add(new CollectionItem(typeof(PrimerOnArmsTalisman), 0x2F59, 1073354, 0x0, 550000.0));
this.Rewards.Add(new CollectionItem(typeof(MyBookTalisman), 0x2F5A, 1073355, 0x0, 550000.0));
this.Rewards.Add(new CollectionItem(typeof(TalkingtoWispsTalisman), 0x2F5B, 1073356, 0x0, 550000.0));
this.Rewards.Add(new CollectionItem(typeof(GrammarOfOrchishTalisman), 0x2F59, 1073358, 0x0, 550000.0));
this.Rewards.Add(new CollectionItem(typeof(BirdsofBritanniaTalisman), 0x2F5A, 1073359, 0x0, 550000.0));
this.Rewards.Add(new CollectionItem(typeof(TheLifeOfTravelingMinstrelTalisman), 0x2F5A, 1073360, 0x0, 550000.0));
this.Rewards.Add(new CollectionTitle(1073344, 1073862, 550000.0)); // Prominent Library Contributor
this.Rewards.Add(new CollectionTitle(1073345, 1073863, 800000.0)); // Eminent Library Contributor
this.Rewards.Add(new CollectionItem(typeof(FoldedSteelGlasses), 0x2FB8, 1073380, 0x47E, 800000.0));
}
public override bool CanDonate(PlayerMobile player)
{
bool can = player.LibraryFriend;
if (!can)
player.SendLocalizedMessage(1074273); // You must speak with Librarian Verity before you can donate to this collection.
return can;
}
/*public override void IncreaseTier()
{
base.IncreaseTier();
List<object> list = new List<object>();
Item c;
switch ( Tier )
{
}
if ( list.Count > 0 )
Tiers.Add( list );
}*/
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,416 @@
#region References
using System;
using Server.Items;
#endregion
namespace Server.Mobiles
{
public class ArcherGuard : BaseGuard
{
private Timer m_AttackTimer, m_IdleTimer;
private Mobile m_Focus;
[Constructable]
public ArcherGuard()
: this(null)
{ }
public ArcherGuard(Mobile target)
: base(target)
{
InitStats(100, 125, 25);
Title = "the guard";
SpeechHue = Utility.RandomDyedHue();
Hue = Utility.RandomSkinHue();
if (Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
}
new Horse().Rider = this;
AddItem(new StuddedChest());
AddItem(new StuddedArms());
AddItem(new StuddedGloves());
AddItem(new StuddedGorget());
AddItem(new StuddedLegs());
AddItem(new Boots());
AddItem(new SkullCap());
Bow bow = new Bow();
bow.Movable = false;
bow.Crafter = this;
bow.Quality = ItemQuality.Exceptional;
AddItem(bow);
Container pack = new Backpack();
pack.Movable = false;
Arrow arrows = new Arrow(250);
arrows.LootType = LootType.Newbied;
pack.DropItem(arrows);
pack.DropItem(new Gold(10, 25));
AddItem(pack);
Skills[SkillName.Anatomy].Base = 120.0;
Skills[SkillName.Tactics].Base = 120.0;
Skills[SkillName.Archery].Base = 120.0;
Skills[SkillName.MagicResist].Base = 120.0;
Skills[SkillName.DetectHidden].Base = 100.0;
NextCombatTime = Core.TickCount + 500;
Focus = target;
}
public ArcherGuard(Serial serial)
: base(serial)
{ }
[CommandProperty(AccessLevel.GameMaster)]
public override Mobile Focus
{
get { return m_Focus; }
set
{
if (Deleted)
{
return;
}
Mobile oldFocus = m_Focus;
if (oldFocus != value)
{
m_Focus = value;
if (value != null)
{
AggressiveAction(value);
}
Combatant = value;
if (oldFocus != null && !oldFocus.Alive)
{
Say("Thou hast suffered thy punishment, scoundrel.");
}
if (value != null)
{
Say(500131); // Thou wilt regret thine actions, swine!
}
if (m_AttackTimer != null)
{
m_AttackTimer.Stop();
m_AttackTimer = null;
}
if (m_IdleTimer != null)
{
m_IdleTimer.Stop();
m_IdleTimer = null;
}
if (m_Focus != null)
{
m_AttackTimer = new AttackTimer(this);
m_AttackTimer.Start();
((AttackTimer)m_AttackTimer).DoOnTick();
}
else
{
m_IdleTimer = new IdleTimer(this);
m_IdleTimer.Start();
}
}
else if (m_Focus == null && m_IdleTimer == null)
{
m_IdleTimer = new IdleTimer(this);
m_IdleTimer.Start();
}
}
}
public override bool OnBeforeDeath()
{
if (m_Focus != null && m_Focus.Alive)
{
new AvengeTimer(m_Focus).Start(); // If a guard dies, three more guards will spawn
}
return base.OnBeforeDeath();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(m_Focus);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Focus = reader.ReadMobile();
if (m_Focus != null)
{
m_AttackTimer = new AttackTimer(this);
m_AttackTimer.Start();
}
else
{
m_IdleTimer = new IdleTimer(this);
m_IdleTimer.Start();
}
break;
}
}
}
public override void OnAfterDelete()
{
if (m_AttackTimer != null)
{
m_AttackTimer.Stop();
m_AttackTimer = null;
}
if (m_IdleTimer != null)
{
m_IdleTimer.Stop();
m_IdleTimer = null;
}
base.OnAfterDelete();
}
private class AvengeTimer : Timer
{
private readonly Mobile m_Focus;
public AvengeTimer(Mobile focus)
: base(TimeSpan.FromSeconds(2.5), TimeSpan.FromSeconds(1.0), 3)
// After 2.5 seconds, one guard will spawn every 1.0 second, three times
{
m_Focus = focus;
}
protected override void OnTick()
{
Spawn(m_Focus, m_Focus, 1, true);
}
}
private class AttackTimer : Timer
{
private readonly ArcherGuard m_Owner;
// private bool m_Shooting;
public AttackTimer(ArcherGuard owner)
: base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(0.1))
{
m_Owner = owner;
}
public void DoOnTick()
{
OnTick();
}
protected override void OnTick()
{
if (m_Owner.Deleted)
{
Stop();
return;
}
m_Owner.Criminal = false;
m_Owner.Kills = 0;
m_Owner.Stam = m_Owner.StamMax;
Mobile target = m_Owner.Focus;
if (target != null && (target.Deleted || !target.Alive || !m_Owner.CanBeHarmful(target)))
{
m_Owner.Focus = null;
Stop();
return;
}
else if (m_Owner.Weapon is Fists)
{
m_Owner.Kill();
Stop();
return;
}
if (target != null && m_Owner.Combatant != target)
{
m_Owner.Combatant = target;
}
if (target == null)
{
Stop();
}
else
{
// <instakill>
TeleportTo(target);
target.BoltEffect(0);
if (target is BaseCreature)
{
((BaseCreature)target).NoKillAwards = true;
}
target.Damage(target.HitsMax, m_Owner);
target.Kill(); // just in case, maybe Damage is overriden on some shard
if (target.Corpse != null && !target.Player)
{
target.Corpse.Delete();
}
m_Owner.Focus = null;
Stop();
} // </instakill>
/*else if ( !m_Owner.InRange( target, 20 ) )
{
m_Shooting = false;
m_Owner.Focus = null;
}
else if ( !m_Owner.InLOS( target ) )
{
m_Shooting = false;
TeleportTo( target );
}
else if ( !m_Owner.CanSee( target ) )
{
m_Shooting = false;
if ( !m_Owner.InRange( target, 2 ) )
{
if ( !m_Owner.Move( m_Owner.GetDirectionTo( target ) | Direction.Running ) && OutOfMaxDistance( target ) )
TeleportTo( target );
}
else
{
if ( !m_Owner.UseSkill( SkillName.DetectHidden ) && Utility.Random( 50 ) == 0 )
m_Owner.Say( "Reveal!" );
}
}
else
{
if ( m_Shooting && (TimeToSpare() || OutOfMaxDistance( target )) )
m_Shooting = false;
else if ( !m_Shooting && InMinDistance( target ) )
m_Shooting = true;
if ( !m_Shooting )
{
if ( m_Owner.InRange( target, 1 ) )
{
if ( !m_Owner.Move( (Direction)(m_Owner.GetDirectionTo( target ) - 4) | Direction.Running ) && OutOfMaxDistance( target ) ) // Too close, move away
TeleportTo( target );
}
else if ( !m_Owner.InRange( target, 2 ) )
{
if ( !m_Owner.Move( m_Owner.GetDirectionTo( target ) | Direction.Running ) && OutOfMaxDistance( target ) )
TeleportTo( target );
}
}
}*/
}
private bool TimeToSpare()
{
return (m_Owner.NextCombatTime - Core.TickCount) > 1000;
}
private bool OutOfMaxDistance(Mobile target)
{
return !m_Owner.InRange(target, m_Owner.Weapon.MaxRange);
}
private bool InMinDistance(Mobile target)
{
return m_Owner.InRange(target, 4);
}
private void TeleportTo(Mobile target)
{
Point3D from = m_Owner.Location;
Point3D to = target.Location;
m_Owner.Location = to;
Effects.SendLocationParticles(
EffectItem.Create(from, m_Owner.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, 2023);
Effects.SendLocationParticles(EffectItem.Create(to, m_Owner.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, 5023);
m_Owner.PlaySound(0x1FE);
}
}
private class IdleTimer : Timer
{
private readonly ArcherGuard m_Owner;
private int m_Stage;
public IdleTimer(ArcherGuard owner)
: base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.5))
{
m_Owner = owner;
}
protected override void OnTick()
{
if (m_Owner.Deleted)
{
Stop();
return;
}
if ((m_Stage++ % 4) == 0 || !m_Owner.Move(m_Owner.Direction))
{
m_Owner.Direction = (Direction)Utility.Random(8);
}
if (m_Stage > 16)
{
Effects.SendLocationParticles(
EffectItem.Create(m_Owner.Location, m_Owner.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, 2023);
m_Owner.PlaySound(0x1FE);
m_Owner.Delete();
}
}
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
namespace Server.Mobiles
{
public class Architect : BaseVendor
{
private readonly List<SBInfo> m_SBInfos = new List<SBInfo>();
[Constructable]
public Architect()
: base("the architect")
{
}
public Architect(Serial serial)
: base(serial)
{
}
public override NpcGuild NpcGuild
{
get
{
return NpcGuild.TinkersGuild;
}
}
protected override List<SBInfo> SBInfos
{
get
{
return this.m_SBInfos;
}
}
public override void InitSBInfo()
{
if (!Core.AOS)
this.m_SBInfos.Add(new SBHouseDeed());
this.m_SBInfos.Add(new SBArchitect());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
namespace Server.Engines.Quests
{
public class Arielle : MondainQuester
{
[Constructable]
public Arielle()
: base("Arielle")
{
this.BaseSoundID = 0x46F;
this.SetSkill(SkillName.Focus, 60.0, 83.0);
}
public Arielle(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(TheJoysOfLifeQuest)
};
}
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = true;
this.Body = 128;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
namespace Server.Items
{
public class AriellesBauble : Item
{
[Constructable]
public AriellesBauble()
: base(0x23B)
{
this.Weight = 2.0;
this.LootType = LootType.Blessed;
}
public AriellesBauble(Serial serial)
: base(serial)
{
}
public override int LabelNumber
{
get
{
return 1073137;
}
}// A bauble
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,165 @@
using System;
using System.Collections.Generic;
using Server.Engines.BulkOrders;
namespace Server.Mobiles
{
public class Armorer : BaseVendor
{
private readonly List<SBInfo> m_SBInfos = new List<SBInfo>();
[Constructable]
public Armorer()
: base("the armourer")
{
SetSkill(SkillName.ArmsLore, 64.0, 100.0);
SetSkill(SkillName.Blacksmith, 60.0, 83.0);
}
public Armorer(Serial serial)
: base(serial)
{
}
public override VendorShoeType ShoeType
{
get
{
return VendorShoeType.Boots;
}
}
protected override List<SBInfo> SBInfos
{
get
{
return m_SBInfos;
}
}
public override void InitSBInfo()
{
switch ( Utility.Random(4))
{
case 0:
{
m_SBInfos.Add(new SBLeatherArmor());
m_SBInfos.Add(new SBStuddedArmor());
m_SBInfos.Add(new SBMetalShields());
m_SBInfos.Add(new SBPlateArmor());
m_SBInfos.Add(new SBHelmetArmor());
m_SBInfos.Add(new SBChainmailArmor());
m_SBInfos.Add(new SBRingmailArmor());
break;
}
case 1:
{
m_SBInfos.Add(new SBStuddedArmor());
m_SBInfos.Add(new SBLeatherArmor());
m_SBInfos.Add(new SBMetalShields());
m_SBInfos.Add(new SBHelmetArmor());
break;
}
case 2:
{
m_SBInfos.Add(new SBMetalShields());
m_SBInfos.Add(new SBPlateArmor());
m_SBInfos.Add(new SBHelmetArmor());
m_SBInfos.Add(new SBChainmailArmor());
m_SBInfos.Add(new SBRingmailArmor());
break;
}
case 3:
{
m_SBInfos.Add(new SBMetalShields());
m_SBInfos.Add(new SBHelmetArmor());
break;
}
}
if (IsTokunoVendor)
{
m_SBInfos.Add(new SBSELeatherArmor());
m_SBInfos.Add(new SBSEArmor());
}
}
#region Bulk Orders
public override BODType BODType { get { return BODType.Smith; } }
public override Item CreateBulkOrder(Mobile from, bool fromContextMenu)
{
PlayerMobile pm = from as PlayerMobile;
if (pm != null && pm.NextSmithBulkOrder == TimeSpan.Zero && (fromContextMenu || 0.2 > Utility.RandomDouble()))
{
double theirSkill = pm.Skills[SkillName.Blacksmith].Base;
if (theirSkill >= 70.1)
pm.NextSmithBulkOrder = TimeSpan.FromHours(6.0);
else if (theirSkill >= 50.1)
pm.NextSmithBulkOrder = TimeSpan.FromHours(2.0);
else
pm.NextSmithBulkOrder = TimeSpan.FromHours(1.0);
if (theirSkill >= 70.1 && ((theirSkill - 40.0) / 300.0) > Utility.RandomDouble())
return new LargeSmithBOD();
return SmallSmithBOD.CreateRandomFor(from);
}
return null;
}
public override bool IsValidBulkOrder(Item item)
{
return (item is SmallSmithBOD || item is LargeSmithBOD);
}
public override bool SupportsBulkOrders(Mobile from)
{
return (from is PlayerMobile && from.Skills[SkillName.Blacksmith].Base > 0);
}
public override TimeSpan GetNextBulkOrder(Mobile from)
{
if (from is PlayerMobile)
return ((PlayerMobile)from).NextSmithBulkOrder;
return TimeSpan.Zero;
}
public override void OnSuccessfulBulkOrderReceive(Mobile from)
{
if (Core.SE && from is PlayerMobile)
((PlayerMobile)from).NextSmithBulkOrder = TimeSpan.Zero;
}
#endregion
public override void InitOutfit()
{
base.InitOutfit();
AddItem(new Server.Items.HalfApron(Utility.RandomYellowHue()));
AddItem(new Server.Items.Bascinet());
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)1); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (version == 0)
{
Title = "the armourer";
}
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using Server.Items;
namespace Server.Mobiles
{
public class Artist : BaseCreature
{
[Constructable]
public Artist()
: base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4)
{
this.InitStats(31, 41, 51);
this.SetSkill(SkillName.Healing, 36, 68);
this.SpeechHue = Utility.RandomDyedHue();
this.Title = "the artist";
this.Hue = Utility.RandomSkinHue();
if (this.Female = Utility.RandomBool())
{
this.Body = 0x191;
this.Name = NameList.RandomName("female");
}
else
{
this.Body = 0x190;
this.Name = NameList.RandomName("male");
}
this.AddItem(new Doublet(Utility.RandomDyedHue()));
this.AddItem(new Sandals(Utility.RandomNeutralHue()));
this.AddItem(new ShortPants(Utility.RandomNeutralHue()));
this.AddItem(new HalfApron(Utility.RandomDyedHue()));
Utility.AssignRandomHair(this);
Container pack = new Backpack();
pack.DropItem(new Gold(250, 300));
pack.Movable = false;
this.AddItem(pack);
}
public Artist(Serial serial)
: base(serial)
{
}
public override bool CanTeach
{
get
{
return true;
}
}
public override bool ClickTitle
{
get
{
return false;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,168 @@
using System;
using Server.Items;
namespace Server.Engines.Quests
{
public class BakersDozenQuest : BaseQuest
{
public BakersDozenQuest()
: base()
{
this.AddObjective(new ObtainObjective(typeof(CookieMix), "cookie mix", 5, 0x103F));
this.AddReward(new BaseReward(typeof(ChefsSatchel), 1074282)); // Craftsman's Satchel
}
/* Baker's Dozen */
public override object Title
{
get
{
return 1075478;
}
}
/* You there! Do you know much about the ways of cooking? If you help me out, I'll show you a thing or two about
how it's done. Bring me some cookie mix, about 5 batches will do it, and I will reward you. Although, I don't
think you can buy it, you can make some in a snap! First get a rolling pin or frying pan or even a flour sifter.
Then you mix one pinch of flour with some water and you've got some dough! Take that dough and add one dollop of
honey and you've got sweet dough. add one more drop of honey and you've got cookie mix. See? Nothing to it! Now
get to work! */
public override object Description
{
get
{
return 1075479;
}
}
/* Argh, I absolutely must have more of these 'cookies!' Come back if you change your mind. */
public override object Refuse
{
get
{
return 1075480;
}
}
/* You're not quite done yet. Get back to work! */
public override object Uncomplete
{
get
{
return 1072271;
}
}
/* Thank you! I haven't been this excited about food in months! */
public override object Complete
{
get
{
return 1075481;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class Asandos : MondainQuester
{
[Constructable]
public Asandos()
: base("Asandos", "the chef")
{
}
public Asandos(Serial serial)
: base(serial)
{
}
public override Type[] Quests
{
get
{
return new Type[]
{
typeof(BakersDozenQuest)
};
}
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = false;
this.CantWalk = true;
this.Race = Race.Human;
this.Hue = 0x83FF;
this.HairItemID = 0x2044;
this.HairHue = 0x1;
}
public override void InitOutfit()
{
this.AddItem(new Backpack());
this.AddItem(new Boots(0x901));
this.AddItem(new ShortPants());
this.AddItem(new Shirt());
this.AddItem(new Cap());
this.AddItem(new HalfApron(0x28));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class ChefsSatchel : Backpack
{
[Constructable]
public ChefsSatchel()
: base()
{
this.Hue = BaseReward.SatchelHue();
this.AddItem(new SackFlour());
this.AddItem(new Skillet());
}
public ChefsSatchel(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class Athialon : BaseVendor
{
private readonly List<SBInfo> m_SBInfos = new List<SBInfo>();
[Constructable]
public Athialon()
: base("the expeditionist")
{
this.Name = "Athialon";
}
public Athialon(Serial serial)
: base(serial)
{
}
public override bool CanTeach
{
get
{
return false;
}
}
public override bool IsInvulnerable
{
get
{
return true;
}
}
protected override List<SBInfo> SBInfos
{
get
{
return this.m_SBInfos;
}
}
public override void InitSBInfo()
{
}
public override void InitBody()
{
this.InitStats(100, 100, 25);
this.Female = false;
this.Race = Race.Elf;
this.Hue = 0x8382;
this.HairItemID = 0x2FC0;
this.HairHue = 0x35;
}
public override void InitOutfit()
{
this.AddItem(new ElvenBoots(0x901));
this.AddItem(new DiamondMace());
this.AddItem(new WoodlandBelt());
Item item;
item = new WoodlandLegs();
item.Hue = 0x3B2;
this.AddItem(item);
item = new WoodlandChest();
item.Hue = 0x3B2;
this.AddItem(item);
item = new WoodlandArms();
item.Hue = 0x3B2;
this.AddItem(item);
item = new WingedHelm();
item.Hue = 0x3B2;
this.AddItem(item);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,200 @@
using System;
using System.Collections.Generic;
using Server.ContextMenus;
using Server.Gumps;
using Server.Items;
using Server.Network;
namespace Server.Mobiles
{
public class AttendantFortuneTeller : PersonalAttendant
{
[Constructable]
public AttendantFortuneTeller()
: this(false)
{
}
[Constructable]
public AttendantFortuneTeller(bool female)
: base("the Fortune Teller")
{
this.Female = female;
}
public AttendantFortuneTeller(Serial serial)
: base(serial)
{
}
public override void OnDoubleClick(Mobile from)
{
if (from.Alive && this.IsOwner(from))
{
from.CloseGump(typeof(InternalGump));
from.SendGump(new InternalGump(this));
}
else
base.OnDoubleClick(from);
}
public override void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
{
if (from.Alive && this.IsOwner(from))
list.Add(new AttendantUseEntry(this, 6245));
base.AddCustomContextEntries(from, list);
}
public override void InitBody()
{
this.SetStr(50, 60);
this.SetDex(20, 30);
this.SetInt(100, 110);
this.Name = NameList.RandomName("female");
this.Female = true;
this.Race = Race.Human;
this.Hue = this.Race.RandomSkinHue();
Utility.AssignRandomHair(this, Utility.RandomHairHue());
}
public override void InitOutfit()
{
this.AddItem(new Shoes(Utility.RandomPinkHue()));
this.AddItem(new Shirt(Utility.RandomPinkHue()));
this.AddItem(new SkullCap(Utility.RandomPinkHue()));
if (Utility.RandomBool())
this.AddItem(new Kilt(Utility.RandomPinkHue()));
else
this.AddItem(new Skirt(Utility.RandomPinkHue()));
}
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();
}
private class InternalGump : Gump
{
private readonly AttendantFortuneTeller m_Teller;
public InternalGump(AttendantFortuneTeller teller)
: base(200, 200)
{
this.m_Teller = teller;
this.AddPage(0);
this.AddBackground(0, 0, 291, 155, 0x13BE);
this.AddImageTiled(5, 6, 280, 20, 0xA40);
this.AddHtmlLocalized(9, 8, 280, 20, 1075994, 0x7FFF, false, false); // Fortune Teller
this.AddImageTiled(5, 31, 280, 91, 0xA40);
this.AddHtmlLocalized(9, 35, 280, 40, 1076025, 0x7FFF, false, false); // Ask your question
this.AddImageTiled(9, 55, 270, 20, 0xDB0);
this.AddImageTiled(10, 55, 270, 2, 0x23C5);
this.AddImageTiled(9, 55, 2, 20, 0x23C3);
this.AddImageTiled(9, 75, 270, 2, 0x23C5);
this.AddImageTiled(279, 55, 2, 22, 0x23C3);
this.AddTextEntry(12, 56, 263, 17, 0xA28, 15, "");
this.AddButton(5, 129, 0xFB1, 0xFB2, 0, GumpButtonType.Reply, 0);
this.AddHtmlLocalized(40, 131, 100, 20, 1060051, 0x7FFF, false, false); // CANCEL
this.AddButton(190, 129, 0xFB7, 0xFB8, 1, GumpButtonType.Reply, 0);
this.AddHtmlLocalized(225, 131, 100, 20, 1006044, 0x7FFF, false, false); // OK
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (this.m_Teller == null || this.m_Teller.Deleted)
return;
if (info.ButtonID == 1)
{
TextRelay text = info.GetTextEntry(15);
if (text != null && !String.IsNullOrEmpty(text.Text))
{
sender.Mobile.CloseGump(typeof(FortuneGump));
sender.Mobile.SendGump(new FortuneGump(text.Text));
}
else
sender.Mobile.SendGump(this);
}
}
}
private class FortuneGump : Gump
{
public FortuneGump(string text)
: base(200, 200)
{
this.AddPage(0);
this.AddImage(0, 0, 0x7724);
int one, two, three;
one = Utility.RandomMinMax(1, 19);
two = Utility.RandomMinMax(one + 1, 20);
three = Utility.RandomMinMax(0, one - 1);
this.AddImageTiled(28, 140, 115, 180, 0x7725 + one);
this.AddTooltip(this.GetTooltip(one));
this.AddHtmlLocalized(28, 115, 125, 20, 1076079, 0x7FFF, false, false); // The Past
this.AddImageTiled(171, 140, 115, 180, 0x7725 + two);
this.AddTooltip(this.GetTooltip(two));
this.AddHtmlLocalized(171, 115, 125, 20, 1076081, 0x7FFF, false, false); // The Question
this.AddImageTiled(314, 140, 115, 180, 0x7725 + three);
this.AddTooltip(this.GetTooltip(three));
this.AddHtmlLocalized(314, 115, 125, 20, 1076080, 0x7FFF, false, false); // The Future
this.AddHtml(30, 32, 400, 25, text, true, false);
}
private int GetTooltip(int number)
{
if (number > 9)
return 1076015 + number - 10;
switch ( number )
{
case 0:
return 1076063;
case 1:
return 1076060;
case 2:
return 1076061;
case 3:
return 1076057;
case 4:
return 1076062;
case 5:
return 1076059;
case 6:
return 1076058;
case 7:
return 1076065;
case 8:
return 1076064;
case 9:
return 1076066;
}
return 1052009; // I have seen the error of my ways!
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,701 @@
using System;
using System.Collections.Generic;
using Server.ContextMenus;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Multis;
using Server.Network;
namespace Server.Mobiles
{
public class AttendantHerald : PersonalAttendant
{
private static readonly HeraldEntry[] m_Announcements = new HeraldEntry[]
{
new HeraldEntry(1076044, "[OWNER TITLE]", "[OWNER NAME]"), // Attention, attention! All hail the arrival of the ~1_TITLE~ ~2_NAME~!
new HeraldEntry(1076045, "[OWNER TITLE]", "[OWNER NAME]"), // Make way ye unwashed hordes! Clear the road! For ~1_TITLE~ ~2_NAME~ has business more important than yours!
new HeraldEntry(1076046, "[OWNER TITLE]", "[OWNER NAME]"), // ~1_TITLE~ ~2_NAME~ approaches! Be ye prepared to kneel before their indomitable presence! And remember, tribute is to be only in gold!
new HeraldEntry(1076047, "[OWNER TITLE]", "[OWNER NAME]"), // Throw down your capes and kerchiefs! Let the petals be strewn! For the ~1_TITLE~ ~2_NAME~ approacheth!
new HeraldEntry(1076048, "[OWNER TITLE]", "[OWNER NAME]"), // ~1_TITLE~ ~2_NAME~ has arrived! Let the drinks flow! Let the festivities commence! And you there, with the pig, get that beast on a skewer!
new HeraldEntry(1076049, "[OWNER SEX P]", "[OWNER OPPOSITE SEX P]", "[OWNER TITLE]", "[OWNER NAME]")// Let the ~1_SAME_SEX~ cower and the ~2_OPPOSITE_SEX~ swoon, for now approaches the ~3_TITLE~ ~4_NAME~.
};
private static readonly HeraldEntry[] m_Greetings = new HeraldEntry[]
{
new HeraldEntry(1076038, "[OWNER NAME]"), // Welcome to the home of ~1_OWNER_NAME~. Please keep your shoes off the furniture.
new HeraldEntry(1076039, "[VISITOR TITLE]", "[VISITOR NAME]", "[OWNER SEX]"), // Announcing the arrival of the ~1_VISITOR_TITLE~ ~2_VISITOR_NAME~. The ~3_OWNER_SEX~ of the house bids you welcome.
new HeraldEntry(1076040, "[OWNER SEX]","[VISITOR TITLE]", "[VISITOR NAME]"), // My ~1_OWNER_SEX~, you have a visitor! ~2_VISITOR_TITLE~ ~3_VISITOR_NAME~ is awaiting your presence.
new HeraldEntry(1076041, "[OWNER TITLE]", "[OWNER NAME]"), // Welcome the the humble abode of ~1_OWNER_TITLE~ ~2_OWNER_NAME~, please remove your shoes, and have a seat where you may find one.
new HeraldEntry(1076042, "[VISITOR TITLE]", "[VISITOR NAME]"), // Ahh, greetings to ~1_VISITOR_TITLE~ ~2_VISITOR_NAME~. Your coming here was foreseen, and I alone know of your purpose.
new HeraldEntry(1076043), // *squints* Not you again! Fine, fine... whatever... come on in, I suppose. *sighs*
new HeraldEntry(1076074, "[OWNER TITLE]", "[OWNER NAME]"), // Welcome to this humble marketplace. If you need any assistance ~1_OWNER_TITLE~ ~2_OWNER_NAME~ will be glad to help you.
new HeraldEntry(1076075, "[OWNER TITLE]", "[OWNER NAME]"), // Come Friend! Enter ~1_OWNER_TITLE~ ~2_OWNER_NAME~'s wondrous shop of many things! If you can't find it here, I suggest you go somewhere else!
new HeraldEntry(1076076, "[VISITOR NAME]")// *Looks ~1_VISITOR_NAME~ over with narrowed eyes, scowling, and points to the sign on the wall* "Reagents for spell casting only, Please do not eat!"
};
private HeraldEntry m_Announcement;
private HeraldEntry m_Greeting;
private DateTime m_NextYell;
private BaseHouse m_House;
private Point3D m_Location;
public AttendantHerald()
: base("the Herald")
{
this.m_Announcement = m_Announcements[0];
this.m_Greeting = m_Greetings[0];
this.m_NextYell = DateTime.UtcNow;
this.m_House = null;
this.m_Location = Point3D.Zero;
}
public AttendantHerald(Serial serial)
: base(serial)
{
}
public virtual TimeSpan YellDelay
{
get
{
return TimeSpan.FromSeconds(15);
}
}
[CommandProperty(AccessLevel.GameMaster)]
public HeraldEntry Announcement
{
get
{
return this.m_Announcement;
}
set
{
this.m_Announcement = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public HeraldEntry Greeting
{
get
{
return this.m_Greeting;
}
set
{
this.m_Greeting = value;
}
}
public override void OnDoubleClick(Mobile from)
{
if (from.Alive && this.IsOwner(from))
{
from.CloseGump(typeof(OptionsGump));
from.SendGump(new OptionsGump(this));
}
else
base.OnDoubleClick(from);
}
public override void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
{
if (from.Alive && this.IsOwner(from))
{
list.Add(new AttendantUseEntry(this, 6248));
list.Add(new HeraldSetAnnouncementTextEntry(this));
list.Add(new HeraldSetGreetingTextEntry(this));
list.Add(new AttendantDismissEntry(this));
}
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
base.OnMovement(m, oldLocation);
if (m != null && m.Player && !m.Hidden && m != this)
{
if (this.ControlOrder == OrderType.Follow && this.m_NextYell < DateTime.UtcNow && m != this.ControlMaster && this.m_Announcement != null)
{
this.m_Announcement.Say(this, m);
this.m_NextYell = DateTime.UtcNow + this.YellDelay + TimeSpan.FromSeconds(Utility.RandomMinMax(-2, 2));
}
else if (this.ControlOrder == OrderType.Stay && this.m_Greeting != null)
{
if (this.m_Location != this.Location)
{
this.m_House = BaseHouse.FindHouseAt(this);
this.m_Location = this.Location;
}
if (this.m_House != null && !this.m_House.IsInside(oldLocation, 16) && this.m_House.IsInside(m))
this.m_Greeting.Say(this, m);
}
}
}
public override bool InGreetingMode(Mobile owner)
{
if (this.m_Location != this.Location)
{
this.m_House = BaseHouse.FindHouseAt(this);
this.m_Location = this.Location;
}
return (this.m_House != null && this.m_House.IsOwner(owner) && this.ControlOrder == OrderType.Stay);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
writer.Write(this.m_Announcement != null);
if (this.m_Announcement != null)
this.m_Announcement.Serialize(writer);
writer.Write(this.m_Greeting != null);
if (this.m_Greeting != null)
this.m_Greeting.Serialize(writer);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
if (reader.ReadBool())
{
this.m_Announcement = new HeraldEntry();
this.m_Announcement.Deserialize(reader);
}
if (reader.ReadBool())
{
this.m_Greeting = new HeraldEntry();
this.m_Greeting.Deserialize(reader);
}
this.m_Location = Point3D.Zero;
}
public virtual void SetAnnouncementText(Mobile by)
{
by.SendGump(new SetTextGump(this, m_Announcements, true));
}
public virtual void SetGreetingText(Mobile by)
{
by.SendGump(new SetTextGump(this, m_Greetings, false));
}
[PropertyObject]
public class HeraldEntry
{
private TextDefinition m_Message;
private string[] m_Arguments;
public HeraldEntry()
: this(null, null)
{
}
public HeraldEntry(TextDefinition message)
: this(message, null)
{
}
public HeraldEntry(TextDefinition message, params string[] args)
{
this.m_Message = message;
this.m_Arguments = args;
}
[CommandProperty(AccessLevel.GameMaster)]
public TextDefinition Message
{
get
{
return this.m_Message;
}
set
{
this.m_Message = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public string Arguments
{
get
{
string text = String.Empty;
foreach (string s in this.m_Arguments)
text += '|' + s;
return text + '|';
}
set
{
if (value != null)
this.m_Arguments = value.Split('|');
else
this.m_Arguments = null;
}
}
public override string ToString()
{
if (this.m_Message != null)
return this.m_Message.ToString();
return base.ToString();
}
public void Say(AttendantHerald herald, Mobile visitor)
{
if (this.m_Message.Number > 0)
{
herald.Say(this.m_Message.Number, this.ConstructNumber(herald, visitor));
}
else if (this.m_Message.String != null)
{
herald.Say(this.ConstructString(herald, visitor));
}
}
public GumpEntry Construct(AttendantHerald herald, int x, int y, int width, int height, int color)
{
if (this.m_Message.Number > 0)
{
string args = this.ConstructNumber(herald, null);
return new GumpHtmlLocalized(x, y, width, height, this.m_Message.Number, args, color, false, false);
}
else if (this.m_Message.String != null)
{
string message = String.Format("<BASEFONT COLOR=#{0:X6}>{1}</BASEFONT>", color, this.ConstructString(herald, null));
return new GumpHtml(x, y, width, height, message, false, false);
}
return null;
}
public string ConstructNumber(AttendantHerald herald, Mobile visitor)
{
string args = String.Empty;
if (this.m_Arguments != null && this.m_Arguments.Length > 0)
{
args = this.Construct(herald, visitor, this.m_Arguments[0]);
for (int i = 1; i < this.m_Arguments.Length; i++)
args = String.Format("{0}\t{1}", args, this.Construct(herald, visitor, this.m_Arguments[i]));
}
return args;
}
public string ConstructString(AttendantHerald herald, Mobile visitor)
{
string message = this.m_Message.String;
if (this.m_Arguments != null && this.m_Arguments.Length > 0)
{
string[] args = new string[this.m_Arguments.Length];
for (int i = 0; i < args.Length; i++)
args[i] = this.Construct(herald, visitor, this.m_Arguments[i]);
message = String.Format(message, args);
}
return message;
}
public string Construct(AttendantHerald herald, Mobile visitor, string argument)
{
if (herald == null || herald.Deleted || herald.ControlMaster == null)
return String.Empty;
Mobile m = herald.ControlMaster;
switch ( argument )
{
case "[OWNER TITLE]":
return "Mighty";
case "[OWNER NAME]":
return m.Name;
case "[OWNER SEX]":
return m.Female ? "lady" : "lord";
case "[OWNER OPPOSITE SEX]":
return m.Female ? "lord" : "lady";
case "[OWNER SEX P]":
return m.Female ? "ladies" : "lords";
case "[OWNER OPPOSITE SEX P]":
return m.Female ? "lords" : "ladies";
case "[VISITOR TITLE]":
return visitor != null ? "Mighty" : argument;
case "[VISITOR NAME]":
return visitor != null ? visitor.Name : argument;
}
return String.Empty;
}
public void Serialize(GenericWriter writer)
{
writer.WriteEncodedInt(0); // version
if (this.m_Message.Number > 0)
{
writer.Write((byte)0x1);
writer.Write(this.m_Message.Number);
}
else if (this.m_Message.String != null)
{
writer.Write((byte)0x2);
writer.Write(this.m_Message.String);
}
else
writer.Write((byte)0x0);
if (this.m_Arguments != null)
{
writer.WriteEncodedInt(this.m_Arguments.Length);
foreach (string s in this.m_Arguments)
writer.Write(s);
}
else
writer.WriteEncodedInt(0);
}
public void Deserialize(GenericReader reader)
{
int version = reader.ReadEncodedInt();
byte type = reader.ReadByte();
switch ( type )
{
case 0x1:
this.m_Message = reader.ReadInt();
break;
case 0x2:
this.m_Message = reader.ReadString();
break;
}
this.m_Arguments = new string[reader.ReadEncodedInt()];
for (int i = 0; i < this.m_Arguments.Length; i++)
this.m_Arguments[i] = reader.ReadString();
}
}
private class OptionsGump : Gump
{
private readonly AttendantHerald m_Herald;
public OptionsGump(AttendantHerald herald)
: base(200, 200)
{
this.m_Herald = herald;
this.AddBackground(0, 0, 273, 324, 0x13BE);
this.AddImageTiled(10, 10, 253, 20, 0xA40);
this.AddImageTiled(10, 40, 253, 244, 0xA40);
this.AddImageTiled(10, 294, 253, 20, 0xA40);
this.AddAlphaRegion(10, 10, 253, 304);
this.AddButton(10, 294, 0xFB1, 0xFB2, 0, GumpButtonType.Reply, 0);
this.AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF, false, false); // CANCEL
this.AddHtmlLocalized(14, 12, 273, 20, 1075996, 0x7FFF, false, false); // Herald
this.AddButton(15, 45, 0x845, 0x846, 3, GumpButtonType.Reply, 0);
this.AddHtmlLocalized(45, 43, 450, 20, 3006247, 0x7FFF, false, false); // Set Announcement Text
this.AddButton(15, 65, 0x845, 0x846, 4, GumpButtonType.Reply, 0);
this.AddHtmlLocalized(45, 63, 450, 20, 3006246, 0x7FFF, false, false); // Set Greeting Text
if (herald.ControlOrder == OrderType.Stay)
{
this.AddHtmlLocalized(45, 83, 450, 20, 1076138, 0x7D32, false, false); // Stay here and greet guests
this.AddButton(15, 105, 0x845, 0x846, 6, GumpButtonType.Reply, 0);
this.AddHtmlLocalized(45, 103, 450, 20, 1076139, 0x7FFF, false, false); // Follow me
}
else
{
this.AddButton(15, 85, 0x845, 0x846, 5, GumpButtonType.Reply, 0);
this.AddHtmlLocalized(45, 83, 450, 20, 1076138, 0x7FFF, false, false); // Stay here and greet guests
this.AddHtmlLocalized(45, 103, 450, 20, 1076139, 0x7D32, false, false); // Follow me
this.AddTooltip(1076141); // You can only issue this command when your herald is in greeting mode.
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (this.m_Herald == null || this.m_Herald.Deleted)
return;
Mobile m = sender.Mobile;
switch ( info.ButtonID )
{
case 3:
this.m_Herald.SetAnnouncementText(m);
break;
case 4:
this.m_Herald.SetGreetingText(m);
break;
case 5:
{
if (this.m_Herald.ControlOrder == OrderType.Follow)
{
BaseHouse house = BaseHouse.FindHouseAt(this.m_Herald);
if (house != null && house.IsOwner(m))
{
this.m_Herald.ControlOrder = OrderType.Stay;
this.m_Herald.ControlTarget = null;
}
else
m.SendLocalizedMessage(1076140); // You must be in a house you control to put your herald into greeting mode.
}
break;
}
case 6:
{
if (this.m_Herald.ControlOrder == OrderType.Stay)
{
this.m_Herald.ControlOrder = OrderType.Follow;
this.m_Herald.ControlTarget = m;
}
break;
}
}
}
}
private class SetTextGump : Gump
{
private readonly AttendantHerald m_Herald;
private readonly HeraldEntry[] m_Entries;
private readonly bool m_Announcement;
public SetTextGump(AttendantHerald herald, HeraldEntry[] entries, bool announcement)
: base(60, 36)
{
this.m_Herald = herald;
this.m_Entries = entries;
this.m_Announcement = announcement;
this.AddPage(0);
this.AddBackground(0, 0, 520, 324, 0x13BE);
this.AddImageTiled(10, 10, 500, 20, 0xA40);
this.AddImageTiled(10, 40, 500, 244, 0xA40);
this.AddImageTiled(10, 294, 500, 20, 0xA40);
this.AddAlphaRegion(10, 10, 500, 304);
this.AddButton(10, 294, 0xFB1, 0xFB2, 0, GumpButtonType.Reply, 0);
this.AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF, false, false); // CANCEL
this.AddHtmlLocalized(14, 12, 520, 20, 3006246 + (announcement ? 1 : 0), 0x7FFF, false, false); // Set Announcement/Greeting Text
for (int i = 0; i < entries.Length; i++)
{
if (i % 5 == 0)
{
int page = i / 5 + 1;
if (page > 1)
{
this.AddButton(435, 294, 0xFA5, 0xFA7, 0, GumpButtonType.Page, page);
this.AddHtmlLocalized(475, 296, 60, 20, 1043353, 0x7FFF, false, false); // Next
}
this.AddPage(page);
if (page > 1)
{
this.AddButton(360, 294, 0xFAE, 0xFB0, 0, GumpButtonType.Page, page - 1);
this.AddHtmlLocalized(400, 296, 60, 20, 1011393, 0x7FFF, false, false); // Back
}
}
this.AddButton(19, 49 + (i % 5) * 48, 0x845, 0x846, 100 + i, GumpButtonType.Reply, 0);
this.Add(entries[i].Construct(herald, 44, 47 + (i % 5) * 48, 460, 40, 0x7FFF));
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (this.m_Herald == null || this.m_Herald.Deleted)
return;
int index = info.ButtonID - 100;
if (index >= 0 && index < this.m_Entries.Length)
{
HeraldEntry entry = this.m_Entries[index];
if (this.m_Announcement)
{
this.m_Herald.Announcement = entry;
sender.Mobile.SendLocalizedMessage(1076686); // Your herald's announcement has been changed.
}
else
{
this.m_Herald.Greeting = entry;
sender.Mobile.SendLocalizedMessage(1076687); // Your herald's greeting has been changed.
}
}
}
}
}
public class AttendantMaleHerald : AttendantHerald
{
[Constructable]
public AttendantMaleHerald()
: base()
{
}
public AttendantMaleHerald(Serial serial)
: base(serial)
{
}
public override void InitBody()
{
this.SetStr(50, 60);
this.SetDex(20, 30);
this.SetInt(100, 110);
this.Name = NameList.RandomName("male");
this.Female = false;
this.Race = Race.Human;
this.Hue = this.Race.RandomSkinHue();
this.HairItemID = this.Race.RandomHair(this.Female);
this.HairHue = this.Race.RandomHairHue();
}
public override void InitOutfit()
{
this.AddItem(new FurBoots());
this.AddItem(new LongPants(0x901));
this.AddItem(new TricorneHat());
this.AddItem(new FormalShirt(Utility.RandomBlueHue()));
}
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 AttendantFemaleHerald : AttendantHerald
{
[Constructable]
public AttendantFemaleHerald()
: base()
{
}
public AttendantFemaleHerald(Serial serial)
: base(serial)
{
}
public override void InitBody()
{
this.SetStr(50, 60);
this.SetDex(20, 30);
this.SetInt(100, 110);
this.Name = NameList.RandomName("female");
this.Female = true;
this.Race = Race.Human;
this.Hue = this.Race.RandomSkinHue();
this.HairItemID = this.Race.RandomHair(this.Female);
this.HairHue = this.Race.RandomHairHue();
}
public override void InitOutfit()
{
Lantern lantern = new Lantern();
lantern.Ignite();
this.AddItem(lantern);
this.AddItem(new Shoes(Utility.RandomNeutralHue()));
this.AddItem(new Bonnet(Utility.RandomPinkHue()));
this.AddItem(new PlainDress(Utility.RandomPinkHue()));
}
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();
}
}
}
namespace Server.ContextMenus
{
public class HeraldSetAnnouncementTextEntry : ContextMenuEntry
{
private readonly AttendantHerald m_Attendant;
public HeraldSetAnnouncementTextEntry(AttendantHerald attendant)
: base(6247)
{
this.m_Attendant = attendant;
}
public override void OnClick()
{
if (this.m_Attendant == null || this.m_Attendant.Deleted)
return;
this.m_Attendant.SetAnnouncementText(this.Owner.From);
}
}
public class HeraldSetGreetingTextEntry : ContextMenuEntry
{
private readonly AttendantHerald m_Attendant;
public HeraldSetGreetingTextEntry(AttendantHerald attendant)
: base(6246)
{
this.m_Attendant = attendant;
}
public override void OnClick()
{
if (this.m_Attendant == null || this.m_Attendant.Deleted)
return;
this.m_Attendant.SetGreetingText(this.Owner.From);
}
}
}

View File

@@ -0,0 +1,265 @@
using System;
using System.Collections.Generic;
using Server.ContextMenus;
using Server.Gumps;
using Server.Items;
using Server.Network;
namespace Server.Mobiles
{
public class AttendantLuckyDealer : PersonalAttendant
{
private DateTime m_NextUse;
private int m_Count;
public AttendantLuckyDealer()
: base("the Lucky Dealer")
{
}
public AttendantLuckyDealer(Serial serial)
: base(serial)
{
}
public override void OnDoubleClick(Mobile from)
{
if (from.Alive && this.IsOwner(from))
{
from.CloseGump(typeof(InternalGump));
from.SendGump(new InternalGump(this));
}
else
base.OnDoubleClick(from);
}
public override void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
{
if (from.Alive && this.IsOwner(from))
list.Add(new AttendantUseEntry(this, 6244));
base.AddCustomContextEntries(from, list);
}
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();
}
private class InternalGump : Gump
{
private readonly AttendantLuckyDealer m_Dealer;
public InternalGump(AttendantLuckyDealer dealer)
: this(dealer, 1, 4)
{
}
public InternalGump(AttendantLuckyDealer dealer, int dice, int faces)
: base(60, 36)
{
this.m_Dealer = dealer;
this.AddHtmlLocalized(14, 12, 273, 20, 1075995, 0x7FFF, false, false); // Lucky Dealer
this.AddPage(0);
this.AddBackground(0, 0, 273, 324, 0x13BE);
this.AddImageTiled(10, 10, 253, 20, 0xA40);
this.AddImageTiled(10, 40, 253, 244, 0xA40);
this.AddImageTiled(10, 294, 253, 20, 0xA40);
this.AddAlphaRegion(10, 10, 253, 304);
this.AddButton(10, 294, 0xFB1, 0xFB2, 0, GumpButtonType.Reply, 0);
this.AddHtmlLocalized(45, 294, 80, 20, 1060051, 0x7FFF, false, false); // CANCEL
this.AddButton(130, 294, 0xFB7, 0xFB9, 1, GumpButtonType.Reply, 0);
this.AddHtmlLocalized(165, 294, 80, 20, 1076002, 0x7FFF, false, false); // Roll
this.AddHtmlLocalized(14, 50, 120, 20, 1076000, 0x7FFF, false, false); // Number of dice
this.AddGroup(0);
this.AddRadio(14, 70, 0xD2, 0xD3, dice == 1, 1001);
this.AddLabel(44, 70, 0x481, "1");
this.AddRadio(14, 100, 0xD2, 0xD3, dice == 2, 1002);
this.AddLabel(44, 100, 0x481, "2");
this.AddRadio(14, 130, 0xD2, 0xD3, dice == 3, 1003);
this.AddLabel(44, 130, 0x481, "3");
this.AddRadio(14, 160, 0xD2, 0xD3, dice == 4, 1004);
this.AddLabel(44, 160, 0x481, "4");
this.AddHtmlLocalized(130, 50, 120, 20, 1076001, 0x7FFF, false, false); // Number of faces
this.AddGroup(1);
this.AddRadio(130, 70, 0xD2, 0xD3, faces == 4, 4);
this.AddLabel(160, 70, 0x481, "4");
this.AddRadio(130, 100, 0xD2, 0xD3, faces == 6, 6);
this.AddLabel(160, 100, 0x481, "6");
this.AddRadio(130, 130, 0xD2, 0xD3, faces == 8, 8);
this.AddLabel(160, 130, 0x481, "8");
this.AddRadio(130, 160, 0xD2, 0xD3, faces == 10, 10);
this.AddLabel(160, 160, 0x481, "10");
this.AddRadio(130, 190, 0xD2, 0xD3, faces == 12, 12);
this.AddLabel(160, 190, 0x481, "12");
this.AddRadio(130, 220, 0xD2, 0xD3, faces == 20, 20);
this.AddLabel(160, 220, 0x481, "20");
this.AddRadio(130, 250, 0xD2, 0xD3, faces == 100, 100);
this.AddLabel(160, 250, 0x481, "100");
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (this.m_Dealer == null || this.m_Dealer.Deleted)
return;
if (info.ButtonID == 1)
{
int dice = 1;
int faces = 4;
if (info.Switches.Length == 2)
{
dice = info.Switches[0] - 1000;
faces = info.Switches[1];
}
if (this.m_Dealer.m_NextUse < DateTime.UtcNow)
{
if (dice > 0 && faces > 0)
{
int sum = 0;
string text = String.Empty;
for (int i = 0; i < dice; i++)
{
int roll = Utility.Random(faces) + 1;
text = String.Format("{0}{1}{2}", text, i > 0 ? " " : "", roll);
sum += roll;
}
this.m_Dealer.Say(1076071, String.Format("{0}\t{1}\t{2}\t{3}\t{4}", sender.Mobile.Name, dice, faces, text, sum)); // ~1_NAME~ rolls ~2_DICE~d~3_FACES~: ~4_ROLLS~ (Total: ~5_TOTAL~)
}
if (this.m_Dealer.m_Count > 0 && DateTime.UtcNow - this.m_Dealer.m_NextUse < TimeSpan.FromSeconds(this.m_Dealer.m_Count))
this.m_Dealer.m_NextUse = DateTime.UtcNow + TimeSpan.FromSeconds(3);
if (this.m_Dealer.m_Count++ == 5)
{
this.m_Dealer.m_NextUse = DateTime.UtcNow;
this.m_Dealer.m_Count = 0;
}
}
else
sender.Mobile.SendLocalizedMessage(501789); // You must wait before trying again.
sender.Mobile.SendGump(new InternalGump(this.m_Dealer, dice, faces));
}
}
}
}
public class AttendantMaleLuckyDealer : AttendantLuckyDealer
{
[Constructable]
public AttendantMaleLuckyDealer()
: base()
{
}
public AttendantMaleLuckyDealer(Serial serial)
: base(serial)
{
}
public override void InitBody()
{
this.SetStr(50, 60);
this.SetDex(20, 30);
this.SetInt(100, 110);
this.Name = NameList.RandomName("male");
this.Female = false;
this.Race = Race.Human;
this.Hue = this.Race.RandomSkinHue();
this.HairItemID = this.Race.RandomHair(this.Female);
this.HairHue = this.Race.RandomHairHue();
}
public override void InitOutfit()
{
this.AddItem(new Boots());
this.AddItem(new ShortPants());
this.AddItem(new JesterHat());
this.AddItem(new JesterSuit());
}
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 AttendantFemaleLuckyDealer : AttendantLuckyDealer
{
[Constructable]
public AttendantFemaleLuckyDealer()
: base()
{
}
public AttendantFemaleLuckyDealer(Serial serial)
: base(serial)
{
}
public override void InitBody()
{
this.SetStr(50, 60);
this.SetDex(20, 30);
this.SetInt(100, 110);
this.Name = NameList.RandomName("female");
this.Female = true;
this.Race = Race.Elf;
this.Hue = this.Race.RandomSkinHue();
this.HairItemID = this.Race.RandomHair(this.Female);
this.HairHue = this.Race.RandomHairHue();
}
public override void InitOutfit()
{
this.AddItem(new ElvenBoots());
this.AddItem(new ElvenPants());
this.AddItem(new ElvenShirt());
this.AddItem(new JesterHat());
}
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();
}
}
}

Some files were not shown because too many files have changed in this diff Show More