mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
142 lines
4.9 KiB
C
142 lines
4.9 KiB
C
#include <stdio.h>
|
|
#include <ultra64.h>
|
|
#include <string.h>
|
|
|
|
#include "chat.h"
|
|
#include "game_init.h"
|
|
#include "ingame_menu.h"
|
|
#include "segment2.h"
|
|
#include "gfx_dimensions.h"
|
|
#include "config.h"
|
|
#include "PR/gbi.h"
|
|
#include "pc/controller/controller_keyboard.h"
|
|
#include "pc/network/network.h"
|
|
#include "audio_defines.h"
|
|
#include "audio/external.h"
|
|
#include "menu/file_select.h"
|
|
|
|
#define CHAT_DIALOG_MAX 96
|
|
#define CHAT_MESSAGES_MAX 16
|
|
#define CHAT_LIFE_MAX 400
|
|
|
|
struct ChatMessage {
|
|
u8 dialog[CHAT_DIALOG_MAX];
|
|
enum ChatMessageType type;
|
|
u16 life;
|
|
};
|
|
|
|
static char inputMessage[CHAT_DIALOG_MAX] = { 0 };
|
|
static struct ChatMessage message[CHAT_MESSAGES_MAX] = { 0 };
|
|
static u8 onMessageIndex = 0;
|
|
static u8 sInChatInput = FALSE;
|
|
|
|
#define CHAT_SCALE 0.5f
|
|
#define CHAT_SPACE 10.0f
|
|
#define CHATBOX_PAD_X 0.0215f
|
|
#define CHATBOX_SCALE_X 0.00385f
|
|
#define CHATBOX_SCALE_Y 0.115f
|
|
#define CHATBOX_X 2.0f
|
|
#define CHATBOX_Y 11.0f
|
|
#define CHAT_X 4.0f
|
|
#define CHAT_Y -18.0f
|
|
|
|
static void render_chat_message(struct ChatMessage* chatMessage, u8 index) {
|
|
f32 textWidth = get_generic_dialog_width(chatMessage->dialog);
|
|
f32 alphaScale = ((f32)chatMessage->life / (f32)(CHAT_LIFE_MAX / 20.0f));
|
|
alphaScale *= alphaScale;
|
|
if (alphaScale > 1) { alphaScale = 1; }
|
|
|
|
f32 chatBoxWidth = CHATBOX_SCALE_X * textWidth + CHATBOX_PAD_X;
|
|
create_dl_translation_matrix(MENU_MTX_PUSH, GFX_DIMENSIONS_FROM_LEFT_EDGE(CHATBOX_X), CHATBOX_Y + index * CHAT_SPACE, 0);
|
|
create_dl_scale_matrix(MENU_MTX_NOPUSH, chatBoxWidth, CHATBOX_SCALE_Y, 1.0f);
|
|
|
|
u8 boxR, boxG, boxB;
|
|
if (chatMessage->type == CMT_INPUT) {
|
|
boxR = 150;
|
|
boxG = 150;
|
|
boxB = 255;
|
|
} else {
|
|
f32 rgbScale = (((f32)chatMessage->life - ((f32)CHAT_LIFE_MAX * 0.98f)) / ((f32)CHAT_LIFE_MAX * 0.02f));
|
|
if (chatMessage->type == CMT_LOCAL || rgbScale < 0) { rgbScale = 0; }
|
|
boxR = 255 * rgbScale;
|
|
boxG = 255 * rgbScale;
|
|
boxB = 255 * rgbScale;
|
|
}
|
|
|
|
gDPSetEnvColor(gDisplayListHead++, boxR, boxG, boxB, 110 * alphaScale);
|
|
gSPDisplayList(gDisplayListHead++, dl_draw_text_bg_box);
|
|
|
|
create_dl_scale_matrix(MENU_MTX_NOPUSH, CHAT_SCALE / chatBoxWidth, CHAT_SCALE / CHATBOX_SCALE_Y, 1.0f);
|
|
|
|
u8 textR, textG, textB;
|
|
switch (chatMessage->type) {
|
|
case CMT_LOCAL: textR = 200; textG = 200; textB = 255; break;
|
|
case CMT_INPUT: textR = 0; textG = 0; textB = 0; break;
|
|
case CMT_SYSTEM: textR = 255; textG = 255; textB = 190; break;
|
|
default: textR = 255; textG = 255; textB = 255;
|
|
}
|
|
|
|
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
|
|
gDPSetEnvColor(gDisplayListHead++, textR, textG, textB, 255 * alphaScale);
|
|
print_generic_string(CHAT_X, CHAT_Y, chatMessage->dialog);
|
|
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
|
|
|
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
|
|
}
|
|
|
|
void chat_add_message(char* ascii, enum ChatMessageType chatMessageType) {
|
|
u8 character = '?';
|
|
switch (chatMessageType) {
|
|
case CMT_INPUT:
|
|
case CMT_LOCAL: character = 0xFD; break;
|
|
case CMT_REMOTE: character = 0xFA; break;
|
|
case CMT_SYSTEM: character = 0xF9; break;
|
|
}
|
|
struct ChatMessage* msg = &message[onMessageIndex];
|
|
msg->dialog[0] = character;
|
|
msg->dialog[1] = 0x9E;
|
|
str_ascii_to_dialog(ascii, &msg->dialog[2], MIN(strlen(ascii), CHAT_DIALOG_MAX - 3));
|
|
msg->life = (sSelectedFileNum != 0) ? CHAT_LIFE_MAX : CHAT_LIFE_MAX / 3;
|
|
msg->type = chatMessageType;
|
|
onMessageIndex = (onMessageIndex + 1) % CHAT_MESSAGES_MAX;
|
|
play_sound((msg->type == CMT_LOCAL) ? SOUND_MENU_MESSAGE_DISAPPEAR : SOUND_MENU_MESSAGE_APPEAR, gDefaultSoundArgs);
|
|
}
|
|
|
|
static void chat_stop_input(void) {
|
|
sInChatInput = FALSE;
|
|
keyboard_stop_text_input();
|
|
}
|
|
|
|
static void chat_send_input(void) {
|
|
sInChatInput = FALSE;
|
|
keyboard_stop_text_input();
|
|
if (strlen(gTextInput) == 0) { return; }
|
|
chat_add_message(gTextInput, CMT_LOCAL);
|
|
network_send_chat(gTextInput);
|
|
}
|
|
|
|
void chat_start_input(void) {
|
|
sInChatInput = TRUE;
|
|
keyboard_start_text_input(TIM_SINGLE_LINE, CHAT_DIALOG_MAX - 3, chat_stop_input, chat_send_input);
|
|
}
|
|
|
|
void render_chat(void) {
|
|
u8 count = 0;
|
|
if (sInChatInput) {
|
|
struct ChatMessage inputMessage = { 0 };
|
|
inputMessage.type = CMT_INPUT;
|
|
inputMessage.dialog[0] = 0xFD;
|
|
inputMessage.dialog[1] = 0x9E;
|
|
str_ascii_to_dialog(gTextInput, &inputMessage.dialog[2], MIN(strlen(gTextInput), CHAT_DIALOG_MAX - 3));
|
|
inputMessage.life = CHAT_LIFE_MAX;
|
|
render_chat_message(&inputMessage, count++);
|
|
}
|
|
|
|
u8 index = onMessageIndex;
|
|
for (int i = 0; i < CHAT_MESSAGES_MAX; i++) {
|
|
if (--index >= CHAT_MESSAGES_MAX) { index = CHAT_MESSAGES_MAX - 1; }
|
|
if (message[index].life == 0) { continue; }
|
|
render_chat_message(&message[index], count++);
|
|
message[index].life--;
|
|
}
|
|
}
|