River Pebble Script

Discussion in 'Editor Projects' started by Emotione11, Jun 9, 2018.

  1. Hey everyone, I made a new script which automatically places pebble layers on river banks- with nothing more than a single flat placeholder!

    Check out the result:



    The script is pretty flexible and allows for you to put in various parameters. Here's a brief explanation of them:

    1. Placeholder

    Simple enough- give the block ID/metadata pair of the blocks you want to put pebble layers above. Note: the placeholder here should not be a wool block (35) as those are used in the script! In the example picture I used gold (41).

    2. Type

    The type of the terrainset you want. The script can also do sand as well. The options are (in terrainset order): 'easternislands', 'ironislands', 'vale', 'north', 'ocean', 'dorne', 'river', 'westerlands', 'arbor', 'stormlands', 'reach', and then 'sand'.

    3. Cutoff

    This represents how high the dry/wet cutoff point should be. You should give the script an integer number between 0 and 9. If you give 0 it will make the entire pebble bank dry, whereas 9 will make the entire bank wet. A value of 4 or 5 will make the cutoff roughly in the middle.

    4. Height profile

    There are various preset "height profiles" preprogrammed into the script- a height profile just represents a distribution of the pebble layers. This should take an integer number between 0 and 6. The presets are listed as follows:

    0 is a special value- if you want more flexibility with the height profile and wet/dry mix in the pebbles you should give 0 as the value for this. It will cause the script to terminate just after making the rainbow gradient, in which case all you have to do is mask over each wool color to set each pebble layer.

    1 gives a "normal" linear slope, with each wool step increasing in height by one layer -->
    :0, :1, :2, :3, :4, :5, :6.

    2 gives a shallow slope, with every other wool step increasing in height by one layer -->
    :0, :0, :1, :1, :2, :2, :3.

    3 gives an even shallower slope, with the same pattern as the previous one but offset by one block -->
    air, :0, :0, :1, :1, :2, :2

    4 gives a convex slope (i.e. "pointier" at the top) -->
    :0, :0, :1, :1, :2, :4, :6

    5 gives a concave slope (i.e. "flatter" at the top) -->
    :0, :1, :2, :3, :3, :4, :4

    6 gives a steeper concave slope -->
    :0, :2, :4, :5, :6, :7, :7


    Please feel free to give feedback and suggestions on the script! One issue I know of already is that the pebbles on the outermost banks don't "transition" to the higher land, they form the same symmetric curve as the rest of the banks. Not sure if it's possible to fix this with the script but I'll work on it.

    Download the script here

    (Alternate download here)
    Andy_Jones, Wazgamer, EStoop and 9 others like this.
  2. This would be fun to try with snow and sand too, great work!
    Wazgamer and Elduwin like this.
  3. Very cool! Can this be modified to work with sand layers as well?
  4. I've tried making an automatic snow script to help with stuff in the North, but it's quite a bit more challenging. The problem here is that the snow layer gradient depends on slope. I've tried doing one where the user puts two placeholders, one for steep areas and one for flat areas, but then the script leaves jagged edges where the areas merge.

    Yeah, you can put 'sand' when it asks for pebble type and it'll do it with sand.
  5. Wow! Emote that's amazing!

    How does it work with a single placeholder? Could you explain in pseudocode the steps it takes?
  6. Yup! It's actually not too complicated, it's all the conditionals which make the script that long. The key thing to the script is the adjacency mask, which has the format //gmask ~[X][min][max], where X is an arbitrary mask (any mask syntax is valid) selecting which adjacent blocks to check, min is the minimum amount of such adjacent blocks necessary to mask the current block, and max is the maximum.

    So the script steps are something like the following:

    1. Let wetid and dryid be the IDs of the wet & dry pebble layers selected by the "type" parameter

    2. //gmask ~[X][4][8] (where X is the ID of the single placeholder),
    //set red

    3. Loop for each prevcolor, color in [red, orange, yellow, green, blue, purple, pink], starting at prevcolor=red, color=orange:
    //gmask ~[prevcolor][4][8]
    //set color

    By the end of this you should have a rainbow gradient which is used in setting the pebble layers.

    4. Let H be the pattern (array) of pebble heights (i.e. metadata values) denoted by the height profile parameter, indexed by color.
    Loop for each color in [red, orange, yellow, green, blue, purple, pink]:
    //gmask 0&>[color]
    //set dryid:H[color]

    5. Omitting some details on the last step, since the conditionals are pretty messy, but basically loop through each color again, replacing dryid with wetid, and terminate once an incremented value is greater than the cutoff parameter.

    6. Replace X (the placeholder) and all wool blocks with the dryidf (the full block ID), or wetidf, depending on the conditionals.
    IwanDeLarch and Thamus_Knoward like this.
  7. WOoaahh I had no idea adjacency masks were a thing. So it's masking objects based on the number of blocks adjacent to them, can it mask based on the ID of the blocks they have adjacent to them too? E.g. like the above/below /mask <[X].
    Last edited: Jun 14, 2018
    Thamus_Knoward likes this.
  8. Dude!! The adjacency mask changes everything :O I really didn't know that existed!
    IwanDeLarch likes this.
  9. I just learned that all these are are a thing - mind blown.
    Block mask [blocks]
    Example: stone,wood
    Explanation: Allows any block which is already stone or wood

    Angle mask /[min],[max]
    Example: /-20,-5
    Explanation: Allows any block where the adjacent block is between 20 and 5 blocks below

    Radius mask {[min],[max]
    Example: {5,20
    Explanation: Restricts blocks to within a specific radius range of the initial block

    Adjacent mask ~[pattern][=min[,max]]
    Example: ~stone,wood
    Explanation: Allows any block if it is adjacent to stone or wood Example: ~bedrock=2,4 Explanation: Allows any block if it is adjacent to between 2 and 4 bedrock

    Below mask <[pattern]
    Example: <stone
    Explanation: Allows any block directly beneath stone

    Above mask >[pattern]
    Example: >stone
    Explanation: Allows any block directly above stone

    Biome mask $[biome]
    Example: $FOREST
    Explanation: Restricts to the specified biome

    Random mask %[chance]
    Example: %34
    Explanation: 34% chance any block is allowed

    Negate mask
    Example: !<stone
    Explanation: Can negate any mask, this will allow any block not below stone

    Expression mask =[expression]
    Example: =abs(z+1)%2-abs(x)%2
    Explanation: Restricts to blocks where x and z coords are even numbers.
    Elduwin, Fin, lemonbear and 2 others like this.
  10. Emote and Cash I'd give both of you Westeroscraftforums Gold if that was a thing. Thanks a lot!
  11. Yup, so say you have red blocks, and you want to mask red blocks adjacent to four or more green blocks. Then you do:

    //gmask red&~[green][4][8].

    So the one inside the brackets is the ID of the blocks adjacent to the ones you want to mask.
  12. BTW @CashBanks you need to keep the brackets around all of those above.

    If you do:

    //gmask >1,2

    It will be interpreted as "mask over 1 OR mask 2".

    //gmask >[1,2]

    "mask over 1 OR 2"

    Also, you missed a very important one:

    Simplex mask #simplex[scale][min][max]
    Example: #simplex[20][40][70]
    Explanation: Uses simplex noise to create "blobs" rather than random noise. The 'scale' parameter changes how "zoomed in" the blobs are, the 'min' and 'max' parameters roughly change the "width" of the blobs.
    CashBanks likes this.
  13. Wowowowow!

    Now if we got an API into the schembrush that would allow the placement of a schem above masked blocks we’d have ourselves a forest generator.

    Especially with simplex allowing for natural clusters or groves of trees within a forest.

    A hack that could work would be if there was a way to write a script using a random teleport command that moves the player character around in a predefined range of coordinates, makes them look down and then executes the schbr command.
    Last edited: Jun 15, 2018
  14. I actually did find a plug-in called RandomTP on bukkit that randomly teleports a player throughout preselected coordinates. It’s got quite good functionality, even preventing players from teleporting onto certain blocks. Not sure how well it would integrate or how good it works on the small scale tho. I also saw mention of a bot plugin that makes virtual players capable of running commands. It would be quite complex to do your workaround, though it could be possible.
  15. I'd rather not have players teleporting around amok without being at the helm, especially with the double-place glitch.

    It seems like integration of masks into the schembrush and having a "bulk" place command (parameter representing density) should be quite doable.
  16. Stein just helped me figure out a very handy way to quickly replace snow/pebble layers.

    Say you've just made a large river bank of dry pebbles, but now you want to mix in some wet pebbles close to the water line. With the #id mask, you can tell world edit to only change a block's ID, not it's metadata.

    So if you wanted to quickly change those dry pebbles to wet pebbles, while maintaining their original height you could do:
    /br s #id[2212] <== the ID for wet northern pebble layers
    mask [2250] <=== the ID for the dry pebbles you're replacing.

    Then just paint over the spots you want to change.

    This also works for snow layers, so you can now quickly make pebble banks with the voxel snow brush /b snow then just swap it to pebbles using the #id brush.
  17. It's also super helpful for replacing stairs in one go.