|
|
|
|
@ -27,131 +27,6 @@
|
|
|
|
|
|
|
|
|
|
namespace devilution { |
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
constexpr auto Physical = MissileDataFlags::Physical; |
|
|
|
|
constexpr auto Fire = MissileDataFlags::Fire; |
|
|
|
|
constexpr auto Lightning = MissileDataFlags::Lightning; |
|
|
|
|
constexpr auto Magic = MissileDataFlags::Magic; |
|
|
|
|
constexpr auto Acid = MissileDataFlags::Acid; |
|
|
|
|
constexpr auto Arrow = MissileDataFlags::Arrow; |
|
|
|
|
constexpr auto Invisible = MissileDataFlags::Invisible; |
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
/** Data related to each missile ID. */ |
|
|
|
|
const MissileData MissilesData[] = { |
|
|
|
|
// clang-format off
|
|
|
|
|
// id mAddProc, mProc, mlSFX, miSFX, mFileNum, flags, MovementDistribution;
|
|
|
|
|
/*Arrow*/ { &AddArrow, &ProcessArrow, SfxID::None, SfxID::None, MissileGraphicID::Arrow, Physical | Arrow, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*Firebolt*/ { &AddFirebolt, &ProcessGenericProjectile, SfxID::SpellFirebolt, SfxID::SpellFireHit, MissileGraphicID::Fireball, Fire, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*Guardian*/ { &AddGuardian, &ProcessGuardian, SfxID::SpellGuardian, SfxID::None, MissileGraphicID::Guardian, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Phasing*/ { &AddPhasing, &ProcessTeleport, SfxID::SpellTeleport, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*NovaBall*/ { &AddNovaBall, &ProcessNovaBall, SfxID::None, SfxID::None, MissileGraphicID::Lightning, Lightning, MissileMovementDistribution::Unblockable }, |
|
|
|
|
/*FireWall*/ { &AddFireWall, &ProcessFireWall, SfxID::SpellFireWall, SfxID::SpellFireHit, MissileGraphicID::FireWall, Fire, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Fireball*/ { &AddFireball, &ProcessFireball, SfxID::SpellFirebolt, SfxID::SpellFireHit, MissileGraphicID::Fireball, Fire, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*LightningControl*/ { &AddLightningControl, &ProcessLightningControl, SfxID::None, SfxID::None, MissileGraphicID::Lightning, Lightning | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Lightning*/ { &AddLightning, &ProcessLightning, SfxID::SpellLightning, SfxID::SpellLightningHit, MissileGraphicID::Lightning, Lightning, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*MagmaBallExplosion*/ { &AddMissileExplosion, &ProcessMissileExplosion, SfxID::None, SfxID::None, MissileGraphicID::MagmaBallExplosion, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*TownPortal*/ { &AddTownPortal, &ProcessTownPortal, SfxID::SpellPortal, SfxID::None, MissileGraphicID::TownPortal, Magic, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*FlashBottom*/ { &AddFlashBottom, &ProcessFlashBottom, SfxID::SpellNova, SfxID::SpellLightningHit, MissileGraphicID::FlashBottom, Magic, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*FlashTop*/ { &AddFlashTop, &ProcessFlashTop, SfxID::None, SfxID::None, MissileGraphicID::FlashTop, Magic, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*ManaShield*/ { &AddManaShield, nullptr, SfxID::SpellManaShield, SfxID::None, MissileGraphicID::ManaShield, Magic | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*FlameWave*/ { &AddFlameWave, &ProcessFlameWave, SfxID::None, SfxID::None, MissileGraphicID::FireWall, Fire, MissileMovementDistribution::Unblockable }, |
|
|
|
|
/*ChainLightning*/ { &AddChainLightning, &ProcessChainLightning, SfxID::SpellLightning, SfxID::SpellLightningHit, MissileGraphicID::Lightning, Lightning, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*ChainBall*/ { nullptr, nullptr, SfxID::None, SfxID::None, MissileGraphicID::Lightning, Lightning, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*BloodHit*/ { nullptr, nullptr, SfxID::SpellBloodStar, SfxID::SpellBloodStarHit, MissileGraphicID::BloodHit, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*BoneHit*/ { nullptr, nullptr, SfxID::None, SfxID::None, MissileGraphicID::BoneHit, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*MetalHit*/ { nullptr, nullptr, SfxID::None, SfxID::None, MissileGraphicID::MetalHit, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Rhino*/ { &AddRhino, &ProcessRhino, SfxID::None, SfxID::None, MissileGraphicID::None, Physical, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*MagmaBall*/ { &AddMagmaBall, &ProcessGenericProjectile, SfxID::None, SfxID::None, MissileGraphicID::MagmaBall, Fire, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*ThinLightningControl*/ { &AddLightningControl, &ProcessLightningControl, SfxID::None, SfxID::None, MissileGraphicID::ThinLightning, Lightning | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*ThinLightning*/ { &AddLightning, &ProcessLightning, SfxID::None, SfxID::None, MissileGraphicID::ThinLightning, Lightning, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*BloodStar*/ { &AddGenericMagicMissile, &ProcessGenericProjectile, SfxID::None, SfxID::None, MissileGraphicID::BloodStar, Magic, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*BloodStarExplosion*/ { &AddMissileExplosion, &ProcessMissileExplosion, SfxID::None, SfxID::None, MissileGraphicID::BloodStarExplosion, Magic, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Teleport*/ { &AddTeleport, &ProcessTeleport, SfxID::SpellElemental, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*FireArrow*/ { &AddElementalArrow, &ProcessElementalArrow, SfxID::None, SfxID::None, MissileGraphicID::FireArrow, Fire | Arrow, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*DoomSerpents*/ { nullptr, nullptr, SfxID::SpellDoomSerpents, SfxID::None, MissileGraphicID::DoomSerpents, Magic | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*FireOnly*/ { nullptr, nullptr, SfxID::None, SfxID::None, MissileGraphicID::FireWall, Fire, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*StoneCurse*/ { &AddStoneCurse, &ProcessStoneCurse, SfxID::SpellStoneCurse, SfxID::None, MissileGraphicID::None, Magic | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*BloodRitual*/ { nullptr, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Invisibility*/ { nullptr, nullptr, SfxID::SpellInvisibility, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Golem*/ { &AddGolem, nullptr, SfxID::SpellGolem, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Etherealize*/ { nullptr, nullptr, SfxID::SpellEtherealize, SfxID::None, MissileGraphicID::Etherealize, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Spurt*/ { nullptr, nullptr, SfxID::None, SfxID::None, MissileGraphicID::Spurt, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*ApocalypseBoom*/ { &AddApocalypseBoom, &ProcessApocalypseBoom, SfxID::None, SfxID::None, MissileGraphicID::ApocalypseBoom, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Healing*/ { &AddHealing, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*FireWallControl*/ { &AddFireWallControl, &ProcessFireWallControl, SfxID::None, SfxID::None, MissileGraphicID::FireWall, Fire | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Infravision*/ { &AddInfravision, &ProcessInfravision, SfxID::SpellInfravision, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Identify*/ { &AddIdentify, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*FlameWaveControl*/ { &AddFlameWaveControl, &ProcessFlameWaveControl, SfxID::SpellFlameWave, SfxID::None, MissileGraphicID::FireWall, Fire, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Nova*/ { &AddNova, &ProcessNova, SfxID::SpellNova, SfxID::None, MissileGraphicID::Lightning, Lightning, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Rage*/ { &AddRage, &ProcessRage, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Apocalypse*/ { &AddApocalypse, &ProcessApocalypse, SfxID::SpellApocalypse, SfxID::None, MissileGraphicID::ApocalypseBoom, Magic, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*ItemRepair*/ { &AddItemRepair, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*StaffRecharge*/ { &AddStaffRecharge, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*TrapDisarm*/ { &AddTrapDisarm, nullptr, SfxID::SpellTrapDisarm, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Inferno*/ { &AddInferno, &ProcessInferno, SfxID::SpellInferno, SfxID::None, MissileGraphicID::Inferno, Fire, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*InfernoControl*/ { &AddInfernoControl, &ProcessInfernoControl, SfxID::None, SfxID::None, MissileGraphicID::None, Fire | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*FireMan*/ { nullptr, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*Krull*/ { nullptr, nullptr, SfxID::None, SfxID::None, MissileGraphicID::Krull, Fire | Arrow, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*ChargedBolt*/ { &AddChargedBolt, &ProcessChargedBolt, SfxID::SpellChargedBolt, SfxID::None, MissileGraphicID::ChargedBolt, Lightning, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*HolyBolt*/ { &AddHolyBolt, &ProcessHolyBolt, SfxID::SpellHolyBolt, SfxID::SpellLightningHit, MissileGraphicID::HolyBolt, Physical, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*Resurrect*/ { &AddResurrect, nullptr, SfxID::None, SfxID::SpellResurrect, MissileGraphicID::None, Magic | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Telekinesis*/ { &AddTelekinesis, nullptr, SfxID::SpellEtherealize, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*LightningArrow*/ { &AddElementalArrow, &ProcessElementalArrow, SfxID::None, SfxID::None, MissileGraphicID::LightningArrow, Lightning | Arrow, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*Acid*/ { &AddAcid, &ProcessGenericProjectile, SfxID::SpellAcid, SfxID::None, MissileGraphicID::Acid, Acid, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*AcidSplat*/ { &AddMissileExplosion, &ProcessAcidSplate, SfxID::None, SfxID::None, MissileGraphicID::AcidSplat, Acid, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*AcidPuddle*/ { &AddAcidPuddle, &ProcessAcidPuddle, SfxID::SpellPuddle, SfxID::None, MissileGraphicID::AcidPuddle, Acid, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*HealOther*/ { &AddHealOther, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Elemental*/ { &AddElemental, &ProcessElemental, SfxID::SpellElemental, SfxID::None, MissileGraphicID::Elemental, Fire, MissileMovementDistribution::Unblockable }, |
|
|
|
|
/*ResurrectBeam*/ { &AddResurrectBeam, &ProcessResurrectBeam, SfxID::None, SfxID::None, MissileGraphicID::Resurrect, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*BoneSpirit*/ { &AddBoneSpirit, &ProcessBoneSpirit, SfxID::SpellBoneSpirit, SfxID::SpellBoneSpiritHit, MissileGraphicID::BoneSpirit, Magic, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*WeaponExplosion*/ { &AddWeaponExplosion, &ProcessWeaponExplosion, SfxID::None, SfxID::None, MissileGraphicID::None, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*RedPortal*/ { &AddRedPortal, &ProcessRedPortal, SfxID::SpellPortal, SfxID::None, MissileGraphicID::RedPortal, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*DiabloApocalypseBoom*/ { &AddApocalypseBoom, &ProcessApocalypseBoom, SfxID::None, SfxID::None, MissileGraphicID::DiabloApocalypseBoom, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*DiabloApocalypse*/ { &AddDiabloApocalypse, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Mana*/ { &AddMana, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Magi*/ { &AddMagi, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*LightningWall*/ { &AddLightningWall, &ProcessLightningWall, SfxID::SpellLightningWall, SfxID::SpellLightningHit, MissileGraphicID::Lightning, Lightning, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*LightningWallControl*/ { &AddFireWallControl, &ProcessLightningWallControl, SfxID::None, SfxID::None, MissileGraphicID::Lightning, Lightning | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Immolation*/ { &AddNova, &ProcessImmolation, SfxID::SpellFirebolt, SfxID::SpellFireHit, MissileGraphicID::Fireball, Fire, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*SpectralArrow*/ { &AddSpectralArrow, &ProcessSpectralArrow, SfxID::None, SfxID::None, MissileGraphicID::Arrow, Physical | Arrow, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*FireballBow*/ { &AddImmolation, &ProcessFireball, SfxID::ShootFireballBow, SfxID::SpellFireHit, MissileGraphicID::Fireball, Fire, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*LightningBow*/ { &AddLightningBow, &ProcessLightningBow, SfxID::ShootFireballBow, SfxID::None, MissileGraphicID::Lightning, Lightning | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*ChargedBoltBow*/ { &AddChargedBoltBow, &ProcessChargedBolt, SfxID::SpellChargedBolt, SfxID::None, MissileGraphicID::ChargedBolt, Lightning, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*HolyBoltBow*/ { &AddHolyBolt, &ProcessHolyBolt, SfxID::SpellHolyBolt, SfxID::SpellLightningHit, MissileGraphicID::HolyBolt, Physical, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*Warp*/ { &AddWarp, &ProcessTeleport, SfxID::SpellEtherealize, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Reflect*/ { &AddReflect, nullptr, SfxID::SpellManaShield, SfxID::None, MissileGraphicID::Reflect, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Berserk*/ { &AddBerserk, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*RingOfFire*/ { &AddRingOfFire, &ProcessRingOfFire, SfxID::None, SfxID::None, MissileGraphicID::FireWall, Fire | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*StealPotions*/ { &AddStealPotions, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*StealMana*/ { &AddStealMana, nullptr, SfxID::SpellEnd, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*RingOfLightning*/ { nullptr, nullptr, SfxID::None, SfxID::None, MissileGraphicID::Lightning, Lightning | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Search*/ { &AddSearch, &ProcessSearch, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Aura*/ { nullptr, nullptr, SfxID::None, SfxID::SpellLightningHit, MissileGraphicID::FlashBottom, Magic | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Aura2*/ { nullptr, nullptr, SfxID::None, SfxID::None, MissileGraphicID::FlashTop, Magic | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*SpiralFireball*/ { nullptr, nullptr, SfxID::SpellFirebolt, SfxID::SpellFireHit, MissileGraphicID::Fireball, Fire, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*RuneOfFire*/ { &AddRuneOfFire, &ProcessRune, SfxID::None, SfxID::None, MissileGraphicID::Rune, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*RuneOfLight*/ { &AddRuneOfLight, &ProcessRune, SfxID::None, SfxID::None, MissileGraphicID::Rune, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*RuneOfNova*/ { &AddRuneOfNova, &ProcessRune, SfxID::None, SfxID::None, MissileGraphicID::Rune, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*RuneOfImmolation*/ { &AddRuneOfImmolation, &ProcessRune, SfxID::None, SfxID::None, MissileGraphicID::Rune, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*RuneOfStone*/ { &AddRuneOfStone, &ProcessRune, SfxID::None, SfxID::None, MissileGraphicID::Rune, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*BigExplosion*/ { &AddBigExplosion, &ProcessBigExplosion, SfxID::BigExplosion, SfxID::BigExplosion, MissileGraphicID::BigExplosion, Fire, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*HorkSpawn*/ { &AddHorkSpawn, &ProcessHorkSpawn, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*Jester*/ { &AddJester, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*OpenNest*/ { &AddOpenNest, nullptr, SfxID::None, SfxID::None, MissileGraphicID::None, Physical | Invisible, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*OrangeFlare*/ { &AddGenericMagicMissile, &ProcessGenericProjectile, SfxID::None, SfxID::None, MissileGraphicID::OrangeFlare, Magic, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*BlueFlare*/ { &AddGenericMagicMissile, &ProcessGenericProjectile, SfxID::None, SfxID::None, MissileGraphicID::BlueFlare2, Magic, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*RedFlare*/ { &AddGenericMagicMissile, &ProcessGenericProjectile, SfxID::None, SfxID::None, MissileGraphicID::RedFlare, Magic, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*YellowFlare*/ { &AddGenericMagicMissile, &ProcessGenericProjectile, SfxID::None, SfxID::None, MissileGraphicID::YellowFlare, Magic, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*BlueFlare2*/ { &AddGenericMagicMissile, &ProcessGenericProjectile, SfxID::None, SfxID::None, MissileGraphicID::BlueFlare2, Magic, MissileMovementDistribution::Blockable }, |
|
|
|
|
/*YellowExplosion*/ { &AddMissileExplosion, &ProcessMissileExplosion, SfxID::SpellFireHit, SfxID::None, MissileGraphicID::YellowFlareExplosion, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*RedExplosion*/ { &AddMissileExplosion, &ProcessMissileExplosion, SfxID::SpellFireHit, SfxID::None, MissileGraphicID::RedFlareExplosion, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*BlueExplosion*/ { &AddMissileExplosion, &ProcessMissileExplosion, SfxID::SpellFireHit, SfxID::None, MissileGraphicID::BlueFlareExplosion, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*BlueExplosion2*/ { &AddMissileExplosion, &ProcessMissileExplosion, SfxID::SpellFireHit, SfxID::None, MissileGraphicID::BlueFlareExplosion2, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
/*OrangeExplosion*/ { &AddMissileExplosion, &ProcessMissileExplosion, SfxID::SpellFireHit, SfxID::None, MissileGraphicID::OrangeFlareExplosion, Physical, MissileMovementDistribution::Disabled }, |
|
|
|
|
// clang-format on
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
/** Data related to each missile graphic ID. */ |
|
|
|
|
@ -159,6 +34,9 @@ std::vector<MissileFileData> MissileSpriteData;
|
|
|
|
|
std::vector<std::array<uint8_t, 16>> MissileAnimDelays; |
|
|
|
|
std::vector<std::array<uint8_t, 16>> MissileAnimLengths; |
|
|
|
|
|
|
|
|
|
/** Data related to each missile ID. */ |
|
|
|
|
std::vector<MissileData> MissilesData; |
|
|
|
|
|
|
|
|
|
size_t ToIndex(std::vector<std::array<uint8_t, 16>> &all, const std::array<uint8_t, 16> &value) |
|
|
|
|
{ |
|
|
|
|
for (size_t i = 0; i < all.size(); ++i) { |
|
|
|
|
@ -176,6 +54,71 @@ tl::expected<MissileGraphicsFlags, std::string> ParseMissileGraphicsFlag(std::st
|
|
|
|
|
return tl::make_unexpected("Unknown enum value"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tl::expected<MissileGraphicID, std::string> ParseMissileGraphicID(std::string_view value) |
|
|
|
|
{ |
|
|
|
|
if (value.empty()) return MissileGraphicID::None; |
|
|
|
|
if (value == "Arrow") return MissileGraphicID::Arrow; |
|
|
|
|
if (value == "Fireball") return MissileGraphicID::Fireball; |
|
|
|
|
if (value == "Guardian") return MissileGraphicID::Guardian; |
|
|
|
|
if (value == "Lightning") return MissileGraphicID::Lightning; |
|
|
|
|
if (value == "FireWall") return MissileGraphicID::FireWall; |
|
|
|
|
if (value == "MagmaBallExplosion") return MissileGraphicID::MagmaBallExplosion; |
|
|
|
|
if (value == "TownPortal") return MissileGraphicID::TownPortal; |
|
|
|
|
if (value == "FlashBottom") return MissileGraphicID::FlashBottom; |
|
|
|
|
if (value == "FlashTop") return MissileGraphicID::FlashTop; |
|
|
|
|
if (value == "ManaShield") return MissileGraphicID::ManaShield; |
|
|
|
|
if (value == "BloodHit") return MissileGraphicID::BloodHit; |
|
|
|
|
if (value == "BoneHit") return MissileGraphicID::BoneHit; |
|
|
|
|
if (value == "MetalHit") return MissileGraphicID::MetalHit; |
|
|
|
|
if (value == "FireArrow") return MissileGraphicID::FireArrow; |
|
|
|
|
if (value == "DoomSerpents") return MissileGraphicID::DoomSerpents; |
|
|
|
|
if (value == "Golem") return MissileGraphicID::Golem; |
|
|
|
|
if (value == "Spurt") return MissileGraphicID::Spurt; |
|
|
|
|
if (value == "ApocalypseBoom") return MissileGraphicID::ApocalypseBoom; |
|
|
|
|
if (value == "StoneCurseShatter") return MissileGraphicID::StoneCurseShatter; |
|
|
|
|
if (value == "BigExplosion") return MissileGraphicID::BigExplosion; |
|
|
|
|
if (value == "Inferno") return MissileGraphicID::Inferno; |
|
|
|
|
if (value == "ThinLightning") return MissileGraphicID::ThinLightning; |
|
|
|
|
if (value == "BloodStar") return MissileGraphicID::BloodStar; |
|
|
|
|
if (value == "BloodStarExplosion") return MissileGraphicID::BloodStarExplosion; |
|
|
|
|
if (value == "MagmaBall") return MissileGraphicID::MagmaBall; |
|
|
|
|
if (value == "Krull") return MissileGraphicID::Krull; |
|
|
|
|
if (value == "ChargedBolt") return MissileGraphicID::ChargedBolt; |
|
|
|
|
if (value == "HolyBolt") return MissileGraphicID::HolyBolt; |
|
|
|
|
if (value == "HolyBoltExplosion") return MissileGraphicID::HolyBoltExplosion; |
|
|
|
|
if (value == "LightningArrow") return MissileGraphicID::LightningArrow; |
|
|
|
|
if (value == "FireArrowExplosion") return MissileGraphicID::FireArrowExplosion; |
|
|
|
|
if (value == "Acid") return MissileGraphicID::Acid; |
|
|
|
|
if (value == "AcidSplat") return MissileGraphicID::AcidSplat; |
|
|
|
|
if (value == "AcidPuddle") return MissileGraphicID::AcidPuddle; |
|
|
|
|
if (value == "Etherealize") return MissileGraphicID::Etherealize; |
|
|
|
|
if (value == "Elemental") return MissileGraphicID::Elemental; |
|
|
|
|
if (value == "Resurrect") return MissileGraphicID::Resurrect; |
|
|
|
|
if (value == "BoneSpirit") return MissileGraphicID::BoneSpirit; |
|
|
|
|
if (value == "RedPortal") return MissileGraphicID::RedPortal; |
|
|
|
|
if (value == "DiabloApocalypseBoom") return MissileGraphicID::DiabloApocalypseBoom; |
|
|
|
|
if (value == "BloodStarBlue") return MissileGraphicID::BloodStarBlue; |
|
|
|
|
if (value == "BloodStarBlueExplosion") return MissileGraphicID::BloodStarBlueExplosion; |
|
|
|
|
if (value == "BloodStarYellow") return MissileGraphicID::BloodStarYellow; |
|
|
|
|
if (value == "BloodStarYellowExplosion") return MissileGraphicID::BloodStarYellowExplosion; |
|
|
|
|
if (value == "BloodStarRed") return MissileGraphicID::BloodStarRed; |
|
|
|
|
if (value == "BloodStarRedExplosion") return MissileGraphicID::BloodStarRedExplosion; |
|
|
|
|
if (value == "HorkSpawn") return MissileGraphicID::HorkSpawn; |
|
|
|
|
if (value == "Reflect") return MissileGraphicID::Reflect; |
|
|
|
|
if (value == "OrangeFlare") return MissileGraphicID::OrangeFlare; |
|
|
|
|
if (value == "BlueFlare") return MissileGraphicID::BlueFlare; |
|
|
|
|
if (value == "RedFlare") return MissileGraphicID::RedFlare; |
|
|
|
|
if (value == "YellowFlare") return MissileGraphicID::YellowFlare; |
|
|
|
|
if (value == "Rune") return MissileGraphicID::Rune; |
|
|
|
|
if (value == "YellowFlareExplosion") return MissileGraphicID::YellowFlareExplosion; |
|
|
|
|
if (value == "BlueFlareExplosion") return MissileGraphicID::BlueFlareExplosion; |
|
|
|
|
if (value == "RedFlareExplosion") return MissileGraphicID::RedFlareExplosion; |
|
|
|
|
if (value == "BlueFlare2") return MissileGraphicID::BlueFlare2; |
|
|
|
|
if (value == "OrangeFlareExplosion") return MissileGraphicID::OrangeFlareExplosion; |
|
|
|
|
if (value == "BlueFlareExplosion2") return MissileGraphicID::BlueFlareExplosion2; |
|
|
|
|
return tl::make_unexpected("Unknown enum value"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void LoadMissileSpriteData() |
|
|
|
|
{ |
|
|
|
|
const std::string_view filename = "txtdata\\missiles\\missile_sprites.tsv"; |
|
|
|
|
@ -190,7 +133,9 @@ void LoadMissileSpriteData()
|
|
|
|
|
for (DataFileRecord record : dataFile) { |
|
|
|
|
RecordReader reader { record, filename }; |
|
|
|
|
MissileFileData &item = MissileSpriteData.emplace_back(); |
|
|
|
|
reader.advance(); // skip id
|
|
|
|
|
MissileGraphicID id; |
|
|
|
|
reader.read("id", id, ParseMissileGraphicID); |
|
|
|
|
assert(static_cast<size_t>(id) + 1 == MissileSpriteData.size()); |
|
|
|
|
reader.readInt("width", item.animWidth); |
|
|
|
|
reader.readInt("width2", item.animWidth2); |
|
|
|
|
reader.readString("name", item.name); |
|
|
|
|
@ -210,6 +155,237 @@ void LoadMissileSpriteData()
|
|
|
|
|
MissileAnimLengths.shrink_to_fit(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tl::expected<MissileDataFlags, std::string> ParseMissileDataFlag(std::string_view value) |
|
|
|
|
{ |
|
|
|
|
if (value == "Physical") return MissileDataFlags::Physical; |
|
|
|
|
if (value == "Fire") return MissileDataFlags::Fire; |
|
|
|
|
if (value == "Lightning") return MissileDataFlags::Lightning; |
|
|
|
|
if (value == "Magic") return MissileDataFlags::Magic; |
|
|
|
|
if (value == "Acid") return MissileDataFlags::Acid; |
|
|
|
|
if (value == "Arrow") return MissileDataFlags::Arrow; |
|
|
|
|
if (value == "Invisible") return MissileDataFlags::Invisible; |
|
|
|
|
return tl::make_unexpected("Unknown enum value"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
|
|
|
|
tl::expected<MissileData::AddFn, std::string> ParseMissileAddFn(std::string_view value) |
|
|
|
|
{ |
|
|
|
|
if (value.empty()) return nullptr; |
|
|
|
|
if (value == "AddOpenNest") return AddOpenNest; |
|
|
|
|
if (value == "AddRuneOfFire") return AddRuneOfFire; |
|
|
|
|
if (value == "AddRuneOfLight") return AddRuneOfLight; |
|
|
|
|
if (value == "AddRuneOfNova") return AddRuneOfNova; |
|
|
|
|
if (value == "AddRuneOfImmolation") return AddRuneOfImmolation; |
|
|
|
|
if (value == "AddRuneOfStone") return AddRuneOfStone; |
|
|
|
|
if (value == "AddReflect") return AddReflect; |
|
|
|
|
if (value == "AddBerserk") return AddBerserk; |
|
|
|
|
if (value == "AddHorkSpawn") return AddHorkSpawn; |
|
|
|
|
if (value == "AddJester") return AddJester; |
|
|
|
|
if (value == "AddStealPotions") return AddStealPotions; |
|
|
|
|
if (value == "AddStealMana") return AddStealMana; |
|
|
|
|
if (value == "AddSpectralArrow") return AddSpectralArrow; |
|
|
|
|
if (value == "AddWarp") return AddWarp; |
|
|
|
|
if (value == "AddLightningWall") return AddLightningWall; |
|
|
|
|
if (value == "AddBigExplosion") return AddBigExplosion; |
|
|
|
|
if (value == "AddImmolation") return AddImmolation; |
|
|
|
|
if (value == "AddLightningBow") return AddLightningBow; |
|
|
|
|
if (value == "AddMana") return AddMana; |
|
|
|
|
if (value == "AddMagi") return AddMagi; |
|
|
|
|
if (value == "AddRingOfFire") return AddRingOfFire; |
|
|
|
|
if (value == "AddSearch") return AddSearch; |
|
|
|
|
if (value == "AddChargedBoltBow") return AddChargedBoltBow; |
|
|
|
|
if (value == "AddElementalArrow") return AddElementalArrow; |
|
|
|
|
if (value == "AddArrow") return AddArrow; |
|
|
|
|
if (value == "AddPhasing") return AddPhasing; |
|
|
|
|
if (value == "AddFirebolt") return AddFirebolt; |
|
|
|
|
if (value == "AddMagmaBall") return AddMagmaBall; |
|
|
|
|
if (value == "AddTeleport") return AddTeleport; |
|
|
|
|
if (value == "AddNovaBall") return AddNovaBall; |
|
|
|
|
if (value == "AddFireWall") return AddFireWall; |
|
|
|
|
if (value == "AddFireball") return AddFireball; |
|
|
|
|
if (value == "AddLightningControl") return AddLightningControl; |
|
|
|
|
if (value == "AddLightning") return AddLightning; |
|
|
|
|
if (value == "AddMissileExplosion") return AddMissileExplosion; |
|
|
|
|
if (value == "AddWeaponExplosion") return AddWeaponExplosion; |
|
|
|
|
if (value == "AddTownPortal") return AddTownPortal; |
|
|
|
|
if (value == "AddFlashBottom") return AddFlashBottom; |
|
|
|
|
if (value == "AddFlashTop") return AddFlashTop; |
|
|
|
|
if (value == "AddManaShield") return AddManaShield; |
|
|
|
|
if (value == "AddFlameWave") return AddFlameWave; |
|
|
|
|
if (value == "AddGuardian") return AddGuardian; |
|
|
|
|
if (value == "AddChainLightning") return AddChainLightning; |
|
|
|
|
if (value == "AddRhino") return AddRhino; |
|
|
|
|
if (value == "AddGenericMagicMissile") return AddGenericMagicMissile; |
|
|
|
|
if (value == "AddAcid") return AddAcid; |
|
|
|
|
if (value == "AddAcidPuddle") return AddAcidPuddle; |
|
|
|
|
if (value == "AddStoneCurse") return AddStoneCurse; |
|
|
|
|
if (value == "AddGolem") return AddGolem; |
|
|
|
|
if (value == "AddApocalypseBoom") return AddApocalypseBoom; |
|
|
|
|
if (value == "AddHealing") return AddHealing; |
|
|
|
|
if (value == "AddHealOther") return AddHealOther; |
|
|
|
|
if (value == "AddElemental") return AddElemental; |
|
|
|
|
if (value == "AddIdentify") return AddIdentify; |
|
|
|
|
if (value == "AddFireWallControl") return AddFireWallControl; |
|
|
|
|
if (value == "AddInfravision") return AddInfravision; |
|
|
|
|
if (value == "AddFlameWaveControl") return AddFlameWaveControl; |
|
|
|
|
if (value == "AddNova") return AddNova; |
|
|
|
|
if (value == "AddRage") return AddRage; |
|
|
|
|
if (value == "AddItemRepair") return AddItemRepair; |
|
|
|
|
if (value == "AddStaffRecharge") return AddStaffRecharge; |
|
|
|
|
if (value == "AddTrapDisarm") return AddTrapDisarm; |
|
|
|
|
if (value == "AddApocalypse") return AddApocalypse; |
|
|
|
|
if (value == "AddInferno") return AddInferno; |
|
|
|
|
if (value == "AddInfernoControl") return AddInfernoControl; |
|
|
|
|
if (value == "AddChargedBolt") return AddChargedBolt; |
|
|
|
|
if (value == "AddHolyBolt") return AddHolyBolt; |
|
|
|
|
if (value == "AddResurrect") return AddResurrect; |
|
|
|
|
if (value == "AddResurrectBeam") return AddResurrectBeam; |
|
|
|
|
if (value == "AddTelekinesis") return AddTelekinesis; |
|
|
|
|
if (value == "AddBoneSpirit") return AddBoneSpirit; |
|
|
|
|
if (value == "AddRedPortal") return AddRedPortal; |
|
|
|
|
if (value == "AddDiabloApocalypse") return AddDiabloApocalypse; |
|
|
|
|
return tl::make_unexpected("Unknown MissileData::AddFn name"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
|
|
|
|
tl::expected<MissileData::ProcessFn, std::string> ParseMissileProcessFn(std::string_view value) |
|
|
|
|
{ |
|
|
|
|
if (value.empty()) return nullptr; |
|
|
|
|
if (value == "ProcessElementalArrow") return ProcessElementalArrow; |
|
|
|
|
if (value == "ProcessArrow") return ProcessArrow; |
|
|
|
|
if (value == "ProcessGenericProjectile") return ProcessGenericProjectile; |
|
|
|
|
if (value == "ProcessNovaBall") return ProcessNovaBall; |
|
|
|
|
if (value == "ProcessAcidPuddle") return ProcessAcidPuddle; |
|
|
|
|
if (value == "ProcessFireWall") return ProcessFireWall; |
|
|
|
|
if (value == "ProcessFireball") return ProcessFireball; |
|
|
|
|
if (value == "ProcessHorkSpawn") return ProcessHorkSpawn; |
|
|
|
|
if (value == "ProcessRune") return ProcessRune; |
|
|
|
|
if (value == "ProcessLightningWall") return ProcessLightningWall; |
|
|
|
|
if (value == "ProcessBigExplosion") return ProcessBigExplosion; |
|
|
|
|
if (value == "ProcessLightningBow") return ProcessLightningBow; |
|
|
|
|
if (value == "ProcessRingOfFire") return ProcessRingOfFire; |
|
|
|
|
if (value == "ProcessSearch") return ProcessSearch; |
|
|
|
|
if (value == "ProcessLightningWallControl") return ProcessLightningWallControl; |
|
|
|
|
if (value == "ProcessImmolation") return ProcessImmolation; |
|
|
|
|
if (value == "ProcessSpectralArrow") return ProcessSpectralArrow; |
|
|
|
|
if (value == "ProcessLightningControl") return ProcessLightningControl; |
|
|
|
|
if (value == "ProcessLightning") return ProcessLightning; |
|
|
|
|
if (value == "ProcessTownPortal") return ProcessTownPortal; |
|
|
|
|
if (value == "ProcessFlashBottom") return ProcessFlashBottom; |
|
|
|
|
if (value == "ProcessFlashTop") return ProcessFlashTop; |
|
|
|
|
if (value == "ProcessFlameWave") return ProcessFlameWave; |
|
|
|
|
if (value == "ProcessGuardian") return ProcessGuardian; |
|
|
|
|
if (value == "ProcessChainLightning") return ProcessChainLightning; |
|
|
|
|
if (value == "ProcessWeaponExplosion") return ProcessWeaponExplosion; |
|
|
|
|
if (value == "ProcessMissileExplosion") return ProcessMissileExplosion; |
|
|
|
|
if (value == "ProcessAcidSplate") return ProcessAcidSplate; |
|
|
|
|
if (value == "ProcessTeleport") return ProcessTeleport; |
|
|
|
|
if (value == "ProcessStoneCurse") return ProcessStoneCurse; |
|
|
|
|
if (value == "ProcessApocalypseBoom") return ProcessApocalypseBoom; |
|
|
|
|
if (value == "ProcessRhino") return ProcessRhino; |
|
|
|
|
if (value == "ProcessFireWallControl") return ProcessFireWallControl; |
|
|
|
|
if (value == "ProcessInfravision") return ProcessInfravision; |
|
|
|
|
if (value == "ProcessApocalypse") return ProcessApocalypse; |
|
|
|
|
if (value == "ProcessFlameWaveControl") return ProcessFlameWaveControl; |
|
|
|
|
if (value == "ProcessNova") return ProcessNova; |
|
|
|
|
if (value == "ProcessRage") return ProcessRage; |
|
|
|
|
if (value == "ProcessInferno") return ProcessInferno; |
|
|
|
|
if (value == "ProcessInfernoControl") return ProcessInfernoControl; |
|
|
|
|
if (value == "ProcessChargedBolt") return ProcessChargedBolt; |
|
|
|
|
if (value == "ProcessHolyBolt") return ProcessHolyBolt; |
|
|
|
|
if (value == "ProcessElemental") return ProcessElemental; |
|
|
|
|
if (value == "ProcessBoneSpirit") return ProcessBoneSpirit; |
|
|
|
|
if (value == "ProcessResurrectBeam") return ProcessResurrectBeam; |
|
|
|
|
if (value == "ProcessRedPortal") return ProcessRedPortal; |
|
|
|
|
return tl::make_unexpected("Unknown MissileData::ProcessFn name"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// A temporary solution for parsing SfxID until we have a more general one.
|
|
|
|
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
|
|
|
|
tl::expected<SfxID, std::string> ParseCastSound(std::string_view value) |
|
|
|
|
{ |
|
|
|
|
if (value.empty()) return SfxID::None; |
|
|
|
|
if (value == "BigExplosion") return SfxID::BigExplosion; |
|
|
|
|
if (value == "ShootFireballBow") return SfxID::ShootFireballBow; |
|
|
|
|
if (value == "SpellAcid") return SfxID::SpellAcid; |
|
|
|
|
if (value == "SpellApocalypse") return SfxID::SpellApocalypse; |
|
|
|
|
if (value == "SpellBloodStar") return SfxID::SpellBloodStar; |
|
|
|
|
if (value == "SpellBoneSpirit") return SfxID::SpellBoneSpirit; |
|
|
|
|
if (value == "SpellChargedBolt") return SfxID::SpellChargedBolt; |
|
|
|
|
if (value == "SpellDoomSerpents") return SfxID::SpellDoomSerpents; |
|
|
|
|
if (value == "SpellElemental") return SfxID::SpellElemental; |
|
|
|
|
if (value == "SpellEnd") return SfxID::SpellEnd; |
|
|
|
|
if (value == "SpellEtherealize") return SfxID::SpellEtherealize; |
|
|
|
|
if (value == "SpellFireHit") return SfxID::SpellFireHit; |
|
|
|
|
if (value == "SpellFireWall") return SfxID::SpellFireWall; |
|
|
|
|
if (value == "SpellFirebolt") return SfxID::SpellFirebolt; |
|
|
|
|
if (value == "SpellFlameWave") return SfxID::SpellFlameWave; |
|
|
|
|
if (value == "SpellGolem") return SfxID::SpellGolem; |
|
|
|
|
if (value == "SpellGuardian") return SfxID::SpellGuardian; |
|
|
|
|
if (value == "SpellHolyBolt") return SfxID::SpellHolyBolt; |
|
|
|
|
if (value == "SpellInferno") return SfxID::SpellInferno; |
|
|
|
|
if (value == "SpellInfravision") return SfxID::SpellInfravision; |
|
|
|
|
if (value == "SpellInvisibility") return SfxID::SpellInvisibility; |
|
|
|
|
if (value == "SpellLightning") return SfxID::SpellLightning; |
|
|
|
|
if (value == "SpellLightningWall") return SfxID::SpellLightningWall; |
|
|
|
|
if (value == "SpellManaShield") return SfxID::SpellManaShield; |
|
|
|
|
if (value == "SpellNova") return SfxID::SpellNova; |
|
|
|
|
if (value == "SpellPortal") return SfxID::SpellPortal; |
|
|
|
|
if (value == "SpellPuddle") return SfxID::SpellPuddle; |
|
|
|
|
if (value == "SpellStoneCurse") return SfxID::SpellStoneCurse; |
|
|
|
|
if (value == "SpellTeleport") return SfxID::SpellTeleport; |
|
|
|
|
if (value == "SpellTrapDisarm") return SfxID::SpellTrapDisarm; |
|
|
|
|
return tl::make_unexpected("Unknown enum value (only a few are supported for now)"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// A temporary solution for parsing SfxID until we have a more general one.
|
|
|
|
|
tl::expected<SfxID, std::string> ParseHitSound(std::string_view value) |
|
|
|
|
{ |
|
|
|
|
if (value.empty()) return SfxID::None; |
|
|
|
|
if (value == "BigExplosion") return SfxID::BigExplosion; |
|
|
|
|
if (value == "SpellBloodStarHit") return SfxID::SpellBloodStarHit; |
|
|
|
|
if (value == "SpellBoneSpiritHit") return SfxID::SpellBoneSpiritHit; |
|
|
|
|
if (value == "SpellFireHit") return SfxID::SpellFireHit; |
|
|
|
|
if (value == "SpellLightningHit") return SfxID::SpellLightningHit; |
|
|
|
|
if (value == "SpellResurrect") return SfxID::SpellResurrect; |
|
|
|
|
return tl::make_unexpected("Unknown enum value (only a few are supported for now)"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tl::expected<MissileMovementDistribution, std::string> ParseMissileMovementDistribution(std::string_view value) |
|
|
|
|
{ |
|
|
|
|
if (value.empty()) return MissileMovementDistribution::Disabled; |
|
|
|
|
if (value == "Blockable") return MissileMovementDistribution::Blockable; |
|
|
|
|
if (value == "Unblockable") return MissileMovementDistribution::Unblockable; |
|
|
|
|
return tl::make_unexpected("Unknown enum value"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void LoadMisdat() |
|
|
|
|
{ |
|
|
|
|
const std::string_view filename = "txtdata\\missiles\\misdat.tsv"; |
|
|
|
|
DataFile dataFile = DataFile::loadOrDie(filename); |
|
|
|
|
dataFile.skipHeaderOrDie(filename); |
|
|
|
|
|
|
|
|
|
MissilesData.clear(); |
|
|
|
|
MissilesData.reserve(dataFile.numRecords()); |
|
|
|
|
for (DataFileRecord record : dataFile) { |
|
|
|
|
RecordReader reader { record, filename }; |
|
|
|
|
MissileData &item = MissilesData.emplace_back(); |
|
|
|
|
reader.advance(); // skip id
|
|
|
|
|
reader.read("addFn", item.mAddProc, ParseMissileAddFn); |
|
|
|
|
reader.read("processFn", item.mProc, ParseMissileProcessFn); |
|
|
|
|
reader.read("castSound", item.mlSFX, ParseCastSound); |
|
|
|
|
reader.read("hitSound", item.mlSFX, ParseHitSound); |
|
|
|
|
reader.read("graphicId", item.mFileNum, ParseMissileGraphicID); |
|
|
|
|
reader.readEnumList("flags", item.flags, ParseMissileDataFlag); |
|
|
|
|
reader.read("movementDistribution", item.movementDistribution, ParseMissileMovementDistribution); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Sanity check because we do not actually parse the IDs yet.
|
|
|
|
|
assert(static_cast<size_t>(MissileID::LAST) + 1 == MissilesData.size()); |
|
|
|
|
|
|
|
|
|
MissilesData.shrink_to_fit(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
uint8_t MissileFileData::animDelay(uint8_t dir) const |
|
|
|
|
@ -254,6 +430,12 @@ MissileFileData &GetMissileSpriteData(MissileGraphicID graphicId)
|
|
|
|
|
void LoadMissileData() |
|
|
|
|
{ |
|
|
|
|
LoadMissileSpriteData(); |
|
|
|
|
LoadMisdat(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const MissileData &GetMissileData(MissileID missileId) |
|
|
|
|
{ |
|
|
|
|
return MissilesData[static_cast<std::underlying_type_t<MissileID>>(missileId)]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void InitMissileGFX(bool loadHellfireGraphics) |
|
|
|
|
|