Tempus

Member
Before I write up a command to do this I figured I'd ask if anyone has seen anything like it. I'm looking for something like the TileZ command that doesn't just fill the bounding box with the item. I'm looking for something that takes the 'normal' parameters (item, props etc) plus a new parameter indicating the number of items to randomly place within the selected region.

My purpose is to quickly landscape (and re-landscape) an area for small quests. I like to do two or so a month so I'm constantly recycling parts of green acres for whatever the next location is. For instance, I manually lay down a quick random number of brambles, then flowers then trees across a rather large area. This takes a considerable about of time and the randomness isn't all that random. I look at the stock map landscaping and the distribution of landscaping is nice and varied. That's when I thought, what if I could TileZ this area with say CedarTree1 trees but instead of filling the area, it would randomly place 30 (or whatever number).

Anyway, like I said, before I start scripting this out the command, I figured I'd look to see if

  • Something like this is already in the code (I couldn't find in the code if it is)
  • Anyone has already created something like this

I searched the published resources here and some of the old RunUO archives but haven't found anything but then again, its not the easiest thing to describe for a search engine.

Thanks for any suggestions.
 
This just came to me. Not sure if it will work as desired, but I was just thinking that you might be able to do this with an XmlSpawner.

Just set the types of "items" to spawn, and the range, and poof, instant random vegetation.
 
hmmm, thats actually a very good suggestion. Beats trying to write a new command. I'll give it a try.
 
with the spawner you could get overlapping items, wich you either need to manually move or remove :p . Also they may stack on one point (same graphic) so you get less from your count to be visible.

Just pointing that out :)
 
You might be able to write a simple loop that checks the spawn tile for an existing item and if it contains one then skip that tile for spawning, no? This would work for vegetation and outdoor decor.
 
If you would write an fill command I would say so, but with the spawner? I dont think so unless you would modify the spawners themself. Unless I dont know an feature of the spawners.
 
You might be able to write a simple loop that checks the spawn tile for an existing item and if it contains one then skip that tile for spawning, no? This would work for vegetation and outdoor decor.

Well, I'm experimenting with both approaches. I did create a working TileZRand command that seems to work pretty well but then again the xmlspawner suggestion also works well. Both have their downsides.

Is there existing functionality (I suppose there must be) to determine if the tile contains an item? Just tooling through the code, I started with testing with Map.GetMultiTilesAt() to prevent placing trees etc. in houses. That seems to work pretty well. I see Map.GetObjectsInRange. I'm assuming that returns an IPoolEnumerable of items or what?
 
I don't have access to any code right now (not easily legible or searchable on my phone), but I'd assume xmlspawner does some sort of looping check when it spawns a mobile to make sure it isn't spawning on something thats flagged impassable or where a static art is drawn etc. I would start by trying to find that code and see if it can be modified or manipulated for the outcome you're looking for.
 
My guess is they are using Map.CanSpawnMobile(). I believe I have seen, as PyrO mentioned, the xmlspawners overlapping non-mobile items on tiles so I doubt they're looking to see if anything other than a mobile is on the tile. I'm running through the other methods now in Map.cs because that seems like the most likely place an item in tile check would be (and Map.GetObjectsInRange() may be it).
 
So in the end, I went with the new tiling command as I didn't want to edit the xmlspawner code. I AM however thinking of using a combination of both depending on the situation because Lokai's xmlspawner idea is nearly perfect and very quick to implement.

As for preventing more than one item on a tile, the Map.GetObjectsInRange() was the key to not stacking items in the same tile. For some reason CanFit() looked like the right choice but on large areas, it seemed to run very long. Probably the result of my lousy/inefficient process of generating random coordinates...

I'll stick the code here in the event anyone cares to see look it over. If anyone thinks there is any value, I suppose I can upload it to the resources.

typical usage would be:

[tilezrand 0 CedarTree1 set movable false 20 // where 20 is the number of trees to tile
 

Attachments

  • TileZRandCommand.cs
    13.4 KB · Views: 7
I like it.

I do have some gut feelings about it, on first glance. You are tiling based on "Z" which in some place in Green Acres would seem to do what you are expecting. But, what if you want to Tile someplace where the ground is less even? Will it adjust Z to place objects on the ground, or will they hover in mid-air? Also, when checking for items, it's looking at X and Y for that specific Z within range 0, so does that mean larger items might overlap and look strange? I think that is why spawners use CanFit(), because it does the more complex calculations for them, and doesn't just count objects at X and Y. Anyway, let us know how it works for you. I don't really have a test server up and running at the moment.
 
All good points and things to look into working out. Good catch that GetObjectsInRange is only looking at one Z (and in this case, an improperly hard coded 0). As for the single z axis, the TileZ command only tiles on a single axis, its the first parameter of the method so that limitation isn't new. In the end, I think even after spending the time to create the script, I'm swaying toward just using the spawner. Its just faster to implement and is far more tested than my script.
 

Active Shards

Donations

Total amount
$0.00
Goal
$1,000.00
Back