You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
401 lines
14 KiB
401 lines
14 KiB
/** |
|
* @file missiles.h |
|
* |
|
* Interface of missile functionality. |
|
*/ |
|
#pragma once |
|
|
|
#include <cstdint> |
|
#include <list> |
|
|
|
#include "engine.h" |
|
#include "engine/point.hpp" |
|
#include "miniwin/miniwin.h" |
|
#include "misdat.h" |
|
#include "monster.h" |
|
#include "player.h" |
|
#include "spelldat.h" |
|
|
|
namespace devilution { |
|
|
|
constexpr Point GolemHoldingCell = Point { 1, 0 }; |
|
|
|
struct MissilePosition { |
|
Point tile; |
|
/** Sprite's pixel offset from tile. */ |
|
Displacement offset; |
|
/** Pixel velocity while moving */ |
|
Displacement velocity; |
|
/** Start position */ |
|
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 Stops the missile (set velocity to zero and set offset to last renderer location; shouldn't matter cause the missile don't move anymore) |
|
*/ |
|
void StopMissile() |
|
{ |
|
velocity = {}; |
|
if (tileForRendering == tile) |
|
offset = offsetForRendering; |
|
} |
|
}; |
|
|
|
/** |
|
* Represent a more fine-grained direction than the 8 value Direction enum. |
|
* |
|
* This is used when rendering projectiles like arrows which have additional sprites for "half-winds" on a 16-point compass. |
|
* The sprite sheets are typically 0-indexed and use the following layout (relative to the screen projection) |
|
* |
|
* W WSW SW SSW S |
|
* ^ |
|
* WNW | SSE |
|
* | |
|
* NW -------+------> SE |
|
* | |
|
* NNW | ESE |
|
* | |
|
* N NNE NE ENE E |
|
*/ |
|
enum class Direction16 { |
|
South, |
|
South_SouthWest, |
|
SouthWest, |
|
West_SouthWest, |
|
West, |
|
West_NorthWest, |
|
NorthWest, |
|
North_NorthWest, |
|
North, |
|
North_NorthEast, |
|
NorthEast, |
|
East_NorthEast, |
|
East, |
|
East_SouthEast, |
|
SouthEast, |
|
South_SouthEast, |
|
}; |
|
|
|
struct Missile { |
|
/** Type of projectile */ |
|
missile_id _mitype; |
|
MissilePosition position; |
|
int _mimfnum; // The direction of the missile (direction enum) |
|
int _mispllvl; |
|
bool _miDelFlag; // Indicate whether the missile should be deleted |
|
uint8_t _miAnimType; |
|
MissileDataFlags _miAnimFlags; |
|
const byte *_miAnimData; |
|
int _miAnimDelay; // Tick length of each frame in the current animation |
|
int _miAnimLen; // Number of frames in current animation |
|
uint16_t _miAnimWidth; |
|
int16_t _miAnimWidth2; |
|
int _miAnimCnt; // Increases by one each game tick, counting how close we are to _pAnimDelay |
|
int _miAnimAdd; |
|
int _miAnimFrame; // Current frame of animation + 1. |
|
bool _miDrawFlag; |
|
bool _miLightFlag; |
|
bool _miPreFlag; |
|
uint32_t _miUniqTrans; |
|
int _mirange; // Time to live for the missile in game ticks, oncs 0 the missile will be marked for deletion via _miDelFlag |
|
int _misource; |
|
mienemy_type _micaster; |
|
int _midam; |
|
bool _miHitFlag; |
|
int _midist; // Used for arrows to measure distance travelled (increases by 1 each game tick). Higher value is a penalty for accuracy calculation when hitting enemy |
|
int _mlid; |
|
int _mirnd; |
|
int var1; |
|
int var2; |
|
int var3; |
|
int var4; |
|
int var5; |
|
int var6; |
|
int var7; |
|
bool limitReached; |
|
/** |
|
* @brief For moving missiles lastCollisionTargetHash contains the last entity (player or monster) that was checked in CheckMissileCol (needed to avoid multiple hits for a entity at the same tile). |
|
*/ |
|
int16_t lastCollisionTargetHash; |
|
|
|
/** @brief Was the missile generated by a trap? */ |
|
[[nodiscard]] bool IsTrap() const |
|
{ |
|
return _misource == -1; |
|
} |
|
}; |
|
|
|
extern std::list<Missile> Missiles; |
|
extern bool MissilePreFlag; |
|
|
|
void GetDamageAmt(spell_id i, int *mind, int *maxd); |
|
|
|
/** |
|
* @brief Returns the direction a vector from p1(x1, y1) to p2(x2, y2) is pointing to. |
|
* |
|
* @code{.unparsed} |
|
* W sW SW Sw S |
|
* ^ |
|
* nW | Se |
|
* | |
|
* NW ------+-----> SE |
|
* | |
|
* Nw | sE |
|
* | |
|
* N Ne NE nE E |
|
* @endcode |
|
* |
|
* @param p1 The point from which the vector starts. |
|
* @param p2 The point from which the vector ends. |
|
* @return the direction of the p1->p2 vector |
|
*/ |
|
Direction16 GetDirection16(Point p1, Point p2); |
|
bool MonsterTrapHit(int monsterId, int mindam, int maxdam, int dist, missile_id t, bool shift); |
|
bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, missile_id mtype, bool shift, int earflag, bool *blocked); |
|
|
|
/** |
|
* @brief Could the missile collide with solid objects? (like walls or closed doors) |
|
*/ |
|
bool IsMissileBlockedByTile(Point position); |
|
|
|
/** |
|
* @brief Sets the missile sprite to the given sheet frame |
|
* @param missile this object |
|
* @param dir Sprite frame, typically representing a direction but there are some exceptions (arrows being 1 indexed, directionless spells) |
|
*/ |
|
void SetMissDir(Missile &missile, int dir); |
|
|
|
/** |
|
* @brief Sets the sprite for this missile so it matches the given Direction |
|
* @param missile this object |
|
* @param dir Desired facing |
|
*/ |
|
inline void SetMissDir(Missile &missile, Direction dir) |
|
{ |
|
SetMissDir(missile, static_cast<int>(dir)); |
|
} |
|
|
|
/** |
|
* @brief Sets the sprite for this missile so it matches the given Direction16 |
|
* @param missile this object |
|
* @param dir Desired facing at a 22.8125 degree resolution |
|
*/ |
|
inline void SetMissDir(Missile &missile, Direction16 dir) |
|
{ |
|
SetMissDir(missile, static_cast<int>(dir)); |
|
} |
|
|
|
void InitMissiles(); |
|
|
|
struct AddMissileParameter { |
|
Point dst; |
|
Direction midir; |
|
Missile *pParent; |
|
}; |
|
|
|
void AddHiveExplosion(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddFireRune(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddLightningRune(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddGreatLightningRune(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddImmolationRune(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddStoneRune(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddReflection(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddBerserk(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: Direction to place the spawn |
|
*/ |
|
void AddHorkSpawn(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddJester(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddStealPotions(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddManaTrap(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddSpecArrow(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddWarp(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddLightningWall(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddRuneExplosion(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddFireNova(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddLightningArrow(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddMana(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddMagi(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddRing(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddSearch(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddCboltArrow(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddLArrow(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddArrow(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddRndTeleport(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddFirebolt(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddMagmaball(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddTeleport(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddLightball(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddFirewall(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: X coordinate of the missile-light |
|
* var2: Y coordinate of the missile-light |
|
* var4: X coordinate of the missile-light |
|
* var5: Y coordinate of the missile-light |
|
*/ |
|
void AddFireball(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: X coordinate of the missile |
|
* var2: Y coordinate of the missile |
|
*/ |
|
void AddLightctrl(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddLightning(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddMisexp(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddWeapexp(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: Animation |
|
*/ |
|
void AddTown(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddFlash(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddFlash2(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddManashield(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddFiremove(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: Animation |
|
* var3: Light strength |
|
*/ |
|
void AddGuardian(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: X coordinate of the destination |
|
* var2: Y coordinate of the destination |
|
*/ |
|
void AddChain(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddRhino(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: X coordinate of the missile-light |
|
* var2: Y coordinate of the missile-light |
|
*/ |
|
void AddFlare(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: X coordinate of the missile-light |
|
* var2: Y coordinate of the missile-light |
|
*/ |
|
void AddAcid(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddAcidpud(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: mmode of the monster |
|
* var2: mnum of the monster |
|
*/ |
|
void AddStone(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddGolem(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddBoom(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddHeal(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddHealOther(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: X coordinate of the missile-light |
|
* var2: Y coordinate of the missile-light |
|
* var4: X coordinate of the destination |
|
* var5: Y coordinate of the destination |
|
*/ |
|
void AddElement(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddIdentify(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: X coordinate of the first wave |
|
* var2: Y coordinate of the first wave |
|
* var3: Direction of the first wave |
|
* var4: Direction of the second wave |
|
* var5: X coordinate of the second wave |
|
* var6: Y coordinate of the second wave |
|
*/ |
|
void AddFirewallC(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddInfra(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: X coordinate of the destination |
|
* var2: Y coordinate of the destination |
|
*/ |
|
void AddWave(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddNova(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddBlodboil(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddRepair(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddRecharge(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddDisarm(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddApoca(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddFlame(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddFlamec(Missile &missile, const AddMissileParameter ¶meter); |
|
|
|
/** |
|
* var1: Light strength |
|
* var2: Base direction |
|
*/ |
|
void AddCbolt(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddHbolt(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddResurrect(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddResurrectBeam(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddTelekinesis(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddBoneSpirit(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddRportal(Missile &missile, const AddMissileParameter ¶meter); |
|
void AddDiabApoca(Missile &missile, const AddMissileParameter ¶meter); |
|
Missile *AddMissile(Point src, Point dst, Direction midir, missile_id mitype, mienemy_type micaster, int id, int midam, int spllvl, Missile *pParent = nullptr); |
|
void MI_LArrow(Missile &missile); |
|
void MI_Arrow(Missile &missile); |
|
void MI_Firebolt(Missile &missile); |
|
void MI_Lightball(Missile &missilei); |
|
void MI_Acidpud(Missile &missile); |
|
void MI_Firewall(Missile &missile); |
|
void MI_Fireball(Missile &missile); |
|
void MI_HorkSpawn(Missile &missile); |
|
void MI_Rune(Missile &missile); |
|
void MI_LightningWall(Missile &missile); |
|
void MI_HiveExplode(Missile &missile); |
|
void MI_LightningArrow(Missile &missile); |
|
void MI_FireRing(Missile &missile); |
|
void MI_Search(Missile &missile); |
|
void MI_LightningWallC(Missile &missile); |
|
void MI_FireNova(Missile &missile); |
|
void MI_SpecArrow(Missile &missile); |
|
void MI_Lightctrl(Missile &missile); |
|
void MI_Lightning(Missile &missile); |
|
void MI_Town(Missile &missile); |
|
void MI_Flash(Missile &missile); |
|
void MI_Flash2(Missile &missile); |
|
void MI_Firemove(Missile &missile); |
|
void MI_Guardian(Missile &missile); |
|
void MI_Chain(Missile &missile); |
|
void MI_Weapexp(Missile &missile); |
|
void MI_Misexp(Missile &missile); |
|
void MI_Acidsplat(Missile &missile); |
|
void MI_Teleport(Missile &missile); |
|
void MI_Stone(Missile &missile); |
|
void MI_Boom(Missile &missile); |
|
void MI_Rhino(Missile &missile); |
|
void MI_FirewallC(Missile &missile); |
|
void MI_Infra(Missile &missile); |
|
void MI_Apoca(Missile &missile); |
|
void MI_Wave(Missile &missile); |
|
void MI_Nova(Missile &missile); |
|
void MI_Blodboil(Missile &missile); |
|
void MI_Flame(Missile &missile); |
|
void MI_Flamec(Missile &missile); |
|
void MI_Cbolt(Missile &missile); |
|
void MI_Hbolt(Missile &missile); |
|
void MI_Element(Missile &missile); |
|
void MI_Bonespirit(Missile &missile); |
|
void MI_ResurrectBeam(Missile &missile); |
|
void MI_Rportal(Missile &missile); |
|
void ProcessMissiles(); |
|
void missiles_process_charge(); |
|
void RedoMissileFlags(); |
|
|
|
} // namespace devilution
|
|
|