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!

Making spawned items [rares] not decay?

Alcsaar

Sorceror
Been struggling to find a way to prevent "daily" rares, ect from decaying when they spawn.

As it is they decay 1 hour after spawning. On OSI this wasn't an issue because you knew EXACTLY when a daily rare would spawn (On server up). On private servers where you are using spawners to create rare spawns, its not nearly as predictable. Which means 99% of the time a rare decays before anyone even checks the spawn location, and then it could be another 1-5 days before that particular rare respawns.

Things I have considered doing:

Over ride method in the script for the rare to force decays to false.

Theoretically this would work as long as all your rares are scripts, however it also means they will NEVER Decay. House falls with one in it? Its there forever until some one happens upon it. Its also tedious adding it to every rare script.

Additionally if your rares aren't all scripts (Using nerun's premium spawners you can spawn them in by static item id) this method won't work.

Region-based method

Giving each rare spawn location a custom region with decay disabled. This solves the problem of the rare not decaying after its been taken. However, this is very tedious if you have dozens and dozens of rare spawns, and probably not very efficient.


I am POSITIVE that some one has found a solution to similar problems like this, and I'm curious if anyone can point me in the direction of those solutions?
 

Alcsaar

Sorceror
Brainstorming other ideas now, if I over ride the decay property to false in the script, is it possible to do some sort of command like OnDragDrop or OnPickup and then over ride the decay again to true?
 

pooka01

Sorceror
Make Decay = false; then, override OnDragLift() with
Code:
 Decay = true;
return base.OnDragLift();
if someone moves the rare, it will start the decay rate.
 

daat99

Moderator
Staff member
That won't work will it? Because you can't just set decay true or false, you have to over ride it.
Try it :)
Overriding is usually used to change the logic.
If you just want to change the value you can just set it as demonstrated.
 

Alcsaar

Sorceror
As I thought, it doesn't work.

Code:
Errors:
 + Items/Special/Rares/Daily/DecoRocks.cs:
    CS0200: Line 13: Property or indexer 'Server.Item.Decays' cannot be assigned
 to -- it is read only
    CS0200: Line 28: Property or indexer 'Server.Item.Decays' cannot be assigned
 to -- it is read only

You can't just set decays = false/true because its a read only value. It has to be over rode.
 

daat99

Moderator
Staff member
Brainstorming other ideas now, if I over ride the decay property to false in the script, is it possible to do some sort of command like OnDragDrop or OnPickup and then over ride the decay again to true?
Yes,
Instead of always returning true/false you need to return a value you saved in a local field.
Try to look at other values that are being serialized (either Frozen or CantWalk if I remember correctly).

Keep in mind that you'll need to serialize this new field if you want it to be persistent across server restarts.
 

Alcsaar

Sorceror
Yes,
Instead of always returning true/false you need to return a value you saved in a local field.
Try to look at other values that are being serialized (either Frozen or CantWalk if I remember correctly).

Keep in mind that you'll need to serialize this new field if you want it to be persistent across server restarts.

Yea, that is outside my skill level/going over my head. This is dissapointing, I thought surely there must be an easy way to simply do this.
 

daat99

Moderator
Staff member
Yea, that is outside my skill level/going over my head. This is dissapointing, I thought surely there must be an easy way to simply do this.
This is indeed easy relative to most changes people are doing in the forums.
You just need to copy/paste most of the code from scripts you already have.
There are plenty of examples of "properties" in almost any script (PlayerMobile, BaseCreature, HarvestEngine...).
The easiest will probably be from PlayerMobile or BaseCreature because you can [prop most of them so you know how to recognize them.
 

Alcsaar

Sorceror
This is indeed easy relative to most changes people are doing in the forums.
You just need to copy/paste most of the code from scripts you already have.
There are plenty of examples of "properties" in almost any script (PlayerMobile, BaseCreature, HarvestEngine...).
The easiest will probably be from PlayerMobile or BaseCreature because you can [prop most of them so you know how to recognize them.

Hmm in layman's terms are you saying I need to create a new property so to speak that exists solely for my rare items, that triggers decay? Like I could add it as a property to core item.cs under the decay portion, but I would actually have the ability to change it using an over ride? Say I name it RareDecay I could have it initially spawn as RareDecay = false and then on lift RareDecay = true?
 

zerodowned

Sorceror
decay is directly related to movable

if you look at stealing you'll see this

if ( stolen != null )
{
m_Thief.SendLocalizedMessage( 502724 ); // You succesfully steal the item.
if ( si != null )
{
toSteal.Movable = true;
si.Item = null;
}
}


as pooka mentioned earlier, override draglift but set movable to true instead of decay to true
 

Alcsaar

Sorceror
Hey Zero. We actually tried that method, but we couldn't get OnLift to work properly. I'll look through it again however.

Edit* Tried it again, it wont work.

If I set the item to not decay above, it sets it to not be movable. OnItemLifted only functions if the item is ACTUALLY lifted - which it wouldn't be because when you try to pick it up you get the error "You can not pick that up" and the movable over ride fails due to that.

Does anyone know a method that detects if a player is in range of the object? If I could find that I could make it set the item to movable once a player enters a certain range of the item. I think this is a fair fix which resolves the issue of requiring an extra step to make the item movable.

The only issue is I would have to figure out a way to stop it from working if the item is inside a house region.
 

Alcsaar

Sorceror
I have it working using OnMovement method. Its initially set to movable false and when a player enters with in 5 tiles it becomes movable true. HOWEVER, this is going to cause issues with house lockdowns. If its locked down in a house and a player moves near it its going to set it to movable true again and anyone can simply pick it up from a house, so I need the code to check and see and make sure its not in a house region first.

Here is what I have so far:

Code:
      private int m_Range = 5;
        public override bool HandlesOnMovement { get { return true; } }
 
        public override void OnMovement(Mobile m, Point3D oldLocation)
        {
            if (m.Player && m.InRange(this, m_Range))
            {
                Movable = true;
            }
        }

This works fine, now I justr need to find out the proper syntax to add to the if statement to make sure the item isn't in a house region. Any help?
 

Alyssa Dark

Sorceror
this is only a reference, this is in an item script we have that prevents it from being used in a house, so maybe it'll help some for figuring out what you need... this item looks at the player's location (item is in player's pack) and if they are in house region or not, so that would need to be changed to having it check your rare item location instead, that I'm not quite sure of the syntax either... can't have it check for players in range location in case they're outside the house walking by...

part of an item OnDoubleClick
Code:
            if (from.Region.IsPartOf("GreenAcres"))
            {
                from.SendMessage("The magical power in this region prevents you from spawning this Dark Crusader here"); // Change this message aswell
                return;
            }
            else if (IsChildOf(from) && !Region.Find(from.Location, from.Map).IsPartOf( typeof(HouseRegion)))
            {
 
                if (!IsChildOf(from.Backpack))
                {
                    from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it.
                }
 
                else....

this might not help at all but does reference a house region related to item use

good luck :)
 

Alyssa Dark

Sorceror
hmm, maybe something like this? I'm not quite sure if 'this' would be the proper syntax to reference your item or not...

Code:
private int m_Range = 5;
        public override bool HandlesOnMovement { get { return true; } }
 
        public override void OnMovement(Mobile m, Point3D oldLocation)
        {
            if ((m.Player && m.InRange(this, m_Range)) && !Region.Find(this.Location, this.Map).IsPartOf( typeof(HouseRegion)))
            {
                Movable = true;
            }
        }
 

Alcsaar

Sorceror
Alyssa I think that might work. Looks good in theory. I actually got mine working using this:

Code:
      private int m_Range = 4;
        public override bool HandlesOnMovement { get { return true; } }
 
        public override void OnMovement(Mobile m, Point3D oldLocation)
 
        {
            BaseHouse house = BaseHouse.FindHouseAt(this);
            Region r = m.Region;
            if (m.Player && m.InRange(this, m_Range)) //if (m.Player && m.InRange(this, m_Range) && !r.IsPartOf( typeof( Server.Regions.HouseRegion )))
            {
                if (house != null && !house.IsLockedDown(this))
                {
                    Movable = true;
                }
            }
        }
 
Top