2011-04-26 12:04:45 +02:00
|
|
|
/*
|
2019-08-03 19:43:48 +02:00
|
|
|
* This software is licensed under the terms of the MIT License.
|
2017-02-11 04:52:08 +01:00
|
|
|
* See COPYING for further information.
|
2011-04-26 12:04:45 +02:00
|
|
|
* ---
|
2019-01-23 21:10:43 +01:00
|
|
|
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
|
2019-07-03 20:00:56 +02:00
|
|
|
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
|
2011-04-26 12:04:45 +02:00
|
|
|
*/
|
|
|
|
|
2019-01-23 21:10:43 +01:00
|
|
|
#ifndef IGUARD_enemy_h
|
|
|
|
#define IGUARD_enemy_h
|
|
|
|
|
2017-11-25 20:45:11 +01:00
|
|
|
#include "taisei.h"
|
2011-05-08 13:48:25 +02:00
|
|
|
|
2017-03-06 01:25:59 +01:00
|
|
|
#include "util.h"
|
|
|
|
#include "projectile.h"
|
2017-12-13 20:05:12 +01:00
|
|
|
#include "objectpool.h"
|
2018-04-13 21:13:48 +02:00
|
|
|
#include "entity.h"
|
2019-07-17 04:04:49 +02:00
|
|
|
#include "coroutine.h"
|
2019-07-27 22:14:48 +02:00
|
|
|
#include "move.h"
|
2011-04-26 12:04:45 +02:00
|
|
|
|
2017-11-15 07:05:47 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
#define ENEMY_DEBUG
|
|
|
|
#endif
|
|
|
|
|
2020-04-17 09:18:53 +02:00
|
|
|
#ifdef ENEMY_DEBUG
|
|
|
|
#define IF_ENEMY_DEBUG(...) __VA_ARGS__
|
|
|
|
#else
|
|
|
|
#define IF_ENEMY_DEBUG(...)
|
|
|
|
#endif
|
|
|
|
|
2018-06-01 20:40:18 +02:00
|
|
|
typedef LIST_ANCHOR(Enemy) EnemyList;
|
2020-04-17 09:18:53 +02:00
|
|
|
typedef int (*EnemyLogicRule)(Enemy*, int t);
|
|
|
|
typedef void (*EnemyVisualRule)(Enemy*, int t, bool render);
|
2011-04-26 12:04:45 +02:00
|
|
|
|
2020-07-09 14:07:40 +02:00
|
|
|
typedef enum EnemyFlag {
|
|
|
|
EFLAG_KILLED = (1 << 0), // is dead, pending removal (internal)
|
|
|
|
EFLAG_NO_HIT = (1 << 1), // can't be hit by player
|
|
|
|
EFLAG_NO_HURT = (1 << 2), // can't hurt player
|
|
|
|
EFLAG_NO_AUTOKILL = (1 << 3), // no autokill when out of bounds
|
|
|
|
EFLAG_NO_VISUAL_CORRECTION = (1 << 4), // disable the slide-in hack for enemies spawning at screen edges
|
|
|
|
EFLAG_NO_DEATH_EXPLOSION = (1 << 5), // don't explode on death; currently also disables bonus voltage on kill
|
|
|
|
EFLAG_INVULNERABLE = (1 << 6), // can't be damaged by player (but can be hit)
|
|
|
|
EFLAG_IMPENETRABLE = (1 << 7), // penetrating shots can't pass through (e.g. Marisa's laser)
|
|
|
|
|
|
|
|
EFLAGS_GHOST =
|
|
|
|
EFLAG_NO_HIT |
|
|
|
|
EFLAG_NO_HURT |
|
|
|
|
EFLAG_NO_AUTOKILL |
|
|
|
|
EFLAG_NO_VISUAL_CORRECTION |
|
|
|
|
EFLAG_NO_DEATH_EXPLOSION |
|
|
|
|
EFLAG_INVULNERABLE |
|
|
|
|
0,
|
|
|
|
} EnemyFlag;
|
|
|
|
|
2011-04-26 12:04:45 +02:00
|
|
|
enum {
|
2020-07-09 14:07:40 +02:00
|
|
|
_internal_ENEMY_IMMUNE = -9000,
|
|
|
|
ENEMY_IMMUNE attr_deprecated("Set enemy flags explicitly") = _internal_ENEMY_IMMUNE,
|
|
|
|
// ENEMY_KILLED = -9002,
|
2011-04-26 12:04:45 +02:00
|
|
|
};
|
|
|
|
|
2020-04-17 09:18:53 +02:00
|
|
|
DEFINE_ENTITY_TYPE(Enemy, {
|
2019-11-22 04:37:11 +01:00
|
|
|
cmplx pos;
|
|
|
|
cmplx pos0;
|
|
|
|
cmplx pos0_visual;
|
2019-07-27 22:14:48 +02:00
|
|
|
|
|
|
|
union {
|
|
|
|
cmplx args[RULE_ARGC];
|
|
|
|
MoveParams move;
|
|
|
|
};
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2011-04-26 12:04:45 +02:00
|
|
|
EnemyLogicRule logic_rule;
|
2017-11-15 07:05:47 +01:00
|
|
|
EnemyVisualRule visual_rule;
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2019-07-17 04:04:49 +02:00
|
|
|
struct {
|
|
|
|
CoEvent killed;
|
|
|
|
} events;
|
|
|
|
|
2020-07-09 14:07:40 +02:00
|
|
|
EnemyFlag flags;
|
|
|
|
|
2019-07-17 04:04:49 +02:00
|
|
|
int birthtime;
|
|
|
|
int dir;
|
|
|
|
|
2018-07-30 09:04:09 +02:00
|
|
|
float spawn_hp;
|
|
|
|
float hp;
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2012-07-18 12:33:37 +02:00
|
|
|
float alpha;
|
2017-11-15 07:05:47 +01:00
|
|
|
|
2020-07-09 14:07:40 +02:00
|
|
|
float hit_radius;
|
|
|
|
float hurt_radius;
|
|
|
|
|
2019-07-17 04:04:49 +02:00
|
|
|
bool moving;
|
|
|
|
|
2020-04-17 09:18:53 +02:00
|
|
|
IF_ENEMY_DEBUG(
|
|
|
|
DebugInfo debug;
|
|
|
|
)
|
|
|
|
});
|
2011-04-26 12:04:45 +02:00
|
|
|
|
2011-06-26 13:45:27 +02:00
|
|
|
#define create_enemy4c(p,h,d,l,a1,a2,a3,a4) create_enemy_p(&global.enemies,p,h,d,l,a1,a2,a3,a4)
|
|
|
|
#define create_enemy3c(p,h,d,l,a1,a2,a3) create_enemy_p(&global.enemies,p,h,d,l,a1,a2,a3,0)
|
|
|
|
#define create_enemy2c(p,h,d,l,a1,a2) create_enemy_p(&global.enemies,p,h,d,l,a1,a2,0,0)
|
|
|
|
#define create_enemy1c(p,h,d,l,a1) create_enemy_p(&global.enemies,p,h,d,l,a1,0,0,0)
|
|
|
|
|
2018-01-12 19:26:07 +01:00
|
|
|
Enemy *create_enemy_p(
|
2019-11-22 04:37:11 +01:00
|
|
|
EnemyList *enemies, cmplx pos, float hp, EnemyVisualRule draw_rule, EnemyLogicRule logic_rule,
|
|
|
|
cmplx a1, cmplx a2, cmplx a3, cmplx a4
|
2018-01-12 19:26:07 +01:00
|
|
|
);
|
|
|
|
|
2017-11-15 07:05:47 +01:00
|
|
|
#ifdef ENEMY_DEBUG
|
|
|
|
Enemy* _enemy_attach_dbginfo(Enemy *p, DebugInfo *dbg);
|
|
|
|
#define create_enemy_p(...) _enemy_attach_dbginfo(create_enemy_p(__VA_ARGS__), _DEBUG_INFO_PTR_)
|
|
|
|
#endif
|
|
|
|
|
2018-06-01 20:40:18 +02:00
|
|
|
void delete_enemy(EnemyList *enemies, Enemy* enemy);
|
|
|
|
void delete_enemies(EnemyList *enemies);
|
2011-04-26 12:04:45 +02:00
|
|
|
|
2018-06-01 20:40:18 +02:00
|
|
|
void process_enemies(EnemyList *enemies);
|
2011-04-26 12:04:45 +02:00
|
|
|
|
2018-06-01 22:56:02 +02:00
|
|
|
bool enemy_is_vulnerable(Enemy *enemy);
|
2020-07-09 14:07:40 +02:00
|
|
|
bool enemy_is_targetable(Enemy *enemy);
|
2018-06-01 22:56:02 +02:00
|
|
|
bool enemy_in_viewport(Enemy *enemy);
|
2020-07-09 14:07:40 +02:00
|
|
|
float enemy_get_hurt_radius(Enemy *enemy);
|
|
|
|
|
2020-03-13 21:54:07 +01:00
|
|
|
void enemy_kill(Enemy *enemy);
|
2018-06-01 22:56:02 +02:00
|
|
|
void enemy_kill_all(EnemyList *enemies);
|
2012-07-19 19:48:17 +02:00
|
|
|
|
2017-11-15 07:05:47 +01:00
|
|
|
void Fairy(Enemy*, int t, bool render);
|
|
|
|
void Swirl(Enemy*, int t, bool render);
|
|
|
|
void BigFairy(Enemy*, int t, bool render);
|
2012-04-04 17:19:53 +02:00
|
|
|
|
|
|
|
int enemy_flare(Projectile *p, int t);
|
|
|
|
|
2017-03-11 04:41:57 +01:00
|
|
|
void enemies_preload(void);
|
2019-01-23 21:10:43 +01:00
|
|
|
|
|
|
|
#endif // IGUARD_enemy_h
|