FILES ----- player.config cinematics\story\esther\esther.cinematic dungeons\microdungeons\bounty\boat.dungeon dungeons\microdungeons\bounty\boatinteract_2.json dungeons\microdungeons\bounty\boatvault_1.json dungeons\microdungeons\bounty\boatvault_2.json dungeons\microdungeons\bounty\boatvault_3.json dungeons\microdungeons\bounty\boat_1.json dungeons\microdungeons\bounty\boat_2.json dungeons\microdungeons\bounty\boat_3.json dungeons\microdungeons\bounty\boat_4.json dungeons\microdungeons\bounty\boat_5.json dungeons\microdungeons\bounty\boat_6.json dungeons\microdungeons\bounty\boat_7.json [NEW] dungeons\microdungeons\bounty\boat_8.json [NEW] dungeons\microdungeons\bounty\boat_9.json dungeons\microdungeons\bounty\interactobject_5.json dungeons\microdungeons\bounty\interactobject_6.json dungeons\microdungeons\bounty\interactobject_7.json dungeons\microdungeons\bounty\interactobject_8.json dungeons\microdungeons\bounty\safehouse.dungeon dungeons\microdungeons\bounty\safehouse_1.json dungeons\microdungeons\bounty\safehouse_10.json dungeons\microdungeons\bounty\safehouse_11.json dungeons\microdungeons\bounty\safehouse_12.json dungeons\microdungeons\bounty\safehouse_13.json dungeons\microdungeons\bounty\safehouse_14.json dungeons\microdungeons\bounty\safehouse_15.json dungeons\microdungeons\bounty\safehouse_16.json dungeons\microdungeons\bounty\safehouse_17.json [NEW] dungeons\microdungeons\bounty\safehouse_18.json [NEW] dungeons\microdungeons\bounty\safehouse_19.json dungeons\microdungeons\bounty\safehouse_2.json dungeons\microdungeons\bounty\safehouse_3.json dungeons\microdungeons\bounty\safehouse_4.json dungeons\microdungeons\bounty\safehouse_5.json dungeons\microdungeons\bounty\safehouse_6.json dungeons\microdungeons\bounty\safehouse_7.json dungeons\microdungeons\bounty\safehouse_8.json dungeons\microdungeons\bounty\safehouse_9.json [NEW] dungeons\microdungeons\bounty\tutorial_1.json [NEW] dungeons\microdungeons\bounty\tutorial_2.json dungeons\microdungeons\bounty\undergroundinteract_2.json dungeons\microdungeons\bounty\undergroundinteract_5.json dungeons\microdungeons\bounty\undergroundsafehouse.dungeon dungeons\microdungeons\bounty\undergroundsafehouse_1.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_10.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_11.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_12.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_13.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_14.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_15.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_16.json dungeons\microdungeons\bounty\undergroundsafehouse_2.json dungeons\microdungeons\bounty\undergroundsafehouse_3.json dungeons\microdungeons\bounty\undergroundsafehouse_4.json dungeons\microdungeons\bounty\undergroundsafehouse_5.json dungeons\microdungeons\bounty\undergroundsafehouse_6.json dungeons\microdungeons\bounty\undergroundsafehouse_7.json dungeons\microdungeons\bounty\undergroundsafehouse_8.json dungeons\microdungeons\bounty\undergroundsafehouse_9.json dungeons\microdungeons\bounty\undergroundvault_1.json dungeons\microdungeons\bounty\undergroundvault_2.json dungeons\microdungeons\bounty\undergroundvault_3.json dungeons\microdungeons\bounty\vault_1.json dungeons\microdungeons\bounty\vault_2.json dungeons\microdungeons\bounty\vault_3.json dungeons\missions\cultistmissions\cultistmission1.json dungeons\space\bountyspacesafehouse\bountyspacesafehouse.dungeon dungeons\space\bountyspacesafehouse\end_1.json dungeons\space\bountyspacesafehouse\end_2.json dungeons\space\bountyspacesafehouse\end_3.json dungeons\space\bountyspacesafehouse\end_4.json dungeons\space\bountyspacesafehouse\end_5.json dungeons\space\bountyspacesafehouse\end_6.json dungeons\space\bountyspacesafehouse\room_1.json [NEW] dungeons\space\bountyspacesafehouse\room_10.json dungeons\space\bountyspacesafehouse\room_2.json dungeons\space\bountyspacesafehouse\room_3.json dungeons\space\bountyspacesafehouse\room_4.json dungeons\space\bountyspacesafehouse\room_5.json dungeons\space\bountyspacesafehouse\room_6.json dungeons\space\bountyspacesafehouse\room_7.json dungeons\space\bountyspacesafehouse\room_8.json dungeons\space\bountyspacesafehouse\room_9.json items\armors\decorative\hats\bandithat1\bandithat1.head items\armors\decorative\hats\shroomdisguise\head.png items\armors\decorative\hats\shroomdisguise\icons.png monsters\ghosts\lumoth\lumothlit.png [NEW] monsters\ghosts\lumoth\lumoth_fire.png [NEW] monsters\ghosts\lumoth\lumoth_firelit.png [NEW] monsters\walkers\anglure\anglure_electric.png [NEW] monsters\walkers\bulbop\bulbop_poison.png [NEW] monsters\walkers\hemogoblin\hemogoblin_electric.png [NEW] monsters\walkers\hemogoblinbutt\hemogoblinbutt_electric.png [NEW] monsters\walkers\hemogoblinhead\hemogoblinhead_electric.png [NEW] monsters\walkers\hypnare\hypnare_ice.png [NEW] monsters\walkers\mandraflora\mandraflora_poison.png [NEW] monsters\walkers\narfin\narfin_ice.png [NEW] monsters\walkers\oogler\oogler_fire.png [NEW] monsters\walkers\orbide\orbide_ice.png [NEW] monsters\walkers\pipkin\pipkin_poison.png [NEW] monsters\walkers\quagmutt\quagmutt_electric.png [NEW] monsters\walkers\ringram\ringram_ice.png [NEW] monsters\walkers\sporgus\sporgus_poison.png [NEW] monsters\walkers\taroni\taroni_fire.png [NEW] monsters\walkers\toumingo\toumingo_fire.png [NEW] monsters\walkers\trictus\trictus_poison.png [NEW] monsters\walkers\yokat\yokat_electric.png [NEW] npcs\bounty\gangmember.npctype [NEW] objects\bounty\scanclue1\scanclue1.frames [NEW] objects\bounty\scanclue1\scanclue1.object [NEW] objects\bounty\scanclue1\scanclue1.png [NEW] objects\bounty\scanclue1\scanclue1icon.png [NEW] objects\generic\darkcomputer\darkcomputer.animation [NEW] objects\generic\darkcomputer\darkcomputer.frames [NEW] objects\generic\darkcomputer\darkcomputer.object [NEW] objects\generic\darkcomputer\darkcomputer.png [NEW] objects\generic\darkcomputer\darkcomputericon.png [NEW] objects\generic\darkcomputer\darkcomputerlit.frames [NEW] objects\generic\darkcomputer\darkcomputerlit.png quests\bounty\bounty.lua quests\bounty\bounty_gen.lua quests\bounty\capture_bounty.questtemplate quests\bounty\clue_items.config quests\bounty\clue_objects.config [NEW] quests\bounty\clue_scans.config quests\bounty\dungeons.config quests\bounty\find_clue_item.questtemplate quests\bounty\find_clue_npc.questtemplate quests\bounty\find_clue_object.questtemplate [NEW] quests\bounty\find_clue_scan.questtemplate [NEW] quests\bounty\find_space_clue_scan.questtemplate quests\bounty\generator.config quests\bounty\stages.lua scripts\bountygeneration.lua scripts\util.lua stagehands\bountymanager.lua [NEW] stagehands\bounty\scanclue.stagehand [NEW] stagehands\bounty\storageclue.stagehand tilesets\packed\objects-by-category\decorative.json tilesets\packed\objects-by-category\wire.json tilesets\packed\objects-by-colonytag\electronic.json tilesets\packed\objects-by-colonytag\misc.json tilesets\packed\objects-by-colonytag\wired.json tilesets\packed\objects-by-race\generic.json treasure\space.treasurepools DIFFS ----- player.config 782c782 < "events" : "/events/events.lua" --- > //"events" : "/events/events.lua" cinematics\story\esther\esther.cinematic 4c4 < "skippable" : false, --- > "skippable" : true, dungeons\microdungeons\bounty\boat.dungeon 7c7 < "anchor" : [ "boat_1", "boat_2", "boat_3", "boat_4", "boat_5", "boat_6", "boat_7" ], --- > "anchor" : [ "boat_1", "boat_2", "boat_3", "boat_4", "boat_5", "boat_6", "boat_7", "boat_8", "boat_9" ], 62a63,76 > }, > { > "name" : "boat_8", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "boat_8.json" ] > }, > { > "name" : "boat_9", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "boat_9.json" ] dungeons\microdungeons\bounty\boatinteract_2.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\boatvault_1.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\boatvault_2.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\boatvault_3.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\boat_1.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\boat_2.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\boat_3.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\boat_4.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\boat_5.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\boat_6.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\boat_7.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\interactobject_5.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\interactobject_6.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\interactobject_7.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\interactobject_8.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse.dungeon 7c7 < "anchor" : [ "safehouse_1", "safehouse_2", "safehouse_3", "safehouse_4", "safehouse_5", "safehouse_6", "safehouse_7", "safehouse_8", "safehouse_9", "safehouse_10", "safehouse_11", "safehouse_12", "safehouse_13", "safehouse_14", "safehouse_15", "safehouse_16", "safehouse_17" ], --- > "anchor" : [ "safehouse_1", "safehouse_2", "safehouse_3", "safehouse_4", "safehouse_5", "safehouse_6", "safehouse_7", "safehouse_8", "safehouse_9", "safehouse_10", "safehouse_11", "safehouse_12", "safehouse_13", "safehouse_14", "safehouse_15", "safehouse_16", "safehouse_17", "safehouse_18", "safehouse_19" ], 132a133,146 > }, > { > "name" : "safehouse_18", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "safehouse_18.json" ] > }, > { > "name" : "safehouse_19", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "safehouse_19.json" ] dungeons\microdungeons\bounty\safehouse_1.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_10.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_11.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_12.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_13.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_14.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_15.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_16.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_17.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_2.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_3.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_4.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_5.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_6.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_7.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_8.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\safehouse_9.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundinteract_2.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundinteract_5.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundsafehouse.dungeon 7c7 < "anchor" : [ "undergroundsafehouse_1", "undergroundsafehouse_2", "undergroundsafehouse_3", "undergroundsafehouse_4", "undergroundsafehouse_5", "undergroundsafehouse_6", "undergroundsafehouse_7", "undergroundsafehouse_8", "undergroundsafehouse_9" ], --- > "anchor" : [ "undergroundsafehouse_1", "undergroundsafehouse_2", "undergroundsafehouse_3", "undergroundsafehouse_4", "undergroundsafehouse_5", "undergroundsafehouse_6", "undergroundsafehouse_7", "undergroundsafehouse_8", "undergroundsafehouse_9", "undergroundsafehouse_10", "undergroundsafehouse_11", "undergroundsafehouse_12", "undergroundsafehouse_13", "undergroundsafehouse_14", "undergroundsafehouse_15", "undergroundsafehouse_16" ], 76a77,125 > }, > { > "name" : "undergroundsafehouse_10", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "undergroundsafehouse_10.json" ] > }, > { > "name" : "undergroundsafehouse_11", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "undergroundsafehouse_11.json" ] > }, > { > "name" : "undergroundsafehouse_12", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "undergroundsafehouse_12.json" ] > }, > { > "name" : "undergroundsafehouse_13", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "undergroundsafehouse_13.json" ] > }, > { > "name" : "undergroundsafehouse_14", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "undergroundsafehouse_14.json" ] > }, > { > "name" : "undergroundsafehouse_15", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "undergroundsafehouse_15.json" ] > }, > { > "name" : "undergroundsafehouse_16", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "undergroundsafehouse_16.json" ] dungeons\microdungeons\bounty\undergroundsafehouse_1.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundsafehouse_2.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundsafehouse_3.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundsafehouse_4.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundsafehouse_5.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundsafehouse_6.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundsafehouse_7.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundsafehouse_8.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundsafehouse_9.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundvault_1.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundvault_2.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\undergroundvault_3.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\vault_1.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\vault_2.json [TMX file differences are left out for huge size.] dungeons\microdungeons\bounty\vault_3.json [TMX file differences are left out for huge size.] dungeons\missions\cultistmissions\cultistmission1.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\bountyspacesafehouse.dungeon 512a513,518 > "name" : "room_10", > "rules" : [], > "def" : [ "tmx", "room_10.json" ], > "chance" : 1 > }, > { dungeons\space\bountyspacesafehouse\end_1.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\end_2.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\end_3.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\end_4.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\end_5.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\end_6.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\room_1.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\room_2.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\room_3.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\room_4.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\room_5.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\room_6.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\room_7.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\room_8.json [TMX file differences are left out for huge size.] dungeons\space\bountyspacesafehouse\room_9.json [TMX file differences are left out for huge size.] items\armors\decorative\hats\bandithat1\bandithat1.head 8c8 < "description" : "A bandit's bandanna.", --- > "description" : "A bandit's bandana.", quests\bounty\bounty.lua 14a15 > storage.scanIds = storage.scanIds or {} 19a21,23 > message.setHandler(quest.questId().."scanIds", function(_, _, param, uuids) > storage.scanIds[param] = uuids; > end) 38a43,56 > storage.scanObjects = storage.scanObjects or nil > self.scanClue = nil > message.setHandler("objectScanned", function(message, isLocal, objectName) > if storage.scanObjects ~= nil then > storage.scanObjects = copyArray(util.filter(storage.scanObjects, function(n) return n ~= objectName end)) > end > if self.scanClue and objectName == self.scanClue then > return nextStage() > end > end) > message.setHandler("interestingObjects", function(...) > return storage.scanObjects or jarray() > end) > 107a126,133 > > table.insert(self.tasks, coroutine.create(function() > while storage.scanIds["inertScans"] == nil do > coroutine.yield(false) > end > storage.scanObjects = copyArray(storage.scanIds["inertScans"]) > return true > end)) quests\bounty\bounty_gen.lua 4,43d3 < self.generatedQuests = {} < self.generators = {} < local behaviorNames = { < "scared", < "crazy", < "deceptive", < "tricky", < "bribe" < } < for _,behaviorName in ipairs(behaviorNames) do < table.insert(self.generators, coroutine.create(function() < local generator = questGenerator(behaviorName, "capture_bounty", 1) < local arc = generator:generateBountyArc(target) < if arc then < table.insert(self.generatedQuests, arc) < else < error("No arc produced") < end < end)) < end < < -- for _,endStep in ipairs({"capture_space_bounty", "capture_ship_bounty"}) do < -- table.insert(self.generators, coroutine.create(function() < -- local generator = questGenerator(nil, endStep, 2) < -- local arc = generator:generateBountyArc(target) < -- if arc then < -- table.insert(self.generatedQuests, arc) < -- else < -- error("No arc produced") < -- end < -- end)) < -- end < < -- for i = 1, 100 do < -- local gang = generateGang(sb.makeRandomSource():randu64()) < -- sb.logInfo("%s", gang.name) < -- end < end < < function questGenerator(behaviorName, endStep, stepCount) 48,50c8,10 < local generator = BountyGenerator.new(seed, systemPosition(celestial.currentSystem()), {"orangestar", "whitestar"}, categories, endStep) < generator.stepCount = {stepCount, stepCount} < local target = generator:generateBountyNpc(gang, nil, behaviorName) --- > local generator = BountyGenerator.new(seed, systemPosition(celestial.currentSystem()), {"orangestar", "whitestar"}, categories, "capstone_1") > generator.stepCount = {1, 1} > local target = generator:generateBountyNpc(gang) 64a25 > self.generate = coroutine.create(function() return generator:generateBountyArc(target) end) 66c27,30 < return generator --- > -- for i = 1, 100 do > -- local gang = generateGang(sb.makeRandomSource():randu64()) > -- sb.logInfo("%s", gang.name) > -- end 70,79c34,37 < if #self.generators > 0 then < self.generators = util.filter(self.generators, function(gen) < local s, res = coroutine.resume(gen) < if not s then error(res) end < < return coroutine.status(gen) ~= "dead" < end) < else < for _,arc in ipairs(self.generatedQuests) do < player.startQuest(arc, player.serverUuid()) --- > if self.generate then > local status, result = coroutine.resume(self.generate) > if not status then > error(result) 80a39,42 > if result ~= nil then > local arc = result > sb.logInfo("Quest arc: %s", sb.printJson(arc, 1)) > player.startQuest(arc, player.serverUuid()) 81a44,45 > self.generate = nil > end quests\bounty\capture_bounty.questtemplate 46a47,49 > "playApproachMessage" : true, > "playExploreMessage" : true, > quests\bounty\clue_items.config 332,333c332,333 < "...Are you recording this? Good. says there's been a change of plan...", < "We're to head to instead! You got that?" --- > "I hope you find this, Peacekeeper! This is . Guess what?", > "That was ME you spoke to earlier! It was a trick! I decieved you!" 336c336 < "message" : "Well that is a mighty fine lead! I think you need to hurry your hide over to !" --- > "message" : "Dangnabbit, we've been taken on a ride! I think you need to hurry your hide back to the previous location!" 341,342c341,342 < "...You ended up WHERE? No, didn't get you get the notice? We aren't meant to BE there anymore!", < "Meet me at instead. We have Peacekeepers on our tail!" --- > "It is I, ! I have a message for you, Peacekeeper...", > "I tricked you! The helpful citizen you met earlier was me all along! Your time has been truly wasted!" 345c345 < "message" : "Looks like they're half a step ahead of us - but it's seemin' like we can catch 'em at !" --- > "message" : "These criminals are masters of disguise... I think you should go back to your previous location and find this crook, partner!" 350,351c350,351 < "...And because of that, is heading to instead, okay?", < "...And don't leave a recording of this conversation behind by accident again!" --- > "Hey, Peacekeeper! This is - the helpful citizen you met earlier was actually me! Ha!", > "You've been taken on a cruise of ruses! A trick trek! A deceit drive!" 354c354 < "message" : "It's just our luck that wrong-doers ain't so smart, huh? Y'all better head on over to ." --- > "message" : "Dangnabbit, we've been taken on a ride! I think you need to hurry your hide back to the previous location!" 359,360c359,360 < "...And I just get bored sometimes, you know? I find that recording myself talking is pretty entertaining.", < "But enough of that, I need to meet up with on ." --- > "Do you recognise my voice, Peacekeeper? - the helpful citizen you met earlier was I, !", > "Never forget the day that you were made a fool of!" 363c363 < "message" : "..Well, I guess that's a good enough lead. Sounds like is your next destination, partner!" --- > "message" : "What a mighty waste of Peacekeeper time! You better head back to your previous location an' teach this crook a lesson!" 368,369c368,369 < "...And really didn't believe me when I explained what happened at the Outpost...", < "...So that's why I'm running late! I'll meet up with you at ..." --- > "I hope you find this, Peacekeeper! This is . Guess what?", > "That was ME you spoke to earlier! It was a ruse! You got GOT!" 372c372 < "message" : "That's a tip-off if I ever heard one! I suppose you best be headin' to , next!" --- > "message" : "Tarnation - we've been taken on a ride! I think you need to hurry your hide back to the previous location!" 377,378c377,378 < "...Didn't you hear? We're being followed. We have to throw the Peacekeepers off the lead...", < "...Bring the goods to instead..." --- > "Greetins! it is I, ! I have a message for you, Peacekeeper...", > "I tricked you! The helpful citizen you met earlier was me all along! I bet you feel embarassed now, huh?!" 381c381 < "message" : "They're slick, but they ain't slick enough to throw us off! Onward-bound to !" --- > "message" : "Why would they tell us where they are? Just to brag? You should go back to your earlier location and find this crook, partner!" 386,387c386,387 < "...And that's when I found this blank CD, so I thought I'd record my voice and see what I sound like...", < "...My voice sounds super weird! Anyway, I'll bring the goods to now..." --- > "Hey, Peacekeeper! This is - do you remember the helpful citizen you met earlier?", > "IT WAS ME! IT WAS ME ALL ALONG, PEACEKEEPER!" 390c390 < "message" : "I don't think we're dealin' with smart folks on this case. You better head to !" --- > "message" : "Aw, son of a snuffish! I think you need to hurry your hide back to the previous location!" quests\bounty\clue_objects.config 286a287,308 > }, > "darkcomputer" : { > "planetClue" : { > "dialog" : "[QUERY_LOCATION] COMPLETE: ^green;^reset;", > "message" : "^green;^reset;? That sounds like a mighty fine tip-off if I ever heard one!" > }, > "planetBounty" : { > "dialog" : ">USER: ^green;^reset; >LOCATION: ^green;^reset;", > "message" : "You found the target's location? You better trek on over to ^green;^reset;!" > }, > "spaceClue" : { > "dialog" : ">HIDEOUT_SYSTEM_LOCATION: ^green;^reset;", > "message" : "The target must have intel hidin' in the ^green;^reset; system... The trail is still hot!" > }, > "spaceBounty" : { > "dialog" : " is [LOCATED] in [SYSTEM] ^green;^reset;", > "message" : "The target is hidin' out somewhere in space over in ^green;^reset;. You know what to do, partner!" > }, > "vaultClue" : { > "dialog" : "[WELCOME_NEW_USER] The ^green;^reset; Vault Code = ^green;^reset; [BEEP BOOP]", > "message" : "The code is ! You better go back to that vault, partner!" > } quests\bounty\dungeons.config 3,7c3,7 < "default" : [ "bountycamp", "safehouse", "interactobject", "vault", "undergroundsafehouse", "undergroundinteract", "undergroundvault", "minor_spawn" ], < "ocean" : [ "bountycamp", "safehouse", "interactobject", "vault", "boat", "boatinteract", "boatvault", "undergroundsafehouse", "undergroundinteract", "undergroundvault", "minor_spawn" ], < "toxic" : [ "bountycamp", "safehouse", "interactobject", "vault", "boat", "boatinteract", "boatvault", "undergroundsafehouse", "undergroundinteract", "undergroundvault", "minor_spawn" ], < "arctic" : [ "bountycamp", "safehouse", "interactobject", "vault", "boat", "boatinteract", "boatvault", "undergroundsafehouse", "undergroundinteract", "undergroundvault", "minor_spawn" ], < "magma" : [ "bountycamp", "safehouse", "interactobject", "vault", "boat", "boatinteract", "boatvault", "undergroundsafehouse", "undergroundinteract", "undergroundvault", "minor_spawn" ] --- > "default" : [ "safehouse", "vault", "undergroundsafehouse", "undergroundvault", "minor_spawn" ], > "ocean" : [ "safehouse", "vault", "boat", "boatvault", "undergroundsafehouse", "undergroundvault", "minor_spawn" ], > "toxic" : [ "safehouse", "vault", "boat", "boatvault", "undergroundsafehouse", "undergroundvault", "minor_spawn" ], > "arctic" : [ "safehouse", "vault", "boat", "boatvault", "undergroundsafehouse", "undergroundvault", "minor_spawn" ], > "magma" : [ "safehouse", "vault", "boat", "boatvault", "undergroundsafehouse", "undergroundvault", "minor_spawn" ] 17,21c17 < "tags" : [ "clue_item", "clue_npc", "npc_bounty" ] < }, < "interactobject": { < "type" : "surface", < "tags" : [ "clue_object" ] --- > "tags" : [ "clue_item", "clue_object", "clue_npc", "clue_scan", "npc_bounty" ] 29,33c25 < "tags" : [ "clue_item", "clue_npc", "npc_bounty" ] < }, < "boatinteract" : { < "type" : "ocean", < "tags" : [ "clue_object" ] --- > "tags" : [ "clue_item", "clue_npc", "clue_object", "clue_scan", "npc_bounty" ] 41,45c33 < "tags" : [ "clue_item", "clue_npc", "npc_bounty" ] < }, < "undergroundinteract": { < "type" : "surface", < "tags" : [ "clue_object" ] --- > "tags" : [ "clue_item", "clue_object", "clue_npc", "clue_scan", "npc_bounty" ] quests\bounty\find_clue_item.questtemplate 39c39 < "^orange;Investigate containers^reset; for clues" --- > "^orange;Search^reset; for clues" 41a42,44 > > "playApproachMessage" : true, > "playExploreMessage" : true, quests\bounty\find_clue_npc.questtemplate 39c39 < "^orange;\"Interrogate\" criminal^reset; for clues" --- > "^orange;Search^reset; for clues" 41a42,44 > > "playApproachMessage" : true, > "playExploreMessage" : true, quests\bounty\find_clue_object.questtemplate 39c39 < "^orange;Investigate computers^reset; for clues" --- > "^orange;Search^reset; for clues" 41a42,44 > > "playApproachMessage" : true, > "playExploreMessage" : true, quests\bounty\generator.config 80c80 < "useBountyGang" : true, --- > "gangMember" : true, 131c131 < "useBountyGang" : true, --- > "gangMember" : true, 140a141,144 > "warp" : { > "type" : "json", > "warpType" : "deploy" > }, 182c186 < "useBountyGang" : true, --- > "gangMember" : true, 233c237 < "useBountyGang" : true, --- > "gangMember" : true, 307a312,355 > }, > "gang" : { > "location" : "clue", > "type" : "npc", > "gangMember" : true, > "multiple" : true > } > } > }, > > "find_clue_scan" : { > "category" : "planet", > "quest" : "find_clue_scan", > "questParameters" : {}, > "clueTypes" : [ > "planetClue", > "planetBounty", > "spaceClue", > "spaceBounty" > ], > > "coordinate" : { > "type" : "world", > "questParameter" : "world" > }, > > "locations" : { > "clue" : { > "type" : "dungeon", > "position" : "surface", > "tags" : [ "clue_scan" ] > } > }, > > "spawns" : { > "clue" : { > "location" : "clue", > "type" : "clueScan" > }, > "gang" : { > "location" : "clue", > "type" : "npc", > "gangMember" : true, > "multiple" : true 346a395,400 > }, > "gang" : { > "location" : "clue", > "type" : "npc", > "gangMember" : true, > "multiple" : true 350a405,440 > // "find_space_clue_scan" : { > // "category" : "anomaly", > // "quest" : "find_space_clue_scan", > // "questParameters" : { > // "systemSpawns" : { > // "type" : "json", > // "spaceObject" : "bountyanomaly" > // } > // }, > // "clueTypes" : [ > // "planetClue", > // "planetBounty", > // "spaceClue", > // "spaceBounty" > // ], > > // "coordinate" : { > // "type" : "system", > // "questParameter" : "system" > // }, > > // "locations" : { > // "clue" : { > // "type" : "stagehand", > // "stagehand" : "clueroom" > // } > // }, > > // "spawns" : { > // "clue" : { > // "location" : "clue", > // "type" : "clueScan" > // } > // } > // }, > 382a473,478 > }, > "gang" : { > "location" : "clue", > "type" : "npc", > "gangMember" : true, > "multiple" : true 415a512,517 > }, > "gang" : { > "location" : "clue", > "type" : "npc", > "gangMember" : true, > "multiple" : true 420a523 > "weight" : 0.00000000000000001, 461a565,570 > }, > "gang" : { > "location" : "clue", > "type" : "npc", > "gangMember" : true, > "multiple" : true 498a608,613 > }, > "gang" : { > "location" : "clue", > "type" : "npc", > "gangMember" : true, > "multiple" : true 503a619 > "weight" : 0.25, 535a652 > "weight" : 0.25, 591a709,714 > }, > "gang" : { > "location" : "bounty", > "type" : "npc", > "gangMember" : true, > "multiple" : true 623a747,752 > }, > "gang" : { > "location" : "bounty", > "type" : "npc", > "gangMember" : true, > "multiple" : true 653,656d781 < }, < "gang" : { < "type" : "stagehand", < "stagehand" : "gangspawn" 724a850,859 > "clueType" : "planetClue" > }, > > "next" : { > "step" : "find_clue_scan" > } > }, > > { > "prev" : { 887c1022 < "stagehand" : "cluespawn" --- > "stagehand" : "storageclue" 951c1086 < "stagehand" : "cluespawn" --- > "stagehand" : "storageclue" 1015c1150 < "stagehand" : "cluespawn" --- > "stagehand" : "storageclue" quests\bounty\stages.lua 2c2,3 < if quest.isCurrent() and not storage.playedExploreMessage then --- > local shouldPlay = config.getParameter("playExploreMessage", false) > if shouldPlay and quest.isCurrent() and not storage.playedExploreMessage then 9c10,11 < if quest.isCurrent() and not storage.playedApproachMessage then --- > local shouldPlay = config.getParameter("playApproachMessage", false) > if shouldPlay and quest.isCurrent() and not storage.playedApproachMessage then 15d16 < 292a294,337 > function findClueScanStage() > local objectiveText = config.getParameter("objectives.findClueScanStage") > > quest.setObjectiveList({ > {objectiveText[1], false} > }) > quest.setCompassDirection(nil) > quest.setIndicators({}) > > while (not storage.spawned["clue"] or not storage.scanIds["clue"]) and player.worldId() == quest.worldId() do > playExploreMessage() > > if player.worldId() ~= quest.worldId() then > return previousStage() > end > > coroutine.yield() > end > > playApproachMessage("approachingclue") > quest.setObjectiveList({ > {objectiveText[1], true}, > {objectiveText[2], false} > }) > > storage.scanObjects = storage.scanObjects or copyArray(storage.scanIds["clue"]) > self.scanClue = quest.parameters().spawns.spawns.clue.uuid > > while true do > local toClue = world.distance(storage.spawned["clue"], entity.position()) > local distance = world.magnitude(toClue) > if distance > 32 then > quest.setCompassDirection(vec2.angle(toClue)) > else > quest.setCompassDirection(nil) > end > > if player.worldId() ~= quest.worldId() or player.serverUuid() ~= quest.serverUuid() then > return previousStage() > end > coroutine.yield() > end > end > 489c534,539 < player.warp(missionWorld, "beam") --- > local warpType = "beam" > if quest.parameters().warp then > warpType = quest.parameters().warp.warpType > end > local deploy = warpType == "deploy" > player.warp(missionWorld, warpType, deploy) scripts\bountygeneration.lua 77a78 > self.clueScans = root.assetJson("/quests/bounty/clue_scans.config") 165a167,186 > function BountyGenerator:generateGangMember(gang) > local species = util.randomFromList({"human", "hylotl", "avian", "glitch", "novakid", "apex", "floran"}, self.rand) > local bounty = { > type = "npc", > species = species, > typeName = "gangmember", > gang = { > name = gang.name, > hat = gang.hat, > colorIndex = colorIndex, > }, > parameters = { > scriptConfig = { > gang = gang > } > } > } > return bounty > end > 685a707,713 > elseif spawnConfig.type == "clueScan" then > step.questParameters.spawns.spawns[k] = { > type = "scan", > location = spawnConfig.location, > uuid = sb.makeUuid(), > clueType = step.clueType > } 696,698c724,732 < local gang < if spawnConfig.useBountyGang then < gang = bounty.gang --- > local generated > if spawnConfig.gangMember then > generated = self:generateGangMember(bounty.gang) > else > local gang > if spawnConfig.useBountyGang then > gang = bounty.gang > end > generated = self:generateBountyNpc(gang) 700d733 < local generated = self:generateBountyNpc(gang) 706a740,746 > > local behaviorOverrides > if spawnConfig.behaviorOverrides then > behaviorOverrides = { > [step.questId] = spawnConfig.behaviorOverrides > } > end 713,715c753 < behaviorOverrides = { < [step.questId] = spawnConfig.behaviorOverrides < } --- > behaviorOverrides = behaviorOverrides, 718,726c756,766 < for _, overrides in pairs(spawn.behaviorOverrides) do < for _, override in ipairs(overrides) do < for k,v in pairs(override.behavior.parameters or {}) do < local tags = { < questId = step.questId, < clueType = step.clueType < } < if type(v) == "string" then < override.behavior.parameters[k] = sb.replaceTags(v, tags) --- > if spawn.behaviorOverrides then > for _, overrides in pairs(spawn.behaviorOverrides) do > for _, override in ipairs(overrides) do > for k,v in pairs(override.behavior.parameters or {}) do > local tags = { > questId = step.questId, > clueType = step.clueType > } > if type(v) == "string" then > override.behavior.parameters[k] = sb.replaceTags(v, tags) > end scripts\util.lua 856a857,864 > function copyArray(t) > local array = jarray() > for i,v in ipairs(t) do > table.insert(array, copy(v)) > end > return array > end > stagehands\bountymanager.lua 95c95 < local status, result, position = coroutine.resume(spawn.coroutine, spawn.config) --- > local status, result, position = coroutine.resume(spawn.coroutine, spawn.config, spawnName) 120,121c120,123 < if not questStorage(spawn.config.questId).spawned[spawn.config.name] then < questStorage(spawn.config.questId).spawned[spawn.config.name] = result --- > if spawn.config.questId then > if not questStorage(spawn.config.questId).spawned[spawn.config.name] then > questStorage(spawn.config.questId).spawned[spawn.config.name] = result > end 191a194 > local addScanObjectLocation = nil 217a221,224 > if not spawnConfig.multiple then > -- spawn for a single clue or bounty npc, add scan objects > addScanObjectLocation = spawnConfig.location > end 221a229,230 > -- spawn for an item clue, add scan objects > addScanObjectLocation = spawnConfig.location 223a233,234 > -- spawn for an object clue, add scan objects > addScanObjectLocation = spawnConfig.location 228a240,243 > elseif spawnConfig.type == "scan" then > hasScanClue = true > spawnConfig.clue = true > spawner = coroutine.create(spawnScanObject) 239a255,265 > > -- spawn non-clue scan objects at locations that have another clue > if addScanObjectLocation ~= nil then > self.spawners["inertScans"] = { > config = { > location = addScanObjectLocation, > clue = false, > }, > coroutine = coroutine.create(spawnScanObject) > } > end 682a709,779 > end > > function spawnScanObject(spawnConfig, spawnName) > local positions = getLocationPositions(spawnConfig.location) > > local clueConfigs = root.assetJson("/quests/bounty/clue_scans.config") > sb.logInfo("%s", clueConfigs) > > local stagehands = {} > for _, position in ipairs(positions) do > local region = rect.withSize(vec2.sub(position, {32, 32}), {64, 64}) > while not world.regionActive(region) do > world.loadRegion(region) > coroutine.yield() > end > local near = world.entityQuery(rect.ll(region), rect.ur(region), {includedTypes = {"stagehand"}}) > near = util.filter(near, function(entityId) > return world.entityName(entityId) == "scanclue" > end) > for _, entityId in ipairs(near) do > stagehands[entityId] = true > end > end > stagehands = util.keys(stagehands) > if spawnConfig.clue and #stagehands == 0 then > error("no scanclue stagehands found") > end > > local objectNames = util.keys(clueConfigs) > local uuids = {} > > -- disable tile protection to place objects, then re-enable it again immediately after > -- this should be synchronous and happen within the same frame > -- still hugely hacky > for _, dungeonId in ipairs(storage.tileProtection) do > world.setTileProtection(dungeonId, false) > end > for i,stagehandId in ipairs(stagehands) do > local uuid = sb.makeUuid(); > local objectName = util.randomFromList(objectNames) > local description > if spawnConfig.clue and i == 1 then > local clueConfig = clueConfigs[objectName][spawnConfig.clueType] > description = clueConfig.description > uuid = spawnConfig.uuid > > local tags = util.generateTextTags(storage.quest.parameters.text.tags) > self.outbox:sendMessage(self.source, storage.questId.."setCompleteMessage", sb.replaceTags(clueConfig.message, tags)) > end > > local parameters = { > inspectionLogName = uuid, > inspectionDescription = description, > } > local entityId = world.placeObject(objectName, world.entityPosition(stagehandId), 1, parameters, true) > if entityId == nil then > sb.logInfo("Failed to place object %s at %s", objectName, world.entityPosition(stagehandId)) > else > sb.logInfo("Placed object %s at %s", entityId, world.entityPosition(stagehandId)) > end > table.insert(uuids, uuid) > end > -- re-enable all tile protection after placing objects > for _, dungeonId in ipairs(storage.tileProtection) do > world.setTileProtection(dungeonId, true) > end > self.outbox:sendMessage(self.source, storage.questId.."scanIds", spawnName, uuids) > > > -- return average position > return vec2.div(util.fold(positions, {0, 0}, vec2.add), #positions) tilesets\packed\objects-by-category\decorative.json 7c7 < "tilecount" : 1435, --- > "tilecount" : 1436, 4202a4203,4210 > "1435" : { > "//description" : "A clue for a bounty.", > "//name" : "scanclue1", > "//shortdescription" : "Scan Clue 1", > "imagePositionX" : "-8", > "imagePositionY" : "-8", > "object" : "scanclue1" > }, 13468a13477,13479 > }, > "1435" : { > "image" : "../../../../../tiled/packed/objects/scanclue1.png" tilesets\packed\objects-by-category\wire.json 7c7 < "tilecount" : 221, --- > "tilecount" : 222, 1188a1189,1197 > "221" : { > "//description" : "An antiquated computer terminal, with a deep red display.", > "//name" : "darkcomputer", > "//shortdescription" : "Dark Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "darkcomputer", > "tilesetDirection" : "right" > }, 2319a2329,2331 > }, > "221" : { > "image" : "../../../../../tiled/packed/objects/darkcomputer.png" tilesets\packed\objects-by-colonytag\electronic.json 7c7 < "tilecount" : 130, --- > "tilecount" : 131, 316a317,325 > "130" : { > "//description" : "An antiquated computer terminal, with a deep red display.", > "//name" : "darkcomputer", > "//shortdescription" : "Dark Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "darkcomputer", > "tilesetDirection" : "right" > }, 1236a1246,1248 > }, > "130" : { > "image" : "../../../../../tiled/packed/objects/darkcomputer.png" tilesets\packed\objects-by-colonytag\misc.json 7c7 < "tilecount" : 165, --- > "tilecount" : 166, 643a644,651 > "165" : { > "//description" : "A clue for a bounty.", > "//name" : "scanclue1", > "//shortdescription" : "Scan Clue 1", > "imagePositionX" : "-8", > "imagePositionY" : "-8", > "object" : "scanclue1" > }, 1613a1622,1624 > }, > "165" : { > "image" : "../../../../../tiled/packed/objects/scanclue1.png" tilesets\packed\objects-by-colonytag\wired.json 7c7 < "tilecount" : 180, --- > "tilecount" : 181, 797a798,806 > "180" : { > "//description" : "An antiquated computer terminal, with a deep red display.", > "//name" : "darkcomputer", > "//shortdescription" : "Dark Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "darkcomputer", > "tilesetDirection" : "right" > }, 1847a1857,1859 > }, > "180" : { > "image" : "../../../../../tiled/packed/objects/darkcomputer.png" tilesets\packed\objects-by-race\generic.json 7c7 < "tilecount" : 1971, --- > "tilecount" : 1973, 9156a9157,9173 > "1971" : { > "//description" : "An antiquated computer terminal, with a deep red display.", > "//name" : "darkcomputer", > "//shortdescription" : "Dark Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "darkcomputer", > "tilesetDirection" : "right" > }, > "1972" : { > "//description" : "A clue for a bounty.", > "//name" : "scanclue1", > "//shortdescription" : "Scan Clue 1", > "imagePositionX" : "-8", > "imagePositionY" : "-8", > "object" : "scanclue1" > }, 19868a19886,19891 > }, > "1971" : { > "image" : "../../../../../tiled/packed/objects/darkcomputer.png" > }, > "1972" : { > "image" : "../../../../../tiled/packed/objects/scanclue1.png" treasure\space.treasurepools 217a218 > {"weight" : 0.25, "item" : ["slopedglasspanel", 50]},