sm64coopdx/src/game/chat.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--;
}
}