From 324346a87c114f0991a092ac8653afecada364b5 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Mon, 5 Jul 2021 11:58:29 -0400 Subject: Added background scripts Background scripts are scripts that are launched when a map is loaded. They differ in use from a map's init script in that they are expected to contain an infinite loop. These scripts are linked to a sprite and will be killed when that sprite is destroyed (usually when the map is unloaded, but if the sprite is made persistent then it may last longer). The thread running the script is given no warning that it is being killed; the coroutine is simply never called again, and the thread is disposed of. Because of this, background scripts MUST ensure the game is in a consistent state before coroutine yielding, because it is not guaranteed that the coroutine will ever be called again. --- res/scripts/common.lua | 14 ++++++++++++++ src/game.cpp | 9 +++++++++ src/map.cpp | 2 ++ src/map.h | 1 + src/script_system.cpp | 9 ++++++++- src/script_system.h | 5 ++++- 6 files changed, 38 insertions(+), 2 deletions(-) diff --git a/res/scripts/common.lua b/res/scripts/common.lua index 2e95f26..35eec22 100644 --- a/res/scripts/common.lua +++ b/res/scripts/common.lua @@ -579,6 +579,20 @@ function FaceTowardSpriteCardinally(spriteName, targetName) SetDirection(spriteName, dir) end +--- Checks whether the given sprite is facing another sprite. +-- @param spriteName the name of the sprite whose facing direction is relevant +-- @param targetName the name of the sprite that is or isn't being looked at +function IsFacingTowardSprite(spriteName, targetName) + local spriteId = getSpriteByAlias(spriteName) + local targetId = getSpriteByAlias(targetName) + local sprite = getSprite(spriteId) + local target = getSprite(targetId) + local diff = vec2i.new(target.loc:x() - sprite.loc:x(), target.loc:y() - sprite.loc:y()) + local dir = directionFacingPoint(diff) + + return sprite.dir == dir +end + --- Detaches the sprite's followers and erases their following trails. function BreakUpParty(spriteName) local spriteId = getSpriteByAlias(spriteName) diff --git a/src/game.cpp b/src/game.cpp index 80ff506..dff8af0 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -52,6 +52,7 @@ void Game::loadMap(std::string filename) { // Load the new map. map_ = std::make_unique(filename); + std::vector> backgroundScripts; for (const Prototype& p : map_->getPrototypes()) { if (spritesByAlias_.count(p.name)) continue; @@ -84,6 +85,9 @@ void Game::loadMap(std::string filename) { getSprite(spriteId).mirrorAxis = p.mirrorAxis; getSprite(spriteId).mirroredSpriteId = getSpriteByAlias(p.spriteToMirror); } + if (!p.backgroundScript.empty()) { + backgroundScripts.push_back({spriteId, p.backgroundScript}); + } } for (const Trigger& t : map_->getTriggers()) { @@ -99,4 +103,9 @@ void Game::loadMap(std::string filename) { if (getSystem().mapHasScript(map_->getName(), "init")) { getSystem().runScript(map_->getName(), "init"); } + + // Run any background scripts associated with new sprites. + for (auto& [spriteId, scriptName] : backgroundScripts) { + getSystem().runScript(map_->getName(), scriptName, spriteId); + } } diff --git a/src/map.cpp b/src/map.cpp index c8bf18f..f28a976 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -121,6 +121,8 @@ Map::Map(std::string_view name) : name_(name) { p.spriteToMirror = property.getStringValue(); } else if (property.getName() == "bumpPlayerScript") { p.bumpPlayerScript = property.getStringValue(); + } else if (property.getName() == "backgroundScript") { + p.backgroundScript = property.getStringValue(); } } diff --git a/src/map.h b/src/map.h index 7300e76..48c0223 100644 --- a/src/map.h +++ b/src/map.h @@ -28,6 +28,7 @@ struct Prototype { Direction dir = Direction::down; std::string interactionScript; std::string bumpPlayerScript; + std::string backgroundScript; bool shadow = false; bool wander = false; int movementSpeed = -1; diff --git a/src/script_system.cpp b/src/script_system.cpp index b4a7b9b..c820ecb 100644 --- a/src/script_system.cpp +++ b/src/script_system.cpp @@ -269,6 +269,12 @@ void ScriptSystem::tick(double dt) { }); } +void ScriptSystem::destroySprite(int spriteId) { + scripts_.remove_if([spriteId] (const Script& script) { + return (script.linkedSprite == spriteId); + }); +} + void ScriptSystem::loadMapScripts(std::string mapName) { if (!loadedScripts_.count(mapName)) { engine_.script_file("../res/scripts/" + mapName + ".lua"); @@ -282,7 +288,7 @@ bool ScriptSystem::mapHasScript(std::string mapName, std::string scriptName) { return !!engine_.traverse_get(mapName, scriptName); } -void ScriptSystem::runScript(std::string mapName, std::string scriptName) { +void ScriptSystem::runScript(std::string mapName, std::string scriptName, int linkedSprite) { loadMapScripts(mapName); Script newScript; @@ -291,6 +297,7 @@ void ScriptSystem::runScript(std::string mapName, std::string scriptName) { #ifdef TANETANE_DEBUG newScript.debugInfo = mapName + "." + scriptName; #endif + newScript.linkedSprite = linkedSprite; if (!*newScript.callable) { throw std::runtime_error("Error running script: " + mapName + "." + scriptName); diff --git a/src/script_system.h b/src/script_system.h index 6a28430..0718e90 100644 --- a/src/script_system.h +++ b/src/script_system.h @@ -19,9 +19,11 @@ public: void tick(double dt) override; + void destroySprite(int spriteId) override; + bool mapHasScript(std::string mapName, std::string scriptName); - void runScript(std::string mapName, std::string scriptName); + void runScript(std::string mapName, std::string scriptName, int linkedSprite = -1); void runDebugScript(std::string script); @@ -33,6 +35,7 @@ private: std::unique_ptr runner; std::unique_ptr callable; std::string debugInfo; + int linkedSprite = -1; }; Game& game_; -- cgit 1.4.1