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