Code:
Problem description:
How to make a mob move towards another mob, (like using step_to), but making sure that he won't be able to move diagonally.
So, in this situation he should stop movement:
X--X
MO--
XXXX
X = wall
M = mob
O = random obj in M's way
- = free space
Jul 7 2013, 11:48 am
|
|
Modify the mobs Move() proc to return 0 on diagonals.
|
I tried to do it myself but I couldn't, then I found a post by forum_account who worked for me:
Move(atom/new_loc) Now, can someone explain what is this, and why it works? (I am having trouble trying to understand what the "&" and "|" operators do). |
The bitwise AND (&) and bitwise OR (|) operators consider each "bit" in a number individually, in contrast to the logical AND (&&) and logical OR (||) operators which consider the entire the value.
Because the directions in BYOND are bit flags, they can be broken apart and combined with the bitwise operators. I don't have the time or the knowledge to give you a crash-course on binary number representation, but the gist is that instead of each digit increasing by a factor of ten like in decimal, they increase by a factor of 2 (so instead of 1, 10, 100, 1000, ect it's 1, 2, 4, 8, 16, 32, 64, ect). Regardless, here's what you need to know about how the bitwise operators work with directions: NORTH = 1 So you can think of the bitwise OR (|) operator as combining two directions. The bitwise AND (&) operator is equivalent to taking the "union" of the two directions (returns what they have in common). Applying this to Forum_Account's code, the first thing he does it use a trick to check if the direction is a diagonal. If a direction is diagonal, then ANDing that direction with one less than itself will return a true value. It works out this way because each of the values BYOND chose for the directions only have a single true bit, so subtracting 1 from a cardinal direction will unset that bit and carry over the remainder to all the less significant bits, causing the AND to return a false value. But for diagonal directions, two bits are set, so the more significant bit survives the subtraction and causes the AND to return a true value. You don't need to understand that, though, you can just regard it as binary magic ;) Next, he breaks the direction into its x (EAST and WEST) and y (NORTH and SOUTH) components. He does this by creating a composite direction for each axis ("NORTHSOUTH" and "EASTWEST") and ANDing it with the direction. So d1 will be left with either NORTH or SOUTH depending on which component it contained, and d2 will be left with either EAST or WEST. Now, since you don't want to allow diagonal movement, you have to pick one of the two component directions to step in instead. However, FA didn't want the mob to always favor vertical directions over horizontal ones, or vice-versa, so he adds a 50% chance to swap them so it can try the horizontal directions first half the time. Next, it tries stepping in the first component direction. If that succeeds, it returns 1 and we're done. If it failed, it tries the other component direction, and returns 1 if that succeeds. If it failed to step along either axis, it reaches the bottom and returns 0. -------------------------------------------- So, to summarize that wall of text, it breaks a diagonal movement into its two components, and then tries stepping in either one of those. |
Thank you for your help, there is still one more question I would like to ask.
With the current code I have for my NPC: proc This code works when the monsters are not blocking his way, but when they block his way sometimes the hero just stand still doing nothing. Is there any way to force him go throught his way killing the monsters to reach his target (the player)? I don't wanna use density=0 to monsters, so is there any other possibility? |
That doesn't solve my problem, my hero never bumps into anything if the path is blocked (he just stands there waiting for the monsters to move, which never happens in a maze-like map).
Setting density to 0 is the only thing I don't wanna do, is there any other fix? |
If monsters are in the way will he not bump() them?
Anyway you could force the monsters in view to walk_away or step_away.. |
Look, this is what happens:
XXXXXXXXXXX M--------O---X XXXXXXXXX-X XXXXXXXXX-X XXXXXXXXXRX X wall - free space M hero O monster R target (player) In this case, nothing happens because there is a monster blocking the path, the hero WONT move and thus wont bump in anything. Also, I don't want the monsters to run away from hero, I want the hero to run towards the monster and fight him, then continue his path towards the target |
I think your problem relates to whether or not you're using step_to/walk_to, and step_towards/walk_towards.
One uses pathfinding and as such doesn't actually Bump() things. |
Maybe, but I don't see how I could find a way to use step_towards in cases like these.
|
Barring any density-based hacks, you can use a custom pathfinding lib and override a proc or two so heroes don't consider enemies as obstacles:
http://www.byond.com/developer/?text=pathfinding&sort=pop I used Deadron's a long time ago, but I'm sure Theodis'/ Kuraudo's are worth looking into. |
I solved the problem by overriding /mob's Move(), while changing their density to 0, so step_to will work and the monsters won't cross the walls or the player, like this:
Move(atom/new_loc) |
In response to Muvuca
|
|
You could of alternatively used the Cross() proc, which allows the default functionality of Move() and Bump(), but permits certain things to pass over each other if you return 1.
|
I have another problem with all these codes for movement... They work, but when there are 2 paths, and one of them you can only pass with diagonal movement, if this path is the shortest one, the hero will go through it and then become stuck on the diagonal parta doing nothing.
How can I make him choose the longer path? Hope you understand what I mean. |
In response to Muvuca
|
|
I think you're going to have to use a custom pathfinding system.
|