1 /*
2 * This software is licensed under the terms of the MIT License.
3 * See COPYING for further information.
4 * ---
5 * Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
6 * Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
7 */
8
9 #include "taisei.h"
10
11 #include "global.h"
12 #include "plrmodes.h"
13 #include "marisa.h"
14 #include "stagedraw.h"
15
16 PlayerCharacter character_marisa = {
17 .id = PLR_CHAR_MARISA,
18 .lower_name = "marisa",
19 .proper_name = "Marisa",
20 .full_name = "Kirisame Marisa",
21 .title = "Ordinary Black Magician",
22 .dialog_base_sprite_name = "dialog/marisa",
23 .player_sprite_name = "player/marisa",
24 .menu_texture_name = "marisa_bombbg",
25 .ending = {
26 .good = good_ending_marisa,
27 .bad = bad_ending_marisa,
28 },
29 };
30
marisa_common_property(Player * plr,PlrProperty prop)31 double marisa_common_property(Player *plr, PlrProperty prop) {
32 switch(prop) {
33 case PLR_PROP_BOMB_TIME:
34 return 300;
35
36 case PLR_PROP_COLLECT_RADIUS:
37 return (plr->inputflags & INFLAG_FOCUS) ? 60 : 30;
38
39 case PLR_PROP_SPEED:
40 // NOTE: For equivalents in Touhou units, divide these by 1.25.
41 return (plr->inputflags & INFLAG_FOCUS) ? 2.75 : 6.25;
42
43 case PLR_PROP_POC:
44 return VIEWPORT_H / 3.5;
45
46 case PLR_PROP_DEATHBOMB_WINDOW:
47 return 12;
48 }
49
50 UNREACHABLE;
51 }
52
marisa_common_shot(Player * plr,float dmg)53 void marisa_common_shot(Player *plr, float dmg) {
54 play_loop("generic_shot");
55
56 if(!(global.frames % 6)) {
57 Color *c = RGB(1, 1, 1);
58
59 for(int i = -1; i < 2; i += 2) {
60 PROJECTILE(
61 .proto = pp_marisa,
62 .pos = plr->pos + 10 * i - 15.0*I,
63 .color = c,
64 .rule = linear,
65 .args = { -20.0*I },
66 .type = PROJ_PLAYER,
67 .damage = dmg,
68 .shader = "sprite_default",
69 );
70 }
71 }
72 }
73
marisa_common_slave_visual(Enemy * e,int t,bool render)74 void marisa_common_slave_visual(Enemy *e, int t, bool render) {
75 if(!render) {
76 return;
77 }
78
79 r_draw_sprite(&(SpriteParams) {
80 .sprite = "hakkero",
81 .shader = "sprite_hakkero",
82 .pos = { creal(e->pos), cimag(e->pos) },
83 .rotation.angle = t * 0.05,
84 .color = RGB(0.2, 0.4, 0.5),
85 });
86 }
87
draw_masterspark_ring(int t,float width)88 static void draw_masterspark_ring(int t, float width) {
89 float sy = sqrt(t / 500.0) * 6;
90 float sx = sy * width / 800;
91
92 if(sx == 0 || sy == 0) {
93 return;
94 }
95
96 r_draw_sprite(&(SpriteParams) {
97 .sprite = "masterspark_ring",
98 .shader = "sprite_default",
99 .pos = { 0, -t*t*0.4 + 2 },
100 .color = RGBA(0.5, 0.5, 0.5, 0.0),
101 .scale = { .x = sx, .y = sy * sy * 1.5 },
102 });
103 }
104
draw_masterspark_beam(cmplx origin,cmplx size,float angle,int t,float alpha)105 static void draw_masterspark_beam(cmplx origin, cmplx size, float angle, int t, float alpha) {
106 r_mat_mv_push();
107 r_mat_mv_translate(creal(origin), cimag(origin), 0);
108 r_mat_mv_rotate(angle, 0, 0, 1);
109
110 r_shader("masterspark");
111 r_uniform_float("t", t);
112
113 r_mat_mv_push();
114 r_mat_mv_translate(0, cimag(size) * -0.5, 0);
115 r_mat_mv_scale(alpha * creal(size), cimag(size), 1);
116 r_draw_quad();
117 r_mat_mv_pop();
118
119 for(int i = 0; i < 4; i++) {
120 draw_masterspark_ring(t % 20 + 10 * i, alpha * creal(size));
121 }
122
123 r_mat_mv_pop();
124 }
125
marisa_common_masterspark_draw(int numBeams,MarisaBeamInfo * beamInfos,float alpha)126 void marisa_common_masterspark_draw(int numBeams, MarisaBeamInfo *beamInfos, float alpha) {
127 r_state_push();
128
129 float blur = 1.0 - alpha;
130 int pp_quality = config_get_int(CONFIG_POSTPROCESS);
131
132 if(pp_quality < 1 || (pp_quality < 2 && blur == 0)) {
133 Framebuffer *main_fb = r_framebuffer_current();
134 FBPair *aux = stage_get_fbpair(FBPAIR_FG_AUX);
135
136 r_framebuffer(aux->back);
137 r_clear(CLEAR_COLOR, RGBA(0, 0, 0, 0), 1);
138 for(int i = 0; i < numBeams; i++) {
139 draw_masterspark_beam(beamInfos[i].origin, beamInfos[i].size, beamInfos[i].angle, beamInfos[i].t, alpha);
140 }
141
142 fbpair_swap(aux);
143 r_framebuffer(main_fb);
144 r_shader_standard();
145 r_color4(1, 1, 1, 1);
146 draw_framebuffer_tex(aux->front, VIEWPORT_W, VIEWPORT_H);
147 } else if(blur == 0) {
148 for(int i = 0; i < numBeams; i++) {
149 draw_masterspark_beam(beamInfos[i].origin, beamInfos[i].size, beamInfos[i].angle, beamInfos[i].t, alpha);
150 }
151 } else {
152 Framebuffer *main_fb = r_framebuffer_current();
153 FBPair *aux = stage_get_fbpair(FBPAIR_FG_AUX);
154
155 r_framebuffer(aux->back);
156 r_clear(CLEAR_COLOR, RGBA(0, 0, 0, 0), 1);
157
158 for(int i = 0; i < numBeams; i++) {
159 draw_masterspark_beam(beamInfos[i].origin, beamInfos[i].size, beamInfos[i].angle, beamInfos[i].t, alpha);
160 }
161
162 if(pp_quality > 1) {
163 r_shader("blur25");
164 } else {
165 r_shader("blur5");
166 }
167
168 r_uniform_vec2("blur_resolution", VIEWPORT_W, VIEWPORT_H);
169 r_uniform_vec2("blur_direction", blur, 0);
170
171 fbpair_swap(aux);
172 r_framebuffer(aux->back);
173 r_clear(CLEAR_COLOR, RGBA(0, 0, 0, 0), 1);
174 draw_framebuffer_tex(aux->front, VIEWPORT_W, VIEWPORT_H);
175
176 r_uniform_vec2("blur_direction", 0, blur);
177
178 fbpair_swap(aux);
179 r_framebuffer(main_fb);
180 draw_framebuffer_tex(aux->front, VIEWPORT_W, VIEWPORT_H);
181 }
182
183 r_state_pop();
184 }
185