PCBrawl/src/attack.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;
}