#include "common.h" extern s32 ShowMessageScreenOffsetX; extern s32 ShowMessageScreenOffsetY; extern s32 D_802DAE58[2]; // unused? extern char D_802DAE60[0x400]; // unused? extern MessagePrintState* gCurrentPrintContext; extern bool D_802DB264; extern MessagePrintState* D_802DB268; ApiStatus _show_message(Evt* script, s32 isInitialCall, s32 mode); enum { SHOW_MESSAGE_SPEAK_TO_PLAYER = 0, SHOW_MESSAGE_END_SPEECH = 1, SHOW_MESSAGE_CONTINUE_SPEECH = 2, SHOW_MESSAGE_SPEAK_TO_NPC = 3, }; API_CALLABLE(SpeakToPlayer) { return _show_message(script, isInitialCall, SHOW_MESSAGE_SPEAK_TO_PLAYER); } API_CALLABLE(EndSpeech) { return _show_message(script, isInitialCall, SHOW_MESSAGE_END_SPEECH); } API_CALLABLE(ContinueSpeech) { return _show_message(script, isInitialCall, SHOW_MESSAGE_CONTINUE_SPEECH); } API_CALLABLE(SpeakToNpc) { return _show_message(script, isInitialCall, SHOW_MESSAGE_SPEAK_TO_NPC); } s32 _show_message(Evt* script, s32 isInitialCall, s32 mode) { PlayerStatus* playerStatus = &gPlayerStatus; Bytecode* args = script->ptrReadPos; s32 screenX, screenY, screenZ; Npc* speakerNpc; Npc* targetNpc; f32 reverseAngle; f32 angle; f32* listenerYaw; s32 speakerNpcID; s32 targetNpcID; s32 msgID; s32 animID; s32 ret; targetNpc = NULL; if (isInitialCall) { D_802DB264 = false; speakerNpcID = evt_get_variable(script, *args++); script->varTable[13] = evt_get_variable(script, *args++); script->varTable[14] = evt_get_variable(script, *args++); script->functionTemp[1] = evt_get_variable(script, *args++); ShowMessageScreenOffsetY = 0; ShowMessageScreenOffsetX = 0; if (script->functionTemp[1] & SPEECH_FLAG_HAS_OFFSET) { ShowMessageScreenOffsetX = evt_get_variable(script, *args++); ShowMessageScreenOffsetY = evt_get_variable(script, *args++); } switch (mode) { case SHOW_MESSAGE_SPEAK_TO_PLAYER: msgID = evt_get_variable(script, *args++); gCurrentPrintContext = msg_get_printer_for_msg(msgID, &D_802DB264); break; case SHOW_MESSAGE_END_SPEECH: close_message(gCurrentPrintContext); break; case SHOW_MESSAGE_CONTINUE_SPEECH: msgID = evt_get_variable(script, *args++); msg_printer_load_msg(msgID, gCurrentPrintContext); break; case SHOW_MESSAGE_SPEAK_TO_NPC: targetNpcID = evt_get_variable(script, *args++); msgID = evt_get_variable(script, *args++); targetNpc = resolve_npc(script, targetNpcID); gCurrentPrintContext = msg_get_printer_for_msg(msgID, &D_802DB264); break; } if (speakerNpcID == NPC_PLAYER) { get_screen_coords(gCurrentCameraID, playerStatus->pos.x, playerStatus->pos.y + playerStatus->colliderHeight, playerStatus->pos.z, &screenX, &screenY, &screenZ); script->functionTemp[3] = playerStatus->anim; speakerNpc = (Npc*) NPC_PLAYER; script->varTable[15] = playerStatus->targetYaw; } else { speakerNpc = resolve_npc(script, speakerNpcID); get_screen_coords(gCurrentCameraID, speakerNpc->pos.x, speakerNpc->pos.y + speakerNpc->collisionHeight, speakerNpc->pos.z, &screenX, &screenY, &screenZ); script->functionTemp[3] = speakerNpc->curAnim; script->varTable[15] = speakerNpc->yaw; } msg_printer_set_origin_pos(gCurrentPrintContext, screenX + ShowMessageScreenOffsetX, screenY + ShowMessageScreenOffsetY); script->varTablePtr[12] = speakerNpc; if (speakerNpc != (Npc*) NPC_PLAYER) { if (mode == SHOW_MESSAGE_SPEAK_TO_NPC) { listenerYaw = &targetNpc->yaw; angle = atan2(speakerNpc->pos.x, speakerNpc->pos.z, targetNpc->pos.x, targetNpc->pos.z); } else { listenerYaw = &playerStatus->targetYaw; angle = atan2(speakerNpc->pos.x, speakerNpc->pos.z, playerStatus->pos.x, playerStatus->pos.z); } reverseAngle = clamp_angle(angle + 180.0f); switch (script->functionTemp[1] & SPEECH_ORIENTATION_MASK) { case SPEECH_FACE_EACH_OTHER: speakerNpc->yaw = angle; *listenerYaw = reverseAngle; break; case SPEECH_FACE_LIKE_LISTENER: speakerNpc->yaw = reverseAngle; *listenerYaw = reverseAngle; break; case SPEECH_FACE_LIKE_SPEAKER: speakerNpc->yaw = angle; *listenerYaw = angle; break; case SPEECH_FACE_AWAY_FROM: speakerNpc->yaw = reverseAngle; *listenerYaw = angle; break; case SPEECH_FACE_SPEAKER_ONLY: speakerNpc->yaw = angle; break; case 5: break; } } } speakerNpc = script->varTablePtr[12]; if (speakerNpc != (Npc*) NPC_PLAYER) { get_screen_coords(gCurrentCameraID, speakerNpc->pos.x, speakerNpc->pos.y + speakerNpc->collisionHeight, speakerNpc->pos.z, &screenX, &screenY, &screenZ); animID = script->varTable[13]; if (animID != -1) { if (!(gCurrentPrintContext->stateFlags & MSG_STATE_FLAG_SPEAKING)) { animID = script->varTable[14]; } set_npc_animation(speakerNpc, animID); } } else { get_screen_coords(gCurrentCameraID, playerStatus->pos.x, playerStatus->pos.y + playerStatus->colliderHeight, playerStatus->pos.z, &screenX, &screenY, &screenZ); if (script->varTable[13] != -1) { if (gCurrentPrintContext->stateFlags & MSG_STATE_FLAG_SPEAKING) { playerStatus->anim = script->varTable[13]; } else { playerStatus->anim = script->varTable[14]; } } } if (!(script->functionTemp[1] & SPEECH_FLAG_200)) { msg_printer_set_origin_pos(gCurrentPrintContext, screenX + ShowMessageScreenOffsetX, screenY + ShowMessageScreenOffsetY); } if (gCurrentPrintContext->stateFlags & MSG_STATE_FLAG_40) { return true; } if (D_802DB264 != true) { return false; } if (script->varTable[13] != -1) { if (speakerNpc != (Npc*) NPC_PLAYER) { set_npc_animation(speakerNpc, script->functionTemp[3]); } else { playerStatus->anim = script->functionTemp[3]; } } if (script->functionTemp[1] & SPEECH_FLAG_10) { speakerNpc->yaw = script->varTable[0xF]; } return true; } API_CALLABLE(ShowMessageAtScreenPos) { Bytecode* args = script->ptrReadPos; if (isInitialCall) { s32 msgID = evt_get_variable(script, *args++); s32 x = evt_get_variable(script, *args++); s32 y = evt_get_variable(script, *args++); bool* temp802DB264 = &D_802DB264; *temp802DB264 = false; gCurrentPrintContext = msg_get_printer_for_msg(msgID, temp802DB264); msg_printer_set_origin_pos(gCurrentPrintContext, x, y); } if (gCurrentPrintContext->stateFlags & MSG_STATE_FLAG_40) { return ApiStatus_DONE1; } if (D_802DB264 != true) { return ApiStatus_BLOCK; } script->varTable[0] = gCurrentPrintContext->curOption; return ApiStatus_DONE1; } API_CALLABLE(ShowMessageAtWorldPos) { Bytecode* args = script->ptrReadPos; MessagePrintState** currentPrintContext; s32* currentCameraID = &gCurrentCameraID; if (isInitialCall) { s32 msgID = evt_get_variable(script, *args++); s32 x = evt_get_variable(script, *args++); s32 y = evt_get_variable(script, *args++); s32 z = evt_get_variable(script, *args++); s32 x2; s32 y2; s32 z2; bool* temp802DB264 = &D_802DB264; *temp802DB264 = false; currentPrintContext = &gCurrentPrintContext; *currentPrintContext = msg_get_printer_for_msg(msgID, temp802DB264); get_screen_coords(*currentCameraID, x, y, z, &x2, &y2, &z2); msg_printer_set_origin_pos(*currentPrintContext, x2, y2); } if (gCurrentPrintContext->stateFlags & MSG_STATE_FLAG_40) { return ApiStatus_DONE1; } if (D_802DB264 != true) { return ApiStatus_BLOCK; } script->varTable[0] = gCurrentPrintContext->curOption; return ApiStatus_DONE1; } API_CALLABLE(CloseMessage) { if (isInitialCall) { close_message(gCurrentPrintContext); } if (gCurrentPrintContext->stateFlags & MSG_STATE_FLAG_40) { return ApiStatus_DONE1; } else if (D_802DB264 != true) { return ApiStatus_BLOCK; } else { script->varTable[0] = gCurrentPrintContext->curOption; return ApiStatus_DONE1; } } API_CALLABLE(SwitchMessage) { Bytecode* args = script->ptrReadPos; if (isInitialCall) { msg_printer_load_msg(evt_get_variable(script, *args), gCurrentPrintContext); } if (gCurrentPrintContext->stateFlags & MSG_STATE_FLAG_40) { return ApiStatus_DONE1; } else if (D_802DB264 != true) { return ApiStatus_BLOCK; } else { script->varTable[0] = gCurrentPrintContext->curOption; return ApiStatus_DONE1; } } API_CALLABLE(ShowChoice) { Bytecode* args = script->ptrReadPos; MessagePrintState** temp802DB268; if (isInitialCall) { s32 msgID = evt_get_variable(script, *args++); script->functionTempBool[1] = false; D_802DB268 = msg_get_printer_for_msg(msgID, &script->functionTempBool[1]); } temp802DB268 = &D_802DB268; script->varTable[0] = gCurrentPrintContext->curOption = (*temp802DB268)->curOption; if ((*temp802DB268)->stateFlags & MSG_STATE_FLAG_40) { return ApiStatus_DONE1; } return script->functionTempBool[1] == true; } API_CALLABLE(CloseChoice) { close_message(D_802DB268); return ApiStatus_DONE1; } API_CALLABLE(CancelMessage) { cancel_message(gCurrentPrintContext); return ApiStatus_DONE2; } s32 cancel_current_message(void) { cancel_message(gCurrentPrintContext); return 0; } API_CALLABLE(SetMessageImages) { Bytecode* args = script->ptrReadPos; set_message_images((MessageImageData*) *args++); return ApiStatus_DONE2; } API_CALLABLE(func_802D0C94) { Bytecode* args = script->ptrReadPos; if (evt_get_variable(script, *args++) == 0) { gOverrideFlags |= GLOBAL_OVERRIDES_MESSAGES_OVER_FRONTUI; } else { gOverrideFlags &= ~GLOBAL_OVERRIDES_MESSAGES_OVER_FRONTUI; } return ApiStatus_DONE2; } API_CALLABLE(SetMessageText) { Bytecode* args = script->ptrReadPos; s32 msg = evt_get_variable(script, *args++); s32 index = evt_get_variable(script, *args++); set_message_text_var(msg, index); return ApiStatus_DONE2; } API_CALLABLE(SetMessageValue) { Bytecode* ptrReadPos = script->ptrReadPos; s32 value = evt_get_variable(script, *ptrReadPos++); s32 index = evt_get_variable(script, *ptrReadPos); set_message_int_var(value, index); return ApiStatus_DONE2; }