From 32d397eb2a7a76d7f74079cb43e57b4766ad3c68 Mon Sep 17 00:00:00 2001 From: ephphatha Date: Sun, 23 Jan 2022 10:41:41 +1100 Subject: [PATCH] Add max_size checks when adding missiles to allow for limited size containers This doesn't handle failed allocations (e.g. if the platform runs out of memory) but makes it easier to use a fixed size container on limited memory devices. --- Source/loadsave.cpp | 4 +++- Source/missiles.cpp | 8 +++++--- Source/missiles.h | 2 +- Source/monster.cpp | 49 +++++++++++++++++++++++++-------------------- Source/portal.cpp | 10 +++++---- 5 files changed, 42 insertions(+), 31 deletions(-) diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index bbbd86e76..25fb8d589 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -715,7 +715,9 @@ void LoadMissile(LoadHelper *file) missile.var7 = file->NextLE(); missile.limitReached = file->NextBool32(); missile.lastCollisionTargetHash = 0; - Missiles.push_back(missile); + if (Missiles.size() < Missiles.max_size()) { + Missiles.push_back(missile); + } } void LoadObject(LoadHelper &file, Object &object) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 17d5a5bae..7d90743c8 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2692,9 +2692,11 @@ void AddDiabApoca(Missile &missile, const AddMissileParameter & /*parameter*/) missile._miDelFlag = true; } -Missile &AddMissile(Point src, Point dst, Direction midir, missile_id mitype, mienemy_type micaster, int id, int midam, int spllvl, Missile *pParent /*= nullptr*/) +Missile *AddMissile(Point src, Point dst, Direction midir, missile_id mitype, mienemy_type micaster, int id, int midam, int spllvl, Missile *pParent /*= nullptr*/) { - constexpr int32_t MaxMissiles = std::numeric_limits::max(); + if (Missiles.size() >= Missiles.max_size()) { + return nullptr; + } Missiles.emplace_back(Missile {}); auto &missile = Missiles.back(); @@ -2726,7 +2728,7 @@ Missile &AddMissile(Point src, Point dst, Direction midir, missile_id mitype, mi AddMissileParameter parameter = { dst, midir, pParent }; missileData.mAddProc(missile, parameter); - return missile; + return &missile; } void MI_LArrow(Missile &missile) diff --git a/Source/missiles.h b/Source/missiles.h index 97a09b665..9f7502698 100644 --- a/Source/missiles.h +++ b/Source/missiles.h @@ -341,7 +341,7 @@ 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); +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_Golem(Missile &missile); void MI_Manashield(Missile &missile); void MI_LArrow(Missile &missile); diff --git a/Source/monster.cpp b/Source/monster.cpp index 699195726..dde6f2082 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1616,16 +1616,18 @@ bool MonsterRangedSpecialAttack(int i) assert(monster.MData != nullptr); if (monster.AnimInfo.CurrentFrame == monster.MData->mAFNum2 && monster.AnimInfo.TickCounterOfCurrentFrame == 0) { - AddMissile( - monster.position.tile, - monster.enemyPosition, - monster._mdir, - static_cast(monster._mVar1), - TARGET_PLAYERS, - i, - monster._mVar3, - 0); - PlayEffect(monster, 3); + if (AddMissile( + monster.position.tile, + monster.enemyPosition, + monster._mdir, + static_cast(monster._mVar1), + TARGET_PLAYERS, + i, + monster._mVar3, + 0) + != nullptr) { + PlayEffect(monster, 3); + } } if (monster._mAi == AI_MEGA && monster.AnimInfo.CurrentFrame == monster.MData->mAFNum2) { @@ -2556,11 +2558,12 @@ void RhinoAi(int i) if (dist >= 5 && v < 2 * monster._mint + 43 && LineClear([&monster](Point position) { return IsTileAvailable(monster, position); }, monster.position.tile, { fx, fy })) { - AddMissile(monster.position.tile, { fx, fy }, md, MIS_RHINO, TARGET_PLAYERS, i, 0, 0); - if (monster.MData->snd_special) - PlayEffect(monster, 3); - dMonster[monster.position.tile.x][monster.position.tile.y] = -(i + 1); - monster._mmode = MonsterMode::Charge; + if (AddMissile(monster.position.tile, { fx, fy }, md, MIS_RHINO, TARGET_PLAYERS, i, 0, 0) != nullptr) { + if (monster.MData->snd_special) + PlayEffect(monster, 3); + dMonster[monster.position.tile.x][monster.position.tile.y] = -(i + 1); + monster._mmode = MonsterMode::Charge; + } } else { if (dist >= 2) { v = GenerateRnd(100); @@ -2758,9 +2761,10 @@ void BatAi(int i) && (abs(xd) >= 5 || abs(yd) >= 5) && v < 4 * monster._mint + 33 && LineClear([&monster](Point position) { return IsTileAvailable(monster, position); }, monster.position.tile, { fx, fy })) { - AddMissile(monster.position.tile, { fx, fy }, md, MIS_RHINO, TARGET_PLAYERS, i, 0, 0); - dMonster[monster.position.tile.x][monster.position.tile.y] = -(i + 1); - monster._mmode = MonsterMode::Charge; + if (AddMissile(monster.position.tile, { fx, fy }, md, MIS_RHINO, TARGET_PLAYERS, i, 0, 0) != nullptr) { + dMonster[monster.position.tile.x][monster.position.tile.y] = -(i + 1); + monster._mmode = MonsterMode::Charge; + } } else if (abs(xd) >= 2 || abs(yd) >= 2) { if ((monster._mVar2 > 20 && v < monster._mint + 13) || (IsAnyOf(static_cast(monster._mVar1), MonsterMode::MoveNorthwards, MonsterMode::MoveSouthwards, MonsterMode::MoveSideways) @@ -3026,10 +3030,11 @@ void SnakeAi(int i) monster._mdir = md; if (abs(mx) >= 2 || abs(my) >= 2) { if (abs(mx) < 3 && abs(my) < 3 && LineClear([&monster](Point position) { return IsTileAvailable(monster, position); }, monster.position.tile, { fx, fy }) && static_cast(monster._mVar1) != MonsterMode::Charge) { - AddMissile(monster.position.tile, { fx, fy }, md, MIS_RHINO, TARGET_PLAYERS, i, 0, 0); - PlayEffect(monster, 0); - dMonster[monster.position.tile.x][monster.position.tile.y] = -(i + 1); - monster._mmode = MonsterMode::Charge; + if (AddMissile(monster.position.tile, { fx, fy }, md, MIS_RHINO, TARGET_PLAYERS, i, 0, 0) != nullptr) { + PlayEffect(monster, 0); + dMonster[monster.position.tile.x][monster.position.tile.y] = -(i + 1); + monster._mmode = MonsterMode::Charge; + } } else if (static_cast(monster._mVar1) == MonsterMode::Delay || GenerateRnd(100) >= 35 - 2 * monster._mint) { if (pattern[monster._mgoalvar1] == -1) md = Left(md); diff --git a/Source/portal.cpp b/Source/portal.cpp index 1f1111cea..f3bce6b55 100644 --- a/Source/portal.cpp +++ b/Source/portal.cpp @@ -51,11 +51,13 @@ void AddWarpMissile(int i, Point position) { MissilesData[MIS_TOWN].mlSFX = SFX_NONE; - auto &missile = AddMissile({ 0, 0 }, position, Direction::South, MIS_TOWN, TARGET_MONSTERS, i, 0, 0); - SetMissDir(missile, 1); + auto *missile = AddMissile({ 0, 0 }, position, Direction::South, MIS_TOWN, TARGET_MONSTERS, i, 0, 0); + if (missile != nullptr) { + SetMissDir(*missile, 1); - if (currlevel != 0) - missile._mlid = AddLight(missile.position.tile, 15); + if (currlevel != 0) + missile->_mlid = AddLight(missile->position.tile, 15); + } MissilesData[MIS_TOWN].mlSFX = LS_SENTINEL; }