433 lines
14 KiB
C#
433 lines
14 KiB
C#
using Server;
|
|
using System;
|
|
using Server.Items;
|
|
using Server.Mobiles;
|
|
using Server.Network;
|
|
using Server.SkillHandlers;
|
|
|
|
namespace Server.Mobiles
|
|
{
|
|
public enum Alignment
|
|
{
|
|
Neutral,
|
|
Good,
|
|
Evil
|
|
}
|
|
}
|
|
|
|
namespace Server.Engines.Despise
|
|
{
|
|
public class DespiseCreature : BaseCreature
|
|
{
|
|
private WispOrb m_Orb;
|
|
private int m_Power;
|
|
private int m_MaxPower;
|
|
private int m_Progress;
|
|
|
|
[CommandProperty(AccessLevel.GameMaster)]
|
|
public virtual Alignment Alignment
|
|
{
|
|
get
|
|
{
|
|
if (Karma > 0)
|
|
return Alignment.Good;
|
|
if (Karma < 0)
|
|
return Alignment.Evil;
|
|
return Alignment.Neutral;
|
|
}
|
|
}
|
|
|
|
[CommandProperty(AccessLevel.GameMaster)]
|
|
public WispOrb Orb { get { return m_Orb; } set { m_Orb = value; } }
|
|
|
|
[CommandProperty(AccessLevel.GameMaster)]
|
|
public int MaxPower { get { return m_MaxPower; } set { m_MaxPower = value; } }
|
|
|
|
[CommandProperty(AccessLevel.GameMaster)]
|
|
public int Power
|
|
{
|
|
get { return m_Power; }
|
|
set
|
|
{
|
|
int oldPower = m_Power;
|
|
|
|
if (value > m_MaxPower)
|
|
m_Power = m_MaxPower;
|
|
|
|
if (oldPower < value)
|
|
{
|
|
m_Power = value;
|
|
IncreasePower();
|
|
InvalidateProperties();
|
|
}
|
|
|
|
if (m_Orb != null)
|
|
m_Orb.InvalidateProperties();
|
|
}
|
|
}
|
|
|
|
[CommandProperty(AccessLevel.GameMaster)]
|
|
public int Progress
|
|
{
|
|
get { return m_Progress; }
|
|
set
|
|
{
|
|
m_Progress = value;
|
|
|
|
if (m_Progress >= m_Power)
|
|
{
|
|
Power++;
|
|
|
|
IncreaseResists();
|
|
|
|
m_Progress = 0;
|
|
}
|
|
|
|
if (m_Orb != null)
|
|
m_Orb.InvalidateProperties();
|
|
}
|
|
}
|
|
|
|
public virtual int TightLeashLength { get { return 1; } }
|
|
public virtual int ShortLeashLength { get { return 1; } }
|
|
public virtual int LongLeashLength { get { return 10; } }
|
|
|
|
public virtual int StatRatio { get { return Utility.RandomMinMax(35, 60); } }
|
|
|
|
public virtual double SkillStart { get { return Utility.RandomMinMax(80.0, 130.0); } }
|
|
public virtual double SkillMax { get { return m_MaxPower == 15 ? 130.0 : 110.0; } }
|
|
|
|
public virtual int StrStart { get { return Utility.RandomMinMax(91, 100); } }
|
|
public virtual int DexStart { get { return Utility.RandomMinMax(91, 100); } }
|
|
public virtual int IntStart { get { return Utility.RandomMinMax(91, 100); } }
|
|
|
|
public virtual int StrMax { get { return 600; } }
|
|
public virtual int DexMax { get { return 150; } }
|
|
public virtual int IntMax { get { return 450; } }
|
|
|
|
public virtual int HitsStart { get { return StrStart + (int)((double)StrStart * ((double)StatRatio / 100.0)); } }
|
|
public virtual int StamStart { get { return DexStart + (int)((double)DexStart * ((double)StatRatio / 100.0)); } }
|
|
public virtual int ManaStart { get { return IntStart + (int)((double)IntStart * ((double)StatRatio / 100.0)); } }
|
|
|
|
public virtual int MaxHits { get { return 1000; } }
|
|
public virtual int MaxStam { get { return 1000; } }
|
|
public virtual int MaxMana { get { return 1500; } }
|
|
|
|
public virtual int MinDamStart { get { return 8; } }
|
|
public virtual int MaxDamStart { get { return 13; } }
|
|
|
|
public virtual int MinDamMax { get { return 12; } }
|
|
public virtual int MaxDamMax { get { return 17; } }
|
|
|
|
public virtual bool RaiseDamage { get { return false; } }
|
|
public virtual double RaiseDamageFactor { get { return 0.33; } }
|
|
|
|
public virtual int GetFame { get { return m_Power * 500; } }
|
|
public virtual int GetKarmaGood { get { return m_Power * 500; } }
|
|
public virtual int GetKarmaEvil { get { return m_Power * -500; } }
|
|
|
|
public override bool Commandable { get { return false; } }
|
|
|
|
public override bool InitialInnocent { get { return Alignment < Alignment.Evil; } }
|
|
public override bool AlwaysMurderer { get { return Alignment == Alignment.Evil; } }
|
|
public override bool ForceNotoriety { get { return true; } }
|
|
public override bool IsBondable { get { return false; } }
|
|
public override bool GivesFameAndKarmaAward { get { return false; } }
|
|
public override bool CanAutoStable { get { return false; } }
|
|
|
|
public override Poison GetHitPoison()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public override TimeSpan ReacquireDelay
|
|
{
|
|
get
|
|
{
|
|
if (!Controlled || m_Orb == null || m_Orb.Aggression == Aggression.Defensive)
|
|
{
|
|
return TimeSpan.FromSeconds(10.0);
|
|
}
|
|
else
|
|
{
|
|
return TimeSpan.FromSeconds(Utility.RandomMinMax(4, 6));
|
|
}
|
|
}
|
|
}
|
|
|
|
public DespiseCreature(AIType ai, FightMode fightmode)
|
|
: base(ai, fightmode, 10, 1, .2, .4)
|
|
{
|
|
m_MaxPower = 10;
|
|
m_Power = 1;
|
|
|
|
SetStr(StrStart);
|
|
SetDex(DexStart);
|
|
SetInt(IntStart);
|
|
|
|
SetHits(HitsStart);
|
|
SetStam(StamStart);
|
|
SetMana(ManaStart);
|
|
|
|
SetDamageType(ResistanceType.Physical, 100);
|
|
|
|
SetResistance(ResistanceType.Physical, 5, 50);
|
|
SetResistance(ResistanceType.Fire, 5, 50);
|
|
SetResistance(ResistanceType.Cold, 5, 50);
|
|
SetResistance(ResistanceType.Poison, 5, 50);
|
|
SetResistance(ResistanceType.Energy, 5, 50);
|
|
|
|
SetSkill(SkillName.Wrestling, SkillStart);
|
|
SetSkill(SkillName.Tactics, SkillStart);
|
|
SetSkill(SkillName.MagicResist, SkillStart);
|
|
SetSkill(SkillName.Anatomy, SkillStart);
|
|
SetSkill(SkillName.Poisoning, SkillStart);
|
|
SetSkill(SkillName.DetectHidden, SkillStart);
|
|
SetSkill(SkillName.Parry, SkillStart);
|
|
SetSkill(SkillName.Magery, SkillStart);
|
|
SetSkill(SkillName.EvalInt, SkillStart);
|
|
SetSkill(SkillName.Meditation, SkillStart);
|
|
SetSkill(SkillName.Necromancy, SkillStart);
|
|
SetSkill(SkillName.SpiritSpeak, SkillStart);
|
|
SetSkill(SkillName.Focus, SkillStart);
|
|
SetSkill(SkillName.Discordance, SkillStart);
|
|
|
|
NoLootOnDeath = true;
|
|
|
|
SetDamage(MinDamStart, MaxDamStart);
|
|
}
|
|
|
|
public override bool IsEnemy(Mobile m)
|
|
{
|
|
if (m is PlayerMobile)
|
|
{
|
|
if (m.Karma <= 1000 && Alignment == Alignment.Good)
|
|
return true;
|
|
|
|
if (m.Karma >= 1000 && Alignment == Alignment.Evil)
|
|
return true;
|
|
}
|
|
else if (m is DespiseCreature)
|
|
{
|
|
return ((DespiseCreature)m).Alignment != this.Alignment;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override bool CanBeRenamedBy(Mobile from)
|
|
{
|
|
if (from.AccessLevel > AccessLevel.Player)
|
|
return base.CanBeRenamedBy(from);
|
|
|
|
return false;
|
|
}
|
|
|
|
public override void GetContextMenuEntries(Mobile from, System.Collections.Generic.List<Server.ContextMenus.ContextMenuEntry> list)
|
|
{
|
|
}
|
|
|
|
public override void GetProperties(ObjectPropertyList list)
|
|
{
|
|
base.GetProperties(list);
|
|
|
|
if (ControlMaster != null)
|
|
list.Add(1153303, ControlMaster.Name); // Controller: ~1_NAME~
|
|
|
|
list.Add(1153297, String.Format("{0}\t#{1}", m_Power.ToString(), GetPowerLabel(m_Power))); // Power Level: ~1_LEVEL~: ~2_VAL~
|
|
}
|
|
|
|
public override void OnCombatantChange()
|
|
{
|
|
base.OnCombatantChange();
|
|
|
|
if (m_Orb != null)
|
|
m_Orb.InvalidateHue();
|
|
}
|
|
|
|
public override void OnKarmaChange(int oldValue)
|
|
{
|
|
if ((oldValue < 0 && Karma > 0) || (oldValue > 0 && Karma < 0))
|
|
{
|
|
switch (Alignment)
|
|
{
|
|
case Alignment.Good: FightMode = FightMode.Evil; break;
|
|
case Alignment.Evil: FightMode = FightMode.Good; break;
|
|
default: FightMode = FightMode.Aggressor; break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void OnDeath(Container c)
|
|
{
|
|
base.OnDeath(c);
|
|
|
|
if (m_Orb != null)
|
|
{
|
|
Unlink(false);
|
|
}
|
|
}
|
|
|
|
public override void Delete()
|
|
{
|
|
base.Delete();
|
|
|
|
if (m_Orb != null && !m_Orb.Deleted)
|
|
m_Orb.Pet = null;
|
|
}
|
|
|
|
public int GetLeashLength()
|
|
{
|
|
if (m_Orb == null)
|
|
return RangePerception;
|
|
|
|
switch (m_Orb.LeashLength)
|
|
{
|
|
default:
|
|
case LeashLength.Short: return ShortLeashLength;
|
|
case LeashLength.Long: return LongLeashLength;
|
|
}
|
|
}
|
|
|
|
public void Link(WispOrb orb)
|
|
{
|
|
m_Orb = orb;
|
|
RangeHome = 2;
|
|
m_Orb.InvalidateHue();
|
|
}
|
|
|
|
public void Unlink(bool message = true)
|
|
{
|
|
RangeHome = 10;
|
|
SetControlMaster(null);
|
|
|
|
if (Alive && message)
|
|
{
|
|
if (m_Orb != null && m_Orb.Owner != null)
|
|
{
|
|
m_Orb.Owner.SendLocalizedMessage(1153335, Name); // You have released control of ~1_NAME~.
|
|
NonlocalOverheadMessage(MessageType.Regular, 0x59, 1153296, Name); // * This creature is no longer influenced by a Wisp Orb *
|
|
}
|
|
}
|
|
|
|
if (m_Orb != null)
|
|
{
|
|
m_Orb.Conscripted = false;
|
|
m_Orb.OnUnlinkPet();
|
|
m_Orb.InvalidateHue();
|
|
|
|
m_Orb = null;
|
|
}
|
|
}
|
|
|
|
public virtual void IncreasePower()
|
|
{
|
|
foreach (Skill skill in Skills)
|
|
{
|
|
if (skill != null && skill.Base > 0 && skill.Base < SkillMax)
|
|
{
|
|
double toRaise = ((SkillMax / m_MaxPower) * m_Power) + Utility.RandomMinMax(-5, 5);
|
|
|
|
if (toRaise > skill.Base)
|
|
skill.Base = Math.Min(SkillMax, toRaise);
|
|
}
|
|
}
|
|
|
|
int strRaise = ((StrMax / 15) * m_Power) + Utility.RandomMinMax(-5, 5);
|
|
int dexRaise = ((DexMax / 15) * m_Power) + Utility.RandomMinMax(-5, 5);
|
|
int intRaise = ((IntMax / 15) * m_Power) + Utility.RandomMinMax(-5, 5);
|
|
|
|
if (strRaise > RawStr)
|
|
SetStr(Math.Min(StrMax, strRaise));
|
|
|
|
if (dexRaise > RawDex)
|
|
SetDex(Math.Min(DexMax, dexRaise));
|
|
|
|
if (intRaise > RawInt)
|
|
SetInt(Math.Min(IntMax, intRaise));
|
|
|
|
int hitsRaise = ((MaxHits / 15) * m_Power) + Utility.RandomMinMax(-5, 5);
|
|
int stamRaise = ((MaxStam / 15) * m_Power) + Utility.RandomMinMax(-5, 5);
|
|
int manaRaise = ((MaxMana / 15) * m_Power) + Utility.RandomMinMax(-5, 5);
|
|
|
|
if (hitsRaise > HitsMax)
|
|
SetHits(Math.Min(MaxHits, hitsRaise));
|
|
|
|
if (stamRaise > StamMax)
|
|
SetStam(Math.Min(MaxStam, stamRaise));
|
|
|
|
if (manaRaise > ManaMax)
|
|
SetMana(Math.Min(MaxMana, manaRaise));
|
|
|
|
if (RaiseDamage && Utility.RandomDouble() < RaiseDamageFactor)
|
|
{
|
|
DamageMin = Math.Min(MinDamMax, DamageMin + 1);
|
|
DamageMax = Math.Min(MaxDamMax, DamageMax + 1);
|
|
}
|
|
|
|
FixedEffect(0x373A, 10, 30);
|
|
PlaySound(0x209);
|
|
}
|
|
|
|
private void IncreaseResists()
|
|
{
|
|
SetResistance(ResistanceType.Physical, Math.Min(80, PhysicalResistanceSeed + Utility.RandomMinMax(5, 15)));
|
|
SetResistance(ResistanceType.Fire, Math.Min(80, FireResistSeed + Utility.RandomMinMax(5, 15)));
|
|
SetResistance(ResistanceType.Cold, Math.Min(80, ColdResistSeed + Utility.RandomMinMax(5, 15)));
|
|
SetResistance(ResistanceType.Poison, Math.Min(80, PoisonResistSeed + Utility.RandomMinMax(5, 15)));
|
|
SetResistance(ResistanceType.Energy, Math.Min(80, EnergyResistSeed + Utility.RandomMinMax(5, 15)));
|
|
}
|
|
|
|
public static int GetPowerLabel(int power)
|
|
{
|
|
switch (power)
|
|
{
|
|
default:
|
|
case 0:
|
|
case 1:
|
|
case 3: return 1153298; // Normal
|
|
case 4:
|
|
case 5:
|
|
case 6: return 1153299; // Improved
|
|
case 7:
|
|
case 8: return 1153300; // Heightened
|
|
case 9:
|
|
case 10: return 1153301; // Magnified
|
|
case 11:
|
|
case 12: return 1153302; // Amplified
|
|
case 13:
|
|
case 14: return 1153307; // Inspired
|
|
case 15: return 1153308; // Galvanized
|
|
}
|
|
}
|
|
|
|
public DespiseCreature(Serial serial)
|
|
: base(serial)
|
|
{
|
|
}
|
|
|
|
public override void Serialize(GenericWriter writer)
|
|
{
|
|
base.Serialize(writer);
|
|
writer.Write((int)0);
|
|
writer.Write(m_Orb);
|
|
writer.Write(m_Power);
|
|
writer.Write(m_MaxPower);
|
|
writer.Write(m_Progress);
|
|
}
|
|
|
|
public override void Deserialize(GenericReader reader)
|
|
{
|
|
base.Deserialize(reader);
|
|
int v = reader.ReadInt();
|
|
m_Orb = reader.ReadItem() as WispOrb;
|
|
m_Power = reader.ReadInt();
|
|
m_MaxPower = reader.ReadInt();
|
|
m_Progress = reader.ReadInt();
|
|
|
|
if (!NoLootOnDeath)
|
|
NoLootOnDeath = true;
|
|
}
|
|
}
|
|
}
|