taisei/src/player.h

255 lines
6.6 KiB
C
Raw Permalink Normal View History

/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
2024-05-16 23:30:41 +02:00
* Copyright (c) 2011-2024, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2024, Andrei Alexeyev <akari@taisei-project.org>.
*/
#pragma once
#include "taisei.h"
2017-10-03 17:25:38 +02:00
#include "aniplayer.h"
#include "color.h"
#include "coroutine/coevent.h"
#include "entity.h"
#include "replay/eventcodes.h"
#include "replay/state.h"
#include "resource/resource.h"
#include "stats.h"
#ifdef DEBUG
#define PLR_DPS_STATS
#endif
#ifdef PLR_DPS_STATS
#define IF_PLR_DPS_STATS(...) __VA_ARGS__
#else
#define IF_PLR_DPS_STATS(...)
#endif
enum {
PLR_MAX_POWER_EFFECTIVE = 400,
PLR_MAX_POWER_STORED = 600,
Lots of disorganized (mostly) visual overhaul (#156) * WIP some projectile effects * fix segfault * Laser smoothing and glow via post-processing blur magic TODO: make it optional * fix memory corruption * fix memory corruption for realsies now * fix color_get_hsl for out-of-range colors * some more bullet flare tweaks * some lame clear effect workarounds * spawn bullet flares after frame 0; looks better and fixes some problems * New baryon explosion; fix petal_explosion; leanify everything * Add missing bullet flare sprite, rebuild main atlas * improve batching efficiency with bullet spawn flares * forgot git add * Group projectiles/particles by shader where possible * Another take on baryon explosion; make fg framebuffers 16bit * WIP some settings for toasters * remove stupid debug log * microoptimization that probably does nothing anyway * somewhat more intuitive quality settings * Whitelist more particles (MarisaB is on hold) * Whitelist (and fix) some more stage6 particles (mostly ToE) * Add a spell name background * Experimental radial healthbar for bosses * healthbar tweaks * thiccer healthbars in response to feedback * remove healthbar survival timer; just fade out on survivals * Add linear healthbars option; WIP other boss HUD tweaks * Use the proper spell card name format * New font and some random garbage to go along with it * Generate static font outlines for use in text shaders * Use outlines in overlay text shader * Complete boss HUD/healthbar fading logic * fix boss timer limit * stage5 bombs explosion effect * split PFLAG_NOSPAWNZOOM into PFLAG_NOSPAWNFLARE and PFLAG_NOSPAWNFADE; introduce PFLAG_NOSPAWNEFFECTS which disables both (it's just the two values OR'd together) simplify vampiric vapor bullet spawning effect * Remove spawn fade-in from super-fast stage5 fairy projectiles (limiters) * lower particle density in v.vapor in minimal mode * graze effect tweaks * fix text shortening, tweak replay menu layout * stupid debug spam * revisit grazing effects again * dumb debug spam again * improve boss attack timer * overlay effect for boss deaths (similar to the player one) * spice up spellcard declaration (HUD) * don't spawn boss death overlay if fleed * modify Exo2 font to use tabular figures * adjust replay menu for the font change * draw timer & power with standard font (phasing out the numbers font) * WIP new HUD; random fixes/tweaks * hud: move difficulty indicator * hud: move debug stuff around * preloads, mostly * fix youmuA batching conflict * shitty workaround for the shitty screenshake shit * remove extraspell lag by stopping to draw stagebg sooner which is possible because extra spells have a different spellcard_intro timing. Fun fact of the day: the duration of spellcard_intro is always ATTACK_START_DELAY_EXTRA even for normal spells! * new stain particle * i disabled background rendering… * "batch" marisa_b masterspark draws * remove these once a new atlas is generated * make toe quick again * hopefully fix all occurences of changed stain and ScaleFade behavior * tweaking reimu_a and toe boson launch effects * make lhc fast again * softer involnerability effect * fix stage 1 snow on the water bug (and improve performance) translated the time to the future a bit because it only seemed to be an issue for small time values * remove unnecessary spawnflare from toe * tone down extra spell start effect * experimental ReimuB gap shader optimization * fix python3 shebangs * generate simple blur shaders w/ hardcoded kernels * New loading screen * lasers: fix incorrect draw hook registration * add webp support for atlas generator * Use ImageMagick for atlas composition (adds 16-bit support) * Atlas maintenance * make the vampiric vapor bullets less prone to invisibility * Revert a few particles to the quadratic fade curve * experimental baryon effect * improve baryon sprites * disable the baryon effect on minimal postprocessing setting
2019-01-04 23:59:39 +01:00
PLR_MAX_LIVES = 8,
PLR_MAX_BOMBS = 8,
// -Wpedantic doesn't like this
// PLR_MAX_PIV = UINT32_MAX,
#define PLR_MAX_PIV UINT32_MAX
#define PLR_MAX_GRAZE UINT32_MAX
#define PLR_MAX_VOLTAGE UINT16_MAX
PLR_MAX_LIFE_FRAGMENTS = 5,
PLR_MAX_BOMB_FRAGMENTS = 500,
PLR_START_LIVES = 2,
PLR_START_BOMBS = 3,
PLR_START_PIV = 10000,
2017-04-08 01:09:08 +02:00
PLR_STGPRACTICE_LIVES = PLR_MAX_LIVES,
PLR_STGPRACTICE_BOMBS = PLR_START_BOMBS,
PLR_MIN_BORDER_DIST = 16,
PLR_POWERSURGE_POWERCOST = 200,
PLR_RESPAWN_TIME = 60,
PLR_RECOVERY_TIME = 210,
};
#define PLR_SPAWN_POS_X (VIEWPORT_W * 0.5)
#define PLR_SPAWN_POS_Y (VIEWPORT_H - 64.0)
#define PLR_SPAWN_POS CMPLX(PLR_SPAWN_POS_X, PLR_SPAWN_POS_Y)
static const float PLR_POWERSURGE_POSITIVE_DRAIN_MAX = (0.15 / 60.0);
static const float PLR_POWERSURGE_POSITIVE_DRAIN_MIN = (0.15 / 60.0);
static const float PLR_POWERSURGE_NEGATIVE_DRAIN_MAX = (0.15 / 60.0);
static const float PLR_POWERSURGE_NEGATIVE_DRAIN_MIN = (0.01 / 60.0);
static const float PLR_POWERSURGE_POSITIVE_GAIN = (1.50 / 60.0);
static const float PLR_POWERSURGE_NEGATIVE_GAIN = (0.40 / 60.0);
2023-06-14 03:08:18 +02:00
// do not reorder these or you'll break replays
#define INFLAGS \
INFLAG(UP, 0) \
INFLAG(DOWN, 1) \
INFLAG(LEFT, 2) \
INFLAG(RIGHT, 3) \
INFLAG(FOCUS, 4) \
INFLAG(SHOT, 5) \
INFLAG(SKIP, 6) \
typedef enum {
2023-06-14 03:08:18 +02:00
#define INFLAG(name, bit) \
INFLAG_##name = (1 << bit),
INFLAGS
#undef INFLAG
} PlrInputFlag;
enum {
INFLAGS_MOVE = INFLAG_UP | INFLAG_DOWN | INFLAG_LEFT | INFLAG_RIGHT
};
typedef struct PowerSurgeBonus {
uint baseline;
uint score;
uint gain_rate;
float discharge_power;
float discharge_range;
float discharge_damage;
} PowerSurgeBonus;
DEFINE_ENTITY_TYPE(Player, {
cmplx pos;
cmplx velocity;
cmplx uncapped_velocity;
cmplx deathpos;
struct PlayerMode *mode;
AniPlayer ani;
Sprite bomb_portrait;
2020-04-26 21:27:13 +02:00
Stats stats;
struct {
float positive;
float negative;
struct {
int activated, expired;
} time;
int total_charge;
int player_power;
double damage_done;
double damage_accum;
PowerSurgeBonus bonus;
} powersurge;
2020-03-13 21:54:07 +01:00
COEVENTS_ARRAY(
shoot,
inputflags_changed,
stored_power_changed,
effective_power_changed,
2020-03-25 07:52:18 +01:00
bomb_used
2020-03-13 21:54:07 +01:00
) events;
uint64_t points;
uint64_t extralife_threshold;
uint extralives_given;
uint point_item_value;
uint graze;
uint voltage;
int lives;
int bombs;
int life_fragments;
int bomb_fragments;
int power_stored;
int _prev_effective_power;
int continuetime;
int deathtime; /* time of hit + deathbomb window */
int respawntime; /* end of respawn animation; control returns to player */
int recoverytime; /* end of post-death i-frames */
int bomb_triggertime; /* time when the bomb was triggered */
int bomb_endtime; /* time when the bomb i-frames end */
2020-03-13 21:54:07 +01:00
uint inputflags;
int lastmovesequence; // used for animation
2012-08-15 16:36:39 +02:00
int axis_ud;
int axis_lr;
float focus_circle_alpha;
float bomb_cutin_alpha;
bool gamepadmove;
bool iddqd;
2017-03-06 13:02:46 +01:00
IF_PLR_DPS_STATS(
int dmglogframe;
int dmglog[240];
)
});
typedef enum PlayerEventResult {
PLREVT_USEFUL = (1 << 0),
PLREVT_CHEAT = (1 << 1),
} PlayerEventResult;
// This is called first before we even enter stage_loop.
// It's also called right before syncing player state from a replay stage struct, if a replay is being watched or recorded, before every stage.
// The entire state is reset here, and defaults for story mode are set.
void player_init(Player *plr);
// This is called early in stage_loop, before creating or reading replay stage data.
// State that is not supposed to be preserved between stages is reset here, and any plrmode-specific resources are preloaded.
void player_stage_pre_init(Player *plr);
// This is called right after the stage's begin proc. After that, the actual game loop starts.
void player_stage_post_init(Player *plr);
// Yes, that's 3 different initialization functions right here.
2017-11-25 16:51:43 +01:00
void player_free(Player *plr);
void player_draw_overlay(Player *plr);
2020-04-01 22:08:40 +02:00
bool player_should_shoot(Player *plr);
2017-10-24 04:57:14 +02:00
bool player_set_power(Player *plr, short npow);
bool player_add_power(Player *plr, short pdelta);
int player_get_effective_power(Player *plr);
void player_move(Player*, cmplx delta);
2011-07-05 15:20:19 +02:00
2012-07-20 16:11:24 +02:00
void player_realdeath(Player*);
void player_death(Player*);
void player_graze(Player *plr, cmplx pos, int pts, int effect_intensity, const Color *color);
PlayerEventResult player_event(
Player *plr,
ReplayState *rpy_in,
ReplayState *rpy_out,
ReplayEventCode type,
uint16_t value
) attr_nonnull(1);
void player_fix_input(Player *plr, ReplayState *rpy_out);
void player_applymovement(Player* plr);
void player_add_life_fragments(Player *plr, int frags);
void player_add_bomb_fragments(Player *plr, int frags);
void player_add_lives(Player *plr, int lives);
void player_add_bombs(Player *plr, int bombs);
void player_add_points(Player *plr, uint points, cmplx location);
void player_add_piv(Player *plr, uint piv, cmplx location);
void player_add_voltage(Player *plr, uint voltage);
bool player_drain_voltage(Player *plr, uint voltage);
void player_extend_powersurge(Player *plr, float pos, float neg);
2018-07-30 09:04:09 +02:00
void player_register_damage(Player *plr, EntityInterface *target, const DamageInfo *damage);
void player_cancel_powersurge(Player *plr);
void player_placeholder_bomb_logic(Player *plr);
2017-11-26 14:06:35 +01:00
bool player_is_recovering(Player *plr);
bool player_is_bomb_active(Player *plr);
bool player_is_powersurge_active(Player *plr);
bool player_is_vulnerable(Player *plr);
bool player_is_alive(Player *plr);
void player_powersurge_calc_bonus(Player *plr, PowerSurgeBonus *bonus);
uint64_t player_next_extralife_threshold(uint64_t step);
2017-11-26 14:06:35 +01:00
// Progress is normalized from 0: bomb start to 1: bomb end
double player_get_bomb_progress(Player *plr);
void player_damage_hook(Player *plr, EntityInterface *target, DamageInfo *dmg);
void player_preload(ResourceGroup *rg);
Add Reimu Hakurei as a playable character (#106) * Reimu (#101) * add the reimu * Add Reimu story * account for various blunders * add reimu dialog picture * Reimu: WIP yin-yang orbs * reimu: fix up indents * Reimu: swap the shotmode names to match the kanji order in her Japanese name * Reimu: compatibility with the latest system * WIP ReimuA crap * ReimuA homing trails * more ReimuA stuff * more ReimuA adjustments + enhanced DPS stats * Reimu: stubs for new player animation sequences * Reimu: occupy the 0th character slot * Reimu: tweak needle sprite * Reimu: buff movement speed to better match Touhou * Reimu: fixup for the recent projectile changes * ReimuA: make homing shots a bit smaller; give them custom effect on collision * Reimu: add intermediate frames; move some loose sprites to the atlas * Reimu: fix compile errors * replace DBL_MAX by INFINITY * Don’t draw reimu orbs twice fixes #127 * add new reimu dialog pic * ReimuA adjustments (mostly homing); it's still OP * wip ReimuB gaps * still not sure where i'm going with these gaps * meh * Reimu: premultiplied alpha fixups after rebase * reimuB shot pattern with basic power scaling (not balanced at all) * reimuB: some lame-ass particle effects * ReimuB bomb effect prototype * reimuA bomb prototype * fix reimu shots for the new damage system * Reimu: use the new player_is_bomb_active() function, add placeholder BG for ReimuB * some reimuB bomb projectiles * ReimuB bomb bg and some framebuffer utils required to support it. Might reuse this at least in part for ReimuA unless we come up with something better. * hack to fix ReimuB bomb fade; refactoring needed * reimuA damaging bombs * fix ub * prevent nan when reimuA bombs without enemies present * add a bomb_bg to reimuA * ... * various fantasy seal tweaks * Reimu: placeholder bomb sounds; slight fantasy seal buff * fix null pointer dereference * Reimu "balance" adjustments; minor fixes * putting bandaids over gunshot wounds * Add aoe damage and bullet cancel to ReimuB's bomb * more exorcism porn * make reimu bomb bg runes better visible on dark backgrounds * More ReimuA shot changes
2018-08-11 21:13:48 +02:00
// FIXME: where should this be?
cmplx plrutil_homing_target(cmplx org, cmplx fallback);
void plrutil_slave_retract(BoxedPlayer bplr, cmplx *pos, real retract_time);