ID:1298481
 
(See the best response by Metamorphman.)
Code:
obj
Wilderness
icon='Wilderness.dmi'
Oak1a
icon_state="Oaka"
density = 1
bound_x = 16
bound_width = 12
bound_height = 16
New()
new /obj/Wilderness/Oakb(locate(src.x+1,src.y,src.z))
new /obj/Wilderness/Oakc(locate(src.x,src.y+1,src.z))
new /obj/Wilderness/Oakd(locate(src.x+1,src.y+1,src.z))
..()
Oakb
icon_state="Oakb"
density = 1
bound_x = 0
bound_width =12
bound_height = 16
Oakc
icon_state="Oakc"
layer = 5
Oakd
icon_state="Oakd"
layer = 5


Problem description:

So I have a 4-tile tree. The top two tiles have "layer = 5" because they'll always be "over" the player, but the bottom two tiles are tricky. When the player walks past them they need to be "beneath" him, and due to their bounds settings he can walk past them using EAST and WEST. But when he walks behind them they need to be "above" him, but again, due to bounds settings, he can still enter using EAST and WEST.

I've thought of a clunky Enter() adaptation checking the mob's pixel height, but hoped there was a more elegant alternative.

Current behaviour looks like this:



Best response
I think setting world.map_format to SIDE_MAP is what you're looking for

see: side-view maps
Argh, I now have the reverse problem:





I've tried changing the top two tiles (Oakc and Oakd) in to overlays, hoping they would take the "near" value from the bottom icon (Oaka), but to no avail.

obj
Wilderness
icon='Tree.dmi'
Oak1a
icon_state="Oaka"
density = 1
bound_x = 16
bound_width = 12
bound_height = 16
New()
new /obj/Wilderness/Oakb(locate(src.x+1,src.y,src.z))
var /obj/Wilderness/Oakc/c = new()
var /obj/Wilderness/Oakd/d = new()
c.pixel_y=32
d.pixel_x=32
d.pixel_y=32

src.overlays+=c
src.overlays+=d
.=..()
Oakb
icon_state="Oakb"
density = 1
bound_x = 0
bound_width =12
bound_height = 16
Oakc
icon_state="Oakc"
layer = 15
Oakd
icon_state="Oakd"
layer = 15

Have you tried to something to check if the player is on the lower side of the y value vs the upper level of y value?

Such as:

obj
wilderness
Enter(mob/player)
if(player.y >= src.y)
src.layer = player.layer + 1
if(player.y < src.y)
src.layer = player.layer - 1
..()


My thought process with this is if the oak tiles y is say 10 and the player enters from 9 than it will make the oak tile be on a layer 1 under the player, or you could choose to add the oak tile to the player's underlay. Now if the player is at y = 11 and enters the oak tile than the oak tile's layer will go up one to be displayed on top of the player or you could add it as an overlay. That is assuming that enter checks the location that the player is entering from and not the location the player is at once they have finished entering.
Also you need to make the tiles for the top part of the tree to have a bit larger y bounding box or step it down some because it is doing what you showed in your second set of images because the player is exiting the base tile without triggering the enter proc for the top tile.

This can also be caused by if the bounding boxes are overlapping. So the bottom tile is not being exited until they are half way into the upper tree leaf area.
But Enter() isn't called as these trees are objects and not turfs; the mob never enters their contents.

I think I'm going to give up this method, as I believe I'm only using it due to old habit of pre-4.0 BYOND. Instead I'm going to just use BIG ICONS with "world.map_format=SIDE_MAP".
The method of using overlays is pretty outdated; so yeah, just BYOND's native large icon stuff.
Heh, one of the (many) down-sides to learning DM thoroughly 10 years ago, and then having a 7 year hiatus :P
You can create an image with a layer you want and apply it to a bare trunk's overlays.
The way I do this is just to set the tree's bounding box to the trunk, so only the part I don't want them to hit.

When they are above this area, I use an image of the tree put on a higher layer (So it goes over the mob).
SIDE_MAP could be awesome, but it isn't.

Fortunately, I came up with a simple solution that has been working for me for a while.
//  Super secret cool-people defines:
#define tile_width 32
#define tile_height 32
#define true 1
#define false 0

// Super awesome and common pixel-based procs:
atom
proc/width() return tile_width
proc/height() return tile_height
proc/px(p) return z && tile_width * (x - 1) + (p && p * width())
proc/py(p) return z && tile_height * (y - 1) + (p && p * height())

movable
width() return bound_width
height() return bound_height
px(p) return z && ..() + bound_x + step_x
py(p) return z && ..() + bound_y + step_y

// Super cool standing layers system:
atom
// Set this to true if you want the atom to
// layer like it's standing up
var standing = false
var bottom_offset = 0

// Call this whenever a player's absolute pixel-y-coordinate changes.
proc/update_layer()
var max_py = world.maxy * tile_height
if(!max_py) return

// The base layer for all standing atoms
layer = MOB_LAYER

// px / max_py
if(loc) layer -= (py() + bottom_offset) / max_py

// Examples of when to call update_layer():
New()
..()
standing && update_layer()

movable/Move()
. = ..()
. && standing && update_layer()

The key here is that some (most) atoms are standing upright, like trees, pillars, and humanoids, unlike floors.
Usually, they stand from the base of their bounding boxes, but you can add an offset.
If you want it to go by the center of the bounding box, just change py() to py(0.5).
I'd recommend using a 64x64 icon, instead of multiple tiles. Then you can simply do something like

Cross(atom/movable/O)
if(O.y<y&O.y!=y)
O.layer=layer+1
else
O.layer=layer-1
Games has the correct way.
In response to JunK Games
JunK Games wrote:
I'd recommend using a 64x64 icon, instead of multiple tiles. Then you can simply do something like

> Cross(atom/movable/O)
> if(O.y<y&O.y!=y)
> O.layer=layer+1
> else
> O.layer=layer-1
>


I think you'd want Crossed() instead of Cross() there.
Interestingly enough, if you have your walls broken into sections (lets say some walls are 2x or 3x tiles tall), and its possible to become a mob of variable size... there really isn't a solution for proper sorting, especially if the walls are used to create pillars... (a 3x tall mob should appear in front of the 2x tall pillar until his y level is above the bottom of the pillar, but the pillar is made up of several smaller predefined pieces).

This is a problem I haven't been able to solve yet.
Is the top of the tree suppose to be not dense?

If so that could explain why it is doing what it does as the trunk is dense, and that branch that is appearing over your player is part of the trunk icon. Have you tried moving that branch area to the icon for the top of the tree?

Also it would explain why the player appears through the leafs as they are not dense so they would not effect the view at all. Thus, they would not have a reason to appear over the player.
No, Cross() works just fine for me.
I believe I tried Crossed() and it didn't have the desired effect.

Really, which you should use depends on the size of your bound boxes and how far up the overlaying object the mob will overlap.
Akando, theres not many reasons to e usingultitiled icons anymore. BYOND got support for big icons long ago and now we even have bounding boxes. Your comment about layering because of density is also...wrong.
Please explain how it is wrong?
Graphic layers are independent of density.
Page: 1 2