Initial commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shweetandClaude Opus 5.5 committed 2026-11-08 01:30:33 -05:00
commit 2007fb7edc
200 files changed
+27710

No files matched your search

+173
View File
@@ -0,0 +1,173 @@
#pragma once
#include "anm2.h"
#include "input.h"
#include "renderer.h"
#include "trinket.h"
#include "world.h"
struct Attack;
constexpr int ECHO_MAX = 64;
constexpr int MAX_FIGHTERS = SPAWN_COUNT;
constexpr float BOUNCE_KEEP = 0.75f;
constexpr float SECONDARY_SHADE = 0.5f;
constexpr int COLOR_COUNT = 16;
constexpr int COLOR_UNASSIGNED = -1;
// The colours fighters can wear, in the order fighters without one are given them.
constexpr Color PALETTE[COLOR_COUNT] = {
{1, 0.35f, 0.35f, 1}, {0.4f, 0.6f, 1, 1}, {1, 0.9f, 0.3f, 1}, {0.4f, 1, 0.45f, 1},
{1, 0.6f, 0.2f, 1}, {0.7f, 0.45f, 1, 1}, {0.3f, 0.95f, 1, 1}, {1, 0.5f, 0.8f, 1},
{0.75f, 1, 0.3f, 1}, {0.2f, 0.75f, 0.7f, 1}, {1, 0.3f, 1, 1}, {0.6f, 0.85f, 1, 1},
{1, 0.78f, 0.6f, 1}, {0.8f, 0.75f, 1, 1}, {0.75f, 0.5f, 0.3f, 1}, {0.75f, 0.78f, 0.85f, 1},
};
constexpr const char* COLOR_NAMES[COLOR_COUNT] = {"Red", "Blue", "Yellow", "Green", "Orange", "Purple",
"Cyan", "Pink", "Lime", "Teal", "Magenta", "Sky",
"Peach", "Lavender", "Brown", "Silver"};
constexpr float BOUNCE_MIN = 120;
constexpr float BOX_HEIGHT = 24;
constexpr float BOX_WIDTH = 12;
constexpr float JUMP_SPEED = 400;
constexpr float KNOCK_DECAY = 1.2f;
constexpr float LAUNCH_END_SPEED = 200;
constexpr float RUN_SPEED = 150;
constexpr float RACE_KNOCK = 0.5f;
constexpr float SLAM_SPEED = 400;
constexpr float CHARGE_TIME = 1.0f;
constexpr float CHARGE_VISIBLE = 0.15f;
// Shock Absorber takes off this share of what it takes off weapon movement from knockback.
constexpr float ABSORB_KNOCK_SHARE = 2 / 3.0f;
// A platforming fighter driven by Controls: movement, aiming, the shared weapon charge, and everything it carries.
// Loadouts hold weapon and trinket numbers (-1 for empty), with only their first slots counts in use (the rest stay
// empty). The same item can sit in several slots, each copy with its own level (slot levels); item levels are what a
// copy gets when equipped, and what an unequipped item is described at. Copies always stack: weapon copies are separate
// weapons with their own cooldowns (Dual Wield can hold two of one), and trinket copies add up. Cooldowns (per weapon
// key, see weapon_key), Doubler echoes and the kick animation belong to its weapons. Index is its place in the game's
// fighter list, which its attacks record. Hitstop freezes it (and its attacks) after landing or taking a heavy hit. A
// big hit launches it: it flies, bouncing off whatever it hits, tumbling, with no say in where it goes until it slows
// down. Crouching on the ground lowers it, slows it to a waddle and halves the knockback it takes. Spinning a flail
// lightens its gravity. Hard bounces hurt, credited to the launcher, whoever landed the last hit. In a race, hits only
// knock it about (half as hard), and touching a pit puts it back on the last ground it stood squarely on. Slopes slow
// it climbing and speed it up descending. Crouching on one slides it down, rolling, and the slide carries on over flat
// ground until it slows.
class Fighter
{
public:
Body body;
Controls controls;
Vec2 aim = {1, 0};
FixedList<Echo, ECHO_MAX> echoes;
float charge = 0;
float cooldowns[SLOT_MAX] = {};
float flash = 0;
float health = 0;
float hitstop = 0;
float kickFrom = 0;
float kickTime = 1;
float kickTo = 0;
float scale = 1;
float shockCooldown = 0;
float contactCooldown = 0;
int index = 0;
int launcher = 0;
int offSlot = -1;
int slot = 0;
int trinketItemLevels[TRINKET_COUNT] = {};
int trinketSlotLevels[SLOT_MAX] = {};
int trinketLoadout[SLOT_MAX];
int trinketSlots = SLOTS_DEFAULT;
int weaponItemLevels[WEAPON_COUNT] = {};
int weaponSlotLevels[SLOT_MAX] = {};
int weaponLoadout[SLOT_MAX];
int weaponSlots = SLOTS_DEFAULT;
bool isAlive = true;
bool isBot = false;
bool isCrouching = false;
bool isSpinning = false;
bool isLaunched = false;
// In the sandbox, whether it fights other fighters (both need it on); without it, it's drawn darkened.
bool isPvp = false;
bool isSliding = false;
void init(Game& game, int number);
void state_reset(Game& game, float maxHealth);
void position_reset(Game& game);
void position_set(Game& game, Vec2 feet);
void slots_set(int weapons, int trinkets);
void damage_take(Game& game, Damage damage);
void update(Game& game);
void draw(Game& game);
void blend(float alpha);
void impulse_add(Vec2 impulse, bool isDamped = true);
void teleport_to(Vec2 centre);
void burst_add(Vec2 impulse);
void charge_cancel(Game& game);
int weapon_get();
int weapon_key(int weaponSlot);
int off_slot_get();
int off_weapon_get();
int slot_level_get(int weaponSlot);
const LevelDef& level_get(int weaponSlot);
void item_set(bool isTrinket, int itemSlot, int item);
void levels_fill(int weaponLevel, int trinketLevel);
float trinket_get(TrinketId trinket, float neutral);
float trinket_best_get(TrinketId trinket, float neutral);
float trinket_sum_get(int trinket, const float* table);
int trinket_level_get(int trinket);
int trinket_count(int trinket);
float trinket_cooldown_get(int trinket);
float knock_absorb_get();
float pound_area_get();
const char* animation_get();
void animator_update(Animator& animator);
Pose pose_get(Game& game);
Vec2 center_get();
Vec2 hand_get();
Vec2 offhand_get();
bool is_any_pressed();
bool is_down(Control control);
bool is_pressed(Control control);
bool is_released(Control control);
bool is_trinket_equipped(int trinket);
int wall_get(Game& game);
bool is_crawling();
bool is_flashing();
bool is_left();
private:
Vec2 cornerPrevious;
Vec2 safe;
float coyoteTimer = 0;
float dashCooldown = 0;
float dashTimer = 0;
float jumpBuffer = 0;
float kickTimer = 0;
float kickPose = 0;
float slideTimer = 0;
float stepDistance = 0;
float wallMemory = 0;
float roll = 0;
float rollSpin = 0;
float tumble = 0;
float wallSpeed = 0;
int chargeVoice = -1;
int slideWall = 0;
Uint16 buttonsPrevious = 0;
bool isCharging = false;
bool isFireBlocked = false;
bool isFacingLeft = false;
bool isJumping = false;
void slot_update(Game& game);
void safe_update(Game& game);
void size_update();
void dash_update(Game& game, bool isJumpPressed);
void climb_update(Game& game);
Vec2 wall_point_get(int wall);
void wall_push(Game& game, int wall, Vec2 base);
void bounce_resolve(Game& game, Vec2 before);
void run_update(Attack* hook);
void rope_update(Attack& hook);
void charge_update(Game& game);
};