Skip to content

Commit

Permalink
Add town portal spell
Browse files Browse the repository at this point in the history
  • Loading branch information
grantramsay committed Mar 2, 2020
1 parent 15a2a35 commit 9a3de11
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 4 deletions.
4 changes: 2 additions & 2 deletions apps/freeablo/faworld/gamelevel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ namespace FAWorld
actorMapInsert(mActors[i]);
}

Misc::Point GameLevel::getFreeSpotNear(Misc::Point point, int32_t radius) const
Misc::Point GameLevel::getFreeSpotNear(Misc::Point point, int32_t radius, const std::function<bool(const Misc::Point& point)>& additionalConstraints) const
{
// partially based on https://stackoverflow.com/a/398302

Expand All @@ -192,7 +192,7 @@ namespace FAWorld
Misc::Point targetPoint = point + Misc::Point{xOffset, yOffset};
if (targetPoint.x >= 0 && targetPoint.x < width() && targetPoint.y >= 0 && targetPoint.y < height())
{
if (isPassable(targetPoint, nullptr))
if (isPassable(targetPoint, nullptr) && (additionalConstraints == nullptr || additionalConstraints(targetPoint)))
return targetPoint;
}

Expand Down
4 changes: 3 additions & 1 deletion apps/freeablo/faworld/gamelevel.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ namespace FAWorld

void actorMapRefresh();

Misc::Point getFreeSpotNear(Misc::Point point, int32_t radius = std::numeric_limits<int32_t>::max()) const;
Misc::Point getFreeSpotNear(Misc::Point point,
int32_t radius = std::numeric_limits<int32_t>::max(),
const std::function<bool(const Misc::Point& point)>& additionalConstraints = nullptr) const;

virtual bool isPassable(const Misc::Point& point, const FAWorld::Actor* forActor) const;

Expand Down
2 changes: 2 additions & 0 deletions apps/freeablo/faworld/missile/missile.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ namespace FAWorld::Missile
static void animated16Direction(Missile& missile, Misc::Point dest, GameLevel* level);
static void firewall(Missile& missile, Misc::Point dest, GameLevel* level);
static void basicAnimated(Missile& missile, Misc::Point dest, GameLevel* level);
static void townPortal(Missile& missile, Misc::Point dest, GameLevel* level);
};

class Movement
Expand All @@ -69,6 +70,7 @@ namespace FAWorld::Missile
static void none(Missile& missile, MissileGraphic& graphic, Actor& actor);
static void damageEnemy(Missile& missile, MissileGraphic& graphic, Actor& actor);
static void damageEnemyAndStop(Missile& missile, MissileGraphic& graphic, Actor& actor);
static void townPortal(Missile& missile, MissileGraphic& graphic, Actor& actor);
};

// Inner class that holds reference to all missile attributes.
Expand Down
22 changes: 22 additions & 0 deletions apps/freeablo/faworld/missile/missileactorengagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,26 @@ namespace FAWorld::Missile
if (&actor != missile.mCreator)
graphic.stop();
}

void Missile::ActorEngagement::townPortal(Missile& missile, MissileGraphic& graphic, Actor& actor)
{
if (&actor == missile.mCreator)
{
// Teleport to other portal
auto& otherPortal = missile.mGraphics[0].get() != &graphic ? missile.mGraphics[0] : missile.mGraphics[1];
auto noMissilesAtPoint = [&otherPortal](const Misc::Point& p) {
return std::none_of(
otherPortal->getLevel()->mMissileGraphics.begin(), otherPortal->getLevel()->mMissileGraphics.end(),
[&p](const MissileGraphic* g) { return p == g->mCurPos.current();});
};
auto point = otherPortal->getLevel()->getFreeSpotNear(otherPortal->mCurPos.current(), INT32_MAX, noMissilesAtPoint);
actor.teleport(otherPortal->getLevel(), Position(point));
// Close the portal if teleporting back through the 2nd (town located) portal
if (&graphic == missile.mGraphics[1].get())
{
graphic.stop();
otherPortal->stop();
}
}
}
}
2 changes: 2 additions & 0 deletions apps/freeablo/faworld/missile/missileattributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ namespace FAWorld::Missile
return Attributes(Creation::firewall, Movement::stationary, ActorEngagement::damageEnemy, maxRangeIgnore, World::getTicksInPeriod(8));
case MissileId::manashield:
return Attributes(Creation::basicAnimated, Movement::hoverOverCreator, ActorEngagement::none, maxRangeIgnore, World::getTicksInPeriod(8));
case MissileId::town:
return Attributes(Creation::townPortal, Movement::stationary, ActorEngagement::townPortal, maxRangeIgnore, ttlIgnore);
default:
invalid_enum(MissileId, missileId);
}
Expand Down
26 changes: 26 additions & 0 deletions apps/freeablo/faworld/missile/missilecreation.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "engine/enginemain.h"
#include "faworld/gamelevel.h"
#include "missile.h"
#include <misc/simplevec2.h>

Expand Down Expand Up @@ -42,4 +44,28 @@ namespace FAWorld::Missile
{
missile.mGraphics.push_back(std::make_unique<MissileGraphic>("", missile.getGraphicsPath(0), std::nullopt, Position(missile.mSrcPoint), level));
}

void Missile::Creation::townPortal(Missile& missile, Misc::Point, GameLevel* level)
{
// Add portal near player
auto noMissilesAtPoint = [&level](const Misc::Point& p) {
return std::none_of(
level->mMissileGraphics.begin(), level->mMissileGraphics.end(),
[&p](const MissileGraphic* g) { return p == g->mCurPos.current();});
};
auto point = level->getFreeSpotNear(missile.mSrcPoint, INT32_MAX, noMissilesAtPoint);
missile.mGraphics.push_back(std::make_unique<MissileGraphic>(
missile.getGraphicsPath(0), missile.getGraphicsPath(1), std::nullopt, Position(point), level));
// Add portal in town
auto town = Engine::EngineMain::get()->mWorld->getLevel(0);
static const Misc::Point townPortalPoint = Misc::Point(60, 80);
auto noMissilesAtTownPoint = [&town](const Misc::Point& p) {
return std::none_of(
town->mMissileGraphics.begin(), town->mMissileGraphics.end(),
[&p](const MissileGraphic* g) { return p == g->mCurPos.current();});
};
point = town->getFreeSpotNear(townPortalPoint, INT32_MAX, noMissilesAtTownPoint);
missile.mGraphics.push_back(std::make_unique<MissileGraphic>(
missile.getGraphicsPath(0), missile.getGraphicsPath(1), std::nullopt, Position(point), town));
}
}
2 changes: 1 addition & 1 deletion apps/freeablo/faworld/spells.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ namespace FAWorld
// Temporary quirk to only allow implemented spells to be used.
static bool isSpellImplemented(SpellId spell)
{
static const SpellId implementedSpells[] = {SpellId::firebolt, SpellId::firewall, SpellId::manashield};
static const SpellId implementedSpells[] = {SpellId::firebolt, SpellId::firewall, SpellId::manashield, SpellId::town};
for (auto sp : implementedSpells)
if (spell == sp)
return true;
Expand Down

0 comments on commit 9a3de11

Please sign in to comment.