taisei/src/dialog.c
2019-03-18 06:41:12 +02:00

176 lines
3.8 KiB
C

/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@alienslab.net>.
*/
#include "taisei.h"
#include "dialog.h"
#include "global.h"
Dialog *create_dialog(const char *left, const char *right) {
Dialog *d = malloc(sizeof(Dialog));
memset(d, 0, sizeof(Dialog));
if(left) {
d->images[Left] = get_sprite(left);
}
if(right) {
d->images[Right] = get_sprite(right);
}
d->page_time = global.frames;
d->birthtime = global.frames;
return d;
}
void dset_image(Dialog *d, Side side, const char *name) {
d->images[side] = get_sprite(name);
}
DialogMessage* dadd_msg(Dialog *d, Side side, const char *msg) {
d->messages = realloc(d->messages, (++d->count)*sizeof(DialogMessage));
d->messages[d->count-1].side = side;
d->messages[d->count-1].msg = malloc(strlen(msg) + 1);
d->messages[d->count-1].timeout = 0;
strlcpy(d->messages[d->count-1].msg, msg, strlen(msg) + 1);
return &d->messages[d->count-1];
}
void delete_dialog(Dialog *d) {
int i;
for(i = 0; i < d->count; i++)
free(d->messages[i].msg);
free(d->messages);
free(d);
}
void draw_dialog(Dialog *dialog) {
CullFaceMode cull_saved = r_cull_current();
r_mat_push();
r_mat_translate(VIEWPORT_W/2.0, VIEWPORT_H*3.0/4.0, 0);
int i;
for(i = 0; i < 2; i++) {
r_mat_push();
if(i == Left) {
r_cull(CULL_FRONT);
r_mat_scale(-1, 1, 1);
} else {
r_cull(CULL_BACK);
}
if(global.frames - dialog->birthtime < 30)
r_mat_translate(120 - (global.frames - dialog->birthtime)*4, 0, 0);
int cur = dialog->messages[dialog->pos].side;
int pre = 2;
if(dialog->pos > 0)
pre = dialog->messages[dialog->pos-1].side;
short dir = (1 - 2*(i == dialog->messages[dialog->pos].side));
if(global.frames - dialog->page_time < 10 && ((i != pre && i == cur) || (i == pre && i != cur))) {
int time = (global.frames - dialog->page_time) * dir;
r_mat_translate(time, time, 0);
float clr = min(1.0 - 0.07*time,1);
r_color3(clr, clr, clr);
} else {
r_mat_translate(dir*10, dir*10, 0);
r_color3(1 - (dir>0)*0.7, 1 - (dir>0)*0.7, 1 - (dir>0)*0.7);
}
r_mat_translate(VIEWPORT_W*7.0/18.0, 0, 0);
if(dialog->images[i])
draw_sprite_batched_p(0, 0, dialog->images[i]);
r_mat_pop();
r_color3(1,1,1);
}
r_mat_pop();
r_cull(cull_saved);
r_mat_push();
if(global.frames - dialog->birthtime < 25)
r_mat_translate(0, 100-(global.frames-dialog->birthtime)*4, 0);
r_color4(0,0,0,0.8);
r_mat_push();
r_mat_translate(VIEWPORT_W/2, VIEWPORT_H-75, 0);
r_mat_scale(VIEWPORT_W-40, 110, 1);
r_shader_standard_notex();
r_draw_quad();
r_shader_standard();
r_mat_pop();
r_color4(1,1,1,1);
if(dialog->messages[dialog->pos].side == Right)
r_color3(0.6,0.6,1);
r_shader("text_default");
text_draw_wrapped(dialog->messages[dialog->pos].msg, VIEWPORT_W * 0.85, &(TextParams) {
.pos = { VIEWPORT_W/2, VIEWPORT_H-110 },
.align = ALIGN_CENTER
});
if(dialog->messages[dialog->pos].side == Right)
r_color3(1,1,1);
r_mat_pop();
r_shader("sprite_default");
}
bool page_dialog(Dialog **d) {
if(!*d) {
return false;
}
int to = (*d)->messages[(*d)->pos].timeout;
if(to && to > global.frames) {
return false;
}
(*d)->pos++;
(*d)->page_time = global.frames;
if((*d)->pos >= (*d)->count) {
delete_dialog(*d);
*d = NULL;
// XXX: maybe this can be handled elsewhere?
if(!global.boss)
global.timer++;
} else if((*d)->messages[(*d)->pos].side == BGM) {
stage_start_bgm((*d)->messages[(*d)->pos].msg);
return page_dialog(d);
}
return true;
}
void process_dialog(Dialog **d) {
if(!*d) {
return;
}
int to = (*d)->messages[(*d)->pos].timeout;
if(
(to && to >= global.frames) ||
((global.plr.inputflags & INFLAG_SKIP) && global.frames - (*d)->page_time > 3)
) {
page_dialog(d);
}
}