ServUO Version
Publish Unknown
Ultima Expansion
None
I was designing a building recently, and I wanted to make some tight stairs. I noticed something odd about how UO tests whether a passage is blocked or not:

Let's say I place an impassable object at coordinate x=0, z=20. Then I place a stair object which rises in positive x-direction at x=1, z=0 . The configuration looks something like this:

Stairs.png

What I noticed, is that with this configuration, I can walk from left to right, out from under the block and up the stairs, without a problem. I cannot however walk from right to left, and back under the block. What happens in that case, is that I get stuck at the bottom most stair (position x=1) and cannot go any further. So this is a rather odd situation, where the stairs are traversable in one direction, but not the other.

I was trying to figure out why this happens and started to dig into the RunUO 2.6 source code (a brief glance into the ServUO source code tells me that it works the same there). The relevant function seems to be "CheckMovement( )" in the "MovementImpl" class in the file Movement.cs, which exists in the "Scripts/" folder (there is also such a file in the Server/ folder but it ends up calling the one in Scripts/).

The function does a sequence of checks whenever a move action is requested by a mobile, which decides whether or not the move is possible, and part of this is determining whether the mobile will fit into the target location. To do this, it uses a class wide variable "PersonHeight", which by default is set to "16".
Judging by the way the function appears to operate, it seemed like the problem described here shouldn't occur. The target location, right beneath the block, definitely has enough room for a player, regardless from which direction the player is moving in.

To be sure I am doing the right thing, I did the following two things:
- I changed "PersonHeight" to "10"
- I added a "Console.WriteLine" statement which reports back every time "CheckMovement( )" is called.

And here is where things get problematic. First of all, my change of "PersonHeight" did not solve the problem. What seems to happen, is that the UO client does its own set of checks, before even sending the move request to the server. I can see this, because not every move that I attempted to make resulted in a message in the console. Specifically when walking againt most (or all) impassable statics (walls, rocks etc.), but also some impassable items, the client seems to determine on its own that this is a move it cannot make.

Now I realize why this is done in such a way. It is actually a pretty clever way of keeping workload off of the server. Unfortunately, by whatever internal criteria the client seems to use, it seems to produce the problem I described above. Also, this effectively means that the "PersonHeight" variable can never work properly.

I was wondering if anyone here knows a solution to this. Is there any way I can request that the client forego its own collision check from the server side? Any help is appreciated. I know that I can simply change the geometry of the building, but now I feel challenged.
 
There is no way to avoid this in the stock client.exe
The PersonHeight constant is not necessarily there for it to be configured / changed, it just helps to have a singular value to reference when it is used in multiple places.
 
Thanks for the quick reply! That is what I feared... oh well.

I was just looking through at the "Item" base class in "Item.cs" and I suppose there also isn't a way to create dummy items that look like blocks or walls but are passable. At least not at the script level.

Passability is controlled by flags that are hardcoded into the .mul files an associated with item id, right? So if I use some tool like Mulpatcher, I could maybe do this?

I also have a situation in the building, which looks like the picture above, only that the solid block at x=0, z=20 is actually a railing on the upper floor. So in that case, I actually want it to block people from falling down onto the stairs, but not block people that are walking down the stairs. I'm thinking that if I can make a .mul entry for a railing that is passable, and then place an invisible block on top of it, a few ticks higher, I can get the behavior that I want.
 
The solution I ended up going for was super simple, and could be accomodated in my building without any aesthetic sacrifices: I just adjusted the floor by one z-position in various places. Duh...
 
Back