A system like this could be a part of the idea proposed by Jill which looks fantastic IMO and I would be happy to contribute to or work on that project!
I am posting the code for the final Spiritmaster here along with the soul and spirit codes for the Dark Father. And yes, I am FNP from the old RunUO board and Walker Oakroot here on Excelsior!
The Master of Spirits:
Code: Select all
//////////////////////////////////// //
// Spirits by //
// FNP //
// //
//////////////////////////////////
using System;
using Server;
using System.Collections;
using Server.Items;
using Server.Network;
namespace Server.Mobiles
{
[CorpseName( "a spirit master corpse" )]
public class SpiritMaster : BaseCreature
{
[Constructable]
public SpiritMaster() : base( AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4 )
{
Name = "The Master of Spirits";
Body = 770;
Hue = 0x455;
SetStr( 526, 750 );
SetDex( 226, 320 );
SetInt( 651, 975 );
SetHits( 2500, 4000 );
SetDamage( 18, 22 );
SetDamageType( ResistanceType.Physical, 100 );
SetResistance( ResistanceType.Physical, 30, 40 );
SetResistance( ResistanceType.Fire, 45, 65 );
SetResistance( ResistanceType.Cold, 35, 45 );
SetResistance( ResistanceType.Poison, 25, 45 );
SetResistance( ResistanceType.Energy, 35, 55 );
SetSkill( SkillName.EvalInt, 110.1, 130.0 );
SetSkill( SkillName.Magery, 115.1, 130.0 );
SetSkill( SkillName.Meditation, 105.1, 120.0 );
SetSkill( SkillName.MagicResist, 112.5, 135.0 );
SetSkill( SkillName.Tactics, 85.0, 107.5 );
SetSkill( SkillName.Wrestling, 95.0, 117.5 );
Fame = 15000;
Karma = -15000;
VirtualArmor = 76;
}
public override bool CanRummageCorpses{ get{ return true; } }
public override bool Unprovokable{ get{ return true; } }
public override bool Uncalmable{ get{ return true; } }
public override void GenerateLoot()
{
AddLoot( LootPack.UltraRich, 2 );
switch ( Utility.Random( 7 ) )
{
case 0: AddItem( new BalronSoul( ) ); break;
case 1: AddItem( new AngelSoul( ) ); break;
case 2: AddItem( new BoneDemonSoul( ) ); break;
case 3: AddItem( new RiktorSoul( ) ); break;
case 4: AddItem( new SuccubusSoul( ) ); break;
case 5: AddItem( new ArachnidSoul( ) ); break;
case 6: AddItem( new AncientWyrmSoul( ) ); break;
}
if ( 0.05 > Utility.RandomDouble() )
AddItem( new DarkFatherSoul( ) );
}
public override void OnDamagedBySpell( Mobile caster )
{
if ( caster == this )
return;
AddSpirit( caster, 0.25 );
}
public override void OnGaveMeleeAttack( Mobile defender )
{
base.OnGaveMeleeAttack( defender );
if ( 0.2 >= Utility.RandomDouble() ) // 20% chance to spawn a spirit
AddSpirit( defender, 0.25 );
}
public override void OnGotMeleeAttack( Mobile attacker )
{
base.OnGotMeleeAttack( attacker );
if ( 0.2 >= Utility.RandomDouble() ) // 20% chance to spawn a spirit
AddSpirit( attacker, 0.25 );
}
public void AddSpirit( Mobile target, double chanceToThrow )
{
if ( chanceToThrow >= Utility.RandomDouble() )
{
Direction = GetDirectionTo( target );
MovingEffect( target, 0xF7E, 10, 1, true, false, 0x496, 0 );
Mobile spawn;
switch ( Utility.Random( 7 ) )
{
default:
case 0: spawn = new SpiritAncientWyrm(); break;
case 1: spawn = new SpiritBalron(); break;
case 2: spawn = new SpiritRiktor(); break;
case 3: spawn = new SpiritBoneDemon(); break;
case 4: spawn = new SpiritArachnid(); break;
case 5: spawn = new SpiritSuccubus(); break;
case 6: spawn = new SpiritDarkFather(); break;
}
spawn.MoveToWorld( Location, Map );
}
}
public override bool ClickTitle{ get{ return false; } }
public override bool ShowFameTitle{ get{ return false; } }
public override bool AlwaysMurderer{ get{ return true; } }
public SpiritMaster( 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 version = reader.ReadInt();
}
}
}
Code: Select all
//////////////////////////////////
// //
// Spirits by //
// FNP //
// //
//////////////////////////////////
using System;
using Server;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName( "a dark father corpse" )]
public class SpiritDarkFather : BaseCreature
{
private DateTime m_ExpireTime;
[CommandProperty( AccessLevel.GameMaster )]
public DateTime ExpireTime
{
get{ return m_ExpireTime; }
set{ m_ExpireTime = value; }
}
public override void OnThink()
{
bool expired;
expired = ( DateTime.Now >= m_ExpireTime );
if ( expired )
{
PlaySound( GetIdleSound() );
Delete();
}
else
{
base.OnThink();
}
}
[Constructable]
public SpiritDarkFather() : this( false, 1.2 )
{
}
[Constructable]
public SpiritDarkFather ( bool summoned, double scalar ) : base( AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4 )
{
m_ExpireTime = DateTime.Now + TimeSpan.FromMinutes( (int)(60*scalar) + 45 );
Name = "an dark father spirit";
Body = 318;
BaseSoundID = 0x165;
Hue = 0x4001;
SetStr( (int)(502*scalar), (int)(666*scalar) );
SetDex( (int)(111*scalar), (int)(200*scalar) );
SetInt( (int)(900*scalar), (int)(1100*scalar) );
SetHits( (int)(29000*scalar), (int)(31000*scalar) );
SetMana( 5000 );
SetDamage( (int)(17*scalar), (int)(21*scalar) );
SetDamageType( ResistanceType.Physical, 20 );
SetDamageType( ResistanceType.Fire, 20 );
SetDamageType( ResistanceType.Cold, 20 );
SetDamageType( ResistanceType.Poison, 20 );
SetDamageType( ResistanceType.Energy, 20 );
SetResistance( ResistanceType.Physical, 30 );
SetResistance( ResistanceType.Fire, 30 );
SetResistance( ResistanceType.Cold, 30 );
SetResistance( ResistanceType.Poison, 30 );
SetResistance( ResistanceType.Energy, 30 );
SetSkill( SkillName.EvalInt, 100.0 );
SetSkill( SkillName.Magery, 100.0 );
SetSkill( SkillName.Meditation, 120.0 );
SetSkill( SkillName.MagicResist, 150.0 );
SetSkill( SkillName.Tactics, 100.0 );
SetSkill( SkillName.Wrestling, 120.0 );
SetSkill( SkillName.EvalInt, (int)(95*scalar), (int)(115*scalar) );
SetSkill( SkillName.Magery, (int)(95*scalar), (int)(110*scalar) );
SetSkill( SkillName.Meditation, (int)(100*scalar), (int)(130*scalar) );
SetSkill( SkillName.MagicResist, (int)(140*scalar), (int)(150*scalar) );
SetSkill( SkillName.Tactics, (int)(100*scalar), (int)(110*scalar) );
SetSkill( SkillName.Wrestling, (int)(110*scalar), (int)(130*scalar) );
Fame = 22000;
Karma = -22000;
VirtualArmor = 88;
ControlSlots = 4;
}
public override bool DeleteOnRelease{ get{ return true; } }
public override Poison PoisonImmune{ get{ return Poison.Regular; } } // TODO: Immune to poison?
public override void GenerateLoot()
{
if ( 0.1 > Utility.RandomDouble() )
AddItem( new DarkFatherSoul() );
}
public SpiritDarkFather( 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 version = reader.ReadInt();
}
}
}
Code: Select all
//////////////////////////////////
// //
// Spirits by //
// FNP //
// //
//////////////////////////////////
using System;
using Server;
using Server.Mobiles;
using Server.Network;
using Server.Spells;
namespace Server.Items
{
public class DarkFatherSoul : Item
{
[Constructable]
public DarkFatherSoul() : base( 0x241D )
{
Movable = true;
Name = "a dark father soul";
Stackable = false;
Weight = 1.0;
}
public DarkFatherSoul( 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();
}
public override void OnDoubleClick( Mobile from )
{
if ( (from.Followers + 4) > from.FollowersMax )
{
from.SendLocalizedMessage( 1049607 ); // You have too many followers to control that creature.
return;
}
double necroSkill = from.Skills[SkillName.SpiritSpeak].Value;
double scalar;
if ( necroSkill >= 140.0 )
scalar = 1.4;
else if ( necroSkill >= 120.0 )
scalar = 1.2;
else if ( necroSkill >= 100.0 )
scalar = 1.0;
else if ( necroSkill >= 70.0 )
scalar = 0.9;
else
scalar = 0.8;
{
SpiritDarkFather g = new SpiritDarkFather( true, scalar );
if ( g.SetControlMaster( from ) )
{
Delete();
g.MoveToWorld( from.Location, from.Map );
}
}
}
}
}
Respectfully,
Walker