diff --git a/docs/progress.svg b/docs/progress.svg
index b1a4f167..8ad88647 100644
--- a/docs/progress.svg
+++ b/docs/progress.svg
@@ -69,10 +69,10 @@
Tomb2.exe progress according to the physical function order:
-35.80% (436) · 61.74% (752) · 0.41% (5) · 2.05% (25)
+35.88% (437) · 61.66% (751) · 0.41% (5) · 2.05% (25)
-
-
+
+
@@ -199,7 +199,7 @@
int16_t __cdecl Creature_Effect(ITEM_INFO *item, BITE_INFO *bite, int16_t (*__cdecl spawn)(int32_t x, int32_t y, int32_t z, int16_t speed, int16_t y_rot, int16_t room_num));
int32_t __cdecl Creature_Vault(int16_t item_num, int16_t angle, int32_t vault, int32_t shift);
void __cdecl Creature_Kill(ITEM_INFO *item, int32_t kill_anim, int32_t kill_state, int32_t lara_kill_state);
-void __cdecl Creature_GetBaddieTarget(int16_t item_num, int32_t goody);
+void __cdecl Creature_GetBaddieTarget(int16_t item_num, int32_t goody);
void __cdecl Camera_Initialise(void);
void __cdecl Camera_Move(const GAME_VECTOR *target, int32_t speed);
void __cdecl Camera_Clip(int32_t *x, int32_t *y, int32_t *h, int32_t target_x, int32_t target_y, int32_t target_h, int32_t left, int32_t top, int32_t right, int32_t bottom);
@@ -1299,10 +1299,10 @@
Tomb2.exe progress according to the function sizes:
-32.50% · 67.18% · 0% · 0.32%
+32.63% · 67.04% · 0% · 0.32%
-
-
+
+
@@ -1499,7 +1499,7 @@
void __cdecl Matrix_RotYXZ(int16_t ry, int16_t rx, int16_t rz);
void __cdecl MouseControl(int16_t item_num);
void __cdecl SE_GraphicsDlgFullScreenModesUpdate(HWND hwndDlg);
-void __cdecl Creature_GetBaddieTarget(int16_t item_num, int32_t goody);
+void __cdecl Creature_GetBaddieTarget(int16_t item_num, int32_t goody);
void __cdecl CreateFlare(int32_t thrown);
void __cdecl ShowGymStatsText(char *time_str, int32_t type);
BOOL __cdecl LoadItems(HANDLE handle);
diff --git a/docs/progress.txt b/docs/progress.txt
index b3bc8b9b..e5255f29 100644
--- a/docs/progress.txt
+++ b/docs/progress.txt
@@ -1824,7 +1824,7 @@ typedef struct {
004100B0 0000005C + int16_t __cdecl Creature_Effect(ITEM_INFO *item, BITE_INFO *bite, int16_t (*__cdecl spawn)(int32_t x, int32_t y, int32_t z, int16_t speed, int16_t y_rot, int16_t room_num));
00410110 00000131 + int32_t __cdecl Creature_Vault(int16_t item_num, int16_t angle, int32_t vault, int32_t shift);
00410250 0000016F + void __cdecl Creature_Kill(ITEM_INFO *item, int32_t kill_anim, int32_t kill_state, int32_t lara_kill_state);
-004103C0 000001DB - void __cdecl Creature_GetBaddieTarget(int16_t item_num, int32_t goody);
+004103C0 000001DB + void __cdecl Creature_GetBaddieTarget(int16_t item_num, int32_t goody);
# game/camera.c
004105A0 000000B0 + void __cdecl Camera_Initialise(void);
@@ -3315,3 +3315,4 @@ typedef struct {
005263C0 - int16_t *g_FlyZone[2];
00526398 - int16_t *g_GroundZone[][2];
005263C8 - uint16_t *g_Overlap;
+005206C0 - CREATURE_INFO *g_BaddieSlots;
diff --git a/src/game/creature.c b/src/game/creature.c
index 6b6ce59a..abea2885 100644
--- a/src/game/creature.c
+++ b/src/game/creature.c
@@ -18,6 +18,7 @@
#define MAX_HEAD_CHANGE (5 * PHD_DEGREE) // = 910
#define HEAD_ARC 0x3000 // = 12288
#define FLOAT_SPEED 32
+#define TARGET_TOLERANCE 0x400000
void __cdecl Creature_Initialise(const int16_t item_num)
{
@@ -798,3 +799,69 @@ void __cdecl Creature_Kill(
g_Camera.pos.room_num = g_LaraItem->room_num;
}
+
+void __cdecl Creature_GetBaddieTarget(
+ const int16_t item_num, const int32_t goody)
+{
+ ITEM_INFO *const item = &g_Items[item_num];
+ CREATURE_INFO *const creature = item->data;
+
+ ITEM_INFO *best_item = NULL;
+ int32_t best_distance = INT32_MAX;
+ for (int i = 0; i < NUM_SLOTS; i++) {
+ const int16_t target_item_num = g_BaddieSlots[i].item_num;
+ if (target_item_num == NO_ITEM || target_item_num == item_num) {
+ continue;
+ }
+
+ ITEM_INFO *target = &g_Items[target_item_num];
+ const int16_t object_num = target->object_num;
+ if (goody && object_num != O_BANDIT_1 && object_num != O_BANDIT_2) {
+ continue;
+ } else if (!goody && object_num != O_MONK_1 && object_num != O_MONK_2) {
+ continue;
+ }
+
+ const int32_t dx = (target->pos.x - item->pos.x) >> 6;
+ const int32_t dy = (target->pos.y - item->pos.y) >> 6;
+ const int32_t dz = (target->pos.z - item->pos.z) >> 6;
+ const int32_t distance = SQUARE(dx) + SQUARE(dy) + SQUARE(dz);
+ if (distance < best_distance) {
+ best_item = target;
+ best_distance = distance;
+ }
+ }
+
+ if (best_item == NULL) {
+ if (!goody || g_IsMonkAngry) {
+ creature->enemy = g_LaraItem;
+ } else {
+ creature->enemy = NULL;
+ }
+ return;
+ }
+
+ if (!goody || g_IsMonkAngry) {
+ const int32_t dx = (g_LaraItem->pos.x - item->pos.x) >> 6;
+ const int32_t dy = (g_LaraItem->pos.y - item->pos.y) >> 6;
+ const int32_t dz = (g_LaraItem->pos.z - item->pos.z) >> 6;
+ const int32_t distance = SQUARE(dx) + SQUARE(dy) + SQUARE(dz);
+ if (distance < best_distance) {
+ best_item = g_LaraItem;
+ best_distance = distance;
+ }
+ }
+
+ const ITEM_INFO *const target = creature->enemy;
+ if (target == NULL || target->status != IS_ACTIVE) {
+ creature->enemy = best_item;
+ } else {
+ const int32_t dx = (target->pos.x - item->pos.x) >> 6;
+ const int32_t dy = (target->pos.y - item->pos.y) >> 6;
+ const int32_t dz = (target->pos.z - item->pos.z) >> 6;
+ const int32_t distance = SQUARE(dz) + SQUARE(dy) + SQUARE(dx);
+ if (distance < best_distance + TARGET_TOLERANCE) {
+ creature->enemy = best_item;
+ }
+ }
+}
diff --git a/src/game/creature.h b/src/game/creature.h
index 216e7e33..a32d0d80 100644
--- a/src/game/creature.h
+++ b/src/game/creature.h
@@ -28,3 +28,5 @@ int32_t __cdecl Creature_Vault(
void __cdecl Creature_Kill(
ITEM_INFO *const item, int32_t kill_anim, int32_t kill_state,
int32_t lara_kill_state);
+void __cdecl Creature_GetBaddieTarget(
+ const int16_t item_num, const int32_t goody);
diff --git a/src/global/const.h b/src/global/const.h
index 9d62087a..4d15a563 100644
--- a/src/global/const.h
+++ b/src/global/const.h
@@ -139,6 +139,7 @@
#define FOG_START (12 * WALL_L) // = 12288
#define FOG_END (20 * WALL_L) // = 20480
+#define NUM_SLOTS 5
#define DONT_TARGET (-16384)
#define IDS_DX5_REQUIRED 1
diff --git a/src/global/funcs.h b/src/global/funcs.h
index 6f357e27..0073d038 100644
--- a/src/global/funcs.h
+++ b/src/global/funcs.h
@@ -18,7 +18,6 @@
#define Boat_Animation ((void __cdecl (*)(ITEM_INFO *boat, int32_t collide))0x0040D950)
#define Boat_Control ((void __cdecl (*)(int16_t item_num))0x0040DAC0)
#define Gondola_Control ((void __cdecl (*)(int16_t item_num))0x0040E0F0)
-#define Creature_GetBaddieTarget ((void __cdecl (*)(int16_t item_num, int32_t goody))0x004103C0)
#define Game_SetCutsceneTrack ((void __cdecl (*)(int32_t track))0x00411F50)
#define Game_Cutscene_Start ((int32_t __cdecl (*)(int32_t level_num))0x00411F60)
#define Misc_InitCinematicRooms ((void __cdecl (*)(void))0x00412080)
diff --git a/src/global/vars.h b/src/global/vars.h
index 3da258ea..c8e7576a 100644
--- a/src/global/vars.h
+++ b/src/global/vars.h
@@ -250,6 +250,7 @@
#define g_TextstringBuffers (*(char(*)[64][64])0x0051D6C0)
#define g_SoundIsActive (*(int32_t*)0x0051E6C4)
#define g_SaveGame (*(SAVEGAME_INFO*)0x0051E9E0)
+#define g_BaddieSlots (*(CREATURE_INFO **)0x005206C0)
#define g_Lara (*(LARA_INFO*)0x005206E0)
#define g_LaraItem (*(ITEM_INFO **)0x005207BC)
#define g_Effects (*(FX_INFO **)0x005207C0)
diff --git a/src/inject_exec.c b/src/inject_exec.c
index 7f24d23c..9b6b1c15 100644
--- a/src/inject_exec.c
+++ b/src/inject_exec.c
@@ -531,6 +531,7 @@ static void Inject_Creature(void)
INJECT(1, 0x004100B0, Creature_Effect);
INJECT(1, 0x00410110, Creature_Vault);
INJECT(1, 0x00410250, Creature_Kill);
+ INJECT(1, 0x004103C0, Creature_GetBaddieTarget);
}
static void Inject_Box(void)