2010-10-12 10:55:23 +02:00
|
|
|
/*
|
2011-03-05 19:03:32 +01:00
|
|
|
* This software is licensed under the terms of the MIT-License
|
2017-02-10 23:05:22 +01:00
|
|
|
* See COPYING for further information.
|
2011-03-05 19:03:32 +01:00
|
|
|
* ---
|
2017-09-12 03:28:15 +02:00
|
|
|
* Copyright (c) 2011-2017, Lukas Weber <laochailan@web.de>.
|
|
|
|
* Copyright (c) 2012-2017, Andrei Alexeyev <akari@alienslab.net>.
|
2010-10-12 10:55:23 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "projectile.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "global.h"
|
2010-10-27 19:51:49 +02:00
|
|
|
#include "list.h"
|
2011-12-25 08:18:03 +01:00
|
|
|
#include "vbo.h"
|
2011-04-26 16:55:18 +02:00
|
|
|
|
2017-02-26 21:59:51 +01:00
|
|
|
Projectile *create_particle4c(char *name, complex pos, Color clr, ProjDRule draw, ProjRule rule, complex a1, complex a2, complex a3, complex a4) {
|
2011-06-26 13:45:27 +02:00
|
|
|
Projectile *p = create_projectile_p(&global.particles, prefix_get_tex(name, "part/"), pos, clr, draw, rule, a1, a2, a3, a4);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-21 15:02:19 +02:00
|
|
|
p->type = Particle;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2017-02-26 21:59:51 +01:00
|
|
|
Projectile *create_projectile4c(char *name, complex pos, Color clr, ProjRule rule, complex a1, complex a2, complex a3, complex a4) {
|
2011-06-26 13:45:27 +02:00
|
|
|
return create_projectile_p(&global.projs, prefix_get_tex(name, "proj/"), pos, clr, ProjDraw, rule, a1, a2, a3, a4);
|
2011-05-13 19:03:02 +02:00
|
|
|
}
|
|
|
|
|
2017-02-26 21:59:51 +01:00
|
|
|
Projectile *create_projectile_p(Projectile **dest, Texture *tex, complex pos, Color clr,
|
2011-06-26 13:45:27 +02:00
|
|
|
ProjDRule draw, ProjRule rule, complex a1, complex a2, complex a3, complex a4) {
|
2012-08-17 16:20:05 +02:00
|
|
|
Projectile *p, *e, **d;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-08-17 16:20:05 +02:00
|
|
|
for(e = *dest; e && e->next; e = e->next)
|
|
|
|
if(e->prev && tex->w*tex->h > e->tex->w*e->tex->h)
|
|
|
|
break;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-08-17 16:20:05 +02:00
|
|
|
if(e == NULL)
|
|
|
|
d = dest;
|
|
|
|
else
|
|
|
|
d = &e;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-08-17 16:20:05 +02:00
|
|
|
p = create_element((void **)d, sizeof(Projectile));
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-03-07 07:26:43 +01:00
|
|
|
p->birthtime = global.frames;
|
2011-03-18 19:03:06 +01:00
|
|
|
p->pos = pos;
|
|
|
|
p->pos0 = pos;
|
2011-06-29 17:01:03 +02:00
|
|
|
p->angle = M_PI/2;
|
2010-10-27 19:51:49 +02:00
|
|
|
p->rule = rule;
|
2011-05-13 19:03:02 +02:00
|
|
|
p->draw = draw;
|
2011-05-21 15:02:19 +02:00
|
|
|
p->tex = tex;
|
2010-10-27 19:51:49 +02:00
|
|
|
p->type = FairyProj;
|
|
|
|
p->clr = clr;
|
2012-08-12 21:29:10 +02:00
|
|
|
p->grazed = 0;
|
2017-09-05 23:02:40 +02:00
|
|
|
p->maxviewportdist = 0;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-06-26 13:45:27 +02:00
|
|
|
p->args[0] = a1;
|
|
|
|
p->args[1] = a2;
|
|
|
|
p->args[2] = a3;
|
|
|
|
p->args[3] = a4;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2010-10-17 10:39:07 +02:00
|
|
|
return p;
|
2010-10-12 10:55:23 +02:00
|
|
|
}
|
|
|
|
|
2011-04-26 22:39:50 +02:00
|
|
|
void _delete_projectile(void **projs, void *proj) {
|
2011-05-21 15:02:19 +02:00
|
|
|
Projectile *p = proj;
|
|
|
|
p->rule(p, EVENT_DEATH);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-13 19:03:02 +02:00
|
|
|
del_ref(proj);
|
2011-04-26 22:39:50 +02:00
|
|
|
delete_element(projs, proj);
|
|
|
|
}
|
|
|
|
|
2011-05-06 17:09:43 +02:00
|
|
|
void delete_projectile(Projectile **projs, Projectile *proj) {
|
|
|
|
_delete_projectile((void **)projs, proj);
|
2010-10-12 10:55:23 +02:00
|
|
|
}
|
|
|
|
|
2011-05-06 17:09:43 +02:00
|
|
|
void delete_projectiles(Projectile **projs) {
|
|
|
|
delete_all_elements((void **)projs, _delete_projectile);
|
2010-10-12 10:55:23 +02:00
|
|
|
}
|
|
|
|
|
2012-08-14 16:14:53 +02:00
|
|
|
int collision_projectile(Projectile *p) {
|
2010-10-17 10:39:07 +02:00
|
|
|
if(p->type == FairyProj) {
|
2012-08-13 21:53:36 +02:00
|
|
|
double angle = carg(global.plr.pos - p->pos) + p->angle;
|
|
|
|
double projr = sqrt(pow(p->tex->w/4*cos(angle),2)*5/10.0 + pow(p->tex->h/2*sin(angle)*5/10.0,2));
|
2012-08-12 21:29:10 +02:00
|
|
|
double grazer = max(p->tex->w, p->tex->h);
|
2012-08-13 21:53:36 +02:00
|
|
|
double dst = cabs(global.plr.pos - p->pos);
|
2017-02-10 23:05:22 +01:00
|
|
|
grazer = (0.9 * sqrt(grazer) + 0.1 * grazer) * 6;
|
|
|
|
|
2012-08-12 21:29:10 +02:00
|
|
|
if(dst < projr + 1)
|
2010-10-17 10:39:07 +02:00
|
|
|
return 1;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-08-13 18:09:32 +02:00
|
|
|
if(!p->grazed && dst < grazer && global.frames - abs(global.plr.recovery) > 0) {
|
2017-02-11 04:52:08 +01:00
|
|
|
p->grazed = true;
|
2017-02-10 23:05:22 +01:00
|
|
|
player_graze(&global.plr, p->pos - grazer * 0.3 * cexp(I*carg(p->pos - global.plr.pos)), 50);
|
2012-08-12 21:29:10 +02:00
|
|
|
}
|
2011-07-06 14:33:53 +02:00
|
|
|
} else if(p->type >= PlrProj) {
|
2011-04-26 12:04:45 +02:00
|
|
|
Enemy *e = global.enemies;
|
2017-02-10 23:05:22 +01:00
|
|
|
int damage = p->type - PlrProj;
|
|
|
|
|
2011-04-26 12:04:45 +02:00
|
|
|
while(e != NULL) {
|
|
|
|
if(e->hp != ENEMY_IMMUNE && cabs(e->pos - p->pos) < 15) {
|
2017-03-25 19:18:24 +01:00
|
|
|
player_add_points(&global.plr, damage * 0.5);
|
2017-03-06 13:02:46 +01:00
|
|
|
|
|
|
|
#ifdef PLR_DPS_STATS
|
|
|
|
global.plr.total_dmg += min(e->hp, damage);
|
|
|
|
#endif
|
|
|
|
|
2017-02-10 23:05:22 +01:00
|
|
|
e->hp -= damage;
|
2010-10-17 10:39:07 +02:00
|
|
|
return 2;
|
|
|
|
}
|
2011-04-26 12:04:45 +02:00
|
|
|
e = e->next;
|
2010-10-17 10:39:07 +02:00
|
|
|
}
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-08-12 18:58:58 +02:00
|
|
|
if(global.boss && cabs(global.boss->pos - p->pos) < 42
|
2017-09-12 11:58:28 +02:00
|
|
|
&& boss_is_vulnerable(global.boss)) {
|
2017-03-25 19:18:24 +01:00
|
|
|
player_add_points(&global.plr, damage * 0.2);
|
2017-09-13 10:33:58 +02:00
|
|
|
global.boss->current->hp -= damage;
|
2017-03-06 13:02:46 +01:00
|
|
|
|
|
|
|
#ifdef PLR_DPS_STATS
|
|
|
|
global.plr.total_dmg += damage;
|
|
|
|
#endif
|
|
|
|
|
2011-04-08 18:59:03 +02:00
|
|
|
return 2;
|
|
|
|
}
|
2010-10-17 10:39:07 +02:00
|
|
|
}
|
2010-10-17 09:27:44 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-08-14 16:14:53 +02:00
|
|
|
void draw_projectiles(Projectile *projs) {
|
2011-03-07 13:41:10 +01:00
|
|
|
Projectile *proj;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-08-14 16:14:53 +02:00
|
|
|
for(proj = projs; proj; proj = proj->next)
|
2011-05-13 19:03:02 +02:00
|
|
|
proj->draw(proj, global.frames - proj->birthtime);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2010-10-18 14:40:15 +02:00
|
|
|
}
|
2010-10-17 09:27:44 +02:00
|
|
|
|
2017-02-11 04:52:08 +01:00
|
|
|
void process_projectiles(Projectile **projs, bool collision) {
|
2011-05-06 17:09:43 +02:00
|
|
|
Projectile *proj = *projs, *del = NULL;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-13 19:03:02 +02:00
|
|
|
char killed = 0;
|
|
|
|
char col = 0;
|
|
|
|
int action;
|
2010-10-12 10:55:23 +02:00
|
|
|
while(proj != NULL) {
|
2011-05-13 19:03:02 +02:00
|
|
|
action = proj->rule(proj, global.frames - proj->birthtime);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-07-20 11:45:29 +02:00
|
|
|
if(proj->type == DeadProj && killed < 5) {
|
2011-05-13 19:03:02 +02:00
|
|
|
killed++;
|
|
|
|
action = ACTION_DESTROY;
|
2017-02-26 21:59:51 +01:00
|
|
|
create_particle1c("flare", proj->pos, 0, Fade, timeout, 30);
|
2011-05-13 19:03:02 +02:00
|
|
|
create_item(proj->pos, 0, BPoint)->auto_collect = 10;
|
|
|
|
}
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-06 17:09:43 +02:00
|
|
|
if(collision)
|
2011-05-13 19:03:02 +02:00
|
|
|
col = collision_projectile(proj);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-21 15:02:19 +02:00
|
|
|
if(col && proj->type != Particle) {
|
2017-03-06 14:22:31 +01:00
|
|
|
Projectile *p = create_projectile_p(&global.particles, proj->tex, proj->pos, proj->clr, DeathShrink, timeout_linear, 10, 5*cexp(proj->angle*I), 0, 0);
|
|
|
|
|
|
|
|
if(proj->type > PlrProj) {
|
|
|
|
p->type = PlrProj;
|
|
|
|
}
|
2011-05-21 15:02:19 +02:00
|
|
|
}
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-21 15:02:19 +02:00
|
|
|
if(col == 1 && global.frames - abs(global.plr.recovery) >= 0)
|
2012-07-20 16:11:24 +02:00
|
|
|
player_death(&global.plr);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2017-09-05 23:02:40 +02:00
|
|
|
int e = proj->maxviewportdist;
|
|
|
|
|
|
|
|
if(e < 300 && (proj->type == Particle || proj->type >= PlrProj)) {
|
|
|
|
// XXX: maybe have them set it manually?
|
2011-11-01 21:20:40 +01:00
|
|
|
e = 300;
|
|
|
|
}
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-13 19:03:02 +02:00
|
|
|
if(action == ACTION_DESTROY || col
|
2011-11-01 21:20:40 +01:00
|
|
|
|| creal(proj->pos) + proj->tex->w/2 + e < 0 || creal(proj->pos) - proj->tex->w/2 - e > VIEWPORT_W
|
|
|
|
|| cimag(proj->pos) + proj->tex->h/2 + e < 0 || cimag(proj->pos) - proj->tex->h/2 - e > VIEWPORT_H) {
|
2010-10-18 14:40:15 +02:00
|
|
|
del = proj;
|
|
|
|
proj = proj->next;
|
2011-05-06 17:09:43 +02:00
|
|
|
delete_projectile(projs, del);
|
2010-10-18 14:40:15 +02:00
|
|
|
if(proj == NULL) break;
|
|
|
|
} else {
|
|
|
|
proj = proj->next;
|
2010-10-17 10:39:07 +02:00
|
|
|
}
|
2010-10-27 19:51:49 +02:00
|
|
|
}
|
2010-10-12 10:55:23 +02:00
|
|
|
}
|
|
|
|
|
2011-05-21 15:02:19 +02:00
|
|
|
|
2011-07-07 14:34:30 +02:00
|
|
|
int linear(Projectile *p, int t) { // sure is physics in here; a[0]: velocity
|
|
|
|
if(t < 0)
|
|
|
|
return 1;
|
2011-05-06 17:09:43 +02:00
|
|
|
p->angle = carg(p->args[0]);
|
|
|
|
p->pos = p->pos0 + p->args[0]*t;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-13 19:03:02 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-06-27 13:36:35 +02:00
|
|
|
int accelerated(Projectile *p, int t) {
|
2011-07-07 14:34:30 +02:00
|
|
|
if(t < 0)
|
|
|
|
return 1;
|
2012-07-31 14:34:20 +02:00
|
|
|
p->angle = carg(p->args[0]);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-07-31 14:34:20 +02:00
|
|
|
p->pos += p->args[0];
|
|
|
|
p->args[0] += p->args[1];
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-06-27 13:36:35 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-06-28 19:23:02 +02:00
|
|
|
int asymptotic(Projectile *p, int t) { // v = a[0]*(a[1] + 1); a[1] -> 0
|
2011-07-07 14:34:30 +02:00
|
|
|
if(t < 0)
|
|
|
|
return 1;
|
2011-08-27 15:56:02 +02:00
|
|
|
p->angle = carg(p->args[0]);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-06-28 19:23:02 +02:00
|
|
|
p->args[1] *= 0.8;
|
|
|
|
p->pos += p->args[0]*(p->args[1] + 1);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-06-28 19:23:02 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-05-21 15:02:19 +02:00
|
|
|
void _ProjDraw(Projectile *proj, int t) {
|
2017-03-02 11:23:30 +01:00
|
|
|
if(proj->clr) {
|
2017-02-26 21:59:51 +01:00
|
|
|
static GLfloat clr[4];
|
2012-04-05 16:27:18 +02:00
|
|
|
Shader *shader = get_shader("bullet_color");
|
2012-07-29 10:58:46 +02:00
|
|
|
glUseProgram(shader->prog);
|
2017-02-26 21:59:51 +01:00
|
|
|
parse_color_array(proj->clr, clr);
|
|
|
|
glUniform4fv(uniloc(shader, "color"), 1, clr);
|
2011-05-13 19:03:02 +02:00
|
|
|
}
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-21 15:02:19 +02:00
|
|
|
draw_texture_p(0,0, proj->tex);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2017-03-02 11:23:30 +01:00
|
|
|
if(proj->clr) {
|
2017-02-10 23:05:22 +01:00
|
|
|
glUseProgram(0);
|
2017-03-02 11:23:30 +01:00
|
|
|
}
|
2011-05-21 15:02:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ProjDraw(Projectile *proj, int t) {
|
2011-05-13 19:03:02 +02:00
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(creal(proj->pos), cimag(proj->pos), 0);
|
|
|
|
glRotatef(proj->angle*180/M_PI+90, 0, 0, 1);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-04-06 18:01:12 +02:00
|
|
|
if(t < 16 && proj->type < PlrProj && proj->type != Particle) {
|
2012-04-06 15:54:30 +02:00
|
|
|
float s = 2.0-t/16.0;
|
|
|
|
if(s != 1)
|
|
|
|
glScalef(s,s,1);
|
|
|
|
}
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-21 15:02:19 +02:00
|
|
|
_ProjDraw(proj, t);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-07-06 14:33:53 +02:00
|
|
|
glPopMatrix();
|
2010-10-12 10:55:23 +02:00
|
|
|
}
|
2011-05-13 19:03:02 +02:00
|
|
|
|
2017-04-20 18:37:46 +02:00
|
|
|
void ProjDrawNoFlareAdd(Projectile *proj, int t) {
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(creal(proj->pos), cimag(proj->pos), 0);
|
|
|
|
glRotatef(proj->angle*180/M_PI+90, 0, 0, 1);
|
|
|
|
|
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
|
|
|
_ProjDraw(proj, t);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
2012-07-18 23:12:31 +02:00
|
|
|
void ProjDrawAdd(Projectile *proj, int t) {
|
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
|
|
|
ProjDraw(proj, t);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
}
|
|
|
|
|
2012-07-25 15:32:37 +02:00
|
|
|
void ProjDrawSub(Projectile *proj, int t) {
|
|
|
|
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
|
|
|
ProjDraw(proj, t);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glBlendEquation(GL_FUNC_ADD);
|
|
|
|
}
|
|
|
|
|
2011-06-29 17:01:03 +02:00
|
|
|
void PartDraw(Projectile *proj, int t) {
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(creal(proj->pos), cimag(proj->pos), 0);
|
|
|
|
glRotatef(proj->angle*180/M_PI+90, 0, 0, 1);
|
|
|
|
|
2017-02-26 21:59:51 +01:00
|
|
|
if(proj->clr) {
|
|
|
|
parse_color_call(proj->clr, glColor4f);
|
|
|
|
}
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-06-29 17:01:03 +02:00
|
|
|
draw_texture_p(0,0, proj->tex);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-04-05 14:24:55 +02:00
|
|
|
glPopMatrix();
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-04-05 14:24:55 +02:00
|
|
|
if(proj->clr)
|
|
|
|
glColor3f(1,1,1);
|
2011-06-29 17:01:03 +02:00
|
|
|
}
|
2011-11-02 20:00:14 +01:00
|
|
|
|
2011-06-28 19:23:02 +02:00
|
|
|
void Blast(Projectile *p, int t) {
|
|
|
|
if(t == 1) {
|
|
|
|
p->args[1] = frand()*360 + frand()*I;
|
|
|
|
p->args[2] = frand() + frand()*I;
|
|
|
|
}
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-06-28 19:23:02 +02:00
|
|
|
glPushMatrix();
|
2012-04-05 14:24:55 +02:00
|
|
|
if(p->pos)
|
|
|
|
glTranslatef(creal(p->pos), cimag(p->pos), 0);
|
2011-06-28 19:23:02 +02:00
|
|
|
glRotatef(creal(p->args[1]), cimag(p->args[1]), creal(p->args[2]), cimag(p->args[2]));
|
2012-04-05 14:24:55 +02:00
|
|
|
if(t != p->args[0])
|
|
|
|
glScalef(t/p->args[0], t/p->args[0], 1);
|
2011-06-28 19:23:02 +02:00
|
|
|
glColor4f(0.3,0.6,1,1 - t/p->args[0]);
|
2017-03-21 11:59:31 +01:00
|
|
|
draw_texture_p(0,0,p->tex);
|
2017-03-21 09:22:10 +01:00
|
|
|
glScalef(0.5+creal(p->args[2]),0.5+creal(p->args[2]),1);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
2011-06-28 19:23:02 +02:00
|
|
|
draw_texture_p(0,0,p->tex);
|
2017-03-21 09:22:10 +01:00
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
2011-06-28 19:23:02 +02:00
|
|
|
glPopMatrix();
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-06-28 19:23:02 +02:00
|
|
|
glColor4f(1,1,1,1);
|
|
|
|
}
|
2017-02-10 23:05:22 +01:00
|
|
|
|
|
|
|
void Shrink(Projectile *p, int t) {
|
2011-05-13 19:03:02 +02:00
|
|
|
glPushMatrix();
|
2011-05-14 17:26:43 +02:00
|
|
|
float s = 2.0-t/p->args[0]*2;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-04-05 14:24:55 +02:00
|
|
|
if(p->pos)
|
|
|
|
glTranslatef(creal(p->pos), cimag(p->pos), 0);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-04-05 14:24:55 +02:00
|
|
|
if(p->angle != M_PI*0.5)
|
|
|
|
glRotatef(p->angle*180/M_PI+90, 0, 0, 1);
|
2012-04-06 18:01:12 +02:00
|
|
|
if(s != 1)
|
2012-04-05 14:24:55 +02:00
|
|
|
glScalef(s, s, 1);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-21 15:02:19 +02:00
|
|
|
_ProjDraw(p, t);
|
2011-05-13 19:03:02 +02:00
|
|
|
glPopMatrix();
|
2011-05-21 15:02:19 +02:00
|
|
|
}
|
|
|
|
|
2012-08-01 17:32:11 +02:00
|
|
|
void ShrinkAdd(Projectile *p, int t) {
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
2012-07-24 20:44:58 +02:00
|
|
|
Shrink(p, t);
|
2012-08-01 17:32:11 +02:00
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
}
|
|
|
|
|
2011-05-21 15:02:19 +02:00
|
|
|
void DeathShrink(Projectile *p, int t) {
|
|
|
|
glPushMatrix();
|
|
|
|
float s = 2.0-t/p->args[0]*2;
|
|
|
|
glTranslatef(creal(p->pos), cimag(p->pos), 0);
|
2011-06-24 19:16:05 +02:00
|
|
|
glRotatef(p->angle*180/M_PI+90, 0, 0, 1);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-04-05 14:24:55 +02:00
|
|
|
if(s != 1)
|
|
|
|
glScalef(s, 1, 1);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-21 15:02:19 +02:00
|
|
|
_ProjDraw(p, t);
|
|
|
|
glPopMatrix();
|
2011-05-13 19:03:02 +02:00
|
|
|
}
|
|
|
|
|
2012-07-30 17:57:38 +02:00
|
|
|
void GrowFadeAdd(Projectile *p, int t) {
|
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
|
|
|
GrowFade(p, t);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
}
|
|
|
|
|
2011-06-28 19:23:02 +02:00
|
|
|
void GrowFade(Projectile *p, int t) {
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(creal(p->pos), cimag(p->pos), 0);
|
|
|
|
glRotatef(p->angle*180/M_PI+90, 0, 0, 1);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-08-18 01:49:59 +02:00
|
|
|
float s = t/p->args[0]*(1 + (creal(p->args[2])? p->args[2] : p->args[1]));
|
2012-04-05 14:24:55 +02:00
|
|
|
if(s != 1)
|
|
|
|
glScalef(s, s, 1);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-06-28 19:23:02 +02:00
|
|
|
if(p->clr)
|
2017-02-26 21:59:51 +01:00
|
|
|
parse_color_call(derive_color(p->clr, CLRMASK_A, rgba(0,0,0,1-t/p->args[0])), glColor4f);
|
2012-04-05 14:24:55 +02:00
|
|
|
else if(t/p->args[0] != 0)
|
2011-06-28 19:23:02 +02:00
|
|
|
glColor4f(1,1,1,1-t/p->args[0]);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-06-28 19:23:02 +02:00
|
|
|
draw_texture_p(0,0,p->tex);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-06-28 19:23:02 +02:00
|
|
|
glColor4f(1,1,1,1);
|
|
|
|
glPopMatrix();
|
2017-02-10 23:05:22 +01:00
|
|
|
}
|
2011-06-28 19:23:02 +02:00
|
|
|
|
2011-05-13 19:03:02 +02:00
|
|
|
void Fade(Projectile *p, int t) {
|
2012-04-05 14:24:55 +02:00
|
|
|
if(t/creal(p->args[0]) != 0)
|
|
|
|
glColor4f(1,1,1, 1.0 - (float)t/p->args[0]);
|
2011-05-21 15:02:19 +02:00
|
|
|
ProjDraw(p, t);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-04-05 14:24:55 +02:00
|
|
|
if(t/creal(p->args[0]) != 0)
|
|
|
|
glColor4f(1,1,1,1);
|
2011-05-13 19:03:02 +02:00
|
|
|
}
|
|
|
|
|
2012-08-01 17:32:11 +02:00
|
|
|
void FadeAdd(Projectile *p, int t) {
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2017-02-26 21:59:51 +01:00
|
|
|
parse_color_call(derive_color(p->clr, CLRMASK_A, rgba(0,0,0, 1.0 - (float)t/p->args[0])), glColor4f);
|
2012-08-01 17:32:11 +02:00
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(creal(p->pos), cimag(p->pos), 0);
|
|
|
|
glRotatef(180/M_PI*p->angle+90, 0, 0, 1);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-08-01 17:32:11 +02:00
|
|
|
draw_texture_p(0,0, p->tex);
|
|
|
|
glPopMatrix();
|
|
|
|
glColor4f(1,1,1,1);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2012-08-01 17:32:11 +02:00
|
|
|
}
|
|
|
|
|
2011-05-13 19:03:02 +02:00
|
|
|
int timeout(Projectile *p, int t) {
|
|
|
|
if(t >= creal(p->args[0]))
|
|
|
|
return ACTION_DESTROY;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-13 19:03:02 +02:00
|
|
|
return 1;
|
2011-05-21 15:02:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int timeout_linear(Projectile *p, int t) {
|
|
|
|
if(t >= creal(p->args[0]))
|
|
|
|
return ACTION_DESTROY;
|
2011-07-07 14:34:30 +02:00
|
|
|
if(t < 0)
|
|
|
|
return 1;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-05-21 15:02:19 +02:00
|
|
|
p->angle = carg(p->args[1]);
|
|
|
|
p->pos = p->pos0 + p->args[1]*t;
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-06-26 16:10:13 +02:00
|
|
|
return 1;
|
2011-08-28 10:57:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Petal(Projectile *p, int t) {
|
|
|
|
float x = creal(p->args[2]);
|
|
|
|
float y = cimag(p->args[2]);
|
|
|
|
float z = creal(p->args[3]);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2017-03-24 14:53:57 +01:00
|
|
|
float r = sqrt(x*x+y*y+z*z);
|
|
|
|
x /= r; y /= r; z /= r;
|
|
|
|
|
2011-08-28 10:57:45 +02:00
|
|
|
glDisable(GL_CULL_FACE);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-08-28 10:57:45 +02:00
|
|
|
glPushMatrix();
|
2012-04-05 14:24:55 +02:00
|
|
|
if(p->pos)
|
|
|
|
glTranslatef(creal(p->pos), cimag(p->pos),0);
|
2011-08-28 10:57:45 +02:00
|
|
|
glRotatef(t*4.0 + cimag(p->args[3]), x, y, z);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2017-02-26 21:59:51 +01:00
|
|
|
if(p->clr) {
|
|
|
|
parse_color_call(p->clr, glColor4f);
|
|
|
|
}
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2012-04-04 17:19:53 +02:00
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
2011-08-28 10:57:45 +02:00
|
|
|
draw_texture_p(0,0, p->tex);
|
2012-04-04 17:19:53 +02:00
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-08-28 10:57:45 +02:00
|
|
|
if(p->clr)
|
|
|
|
glColor4f(1,1,1,1);
|
|
|
|
glPopMatrix();
|
2017-02-10 23:05:22 +01:00
|
|
|
|
2011-08-28 10:57:45 +02:00
|
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void petal_explosion(int n, complex pos) {
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < n; i++) {
|
2017-03-24 14:53:57 +01:00
|
|
|
tsrand_fill(6);
|
|
|
|
float t = frand();
|
|
|
|
Color c = rgba(sin(5*t),cos(5*t),0.5,t);
|
|
|
|
create_particle4c("petal", pos, c, Petal, asymptotic, (3+5*afrand(2))*cexp(I*M_PI*2*afrand(3)), 5, afrand(4) + afrand(5)*I, afrand(1) + 360.0*I*afrand(0));
|
2011-08-28 10:57:45 +02:00
|
|
|
}
|
2012-07-18 12:33:37 +02:00
|
|
|
}
|
2017-03-11 04:41:57 +01:00
|
|
|
|
|
|
|
void projectiles_preload(void) {
|
|
|
|
preload_resources(RES_TEXTURE, RESF_PERMANENT,
|
2017-03-20 07:38:07 +01:00
|
|
|
// XXX: maybe split this up into stage-specific preloads too?
|
|
|
|
// some of these are ubiquitous, but some only appear in very specific parts.
|
|
|
|
|
2017-03-11 04:41:57 +01:00
|
|
|
"part/blast",
|
|
|
|
"part/boss_shadow",
|
|
|
|
"part/flare",
|
|
|
|
"part/lasercurve",
|
|
|
|
"part/marilaser_part0",
|
|
|
|
"part/maristar_orbit",
|
|
|
|
"part/petal",
|
|
|
|
"part/smoke",
|
|
|
|
"part/stain",
|
|
|
|
"part/youmu_slice",
|
2017-03-20 07:38:07 +01:00
|
|
|
"part/lightning0",
|
|
|
|
"part/lightning1",
|
|
|
|
"part/lightningball",
|
2017-03-11 04:41:57 +01:00
|
|
|
"proj/ball",
|
|
|
|
"proj/bigball",
|
|
|
|
"proj/bullet",
|
|
|
|
"proj/card",
|
|
|
|
"proj/crystal",
|
|
|
|
"proj/flea",
|
|
|
|
"proj/hghost",
|
|
|
|
"proj/marilaser",
|
|
|
|
"proj/marisa",
|
|
|
|
"proj/maristar",
|
|
|
|
"proj/plainball",
|
|
|
|
"proj/rice",
|
|
|
|
"proj/soul",
|
|
|
|
"proj/thickrice",
|
|
|
|
"proj/wave",
|
|
|
|
"proj/youhoming",
|
|
|
|
"proj/youmu",
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
preload_resources(RES_SHADER, RESF_PERMANENT,
|
|
|
|
"bullet_color",
|
|
|
|
NULL);
|
|
|
|
}
|