tmc/src/npcUtils.c

341 lines
8.2 KiB
C

#include "global.h"
#include "asm.h"
#include "entity.h"
#include "functions.h"
#include "definitions.h"
#include "save.h"
#include "npc.h"
#include "kinstone.h"
extern const NPCDefinition gNPCDefinitions[];
extern Hitbox* gNPCHitboxes[];
extern u32 (*gUnk_08114EFC[])(Entity*);
extern u32 (*gUnk_08114F0C[])(Entity*, u8*);
typedef struct {
u16 _0;
u16 _2;
u16 _4;
} NPCData;
extern NPCData* gUnk_08001A7C[];
u32 sub_080041DC(Entity*, u32, u32);
u32 sub_0806EF88(Entity*);
static void sub_0806EF14(Entity*);
static void sub_0806EF4C(Entity*, u16*);
static u32 sub_0806EF74(Entity*, u32);
void sub_0806EC20(Entity* ent) {
Entity* e = CreateNPC(0x58, 0, 0);
if (e != NULL) {
e->parent = ent;
}
}
void sub_0806EC38(void) {
Entity* e = FindEntityByID(7, 0x58, 7);
if (e != NULL)
DeleteEntity(e);
}
static const NPCDefinition* GetNPCDefinition(Entity* this) {
const NPCDefinition* definition = &gNPCDefinitions[this->id];
if (definition->bitfield.type == 2) {
definition = &definition->data.definition[this->type];
}
return definition;
}
void NPCInit(Entity* this) {
u32 tmp;
u32 tmp2;
if ((this->flags & ENT_DID_INIT) == 0) {
const NPCDefinition* definition = GetNPCDefinition(this);
if (definition->bitfield.type == 0) {
// No sprite for this NPC
this->flags |= 1;
} else {
tmp = definition->bitfield.gfx;
switch (definition->bitfield.gfx_type) {
case 2:
this->spriteVramOffset = definition->bitfield.gfx;
break;
case 1:
LoadSwapGFX(this, tmp, 0);
break;
default:
LoadFixedGFX(this, tmp);
break;
}
tmp = definition->data.sprite.paletteIndex;
LoadObjPalette(this, tmp);
this->spriteIndex = definition->data.sprite.spriteIndex;
this->spriteSettings.shadow = definition->data.sprite.shadow;
this->spritePriority.b1 = definition->data.sprite.spritePriority;
this->spriteSettings.draw = definition->data.sprite.draw;
this->hitbox = gNPCHitboxes[definition->bitfield.hitbox];
this->flags |= ENT_DID_INIT;
tmp2 = 0xff;
this->animIndex = tmp2;
this->frameIndex = tmp2;
UpdateSpriteForCollisionLayer(this);
}
}
}
Entity* CreateNPC(u32 subtype, u32 form, u32 parameter) {
Entity* entity = GetEmptyEntity();
if (entity != NULL) {
entity->kind = 7;
entity->id = subtype;
entity->type = form;
entity->type2 = parameter;
AppendEntityToList(entity, 7);
}
return entity;
}
u32 sub_0806ED78(Entity* ent) {
u32 result = sub_0800445C(ent);
if (result) {
if (gPlayerState.dash_state & 0x40) {
sub_08077B20();
}
}
return result;
}
s32 sub_0806ED9C(Entity* ent, u32 x, u32 y) {
s32 anim = -1;
if (EntityInRectRadius(ent, &gPlayerEntity, x, y))
anim = GetAnimationState(ent);
return anim;
}
u32 GetAnimationState(Entity* ent) {
u32 direction = GetFacingDirection(ent, &gPlayerEntity);
return sub_0806F5A4(direction);
}
s32 sub_0806EDD8(Entity* ent, u32 x, u32 y) {
s32 anim = -1;
if (EntityInRectRadius(ent, &gPlayerEntity, x, y))
anim = GetFacingDirection(ent, &gPlayerEntity);
return anim;
}
void sub_0806EE04(Entity* ent, void* a2, u32 a3) {
ent->child = a2;
ent->field_0x3c = a3;
ent->hitType = 0;
ent->field_0x46 = 0;
ent->field_0x16 = 0;
}
u32 sub_0806EE20(Entity* ent) {
u32 v3;
if (!ent->interactType) {
if (ent->child)
return gUnk_08114EFC[ent->field_0x16](ent);
} else {
ent->field_0x46 = 8;
v3 = GetFacingDirection(ent, &gPlayerEntity);
ent->knockbackDirection = sub_0806F5A4(v3);
}
return 0;
}
u32 sub_0806EE70(Entity* ent) {
s32 tmp1;
s32 tmp2;
u32 result;
u16 xy[2];
if (++ent->field_0x46 > 8) {
ent->field_0x46 = 0;
sub_0806EF14(ent);
}
LinearMoveUpdate(ent);
sub_0806EF4C(ent, xy);
tmp1 = sub_080041DC(ent, xy[0], xy[1]);
tmp2 = ent->speed;
if (tmp2 < 0)
tmp2 = -tmp2;
if ((u32)tmp2 / 8 <= tmp1)
result = 0;
else
result = sub_0806EF74(ent, 3);
return result;
}
u32 sub_0806EED0(Entity* ent) {
if (!--ent->field_0x46)
return sub_0806EF74(ent, 2);
return 0;
}
u32 sub_0806EEF4(Entity* ent) {
if (ent->frame & 0x80)
return sub_0806EF74(ent, 1);
return 0;
}
static void sub_0806EF14(Entity* ent) {
u16 xy[2];
sub_0806EF4C(ent, xy);
ent->direction = sub_080045B4(ent, xy[0], xy[1]);
if ((ent->field_0x3c & 1) == 0)
ent->knockbackDirection = sub_0806F5A4(ent->direction);
}
static void sub_0806EF4C(Entity* ent, u16* xy) {
u16* src = &((u16*)ent->child)[ent->hitType];
xy[0] = gRoomControls.origin_x + src[1];
xy[1] = gRoomControls.origin_y + src[2];
}
static u32 sub_0806EF74(Entity* ent, u32 a2) {
ent->hitType += a2;
return sub_0806EF88(ent);
}
u32 sub_0806EF88(Entity* ent) {
u8* v1 = (u8*)&((u16*)ent->child)[ent->hitType];
return gUnk_08114F0C[*v1](ent, v1);
}
u32 sub_0806EFAC(Entity* ent, u16* a2) {
ent->hitType = 0;
return sub_0806EF88(ent);
}
u32 sub_0806EFBC(Entity* ent, u16* a2) {
ent->field_0x16 = 1;
ent->field_0x46 = 8;
return 0;
}
u32 sub_0806EFCC(Entity* ent, u16* a2) {
ent->field_0x16 = 2;
ent->field_0x46 = a2[1];
return 0;
}
u32 sub_0806EFDC(Entity* ent, u16* a2) {
if (*a2 >> 8) {
ent->field_0x3c &= ~1;
} else {
ent->field_0x3c |= 1;
}
ent->hitType++;
return sub_0806EF88(ent);
}
u32 sub_0806F014(Entity* ent, u16* a2) {
ent->speed = a2[1];
ent->hitType += 2;
return sub_0806EF88(ent);
}
u32 sub_0806F02C(Entity* ent, u16* a2) {
ent->knockbackDirection = *a2 >> 8;
ent->hitType++;
return sub_0806EF88(ent);
}
u32 sub_0806F048(Entity* ent, u16* a2) {
ent->field_0x16 = 3;
return 0;
}
u32 sub_0806F050(Entity* ent, u16* a2) {
(u16*)ent->child = a2 + 1;
ent->hitType = 0;
return sub_0806EF88(ent);
}
u32 sub_0806F064(Entity* ent, u16* a2) {
ent->field_0x16 = 0;
ent->hitType++;
return *a2 >> 8;
}
s32 sub_0806F078(Entity* ent, s32 a2) {
if (a2 != ent->animIndex) {
if (ent->spriteAnimation[0])
InitAnimationForceUpdate(ent, a2);
else
InitializeAnimation(ent, a2);
return 1;
}
return 0;
}
void sub_0806F0A4(void) {
LinkedList* entityList = gEntityLists + 7;
Entity* currentEntity;
u32 val;
for (currentEntity = entityList->first, val = 0; currentEntity != (Entity*)entityList;
currentEntity = currentEntity->next) {
val++;
}
if (val <= 1)
return;
for (currentEntity = entityList->first; currentEntity != (Entity*)entityList; currentEntity = currentEntity->next) {
Entity* nextEnt;
if ((currentEntity->flags & 1) == 0)
continue;
if ((currentEntity->field_0x17 & 1) == 0)
continue;
for (nextEnt = currentEntity->next; nextEnt != (Entity*)entityList; nextEnt = nextEnt->next) {
if ((nextEnt->flags & 1) == 0)
continue;
if ((nextEnt->field_0x17 & 1) == 0)
continue;
sub_08004484(currentEntity, nextEnt);
}
}
}
void sub_0806F118(Entity* ent) {
u32 idx = sub_08002632(ent);
NPCData* data = gUnk_08001A7C[idx];
sub_0801DFB4(ent, data->_0, data->_2, data->_4);
gPlayerState.controlMode = 3;
}
u32 UpdateFuseInteraction(Entity* ent) {
u32 ret;
sub_0801E00C();
ret = -1;
switch (gFuseInfo._0) {
default:
ret = 0;
break;
case 2:
gPlayerState.controlMode = 3;
ret = 1;
case 1:
sub_0807919C();
gPlayerState.controlMode = 1;
break;
}
return ret;
}
void sub_0806F188(Entity* ent) {
u32 idx = sub_08002632(ent);
if (idx != 0)
gSave.unk1C1[idx] = 0xF3;
}
ASM_FUNC("asm/non_matching/showNPCDialogue.inc", void ShowNPCDialogue(Entity* ent, Dialog* dia));