261 lines
No EOL
6.6 KiB
C#
261 lines
No EOL
6.6 KiB
C#
using System;
|
|
using System.Collections;
|
|
using Server.Items;
|
|
using Server.Targeting;
|
|
using Server.Network;
|
|
|
|
namespace Server.Mobiles
|
|
{
|
|
[CorpseName( "a plague beast corpse" )]
|
|
public class PlagueBeast : BaseCreature, IDevourer
|
|
{
|
|
private int m_DevourTotal;
|
|
private int m_DevourGoal;
|
|
private bool m_HasMetalChest = false;
|
|
|
|
[CommandProperty( AccessLevel.GameMaster )]
|
|
public int TotalDevoured
|
|
{
|
|
get { return m_DevourTotal; }
|
|
set { m_DevourTotal = value; }
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.GameMaster )]
|
|
public int DevourGoal
|
|
{
|
|
get { return ( IsParagon ? m_DevourGoal + 25 : m_DevourGoal ); }
|
|
set { m_DevourGoal = value; }
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.GameMaster )]
|
|
public bool HasMetalChest
|
|
{
|
|
get { return m_HasMetalChest; }
|
|
}
|
|
|
|
[Constructable]
|
|
public PlagueBeast() : base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4 )
|
|
{
|
|
Name = "a plague beast";
|
|
Body = 775;
|
|
|
|
SetStr( 302, 500 );
|
|
SetDex( 80 );
|
|
SetInt( 16, 20 );
|
|
|
|
SetHits( 318, 404 );
|
|
|
|
SetDamage( 20, 24 );
|
|
|
|
SetDamageType( ResistanceType.Physical, 60 );
|
|
SetDamageType( ResistanceType.Poison, 40 );
|
|
|
|
SetResistance( ResistanceType.Physical, 45, 55 );
|
|
SetResistance( ResistanceType.Fire, 40, 50 );
|
|
SetResistance( ResistanceType.Cold, 25, 35 );
|
|
SetResistance( ResistanceType.Poison, 65, 75 );
|
|
SetResistance( ResistanceType.Energy, 25, 35 );
|
|
|
|
SetSkill( SkillName.MagicResist, 35.0 );
|
|
SetSkill( SkillName.Tactics, 100.0 );
|
|
SetSkill( SkillName.Wrestling, 100.0 );
|
|
|
|
Fame = 13000;
|
|
Karma = -13000;
|
|
|
|
VirtualArmor = 30;
|
|
PackArmor( 1, 5 );
|
|
if ( Utility.RandomDouble() < 0.80 )
|
|
PackItem( new PlagueBeastGland() );
|
|
|
|
if ( Core.ML && Utility.RandomDouble() < 0.33 )
|
|
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(4) );
|
|
|
|
m_DevourTotal = 0;
|
|
m_DevourGoal = Utility.RandomMinMax( 15, 25 ); // How many corpses must be devoured before a metal chest is awarded
|
|
}
|
|
|
|
public override void GenerateLoot()
|
|
{
|
|
AddLoot( LootPack.FilthyRich );
|
|
AddLoot( LootPack.Gems, Utility.Random( 1, 3 ) );
|
|
// TODO: dungeon chest, healthy gland
|
|
}
|
|
|
|
public override void OnGaveMeleeAttack( Mobile defender )
|
|
{
|
|
base.OnGaveMeleeAttack( defender );
|
|
|
|
defender.ApplyPoison( this, IsParagon ? Poison.Lethal : Poison.Deadly );
|
|
defender.FixedParticles( 0x374A, 10, 15, 5021, EffectLayer.Waist );
|
|
defender.PlaySound( 0x1CB );
|
|
}
|
|
|
|
public override void OnDamagedBySpell( Mobile caster )
|
|
{
|
|
if ( this.Map != null && caster != this && 0.25 > Utility.RandomDouble() )
|
|
{
|
|
BaseCreature spawn = new PlagueSpawn( this );
|
|
|
|
spawn.Team = this.Team;
|
|
spawn.MoveToWorld( this.Location, this.Map );
|
|
spawn.Combatant = caster;
|
|
|
|
Say( 1053034 ); // * The plague beast creates another beast from its flesh! *
|
|
}
|
|
|
|
base.OnDamagedBySpell( caster );
|
|
}
|
|
|
|
public override bool AutoDispel{ get{ return true; } }
|
|
public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
|
|
|
|
public override void OnGotMeleeAttack( Mobile attacker )
|
|
{
|
|
if ( this.Map != null && attacker != this && 0.25 > Utility.RandomDouble() )
|
|
{
|
|
BaseCreature spawn = new PlagueSpawn( this );
|
|
|
|
spawn.Team = this.Team;
|
|
spawn.MoveToWorld( this.Location, this.Map );
|
|
spawn.Combatant = attacker;
|
|
|
|
Say( 1053034 ); // * The plague beast creates another beast from its flesh! *
|
|
}
|
|
|
|
base.OnGotMeleeAttack( attacker );
|
|
}
|
|
|
|
public PlagueBeast( Serial serial ) : base( serial )
|
|
{
|
|
}
|
|
|
|
public override int GetIdleSound()
|
|
{
|
|
return 0x1BF;
|
|
}
|
|
|
|
public override int GetAttackSound()
|
|
{
|
|
return 0x1C0;
|
|
}
|
|
|
|
public override int GetHurtSound()
|
|
{
|
|
return 0x1C1;
|
|
}
|
|
|
|
public override int GetDeathSound()
|
|
{
|
|
return 0x1C2;
|
|
}
|
|
|
|
public override void Serialize( GenericWriter writer )
|
|
{
|
|
base.Serialize( writer );
|
|
writer.Write( (int) 1 );
|
|
|
|
writer.Write( m_HasMetalChest );
|
|
writer.Write( m_DevourTotal );
|
|
writer.Write( m_DevourGoal );
|
|
}
|
|
|
|
public override void Deserialize( GenericReader reader )
|
|
{
|
|
base.Deserialize( reader );
|
|
int version = reader.ReadInt();
|
|
|
|
switch( version )
|
|
{
|
|
case 1:
|
|
{
|
|
m_HasMetalChest = reader.ReadBool();
|
|
m_DevourTotal = reader.ReadInt();
|
|
m_DevourGoal = reader.ReadInt();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void OnThink()
|
|
{
|
|
base.OnThink();
|
|
|
|
// Check to see if we need to devour any corpses
|
|
IPooledEnumerable eable = GetItemsInRange( 3 ); // Get all corpses in range
|
|
|
|
foreach( Item item in eable )
|
|
{
|
|
if( item is Corpse ) // For each Corpse
|
|
{
|
|
Corpse corpse = item as Corpse;
|
|
|
|
// Ensure that the corpse was killed by us
|
|
if( corpse != null && corpse.Killer == this && corpse.Owner != null )
|
|
{
|
|
if( !corpse.DevourCorpse() && !corpse.Devoured )
|
|
PublicOverheadMessage( MessageType.Emote, 0x3B2, 1053032 ); // * The plague beast attempts to absorb the remains, but cannot! *
|
|
}
|
|
}
|
|
}
|
|
eable.Free();
|
|
}
|
|
|
|
#region IDevourer Members
|
|
|
|
public bool Devour( Corpse corpse )
|
|
{
|
|
if( corpse == null || corpse.Owner == null ) // sorry we can't devour because the corpse's owner is null
|
|
return false;
|
|
|
|
if( corpse.Owner.Body.IsHuman )
|
|
corpse.TurnToBones(); // Not bones yet, and we are a human body therefore we turn to bones.
|
|
|
|
IncreaseHits( (int)Math.Ceiling( (double)corpse.Owner.HitsMax * 0.75 ) );
|
|
m_DevourTotal++;
|
|
|
|
PublicOverheadMessage( MessageType.Emote, 0x3B2, 1053033 ); // * The plague beast absorbs the fleshy remains of the corpse *
|
|
|
|
if( !m_HasMetalChest && m_DevourTotal >= DevourGoal )
|
|
{
|
|
PackItem( new MetalChest() );
|
|
m_HasMetalChest = true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void IncreaseHits( int hp )
|
|
{
|
|
int maxhits = 2000;
|
|
|
|
if ( this.IsParagon )
|
|
maxhits = (int)(maxhits * Paragon.HitsBuff);
|
|
|
|
if( hp < 1000 && !Core.AOS )
|
|
hp = (hp * 100) / 60;
|
|
|
|
if( HitsMaxSeed >= maxhits )
|
|
{
|
|
HitsMaxSeed = maxhits;
|
|
|
|
int newHits = this.Hits + hp + Utility.RandomMinMax( 10, 20 ); // increase the hp until it hits if it goes over it'll max at 2000
|
|
|
|
this.Hits = Math.Min( maxhits, newHits );
|
|
// Also provide heal for each devour on top of the hp increase
|
|
}
|
|
else
|
|
{
|
|
int min = (hp / 2) + 10;
|
|
int max = hp + 20;
|
|
int hpToIncrease = Utility.RandomMinMax( min, max );
|
|
|
|
HitsMaxSeed += hpToIncrease;
|
|
Hits += hpToIncrease;
|
|
// Also provide heal for each devour
|
|
}
|
|
}
|
|
}
|
|
} |