Files
psopeeps-newserv/src/EnemyType.hh
T
2026-03-08 20:40:15 -07:00

204 lines
4.1 KiB
C++

#pragma once
#include <inttypes.h>
#include <phosg/Tools.hh>
#include "StaticGameData.hh"
#include "Types.hh"
// We don't know what the actual maximum was, since it was presumably only stored server-side on Sega's servers. The
// client uses values up to 0x6C (Kondrieu), so we just choose a value larger than that.
static constexpr size_t NUM_RT_INDEXES_V3 = 0x64;
static constexpr size_t NUM_RT_INDEXES_V4 = 0x70;
enum class EnemyType : uint8_t {
MIN_VALUE = 0,
UNKNOWN = 0,
NONE,
NON_ENEMY_NPC,
AL_RAPPY,
ASTARK,
BA_BOOTA,
BARBA_RAY,
BARBA_RAY_JOINT,
BARBAROUS_WOLF,
BEE_L,
BEE_R,
BOOMA,
BOOTA,
BULCLAW,
BULK,
CANADINE,
CANADINE_GROUP,
CANANE,
CHAOS_BRINGER,
CHAOS_SORCERER,
CLAW,
DARK_BELRA,
DARK_FALZ_1,
DARK_FALZ_2,
DARK_FALZ_3,
DARK_GUNNER,
DARK_GUNNER_CONTROL,
DARVANT,
DE_ROL_LE,
DE_ROL_LE_BODY,
DE_ROL_LE_MINE,
DEATH_GUNNER,
DEL_LILY,
DEL_RAPPY_CRATER,
DEL_RAPPY_DESERT,
DELBITER,
DELDEPTH,
DELSABER,
DIMENIAN,
DOLMDARL,
DOLMOLM,
DORPHON,
DORPHON_ECLAIR,
DRAGON,
DUBCHIC,
DUBWITCH, // Has no entry in battle params
EGG_RAPPY,
EPSIGARD,
EPSILON,
EVIL_SHARK,
GAEL_OR_GIEL,
GAL_GRYPHON,
GARANZ,
GEE,
GI_GUE,
GIBBLES,
GIGOBOOMA,
GILLCHIC,
GIRTABLULU,
GOBOOMA,
GOL_DRAGON,
GORAN,
GORAN_DETONATOR,
GRASS_ASSASSIN,
GUIL_SHARK,
HALLO_RAPPY,
HIDOOM,
HILDEBEAR,
HILDEBLUE,
ILL_GILL,
KONDRIEU,
KONDRIEU_SPINNER,
LA_DIMENIAN,
LOVE_RAPPY,
MERICARAND,
MERICAROL,
MERICUS,
MERIKLE,
MERILLIA,
MERILTAS,
MERISSA_A,
MERISSA_AA,
MIGIUM,
MONEST,
MORFOS,
MOTHMANT,
NANO_DRAGON,
NAR_LILY,
OLGA_FLOW_1,
OLGA_FLOW_2,
PAL_SHARK,
PAN_ARMS,
PAZUZU_CRATER,
PAZUZU_DESERT,
PIG_RAY,
POFUILLY_SLIME,
POUILLY_SLIME,
POISON_LILY,
PYRO_GORAN,
RAG_RAPPY,
RECOBOX,
RECON,
SAINT_MILION,
SAINT_MILION_SPINNER,
SAINT_RAPPY,
SAND_RAPPY_CRATER,
SAND_RAPPY_DESERT,
SATELLITE_LIZARD_CRATER,
SATELLITE_LIZARD_DESERT,
SAVAGE_WOLF,
SHAMBERTIN,
SHAMBERTIN_SPINNER,
SINOW_BEAT,
SINOW_BERILL,
SINOW_GOLD,
SINOW_SPIGELL,
SINOW_ZELE,
SINOW_ZOA,
SO_DIMENIAN,
UL_GIBBON,
UL_RAY,
VOL_OPT_1,
VOL_OPT_2,
VOL_OPT_AMP,
VOL_OPT_CORE,
VOL_OPT_MONITOR,
VOL_OPT_PILLAR,
YOWIE_CRATER,
YOWIE_DESERT,
ZE_BOOTA,
ZOL_GIBBON,
ZU_CRATER,
ZU_DESERT,
MAX_VALUE,
};
struct EnemyTypeDefinition {
enum Flag : uint8_t {
VALID_EP1 = 0x01,
VALID_EP2 = 0x02,
VALID_EP4 = 0x04,
IS_RARE = 0x08,
IS_BOSS = 0x10,
};
EnemyType type;
uint8_t flags;
uint8_t rt_index; // 0xFF if not valid (e.g. not an enemy, or has no drops)
uint8_t legacy_rt_index; // Index used by Schtserv in their Ep4 .rel format
std::vector<uint8_t> bp_stats_indexes;
std::vector<uint8_t> bp_attack_data_indexes;
std::vector<uint8_t> bp_resist_data_indexes;
// Note: movement data isn't bound as strongly to the enemy types; some enemies use many entries and some use none at
// all, so we don't list them here. See notes/movement-data.txt for a listing of which enemies use which entries.
const char* enum_name;
const char* in_game_name;
const char* ultimate_name; // May be null if same as in_game_name
inline bool valid_in_episode(Episode ep) const {
switch (ep) {
case Episode::EP1:
return (this->flags & Flag::VALID_EP1);
case Episode::EP2:
return (this->flags & Flag::VALID_EP2);
case Episode::EP4:
return (this->flags & Flag::VALID_EP4);
default:
throw std::logic_error("invalid episode number");
}
}
inline bool is_rare() const {
return (this->flags & Flag::IS_RARE);
}
inline bool is_boss() const {
return (this->flags & Flag::IS_BOSS);
}
EnemyType rare_type(uint8_t area, uint8_t event) const;
};
const EnemyTypeDefinition& type_definition_for_enemy(EnemyType type);
template <>
const char* phosg::name_for_enum<EnemyType>(EnemyType type);
template <>
EnemyType phosg::enum_for_name<EnemyType>(const char* name);
const std::vector<EnemyType>& enemy_types_for_rare_table_index(Episode episode, uint8_t rt_index);
const std::vector<EnemyType>& enemy_types_for_battle_param_stats_index(Episode episode, uint8_t bp_index);