player property system; adjust character speeds and PoC
This commit is contained in:
parent
f67396423e
commit
45da133768
13 changed files with 142 additions and 72 deletions
|
@ -61,10 +61,10 @@ enum {
|
|||
VIEWPORT_W = 480,
|
||||
VIEWPORT_H = 560,
|
||||
|
||||
POINT_OF_COLLECT = VIEWPORT_H/4,
|
||||
DEATHBOMB_TIME = 12,
|
||||
// POINT_OF_COLLECT = VIEWPORT_H/4,
|
||||
// DEATHBOMB_TIME = 12,
|
||||
DEATH_DELAY = 70,
|
||||
BOMB_RECOVERY = 300,
|
||||
// BOMB_RECOVERY = 300,
|
||||
|
||||
MAX_CONTINUES = 3,
|
||||
|
||||
|
|
10
src/item.c
10
src/item.c
|
@ -125,11 +125,7 @@ void move_item(Item *i) {
|
|||
|
||||
void process_items(void) {
|
||||
Item *item = global.items, *del = NULL;
|
||||
int v;
|
||||
|
||||
float r = 30;
|
||||
if(global.plr.inputflags & INFLAG_FOCUS)
|
||||
r *= 2;
|
||||
float r = player_property(&global.plr, PLR_PROP_COLLECT_RADIUS);
|
||||
|
||||
while(item != NULL) {
|
||||
if((item->type == Power && global.plr.power >= PLR_MAX_POWER) ||
|
||||
|
@ -144,7 +140,7 @@ void process_items(void) {
|
|||
} else {
|
||||
bool plr_alive = global.plr.deathtime <= global.frames && global.plr.deathtime == -1;
|
||||
|
||||
if((cimag(global.plr.pos) < POINT_OF_COLLECT && plr_alive)
|
||||
if((cimag(global.plr.pos) < player_property(&global.plr, PLR_PROP_POC) && plr_alive)
|
||||
|| global.frames - global.plr.recovery < 0)
|
||||
item->auto_collect = 1;
|
||||
|
||||
|
@ -158,7 +154,7 @@ void process_items(void) {
|
|||
|
||||
move_item(item);
|
||||
|
||||
v = collision_item(item);
|
||||
int v = collision_item(item);
|
||||
if(v == 1) {
|
||||
switch(item->type) {
|
||||
case Power:
|
||||
|
|
41
src/player.c
41
src/player.c
|
@ -36,6 +36,10 @@ void player_stage_pre_init(Player *plr) {
|
|||
plrmode_preload(plr->mode);
|
||||
}
|
||||
|
||||
double player_property(Player *plr, PlrProperty prop) {
|
||||
return plr->mode->procs.property(plr, prop);
|
||||
}
|
||||
|
||||
static void ent_draw_player(EntityInterface *ent);
|
||||
static Enemy* player_spawn_focus_circle(void);
|
||||
|
||||
|
@ -45,6 +49,7 @@ void player_stage_post_init(Player *plr) {
|
|||
// ensure the essential callbacks are there. other code tests only for the optional ones
|
||||
assert(plr->mode->procs.shot != NULL);
|
||||
assert(plr->mode->procs.bomb != NULL);
|
||||
assert(plr->mode->procs.property != NULL);
|
||||
|
||||
delete_enemies(&global.plr.slaves);
|
||||
|
||||
|
@ -98,17 +103,7 @@ bool player_set_power(Player *plr, short npow) {
|
|||
}
|
||||
|
||||
void player_move(Player *plr, complex delta) {
|
||||
float speed = 0.01*VIEWPORT_W;
|
||||
|
||||
if(plr->inputflags & INFLAG_FOCUS) {
|
||||
speed /= 2.0;
|
||||
}
|
||||
|
||||
if(plr->mode->procs.speed_mod) {
|
||||
speed = plr->mode->procs.speed_mod(plr, speed);
|
||||
}
|
||||
|
||||
delta *= speed;
|
||||
delta *= player_property(plr, PLR_PROP_SPEED);
|
||||
complex lastpos = plr->pos;
|
||||
double x = clamp(creal(plr->pos) + creal(delta), PLR_MIN_BORDER_DIST, VIEWPORT_W - PLR_MIN_BORDER_DIST);
|
||||
double y = clamp(cimag(plr->pos) + cimag(delta), PLR_MIN_BORDER_DIST, VIEWPORT_H - PLR_MIN_BORDER_DIST);
|
||||
|
@ -279,6 +274,12 @@ bool player_bomb(Player *plr) {
|
|||
if(global.boss && global.boss->current && global.boss->current->type == AT_ExtraSpell)
|
||||
return false;
|
||||
|
||||
int bomb_time = floor(player_property(plr, PLR_PROP_BOMB_TIME));
|
||||
|
||||
if(bomb_time <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(global.frames - plr->recovery >= 0 && (plr->bombs > 0 || plr->iddqd) && global.frames - plr->respawntime >= 60) {
|
||||
player_fail_spell(plr);
|
||||
stage_clear_hazards(CLEAR_HAZARDS_ALL);
|
||||
|
@ -288,15 +289,17 @@ bool player_bomb(Player *plr) {
|
|||
if(plr->deathtime > 0) {
|
||||
plr->deathtime = -1;
|
||||
|
||||
if(plr->bombs)
|
||||
if(plr->bombs) {
|
||||
plr->bombs--;
|
||||
}
|
||||
}
|
||||
|
||||
if(plr->bombs < 0) {
|
||||
plr->bombs = 0;
|
||||
}
|
||||
|
||||
plr->recovery = global.frames + BOMB_RECOVERY;
|
||||
plr->bombtotaltime = bomb_time;
|
||||
plr->recovery = global.frames + plr->bombtotaltime;
|
||||
plr->bombcanceltime = 0;
|
||||
plr->bombcanceldelay = 0;
|
||||
|
||||
|
@ -334,7 +337,7 @@ double player_get_bomb_progress(Player *plr, double *out_speed) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int start_time = plr->recovery - BOMB_RECOVERY;
|
||||
int start_time = plr->recovery - plr->bombtotaltime;
|
||||
int end_time = plr->recovery;
|
||||
|
||||
if(!plr->bombcanceltime || plr->bombcanceltime + plr->bombcanceldelay >= end_time) {
|
||||
|
@ -342,21 +345,21 @@ double player_get_bomb_progress(Player *plr, double *out_speed) {
|
|||
*out_speed = 1.0;
|
||||
}
|
||||
|
||||
return (BOMB_RECOVERY - (end_time - global.frames))/(double)BOMB_RECOVERY;
|
||||
return (plr->bombtotaltime - (end_time - global.frames))/(double)plr->bombtotaltime;
|
||||
}
|
||||
|
||||
int cancel_time = plr->bombcanceltime + plr->bombcanceldelay;
|
||||
int passed_time = plr->bombcanceltime - start_time;
|
||||
|
||||
int shortened_total_time = (BOMB_RECOVERY - passed_time) - (end_time - cancel_time);
|
||||
int shortened_total_time = (plr->bombtotaltime - passed_time) - (end_time - cancel_time);
|
||||
int shortened_passed_time = (global.frames - plr->bombcanceltime);
|
||||
|
||||
double passed_fraction = passed_time / (double)BOMB_RECOVERY;
|
||||
double passed_fraction = passed_time / (double)plr->bombtotaltime;
|
||||
double shortened_fraction = shortened_passed_time / (double)shortened_total_time;
|
||||
shortened_fraction *= (1 - passed_fraction);
|
||||
|
||||
if(out_speed != NULL) {
|
||||
*out_speed = (BOMB_RECOVERY - passed_time) / (double)shortened_total_time;
|
||||
*out_speed = (plr->bombtotaltime - passed_time) / (double)shortened_total_time;
|
||||
}
|
||||
|
||||
return passed_fraction + shortened_fraction;
|
||||
|
@ -423,7 +426,7 @@ void player_death(Player *plr) {
|
|||
.flags = PFLAG_NOREFLECT | PFLAG_REQUIREDPARTICLE,
|
||||
);
|
||||
|
||||
plr->deathtime = global.frames + DEATHBOMB_TIME;
|
||||
plr->deathtime = global.frames + floor(player_property(plr, PLR_PROP_DEATHBOMB_WINDOW));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ struct Player {
|
|||
int respawntime;
|
||||
int bombcanceltime;
|
||||
int bombcanceldelay;
|
||||
int bombtotaltime;
|
||||
|
||||
struct PlayerMode *mode;
|
||||
AniPlayer ani;
|
||||
|
|
|
@ -28,15 +28,27 @@ typedef enum {
|
|||
typedef enum {
|
||||
/* do not reorder - screws replays */
|
||||
|
||||
PLR_SHOT_MARISA_LASER = 0,
|
||||
PLR_SHOT_MARISA_STAR = 1,
|
||||
|
||||
PLR_SHOT_YOUMU_MIRROR = 0,
|
||||
PLR_SHOT_YOUMU_HAUNTING = 1,
|
||||
|
||||
PLR_SHOT_A,
|
||||
PLR_SHOT_B,
|
||||
NUM_SHOT_MODES_PER_CHARACTER,
|
||||
|
||||
PLR_SHOT_MARISA_LASER = PLR_SHOT_A,
|
||||
PLR_SHOT_MARISA_STAR = PLR_SHOT_B,
|
||||
|
||||
PLR_SHOT_YOUMU_MIRROR = PLR_SHOT_A,
|
||||
PLR_SHOT_YOUMU_HAUNTING = PLR_SHOT_B,
|
||||
} ShotModeID;
|
||||
|
||||
typedef enum {
|
||||
// vpu = viewport units
|
||||
|
||||
PLR_PROP_SPEED, // current player movement speed (vpu/frame)
|
||||
PLR_PROP_POC, // "point of collection" boundary: all items are auto-collected when player is above this (vpu)
|
||||
PLR_PROP_COLLECT_RADIUS, // how near the player has to be to an item before it's auto-collected (vpu)
|
||||
PLR_PROP_BOMB_TIME, // how long a bomb should last if it were to activate this frame; 0 prevents activation (frames)
|
||||
PLR_PROP_DEATHBOMB_WINDOW, // how much time the player has to recover with a bomb if they died in this frame (frames)
|
||||
} PlrProperty;
|
||||
|
||||
typedef void (*PlrCharEndingProc)(Ending *e);
|
||||
|
||||
typedef struct PlayerCharacter {
|
||||
|
@ -61,8 +73,8 @@ typedef void (*PlayerModeShotProc)(Player *plr);
|
|||
typedef void (*PlayerModeBombProc)(Player *plr);
|
||||
typedef void (*PlayerModeBombBgProc)(Player *plr);
|
||||
typedef void (*PlayerModePowerProc)(Player *plr, short npow);
|
||||
typedef double (*PlayerModeSpeedModProc)(Player *plr, double speed);
|
||||
typedef void (*PlayerModePreloadProc)(void);
|
||||
typedef double (*PlayerModePropertyProc)(Player *plr, PlrProperty prop);
|
||||
|
||||
typedef struct PlayerMode {
|
||||
const char *name;
|
||||
|
@ -78,8 +90,8 @@ typedef struct PlayerMode {
|
|||
ShaderRule bomb_shader;
|
||||
PlayerModeBombBgProc bombbg;
|
||||
PlayerModePowerProc power;
|
||||
PlayerModeSpeedModProc speed_mod;
|
||||
PlayerModePreloadProc preload;
|
||||
PlayerModePropertyProc property;
|
||||
} procs;
|
||||
} PlayerMode;
|
||||
|
||||
|
@ -94,3 +106,5 @@ PlayerMode* plrmode_find(CharacterID charid, ShotModeID shotid);
|
|||
int plrmode_repr(char *out, size_t outsize, PlayerMode *mode);
|
||||
PlayerMode* plrmode_parse(const char *name);
|
||||
void plrmode_preload(PlayerMode *mode);
|
||||
|
||||
double player_property(Player *plr, PlrProperty prop);
|
||||
|
|
|
@ -27,6 +27,27 @@ PlayerCharacter character_marisa = {
|
|||
},
|
||||
};
|
||||
|
||||
double marisa_common_property(Player *plr, PlrProperty prop) {
|
||||
switch(prop) {
|
||||
case PLR_PROP_BOMB_TIME:
|
||||
return 300;
|
||||
|
||||
case PLR_PROP_COLLECT_RADIUS:
|
||||
return (plr->inputflags & INFLAG_FOCUS) ? 60 : 30;
|
||||
|
||||
case PLR_PROP_SPEED:
|
||||
return (plr->inputflags & INFLAG_FOCUS) ? 2.2 : 5;
|
||||
|
||||
case PLR_PROP_POC:
|
||||
return VIEWPORT_H / 3.5;
|
||||
|
||||
case PLR_PROP_DEATHBOMB_WINDOW:
|
||||
return 12;
|
||||
}
|
||||
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
void marisa_common_shot(Player *plr, int dmg) {
|
||||
if(!(global.frames % 4)) {
|
||||
play_sound("generic_shot");
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
extern PlayerCharacter character_marisa;
|
||||
|
||||
double marisa_common_property(Player *plr, PlrProperty prop);
|
||||
void marisa_common_shot(Player *plr, int dmg);
|
||||
void marisa_common_slave_visual(Enemy *e, int t, bool render);
|
||||
void marisa_common_masterspark_draw(int t);
|
||||
|
|
|
@ -396,7 +396,7 @@ static void masterspark_visual(Enemy *e, int t2, bool render) {
|
|||
r_mat_push();
|
||||
r_mat_translate(creal(global.plr.pos),cimag(global.plr.pos)-40-VIEWPORT_H/2,0);
|
||||
r_mat_scale(fade*800,VIEWPORT_H,1);
|
||||
marisa_common_masterspark_draw(t*BOMB_RECOVERY);
|
||||
marisa_common_masterspark_draw(t*global.plr.bombtotaltime);
|
||||
r_mat_pop();
|
||||
}
|
||||
|
||||
|
@ -572,18 +572,27 @@ static void marisa_laser_think(Player *plr) {
|
|||
}
|
||||
}
|
||||
|
||||
static double marisa_laser_speed_mod(Player *plr, double speed) {
|
||||
if(global.frames - plr->recovery < 0) {
|
||||
speed /= 5.0;
|
||||
}
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
static void marisa_laser_shot(Player *plr) {
|
||||
marisa_common_shot(plr, 175 - 4 * (plr->power / 100));
|
||||
}
|
||||
|
||||
static double marisa_laser_property(Player *plr, PlrProperty prop) {
|
||||
switch(prop) {
|
||||
case PLR_PROP_SPEED: {
|
||||
double s = marisa_common_property(plr, prop);
|
||||
|
||||
if(global.frames - plr->recovery < 0) {
|
||||
s /= 5.0;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
default:
|
||||
return marisa_common_property(plr, prop);
|
||||
}
|
||||
}
|
||||
|
||||
static void marisa_laser_preload(void) {
|
||||
const int flags = RESF_DEFAULT;
|
||||
|
||||
|
@ -614,11 +623,11 @@ PlayerMode plrmode_marisa_a = {
|
|||
.character = &character_marisa,
|
||||
.shot_mode = PLR_SHOT_MARISA_LASER,
|
||||
.procs = {
|
||||
.property = marisa_laser_property,
|
||||
.bomb = marisa_laser_bomb,
|
||||
.bombbg = marisa_laser_bombbg,
|
||||
.shot = marisa_laser_shot,
|
||||
.power = marisa_laser_power,
|
||||
.speed_mod = marisa_laser_speed_mod,
|
||||
.preload = marisa_laser_preload,
|
||||
.init = marisa_laser_init,
|
||||
.think = marisa_laser_think,
|
||||
|
|
|
@ -207,7 +207,7 @@ static void marisa_star_orbit_visual(Enemy *e, int t, bool render) {
|
|||
|
||||
r_mat_scale(120*fade,VIEWPORT_H*1.5,1);
|
||||
r_mat_translate(0,-0.5,0);
|
||||
marisa_common_masterspark_draw(BOMB_RECOVERY*tb);
|
||||
marisa_common_masterspark_draw(global.plr.bombtotaltime*tb);
|
||||
|
||||
r_mat_pop();
|
||||
r_blend(BLEND_ADD);
|
||||
|
@ -230,14 +230,6 @@ static void marisa_star_bomb(Player *plr) {
|
|||
}
|
||||
}
|
||||
|
||||
static double marisa_star_speed_mod(Player *plr, double speed) {
|
||||
if(global.frames - plr->recovery < 0) {
|
||||
speed /= 5.0;
|
||||
}
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
static void marisa_star_bombbg(Player *plr) {
|
||||
float t = player_get_bomb_progress(&global.plr, NULL);
|
||||
float fade = 1;
|
||||
|
@ -310,6 +302,23 @@ static void marisa_star_shot(Player *plr) {
|
|||
marisa_common_shot(plr, 175 - 10*p);
|
||||
}
|
||||
|
||||
static double marisa_star_property(Player *plr, PlrProperty prop) {
|
||||
switch(prop) {
|
||||
case PLR_PROP_SPEED: {
|
||||
double s = marisa_common_property(plr, prop);
|
||||
|
||||
if(global.frames - plr->recovery < 0) {
|
||||
s /= 4.0;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
default:
|
||||
return marisa_common_property(plr, prop);
|
||||
}
|
||||
}
|
||||
|
||||
static void marisa_star_preload(void) {
|
||||
const int flags = RESF_DEFAULT;
|
||||
|
||||
|
@ -342,10 +351,10 @@ PlayerMode plrmode_marisa_b = {
|
|||
.character = &character_marisa,
|
||||
.shot_mode = PLR_SHOT_MARISA_STAR,
|
||||
.procs = {
|
||||
.property = marisa_star_property,
|
||||
.bomb = marisa_star_bomb,
|
||||
.bombbg = marisa_star_bombbg,
|
||||
.shot = marisa_star_shot,
|
||||
.speed_mod = marisa_star_speed_mod,
|
||||
.power = marisa_star_power,
|
||||
.preload = marisa_star_preload,
|
||||
.init = marisa_star_init,
|
||||
|
|
|
@ -26,6 +26,27 @@ PlayerCharacter character_youmu = {
|
|||
},
|
||||
};
|
||||
|
||||
double youmu_common_property(Player *plr, PlrProperty prop) {
|
||||
switch(prop) {
|
||||
case PLR_PROP_BOMB_TIME:
|
||||
return 300;
|
||||
|
||||
case PLR_PROP_COLLECT_RADIUS:
|
||||
return (plr->inputflags & INFLAG_FOCUS) ? 60 : 30;
|
||||
|
||||
case PLR_PROP_SPEED:
|
||||
return (plr->inputflags & INFLAG_FOCUS) ? 1.75 : 4.8;
|
||||
|
||||
case PLR_PROP_POC:
|
||||
return VIEWPORT_H / 3.5;
|
||||
|
||||
case PLR_PROP_DEATHBOMB_WINDOW:
|
||||
return 12;
|
||||
}
|
||||
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
void youmu_common_shot(Player *plr) {
|
||||
if(!(global.frames % 4)) {
|
||||
play_sound("generic_shot");
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
extern PlayerCharacter character_youmu;
|
||||
|
||||
|
||||
double youmu_common_property(Player *plr, PlrProperty prop);
|
||||
void youmu_common_shot(Player *plr);
|
||||
void youmu_common_draw_proj(Projectile *p, Color c, float scale);
|
||||
void youmu_common_bombbg(Player *plr);
|
||||
|
|
|
@ -399,14 +399,6 @@ static void youmu_mirror_init(Player *plr) {
|
|||
myon->ent.draw_layer = LAYER_PLAYER_SLAVE;
|
||||
}
|
||||
|
||||
static double youmu_mirror_speed_mod(Player *plr, double speed) {
|
||||
if(global.frames - plr->recovery < 0) {
|
||||
speed /= 5.0;
|
||||
}
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
static void youmu_mirror_preload(void) {
|
||||
const int flags = RESF_DEFAULT;
|
||||
|
||||
|
@ -435,12 +427,12 @@ PlayerMode plrmode_youmu_a = {
|
|||
.character = &character_youmu,
|
||||
.shot_mode = PLR_SHOT_YOUMU_MIRROR,
|
||||
.procs = {
|
||||
.bomb = youmu_mirror_bomb,
|
||||
.speed_mod = youmu_mirror_speed_mod,
|
||||
.bomb_shader = youmu_mirror_shader,
|
||||
.bombbg = youmu_common_bombbg,
|
||||
.shot = youmu_mirror_shot,
|
||||
.init = youmu_mirror_init,
|
||||
.preload = youmu_mirror_preload,
|
||||
.property = youmu_common_property,
|
||||
.bomb = youmu_mirror_bomb,
|
||||
.bomb_shader = youmu_mirror_shader,
|
||||
.bombbg = youmu_common_bombbg,
|
||||
.shot = youmu_mirror_shot,
|
||||
.init = youmu_mirror_init,
|
||||
.preload = youmu_mirror_preload,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -400,6 +400,7 @@ PlayerMode plrmode_youmu_b = {
|
|||
.character = &character_youmu,
|
||||
.shot_mode = PLR_SHOT_YOUMU_HAUNTING,
|
||||
.procs = {
|
||||
.property = youmu_common_property,
|
||||
.bomb = youmu_haunting_bomb,
|
||||
.bombbg = youmu_common_bombbg,
|
||||
.shot = youmu_haunting_shot,
|
||||
|
|
Loading…
Reference in a new issue