mirror of
https://github.com/pret/pmd-red.git
synced 2026-08-03 01:00:09 -05:00
Started decomping DecideMovement()
This commit is contained in:
parent
18d8a1a381
commit
89805ab019
|
|
@ -1,408 +0,0 @@
|
|||
#include "asm/constants/gba_constants.inc"
|
||||
#include "asm/macros.inc"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.text
|
||||
|
||||
thumb_func_start DecideMovement
|
||||
DecideMovement:
|
||||
push {r4-r7,lr}
|
||||
mov r7, r10
|
||||
mov r6, r9
|
||||
mov r5, r8
|
||||
push {r5-r7}
|
||||
sub sp, 0x3C
|
||||
mov r9, r0
|
||||
lsls r1, 24
|
||||
lsrs r7, r1, 24
|
||||
ldr r5, [r0, 0x70]
|
||||
movs r0, 0xB6
|
||||
lsls r0, 1
|
||||
adds r1, r5, r0
|
||||
adds r4, r5, 0
|
||||
adds r4, 0x88
|
||||
ldr r0, [r4]
|
||||
str r0, [r1]
|
||||
mov r2, r9
|
||||
ldr r1, [r2, 0x4]
|
||||
ldr r0, [r4]
|
||||
cmp r1, r0
|
||||
beq _0807B348
|
||||
mov r6, r9
|
||||
adds r6, 0x4
|
||||
adds r0, r6, 0
|
||||
adds r1, r4, 0
|
||||
bl CalculateFacingDir
|
||||
mov r8, r0
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x7A
|
||||
ldrb r1, [r0]
|
||||
mov r0, r9
|
||||
bl ShouldAvoidFirstHit
|
||||
lsls r0, 24
|
||||
cmp r0, 0
|
||||
beq _0807B366
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x78
|
||||
ldrb r0, [r0]
|
||||
cmp r0, 0x1
|
||||
bne _0807B37C
|
||||
adds r0, r6, 0
|
||||
adds r1, r4, 0
|
||||
bl IsTargetTwoTilesAway
|
||||
lsls r0, 24
|
||||
cmp r0, 0
|
||||
beq _0807B37C
|
||||
adds r0, r6, 0
|
||||
adds r1, r4, 0
|
||||
bl GetDistance
|
||||
cmp r0, 0x2
|
||||
bne _0807B354
|
||||
_0807B348:
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x44
|
||||
movs r1, 0x1
|
||||
bl SetAction
|
||||
b _0807B5CE
|
||||
_0807B354:
|
||||
cmp r0, 0x1
|
||||
bgt _0807B37C
|
||||
movs r3, 0x4
|
||||
add r8, r3
|
||||
movs r0, 0x7
|
||||
mov r1, r8
|
||||
ands r1, r0
|
||||
mov r8, r1
|
||||
b _0807B37C
|
||||
_0807B366:
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x7B
|
||||
ldrb r0, [r0]
|
||||
cmp r0, 0
|
||||
beq _0807B37C
|
||||
movs r2, 0x4
|
||||
add r8, r2
|
||||
movs r0, 0x7
|
||||
mov r3, r8
|
||||
ands r3, r0
|
||||
mov r8, r3
|
||||
_0807B37C:
|
||||
add r4, sp, 0x30
|
||||
mov r0, r9
|
||||
mov r1, r8
|
||||
adds r2, r4, 0
|
||||
bl CanMoveForward
|
||||
lsls r0, 24
|
||||
cmp r0, 0
|
||||
beq _0807B3A8
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x44
|
||||
movs r2, 0x2
|
||||
ldrsh r1, [r5, r2]
|
||||
bl SetWalkAction
|
||||
movs r0, 0x7
|
||||
mov r3, r8
|
||||
ands r3, r0
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x46
|
||||
strb r3, [r0]
|
||||
b _0807B5CE
|
||||
_0807B3A8:
|
||||
ldrb r0, [r4]
|
||||
cmp r0, 0
|
||||
beq _0807B444
|
||||
ldrb r0, [r5, 0x6]
|
||||
cmp r0, 0
|
||||
bne _0807B3E8
|
||||
ldr r1, _0807B3E0
|
||||
adds r0, r5, r1
|
||||
ldrb r0, [r0]
|
||||
cmp r0, 0
|
||||
bne _0807B3E8
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x79
|
||||
movs r4, 0x1
|
||||
strb r4, [r0]
|
||||
movs r2, 0xA2
|
||||
lsls r2, 1
|
||||
adds r0, r5, r2
|
||||
strb r4, [r0]
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x44
|
||||
movs r1, 0x1
|
||||
bl SetAction
|
||||
ldr r3, _0807B3E4
|
||||
adds r0, r5, r3
|
||||
strb r4, [r0]
|
||||
b _0807B5CE
|
||||
.align 2, 0
|
||||
_0807B3E0: .4byte 0x00000145
|
||||
_0807B3E4: .4byte 0x00000147
|
||||
_0807B3E8:
|
||||
mov r0, r9
|
||||
movs r2, 0x4
|
||||
ldrsh r1, [r0, r2]
|
||||
ldr r2, _0807B434
|
||||
mov r3, r8
|
||||
lsls r0, r3, 2
|
||||
adds r2, r0, r2
|
||||
movs r3, 0
|
||||
ldrsh r0, [r2, r3]
|
||||
adds r1, r0
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x88
|
||||
movs r3, 0
|
||||
ldrsh r0, [r0, r3]
|
||||
cmp r1, r0
|
||||
bne _0807B43C
|
||||
mov r1, r9
|
||||
movs r3, 0x6
|
||||
ldrsh r0, [r1, r3]
|
||||
movs r3, 0x2
|
||||
ldrsh r1, [r2, r3]
|
||||
adds r0, r1
|
||||
adds r1, r5, 0
|
||||
adds r1, 0x8A
|
||||
movs r2, 0
|
||||
ldrsh r1, [r1, r2]
|
||||
cmp r0, r1
|
||||
bne _0807B43C
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x44
|
||||
movs r1, 0x1
|
||||
bl SetAction
|
||||
ldr r3, _0807B438
|
||||
adds r1, r5, r3
|
||||
movs r0, 0x1
|
||||
strb r0, [r1]
|
||||
b _0807B5CE
|
||||
.align 2, 0
|
||||
_0807B434: .4byte gAdjacentTileOffsets
|
||||
_0807B438: .4byte 0x00000147
|
||||
_0807B43C:
|
||||
adds r1, r5, 0
|
||||
adds r1, 0x79
|
||||
movs r0, 0x1
|
||||
strb r0, [r1]
|
||||
_0807B444:
|
||||
mov r3, sp
|
||||
mov r2, sp
|
||||
mov r1, sp
|
||||
add r0, sp, 0x28
|
||||
movs r4, 0x1
|
||||
strb r4, [r0]
|
||||
add r0, sp, 0x20
|
||||
strb r4, [r0]
|
||||
strb r4, [r1, 0x18]
|
||||
strb r4, [r2, 0x10]
|
||||
strb r4, [r3, 0x8]
|
||||
ldrb r6, [r5, 0x6]
|
||||
cmp r6, 0
|
||||
bne _0807B4C8
|
||||
mov r0, r8
|
||||
ands r0, r4
|
||||
cmp r0, 0
|
||||
beq _0807B4C8
|
||||
mov r1, r9
|
||||
movs r2, 0x4
|
||||
ldrsh r0, [r1, r2]
|
||||
adds r1, r5, 0
|
||||
adds r1, 0x88
|
||||
movs r3, 0
|
||||
ldrsh r1, [r1, r3]
|
||||
subs r2, r0, r1
|
||||
cmp r2, 0
|
||||
bge _0807B47E
|
||||
negs r2, r2
|
||||
_0807B47E:
|
||||
mov r0, r9
|
||||
movs r3, 0x6
|
||||
ldrsh r1, [r0, r3]
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x8A
|
||||
movs r3, 0
|
||||
ldrsh r0, [r0, r3]
|
||||
subs r1, r0
|
||||
cmp r1, 0
|
||||
bge _0807B494
|
||||
negs r1, r1
|
||||
_0807B494:
|
||||
cmp r2, 0x2
|
||||
bgt _0807B4C8
|
||||
cmp r1, 0x2
|
||||
bgt _0807B4C8
|
||||
cmp r2, r1
|
||||
beq _0807B4C8
|
||||
movs r3, 0x2
|
||||
mov r0, r8
|
||||
ands r3, r0
|
||||
cmp r3, 0
|
||||
beq _0807B4BA
|
||||
cmp r2, r1
|
||||
bge _0807B4B4
|
||||
mov r0, sp
|
||||
strb r6, [r0, 0x10]
|
||||
b _0807B4C8
|
||||
_0807B4B4:
|
||||
mov r0, sp
|
||||
strb r6, [r0, 0x8]
|
||||
b _0807B4C8
|
||||
_0807B4BA:
|
||||
cmp r2, r1
|
||||
bge _0807B4C4
|
||||
mov r0, sp
|
||||
strb r3, [r0, 0x8]
|
||||
b _0807B4C8
|
||||
_0807B4C4:
|
||||
mov r0, sp
|
||||
strb r3, [r0, 0x10]
|
||||
_0807B4C8:
|
||||
movs r1, 0x3
|
||||
mov r10, r1
|
||||
mov r0, r9
|
||||
adds r1, r7, 0
|
||||
bl ShouldAvoidEnemiesAndShowEffect
|
||||
lsls r0, 24
|
||||
cmp r0, 0
|
||||
bne _0807B4E4
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x7B
|
||||
ldrb r0, [r0]
|
||||
cmp r0, 0
|
||||
beq _0807B4E8
|
||||
_0807B4E4:
|
||||
movs r2, 0x5
|
||||
mov r10, r2
|
||||
_0807B4E8:
|
||||
movs r6, 0x1
|
||||
adds r3, r5, 0
|
||||
adds r3, 0x44
|
||||
str r3, [sp, 0x34]
|
||||
cmp r6, r10
|
||||
bge _0807B53C
|
||||
mov r3, sp
|
||||
mov r4, sp
|
||||
adds r4, 0xA
|
||||
add r7, sp, 0x8
|
||||
_0807B4FC:
|
||||
lsls r0, r6, 3
|
||||
add r2, sp, 0x4
|
||||
adds r2, r0
|
||||
ldr r1, _0807B598
|
||||
lsls r0, r6, 2
|
||||
adds r0, r1
|
||||
ldr r1, [r0]
|
||||
add r1, r8
|
||||
movs r0, 0x7
|
||||
ands r1, r0
|
||||
str r1, [r2]
|
||||
mov r0, r9
|
||||
adds r2, r4, 0
|
||||
str r3, [sp, 0x38]
|
||||
bl CanMoveForward
|
||||
strb r0, [r7, 0x1]
|
||||
lsls r0, 24
|
||||
ldr r3, [sp, 0x38]
|
||||
cmp r0, 0
|
||||
bne _0807B532
|
||||
ldrb r0, [r4]
|
||||
cmp r0, 0
|
||||
bne _0807B532
|
||||
movs r0, 0x1
|
||||
strb r0, [r3, 0x10]
|
||||
strb r0, [r3, 0x8]
|
||||
_0807B532:
|
||||
adds r4, 0x8
|
||||
adds r7, 0x8
|
||||
adds r6, 0x1
|
||||
cmp r6, r10
|
||||
blt _0807B4FC
|
||||
_0807B53C:
|
||||
movs r6, 0x1
|
||||
cmp r6, r10
|
||||
bge _0807B56E
|
||||
adds r3, r5, 0
|
||||
adds r3, 0x79
|
||||
add r1, sp, 0x8
|
||||
movs r4, 0x8
|
||||
movs r7, 0x1
|
||||
_0807B54C:
|
||||
adds r2, r4, 0
|
||||
ldrb r0, [r1, 0x1]
|
||||
cmp r0, 0
|
||||
beq _0807B55A
|
||||
ldrb r0, [r1]
|
||||
cmp r0, 0
|
||||
bne _0807B5A0
|
||||
_0807B55A:
|
||||
ldrb r0, [r1, 0x2]
|
||||
cmp r0, 0
|
||||
beq _0807B562
|
||||
strb r7, [r3]
|
||||
_0807B562:
|
||||
adds r1, 0x8
|
||||
adds r4, r2, 0
|
||||
adds r4, 0x8
|
||||
adds r6, 0x1
|
||||
cmp r6, r10
|
||||
blt _0807B54C
|
||||
_0807B56E:
|
||||
ldr r0, [sp, 0x34]
|
||||
movs r1, 0x1
|
||||
bl SetAction
|
||||
ldr r1, _0807B59C
|
||||
adds r0, r5, r1
|
||||
movs r1, 0
|
||||
movs r2, 0x1
|
||||
strb r2, [r0]
|
||||
ldrb r0, [r5, 0x7]
|
||||
cmp r0, 0
|
||||
beq _0807B5BC
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x79
|
||||
strb r1, [r0]
|
||||
movs r2, 0xA2
|
||||
lsls r2, 1
|
||||
adds r0, r5, r2
|
||||
strb r1, [r0]
|
||||
b _0807B5CE
|
||||
.align 2, 0
|
||||
_0807B598: .4byte gFaceDirectionIncrements
|
||||
_0807B59C: .4byte 0x00000147
|
||||
_0807B5A0:
|
||||
movs r3, 0x2
|
||||
ldrsh r1, [r5, r3]
|
||||
ldr r0, [sp, 0x34]
|
||||
bl SetWalkAction
|
||||
add r0, sp, 0x4
|
||||
adds r0, r4
|
||||
ldr r0, [r0]
|
||||
movs r1, 0x7
|
||||
ands r0, r1
|
||||
adds r1, r5, 0
|
||||
adds r1, 0x46
|
||||
strb r0, [r1]
|
||||
b _0807B5CE
|
||||
_0807B5BC:
|
||||
adds r0, r5, 0
|
||||
adds r0, 0x79
|
||||
ldrb r0, [r0]
|
||||
cmp r0, 0
|
||||
beq _0807B5CE
|
||||
movs r1, 0xA2
|
||||
lsls r1, 1
|
||||
adds r0, r5, r1
|
||||
strb r2, [r0]
|
||||
_0807B5CE:
|
||||
add sp, 0x3C
|
||||
pop {r3-r5}
|
||||
mov r8, r3
|
||||
mov r9, r4
|
||||
mov r10, r5
|
||||
pop {r4-r7}
|
||||
pop {r0}
|
||||
bx r0
|
||||
thumb_func_end DecideMovement
|
||||
|
||||
.align 2, 0
|
||||
|
|
@ -6,5 +6,8 @@
|
|||
void MoveIfPossible(struct DungeonEntity *pokemon, bool8 showRunAwayEffect);
|
||||
bool8 CanTakeItem(struct DungeonEntity *pokemon);
|
||||
bool8 ChooseTargetPosition(struct DungeonEntity *pokemon);
|
||||
void DecideMovement(struct DungeonEntity *pokemon, bool8 showRunAwayEffect);
|
||||
bool8 AvoidEnemies(struct DungeonEntity *pokemon);
|
||||
bool8 Wander(struct DungeonEntity *pokemon);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef GUARD_DUNGEON_AI_MOVEMENT_1_H
|
||||
#define GUARD_DUNGEON_AI_MOVEMENT_1_H
|
||||
|
||||
#include "dungeon_entity.h"
|
||||
|
||||
bool8 AvoidEnemies(struct DungeonEntity *pokemon);
|
||||
bool8 Wander(struct DungeonEntity *pokemon);
|
||||
|
||||
#endif
|
||||
|
|
@ -254,8 +254,6 @@ SECTIONS {
|
|||
src/code_8077274_1.o(.text);
|
||||
asm/code_8077274_1.o(.text);
|
||||
src/dungeon_ai_movement.o(.text);
|
||||
asm/code_807B2D8.o(.text);
|
||||
src/dungeon_ai_movement_1.o(.text);
|
||||
src/dungeon_ai_attack.o(.text);
|
||||
asm/code_807CABC.o(.text);
|
||||
src/targeting_flags.o(.text);
|
||||
|
|
@ -448,7 +446,7 @@ SECTIONS {
|
|||
data/data_80F4278.o(.rodata);
|
||||
src/dungeon_util.o(.rodata);
|
||||
data/data_80F4468.o(.rodata);
|
||||
src/dungeon_ai_movement_1.o(.rodata);
|
||||
src/dungeon_ai_movement.o(.rodata);
|
||||
data/data_80F4D44.o(.rodata);
|
||||
src/status_checks.o(.rodata);
|
||||
data/data_80F4DB4.o(.rodata);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,631 +0,0 @@
|
|||
#include "global.h"
|
||||
#include "dungeon_ai_movement_1.h"
|
||||
|
||||
#include "constants/targeting.h"
|
||||
#include "dungeon_ai_targeting.h"
|
||||
#include "dungeon_global_data.h"
|
||||
#include "dungeon_map_access.h"
|
||||
#include "dungeon_random.h"
|
||||
#include "dungeon_util.h"
|
||||
#include "dungeon_visibility.h"
|
||||
#include "position_util.h"
|
||||
|
||||
#define INFINITY 999999
|
||||
|
||||
const s32 gFaceDirectionIncrements[] = {0, 1, -1, 2, -2, 3, -3, 4, 0, -1, 1, -2, 2, -3, 3, 4};
|
||||
|
||||
extern bool8 IsAtJunction(struct DungeonEntity *pokemon);
|
||||
|
||||
bool8 AvoidEnemies(struct DungeonEntity *pokemon)
|
||||
{
|
||||
bool8 pokemonInFront;
|
||||
u8 closestTargetRoomIndex;
|
||||
s32 closestTargetDistance = INFINITY;
|
||||
struct DungeonEntity *closestTarget;
|
||||
struct DungeonEntityData *pokemonData = pokemon->entityData;
|
||||
u8 roomIndex = GetEntityRoomIndex(pokemon);
|
||||
struct DungeonEntity **possibleTargets;
|
||||
s32 numPossibleTargets;
|
||||
s32 i;
|
||||
if (gDungeonGlobalData->decoyActive)
|
||||
{
|
||||
possibleTargets = gDungeonGlobalData->allPokemon;
|
||||
numPossibleTargets = DUNGEON_MAX_POKEMON;
|
||||
}
|
||||
else if (pokemonData->isEnemy)
|
||||
{
|
||||
possibleTargets = gDungeonGlobalData->teamPokemon;
|
||||
numPossibleTargets = MAX_TEAM_MEMBERS;
|
||||
}
|
||||
else
|
||||
{
|
||||
possibleTargets = gDungeonGlobalData->wildPokemon;
|
||||
numPossibleTargets = DUNGEON_MAX_WILD_POKEMON;
|
||||
}
|
||||
closestTarget = NULL;
|
||||
closestTargetRoomIndex = CORRIDOR_ROOM_INDEX;
|
||||
for (i = 0; i < numPossibleTargets; i++)
|
||||
{
|
||||
struct DungeonEntity *target = possibleTargets[i];
|
||||
if (EntityExists(target) && CanSee(pokemon, target))
|
||||
{
|
||||
s32 distance;
|
||||
if (gDungeonGlobalData->decoyActive && CanTarget(pokemon, target, FALSE, TRUE) != TARGET_CAPABILITY_CAN_TARGET)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
distance = GetDistance(&pokemon->posWorld, &target->posWorld);
|
||||
if (closestTargetDistance > distance)
|
||||
{
|
||||
closestTargetDistance = distance;
|
||||
closestTarget = target;
|
||||
closestTargetRoomIndex = GetEntityRoomIndex(target);
|
||||
pokemonData->targetMovePosition = closestTarget->posWorld;
|
||||
pokemonData->targetPosition = closestTarget->posWorld;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (closestTargetDistance != INFINITY)
|
||||
{
|
||||
if (roomIndex == closestTargetRoomIndex && roomIndex != CORRIDOR_ROOM_INDEX)
|
||||
{
|
||||
struct MapTile *tile = GetMapTile_1(pokemon->posWorld.x, pokemon->posWorld.y);
|
||||
if (tile->tileType & TILE_TYPE_ROOM_EXIT)
|
||||
{
|
||||
struct Position targetMovePosition;
|
||||
s32 targetDir;
|
||||
targetMovePosition.x = pokemon->posWorld.x;
|
||||
targetMovePosition.y = pokemon->posWorld.y;
|
||||
// Scan for a direction leading outside the room.
|
||||
for (targetDir = 0; targetDir < NUM_DIRECTIONS; targetDir++)
|
||||
{
|
||||
struct MapTile *adjacentTile;
|
||||
targetMovePosition.x = pokemon->posWorld.x + gAdjacentTileOffsets[targetDir].x;
|
||||
targetMovePosition.y = pokemon->posWorld.y + gAdjacentTileOffsets[targetDir].y;
|
||||
adjacentTile = GetMapTile_1(targetMovePosition.x, targetMovePosition.y);
|
||||
if (adjacentTile->roomIndex != roomIndex && CanMoveForward(pokemon, targetDir, &pokemonInFront))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (targetDir == NUM_DIRECTIONS)
|
||||
{
|
||||
targetDir = DungeonRandomCapped(NUM_DIRECTIONS);
|
||||
pokemonData->movementAction = MOVEMENT_ACTION_FACE_RANDOM_DIRECTION;
|
||||
pokemonData->targetMovePosition.x = pokemon->posWorld.x + gAdjacentTileOffsets[targetDir].x;
|
||||
pokemonData->targetMovePosition.y = pokemon->posWorld.y + gAdjacentTileOffsets[targetDir].y;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pokemonData->movementAction = MOVEMENT_ACTION_RUN_AWAY_FROM_ENEMY;
|
||||
pokemonData->targetMovePosition = targetMovePosition;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// At this point, the Pokémon is running directly away from the target.
|
||||
// If there are any room exits that the Pokémon can head towards without moving
|
||||
// closer to the target, head towards the furthest eligible exit.
|
||||
s32 numRoomExits;
|
||||
struct Position *roomExits = gDungeonGlobalData->roomExits[roomIndex];
|
||||
s32 furthestTargetExitIndex;
|
||||
s32 furthestTargetToExitDistance;
|
||||
s32 distanceX;
|
||||
s32 pokemonToTargetDistance;
|
||||
s32 i;
|
||||
numRoomExits = gDungeonGlobalData->numRoomExits[roomIndex];
|
||||
furthestTargetToExitDistance = -INFINITY;
|
||||
furthestTargetExitIndex = 0;
|
||||
distanceX = closestTarget->posWorld.x - pokemon->posWorld.x;
|
||||
if (distanceX < 0)
|
||||
{
|
||||
distanceX = -distanceX;
|
||||
}
|
||||
pokemonToTargetDistance = closestTarget->posWorld.y - pokemon->posWorld.y;
|
||||
if (pokemonToTargetDistance < 0)
|
||||
{
|
||||
pokemonToTargetDistance = -pokemonToTargetDistance;
|
||||
}
|
||||
if (pokemonToTargetDistance < distanceX)
|
||||
{
|
||||
pokemonToTargetDistance = distanceX;
|
||||
}
|
||||
for (i = 0; i < numRoomExits; i++)
|
||||
{
|
||||
s32 targetToExitDistance;
|
||||
s32 pokemonToExitSignX, pokemonToExitSignY;
|
||||
s32 adjacentToTargetDistanceX, adjacentToTargetDistance;
|
||||
s32 distanceX = closestTarget->posWorld.x - roomExits[i].x;
|
||||
if (distanceX < 0)
|
||||
{
|
||||
distanceX = -distanceX;
|
||||
}
|
||||
targetToExitDistance = closestTarget->posWorld.y - roomExits[i].y;
|
||||
if (targetToExitDistance < 0)
|
||||
{
|
||||
targetToExitDistance = -targetToExitDistance;
|
||||
}
|
||||
if (targetToExitDistance < distanceX)
|
||||
{
|
||||
targetToExitDistance = distanceX;
|
||||
}
|
||||
pokemonToExitSignX = roomExits[i].x - pokemon->posWorld.x;
|
||||
pokemonToExitSignY = roomExits[i].y - pokemon->posWorld.y;
|
||||
if (pokemonToExitSignX < -1)
|
||||
{
|
||||
pokemonToExitSignX = -1;
|
||||
}
|
||||
if (pokemonToExitSignY < -1)
|
||||
{
|
||||
pokemonToExitSignY = -1;
|
||||
}
|
||||
if (pokemonToExitSignX > 1)
|
||||
{
|
||||
pokemonToExitSignX = 1;
|
||||
}
|
||||
if (pokemonToExitSignY > 1)
|
||||
{
|
||||
pokemonToExitSignY = 1;
|
||||
}
|
||||
adjacentToTargetDistanceX = closestTarget->posWorld.x - (pokemon->posWorld.x + pokemonToExitSignX);
|
||||
if (adjacentToTargetDistanceX < 0)
|
||||
{
|
||||
adjacentToTargetDistanceX = -adjacentToTargetDistanceX;
|
||||
}
|
||||
adjacentToTargetDistance = closestTarget->posWorld.y - (pokemon->posWorld.y + pokemonToExitSignY);
|
||||
if (adjacentToTargetDistance < 0)
|
||||
{
|
||||
adjacentToTargetDistance = -adjacentToTargetDistance;
|
||||
}
|
||||
if (adjacentToTargetDistance < adjacentToTargetDistanceX)
|
||||
{
|
||||
adjacentToTargetDistance = adjacentToTargetDistanceX;
|
||||
}
|
||||
// BUG: The Pokémon is allowed to move towards the exit and remain the same
|
||||
// distance away from the target.
|
||||
// This leads to odd behavior like turning around when near an exit.
|
||||
// Using a > instead of a >= would avoid this issue.
|
||||
// For an example of this behavior, see https://youtu.be/plke4eU_PU8?t=435.
|
||||
if (adjacentToTargetDistance >= pokemonToTargetDistance &&
|
||||
furthestTargetToExitDistance < targetToExitDistance)
|
||||
{
|
||||
furthestTargetExitIndex = i;
|
||||
furthestTargetToExitDistance = targetToExitDistance;
|
||||
}
|
||||
}
|
||||
if (furthestTargetToExitDistance >= 0)
|
||||
{
|
||||
pokemonData->movementAction = MOVEMENT_ACTION_RUN_AWAY_FROM_ENEMY;
|
||||
pokemonData->targetMovePosition.x = roomExits[furthestTargetExitIndex].x;
|
||||
pokemonData->targetMovePosition.y = roomExits[furthestTargetExitIndex].y;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
pokemonData->movementAction = MOVEMENT_ACTION_RUN_AWAY_FROM_ENEMY;
|
||||
pokemonData->targetMovePosition.x = pokemon->posWorld.x - (closestTarget->posWorld.x - pokemon->posWorld.x);
|
||||
pokemonData->targetMovePosition.y = pokemon->posWorld.y - (closestTarget->posWorld.y - pokemon->posWorld.y);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Wander(pokemon);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NONMATCHING
|
||||
bool8 Wander(struct DungeonEntity *pokemon)
|
||||
{
|
||||
struct DungeonEntityData *pokemonData = pokemon->entityData;
|
||||
s32 roomIndex = GetEntityRoomIndex(pokemon);
|
||||
s32 targetFacingDir;
|
||||
if (roomIndex == CORRIDOR_ROOM_INDEX)
|
||||
{
|
||||
bool8 isAtJunction = FALSE;
|
||||
s32 oppositeFacingDir = (pokemonData->action.facingDir + NUM_DIRECTIONS / 2) & DIRECTION_MASK;
|
||||
s32 targetFacingDir2;
|
||||
s32 i;
|
||||
if (IsAtJunction(pokemon))
|
||||
{
|
||||
pokemonData->action.facingDir = DungeonRandomCapped(NUM_DIRECTIONS);
|
||||
isAtJunction = TRUE;
|
||||
}
|
||||
for (i = 0; i < NUM_DIRECTIONS; i++)
|
||||
{
|
||||
bool8 pokemonInFront;
|
||||
targetFacingDir = (pokemonData->action.facingDir + gFaceDirectionIncrements[i]) & DIRECTION_MASK;
|
||||
if ((!isAtJunction || targetFacingDir != oppositeFacingDir) &&
|
||||
CanMoveForward(pokemon, targetFacingDir, &pokemonInFront))
|
||||
{
|
||||
pokemonData->movementAction = MOVEMENT_ACTION_WANDER_CORRIDOR;
|
||||
pokemonData->targetMovePosition.x = pokemon->posWorld.x + gAdjacentTileOffsets[targetFacingDir].x;
|
||||
pokemonData->targetMovePosition.y = pokemon->posWorld.y + gAdjacentTileOffsets[targetFacingDir].y;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
targetFacingDir2 = DungeonRandomCapped(NUM_DIRECTIONS);
|
||||
pokemonData->movementAction = MOVEMENT_ACTION_FACE_RANDOM_DIRECTION;
|
||||
pokemonData->targetMovePosition.x = pokemon->posWorld.x + gAdjacentTileOffsets[targetFacingDir2].x;
|
||||
pokemonData->targetMovePosition.y = pokemon->posWorld.y + gAdjacentTileOffsets[targetFacingDir2].y;
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 numRoomExits = gDungeonGlobalData->numRoomExits[roomIndex];
|
||||
struct Position *roomExits = gDungeonGlobalData->roomExits[roomIndex];
|
||||
if (pokemonData->moveRandomly)
|
||||
{
|
||||
s32 targetFacingDir = DungeonRandomCapped(NUM_DIRECTIONS);
|
||||
pokemonData->movementAction = MOVEMENT_ACTION_FACE_RANDOM_DIRECTION;
|
||||
pokemonData->targetMovePosition.x = pokemon->posWorld.x + gAdjacentTileOffsets[targetFacingDir].x;
|
||||
pokemonData->targetMovePosition.y = pokemon->posWorld.y + gAdjacentTileOffsets[targetFacingDir].y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pokemonData->movementAction != MOVEMENT_ACTION_EXIT_ROOM)
|
||||
{
|
||||
s32 i;
|
||||
if (numRoomExits == 0)
|
||||
{
|
||||
targetFacingDir = DungeonRandomCapped(NUM_DIRECTIONS);
|
||||
pokemonData->movementAction = MOVEMENT_ACTION_FACE_RANDOM_DIRECTION;
|
||||
pokemonData->targetMovePosition.x = pokemon->posWorld.x + gAdjacentTileOffsets[targetFacingDir].x;
|
||||
pokemonData->targetMovePosition.y = pokemon->posWorld.y + gAdjacentTileOffsets[targetFacingDir].y;
|
||||
return TRUE;
|
||||
}
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
targetFacingDir = DungeonRandomCapped(numRoomExits);
|
||||
if (pokemon->posWorld.x != roomExits[targetFacingDir].x ||
|
||||
pokemon->posWorld.y != roomExits[targetFacingDir].y)
|
||||
{
|
||||
pokemonData->movementAction = MOVEMENT_ACTION_EXIT_ROOM;
|
||||
pokemonData->targetMovePosition.x = roomExits[targetFacingDir].x;
|
||||
pokemonData->targetMovePosition.y = roomExits[targetFacingDir].y;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
// If the AI randomly picks the exit it's standing on 10 times,
|
||||
// it gives up and exits the way it came.
|
||||
// This occurs normally for one-exit rooms, but can happen rarely for multi-exit rooms.
|
||||
}
|
||||
if (GetMapTile_1(pokemon->posWorld.x, pokemon->posWorld.y)->tileType & TILE_TYPE_ROOM_EXIT)
|
||||
{
|
||||
s32 i;
|
||||
targetFacingDir = DungeonRandomCapped(NUM_DIRECTIONS);
|
||||
for (i = 0; i < NUM_DIRECTIONS; i++, targetFacingDir++)
|
||||
{
|
||||
bool8 pokemonInFront;
|
||||
s32 forwardX, forwardY;
|
||||
targetFacingDir &= DIRECTION_MASK;
|
||||
forwardX = pokemon->posWorld.x + gAdjacentTileOffsets[targetFacingDir].x;
|
||||
forwardY = pokemon->posWorld.y + gAdjacentTileOffsets[targetFacingDir].y;
|
||||
if (GetMapTile_1(forwardX, forwardY)->roomIndex == CORRIDOR_ROOM_INDEX &&
|
||||
CanMoveForward(pokemon, targetFacingDir, &pokemonInFront))
|
||||
{
|
||||
pokemonData->movementAction = MOVEMENT_ACTION_WANDER_CORRIDOR;
|
||||
pokemonData->targetMovePosition.x = forwardX;
|
||||
pokemonData->targetMovePosition.y = forwardY;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
NAKED
|
||||
bool8 Wander(struct DungeonEntity *pokemon)
|
||||
{
|
||||
asm_unified("push {r4-r7,lr}\n"
|
||||
"mov r7, r10\n"
|
||||
"mov r6, r9\n"
|
||||
"mov r5, r8\n"
|
||||
"push {r5-r7}\n"
|
||||
"sub sp, 0x10\n"
|
||||
"adds r6, r0, 0\n"
|
||||
"ldr r7, [r6, 0x70]\n"
|
||||
"bl GetEntityRoomIndex\n"
|
||||
"lsls r0, 24\n"
|
||||
"lsrs r3, r0, 24\n"
|
||||
"cmp r3, 0xFF\n"
|
||||
"bne _0807B9DC\n"
|
||||
"movs r0, 0\n"
|
||||
"str r0, [sp, 0x4]\n"
|
||||
"adds r4, r7, 0\n"
|
||||
"adds r4, 0x46\n"
|
||||
"ldrb r0, [r4]\n"
|
||||
"adds r0, 0x4\n"
|
||||
"mov r8, r0\n"
|
||||
"movs r0, 0x7\n"
|
||||
"mov r1, r8\n"
|
||||
"ands r1, r0\n"
|
||||
"mov r8, r1\n"
|
||||
"adds r0, r6, 0\n"
|
||||
"bl IsAtJunction\n"
|
||||
"lsls r0, 24\n"
|
||||
"mov r9, r4\n"
|
||||
"cmp r0, 0\n"
|
||||
"beq _0807B96C\n"
|
||||
"movs r0, 0x8\n"
|
||||
"bl DungeonRandomCapped\n"
|
||||
"strb r0, [r4]\n"
|
||||
"movs r2, 0x1\n"
|
||||
"str r2, [sp, 0x4]\n"
|
||||
"_0807B96C:\n"
|
||||
"movs r3, 0\n"
|
||||
"movs r4, 0x78\n"
|
||||
"adds r4, r7\n"
|
||||
"mov r10, r4\n"
|
||||
"adds r0, r7, 0\n"
|
||||
"adds r0, 0x88\n"
|
||||
"str r0, [sp, 0x8]\n"
|
||||
"adds r7, 0x8A\n"
|
||||
"ldr r5, _0807B9D4\n"
|
||||
"_0807B97E:\n"
|
||||
"mov r1, r9\n"
|
||||
"ldrb r0, [r1]\n"
|
||||
"ldr r1, [r5]\n"
|
||||
"adds r4, r0, r1\n"
|
||||
"movs r0, 0x7\n"
|
||||
"ands r4, r0\n"
|
||||
"ldr r2, [sp, 0x4]\n"
|
||||
"cmp r2, 0\n"
|
||||
"beq _0807B994\n"
|
||||
"cmp r4, r8\n"
|
||||
"beq _0807B9AA\n"
|
||||
"_0807B994:\n"
|
||||
"adds r0, r6, 0\n"
|
||||
"adds r1, r4, 0\n"
|
||||
"mov r2, sp\n"
|
||||
"str r3, [sp, 0xC]\n"
|
||||
"bl CanMoveForward\n"
|
||||
"lsls r0, 24\n"
|
||||
"ldr r3, [sp, 0xC]\n"
|
||||
"cmp r0, 0\n"
|
||||
"beq _0807B9AA\n"
|
||||
"b _0807BB42\n"
|
||||
"_0807B9AA:\n"
|
||||
"adds r5, 0x4\n"
|
||||
"adds r3, 0x1\n"
|
||||
"cmp r3, 0x7\n"
|
||||
"ble _0807B97E\n"
|
||||
"movs r0, 0x8\n"
|
||||
"bl DungeonRandomCapped\n"
|
||||
"movs r1, 0x6\n"
|
||||
"mov r3, r10\n"
|
||||
"strb r1, [r3]\n"
|
||||
"ldr r1, _0807B9D8\n"
|
||||
"lsls r0, 2\n"
|
||||
"adds r0, r1\n"
|
||||
"ldrh r1, [r0]\n"
|
||||
"ldrh r4, [r6, 0x4]\n"
|
||||
"adds r1, r4\n"
|
||||
"ldr r2, [sp, 0x8]\n"
|
||||
"strh r1, [r2]\n"
|
||||
"ldrh r0, [r0, 0x2]\n"
|
||||
"b _0807BB5A\n"
|
||||
".align 2, 0\n"
|
||||
"_0807B9D4: .4byte gFaceDirectionIncrements\n"
|
||||
"_0807B9D8: .4byte gAdjacentTileOffsets\n"
|
||||
"_0807B9DC:\n"
|
||||
"ldr r0, _0807BA30\n"
|
||||
"ldr r2, [r0]\n"
|
||||
"lsls r1, r3, 1\n"
|
||||
"ldr r4, _0807BA34\n"
|
||||
"adds r0, r2, r4\n"
|
||||
"adds r0, r1\n"
|
||||
"movs r4, 0\n"
|
||||
"ldrsh r1, [r0, r4]\n"
|
||||
"mov r8, r1\n"
|
||||
"lsls r0, r3, 7\n"
|
||||
"ldr r1, _0807BA38\n"
|
||||
"adds r0, r1\n"
|
||||
"adds r2, r0\n"
|
||||
"mov r9, r2\n"
|
||||
"movs r2, 0x8A\n"
|
||||
"lsls r2, 1\n"
|
||||
"adds r0, r7, r2\n"
|
||||
"ldr r0, [r0]\n"
|
||||
"cmp r0, 0\n"
|
||||
"beq _0807BA40\n"
|
||||
"movs r0, 0x8\n"
|
||||
"bl DungeonRandomCapped\n"
|
||||
"adds r2, r7, 0\n"
|
||||
"adds r2, 0x78\n"
|
||||
"movs r1, 0x6\n"
|
||||
"strb r1, [r2]\n"
|
||||
"ldr r1, _0807BA3C\n"
|
||||
"lsls r0, 2\n"
|
||||
"adds r0, r1\n"
|
||||
"ldrh r1, [r0]\n"
|
||||
"ldrh r3, [r6, 0x4]\n"
|
||||
"adds r1, r3\n"
|
||||
"adds r2, 0x10\n"
|
||||
"strh r1, [r2]\n"
|
||||
"ldrh r0, [r0, 0x2]\n"
|
||||
"ldrh r6, [r6, 0x6]\n"
|
||||
"adds r0, r6\n"
|
||||
"adds r1, r7, 0\n"
|
||||
"adds r1, 0x8A\n"
|
||||
"strh r0, [r1]\n"
|
||||
"b _0807BB60\n"
|
||||
".align 2, 0\n"
|
||||
"_0807BA30: .4byte gDungeonGlobalData\n"
|
||||
"_0807BA34: .4byte 0x00010844\n"
|
||||
"_0807BA38: .4byte 0x00010884\n"
|
||||
"_0807BA3C: .4byte gAdjacentTileOffsets\n"
|
||||
"_0807BA40:\n"
|
||||
"adds r0, r7, 0\n"
|
||||
"adds r0, 0x78\n"
|
||||
"ldrb r1, [r0]\n"
|
||||
"mov r10, r0\n"
|
||||
"cmp r1, 0x4\n"
|
||||
"beq _0807BAA2\n"
|
||||
"mov r4, r8\n"
|
||||
"cmp r4, 0\n"
|
||||
"bne _0807BA84\n"
|
||||
"movs r0, 0x8\n"
|
||||
"bl DungeonRandomCapped\n"
|
||||
"adds r4, r0, 0\n"
|
||||
"movs r0, 0x6\n"
|
||||
"mov r1, r10\n"
|
||||
"strb r0, [r1]\n"
|
||||
"ldr r0, _0807BA80\n"
|
||||
"lsls r2, r4, 2\n"
|
||||
"adds r2, r0\n"
|
||||
"ldrh r0, [r2]\n"
|
||||
"ldrh r3, [r6, 0x4]\n"
|
||||
"adds r0, r3\n"
|
||||
"adds r1, r7, 0\n"
|
||||
"adds r1, 0x88\n"
|
||||
"strh r0, [r1]\n"
|
||||
"ldrh r0, [r2, 0x2]\n"
|
||||
"ldrh r6, [r6, 0x6]\n"
|
||||
"adds r0, r6\n"
|
||||
"adds r1, 0x2\n"
|
||||
"strh r0, [r1]\n"
|
||||
"b _0807BB60\n"
|
||||
".align 2, 0\n"
|
||||
"_0807BA80: .4byte gAdjacentTileOffsets\n"
|
||||
"_0807BA84:\n"
|
||||
"movs r5, 0\n"
|
||||
"_0807BA86:\n"
|
||||
"mov r0, r8\n"
|
||||
"bl DungeonRandomCapped\n"
|
||||
"adds r4, r0, 0\n"
|
||||
"ldr r0, [r6, 0x4]\n"
|
||||
"lsls r1, r4, 2\n"
|
||||
"mov r4, r9\n"
|
||||
"adds r2, r1, r4\n"
|
||||
"ldr r1, [r2]\n"
|
||||
"cmp r0, r1\n"
|
||||
"bne _0807BB18\n"
|
||||
"adds r5, 0x1\n"
|
||||
"cmp r5, 0x9\n"
|
||||
"ble _0807BA86\n"
|
||||
"_0807BAA2:\n"
|
||||
"movs r1, 0x4\n"
|
||||
"ldrsh r0, [r6, r1]\n"
|
||||
"movs r2, 0x6\n"
|
||||
"ldrsh r1, [r6, r2]\n"
|
||||
"bl GetMapTile_1\n"
|
||||
"ldrh r1, [r0]\n"
|
||||
"movs r0, 0x8\n"
|
||||
"ands r0, r1\n"
|
||||
"cmp r0, 0\n"
|
||||
"beq _0807BB60\n"
|
||||
"movs r0, 0x8\n"
|
||||
"bl DungeonRandomCapped\n"
|
||||
"adds r4, r0, 0\n"
|
||||
"movs r3, 0\n"
|
||||
"mov r9, r3\n"
|
||||
"_0807BAC4:\n"
|
||||
"movs r0, 0x7\n"
|
||||
"ands r4, r0\n"
|
||||
"movs r0, 0x4\n"
|
||||
"ldrsh r2, [r6, r0]\n"
|
||||
"ldr r0, _0807BB14\n"
|
||||
"lsls r1, r4, 2\n"
|
||||
"adds r1, r0\n"
|
||||
"movs r3, 0\n"
|
||||
"ldrsh r0, [r1, r3]\n"
|
||||
"adds r2, r0\n"
|
||||
"mov r8, r2\n"
|
||||
"movs r0, 0x6\n"
|
||||
"ldrsh r2, [r6, r0]\n"
|
||||
"movs r3, 0x2\n"
|
||||
"ldrsh r0, [r1, r3]\n"
|
||||
"adds r5, r2, r0\n"
|
||||
"mov r0, r8\n"
|
||||
"adds r1, r5, 0\n"
|
||||
"bl GetMapTile_1\n"
|
||||
"ldrb r0, [r0, 0x9]\n"
|
||||
"cmp r0, 0xFF\n"
|
||||
"bne _0807BB04\n"
|
||||
"adds r0, r6, 0\n"
|
||||
"adds r1, r4, 0\n"
|
||||
"mov r2, sp\n"
|
||||
"adds r2, 0x1\n"
|
||||
"bl CanMoveForward\n"
|
||||
"lsls r0, 24\n"
|
||||
"cmp r0, 0\n"
|
||||
"bne _0807BB2E\n"
|
||||
"_0807BB04:\n"
|
||||
"movs r0, 0x1\n"
|
||||
"add r9, r0\n"
|
||||
"adds r4, 0x1\n"
|
||||
"mov r1, r9\n"
|
||||
"cmp r1, 0x7\n"
|
||||
"ble _0807BAC4\n"
|
||||
"b _0807BB60\n"
|
||||
".align 2, 0\n"
|
||||
"_0807BB14: .4byte gAdjacentTileOffsets\n"
|
||||
"_0807BB18:\n"
|
||||
"movs r0, 0x4\n"
|
||||
"mov r3, r10\n"
|
||||
"strb r0, [r3]\n"
|
||||
"ldrh r1, [r2]\n"
|
||||
"adds r0, r7, 0\n"
|
||||
"adds r0, 0x88\n"
|
||||
"strh r1, [r0]\n"
|
||||
"ldrh r1, [r2, 0x2]\n"
|
||||
"adds r0, 0x2\n"
|
||||
"strh r1, [r0]\n"
|
||||
"b _0807BB60\n"
|
||||
"_0807BB2E:\n"
|
||||
"movs r0, 0x3\n"
|
||||
"mov r4, r10\n"
|
||||
"strb r0, [r4]\n"
|
||||
"adds r0, r7, 0\n"
|
||||
"adds r0, 0x88\n"
|
||||
"mov r1, r8\n"
|
||||
"strh r1, [r0]\n"
|
||||
"adds r0, 0x2\n"
|
||||
"strh r5, [r0]\n"
|
||||
"b _0807BB60\n"
|
||||
"_0807BB42:\n"
|
||||
"movs r0, 0x3\n"
|
||||
"mov r2, r10\n"
|
||||
"strb r0, [r2]\n"
|
||||
"ldr r0, _0807BB74\n"
|
||||
"lsls r1, r4, 2\n"
|
||||
"adds r1, r0\n"
|
||||
"ldrh r0, [r1]\n"
|
||||
"ldrh r3, [r6, 0x4]\n"
|
||||
"adds r0, r3\n"
|
||||
"ldr r4, [sp, 0x8]\n"
|
||||
"strh r0, [r4]\n"
|
||||
"ldrh r0, [r1, 0x2]\n"
|
||||
"_0807BB5A:\n"
|
||||
"ldrh r6, [r6, 0x6]\n"
|
||||
"adds r0, r6\n"
|
||||
"strh r0, [r7]\n"
|
||||
"_0807BB60:\n"
|
||||
"movs r0, 0x1\n"
|
||||
"add sp, 0x10\n"
|
||||
"pop {r3-r5}\n"
|
||||
"mov r8, r3\n"
|
||||
"mov r9, r4\n"
|
||||
"mov r10, r5\n"
|
||||
"pop {r4-r7}\n"
|
||||
"pop {r1}\n"
|
||||
"bx r1\n"
|
||||
".align 2, 0\n"
|
||||
"_0807BB74: .4byte gAdjacentTileOffsets");
|
||||
}
|
||||
#endif
|
||||
|
||||
void sub_807BB78(struct DungeonEntity *pokemon)
|
||||
{
|
||||
struct DungeonEntityData *entityData;
|
||||
|
||||
entityData = pokemon->entityData;
|
||||
entityData->movementAction = 0;
|
||||
entityData->targetMovePosition = pokemon->posWorld;
|
||||
entityData->targetPokemon = 0;
|
||||
entityData->targetPokemonSpawnIndex = 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user