Fixes code according to modern code style. Fixes a few expression bugs.

This commit is contained in:
Kamron Batman 2018-09-15 09:58:51 -07:00
parent 89eea25e5f
commit 970fd563b2
3324 changed files with 441118 additions and 433755 deletions

View file

@ -1,411 +1,419 @@
using System;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Targeting;
using Server.Items;
using Server.Engines.Quests;
using Server.Engines.Quests.Necro;
using Server.Items;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Necromancy
{
public class AnimateDeadSpell : NecromancerSpell
{
private static SpellInfo m_Info = new SpellInfo(
"Animate Dead", "Uus Corp",
203,
9031,
Reagent.GraveDust,
Reagent.DaemonBlood
);
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 1.5 );
public override double RequiredSkill => 40.0;
public override int RequiredMana => 23;
public AnimateDeadSpell( Mobile caster, Item scroll ) : base( caster, scroll, m_Info )
{
}
public override void OnCast()
{
Caster.Target = new InternalTarget( this );
Caster.SendLocalizedMessage( 1061083 ); // Animate what corpse?
}
private class CreatureGroup
{
public Type[] m_Types;
public SummonEntry[] m_Entries;
public CreatureGroup( Type[] types, SummonEntry[] entries )
{
m_Types = types;
m_Entries = entries;
}
}
private class SummonEntry
{
public Type[] m_ToSummon;
public int m_Requirement;
public SummonEntry( int requirement, params Type[] toSummon )
{
m_ToSummon = toSummon;
m_Requirement = requirement;
}
}
private static CreatureGroup FindGroup( Type type )
{
for ( int i = 0; i < m_Groups.Length; ++i )
{
CreatureGroup group = m_Groups[i];
Type[] types = group.m_Types;
bool contains = ( types.Length == 0 );
for ( int j = 0; !contains && j < types.Length; ++j )
contains = types[j].IsAssignableFrom( type );
if ( contains )
return group;
}
return null;
}
private static CreatureGroup[] m_Groups = {
// Undead group--empty
new CreatureGroup( SlayerGroup.GetEntryByName( SlayerName.Silver ).Types, new SummonEntry[0] ),
// Insects
new CreatureGroup( new[]
{
typeof( DreadSpider ), typeof( FrostSpider ), typeof( GiantSpider ), typeof( GiantBlackWidow ),
typeof( BlackSolenInfiltratorQueen ), typeof( BlackSolenInfiltratorWarrior ),
typeof( BlackSolenQueen ), typeof( BlackSolenWarrior ), typeof( BlackSolenWorker ),
typeof( RedSolenInfiltratorQueen ), typeof( RedSolenInfiltratorWarrior ),
typeof( RedSolenQueen ), typeof( RedSolenWarrior ), typeof( RedSolenWorker ),
typeof( TerathanAvenger ), typeof( TerathanDrone ), typeof( TerathanMatriarch ),
typeof( TerathanWarrior )
// TODO: Giant beetle? Ant lion? Ophidians?
},
new[]
{
new SummonEntry( 0, typeof( MoundOfMaggots ) )
} ),
// Mounts
new CreatureGroup( new[]
{
typeof( Horse ), typeof( Nightmare ), typeof( FireSteed ),
typeof( Kirin ), typeof( Unicorn )
}, new[]
{
new SummonEntry( 10000, typeof( HellSteed ) ),
new SummonEntry( 0, typeof( SkeletalMount ) )
} ),
// Elementals
new CreatureGroup( new[]
{
typeof( BloodElemental ), typeof( EarthElemental ), typeof( SummonedEarthElemental ),
typeof( AgapiteElemental ), typeof( BronzeElemental ), typeof( CopperElemental ),
typeof( DullCopperElemental ), typeof( GoldenElemental ), typeof( ShadowIronElemental ),
typeof( ValoriteElemental ), typeof( VeriteElemental ), typeof( PoisonElemental ),
typeof( FireElemental ), typeof( SummonedFireElemental ), typeof( SnowElemental ),
typeof( AirElemental ), typeof( SummonedAirElemental ), typeof( WaterElemental ),
typeof( SummonedAirElemental ), typeof ( AcidElemental )
}, new[]
{
new SummonEntry( 5000, typeof( WailingBanshee ) ),
new SummonEntry( 0, typeof( Wraith ) )
} ),
// Dragons
new CreatureGroup( new[]
{
typeof( AncientWyrm ), typeof( Dragon ), typeof( GreaterDragon ), typeof( SerpentineDragon ),
typeof( ShadowWyrm ), typeof( SkeletalDragon ), typeof( WhiteWyrm ),
typeof( Drake ), typeof( Wyvern ), typeof( LesserHiryu ), typeof( Hiryu )
}, new[]
{
new SummonEntry( 18000, typeof( SkeletalDragon ) ),
new SummonEntry( 10000, typeof( FleshGolem ) ),
new SummonEntry( 5000, typeof( Lich ) ),
new SummonEntry( 3000, typeof( SkeletalKnight ), typeof( BoneKnight ) ),
new SummonEntry( 2000, typeof( Mummy ) ),
new SummonEntry( 1000, typeof( SkeletalMage ), typeof( BoneMagi ) ),
new SummonEntry( 0, typeof( PatchworkSkeleton ) )
} ),
// Default group
new CreatureGroup( new Type[0], new[]
{
new SummonEntry( 18000, typeof( LichLord ) ),
new SummonEntry( 10000, typeof( FleshGolem ) ),
new SummonEntry( 5000, typeof( Lich ) ),
new SummonEntry( 3000, typeof( SkeletalKnight ), typeof( BoneKnight ) ),
new SummonEntry( 2000, typeof( Mummy ) ),
new SummonEntry( 1000, typeof( SkeletalMage ), typeof( BoneMagi ) ),
new SummonEntry( 0, typeof( PatchworkSkeleton ) )
} ),
};
public void Target( object obj )
{
MaabusCoffinComponent comp = obj as MaabusCoffinComponent;
MaabusCoffin addon = comp?.Addon as MaabusCoffin;
if ( addon != null )
{
PlayerMobile pm = Caster as PlayerMobile;
QuestSystem qs = pm?.Quest;
if ( qs is DarkTidesQuest )
{
QuestObjective objective = qs.FindObjective( typeof( AnimateMaabusCorpseObjective ) );
if ( objective != null && !objective.Completed )
{
addon.Awake( Caster );
objective.Complete();
}
}
return;
}
Corpse c = obj as Corpse;
if ( c == null )
{
Caster.SendLocalizedMessage( 1061084 ); // You cannot animate that.
}
else
{
Type type = null;
if ( c.Owner != null )
{
type = c.Owner.GetType();
}
if ( c.ItemID != 0x2006 || c.Animated || type == typeof( PlayerMobile ) || type == null || ( c.Owner != null && c.Owner.Fame < 100 ) || ( c.Owner is BaseCreature && ( ( ( BaseCreature )c.Owner ).Summoned || ( ( BaseCreature )c.Owner ).IsBonded ) ) )
{
Caster.SendLocalizedMessage( 1061085 ); // There's not enough life force there to animate.
}
else
{
CreatureGroup group = FindGroup( type );
if ( group != null )
{
if ( group.m_Entries.Length == 0 || type == typeof( DemonKnight ) )
{
Caster.SendLocalizedMessage( 1061086 ); // You cannot animate undead remains.
}
else if ( CheckSequence() )
{
Point3D p = c.GetWorldLocation();
Map map = c.Map;
if ( map != null )
{
Effects.PlaySound( p, map, 0x1FB );
Effects.SendLocationParticles( EffectItem.Create( p, map, EffectItem.DefaultDuration ), 0x3789, 1, 40, 0x3F, 3, 9907, 0 );
Timer.DelayCall( TimeSpan.FromSeconds( 2.0 ), new TimerStateCallback( SummonDelay_Callback ), new object[] { Caster, c, p, map, group } );
}
}
}
}
}
FinishSequence();
}
private static Dictionary<Mobile, List<Mobile>> m_Table = new Dictionary<Mobile, List<Mobile>>();
public static void Unregister( Mobile master, Mobile summoned )
{
if ( master == null )
return;
m_Table.TryGetValue( master, out List<Mobile> list );
if ( list == null )
return;
public class AnimateDeadSpell : NecromancerSpell
{
private static SpellInfo m_Info = new SpellInfo(
"Animate Dead", "Uus Corp",
203,
9031,
Reagent.GraveDust,
Reagent.DaemonBlood
);
private static CreatureGroup[] m_Groups =
{
// Undead group--empty
new CreatureGroup(SlayerGroup.GetEntryByName(SlayerName.Silver).Types, new SummonEntry[0]),
// Insects
new CreatureGroup(new[]
{
typeof(DreadSpider), typeof(FrostSpider), typeof(GiantSpider), typeof(GiantBlackWidow),
typeof(BlackSolenInfiltratorQueen), typeof(BlackSolenInfiltratorWarrior),
typeof(BlackSolenQueen), typeof(BlackSolenWarrior), typeof(BlackSolenWorker),
typeof(RedSolenInfiltratorQueen), typeof(RedSolenInfiltratorWarrior),
typeof(RedSolenQueen), typeof(RedSolenWarrior), typeof(RedSolenWorker),
typeof(TerathanAvenger), typeof(TerathanDrone), typeof(TerathanMatriarch),
typeof(TerathanWarrior)
// TODO: Giant beetle? Ant lion? Ophidians?
},
new[]
{
new SummonEntry(0, typeof(MoundOfMaggots))
}),
// Mounts
new CreatureGroup(new[]
{
typeof(Horse), typeof(Nightmare), typeof(FireSteed),
typeof(Kirin), typeof(Unicorn)
}, new[]
{
new SummonEntry(10000, typeof(HellSteed)),
new SummonEntry(0, typeof(SkeletalMount))
}),
// Elementals
new CreatureGroup(new[]
{
typeof(BloodElemental), typeof(EarthElemental), typeof(SummonedEarthElemental),
typeof(AgapiteElemental), typeof(BronzeElemental), typeof(CopperElemental),
typeof(DullCopperElemental), typeof(GoldenElemental), typeof(ShadowIronElemental),
typeof(ValoriteElemental), typeof(VeriteElemental), typeof(PoisonElemental),
typeof(FireElemental), typeof(SummonedFireElemental), typeof(SnowElemental),
typeof(AirElemental), typeof(SummonedAirElemental), typeof(WaterElemental),
typeof(SummonedAirElemental), typeof(AcidElemental)
}, new[]
{
new SummonEntry(5000, typeof(WailingBanshee)),
new SummonEntry(0, typeof(Wraith))
}),
// Dragons
new CreatureGroup(new[]
{
typeof(AncientWyrm), typeof(Dragon), typeof(GreaterDragon), typeof(SerpentineDragon),
typeof(ShadowWyrm), typeof(SkeletalDragon), typeof(WhiteWyrm),
typeof(Drake), typeof(Wyvern), typeof(LesserHiryu), typeof(Hiryu)
}, new[]
{
new SummonEntry(18000, typeof(SkeletalDragon)),
new SummonEntry(10000, typeof(FleshGolem)),
new SummonEntry(5000, typeof(Lich)),
new SummonEntry(3000, typeof(SkeletalKnight), typeof(BoneKnight)),
new SummonEntry(2000, typeof(Mummy)),
new SummonEntry(1000, typeof(SkeletalMage), typeof(BoneMagi)),
new SummonEntry(0, typeof(PatchworkSkeleton))
}),
// Default group
new CreatureGroup(new Type[0], new[]
{
new SummonEntry(18000, typeof(LichLord)),
new SummonEntry(10000, typeof(FleshGolem)),
new SummonEntry(5000, typeof(Lich)),
new SummonEntry(3000, typeof(SkeletalKnight), typeof(BoneKnight)),
new SummonEntry(2000, typeof(Mummy)),
new SummonEntry(1000, typeof(SkeletalMage), typeof(BoneMagi)),
new SummonEntry(0, typeof(PatchworkSkeleton))
})
};
private static Dictionary<Mobile, List<Mobile>> m_Table = new Dictionary<Mobile, List<Mobile>>();
public AnimateDeadSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
{
}
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5);
public override double RequiredSkill => 40.0;
public override int RequiredMana => 23;
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
Caster.SendLocalizedMessage(1061083); // Animate what corpse?
}
private static CreatureGroup FindGroup(Type type)
{
for (int i = 0; i < m_Groups.Length; ++i)
{
CreatureGroup group = m_Groups[i];
Type[] types = group.m_Types;
bool contains = types.Length == 0;
for (int j = 0; !contains && j < types.Length; ++j)
contains = types[j].IsAssignableFrom(type);
if (contains)
return group;
}
return null;
}
public void Target(object obj)
{
MaabusCoffinComponent comp = obj as MaabusCoffinComponent;
MaabusCoffin addon = comp?.Addon as MaabusCoffin;
if (addon != null)
{
PlayerMobile pm = Caster as PlayerMobile;
QuestSystem qs = pm?.Quest;
if (qs is DarkTidesQuest)
{
QuestObjective objective = qs.FindObjective(typeof(AnimateMaabusCorpseObjective));
if (objective != null && !objective.Completed)
{
addon.Awake(Caster);
objective.Complete();
}
}
return;
}
Corpse c = obj as Corpse;
if (c == null)
{
Caster.SendLocalizedMessage(1061084); // You cannot animate that.
}
else
{
Type type = null;
if (c.Owner != null) type = c.Owner.GetType();
if (c.ItemID != 0x2006 || c.Animated || type == typeof(PlayerMobile) || type == null ||
c.Owner != null && c.Owner.Fame < 100 || c.Owner is BaseCreature &&
(((BaseCreature)c.Owner).Summoned || ((BaseCreature)c.Owner).IsBonded))
{
Caster.SendLocalizedMessage(1061085); // There's not enough life force there to animate.
}
else
{
CreatureGroup group = FindGroup(type);
if (group != null)
{
if (group.m_Entries.Length == 0 || type == typeof(DemonKnight))
{
Caster.SendLocalizedMessage(1061086); // You cannot animate undead remains.
}
else if (CheckSequence())
{
Point3D p = c.GetWorldLocation();
Map map = c.Map;
if (map != null)
{
Effects.PlaySound(p, map, 0x1FB);
Effects.SendLocationParticles(EffectItem.Create(p, map, EffectItem.DefaultDuration), 0x3789,
1, 40, 0x3F, 3, 9907, 0);
list.Remove( summoned );
Timer.DelayCall(TimeSpan.FromSeconds(2.0), new TimerStateCallback(SummonDelay_Callback),
new object[] { Caster, c, p, map, group });
}
}
}
}
}
if ( list.Count == 0 )
m_Table.Remove( master );
}
FinishSequence();
}
public static void Register( Mobile master, Mobile summoned )
{
if ( master == null )
return;
public static void Unregister(Mobile master, Mobile summoned)
{
if (master == null)
return;
m_Table.TryGetValue( master, out List<Mobile> list );
m_Table.TryGetValue(master, out List<Mobile> list);
if ( list == null )
m_Table[master] = list = new List<Mobile>();
if (list == null)
return;
for ( int i = list.Count - 1; i >= 0; --i )
{
if ( i >= list.Count )
continue;
list.Remove(summoned);
Mobile mob = list[i];
if (list.Count == 0)
m_Table.Remove(master);
}
if ( mob.Deleted )
list.RemoveAt( i-- );
}
public static void Register(Mobile master, Mobile summoned)
{
if (master == null)
return;
list.Add( summoned );
m_Table.TryGetValue(master, out List<Mobile> list);
if ( list.Count > 3 )
Timer.DelayCall( TimeSpan.Zero, list[0].Kill );
if (list == null)
m_Table[master] = list = new List<Mobile>();
Timer.DelayCall( TimeSpan.FromSeconds( 2.0 ), TimeSpan.FromSeconds( 2.0 ), new TimerStateCallback( Summoned_Damage ), summoned );
}
for (int i = list.Count - 1; i >= 0; --i)
{
if (i >= list.Count)
continue;
private static void Summoned_Damage( object state )
{
Mobile mob = (Mobile)state;
Mobile mob = list[i];
if ( mob.Hits > 0 )
--mob.Hits;
else
mob.Kill();
}
if (mob.Deleted)
list.RemoveAt(i--);
}
private static void SummonDelay_Callback( object state )
{
object[] states = (object[])state;
list.Add(summoned);
Mobile caster = (Mobile)states[0];
Corpse corpse = (Corpse)states[1];
Point3D loc = (Point3D)states[2];
Map map = (Map)states[3];
CreatureGroup group = (CreatureGroup)states[4];
if (list.Count > 3)
Timer.DelayCall(TimeSpan.Zero, list[0].Kill);
if ( corpse.Animated )
return;
Timer.DelayCall(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0), new TimerStateCallback(Summoned_Damage),
summoned);
}
Mobile owner = corpse.Owner;
private static void Summoned_Damage(object state)
{
Mobile mob = (Mobile)state;
if ( owner == null )
return;
if (mob.Hits > 0)
--mob.Hits;
else
mob.Kill();
}
double necromancy = caster.Skills[SkillName.Necromancy].Value;
double spiritSpeak = caster.Skills[SkillName.SpiritSpeak].Value;
private static void SummonDelay_Callback(object state)
{
object[] states = (object[])state;
int casterAbility = 0;
Mobile caster = (Mobile)states[0];
Corpse corpse = (Corpse)states[1];
Point3D loc = (Point3D)states[2];
Map map = (Map)states[3];
CreatureGroup group = (CreatureGroup)states[4];
casterAbility += (int)(necromancy * 30);
casterAbility += (int)(spiritSpeak * 70);
casterAbility /= 10;
casterAbility *= 18;
if (corpse.Animated)
return;
if ( casterAbility > owner.Fame )
casterAbility = owner.Fame;
Mobile owner = corpse.Owner;
if ( casterAbility < 0 )
casterAbility = 0;
if (owner == null)
return;
Type toSummon = null;
SummonEntry[] entries = group.m_Entries;
double necromancy = caster.Skills[SkillName.Necromancy].Value;
double spiritSpeak = caster.Skills[SkillName.SpiritSpeak].Value;
for ( int i = 0; toSummon == null && i < entries.Length; ++i )
{
SummonEntry entry = entries[i];
int casterAbility = 0;
if ( casterAbility < entry.m_Requirement )
continue;
casterAbility += (int)(necromancy * 30);
casterAbility += (int)(spiritSpeak * 70);
casterAbility /= 10;
casterAbility *= 18;
Type[] animates = entry.m_ToSummon;
if (casterAbility > owner.Fame)
casterAbility = owner.Fame;
if ( animates.Length >= 0 )
toSummon = animates[Utility.Random( animates.Length )];
}
if (casterAbility < 0)
casterAbility = 0;
if ( toSummon == null )
return;
Type toSummon = null;
SummonEntry[] entries = group.m_Entries;
Mobile summoned = null;
for (int i = 0; toSummon == null && i < entries.Length; ++i)
{
SummonEntry entry = entries[i];
try{ summoned = Activator.CreateInstance( toSummon ) as Mobile; }
catch{}
if (casterAbility < entry.m_Requirement)
continue;
if ( summoned == null )
return;
Type[] animates = entry.m_ToSummon;
if ( summoned is BaseCreature )
{
BaseCreature bc = (BaseCreature)summoned;
if (animates.Length >= 0)
toSummon = animates[Utility.Random(animates.Length)];
}
// to be sure
bc.Tamable = false;
if (toSummon == null)
return;
if ( bc is BaseMount )
bc.ControlSlots = 1;
else
bc.ControlSlots = 0;
Mobile summoned = null;
Effects.PlaySound( loc, map, bc.GetAngerSound() );
try
{
summoned = Activator.CreateInstance(toSummon) as Mobile;
}
catch
{
}
BaseCreature.Summon( (BaseCreature)summoned, false, caster, loc, 0x28, TimeSpan.FromDays( 1.0 ) );
}
if (summoned == null)
return;
if ( summoned is SkeletalDragon )
Scale( (SkeletalDragon)summoned, 50 ); // lose 50% hp and strength
if (summoned is BaseCreature)
{
BaseCreature bc = (BaseCreature)summoned;
summoned.Fame = 0;
summoned.Karma = -1500;
// to be sure
bc.Tamable = false;
summoned.MoveToWorld( loc, map );
if (bc is BaseMount)
bc.ControlSlots = 1;
else
bc.ControlSlots = 0;
corpse.Hue = 1109;
corpse.Animated = true;
Effects.PlaySound(loc, map, bc.GetAngerSound());
Register( caster, summoned );
}
BaseCreature.Summon((BaseCreature)summoned, false, caster, loc, 0x28, TimeSpan.FromDays(1.0));
}
public static void Scale( BaseCreature bc, int scalar )
{
int toScale;
if (summoned is SkeletalDragon)
Scale((SkeletalDragon)summoned, 50); // lose 50% hp and strength
toScale = bc.RawStr;
bc.RawStr = AOS.Scale( toScale, scalar );
summoned.Fame = 0;
summoned.Karma = -1500;
toScale = bc.HitsMaxSeed;
summoned.MoveToWorld(loc, map);
if ( toScale > 0 )
bc.HitsMaxSeed = AOS.Scale( toScale, scalar );
corpse.Hue = 1109;
corpse.Animated = true;
bc.Hits = bc.Hits; // refresh hits
}
Register(caster, summoned);
}
private class InternalTarget : Target
{
private AnimateDeadSpell m_Owner;
public static void Scale(BaseCreature bc, int scalar)
{
int toScale;
public InternalTarget( AnimateDeadSpell owner ) : base( Core.ML ? 10 : 12, false, TargetFlags.None )
{
m_Owner = owner;
}
toScale = bc.RawStr;
bc.RawStr = AOS.Scale(toScale, scalar);
protected override void OnTarget( Mobile from, object o )
{
m_Owner.Target( o );
}
toScale = bc.HitsMaxSeed;
protected override void OnTargetFinish( Mobile from )
{
m_Owner.FinishSequence();
}
}
}
}
if (toScale > 0)
bc.HitsMaxSeed = AOS.Scale(toScale, scalar);
bc.Hits = bc.Hits; // refresh hits
}
private class CreatureGroup
{
public SummonEntry[] m_Entries;
public Type[] m_Types;
public CreatureGroup(Type[] types, SummonEntry[] entries)
{
m_Types = types;
m_Entries = entries;
}
}
private class SummonEntry
{
public int m_Requirement;
public Type[] m_ToSummon;
public SummonEntry(int requirement, params Type[] toSummon)
{
m_ToSummon = toSummon;
m_Requirement = requirement;
}
}
private class InternalTarget : Target
{
private AnimateDeadSpell m_Owner;
public InternalTarget(AnimateDeadSpell owner) : base(Core.ML ? 10 : 12, false, TargetFlags.None)
{
m_Owner = owner;
}
protected override void OnTarget(Mobile from, object o)
{
m_Owner.Target(o);
}
protected override void OnTargetFinish(Mobile from)
{
m_Owner.FinishSequence();
}
}
}
}