Skip to content

Commit

Permalink
Optimize MissileData: 32 bytes -> 24
Browse files Browse the repository at this point in the history
23 bytes used, 1 spare byte in the padding.
  • Loading branch information
glebm authored and AJenbo committed Feb 7, 2023
1 parent 2d4e84c commit 98294e0
Show file tree
Hide file tree
Showing 7 changed files with 255 additions and 212 deletions.
2 changes: 1 addition & 1 deletion Source/engine/render/scrollrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void UpdateMissileRendererData(Missile &m)
m.position.tileForRendering = m.position.tile;
m.position.offsetForRendering = m.position.offset;

const MissileMovementDistribution missileMovement = GetMissileData(m._mitype).MovementDistribution;
const MissileMovementDistribution missileMovement = GetMissileData(m._mitype).movementDistribution;
// don't calculate missile position if they don't move
if (missileMovement == MissileMovementDistribution::Disabled || m.position.velocity == Displacement {})
return;
Expand Down
2 changes: 1 addition & 1 deletion Source/loadsave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ void LoadMissile(LoadHelper *file)
missile._miDelFlag = file->NextBool32();
missile._miAnimType = static_cast<MissileGraphicID>(file->NextLE<uint8_t>());
file->Skip(3); // Alignment
missile._miAnimFlags = static_cast<MissileDataFlags>(file->NextLE<int32_t>());
missile._miAnimFlags = static_cast<MissileGraphicsFlags>(file->NextLE<int32_t>());
file->Skip(4); // Skip pointer _miAnimData
missile._miAnimDelay = file->NextLE<int32_t>();
missile._miAnimLen = file->NextLE<int32_t>();
Expand Down
352 changes: 181 additions & 171 deletions Source/misdat.cpp

Large diffs are not rendered by default.

47 changes: 40 additions & 7 deletions Source/misdat.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "engine.h"
#include "engine/clx_sprite.hpp"
#include "spelldat.h"
#include "utils/enum_traits.h"
#include "utils/stdcompat/cstddef.hpp"
#include "utils/stdcompat/string_view.hpp"

Expand Down Expand Up @@ -116,19 +117,51 @@ enum class MissileMovementDistribution : uint8_t {
struct Missile;
struct AddMissileParameter;

enum class MissileDataFlags : uint8_t {
// The lower 3 bytes are used to store DamageType.
Physical = static_cast<uint8_t>(DamageType::Physical),
Fire = static_cast<uint8_t>(DamageType::Fire),
Lightning = static_cast<uint8_t>(DamageType::Lightning),
Magic = static_cast<uint8_t>(DamageType::Magic),
Acid = static_cast<uint8_t>(DamageType::Acid),
Arrow = 1 << 4,
Invisible = 1 << 5,
};
use_enum_as_flags(MissileDataFlags);

struct MissileData {
void (*mAddProc)(Missile &, AddMissileParameter &);
void (*mProc)(Missile &);
bool mDraw;
uint8_t mType;
DamageType damageType;
MissileGraphicID mFileNum;
_sfx_id mlSFX;
_sfx_id miSFX;
MissileMovementDistribution MovementDistribution;
MissileGraphicID mFileNum;
MissileDataFlags flags;
MissileMovementDistribution movementDistribution;

[[nodiscard]] bool isDrawn() const
{
return !HasAnyOf(flags, MissileDataFlags::Invisible);
}

[[nodiscard]] bool isArrow() const
{
return HasAnyOf(flags, MissileDataFlags::Arrow);
}

[[nodiscard]] DamageType damageType() const
{
return static_cast<DamageType>(static_cast<std::underlying_type<MissileDataFlags>::type>(flags) & 0b111U);
}

void setDamageType(DamageType damageType)
{
flags = static_cast<MissileDataFlags>(
(static_cast<std::underlying_type<MissileDataFlags>::type>(flags) & 0b11111000U)
| static_cast<std::underlying_type<DamageType>::type>(damageType));
}
};

enum class MissileDataFlags : uint8_t {
enum class MissileGraphicsFlags : uint8_t {
// clang-format off
None = 0,
MonsterOwned = 1 << 0,
Expand All @@ -142,7 +175,7 @@ struct MissileFileData {
int8_t animWidth2;
char name[9];
uint8_t animFAmt;
MissileDataFlags flags;
MissileGraphicsFlags flags;
uint8_t animDelayIdx;
uint8_t animLenIdx;

Expand Down
58 changes: 29 additions & 29 deletions Source/missiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ bool MonsterMHit(int pnum, int monsterId, int mindam, int maxdam, int dist, Miss
int hper = 0;
const Player &player = Players[pnum];
const MissileData &missileData = GetMissileData(t);
if (missileData.mType == 0) {
if (missileData.isArrow()) {
hper = player.GetRangedPiercingToHit();
hper -= player.CalculateArmorPierce(monster.armorClass, false);
hper -= (dist * dist) / 2;
Expand Down Expand Up @@ -241,7 +241,7 @@ bool MonsterMHit(int pnum, int monsterId, int mindam, int maxdam, int dist, Miss
dam = mindam + GenerateRnd(maxdam - mindam + 1);
}

if (missileData.mType == 0 && missileData.damageType == DamageType::Physical) {
if (missileData.isArrow() && missileData.damageType() == DamageType::Physical) {
dam = player._pIBonusDamMod + dam * player._pIBonusDam / 100 + dam;
if (player._pClass == HeroClass::Rogue)
dam += player._pDamageMod;
Expand All @@ -257,15 +257,15 @@ bool MonsterMHit(int pnum, int monsterId, int mindam, int maxdam, int dist, Miss
dam >>= 2;

if (&player == MyPlayer)
ApplyMonsterDamage(missileData.damageType, monster, dam);
ApplyMonsterDamage(missileData.damageType(), monster, dam);

if (monster.hitPoints >> 6 <= 0) {
M_StartKill(monster, player);
} else if (resist) {
monster.tag(player);
PlayEffect(monster, MonsterSound::Hit);
} else {
if (monster.mode != MonsterMode::Petrified && missileData.mType == 0 && HasAnyOf(player._pIFlags, ItemSpecialEffect::Knockback))
if (monster.mode != MonsterMode::Petrified && missileData.isArrow() && HasAnyOf(player._pIFlags, ItemSpecialEffect::Knockback))
M_GetKnockback(monster);
if (monster.type().type != MT_GOLEM)
M_StartHit(monster, player, dam);
Expand Down Expand Up @@ -301,12 +301,12 @@ bool Plr2PlrMHit(const Player &player, int p, int mindam, int maxdam, int dist,

const MissileData &missileData = GetMissileData(mtype);

if (HasAnyOf(target._pSpellFlags, SpellFlag::Etherealize) && missileData.mType == 0) {
if (HasAnyOf(target._pSpellFlags, SpellFlag::Etherealize) && missileData.isArrow()) {
return false;
}

int8_t resper;
switch (missileData.damageType) {
switch (missileData.damageType()) {
case DamageType::Fire:
resper = target._pFireResist;
break;
Expand All @@ -325,7 +325,7 @@ bool Plr2PlrMHit(const Player &player, int p, int mindam, int maxdam, int dist,
int hper = GenerateRnd(100);

int hit;
if (missileData.mType == 0) {
if (missileData.isArrow()) {
hit = player.GetRangedToHit()
- (dist * dist / 2)
- target.GetArmor();
Expand Down Expand Up @@ -354,17 +354,17 @@ bool Plr2PlrMHit(const Player &player, int p, int mindam, int maxdam, int dist,
dam = target._pHitPoints / 3;
} else {
dam = mindam + GenerateRnd(maxdam - mindam + 1);
if (missileData.mType == 0 && missileData.damageType == DamageType::Physical)
if (missileData.isArrow() && missileData.damageType() == DamageType::Physical)
dam += player._pIBonusDamMod + player._pDamageMod + dam * player._pIBonusDam / 100;
if (!shift)
dam <<= 6;
}
if (missileData.mType != 0)
if (!missileData.isArrow())
dam /= 2;
if (resper > 0) {
dam -= (dam * resper) / 100;
if (&player == MyPlayer)
NetSendCmdDamage(true, p, dam, missileData.damageType);
NetSendCmdDamage(true, p, dam, missileData.damageType());
target.Say(HeroSpeech::ArghClang);
return true;
}
Expand All @@ -374,7 +374,7 @@ bool Plr2PlrMHit(const Player &player, int p, int mindam, int maxdam, int dist,
*blocked = true;
} else {
if (&player == MyPlayer)
NetSendCmdDamage(true, p, dam, missileData.damageType);
NetSendCmdDamage(true, p, dam, missileData.damageType());
StartPlrHit(target, dam, false);
}

Expand Down Expand Up @@ -562,7 +562,7 @@ void MoveMissileAndCheckMissileCol(Missile &missile, int mindam, int maxdam, boo
if (missile._mirange != 0)
return true;

if (missile._miHitFlag && GetMissileData(missile._mitype).MovementDistribution == MissileMovementDistribution::Blockable)
if (missile._miHitFlag && GetMissileData(missile._mitype).movementDistribution == MissileMovementDistribution::Blockable)
return false;

return !IsMissileBlockedByTile(tile);
Expand Down Expand Up @@ -953,7 +953,7 @@ bool MonsterTrapHit(int monsterId, int mindam, int maxdam, int dist, MissileID t
dam <<= 6;
if (resist)
dam /= 4;
ApplyMonsterDamage(GetMissileData(t).damageType, monster, dam);
ApplyMonsterDamage(GetMissileData(t).damageType(), monster, dam);
#ifdef _DEBUG
if (DebugGodMode)
monster.hitPoints = 0;
Expand Down Expand Up @@ -984,7 +984,7 @@ bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, Missil

const MissileData &missileData = GetMissileData(mtype);

if (HasAnyOf(player._pSpellFlags, SpellFlag::Etherealize) && missileData.mType == 0) {
if (HasAnyOf(player._pSpellFlags, SpellFlag::Etherealize) && missileData.isArrow()) {
return false;
}

Expand All @@ -994,7 +994,7 @@ bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, Missil
hit = 1000;
#endif
int hper = 40;
if (missileData.mType == 0) {
if (missileData.isArrow()) {
int tac = player.GetArmor();
if (monster != nullptr) {
hper = monster->toHit
Expand Down Expand Up @@ -1033,7 +1033,7 @@ bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, Missil
blkper = clamp(blkper, 0, 100);

int8_t resper;
switch (missileData.damageType) {
switch (missileData.damageType()) {
case DamageType::Fire:
resper = player._pFireResist;
break;
Expand Down Expand Up @@ -1087,7 +1087,7 @@ bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, Missil
if (resper > 0) {
dam -= dam * resper / 100;
if (&player == MyPlayer) {
ApplyPlrDamage(missileData.damageType, player, 0, 0, dam, earflag);
ApplyPlrDamage(missileData.damageType(), player, 0, 0, dam, earflag);
}

if (player._pHitPoints >> 6 > 0) {
Expand All @@ -1097,7 +1097,7 @@ bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, Missil
}

if (&player == MyPlayer) {
ApplyPlrDamage(missileData.damageType, player, 0, 0, dam, earflag);
ApplyPlrDamage(missileData.damageType(), player, 0, 0, dam, earflag);
}

if (player._pHitPoints >> 6 > 0) {
Expand Down Expand Up @@ -2144,7 +2144,7 @@ void InitMissileAnimationFromMonster(Missile &mis, Direction midir, const Monste
{
const AnimStruct &anim = mon.type().getAnimData(graphic);
mis._mimfnum = static_cast<int32_t>(midir);
mis._miAnimFlags = MissileDataFlags::None;
mis._miAnimFlags = MissileGraphicsFlags::None;
ClxSpriteList sprites = *anim.spritesForDirection(midir);
const uint16_t width = sprites[0].width();
mis._miAnimData.emplace(sprites);
Expand Down Expand Up @@ -2714,7 +2714,7 @@ Missile *AddMissile(Point src, Point dst, Direction midir, MissileID mitype, mie
missile.position.start = src;
missile._miAnimAdd = 1;
missile._miAnimType = missileData.mFileNum;
missile._miDrawFlag = missileData.mDraw;
missile._miDrawFlag = missileData.isDrawn();
missile._mlid = NO_LIGHT;
missile.lastCollisionTargetHash = 0;

Expand Down Expand Up @@ -2770,16 +2770,16 @@ void ProcessElementalArrow(Missile &missile)
maxd = GenerateRnd(10) + 1 + currlevel * 2;
}
MissileData &missileData = GetMissileData(missile._mitype);
DamageType rst = missileData.damageType;
missileData.damageType = DamageType::Physical;
DamageType rst = missileData.damageType();
missileData.setDamageType(DamageType::Physical);
MoveMissileAndCheckMissileCol(missile, mind, maxd, true, false);
missileData.damageType = rst;
missileData.setDamageType(rst);
if (missile._mirange == 0) {
missile._mimfnum = 0;
missile._mirange = missile._miAnimLen - 1;
missile.position.StopMissile();

rst = missileData.damageType;
rst = missileData.damageType();

int eMind;
int eMaxd;
Expand Down Expand Up @@ -2817,9 +2817,9 @@ void ProcessElementalArrow(Missile &missile)
break;
}
SetMissAnim(missile, eAnim);
missileData.damageType = eRst;
missileData.setDamageType(eRst);
CheckMissileCol(missile, eMind, eMaxd, false, missile.position.tile, true);
missileData.damageType = rst;
missileData.setDamageType(rst);
} else {
if (missile.position.tile != Point { missile.var1, missile.var2 }) {
missile.var1 = missile.position.tile.x;
Expand Down Expand Up @@ -3545,12 +3545,12 @@ void ProcessWeaponExplosion(Missile &missile)
// BUGFIX: damage of missile should be encoded in missile struct; player can be dead/have left the game before missile arrives.
mind = player._pIFMinDam;
maxd = player._pIFMaxDam;
missileData.damageType = DamageType::Fire;
missileData.setDamageType(DamageType::Fire);
} else {
// BUGFIX: damage of missile should be encoded in missile struct; player can be dead/have left the game before missile arrives.
mind = player._pILMinDam;
maxd = player._pILMaxDam;
missileData.damageType = DamageType::Lightning;
missileData.setDamageType(DamageType::Lightning);
}
CheckMissileCol(missile, mind, maxd, false, missile.position.tile, false);
if (missile.var1 == 0) {
Expand Down Expand Up @@ -4142,7 +4142,7 @@ void ProcessMissiles()
const MissileData &missileData = GetMissileData(missile._mitype);
if (missileData.mProc != nullptr)
missileData.mProc(missile);
if (missile._miAnimFlags == MissileDataFlags::NotAnimated)
if (missile._miAnimFlags == MissileGraphicsFlags::NotAnimated)
continue;

missile._miAnimCnt++;
Expand Down
2 changes: 1 addition & 1 deletion Source/missiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ struct Missile {
int _mispllvl;
bool _miDelFlag; // Indicate whether the missile should be deleted
MissileGraphicID _miAnimType;
MissileDataFlags _miAnimFlags;
MissileGraphicsFlags _miAnimFlags;
OptionalClxSpriteList _miAnimData;
int _miAnimDelay; // Tick length of each frame in the current animation
int _miAnimLen; // Number of frames in current animation
Expand Down
4 changes: 2 additions & 2 deletions Source/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4609,7 +4609,7 @@ bool Monster::isWalking() const

bool Monster::isImmune(MissileID missileType) const
{
DamageType missileElement = GetMissileData(missileType).damageType;
DamageType missileElement = GetMissileData(missileType).damageType();

if (((resistance & IMMUNE_MAGIC) != 0 && missileElement == DamageType::Magic)
|| ((resistance & IMMUNE_FIRE) != 0 && missileElement == DamageType::Fire)
Expand All @@ -4623,7 +4623,7 @@ bool Monster::isImmune(MissileID missileType) const

bool Monster::isResistant(MissileID missileType) const
{
DamageType missileElement = GetMissileData(missileType).damageType;
DamageType missileElement = GetMissileData(missileType).damageType();

if (((resistance & RESIST_MAGIC) != 0 && missileElement == DamageType::Magic)
|| ((resistance & RESIST_FIRE) != 0 && missileElement == DamageType::Fire)
Expand Down

0 comments on commit 98294e0

Please sign in to comment.