diff --git a/asm/include/itcm.inc b/asm/include/itcm.inc index 7ca3d56e..b4f3812a 100644 --- a/asm/include/itcm.inc +++ b/asm/include/itcm.inc @@ -1,4 +1,23 @@ #pragma once +.public DTCM_BSS +.public EnableIrqFlag +.public G3_MultMtx43 +.public GeomSetTexImageParam +.public GeomSetVertexCoord16 +.public GetAllBaseForms +.public GetWindow +.public MONSTER_DATA_TABLE_PTR +.public MemcpyFast +.public MemsetFast +.public OS_IRQTable +.public RENDER_3D +.public RENDER_3D_FUNCTIONS +.public Rgb8ToRgb5 +.public SetIrqFlag +.public ShouldMonsterRunAwayAndShowEffect +.public TRIG_TABLE +.public UpdateWindow +.public WINDOW_LIST .public _02099724 .public _02099734 .public _02099744 @@ -10,77 +29,7 @@ .public _022A88FC .public _022B966C .public _022B99D0 -.public AbilityIsActiveVeneer -.public abs -.public AI_CONFUSED_NO_ATTACK_CHANCE -.public AI_REGULAR_ATTACK_WEIGHTS -.public AiConsiderMove -.public AreMovesEnabled -.public CanAiMonsterMoveInDirection -.public CanAiUseMove -.public CanSeeTarget -.public CanTargetEntity -.public CanTargetPosition -.public CeilFixedPoint -.public CheckVariousConditions -.public DIRECTIONS_XY -.public DTCM_BSS -.public DUNGEON_PTR -.public DungeonRandInt -.public DungeonRandOutcome__022EAB20 -.public EnableIrqFlag -.public EntityIsValid__0230827C -.public G3_MultMtx43 -.public GeomSetTexImageParam -.public GeomSetVertexCoord16 -.public GetAllBaseForms -.public GetChebyshevDistance -.public GetDirectionTowardsPosition -.public GetItemInfo -.public GetMoveAiWeight -.public GetMoveTypeForMonster -.public GetTile -.public GetTileAtEntity -.public GetTileSafe -.public GetTreatmentBetweenMonsters -.public GetVisibilityRange -.public GetWindow -.public HasDropeyeStatus -.public InitMove -.public IqSkillIsEnabled -.public IsBagFull -.public IsChargingTwoTurnMove -.public IsMonsterCornered -.public IsTacticSet -.public MemcpyFast -.public MemsetFast -.public MONSTER_DATA_TABLE_PTR -.public MonsterCannotAttack -.public OS_IRQTable -.public IsPositionWithinTwoTiles -.public ov29_022FBDF0 -.public ov29_022FBE04 -.public ov29_022FF908 -.public ov29_02301498 -.public ShouldAvoidFirstHit -.public ov29_02302200 -.public ov29_023082C4 -.public ov29_02348D00 -.public FACING_DIRECTION_INCREMENTS .public ov29_02353530 -.public RENDER_3D -.public RENDER_3D_FUNCTIONS -.public Rgb8ToRgb5 -.public SetActionPassTurnOrWalk -.public SetActionRegularAttack -.public SetActionStruggle -.public SetActionUseMoveAi -.public SetActionUseMoveAi -.public SetIrqFlag -.public SetMonsterActionFields -.public ShouldMonsterFollowLeader -.public ShouldMonsterHeadToStairs -.public ShouldMonsterRunAwayAndShowEffect .public sub_0201BD50 .public sub_0201BD80 .public sub_0202760C @@ -91,10 +40,3 @@ .public sub_0207A324 .public sub_02080EF0 .public sub_02080F30 -.public TargetRegularAttack -.public TRIG_TABLE -.public UpdateAiTargetPos -.public UpdateAiTargetPos -.public UpdateAiTargetPos -.public UpdateWindow -.public WINDOW_LIST diff --git a/asm/include/itcm_01FFB2C8.inc b/asm/include/itcm_01FFB2C8.inc new file mode 100644 index 00000000..6ea2e682 --- /dev/null +++ b/asm/include/itcm_01FFB2C8.inc @@ -0,0 +1,8 @@ +#pragma once +.public CanAiMonsterMoveInDirection +.public DIRECTIONS_XY +.public DUNGEON_PTR +.public DungeonRandInt +.public FACING_DIRECTION_INCREMENTS +.public GetTile +.public ov29_02301498 diff --git a/asm/itcm.s b/asm/itcm.s index 658886ca..e0a0c29d 100644 --- a/asm/itcm.s +++ b/asm/itcm.s @@ -2809,1331 +2809,3 @@ _01FFA3BC: mov r0, r4 ldmia sp!, {r3, r4, r5, pc} arm_func_end ShouldMonsterRunAwayAndShowEffectOutlawCheck - - arm_func_start AiMovement -AiMovement: ; 0x01FFA3C4 -#ifdef JAPAN -#define AI_MOVEMENT_OFFSET -4 -#define AI_MOVEMENT_OFFSET_2 -0xA4 -#else -#define AI_MOVEMENT_OFFSET 0 -#define AI_MOVEMENT_OFFSET_2 0 -#endif - stmdb sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, lr} - sub sp, sp, #0x88 - mov r4, r0 - ldr r8, [r4, #0xb4] - mov r2, #0 - strb r2, [r8, #0x7d] - str r1, [sp] - strb r2, [r8, #0x7e] - mov r1, #7 - strb r2, [r8, #0x7f] - bl IsTacticSet - cmp r0, #0 - beq _01FFA428 - ldrsh r2, [r8, #0x12] - ldrsh r1, [r8, #0x16] - ldr r0, _01FFB2AC ; =0x000003E7 - add r2, r2, r1 - cmp r2, r0 - movgt r2, r0 - ldrsh r1, [r8, #0x10] - add r0, r2, r2, lsr #31 - cmp r1, r0, asr #1 - movle r0, #0 - strleh r0, [r8, #0x4a] - ble _01FFB2A4 -_01FFA428: - mov r0, r4 - mov r1, #9 - bl IsTacticSet - cmp r0, #0 - bne _01FFA44C - mov r0, r4 - bl ov29_022FBDF0 - cmp r0, #0 - beq _01FFA458 -_01FFA44C: - mov r0, #0 - strh r0, [r8, #0x4a] - b _01FFB2A4 -_01FFA458: - ldrb r0, [r8, #7] - cmp r0, #0 - bne _01FFA494 - add r0, r8, #0x100 - ldrh r1, [r0, #0x46 + AI_MOVEMENT_OFFSET] - sub r2, sp, #4 - strh r1, [r2] - ldrh r0, [r0, #0x48 + AI_MOVEMENT_OFFSET] - strh r0, [r2, #2] - ldr r0, [r2] - bl CeilFixedPoint - cmp r0, #0 - moveq r0, #0 - streqh r0, [r8, #0x4a] - beq _01FFB2A4 -_01FFA494: - ldrb r0, [r8, #0xbc] - cmp r0, #7 - bne _01FFA4D4 - ldrsh r1, [r8, #2] - add r0, r8, #0x4a - bl SetActionPassTurnOrWalk - mov r0, #8 - bl DungeonRandInt - strb r0, [r8, #0x4c] - ldrsh r1, [r4, #4] - add r0, r8, #0x100 - strh r1, [r0, #0x7e + AI_MOVEMENT_OFFSET] - ldrsh r1, [r4, #6] - sub r1, r1, #1 - strh r1, [r0, #0x80 + AI_MOVEMENT_OFFSET] - b _01FFB2A4 -_01FFA4D4: - ldr r1, [sp] - mov r0, r4 - bl ShouldMonsterRunAwayAndShowEffectOutlawCheck - cmp r0, #0 - beq _01FFA9A8 - ldr sb, [r4, #0xb4] - ldrb r5, [r4, #0x25] - ldrb r0, [sb, #0xbc] - ldr fp, _01FFB2B0 ; =0x000F423F - cmp r0, #3 - bne _01FFA550 - mov r0, r4 - bl ShouldMonsterHeadToStairs - cmp r0, #0 - beq _01FFA550 - ldr r3, _01FFB2B4 ; =DUNGEON_PTR - add r2, sb, #0x100 - ldr r1, [r3] - mov r0, #1 - add r1, r1, #0xcc00 - ldrh r5, [r1, #0xe4 + AI_MOVEMENT_OFFSET_2] - strh r5, [sb, #0x8c] - ldrh r1, [r1, #0xe6 + AI_MOVEMENT_OFFSET_2] - strh r1, [sb, #0x8e] - ldr r1, [r3] - add r1, r1, #0xcc00 - ldrh r3, [r1, #0xe4 + AI_MOVEMENT_OFFSET_2] - strh r3, [r2, #0x7e + AI_MOVEMENT_OFFSET] - ldrh r1, [r1, #0xe6 + AI_MOVEMENT_OFFSET_2] - strh r1, [r2, #0x80 + AI_MOVEMENT_OFFSET] - b _01FFAF28 -_01FFA550: - ldr r0, _01FFB2B4 ; =DUNGEON_PTR - ldr r1, [r0] - add r0, r1, #0x3000 - ldrb r0, [r0, #0xe38 + AI_MOVEMENT_OFFSET_2] - cmp r0, #0 - beq _01FFA580 - add r0, r1, #0x378 + AI_MOVEMENT_OFFSET_2 - add r0, r0, #0x12800 - str r0, [sp, #0x2c] - mov r0, #0x14 - str r0, [sp, #0x28] - b _01FFA5C4 -_01FFA580: - ldrb r0, [sb, #6] - cmp r0, #0 - beq _01FFA5B0 - ldrb r0, [sb, #8] - cmp r0, #0 - bne _01FFA5B0 - add r0, r1, #0x328 + AI_MOVEMENT_OFFSET_2 - add r0, r0, #0x12800 - str r0, [sp, #0x2c] - mov r0, #4 - str r0, [sp, #0x28] - b _01FFA5C4 -_01FFA5B0: - add r0, r1, #0x338 + AI_MOVEMENT_OFFSET_2 - add r0, r0, #0x12800 - str r0, [sp, #0x2c] - mov r0, #0x10 - str r0, [sp, #0x28] -_01FFA5C4: - mov r0, #0xff - mov r7, #0 - str r0, [sp, #0x24] - add r0, sb, #0x100 - mov sl, r7 - str r0, [sp, #0x4c] - b _01FFA68C -_01FFA5E0: - ldr r0, [sp, #0x2c] - ldr r6, [r0, sl, lsl #2] - mov r0, r6 - bl EntityIsValid__0230827C - cmp r0, #0 - beq _01FFA688 - mov r0, r4 - mov r1, r6 - bl CanSeeTarget - cmp r0, #0 - beq _01FFA688 - ldr r0, _01FFB2B4 ; =DUNGEON_PTR - ldr r0, [r0] - add r0, r0, #0x3000 - ldrb r0, [r0, #0xe38 + AI_MOVEMENT_OFFSET_2] - cmp r0, #0 - beq _01FFA640 - mov r0, r4 - mov r1, r6 - mov r2, #0 - mov r3, #1 - bl GetTreatmentBetweenMonsters - cmp r0, #1 - bne _01FFA688 -_01FFA640: - add r0, r4, #4 - add r1, r6, #4 - bl GetChebyshevDistance - cmp fp, r0 - ble _01FFA688 - mov fp, r0 - ldrb r0, [r6, #0x25] - mov r7, r6 - str r0, [sp, #0x24] - ldrh r0, [r6, #4] - strh r0, [sb, #0x8c] - ldrh r0, [r6, #6] - strh r0, [sb, #0x8e] - ldrh r1, [r6, #4] - ldr r0, [sp, #0x4c] - strh r1, [r0, #0x7e + AI_MOVEMENT_OFFSET] - ldrh r1, [r6, #6] - strh r1, [r0, #0x80 + AI_MOVEMENT_OFFSET] -_01FFA688: - add sl, sl, #1 -_01FFA68C: - ldr r0, [sp, #0x28] - cmp sl, r0 - blt _01FFA5E0 - ldr r0, _01FFB2B0 ; =0x000F423F - cmp fp, r0 - beq _01FFA99C - ldr r0, [sp, #0x24] - cmp r5, r0 - bne _01FFA96C - cmp r5, #0xff - beq _01FFA96C - ldrsh r0, [r4, #4] - ldrsh r1, [r4, #6] - bl GetTile - ldrh r0, [r0] - tst r0, #8 - beq _01FFA7C0 - ldrsh r1, [r4, #4] - ldrsh r0, [r4, #6] - mov r7, #0 - strh r1, [sp, #0x52] - strh r0, [sp, #0x54] - add sl, sp, #0x51 - ldr r6, _01FFB2B8 ; =DIRECTIONS_XY - b _01FFA74C -_01FFA6F0: - mov r1, r7, lsl #2 - add r0, r6, r7, lsl #2 - ldrsh r3, [r4, #4] - ldrsh r2, [r6, r1] - ldrsh r1, [r4, #6] - ldrsh r0, [r0, #2] - add r2, r3, r2 - strh r2, [sp, #0x52] - add r0, r1, r0 - strh r0, [sp, #0x54] - ldrsh r0, [sp, #0x52] - ldrsh r1, [sp, #0x54] - bl GetTile - ldrb r0, [r0, #7] - cmp r5, r0 - beq _01FFA748 - mov r0, r4 - mov r1, r7 - mov r2, sl - bl CanAiMonsterMoveInDirection - cmp r0, #0 - bne _01FFA754 -_01FFA748: - add r7, r7, #1 -_01FFA74C: - cmp r7, #8 - blt _01FFA6F0 -_01FFA754: - cmp r7, #8 - bne _01FFA7A0 - mov r0, #8 - bl DungeonRandInt - mov r1, #6 - strb r1, [sb, #0x7c] - mov r3, r0, lsl #2 - ldr r0, _01FFB2B8 ; =DIRECTIONS_XY - ldrsh r5, [r4, #4] - ldrsh r2, [r0, r3] - ldr r1, _01FFB2BC ; =DIRECTIONS_XY + 2 - mov r0, #1 - add r2, r5, r2 - strh r2, [sb, #0x8c] - ldrsh r2, [r4, #6] - ldrsh r1, [r1, r3] - add r1, r2, r1 - strh r1, [sb, #0x8e] - b _01FFAF28 -_01FFA7A0: - ldrh r0, [sp, #0x52] - mov r1, #5 - strb r1, [sb, #0x7c] - ldrh r1, [sp, #0x54] - strh r0, [sb, #0x8c] - mov r0, #1 - strh r1, [sb, #0x8e] - b _01FFAF28 -_01FFA7C0: - ldr r0, _01FFB2B4 ; =DUNGEON_PTR - ldrsh sl, [r4, #6] - ldr r1, [r0] - ldrsh r2, [r7, #6] - add r0, r1, #0x2a8 + AI_MOVEMENT_OFFSET_2 - add r1, r1, r5, lsl #1 -#ifdef JAPAN - add r1, r1, #0xf100 - ldrsh r1, [r1, #0xc4] -#else - add r1, r1, #0xf200 - ldrsh r1, [r1, #0x68] -#endif - add r3, r0, #0xf000 - sub r0, r2, sl - str r1, [sp, #0x30] - ldr r1, _01FFB2C0 ; =0xFFF0BDC1 - add r6, r3, r5, lsl #7 - str r1, [sp, #0x38] - mov r1, #0 - str r1, [sp, #0x34] - bl abs - ldrsh fp, [r4, #4] - ldrsh r1, [r7, #4] - mov r5, r0 - sub r0, r1, fp - bl abs - str r0, [sp, #8] - cmp r0, r5 - mvn r0, #0 - strle r5, [sp, #8] - mov r5, #0 - str r0, [sp, #0x44] - b _01FFA924 -_01FFA834: - add r0, r6, r5, lsl #2 - ldrsh r0, [r0, #2] - ldrsh r1, [r7, #6] - str r0, [sp, #0x10] - sub r0, r1, r0 - str r1, [sp, #0xc] - bl abs - str r0, [sp, #0x40] - mov r0, r5, lsl #2 - ldrsh r0, [r6, r0] - ldrsh r1, [r7, #4] - str r0, [sp, #0x18] - sub r0, r1, r0 - str r1, [sp, #0x14] - bl abs - ldr r1, [sp, #0x40] - str r0, [sp, #4] - cmp r0, r1 - movle r0, r1 - strle r0, [sp, #4] - ldr r0, [sp, #0x18] - ldr r1, [sp, #0x44] - sub r0, r0, fp - str r0, [sp, #0x3c] - ldr r2, [sp, #0x3c] - ldr r0, [sp, #0x10] - cmp r2, r1 - strlt r1, [sp, #0x3c] - ldr r1, [sp, #0x44] - sub r0, r0, sl - cmp r0, r1 - movlt r0, r1 - ldr r1, [sp, #0x3c] - cmp r1, #1 - movgt r1, #1 - strgt r1, [sp, #0x3c] - cmp r0, #1 - movgt r0, #1 - add r1, sl, r0 - ldr r0, [sp, #0xc] - sub r0, r0, r1 - bl abs - ldr r1, [sp, #0x3c] - str r0, [sp, #0x48] - ldr r0, [sp, #0x14] - add r1, fp, r1 - sub r0, r0, r1 - bl abs - ldr r1, [sp, #0x48] - cmp r0, r1 - movle r0, r1 - ldr r1, [sp, #8] - cmp r0, r1 - blt _01FFA920 - ldr r1, [sp, #0x38] - ldr r0, [sp, #4] - cmp r1, r0 - strlt r0, [sp, #0x38] - strlt r5, [sp, #0x34] -_01FFA920: - add r5, r5, #1 -_01FFA924: - ldr r0, [sp, #0x30] - cmp r5, r0 - blt _01FFA834 - ldr r0, [sp, #0x38] - cmp r0, #0 - blt _01FFA96C - mov r0, #5 - strb r0, [sb, #0x7c] - ldr r0, [sp, #0x34] - mov r0, r0, lsl #2 - ldrsh r2, [r6, r0] - ldr r0, [sp, #0x34] - add r1, r6, r0, lsl #2 - strh r2, [sb, #0x8c] - ldrsh r1, [r1, #2] - mov r0, #1 - strh r1, [sb, #0x8e] - b _01FFAF28 -_01FFA96C: - mov r0, #5 - strb r0, [sb, #0x7c] - ldrsh r2, [r4, #4] - ldrsh r1, [r7, #4] - mov r0, #1 - rsb r1, r1, r2, lsl #1 - strh r1, [sb, #0x8c] - ldrsh r2, [r4, #6] - ldrsh r1, [r7, #6] - rsb r1, r1, r2, lsl #1 - strh r1, [sb, #0x8e] - b _01FFAF28 -_01FFA99C: - mov r0, r4 - bl CalculateAiTargetPos - b _01FFAF28 -_01FFA9A8: - mov r0, r4 - ldr r7, [r4, #0xb4] - bl EntityIsValid__0230827C - cmp r0, #0 - moveq r0, #0 - beq _01FFAAB8 - mov r0, r4 - bl CheckVariousConditions - cmp r0, #0 - movne r0, #0 - bne _01FFAAB8 - mov r0, r4 - bl GetTileAtEntity - mov r5, r0 - ldr r6, [r5, #0x10] - cmp r6, #0 - moveq r0, #0 - beq _01FFAAB8 - ldr r0, [r6] - cmp r0, #6 - addls pc, pc, r0, lsl #2 - b _01FFAAB4 -_01FFAA00: ; jump table - b _01FFAAB4 ; case 0 - b _01FFAAB4 ; case 1 - b _01FFAAB4 ; case 2 - b _01FFAA1C ; case 3 - b _01FFAAB4 ; case 4 - b _01FFAAB4 ; case 5 - b _01FFAAB4 ; case 6 -_01FFAA1C: - ldrb r0, [r7, #7] - cmp r0, #0 - bne _01FFAAB4 - ldrb r0, [r7, #0x62] - tst r0, #1 - movne r0, #1 - moveq r0, #0 - tst r0, #0xff - bne _01FFAAB4 - ldrh r0, [r5] - tst r0, #3 - bne _01FFAA58 - ldrb r0, [r7, #6] - cmp r0, #0 - bne _01FFAAB4 -_01FFAA58: - ldrb r0, [r7, #6] - cmp r0, #0 - bne _01FFAA84 - bl IsBagFull - cmp r0, #0 - bne _01FFAAB4 - ldrh r0, [r5] - tst r0, #0x20 - bne _01FFAAB4 - mov r0, #1 - b _01FFAAB8 -_01FFAA84: - mov r0, r6 - bl GetItemInfo - bl ov29_02348D00 - cmp r0, #0 - movne r0, #0 - bne _01FFAAB8 - mov r0, r6 - bl GetItemInfo - ldrb r0, [r0] - tst r0, #2 - moveq r0, #1 - beq _01FFAAB8 -_01FFAAB4: - mov r0, #0 -_01FFAAB8: - cmp r0, #0 - movne r0, #0x3f - strneh r0, [r8, #0x4a] - bne _01FFB2A4 - mov r0, r4 - ldr sl, [r4, #0xb4] - bl ShouldMonsterFollowLeader - cmp r0, #0 - bne _01FFAD14 - ldr r0, _01FFB2B4 ; =DUNGEON_PTR - ldr r1, [r0] - add r0, r1, #0x3000 - ldrb r0, [r0, #0xe38 + AI_MOVEMENT_OFFSET_2] - cmp r0, #0 - addne r0, r1, #0x378 + AI_MOVEMENT_OFFSET_2 - addne sb, r0, #0x12800 - movne fp, #0x14 - bne _01FFAB30 - ldrb r0, [sl, #6] - cmp r0, #0 - beq _01FFAB24 - ldrb r0, [sl, #8] - cmp r0, #0 - addeq r0, r1, #0x328 + AI_MOVEMENT_OFFSET_2 - addeq sb, r0, #0x12800 - moveq fp, #4 - beq _01FFAB30 -_01FFAB24: - add r0, r1, #0x338 + AI_MOVEMENT_OFFSET_2 - add sb, r0, #0x12800 - mov fp, #0x10 -_01FFAB30: - mov r0, r4 - bl ov29_022FF908 - mvn r6, #0 - str r0, [sp, #0x20] - add r0, r6, #0x3e8 - str r0, [sp, #0x1c] - mov r7, #0 - b _01FFAC64 -_01FFAB50: - ldr r5, [sb, r7, lsl #2] - mov r0, r5 - bl EntityIsValid__0230827C - cmp r0, #0 - beq _01FFAC60 - ldr r0, [r5, #0xb4] - ldrb r1, [r0, #0xbc] - cmp r1, #6 - bhi _01FFAC60 - ldr r1, _01FFB2B4 ; =DUNGEON_PTR - ldr r1, [r1] - add r1, r1, #0x3000 - ldrb r1, [r1, #0xe38 + AI_MOVEMENT_OFFSET_2] - cmp r1, #0 - beq _01FFABAC - mov r0, r4 - mov r1, r5 - mov r2, #0 - mov r3, #1 - bl GetTreatmentBetweenMonsters - cmp r0, #1 - bne _01FFAC60 - b _01FFABC0 -_01FFABAC: - ldrb r1, [sl, #6] - cmp r1, #0 - ldreqb r0, [r0, #0xc4] - cmpeq r0, #6 - beq _01FFAC60 -_01FFABC0: - ldr r0, [r5, #0xb4] - ldrb r0, [r0, #9] - cmp r0, #1 - beq _01FFAC60 - ldr r0, [sp, #0x20] - cmp r0, #0 - beq _01FFAC24 - ldrsh r1, [r4, #4] - ldrsh r0, [r5, #4] - sub r0, r1, r0 - bl abs - cmp r0, #5 - bgt _01FFAC0C - ldrsh r1, [r4, #6] - ldrsh r0, [r5, #6] - sub r0, r1, r0 - bl abs - cmp r0, #5 - ble _01FFAC38 -_01FFAC0C: - mov r0, r4 - mov r1, r5 - bl CanTargetEntity - cmp r0, #0 - beq _01FFAC60 - b _01FFAC38 -_01FFAC24: - mov r0, r4 - mov r1, r5 - bl CanTargetEntity - cmp r0, #0 - beq _01FFAC60 -_01FFAC38: - add r1, r5, #4 - add r0, r4, #4 - bl GetChebyshevDistance - ldr r1, [sp, #0x1c] - cmp r1, r0 - ble _01FFAC60 - str r0, [sp, #0x1c] - mov r6, r7 - cmp r0, #2 - blt _01FFAC6C -_01FFAC60: - add r7, r7, #1 -_01FFAC64: - cmp r7, fp - blt _01FFAB50 -_01FFAC6C: - cmp r6, #0 - blt _01FFAD14 - mov r2, #1 - strb r2, [sl, #0x7c] - ldr r7, [sb, r6, lsl #2] - mov r0, r4 - ldrh r5, [r7, #4] - mov r3, #0 - mov r1, #8 - strh r5, [sl, #0x8c] - ldrh r5, [r7, #6] - strh r5, [sl, #0x8e] - ldr r5, [sb, r6, lsl #2] - str r5, [sl, #0x84] - ldr r5, [sb, r6, lsl #2] - ldrh r5, [r5, #0x26] - strh r5, [sl, #0x80] - strb r2, [sl, #0x7e] - str r3, [sl, #0x120 + AI_MOVEMENT_OFFSET] - bl IsTacticSet - cmp r0, #0 - beq _01FFAD0C - mov r0, r4 - bl ov29_02302200 - cmp r0, #0 - bne _01FFAD0C - ldr r5, [sb, r6, lsl #2] - ldrsh r1, [r4, #4] - ldrsh r0, [r5, #4] - sub r0, r1, r0 - bl abs - cmp r0, #1 - bgt _01FFAD0C - ldrsh r1, [r4, #6] - ldrsh r0, [r5, #6] - sub r0, r1, r0 - bl abs - cmp r0, #1 - movle r0, #1 - strleb r0, [sl, #0x7f] -_01FFAD0C: - mov r0, #1 - b _01FFAF28 -_01FFAD14: - mov r0, r4 - mov r1, #1 - bl IsTacticSet - cmp r0, #0 - bne _01FFAD7C - ldrb r0, [sl, #6] - cmp r0, #0 - bne _01FFAE68 - mov r0, r4 - bl ov29_023082C4 - mov r5, r0 - bl EntityIsValid__0230827C - cmp r0, #0 - beq _01FFAE68 - mov r0, #1 - strb r0, [sl, #0x7c] - ldrh r2, [r5, #4] - mov r1, #0 - strh r2, [sl, #0x8c] - ldrh r2, [r5, #6] - strh r2, [sl, #0x8e] - str r5, [sl, #0x84] - ldrh r2, [r5, #0x26] - strh r2, [sl, #0x80] - str r1, [sl, #0x120 + AI_MOVEMENT_OFFSET] - b _01FFAF28 -_01FFAD7C: - ldrb r0, [sl, #7] - cmp r0, #0 - beq _01FFAE68 - bl GetVisibilityRange - ldrsh r0, [r4, #4] - ldrsh r1, [r4, #6] - bl GetTile - ldrb r2, [r0, #7] - cmp r2, #0xff - bne _01FFADC0 - ldrsh r1, [r4, #4] - ldrsh r0, [r4, #6] - sub fp, r1, #2 - sub sb, r0, #2 - add r6, r1, #2 - add r5, r0, #2 - b _01FFAE60 -_01FFADC0: - ldr r0, _01FFB2B4 ; =DUNGEON_PTR - mov r1, #0x1c - ldr r0, [r0] - add r0, r0, #0x2e8 + AI_MOVEMENT_OFFSET_2 - add r0, r0, #0xec00 - mla r0, r2, r1, r0 - ldrsh r3, [r0, #2] - ldrsh r2, [r0, #4] - ldrsh r1, [r0, #6] - ldrsh r0, [r0, #8] - sub fp, r3, #1 - sub sb, r2, #1 - add r6, r1, #1 - add r5, r0, #1 - b _01FFAE60 -_01FFADFC: - mov r7, fp - b _01FFAE54 -_01FFAE04: - mov r0, r7 - mov r1, sb - bl GetTileSafe - ldr r0, [r0, #0x10] - cmp r0, #0 - beq _01FFAE50 - ldr r0, [r0] - cmp r0, #3 - bne _01FFAE50 - mov r0, #7 - strb r0, [sl, #0x7c] - strh r7, [sl, #0x8c] - strh sb, [sl, #0x8e] - mov r0, #0 - str r0, [sl, #0x84] - strh r0, [sl, #0x80] - str r0, [sl, #0x120 + AI_MOVEMENT_OFFSET] - mov r0, #1 - b _01FFAF28 -_01FFAE50: - add r7, r7, #1 -_01FFAE54: - cmp r7, r6 - ble _01FFAE04 - add sb, sb, #1 -_01FFAE60: - cmp sb, r5 - ble _01FFADFC -_01FFAE68: - mov r0, r4 - bl HasDropeyeStatus - cmp r0, #0 - bne _01FFAF1C - ldrb r0, [sl, #0x7c] - add r0, r0, #0xff - and r0, r0, #0xff - cmp r0, #1 - bhi _01FFAF1C - ldr r2, [sl, #0x84] - cmp r2, #0 - beq _01FFAF1C - ldrh r1, [r2, #0x26] - ldrh r0, [sl, #0x80] - cmp r1, r0 - bne _01FFAF08 - ldr r7, [r2, #0xb4] - mov r6, #0 - add r5, r7, #0x6a - b _01FFAEFC -_01FFAEB8: - mov r0, r4 - add r1, r5, r6, lsl #2 - bl CanTargetPosition - cmp r0, #0 - beq _01FFAEF8 - mov r0, #2 - strb r0, [sl, #0x7c] - add r3, r7, r6, lsl #2 - ldrh r2, [r3, #0x6a] - mov r1, #0 - mov r0, #1 - strh r2, [sl, #0x8c] - ldrh r2, [r3, #0x6c] - strh r2, [sl, #0x8e] - str r1, [sl, #0x120 + AI_MOVEMENT_OFFSET] - b _01FFAF28 -_01FFAEF8: - add r6, r6, #1 -_01FFAEFC: - cmp r6, #4 - blt _01FFAEB8 - b _01FFAF1C -_01FFAF08: - mov r0, #6 - strb r0, [sl, #0x7c] - mov r0, #0 - str r0, [sl, #0x84] - strh r0, [sl, #0x80] -_01FFAF1C: - mov r0, r4 - bl CalculateAiTargetPos - mov r0, #1 -_01FFAF28: - cmp r0, #0 - moveq r0, #0 - streqh r0, [r8, #0x4a] - beq _01FFB2A4 - ldr sb, [r4, #0xb4] - ldrh r1, [sb, #0x8c] - add r0, sb, #0x100 - strh r1, [r0, #0x7e + AI_MOVEMENT_OFFSET] - ldrh r1, [sb, #0x8e] - strh r1, [r0, #0x80 + AI_MOVEMENT_OFFSET] - ldrsh r1, [r4, #4] - ldrsh r0, [sb, #0x8c] - cmp r1, r0 - ldreqsh r1, [r4, #6] - ldreqsh r0, [sb, #0x8e] - cmpeq r1, r0 - bne _01FFAF7C - add r0, sb, #0x4a - mov r1, #1 - bl SetMonsterActionFields - b _01FFB2A4 -_01FFAF7C: - mov r0, sb - bl ov29_022FBE04 - cmp r0, #0 - bne _01FFB2A4 - add r0, r4, #4 - add r1, sb, #0x8c - bl GetDirectionTowardsPosition - mov r7, r0 - ldrb r1, [sb, #0x7e] - mov r0, r4 - bl ShouldAvoidFirstHit - cmp r0, #0 - beq _01FFB000 - ldrb r0, [sb, #0x7c] - cmp r0, #1 - bne _01FFB010 - add r0, r4, #4 - add r1, sb, #0x8c - bl IsPositionWithinTwoTiles - cmp r0, #0 - beq _01FFB010 - add r0, r4, #4 - add r1, sb, #0x8c - bl GetChebyshevDistance - cmp r0, #2 - bne _01FFAFF4 - add r0, sb, #0x4a - mov r1, #1 - bl SetMonsterActionFields - b _01FFB2A4 -_01FFAFF4: - addlt r0, r7, #4 - andlt r7, r0, #7 - b _01FFB010 -_01FFB000: - ldrb r0, [sb, #0x7f] - cmp r0, #0 - addne r0, r7, #4 - andne r7, r0, #7 -_01FFB010: - add r2, sp, #0x50 - mov r0, r4 - mov r1, r7 - bl CanAiMonsterMoveInDirection - cmp r0, #0 - beq _01FFB040 - ldrsh r1, [sb, #2] - add r0, sb, #0x4a - bl SetActionPassTurnOrWalk - and r0, r7, #7 - strb r0, [sb, #0x4c] - b _01FFB2A4 -_01FFB040: - ldrb r0, [sp, #0x50] - cmp r0, #0 - beq _01FFB0DC - ldrb r0, [sb, #6] - cmp r0, #0 - ldreqb r0, [sb, #0x14f + AI_MOVEMENT_OFFSET] - cmpeq r0, #0 - bne _01FFB080 - mov r1, #1 - strb r1, [sb, #0x7d] - add r0, sb, #0x4a - strb r1, [sb, #0x14e + AI_MOVEMENT_OFFSET] - bl SetMonsterActionFields - mov r0, #1 - strb r0, [sb, #0x151 + AI_MOVEMENT_OFFSET] - b _01FFB2A4 -_01FFB080: - ldr r0, _01FFB2B8 ; =DIRECTIONS_XY - mov r2, r7, lsl #2 - ldrsh r1, [r4, #4] - ldrsh r0, [r0, r2] - ldrsh r3, [sb, #0x8c] - add r0, r1, r0 - cmp r3, r0 - bne _01FFB0D4 - ldr r0, _01FFB2BC ; =DIRECTIONS_XY + 2 - ldrsh r1, [r4, #6] - ldrsh r0, [r0, r2] - ldrsh r2, [sb, #0x8e] - add r0, r1, r0 - cmp r2, r0 - bne _01FFB0D4 - add r0, sb, #0x4a - mov r1, #1 - bl SetMonsterActionFields - mov r0, #1 - strb r0, [sb, #0x151 + AI_MOVEMENT_OFFSET] - b _01FFB2A4 -_01FFB0D4: - mov r0, #1 - strb r0, [sb, #0x7d] -_01FFB0DC: - mov r0, #1 - strb r0, [sp, #0x80] - strb r0, [sp, #0x78] - strb r0, [sp, #0x70] - strb r0, [sp, #0x68] - strb r0, [sp, #0x60] - ldrb r0, [sb, #6] - cmp r0, #0 - bne _01FFB16C - tst r7, #1 - beq _01FFB16C - ldrsh r1, [r4, #4] - ldrsh r0, [sb, #0x8c] - sub r0, r1, r0 - bl abs - ldrsh r2, [r4, #6] - ldrsh r1, [sb, #0x8e] - mov r5, r0 - sub r0, r2, r1 - bl abs - cmp r5, #2 - cmple r0, #2 - bgt _01FFB16C - cmp r5, r0 - beq _01FFB16C - tst r7, #2 - beq _01FFB15C - cmp r5, r0 - mov r0, #0 - strltb r0, [sp, #0x68] - strgeb r0, [sp, #0x60] - b _01FFB16C -_01FFB15C: - cmp r5, r0 - mov r0, #0 - strltb r0, [sp, #0x60] - strgeb r0, [sp, #0x68] -_01FFB16C: - ldrsh r0, [r4, #4] - ldrsh r1, [r4, #6] - bl GetTile - ldrh r0, [r0] - ldr r1, [sp] - tst r0, #0x100 - movne sl, #5 - mov r0, r4 - moveq sl, #3 - bl ShouldMonsterRunAwayAndShowEffectOutlawCheck - cmp r0, #0 - ldreqb r0, [sb, #0x7f] - mov r8, #1 - mov fp, r8 - cmpeq r0, #0 - movne sl, #5 - ldr r6, _01FFB2C4 ; =FACING_DIRECTION_INCREMENTS - add r5, sp, #0x58 - b _01FFB1FC -_01FFB1B8: - ldr r0, [r6, r8, lsl #2] - add r3, r5, r8, lsl #3 - add r0, r7, r0 - and r1, r0, #7 - mov r0, r4 - add r2, r3, #2 - str r1, [r3, #4] - bl CanAiMonsterMoveInDirection - add r1, r5, r8, lsl #3 - strb r0, [r1, #1] - tst r0, #0xff - ldreqb r0, [r1, #2] - add r8, r8, #1 - cmpeq r0, #0 - andeq r0, fp, #0xff - streqb fp, [sp, #0x68] - streqb r0, [sp, #0x60] -_01FFB1FC: - cmp r8, sl - blt _01FFB1B8 - mov r4, #1 - add r2, sp, #0x58 - mov r0, r4 - b _01FFB264 -_01FFB214: - add r1, r2, r4, lsl #3 - ldrb r1, [r1, #1] - mov r3, r4, lsl #3 - cmp r1, #0 - ldrneb r1, [r2, r3] - cmpne r1, #0 - beq _01FFB250 - ldrsh r1, [sb, #2] - add r0, sb, #0x4a - bl SetActionPassTurnOrWalk - add r0, sp, #0x5c - ldr r0, [r0, r4, lsl #3] - and r0, r0, #7 - strb r0, [sb, #0x4c] - b _01FFB2A4 -_01FFB250: - add r1, r2, r4, lsl #3 - ldrb r1, [r1, #2] - add r4, r4, #1 - cmp r1, #0 - strneb r0, [sb, #0x7d] -_01FFB264: - cmp r4, sl - blt _01FFB214 - add r0, sb, #0x4a - mov r1, #1 - bl SetMonsterActionFields - mov r1, #1 - strb r1, [sb, #0x151 + AI_MOVEMENT_OFFSET] - ldrb r0, [sb, #7] - cmp r0, #0 - movne r0, #0 - strneb r0, [sb, #0x7d] - strneb r0, [sb, #0x14e + AI_MOVEMENT_OFFSET] - bne _01FFB2A4 - ldrb r0, [sb, #0x7d] - cmp r0, #0 - strneb r1, [sb, #0x14e + AI_MOVEMENT_OFFSET] -_01FFB2A4: - add sp, sp, #0x88 - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} - .align 2, 0 -_01FFB2AC: .word 0x000003E7 -_01FFB2B0: .word 0x000F423F -_01FFB2B4: .word DUNGEON_PTR -_01FFB2B8: .word DIRECTIONS_XY -_01FFB2BC: .word DIRECTIONS_XY + 2 -_01FFB2C0: .word 0xFFF0BDC1 -_01FFB2C4: .word FACING_DIRECTION_INCREMENTS - arm_func_end AiMovement - - arm_func_start CalculateAiTargetPos -CalculateAiTargetPos: ; 0x01FFB2C8 - stmdb sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, lr} - ldr r1, _01FFB61C ; =DUNGEON_PTR - mov sl, r0 - ldr r0, [r1] - ldr sb, [sl, #0xb4] - add r0, r0, #0x4000 -#ifdef JAPAN - ldrb r0, [r0, #0x36] -#else - ldrb r0, [r0, #0xda] -#endif - ldrb r4, [sl, #0x25] - mov r5, #0 - cmp r0, #0xa5 - beq _01FFB304 - cmp r0, #0xaa - blo _01FFB31C - cmp r0, #0xdc - bhs _01FFB31C -_01FFB304: - ldrsh r0, [sl, #4] - ldrsh r1, [sl, #6] - bl GetTile - ldrh r0, [r0] - tst r0, #0x100 - movne r5, #1 -_01FFB31C: - cmp r5, #0 - bne _01FFB32C - cmp r4, #0xff - bne _01FFB3F0 -_01FFB32C: - ldrb r1, [sb, #0x4c] - mov r0, sl - mov r7, #0 - add r1, r1, #4 - and r6, r1, #7 - bl ov29_02301498 - cmp r0, #0 - beq _01FFB35C - mov r0, #8 - bl DungeonRandInt - strb r0, [sb, #0x4c] - mov r7, #1 -_01FFB35C: - mov r5, #0 - ldr r4, _01FFB620 ; =FACING_DIRECTION_INCREMENTS - add fp, sp, #1 - b _01FFB3E4 -_01FFB36C: - ldrb r1, [sb, #0x4c] - ldr r0, [r4, r5, lsl #2] - cmp r7, #0 - add r0, r1, r0 - and r8, r0, #7 - beq _01FFB38C - cmp r8, r6 - beq _01FFB3E0 -_01FFB38C: - mov r0, sl - mov r1, r8 - mov r2, fp - bl CanAiMonsterMoveInDirection - cmp r0, #0 - beq _01FFB3E0 - mov r0, #3 - strb r0, [sb, #0x7c] - ldr r0, _01FFB624 ; =DIRECTIONS_XY - mov r3, r8, lsl #2 - ldrsh r2, [r0, r3] - ldrsh r4, [sl, #4] - ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2 - mov r0, #1 - add r2, r4, r2 - strh r2, [sb, #0x8c] - ldrsh r2, [sl, #6] - ldrsh r1, [r1, r3] - add r1, r2, r1 - strh r1, [sb, #0x8e] - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} -_01FFB3E0: - add r5, r5, #1 -_01FFB3E4: - cmp r5, #8 - blt _01FFB36C - b _01FFB5D8 -_01FFB3F0: - ldr r0, _01FFB61C ; =DUNGEON_PTR -#ifdef JAPAN - ldr r1, [sb, #0x11c] - ldr r2, [r0] - cmp r1, #0 - add r0, r2, r4, lsl #1 - add r1, r2, #0x204 - add r0, r0, #0xf100 - add r1, r1, #0xf000 - add r6, r1, r4, lsl #7 - ldrsh r5, [r0, #0xc4] -#else - ldr r1, [sb, #0x120] - ldr r2, [r0] - cmp r1, #0 - add r0, r2, r4, lsl #1 - add r1, r2, #0x2a8 - add r0, r0, #0xf200 - add r1, r1, #0xf000 - add r6, r1, r4, lsl #7 - ldrsh r5, [r0, #0x68] -#endif - beq _01FFB460 - mov r0, #8 - bl DungeonRandInt - mov r1, #6 - strb r1, [sb, #0x7c] - mov r3, r0, lsl #2 - ldr r0, _01FFB624 ; =DIRECTIONS_XY - ldrsh r4, [sl, #4] - ldrsh r2, [r0, r3] - ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2 - mov r0, #1 - add r2, r4, r2 - strh r2, [sb, #0x8c] - ldrsh r2, [sl, #6] - ldrsh r1, [r1, r3] - add r1, r2, r1 - strh r1, [sb, #0x8e] - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} -_01FFB460: - ldrb r0, [sb, #0x7c] - cmp r0, #4 - beq _01FFB520 - cmp r5, #0 - bne _01FFB4B8 - mov r0, #8 - bl DungeonRandInt - mov r1, #6 - strb r1, [sb, #0x7c] - mov r3, r0, lsl #2 - ldr r0, _01FFB624 ; =DIRECTIONS_XY - ldrsh r4, [sl, #4] - ldrsh r2, [r0, r3] - ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2 - mov r0, #1 - add r2, r4, r2 - strh r2, [sb, #0x8c] - ldrsh r2, [sl, #6] - ldrsh r1, [r1, r3] - add r1, r2, r1 - strh r1, [sb, #0x8e] - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} -_01FFB4B8: - mov r4, #0 - b _01FFB518 -_01FFB4C0: - mov r0, r5 - bl DungeonRandInt - mov r2, r0, lsl #2 - ldrsh r3, [sl, #4] - ldrsh r1, [r6, r2] - cmp r3, r1 - addeq r1, r6, r2 - ldreqsh r2, [sl, #6] - ldreqsh r1, [r1, #2] - cmpeq r2, r1 - beq _01FFB514 - mov r1, #4 - strb r1, [sb, #0x7c] - mov r1, r0, lsl #2 - ldrsh r2, [r6, r1] - add r1, r6, r0, lsl #2 - mov r0, #1 - strh r2, [sb, #0x8c] - ldrsh r1, [r1, #2] - strh r1, [sb, #0x8e] - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} -_01FFB514: - add r4, r4, #1 -_01FFB518: - cmp r4, #0xa - blt _01FFB4C0 -_01FFB520: - ldrsh r0, [sl, #4] - ldrsh r1, [sl, #6] - bl GetTile - ldrh r0, [r0] - tst r0, #8 - beq _01FFB5D0 - mov r0, #8 - bl DungeonRandInt - mov r8, r0 - mov r5, #0 - add fp, sp, #0 - ldr r4, _01FFB624 ; =DIRECTIONS_XY - b _01FFB5C8 -_01FFB554: - and r8, r8, #7 - mov r1, r8, lsl #2 - add r0, r4, r8, lsl #2 - ldrsh r6, [sl, #4] - ldrsh r3, [r4, r1] - ldrsh r2, [sl, #6] - ldrsh r1, [r0, #2] - add r6, r6, r3 - mov r0, r6 - add r7, r2, r1 - mov r1, r7 - bl GetTile - ldrb r0, [r0, #7] - cmp r0, #0xff - bne _01FFB5C0 - mov r0, sl - mov r1, r8 - mov r2, fp - bl CanAiMonsterMoveInDirection - cmp r0, #0 - beq _01FFB5C0 - mov r0, #3 - strb r0, [sb, #0x7c] - strh r6, [sb, #0x8c] - strh r7, [sb, #0x8e] - mov r0, #1 - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} -_01FFB5C0: - add r5, r5, #1 - add r8, r8, #1 -_01FFB5C8: - cmp r5, #8 - blt _01FFB554 -_01FFB5D0: - mov r0, #1 - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} -_01FFB5D8: - mov r0, #8 - bl DungeonRandInt - mov r1, #6 - strb r1, [sb, #0x7c] - mov r3, r0, lsl #2 - ldr r0, _01FFB624 ; =DIRECTIONS_XY - ldrsh r4, [sl, #4] - ldrsh r2, [r0, r3] - ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2 - mov r0, #1 - add r2, r4, r2 - strh r2, [sb, #0x8c] - ldrsh r2, [sl, #6] - ldrsh r1, [r1, r3] - add r1, r2, r1 - strh r1, [sb, #0x8e] - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} - .align 2, 0 -_01FFB61C: .word DUNGEON_PTR -_01FFB620: .word FACING_DIRECTION_INCREMENTS -_01FFB624: .word DIRECTIONS_XY -_01FFB628: .word DIRECTIONS_XY + 2 - arm_func_end CalculateAiTargetPos - - arm_func_start sub_01FFB62C -sub_01FFB62C: ; 0x01FFB62C - ldr r3, [r0, #0xb4] - mov r2, #0 - strb r2, [r3, #0x7c] - ldrh r1, [r0, #4] - strh r1, [r3, #0x8c] - ldrh r0, [r0, #6] - strh r0, [r3, #0x8e] - str r2, [r3, #0x84] - strh r2, [r3, #0x80] - bx lr - arm_func_end sub_01FFB62C - - .global _01FFB654 -_01FFB654: - .byte 0x05, 0x03, 0x00, 0x00 diff --git a/asm/itcm_01FFB2C8.s b/asm/itcm_01FFB2C8.s new file mode 100644 index 00000000..7e53f2cf --- /dev/null +++ b/asm/itcm_01FFB2C8.s @@ -0,0 +1,280 @@ + .include "asm/macros.inc" + .include "itcm_01FFB2C8.inc" + + .section .itcm,4,1,4 + + arm_func_start CalculateAiTargetPos +CalculateAiTargetPos: ; 0x01FFB2C8 + stmdb sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, lr} + ldr r1, _01FFB61C ; =DUNGEON_PTR + mov sl, r0 + ldr r0, [r1] + ldr sb, [sl, #0xb4] + add r0, r0, #0x4000 +#ifdef JAPAN + ldrb r0, [r0, #0x36] +#else + ldrb r0, [r0, #0xda] +#endif + ldrb r4, [sl, #0x25] + mov r5, #0 + cmp r0, #0xa5 + beq _01FFB304 + cmp r0, #0xaa + blo _01FFB31C + cmp r0, #0xdc + bhs _01FFB31C +_01FFB304: + ldrsh r0, [sl, #4] + ldrsh r1, [sl, #6] + bl GetTile + ldrh r0, [r0] + tst r0, #0x100 + movne r5, #1 +_01FFB31C: + cmp r5, #0 + bne _01FFB32C + cmp r4, #0xff + bne _01FFB3F0 +_01FFB32C: + ldrb r1, [sb, #0x4c] + mov r0, sl + mov r7, #0 + add r1, r1, #4 + and r6, r1, #7 + bl ov29_02301498 + cmp r0, #0 + beq _01FFB35C + mov r0, #8 + bl DungeonRandInt + strb r0, [sb, #0x4c] + mov r7, #1 +_01FFB35C: + mov r5, #0 + ldr r4, _01FFB620 ; =FACING_DIRECTION_INCREMENTS + add fp, sp, #1 + b _01FFB3E4 +_01FFB36C: + ldrb r1, [sb, #0x4c] + ldr r0, [r4, r5, lsl #2] + cmp r7, #0 + add r0, r1, r0 + and r8, r0, #7 + beq _01FFB38C + cmp r8, r6 + beq _01FFB3E0 +_01FFB38C: + mov r0, sl + mov r1, r8 + mov r2, fp + bl CanAiMonsterMoveInDirection + cmp r0, #0 + beq _01FFB3E0 + mov r0, #3 + strb r0, [sb, #0x7c] + ldr r0, _01FFB624 ; =DIRECTIONS_XY + mov r3, r8, lsl #2 + ldrsh r2, [r0, r3] + ldrsh r4, [sl, #4] + ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2 + mov r0, #1 + add r2, r4, r2 + strh r2, [sb, #0x8c] + ldrsh r2, [sl, #6] + ldrsh r1, [r1, r3] + add r1, r2, r1 + strh r1, [sb, #0x8e] + ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} +_01FFB3E0: + add r5, r5, #1 +_01FFB3E4: + cmp r5, #8 + blt _01FFB36C + b _01FFB5D8 +_01FFB3F0: + ldr r0, _01FFB61C ; =DUNGEON_PTR +#ifdef JAPAN + ldr r1, [sb, #0x11c] + ldr r2, [r0] + cmp r1, #0 + add r0, r2, r4, lsl #1 + add r1, r2, #0x204 + add r0, r0, #0xf100 + add r1, r1, #0xf000 + add r6, r1, r4, lsl #7 + ldrsh r5, [r0, #0xc4] +#else + ldr r1, [sb, #0x120] + ldr r2, [r0] + cmp r1, #0 + add r0, r2, r4, lsl #1 + add r1, r2, #0x2a8 + add r0, r0, #0xf200 + add r1, r1, #0xf000 + add r6, r1, r4, lsl #7 + ldrsh r5, [r0, #0x68] +#endif + beq _01FFB460 + mov r0, #8 + bl DungeonRandInt + mov r1, #6 + strb r1, [sb, #0x7c] + mov r3, r0, lsl #2 + ldr r0, _01FFB624 ; =DIRECTIONS_XY + ldrsh r4, [sl, #4] + ldrsh r2, [r0, r3] + ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2 + mov r0, #1 + add r2, r4, r2 + strh r2, [sb, #0x8c] + ldrsh r2, [sl, #6] + ldrsh r1, [r1, r3] + add r1, r2, r1 + strh r1, [sb, #0x8e] + ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} +_01FFB460: + ldrb r0, [sb, #0x7c] + cmp r0, #4 + beq _01FFB520 + cmp r5, #0 + bne _01FFB4B8 + mov r0, #8 + bl DungeonRandInt + mov r1, #6 + strb r1, [sb, #0x7c] + mov r3, r0, lsl #2 + ldr r0, _01FFB624 ; =DIRECTIONS_XY + ldrsh r4, [sl, #4] + ldrsh r2, [r0, r3] + ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2 + mov r0, #1 + add r2, r4, r2 + strh r2, [sb, #0x8c] + ldrsh r2, [sl, #6] + ldrsh r1, [r1, r3] + add r1, r2, r1 + strh r1, [sb, #0x8e] + ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} +_01FFB4B8: + mov r4, #0 + b _01FFB518 +_01FFB4C0: + mov r0, r5 + bl DungeonRandInt + mov r2, r0, lsl #2 + ldrsh r3, [sl, #4] + ldrsh r1, [r6, r2] + cmp r3, r1 + addeq r1, r6, r2 + ldreqsh r2, [sl, #6] + ldreqsh r1, [r1, #2] + cmpeq r2, r1 + beq _01FFB514 + mov r1, #4 + strb r1, [sb, #0x7c] + mov r1, r0, lsl #2 + ldrsh r2, [r6, r1] + add r1, r6, r0, lsl #2 + mov r0, #1 + strh r2, [sb, #0x8c] + ldrsh r1, [r1, #2] + strh r1, [sb, #0x8e] + ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} +_01FFB514: + add r4, r4, #1 +_01FFB518: + cmp r4, #0xa + blt _01FFB4C0 +_01FFB520: + ldrsh r0, [sl, #4] + ldrsh r1, [sl, #6] + bl GetTile + ldrh r0, [r0] + tst r0, #8 + beq _01FFB5D0 + mov r0, #8 + bl DungeonRandInt + mov r8, r0 + mov r5, #0 + add fp, sp, #0 + ldr r4, _01FFB624 ; =DIRECTIONS_XY + b _01FFB5C8 +_01FFB554: + and r8, r8, #7 + mov r1, r8, lsl #2 + add r0, r4, r8, lsl #2 + ldrsh r6, [sl, #4] + ldrsh r3, [r4, r1] + ldrsh r2, [sl, #6] + ldrsh r1, [r0, #2] + add r6, r6, r3 + mov r0, r6 + add r7, r2, r1 + mov r1, r7 + bl GetTile + ldrb r0, [r0, #7] + cmp r0, #0xff + bne _01FFB5C0 + mov r0, sl + mov r1, r8 + mov r2, fp + bl CanAiMonsterMoveInDirection + cmp r0, #0 + beq _01FFB5C0 + mov r0, #3 + strb r0, [sb, #0x7c] + strh r6, [sb, #0x8c] + strh r7, [sb, #0x8e] + mov r0, #1 + ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} +_01FFB5C0: + add r5, r5, #1 + add r8, r8, #1 +_01FFB5C8: + cmp r5, #8 + blt _01FFB554 +_01FFB5D0: + mov r0, #1 + ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} +_01FFB5D8: + mov r0, #8 + bl DungeonRandInt + mov r1, #6 + strb r1, [sb, #0x7c] + mov r3, r0, lsl #2 + ldr r0, _01FFB624 ; =DIRECTIONS_XY + ldrsh r4, [sl, #4] + ldrsh r2, [r0, r3] + ldr r1, _01FFB628 ; =DIRECTIONS_XY + 2 + mov r0, #1 + add r2, r4, r2 + strh r2, [sb, #0x8c] + ldrsh r2, [sl, #6] + ldrsh r1, [r1, r3] + add r1, r2, r1 + strh r1, [sb, #0x8e] + ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc} + .align 2, 0 +_01FFB61C: .word DUNGEON_PTR +_01FFB620: .word FACING_DIRECTION_INCREMENTS +_01FFB624: .word DIRECTIONS_XY +_01FFB628: .word DIRECTIONS_XY + 2 + arm_func_end CalculateAiTargetPos + + arm_func_start sub_01FFB62C +sub_01FFB62C: ; 0x01FFB62C + ldr r3, [r0, #0xb4] + mov r2, #0 + strb r2, [r3, #0x7c] + ldrh r1, [r0, #4] + strh r1, [r3, #0x8c] + ldrh r0, [r0, #6] + strh r0, [r3, #0x8e] + str r2, [r3, #0x84] + strh r2, [r3, #0x80] + bx lr + arm_func_end sub_01FFB62C + + .global _01FFB654 +_01FFB654: + .byte 0x05, 0x03, 0x00, 0x00 diff --git a/asm/overlay_29_022FF8C8.s b/asm/overlay_29_022FF8C8.s index 57b4b27b..47179e47 100644 --- a/asm/overlay_29_022FF8C8.s +++ b/asm/overlay_29_022FF8C8.s @@ -26,8 +26,8 @@ _022FF8EC: arm_func_end GetMobilityTypeAfterIqSkills #endif - arm_func_start ov29_022FF908 -ov29_022FF908: ; 0x022FF908 + arm_func_start CanCrossWalls +CanCrossWalls: ; 0x022FF908 stmdb sp!, {r3, r4, r5, lr} mov r5, r0 ldr r4, [r5, #0xb4] @@ -48,7 +48,7 @@ ov29_022FF908: ; 0x022FF908 movne r0, #0 and r0, r0, #0xff ldmia sp!, {r3, r4, r5, pc} - arm_func_end ov29_022FF908 + arm_func_end CanCrossWalls arm_func_start ov29_022FF958 ov29_022FF958: ; 0x022FF958 diff --git a/asm/overlay_29_02301FBC.s b/asm/overlay_29_02301FBC.s index fdce701a..a4e53b63 100644 --- a/asm/overlay_29_02301FBC.s +++ b/asm/overlay_29_02301FBC.s @@ -175,8 +175,8 @@ ov29_023021F0: ; 0x023021F0 _023021FC: .word UpdateIqSkills arm_func_end ov29_023021F0 - arm_func_start ov29_02302200 -ov29_02302200: ; 0x02302200 + arm_func_start CanSeeTeammate +CanSeeTeammate: ; 0x02302200 stmdb sp!, {r3, r4, r5, r6, r7, lr} mov r4, r0 ldr r0, [r4, #0xb4] @@ -216,4 +216,4 @@ _02302268: ldmia sp!, {r3, r4, r5, r6, r7, pc} .align 2, 0 _02302278: .word DUNGEON_PTR - arm_func_end ov29_02302200 + arm_func_end CanSeeTeammate diff --git a/asm/overlay_29_023082A0.s b/asm/overlay_29_023082A0.s index 17f1df77..232e93b7 100644 --- a/asm/overlay_29_023082A0.s +++ b/asm/overlay_29_023082A0.s @@ -16,8 +16,8 @@ ShouldMonsterFollowLeader: ; 0x023082A0 ldmia sp!, {r3, pc} arm_func_end ShouldMonsterFollowLeader - arm_func_start ov29_023082C4 -ov29_023082C4: ; 0x023082C4 + arm_func_start GetLeaderIfVisible +GetLeaderIfVisible: ; 0x023082C4 stmdb sp!, {r3, r4, r5, lr} mov r5, r0 ldr r0, [r5, #0xb4] @@ -50,4 +50,4 @@ ov29_023082C4: ; 0x023082C4 _02308338: mov r0, #0 ldmia sp!, {r3, r4, r5, pc} - arm_func_end ov29_023082C4 + arm_func_end GetLeaderIfVisible diff --git a/include/dungeon_ai_movement.h b/include/dungeon_ai_movement.h new file mode 100644 index 00000000..d1369904 --- /dev/null +++ b/include/dungeon_ai_movement.h @@ -0,0 +1,8 @@ +#ifndef PMDSKY_DUNGEON_AI_MOVEMENT_H +#define PMDSKY_DUNGEON_AI_MOVEMENT_H + +#include "dungeon_mode.h" + +void AiMovement(struct entity *monster, bool8 show_run_away_effect); + +#endif //PMDSKY_DUNGEON_AI_MOVEMENT_H diff --git a/include/dungeon_mode.h b/include/dungeon_mode.h index ee447c0d..17d8d536 100644 --- a/include/dungeon_mode.h +++ b/include/dungeon_mode.h @@ -16,9 +16,12 @@ #define DEFAULT_STAT_STAGE 10 #define MAX_STAT_STAGE 20 #define MAX_SPEED_STAGE 4 +#define MAX_HP_LIMIT 999 + #define NUM_SPEED_COUNTERS 5 #define MAX_STOCKPILE_STAGE 3 #define NUM_STATS_PER_CATEGORY 2 +#define NUM_PREV_POS 4 #define STAT_STAGE_ATK 0 #define STAT_STAGE_SP_ATK 1 @@ -290,10 +293,7 @@ struct monster { // in order to update the camera and minimap. Changed to held_item.id after checking. enum item_id previous_held_item_id; // Previous position data is used by the AI - struct position prev_pos; // 0x6A: Position 1 turn ago - struct position prev_pos2; // 0x6E: Position 2 turns ago - struct position prev_pos3; // 0x72: Position 3 turns ago - struct position prev_pos4; // 0x76: Position 4 turns ago + struct position prev_pos[NUM_PREV_POS]; // 0x6A: Position X turns ago struct ai_target ai_target; // 0x7A // 0x90: Work array while updating skills in the menu. Same meaning as iq_skill_flags. struct iq_skill_flags iq_skill_menu_flags; @@ -321,7 +321,7 @@ struct monster { u32 wrap_pair_unique_id; // 0xB8: Tracks the damage taken to deal when bide status ends. Max 0x3E7 (999). u32 bide_damage_tally; - enum monster_behavior monster_behavior : 8; // 0xBC + enum monster_behavior monster_behavior; // 0xBC struct sleep_class_status sleep_class_status; // 0xBD struct burn_class_status burn_class_status; // 0xBF struct frozen_class_status frozen_class_status; // 0xC4 diff --git a/include/math.h b/include/math.h index 86f2e358..58321f98 100644 --- a/include/math.h +++ b/include/math.h @@ -1,6 +1,9 @@ #ifndef PMDSKY_MATH_H #define PMDSKY_MATH_H +#define INFINITY 999 +#define INFINITY_2 999999 + #define F248LessThanFloat(x, y) (x < (int)(y * 0x100)) #define F248LessThanInt(x, y) (x < 0x100 * y) diff --git a/main.lsf b/main.lsf index f6c65563..9c3ecd7c 100644 --- a/main.lsf +++ b/main.lsf @@ -142,6 +142,8 @@ Autoload ITCM { Address 0x01FF8000 Object asm/itcm.o (.itcm) + Object src/dungeon_ai_movement.o (.itcm) + Object asm/itcm_01FFB2C8.o (.itcm) Object src/dungeon_ai_itcm.o (.itcm) Object asm/itcm_01FFBD20.o (.itcm) } diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 6b3c8e37..2706fada 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -63,7 +63,7 @@ u32 AiConsiderMove(struct ai_possible_move *ai_possible_move, struct entity *mon if (GetMoveTargetAndRange(move, FALSE) == TARGET_USER | RANGE_USER | AI_CONDITION_HP_25) { - s32 max_hp = MIN(pokemon_info->max_hp_stat + pokemon_info->max_hp_boost, 999); + s32 max_hp = MIN(pokemon_info->max_hp_stat + pokemon_info->max_hp_boost, MAX_HP_LIMIT); if (pokemon_info->hp == max_hp) return move_weight; } diff --git a/src/dungeon_ai_itcm.c b/src/dungeon_ai_itcm.c index 580c3e26..42b43559 100644 --- a/src/dungeon_ai_itcm.c +++ b/src/dungeon_ai_itcm.c @@ -23,12 +23,12 @@ #include "overlay_29_022EBC50.h" #include "overlay_29_02338350.h" -#define REGULAR_ATTACK_INDEX 4 - #ifdef SDK_ARM9 #include #endif //SDK_ARM9 +#define REGULAR_ATTACK_INDEX 4 + // https://decomp.me/scratch/zg7V6 #ifdef NONMATCHING void ChooseAiMove(struct entity *monster) diff --git a/src/dungeon_ai_item_weight.c b/src/dungeon_ai_item_weight.c index 9c04afdd..955e486e 100644 --- a/src/dungeon_ai_item_weight.c +++ b/src/dungeon_ai_item_weight.c @@ -51,7 +51,7 @@ u32 GetAiUseItemProbability(struct entity *item_consumer, struct item *item, u32 case ITEM_ORAN_BERRY: case ITEM_SITRUS_BERRY: s32 pokemon_max_hp = pokemon_info->max_hp_stat + pokemon_info->max_hp_boost; - if (pokemon_info->hp < Min(999, pokemon_max_hp) && pokemon_info->hp <= Min(999, pokemon_max_hp) / 4) + if (pokemon_info->hp < Min(MAX_HP_LIMIT, pokemon_max_hp) && pokemon_info->hp <= Min(MAX_HP_LIMIT, pokemon_max_hp) / 4) { if (!target_other) if (IsAdjacentToEnemy(item_consumer)) @@ -203,7 +203,7 @@ u32 GetAiUseItemProbability(struct entity *item_consumer, struct item *item, u32 else { s32 pokemon_max_hp = pokemon_info->max_hp_stat + pokemon_info->max_hp_boost; - if (pokemon_info->hp < Min(999, pokemon_max_hp) && pokemon_info->hp < 20) + if (pokemon_info->hp < Min(MAX_HP_LIMIT, pokemon_max_hp) && pokemon_info->hp < 20) { if (!target_other) if (IsAdjacentToEnemy(item_consumer)) diff --git a/src/dungeon_ai_movement.c b/src/dungeon_ai_movement.c new file mode 100644 index 00000000..c22a3d25 --- /dev/null +++ b/src/dungeon_ai_movement.c @@ -0,0 +1,1693 @@ +#include "dungeon_ai_movement.h" +#include "dg_camera.h" +#include "dg_random.h" +#include "dungeon_action.h" +#include "dungeon_ai_targeting_1.h" +#include "dungeon_capabilities_1.h" +#include "dungeon_map_access.h" +#include "dungeon_pokemon_attributes_1.h" +#include "dungeon_util.h" +#include "dungeon_util_1.h" +#include "dungeon_util_static.h" +#include "dungeon_visibility.h" +#include "main_0208655C.h" +#include "math.h" +#include "number_util.h" +#include "overlay_29_022E1610.h" +#include "overlay_29_0230827C.h" +#include "position_util.h" + +#ifdef SDK_ARM9 +#include +#endif //SDK_ARM9 + +#define CHECK_VISIBILITY_DISTANCE 5 +#define CORRIDOR_VISIBILITY 2 + +#define TURN_LEFT_45 1 +#define TURN_RIGHT_45 2 +#define TURN_LEFT_90 3 +#define TURN_RIGHT_90 4 +#define TURN_LEFT_135 5 + +struct can_move_in_direction_info +{ + bool8 try_turn; + bool8 can_move_in_direction; + bool8 pokemon_in_front; + s32 direction; +}; + +extern s32 FACING_DIRECTION_INCREMENTS[]; + +extern bool8 CalculateAiTargetPos(struct entity *monster); +extern bool8 CanAiMonsterMoveInDirection(struct entity *monster, s32 direction, bool8 *out_monster_in_target_position); +extern bool8 CanTargetEntity(struct entity *user, struct entity *target); +extern bool8 CanTargetPosition(struct entity *monster, struct position *position); +extern s32 GetChebyshevDistance(struct position *position_a, struct position *position_b); +extern bool8 IsBagFull(); +extern bool8 ShouldMonsterFollowLeader(struct entity *monster); +extern bool8 ShouldMonsterHeadToStairs(struct entity *entity); +extern bool8 ShouldMonsterRunAwayAndShowEffectOutlawCheck(struct entity* monster, bool8 show_run_away_effect); +extern bool8 IsPositionWithinTwoTiles(struct position *origin, struct position *target); +extern bool8 ov29_022FBDF0(struct entity*); +extern s32 ov29_022FBE04(struct monster*); +extern bool8 CanCrossWalls(struct entity *monster); +extern bool8 ShouldAvoidFirstHit(struct entity *monster, bool8 force_avoid); +extern bool8 CanSeeTeammate(struct entity *monster); +extern struct entity* GetLeaderIfVisible(struct entity *monster); +extern bool8 ov29_02348D00(struct item*); + +// https://decomp.me/scratch/2QnEr +#ifdef NONMATCHING +void AiMovement(struct entity *monster, bool8 show_run_away_effect) +{ + struct monster *pokemon_info = GetEntInfo(monster); + pokemon_info->ai_target.ai_not_next_to_target = FALSE; + pokemon_info->ai_target.ai_targeting_enemy = FALSE; + pokemon_info->ai_target.ai_turning_around = FALSE; + + if (IsTacticSet(monster, TACTIC_BE_PATIENT)) + { + s32 max_hp_stat = pokemon_info->max_hp_stat + pokemon_info->max_hp_boost; + if (pokemon_info->hp <= Min(999, max_hp_stat) / 2) + { + pokemon_info->action.action_id = ACTION_NOTHING; + return; + } + } + + if (IsTacticSet(monster, TACTIC_WAIT_THERE) || ov29_022FBDF0(monster)) + pokemon_info->action.action_id = ACTION_NOTHING; + else if (!pokemon_info->is_team_leader && CeilFixedPoint(pokemon_info->belly) == 0) + pokemon_info->action.action_id = ACTION_NOTHING; + else if (pokemon_info->monster_behavior == BEHAVIOR_RESCUE_TARGET) + { + SetActionPassTurnOrWalk(&pokemon_info->action, pokemon_info->id); + pokemon_info->action.direction = DungeonRandInt(NUM_DIRECTIONS); + pokemon_info->target_pos.x = monster->pos.x; + pokemon_info->target_pos.y = monster->pos.y - 1; + } + else + { + bool8 has_action; + if (ShouldMonsterRunAwayAndShowEffectOutlawCheck(monster, show_run_away_effect)) + { + // AvoidEnemies function from RT. + struct monster *pokemon_info_2 = GetEntInfo(monster); + s32 closest_target_distance = INFINITY_2; + u8 room = monster->room_idx; + + if (pokemon_info_2->monster_behavior == BEHAVIOR_FLEEING_OUTLAW && ShouldMonsterHeadToStairs(monster)) + { + pokemon_info_2->ai_target.ai_target_pos = DUNGEON_PTR[0]->gen_info.stairs_pos; + pokemon_info_2->target_pos = DUNGEON_PTR[0]->gen_info.stairs_pos; + has_action = TRUE; + } + else + { + struct entity **possible_targets; + s32 num_possible_targets; + if (DUNGEON_PTR[0]->decoy_is_active) + { + possible_targets = DUNGEON_PTR[0]->active_monster_ptrs; + num_possible_targets = DUNGEON_MAX_POKEMON; + } + else if (pokemon_info_2->is_not_team_member && !pokemon_info_2->is_ally) + { + possible_targets = DUNGEON_PTR[0]->monster_slots.party_members; + num_possible_targets = MAX_TEAM_MEMBERS; + } + else + { + possible_targets = DUNGEON_PTR[0]->monster_slots.wild_pokemon; + num_possible_targets = DUNGEON_MAX_WILD_POKEMON; + } + + struct entity *closest_target = NULL; + u8 closest_target_room = CORRIDOR_ROOM; + for (s32 i = 0; i < num_possible_targets; i++) + { + struct entity *target = possible_targets[i]; + if (EntityIsValid__0230827C(target) && CanSeeTarget(monster, target)) + { + if (DUNGEON_PTR[0]->decoy_is_active && GetTreatmentBetweenMonsters(monster, target, FALSE, TRUE) != TREATMENT_TREAT_AS_ENEMY) + continue; + + s32 distance = GetChebyshevDistance(&monster->pos, &target->pos); + if (closest_target_distance > distance) + { + closest_target_distance = distance; + closest_target = target; + closest_target_room = target->room_idx; + pokemon_info_2->ai_target.ai_target_pos = closest_target->pos; + pokemon_info_2->target_pos = closest_target->pos; + } + } + } + + if (closest_target_distance != INFINITY_2) + { + if (room == closest_target_room && room != CORRIDOR_ROOM) + { + const struct tile *tile = GetTile(monster->pos.x, monster->pos.y); + if (tile->terrain_flags & TERRAIN_TYPE_NATURAL_JUNCTION) + { + struct position ai_target_pos = { + .x = monster->pos.x, + .y = monster->pos.y + }; + // Scan for a direction leading outside the room. + s32 target_dir; + for (target_dir = 0; target_dir < NUM_DIRECTIONS; target_dir++) + { + ai_target_pos.x = monster->pos.x + DIRECTIONS_XY[target_dir].x; + ai_target_pos.y = monster->pos.y + DIRECTIONS_XY[target_dir].y; + const struct tile *adjacent_tile = GetTile(ai_target_pos.x, ai_target_pos.y); + bool8 pokemon_in_front; + if (adjacent_tile->room != room && CanAiMonsterMoveInDirection(monster, target_dir, &pokemon_in_front)) + break; + } + + if (target_dir == NUM_DIRECTIONS) + { + target_dir = DungeonRandInt(NUM_DIRECTIONS); + pokemon_info_2->ai_target.ai_objective = AI_STAND_STILL; + pokemon_info_2->ai_target.ai_target_pos.x = monster->pos.x + DIRECTIONS_XY[target_dir].x; + pokemon_info_2->ai_target.ai_target_pos.y = monster->pos.y + DIRECTIONS_XY[target_dir].y; + has_action = TRUE; + } + else + { + pokemon_info_2->ai_target.ai_objective = AI_RUN_AWAY; + pokemon_info_2->ai_target.ai_target_pos = ai_target_pos; + has_action = 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. + struct position *natural_junction_list = DUNGEON_PTR[0]->natural_junction_list[room]; + + s16 natural_junction_list_counts = DUNGEON_PTR[0]->natural_junction_list_counts[room]; + s32 furthest_target_to_exit_distance = -INFINITY_2; + s32 furthest_target_exit_index = 0; + s32 distance_y = abs(closest_target->pos.y - monster->pos.y); + s32 pokemon_to_target_distance = abs(closest_target->pos.x - monster->pos.x); + if (pokemon_to_target_distance <= distance_y) + pokemon_to_target_distance = distance_y; + + for (s32 i = 0; i < natural_junction_list_counts; i++) + { + s16 natural_junction_pos_y = natural_junction_list[i].y; + s32 distance_y = abs(closest_target->pos.y - natural_junction_pos_y); + s16 natural_junction_pos_x = natural_junction_list[i].x; + s32 target_to_exit_distance = abs(closest_target->pos.x - natural_junction_pos_x); + if (target_to_exit_distance <= distance_y) + target_to_exit_distance = distance_y; + + s32 pokemon_to_exit_sign_x = natural_junction_pos_x - monster->pos.x; + if (pokemon_to_exit_sign_x < -1) + pokemon_to_exit_sign_x = -1; + + s32 pokemon_to_exit_sign_y = natural_junction_pos_y - monster->pos.y; + if (pokemon_to_exit_sign_y < -1) + pokemon_to_exit_sign_y = -1; + + if (pokemon_to_exit_sign_x > 1) + pokemon_to_exit_sign_x = 1; + + if (pokemon_to_exit_sign_y > 1) + pokemon_to_exit_sign_y = 1; + + s32 adjacent_to_target_distance = abs(closest_target->pos.y - (monster->pos.y + pokemon_to_exit_sign_y)); + s32 adjacent_to_target_distance_x = abs(closest_target->pos.x - (monster->pos.x + pokemon_to_exit_sign_x)); + + if (adjacent_to_target_distance <= adjacent_to_target_distance_x) + adjacent_to_target_distance = adjacent_to_target_distance_x; + + // 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 (adjacent_to_target_distance >= pokemon_to_target_distance && + furthest_target_to_exit_distance < target_to_exit_distance) + { + furthest_target_exit_index = i; + furthest_target_to_exit_distance = target_to_exit_distance; + } + } + + if (furthest_target_to_exit_distance >= 0) + { + pokemon_info_2->ai_target.ai_objective = AI_RUN_AWAY; + pokemon_info_2->ai_target.ai_target_pos.x = natural_junction_list[furthest_target_exit_index].x; + pokemon_info_2->ai_target.ai_target_pos.y = natural_junction_list[furthest_target_exit_index].y; + has_action = TRUE; + } + } + } + else + { + pokemon_info_2->ai_target.ai_objective = AI_RUN_AWAY; + pokemon_info_2->ai_target.ai_target_pos.x = monster->pos.x - (closest_target->pos.x - monster->pos.x); + pokemon_info_2->ai_target.ai_target_pos.y = monster->pos.y - (closest_target->pos.y - monster->pos.y); + has_action = TRUE; + } + } + else + { + has_action = CalculateAiTargetPos(monster); + } + } + } + else + { + // CanTakeItem function from RT. + struct monster *pokemon_info_2 = GetEntInfo(monster); + bool8 can_take_item; + if (!EntityIsValid__0230827C(monster)) + can_take_item = FALSE; + else if (CheckVariousConditions(monster)) + can_take_item = FALSE; + else + { + const struct tile *map_tile = GetTileAtEntity(monster); + struct entity *object = map_tile->object; + if (object == NULL) + can_take_item = FALSE; + else + { + switch (GetEntityType(object)) + { + case ENTITY_ITEM: + if (!pokemon_info_2->is_team_leader && + !ItemExists(pokemon_info_2->held_item.flags) && + (GetTerrainType(map_tile) || !pokemon_info_2->is_not_team_member)) + { + if (!pokemon_info_2->is_not_team_member) + { + if (!IsBagFull() && !(map_tile->terrain_flags & TERRAIN_TYPE_SHOP)) + { + can_take_item = TRUE; + break; + } + } + else if (ov29_02348D00(GetItemInfo(object))) + { + can_take_item = FALSE; + break; + } + else if (!(GetItemInfo(object)->flags & ITEM_FLAG_IN_SHOP)) + { + can_take_item = TRUE; + break; + } + } + case ENTITY_NOTHING: + case ENTITY_MONSTER: + case ENTITY_TRAP: + case ENTITY_HIDDEN_STAIRS: + case ENTITY_TEMPORARY: + default: + can_take_item = FALSE; + break; + } + } + } + + if (can_take_item) + { + pokemon_info->action.action_id = ACTION_PICK_UP_AI; + return; + } + else + { + // ChooseTargetPosition function from RT. + struct monster *pokemon_info_2 = GetEntInfo(monster); + if (!ShouldMonsterFollowLeader(monster)) + { + struct entity **possible_targets; + s32 max_possible_targets; + if (DUNGEON_PTR[0]->decoy_is_active) + { + possible_targets = DUNGEON_PTR[0]->active_monster_ptrs; + max_possible_targets = DUNGEON_MAX_POKEMON; + } + else if (pokemon_info_2->is_not_team_member && !pokemon_info_2->is_ally) + { + possible_targets = DUNGEON_PTR[0]->monster_slots.party_members; + max_possible_targets = MAX_TEAM_MEMBERS; + } + else + { + possible_targets = DUNGEON_PTR[0]->monster_slots.wild_pokemon; + max_possible_targets = DUNGEON_MAX_WILD_POKEMON; + } + + bool8 can_cross_walls = CanCrossWalls(monster); + s32 target_index = -1; + s32 target_distance = INFINITY; + for (s32 i = 0; i < max_possible_targets; i++) + { + struct entity *target = possible_targets[i]; + if (EntityIsValid__0230827C(target) && GetEntInfo(target)->monster_behavior <= BEHAVIOR_FIXED_ENEMY) + { + if (DUNGEON_PTR[0]->decoy_is_active) + { + if (GetTreatmentBetweenMonsters(monster, target, FALSE, TRUE) != TREATMENT_TREAT_AS_ENEMY) + continue; + } + else if (!pokemon_info_2->is_not_team_member && GetEntInfo(target)->frozen_class_status.freeze == STATUS_FROZEN_PETRIFIED) + continue; + + if (GetEntInfo(target)->shopkeeper != SHOPKEEPER_MODE_SHOPKEEPER) + { + if (can_cross_walls) + { + if (abs(monster->pos.x - target->pos.x) > CHECK_VISIBILITY_DISTANCE || + abs(monster->pos.y - target->pos.y) > CHECK_VISIBILITY_DISTANCE) + { + if (!CanTargetEntity(monster, target)) + continue; + } + } + else if (!CanTargetEntity(monster, target)) + continue; + + s32 current_distance = GetChebyshevDistance(&monster->pos, &target->pos); + if (target_distance > current_distance) + { + target_distance = current_distance; + target_index = i; + if (target_distance < 2) + break; + } + } + } + } + + if (target_index >= 0) + { + pokemon_info_2->ai_target.ai_objective = AI_CHASE_TARGET; + pokemon_info_2->ai_target.ai_target_pos = possible_targets[target_index]->pos; + pokemon_info_2->ai_target.ai_target = possible_targets[target_index]; + pokemon_info_2->ai_target.ai_target_spawn_genid = pokemon_info_2->ai_target.ai_target->spawn_genid; + pokemon_info_2->ai_target.ai_targeting_enemy = TRUE; + pokemon_info_2->random_movement = FALSE; + if (IsTacticSet(monster, TACTIC_KEEP_YOUR_DISTANCE) && !CanSeeTeammate(monster)) + { + struct entity *possible_target = possible_targets[target_index]; + s32 distance_x = abs(monster->pos.x - possible_target->pos.x); + if (distance_x <= 1) + { + s32 distance_y = abs(monster->pos.y - possible_target->pos.y); + if (distance_y <= 1) + pokemon_info_2->ai_target.ai_turning_around = TRUE; + } + } + has_action = TRUE; + goto end_choose_target_position; + } + } + if (!IsTacticSet(monster, TACTIC_YOU_GO_THE_OTHER_WAY)) + { + if (!pokemon_info_2->is_not_team_member) + { + struct entity *leader = GetLeaderIfVisible(monster); + if (EntityIsValid__0230827C(leader)) + { + pokemon_info_2->ai_target.ai_objective = AI_CHASE_TARGET; + pokemon_info_2->ai_target.ai_target_pos = leader->pos; + pokemon_info_2->ai_target.ai_target = leader; + pokemon_info_2->ai_target.ai_target_spawn_genid = leader->spawn_genid; + pokemon_info_2->random_movement = FALSE; + has_action = TRUE; + goto end_choose_target_position; + } + } + } + else if (pokemon_info_2->is_team_leader) + { + // This item targeting code is never reached because the leader is never AI-controlled. + GetVisibilityRange(); // Dead code + u8 room = GetTile(monster->pos.x, monster->pos.y)->room; + s32 min_x, min_y, max_x, max_y; + if (room == CORRIDOR_ROOM) + { + min_x = monster->pos.x - CORRIDOR_VISIBILITY; + min_y = monster->pos.y - CORRIDOR_VISIBILITY; + max_x = monster->pos.x + CORRIDOR_VISIBILITY; + max_y = monster->pos.y + CORRIDOR_VISIBILITY; + } + else + { + struct room_data *map_room = &DUNGEON_PTR[0]->room_data[room]; + min_x = map_room->bottom_right_corner.x - 1; + min_y = map_room->bottom_right_corner.y - 1; + max_x = map_room->top_left_corner.x + 1; + max_y = map_room->top_left_corner.y + 1; + } + for (s32 y = min_y; y <= max_y; y++) + { + for (s32 x = min_x; x <= max_x; x++) + { + struct entity *object = GetTileSafe(x, y)->object; + if (object && GetEntityType(object) == ENTITY_ITEM) + { + pokemon_info_2->ai_target.ai_objective = AI_TAKE_ITEM; + pokemon_info_2->ai_target.ai_target_pos.x = x; + pokemon_info_2->ai_target.ai_target_pos.y = y; + pokemon_info_2->ai_target.ai_target = NULL; + pokemon_info_2->ai_target.ai_target_spawn_genid = 0; + pokemon_info_2->random_movement = FALSE; + has_action = TRUE; + goto end_choose_target_position; + } + } + } + } + + if (!HasDropeyeStatus(monster) && (u8) (pokemon_info_2->ai_target.ai_objective + 0xFF) <= 1) + { + if (pokemon_info_2->ai_target.ai_target) + { + if (pokemon_info_2->ai_target.ai_target->spawn_genid == pokemon_info_2->ai_target.ai_target_spawn_genid) + { + struct monster *target_data = GetEntInfo(pokemon_info_2->ai_target.ai_target); + for (s32 i = 0; i < NUM_PREV_POS; i++) + { + if (CanTargetPosition(monster, &target_data->prev_pos[i])) + { + pokemon_info_2->ai_target.ai_objective = AI_CHASE_REMEMBERED_TARGET; + pokemon_info_2->ai_target.ai_target_pos = target_data->prev_pos[i]; + pokemon_info_2->random_movement = FALSE; + has_action = TRUE; + goto end_choose_target_position; + } + } + } + else + { + pokemon_info_2->ai_target.ai_objective = AI_STAND_STILL; + pokemon_info_2->ai_target.ai_target = NULL; + pokemon_info_2->ai_target.ai_target_spawn_genid = 0; + } + } + } + CalculateAiTargetPos(monster); + has_action = TRUE; + } + end_choose_target_position: + + if (!has_action) + pokemon_info->action.action_id = ACTION_NOTHING; + else + { + // DecideMovement function from RT. + struct monster *pokemon_info_2 = GetEntInfo(monster); + pokemon_info_2->target_pos = pokemon_info_2->ai_target.ai_target_pos; + + if (monster->pos.x == pokemon_info_2->ai_target.ai_target_pos.x && + monster->pos.y == pokemon_info_2->ai_target.ai_target_pos.y) + { + SetMonsterActionFields(&pokemon_info_2->action, ACTION_PASS_TURN); + return; + } + + if (ov29_022FBE04(pokemon_info)) + return; + + s32 direction = GetDirectionTowardsPosition(&monster->pos, &pokemon_info_2->ai_target.ai_target_pos); + if (ShouldAvoidFirstHit(monster, pokemon_info_2->ai_target.ai_targeting_enemy)) + { + if (pokemon_info_2->ai_target.ai_objective == AI_CHASE_TARGET && + IsPositionWithinTwoTiles(&monster->pos, &pokemon_info_2->ai_target.ai_target_pos)) + { + s32 distance = GetChebyshevDistance(&monster->pos, &pokemon_info_2->ai_target.ai_target_pos); + if (distance == 2) + { + SetMonsterActionFields(&pokemon_info_2->action, ACTION_PASS_TURN); + return; + } + else if (distance < 2) + { + direction += 4; + direction &= DIRECTION_MASK; + } + } + } + else if (pokemon_info_2->ai_target.ai_turning_around) + { + direction += 4; + direction &= DIRECTION_MASK; + } + + bool8 pokemon_in_front; + if (CanAiMonsterMoveInDirection(monster, direction, &pokemon_in_front)) + { + SetActionPassTurnOrWalk(&pokemon_info_2->action, pokemon_info_2->id); + pokemon_info_2->action.direction = direction & DIRECTION_MASK; + return; + } + else if (pokemon_in_front) + { + if (!pokemon_info_2->is_not_team_member && !pokemon_info_2->ai_next_to_target) + { + pokemon_info_2->ai_target.ai_not_next_to_target = TRUE; + pokemon_info_2->ai_ally_skip = TRUE; + SetMonsterActionFields(&pokemon_info_2->action, ACTION_PASS_TURN); + pokemon_info_2->waiting = TRUE; + return; + } + + if (monster->pos.x + DIRECTIONS_XY[direction].x == pokemon_info_2->ai_target.ai_target_pos.x && + monster->pos.y + DIRECTIONS_XY[direction].y == pokemon_info_2->ai_target.ai_target_pos.y) + { + SetMonsterActionFields(&pokemon_info_2->action, ACTION_PASS_TURN); + pokemon_info_2->waiting = TRUE; + return; + } + + pokemon_info_2->ai_target.ai_not_next_to_target = TRUE; + } + + struct can_move_in_direction_info can_move_in_direction_info[6]; + can_move_in_direction_info[TURN_LEFT_45].try_turn = can_move_in_direction_info[TURN_RIGHT_45].try_turn = can_move_in_direction_info[TURN_LEFT_90].try_turn = can_move_in_direction_info[TURN_RIGHT_90].try_turn = can_move_in_direction_info[TURN_LEFT_135].try_turn = TRUE; + + if (!pokemon_info_2->is_not_team_member && (direction & 1) != 0) + { + s32 target_distance_x = abs(monster->pos.x - pokemon_info_2->ai_target.ai_target_pos.x); + s32 target_distance_y = abs(monster->pos.y - pokemon_info_2->ai_target.ai_target_pos.y); + if (target_distance_x <= 2 && target_distance_y <= 2 && target_distance_x != target_distance_y) + { + if ((direction & 2) != 0) + { + if (target_distance_x < target_distance_y) + can_move_in_direction_info[TURN_RIGHT_45].try_turn = FALSE; + else + can_move_in_direction_info[TURN_LEFT_45].try_turn = FALSE; + } + else + { + if (target_distance_x < target_distance_y) + can_move_in_direction_info[TURN_LEFT_45].try_turn = FALSE; + else + can_move_in_direction_info[TURN_RIGHT_45].try_turn = FALSE; + } + } + } + + s32 turn_limit; + if (GetTile(monster->pos.x, monster->pos.y)->terrain_flags & TERRAIN_TYPE_UNBREAKABLE) + turn_limit = TURN_LEFT_135; + else + turn_limit = TURN_LEFT_90; + + if (ShouldMonsterRunAwayAndShowEffectOutlawCheck(monster, show_run_away_effect) || pokemon_info_2->ai_target.ai_turning_around) + turn_limit = TURN_LEFT_135; + + for (s32 i = TURN_LEFT_45; i < turn_limit; i++) + { + can_move_in_direction_info[i].direction = (FACING_DIRECTION_INCREMENTS[i] + direction) & DIRECTION_MASK; + can_move_in_direction_info[i].can_move_in_direction = CanAiMonsterMoveInDirection(monster, can_move_in_direction_info[i].direction, &can_move_in_direction_info[i].pokemon_in_front); + if (!can_move_in_direction_info[i].can_move_in_direction && !can_move_in_direction_info[i].pokemon_in_front) + { + can_move_in_direction_info[TURN_RIGHT_45].try_turn = TRUE; + can_move_in_direction_info[TURN_LEFT_45].try_turn = TRUE; + } + } + + for (s32 i = TURN_LEFT_45; i < turn_limit; i++) + { + if (can_move_in_direction_info[i].can_move_in_direction && can_move_in_direction_info[i].try_turn) + { + SetActionPassTurnOrWalk(&pokemon_info_2->action, pokemon_info_2->id); + pokemon_info_2->action.direction = can_move_in_direction_info[i].direction & DIRECTION_MASK; + return; + } + if (can_move_in_direction_info[i].pokemon_in_front) + pokemon_info_2->ai_target.ai_not_next_to_target = TRUE; + } + + SetMonsterActionFields(&pokemon_info_2->action, ACTION_PASS_TURN); + pokemon_info_2->waiting = TRUE; + if (pokemon_info_2->is_team_leader) + { + pokemon_info_2->ai_target.ai_not_next_to_target = FALSE; + pokemon_info_2->ai_ally_skip = FALSE; + } + else if (pokemon_info_2->ai_target.ai_not_next_to_target) + pokemon_info_2->ai_ally_skip = TRUE; + } + } + } +} +#else +asm void AiMovement(struct entity *monster, bool8 show_run_away_effect) +{ +#ifdef JAPAN +#define AI_MOVEMENT_OFFSET -4 +#define AI_MOVEMENT_OFFSET_2 -0xA4 +#else +#define AI_MOVEMENT_OFFSET 0 +#define AI_MOVEMENT_OFFSET_2 0 +#endif + stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, r10, r11, lr} + sub sp, sp, #0x88 + mov r4, r0 + ldr r8, [r4, #0xb4] + mov r2, #0 + strb r2, [r8, #0x7d] + str r1, [sp] + strb r2, [r8, #0x7e] + mov r1, #7 + strb r2, [r8, #0x7f] + bl IsTacticSet + cmp r0, #0 + beq _01FFA428 + ldrsh r2, [r8, #0x12] + ldrsh r1, [r8, #0x16] + ldr r0, =0x000003E7 + add r2, r2, r1 + cmp r2, r0 + movgt r2, r0 + ldrsh r1, [r8, #0x10] + add r0, r2, r2, lsr #31 + cmp r1, r0, asr #1 + movle r0, #0 + strleh r0, [r8, #0x4a] + ble _01FFB2A4 +_01FFA428: + mov r0, r4 + mov r1, #9 + bl IsTacticSet + cmp r0, #0 + bne _01FFA44C + mov r0, r4 + bl ov29_022FBDF0 + cmp r0, #0 + beq _01FFA458 +_01FFA44C: + mov r0, #0 + strh r0, [r8, #0x4a] + b _01FFB2A4 +_01FFA458: + ldrb r0, [r8, #7] + cmp r0, #0 + bne _01FFA494 + add r0, r8, #0x100 + ldrh r1, [r0, #0x46 + AI_MOVEMENT_OFFSET] + sub r2, sp, #4 + strh r1, [r2] + ldrh r0, [r0, #0x48 + AI_MOVEMENT_OFFSET] + strh r0, [r2, #2] + ldr r0, [r2] + bl CeilFixedPoint + cmp r0, #0 + moveq r0, #0 + streqh r0, [r8, #0x4a] + beq _01FFB2A4 +_01FFA494: + ldrb r0, [r8, #0xbc] + cmp r0, #7 + bne _01FFA4D4 + ldrsh r1, [r8, #2] + add r0, r8, #0x4a + bl SetActionPassTurnOrWalk + mov r0, #8 + bl DungeonRandInt + strb r0, [r8, #0x4c] + ldrsh r1, [r4, #4] + add r0, r8, #0x100 + strh r1, [r0, #0x7e + AI_MOVEMENT_OFFSET] + ldrsh r1, [r4, #6] + sub r1, r1, #1 + strh r1, [r0, #0x80 + AI_MOVEMENT_OFFSET] + b _01FFB2A4 +_01FFA4D4: + ldr r1, [sp] + mov r0, r4 + bl ShouldMonsterRunAwayAndShowEffectOutlawCheck + cmp r0, #0 + beq _01FFA9A8 + ldr r9, [r4, #0xb4] + ldrb r5, [r4, #0x25] + ldrb r0, [r9, #0xbc] + ldr r11, =0x000F423F + cmp r0, #3 + bne _01FFA550 + mov r0, r4 + bl ShouldMonsterHeadToStairs + cmp r0, #0 + beq _01FFA550 + ldr r3, =DUNGEON_PTR + add r2, r9, #0x100 + ldr r1, [r3] + mov r0, #1 + add r1, r1, #0xcc00 + ldrh r5, [r1, #0xe4 + AI_MOVEMENT_OFFSET_2] + strh r5, [r9, #0x8c] + ldrh r1, [r1, #0xe6 + AI_MOVEMENT_OFFSET_2] + strh r1, [r9, #0x8e] + ldr r1, [r3] + add r1, r1, #0xcc00 + ldrh r3, [r1, #0xe4 + AI_MOVEMENT_OFFSET_2] + strh r3, [r2, #0x7e + AI_MOVEMENT_OFFSET] + ldrh r1, [r1, #0xe6 + AI_MOVEMENT_OFFSET_2] + strh r1, [r2, #0x80 + AI_MOVEMENT_OFFSET] + b _01FFAF28 +_01FFA550: + ldr r0, =DUNGEON_PTR + ldr r1, [r0] + add r0, r1, #0x3000 + ldrb r0, [r0, #0xe38 + AI_MOVEMENT_OFFSET_2] + cmp r0, #0 + beq _01FFA580 + add r0, r1, #0x378 + AI_MOVEMENT_OFFSET_2 + add r0, r0, #0x12800 + str r0, [sp, #0x2c] + mov r0, #0x14 + str r0, [sp, #0x28] + b _01FFA5C4 +_01FFA580: + ldrb r0, [r9, #6] + cmp r0, #0 + beq _01FFA5B0 + ldrb r0, [r9, #8] + cmp r0, #0 + bne _01FFA5B0 + add r0, r1, #0x328 + AI_MOVEMENT_OFFSET_2 + add r0, r0, #0x12800 + str r0, [sp, #0x2c] + mov r0, #4 + str r0, [sp, #0x28] + b _01FFA5C4 +_01FFA5B0: + add r0, r1, #0x338 + AI_MOVEMENT_OFFSET_2 + add r0, r0, #0x12800 + str r0, [sp, #0x2c] + mov r0, #0x10 + str r0, [sp, #0x28] +_01FFA5C4: + mov r0, #0xff + mov r7, #0 + str r0, [sp, #0x24] + add r0, r9, #0x100 + mov r10, r7 + str r0, [sp, #0x4c] + b _01FFA68C +_01FFA5E0: + ldr r0, [sp, #0x2c] + ldr r6, [r0, r10, lsl #2] + mov r0, r6 + bl EntityIsValid__0230827C + cmp r0, #0 + beq _01FFA688 + mov r0, r4 + mov r1, r6 + bl CanSeeTarget + cmp r0, #0 + beq _01FFA688 + ldr r0, =DUNGEON_PTR + ldr r0, [r0] + add r0, r0, #0x3000 + ldrb r0, [r0, #0xe38 + AI_MOVEMENT_OFFSET_2] + cmp r0, #0 + beq _01FFA640 + mov r0, r4 + mov r1, r6 + mov r2, #0 + mov r3, #1 + bl GetTreatmentBetweenMonsters + cmp r0, #1 + bne _01FFA688 +_01FFA640: + add r0, r4, #4 + add r1, r6, #4 + bl GetChebyshevDistance + cmp r11, r0 + ble _01FFA688 + mov r11, r0 + ldrb r0, [r6, #0x25] + mov r7, r6 + str r0, [sp, #0x24] + ldrh r0, [r6, #4] + strh r0, [r9, #0x8c] + ldrh r0, [r6, #6] + strh r0, [r9, #0x8e] + ldrh r1, [r6, #4] + ldr r0, [sp, #0x4c] + strh r1, [r0, #0x7e + AI_MOVEMENT_OFFSET] + ldrh r1, [r6, #6] + strh r1, [r0, #0x80 + AI_MOVEMENT_OFFSET] +_01FFA688: + add r10, r10, #1 +_01FFA68C: + ldr r0, [sp, #0x28] + cmp r10, r0 + blt _01FFA5E0 + ldr r0, =0x000F423F + cmp r11, r0 + beq _01FFA99C + ldr r0, [sp, #0x24] + cmp r5, r0 + bne _01FFA96C + cmp r5, #0xff + beq _01FFA96C + ldrsh r0, [r4, #4] + ldrsh r1, [r4, #6] + bl GetTile + ldrh r0, [r0] + tst r0, #8 + beq _01FFA7C0 + ldrsh r1, [r4, #4] + ldrsh r0, [r4, #6] + mov r7, #0 + strh r1, [sp, #0x52] + strh r0, [sp, #0x54] + add r10, sp, #0x51 + ldr r6, =DIRECTIONS_XY + b _01FFA74C +_01FFA6F0: + mov r1, r7, lsl #2 + add r0, r6, r7, lsl #2 + ldrsh r3, [r4, #4] + ldrsh r2, [r6, r1] + ldrsh r1, [r4, #6] + ldrsh r0, [r0, #2] + add r2, r3, r2 + strh r2, [sp, #0x52] + add r0, r1, r0 + strh r0, [sp, #0x54] + ldrsh r0, [sp, #0x52] + ldrsh r1, [sp, #0x54] + bl GetTile + ldrb r0, [r0, #7] + cmp r5, r0 + beq _01FFA748 + mov r0, r4 + mov r1, r7 + mov r2, r10 + bl CanAiMonsterMoveInDirection + cmp r0, #0 + bne _01FFA754 +_01FFA748: + add r7, r7, #1 +_01FFA74C: + cmp r7, #8 + blt _01FFA6F0 +_01FFA754: + cmp r7, #8 + bne _01FFA7A0 + mov r0, #8 + bl DungeonRandInt + mov r1, #6 + strb r1, [r9, #0x7c] + mov r3, r0, lsl #2 + ldr r0, =DIRECTIONS_XY + ldrsh r5, [r4, #4] + ldrsh r2, [r0, r3] + ldr r1, =DIRECTIONS_XY + 2 + mov r0, #1 + add r2, r5, r2 + strh r2, [r9, #0x8c] + ldrsh r2, [r4, #6] + ldrsh r1, [r1, r3] + add r1, r2, r1 + strh r1, [r9, #0x8e] + b _01FFAF28 +_01FFA7A0: + ldrh r0, [sp, #0x52] + mov r1, #5 + strb r1, [r9, #0x7c] + ldrh r1, [sp, #0x54] + strh r0, [r9, #0x8c] + mov r0, #1 + strh r1, [r9, #0x8e] + b _01FFAF28 +_01FFA7C0: + ldr r0, =DUNGEON_PTR + ldrsh r10, [r4, #6] + ldr r1, [r0] + ldrsh r2, [r7, #6] + add r0, r1, #0x2a8 + AI_MOVEMENT_OFFSET_2 + add r1, r1, r5, lsl #1 +#ifdef JAPAN + add r1, r1, #0xf100 + ldrsh r1, [r1, #0xc4] +#else + add r1, r1, #0xf200 + ldrsh r1, [r1, #0x68] +#endif + add r3, r0, #0xf000 + sub r0, r2, r10 + str r1, [sp, #0x30] + ldr r1, =0xFFF0BDC1 + add r6, r3, r5, lsl #7 + str r1, [sp, #0x38] + mov r1, #0 + str r1, [sp, #0x34] + bl abs + ldrsh r11, [r4, #4] + ldrsh r1, [r7, #4] + mov r5, r0 + sub r0, r1, r11 + bl abs + str r0, [sp, #8] + cmp r0, r5 + mvn r0, #0 + strle r5, [sp, #8] + mov r5, #0 + str r0, [sp, #0x44] + b _01FFA924 +_01FFA834: + add r0, r6, r5, lsl #2 + ldrsh r0, [r0, #2] + ldrsh r1, [r7, #6] + str r0, [sp, #0x10] + sub r0, r1, r0 + str r1, [sp, #0xc] + bl abs + str r0, [sp, #0x40] + mov r0, r5, lsl #2 + ldrsh r0, [r6, r0] + ldrsh r1, [r7, #4] + str r0, [sp, #0x18] + sub r0, r1, r0 + str r1, [sp, #0x14] + bl abs + ldr r1, [sp, #0x40] + str r0, [sp, #4] + cmp r0, r1 + movle r0, r1 + strle r0, [sp, #4] + ldr r0, [sp, #0x18] + ldr r1, [sp, #0x44] + sub r0, r0, r11 + str r0, [sp, #0x3c] + ldr r2, [sp, #0x3c] + ldr r0, [sp, #0x10] + cmp r2, r1 + strlt r1, [sp, #0x3c] + ldr r1, [sp, #0x44] + sub r0, r0, r10 + cmp r0, r1 + movlt r0, r1 + ldr r1, [sp, #0x3c] + cmp r1, #1 + movgt r1, #1 + strgt r1, [sp, #0x3c] + cmp r0, #1 + movgt r0, #1 + add r1, r10, r0 + ldr r0, [sp, #0xc] + sub r0, r0, r1 + bl abs + ldr r1, [sp, #0x3c] + str r0, [sp, #0x48] + ldr r0, [sp, #0x14] + add r1, r11, r1 + sub r0, r0, r1 + bl abs + ldr r1, [sp, #0x48] + cmp r0, r1 + movle r0, r1 + ldr r1, [sp, #8] + cmp r0, r1 + blt _01FFA920 + ldr r1, [sp, #0x38] + ldr r0, [sp, #4] + cmp r1, r0 + strlt r0, [sp, #0x38] + strlt r5, [sp, #0x34] +_01FFA920: + add r5, r5, #1 +_01FFA924: + ldr r0, [sp, #0x30] + cmp r5, r0 + blt _01FFA834 + ldr r0, [sp, #0x38] + cmp r0, #0 + blt _01FFA96C + mov r0, #5 + strb r0, [r9, #0x7c] + ldr r0, [sp, #0x34] + mov r0, r0, lsl #2 + ldrsh r2, [r6, r0] + ldr r0, [sp, #0x34] + add r1, r6, r0, lsl #2 + strh r2, [r9, #0x8c] + ldrsh r1, [r1, #2] + mov r0, #1 + strh r1, [r9, #0x8e] + b _01FFAF28 +_01FFA96C: + mov r0, #5 + strb r0, [r9, #0x7c] + ldrsh r2, [r4, #4] + ldrsh r1, [r7, #4] + mov r0, #1 + rsb r1, r1, r2, lsl #1 + strh r1, [r9, #0x8c] + ldrsh r2, [r4, #6] + ldrsh r1, [r7, #6] + rsb r1, r1, r2, lsl #1 + strh r1, [r9, #0x8e] + b _01FFAF28 +_01FFA99C: + mov r0, r4 + bl CalculateAiTargetPos + b _01FFAF28 +_01FFA9A8: + mov r0, r4 + ldr r7, [r4, #0xb4] + bl EntityIsValid__0230827C + cmp r0, #0 + moveq r0, #0 + beq _01FFAAB8 + mov r0, r4 + bl CheckVariousConditions + cmp r0, #0 + movne r0, #0 + bne _01FFAAB8 + mov r0, r4 + bl GetTileAtEntity + mov r5, r0 + ldr r6, [r5, #0x10] + cmp r6, #0 + moveq r0, #0 + beq _01FFAAB8 + ldr r0, [r6] + cmp r0, #6 + addls pc, pc, r0, lsl #2 + b _01FFAAB4 +_01FFAA00: + b _01FFAAB4 + b _01FFAAB4 + b _01FFAAB4 + b _01FFAA1C + b _01FFAAB4 + b _01FFAAB4 + b _01FFAAB4 +_01FFAA1C: + ldrb r0, [r7, #7] + cmp r0, #0 + bne _01FFAAB4 + ldrb r0, [r7, #0x62] + tst r0, #1 + movne r0, #1 + moveq r0, #0 + tst r0, #0xff + bne _01FFAAB4 + ldrh r0, [r5] + tst r0, #3 + bne _01FFAA58 + ldrb r0, [r7, #6] + cmp r0, #0 + bne _01FFAAB4 +_01FFAA58: + ldrb r0, [r7, #6] + cmp r0, #0 + bne _01FFAA84 + bl IsBagFull + cmp r0, #0 + bne _01FFAAB4 + ldrh r0, [r5] + tst r0, #0x20 + bne _01FFAAB4 + mov r0, #1 + b _01FFAAB8 +_01FFAA84: + mov r0, r6 + bl GetItemInfo + bl ov29_02348D00 + cmp r0, #0 + movne r0, #0 + bne _01FFAAB8 + mov r0, r6 + bl GetItemInfo + ldrb r0, [r0] + tst r0, #2 + moveq r0, #1 + beq _01FFAAB8 +_01FFAAB4: + mov r0, #0 +_01FFAAB8: + cmp r0, #0 + movne r0, #0x3f + strneh r0, [r8, #0x4a] + bne _01FFB2A4 + mov r0, r4 + ldr r10, [r4, #0xb4] + bl ShouldMonsterFollowLeader + cmp r0, #0 + bne _01FFAD14 + ldr r0, =DUNGEON_PTR + ldr r1, [r0] + add r0, r1, #0x3000 + ldrb r0, [r0, #0xe38 + AI_MOVEMENT_OFFSET_2] + cmp r0, #0 + addne r0, r1, #0x378 + AI_MOVEMENT_OFFSET_2 + addne r9, r0, #0x12800 + movne r11, #0x14 + bne _01FFAB30 + ldrb r0, [r10, #6] + cmp r0, #0 + beq _01FFAB24 + ldrb r0, [r10, #8] + cmp r0, #0 + addeq r0, r1, #0x328 + AI_MOVEMENT_OFFSET_2 + addeq r9, r0, #0x12800 + moveq r11, #4 + beq _01FFAB30 +_01FFAB24: + add r0, r1, #0x338 + AI_MOVEMENT_OFFSET_2 + add r9, r0, #0x12800 + mov r11, #0x10 +_01FFAB30: + mov r0, r4 + bl CanCrossWalls + mvn r6, #0 + str r0, [sp, #0x20] + add r0, r6, #0x3e8 + str r0, [sp, #0x1c] + mov r7, #0 + b _01FFAC64 +_01FFAB50: + ldr r5, [r9, r7, lsl #2] + mov r0, r5 + bl EntityIsValid__0230827C + cmp r0, #0 + beq _01FFAC60 + ldr r0, [r5, #0xb4] + ldrb r1, [r0, #0xbc] + cmp r1, #6 + bhi _01FFAC60 + ldr r1, =DUNGEON_PTR + ldr r1, [r1] + add r1, r1, #0x3000 + ldrb r1, [r1, #0xe38 + AI_MOVEMENT_OFFSET_2] + cmp r1, #0 + beq _01FFABAC + mov r0, r4 + mov r1, r5 + mov r2, #0 + mov r3, #1 + bl GetTreatmentBetweenMonsters + cmp r0, #1 + bne _01FFAC60 + b _01FFABC0 +_01FFABAC: + ldrb r1, [r10, #6] + cmp r1, #0 + ldreqb r0, [r0, #0xc4] + cmpeq r0, #6 + beq _01FFAC60 +_01FFABC0: + ldr r0, [r5, #0xb4] + ldrb r0, [r0, #9] + cmp r0, #1 + beq _01FFAC60 + ldr r0, [sp, #0x20] + cmp r0, #0 + beq _01FFAC24 + ldrsh r1, [r4, #4] + ldrsh r0, [r5, #4] + sub r0, r1, r0 + bl abs + cmp r0, #5 + bgt _01FFAC0C + ldrsh r1, [r4, #6] + ldrsh r0, [r5, #6] + sub r0, r1, r0 + bl abs + cmp r0, #5 + ble _01FFAC38 +_01FFAC0C: + mov r0, r4 + mov r1, r5 + bl CanTargetEntity + cmp r0, #0 + beq _01FFAC60 + b _01FFAC38 +_01FFAC24: + mov r0, r4 + mov r1, r5 + bl CanTargetEntity + cmp r0, #0 + beq _01FFAC60 +_01FFAC38: + add r1, r5, #4 + add r0, r4, #4 + bl GetChebyshevDistance + ldr r1, [sp, #0x1c] + cmp r1, r0 + ble _01FFAC60 + str r0, [sp, #0x1c] + mov r6, r7 + cmp r0, #2 + blt _01FFAC6C +_01FFAC60: + add r7, r7, #1 +_01FFAC64: + cmp r7, r11 + blt _01FFAB50 +_01FFAC6C: + cmp r6, #0 + blt _01FFAD14 + mov r2, #1 + strb r2, [r10, #0x7c] + ldr r7, [r9, r6, lsl #2] + mov r0, r4 + ldrh r5, [r7, #4] + mov r3, #0 + mov r1, #8 + strh r5, [r10, #0x8c] + ldrh r5, [r7, #6] + strh r5, [r10, #0x8e] + ldr r5, [r9, r6, lsl #2] + str r5, [r10, #0x84] + ldr r5, [r9, r6, lsl #2] + ldrh r5, [r5, #0x26] + strh r5, [r10, #0x80] + strb r2, [r10, #0x7e] + str r3, [r10, #0x120 + AI_MOVEMENT_OFFSET] + bl IsTacticSet + cmp r0, #0 + beq _01FFAD0C + mov r0, r4 + bl CanSeeTeammate + cmp r0, #0 + bne _01FFAD0C + ldr r5, [r9, r6, lsl #2] + ldrsh r1, [r4, #4] + ldrsh r0, [r5, #4] + sub r0, r1, r0 + bl abs + cmp r0, #1 + bgt _01FFAD0C + ldrsh r1, [r4, #6] + ldrsh r0, [r5, #6] + sub r0, r1, r0 + bl abs + cmp r0, #1 + movle r0, #1 + strleb r0, [r10, #0x7f] +_01FFAD0C: + mov r0, #1 + b _01FFAF28 +_01FFAD14: + mov r0, r4 + mov r1, #1 + bl IsTacticSet + cmp r0, #0 + bne _01FFAD7C + ldrb r0, [r10, #6] + cmp r0, #0 + bne _01FFAE68 + mov r0, r4 + bl GetLeaderIfVisible + mov r5, r0 + bl EntityIsValid__0230827C + cmp r0, #0 + beq _01FFAE68 + mov r0, #1 + strb r0, [r10, #0x7c] + ldrh r2, [r5, #4] + mov r1, #0 + strh r2, [r10, #0x8c] + ldrh r2, [r5, #6] + strh r2, [r10, #0x8e] + str r5, [r10, #0x84] + ldrh r2, [r5, #0x26] + strh r2, [r10, #0x80] + str r1, [r10, #0x120 + AI_MOVEMENT_OFFSET] + b _01FFAF28 +_01FFAD7C: + ldrb r0, [r10, #7] + cmp r0, #0 + beq _01FFAE68 + bl GetVisibilityRange + ldrsh r0, [r4, #4] + ldrsh r1, [r4, #6] + bl GetTile + ldrb r2, [r0, #7] + cmp r2, #0xff + bne _01FFADC0 + ldrsh r1, [r4, #4] + ldrsh r0, [r4, #6] + sub r11, r1, #2 + sub r9, r0, #2 + add r6, r1, #2 + add r5, r0, #2 + b _01FFAE60 +_01FFADC0: + ldr r0, =DUNGEON_PTR + mov r1, #0x1c + ldr r0, [r0] + add r0, r0, #0x2e8 + AI_MOVEMENT_OFFSET_2 + add r0, r0, #0xec00 + mla r0, r2, r1, r0 + ldrsh r3, [r0, #2] + ldrsh r2, [r0, #4] + ldrsh r1, [r0, #6] + ldrsh r0, [r0, #8] + sub r11, r3, #1 + sub r9, r2, #1 + add r6, r1, #1 + add r5, r0, #1 + b _01FFAE60 +_01FFADFC: + mov r7, r11 + b _01FFAE54 +_01FFAE04: + mov r0, r7 + mov r1, r9 + bl GetTileSafe + ldr r0, [r0, #0x10] + cmp r0, #0 + beq _01FFAE50 + ldr r0, [r0] + cmp r0, #3 + bne _01FFAE50 + mov r0, #7 + strb r0, [r10, #0x7c] + strh r7, [r10, #0x8c] + strh r9, [r10, #0x8e] + mov r0, #0 + str r0, [r10, #0x84] + strh r0, [r10, #0x80] + str r0, [r10, #0x120 + AI_MOVEMENT_OFFSET] + mov r0, #1 + b _01FFAF28 +_01FFAE50: + add r7, r7, #1 +_01FFAE54: + cmp r7, r6 + ble _01FFAE04 + add r9, r9, #1 +_01FFAE60: + cmp r9, r5 + ble _01FFADFC +_01FFAE68: + mov r0, r4 + bl HasDropeyeStatus + cmp r0, #0 + bne _01FFAF1C + ldrb r0, [r10, #0x7c] + add r0, r0, #0xff + and r0, r0, #0xff + cmp r0, #1 + bhi _01FFAF1C + ldr r2, [r10, #0x84] + cmp r2, #0 + beq _01FFAF1C + ldrh r1, [r2, #0x26] + ldrh r0, [r10, #0x80] + cmp r1, r0 + bne _01FFAF08 + ldr r7, [r2, #0xb4] + mov r6, #0 + add r5, r7, #0x6a + b _01FFAEFC +_01FFAEB8: + mov r0, r4 + add r1, r5, r6, lsl #2 + bl CanTargetPosition + cmp r0, #0 + beq _01FFAEF8 + mov r0, #2 + strb r0, [r10, #0x7c] + add r3, r7, r6, lsl #2 + ldrh r2, [r3, #0x6a] + mov r1, #0 + mov r0, #1 + strh r2, [r10, #0x8c] + ldrh r2, [r3, #0x6c] + strh r2, [r10, #0x8e] + str r1, [r10, #0x120 + AI_MOVEMENT_OFFSET] + b _01FFAF28 +_01FFAEF8: + add r6, r6, #1 +_01FFAEFC: + cmp r6, #4 + blt _01FFAEB8 + b _01FFAF1C +_01FFAF08: + mov r0, #6 + strb r0, [r10, #0x7c] + mov r0, #0 + str r0, [r10, #0x84] + strh r0, [r10, #0x80] +_01FFAF1C: + mov r0, r4 + bl CalculateAiTargetPos + mov r0, #1 +_01FFAF28: + cmp r0, #0 + moveq r0, #0 + streqh r0, [r8, #0x4a] + beq _01FFB2A4 + ldr r9, [r4, #0xb4] + ldrh r1, [r9, #0x8c] + add r0, r9, #0x100 + strh r1, [r0, #0x7e + AI_MOVEMENT_OFFSET] + ldrh r1, [r9, #0x8e] + strh r1, [r0, #0x80 + AI_MOVEMENT_OFFSET] + ldrsh r1, [r4, #4] + ldrsh r0, [r9, #0x8c] + cmp r1, r0 + ldreqsh r1, [r4, #6] + ldreqsh r0, [r9, #0x8e] + cmpeq r1, r0 + bne _01FFAF7C + add r0, r9, #0x4a + mov r1, #1 + bl SetMonsterActionFields + b _01FFB2A4 +_01FFAF7C: + mov r0, r9 + bl ov29_022FBE04 + cmp r0, #0 + bne _01FFB2A4 + add r0, r4, #4 + add r1, r9, #0x8c + bl GetDirectionTowardsPosition + mov r7, r0 + ldrb r1, [r9, #0x7e] + mov r0, r4 + bl ShouldAvoidFirstHit + cmp r0, #0 + beq _01FFB000 + ldrb r0, [r9, #0x7c] + cmp r0, #1 + bne _01FFB010 + add r0, r4, #4 + add r1, r9, #0x8c + bl IsPositionWithinTwoTiles + cmp r0, #0 + beq _01FFB010 + add r0, r4, #4 + add r1, r9, #0x8c + bl GetChebyshevDistance + cmp r0, #2 + bne _01FFAFF4 + add r0, r9, #0x4a + mov r1, #1 + bl SetMonsterActionFields + b _01FFB2A4 +_01FFAFF4: + addlt r0, r7, #4 + andlt r7, r0, #7 + b _01FFB010 +_01FFB000: + ldrb r0, [r9, #0x7f] + cmp r0, #0 + addne r0, r7, #4 + andne r7, r0, #7 +_01FFB010: + add r2, sp, #0x50 + mov r0, r4 + mov r1, r7 + bl CanAiMonsterMoveInDirection + cmp r0, #0 + beq _01FFB040 + ldrsh r1, [r9, #2] + add r0, r9, #0x4a + bl SetActionPassTurnOrWalk + and r0, r7, #7 + strb r0, [r9, #0x4c] + b _01FFB2A4 +_01FFB040: + ldrb r0, [sp, #0x50] + cmp r0, #0 + beq _01FFB0DC + ldrb r0, [r9, #6] + cmp r0, #0 + ldreqb r0, [r9, #0x14f + AI_MOVEMENT_OFFSET] + cmpeq r0, #0 + bne _01FFB080 + mov r1, #1 + strb r1, [r9, #0x7d] + add r0, r9, #0x4a + strb r1, [r9, #0x14e + AI_MOVEMENT_OFFSET] + bl SetMonsterActionFields + mov r0, #1 + strb r0, [r9, #0x151 + AI_MOVEMENT_OFFSET] + b _01FFB2A4 +_01FFB080: + ldr r0, =DIRECTIONS_XY + mov r2, r7, lsl #2 + ldrsh r1, [r4, #4] + ldrsh r0, [r0, r2] + ldrsh r3, [r9, #0x8c] + add r0, r1, r0 + cmp r3, r0 + bne _01FFB0D4 + ldr r0, =DIRECTIONS_XY + 2 + ldrsh r1, [r4, #6] + ldrsh r0, [r0, r2] + ldrsh r2, [r9, #0x8e] + add r0, r1, r0 + cmp r2, r0 + bne _01FFB0D4 + add r0, r9, #0x4a + mov r1, #1 + bl SetMonsterActionFields + mov r0, #1 + strb r0, [r9, #0x151 + AI_MOVEMENT_OFFSET] + b _01FFB2A4 +_01FFB0D4: + mov r0, #1 + strb r0, [r9, #0x7d] +_01FFB0DC: + mov r0, #1 + strb r0, [sp, #0x80] + strb r0, [sp, #0x78] + strb r0, [sp, #0x70] + strb r0, [sp, #0x68] + strb r0, [sp, #0x60] + ldrb r0, [r9, #6] + cmp r0, #0 + bne _01FFB16C + tst r7, #1 + beq _01FFB16C + ldrsh r1, [r4, #4] + ldrsh r0, [r9, #0x8c] + sub r0, r1, r0 + bl abs + ldrsh r2, [r4, #6] + ldrsh r1, [r9, #0x8e] + mov r5, r0 + sub r0, r2, r1 + bl abs + cmp r5, #2 + cmple r0, #2 + bgt _01FFB16C + cmp r5, r0 + beq _01FFB16C + tst r7, #2 + beq _01FFB15C + cmp r5, r0 + mov r0, #0 + strltb r0, [sp, #0x68] + strgeb r0, [sp, #0x60] + b _01FFB16C +_01FFB15C: + cmp r5, r0 + mov r0, #0 + strltb r0, [sp, #0x60] + strgeb r0, [sp, #0x68] +_01FFB16C: + ldrsh r0, [r4, #4] + ldrsh r1, [r4, #6] + bl GetTile + ldrh r0, [r0] + ldr r1, [sp] + tst r0, #0x100 + movne r10, #5 + mov r0, r4 + moveq r10, #3 + bl ShouldMonsterRunAwayAndShowEffectOutlawCheck + cmp r0, #0 + ldreqb r0, [r9, #0x7f] + mov r8, #1 + mov r11, r8 + cmpeq r0, #0 + movne r10, #5 + ldr r6, =FACING_DIRECTION_INCREMENTS + add r5, sp, #0x58 + b _01FFB1FC +_01FFB1B8: + ldr r0, [r6, r8, lsl #2] + add r3, r5, r8, lsl #3 + add r0, r7, r0 + and r1, r0, #7 + mov r0, r4 + add r2, r3, #2 + str r1, [r3, #4] + bl CanAiMonsterMoveInDirection + add r1, r5, r8, lsl #3 + strb r0, [r1, #1] + tst r0, #0xff + ldreqb r0, [r1, #2] + add r8, r8, #1 + cmpeq r0, #0 + andeq r0, r11, #0xff + streqb r11, [sp, #0x68] + streqb r0, [sp, #0x60] +_01FFB1FC: + cmp r8, r10 + blt _01FFB1B8 + mov r4, #1 + add r2, sp, #0x58 + mov r0, r4 + b _01FFB264 +_01FFB214: + add r1, r2, r4, lsl #3 + ldrb r1, [r1, #1] + mov r3, r4, lsl #3 + cmp r1, #0 + ldrneb r1, [r2, r3] + cmpne r1, #0 + beq _01FFB250 + ldrsh r1, [r9, #2] + add r0, r9, #0x4a + bl SetActionPassTurnOrWalk + add r0, sp, #0x5c + ldr r0, [r0, r4, lsl #3] + and r0, r0, #7 + strb r0, [r9, #0x4c] + b _01FFB2A4 +_01FFB250: + add r1, r2, r4, lsl #3 + ldrb r1, [r1, #2] + add r4, r4, #1 + cmp r1, #0 + strneb r0, [r9, #0x7d] +_01FFB264: + cmp r4, r10 + blt _01FFB214 + add r0, r9, #0x4a + mov r1, #1 + bl SetMonsterActionFields + mov r1, #1 + strb r1, [r9, #0x151 + AI_MOVEMENT_OFFSET] + ldrb r0, [r9, #7] + cmp r0, #0 + movne r0, #0 + strneb r0, [r9, #0x7d] + strneb r0, [r9, #0x14e + AI_MOVEMENT_OFFSET] + bne _01FFB2A4 + ldrb r0, [r9, #0x7d] + cmp r0, #0 + strneb r1, [r9, #0x14e + AI_MOVEMENT_OFFSET] +_01FFB2A4: + add sp, sp, #0x88 + ldmia sp!, {r3, r4, r5, r6, r7, r8, r9, r10, r11, pc} +} +#endif diff --git a/src/dungeon_ai_targeting.c b/src/dungeon_ai_targeting.c index ba14ec30..1b6e8215 100644 --- a/src/dungeon_ai_targeting.c +++ b/src/dungeon_ai_targeting.c @@ -21,8 +21,8 @@ bool8 ShouldMonsterRunAway(struct entity *monster) if (AbilityIsActive(monster, ABILITY_RUN_AWAY)) { s32 max_hp = pokemon_info->max_hp_stat + pokemon_info->max_hp_boost; - if (max_hp > 999) - max_hp = 999; + if (max_hp > MAX_HP_LIMIT) + max_hp = MAX_HP_LIMIT; bool8 run_away_active = pokemon_info->hp < max_hp / 2; if (run_away_active) @@ -35,8 +35,8 @@ bool8 ShouldMonsterRunAway(struct entity *monster) if (IsTacticSet(monster, TACTIC_AVOID_TROUBLE)) { s32 max_hp = pokemon_info->max_hp_stat + pokemon_info->max_hp_boost; - if (max_hp > 999) - max_hp = 999; + if (max_hp > MAX_HP_LIMIT) + max_hp = MAX_HP_LIMIT; if (pokemon_info->hp <= max_hp / 2) return TRUE; diff --git a/src/dungeon_capabilities.c b/src/dungeon_capabilities.c index 720ba16d..be10623a 100644 --- a/src/dungeon_capabilities.c +++ b/src/dungeon_capabilities.c @@ -21,8 +21,8 @@ bool8 MonsterHasQuarterHp(struct entity *monster) { struct monster *entity_data = GetEntInfo(monster); s32 max_hp = entity_data->max_hp_stat + entity_data->max_hp_boost; - if (max_hp > 999) - max_hp = 999; + if (max_hp > MAX_HP_LIMIT) + max_hp = MAX_HP_LIMIT; if (entity_data->hp <= max_hp / 4) return TRUE; diff --git a/src/dungeon_damage.c b/src/dungeon_damage.c index c2019923..5d072205 100644 --- a/src/dungeon_damage.c +++ b/src/dungeon_damage.c @@ -84,28 +84,28 @@ s32 WeightWeakTypePicker(struct entity *user, struct entity *target, enum type_i if (move_type == TYPE_WATER && AbilityIsActiveVeneer(user, ABILITY_TORRENT)) { - s32 max_hp_stat = MIN(user_data->max_hp_stat + user_data->max_hp_boost, 999); + s32 max_hp_stat = MIN(user_data->max_hp_stat + user_data->max_hp_boost, MAX_HP_LIMIT); if (max_hp_stat / 4 >= user_data->hp) weight *= 2; } if (move_type == TYPE_GRASS && AbilityIsActiveVeneer(user, ABILITY_OVERGROW)) { - s32 max_hp_stat = MIN(user_data->max_hp_stat + user_data->max_hp_boost, 999); + s32 max_hp_stat = MIN(user_data->max_hp_stat + user_data->max_hp_boost, MAX_HP_LIMIT); if (max_hp_stat / 4 >= user_data->hp) weight *= 2; } if (move_type == TYPE_BUG && AbilityIsActiveVeneer(user, ABILITY_SWARM)) { - s32 max_hp_stat = MIN(user_data->max_hp_stat + user_data->max_hp_boost, 999); + s32 max_hp_stat = MIN(user_data->max_hp_stat + user_data->max_hp_boost, MAX_HP_LIMIT); if (max_hp_stat / 4 >= user_data->hp) weight *= 2; } if (move_type == TYPE_FIRE && AbilityIsActiveVeneer(user, ABILITY_BLAZE)) { - s32 max_hp_stat = MIN(user_data->max_hp_stat + user_data->max_hp_boost, 999); + s32 max_hp_stat = MIN(user_data->max_hp_stat + user_data->max_hp_boost, MAX_HP_LIMIT); if (max_hp_stat / 4 >= user_data->hp) weight *= 2; } diff --git a/src/dungeon_logic_4.c b/src/dungeon_logic_4.c index 7a0846af..74c98472 100644 --- a/src/dungeon_logic_4.c +++ b/src/dungeon_logic_4.c @@ -12,8 +12,8 @@ bool8 HasLowHealth(struct entity *entity) struct monster *pokemon_info = GetEntInfo(entity); s32 max_hp = pokemon_info->max_hp_stat + pokemon_info->max_hp_boost; - if (max_hp > 999) - max_hp = 999; + if (max_hp > MAX_HP_LIMIT) + max_hp = MAX_HP_LIMIT; return pokemon_info->hp < max_hp / 4; } diff --git a/src/dungeon_recruitment.c b/src/dungeon_recruitment.c index 10fb1370..acf57ac4 100644 --- a/src/dungeon_recruitment.c +++ b/src/dungeon_recruitment.c @@ -1,13 +1,14 @@ #include "dungeon_recruitment.h" -#include "dungeon.h" -#include "dungeon_mode.h" -#include "dungeon_logic_3.h" -#include "dungeon_pokemon_attributes_1.h" -#include "main_0208655C.h" -#include "enums.h" -#include "dungeon_visibility.h" #include "dg_random.h" +#include "dungeon_logic_3.h" +#include "dungeon_mode.h" +#include "dungeon_pokemon_attributes_1.h" +#include "dungeon_visibility.h" +#include "dungeon.h" +#include "enums.h" #include "main_0205283C.h" // GetRecruitRate1 and GetRecruitRate2 +#include "main_0208655C.h" +#include "math.h" #include "overlay_29_0230E578.h" // ItemIsActive__0230E578 extern bool8 IsRecruitingAllowed(u8 dungeon_id); @@ -36,7 +37,7 @@ extern const s16 SKY_MELODICA_RECRUIT_BOOST; extern s16 RECRUITMENT_LEVEL_BOOST_TABLE[]; -bool8 SpecificRecruitCheck(u32 monster_id) +bool8 SpecificRecruitCheck(u32 monster_id) { if (DUNGEON_PTR[0]->recruiting_enabled == FALSE) { return FALSE; @@ -83,19 +84,19 @@ bool8 SpecificRecruitCheck(u32 monster_id) } } -bool8 RecruitCheck(struct entity* leader, struct entity* target) +bool8 RecruitCheck(struct entity* leader, struct entity* target) { s32 random_roll; struct monster* leader_monster_info = leader->info; struct monster* target_monster_info = target->info; - + s32 recruit_rate; bool8 already_on_team; s16 target_mon_id; - if (!IsRecruitingAllowed(DUNGEON_PTR[0]->id) || - IsFullFloorFixedRoom() || - IsLegendaryChallengeFloor() || + if (!IsRecruitingAllowed(DUNGEON_PTR[0]->id) || + IsFullFloorFixedRoom() || + IsLegendaryChallengeFloor() || IsCurrentMissionTypeExact(MISSION_ARREST_OUTLAW, MISSION_OUTLAW_HIDEOUT)) return FALSE; @@ -116,7 +117,7 @@ bool8 RecruitCheck(struct entity* leader, struct entity* target) || target_mon_id == MONSTER_LATIAS || target_mon_id == MONSTER_LATIOS || target_mon_id == MONSTER_JIRACHI || target_mon_id == MONSTER_RAYQUAZA || target_mon_id == MONSTER_DEOXYS_NORMAL || target_mon_id == MONSTER_REGIROCK - || target_mon_id == MONSTER_REGICE || target_mon_id == MONSTER_REGISTEEL + || target_mon_id == MONSTER_REGICE || target_mon_id == MONSTER_REGISTEEL || (u16)(s16)(target_mon_id - 534) <= 1) { if (IsMonsterOnTeam(target_mon_id, 1)) return FALSE; @@ -156,9 +157,9 @@ bool8 RecruitCheck(struct entity* leader, struct entity* target) recruit_rate = recruit_rate >>= 1; } - if (recruit_rate == -999) + if (recruit_rate == -INFINITY) return FALSE; - + if (ItemIsActive__0230E578(leader, ITEM_FRIEND_BOW)) { recruit_rate += FRIEND_BOW_FAST_FRIEND_BOOST; } else if (ItemIsActive__0230E578(leader, ITEM_GOLDEN_MASK)) { @@ -189,16 +190,16 @@ bool8 RecruitCheck(struct entity* leader, struct entity* target) if (random_roll >= recruit_rate) return FALSE; - + s32 free_slot_index = GetFirstEmptyMemberIdx(0); if(free_slot_index < 0) { return FALSE; } - + if(free_slot_index >= 0) { return TRUE; } - + return TRUE; } diff --git a/src/move_checks.c b/src/move_checks.c index 2e32b4ac..b3970c7b 100644 --- a/src/move_checks.c +++ b/src/move_checks.c @@ -114,14 +114,14 @@ bool8 StatusCheckerCheck(struct entity *attacker, struct move *move) if (pokemon_info->frozen_class_status.freeze == STATUS_FROZEN_INGRAIN) return FALSE; - s32 max_hp = Min(999, pokemon_info->max_hp_stat + pokemon_info->max_hp_boost); + s32 max_hp = Min(MAX_HP_LIMIT, pokemon_info->max_hp_stat + pokemon_info->max_hp_boost); if (max_hp / 2 < pokemon_info->hp) return FALSE; break; } case MOVE_SWALLOW: { - s32 max_hp = Min(999, pokemon_info->max_hp_stat + pokemon_info->max_hp_boost); + s32 max_hp = Min(MAX_HP_LIMIT, pokemon_info->max_hp_stat + pokemon_info->max_hp_boost); if (max_hp <= pokemon_info->hp || pokemon_info->stockpile_stage == 0) return FALSE; break;