mirror of https://github.com/pmret/papermario.git
1092 lines
32 KiB
C
1092 lines
32 KiB
C
#include "common.h"
|
|
#include "npc.h"
|
|
#include "world/partners.h"
|
|
|
|
extern s32 wExtraPartnerID;
|
|
extern s32 wExtraPartnerNpcID;
|
|
|
|
Npc* resolve_npc(Evt* script, s32 npcIdOrPtr) {
|
|
if (npcIdOrPtr == NPC_SELF) {
|
|
return get_npc_safe(script->owner2.npcID);
|
|
} else if (npcIdOrPtr >= EVT_LIMIT) {
|
|
return get_npc_safe(npcIdOrPtr);
|
|
} else {
|
|
return (Npc*) npcIdOrPtr;
|
|
}
|
|
}
|
|
|
|
void set_npc_animation(Npc* npc, u32 animID) {
|
|
PlayerData* playerData = &gPlayerData;
|
|
|
|
if (PARTNER_ANIM_STILL <= animID && animID <= PARTNER_ANIM_HURT) {
|
|
npc->currentAnim = gPartnerAnimations[playerData->currentPartner].anims[animID - PARTNER_ANIM_STILL];
|
|
} else if (ENEMY_ANIM_IDLE <= animID && animID <= ENEMY_ANIM_F) {
|
|
npc->currentAnim = get_enemy(npc->npcID)->animList[animID - ENEMY_ANIM_IDLE];
|
|
} else {
|
|
npc->currentAnim = animID;
|
|
}
|
|
}
|
|
|
|
ApiStatus CreateNpc(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
s32 initialAnim = evt_get_variable(script, *args++);
|
|
NpcBlueprint blueprint;
|
|
Npc *npc;
|
|
|
|
blueprint.flags = 0;
|
|
blueprint.initialAnim = initialAnim;
|
|
blueprint.onUpdate = NULL;
|
|
blueprint.onRender = NULL;
|
|
|
|
npc = get_npc_by_index(create_basic_npc(&blueprint));
|
|
npc->npcID = npcID;
|
|
disable_npc_shadow(npc);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus DeleteNpc(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
Npc* npc = get_npc_unsafe(evt_get_variable(script, *args++));
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
free_npc(npc);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus GetNpcPointer(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
Bytecode varNPC = *args++;
|
|
|
|
evt_set_variable(script, varNPC, (s32)get_npc_safe(npcID));
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcPos(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
f32 x = evt_get_variable(script, *args++);
|
|
f32 y = evt_get_variable(script, *args++);
|
|
f32 z = evt_get_variable(script, *args++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->pos.x = x;
|
|
npc->pos.y = y;
|
|
npc->pos.z = z;
|
|
npc->colliderPos.x = npc->pos.x;
|
|
npc->colliderPos.y = npc->pos.y;
|
|
npc->colliderPos.z = npc->pos.z;
|
|
npc->flags |= NPC_FLAG_DIRTY_SHADOW;
|
|
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcRotation(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
f32 rotX = evt_get_float_variable(script, *args++);
|
|
f32 rotY = evt_get_float_variable(script, *args++);
|
|
f32 rotZ = evt_get_float_variable(script, *args++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->rotation.x = rotX;
|
|
npc->rotation.y = rotY;
|
|
npc->rotation.z = rotZ;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcRotationPivot(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcId = evt_get_variable(script, *args++);
|
|
f32 value = evt_get_float_variable(script, *args++);
|
|
Npc* npc;
|
|
|
|
npc = resolve_npc(script, npcId);
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->rotationVerticalPivotOffset = value;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcScale(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
f32 scaleX = evt_get_float_variable(script, *ptrReadPos++);
|
|
f32 scaleY = evt_get_float_variable(script, *ptrReadPos++);
|
|
f32 scaleZ = evt_get_float_variable(script, *ptrReadPos++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->scale.x = scaleX;
|
|
npc->scale.y = scaleY;
|
|
npc->scale.z = scaleZ;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcCollisionSize(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
s32 height = evt_get_variable(script, *ptrReadPos++);
|
|
s32 radius = evt_get_variable(script, *ptrReadPos++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->collisionHeight = height;
|
|
npc->collisionRadius = radius;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcSpeed(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
f32 speed = evt_get_float_variable(script, *ptrReadPos);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->moveSpeed = speed;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcJumpscale(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
f32 jumpScale = evt_get_float_variable(script, *ptrReadPos);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->jumpScale = jumpScale;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcAnimation(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
s32 animation = evt_get_variable(script, *ptrReadPos);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
set_npc_animation(npc, animation);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus GetNpcAnimation(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
Bytecode outVar = *ptrReadPos++;
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
evt_set_variable(script, outVar, npc->currentAnim);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcAnimationSpeed(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
f32 animationSpeed = evt_get_float_variable(script, *ptrReadPos++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->animationSpeed = animationSpeed;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus NpcMoveTo(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
Npc* npc;
|
|
f32 dist;
|
|
f32 moveSpeed;
|
|
|
|
if (isInitialCall) {
|
|
script->functionTemp[0] = 0;
|
|
}
|
|
|
|
if (script->functionTemp[0] == 0) {
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
f32 goalX = evt_get_variable(script, *args++);
|
|
f32 goalZ = evt_get_variable(script, *args++);
|
|
s32 duration = evt_get_variable(script, *args++);
|
|
|
|
npc = resolve_npc(script, npcID);
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
script->functionTempPtr[1] = npc;
|
|
npc->moveToPos.x = goalX;
|
|
npc->moveToPos.z = goalZ;
|
|
npc->duration = duration;
|
|
dist = dist2D(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
|
|
|
|
if (npc->duration == 0) {
|
|
npc->duration = dist / npc->moveSpeed;
|
|
} else {
|
|
npc->moveSpeed = dist / npc->duration;
|
|
}
|
|
if (npc->duration == 0) {
|
|
npc->duration = 1;
|
|
}
|
|
script->functionTemp[0] = 1;
|
|
}
|
|
|
|
npc = script->functionTempPtr[1];
|
|
npc->yaw = atan2(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
|
|
npc_move_heading(npc, npc->moveSpeed, npc->yaw);
|
|
|
|
if (npc->moveSpeed < 4.0) {
|
|
spawn_surface_effects(npc, SURFACE_INTERACT_WALK);
|
|
} else {
|
|
spawn_surface_effects(npc, SURFACE_INTERACT_RUN);
|
|
}
|
|
|
|
dist = dist2D(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
|
|
|
|
moveSpeed = npc->moveSpeed;
|
|
if (moveSpeed < 1.0) {
|
|
moveSpeed = 1.0f;
|
|
}
|
|
|
|
if (dist <= moveSpeed) {
|
|
return ApiStatus_DONE1;
|
|
}
|
|
return ApiStatus_BLOCK;
|
|
}
|
|
|
|
ApiStatus _npc_jump_to(Evt* script, s32 isInitialCall, s32 snapYaw) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
f32* yaw = &script->functionTempF[2];
|
|
Npc* npc;
|
|
|
|
if (isInitialCall) {
|
|
script->functionTemp[0] = 0;
|
|
}
|
|
|
|
if (script->functionTemp[0] == 0) {
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
f32 goalX = evt_get_variable(script, *args++);
|
|
f32 goalY = evt_get_variable(script, *args++);
|
|
f32 goalZ = evt_get_variable(script, *args++);
|
|
s32 duration = evt_get_variable(script, *args++);
|
|
f32 dist;
|
|
|
|
npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
script->functionTempPtr[1] = npc;
|
|
npc->moveToPos.x = goalX;
|
|
npc->moveToPos.y = goalY;
|
|
npc->moveToPos.z = goalZ;
|
|
|
|
npc->duration = duration;
|
|
dist = dist2D(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
|
|
*yaw = 0.0f;
|
|
if (dist > 2.0) {
|
|
*yaw = atan2(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
|
|
if (snapYaw == 0) {
|
|
npc->yaw = *yaw;
|
|
}
|
|
}
|
|
|
|
goalY = npc->moveToPos.y - npc->pos.y;
|
|
|
|
if (npc->duration == 0) {
|
|
npc->duration = dist / npc->moveSpeed;
|
|
} else {
|
|
npc->moveSpeed = dist / npc->duration;
|
|
}
|
|
|
|
npc->flags |= NPC_FLAG_JUMPING;
|
|
npc->jumpVelocity = (npc->jumpScale * npc->duration * 0.5f) + (goalY / npc->duration);
|
|
script->functionTemp[0] =1;
|
|
}
|
|
|
|
npc = script->functionTempPtr[1];
|
|
npc_move_heading(npc, npc->moveSpeed, *yaw);
|
|
|
|
npc->pos.y += npc->jumpVelocity;
|
|
npc->jumpVelocity -= npc->jumpScale;
|
|
|
|
npc->duration--;
|
|
if (npc->duration < 0) {
|
|
npc->jumpVelocity = 0.0f;
|
|
npc->pos.x = npc->moveToPos.x;
|
|
npc->pos.y = npc->moveToPos.y;
|
|
npc->pos.z = npc->moveToPos.z;
|
|
npc->flags &= ~NPC_FLAG_JUMPING;
|
|
spawn_surface_effects(npc, SURFACE_INTERACT_LAND);
|
|
return ApiStatus_DONE1;
|
|
}
|
|
return ApiStatus_BLOCK;
|
|
}
|
|
|
|
ApiStatus NpcJump0(Evt* script, s32 isInitialCall) {
|
|
return _npc_jump_to(script, isInitialCall, 0);
|
|
}
|
|
|
|
ApiStatus NpcJump1(Evt* script, s32 isInitialCall) {
|
|
return _npc_jump_to(script, isInitialCall, 1);
|
|
}
|
|
|
|
ApiStatus NpcFlyTo(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
f32* outX = (f32*)&script->varTable[3];
|
|
f32* outY = (f32*)&script->varTable[4];
|
|
f32* outZ = (f32*)&script->varTable[5];
|
|
Npc* npc;
|
|
f32 dist;
|
|
f32 yDelta;
|
|
|
|
if (isInitialCall) {
|
|
npc = resolve_npc(script, evt_get_variable(script, *args++));
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
script->functionTempPtr[1] = npc;
|
|
npc->moveToPos.x = evt_get_float_variable(script, *args++);
|
|
npc->moveToPos.y = evt_get_float_variable(script, *args++);
|
|
npc->moveToPos.z = evt_get_float_variable(script, *args++);
|
|
script->varTable[6] = evt_get_variable(script, *args++);
|
|
script->functionTemp[2] = evt_get_variable(script, *args++);
|
|
script->functionTemp[3] = evt_get_variable(script, *args++);
|
|
npc->duration = 0;
|
|
*outX = npc->pos.x;
|
|
*outY = npc->pos.y;
|
|
*outZ = npc->pos.z;
|
|
npc->yaw = atan2(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
|
|
dist = dist2D(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
|
|
npc->planarFlyDist = dist;
|
|
|
|
if (script->varTable[6] == 0) {
|
|
script->varTable[6] = (dist / npc->moveSpeed);
|
|
} else {
|
|
npc->moveSpeed = dist / script->varTable[6];
|
|
}
|
|
}
|
|
|
|
npc = script->functionTempPtr[1];
|
|
npc->pos.x = update_lerp(script->functionTemp[3], *outX, npc->moveToPos.x, npc->duration, script->varTable[6]);
|
|
npc->pos.y = update_lerp(script->functionTemp[3], *outY, npc->moveToPos.y, npc->duration, script->varTable[6]);
|
|
npc->pos.z = update_lerp(script->functionTemp[3], *outZ, npc->moveToPos.z, npc->duration, script->varTable[6]);
|
|
|
|
npc->duration++;
|
|
if (npc->duration >= script->varTable[6]) {
|
|
npc->pos.x = npc->moveToPos.x;
|
|
npc->pos.y = npc->moveToPos.y;
|
|
npc->pos.z = npc->moveToPos.z;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
dist = dist2D(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
|
|
if (dist == 0.0f) {
|
|
dist = 1.0f;
|
|
}
|
|
if (npc->planarFlyDist == 0.0f) {
|
|
npc->planarFlyDist = 1.0f;
|
|
}
|
|
|
|
yDelta = sin_deg((1.0 - (dist / npc->planarFlyDist)) * 180.0);
|
|
if (script->functionTemp[2] == 0) {
|
|
yDelta = 0.0f;
|
|
}
|
|
if (script->functionTemp[2] < 0) {
|
|
yDelta = -yDelta * -script->functionTemp[2];
|
|
}
|
|
if (script->functionTemp[2] > 0) {
|
|
yDelta *= script->functionTemp[2];
|
|
}
|
|
npc->pos.y += yDelta;
|
|
return ApiStatus_BLOCK;
|
|
}
|
|
|
|
ApiStatus GetNpcYaw(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
Bytecode outVar = *ptrReadPos++;
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
evt_set_variable(script, outVar, clamp_angle(npc->yaw));
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcYaw(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
set_npc_yaw(npc, evt_get_variable(script, *ptrReadPos++));
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus InterpNpcYaw(Evt* script, s32 isInitialCall) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
Bytecode* args = script->ptrReadPos;
|
|
f32* initialYaw = &script->functionTempF[1];
|
|
f32* deltaYaw = &script->functionTempF[2];
|
|
s32* turnTime = &script->functionTemp[3];
|
|
Npc* npc;
|
|
|
|
if (isInitialCall) {
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
|
|
npc = resolve_npc(script, npcID);
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
*initialYaw = npc->yaw;
|
|
*deltaYaw = evt_get_variable(script, *args++) - *initialYaw;
|
|
script->functionTempPtr[0] = npc;
|
|
*turnTime = evt_get_variable(script, *args++);
|
|
|
|
if (*turnTime == 0) {
|
|
npc->yaw += *deltaYaw;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->duration = 0;
|
|
|
|
if (*deltaYaw < -180.0f) {
|
|
*deltaYaw += 360.0f;
|
|
}
|
|
if (*deltaYaw > 180.0f) {
|
|
*deltaYaw -= 360.0f;
|
|
}
|
|
}
|
|
|
|
npc = script->functionTempPtr[0];
|
|
if (*turnTime > 0) {
|
|
npc->duration++;
|
|
npc->yaw = *initialYaw + ((*deltaYaw * npc->duration) / *turnTime);
|
|
npc->yaw = clamp_angle(npc->yaw);
|
|
return !(npc->duration < *turnTime) * ApiStatus_DONE1;
|
|
}
|
|
|
|
npc->yaw += *deltaYaw;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus NpcFacePlayer(Evt* script, s32 isInitialCall) {
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
Bytecode* args = script->ptrReadPos;
|
|
f32* initialYaw = &script->functionTempF[1];
|
|
f32* deltaYaw = &script->functionTempF[2];
|
|
s32* turnTime = &script->functionTemp[3];
|
|
Npc* npc;
|
|
|
|
if (isInitialCall) {
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
|
|
npc = resolve_npc(script, npcID);
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
*initialYaw = npc->yaw;
|
|
*deltaYaw = atan2(npc->pos.x, npc->pos.z, playerStatus->position.x, playerStatus->position.z) - *initialYaw;
|
|
script->functionTempPtr[0] = npc;
|
|
*turnTime = evt_get_variable(script, *args++);
|
|
npc->duration = 0;
|
|
|
|
if (*deltaYaw < -180.0f) {
|
|
*deltaYaw += 360.0f;
|
|
}
|
|
if (*deltaYaw > 180.0f) {
|
|
*deltaYaw -= 360.0f;
|
|
}
|
|
}
|
|
|
|
npc = script->functionTempPtr[0];
|
|
if (*turnTime > 0) {
|
|
npc->duration++;
|
|
npc->yaw = *initialYaw + ((*deltaYaw * npc->duration) / *turnTime);
|
|
npc->yaw = clamp_angle(npc->yaw);
|
|
return !(npc->duration < *turnTime) * ApiStatus_DONE1;
|
|
}
|
|
|
|
npc->yaw += *deltaYaw;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus NpcFaceNpc(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
f32* initialYaw = &script->functionTempF[1];
|
|
f32* deltaYaw = &script->functionTempF[2];
|
|
s32* turnTime = &script->functionTemp[3];
|
|
Npc* targetNpc;
|
|
Npc* turningNpc;
|
|
|
|
if (isInitialCall) {
|
|
s32 turningNpcID = evt_get_variable(script, *args++);
|
|
s32 targetNpcID = evt_get_variable(script, *args++);
|
|
|
|
targetNpc = resolve_npc(script, targetNpcID);
|
|
if (targetNpc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
turningNpc = resolve_npc(script, turningNpcID);
|
|
if (turningNpc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
*initialYaw = turningNpc->yaw;
|
|
*deltaYaw = atan2(turningNpc->pos.x, turningNpc->pos.z, targetNpc->pos.x, targetNpc->pos.z) - *initialYaw;
|
|
script->functionTempPtr[0] = turningNpc;
|
|
*turnTime = evt_get_variable(script, *args++);
|
|
turningNpc->duration = 0;
|
|
|
|
if (*deltaYaw < -180.0f) {
|
|
*deltaYaw += 360.0f;
|
|
}
|
|
if (*deltaYaw > 180.0f) {
|
|
*deltaYaw -= 360.0f;
|
|
}
|
|
}
|
|
|
|
turningNpc = script->functionTempPtr[0];
|
|
if (*turnTime > 0) {
|
|
turningNpc->duration++;
|
|
turningNpc->yaw = *initialYaw + ((*deltaYaw * turningNpc->duration) / *turnTime);
|
|
turningNpc->yaw = clamp_angle(turningNpc->yaw);
|
|
return !(turningNpc->duration < *turnTime) * ApiStatus_DONE1;
|
|
}
|
|
|
|
turningNpc->yaw += *deltaYaw;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcFlagBits(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
s32 bits = *args++;
|
|
s32 mode = evt_get_variable(script, *args++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
if (mode) {
|
|
npc->flags |= bits;
|
|
} else {
|
|
npc->flags &= ~bits;
|
|
}
|
|
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus GetNpcPos(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
s32 outX = *args++;
|
|
s32 outY = *args++;
|
|
s32 outZ = *args++;
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
evt_set_variable(script, outX, npc->pos.x);
|
|
evt_set_variable(script, outY, npc->pos.y);
|
|
evt_set_variable(script, outZ, npc->pos.z);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcCollisionChannel(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
Bytecode channel = *args;
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->collisionChannel = channel;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcSprite(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *args++);
|
|
Bytecode animID = *args;
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
set_npc_sprite(npc, animID, NULL);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus EnableNpcShadow(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
s32 enableShadow = evt_get_variable(script, *ptrReadPos++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
if (enableShadow) {
|
|
enable_npc_shadow(npc);
|
|
} else {
|
|
disable_npc_shadow(npc);
|
|
}
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus EnableNpcBlur(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
s32 enableBlur = evt_get_variable(script, *ptrReadPos++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
if (enableBlur) {
|
|
enable_npc_blur(npc);
|
|
} else {
|
|
disable_npc_blur(npc);
|
|
}
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus ClearPartnerMoveHistory(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
partner_clear_player_tracking(npc);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus NpcSetHomePosToCurrent(Evt* script, s32 isInitialCall) {
|
|
Npc* npc = resolve_npc(script, evt_get_variable(script, *script->ptrReadPos));
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->homePos.x = npc->pos.x;
|
|
npc->homePos.y = npc->pos.y;
|
|
npc->homePos.z = npc->pos.z;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus GetPartnerPos(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
Bytecode posX = *ptrReadPos++;
|
|
Bytecode posY = *ptrReadPos++;
|
|
Bytecode posZ = *ptrReadPos++;
|
|
Npc* npc = get_npc_unsafe(NPC_PARTNER);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
evt_set_variable(script, posX, npc->pos.x);
|
|
evt_set_variable(script, posY, npc->pos.y);
|
|
evt_set_variable(script, posZ, npc->pos.z);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus DisablePartnerAI(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
|
|
if (evt_get_variable(script, *ptrReadPos++) == 0) {
|
|
func_800EF314();
|
|
} else {
|
|
func_800EF300();
|
|
}
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus EnablePartnerAI(Evt* script, s32 isInitialCall) {
|
|
enable_partner_ai();
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus func_802CF54C(Evt* script, s32 isInitialCall) {
|
|
func_800EF43C();
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus func_802CF56C(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 value = evt_get_variable(script, *ptrReadPos++);
|
|
|
|
if (value == 2) {
|
|
func_800EF3E4();
|
|
} else {
|
|
func_800EF3D4(value);
|
|
}
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
s32 BringPartnerOut(Evt *script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
NpcBlueprint bp;
|
|
NpcBlueprint* bpPointer = &bp;
|
|
PlayerData* playerData = &gPlayerData;
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
Npc* partner;
|
|
Npc* npc;
|
|
f32 duration;
|
|
f32 playerZ;
|
|
f32 targetZ;
|
|
f32 playerX;
|
|
f32 targetX;
|
|
f32 targetY;
|
|
f32 playerY;
|
|
|
|
if (isInitialCall) {
|
|
wExtraPartnerID = evt_get_variable(script, *args++);
|
|
if (playerData->currentPartner == wExtraPartnerID) {
|
|
wExtraPartnerID = 0;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
partner = get_npc_unsafe(NPC_PARTNER);
|
|
partner->npcID = -5;
|
|
|
|
bpPointer->flags = NPC_FLAG_IGNORE_PLAYER_COLLISION;
|
|
bpPointer->initialAnim = gPartnerAnimations[wExtraPartnerID].fly;
|
|
bpPointer->onUpdate = NULL;
|
|
bpPointer->onRender = NULL;
|
|
|
|
wExtraPartnerNpcID = create_basic_npc(bpPointer);
|
|
npc = get_npc_by_index(wExtraPartnerNpcID);
|
|
npc->collisionRadius = 10;
|
|
npc->collisionHeight = 10;
|
|
npc->npcID = NPC_PARTNER;
|
|
npc->scale.x = 0.0f;
|
|
npc->scale.y = 0.0f;
|
|
npc->scale.z = 0.0f;
|
|
|
|
npc->moveToPos.x = targetX = partner->pos.x;
|
|
playerY = playerStatus->position.y;
|
|
npc->moveToPos.y = playerStatus->position.y;
|
|
npc->moveToPos.z = targetZ = partner->pos.z + 30.0f;
|
|
npc->pos.x = playerX = playerStatus->position.x;
|
|
npc->pos.y = targetY = playerStatus->position.y + (playerStatus->colliderHeight / 2);
|
|
playerZ = playerStatus->position.z;
|
|
npc->moveSpeed = 4.0f;
|
|
npc->jumpScale = 1.6f;
|
|
npc->pos.z = playerZ;
|
|
|
|
npc->planarFlyDist = dist2D(playerX, npc->pos.z, targetX, targetZ);
|
|
npc->yaw = atan2(playerX, playerZ, targetX, targetZ);
|
|
npc->duration = npc->planarFlyDist / npc->moveSpeed;
|
|
|
|
if (npc->duration < 10) {
|
|
npc->duration = 10;
|
|
npc->moveSpeed = npc->planarFlyDist / npc->duration;
|
|
}
|
|
|
|
npc->jumpVelocity = ((playerY - targetY) + (npc->jumpScale * npc->duration * npc->duration * 0.5f)) / npc->duration;
|
|
npc->currentAnim = gPartnerAnimations[wExtraPartnerID].walk;
|
|
return ApiStatus_BLOCK;
|
|
}
|
|
|
|
npc = get_npc_by_index(wExtraPartnerNpcID);
|
|
npc->jumpVelocity -= npc->jumpScale;
|
|
npc->pos.y += npc->jumpVelocity;
|
|
if (npc->jumpVelocity <= 0.0f) {
|
|
npc->currentAnim = gPartnerAnimations[wExtraPartnerID].jump;
|
|
}
|
|
npc_move_heading(npc, npc->moveSpeed, npc->yaw);
|
|
duration = npc->duration;
|
|
if (duration > 10.0f) {
|
|
duration = 10.0f;
|
|
}
|
|
npc->scale.x = (10.0f - duration) / 10.0f;
|
|
npc->scale.y = npc->scale.x;
|
|
npc->scale.z = npc->scale.x;
|
|
|
|
npc->duration--;
|
|
if (npc->duration < 0) {
|
|
npc->currentAnim = gPartnerAnimations[wExtraPartnerID].idle;
|
|
npc->jumpVelocity = 0.0f;
|
|
npc->pos.y = npc->moveToPos.y;
|
|
npc->scale.x = 1.0f;
|
|
npc->scale.y = 1.0f;
|
|
npc->scale.z = 1.0f;
|
|
npc->yaw = clamp_angle(npc->yaw + 180.0f);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
return ApiStatus_BLOCK;
|
|
}
|
|
|
|
ApiStatus PutPartnerAway(Evt* script, s32 isInitialCall) {
|
|
Npc* partner = get_npc_unsafe(NPC_PARTNER);
|
|
PlayerStatus* playerStatus = &gPlayerStatus;
|
|
f32 scale;
|
|
f32 targetX;
|
|
f32 targetY;
|
|
f32 targetZ;
|
|
f32 partnerX;
|
|
f32 partnerY;
|
|
f32 partnerZ;
|
|
|
|
if (isInitialCall) {
|
|
if (wExtraPartnerID != 0) {
|
|
partner->flags &= ~NPC_FLAG_GRAVITY;
|
|
partner->flags &= ~NPC_FLAG_8;
|
|
targetX = playerStatus->position.x;
|
|
partner->moveToPos.x = targetX;
|
|
partnerX = partner->pos.x;
|
|
targetY = playerStatus->position.y + (playerStatus->colliderHeight / 2);
|
|
partner->moveToPos.y = targetY;
|
|
partnerY = partner->pos.y;
|
|
targetZ = playerStatus->position.z;
|
|
partner->moveToPos.z = targetZ;
|
|
partnerZ = partner->pos.z;
|
|
partner->moveSpeed = 4.0f;
|
|
partner->jumpScale = 2.6f;
|
|
partner->planarFlyDist = dist2D(partnerX, partnerZ, targetX, targetZ);
|
|
partner->yaw = atan2(partnerX, partnerZ, targetX, targetZ);
|
|
partner->duration = partner->planarFlyDist / partner->moveSpeed;
|
|
|
|
if (partner->duration < 10) {
|
|
partner->duration = 10;
|
|
partner->moveSpeed = partner->planarFlyDist / partner->duration;
|
|
}
|
|
|
|
partnerY = targetY - partnerY;
|
|
partner->jumpVelocity = (partnerY + (partner->jumpScale * partner->duration * partner->duration * 0.5f)) / partner->duration;
|
|
partner->currentAnim = gPartnerAnimations[wExtraPartnerID].walk;
|
|
return ApiStatus_BLOCK;
|
|
} else {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
}
|
|
|
|
partner->jumpVelocity -= partner->jumpScale;
|
|
partner->pos.y += partner->jumpVelocity;
|
|
if (partner->jumpVelocity <= 0.0f) {
|
|
partner->currentAnim = gPartnerAnimations[wExtraPartnerID].jump;
|
|
}
|
|
npc_move_heading(partner, partner->moveSpeed, partner->yaw);
|
|
|
|
scale = partner->duration;
|
|
if (scale > 10.0f) {
|
|
scale = 10.0f;
|
|
}
|
|
|
|
partner->scale.x = scale / 10.0f;
|
|
partner->scale.y = partner->scale.x;
|
|
partner->scale.z = partner->scale.x;
|
|
|
|
partner->duration--;
|
|
if (partner->duration < 0) {
|
|
partner->currentAnim = gPartnerAnimations[wExtraPartnerID].fall;
|
|
partner->jumpVelocity = 0.0f;
|
|
partner->pos.y = partner->moveToPos.y;
|
|
free_npc_by_index(wExtraPartnerNpcID);
|
|
get_npc_unsafe(-5)->npcID = NPC_PARTNER;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
return ApiStatus_BLOCK;
|
|
}
|
|
|
|
ApiStatus GetCurrentPartnerID(Evt* script, s32 isInitialCall) {
|
|
evt_set_variable(script, *script->ptrReadPos, gPlayerData.currentPartner);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus PartnerCanUseAbility(Evt* script, s32 isInitialCall) {
|
|
Bytecode arg0 = *script->ptrReadPos;
|
|
|
|
evt_set_variable(script, arg0, partner_can_use_ability());
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus PartnerIsFlying(Evt* script, s32 isInitialCall) {
|
|
Bytecode arg0 = *script->ptrReadPos;
|
|
|
|
evt_set_variable(script, arg0, partner_is_flying());
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus func_802CFD30(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcId = evt_get_variable(script, *args++);
|
|
Bytecode foldType = evt_get_variable(script, *args++);
|
|
Bytecode var2 = evt_get_variable(script, *args++);
|
|
Bytecode var3 = evt_get_variable(script, *args++);
|
|
Bytecode var4 = evt_get_variable(script, *args++);
|
|
Bytecode var5 = evt_get_variable(script, *args++);
|
|
Npc* npc = resolve_npc(script, npcId);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
func_8003D624(npc, foldType, var2, var3, var4, var5, npc->foldArg5);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus func_802CFE2C(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcId = evt_get_variable(script, *args++);
|
|
Bytecode arg1 = *args;
|
|
Npc* npc = resolve_npc(script, npcId);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc->foldArg5 = arg1;
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcPaletteSwapMode(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcId = evt_get_variable(script, *args++);
|
|
Bytecode var1 = evt_get_variable(script, *args++);
|
|
Npc* npc = resolve_npc(script, npcId);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc_set_palswap_mode_A(npc, var1);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcPaletteSwapLower(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcId = evt_get_variable(script, *args++);
|
|
Bytecode var1 = evt_get_variable(script, *args++);
|
|
Bytecode var2 = evt_get_variable(script, *args++);
|
|
Bytecode var3 = evt_get_variable(script, *args++);
|
|
Bytecode var4 = evt_get_variable(script, *args++);
|
|
Npc* npc = resolve_npc(script, npcId);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc_set_palswap_1(npc, var1, var2, var3, var4);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcPaletteSwapping(Evt* script, s32 isInitialCall) {
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 npcId = evt_get_variable(script, *args++);
|
|
Bytecode var1 = evt_get_variable(script, *args++);
|
|
Bytecode var2 = evt_get_variable(script, *args++);
|
|
Bytecode var3 = evt_get_variable(script, *args++);
|
|
Bytecode var4 = evt_get_variable(script, *args++);
|
|
Bytecode var5 = evt_get_variable(script, *args++);
|
|
Bytecode var6 = evt_get_variable(script, *args++);
|
|
Bytecode var7 = evt_get_variable(script, *args++);
|
|
Bytecode var8 = evt_get_variable(script, *args++);
|
|
Npc* npc = resolve_npc(script, npcId);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc_set_palswap_1(npc, var1, var2, var3, var4);
|
|
npc_set_palswap_2(npc, var5, var6, var7, var8);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcDecoration(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
s32 value1 = evt_get_variable(script, *ptrReadPos++);
|
|
s32 value2 = evt_get_variable(script, *ptrReadPos++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
npc_set_decoration(npc, value1, value2);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus PlaySoundAtNpc(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
s32 soundID = evt_get_variable(script, *ptrReadPos++);
|
|
s32 flags = evt_get_variable(script, *ptrReadPos++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
if (npc == NULL) {
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
sfx_play_sound_at_position(soundID, flags, npc->pos.x, npc->pos.y, npc->pos.z);
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus SetNpcRenderMode(Evt* script, s32 isInitialCall) {
|
|
Bytecode* ptrReadPos = script->ptrReadPos;
|
|
s32 npcID = evt_get_variable(script, *ptrReadPos++);
|
|
u8 renderMode = evt_get_variable(script, *ptrReadPos++);
|
|
Npc* npc = resolve_npc(script, npcID);
|
|
|
|
npc->renderMode = renderMode;
|
|
return ApiStatus_DONE2;
|
|
}
|