Decompile tt_002 func_us_80174998 (#1846)

Weird issue with this one. The explicit casts for CalculateAngleToEntity
and GetTargetPositionWithDistanceBuffer are required.
Decomp.me will compile to the correct code without the casts, but the
bit shifts to clear the high side get compiled out with the actual
build.

PSX: https://decomp.me/scratch/K1ruf
PSP: https://decomp.me/scratch/x5w17
This commit is contained in:
H.M. Burger 2024-10-29 17:14:30 -05:00 committed by GitHub
parent 35ffeb8314
commit 7d285b6d5e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 180 additions and 33 deletions

View File

@ -23,3 +23,14 @@ ServantUnk0 = 0x8017925C;
s_ServantId = 0x801792DC; s_ServantId = 0x801792DC;
s_zPriority = 0x801792E0; s_zPriority = 0x801792E0;
s_FaerieStats = 0x801792E4; s_FaerieStats = 0x801792E4;
D_us_80179310 = 0x80179310;
D_us_80179314 = 0x80179314;
D_us_80179318 = 0x80179318;
s_TargetLocationX = 0x80179324;
s_TargetLocationY = 0x80179328;
s_TargetLocationX_calc = 0x8017932C;
s_TargetLocationY_calc = 0x80179330;
s_AngleToTarget = 0x80179334;
s_AllowedAngle = 0x80179338;
s_DistToTargetLocation = 0x8017933C;
s_TargetLocOffset_calc = 0x80179340;

View File

@ -602,23 +602,25 @@ typedef struct {
/* 0xA2 */ struct Entity* attackTarget; /* 0xA2 */ struct Entity* attackTarget;
} ET_Ghost; } ET_Ghost;
// There appears to be a 2nd Ext used in the Faerie code
typedef struct { typedef struct {
/* 0x7C */ struct Entity* unk7C; /* 0x7C */ struct Entity* unk7C;
} ET_Faerie; } ET_FaerieUnk0;
// There appears to be a 2nd Ext used in the Faerie code
typedef struct { typedef struct {
/* 0x7C */ s16 pad7c; /* 0x7C */ s16 pad7c;
/* 0x7E */ s16 unk7E; /* 0x7E */ s16 unk7E;
/* 0x80 */ s16 unk80; /* 0x80 */ s16 unk80;
/* 0x82 */ s16 pad82; /* 0x82 */ s16 pad82;
/* 0x84 */ s16 unk84; /* 0x84 */ s16 randomMovementAngle;
/* 0x86 */ s16 unk86; /* 0x86 */ s16 targetAngle;
/* 0x88 */ s16 unk88; /* 0x88 */ s16 unk88;
/* 0x8A */ s16 unk8A; /* 0x8A */ s16 maxAngle;
/* 0x8C */ s16 pad8C[5]; /* 0x8C */ s16 pad8C[5];
/* 0x96 */ s16 unk96; /* 0x96 */ s16 unk96;
} ET_FaerieUnk0; /* 0x98 */ s16 pad98[4];
/* 0xA0 */ s16 unkCounter;
} ET_Faerie;
struct draculaPrimitive; struct draculaPrimitive;
typedef struct ET_Dracula { typedef struct ET_Dracula {

View File

@ -11,6 +11,17 @@ extern s32 s_zPriority;
extern FamiliarStats s_FaerieStats; extern FamiliarStats s_FaerieStats;
extern s32 D_us_8017931C; extern s32 D_us_8017931C;
extern s32 D_us_80179320; extern s32 D_us_80179320;
extern s32 D_us_80179310;
extern s16 D_us_80179314;
extern s16 D_us_80179318;
extern s32 s_AllowedAngle;
extern s32 s_AngleToTarget;
extern s32 s_DistToTargetLocation;
extern s16 s_TargetLocOffset_calc;
extern s32 s_TargetLocationX;
extern s32 s_TargetLocationX_calc;
extern s32 s_TargetLocationY;
extern s32 s_TargetLocationY_calc;
// this may actually be a multi dimensional array instead of a struct // this may actually be a multi dimensional array instead of a struct
typedef struct { typedef struct {
@ -21,10 +32,17 @@ typedef struct {
extern UnkFaerieStruct D_us_80172368[]; extern UnkFaerieStruct D_us_80172368[];
extern AnimationFrame* D_us_80172B14[]; extern AnimationFrame* D_us_80172B14[];
void func_us_801739C8(Entity*);
void func_us_80173D60(Entity*);
void func_us_80173994(Entity*, s32); void func_us_80173994(Entity*, s32);
static s16 CalculateAngleToEntity(Entity* entity, s16 targetX, s16 targetY);
static s32 CalculateDistance(Entity* entity, s32 targetX, s32 targetY);
static s16 GetTargetPositionWithDistanceBuffer(
s16 currentX, s16 targetX, s16 distanceBuffer);
void func_us_801739D0(Entity* arg0) { void func_us_801739D0(Entity* arg0) {
if (!arg0->ext.faerieUnk0.unk7E) { if (!arg0->ext.faerie.unk7E) {
switch (arg0->entityId) { switch (arg0->entityId) {
case 0xD1: case 0xD1:
@ -34,10 +52,10 @@ void func_us_801739D0(Entity* arg0) {
func_us_80173994(arg0, 0xE); func_us_80173994(arg0, 0xE);
arg0->ext.faerieUnk0.unk84 = rand() % 4096; arg0->ext.faerie.randomMovementAngle = rand() % 4096;
arg0->ext.faerieUnk0.unk86 = 0; arg0->ext.faerie.targetAngle = 0;
arg0->ext.faerieUnk0.unk88 = 8; arg0->ext.faerie.unk88 = 8;
arg0->ext.faerieUnk0.unk8A = 0x20; arg0->ext.faerie.maxAngle = 0x20;
arg0->step++; arg0->step++;
break; break;
case 0xD9: case 0xD9:
@ -50,7 +68,7 @@ void func_us_801739D0(Entity* arg0) {
} else { } else {
switch (arg0->entityId) { switch (arg0->entityId) {
case 0xD1: case 0xD1:
arg0->ext.faerieUnk0.unk96 = 0x78; arg0->ext.faerie.unk96 = 0x78;
// fallthrough // fallthrough
case 0xD2: case 0xD2:
case 0xD3: case 0xD3:
@ -71,7 +89,7 @@ void func_us_801739D0(Entity* arg0) {
arg0->step++; arg0->step++;
} }
} }
arg0->ext.faerieUnk0.unk7E = arg0->entityId; arg0->ext.faerie.unk7E = arg0->entityId;
D_us_8017931C = 0; D_us_8017931C = 0;
} }
@ -106,37 +124,37 @@ void CreateEventEntity_Dupe(Entity* entityParent, s32 entityId, s32 params) {
void func_us_80173BD0(Entity* arg0) { void func_us_80173BD0(Entity* arg0) {
if (abs(arg0->velocityY) > abs(arg0->velocityX)) { if (abs(arg0->velocityY) > abs(arg0->velocityX)) {
if (abs(arg0->velocityY) < FIX(0.5)) { if (abs(arg0->velocityY) < FIX(0.5)) {
if (arg0->ext.faerieUnk0.unk80 == 1) { if (arg0->ext.faerie.unk80 == 1) {
arg0->ext.faerieUnk0.unk80 = 0; arg0->ext.faerie.unk80 = 0;
func_us_80173994(arg0, 0x29); func_us_80173994(arg0, 0x29);
} else if (arg0->ext.faerieUnk0.unk80 == 2) { } else if (arg0->ext.faerie.unk80 == 2) {
arg0->ext.faerieUnk0.unk80 = 0; arg0->ext.faerie.unk80 = 0;
func_us_80173994(arg0, 0xE); func_us_80173994(arg0, 0xE);
} }
} else if (abs(arg0->velocityY) > FIX(1)) { } else if (abs(arg0->velocityY) > FIX(1)) {
if (arg0->velocityY >= 0) { if (arg0->velocityY >= 0) {
arg0->ext.faerieUnk0.unk80 = 2; arg0->ext.faerie.unk80 = 2;
func_us_80173994(arg0, 0xB); func_us_80173994(arg0, 0xB);
} else { } else {
arg0->ext.faerieUnk0.unk80 = 2; arg0->ext.faerie.unk80 = 2;
func_us_80173994(arg0, 0xC); func_us_80173994(arg0, 0xC);
} }
} }
} else { } else {
if (abs(arg0->velocityX) > FIX(0.5625)) { if (abs(arg0->velocityX) > FIX(0.5625)) {
if (arg0->ext.faerieUnk0.unk80 == 0) { if (arg0->ext.faerie.unk80 == 0) {
arg0->ext.faerieUnk0.unk80 = 1; arg0->ext.faerie.unk80 = 1;
func_us_80173994(arg0, 0xF); func_us_80173994(arg0, 0xF);
} else if (arg0->ext.faerieUnk0.unk80 == 2) { } else if (arg0->ext.faerie.unk80 == 2) {
arg0->ext.faerieUnk0.unk80 = 0; arg0->ext.faerie.unk80 = 0;
func_us_80173994(arg0, 0xE); func_us_80173994(arg0, 0xE);
} }
} else if (abs(arg0->velocityX) < FIX(0.375)) { } else if (abs(arg0->velocityX) < FIX(0.375)) {
if (arg0->ext.faerieUnk0.unk80 == 1) { if (arg0->ext.faerie.unk80 == 1) {
arg0->ext.faerieUnk0.unk80 = 0; arg0->ext.faerie.unk80 = 0;
func_us_80173994(arg0, 0x29); func_us_80173994(arg0, 0x29);
} else if (arg0->ext.faerieUnk0.unk80 == 2) { } else if (arg0->ext.faerie.unk80 == 2) {
arg0->ext.faerieUnk0.unk80 = 0; arg0->ext.faerie.unk80 = 0;
func_us_80173994(arg0, 0xE); func_us_80173994(arg0, 0xE);
} }
} }
@ -248,7 +266,123 @@ void func_us_801746E8(InitializeMode mode) {
g_api.GetServantStats(entity, 0, 0, &s_FaerieStats); g_api.GetServantStats(entity, 0, 0, &s_FaerieStats);
} }
INCLUDE_ASM("servant/tt_002/nonmatchings/3678", func_us_80174998); void func_us_80174998(Entity* self) {
g_api.GetServantStats(self, 0, 0, &s_FaerieStats);
if (D_us_80179320) {
self->zPriority = PLAYER.zPriority - 2;
s_zPriority = self->zPriority;
}
if (D_8003C708.flags & FLAG_UNK_20) {
switch (ServantUnk0()) {
case 0:
s_TargetLocationX = 0x40;
break;
case 1:
s_TargetLocationX = 0xC0;
break;
case 2:
s_TargetLocationX = self->posX.i.hi > 0x80 ? 0xC0 : 0x40;
break;
}
s_TargetLocationY = 0xA0;
} else {
s_TargetLocOffset_calc = -0x18;
if (PLAYER.facingLeft) {
s_TargetLocOffset_calc = -s_TargetLocOffset_calc;
}
s_TargetLocationX_calc = PLAYER.posX.i.hi + s_TargetLocOffset_calc;
s_TargetLocationY_calc = PLAYER.posY.i.hi - 0x20;
s_AngleToTarget = self->ext.faerie.randomMovementAngle;
self->ext.faerie.randomMovementAngle += 0x10;
self->ext.faerie.randomMovementAngle &= 0xfff;
s_DistToTargetLocation = self->ext.faerie.unk88;
s_TargetLocationX =
s_TargetLocationX_calc +
((rcos(s_AngleToTarget / 2) * s_DistToTargetLocation) >> 0xC);
s_TargetLocationY =
s_TargetLocationY_calc -
((rsin(s_AngleToTarget) * (s_DistToTargetLocation / 2)) >> 0xC);
}
switch (self->step) {
case 0:
func_us_801739D0(self);
self->ext.faerie.unk80 = 0;
func_us_80173994(self, 0xE);
D_us_80179310 = g_Status.hp;
D_us_80179314 = 0;
D_us_80179318 = 0;
self->ext.faerie.unkCounter = 0;
break;
case 1:
s_AngleToTarget =
CalculateAngleToEntity(self, s_TargetLocationX, s_TargetLocationY);
s_AllowedAngle = GetTargetPositionWithDistanceBuffer(
s_AngleToTarget, self->ext.faerie.targetAngle,
self->ext.faerie.maxAngle);
self->ext.faerie.targetAngle = s_AllowedAngle;
s_DistToTargetLocation =
CalculateDistance(self, s_TargetLocationX, s_TargetLocationY);
if (s_DistToTargetLocation < 0x28) {
self->velocityY = -(rsin(s_AllowedAngle) << 3);
self->velocityX = rcos(s_AllowedAngle) << 3;
self->ext.faerie.maxAngle = 0x20;
} else if (s_DistToTargetLocation < 0x3C) {
self->velocityY = -(rsin(s_AllowedAngle) << 4);
self->velocityX = rcos(s_AllowedAngle) << 4;
self->ext.faerie.maxAngle = 0x40;
} else if (s_DistToTargetLocation < 0x64) {
self->velocityY = -(rsin(s_AllowedAngle) << 5);
self->velocityX = rcos(s_AllowedAngle) << 5;
self->ext.faerie.maxAngle = 0x60;
} else if (s_DistToTargetLocation < 0x100) {
self->velocityY = -(rsin(s_AllowedAngle) << 6);
self->velocityX = rcos(s_AllowedAngle) << 6;
self->ext.faerie.maxAngle = 0x80;
} else {
self->velocityX = (s_TargetLocationX - self->posX.i.hi) << 0xE;
self->velocityY = (s_TargetLocationY - self->posY.i.hi) << 0xE;
self->ext.faerie.maxAngle = 0x80;
}
func_us_80173BD0(self);
self->posX.val += self->velocityX;
self->posY.val += self->velocityY;
if (!g_CutsceneHasControl && !IsMovementAllowed(1) &&
!CheckAllEntitiesValid() && !(D_8003C708.flags & FLAG_UNK_20)) {
self->ext.faerie.unkCounter += 1;
} else {
self->ext.faerie.unkCounter = 0;
}
if (self->ext.faerie.unkCounter > 0x708) {
self->entityId = 0xDA;
self->step = 0;
return;
}
if (D_us_8017931C >= 2) {
self->entityId = 0xDB;
self->step = 0;
self->params = D_us_8017931C - 2;
}
break;
}
ProcessEvent(self, false);
if (!g_CutsceneHasControl) {
func_us_80173D60(self);
}
func_us_801739C8(self);
ServantUpdateAnim(self, NULL, D_us_80172B14);
}
INCLUDE_ASM("servant/tt_002/nonmatchings/3678", func_us_80174F0C); INCLUDE_ASM("servant/tt_002/nonmatchings/3678", func_us_80174F0C);
@ -276,15 +410,15 @@ void func_us_80176B6C(Entity* self) {
if (!self->step) { if (!self->step) {
func_us_801739D0(self); func_us_801739D0(self);
self->ext.faerie.unk7C = &thisFamiliar; self->ext.faerieUnk0.unk7C = &thisFamiliar;
self->step += 1; self->step += 1;
} }
self->posX.val = self->ext.faerie.unk7C->posX.val; self->posX.val = self->ext.faerieUnk0.unk7C->posX.val;
self->posY.val = self->ext.faerie.unk7C->posY.val; self->posY.val = self->ext.faerieUnk0.unk7C->posY.val;
self->facingLeft = self->ext.faerie.unk7C->facingLeft; self->facingLeft = self->ext.faerieUnk0.unk7C->facingLeft;
for (i = 6; i <= 0x2D; i++) { for (i = 6; i <= 0x2D; i++) {
if (self->ext.faerie.unk7C->anim == D_us_80172B14[i]) if (self->ext.faerieUnk0.unk7C->anim == D_us_80172B14[i])
break; break;
} }