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!

[2.0-SVN] Lootable Trash Piles

David

Moderate
[2.0-SVN] Lootable Trash Piles

Lootable Trash Piles
RunUO 2.0 or SVN
Based on the Lootable Treasure Piles script; modification suggested by Macil.

Description:
This script adds four Addons (without Deeds) which are decorative trash piles that produce loot for Players. Once added a Player stands within one tile of the treasure and double-clicks it. They will receive one or two bandages or kindling plus a chance of any one of over 100 random items plus a slim chance of a ring or bracelet or a low level rare item. Each Trash Pile remembers who received the loot and will not produce loot for that player again for 90 minutes (adjustable.)

Use:
Place this script in your Scripts\Custom folder and restart the server. Ingame, as a GM or better type [Add TrashPileSmall or [Add TrashPileMedium or [Add TrashPileLarge or [Add TrashPileXLarge. There are settings in Props for the chance a random item or a rare item will drop, the time delay before the pile is lootable again by that Player, and which (or none) sound will play when the pile is looted. Note that the percent chance is expressed as a number between 0 and 1, to have it produce a random item every time use .99999. There is a MaxUses property which defaults to zero. If MaxUses is anything other than zero the Trash Pile will be deleted when UsesCount equals MaxUses. There is also a setting to make the looter a criminal; there are no other qualifications to that so it works in any region and for any player. (Not sure why picking through a pile of trash would be a criminal act, but the option is there if you need it.)

Notes:
  • Some of the decorative Items produced as random loot may not currently be available as Player owned items (Dirty Pot, Ruined Chair, Wood Debris, etc.) Those are standard RunUO Items and this script will hand them out to your Players. Please review the loot tables in the script to be sure they are appropriate for your shard.
  • Each Player can only loot the pile once per time period. However many Players can loot the pile in a short time span. The (default) 90 minute delay applies to each Player individually.
  • When a Player loots the pile they receive a message telling them what they have found.
  • The list of Players who have looted the pile is not serialized. If the server is restarted the pile will be available again to anyone.
  • For scriptors; this is based on the Lootable Treasure Piles script but uses a much improved loot generation process.

Updates:
First release.
 

Attachments

  • TrashPiles.cs
    18.2 KB · Views: 296

krazeykow

Sorceror
Enjoyed Reading

The script was well laid out and easy to read; I learned a few things about organization from looking over it. Useful for learning about random generation, etc.
It also seems like a nice incentive to keep the players logging in on a regular bases.
 

David

Moderate
krazeykow;797474 said:
The script was well laid out and easy to read; I learned a few things about organization from looking over it. Useful for learning about random generation, etc.
It also seems like a nice incentive to keep the players logging in on a regular bases.

Thanks. :)

and...

krazeykow;797474 said:
I learned C# with RunUO.

so did I! :D
 

Thilgon

Sorceror
very nice, thanks David :)

a nice addition to it could be extra finding chance of good loot based on begging or itemid, or both (something like (begging+itemid)/100 extra chance), since beggars are good at finding good things in trash, and itemid could mean "sharp eye" :p
 

David

Moderate
Thilgon;797568 said:
very nice, thanks David :)

a nice addition to it could be extra finding chance of good loot based on begging or itemid, or both (something like (begging+itemid)/100 extra chance), since beggars are good at finding good things in trash, and itemid could mean "sharp eye" :p

That's not to tough to do. Find the OnLoot() method and make these changes (highlighted in red.)

Note that the only testing I have done here is to make sure it compiles, but I think it will be fine.
Code:
                [COLOR="Red"]// improved chance of finding good loot based on certain skills
                double useskills = (from.Skills.Begging.Value + from.Skills.ItemID.Value) / 4000;[/COLOR]

                if (m_RareChance[COLOR="red"] + useskills[/COLOR] > Utility.RandomDouble()) // plus chance for a random prize
                {
                    m_Loot = Loot.Construct(m_TrashRareTypes);
                    from.AddToBackpack(m_Loot);
                    m_Collected = m_Collected + ", and " + GetName(m_Loot) + "!";
                }

I used Begging plus ItemID divided by 40 to get a 5% better chance of finding a 'prize' if both skills are at 100 (then divided again by 100 to get the decimal equivalent.) The result is if a Player has 100 Begging and 100 ItemID their chances of finding something decent goes from .5% to 5.5%; if both skills are 50 the chance becomes 2.5 plus .5 or 3%.

That still may be a little high so depending on what you have in the m_TrashRareTypes list you may want to change the 4000 to say 8000 which would cut the increased percentage in half.

/edit: I also used the skill Value which includes any SkillMods like a Mythical Knee Brace of Item Identification or whatever your shard may have. To ignore any such equipment you can use skill.Base instead.
 

Thilgon

Sorceror
compiles fine :) haven't tried yet it in game... i've added the skill chance increase to the normal trash items as well, so who trains those skill will have anyway some more chances anytime...
definitely love your scripts :)
 

David

Moderate
Here is what I settled on for the increased chance of loot idea. This is the entire OnLoot() method with the changes highlighted in red. I am not going to resubmit for this change but it will be in any future versions. I wound up using the first suggestion of Begging + Item ID / 100 for the rares and double that value for regular loot. This gives someone with 100 in both skills a 2% better chance of rare trash and a 4% better chance of regular trash. The common items, bandage or kindling, are not affected. Skill increasing items or effects are considered in the calculations.

have fun!

Code:
        public virtual void OnLoot(Mobile from) 
        {
            Item m_Loot;
            string m_Collected = "";

[COLOR="Red"]            // improved chance of finding good loot based on certian skills
            double useskills = (from.Skills.Begging.Value + from.Skills.ItemID.Value) / 10000;[/COLOR]

            DefragLooters();
            if (!FindLooter(from))
            {
                // always one
                m_Loot = Loot.Construct(m_TrashCommonTypes);
                from.AddToBackpack(m_Loot); 
                m_Collected = "You have recovered " + GetName(m_Loot);

                // maybe two
                if (Utility.RandomBool())
                {
                    m_Loot = Loot.Construct(m_TrashCommonTypes);
                    from.AddToBackpack(m_Loot);
                    m_Collected = m_Collected + ", " + GetName(m_Loot);
                }

                // plus chance for a random item
                if (m_ItemChance [COLOR="red"]+ useskills * 2[/COLOR] > Utility.RandomDouble())
                {
                    m_Loot = Loot.Construct(m_TrashItemTypes);
                    from.AddToBackpack(m_Loot);
                    m_Collected = m_Collected + ", " + GetName(m_Loot);
                }

                // plus chance for a random prize
                if (m_RareChance [COLOR="red"]+ useskills[/COLOR] > Utility.RandomDouble()) 
                {
                    m_Loot = Loot.Construct(m_TrashRareTypes);
                    from.AddToBackpack(m_Loot);
                    m_Collected = m_Collected + ", and " + GetName(m_Loot) + "!";
                }

                if (m_Sound > 0)
                    Effects.PlaySound(from.Location, from.Map, m_Sound);

                from.SendMessage(m_Collected);

                Looters.Add(new TrashLooter(from));
                m_usesCount++;

                if (m_MaxUses > 0 && m_usesCount >= m_MaxUses)
                {
                    from.SendMessage("You have recovered the last useable item!");
                    this.Delete();
                }

                if (m_MakesCriminal)
                {
                    from.CriminalAction(false);
                    from.SendLocalizedMessage(1010630); // Taking someone else's treasure is a criminal offense!
                }
            }
            else
                from.SendMessage("You find nothing of value at this time.");
        }

Thanks Thilgon for your ideas and support!
 

Kamron

Knight
David, this is one of the best ideas I have seen on the forums. Thank you for this script!

Here is a quick change to make the GetName function work better.

Code:
		public string GetName(Item item)
		{
			string[] splitname;
			string[] splitplural;
			string name = String.Empty;

			if ( String.IsNullOrEmpty( name ) )
			{
				name = item.ItemData.Name;

				splitname = name.Split('%'); // 0 is the main item, 1 is the conjugation, 2+ is the rest of the word
				name = splitname[0].Trim().ToLower();
				if ( splitname.Length > 1 )
				{
					splitplural = splitname[1].Split('/'); //0 is Plural, 1 is Singular (if exists)
					if ( splitplural.Length > 1 )
						name += splitplural[1].Trim().ToLower();;

					for ( int i = 2; i < splitname.Length; i++ ) //Add the rest of the name to the end
						name += splitname[i].Trim().ToLower();
				}

				if ( (item.ItemData.Flags & TileFlag.ArticleA) != 0 )
					name = "a " + name;
				else if ( (item.ItemData.Flags & TileFlag.ArticleAn) != 0 )
					name = "an " + name;
			}
			else
				name = item.Name;

			return name;
		}

This is untested, however it should work.
 

koluch

Sorceror
Server Crash :(

Server Crash Report
===================

RunUO Version 2.1, Build 4234.30397
Operating System: Microsoft Windows NT 5.2.3790 Service Pack 2
.NET Framework: 2.0.50727.3623
Time: 8/23/2011 9:11:12 PM
Mobiles: 35252
Items: 351742
Exception:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Server.Items.BaseTrash.GetName(Item i) in c:\RunUO 8-7-11\Scripts\Customs\Items\TrashPiles.cs:line 109
at Server.Items.BaseTrash.OnLoot(Mobile from) in c:\RunUO 8-7-11\Scripts\Customs\Items\TrashPiles.cs:line 155
at Server.Items.TrashComponent.OnDoubleClick(Mobile from) in c:\RunUO 8-7-11\Scripts\Customs\Items\TrashPiles.cs:line 358
at Server.Mobile.Use(Item item)
at Server.Engines.XmlSpawner2.XmlAttach.UseReq(NetState state, PacketReader pvSrc) in c:\RunUO 8-7-11\Scripts\XML Spawner 322\XML Spawner 322a\XmlSpawner2_20_2of3\XmlAttach\XmlAttach.cs:line 2352
at Server.Network.MessagePump.HandleReceive(NetState ns)
at Server.Network.MessagePump.Slice()
at Server.Core.Main(String[] args)

Line 109 = switch (name[0])

Line 155 = m_Collected = m_Collected + ", " + GetName(m_Loot);

Line 385 = public TrashPileSmall()
XML spawner line (there was no xmlattachment on the trashpile, they were in all by themselves, FYI)=
Code:
// need to check the item again in case it was modified in the OnUse or OnUser method
                            if (!blockdefaultonuse && item != null && !item.Deleted)
                                from.Use(item);

Any ideas?
Perhaps it has to do with the AA,E,I,O,U,Y???

Server is patched to 7.0.15.1.

Thanks!

Koluch
PS = We have had these in since the release, so I am sure it must have something to do with the latest updates to either the SVN or the 7.0.15.1 Classic Client.
 

mumuboy

Sorceror
A while ago I modified that function, so maybe this will work for you.

Code:
        public string GetName(Item item)
        {
            string[] splitname;
            string[] splitplural;
            string name = String.Empty;

            if ( String.IsNullOrEmpty( name ) )
            {
                name = item.ItemData.Name;

                splitname = name.Split('%'); // 0 is the main item, 1 is the conjugation, 2+ is the rest of the word
                name = splitname[0].Trim().ToLower();
                if ( splitname.Length > 1 )
                {
                    splitplural = splitname[1].Split('/'); //0 is Plural, 1 is Singular (if exists)
                    if ( splitplural.Length > 1 )
                        name += splitplural[1].Trim().ToLower();

                    for ( int i = 2; i < splitname.Length; i++ ) //Add the rest of the name to the end
                        name += splitname[i].Trim().ToLower();
                }

                if ( (item.ItemData.Flags & TileFlag.ArticleA) != 0 )
                    name = "a " + name;
                else if ( (item.ItemData.Flags & TileFlag.ArticleAn) != 0 )
                    name = "an " + name;
            }
            else
                name = item.Name;

            return name;
        }

I realize now that StringBuilder is a better way to go. You can look at Zippy's UO Rebirth BaseItem script to see a similar implementation using StringBuilder.
 

koluch

Sorceror
A while ago I modified that function, so maybe this will work for you.

Code:
        public string GetName(Item item)
        {
            string[] splitname;
            string[] splitplural;
            string name = String.Empty;
 
            if ( String.IsNullOrEmpty( name ) )
            {
                name = item.ItemData.Name;
 
                splitname = name.Split('%'); // 0 is the main item, 1 is the conjugation, 2+ is the rest of the word
                name = splitname[0].Trim().ToLower();
                if ( splitname.Length > 1 )
                {
                    splitplural = splitname[1].Split('/'); //0 is Plural, 1 is Singular (if exists)
                    if ( splitplural.Length > 1 )
                        name += splitplural[1].Trim().ToLower();
 
                    for ( int i = 2; i < splitname.Length; i++ ) //Add the rest of the name to the end
                        name += splitname[i].Trim().ToLower();
                }
 
                if ( (item.ItemData.Flags & TileFlag.ArticleA) != 0 )
                    name = "a " + name;
                else if ( (item.ItemData.Flags & TileFlag.ArticleAn) != 0 )
                    name = "an " + name;
            }
            else
                name = item.Name;
 
            return name;
        }

I realize now that StringBuilder is a better way to go. You can look at Zippy's UO Rebirth BaseItem script to see a similar implementation using StringBuilder.

I am having a hard time testing this, because it works, but I do no know if it fixes the crash?

Can someone post their script they are using without issue, it would be greatly appreciated.
( One thing I noticed, it does not have the i.movable = true; line in this section.)

Anyway, thanks for any assistance you can provide.

Koluch
 
Top