diff --git a/src/engine/game/debugsystem.lua b/src/engine/game/debugsystem.lua index 3ab5e82bc..933723f50 100644 --- a/src/engine/game/debugsystem.lua +++ b/src/engine/game/debugsystem.lua @@ -717,10 +717,10 @@ function DebugSystem:registerSubMenus() else Game:addPartyMember(id) if Game.world.player then - Game.world:spawnFollower(Game.party_data[id]:getActor()) + Game.world:spawnFollower(Game.party_data[id]:getActor(), {party = id}) else local x, y = Game.world.camera:getPosition() - Game.world:spawnPlayer(x, y, Game.party_data[id]:getActor()) + Game.world:spawnPlayer(x, y, Game.party_data[id]:getActor(), id) end end end) diff --git a/src/engine/game/world.lua b/src/engine/game/world.lua index 6c602ed7a..2d4d97bd6 100644 --- a/src/engine/game/world.lua +++ b/src/engine/game/world.lua @@ -507,21 +507,27 @@ function World:showText(text, after) end --- Spawns the player into the world +---@overload fun(self: World, x: number, y: number, chara: string|Actor, party?: string) +---@overload fun(self: World, marker: string, chara: string|Actor, party?: string) ---@param ... unknown Arguments detailing how the player spawns ---|"x, y, chara" # The co-ordinates of the player spawn and the Actor (instance or id) to use for the player ---|"marker, chara" # The marker name to spawn the player at and the Actor (instance or id) to use for the player +---@param party? string The party member ID associated with the player function World:spawnPlayer(...) local args = {...} local x, y = 0, 0 local chara = self.player and self.player.actor + local party if #args > 0 then if type(args[1]) == "number" then x, y = args[1], args[2] chara = args[3] or chara + party = args[4] elseif type(args[1]) == "string" then x, y = self.map:getMarker(args[1]) chara = args[2] or chara + party = args[3] end end @@ -544,6 +550,10 @@ function World:spawnPlayer(...) self.player:setFacing(facing) self:addChild(self.player) + if party then + self.player.party = party + end + self.soul = OverworldSoul(self.player:getRelativePos(self.player.actor:getSoulOffset())) self.soul:setColor(Game:getSoulColor()) self.soul.layer = WORLD_LAYERS["soul"] @@ -564,11 +574,18 @@ function World:getPartyCharacter(party) if type(party) == "string" then party = Game:getPartyMember(party) end + local char_to_return for _,char in ipairs(Game.stage:getObjects(Character)) do - if char.actor and char.actor.id == party:getActor().id then + -- Immediately break the loop and return if we find an explicit party match + if char.party and char.party.id == party.id then return char end + -- Store the first actor match, do not break loop as the match is not explicit + if char.actor and char.actor.id == party:getActor().id then + char_to_return = char_to_return or char + end end + return char_to_return end --- Gets the `Follower` or `Player` of a character currently in the party @@ -609,12 +626,13 @@ function World:removeFollower(chara) end --- Spawns a follower into the world ----@param chara Follower|string|Actor The character to spawn as a follower ----@param options table A table defining additional properties to control the new follower +---@param chara Follower|string|Actor The character to spawn as a follower +---@param options? table A table defining additional properties to control the new follower ---|"x" # The position of the follower ---|"y" # The position of the follower ---|"index" # The index of the follower in the list of followers ---|"temp" # Whether the follower is temporary and disappears when the current map is exited (defaults to `true`) +---|"party" # The id of the party member associated with this follower ---@return Follower function World:spawnFollower(chara, options) if type(chara) == "string" then @@ -652,6 +670,9 @@ function World:spawnFollower(chara, options) table.insert(Game.temp_followers, follower.actor.id) end end + if options["party"] then + follower.party = options["party"] + end self:addChild(follower) follower:updateIndex() return follower @@ -671,15 +692,15 @@ function World:spawnParty(marker, party, extra, facing) end end if type(marker) == "table" then - self:spawnPlayer(marker[1], marker[2], party[1]:getActor()) + self:spawnPlayer(marker[1], marker[2], party[1]:getActor(), party[1].id) else - self:spawnPlayer(marker or "spawn", party[1]:getActor()) + self:spawnPlayer(marker or "spawn", party[1]:getActor(), party[1].id) end if facing then self.player:setFacing(facing) end for i = 2, #party do - local follower = self:spawnFollower(party[i]:getActor()) + local follower = self:spawnFollower(party[i]:getActor(), {party = party[i].id}) follower:setFacing(facing or self.player.facing) end for _,actor in ipairs(extra or Game.temp_followers or {}) do @@ -750,7 +771,7 @@ function World:getCharacter(id, index) local party_member = Game:getPartyMember(id) local i = 0 for _,chara in ipairs(Game.stage:getObjects(Character)) do - if chara.actor.id == id or (party_member and chara.actor.id == party_member:getActor().id) then + if chara.actor.id == id or (party_member and chara.party and chara.party == party_member.id) then i = i + 1 if not index or index == i then return chara diff --git a/src/engine/game/world/character.lua b/src/engine/game/world/character.lua index aa259533d..3ba4bc5ee 100644 --- a/src/engine/game/world/character.lua +++ b/src/engine/game/world/character.lua @@ -14,6 +14,9 @@ function Character:init(actor, x, y) self.is_player = false self.is_follower = false + -- The party member id represented by this character + self.party = nil + self.facing = "down" self:setActor(actor) @@ -41,6 +44,9 @@ end function Character:getDebugInfo() local info = super.getDebugInfo(self) table.insert(info, "Actor: " .. self.actor.name) + if self.party then + table.insert(info, "Party Member: " .. self.party) + end table.insert(info, "Noclip: " .. (self.noclip and "True" or "False")) return info end @@ -70,6 +76,10 @@ function Character:getFlag(flag, default) end function Character:getPartyMember() + if self.party then + return Game:getPartyMember(self.id) + end + for _,party in pairs(Game.party_data) do local actor = party:getActor() if actor and actor.id == self.actor.id then @@ -598,7 +608,7 @@ function Character:convertToFollower(index, save) local follower = Follower(self.actor, self.x, self.y) follower.layer = self.layer follower:setFacing(self.facing) - self.world:spawnFollower(follower, {index = index}) + self.world:spawnFollower(follower, {index = index, party = self.party}) if save then Game:addFollower(follower, index) end @@ -607,7 +617,7 @@ function Character:convertToFollower(index, save) end function Character:convertToPlayer() - self.world:spawnPlayer(self.x, self.y, self.actor) + self.world:spawnPlayer(self.x, self.y, self.actor, self.party) local player = self.world.player player:setLayer(self.layer) player:setFacing(self.facing) @@ -618,6 +628,7 @@ end function Character:convertToNPC(properties) local npc = NPC(self.actor, self.x, self.y, properties) npc.layer = self.layer + npc.party = self.party npc:setFacing(self.facing) self.world:addChild(npc) self:remove() @@ -627,6 +638,7 @@ end function Character:convertToCharacter() local character = Character(self.actor, self.x, self.y) character.layer = self.layer + character.party = self.party character:setFacing(self.facing) self.world:addChild(character) self:remove() @@ -636,6 +648,7 @@ end function Character:convertToEnemy(properties) local enemy = ChaserEnemy(self.actor, self.x, self.y, properties) enemy.layer = self.layer + enemy.party = self.party enemy:setFacing(self.facing) self.world:addChild(enemy) self:remove()