Browse Source

Decouple missile movement from game logic (#2322)

pull/2321/head
obligaron 5 years ago committed by GitHub
parent
commit
be53349c2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 218
      Source/misdat.cpp
  2. 19
      Source/misdat.h
  3. 5
      Source/missiles.cpp
  4. 13
      Source/missiles.h
  5. 153
      Source/scrollrt.cpp

218
Source/misdat.cpp

@ -12,115 +12,115 @@ namespace devilution {
/** Data related to each missile ID. */
MissileData missiledata[] = {
// clang-format off
// mAddProc, mProc, mName, mDraw, mType, mResist, mFileNum, miSFX, mlSFX;
{ &AddArrow, &MI_Arrow, MIS_ARROW, true, 0, MISR_NONE, MFILE_ARROWS, SFX_NONE, SFX_NONE },
{ &AddFirebolt, &MI_Firebolt, MIS_FIREBOLT, true, 1, MISR_FIRE, MFILE_FIREBA, LS_FBOLT1, LS_FIRIMP2 },
{ &AddGuardian, &MI_Guardian, MIS_GUARDIAN, true, 1, MISR_NONE, MFILE_GUARD, LS_GUARD, LS_GUARDLAN },
{ &AddRndTeleport, &MI_Teleport, MIS_RNDTELEPORT, false, 1, MISR_NONE, MFILE_NONE, LS_TELEPORT, SFX_NONE },
{ &AddLightball, &MI_Lightball, MIS_LIGHTBALL, true, 1, MISR_LIGHTNING, MFILE_LGHNING, SFX_NONE, SFX_NONE },
{ &AddFirewall, &MI_Firewall, MIS_FIREWALL, true, 1, MISR_FIRE, MFILE_FIREWAL, LS_WALLLOOP, LS_FIRIMP2 },
{ &AddFireball, &MI_Fireball, MIS_FIREBALL, true, 1, MISR_FIRE, MFILE_FIREBA, LS_FBOLT1, LS_FIRIMP2 },
{ &AddLightctrl, &MI_Lightctrl, MIS_LIGHTCTRL, false, 1, MISR_LIGHTNING, MFILE_LGHNING, SFX_NONE, SFX_NONE },
{ &AddLightning, &MI_Lightning, MIS_LIGHTNING, true, 1, MISR_LIGHTNING, MFILE_LGHNING, LS_LNING1, LS_ELECIMP1 },
{ &AddMisexp, &MI_Misexp, MIS_MISEXP, true, 2, MISR_NONE, MFILE_MAGBLOS, SFX_NONE, SFX_NONE },
{ &AddTown, &MI_Town, MIS_TOWN, true, 1, MISR_MAGIC, MFILE_PORTAL, LS_SENTINEL, LS_ELEMENTL },
{ &AddFlash, &MI_Flash, MIS_FLASH, true, 1, MISR_MAGIC, MFILE_BLUEXFR, LS_NOVA, LS_ELECIMP1 },
{ &AddFlash2, &MI_Flash2, MIS_FLASH2, true, 1, MISR_MAGIC, MFILE_BLUEXBK, SFX_NONE, SFX_NONE },
{ &AddManashield, &MI_Manashield, MIS_MANASHIELD, false, 1, MISR_MAGIC, MFILE_MANASHLD, LS_MSHIELD, SFX_NONE },
{ &AddFiremove, &MI_Firemove, MIS_FIREMOVE, true, 1, MISR_FIRE, MFILE_FIREWAL, SFX_NONE, SFX_NONE },
{ &AddChain, &MI_Chain, MIS_CHAIN, true, 1, MISR_LIGHTNING, MFILE_LGHNING, LS_LNING1, LS_ELECIMP1 },
{ nullptr, nullptr, MIS_SENTINAL, true, 1, MISR_LIGHTNING, MFILE_LGHNING, SFX_NONE, SFX_NONE },
{ &AddBloodStar, &MI_Blood, MIS_BLODSTAR, true, 2, MISR_NONE, MFILE_BLOOD, LS_BLODSTAR, LS_BLSIMPT },
{ &AddBone, &MI_Blood, MIS_BONE, true, 2, MISR_NONE, MFILE_BONE, SFX_NONE, SFX_NONE },
{ &AddMetlHit, &MI_Blood, MIS_METLHIT, true, 2, MISR_NONE, MFILE_METLHIT, SFX_NONE, SFX_NONE },
{ &AddRhino, &MI_Rhino, MIS_RHINO, true, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddMagmaball, &MI_Firebolt, MIS_MAGMABALL, true, 1, MISR_FIRE, MFILE_MAGBALL, SFX_NONE, SFX_NONE },
{ &AddLightctrl, &MI_Lightctrl, MIS_LIGHTCTRL2, false, 1, MISR_LIGHTNING, MFILE_THINLGHT, SFX_NONE, SFX_NONE },
{ &AddLightning, &MI_Lightning, MIS_LIGHTNING2, true, 1, MISR_LIGHTNING, MFILE_THINLGHT, SFX_NONE, SFX_NONE },
{ &AddFlare, &MI_Firebolt, MIS_FLARE, true, 1, MISR_MAGIC, MFILE_FLARE, SFX_NONE, SFX_NONE },
{ &AddMisexp, &MI_Misexp, MIS_MISEXP2, true, 2, MISR_MAGIC, MFILE_FLAREEXP, SFX_NONE, SFX_NONE },
{ &AddTeleport, &MI_Teleport, MIS_TELEPORT, false, 1, MISR_NONE, MFILE_NONE, LS_ELEMENTL, SFX_NONE },
{ &AddLArrow, &MI_LArrow, MIS_FARROW, true, 0, MISR_FIRE, MFILE_FARROW, SFX_NONE, SFX_NONE },
{ nullptr, nullptr, MIS_DOOMSERP, false, 1, MISR_MAGIC, MFILE_DOOM, LS_DSERP, SFX_NONE },
{ &AddFireWallA, &MI_Firewall, MIS_FIREWALLA, true, 2, MISR_FIRE, MFILE_FIREWAL, SFX_NONE, SFX_NONE },
{ &AddStone, &MI_Stone, MIS_STONE, false, 1, MISR_MAGIC, MFILE_NONE, LS_SCURIMP, SFX_NONE },
{ &AddDummy, &MI_Dummy, MIS_NULL_1F, true, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ nullptr, nullptr, MIS_INVISIBL, false, 1, MISR_NONE, MFILE_NONE, LS_INVISIBL, SFX_NONE },
{ &AddGolem, &MI_Golem, MIS_GOLEM, false, 1, MISR_NONE, MFILE_NONE, LS_GOLUM, SFX_NONE },
{ &AddEtherealize, &MI_Etherealize, MIS_ETHEREALIZE, true, 1, MISR_NONE, MFILE_ETHRSHLD, LS_ETHEREAL, SFX_NONE },
{ &AddBlodbur, &MI_Blood, MIS_BLODBUR, true, 2, MISR_NONE, MFILE_BLODBUR, SFX_NONE, SFX_NONE },
{ &AddBoom, &MI_Boom, MIS_BOOM, true, 2, MISR_NONE, MFILE_NEWEXP, SFX_NONE, SFX_NONE },
{ &AddHeal, &MI_Dummy, MIS_HEAL, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddFirewallC, &MI_FirewallC, MIS_FIREWALLC, false, 1, MISR_FIRE, MFILE_FIREWAL, SFX_NONE, SFX_NONE },
{ &AddInfra, &MI_Infra, MIS_INFRA, false, 1, MISR_NONE, MFILE_NONE, LS_INFRAVIS, SFX_NONE },
{ &AddIdentify, &MI_Dummy, MIS_IDENTIFY, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddWave, &MI_Wave, MIS_WAVE, true, 1, MISR_FIRE, MFILE_FIREWAL, LS_FLAMWAVE, SFX_NONE },
{ &AddNova, &MI_Nova, MIS_NOVA, true, 1, MISR_LIGHTNING, MFILE_LGHNING, LS_NOVA, SFX_NONE },
{ &AddBlodboil, &MI_Blodboil, MIS_BLODBOIL, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddApoca, &MI_Apoca, MIS_APOCA, true, 1, MISR_MAGIC, MFILE_NEWEXP, LS_APOC, SFX_NONE },
{ &AddRepair, &MI_Dummy, MIS_REPAIR, false, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddRecharge, &MI_Dummy, MIS_RECHARGE, false, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddDisarm, &MI_Dummy, MIS_DISARM, false, 2, MISR_NONE, MFILE_NONE, LS_TRAPDIS, SFX_NONE },
{ &AddFlame, &MI_Flame, MIS_FLAME, true, 1, MISR_FIRE, MFILE_INFERNO, LS_SPOUTSTR, SFX_NONE },
{ &AddFlamec, &MI_Flamec, MIS_FLAMEC, false, 1, MISR_FIRE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddFireman, &MI_Fireman, MIS_FIREMAN, true, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddKrull, &MI_Krull, MIS_KRULL, true, 0, MISR_FIRE, MFILE_KRULL, SFX_NONE, SFX_NONE },
{ &AddCbolt, &MI_Cbolt, MIS_CBOLT, true, 1, MISR_LIGHTNING, MFILE_MINILTNG, LS_CBOLT, SFX_NONE },
{ &AddHbolt, &MI_Hbolt, MIS_HBOLT, true, 1, MISR_NONE, MFILE_HOLY, LS_HOLYBOLT, LS_ELECIMP1 },
{ &AddResurrect, &MI_Dummy, MIS_RESURRECT, false, 1, MISR_MAGIC, MFILE_NONE, SFX_NONE, LS_RESUR },
{ &AddTelekinesis, &MI_Dummy, MIS_TELEKINESIS, false, 1, MISR_NONE, MFILE_NONE, LS_ETHEREAL, SFX_NONE },
{ &AddLArrow, &MI_LArrow, MIS_LARROW, true, 0, MISR_LIGHTNING, MFILE_LARROW, SFX_NONE, SFX_NONE },
{ &AddAcid, &MI_Firebolt, MIS_ACID, true, 1, MISR_ACID, MFILE_ACIDBF, LS_ACID, SFX_NONE },
{ &AddMisexp, &MI_Acidsplat, MIS_MISEXP3, true, 2, MISR_ACID, MFILE_ACIDSPLA, SFX_NONE, SFX_NONE },
{ &AddAcidpud, &MI_Acidpud, MIS_ACIDPUD, true, 2, MISR_ACID, MFILE_ACIDPUD, LS_PUDDLE, SFX_NONE },
{ &AddHealOther, &MI_Dummy, MIS_HEALOTHER, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddElement, &MI_Element, MIS_ELEMENT, true, 1, MISR_FIRE, MFILE_FIRERUN, LS_ELEMENTL, SFX_NONE },
{ &AddResurrectBeam, &MI_ResurrectBeam, MIS_RESURRECTBEAM, true, 1, MISR_NONE, MFILE_RESSUR1, SFX_NONE, SFX_NONE },
{ &AddBoneSpirit, &MI_Bonespirit, MIS_BONESPIRIT, true, 1, MISR_MAGIC, MFILE_SKLBALL, LS_BONESP, LS_BSIMPCT },
{ &AddWeapexp, &MI_Weapexp, MIS_WEAPEXP, true, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddRportal, &MI_Rportal, MIS_RPORTAL, true, 2, MISR_NONE, MFILE_RPORTAL, LS_SENTINEL, LS_ELEMENTL },
{ &AddBoom, &MI_Boom, MIS_BOOM2, true, 2, MISR_NONE, MFILE_FIREPLAR, SFX_NONE, SFX_NONE },
{ &AddDiabApoca, &MI_Dummy, MIS_DIABAPOCA, false, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddMana, &MI_Dummy, MIS_MANA, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddMagi, &MI_Dummy, MIS_MAGI, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddLightningWall, &MI_LightningWall, MIS_LIGHTWALL, true, 1, MISR_LIGHTNING, MFILE_LGHNING, LS_LMAG, LS_ELECIMP1 },
{ &AddFirewallC, &MI_LightningWallC, MIS_LIGHTNINGWALL, false, 1, MISR_LIGHTNING, MFILE_LGHNING, SFX_NONE, SFX_NONE },
{ &AddNova, &MI_FireNova, MIS_IMMOLATION, true, 1, MISR_FIRE, MFILE_FIREBA, LS_FBOLT1, LS_FIRIMP2 },
{ &AddSpecArrow, &MI_SpecArrow, MIS_SPECARROW, true, 0, MISR_NONE, MFILE_ARROWS, SFX_NONE, SFX_NONE },
{ &AddFireNova, &MI_Fireball, MIS_FIRENOVA, true, 1, MISR_FIRE, MFILE_FIREBA, IS_FBALLBOW, LS_FIRIMP2 },
{ &AddLightningArrow, &MI_LightningArrow, MIS_LIGHTARROW, false, 1, MISR_LIGHTNING, MFILE_LGHNING, IS_FBALLBOW, SFX_NONE },
{ &AddCboltArrow, &MI_Cbolt, MIS_CBOLTARROW, true, 1, MISR_LIGHTNING, MFILE_MINILTNG, LS_CBOLT, SFX_NONE },
{ &AddHbolt, &MI_Hbolt, MIS_HBOLTARROW, true, 1, MISR_NONE, MFILE_HOLY, LS_HOLYBOLT, LS_ELECIMP1 },
{ &AddWarp, &MI_Teleport, MIS_WARP, false, 1, MISR_NONE, MFILE_NONE, LS_ETHEREAL, SFX_NONE },
{ &AddReflection, &MI_Reflect, MIS_REFLECT, false, 1, MISR_NONE, MFILE_REFLECT, LS_MSHIELD, SFX_NONE },
{ &AddBerserk, &MI_Dummy, MIS_BERSERK, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddRing, &MI_FireRing, MIS_FIRERING, false, 1, MISR_FIRE, MFILE_FIREWAL, SFX_NONE, SFX_NONE },
{ &AddStealPotions, &MI_Dummy, MIS_STEALPOTS, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddManaTrap, &MI_Dummy, MIS_MANATRAP, false, 1, MISR_NONE, MFILE_NONE, IS_CAST7, SFX_NONE },
{ &AddRing, &MI_LightningRing, MIS_LIGHTRING, false, 1, MISR_LIGHTNING, MFILE_LGHNING, SFX_NONE, SFX_NONE },
{ &AddSearch, &MI_Search, MIS_SEARCH, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ nullptr, nullptr, MIS_FLASHFR, false, 1, MISR_MAGIC, MFILE_BLUEXFR, SFX_NONE, LS_ELECIMP1 },
{ nullptr, nullptr, MIS_FLASHBK, false, 1, MISR_MAGIC, MFILE_BLUEXBK, SFX_NONE, SFX_NONE },
{ &AddImmolation, &MI_Immolation, MIS_IMMOLATION2, true, 1, MISR_FIRE, MFILE_FIREBA, LS_FBOLT1, LS_FIRIMP2 },
{ &AddFireRune, &MI_Rune, MIS_RUNEFIRE, true, 1, MISR_NONE, MFILE_RUNE, SFX_NONE, SFX_NONE },
{ &AddLightningRune, &MI_Rune, MIS_RUNELIGHT, true, 1, MISR_NONE, MFILE_RUNE, SFX_NONE, SFX_NONE },
{ &AddGreatLightningRune, &MI_Rune, MIS_RUNENOVA, true, 1, MISR_NONE, MFILE_RUNE, SFX_NONE, SFX_NONE },
{ &AddImmolationRune, &MI_Rune, MIS_RUNEIMMOLAT, true, 1, MISR_NONE, MFILE_RUNE, SFX_NONE, SFX_NONE },
{ &AddStoneRune, &MI_Rune, MIS_RUNESTONE, true, 1, MISR_NONE, MFILE_RUNE, SFX_NONE, SFX_NONE },
{ &AddRuneExplosion, &MI_HiveExplode, MIS_HIVEEXP, true, 1, MISR_FIRE, MFILE_BIGEXP, LS_NESTXPLD, LS_NESTXPLD },
{ &AddHorkSpawn, &MI_HorkSpawn, MIS_HORKDMN, true, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddJester, &MI_Dummy, MIS_JESTER, false, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddHiveExplosion, &MI_Dummy, MIS_HIVEEXP2, false, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE },
{ &AddFlare, &MI_Firebolt, MIS_LICH, true, 1, MISR_MAGIC, MFILE_LICH, SFX_NONE, SFX_NONE },
{ &AddFlare, &MI_Firebolt, MIS_PSYCHORB, true, 1, MISR_MAGIC, MFILE_BONEDEMON, SFX_NONE, SFX_NONE },
{ &AddFlare, &MI_Firebolt, MIS_NECROMORB, true, 1, MISR_MAGIC, MFILE_NECROMORB, SFX_NONE, SFX_NONE },
{ &AddFlare, &MI_Firebolt, MIS_ARCHLICH, true, 1, MISR_MAGIC, MFILE_ARCHLICH, SFX_NONE, SFX_NONE },
{ &AddFlare, &MI_Firebolt, MIS_BONEDEMON, true, 1, MISR_MAGIC, MFILE_BONEDEMON, SFX_NONE, SFX_NONE },
{ &AddMisexp, &MI_Misexp, MIS_EXYEL2, true, 2, MISR_NONE, MFILE_EXYEL2, LS_FIRIMP2, SFX_NONE },
{ &AddMisexp, &MI_Misexp, MIS_EXRED3, true, 2, MISR_NONE, MFILE_EXRED3, LS_FIRIMP2, SFX_NONE },
{ &AddMisexp, &MI_Misexp, MIS_EXBL2, true, 2, MISR_NONE, MFILE_EXBL2, LS_FIRIMP2, SFX_NONE },
{ &AddMisexp, &MI_Misexp, MIS_EXBL3, true, 2, MISR_NONE, MFILE_EXBL3, LS_FIRIMP2, SFX_NONE },
{ &AddMisexp, &MI_Misexp, MIS_EXORA1, true, 2, MISR_NONE, MFILE_EXORA1, LS_FIRIMP2, SFX_NONE },
// mAddProc, mProc, mName, mDraw, mType, mResist, mFileNum, miSFX, mlSFX, MovementDistribution;
{ &AddArrow, &MI_Arrow, MIS_ARROW, true, 0, MISR_NONE, MFILE_ARROWS, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddFirebolt, &MI_Firebolt, MIS_FIREBOLT, true, 1, MISR_FIRE, MFILE_FIREBA, LS_FBOLT1, LS_FIRIMP2, MissileMovementDistrubution::Blockable },
{ &AddGuardian, &MI_Guardian, MIS_GUARDIAN, true, 1, MISR_NONE, MFILE_GUARD, LS_GUARD, LS_GUARDLAN, MissileMovementDistrubution::Disabled },
{ &AddRndTeleport, &MI_Teleport, MIS_RNDTELEPORT, false, 1, MISR_NONE, MFILE_NONE, LS_TELEPORT, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddLightball, &MI_Lightball, MIS_LIGHTBALL, true, 1, MISR_LIGHTNING, MFILE_LGHNING, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Unblockable },
{ &AddFirewall, &MI_Firewall, MIS_FIREWALL, true, 1, MISR_FIRE, MFILE_FIREWAL, LS_WALLLOOP, LS_FIRIMP2, MissileMovementDistrubution::Disabled },
{ &AddFireball, &MI_Fireball, MIS_FIREBALL, true, 1, MISR_FIRE, MFILE_FIREBA, LS_FBOLT1, LS_FIRIMP2, MissileMovementDistrubution::Blockable },
{ &AddLightctrl, &MI_Lightctrl, MIS_LIGHTCTRL, false, 1, MISR_LIGHTNING, MFILE_LGHNING, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddLightning, &MI_Lightning, MIS_LIGHTNING, true, 1, MISR_LIGHTNING, MFILE_LGHNING, LS_LNING1, LS_ELECIMP1, MissileMovementDistrubution::Disabled },
{ &AddMisexp, &MI_Misexp, MIS_MISEXP, true, 2, MISR_NONE, MFILE_MAGBLOS, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddTown, &MI_Town, MIS_TOWN, true, 1, MISR_MAGIC, MFILE_PORTAL, LS_SENTINEL, LS_ELEMENTL, MissileMovementDistrubution::Disabled },
{ &AddFlash, &MI_Flash, MIS_FLASH, true, 1, MISR_MAGIC, MFILE_BLUEXFR, LS_NOVA, LS_ELECIMP1, MissileMovementDistrubution::Disabled },
{ &AddFlash2, &MI_Flash2, MIS_FLASH2, true, 1, MISR_MAGIC, MFILE_BLUEXBK, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddManashield, &MI_Manashield, MIS_MANASHIELD, false, 1, MISR_MAGIC, MFILE_MANASHLD, LS_MSHIELD, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddFiremove, &MI_Firemove, MIS_FIREMOVE, true, 1, MISR_FIRE, MFILE_FIREWAL, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Unblockable },
{ &AddChain, &MI_Chain, MIS_CHAIN, true, 1, MISR_LIGHTNING, MFILE_LGHNING, LS_LNING1, LS_ELECIMP1, MissileMovementDistrubution::Disabled },
{ nullptr, nullptr, MIS_SENTINAL, true, 1, MISR_LIGHTNING, MFILE_LGHNING, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddBloodStar, &MI_Blood, MIS_BLODSTAR, true, 2, MISR_NONE, MFILE_BLOOD, LS_BLODSTAR, LS_BLSIMPT, MissileMovementDistrubution::Disabled },
{ &AddBone, &MI_Blood, MIS_BONE, true, 2, MISR_NONE, MFILE_BONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddMetlHit, &MI_Blood, MIS_METLHIT, true, 2, MISR_NONE, MFILE_METLHIT, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddRhino, &MI_Rhino, MIS_RHINO, true, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddMagmaball, &MI_Firebolt, MIS_MAGMABALL, true, 1, MISR_FIRE, MFILE_MAGBALL, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddLightctrl, &MI_Lightctrl, MIS_LIGHTCTRL2, false, 1, MISR_LIGHTNING, MFILE_THINLGHT, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddLightning, &MI_Lightning, MIS_LIGHTNING2, true, 1, MISR_LIGHTNING, MFILE_THINLGHT, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddFlare, &MI_Firebolt, MIS_FLARE, true, 1, MISR_MAGIC, MFILE_FLARE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddMisexp, &MI_Misexp, MIS_MISEXP2, true, 2, MISR_MAGIC, MFILE_FLAREEXP, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddTeleport, &MI_Teleport, MIS_TELEPORT, false, 1, MISR_NONE, MFILE_NONE, LS_ELEMENTL, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddLArrow, &MI_LArrow, MIS_FARROW, true, 0, MISR_FIRE, MFILE_FARROW, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ nullptr, nullptr, MIS_DOOMSERP, false, 1, MISR_MAGIC, MFILE_DOOM, LS_DSERP, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddFireWallA, &MI_Firewall, MIS_FIREWALLA, true, 2, MISR_FIRE, MFILE_FIREWAL, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddStone, &MI_Stone, MIS_STONE, false, 1, MISR_MAGIC, MFILE_NONE, LS_SCURIMP, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddDummy, &MI_Dummy, MIS_NULL_1F, true, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ nullptr, nullptr, MIS_INVISIBL, false, 1, MISR_NONE, MFILE_NONE, LS_INVISIBL, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddGolem, &MI_Golem, MIS_GOLEM, false, 1, MISR_NONE, MFILE_NONE, LS_GOLUM, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddEtherealize, &MI_Etherealize, MIS_ETHEREALIZE, true, 1, MISR_NONE, MFILE_ETHRSHLD, LS_ETHEREAL, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddBlodbur, &MI_Blood, MIS_BLODBUR, true, 2, MISR_NONE, MFILE_BLODBUR, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddBoom, &MI_Boom, MIS_BOOM, true, 2, MISR_NONE, MFILE_NEWEXP, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddHeal, &MI_Dummy, MIS_HEAL, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddFirewallC, &MI_FirewallC, MIS_FIREWALLC, false, 1, MISR_FIRE, MFILE_FIREWAL, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddInfra, &MI_Infra, MIS_INFRA, false, 1, MISR_NONE, MFILE_NONE, LS_INFRAVIS, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddIdentify, &MI_Dummy, MIS_IDENTIFY, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddWave, &MI_Wave, MIS_WAVE, true, 1, MISR_FIRE, MFILE_FIREWAL, LS_FLAMWAVE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddNova, &MI_Nova, MIS_NOVA, true, 1, MISR_LIGHTNING, MFILE_LGHNING, LS_NOVA, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddBlodboil, &MI_Blodboil, MIS_BLODBOIL, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddApoca, &MI_Apoca, MIS_APOCA, true, 1, MISR_MAGIC, MFILE_NEWEXP, LS_APOC, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddRepair, &MI_Dummy, MIS_REPAIR, false, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddRecharge, &MI_Dummy, MIS_RECHARGE, false, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddDisarm, &MI_Dummy, MIS_DISARM, false, 2, MISR_NONE, MFILE_NONE, LS_TRAPDIS, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddFlame, &MI_Flame, MIS_FLAME, true, 1, MISR_FIRE, MFILE_INFERNO, LS_SPOUTSTR, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddFlamec, &MI_Flamec, MIS_FLAMEC, false, 1, MISR_FIRE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddFireman, &MI_Fireman, MIS_FIREMAN, true, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddKrull, &MI_Krull, MIS_KRULL, true, 0, MISR_FIRE, MFILE_KRULL, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddCbolt, &MI_Cbolt, MIS_CBOLT, true, 1, MISR_LIGHTNING, MFILE_MINILTNG, LS_CBOLT, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddHbolt, &MI_Hbolt, MIS_HBOLT, true, 1, MISR_NONE, MFILE_HOLY, LS_HOLYBOLT, LS_ELECIMP1, MissileMovementDistrubution::Blockable },
{ &AddResurrect, &MI_Dummy, MIS_RESURRECT, false, 1, MISR_MAGIC, MFILE_NONE, SFX_NONE, LS_RESUR, MissileMovementDistrubution::Disabled },
{ &AddTelekinesis, &MI_Dummy, MIS_TELEKINESIS, false, 1, MISR_NONE, MFILE_NONE, LS_ETHEREAL, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddLArrow, &MI_LArrow, MIS_LARROW, true, 0, MISR_LIGHTNING, MFILE_LARROW, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddAcid, &MI_Firebolt, MIS_ACID, true, 1, MISR_ACID, MFILE_ACIDBF, LS_ACID, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddMisexp, &MI_Acidsplat, MIS_MISEXP3, true, 2, MISR_ACID, MFILE_ACIDSPLA, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddAcidpud, &MI_Acidpud, MIS_ACIDPUD, true, 2, MISR_ACID, MFILE_ACIDPUD, LS_PUDDLE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddHealOther, &MI_Dummy, MIS_HEALOTHER, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddElement, &MI_Element, MIS_ELEMENT, true, 1, MISR_FIRE, MFILE_FIRERUN, LS_ELEMENTL, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddResurrectBeam, &MI_ResurrectBeam, MIS_RESURRECTBEAM, true, 1, MISR_NONE, MFILE_RESSUR1, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddBoneSpirit, &MI_Bonespirit, MIS_BONESPIRIT, true, 1, MISR_MAGIC, MFILE_SKLBALL, LS_BONESP, LS_BSIMPCT, MissileMovementDistrubution::Blockable },
{ &AddWeapexp, &MI_Weapexp, MIS_WEAPEXP, true, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddRportal, &MI_Rportal, MIS_RPORTAL, true, 2, MISR_NONE, MFILE_RPORTAL, LS_SENTINEL, LS_ELEMENTL, MissileMovementDistrubution::Disabled },
{ &AddBoom, &MI_Boom, MIS_BOOM2, true, 2, MISR_NONE, MFILE_FIREPLAR, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddDiabApoca, &MI_Dummy, MIS_DIABAPOCA, false, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddMana, &MI_Dummy, MIS_MANA, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddMagi, &MI_Dummy, MIS_MAGI, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddLightningWall, &MI_LightningWall, MIS_LIGHTWALL, true, 1, MISR_LIGHTNING, MFILE_LGHNING, LS_LMAG, LS_ELECIMP1, MissileMovementDistrubution::Disabled },
{ &AddFirewallC, &MI_LightningWallC, MIS_LIGHTNINGWALL, false, 1, MISR_LIGHTNING, MFILE_LGHNING, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddNova, &MI_FireNova, MIS_IMMOLATION, true, 1, MISR_FIRE, MFILE_FIREBA, LS_FBOLT1, LS_FIRIMP2, MissileMovementDistrubution::Disabled },
{ &AddSpecArrow, &MI_SpecArrow, MIS_SPECARROW, true, 0, MISR_NONE, MFILE_ARROWS, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddFireNova, &MI_Fireball, MIS_FIRENOVA, true, 1, MISR_FIRE, MFILE_FIREBA, IS_FBALLBOW, LS_FIRIMP2, MissileMovementDistrubution::Blockable },
{ &AddLightningArrow, &MI_LightningArrow, MIS_LIGHTARROW, false, 1, MISR_LIGHTNING, MFILE_LGHNING, IS_FBALLBOW, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddCboltArrow, &MI_Cbolt, MIS_CBOLTARROW, true, 1, MISR_LIGHTNING, MFILE_MINILTNG, LS_CBOLT, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddHbolt, &MI_Hbolt, MIS_HBOLTARROW, true, 1, MISR_NONE, MFILE_HOLY, LS_HOLYBOLT, LS_ELECIMP1, MissileMovementDistrubution::Blockable },
{ &AddWarp, &MI_Teleport, MIS_WARP, false, 1, MISR_NONE, MFILE_NONE, LS_ETHEREAL, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddReflection, &MI_Reflect, MIS_REFLECT, false, 1, MISR_NONE, MFILE_REFLECT, LS_MSHIELD, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddBerserk, &MI_Dummy, MIS_BERSERK, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddRing, &MI_FireRing, MIS_FIRERING, false, 1, MISR_FIRE, MFILE_FIREWAL, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddStealPotions, &MI_Dummy, MIS_STEALPOTS, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddManaTrap, &MI_Dummy, MIS_MANATRAP, false, 1, MISR_NONE, MFILE_NONE, IS_CAST7, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddRing, &MI_LightningRing, MIS_LIGHTRING, false, 1, MISR_LIGHTNING, MFILE_LGHNING, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddSearch, &MI_Search, MIS_SEARCH, false, 1, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ nullptr, nullptr, MIS_FLASHFR, false, 1, MISR_MAGIC, MFILE_BLUEXFR, SFX_NONE, LS_ELECIMP1, MissileMovementDistrubution::Disabled },
{ nullptr, nullptr, MIS_FLASHBK, false, 1, MISR_MAGIC, MFILE_BLUEXBK, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddImmolation, &MI_Immolation, MIS_IMMOLATION2, true, 1, MISR_FIRE, MFILE_FIREBA, LS_FBOLT1, LS_FIRIMP2, MissileMovementDistrubution::Disabled },
{ &AddFireRune, &MI_Rune, MIS_RUNEFIRE, true, 1, MISR_NONE, MFILE_RUNE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddLightningRune, &MI_Rune, MIS_RUNELIGHT, true, 1, MISR_NONE, MFILE_RUNE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddGreatLightningRune, &MI_Rune, MIS_RUNENOVA, true, 1, MISR_NONE, MFILE_RUNE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddImmolationRune, &MI_Rune, MIS_RUNEIMMOLAT, true, 1, MISR_NONE, MFILE_RUNE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddStoneRune, &MI_Rune, MIS_RUNESTONE, true, 1, MISR_NONE, MFILE_RUNE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddRuneExplosion, &MI_HiveExplode, MIS_HIVEEXP, true, 1, MISR_FIRE, MFILE_BIGEXP, LS_NESTXPLD, LS_NESTXPLD, MissileMovementDistrubution::Disabled },
{ &AddHorkSpawn, &MI_HorkSpawn, MIS_HORKDMN, true, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddJester, &MI_Dummy, MIS_JESTER, false, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddHiveExplosion, &MI_Dummy, MIS_HIVEEXP2, false, 2, MISR_NONE, MFILE_NONE, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddFlare, &MI_Firebolt, MIS_LICH, true, 1, MISR_MAGIC, MFILE_LICH, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddFlare, &MI_Firebolt, MIS_PSYCHORB, true, 1, MISR_MAGIC, MFILE_BONEDEMON, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddFlare, &MI_Firebolt, MIS_NECROMORB, true, 1, MISR_MAGIC, MFILE_NECROMORB, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddFlare, &MI_Firebolt, MIS_ARCHLICH, true, 1, MISR_MAGIC, MFILE_ARCHLICH, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddFlare, &MI_Firebolt, MIS_BONEDEMON, true, 1, MISR_MAGIC, MFILE_BONEDEMON, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddMisexp, &MI_Misexp, MIS_EXYEL2, true, 2, MISR_NONE, MFILE_EXYEL2, LS_FIRIMP2, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddMisexp, &MI_Misexp, MIS_EXRED3, true, 2, MISR_NONE, MFILE_EXRED3, LS_FIRIMP2, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddMisexp, &MI_Misexp, MIS_EXBL2, true, 2, MISR_NONE, MFILE_EXBL2, LS_FIRIMP2, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddMisexp, &MI_Misexp, MIS_EXBL3, true, 2, MISR_NONE, MFILE_EXBL3, LS_FIRIMP2, SFX_NONE, MissileMovementDistrubution::Disabled },
{ &AddMisexp, &MI_Misexp, MIS_EXORA1, true, 2, MISR_NONE, MFILE_EXORA1, LS_FIRIMP2, SFX_NONE, MissileMovementDistrubution::Disabled },
// clang-format on
};

19
Source/misdat.h

@ -90,6 +90,24 @@ typedef enum missile_graphic_id : uint8_t {
MFILE_NONE, // BUGFIX: should be `MFILE_NONE = MFILE_SCBSEXPD+1`, i.e. MFILE_NULL, since there would otherwise be an out-of-bounds in SetMissAnim when accessing misfiledata for any of the missiles that have MFILE_NONE as mFileNum in missiledata. (fixed)
} missile_graphic_id;
/**
* @brief Specifies what if and how movement distribution is applied
*/
enum class MissileMovementDistrubution {
/**
* @brief No movement distribution is calculated. Normally this means the missile doesn't move at all.
*/
Disabled,
/**
* @brief The missile moves and if it hits a enemey it stops (for example firebolt)
*/
Blockable,
/**
* @brief The missile moves and even it hits a enemy it keeps moving (for example flame wave)
*/
Unblockable,
};
typedef struct MissileData {
void (*mAddProc)(int, Point, Point, int, int8_t, int, int);
void (*mProc)(int);
@ -100,6 +118,7 @@ typedef struct MissileData {
uint8_t mFileNum;
_sfx_id mlSFX;
_sfx_id miSFX;
MissileMovementDistrubution MovementDistribution;
} MissileData;
typedef struct MisFileData {

5
Source/missiles.cpp

@ -2103,6 +2103,9 @@ void AddMisexp(int mi, Point /*src*/, Point dst, int /*midir*/, int8_t mienemy,
missile[mi].position.offset = missile[dst.x].position.offset;
missile[mi].position.traveled = missile[dst.x].position.traveled;
missile[mi].position.velocity = { 0, 0 };
missile[mi].position.renderingIsFixed = true;
missile[mi].position.tileForRendering = missile[dst.x].position.tileForRendering;
missile[mi].position.offsetForRendering = missile[dst.x].position.offsetForRendering;
missile[mi]._mirange = missile[mi]._miAnimLen;
missile[mi]._miVar1 = 0;
}
@ -3203,6 +3206,7 @@ void MI_Firebolt(int i)
break;
case MIS_BONESPIRIT:
SetMissDir(i, DIR_OMNI);
missile[i].position.velocity = {};
missile[i]._mirange = 7;
missile[i]._miDelFlag = false;
PutMissile(i);
@ -4732,6 +4736,7 @@ void MI_Bonespirit(int i)
}
if (missile[i]._mirange == 0) {
SetMissDir(i, DIR_OMNI);
missile[i].position.velocity = {};
missile[i]._mirange = 7;
}
PutMissile(i);

13
Source/missiles.h

@ -33,6 +33,19 @@ struct MissilePosition {
Point start;
/** Start position */
Displacement traveled;
/**
* @brief Specifies the location (tile) while rendering
*/
Point tileForRendering;
/**
* @brief Specifies the location (offset) while rendering
*/
Displacement offsetForRendering;
/**
* @brief tileForRendering and offsetForRendering shouldn't be updated while rendering. This is needed for explosion.
*/
bool renderingIsFixed;
};
/*

153
Source/scrollrt.cpp

@ -38,6 +38,130 @@
namespace devilution {
namespace {
/**
* @brief Hash algorithm for point
*/
struct PointHash {
std::size_t operator()(Point const &s) const noexcept
{
return s.x ^ (s.y << 1);
}
};
/**
* @brief Contains all Missile at rendering position
*/
std::unordered_multimap<Point, MissileStruct*, PointHash> MissilesAtRenderingTile;
/**
* @brief Could the missile (at the next game tick) collide? This method is a simplified version of CheckMissileCol (for example without random).
*/
bool CouldMissileCollide(Point tile, bool checkPlayerAndMonster)
{
if (tile.x >= MAXDUNX || tile.x < 0)
return true;
if (tile.y >= MAXDUNY || tile.y < 0)
return true;
if (checkPlayerAndMonster) {
if (dMonster[tile.x][tile.y] > 0)
return true;
if (dPlayer[tile.x][tile.y] > 0)
return true;
}
int oid = dObject[tile.x][tile.y];
if (oid != 0) {
oid = oid > 0 ? oid - 1 : -(oid + 1);
if (!object[oid]._oMissFlag)
return true;
}
if (nMissileTable[dPiece[tile.x][tile.y]])
return true;
return false;
}
void UpdateMissileRendererData(MissileStruct &m)
{
if (m.position.renderingIsFixed)
return;
m.position.tileForRendering = m.position.tile;
m.position.offsetForRendering = m.position.offset;
const MissileMovementDistrubution missileMovement = missiledata[m._mitype].MovementDistribution;
// don't calculate missile position if they don't move
if (missileMovement == MissileMovementDistrubution::Disabled)
return;
// when some missiles hit, they change there animation to a explosion and the explosion shouldn't move (for example fireball)
if (missiledata[m._mitype].mFileNum != m._miAnimType)
return;
float fProgress = gfProgressToNextGameTick;
Displacement velocity = m.position.velocity * fProgress;
Displacement traveled = m.position.traveled + velocity;
int mx = traveled.deltaX >> 16;
int my = traveled.deltaY >> 16;
int dx = (mx + 2 * my) / 64;
int dy = (2 * my - mx) / 64;
// calculcate the future missile position
m.position.tileForRendering = m.position.start + Displacement { dx, dy };
m.position.offsetForRendering = { mx + (dy * 32) - (dx * 32), my - (dx * 16) - (dy * 16) };
// In some cases this calculcated position is invalid.
// For example a missile shouldn't move inside a wall.
// In this case the game logic don't advance the missile position and removes the missile or shows an explosion animation at the old position.
// For the animation distribution logic this means we are not allowed to move to a tile where the missile could collide, cause this could be a invalid position.
// If we are still at the current tile, this tile was already checked and is a valid tile
if (m.position.tileForRendering == m.position.tile)
return;
// If no collision can happen at the new tile we can advance
if (!CouldMissileCollide(m.position.tileForRendering, missileMovement == MissileMovementDistrubution::Blockable))
return;
// The new tile could be invalid, so don't advance to it.
// We search the last offset that is in the old (valid) tile.
// Implementation note: If someone knows the correct math to calculate this without the loop, I would really appreciate it.
while (m.position.tile != m.position.tileForRendering) {
fProgress -= 0.01f;
if (fProgress <= 0.0f) {
m.position.tileForRendering = m.position.tile;
m.position.offsetForRendering = m.position.offset;
return;
}
velocity = m.position.velocity * fProgress;
traveled = m.position.traveled + velocity;
mx = traveled.deltaX >> 16;
my = traveled.deltaY >> 16;
dx = (mx + 2 * my) / 64;
dy = (2 * my - mx) / 64;
m.position.tileForRendering = m.position.start + Displacement { dx, dy };
m.position.offsetForRendering = { mx + (dy * 32) - (dx * 32), my - (dx * 16) - (dy * 16) };
}
}
void UpdateMissilesRendererData()
{
MissilesAtRenderingTile.clear();
for (int i = 0; i < nummissiles; i++) {
assert(missileactive[i] < MAXMISSILES);
MissileStruct &m = missile[missileactive[i]];
UpdateMissileRendererData(m);
MissilesAtRenderingTile.insert(std::make_pair(m.position.tileForRendering, &m));
}
}
}
/**
* Specifies the current light entry.
*/
@ -240,7 +364,7 @@ static void DrawCursor(const Surface &out)
* @param sy Output buffer coordinate
* @param pre Is the sprite in the background
*/
void DrawMissilePrivate(const Surface &out, MissileStruct *m, int sx, int sy, bool pre)
void DrawMissilePrivate(const Surface&out, const MissileStruct *m, int sx, int sy, bool pre)
{
if (m->_miPreFlag != pre || !m->_miDrawFlag)
return;
@ -256,8 +380,8 @@ void DrawMissilePrivate(const Surface &out, MissileStruct *m, int sx, int sy, bo
Log("Draw Missile 2: frame {} of {}, missile type=={}", nCel, frames, m->_mitype);
return;
}
int mx = sx + m->position.offset.deltaX - m->_miAnimWidth2;
int my = sy + m->position.offset.deltaY;
int mx = sx + m->position.offsetForRendering.deltaX - m->_miAnimWidth2;
int my = sy + m->position.offsetForRendering.deltaY;
CelSprite cel { m->_miAnimData, m->_miAnimWidth };
if (m->_miUniqTrans != 0)
Cl2DrawLightTbl(out, mx, my, cel, m->_miAnimFrame, m->_miUniqTrans + 3);
@ -278,24 +402,9 @@ void DrawMissilePrivate(const Surface &out, MissileStruct *m, int sx, int sy, bo
*/
void DrawMissile(const Surface &out, int x, int y, int sx, int sy, bool pre)
{
int i;
MissileStruct *m;
if ((dFlags[x][y] & BFLAG_MISSILE) == 0)
return;
if (dMissile[x][y] > 0) {
m = &missile[dMissile[x][y] - 1];
DrawMissilePrivate(out, m, sx, sy, pre);
return;
}
for (i = 0; i < nummissiles; i++) {
assert(missileactive[i] < MAXMISSILES);
m = &missile[missileactive[i]];
if (m->position.tile.x != x || m->position.tile.y != y)
continue;
DrawMissilePrivate(out, m, sx, sy, pre);
const auto range = MissilesAtRenderingTile.equal_range(Point { x, y });
for (auto it = range.first; it != range.second; ++it) {
DrawMissilePrivate(out, it->second, sx, sy, pre);
}
}
@ -1201,6 +1310,8 @@ static void DrawGame(const Surface &fullOut, int x, int y)
}
}
UpdateMissilesRendererData();
// Draw areas moving in and out of the screen
switch (ScrollInfo._sdir) {
case SDIR_N:

Loading…
Cancel
Save