RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Perma-Death System

Gosmann

Sorceror
Hi community:)

here is something we made during this week:) It is a permanent death system.

How it works:

After being defeated by a player or a basecreature, you get unconscious. After 1 minute you ressurect over your body ( you cant move while you are dead ) and you wear all your stuff ( small distro changes needed fot this feature ).
But if your corpse ist carved by a player while you are unconscious, you die and your char will be deleted!

Installation:
1. Simply drag n' drop somewhere in your runuo scripts folder

2. Not needed but recommended

Open PlayerMobile.cs and SEARCH for:

Code:
public override DeathMoveResult GetParentMoveResultFor( Item item )
        {
            if ( CheckInsuranceOnDeath( item ) )
                return DeathMoveResult.MoveToBackpack;
 
            DeathMoveResult res = base.GetParentMoveResultFor( item );
 
            if ( res == DeathMoveResult.MoveToCorpse && item.Movable && this.Young )
                res = DeathMoveResult.MoveToBackpack;
 
            return res;
        }
 
        public override DeathMoveResult GetInventoryMoveResultFor( Item item )
        {
            if ( CheckInsuranceOnDeath( item ) )
                return DeathMoveResult.MoveToBackpack;
 
            DeathMoveResult res = base.GetInventoryMoveResultFor( item );
 
            if ( res == DeathMoveResult.MoveToCorpse && item.Movable && this.Young )
                res = DeathMoveResult.MoveToBackpack;
 
            return res;
        }

and REPLACE with this:

Code:
public override DeathMoveResult GetParentMoveResultFor( Item item )
        {
            if ( CheckInsuranceOnDeath( item ) )
                return DeathMoveResult.RemainEquiped;
 
            DeathMoveResult res = base.GetParentMoveResultFor( item );
 
            if ( res == DeathMoveResult.MoveToCorpse && item.Movable && this.Young )
                res = DeathMoveResult.RemainEquiped;
 
            return res;
        }
 
        public override DeathMoveResult GetInventoryMoveResultFor( Item item )
        {
            if ( CheckInsuranceOnDeath( item ) )
                return DeathMoveResult.RemainEquiped;
 
            DeathMoveResult res = base.GetInventoryMoveResultFor( item );
 
            if ( res == DeathMoveResult.MoveToCorpse && item.Movable && this.Young )
                res = DeathMoveResult.RemainEquiped;
 
            return res;
        }

You may want to check out Tarn Blackhails site, he put his own twist into this system, really interesting!

Special thanks to Tarn Blackhail, Solteric and especially Vorspire
 

Attachments

  • PermaDeath.cs
    3 KB · Views: 68

Zagros

Sorceror
I really like the unconscious spin on this, Playing another shard back in the day. We had a simmilar system without first being unconsious before perma death, but we called them mortals, death included dropping thier house and all thier belongings back into the world too... I think the longest living mortal was just over a year old... boy was it fun.
 

hungry4knowhow

Sorceror
Serious business here.

Maybe version 2 can have a feature that will automatically unplug your internet, and then blow up your computer. Serious Serious business. :)

Nicely done. And it was cool to see the two of you guys work together on that. Congrats on getting her figured out, and thanks for posting it for everyone.
 

Gosmann

Sorceror
@ zagros, I also played on a perma death shard, it was so much fun, no overpowered chars and no "noobs" cause everybody could kill someone, also cant forget, how a friend of mine was killed, who played for a long time, big emotions there :)
 

Tarn Blackhail

Sorceror
being that i never officially released the one i ended up being happy with, i will post it here... reason being, i just made a very basic npc, its nothing more than a rewash of a wandering healer, but if you use the move method, it might come in handy... i wrote it for someone else who contacted me, and requested it for the move method..

Death.cs is the copy i finally rested upon... it is not as kind as Gosmann's, so fair warning, look at what its doing before you add it to your server. if you do not know, simply ask.

MasterofDeath.cs is the NPC, its a grim-reaper looking wandering healer, with a fixed name that you might find farmiliar...
 

Attachments

  • MasterofDeath.cs
    1.4 KB · Views: 13
  • death.cs
    1.7 KB · Views: 25

Fastburn

Sorceror
Osmann, you've made a awesome script here, it's almost exactly what I was looking for. I have noticed a few problems, and I'd like some help adjusting the script towards how I'm handling death on my shard. If you guys could help, it'd be a big help.

I've noticed a few things. When someone is knocked out, and then they regain consciousness, they retain their items, but they wake up naked. In addition, you are unable to loot their unconscious body. I'd like them to be able to be looted during their knock out period, after all it makes since for people to disarm someone while their unconscious after a fight.

I understand the core edit would take care of retaining items, but I wonder if there isn't a better way, at lest in my case. I believe the SelfLoot in Carve.CS (which allows you to collect belongings and auto-reequip in normal UO after resurrecting and double clicking your corpse) might be a better option as the other approach seems to make everything effectively blessed items. Would using the SelfLoot option allow people to loot the corpse during knockout?

Here's Corpse.CS; Look for Self Loot.
Code:
using System;
using System.Collections;
using System.Collections.Generic;
using Server;
using Server.ContextMenus;
using Server.Engines.PartySystem;
using Server.Engines.Quests;
using Server.Engines.Quests.Doom;
using Server.Engines.Quests.Haven;
using Server.Guilds;
using Server.Misc;
using Server.Mobiles;
using Server.Network;
 
namespace Server.Items
{
    public class Corpse : Container, ICarvable
    {
        private Mobile        m_Owner;                // Whos corpse is this?
        private Mobile        m_Killer;                // Who killed the owner?
        private bool        m_Carved;                // Has this corpse been carved?
 
        private List<Mobile>    m_Looters;                // Who's looted this corpse?
        private List<Item>        m_EquipItems;            // List of items equiped when the owner died. Ingame, these items display /on/ the corpse, not just inside
        private List<Mobile>    m_Aggressors;            // Anyone from this list will be able to loot this corpse; we attacked them, or they attacked us when we were freely attackable
 
        private string        m_CorpseName;            // Value of the CorpseNameAttribute attached to the owner when he died -or- null if the owner had no CorpseNameAttribute; use "the remains of ~name~"
        private bool        m_NoBones;                // If true, this corpse will not turn into bones
 
        private bool        m_VisitedByTaxidermist;    // Has this corpse yet been visited by a taxidermist?
        private bool        m_Channeled;            // Has this corpse yet been used to channel spiritual energy? (AOS Spirit Speak)
 
        // For notoriety:
        private AccessLevel    m_AccessLevel;            // Which AccessLevel the owner had when he died
        private Guild        m_Guild;                // Which Guild the owner was in when he died
        private int            m_Kills;                // How many kills the owner had when he died
        private bool        m_Criminal;                // Was the owner criminal when he died?
 
        private DateTime    m_TimeOfDeath;            // What time was this corpse created?
 
        private HairInfo m_Hair;                    // This contains the hair of the owner
        private FacialHairInfo m_FacialHair;        // This contains the facial hair of the owner
 
        public static readonly TimeSpan MonsterLootRightSacrifice = TimeSpan.FromMinutes( 2.0 );
 
        public static readonly TimeSpan InstancedCorpseTime = TimeSpan.FromMinutes( 3.0 );
 
        [CommandProperty( AccessLevel.GameMaster )]
        public virtual bool InstancedCorpse
        {
            get
            {
                if ( !Core.SE )
                    return false;
 
                return ( DateTime.Now > m_TimeOfDeath + InstancedCorpseTime );
            }
        }
 
        public override bool IsDecoContainer
        {
            get{ return false; }
        }
 
        private Dictionary<Mobile, List<Item>> m_InstancedItems;
 
        [CommandProperty( AccessLevel.GameMaster )]
        public DateTime TimeOfDeath
        {
            get{ return m_TimeOfDeath; }
            set{ m_TimeOfDeath = value; }
        }
 
        public override bool DisplayWeight { get { return false; } }
 
        public HairInfo Hair { get { return m_Hair; } }
        public FacialHairInfo FacialHair { get { return m_FacialHair; } }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public bool Carved
        {
            get{ return m_Carved; }
            set{ m_Carved = value; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public bool VisitedByTaxidermist
        {
            get{ return m_VisitedByTaxidermist; }
            set{ m_VisitedByTaxidermist = value; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public bool Channeled
        {
            get{ return m_Channeled; }
            set{ m_Channeled = value; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public AccessLevel AccessLevel
        {
            get{ return m_AccessLevel; }
        }
 
        public List<Mobile> Aggressors
        {
            get{ return m_Aggressors; }
        }
 
        public List<Mobile> Looters
        {
            get{ return m_Looters; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public Mobile Killer
        {
            get{ return m_Killer; }
        }
 
        public List<Item> EquipItems
        {
            get{ return m_EquipItems; }
        }
 
        public Guild Guild
        {
            get{ return m_Guild; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public int Kills
        {
            get{ return m_Kills; }
            set{ m_Kills = value; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public bool Criminal
        {
            get{ return m_Criminal; }
            set{ m_Criminal = value; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public Mobile Owner
        {
            get{ return m_Owner; }
        }
 
        public void TurnToBones()
        {
            if ( Deleted )
                return;
 
            ProcessDelta();
            SendRemovePacket();
            ItemID = Utility.Random( 0xECA, 9 ); // bone graphic
            Hue = 0;
 
       
            ProcessDelta();
 
            m_NoBones = true;
            BeginDecay( m_BoneDecayTime );
            MoveToWorld(new Point3D(300,620,21), Map.Tokuno);
        }
 
        private static TimeSpan m_DefaultDecayTime = TimeSpan.FromMinutes( 7.0 );
        private static TimeSpan m_BoneDecayTime = TimeSpan.FromMinutes( 7.0 );
 
        private Timer m_DecayTimer;
        private DateTime m_DecayTime;
 
        public void BeginDecay( TimeSpan delay )
        {
            if ( m_DecayTimer != null )
                m_DecayTimer.Stop();
 
            m_DecayTime = DateTime.Now + delay;
 
            m_DecayTimer = new InternalTimer( this, delay );
            m_DecayTimer.Start();
        }
 
        public override void OnAfterDelete()
        {
            if ( m_DecayTimer != null )
                m_DecayTimer.Stop();
 
            m_DecayTimer = null;
        }
 
        private class InternalTimer : Timer
        {
            private Corpse m_Corpse;
 
            public InternalTimer( Corpse c, TimeSpan delay ) : base( delay )
            {
                m_Corpse = c;
                Priority = TimerPriority.FiveSeconds;
            }
 
            protected override void OnTick()
            {
                if ( !m_Corpse.m_NoBones )
                    m_Corpse.TurnToBones();
                else
                    m_Corpse.Delete();
            }
        }
 
        public static string GetCorpseName( Mobile m )
        {
            Type t = m.GetType();
 
            object[] attrs = t.GetCustomAttributes( typeof( CorpseNameAttribute ), true );
 
            if ( attrs != null && attrs.Length > 0 )
            {
                CorpseNameAttribute attr = attrs[0] as CorpseNameAttribute;
 
                if ( attr != null )
                    return attr.Name;
            }
 
            return null;
        }
 
        public static void Initialize()
        {
            Mobile.CreateCorpseHandler += new CreateCorpseHandler( Mobile_CreateCorpseHandler );
        }
 
        public static Container Mobile_CreateCorpseHandler( Mobile owner, HairInfo hair, FacialHairInfo facialhair, List<Item> initialContent, List<Item> equipItems )
        {
            bool shouldFillCorpse = true;
 
            //if ( owner is BaseCreature )
            //    shouldFillCorpse = !((BaseCreature)owner).IsBonded;
 
            Corpse c;
            if( owner is MilitiaFighter )
                c = new MilitiaFighterCorpse( owner, hair, facialhair, shouldFillCorpse ? equipItems : new List<Item>() );
            else
                c = new Corpse( owner, hair, facialhair, shouldFillCorpse ? equipItems : new List<Item>() );
 
            owner.Corpse = c;
 
            if ( shouldFillCorpse )
            {
                for ( int i = 0; i < initialContent.Count; ++i )
                {
                    Item item = initialContent[i];
 
                    if ( Core.AOS && owner.Player && item.Parent == owner.Backpack )
                        c.AddItem( item );
                    else
                        c.DropItem( item );
 
                    if ( owner.Player && Core.AOS )
                        c.SetRestoreInfo( item, item.Location );
                }
            }
            else
            {
                c.Carved = true; // TODO: Is it needed?
            }
 
            Point3D loc = owner.Location;
            Map map = owner.Map;
 
            if ( map == null || map == Map.Internal )
            {
                loc = owner.LogoutLocation;
                map = owner.LogoutMap;
            }
 
            c.MoveToWorld( loc, map );
 
            return c;
        }
 
        public override bool IsPublicContainer{ get{ return true; } }
 
        public Corpse( Mobile owner, List<Item> equipItems ) : this( owner, null, null, equipItems )
        {
        }
 
        public Corpse( Mobile owner, HairInfo hair, FacialHairInfo facialhair, List<Item> equipItems )
            : base( 0x2006 )
        {
            // To supress console warnings, stackable must be true
            Stackable = true;
            Amount = owner.Body; // protocol defines that for itemid 0x2006, amount=body
            Stackable = false;
 
            Movable = false;
            Hue = owner.Hue;
            Direction = owner.Direction;
            Name = owner.Name;
 
            m_Owner = owner;
 
            m_CorpseName = GetCorpseName( owner );
 
            m_TimeOfDeath = DateTime.Now;
 
            m_AccessLevel = owner.AccessLevel;
            m_Guild = owner.Guild as Guild;
            m_Kills = owner.Kills;
            m_Criminal = owner.Criminal;
 
            m_Hair = hair;
            m_FacialHair = facialhair;
 
 
            // This corpse does not turn to bones if: the owner is not a player
            m_NoBones = !owner.Player;
 
            m_Looters = new List<Mobile>();
            m_EquipItems = equipItems;
 
            m_Aggressors = new List<Mobile>( owner.Aggressors.Count + owner.Aggressed.Count );
            bool addToAggressors = !( owner is BaseCreature );
 
            TimeSpan lastTime = TimeSpan.MaxValue;
 
            for ( int i = 0; i < owner.Aggressors.Count; ++i )
            {
                AggressorInfo info = owner.Aggressors[i];
 
                if ( (DateTime.Now - info.LastCombatTime) < lastTime )
                {
                    m_Killer = info.Attacker;
                    lastTime = (DateTime.Now - info.LastCombatTime);
                }
 
                if ( addToAggressors && !info.CriminalAggression )
                    m_Aggressors.Add( info.Attacker );
            }
 
            for ( int i = 0; i < owner.Aggressed.Count; ++i )
            {
                AggressorInfo info = owner.Aggressed[i];
 
                if ( (DateTime.Now - info.LastCombatTime) < lastTime )
                {
                    m_Killer = info.Defender;
                    lastTime = (DateTime.Now - info.LastCombatTime);
                }
 
                if ( addToAggressors )
                    m_Aggressors.Add( info.Defender );
            }
 
            if ( !addToAggressors )
            {
                BaseCreature bc = (BaseCreature)owner;
 
                Mobile master = bc.GetMaster();
                if( master != null )
                    m_Aggressors.Add( master );
 
                List<DamageStore> rights = BaseCreature.GetLootingRights( bc.DamageEntries, bc.HitsMax );
                for ( int i = 0; i < rights.Count; ++i )
                {
                    DamageStore ds = rights[i];
 
                    if ( ds.m_HasRight )
                        m_Aggressors.Add( ds.m_Mobile );
                }
            }
 
            BeginDecay( m_DefaultDecayTime );
        }
 
        private void AssignInstancedLoot()
        {
            if ( m_InstancedItems == null )
                m_InstancedItems = new Dictionary<Mobile, List<Item>>();
        }
 
        public Corpse( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 10 ); // version
 
            writer.WriteDeltaTime( m_TimeOfDeath );
 
            List<KeyValuePair<Item, Point3D>> list = ( m_RestoreTable == null ? null : new List<KeyValuePair<Item, Point3D>>( m_RestoreTable ) );
            int count = ( list == null ? 0 : list.Count );
 
            writer.Write( count );
 
            for ( int i = 0; i < count; ++i )
            {
                KeyValuePair<Item, Point3D> kvp = list[i];
                Item item = kvp.Key;
                Point3D loc = kvp.Value;
 
                writer.Write( item );
 
                if ( item.Location == loc )
                {
                    writer.Write( false );
                }
                else
                {
                    writer.Write( true );
                    writer.Write( loc );
                }
            }
 
            writer.Write( m_VisitedByTaxidermist );
 
            writer.Write( m_DecayTimer != null );
 
            if ( m_DecayTimer != null )
                writer.WriteDeltaTime( m_DecayTime );
 
            writer.Write( m_Looters );
            writer.Write( m_Killer );
 
            writer.Write( (bool) m_Carved );
 
            writer.Write( m_Aggressors );
 
            writer.Write( m_Owner );
 
            writer.Write( m_NoBones );
 
            writer.Write( (string) m_CorpseName );
 
            writer.Write( (int) m_AccessLevel );
            writer.Write( (Guild) m_Guild );
            writer.Write( (int) m_Kills );
            writer.Write( (bool) m_Criminal );
 
            writer.Write( m_EquipItems );
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            switch ( version )
            {
                case 10:
                {
                    m_TimeOfDeath = reader.ReadDeltaTime();
 
                    goto case 9;
                }
                case 9:
                {
                    int count = reader.ReadInt();
 
                    for ( int i = 0; i < count; ++i )
                    {
                        Item item = reader.ReadItem();
 
                        if ( reader.ReadBool() )
                            SetRestoreInfo( item, reader.ReadPoint3D() );
                        else if ( item != null )
                            SetRestoreInfo( item, item.Location );
                    }
 
                    goto case 8;
                }
                case 8:
                {
                    m_VisitedByTaxidermist = reader.ReadBool();
 
                    goto case 7;
                }
                case 7:
                {
                    if ( reader.ReadBool() )
                        BeginDecay( reader.ReadDeltaTime() - DateTime.Now );
 
                    goto case 6;
                }
                case 6:
                {
                    m_Looters = reader.ReadStrongMobileList();
                    m_Killer = reader.ReadMobile();
 
                    goto case 5;
                }
                case 5:
                {
                    m_Carved = reader.ReadBool();
 
                    goto case 4;
                }
                case 4:
                {
                    m_Aggressors = reader.ReadStrongMobileList();
 
                    goto case 3;
                }
                case 3:
                {
                    m_Owner = reader.ReadMobile();
 
                    goto case 2;
                }
                case 2:
                {
                    m_NoBones = reader.ReadBool();
 
                    goto case 1;
                }
                case 1:
                {
                    m_CorpseName = reader.ReadString();
 
                    goto case 0;
                }
                case 0:
                {
                    if ( version < 10 )
                        m_TimeOfDeath = DateTime.Now;
 
                    if ( version < 7 )
                        BeginDecay( m_DefaultDecayTime );
 
                    if ( version < 6 )
                        m_Looters = new List<Mobile>();
 
                    if ( version < 4 )
                        m_Aggressors = new List<Mobile>();
 
                    m_AccessLevel = (AccessLevel)reader.ReadInt();
                    reader.ReadInt(); // guild reserve
                    m_Kills = reader.ReadInt();
                    m_Criminal = reader.ReadBool();
 
                    m_EquipItems = reader.ReadStrongItemList();
 
                    break;
                }
            }
        }
 
        public override void SendInfoTo( NetState state, bool sendOplPacket )
        {
            base.SendInfoTo( state, sendOplPacket );
 
            if ( ItemID == 0x2006 )
            {
                state.Send( new CorpseContent( state.Mobile, this ) );
                state.Send( new CorpseEquip( state.Mobile, this ) );
            }
        }
 
        public bool IsCriminalAction( Mobile from )
        {
            if ( from == m_Owner || from.AccessLevel >= AccessLevel.GameMaster )
                return false;
 
            Party p = Party.Get( m_Owner );
 
            if ( p != null && p.Contains( from ) )
            {
                PartyMemberInfo pmi = p[m_Owner];
 
                if ( pmi != null && pmi.CanLoot )
                    return false;
            }
 
            return ( NotorietyHandlers.CorpseNotoriety( from, this ) == Notoriety.Innocent );
        }
 
        public override bool CheckItemUse( Mobile from, Item item )
        {
            if ( !base.CheckItemUse( from, item ) )
                return false;
 
            if ( item != this )
                return CanLoot( from, item );
 
            return true;
        }
 
        public override bool CheckLift( Mobile from, Item item, ref LRReason reject )
        {
            if ( !base.CheckLift( from, item, ref reject ) )
                return false;
 
            return CanLoot( from,item );
        }
 
        public override void OnItemUsed( Mobile from, Item item )
        {
            base.OnItemUsed( from, item );
 
            if ( from != m_Owner )
                from.RevealingAction();
 
            if ( item != this && IsCriminalAction( from ) )
                from.CriminalAction( true );
 
            if ( !m_Looters.Contains( from ) )
                m_Looters.Add( from );
        }
 
        public override void OnItemLifted( Mobile from, Item item )
        {
            base.OnItemLifted( from, item );
 
            if ( item != this && from != m_Owner )
                from.RevealingAction();
 
            if ( item != this && IsCriminalAction( from ) )
                from.CriminalAction( true );
 
            if ( !m_Looters.Contains( from ) )
                m_Looters.Add( from );
        }
 
        private class OpenCorpseEntry : ContextMenuEntry
        {
            public OpenCorpseEntry() : base( 6215, 2 )
            {
            }
 
            public override void OnClick()
            {
                Corpse corpse = Owner.Target as Corpse;
 
                if ( corpse != null && Owner.From.CheckAlive() )
                    corpse.Open( Owner.From, false );
            }
        }
 
        public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
        {
            base.GetContextMenuEntries( from, list );
 
            if ( Core.AOS && m_Owner == from && from.Alive )
                list.Add( new OpenCorpseEntry() );
        }
 
        private Dictionary<Item, Point3D> m_RestoreTable;
 
        public bool GetRestoreInfo( Item item, ref Point3D loc )
        {
            if ( m_RestoreTable == null || item == null )
                return false;
 
            return m_RestoreTable.TryGetValue( item, out loc );
        }
 
        public void SetRestoreInfo( Item item, Point3D loc )
        {
            if ( item == null )
                return;
 
            if ( m_RestoreTable == null )
                m_RestoreTable = new Dictionary<Item, Point3D>();
 
            m_RestoreTable[item] = loc;
        }
 
        public void ClearRestoreInfo( Item item )
        {
            if ( m_RestoreTable == null || item == null )
                return;
 
            m_RestoreTable.Remove( item );
 
            if ( m_RestoreTable.Count == 0 )
                m_RestoreTable = null;
        }
 
        public bool CanLoot( Mobile from, Item item )
        {
            if ( !IsCriminalAction( from ) )
                return true;
 
            Map map = this.Map;
 
            if ( map == null || (map.Rules & MapRules.HarmfulRestrictions) != 0 )
                return false;
 
            return true;
        }
 
        public bool CheckLoot( Mobile from, Item item )
        {
            if ( !CanLoot( from, item ) )
            {
                if ( m_Owner == null || !m_Owner.Player )
                    from.SendLocalizedMessage( 1005035 ); // You did not earn the right to loot this creature!
                else
                    from.SendLocalizedMessage( 1010049 ); // You may not loot this corpse.
 
                return false;
            }
            else if ( IsCriminalAction( from ) )
            {
                if ( m_Owner == null || !m_Owner.Player )
                    from.SendLocalizedMessage( 1005036 ); // Looting this monster corpse will be a criminal act!
                else
                    from.SendLocalizedMessage( 1005038 ); // Looting this corpse will be a criminal act!
            }
 
            return true;
        }
 
        public virtual void Open( Mobile from, bool checkSelfLoot )
        {
            if ( from.AccessLevel > AccessLevel.Player || from.InRange( this.GetWorldLocation(), 2 ) )
            {
 
                #region Self Looting
                bool selfLoot = ( checkSelfLoot && ( from == m_Owner ) );
 
                if ( selfLoot )
                {
                    List<Item> items = new List<Item>( this.Items );
 
                    bool gathered = false;
                    bool didntFit = false;
 
                    Container pack = from.Backpack;
 
                    bool checkRobe = true;
 
                    for ( int i = 0; !didntFit && i < items.Count; ++i )
                    {
                        Item item = items[i];
                        Point3D loc = item.Location;
 
                        if ( (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair) || !item.Movable || !GetRestoreInfo( item, ref loc ) )
                            continue;
 
                        if ( checkRobe )
                        {
                            DeathRobe robe = from.FindItemOnLayer( Layer.OuterTorso ) as DeathRobe;
 
                            if ( robe != null )
                            {
                                if ( Core.SE )
                                {
                                    robe.Delete();
                                }
                                else
                                {
                                    Map map = from.Map;
   
                                    if ( map != null && map != Map.Internal )
                                        robe.MoveToWorld( from.Location, map );
                                }
                            }
                        }
 
                        if ( m_EquipItems.Contains( item ) && from.EquipItem( item ) )
                        {
                            gathered = true;
                        }
                        else if ( pack != null && pack.CheckHold( from, item, false, true ) )
                        {
                            item.Location = loc;
                            pack.AddItem( item );
                            gathered = true;
                        }
                        else
                        {
                            didntFit = true;
                        }
                    }
 
                    if ( gathered && !didntFit )
                    {
                        m_Carved = true;
 
                        if ( ItemID == 0x2006 )
                        {
                            ProcessDelta();
                            SendRemovePacket();
                            ItemID = Utility.Random( 0xECA, 9 ); // bone graphic
                            Hue = 0;
                            ProcessDelta();
                        }
 
                        from.PlaySound( 0x3E3 );
                        from.SendLocalizedMessage( 1062471 ); // You quickly gather all of your belongings.
                        return;
                    }
 
                    if ( gathered && didntFit )
                        from.SendLocalizedMessage( 1062472 ); // You gather some of your belongings. The rest remain on the corpse.
                }
 
                #endregion
 
                if ( !CheckLoot( from, null ) )
                    return;
 
                #region Quests
                PlayerMobile player = from as PlayerMobile;
 
                if ( player != null )
                {
                    QuestSystem qs = player.Quest;
 
                    if ( qs is UzeraanTurmoilQuest )
                    {
                        GetDaemonBoneObjective obj = qs.FindObjective( typeof( GetDaemonBoneObjective ) ) as GetDaemonBoneObjective;
 
                        if ( obj != null && obj.CorpseWithBone == this && ( !obj.Completed || UzeraanTurmoilQuest.HasLostDaemonBone( player ) ) )
                        {
                            Item bone = new QuestDaemonBone();
 
                            if ( player.PlaceInBackpack( bone ) )
                            {
                                obj.CorpseWithBone = null;
                                player.SendLocalizedMessage( 1049341, "", 0x22 ); // You rummage through the bones and find a Daemon Bone!  You quickly place the item in your pack.
 
                                if ( !obj.Completed )
                                    obj.Complete();
                            }
                            else
                            {
                                bone.Delete();
                                player.SendLocalizedMessage( 1049342, "", 0x22 ); // Rummaging through the bones you find a Daemon Bone, but can't pick it up because your pack is too full.  Come back when you have more room in your pack.
                            }
 
                            return;
                        }
                    }
                    else if ( qs is TheSummoningQuest )
                    {
                        VanquishDaemonObjective obj = qs.FindObjective( typeof( VanquishDaemonObjective ) ) as VanquishDaemonObjective;
 
                        if ( obj != null && obj.Completed && obj.CorpseWithSkull == this )
                        {
                            GoldenSkull sk = new GoldenSkull();
 
                            if ( player.PlaceInBackpack( sk ) )
                            {
                                obj.CorpseWithSkull = null;
                                player.SendLocalizedMessage( 1050022 ); // For your valor in combating the devourer, you have been awarded a golden skull.
                                qs.Complete();
                            }
                            else
                            {
                                sk.Delete();
                                player.SendLocalizedMessage( 1050023 ); // You find a golden skull, but your backpack is too full to carry it.
                            }
                        }
                    }
                }
 
                #endregion
 
                base.OnDoubleClick( from );
 
                if ( from != m_Owner )
                    from.RevealingAction();
            }
            else
            {
                from.SendLocalizedMessage( 500446 ); // That is too far away.
                return;
            }
        }
 
        public override void OnDoubleClick( Mobile from )
        {
            Open( from, Core.AOS );
        }
 
        public override bool CheckContentDisplay( Mobile from )
        {
            return false;
        }
 
        public override bool DisplaysContent{ get{ return false; } }
 
        public override void AddNameProperty( ObjectPropertyList list )
        {
            if ( ItemID == 0x2006 ) // Corpse form
            {
                if ( m_CorpseName != null )
                    list.Add( m_CorpseName );
                else
                    list.Add( 1046414, this.Name ); // the remains of ~1_NAME~
            }
            else // Bone form
            {
                list.Add( 1046414, this.Name ); // the remains of ~1_NAME~
            }
        }
 
        public override void OnAosSingleClick( Mobile from )
        {
            int hue = Notoriety.GetHue( NotorietyHandlers.CorpseNotoriety( from, this ) );
            ObjectPropertyList opl = this.PropertyList;
 
            if ( opl.Header > 0 )
                from.Send( new MessageLocalized( Serial, ItemID, MessageType.Label, hue, 3, opl.Header, Name, opl.HeaderArgs ) );
        }
 
        public override void OnSingleClick( Mobile from )
        {
            int hue = Notoriety.GetHue( NotorietyHandlers.CorpseNotoriety( from, this ) );
 
            if ( ItemID == 0x2006 ) // Corpse form
            {
                if ( m_CorpseName != null )
                    from.Send( new AsciiMessage( Serial, ItemID, MessageType.Label, hue, 3, "", m_CorpseName ) );
                else
                    from.Send( new MessageLocalized( Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name ) );
            }
            else // Bone form
            {
                from.Send( new MessageLocalized( Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name ) );
            }
        }
 
        public void Carve( Mobile from, Item item  )
        {
            if ( IsCriminalAction( from ) && this.Map != null && (this.Map.Rules & MapRules.HarmfulRestrictions) != 0 )
            {
                if ( m_Owner == null || !m_Owner.Player )
                    from.SendLocalizedMessage( 1005035 ); // You did not earn the right to loot this creature!
                else
                    from.SendLocalizedMessage( 1010049 ); // You may not loot this corpse.
 
                return;
            }
 
            Mobile dead = m_Owner;
 
            if ( m_Carved || dead == null )
            {
                from.SendLocalizedMessage( 500485 ); // You see nothing useful to carve from the corpse.
            }
            else if ( ((Body)Amount).IsHuman && ItemID == 0x2006 )
            {
                new Blood( 0x122D ).MoveToWorld( Location, Map );
 
                new Torso().MoveToWorld( Location, Map );
                new LeftLeg().MoveToWorld( Location, Map );
                new LeftArm().MoveToWorld( Location, Map );
                new RightLeg().MoveToWorld( Location, Map );
                new RightArm().MoveToWorld( Location, Map );
                new Head( dead.Name ).MoveToWorld( Location, Map );
 
                m_Carved = true;
 
                ProcessDelta();
                SendRemovePacket();
                ItemID = Utility.Random( 0xECA, 9 ); // bone graphic
                Hue = 0;
                ProcessDelta();
 
                //if ( IsCriminalAction( from ) )
                //    from.CriminalAction( true );
            }
            else if ( dead is BaseCreature )
            {
                ((BaseCreature)dead).OnCarve( from, this );
            }
            else
            {
                from.SendLocalizedMessage( 500485 ); // You see nothing useful to carve from the corpse.
            }
        }
    }
}

Now, another change I need some help on is how the script handles 'Permadeath', instead of deleting players. I have made it so it moves the dead player to a afterlife area, however when they resurrect in the dead area, it still deletes their corpse where they died, and leaves the items they have on them.

I'm fairly sure if the Looting/SelfLooting/Remain Equip question will handle why they keep their items but is there a fairly simple way of disabling the delete on resurrect on this particular part of the system, I'd be fine if they didn't even resurrect in the dead area, my staff can take care of that.

Also, I've notice that the dead.SendMessage("You have been knocked out")" on line 85 and 90 in the script do not seem to show no matter how I tested the script.

Any help you guys can provide be would be awesome, I can post my edits to the PD script but they are mostly just moving a PD'd player.
 

Renato

Wanderer
I would kindly love a solution for the loot problem aswel, this script is perfect, even with waking up naked, it would just be really nifty if the person could be looted, the way it is player looting is inexistent,
 

Renato

Wanderer
Ok, now I'm having another trouble, for some reason, I can loot.
(I added the script and changed the PlayerMobile.cs)

But when the char returns to concience every item in his bag is gone.

I can't figure this out anymore.

If the script would NOT delete the corpse after the ress, that would work.

Just to make things clear:

I installed the script and made the changes to PlayerMobile.cs

Then I couldnt loot and woke up naked with the items.

Then I made some changes, tried Tarn script, etc, but ended up reverting back to PermaDeath.cs and PlayerMobile.cs (modified) and now i CAN loot but wake up without my items.

And yes, I deleted Tarn scripts.
 

Renato

Wanderer
Osmann, you've made a awesome script here, it's almost exactly what I was looking for. I have noticed a few problems, and I'd like some help adjusting the script towards how I'm handling death on my shard. If you guys could help, it'd be a big help.

I've noticed a few things. When someone is knocked out, and then they regain consciousness, they retain their items, but they wake up naked. In addition, you are unable to loot their unconscious body. I'd like them to be able to be looted during their knock out period, after all it makes since for people to disarm someone while their unconscious after a fight.

I understand the core edit would take care of retaining items, but I wonder if there isn't a better way, at lest in my case. I believe the SelfLoot in Carve.CS (which allows you to collect belongings and auto-reequip in normal UO after resurrecting and double clicking your corpse) might be a better option as the other approach seems to make everything effectively blessed items. Would using the SelfLoot option allow people to loot the corpse during knockout?

Here's Corpse.CS; Look for Self Loot.
Code:
using System;
using System.Collections;
using System.Collections.Generic;
using Server;
using Server.ContextMenus;
using Server.Engines.PartySystem;
using Server.Engines.Quests;
using Server.Engines.Quests.Doom;
using Server.Engines.Quests.Haven;
using Server.Guilds;
using Server.Misc;
using Server.Mobiles;
using Server.Network;
 
namespace Server.Items
{
    public class Corpse : Container, ICarvable
    {
        private Mobile        m_Owner;                // Whos corpse is this?
        private Mobile        m_Killer;                // Who killed the owner?
        private bool        m_Carved;                // Has this corpse been carved?
 
        private List<Mobile>    m_Looters;                // Who's looted this corpse?
        private List<Item>        m_EquipItems;            // List of items equiped when the owner died. Ingame, these items display /on/ the corpse, not just inside
        private List<Mobile>    m_Aggressors;            // Anyone from this list will be able to loot this corpse; we attacked them, or they attacked us when we were freely attackable
 
        private string        m_CorpseName;            // Value of the CorpseNameAttribute attached to the owner when he died -or- null if the owner had no CorpseNameAttribute; use "the remains of ~name~"
        private bool        m_NoBones;                // If true, this corpse will not turn into bones
 
        private bool        m_VisitedByTaxidermist;    // Has this corpse yet been visited by a taxidermist?
        private bool        m_Channeled;            // Has this corpse yet been used to channel spiritual energy? (AOS Spirit Speak)
 
        // For notoriety:
        private AccessLevel    m_AccessLevel;            // Which AccessLevel the owner had when he died
        private Guild        m_Guild;                // Which Guild the owner was in when he died
        private int            m_Kills;                // How many kills the owner had when he died
        private bool        m_Criminal;                // Was the owner criminal when he died?
 
        private DateTime    m_TimeOfDeath;            // What time was this corpse created?
 
        private HairInfo m_Hair;                    // This contains the hair of the owner
        private FacialHairInfo m_FacialHair;        // This contains the facial hair of the owner
 
        public static readonly TimeSpan MonsterLootRightSacrifice = TimeSpan.FromMinutes( 2.0 );
 
        public static readonly TimeSpan InstancedCorpseTime = TimeSpan.FromMinutes( 3.0 );
 
        [CommandProperty( AccessLevel.GameMaster )]
        public virtual bool InstancedCorpse
        {
            get
            {
                if ( !Core.SE )
                    return false;
 
                return ( DateTime.Now > m_TimeOfDeath + InstancedCorpseTime );
            }
        }
 
        public override bool IsDecoContainer
        {
            get{ return false; }
        }
 
        private Dictionary<Mobile, List<Item>> m_InstancedItems;
 
        [CommandProperty( AccessLevel.GameMaster )]
        public DateTime TimeOfDeath
        {
            get{ return m_TimeOfDeath; }
            set{ m_TimeOfDeath = value; }
        }
 
        public override bool DisplayWeight { get { return false; } }
 
        public HairInfo Hair { get { return m_Hair; } }
        public FacialHairInfo FacialHair { get { return m_FacialHair; } }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public bool Carved
        {
            get{ return m_Carved; }
            set{ m_Carved = value; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public bool VisitedByTaxidermist
        {
            get{ return m_VisitedByTaxidermist; }
            set{ m_VisitedByTaxidermist = value; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public bool Channeled
        {
            get{ return m_Channeled; }
            set{ m_Channeled = value; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public AccessLevel AccessLevel
        {
            get{ return m_AccessLevel; }
        }
 
        public List<Mobile> Aggressors
        {
            get{ return m_Aggressors; }
        }
 
        public List<Mobile> Looters
        {
            get{ return m_Looters; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public Mobile Killer
        {
            get{ return m_Killer; }
        }
 
        public List<Item> EquipItems
        {
            get{ return m_EquipItems; }
        }
 
        public Guild Guild
        {
            get{ return m_Guild; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public int Kills
        {
            get{ return m_Kills; }
            set{ m_Kills = value; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public bool Criminal
        {
            get{ return m_Criminal; }
            set{ m_Criminal = value; }
        }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public Mobile Owner
        {
            get{ return m_Owner; }
        }
 
        public void TurnToBones()
        {
            if ( Deleted )
                return;
 
            ProcessDelta();
            SendRemovePacket();
            ItemID = Utility.Random( 0xECA, 9 ); // bone graphic
            Hue = 0;
 
     
            ProcessDelta();
 
            m_NoBones = true;
            BeginDecay( m_BoneDecayTime );
            MoveToWorld(new Point3D(300,620,21), Map.Tokuno);
        }
 
        private static TimeSpan m_DefaultDecayTime = TimeSpan.FromMinutes( 7.0 );
        private static TimeSpan m_BoneDecayTime = TimeSpan.FromMinutes( 7.0 );
 
        private Timer m_DecayTimer;
        private DateTime m_DecayTime;
 
        public void BeginDecay( TimeSpan delay )
        {
            if ( m_DecayTimer != null )
                m_DecayTimer.Stop();
 
            m_DecayTime = DateTime.Now + delay;
 
            m_DecayTimer = new InternalTimer( this, delay );
            m_DecayTimer.Start();
        }
 
        public override void OnAfterDelete()
        {
            if ( m_DecayTimer != null )
                m_DecayTimer.Stop();
 
            m_DecayTimer = null;
        }
 
        private class InternalTimer : Timer
        {
            private Corpse m_Corpse;
 
            public InternalTimer( Corpse c, TimeSpan delay ) : base( delay )
            {
                m_Corpse = c;
                Priority = TimerPriority.FiveSeconds;
            }
 
            protected override void OnTick()
            {
                if ( !m_Corpse.m_NoBones )
                    m_Corpse.TurnToBones();
                else
                    m_Corpse.Delete();
            }
        }
 
        public static string GetCorpseName( Mobile m )
        {
            Type t = m.GetType();
 
            object[] attrs = t.GetCustomAttributes( typeof( CorpseNameAttribute ), true );
 
            if ( attrs != null && attrs.Length > 0 )
            {
                CorpseNameAttribute attr = attrs[0] as CorpseNameAttribute;
 
                if ( attr != null )
                    return attr.Name;
            }
 
            return null;
        }
 
        public static void Initialize()
        {
            Mobile.CreateCorpseHandler += new CreateCorpseHandler( Mobile_CreateCorpseHandler );
        }
 
        public static Container Mobile_CreateCorpseHandler( Mobile owner, HairInfo hair, FacialHairInfo facialhair, List<Item> initialContent, List<Item> equipItems )
        {
            bool shouldFillCorpse = true;
 
            //if ( owner is BaseCreature )
            //    shouldFillCorpse = !((BaseCreature)owner).IsBonded;
 
            Corpse c;
            if( owner is MilitiaFighter )
                c = new MilitiaFighterCorpse( owner, hair, facialhair, shouldFillCorpse ? equipItems : new List<Item>() );
            else
                c = new Corpse( owner, hair, facialhair, shouldFillCorpse ? equipItems : new List<Item>() );
 
            owner.Corpse = c;
 
            if ( shouldFillCorpse )
            {
                for ( int i = 0; i < initialContent.Count; ++i )
                {
                    Item item = initialContent[i];
 
                    if ( Core.AOS && owner.Player && item.Parent == owner.Backpack )
                        c.AddItem( item );
                    else
                        c.DropItem( item );
 
                    if ( owner.Player && Core.AOS )
                        c.SetRestoreInfo( item, item.Location );
                }
            }
            else
            {
                c.Carved = true; // TODO: Is it needed?
            }
 
            Point3D loc = owner.Location;
            Map map = owner.Map;
 
            if ( map == null || map == Map.Internal )
            {
                loc = owner.LogoutLocation;
                map = owner.LogoutMap;
            }
 
            c.MoveToWorld( loc, map );
 
            return c;
        }
 
        public override bool IsPublicContainer{ get{ return true; } }
 
        public Corpse( Mobile owner, List<Item> equipItems ) : this( owner, null, null, equipItems )
        {
        }
 
        public Corpse( Mobile owner, HairInfo hair, FacialHairInfo facialhair, List<Item> equipItems )
            : base( 0x2006 )
        {
            // To supress console warnings, stackable must be true
            Stackable = true;
            Amount = owner.Body; // protocol defines that for itemid 0x2006, amount=body
            Stackable = false;
 
            Movable = false;
            Hue = owner.Hue;
            Direction = owner.Direction;
            Name = owner.Name;
 
            m_Owner = owner;
 
            m_CorpseName = GetCorpseName( owner );
 
            m_TimeOfDeath = DateTime.Now;
 
            m_AccessLevel = owner.AccessLevel;
            m_Guild = owner.Guild as Guild;
            m_Kills = owner.Kills;
            m_Criminal = owner.Criminal;
 
            m_Hair = hair;
            m_FacialHair = facialhair;
 
 
            // This corpse does not turn to bones if: the owner is not a player
            m_NoBones = !owner.Player;
 
            m_Looters = new List<Mobile>();
            m_EquipItems = equipItems;
 
            m_Aggressors = new List<Mobile>( owner.Aggressors.Count + owner.Aggressed.Count );
            bool addToAggressors = !( owner is BaseCreature );
 
            TimeSpan lastTime = TimeSpan.MaxValue;
 
            for ( int i = 0; i < owner.Aggressors.Count; ++i )
            {
                AggressorInfo info = owner.Aggressors[i];
 
                if ( (DateTime.Now - info.LastCombatTime) < lastTime )
                {
                    m_Killer = info.Attacker;
                    lastTime = (DateTime.Now - info.LastCombatTime);
                }
 
                if ( addToAggressors && !info.CriminalAggression )
                    m_Aggressors.Add( info.Attacker );
            }
 
            for ( int i = 0; i < owner.Aggressed.Count; ++i )
            {
                AggressorInfo info = owner.Aggressed[i];
 
                if ( (DateTime.Now - info.LastCombatTime) < lastTime )
                {
                    m_Killer = info.Defender;
                    lastTime = (DateTime.Now - info.LastCombatTime);
                }
 
                if ( addToAggressors )
                    m_Aggressors.Add( info.Defender );
            }
 
            if ( !addToAggressors )
            {
                BaseCreature bc = (BaseCreature)owner;
 
                Mobile master = bc.GetMaster();
                if( master != null )
                    m_Aggressors.Add( master );
 
                List<DamageStore> rights = BaseCreature.GetLootingRights( bc.DamageEntries, bc.HitsMax );
                for ( int i = 0; i < rights.Count; ++i )
                {
                    DamageStore ds = rights[i];
 
                    if ( ds.m_HasRight )
                        m_Aggressors.Add( ds.m_Mobile );
                }
            }
 
            BeginDecay( m_DefaultDecayTime );
        }
 
        private void AssignInstancedLoot()
        {
            if ( m_InstancedItems == null )
                m_InstancedItems = new Dictionary<Mobile, List<Item>>();
        }
 
        public Corpse( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 10 ); // version
 
            writer.WriteDeltaTime( m_TimeOfDeath );
 
            List<KeyValuePair<Item, Point3D>> list = ( m_RestoreTable == null ? null : new List<KeyValuePair<Item, Point3D>>( m_RestoreTable ) );
            int count = ( list == null ? 0 : list.Count );
 
            writer.Write( count );
 
            for ( int i = 0; i < count; ++i )
            {
                KeyValuePair<Item, Point3D> kvp = list[i];
                Item item = kvp.Key;
                Point3D loc = kvp.Value;
 
                writer.Write( item );
 
                if ( item.Location == loc )
                {
                    writer.Write( false );
                }
                else
                {
                    writer.Write( true );
                    writer.Write( loc );
                }
            }
 
            writer.Write( m_VisitedByTaxidermist );
 
            writer.Write( m_DecayTimer != null );
 
            if ( m_DecayTimer != null )
                writer.WriteDeltaTime( m_DecayTime );
 
            writer.Write( m_Looters );
            writer.Write( m_Killer );
 
            writer.Write( (bool) m_Carved );
 
            writer.Write( m_Aggressors );
 
            writer.Write( m_Owner );
 
            writer.Write( m_NoBones );
 
            writer.Write( (string) m_CorpseName );
 
            writer.Write( (int) m_AccessLevel );
            writer.Write( (Guild) m_Guild );
            writer.Write( (int) m_Kills );
            writer.Write( (bool) m_Criminal );
 
            writer.Write( m_EquipItems );
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            switch ( version )
            {
                case 10:
                {
                    m_TimeOfDeath = reader.ReadDeltaTime();
 
                    goto case 9;
                }
                case 9:
                {
                    int count = reader.ReadInt();
 
                    for ( int i = 0; i < count; ++i )
                    {
                        Item item = reader.ReadItem();
 
                        if ( reader.ReadBool() )
                            SetRestoreInfo( item, reader.ReadPoint3D() );
                        else if ( item != null )
                            SetRestoreInfo( item, item.Location );
                    }
 
                    goto case 8;
                }
                case 8:
                {
                    m_VisitedByTaxidermist = reader.ReadBool();
 
                    goto case 7;
                }
                case 7:
                {
                    if ( reader.ReadBool() )
                        BeginDecay( reader.ReadDeltaTime() - DateTime.Now );
 
                    goto case 6;
                }
                case 6:
                {
                    m_Looters = reader.ReadStrongMobileList();
                    m_Killer = reader.ReadMobile();
 
                    goto case 5;
                }
                case 5:
                {
                    m_Carved = reader.ReadBool();
 
                    goto case 4;
                }
                case 4:
                {
                    m_Aggressors = reader.ReadStrongMobileList();
 
                    goto case 3;
                }
                case 3:
                {
                    m_Owner = reader.ReadMobile();
 
                    goto case 2;
                }
                case 2:
                {
                    m_NoBones = reader.ReadBool();
 
                    goto case 1;
                }
                case 1:
                {
                    m_CorpseName = reader.ReadString();
 
                    goto case 0;
                }
                case 0:
                {
                    if ( version < 10 )
                        m_TimeOfDeath = DateTime.Now;
 
                    if ( version < 7 )
                        BeginDecay( m_DefaultDecayTime );
 
                    if ( version < 6 )
                        m_Looters = new List<Mobile>();
 
                    if ( version < 4 )
                        m_Aggressors = new List<Mobile>();
 
                    m_AccessLevel = (AccessLevel)reader.ReadInt();
                    reader.ReadInt(); // guild reserve
                    m_Kills = reader.ReadInt();
                    m_Criminal = reader.ReadBool();
 
                    m_EquipItems = reader.ReadStrongItemList();
 
                    break;
                }
            }
        }
 
        public override void SendInfoTo( NetState state, bool sendOplPacket )
        {
            base.SendInfoTo( state, sendOplPacket );
 
            if ( ItemID == 0x2006 )
            {
                state.Send( new CorpseContent( state.Mobile, this ) );
                state.Send( new CorpseEquip( state.Mobile, this ) );
            }
        }
 
        public bool IsCriminalAction( Mobile from )
        {
            if ( from == m_Owner || from.AccessLevel >= AccessLevel.GameMaster )
                return false;
 
            Party p = Party.Get( m_Owner );
 
            if ( p != null && p.Contains( from ) )
            {
                PartyMemberInfo pmi = p[m_Owner];
 
                if ( pmi != null && pmi.CanLoot )
                    return false;
            }
 
            return ( NotorietyHandlers.CorpseNotoriety( from, this ) == Notoriety.Innocent );
        }
 
        public override bool CheckItemUse( Mobile from, Item item )
        {
            if ( !base.CheckItemUse( from, item ) )
                return false;
 
            if ( item != this )
                return CanLoot( from, item );
 
            return true;
        }
 
        public override bool CheckLift( Mobile from, Item item, ref LRReason reject )
        {
            if ( !base.CheckLift( from, item, ref reject ) )
                return false;
 
            return CanLoot( from,item );
        }
 
        public override void OnItemUsed( Mobile from, Item item )
        {
            base.OnItemUsed( from, item );
 
            if ( from != m_Owner )
                from.RevealingAction();
 
            if ( item != this && IsCriminalAction( from ) )
                from.CriminalAction( true );
 
            if ( !m_Looters.Contains( from ) )
                m_Looters.Add( from );
        }
 
        public override void OnItemLifted( Mobile from, Item item )
        {
            base.OnItemLifted( from, item );
 
            if ( item != this && from != m_Owner )
                from.RevealingAction();
 
            if ( item != this && IsCriminalAction( from ) )
                from.CriminalAction( true );
 
            if ( !m_Looters.Contains( from ) )
                m_Looters.Add( from );
        }
 
        private class OpenCorpseEntry : ContextMenuEntry
        {
            public OpenCorpseEntry() : base( 6215, 2 )
            {
            }
 
            public override void OnClick()
            {
                Corpse corpse = Owner.Target as Corpse;
 
                if ( corpse != null && Owner.From.CheckAlive() )
                    corpse.Open( Owner.From, false );
            }
        }
 
        public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
        {
            base.GetContextMenuEntries( from, list );
 
            if ( Core.AOS && m_Owner == from && from.Alive )
                list.Add( new OpenCorpseEntry() );
        }
 
        private Dictionary<Item, Point3D> m_RestoreTable;
 
        public bool GetRestoreInfo( Item item, ref Point3D loc )
        {
            if ( m_RestoreTable == null || item == null )
                return false;
 
            return m_RestoreTable.TryGetValue( item, out loc );
        }
 
        public void SetRestoreInfo( Item item, Point3D loc )
        {
            if ( item == null )
                return;
 
            if ( m_RestoreTable == null )
                m_RestoreTable = new Dictionary<Item, Point3D>();
 
            m_RestoreTable[item] = loc;
        }
 
        public void ClearRestoreInfo( Item item )
        {
            if ( m_RestoreTable == null || item == null )
                return;
 
            m_RestoreTable.Remove( item );
 
            if ( m_RestoreTable.Count == 0 )
                m_RestoreTable = null;
        }
 
        public bool CanLoot( Mobile from, Item item )
        {
            if ( !IsCriminalAction( from ) )
                return true;
 
            Map map = this.Map;
 
            if ( map == null || (map.Rules & MapRules.HarmfulRestrictions) != 0 )
                return false;
 
            return true;
        }
 
        public bool CheckLoot( Mobile from, Item item )
        {
            if ( !CanLoot( from, item ) )
            {
                if ( m_Owner == null || !m_Owner.Player )
                    from.SendLocalizedMessage( 1005035 ); // You did not earn the right to loot this creature!
                else
                    from.SendLocalizedMessage( 1010049 ); // You may not loot this corpse.
 
                return false;
            }
            else if ( IsCriminalAction( from ) )
            {
                if ( m_Owner == null || !m_Owner.Player )
                    from.SendLocalizedMessage( 1005036 ); // Looting this monster corpse will be a criminal act!
                else
                    from.SendLocalizedMessage( 1005038 ); // Looting this corpse will be a criminal act!
            }
 
            return true;
        }
 
        public virtual void Open( Mobile from, bool checkSelfLoot )
        {
            if ( from.AccessLevel > AccessLevel.Player || from.InRange( this.GetWorldLocation(), 2 ) )
            {
 
                #region Self Looting
                bool selfLoot = ( checkSelfLoot && ( from == m_Owner ) );
 
                if ( selfLoot )
                {
                    List<Item> items = new List<Item>( this.Items );
 
                    bool gathered = false;
                    bool didntFit = false;
 
                    Container pack = from.Backpack;
 
                    bool checkRobe = true;
 
                    for ( int i = 0; !didntFit && i < items.Count; ++i )
                    {
                        Item item = items[i];
                        Point3D loc = item.Location;
 
                        if ( (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair) || !item.Movable || !GetRestoreInfo( item, ref loc ) )
                            continue;
 
                        if ( checkRobe )
                        {
                            DeathRobe robe = from.FindItemOnLayer( Layer.OuterTorso ) as DeathRobe;
 
                            if ( robe != null )
                            {
                                if ( Core.SE )
                                {
                                    robe.Delete();
                                }
                                else
                                {
                                    Map map = from.Map;
 
                                    if ( map != null && map != Map.Internal )
                                        robe.MoveToWorld( from.Location, map );
                                }
                            }
                        }
 
                        if ( m_EquipItems.Contains( item ) && from.EquipItem( item ) )
                        {
                            gathered = true;
                        }
                        else if ( pack != null && pack.CheckHold( from, item, false, true ) )
                        {
                            item.Location = loc;
                            pack.AddItem( item );
                            gathered = true;
                        }
                        else
                        {
                            didntFit = true;
                        }
                    }
 
                    if ( gathered && !didntFit )
                    {
                        m_Carved = true;
 
                        if ( ItemID == 0x2006 )
                        {
                            ProcessDelta();
                            SendRemovePacket();
                            ItemID = Utility.Random( 0xECA, 9 ); // bone graphic
                            Hue = 0;
                            ProcessDelta();
                        }
 
                        from.PlaySound( 0x3E3 );
                        from.SendLocalizedMessage( 1062471 ); // You quickly gather all of your belongings.
                        return;
                    }
 
                    if ( gathered && didntFit )
                        from.SendLocalizedMessage( 1062472 ); // You gather some of your belongings. The rest remain on the corpse.
                }
 
                #endregion
 
                if ( !CheckLoot( from, null ) )
                    return;
 
                #region Quests
                PlayerMobile player = from as PlayerMobile;
 
                if ( player != null )
                {
                    QuestSystem qs = player.Quest;
 
                    if ( qs is UzeraanTurmoilQuest )
                    {
                        GetDaemonBoneObjective obj = qs.FindObjective( typeof( GetDaemonBoneObjective ) ) as GetDaemonBoneObjective;
 
                        if ( obj != null && obj.CorpseWithBone == this && ( !obj.Completed || UzeraanTurmoilQuest.HasLostDaemonBone( player ) ) )
                        {
                            Item bone = new QuestDaemonBone();
 
                            if ( player.PlaceInBackpack( bone ) )
                            {
                                obj.CorpseWithBone = null;
                                player.SendLocalizedMessage( 1049341, "", 0x22 ); // You rummage through the bones and find a Daemon Bone!  You quickly place the item in your pack.
 
                                if ( !obj.Completed )
                                    obj.Complete();
                            }
                            else
                            {
                                bone.Delete();
                                player.SendLocalizedMessage( 1049342, "", 0x22 ); // Rummaging through the bones you find a Daemon Bone, but can't pick it up because your pack is too full.  Come back when you have more room in your pack.
                            }
 
                            return;
                        }
                    }
                    else if ( qs is TheSummoningQuest )
                    {
                        VanquishDaemonObjective obj = qs.FindObjective( typeof( VanquishDaemonObjective ) ) as VanquishDaemonObjective;
 
                        if ( obj != null && obj.Completed && obj.CorpseWithSkull == this )
                        {
                            GoldenSkull sk = new GoldenSkull();
 
                            if ( player.PlaceInBackpack( sk ) )
                            {
                                obj.CorpseWithSkull = null;
                                player.SendLocalizedMessage( 1050022 ); // For your valor in combating the devourer, you have been awarded a golden skull.
                                qs.Complete();
                            }
                            else
                            {
                                sk.Delete();
                                player.SendLocalizedMessage( 1050023 ); // You find a golden skull, but your backpack is too full to carry it.
                            }
                        }
                    }
                }
 
                #endregion
 
                base.OnDoubleClick( from );
 
                if ( from != m_Owner )
                    from.RevealingAction();
            }
            else
            {
                from.SendLocalizedMessage( 500446 ); // That is too far away.
                return;
            }
        }
 
        public override void OnDoubleClick( Mobile from )
        {
            Open( from, Core.AOS );
        }
 
        public override bool CheckContentDisplay( Mobile from )
        {
            return false;
        }
 
        public override bool DisplaysContent{ get{ return false; } }
 
        public override void AddNameProperty( ObjectPropertyList list )
        {
            if ( ItemID == 0x2006 ) // Corpse form
            {
                if ( m_CorpseName != null )
                    list.Add( m_CorpseName );
                else
                    list.Add( 1046414, this.Name ); // the remains of ~1_NAME~
            }
            else // Bone form
            {
                list.Add( 1046414, this.Name ); // the remains of ~1_NAME~
            }
        }
 
        public override void OnAosSingleClick( Mobile from )
        {
            int hue = Notoriety.GetHue( NotorietyHandlers.CorpseNotoriety( from, this ) );
            ObjectPropertyList opl = this.PropertyList;
 
            if ( opl.Header > 0 )
                from.Send( new MessageLocalized( Serial, ItemID, MessageType.Label, hue, 3, opl.Header, Name, opl.HeaderArgs ) );
        }
 
        public override void OnSingleClick( Mobile from )
        {
            int hue = Notoriety.GetHue( NotorietyHandlers.CorpseNotoriety( from, this ) );
 
            if ( ItemID == 0x2006 ) // Corpse form
            {
                if ( m_CorpseName != null )
                    from.Send( new AsciiMessage( Serial, ItemID, MessageType.Label, hue, 3, "", m_CorpseName ) );
                else
                    from.Send( new MessageLocalized( Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name ) );
            }
            else // Bone form
            {
                from.Send( new MessageLocalized( Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name ) );
            }
        }
 
        public void Carve( Mobile from, Item item  )
        {
            if ( IsCriminalAction( from ) && this.Map != null && (this.Map.Rules & MapRules.HarmfulRestrictions) != 0 )
            {
                if ( m_Owner == null || !m_Owner.Player )
                    from.SendLocalizedMessage( 1005035 ); // You did not earn the right to loot this creature!
                else
                    from.SendLocalizedMessage( 1010049 ); // You may not loot this corpse.
 
                return;
            }
 
            Mobile dead = m_Owner;
 
            if ( m_Carved || dead == null )
            {
                from.SendLocalizedMessage( 500485 ); // You see nothing useful to carve from the corpse.
            }
            else if ( ((Body)Amount).IsHuman && ItemID == 0x2006 )
            {
                new Blood( 0x122D ).MoveToWorld( Location, Map );
 
                new Torso().MoveToWorld( Location, Map );
                new LeftLeg().MoveToWorld( Location, Map );
                new LeftArm().MoveToWorld( Location, Map );
                new RightLeg().MoveToWorld( Location, Map );
                new RightArm().MoveToWorld( Location, Map );
                new Head( dead.Name ).MoveToWorld( Location, Map );
 
                m_Carved = true;
 
                ProcessDelta();
                SendRemovePacket();
                ItemID = Utility.Random( 0xECA, 9 ); // bone graphic
                Hue = 0;
                ProcessDelta();
 
                //if ( IsCriminalAction( from ) )
                //    from.CriminalAction( true );
            }
            else if ( dead is BaseCreature )
            {
                ((BaseCreature)dead).OnCarve( from, this );
            }
            else
            {
                from.SendLocalizedMessage( 500485 ); // You see nothing useful to carve from the corpse.
            }
        }
    }
}

Now, another change I need some help on is how the script handles 'Permadeath', instead of deleting players. I have made it so it moves the dead player to a afterlife area, however when they resurrect in the dead area, it still deletes their corpse where they died, and leaves the items they have on them.

I'm fairly sure if the Looting/SelfLooting/Remain Equip question will handle why they keep their items but is there a fairly simple way of disabling the delete on resurrect on this particular part of the system, I'd be fine if they didn't even resurrect in the dead area, my staff can take care of that.

Also, I've notice that the dead.SendMessage("You have been knocked out")" on line 85 and 90 in the script do not seem to show no matter how I tested the script.

Any help you guys can provide be would be awesome, I can post my edits to the PD script but they are mostly just moving a PD'd player.

I'm sorry to bump this thread even further, but I remain as I were, I did a clean RunUO install and applied the changes in this topic and still got: Able to loot, wake up and inventory is gone.

But I think you are onto something here. Maybe permadeath can be dealth with just teleporting the character to a "jail" kind of limbo, with a stone that he could use to delete his char. (In case the shard has a 1 char limit).
That would provide a way to un-perma-death somebody in emergency...

Yeah I think that would turn as a lot of Pages, but on a small shard I think that would be no problem.

Anyway, cheers!
 

Gosmann

Sorceror
hi renato, I see your problem here, but right now I do my exams and got no time, just checkin' the forum over time :(
I will have a look/rework this script after I get my life back^^
sorry, but maybe someone else could help you till I'm back
 

Renato

Wanderer
No problem Grosmann,

When you get you life back, hit me up so we can share ideas on this coding, I'm very enthusiastic about this system.

And thanks for the headsup!
 

Fastburn

Sorceror
Renato, during my tests using the Playermobile.cs edit I was able to resurrect with items, via monsters or perma death via player. As I mentioned before, my personal hope is to have the items remain on the corpse, and in permadeath, on the bones. It seems the script is deleting the body in both cases on resurrect, and relying on the core-edit to keep the items effectively blessed. I think you and I are on very much the same track here. I'm too much a neophyte as a programmer to be able to accomplish the SelfLoot command by myself, but I have seen a shard do something almost exactly like this, using that feature for the non-permadeath 'wake ups'.

As far as the Permadeath being a limbo area, I've already accomplished this with only a few tweaks to the code. However, as I pointed out, the item issue causes problems, but functionally they go exactly where I want them.

I'll re-test the system again to confirm, but I have a feeling something is up with the core edit if they aren't resurrecting with their items, as it seems to work as intended on my end. If your still having problems, post up your PlayerMobile.CS and I'll compare it to my changes.
 
Top