281 lines
7.5 KiB
C
281 lines
7.5 KiB
C
#include "attack.h"
|
|
#include "bullet.h"
|
|
#include "conf.h"
|
|
#include "level.h"
|
|
#include "lzy.h"
|
|
#include "particle.h"
|
|
#include "player.h"
|
|
#include "tools.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static struct Attack_table attack_table;
|
|
|
|
static void attack_table_free(void);
|
|
static void attack_update(struct Attack *attack);
|
|
static void attack_draw(struct Attack *attack, int timer);
|
|
static int attack_collide(struct Attack *attack, int x, int y, int w, int h,
|
|
int hitbox);
|
|
|
|
void attack_table_init(void) {
|
|
attack_table_free();
|
|
attack_table.attacks = malloc(MAX_ATTACKS * sizeof(struct Attack));
|
|
attack_table.n = 0;
|
|
|
|
for (int i = 0; i < MAX_ATTACKS; ++i) {
|
|
attack_table.attacks[i].active = 0;
|
|
}
|
|
}
|
|
|
|
void attack_table_free(void) {
|
|
if (attack_table.attacks != NULL) {
|
|
attack_table.attacks = NULL;
|
|
}
|
|
};
|
|
|
|
int attack(int x, int y, int dir_x, int dir_y, int type) {
|
|
int cooldown = 5;
|
|
for (int i = 0; i < MAX_ATTACKS; ++i) {
|
|
if (!attack_table.attacks[i].active) {
|
|
struct Attack *att = &attack_table.attacks[i];
|
|
*att = (struct Attack){
|
|
.pos = (struct Vec2){.x = x, .y = y},
|
|
.type = type,
|
|
.active = 1,
|
|
.ice = 0,
|
|
.dam = 0,
|
|
};
|
|
switch (type) {
|
|
case 1:
|
|
att->w = 5;
|
|
att->h = 5;
|
|
att->life = 2;
|
|
att->dir = (struct FVec2){.x = dir_x * 2, .y = dir_y * 0.5};
|
|
att->dam = 2;
|
|
cooldown = 10;
|
|
particle_new(att->pos.x, att->pos.y, dir_x > 0 ? 7 : 8, att->life);
|
|
break;
|
|
case 2:
|
|
att->w = 10;
|
|
att->h = 10;
|
|
att->life = 2;
|
|
att->dam = 4;
|
|
att->dir = (struct FVec2){.x = 0, .y = -2};
|
|
cooldown = 15;
|
|
particle_new(att->pos.x, att->pos.y, 9, att->life);
|
|
break;
|
|
case 3:
|
|
att->w = 10;
|
|
att->h = 5;
|
|
att->life = 2;
|
|
att->dam = 3;
|
|
att->dir = (struct FVec2){.x = 0, .y = 1.5};
|
|
cooldown = 10;
|
|
particle_new(att->pos.x, att->pos.y, 4, att->life);
|
|
break;
|
|
case 4:
|
|
att->w = 16;
|
|
att->h = 16;
|
|
att->life = 3;
|
|
att->dam = 1;
|
|
att->dir = (struct FVec2){.x = dir_x * 0.5, .y = 0.5};
|
|
cooldown = 60;
|
|
att->ice = 1;
|
|
break;
|
|
case 5:
|
|
att->pos.x -= dir_x * 2;
|
|
att->pos.y += 3;
|
|
att->w = 5;
|
|
att->h = 8;
|
|
att->life = 2;
|
|
att->dam = 2;
|
|
att->dir = (struct FVec2){.x = dir_x * 1.5, .y = dir_y * 0.5};
|
|
cooldown = 10;
|
|
particle_new(att->pos.x, att->pos.y + 4, dir_x > 0 ? 7 : 8, att->life);
|
|
break;
|
|
case 6:
|
|
att->w = 6;
|
|
att->pos.x -= att->w / 2;
|
|
att->h = 2;
|
|
att->life = 80;
|
|
att->dam = 5;
|
|
att->dir = (struct FVec2){.x = 0, .y = -0.5};
|
|
cooldown = 20;
|
|
bullet_fire(att->pos.x, att->pos.y, 0, 1, 8);
|
|
particle_new(att->pos.x, att->pos.y, 9, 2);
|
|
break;
|
|
case 7:
|
|
att->w = 13;
|
|
att->h = 4;
|
|
att->life = 2;
|
|
att->dam = 4;
|
|
att->dir = (struct FVec2){.x = 0, .y = 1.5};
|
|
cooldown = 10;
|
|
particle_new(att->pos.x, att->pos.y, 3, att->life);
|
|
break;
|
|
case 8:
|
|
att->w = 8;
|
|
att->h = 8;
|
|
att->life = 2;
|
|
att->dam = 2;
|
|
att->dir = (struct FVec2){.x = dir_x * 0.25, .y = 1};
|
|
cooldown = 10;
|
|
break;
|
|
case 9:
|
|
att->pos.x += dir_x * 4;
|
|
att->w = 8;
|
|
att->h = 12;
|
|
att->life = 2;
|
|
att->dam = 3;
|
|
att->dir = (struct FVec2){.x = dir_x * 2.5, .y = dir_y * 1};
|
|
cooldown = 10;
|
|
particle_new(att->pos.x - dir_x * 4, att->pos.y, dir_x > 0 ? 7 : 8,
|
|
att->life);
|
|
break;
|
|
case 10:
|
|
att->pos.y += 2;
|
|
att->w = 12;
|
|
att->h = 6;
|
|
att->life = 2;
|
|
att->dam = 5;
|
|
att->dir = (struct FVec2){.x = 0, .y = -4};
|
|
cooldown = 15;
|
|
particle_new(att->pos.x, att->pos.y, 9, att->life);
|
|
break;
|
|
case 11:
|
|
att->w = 10;
|
|
att->h = 5;
|
|
att->life = 2;
|
|
att->dam = 5;
|
|
att->dir = (struct FVec2){.x = 0, .y = 1.5};
|
|
cooldown = 10;
|
|
particle_new(att->pos.x, att->pos.y, 4, att->life);
|
|
break;
|
|
case 12:
|
|
att->w = 18;
|
|
att->h = 18;
|
|
att->life = 1;
|
|
att->dam = 6;
|
|
att->dir = (struct FVec2){.x = dir_x * 2, .y = 1.5};
|
|
particle_new(att->pos.x, att->pos.y, 0, 2);
|
|
particle_new(att->pos.x + dir_x * 8, att->pos.y - 8, 0, 4);
|
|
particle_new(att->pos.x + dir_x * 16, att->pos.y - 16, 0, 8);
|
|
cooldown = 30;
|
|
break;
|
|
case 13:
|
|
att->w = 5;
|
|
att->h = 5;
|
|
att->life = 2;
|
|
att->dam = 2;
|
|
att->dir = (struct FVec2){.x = dir_x * 2, .y = dir_y * 0.5};
|
|
cooldown = 10;
|
|
particle_new(att->pos.x, att->pos.y, dir_x > 0 ? 7 : 8, att->life);
|
|
break;
|
|
case 14:
|
|
att->w = 10;
|
|
att->h = 10;
|
|
att->life = 2;
|
|
att->dir = (struct FVec2){.x = 0, .y = -2};
|
|
cooldown = 15;
|
|
att->dam = 3;
|
|
particle_new(att->pos.x, att->pos.y, 9, att->life);
|
|
break;
|
|
case 15:
|
|
att->w = 10;
|
|
att->h = 5;
|
|
att->life = 2;
|
|
att->dir = (struct FVec2){.x = 0, .y = 1.5};
|
|
cooldown = 10;
|
|
att->dam = 3;
|
|
particle_new(att->pos.x, att->pos.y, 4, att->life);
|
|
break;
|
|
case 16:
|
|
att->w = 16;
|
|
att->h = 16;
|
|
att->life = 60;
|
|
att->dir = (struct FVec2){.x = 0, .y = 0};
|
|
cooldown = 120;
|
|
att->dam = 1;
|
|
particle_new(att->pos.x, att->pos.y, 6, att->life);
|
|
break;
|
|
default:
|
|
att->w = 0;
|
|
att->h = 0;
|
|
att->life = 0;
|
|
att->dir = (struct FVec2){.x = dir_x, .y = 0};
|
|
cooldown = 0;
|
|
break;
|
|
}
|
|
attack_table.attacks[i].pos.x -= attack_table.attacks[i].w / 2;
|
|
attack_table.attacks[i].pos.y -= attack_table.attacks[i].h / 2;
|
|
break;
|
|
}
|
|
}
|
|
++attack_table.n;
|
|
return cooldown;
|
|
}
|
|
|
|
void attack_table_update(void) {
|
|
for (int i = 0; i < MAX_ATTACKS; ++i) {
|
|
if (attack_table.attacks[i].active) {
|
|
attack_update(&attack_table.attacks[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void attack_update(struct Attack *attack) {
|
|
if (attack->type == 6) {
|
|
attack->pos.y += 8;
|
|
}
|
|
|
|
--attack->life;
|
|
if (attack->life < 0) {
|
|
player_reset_attack();
|
|
attack_destroy(attack);
|
|
}
|
|
}
|
|
|
|
void attack_table_draw(int timer) {
|
|
for (int i = 0; i < MAX_ATTACKS; ++i) {
|
|
if (attack_table.attacks[i].active) {
|
|
attack_draw(&attack_table.attacks[i], timer);
|
|
}
|
|
}
|
|
}
|
|
|
|
void attack_draw(struct Attack *attack, int timer) {}
|
|
|
|
void attack_destroy(struct Attack *attack) {
|
|
attack->active = 0;
|
|
--attack_table.n;
|
|
}
|
|
|
|
int attack_nb(void) { return attack_table.n; }
|
|
|
|
struct Attack *attack_table_collide(int x, int y, int w, int h, int hitbox) {
|
|
for (int i = 0; i < MAX_ATTACKS; ++i) {
|
|
if (attack_table.attacks[i].active) {
|
|
if (attack_collide(&attack_table.attacks[i], x, y, w, h, hitbox)) {
|
|
return &attack_table.attacks[i];
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int attack_collide(struct Attack *attack, int x, int y, int w, int h,
|
|
int hitbox) {
|
|
if ((attack->pos.x + hitbox < x + w &&
|
|
attack->pos.x + attack->w - hitbox > x &&
|
|
attack->pos.y + hitbox < y + h &&
|
|
attack->pos.y + attack->h - hitbox > y) ||
|
|
(attack->pos.x + hitbox > x &&
|
|
attack->pos.x + attack->w - hitbox < x + w &&
|
|
attack->pos.y + hitbox > y &&
|
|
attack->pos.y + attack->h - hitbox < y + h)) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|